Browse code

New TM export - cancel_all_uacs() - to allow canceling all branches of a transaction. (Closes issue #SER-253).

Some error messages are corrected to reflect new function name.

(Bits of code for the AS support also added; issue #SER-346 in the works.)

Bogdan Pintea authored on 31/03/2008 18:19:49
Showing 9 changed files
... ...
@@ -45,6 +45,9 @@
45 45
  */
46 46
 
47 47
 #include <stdio.h> /* for FILE* in fifo_uac_cancel */
48
+#ifdef EXTRA_DEBUG
49
+#include <assert.h>
50
+#endif /* EXTRA_DEBUG */
48 51
 
49 52
 #include "defs.h"
50 53
 #include "config.h"
... ...
@@ -106,6 +109,40 @@ int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags)
106 106
 	return ret;
107 107
 }
108 108
 
109
+int cancel_all_uacs(struct cell *trans, int how)
110
+{
111
+	branch_bm_t cancel_bm;
112
+	int i,j;
113
+
114
+#ifdef EXTRA_DEBUG
115
+	assert(trans);
116
+#endif
117
+	DBG("Canceling T@%p [%u:%u]\n", trans, trans->hash_index, trans->label);
118
+	
119
+	cancel_bm=0;
120
+	which_cancel(trans, &cancel_bm);
121
+	 /* tell tm to cancel the call */
122
+	i=cancel_uacs(trans, cancel_bm, how);
123
+	
124
+	if (how & F_CANCEL_UNREF)
125
+#ifndef TM_DEL_UNREF
126
+	/* in case of 'too many' _buggy_ invocations, the ref count (a uint) might 
127
+	 * actually wrap around, possibly leaving the T leaking. */
128
+#warning "use of F_CANCEL_UNREF flag is unsafe without defining TM_DEL_UNREF"
129
+#endif
130
+		UNREF(trans);
131
+
132
+	/* count the still active branches */
133
+	if (! how) {
134
+		j=0;
135
+		while(i){
136
+			j++;
137
+			i&=i-1;
138
+		}
139
+		return j;
140
+	}
141
+	return 0;
142
+}
109 143
 
110 144
 
111 145
 /* should be called directly only if one of the condition bellow is true:
... ...
@@ -71,14 +71,17 @@
71 71
 									if no provisional response was received;
72 72
 									F_CANCEL_B_FORCE_C, F_CANCEL_B_FAKE_REPLY
73 73
 									and F_CANCE_B_KILL take precedence */
74
+#define F_CANCEL_UNREF 16 /* unref the trans after canceling */
74 75
 
75 76
 
76 77
 void which_cancel( struct cell *t, branch_bm_t *cancel_bm );
77 78
 int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags );
79
+int cancel_all_uacs(struct cell *trans, int how);
78 80
 int cancel_branch( struct cell *t, int branch, int flags );
79 81
 
80 82
 typedef int(*cancel_uacs_f)( struct cell *t, branch_bm_t cancel_bm,
81 83
 								int flags );
84
+typedef int (*cancel_all_uacs_f)(struct cell *trans, int how);
82 85
 
83 86
 
84 87
 
... ...
@@ -119,9 +119,6 @@
119 119
 #include "../../atomic_ops.h" /* membar_depends() */
120 120
 #endif
121 121
 
122
-/* cancel hop by hop */
123
-#define E2E_CANCEL_HOP_BY_HOP
124
-
125 122
 static int goto_on_branch = 0, branch_route = 0;
126 123
 
127 124
 void t_on_branch( unsigned int go_to )
... ...
@@ -41,6 +41,9 @@
41 41
 #include "../../proxy.h"
42 42
 #include "h_table.h"
43 43
 
44
+/* cancel hop by hop */
45
+#define E2E_CANCEL_HOP_BY_HOP
46
+
44 47
 enum unmatched_cancel_t { UM_CANCEL_STATEFULL=0, UM_CANCEL_STATELESS,
45 48
 							UM_CANCEL_DROP };
46 49
 
... ...
@@ -108,4 +108,14 @@ int t_set_max_lifetime(struct sip_msg* msg, unsigned int eol_inv,
108 108
 											unsigned int eol_noninv);
109 109
 int t_reset_max_lifetime();
110 110
 
111
+#ifdef WITH_AS_SUPPORT
112
+/**
113
+ * Returns the hash coordinates of the transaction current CANCEL is targeting.
114
+ */
115
+int t_get_canceled_ident(struct sip_msg *msg, unsigned int *hash_index, 
116
+		unsigned int *label);
117
+typedef int (*t_get_canceled_ident_f)(struct sip_msg *msg, 
118
+		unsigned int *hash_index, unsigned int *label);
119
+#endif /* WITH_AS_SUPPORT */
120
+
111 121
 #endif
