Coverage Report

Created: 2025-10-10 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensips/evi/evi_transport.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2011 OpenSIPS Solutions
3
 *
4
 * This file is part of opensips, a free SIP server.
5
 *
6
 * opensips is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * opensips is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 *
21
 * history:
22
 * ---------
23
 *  2011-05-xx  created (razvancrainea)
24
 */
25
26
#include "event_interface.h"
27
#include "evi_transport.h"
28
#include "../mem/shm_mem.h"
29
#include "../lib/cJSON.h"
30
31
0
#define JSONRPC_VERSION "2.0"
32
33
/* list with the transport modules */
34
static evi_trans_t *evi_trans_mods = NULL;
35
static int evi_trans_mods_size = 0;
36
37
/* functions used by the transport modules */
38
39
int register_event_mod(const evi_export_t *ev)
40
0
{
41
0
  evi_trans_t *trans_mod;
42
43
0
  if (!ev || !ev->proto.len || !ev->proto.s) {
44
0
    LM_ERR("no export or name specified\n");
45
0
    goto error;
46
0
  }
47
48
0
  if (!ev->raise) {
49
0
    LM_ERR("raise function should be specified for protocol %.*s\n",
50
0
        ev->proto.len, ev->proto.s);
51
0
    goto error;
52
0
  }
53
54
0
  if (!ev->parse) {
55
0
    LM_ERR("parse function should be specified for protocol %.*s\n",
56
0
        ev->proto.len, ev->proto.s);
57
0
    goto error;
58
0
  }
59
60
0
  if (!ev->print) {
61
0
    LM_ERR("print function should be specified for protocol %.*s\n",
62
0
        ev->proto.len, ev->proto.s);
63
0
    goto error;
64
0
  }
65
66
0
  if (ev->flags) {
67
0
    if (ev->flags & EVI_FREE_LIST) {
68
0
      LM_ERR("module cannot have the id %x\n", ev->flags);
69
0
      goto error;
70
0
    }
71
72
    /* check to see if there are two modules with the same id (or protocol) */
73
0
    for (trans_mod = evi_trans_mods; trans_mod; trans_mod = trans_mod->next){
74
0
      if (trans_mod->module->flags & ev->flags) {
75
0
        LM_ERR("duplicate flag %x\n", ev->flags);
76
0
        goto error;
77
0
      }
78
0
      if (ev->proto.len == trans_mod->module->proto.len &&
79
0
          !memcmp(ev->proto.s,trans_mod->module->proto.s,ev->proto.len)){
80
0
        LM_ERR("duplicate transport module protocol <%.*s>\n",
81
0
            ev->proto.len, ev->proto.s);
82
0
        goto error;
83
0
      }
84
0
    }
85
0
  }
86
87
0
  trans_mod = shm_malloc(sizeof(evi_trans_t));
88
0
  if (!trans_mod) {
89
0
    LM_ERR("no more shm memory\n");
90
0
    goto error;
91
0
  }
92
93
0
  trans_mod->module = ev;
94
0
  trans_mod->next = evi_trans_mods;
95
0
  evi_trans_mods = trans_mod;
96
97
0
  evi_trans_mods_size++;
98
99
0
  return 0;
100
0
error:
101
0
  return EVI_ERROR;
102
0
}
103
104
/* checks if there are any modules loaded */
105
int get_trans_mod_no(void)
106
0
{
107
0
  return evi_trans_mods_size;
108
0
}
109
110
/* Returns the transport export */
111
const evi_export_t* get_trans_mod(str* tran)
112
0
{
113
0
  str t;
114
0
  char *p;
115
0
  evi_trans_t *ev = evi_trans_mods;
116
117
0
  if (!tran || !tran->len || !tran->s)
118
0
    return NULL;
119
120
0
  t.s = tran->s;
121
0
  p = memchr(tran->s, TRANSPORT_SEP, tran->len);
122
0
  if (!p)
123
0
    t.len = tran->len;
124
0
  else
125
0
    t.len = p - tran->s;
126
127
0
  while (ev) {
128
0
    if (ev->module->proto.len == t.len &&
129
0
        !memcmp(ev->module->proto.s, t.s, t.len))
130
0
      return ev->module;
131
0
    ev = ev->next;
132
0
  }
133
134
0
  return NULL;
135
0
}
136
137
static int payload_add_params(cJSON *ret_obj, evi_params_t *params,
138
  str *extra_param_k, str *extra_param_v)
