1 /**
2 * Copyright (C) 2015 Daniel-Constantin Mierla (asipto.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "../../core/dprint.h"
29 #include "../../core/xavp.h"
30 #include "../../core/dset.h"
31 #include "../../core/mem/shm_mem.h"
32 #include "../../core/data_lump.h"
33 #include "../../core/utils/srjson.h"
34 #include "../../modules/tm/tm_load.h"
35 #include "../../modules/uac/api.h"
36
37 #include "rtjson_routing.h"
38
39 typedef struct rtjson_data {
40 srjson_doc_t *jdoc;
41 int idx;
42 } rtjson_data_t;
43
44 extern str _rtjson_xavp_name;
45
46 int rtjson_init_serial(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp);
47 int rtjson_init_parallel(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp);
48
49 /* tm */
50 static struct tm_binds tmb;
51 /* uac */
52 static uac_api_t uacb;
53
rtjson_init(void)54 int rtjson_init(void)
55 {
56 if (load_tm_api( &tmb ) == -1) {
57 LM_NOTICE("cannot load the TM API - some features are disabled\n");
58 memset(&tmb, 0, sizeof(struct tm_binds));
59 }
60 if (load_uac_api(&uacb) < 0) {
61 LM_NOTICE("cannot bind to UAC API - some features are disabled\n");
62 memset(&uacb, 0, sizeof(uac_api_t));
63 }
64 return 0;
65 }
66
67 #ifdef RTJSON_STORE_SHM
68 /**
69 *
70 */
rtjson_data_free(void * ptr,sr_xavp_sfree_f sfree)71 void rtjson_data_free(void *ptr, sr_xavp_sfree_f sfree)
72 {
73 rtjson_data_t *rdata;
74
75 rdata = (rtjson_data_t*)ptr;
76
77 if(rdata->jdoc) {
78 rdata->jdoc->free_fn = sfree;
79 srjson_DeleteDoc(rdata->jdoc);
80 }
81 sfree(ptr);
82 }
83
84 /**
85 *
86 */
rtjson_malloc(size_t sz)87 void *rtjson_malloc(size_t sz)
88 {
89 return shm_malloc(sz);
90 }
91
92 /**
93 *
94 */
rtjson_free(void * ptr)95 void rtjson_free(void *ptr)
96 {
97 shm_free(ptr);
98 }
99
100 /**
101 *
102 */
rtjson_init_routes(sip_msg_t * msg,str * rdoc)103 int rtjson_init_routes(sip_msg_t *msg, str *rdoc)
104 {
105 srjson_Hooks jhooks;
106 srjson_doc_t *tdoc = NULL;
107 sr_data_t *xdata = NULL;
108 rtjson_data_t *rdata = NULL;
109 sr_xavp_t *xavp=NULL;
110 str xname;
111 sr_xval_t xval;
112
113
114 memset(&jhooks, 0, sizeof(srjson_Hooks));
115 jhooks.malloc_fn = rtjson_malloc;
116 jhooks.free_fn = rtjson_free;
117
118 tdoc = srjson_NewDoc(&jhooks);
119
120 if(tdoc==NULL) {
121 LM_ERR("no more shm\n");
122 return -1;
123 }
124 tdoc->root = srjson_Parse(tdoc, rdoc->s);
125 if(tdoc->root == NULL) {
126 LM_ERR("invalid json doc [[%s]]\n", rdoc->s);
127 srjson_DeleteDoc(tdoc);
128 return -1;
129 }
130 xdata = shm_malloc(sizeof(sr_data_t));
131 if(xdata==NULL) {
132 LM_ERR("no more shm\n");
133 srjson_DeleteDoc(tdoc);
134 return -1;
135 }
136 memset(xdata, 0, sizeof(sr_data_t));
137 rdata = shm_malloc(sizeof(rtjson_data_t));
138 if(rdata==NULL) {
139 LM_ERR("no more shm\n");
140 srjson_DeleteDoc(tdoc);
141 shm_free(xdata);
142 return -1;
143 }
144 memset(rdata, 0, sizeof(rtjson_data_t));
145
146 rdata->jdoc = tdoc;
147 xdata->p = rdata;
148 xdata->pfree = rtjson_data_free;
149
150 memset(&xval, 0, sizeof(sr_xval_t));
151 xval.type = SR_XTYPE_STR;
152 xval.v.s = *rdoc;
153 xname.s = "json";
154 xname.len = 4;
155 if(xavp_add_value(&xname, &xval, &xavp)==NULL) {
156 goto error;
157 }
158
159 memset(&xval, 0, sizeof(sr_xval_t));
160 xval.type = SR_XTYPE_DATA;
161 xval.v.data = xdata;
162 xname.s = "data";
163 xname.len = 4;
164 if(xavp_add_value(&xname, &xval, &xavp)==NULL) {
165 goto error;
166 }
167 /* reset pointers - they are linked inside xavp now */
168 tdoc = NULL;
169 xdata = NULL;
170 rdata = NULL;
171
172 memset(&xval, 0, sizeof(sr_xval_t));
173 xval.type = SR_XTYPE_XAVP;
174 xval.v.xavp = xavp;
175 if(xavp_add_value(&_rtjson_xavp_name, &xval, NULL)==NULL) {
176 goto error;
177 }
178
179 return 0;
180 error:
181 if(xavp) xavp_destroy_list(&xavp);
182 if(rdata) shm_free(rdata);
183 if(xdata) shm_free(xdata);
184 if(tdoc) srjson_DeleteDoc(tdoc);
185 return -1;
186 }
187 #else
188
189 /**
190 *
191 */
rtjson_init_routes(sip_msg_t * msg,str * rdoc)192 int rtjson_init_routes(sip_msg_t *msg, str *rdoc)
193 {
194 sr_xavp_t *xavp=NULL;
195 str xname;
196 sr_xval_t xval;
197 srjson_doc_t tdoc;
198
199 srjson_InitDoc(&tdoc, NULL);
200
201 tdoc.root = srjson_Parse(&tdoc, rdoc->s);
202 if(tdoc.root == NULL) {
203 LM_ERR("invalid json doc [[%s]]\n", rdoc->s);
204 srjson_DestroyDoc(&tdoc);
205 return -1;
206 }
207
208 /* basic validation */
209
210 srjson_DestroyDoc(&tdoc);
211
212 memset(&xval, 0, sizeof(sr_xval_t));
213 xval.type = SR_XTYPE_INT;
214 xval.v.i = 0;
215 xname.s = "idx";
216 xname.len = 3;
217 if(xavp_add_value(&xname, &xval, &xavp)==NULL) {
218 goto error;
219 }
220
221 memset(&xval, 0, sizeof(sr_xval_t));
222 xval.type = SR_XTYPE_STR;
223 xval.v.s = *rdoc;
224 xname.s = "json";
225 xname.len = 4;
226 if(xavp_add_value(&xname, &xval, &xavp)==NULL) {
227 goto error;
228 }
229
230 memset(&xval, 0, sizeof(sr_xval_t));
231 xval.type = SR_XTYPE_XAVP;
232 xval.v.xavp = xavp;
233 if(xavp_add_value(&_rtjson_xavp_name, &xval, NULL)==NULL) {
234 goto error;
235 }
236
237 return 0;
238
239 error:
240 if(xavp) xavp_destroy_list(&xavp);
241 return -1;
242 }
243 #endif
244
245 /**
246 *
247 */
rtjson_push_routes(sip_msg_t * msg)248 int rtjson_push_routes(sip_msg_t *msg)
249 {
250 sr_xavp_t *javp = NULL;
251 sr_xavp_t *iavp = NULL;
252 srjson_doc_t tdoc;
253 srjson_t *nj = NULL;
254 str val;
255 str xname;
256 int ret;
257
258 xname.s = "json";
259 xname.len = 4;
260 javp = xavp_get_child_with_sval(&_rtjson_xavp_name, &xname);
261 if(javp==NULL || javp->val.v.s.len<=0) {
262 LM_WARN("no json for routing\n");
263 return -1;
264 }
265
266 xname.s = "idx";
267 xname.len = 3;
268 iavp = xavp_get_child_with_ival(&_rtjson_xavp_name, &xname);
269 if(iavp==NULL) {
270 LM_WARN("no idx for routing\n");
271 return -1;
272 }
273
274 LM_DBG("routes index: %d\n", iavp->val.v.i);
275
276 srjson_InitDoc(&tdoc, NULL);
277
278 tdoc.root = srjson_Parse(&tdoc, javp->val.v.s.s);
279 if(tdoc.root == NULL) {
280 LM_ERR("invalid json doc [[%s]]\n", javp->val.v.s.s);
281 srjson_DestroyDoc(&tdoc);
282 return -1;
283 }
284
285 nj = srjson_GetObjectItem(&tdoc, tdoc.root, "routing");
286 if(nj==NULL || nj->valuestring==NULL) {
287 LM_ERR("missing or invalid routing field\n");
288 goto error;
289 }
290 val.s = nj->valuestring;
291 val.len = strlen(val.s);
292
293 if(val.len==6 && strncmp(val.s, "serial", 6)==0) {
294 LM_DBG("supported routing [%.*s]\n", val.len, val.s);
295 ret = rtjson_init_serial(msg, &tdoc, iavp);
296 } else if(val.len==8 && strncmp(val.s, "parallel", 8)==0) {
297 LM_DBG("supported routing [%.*s]\n", val.len, val.s);
298 ret = rtjson_init_parallel(msg, &tdoc, iavp);
299 } else {
300 LM_ERR("unsupported routing [%.*s]\n", val.len, val.s);
301 goto error;
302 }
303
304 srjson_DestroyDoc(&tdoc);
305 return ret;
306
307 error:
308 srjson_DestroyDoc(&tdoc);
309 return -1;
310 }
311
312 /**
313 *
314 */
rtjson_init_serial(sip_msg_t * msg,srjson_doc_t * jdoc,sr_xavp_t * iavp)315 int rtjson_init_serial(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp)
316 {
317 srjson_t *tj = NULL;
318 srjson_t *nj = NULL;
319 srjson_t *rj = NULL;
320 str val;
321 unsigned int bflags = 0;
322 unsigned int old_bflags = 0;
323 struct socket_info* fsocket = NULL;
324
325 tj = srjson_GetObjectItem(jdoc, jdoc->root, "routes");
326 if(tj==NULL || tj->type!=srjson_Array || tj->child==NULL) {
327 LM_ERR("missing or invalid routes field\n");
328 goto error;
329 }
330 nj = tj->child;
331
332 clear_branches();
333
334 rj = srjson_GetObjectItem(jdoc, nj, "uri");
335 if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
336 val.s = rj->valuestring;
337 val.len = strlen(val.s);
338 LM_DBG("rewrite r-uri to: [%.*s]\n", val.len, val.s);
339 if (rewrite_uri(msg, &val) < 0) {
340 LM_ERR("unable to rewrite Request-URI\n");
341 goto error;
342 }
343 }
344
345 reset_dst_uri(msg);
346 reset_path_vector(msg);
347 reset_instance(msg);
348 reset_ruid(msg);
349 reset_ua(msg);
350 reset_force_socket(msg);
351 msg->reg_id = 0;
352 set_ruri_q(0);
353
354 rj = srjson_GetObjectItem(jdoc, nj, "dst_uri");
355 if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
356 val.s = rj->valuestring;
357 val.len = strlen(val.s);
358 LM_DBG("rewrite dst-uri to: [%.*s]\n", val.len, val.s);
359 if (set_dst_uri(msg, &val) < 0) {
360 LM_ERR("unable to set destination uri\n");
361 goto error;
362 }
363 }
364 /* mark for new branching */
365 ruri_mark_new();
366
367 rj = srjson_GetObjectItem(jdoc, nj, "path");
368 if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
369 val.s = rj->valuestring;
370 val.len = strlen(val.s);
371 LM_DBG("rewrite path to: [%.*s]\n", val.len, val.s);
372 if (set_path_vector(msg, &val) < 0) {
373 LM_ERR("unable to set path\n");
374 goto error;
375 }
376 }
377
378 rj = srjson_GetObjectItem(jdoc, nj, "socket");
379 if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
380 val.s = rj->valuestring;
381 val.len = strlen(val.s);
382 LM_DBG("trying to set send socket to: [%.*s]\n", val.len, val.s);
383 fsocket = lookup_local_socket(&val);
384 if(fsocket) {
385 set_force_socket(msg, fsocket);
386 }
387 }
388
389 rj = srjson_GetObjectItem(jdoc, nj, "branch_flags");
390 if(rj!=NULL && rj->type==srjson_Number && SRJSON_GET_UINT(rj)!=0) {
391 bflags = SRJSON_GET_UINT(rj);
392
393 old_bflags = 0;
394 getbflagsval(0, &old_bflags);
395 setbflagsval(0, old_bflags|bflags);
396 }
397
398 iavp->val.v.i++;
399
400 return 0;
401
402 error:
403 return -1;
404 }
405
406 /**
407 *
408 */
rtjson_prepare_branch(sip_msg_t * msg,srjson_doc_t * jdoc,srjson_t * nj)409 int rtjson_prepare_branch(sip_msg_t *msg, srjson_doc_t *jdoc, srjson_t *nj)
410 {
411 srjson_t *rj = NULL;
412 srjson_t *tj = NULL;
413 srjson_t *vj = NULL;
414 str xdsp = {0};
415 str xuri = {0};
416 str xhdr = {0};
417 unsigned int fr = 0;
418 unsigned int fr_inv = 0;
419 struct lump *anchor = NULL;
420 char *s;
421
422
423 if(tmb.set_fr!=NULL) {
424 rj = srjson_GetObjectItem(jdoc, nj, "fr_timer");
425 if(rj!=NULL && rj->type==srjson_Number && SRJSON_GET_UINT(rj)!=0) {
426 fr = SRJSON_GET_UINT(rj);
427 }
428 rj = srjson_GetObjectItem(jdoc, nj, "fr_inv_timer");
429 if(rj!=NULL && rj->type==srjson_Number && SRJSON_GET_UINT(rj)!=0) {
430 fr_inv = SRJSON_GET_UINT(rj);
431 }
432 if(fr || fr_inv) tmb.set_fr(msg, fr_inv, fr);
433 }
434 rj = srjson_GetObjectItem(jdoc, nj, "headers");
435 if(rj==NULL || rj->type!=srjson_Object || rj->child==NULL) {
436 LM_DBG("no header operations - done\n");
437 return 0;
438 }
439
440 tj = srjson_GetObjectItem(jdoc, rj, "extra");
441 if(tj!=NULL && tj->type==srjson_String && tj->valuestring!=0) {
442 xhdr.s = tj->valuestring;
443 xhdr.len = strlen(xhdr.s);
444 }
445
446 if(xhdr.len>4) {
447 LM_DBG("appending extra headers: [%.*s]\n", xhdr.len, xhdr.s);
448 anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
449 if(anchor == 0) {
450 LM_ERR("can't get anchor\n");
451 return -1;
452 }
453 s = pkg_malloc(xhdr.len+1);
454 if(s==NULL) {
455 LM_ERR("no more pkg\n");
456 return -1;
457 }
458 strncpy(s, xhdr.s, xhdr.len);
459 s[xhdr.len] = '\0';
460 if (insert_new_lump_before(anchor, s, xhdr.len, 0) == 0) {
461 LM_ERR("can't insert lump\n");
462 pkg_free(s);
463 return -1;
464 }
465 }
466
467 if(uacb.replace_from!=NULL) {
468 tj = srjson_GetObjectItem(jdoc, rj, "from");
469 if(tj!=NULL && tj->type==srjson_Object && rj->child!=NULL) {
470 vj = srjson_GetObjectItem(jdoc, tj, "display");
471 if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) {
472 xdsp.s = vj->valuestring;
473 xdsp.len = strlen(xdsp.s);
474 }
475 vj = srjson_GetObjectItem(jdoc, tj, "uri");
476 if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) {
477 xuri.s = vj->valuestring;
478 xuri.len = strlen(xuri.s);
479 }
480 if(xdsp.len>0 || xuri.len>0) {
481 uacb.replace_from(msg, &xdsp, &xuri);
482 }
483 }
484 }
485
486 if(uacb.replace_to!=NULL) {
487 tj = srjson_GetObjectItem(jdoc, rj, "to");
488 if(tj!=NULL && tj->type==srjson_Object && rj->child!=NULL) {
489 vj = srjson_GetObjectItem(jdoc, tj, "display");
490 if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) {
491 xdsp.s = vj->valuestring;
492 xdsp.len = strlen(xdsp.s);
493 }
494 vj = srjson_GetObjectItem(jdoc, tj, "uri");
495 if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) {
496 xuri.s = vj->valuestring;
497 xuri.len = strlen(xuri.s);
498 }
499 if(xdsp.len>0 || xuri.len>0) {
500 uacb.replace_to(msg, &xdsp, &xuri);
501 }
502 }
503 }
504
505 return 0;
506 }
507
508 /**
509 *
510 */
rtjson_append_branch(sip_msg_t * msg,srjson_doc_t * jdoc,srjson_t * nj)511 int rtjson_append_branch(sip_msg_t *msg, srjson_doc_t *jdoc, srjson_t *nj)
512 {
513 srjson_t *rj = NULL;
514 str uri = {0};
515 str duri = {0};
516 str path = {0};
517 str socket = {0};
518 struct socket_info* fsocket = NULL;
519 unsigned int bflags = 0;
520
521 rj = srjson_GetObjectItem(jdoc, nj, "uri");
522 if(rj==NULL || rj->type!=srjson_String || rj->valuestring==NULL) {
523 if (msg->new_uri.s!=NULL) {
524 uri = msg->new_uri;
525 } else {
526 uri = msg->first_line.u.request.uri;
527 }
528 } else {
529 uri.s = rj->valuestring;
530 uri.len = strlen(uri.s);
531 }
532
533 rj = srjson_GetObjectItem(jdoc, nj, "dst_uri");
534 if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
535 duri.s = rj->valuestring;
536 duri.len = strlen(duri.s);
537 }
538 rj = srjson_GetObjectItem(jdoc, nj, "path");
539 if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
540 path.s = rj->valuestring;
541 path.len = strlen(path.s);
542 }
543 rj = srjson_GetObjectItem(jdoc, nj, "socket");
544 if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
545 socket.s = rj->valuestring;
546 socket.len = strlen(socket.s);
547 fsocket = lookup_local_socket(&socket);
548 }
549 if (append_branch(msg, &uri, &duri, &path, 0, bflags,
550 fsocket, 0 /*instance*/, 0,
551 0, 0) <0) {
552 LM_ERR("failed to append branch\n");
553 goto error;
554 }
555
556 return 0;
557
558 error:
559 return -1;
560 }
561
562 /**
563 *
564 */
rtjson_init_parallel(sip_msg_t * msg,srjson_doc_t * jdoc,sr_xavp_t * iavp)565 int rtjson_init_parallel(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp)
566 {
567 srjson_t *tj = NULL;
568 srjson_t *nj = NULL;
569 int ret;
570
571 tj = srjson_GetObjectItem(jdoc, jdoc->root, "routes");
572 if(tj==NULL || tj->type!=srjson_Array || tj->child==NULL) {
573 LM_ERR("missing or invalid routes field\n");
574 goto error;
575 }
576 nj = tj->child;
577
578 ret = rtjson_init_serial(msg, jdoc, iavp);
579 if(ret<0)
580 return ret;
581
582 /* skip first - used for r-uri */
583 nj = nj->next;
584
585 while(nj) {
586 rtjson_append_branch(msg, jdoc, nj);
587
588 iavp->val.v.i++;
589 nj = nj->next;
590 }
591
592 return 0;
593
594 error:
595 return -1;
596 }
597
598 /**
599 *
600 */
rtjson_next_route(sip_msg_t * msg)601 int rtjson_next_route(sip_msg_t *msg)
602 {
603 sr_xavp_t *javp = NULL;
604 sr_xavp_t *iavp = NULL;
605 srjson_doc_t tdoc;
606 srjson_t *tj = NULL;
607 srjson_t *nj = NULL;
608 str val;
609 str xname;
610 int i;
611
612 xname.s = "json";
613 xname.len = 4;
614 javp = xavp_get_child_with_sval(&_rtjson_xavp_name, &xname);
615 if(javp==NULL || javp->val.v.s.len<=0) {
616 LM_WARN("no json for routing\n");
617 return -1;
618 }
619
620 xname.s = "idx";
621 xname.len = 3;
622 iavp = xavp_get_child_with_ival(&_rtjson_xavp_name, &xname);
623 if(iavp==NULL) {
624 LM_WARN("no idx for routing\n");
625 return -1;
626 }
627
628 LM_DBG("routes index: %d\n", iavp->val.v.i);
629
630 srjson_InitDoc(&tdoc, NULL);
631
632 tdoc.root = srjson_Parse(&tdoc, javp->val.v.s.s);
633 if(tdoc.root == NULL) {
634 LM_ERR("invalid json doc [[%s]]\n", javp->val.v.s.s);
635 srjson_DestroyDoc(&tdoc);
636 return -1;
637 }
638
639 nj = srjson_GetObjectItem(&tdoc, tdoc.root, "routing");
640 if(nj==NULL || nj->valuestring==NULL) {
641 LM_ERR("missing or invalid routing field\n");
642 goto error;
643 }
644 val.s = nj->valuestring;
645 val.len = strlen(val.s);
646
647 if(val.len!=6 || strncmp(val.s, "serial", 6)!=0) {
648 LM_DBG("not serial routing [%.*s]\n", val.len, val.s);
649 goto error;
650 }
651
652 tj = srjson_GetObjectItem(&tdoc, tdoc.root, "routes");
653 if(tj==NULL || tj->type!=srjson_Array || tj->child==NULL) {
654 LM_ERR("missing or invalid routes field\n");
655 goto error;
656 }
657 nj = tj->child;
658
659 i = 0;
660 while(nj && i<iavp->val.v.i) {
661 nj = nj->next;
662 i++;
663 }
664 if(nj==NULL) {
665 LM_DBG("no route at index: %d\n", iavp->val.v.i);
666 goto error;
667 }
668
669 iavp->val.v.i++;
670 if(rtjson_append_branch(msg, &tdoc, nj)<0) {
671 LM_DBG("route index %d not appended\n", iavp->val.v.i);
672 goto error;
673 }
674
675 srjson_DestroyDoc(&tdoc);
676 return 0;
677
678 error:
679 srjson_DestroyDoc(&tdoc);
680 return -1;
681 }
682
683 /**
684 *
685 */
rtjson_update_branch(sip_msg_t * msg)686 int rtjson_update_branch(sip_msg_t *msg)
687 {
688 sr_xavp_t *javp = NULL;
689 sr_xavp_t *iavp = NULL;
690 srjson_doc_t tdoc;
691 srjson_t *tj = NULL;
692 srjson_t *nj = NULL;
693 str val;
694 str xname;
695 int i;
696
697 xname.s = "json";
698 xname.len = 4;
699 javp = xavp_get_child_with_sval(&_rtjson_xavp_name, &xname);
700 if(javp==NULL || javp->val.v.s.len<=0) {
701 LM_WARN("no json for routing\n");
702 return -1;
703 }
704
705 xname.s = "idx";
706 xname.len = 3;
707 iavp = xavp_get_child_with_ival(&_rtjson_xavp_name, &xname);
708 if(iavp==NULL) {
709 LM_WARN("no idx for routing\n");
710 return -1;
711 }
712 if(iavp->val.v.i<=0) {
713 LM_WARN("invalid branch idx for routing\n");
714 return -1;
715 }
716
717 srjson_InitDoc(&tdoc, NULL);
718
719 tdoc.root = srjson_Parse(&tdoc, javp->val.v.s.s);
720 if(tdoc.root == NULL) {
721 LM_ERR("invalid json doc [[%s]]\n", javp->val.v.s.s);
722 srjson_DestroyDoc(&tdoc);
723 return -1;
724 }
725
726 nj = srjson_GetObjectItem(&tdoc, tdoc.root, "routing");
727 if(nj==NULL || nj->valuestring==NULL) {
728 LM_ERR("missing or invalid routing field\n");
729 goto error;
730 }
731 val.s = nj->valuestring;
732 val.len = strlen(val.s);
733
734 if(val.len!=6 || strncmp(val.s, "serial", 6)!=0) {
735 LM_DBG("not serial routing [%.*s]\n", val.len, val.s);
736 goto error;
737 }
738
739 tj = srjson_GetObjectItem(&tdoc, tdoc.root, "routes");
740 if(tj==NULL || tj->type!=srjson_Array || tj->child==NULL) {
741 LM_ERR("missing or invalid routes field\n");
742 goto error;
743 }
744 nj = tj->child;
745
746 i = 0;
747 /* stop at number of branches - 1 */
748 while(nj && i<iavp->val.v.i-1) {
749 nj = nj->next;
750 i++;
751 }
752 if(nj==NULL)
753 goto error;
754
755 if(rtjson_prepare_branch(msg, &tdoc, nj)<0)
756 goto error;
757
758 srjson_DestroyDoc(&tdoc);
759 return 0;
760
761 error:
762 srjson_DestroyDoc(&tdoc);
763 return -1;
764
765 }
766
767