Browse code

tm: new api function t_append_branches

Federico Cabiddu authored on 09/09/2014 14:14:46
Showing 7 changed files
... ...
@@ -472,6 +472,8 @@ typedef struct cell
472 472
 	unsigned short on_reply;
473 473
 	 /* The route to take for each downstream branch separately */
474 474
 	unsigned short on_branch;
475
+	 /* branch route backup for late branch add (t_append_branch) */
476
+	unsigned short on_branch_delayed;
475 477
 
476 478
 	/* place holder for MD5checksum, MD5_LEN bytes are extra alloc'ed */
477 479
 	char md5[0];
478 480
new file mode 100644
... ...
@@ -0,0 +1,186 @@
0
+/*
1
+ * late branching functions
2
+ *
3
+ * Copyright (C) 2014 Federico Cabiddu
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ *  1. Redistributions of source code must retain the above copyright notice,
9
+ *     this list of conditions and the following disclaimer.
10
+ *  2. Redistributions in binary form must reproduce the above copyright
11
+ *     notice, this list of conditions and the following disclaimer in the
12
+ *     documentation and/or other materials provided with the distribution.
13
+ *
14
+ * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR
15
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17
+ * EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
+ *
25
+ * History:
26
+ * -------
27
+ *  2014-09-09  first release of t_append_branches
28
+ *
29
+ */
30
+
31
+#include <stdio.h>
32
+#include <string.h>
33
+#include <stdlib.h>
34
+
35
+#include "../../sr_module.h"
36
+#include "../../dprint.h"
37
+#include "../../mod_fix.h"
38
+#include "../../route.h"
39
+#include "../../data_lump.h"
40
+#include "../../lib/kcore/kstats_wrapper.h"
41
+#include "../../dset.h"
42
+#include "../../script_cb.h"
43
+#include "../../parser/msg_parser.h"
44
+#include "../../parser/contact/parse_contact.h"
45
+#include "t_msgbuilder.h"
46
+#include "t_lookup.h"
47
+#include "t_fwd.h"
48
+#include "t_append_branches.h"
49
+
50
+int t_append_branches(void) {
51
+	struct cell *t = NULL;
52
+	struct sip_msg *orig_msg;
53
+	short outgoings;
54
+
55
+	int success_branch;
56
+
57
+	str current_uri;
58
+	str dst_uri, path, instance, ruid, location_ua;
59
+	struct socket_info* si;
60
+	int q, i, found;
61
+	flag_t backup_bflags = 0;
62
+	flag_t bflags = 0;
63
+	int new_branch, branch_ret, lowest_ret;
64
+	branch_bm_t	added_branches;
65
+
66
+	t = get_t();
67
+	if(t == NULL)
68
+	{
69
+		LM_ERR("cannot get transaction\n");
70
+		return -1;
71
+	}
72
+
73
+	LM_DBG("transaction %u:%u in status %d\n", t->hash_index, t->label, t->uas.status);
74
+
75
+	if ((t->uas.status >= 200 && t->uas.status<=399)
76
+			|| ((t->uas.status >= 600 && t->uas.status)
77
+				&& !(t->flags & (T_6xx | T_DISABLE_6xx))) ) {
78
+		LM_DBG("transaction %u:%u in status %d: cannot append new branch\n", t->hash_index, t->label, t->uas.status);
79
+		return -1;
80
+	}
81
+
82
+	/* set the lock on the transaction here */
83
+	LOCK_REPLIES(t);
84
+	outgoings = t->nr_of_outgoings;
85
+	orig_msg = t->uas.request;
86
+
87
+	LM_DBG("Call %.*s: %d (%d) outgoing branches\n",orig_msg->callid->body.len, orig_msg->callid->body.s,outgoings, nr_branches);
88
+
89
+	lowest_ret=E_UNSPEC;
90
+	added_branches=0;
91
+
92
+	/* it's a "late" branch so the on_branch variable has already been
93
+	reset by previous execution of t_forward_nonack: we use the saved
94
+	   value  */
95
+	if (t->on_branch_delayed) {
96
+		/* tell add_uac that it should run branch route actions */
97
+		set_branch_route(t->on_branch_delayed);
98
+	}
99
+
100
+	outgoings = t->nr_of_outgoings;
101
+
102
+	/* not really sure that the following is needed */
103
+
104
+	set_branch_iterator(nr_branches-1);
105
+	found = 0;
106
+	while((current_uri.s=next_branch( &current_uri.len, &q, &dst_uri, &path,
107
+										&bflags, &si, &ruid, &instance, &location_ua))) {
108
+		LM_DBG("Current uri %.*s\n",current_uri.len, current_uri.s);
109
+
110
+		for (i=0; i<nr_branches; i++) {
111
+			if (t->uac[i].ruid.len == ruid.len
112
+					&& !memcmp(t->uac[i].ruid.s, ruid.s, ruid.len)) {
113
+				LM_DBG("branch already added [%.*s]\n", ruid.len, ruid.s);
114
+				found = 1;
115
+				break;
116
+			}
117
+		}
118
+		if (found)
119
+			continue;
120
+
121
+		setbflagsval(0, bflags);
122
+		new_branch=add_uac( t, orig_msg, &current_uri,
123
+					(dst_uri.len) ? (&dst_uri) : &current_uri,
124
+					&path, 0, si, orig_msg->fwd_send_flags,
125
+					orig_msg->rcv.proto, (dst_uri.len)?-1:UAC_SKIP_BR_DST_F, &instance,
126
+					&ruid, &location_ua);
127
+		if (new_branch>=0)
128
+			added_branches |= 1<<new_branch;
129
+		else
130
+			lowest_ret=MIN_int(lowest_ret, new_branch);
131
+	}
132
+
133
+	clear_branches();
134
+
135
+	LM_DBG("Call %.*s: %d (%d) outgoing branches after clear_branches()\n",orig_msg->callid->body.len, orig_msg->callid->body.s,outgoings, nr_branches);
136
+	setbflagsval(0, backup_bflags);
137
+
138
+	/* update message flags, if changed in branch route */
139
+	t->uas.request->flags = orig_msg->flags;
140
+
141
+	if (added_branches==0) {
142
+		if(lowest_ret!=E_CFG)
143
+			LOG(L_ERR, "ERROR: t_append_branch: failure to add branches\n");
144
+		ser_error=lowest_ret;
145
+		UNLOCK_REPLIES(t);
146
+		return lowest_ret;
147
+	}
148
+
149
+	ser_error=0; /* clear branch adding errors */
150
+	/* send them out now */
151
+	success_branch=0;
152
+	/* since t_append_branch can only be called from REQUEST_ROUTE, always lock replies */
153
+
154
+	for (i=outgoings; i<t->nr_of_outgoings; i++) {
155
+		if (added_branches & (1<<i)) {
156
+			branch_ret=t_send_branch(t, i, orig_msg , 0, 0 /* replies are already locked */ );
157
+			if (branch_ret>=0){ /* some kind of success */
158
+				if (branch_ret==i) { /* success */
159
+					success_branch++;
160
+					if (unlikely(has_tran_tmcbs(t, TMCB_REQUEST_OUT)))
161
+						run_trans_callbacks_with_buf( TMCB_REQUEST_OUT, &t->uac[nr_branches].request,
162
+								orig_msg, 0, -orig_msg->REQ_METHOD);
163
+				}
164
+				else /* new branch added */
165
+					added_branches |= 1<<branch_ret;
166
+			}
167
+		}
168
+	}
169
+	if (success_branch<=0) {
170
+		/* return always E_SEND for now
171
+		 * (the real reason could be: denied by onsend routes, blacklisted,
172
+		 *  send failed or any of the errors listed before + dns failed
173
+		 *  when attempting dns failover) */
174
+		ser_error=E_SEND;
175
+		/* else return the last error (?) */
176
+		/* the caller should take care and delete the transaction */
177
+		UNLOCK_REPLIES(t);
178
+		return -1;
179
+	}
180
+
181
+	ser_error=0; /* clear branch send errors, we have overall success */
182
+	set_kr(REQ_FWDED);
183
+	UNLOCK_REPLIES(t);
184
+	return 1;
185
+}
0 186
new file mode 100644
... ...
@@ -0,0 +1,43 @@
0
+/*
1
+ * late branching functions
2
+ *
3
+ * Copyright (C) 2014 Federico Cabiddu
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ *  1. Redistributions of source code must retain the above copyright notice,
9
+ *     this list of conditions and the following disclaimer.
10
+ *  2. Redistributions in binary form must reproduce the above copyright
11
+ *     notice, this list of conditions and the following disclaimer in the
12
+ *     documentation and/or other materials provided with the distribution.
13
+ *
14
+ * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR
15
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17
+ * EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
+ *
25
+ * History:
26
+ * -------
27
+ *  2014-09-09  first release of t_append_branches
28
+ *
29
+ */
30
+
31
+#ifndef _T_APPEND_BRANCHES_H
32
+#define _T_APPEND_BRANCHES_H
33
+
34
+#include "defs.h"
35
+
36
+#include "../../proxy.h"
37
+#include "h_table.h"
38
+
39
+int t_append_branches(void);
40
+typedef int (*t_append_branches_f)(void);
41
+
42
+#endif
... ...
@@ -150,12 +150,12 @@ unsigned int get_on_branch(void)
150 150
 	return goto_on_branch;
