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