... ...
@@ -350,6 +350,12 @@ static cmd_export_t cmds[]={
350 350
 	{"t_unref",            (cmd_function)t_unref,           NO_SCRIPT,   0, 0},
351 351
 	{"run_failure_handlers", (cmd_function)run_failure_handlers, NO_SCRIPT,   0, 0},
352 352
 	{"cancel_uacs",        (cmd_function)cancel_uacs,       NO_SCRIPT,   0, 0},
353
+	{"cancel_all_uacs",    (cmd_function)cancel_all_uacs,        NO_SCRIPT,   0, 0},
354
+#ifdef WITH_AS_SUPPORT
355
+	{"ack_local_uac",      (cmd_function)ack_local_uac,     NO_SCRIPT,   0, 0},
356
+	{"t_get_canceled_ident",   (cmd_function)t_get_canceled_ident,  NO_SCRIPT,
357
+			0, 0},
358
+#endif
353 359
 	{0,0,0,0,0}
354 360
 };
355 361
 
... ...
@@ -190,6 +190,11 @@ int load_tm( struct tm_binds *tmb)
190 190
 		LOG( L_ERR, LOAD_ERROR "'cancel_uacs' not found\n");
191 191
 		return -1;
192 192
 	}
193
+	if (! (tmb->cancel_all_uacs=(cancel_all_uacs_f)find_export(
194
+			"cancel_all_uacs", NO_SCRIPT, 0))) {
195
+		LOG( L_ERR, LOAD_ERROR "'cancel_all_uacs' not found\n");
196
+		return -1;
197
+	}
193 198
 
194 199
 	tmb->prepare_request_within = prepare_req_within;
195 200
 	tmb->send_prepared_request = send_prepared_request;
... ...
@@ -199,5 +204,17 @@ int load_tm( struct tm_binds *tmb)
199 199
 	tmb->register_new_dlg_cb=register_new_dlg_cb;
200 200
 	tmb->register_dlg_tmcb=register_dlg_tmcb;
201 201
 #endif
202
+#ifdef WITH_AS_SUPPORT
203
+	if (! (tmb->ack_local_uac=(ack_local_uac_f)find_export("ack_local_uac",
204
+			NO_SCRIPT, 0))) {
205
+		LOG( L_ERR, LOAD_ERROR "'ack_uac' not found\n");
206
+		return -1;
207
+	}
208
+	if (! (tmb->t_get_canceled_ident=(t_get_canceled_ident_f)find_export(
209
+			"t_get_canceled_ident", NO_SCRIPT, 0))) {
210
+		LOG( L_ERR, LOAD_ERROR "'t_get_canceled_ident' not found\n");
211
+		return -1;
212
+	}
213
+#endif
202 214
 	return 1;
203 215
 }
... ...
@@ -108,6 +108,7 @@ struct tm_binds {
108 108
 	tunref_f           t_unref;
109 109
 	run_failure_handlers_f run_failure_handlers;
110 110
 	cancel_uacs_f      cancel_uacs;
111
+	cancel_all_uacs_f  cancel_all_uacs;
111 112
 	prepare_request_within_f  prepare_request_within;
112 113
 	send_prepared_request_f   send_prepared_request;
113 114
 	enum route_mode*   route_mode;
... ...
@@ -119,6 +120,13 @@ struct tm_binds {
119 119
 	                    if no dlg callbacks are used/defined*/
120 120
 	void* reserved2;
121 121
 #endif
122
+#ifdef WITH_AS_SUPPORT
123
+	ack_local_uac_f           ack_local_uac;
124
+	t_get_canceled_ident_f    t_get_canceled_ident;
125
+#else
126
+	void* reserved3;
127
+	void* reserved4;
128
+#endif
122 129
 };
123 130
 
124 131
 extern int tm_init;
... ...
@@ -297,21 +297,19 @@ inline static struct dest_info *uri2dst(struct dest_info* dst,
297 297
 				return dst; /* found a good one */
298 298
 			}
299 299
 		}while(dns_srv_handle_next(dns_h, err));
300
-		LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for \"%.*s\" "
301
-					"af %d\n", host->len, ZSW(host->s), dst->to.s.sa_family);
300
+		ERR("no corresponding socket for \"%.*s\" af %d\n", host->len, 
301
+				ZSW(host->s), dst->to.s.sa_family);
302 302
 		/* try to continue */
303 303
 		return dst;
304 304
 	}
305 305
 #endif
306 306
 	if (sip_hostport2su(&dst->to, host, parsed_uri.port_no, &dst->proto)!=0){
307
-		LOG(L_ERR, "ERROR: uri2dst: failed to resolve \"%.*s\"\n",
308
-					host->len, ZSW(host->s));
307
+		ERR("failed to resolve \"%.*s\"\n", host->len, ZSW(host->s));
309 308
 		return 0;
310 309
 	}
311 310
 	dst->send_sock = get_send_socket(msg, &dst->to, dst->proto);
312 311
 	if (dst->send_sock==0) {
313
-		LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d\n", 
314
-					dst->to.s.sa_family);
312
+		ERR("no corresponding socket for af %d\n", dst->to.s.sa_family);
315 313
 		/* ser_error = E_NO_SOCKET;*/
316 314
 		/* try to continue */
317 315
 	}