1 /*
2 * Serial forking functions
3 *
4 * Copyright (C) 2008 Juha Heinanen
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 * EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
28 #include "../../core/qvalue.h"
29 #include "../../core/mem/mem.h"
30 #include "../../core/socket_info.h"
31 #include "../../core/usr_avp.h"
32 #include "../../core/dset.h"
33 #include "../../core/parser/msg_parser.h"
34 #include "../../core/ut.h"
35 #include "../../core/xavp.h"
36 #include "../../core/sr_module.h"
37 #include "../../core/rand/kam_rand.h"
38 #include "config.h"
39 #include "t_funcs.h"
40 #include "t_reply.h"
41 #include "t_lookup.h"
42
43 /* usr_avp flag for sequential forking */
44 #define Q_FLAG (1<<2)
45 /* t_load_contacts modes/algorithms */
46 #define T_LOAD_STANDARD 0
47 #define T_LOAD_PROPORTIONAL 1
48
49 extern str ulattrs_xavp_name;
50
51 /* Struture where information regarding contacts is stored */
52 struct contact {
53 str uri;
54 qvalue_t q;
55 str dst_uri;
56 str path;
57 struct socket_info* sock;
58 str instance;
59 str ruid;
60 str location_ua;
61 unsigned int flags;
62 unsigned short q_flag;
63 struct contact *next;
64 sr_xavp_t *ulattrs;
65 unsigned short q_index;
66 };
67
68 struct instance_list {
69 str instance;
70 struct instance_list *next;
71 };
72
73 /*
74 * Frees contact list used by load_contacts function
75 */
free_contact_list(struct contact * curr)76 static inline void free_contact_list(struct contact *curr) {
77 struct contact *prev;
78 while (curr) {
79 prev = curr;
80 curr = curr->next;
81 pkg_free(prev);
82 }
83 }
84
85 /*
86 * Frees instance list used by next_contacts function
87 */
free_instance_list(struct instance_list * curr)88 static inline void free_instance_list(struct instance_list *curr) {
89 struct instance_list *prev;
90 while (curr) {
91 pkg_free(curr->instance.s);
92 prev = curr;
93 curr = curr->next;
94 pkg_free(prev);
95 }
96 }
97
98 static str uri_name = {"uri", 3};
99 static str dst_uri_name = {"dst_uri", 7};
100 static str path_name = {"path", 4};
101 static str sock_name = {"sock", 4};
102 static str instance_name = {"instance", 8};
103 static str flags_name = {"flags", 5};
104 static str q_flag_name = {"q_flag", 6};
105 static str ruid_name = {"ruid", 4};
106 static str ua_name = {"ua", 2};
107
add_contacts_avp(str * uri,str * dst_uri,str * path,str * sock_str,unsigned int flags,unsigned int q_flag,str * instance,str * ruid,str * location_ua,sr_xavp_t * ulattrs_xavp,sr_xavp_t ** pxavp)108 void add_contacts_avp(str *uri, str *dst_uri, str *path, str *sock_str,
109 unsigned int flags, unsigned int q_flag, str *instance,
110 str *ruid, str *location_ua, sr_xavp_t *ulattrs_xavp,
111 sr_xavp_t **pxavp)
112 {
113 sr_xavp_t *record;
114 sr_xval_t val;
115
116 record = NULL;
117
118 val.type = SR_XTYPE_STR;
119 val.v.s = *uri;
120 xavp_add_value(&uri_name, &val, &record);
121
122 if (dst_uri->len > 0) {
123 val.type = SR_XTYPE_STR;
124 val.v.s = *dst_uri;
125 xavp_add_value(&dst_uri_name, &val, &record);
126 }
127
128 if (path->len > 0) {
129 val.type = SR_XTYPE_STR;
130 val.v.s = *path;
131 xavp_add_value(&path_name, &val, &record);
132 }
133
134 if (sock_str->len > 0) {
135 val.v.s = *sock_str;
136 xavp_add_value(&sock_name, &val, &record);
137 }
138
139 val.type = SR_XTYPE_INT;
140 val.v.i = flags;
141 xavp_add_value(&flags_name, &val, &record);
142
143 val.type = SR_XTYPE_INT;
144 val.v.i = q_flag;
145 xavp_add_value(&q_flag_name, &val, &record);
146
147 if (instance->len > 0) {
148 val.type = SR_XTYPE_STR;
149 val.v.s = *instance;
150 xavp_add_value(&instance_name, &val, &record);
151 }
152
153 if (ruid->len > 0) {
154 val.type = SR_XTYPE_STR;
155 val.v.s = *ruid;
156 xavp_add_value(&ruid_name, &val, &record);
157 }
158
159 if (location_ua->len > 0) {
160 val.type = SR_XTYPE_STR;
161 val.v.s = *location_ua;
162 xavp_add_value(&ua_name, &val, &record);
163 }
164
165 xavp_add(xavp_clone_level_nodata(ulattrs_xavp), &record);
166
167 val.type = SR_XTYPE_XAVP;
168 val.v.xavp = record;
169 if(pxavp) {
170 if((*pxavp = xavp_add_value_after(&contacts_avp, &val, *pxavp))==NULL) {
171 /* failed to add xavps to the end of the list */
172 LM_ERR("failed to add xavps to the end of the list\n");
173 xavp_destroy_list(&record);
174 }
175 }
176 else {
177 if(xavp_add_value(&contacts_avp, &val, NULL)==NULL) {
178 /* failed to add xavps to root list */
179 LM_ERR("failed to add xavps to root list\n");
180 xavp_destroy_list(&record);
181 }
182 }
183 }
184
185 /*
186 * Socket preparation for 'add_contacts_avp' function
187 */
add_contacts_avp_preparation(struct contact * curr,char * sock_buf,sr_xavp_t ** pxavp)188 int add_contacts_avp_preparation(struct contact *curr, char *sock_buf, sr_xavp_t **pxavp)
189 {
190 str sock_str;
191 int len;
192
193 if (curr->sock) {
194 len = MAX_SOCKET_STR - 1;
195 if (socket2str(sock_buf, &len, curr->sock) < 0) {
196 LM_ERR("failed to convert socket to str\n");
197 return -1;
198 }
199 sock_buf[len] = 0;
200 sock_str.s = sock_buf;
201 sock_str.len = len + 1;
202 } else {
203 sock_str.s = 0;
204 sock_str.len = 0;
205 }
206
207 add_contacts_avp(&(curr->uri), &(curr->dst_uri), &(curr->path),
208 &sock_str, curr->flags, curr->q_flag,
209 &(curr->instance), &(curr->ruid), &(curr->location_ua),
210 curr->ulattrs, pxavp);
211
212 return 0;
213 }
214
215 /*
216 * Loads contacts in destination set into contacts_avp in reverse
217 * priority order and associated each contact with Q_FLAG telling if
218 * contact is the last one in its priority class.
219 */
t_load_contacts_standard(struct contact * contacts,char * sock_buf)220 int t_load_contacts_standard(struct contact *contacts, char *sock_buf)
221 {
222 struct contact *curr;
223
224 /* Assign values for q_flags */
225 curr = contacts;
226 curr->q_flag = 0;
227 while (curr->next) {
228 if (curr->q < curr->next->q) {
229 curr->next->q_flag = Q_FLAG;
230 } else {
231 curr->next->q_flag = 0;
232 }
233 curr = curr->next;
234 }
235
236 /* Add contacts to contacts_avp */
237 curr = contacts;
238 while (curr) {
239 if (add_contacts_avp_preparation(curr, sock_buf, NULL) < 0) {
240 return -1;
241 }
242
243 curr = curr->next;
244 }
245
246 return 0;
247 }
248
249 /*
250 * Loads contacts in destination set into contacts_avp in reverse
251 * proportional order. Each contact is associated with Q_FLAG beacuse
252 * only one contact at a time has to ring.
253 */
t_load_contacts_proportional(struct contact * contacts,char * sock_buf,int n,unsigned short q_total)254 int t_load_contacts_proportional(struct contact *contacts, char *sock_buf, int n, unsigned short q_total)
255 {
256 int q_remove, n_rand, idx;
257 struct contact *curr;
258 sr_xavp_t *lxavp = NULL;
259
260 /* Add contacts with q-value NOT equals to 0 and NOT negative to contacts_avp */
261 for (idx = 0; idx < n; idx++) {
262 q_remove = 0;
263
264 /* Generate a random number from 0 to (q_total -1) */
265 n_rand = kam_rand() % q_total;
266
267 curr = contacts;
268 while (curr) {
269 if (curr->q <= 0) {
270 curr = curr->next;
271 continue;
272 }
273
274 if (q_remove != 0) {
275 /* ALREADY FOUND */
276 curr->q_index -= q_remove;
277 }
278 else if (curr->q_index > n_rand) {
279 /* FOUND */
280 LM_DBG("proportionally selected contact with uri: %s (q: %d, random: %d, q_index: %d, q_total: %d)\n", curr->uri.s, curr->q, n_rand, curr->q_index, q_total);
281 q_remove = curr->q;
282 q_total -= q_remove;
283 curr->q_index -= q_remove;
284 curr->q_flag = Q_FLAG;
285
286 if (add_contacts_avp_preparation(curr, sock_buf, &lxavp) < 0) {
287 return -1;
288 }
289 }
290
291 curr = curr->next;
292 }
293 }
294
295 /* Add contacts with q-value equals to 0 or negative to contacts_avp */
296 curr = contacts;
297 while (curr) {
298 if (curr->q > 0) {
299 curr = curr->next;
300 continue;
301 }
302
303 LM_DBG("proportionally added backup contact with uri: %s (q: %d)\n", curr->uri.s, curr->q);
304 curr->q_flag = Q_FLAG;
305
306 if (add_contacts_avp_preparation(curr, sock_buf, &lxavp) < 0) {
307 return -1;
308 }
309
310 curr = curr->next;
311 }
312
313 return 0;
314 }
315
316 /*
317 * Loads contacts in destination set and process it. Then call
318 * 't_load_contacts_proportional' or 't_load_contacts_standard'
319 * function based on the selected ordering machanism. Finally,
320 * removes all branches from destination set.
321 */
ki_t_load_contacts_mode(struct sip_msg * msg,int mode)322 int ki_t_load_contacts_mode(struct sip_msg* msg, int mode)
323 {
324 branch_t *branch;
325 str *ruri;
326 struct contact *contacts, *next, *prev, *curr;
327 int first_idx, idx;
328 char sock_buf[MAX_SOCKET_STR];
329 unsigned short q_total = 0;
330 int n_elements = 0;
331
332 /* Check if contacts_avp has been defined */
333 if (contacts_avp.len == 0) {
334 LM_ERR("feature has been disabled - "
335 "to enable define contacts_avp module parameter");
336 return -1;
337 }
338
339 /* Check if anything needs to be done */
340 LM_DBG("nr_branches is %d - new uri mode %d\n", nr_branches, ruri_is_new);
341
342 if ((nr_branches == 0) || ((nr_branches == 1) && !ruri_is_new)) {
343 LM_DBG("nothing to do - only one contact!\n");
344 return 1;
345 }
346
347 /* Allocate memory for first contact */
348 contacts = (struct contact *)pkg_malloc(sizeof(struct contact));
349 if (!contacts) {
350 PKG_MEM_ERROR_FMT("for contact info\n");
351 return -1;
352 }
353 memset(contacts, 0, sizeof(struct contact));
354
355 if (ruri_is_new) {
356 ruri = GET_RURI(msg);
357 if (!ruri) {
358 free_contact_list(contacts);
359 LM_ERR("no Request-URI found\n");
360 return -1;
361 }
362 /* Insert Request-URI branch to first contact */
363 contacts->uri.s = ruri->s;
364 contacts->uri.len = ruri->len;
365 contacts->dst_uri = msg->dst_uri;
366 contacts->sock = msg->force_send_socket;
367 getbflagsval(0, &contacts->flags);
368 contacts->path = msg->path_vec;
369 contacts->q = get_ruri_q();
370 contacts->instance = msg->instance;
371 contacts->ruid = msg->ruid;
372 contacts->location_ua = msg->location_ua;
373 if (ulattrs_xavp_name.s != NULL)
374 {
375 contacts->ulattrs = xavp_get_by_index(&ulattrs_xavp_name, 0, NULL);
376 }
377 first_idx = 0;
378 } else {
379 /* Insert first branch to first contact */
380 branch = get_sip_branch(0);
381 contacts->uri.s = branch->uri;
382 contacts->uri.len = branch->len;
383 contacts->dst_uri.s = branch->dst_uri;
384 contacts->dst_uri.len = branch->dst_uri_len;
385 contacts->sock = branch->force_send_socket;
386 contacts->flags = branch->flags;
387 contacts->path.s = branch->path;
388 contacts->path.len = branch->path_len;
389 contacts->q = branch->q;
390 contacts->instance.s = branch->instance;
391 contacts->instance.len = branch->instance_len;
392 contacts->ruid.s = branch->ruid;
393 contacts->ruid.len = branch->ruid_len;
394 contacts->location_ua.s = branch->location_ua;
395 contacts->location_ua.len = branch->location_ua_len;
396 if (ulattrs_xavp_name.s != NULL)
397 {
398 contacts->ulattrs = xavp_get_by_index(&ulattrs_xavp_name, 1, NULL);
399 }
400 first_idx = 1;
401 }
402
403 contacts->q_index = contacts->q;
404 if (mode == T_LOAD_PROPORTIONAL) {
405 /* Save in q_index the index to check for the proportional order
406 Don't consider elements with Q value 0 or negative */
407 if (contacts->q > 0) {
408 q_total += contacts->q;
409 n_elements += 1;
410 }
411 contacts->q_index = q_total;
412 }
413
414 contacts->next = (struct contact *)0;
415
416 /* Insert (remaining) branches to contact list in increasing q order */
417 for (idx = first_idx; (branch = get_sip_branch(idx)) != 0; idx++) {
418
419 next = (struct contact *)pkg_malloc(sizeof(struct contact));
420 if (!next) {
421 PKG_MEM_ERROR_FMT("for contact info\n");
422 free_contact_list(contacts);
423 return -1;
424 }
425
426 memset(next, 0, sizeof(struct contact));
427 next->uri.s = branch->uri;
428 next->uri.len = branch->len;
429 next->dst_uri.s = branch->dst_uri;
430 next->dst_uri.len = branch->dst_uri_len;
431 next->sock = branch->force_send_socket;
432 next->flags = branch->flags;
433 next->path.s = branch->path;
434 next->path.len = branch->path_len;
435 next->q = branch->q;
436 next->instance.s = branch->instance;
437 next->instance.len = branch->instance_len;
438 next->ruid.s = branch->ruid;
439 next->ruid.len = branch->ruid_len;
440 next->location_ua.s = branch->location_ua;
441 next->location_ua.len = branch->location_ua_len;
442 if (ulattrs_xavp_name.s != NULL)
443 {
444 next->ulattrs = xavp_get_by_index(&ulattrs_xavp_name, idx + 1, NULL);
445 }
446
447 next->q_index = next->q;
448 if (mode == T_LOAD_PROPORTIONAL) {
449 /* Save in q_index the index to check for the proportional order
450 Don't consider elements with Q value 0 or negative */
451 if (next->q > 0) {
452 q_total += next->q;
453 n_elements += 1;
454 }
455 next->q_index = q_total;
456 }
457
458 next->next = (struct contact *)0;
459
460 prev = (struct contact *)0;
461 curr = contacts;
462 if (mode == T_LOAD_PROPORTIONAL) {
463 while (curr &&
464 ((curr->q_index < next->q_index) ||
465 ((curr->q_index == next->q_index) && (next->path.len == 0)))) {
466 prev = curr;
467 curr = curr->next;
468 }
469 } else {
470 while (curr &&
471 ((curr->q < next->q) ||
472 ((curr->q == next->q) && (next->path.len == 0)))) {
473 prev = curr;
474 curr = curr->next;
475 }
476 }
477 if (!curr) {
478 next->next = (struct contact *)0;
479 prev->next = next;
480 } else {
481 next->next = curr;
482 if (prev) {
483 prev->next = next;
484 } else {
485 contacts = next;
486 }
487 }
488 }
489
490 if (mode == T_LOAD_PROPORTIONAL) {
491 if (t_load_contacts_proportional(contacts, sock_buf, n_elements, q_total) < 0) {
492 free_contact_list(contacts);
493 return -1;
494 }
495 }
496 else {
497 if (t_load_contacts_standard(contacts, sock_buf) < 0) {
498 free_contact_list(contacts);
499 return -1;
500 }
501 }
502
503 /* Clear all branches */
504 clear_branches();
505 if (ulattrs_xavp_name.s != NULL){
506 xavp_rm_by_name(&ulattrs_xavp_name, 1, NULL);
507 }
508
509 /* Free contact list */
510 free_contact_list(contacts);
511
512 return 1;
513 }
514
ki_t_load_contacts(struct sip_msg * msg)515 int ki_t_load_contacts(struct sip_msg* msg)
516 {
517 return ki_t_load_contacts_mode(msg, T_LOAD_STANDARD);
518 }
519
t_load_contacts(struct sip_msg * msg,char * mode,char * value)520 int t_load_contacts(struct sip_msg* msg, char* mode, char* value)
521 {
522 int i = T_LOAD_STANDARD;
523
524 if(mode) {
525 if(get_int_fparam(&i, msg, (fparam_t*)mode)<0) return -1;
526
527 if ((i != T_LOAD_STANDARD) && (i != T_LOAD_PROPORTIONAL)) {
528 LM_ERR("invalid load_contact mode: %d, please use 0 (standard) or 1 (proportional)\n", i);
529 return -1;
530 }
531 LM_DBG("load_contact mode selected: %d\n", i);
532 }
533 else
534 {
535 LM_DBG("load_contact mode not selected, using: %d\n", T_LOAD_STANDARD);
536 }
537
538 return ki_t_load_contacts_mode(msg, i);
539 }
540
add_contact_flows_avp(str * uri,str * dst_uri,str * path,str * sock_str,unsigned int flags,str * instance,str * ruid,str * location_ua,sr_xavp_t * ulattrs_xavp)541 void add_contact_flows_avp(str *uri, str *dst_uri, str *path, str *sock_str,
542 unsigned int flags, str *instance, str *ruid,
543 str *location_ua, sr_xavp_t *ulattrs_xavp)
544 {
545 sr_xavp_t *record;
546 sr_xval_t val;
547
548 record = NULL;
549
550 val.type = SR_XTYPE_STR;
551 val.v.s = *uri;
552 xavp_add_value(&uri_name, &val, &record);
553
554 if (dst_uri->len > 0) {
555 val.type = SR_XTYPE_STR;
556 val.v.s = *dst_uri;
557 xavp_add_value(&dst_uri_name, &val, &record);
558 }
559
560 if (path->len > 0) {
561 val.type = SR_XTYPE_STR;
562 val.v.s = *path;
563 xavp_add_value(&path_name, &val, &record);
564 }
565
566 if (sock_str->len > 0) {
567 val.v.s = *sock_str;
568 xavp_add_value(&sock_name, &val, &record);
569 }
570
571 if (instance->len > 0) {
572 val.type = SR_XTYPE_STR;
573 val.v.s = *instance;
574 xavp_add_value(&instance_name, &val, &record);
575 }
576
577 if (ruid->len > 0) {
578 val.type = SR_XTYPE_STR;
579 val.v.s = *ruid;
580 xavp_add_value(&ruid_name, &val, &record);
581 }
582
583 if (location_ua->len > 0) {
584 val.type = SR_XTYPE_STR;
585 val.v.s = *location_ua;
586 xavp_add_value(&ua_name, &val, &record);
587 }
588
589 xavp_add(ulattrs_xavp, &record);
590
591 val.type = SR_XTYPE_INT;
592 val.v.i = flags;
593 xavp_add_value(&flags_name, &val, &record);
594
595 val.type = SR_XTYPE_XAVP;
596 val.v.xavp = record;
597 if(xavp_add_value(&contact_flows_avp, &val, NULL)==NULL) {
598 /* failed to add xavps to root list */
599 LM_ERR("failed to add xavps to root list\n");
600 xavp_destroy_list(&record);
601 }
602 }
603
604 /*
605 * Adds to request a new destination set that includes highest
606 * priority class contacts in contacts_avp, but only one contact with same
607 * +sip.instance value is included. Others are added to contact_flows_avp
608 * for later consumption by next_contact_flow().
609 * Request URI is rewritten with first contact and the remaining contacts
610 * (if any) are added as branches. Removes all highest priority contacts
611 * from contacts_avp.
612 * Returns 1, if contacts_avp was not empty and a destination set was
613 * successfully added. Returns -2, if contacts_avp was empty and thus
614 * there was nothing to do. Returns -1 in case of an error. */
ki_t_next_contacts(struct sip_msg * msg)615 int ki_t_next_contacts(struct sip_msg* msg)
616 {
617 str uri, dst_uri, path, instance, host, sock_str, ruid, location_ua;
618 struct socket_info *sock;
619 unsigned int flags, q_flag;
620 sr_xavp_t *xavp_list, *xavp, *prev_xavp, *vavp;
621 int port, proto;
622 struct instance_list *il, *ilp;
623
624 /* Check if contacts_avp has been defined */
625 if (contacts_avp.len == 0) {
626 LM_ERR("feature has been disabled - "
627 "to enable define contacts_avp module parameter");
628 return -1;
629 }
630
631 /* Load Request-URI and branches */
632
633 /* Find first contacts_avp value */
634 xavp_list = xavp_get(&contacts_avp, NULL);
635 if (!xavp_list) {
636 LM_DBG("no contacts in contacts_avp - we are done!\n");
637 return -2;
638 }
639
640 xavp = xavp_list;
641
642 vavp = xavp_get(&uri_name, xavp->val.v.xavp);
643 uri = vavp->val.v.s;
644
645 vavp = xavp_get(&dst_uri_name, xavp->val.v.xavp);
646 if (vavp != NULL) {
647 dst_uri = vavp->val.v.s;
648 } else {
649 dst_uri.s = 0;
650 dst_uri.len = 0;
651 }
652
653 vavp = xavp_get(&path_name, xavp->val.v.xavp);
654 if (vavp != NULL) {
655 path = vavp->val.v.s;
656 } else {
657 path.s = 0;
658 path.len = 0;
659 }
660
661 vavp = xavp_get(&sock_name, xavp->val.v.xavp);
662 if (vavp != NULL) {
663 sock_str.s = vavp->val.v.s.s;
664 if (parse_phostport(sock_str.s, &host.s, &host.len, &port, &proto)
665 != 0) {
666 LM_ERR("parsing of socket info <%s> failed\n", sock_str.s);
667 xavp_rm(xavp_list, NULL);
668 return -1;
669 }
670 sock = grep_sock_info(&host, (unsigned short)port,
671 (unsigned short)proto);
672 if (sock == 0) {
673 xavp_rm(xavp_list, NULL);
674 return -1;
675 }
676 } else {
677 sock = NULL;
678 }
679
680 vavp = xavp_get(&flags_name, xavp->val.v.xavp);
681 flags = vavp->val.v.i;
682
683 vavp = xavp_get(&q_flag_name, xavp->val.v.xavp);
684 q_flag = vavp->val.v.i;
685
686 vavp = xavp_get(&instance_name, xavp->val.v.xavp);
687 il = (struct instance_list *)0;
688 if ((vavp != NULL) && !q_flag) {
689 instance = vavp->val.v.s;
690 il = (struct instance_list *)pkg_malloc(sizeof(struct instance_list));
691 if (!il) {
692 PKG_MEM_ERROR_FMT("for instance list entry\n");
693 return -1;
694 }
695 il->instance.s = pkg_malloc(instance.len);
696 if (!il->instance.s) {
697 pkg_free(il);
698 PKG_MEM_ERROR_FMT("for instance list instance\n");
699 return -1;
700 }
701 il->instance.len = instance.len;
702 memcpy(il->instance.s, instance.s, instance.len);
703 il->next = (struct instance_list *)0;
704 set_instance(msg, &instance);
705 } else {
706 instance.s = 0;
707 instance.len = 0;
708 }
709
710 vavp = xavp_get(&ruid_name, xavp->val.v.xavp);
711 if (vavp != NULL) {
712 ruid = vavp->val.v.s;
713 } else {
714 ruid.s = 0;
715 ruid.len = 0;
716 }
717 vavp = xavp_get(&ua_name, xavp->val.v.xavp);
718 if (vavp != NULL) {
719 location_ua = vavp->val.v.s;
720 } else {
721 location_ua.s = 0;
722 location_ua.len = 0;
723 }
724
725 if (ulattrs_xavp_name.s != NULL)
726 {
727 vavp = xavp_extract(&ulattrs_xavp_name, &xavp->val.v.xavp);
728 xavp_insert(vavp, 0, NULL);
729 }
730
731 /* Rewrite Request-URI */
732 if(rewrite_uri(msg, &uri)<0) {
733 LM_WARN("failed to rewrite r-uri\n");
734 }
735
736 if (dst_uri.len) {
737 if(set_dst_uri(msg, &dst_uri)<0) {
738 LM_ERR("failed to set dst uri\n");
739 }
740 } else {
741 reset_dst_uri(msg);
742 }
743
744 if (path.len) {
745 if(set_path_vector(msg, &path)<0) {
746 LM_WARN("failed to set path vector\n");
747 }
748 } else {
749 reset_path_vector(msg);
750 }
751
752 set_force_socket(msg, sock);
753
754 setbflagsval(0, flags);
755
756 set_ruid(msg, &ruid);
757
758 set_ua(msg, &location_ua);
759
760 /* Check if there was only one contact at this priority */
761 if (q_flag) {
762 xavp_rm(xavp, NULL);
763 return 1;
764 }
765
766 /* Append branches until out of branches or Q_FLAG is set */
767 /* If a branch has same instance value as some previous branch, */
768 /* instead of appending it, add it to contact_flows_avp */
769
770 xavp_rm_by_name(&contact_flows_avp, 1, NULL);
771 prev_xavp = xavp;
772
773 while ((xavp = xavp_get_next(prev_xavp)) != NULL) {
774
775 xavp_rm(prev_xavp, NULL);
776
777 vavp = xavp_get(&q_flag_name, xavp->val.v.xavp);
778 if(vavp) {
779 q_flag = vavp->val.v.i;
780 } else {
781 q_flag = 0;
782 }
783
784 vavp = xavp_get(&uri_name, xavp->val.v.xavp);
785 if(vavp) {
786 uri = vavp->val.v.s;
787 } else {
788 uri.len = 0;
789 }
790
791 vavp = xavp_get(&dst_uri_name, xavp->val.v.xavp);
792 if (vavp != NULL) {
793 dst_uri = vavp->val.v.s;
794 } else {
795 dst_uri.len = 0;
796 }
797
798 vavp = xavp_get(&path_name, xavp->val.v.xavp);
799 if (vavp != NULL) {
800 path = vavp->val.v.s;
801 } else {
802 path.len = 0;
803 }
804
805 vavp = xavp_get(&sock_name, xavp->val.v.xavp);
806 if (vavp != NULL) {
807 sock_str = vavp->val.v.s;
808 if (parse_phostport(sock_str.s, &host.s, &host.len, &port, &proto)
809 != 0) {
810 LM_ERR("parsing of socket info <%s> failed\n", sock_str.s);
811 free_instance_list(il);
812 xavp_rm(xavp_list, NULL);
813 return -1;
814 }
815 sock = grep_sock_info(&host, (unsigned short)port,
816 (unsigned short)proto);
817 if (sock == 0) {
818 free_instance_list(il);
819 xavp_rm(xavp_list, NULL);
820 return -1;
821 }
822 } else {
823 sock = NULL;
824 sock_str.s = 0;
825 sock_str.len = 0;
826 }
827
828 vavp = xavp_get(&flags_name, xavp->val.v.xavp);
829 if (vavp != NULL) {
830 flags = vavp->val.v.i;
831 } else {
832 flags = 0;
833 }
834
835 vavp = xavp_get(&ruid_name, xavp->val.v.xavp);
836 if (vavp != NULL) {
837 ruid = vavp->val.v.s;
838 } else {
839 ruid.s = 0;
840 ruid.len = 0;
841 }
842
843 vavp = xavp_get(&ua_name, xavp->val.v.xavp);
844 if (vavp != NULL) {
845 location_ua = vavp->val.v.s;
846 } else {
847 location_ua.s = 0;
848 location_ua.len = 0;
849 }
850
851 vavp = xavp_get(&instance_name, xavp->val.v.xavp);
852 if (vavp != NULL) {
853 instance = vavp->val.v.s;
854 ilp = il;
855 while (ilp) {
856 if ((instance.len == ilp->instance.len) &&
857 (strncmp(instance.s, ilp->instance.s, instance.len) == 0))
858 break;
859 ilp = ilp->next;
860 }
861 if (ilp) {
862 vavp = (ulattrs_xavp_name.s != NULL)?xavp_extract(&ulattrs_xavp_name, &xavp->val.v.xavp):NULL;
863 add_contact_flows_avp(&uri, &dst_uri, &path, &sock_str,
864 flags, &instance, &ruid, &location_ua, vavp);
865 goto check_q_flag;
866 }
867 if (!q_flag) {
868 ilp = (struct instance_list *)
869 pkg_malloc(sizeof(struct instance_list));
870 if (!ilp) {
871 PKG_MEM_ERROR_FMT("for instance list element\n");
872 free_instance_list(il);
873 return -1;
874 }
875 ilp->instance.s = pkg_malloc(instance.len);
876 if (!ilp->instance.s) {
877 PKG_MEM_ERROR_FMT("for instance list instance\n");
878 pkg_free(ilp);
879 free_instance_list(il);
880 return -1;
881 }
882 ilp->instance.len = instance.len;
883 memcpy(ilp->instance.s, instance.s, instance.len);
884 ilp->next = il;
885 il = ilp;
886 }
887 } else {
888 instance.s = 0;
889 instance.len = 0;
890 }
891
892 LM_DBG("Appending branch uri-'%.*s' dst-'%.*s' path-'%.*s' inst-'%.*s'"
893 " ruid-'%.*s' location_ua-'%.*s'\n",
894 uri.len, uri.s,
895 dst_uri.len, (dst_uri.len > 0)?dst_uri.s:"",
896 path.len, (path.len>0)?path.s:"",
897 instance.len, (instance.len>0)?instance.s:"",
898 ruid.len, (ruid.len>0)?ruid.s:"",
899 location_ua.len, (location_ua.len>0)?location_ua.s:"");
900 if (append_branch(msg, &uri, &dst_uri, &path, 0, flags, sock, &instance, 0,
901 &ruid, &location_ua) != 1) {
902 LM_ERR("appending branch failed\n");
903 free_instance_list(il);
904 xavp_rm(xavp_list, NULL);
905 return -1;
906 }
907
908 if (ulattrs_xavp_name.s != NULL)
909 {
910 vavp = xavp_extract(&ulattrs_xavp_name, &xavp->val.v.xavp);
911 xavp_insert(vavp, nr_branches, NULL);
912 }
913
914 check_q_flag:
915 if (q_flag) {
916 free_instance_list(il);
917 xavp_rm(xavp, NULL);
918 return 1;
919 }
920
921 prev_xavp = xavp;
922 }
923
924 free_instance_list(il);
925 xavp_rm(prev_xavp, NULL);
926
927 return 1;
928 }
929
t_next_contacts(struct sip_msg * msg,char * key,char * value)930 int t_next_contacts(struct sip_msg* msg, char* key, char* value)
931 {
932 return ki_t_next_contacts(msg);
933 }
934
935 /*
936 * Adds to request a new destination set that includes contacts
937 * from contact_flows_avp. Only one contact with same +sip.instance
938 * value is included.
939 * Request URI is rewritten with first contact and the remaining contacts
940 * (if any) are added as branches. Removes all used contacts
941 * from contacts_avp.
942 * Returns 1, if contact_flows_avp was not empty and a destination set was
943 * successfully added. Returns -2, if contact_flows_avp was empty and thus
944 * there was nothing to do. Returns -1 in case of an error. */
ki_t_next_contact_flow(struct sip_msg * msg)945 int ki_t_next_contact_flow(struct sip_msg* msg)
946 {
947 str uri, dst_uri, path, instance, host, ruid, location_ua;
948 str this_instance;
949 struct socket_info *sock;
950 unsigned int flags;
951 sr_xavp_t *xavp_list, *xavp, *next_xavp, *vavp;
952 char *tmp;
953 int port, proto;
954
955 /* Check if contact_flows_avp has been defined */
956 if (contact_flows_avp.len == 0) {
957 LM_ERR("feature has been disabled - "
958 "to enable define contact_flows_avp module parameter");
959 return -1;
960 }
961
962 /* Load Request-URI and branches */
963 t_get_this_branch_instance(msg, &this_instance);
964
965 if (this_instance.len == 0) {
966 LM_DBG("No instance on this branch\n");
967 return -2;
968 }
969 /* Find first contact_flows_avp value */
970 xavp_list = xavp_get(&contact_flows_avp, NULL);
971 if (!xavp_list) {
972 LM_DBG("no contacts in contact_flows_avp - we are done!\n");
973 return -2;
974 }
975
976 xavp = xavp_list;
977
978 while (xavp) {
979 next_xavp = xavp_get_next(xavp);
980
981 vavp = xavp_get(&instance_name, xavp->val.v.xavp);
982 if (vavp == NULL) {
983 /* Does not match this instance */
984 goto next_xavp;
985 } else {
986 instance = vavp->val.v.s;
987 if ((instance.len != this_instance.len) ||
988 (strncmp(instance.s, this_instance.s, instance.len) != 0))
989 /* Does not match this instance */
990 goto next_xavp;
991 }
992
993 vavp = xavp_get(&uri_name, xavp->val.v.xavp);
994 if (vavp == NULL) {
995 goto next_xavp;
996 } else {
997 uri = vavp->val.v.s;
998 }
999
1000 vavp = xavp_get(&dst_uri_name, xavp->val.v.xavp);
1001 if (vavp != NULL) {
1002 dst_uri = vavp->val.v.s;
1003 } else {
1004 dst_uri.len = 0;
1005 }
1006
1007 vavp = xavp_get(&path_name, xavp->val.v.xavp);
1008 if (vavp != NULL) {
1009 path = vavp->val.v.s;
1010 } else {
1011 path.len = 0;
1012 }
1013
1014 vavp = xavp_get(&sock_name, xavp->val.v.xavp);
1015 if (vavp != NULL) {
1016 tmp = vavp->val.v.s.s;
1017 if (parse_phostport(tmp, &host.s, &host.len, &port, &proto) != 0) {
1018 LM_ERR("parsing of socket info <%s> failed\n", tmp);
1019 xavp_rm(xavp, NULL);
1020 return -1;
1021 }
1022 sock = grep_sock_info(&host, (unsigned short)port,
1023 (unsigned short)proto);
1024 if (sock == 0) {
1025 xavp_rm(xavp, NULL);
1026 return -1;
1027 }
1028 } else {
1029 sock = NULL;
1030 }
1031
1032 vavp = xavp_get(&flags_name, xavp->val.v.xavp);
1033 if (vavp != NULL) {
1034 flags = vavp->val.v.i;
1035 } else {
1036 flags = 0;
1037 }
1038
1039 vavp = xavp_get(&ruid_name, xavp->val.v.xavp);
1040 if (vavp != NULL) {
1041 ruid = vavp->val.v.s;
1042 } else {
1043 ruid.s = "";
1044 ruid.len = 0;
1045 }
1046
1047 vavp = xavp_get(&ua_name, xavp->val.v.xavp);
1048 if (vavp != NULL) {
1049 location_ua = vavp->val.v.s;
1050 } else {
1051 location_ua.s = "";
1052 location_ua.len = 0;
1053 }
1054
1055 LM_DBG("Appending branch uri-'%.*s' dst-'%.*s' path-'%.*s'"
1056 " inst-'%.*s' ruid-'%.*s' location_ua-'%.*s'\n",
1057 uri.len, uri.s,
1058 dst_uri.len, (dst_uri.len > 0)?dst_uri.s:"",
1059 path.len, (path.len>0)?path.s:"",
1060 instance.len, (instance.len>0)?instance.s:"",
1061 ruid.len, ruid.s, location_ua.len, location_ua.s);
1062 if (append_branch(msg, &uri, &dst_uri, &path, 0, flags, sock, &instance, 0,
1063 &ruid, &location_ua) != 1) {
1064 LM_ERR("appending branch failed\n");
1065 xavp_rm(xavp_list, NULL);
1066 return -1;
1067 }
1068
1069 if (ulattrs_xavp_name.s != NULL)
1070 {
1071 vavp = xavp_extract(&ulattrs_xavp_name, &xavp->val.v.xavp);
1072 xavp_insert(vavp, nr_branches, NULL);
1073 }
1074
1075 xavp_rm(xavp, NULL);
1076 return 1;
1077 next_xavp:
1078 xavp = next_xavp;
1079 }
1080
1081 return -1;
1082 }
1083
t_next_contact_flow(struct sip_msg * msg,char * key,char * value)1084 int t_next_contact_flow(struct sip_msg* msg, char* key, char* value)
1085 {
1086 return ki_t_next_contact_flow(msg);
1087 }
1088