151 151
 }
152 152
 
153
+void set_branch_route( unsigned int on_branch)
154
+{
155
+	branch_route = on_branch;
156
+}
153 157
 
154 158
 
155
-/* prepare_new_uac flags */
156
-#define UAC_DNS_FAILOVER_F 1 /**< new branch due to dns failover */
157
-#define UAC_SKIP_BR_DST_F  2 /**< don't set next hop as dst_uri for
158
-							   branch_route */
159 159
 
160 160
 
161 161
 /** prepares a new branch "buffer".
... ...
@@ -797,7 +797,7 @@ int add_blind_uac( /*struct cell *t*/ )
797 797
  *                    @see prepare_new_uac().
798 798
  *  @returns branch id (>=0) or error (<0)
799 799
 */
800
-static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
800
+int add_uac( struct cell *t, struct sip_msg *request, str *uri,
801 801
 					str* next_hop, str* path, struct proxy_l *proxy,
802 802
 					struct socket_info* fsocket, snd_flags_t snd_flags,
803 803
 					int proto, int flags, str *instance, str *ruid,
... ...
@@ -1693,6 +1693,10 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
1693 1693
 	if (t->on_branch) {
1694 1694
 		/* tell add_uac that it should run branch route actions */
1695 1695
 		branch_route = t->on_branch;
1696
+		/* save the branch route so that it
1697
+		 * can be used for adding branches later
1698
+		 */
1699
+		t->on_branch_delayed = t->on_branch;
1696 1700
 		/* reset the flag before running the actions (so that it
1697 1701
 		 * could be set again in branch_route if needed
1698 1702
 		 */
... ...
@@ -52,6 +52,7 @@ typedef int (*taddblind_f)( /*struct cell *t */ void);
52 52
 typedef int (*treplicate_uri_f)(struct sip_msg* p_msg , str *suri );
53 53
 
54 54
 void t_on_branch(unsigned int go_to);
55
+void set_branch_route(unsigned int on_branch);
55 56
 unsigned int get_on_branch(void);
56 57
 int t_replicate_uri(struct sip_msg *p_msg, str *suri);
57 58
 int t_replicate(struct sip_msg *p_msg, struct proxy_l * proxy, int proto);
... ...
@@ -65,6 +66,15 @@ int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel, struct
65 65
 int add_uac(struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
66 66
 				str* path, struct proxy_l *proxy, int proto );
67 67
 */
68
+
69
+/* prepare_new_uac flags */
70
+#define UAC_DNS_FAILOVER_F 1 /**< new branch due to dns failover */
71
+#define UAC_SKIP_BR_DST_F  2 /**< don't set next hop as dst_uri for
72
+							   branch_route */
73
+int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
74
+			str* path, struct proxy_l *proxy, struct socket_info* fsocket,
75
+			snd_flags_t snd_flags, int proto, int flags, str *instance, str *ruid,
76
+			str *location_ua);
68 77
 #ifdef USE_DNS_FAILOVER
69 78
 int add_uac_dns_fallback( struct cell *t, struct sip_msg* msg, 
70 79
 									struct ua_client* old_uac,
... ...
@@ -147,6 +147,7 @@ int load_tm( struct tm_binds *tmb)
147 147
 #ifdef WITH_TM_CTX
148 148
 	tmb->tm_ctx_get = tm_ctx_get;
149 149
 #endif
150
+	tmb->t_append_branches = t_append_branches;
150 151
 	return 1;
151 152
 }
152 153
 
... ...
@@ -49,6 +49,7 @@
49 49
 #include "callid.h"
50 50
 #include "t_cancel.h"
51 51
 #include "t_suspend.h"
52
+#include "t_append_branches.h"
52 53
 #include "t_stats.h"
53 54
 
54 55
 /* export not usable from scripts */
... ...
@@ -133,6 +134,7 @@ struct tm_binds {
133 133
 #else
134 134
 	void* reserved5;
135 135
 #endif
136
+	t_append_branches_f	t_append_branches;
136 137
 };
137 138
 
138 139
 typedef struct tm_binds tm_api_t;