Merge pull request #2326 from NGSegovia/keepalive/first_check_on_start
[sip-router] / src / modules / jansson / jansson_funcs.c
1 /**
2  * Copyright (C) 2013 Flowroute LLC (flowroute.com)
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * This file 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  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <jansson.h>
26
27 #include "../../core/mod_fix.h"
28 #include "../../core/lvalue.h"
29 #include "../../core/str.h"
30
31 #include "jansson_path.h"
32 #include "jansson_funcs.h"
33 #include "jansson_utils.h"
34
35 int janssonmod_get_helper(sip_msg_t* msg, str *path_s, str *src_s, pv_spec_t *dst_pv)
36 {
37         char c;
38         pv_value_t dst_val;
39         json_t* json = NULL;
40         json_error_t parsing_error;
41         STR_VTOZ(src_s->s[src_s->len], c);
42         json = json_loads(src_s->s, JSON_REJECT_DUPLICATES, &parsing_error);
43         STR_ZTOV(src_s->s[src_s->len], c);
44         if(!json) {
45                 ERR("failed to parse json: %.*s\n", src_s->len, src_s->s);
46                 ERR("json error at line %d, col %d: %s\n",
47                                 parsing_error.line, parsing_error.column, parsing_error.text);
48                 goto fail;
49         }
50
51         char* path = path_s->s;
52
53         json_t* v = json_path_get(json, path);
54         if(!v) {
55                 goto fail;
56         }
57
58         char* freeme = NULL;
59
60         if(jansson_to_val(&dst_val, &freeme, v)<0) goto fail;
61
62         dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);
63
64         if(freeme!=NULL) {
65                 free(freeme);
66         }
67
68         json_decref(json);
69         return 1;
70
71 fail:
72         json_decref(json);
73         return -1;
74 }
75
76 int janssonmod_get(struct sip_msg* msg, char* path_in, char* src_in, char* dst)
77 {
78         str src_s;
79         str path_s;
80
81         if (fixup_get_svalue(msg, (gparam_p)src_in, &src_s) != 0) {
82                 ERR("cannot get json string value\n");
83                 return -1;
84         }
85
86         if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0) {
87                 ERR("cannot get path string value\n");
88                 return -1;
89         }
90
91         return janssonmod_get_helper(msg, &path_s, &src_s, (pv_spec_t *)dst);
92 }
93
94 #define STR_EQ_STATIC(a,b) ((a.len == sizeof(b)-1) && (strncmp(a.s, b, sizeof(b)-1)==0))
95
96 int janssonmod_set(unsigned int append, struct sip_msg* msg, char* type_in,
97                  char* path_in, char* value_in, char* result_in)
98 {
99         str type_s;
100         str value_s;
101         str path_s;
102         char c;
103         pv_spec_t* result_pv;
104         pv_value_t result_val;
105
106         if (fixup_get_svalue(msg, (gparam_p)type_in, &type_s) != 0){
107                 ERR("cannot get type string value\n");
108                 return -1;
109         }
110
111         if (fixup_get_svalue(msg, (gparam_p)value_in, &value_s) != 0){
112                 ERR("cannot get value string\n");
113                 return -1;
114         }
115
116         if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0){
117                 ERR("cannot get path string value\n");
118                 return -1;
119         }
120
121         result_pv = (pv_spec_t *)result_in;
122
123         if(pv_get_spec_value(msg, result_pv, &result_val)!=0
124                         || result_val.flags != PV_VAL_STR) {
125                 result_val.flags = PV_VAL_STR;
126                 result_val.rs.s = "{}";
127                 result_val.rs.len = strlen("{}");
128         }
129
130
131         LM_DBG("type is: %.*s\n", type_s.len, type_s.s);
132         LM_DBG("path is: %.*s\n", path_s.len, path_s.s);
133         LM_DBG("value is: %.*s\n", value_s.len, value_s.s);
134         LM_DBG("result is: %.*s\n", result_val.rs.len, result_val.rs.s);
135
136         json_t* result_json = NULL;
137         json_t* value = NULL;
138         char* freeme = NULL;
139         json_error_t parsing_error = {0};
140         char* endptr;
141
142         /* check the type */
143         if(STR_EQ_STATIC(type_s, "object") || STR_EQ_STATIC(type_s, "obj")){
144                 STR_VTOZ(value_s.s[value_s.len], c);
145                 value = json_loads(value_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
146                 STR_ZTOV(value_s.s[value_s.len], c);
147                 if(value && !json_is_object(value)) {
148                         ERR("value to add is not an object - \"%s\"\n", path_s.s);
149                         goto fail;
150                 }
151
152         }else if(STR_EQ_STATIC(type_s, "array")) {
153                 STR_VTOZ(value_s.s[value_s.len], c);
154                 value = json_loads(value_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
155                 STR_ZTOV(value_s.s[value_s.len], c);
156                 if(value && !json_is_array(value)) {
157                         ERR("value to add is not an array - \"%s\"\n", path_s.s);
158                         goto fail;
159                 }
160
161         }else if(STR_EQ_STATIC(type_s, "string")
162                                 || STR_EQ_STATIC(type_s, "str")) {
163                 value = json_string(value_s.s);
164                 if(!value || !json_is_string(value)) {
165                         ERR("value to add is not a string - \"%s\"\n", path_s.s);
166                         goto fail;
167                 }
168
169         }else if(STR_EQ_STATIC(type_s, "integer")
170                                 || STR_EQ_STATIC(type_s, "int")) {
171                 long long i = strtoll(value_s.s, &endptr, 10);
172                 if(*endptr != '\0') {
173                         ERR("parsing int failed for \"%s\" - \"%s\"\n", path_s.s, value_s.s);
174                         goto fail;
175                 }
176                 value = json_integer(i);
177                 if(!value || !json_is_integer(value)) {
178                         ERR("value to add is not an integer \"%s\"\n", path_s.s);
179                         goto fail;
180                 }
181
182         }else if(STR_EQ_STATIC(type_s, "real")) {
183                 double d = strtod(value_s.s, &endptr);
184                 if(*endptr != '\0') {
185                         ERR("parsing real failed for \"%s\" - \"%s\"\n", path_s.s, value_s.s);
186                         goto fail;
187                 }
188                 value = json_real(d);
189                 if(!value || !json_is_real(value)) {
190                         ERR("value to add is not a real \"%s\"\n", path_s.s);
191                         goto fail;
192                 }
193
194         }else if(STR_EQ_STATIC(type_s, "true")) {
195                 value = json_true();
196
197         }else if(STR_EQ_STATIC(type_s, "false")) {
198                 value = json_false();
199
200         }else if(STR_EQ_STATIC(type_s, "null")) {
201                 value = json_null();
202
203         } else {
204                 ERR("unrecognized input type\n");
205                 goto fail;
206         }
207
208         if(!value) {
209                 ERR("parsing failed for \"%s\"\n", value_s.s);
210                 ERR("value error at line %d: %s\n",
211                                 parsing_error.line, parsing_error.text);
212                 goto fail;
213         }
214
215         char* path = path_s.s;
216         STR_VTOZ(result_val.rs.s[result_val.rs.len], c);
217         result_json = json_loads(result_val.rs.s, JSON_REJECT_DUPLICATES, &parsing_error);
218         STR_ZTOV(result_val.rs.s[result_val.rs.len], c);
219         if(!result_json) {
220                 ERR("result has json error at line %d: %s\n",
221                                 parsing_error.line, parsing_error.text);
222                 goto fail;
223         }
224
225         if(json_path_set(result_json, path, value, append)<0) {
226                 goto fail;
227         }
228
229         if(jansson_to_val(&result_val, &freeme, result_json)<0) goto fail;
230
231         result_pv->setf(msg, &result_pv->pvp, (int)EQ_T, &result_val);
232
233         if(freeme) free(freeme);
234         json_decref(result_json);
235         return 1;
236
237 fail:
238         if(freeme) free(freeme);
239         json_decref(result_json);
240         return -1;
241 }
242
243 int janssonmod_array_size(struct sip_msg* msg, char* path_in, char* src_in, char* dst)
244 {
245         char c;
246         str src_s;
247         str path_s;
248         pv_spec_t *dst_pv;
249         pv_value_t dst_val;
250
251         if (fixup_get_svalue(msg, (gparam_p)src_in, &src_s) != 0) {
252                 ERR("cannot get json string value\n");
253                 return -1;
254         }
255
256         if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0) {
257                 ERR("cannot get path string value\n");
258                 return -1;
259         }
260
261         dst_pv = (pv_spec_t *)dst;
262
263         json_t* json = NULL;
264         json_error_t parsing_error;
265         STR_VTOZ(src_s.s[src_s.len], c);
266         json = json_loads(src_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
267         STR_ZTOV(src_s.s[src_s.len], c);
268         if(!json) {
269                 ERR("json error at line %d: %s\n",
270                                 parsing_error.line, parsing_error.text);
271                 goto fail;
272         }
273
274         char* path = path_s.s;
275
276         json_t* v = json_path_get(json, path);
277         if(!v) {
278                 ERR("failed to find %s in json\n", path);
279                 goto fail;
280         }
281
282         if(!json_is_array(v)) {
283                 ERR("value at %s is not an array\n", path);
284                 goto fail;
285         }
286
287         int size = json_array_size(v);
288         dst_val.ri = size;
289         dst_val.flags = PV_TYPE_INT|PV_VAL_INT;
290
291         dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);
292
293         json_decref(json);
294         return 1;
295
296 fail:
297         json_decref(json);
298         return -1;
299 }