Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/rpc_lookup.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2009 iptelorg GmbH
3
 *
4
 * Permission to use, copy, modify, and distribute this software for any
5
 * purpose with or without fee is hereby granted, provided that the above
6
 * copyright notice and this permission notice appear in all copies.
7
 *
8
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
 */
16
17
/*!
18
 * \file
19
 * \brief Kamailio core ::  RPC lookup and register functions
20
 * \ingroup core
21
 * Module: \ref core
22
 */
23
24
#include "rpc.h"
25
#include "str_hash.h"
26
#include "ut.h"
27
#include "dprint.h"
28
#include "mem/shm.h"
29
30
0
#define RPC_HASH_SIZE 32
31
0
#define RPC_SARRAY_SIZE 32 /* initial size */
32
33
static struct str_hash_table rpc_hash_table;
34
35
/* array of pointer to rpc exports, sorted after their name
36
 *  (used by listMethods) */
37
rpc_exportx_t **rpc_sarray;
38
int rpc_sarray_crt_size;    /* used */
39
static int rpc_sarray_max_size; /* number of entries alloc'ed */
40
41
int ksr_rpc_exec_delta = 0;
42
43
/** init the rpc hash table.
44
 * @return 0 on success, -1 on error
45
 */
46
int init_rpcs(void)
47
0
{
48
0
  if(str_hash_alloc(&rpc_hash_table, RPC_HASH_SIZE) < 0)
49
0
    return -1;
50
0
  str_hash_init(&rpc_hash_table);
51
0
  rpc_sarray_max_size = RPC_SARRAY_SIZE;
52
0
  rpc_sarray = pkg_malloc(sizeof(*rpc_sarray) * rpc_sarray_max_size);
53
0
  if(rpc_sarray) {
54
0
    rpc_sarray_crt_size = 0;
55
0
  } else {
56
0
    PKG_MEM_ERROR;
57
0
    return -1;
58
0
  }
59
0
  return 0;
60
0
}
61
62
63
void destroy_rpcs(void)
64
0
{
65
0
  int r;
66
0
  struct str_hash_entry *e;
67
0
  struct str_hash_entry *bak;
68
0
  rpc_exportx_t *rx;
69
0
  for(r = 0; r < rpc_hash_table.size; r++) {
70
0
    clist_foreach_safe(&rpc_hash_table.table[r], e, bak, next)
71
0
    {
72
0
      rx = (rpc_exportx_t *)e->u.p;
73
0
      if(rx->xdata != NULL) {
74
0
        lock_destroy(&rx->xdata->elock);
75
0
        shm_free(rx->xdata);
76
0
      }
77
0
      pkg_free(e);
78
0
    }
79
0
  }
80
0
  if(rpc_hash_table.table)
81
0
    pkg_free(rpc_hash_table.table);
82
0
  if(rpc_sarray)
83
0
    pkg_free(rpc_sarray);
84
0
  rpc_hash_table.table = 0;
85
0
  rpc_hash_table.size = 0;
86
0
  rpc_sarray = 0;
87
0
  rpc_sarray_crt_size = 0;
88
0
  rpc_sarray_max_size = 0;
89
0
}
90
91
92
/** adds a new rpc to the hash table (no checks).
93
 * @return 0 on success, -1 on error, 1 on duplicate
94
 */