139
0
{
140
0
  evi_param_p param;
141
0
  cJSON *param_obj = NULL, *tmp;
142
143
0
  if (!params->first->name.s) {
144
0
    param_obj = cJSON_CreateArray();
145
0
    if (!param_obj) {
146
0
      LM_ERR("Failed to create JSON array\n");
147
0
      return -1;
148
0
    }
149
0
  } else {
150
0
    param_obj = cJSON_CreateObject();
151
0
    if (!param_obj) {
152
0
      LM_ERR("Failed to create JSON object\n");
153
0
      return -1;
154
0
    }
155
0
  }
156
157
0
  if (extra_param_v) {
158
0
    tmp = cJSON_CreateStr(extra_param_v->s, extra_param_v->len);
159
0
    if (!tmp) {
160
0
      LM_ERR("Failed to create JSON string\n");
161
0
      cJSON_Delete(param_obj);
162
0
      return -1;
163
0
    }
164
0
    if (!params->first->name.s)
165
0
      cJSON_AddItemToArray(param_obj, tmp);
166
0
    else
167
0
      _cJSON_AddItemToObject(param_obj, extra_param_k, tmp);
168
0
  }
169
170
0
  cJSON_AddItemToObject(ret_obj, "params", param_obj);
171
0
  for (param = params->first; param; param = param->next) {
172
0
    if (param->flags & EVI_INT_VAL) {
173
0
      tmp = cJSON_CreateNumber(param->val.n);
174
0
      if (!tmp) {
175
0
        LM_ERR("Failed to create JSON number\n");
176
0
        return -1;
177
0
      }
178
0
    } else {
179
0
      if (param->val.s.s)
180
0
        tmp = cJSON_CreateStr(param->val.s.s, param->val.s.len);
181
0
      else
182
0
        tmp = cJSON_CreateNull();
183
0
      if (!tmp) {
184
0
        LM_ERR("Failed to create JSON string %.*s\n", param->name.len, param->name.s);
185
0
        return -1;
186
0
      }
187
0
    }
188
189
0
    if (params->first->name.s)
190
0
      _cJSON_AddItemToObject(param_obj, &param->name, tmp);
191
0
    else
192
0
      cJSON_AddItemToArray(param_obj, tmp);
193
0
  }
194
195
0
  return 0;
196
0
}
197
198
char *evi_build_payload(evi_params_t *params, str *method, int id,
199
  str *extra_param_k, str *extra_param_v)
200
0
{
201
0
  cJSON *ret_obj;
202
0
  char *payload = NULL;
203
204
0
  ret_obj = cJSON_CreateObject();
205
0
  if (!ret_obj)
206
0
    return NULL;
207
208
0
  if (id)
209
0
    cJSON_AddNumberToObject(ret_obj, "id", id);
210
211
0
  cJSON_AddItemToObject(ret_obj, "jsonrpc",
212
0
    cJSON_CreateString(JSONRPC_VERSION));
213
0
  cJSON_AddItemToObject(ret_obj, "method",
214
0
    cJSON_CreateStr(method->s, method->len));
215
216
0
  if (params && params->first &&
217
0
    payload_add_params(ret_obj, params, extra_param_k, extra_param_v) < 0) {
218
0
    LM_ERR("Failed to add parameters\n");
219
0
    goto end;
220
0
  }
221
222
0
  payload = cJSON_PrintUnformatted(ret_obj);
223
0
  if (!payload)
224
0
    LM_ERR("cannot print json object!\n");
225
226
0
end:
227
0
  cJSON_Delete(ret_obj);
228
0
  return payload;
229
0
}
230
231
void evi_free_payload(char *payload)
232
0
{
233
0
  cJSON_PurgeString(payload);
234
0
}