keepalive: early start of OPTIONS checking
[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
30 #include "jansson_path.h"
31 #include "jansson_funcs.h"
32 #include "jansson_utils.h"
33
34 int janssonmod_get_helper(sip_msg_t* msg, str *path_s, str *src_s, pv_spec_t *dst_pv)
35 {
36
37         pv_value_t dst_val;
38         json_t* json = NULL;
39         json_error_t parsing_error;
40
41         json = json_loads(src_s->s, JSON_REJECT_DUPLICATES, &parsing_error);
42
43         if(!json) {
44                 ERR("failed to parse json: %.*s\n", src_s->len, src_s->s);
45                 ERR("json error at line %d, col %d: %s\n",
46                                 parsing_error.line, parsing_error.column, parsing_error.text);
47                 goto fail;
48         }
49
50         char* path = path_s->s;
51
52         json_t* v = json_path_get(json, path);
53         if(!v) {
54                 goto fail;
55         }
56
57         char* freeme = NULL;
58
59         if(jansson_to_val(&dst_val, &freeme, v)<0) goto fail;
60
61         dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);
62
63         if(freeme!=NULL) {
64                 free(freeme);
65         }
66
67         json_decref(json);
68         return 1;
69
70 fail:
71         json_decref(json);
72         return -1;
73 }
74
75 int janssonmod_get(struct sip_msg* msg, char* path_in, char* src_in, char* dst)
76 {
77         str src_s;
78         str path_s;
79
80         if (fixup_get_svalue(msg, (gparam_p)src_in, &src_s) != 0) {
81                 ERR("cannot get json string value\n");
82                 return -1;
83         }
84
85         if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0) {
86                 ERR("cannot get path string value\n");
87                 return -1;
88         }
89
90         return janssonmod_get_helper(msg, &path_s, &src_s, (pv_spec_t *)dst);
91 }
92
93 #define STR_EQ_STATIC(a,b) ((a.len == sizeof(b)-1) && (strncmp(a.s, b, sizeof(b)-1)==0))
94
95 int janssonmod_set(unsigned int append, struct sip_msg* msg, char* type_in,
96                  char* path_in, char* value_in, char* result_in)
97 {
98         str type_s;
99         str value_s;
100         str path_s;
101
102         pv_spec_t* result_pv;
103         pv_value_t result_val;
104
105         if (fixup_get_svalue(msg, (gparam_p)type_in, &type_s) != 0){
106                 ERR("cannot get type string value\n");
107                 return -1;
108         }
109
110         if (fixup_get_svalue(msg, (gparam_p)value_in, &value_s) != 0){
111                 ERR("cannot get value string\n");
112                 return -1;
113         }
114
115         if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0){
116                 ERR("cannot get path string value\n");
117                 return -1;
118         }
119
120         result_pv = (pv_spec_t *)result_in;
121
122         if(pv_get_spec_value(msg, result_pv, &result_val)!=0
123                         || result_val.flags != PV_VAL_STR) {
124                 result_val.flags = PV_VAL_STR;
125                 result_val.rs.s = "{}";
126                 result_val.rs.len = strlen("{}");
127         }
128
129 /*
130         ALERT("type is: %.*s\n", type_s.len, type_s.s);
131         ALERT("path is: %.*s\n", path_s.len, path_s.s);
132         ALERT("value is: %.*s\n", value_s.len, value_s.s);
133         ALERT("result is: %.*s\n", result_val.rs.len, result_val.rs.s);
134 */
135
136         char* result = result_val.rs.s;
137
138         json_t* result_json = NULL;
139         json_t* value = NULL;
140         char* freeme = NULL;
141         json_error_t parsing_error = {0};
142         char* endptr;
143
144         /* check the type */
145         if(STR_EQ_STATIC(type_s, "object") || STR_EQ_STATIC(type_s, "obj")){
146                 value = json_loads(value_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
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                 value = json_loads(value_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
154                 if(value && !json_is_array(value)) {
155                         ERR("value to add is not an array - \"%s\"\n", path_s.s);
156                         goto fail;
157                 }
158
159         }else if(STR_EQ_STATIC(type_s, "string")
160                                 || STR_EQ_STATIC(type_s, "str")) {
161                 value = json_string(value_s.s);
162                 if(!value || !json_is_string(value)) {
163                         ERR("value to add is not a string - \"%s\"\n", path_s.s);
164                         goto fail;
165                 }
166
167         }else if(STR_EQ_STATIC(type_s, "integer")
168                                 || STR_EQ_STATIC(type_s, "int")) {
169                 long long i = strtoll(value_s.s, &endptr, 10);
170                 if(*endptr != '\0') {
171                         ERR("parsing int failed for \"%s\" - \"%s\"\n", path_s.s, value_s.s);
172                         goto fail;
173                 }
174                 value = json_integer(i);
175                 if(!value || !json_is_integer(value)) {
176                         ERR("value to add is not an integer \"%s\"\n", path_s.s);
177                         goto fail;
178                 }
179
180         }else if(STR_EQ_STATIC(type_s, "real")) {
181                 double d = strtod(value_s.s, &endptr);
182                 if(*endptr != '\0') {
183                         ERR("parsing real failed for \"%s\" - \"%s\"\n", path_s.s, value_s.s);
184                         goto fail;
185                 }
186                 value = json_real(d);
187                 if(!value || !json_is_real(value)) {
188                         ERR("value to add is not a real \"%s\"\n", path_s.s);
189                         goto fail;
190                 }
191
192         }else if(STR_EQ_STATIC(type_s, "true")) {
193                 value = json_true();
194
195         }else if(STR_EQ_STATIC(type_s, "false")) {
196                 value = json_false();
197
198         }else if(STR_EQ_STATIC(type_s, "null")) {
199                 value = json_null();
200
201         } else {
202                 ERR("unrecognized input type\n");
203                 goto fail;
204         }
205
206         if(!value) {
207                 ERR("parsing failed for \"%s\"\n", value_s.s);
208                 ERR("value error at line %d: %s\n",
209                                 parsing_error.line, parsing_error.text);
210                 goto fail;
211         }
212
213         char* path = path_s.s;
214
215         result_json = json_loads(result, JSON_REJECT_DUPLICATES, &parsing_error);
216
217         if(!result_json) {
218                 ERR("result has json error at line %d: %s\n",
219                                 parsing_error.line, parsing_error.text);
220                 goto fail;
221         }
222
223         if(json_path_set(result_json, path, value, append)<0) {
224                 goto fail;
225         }
226
227         if(jansson_to_val(&result_val, &freeme, result_json)<0) goto fail;
228
229         result_pv->setf(msg, &result_pv->pvp, (int)EQ_T, &result_val);
230
231         if(freeme) free(freeme);
232         json_decref(result_json);
233         return 1;
234
235 fail:
236         if(freeme) free(freeme);
237         json_decref(result_json);
238         return -1;
239 }
240
241 int janssonmod_array_size(struct sip_msg* msg, char* path_in, char* src_in, char* dst)
242 {
243         str src_s;
244         str path_s;
245         pv_spec_t *dst_pv;
246         pv_value_t dst_val;
247
248         if (fixup_get_svalue(msg, (gparam_p)src_in, &src_s) != 0) {
249                 ERR("cannot get json string value\n");
250                 return -1;
251         }
252
253         if (fixup_get_svalue(msg, (gparam_p)path_in, &path_s) != 0) {
254                 ERR("cannot get path string value\n");
255                 return -1;
256         }
257
258         dst_pv = (pv_spec_t *)dst;
259
260         json_t* json = NULL;
261         json_error_t parsing_error;
262
263         json = json_loads(src_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
264
265         if(!json) {
266                 ERR("json error at line %d: %s\n",
267                                 parsing_error.line, parsing_error.text);
268                 goto fail;
269         }
270
271         char* path = path_s.s;
272
273         json_t* v = json_path_get(json, path);
274         if(!v) {
275                 ERR("failed to find %s in json\n", path);
276                 goto fail;
277         }
278
279         if(!json_is_array(v)) {
280                 ERR("value at %s is not an array\n", path);
281                 goto fail;
282         }
283
284         int size = json_array_size(v);
285         dst_val.ri = size;
286         dst_val.flags = PV_TYPE_INT|PV_VAL_INT;
287
288         dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);
289
290         json_decref(json);
291         return 1;
292
293 fail:
294         json_decref(json);
295         return -1;
296 }