95
static int rpc_hash_add(struct rpc_export *rpc)
96
0
{
97
0
  struct str_hash_entry *e;
98
0
  int name_len;
99
0
  int doc0_len, doc1_len;
100
0
  rpc_exportx_t *n_rpc;
101
0
  rpc_exportx_t **r;
102
0
  rpc_xdata_t *xd = NULL;
103
104
0
  name_len = strlen(rpc->name);
105
0
  doc0_len = rpc->doc_str[0] ? strlen(rpc->doc_str[0]) : 0;
106
0
  doc1_len = rpc->doc_str[1] ? strlen(rpc->doc_str[1]) : 0;
107
  /* alloc everything into one block */
108
109
0
  e = pkg_malloc(ROUND_POINTER(sizeof(struct str_hash_entry))
110
0
           + ROUND_POINTER(sizeof(rpc_exportx_t)) + 2 * sizeof(char *)
111
0
           + +name_len + 1 + doc0_len + (rpc->doc_str[0] != 0)
112
0
           + doc1_len + (rpc->doc_str[1] != 0));
113
0
  if(e == 0) {
114
0
    PKG_MEM_ERROR;
115
0
    goto error;
116
0
  }
117
0
  if(rpc->flags & RPC_EXEC_DELTA) {
118
0
    xd = (rpc_xdata_t *)shm_mallocxz(sizeof(rpc_xdata_t));
119
0
    if(xd == NULL) {
120
0
      pkg_free(e);
121
0
      goto error;
122
0
    }
123
0
    lock_init(&xd->elock);
124
0
  }
125
0
  n_rpc = (rpc_exportx_t *)((char *)e
126
0
                + ROUND_POINTER(sizeof(struct str_hash_entry)));
127
  /* copy rpc into n_rpc */
128
0
  n_rpc->r = *rpc;
129
0
  n_rpc->xdata = xd;
130
0
  n_rpc->r.doc_str = (const char **)((char *)n_rpc
131
0
                     + ROUND_POINTER(sizeof(rpc_exportx_t)));
132
0
  n_rpc->r.name = (char *)n_rpc->r.doc_str + 2 * sizeof(char *);
133
0
  memcpy((char *)n_rpc->r.name, rpc->name, name_len);
134
0
  *((char *)&n_rpc->r.name[name_len]) = 0;
135
0
  if(rpc->doc_str[0]) {
136
0
    n_rpc->r.doc_str[0] = &n_rpc->r.name[name_len + 1];
137
0
    memcpy((char *)n_rpc->r.doc_str[0], rpc->doc_str[0], doc0_len);
138
0
    *(char *)&(n_rpc->r.doc_str[0][doc0_len]) = 0;
139
0
  } else {
140
0
    n_rpc->r.doc_str[0] = 0;
141
0
  }
142
0
  if(rpc->doc_str[1]) {
143
0
    n_rpc->r.doc_str[1] = n_rpc->r.doc_str[0]
144
0
                    ? &n_rpc->r.doc_str[0][doc0_len + 1]
145
0
                    : &n_rpc->r.name[name_len + 1];
146
0
    memcpy((char *)n_rpc->r.doc_str[1], rpc->doc_str[1], doc1_len);
147
0
    *(char *)&(n_rpc->r.doc_str[1][doc1_len]) = 0;
148
0
  } else {
149
0
    n_rpc->r.doc_str[1] = 0;
150
0
  }
151
152
0
  e->key.s = (char *)n_rpc->r.name;
153
0
  e->key.len = name_len;
154
0
  e->flags = 0;
155
0
  e->u.p = n_rpc;
156
0
  str_hash_add(&rpc_hash_table, e);
157
158
  /* insert it into the sorted array */
159
0
  if(rpc_sarray_max_size <= rpc_sarray_crt_size) {
160
    /* array must be increased */
161
0
    r = pkg_realloc(
162
0
        rpc_sarray, 2 * rpc_sarray_max_size * sizeof(*rpc_sarray));
163
0
    if(r == 0) {
164
0
      ERR("out of memory while adding RPC to the sorted list\n");
165
0
      goto error;
166
0
    }
167
0
    rpc_sarray = r;
168
0
    rpc_sarray_max_size *= 2;
169
0
  };
170
  /* insert into array, sorted */
171
0
  for(r = rpc_sarray; r < (rpc_sarray + rpc_sarray_crt_size); r++) {
172
0
    if(strcmp(n_rpc->r.name, (*r)->r.name) < 0)
173
0
      break;
174
0
  }
175
0
  if(r != (rpc_sarray + rpc_sarray_crt_size))
176
0
    memmove(r + 1, r,
177
0
        (int)(long)((char *)(rpc_sarray + rpc_sarray_crt_size)
178
0
              - (char *)r));
179
0
  rpc_sarray_crt_size++;
180
0
  *r = n_rpc;
181
0
  return 0;
182
0
error:
183
0
  return -1;
184
0
}
185
186
187
/** lookup an rpc export after its name.
188
 * @return pointer to rpc export on success, 0 on error
189
 */
190
rpc_export_t *rpc_lookup(const char *name, int len)
191
0
{
192
0
  struct str_hash_entry *e;
193
194
0
  e = str_hash_get(&rpc_hash_table, (char *)name, len);
195
0
  return e ? &(((rpc_exportx_t *)e->u.p)->r) : 0;
196
0
}
197
198
199
/** lookup an extended rpc export after its name.
200
 * @return pointer to rpc export on success, 0 on error
201
 */
202
rpc_exportx_t *rpc_lookupx(const char *name, int len, unsigned int *rdata)
203
0
{
204
0
  rpc_exportx_t *rx;
205
0
  time_t tnow;
206
207
0
  struct str_hash_entry *e;
208
209
0
  e = str_hash_get(&rpc_hash_table, (char *)name, len);
210
0
  *rdata = 0;
211
0
  if(e != NULL) {
212
0
    rx = (rpc_exportx_t *)e->u.p;
213
0
    if(ksr_rpc_exec_delta > 0 && rx->xdata != NULL) {
214
0
      tnow = time(NULL);
215
0
      lock_get(&rx->xdata->elock);
216
0
      if(rx->xdata->etime > 0) {
217
0
        if(rx->xdata->etime > tnow - ksr_rpc_exec_delta) {
218
0
          *rdata = RPC_EXEC_DELTA;
219
0
        } else {
220
0
          rx->xdata->etime = tnow;
221
0
        }
222
0
      } else {
223
0
        rx->xdata->etime = tnow;
224
0
      }
225
0
      lock_release(&rx->xdata->elock);
226
0
    }
227
0
    return rx;
228
0
  }
229
0
  return NULL;
230
0
}
231
232
233
/** register a new rpc.
234
 * @return 0 on success, -1 on error, 1 on duplicate
235
 */
236
int rpc_register(rpc_export_t *rpc)
237
0
{
238
239
  /* check if the entry is already registered */
240
0
  if(rpc_lookup(rpc->name, strlen(rpc->name))) {
241
0
    WARN("duplicate rpc \"%s\"\n", rpc->name);
242
0
    return 1;
243
0
  }
244
0
  if(rpc_hash_add(rpc) != 0)
245
0
    return -1;
246
0
  return 0;
247
0
}
248
249
250
/** register all the rpc in a null-terminated array.
251
 * @return 0 on success, >0 if duplicates were found (number of
252
 * duplicates), -1 on error
253
 */
254
int rpc_register_array(rpc_export_t *rpc_array)
255
0
{
256
0
  rpc_export_t *rpc;
257
0
  int ret, i;
258
259
0
  ret = 0;
260
0
  for(rpc = rpc_array; rpc && rpc->name; rpc++) {
261
0
    i = rpc_register(rpc);
262
0
    if(i != 0) {
263
0
      if(i < 0)
264
0
        goto error;
265
0
      ret++;
266
0
    }
267
0
  }
268
0
  return ret;
269
0
error:
270
0
  return -1;
271
0
}
272
273
274
/* vi: set ts=4 sw=4 tw=79:ai:cindent: */