Browse code

modules/tm: Remember per-branch onreply_route and onfailure_route settings

The onreply and onfailure routes were set only per transaction. This means
that when the onreply and/or failure route is changed in failure route (serial
forking), late replies to earlier branches would use the new onreply and
failure route instead of the routes set for them.

This commit copies the transaction's onreply and failure routes to the branch,
so the route set when the request is sent out is always chosen, no matter
how late the reply arrives.

Because the per-branch setting is copied after running onbranch_route, it is
now also possible to set the routes per-branch instead of per-transaction.

Alex Hermann authored on 11/10/2012 16:28:34
Showing 3 changed files
... ...
@@ -247,6 +247,10 @@ typedef struct ua_client
247 247
 	 */
248 248
 	struct retr_buf *local_ack;
249 249
 #endif
250
+	/* the route to take if no final positive reply arrived */
251
+	unsigned short on_failure;
252
+	/* the onreply_route to be processed if registered to do so */
253
+	unsigned short on_reply;
250 254
 }ua_client_type;
251 255
 
252 256
 
... ...
@@ -416,7 +416,11 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
416 416
 	} /* else next_hop==0 =>
417 417
 		no dst_uri / empty dst_uri and initial next_hop==0 =>
418 418
 		dst is pre-filled with a valid dst => use the pre-filled dst */
419
-	
419
+
420
+	/* Set on_reply and on_negative handlers for this branch to the handlers in the transaction */
421
+	t->uac[branch].on_reply = t->on_reply;
422
+	t->uac[branch].on_failure = t->on_failure;
423
+
420 424
 	/* check if send_sock is ok */
421 425
 	if (t->uac[branch].request.dst.send_sock==0) {
422 426
 		LOG(L_ERR, "ERROR: can't fwd to af %d, proto %d "
... ...
@@ -986,19 +986,20 @@ int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
986 986
 	struct sip_msg *shmem_msg = t->uas.request;
987 987
 	int on_failure;
988 988
 
989
+	on_failure = t->uac[picked_branch].on_failure;
990
+
989 991
 	/* failure_route for a local UAC? */
990 992
 	if (!shmem_msg) {
991 993
 		LOG(L_WARN,"Warning: run_failure_handlers: no UAC support (%d, %d) \n",
992
-			t->on_failure, t->tmcb_hl.reg_types);
994
+			on_failure, t->tmcb_hl.reg_types);
993 995
 		return 0;
994 996
 	}
995 997
 
996 998
 	/* don't start faking anything if we don't have to */
997
-	if (unlikely(!t->on_failure && !has_tran_tmcbs( t, TMCB_ON_FAILURE))) {
999
+	if (unlikely(!on_failure && !has_tran_tmcbs( t, TMCB_ON_FAILURE))) {
998 1000
 		LOG(L_WARN,
999
-			"Warning: run_failure_handlers: no negative handler (%d, %d)\n",
1000
-			t->on_failure,
1001
-			t->tmcb_hl.reg_types);
1001
+			"Warning: run_failure_handlers: no failure handler (%d, %d)\n",
1002
+			on_failure, t->tmcb_hl.reg_types);
1002 1003
 		return 1;
1003 1004
 	}
1004 1005
 
... ...
@@ -1013,11 +1014,10 @@ int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
1013 1013
 	if (unlikely(has_tran_tmcbs( t, TMCB_ON_FAILURE)) ) {
1014 1014
 		run_trans_callbacks( TMCB_ON_FAILURE, t, &faked_req, rpl, code);
1015 1015
 	}
1016
-	if (t->on_failure) {
1016
+	if (on_failure) {
1017 1017
 		/* avoid recursion -- if failure_route forwards, and does not
1018 1018
 		 * set next failure route, failure_route will not be reentered
1019 1019
 		 * on failure */
1020
-		on_failure = t->on_failure;
1021 1020
 		t->on_failure=0;
1022 1021
 		if (exec_pre_script_cb(&faked_req, FAILURE_CB_TYPE)>0) {
1023 1022
 			/* run a failure_route action if some was marked */
... ...
@@ -1290,7 +1290,7 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
1290 1290
 		replies_dropped = 0;
1291 1291
 		/* run ON_FAILURE handlers ( route and callbacks) */
1292 1292
 		if (unlikely(has_tran_tmcbs( Trans, TMCB_ON_FAILURE_RO|TMCB_ON_FAILURE)
1293
-						|| Trans->on_failure )) {
1293
+						|| Trans->uac[picked_branch].on_failure )) {
1294 1294
 			extra_flags=
1295 1295
 				((Trans->uac[picked_branch].request.flags & F_RB_TIMEOUT)?
1296 1296
 							FL_TIMEOUT:0) | 
... ...
@@ -2099,7 +2099,7 @@ int reply_received( struct sip_msg  *p_msg )
2099 2099
 			goto done;
2100 2100
 	}
2101 2101
 	
2102
-	onreply_route=t->on_reply;
2102
+	onreply_route=uac->on_reply;
2103 2103
 	if ( msg_status >= 200 ){
2104 2104
 #ifdef TM_ONREPLY_FINAL_DROP_OK
2105 2105
 #warning Experimental tm onreply_route final reply DROP support active