Parcourir la source

modules/tm: Enable named branch_failure routes

- branch failure routes must be named with the format:
-- "tm:branch-failure:myroute"
- and enabled with the function:
-- t_on_branch_failure("myroute")
Hugh Waite il y a 12 ans
Parent
commit
6e28b187ab
6 fichiers modifiés avec 80 ajouts et 16 suppressions
  1. 4 0
      modules/tm/h_table.h
  2. 1 0
      modules/tm/t_fwd.c
  3. 1 0
      modules/tm/t_lookup.c
  4. 32 9
      modules/tm/t_reply.c
  5. 2 1
      modules/tm/t_reply.h
  6. 40 6
      modules/tm/tm.c

+ 4 - 0
modules/tm/h_table.h

@@ -251,6 +251,8 @@ typedef struct ua_client
 #endif
 	/* the route to take if no final positive reply arrived */
 	unsigned short on_failure;
+	/* the route to take for all failure replies */
+	unsigned short on_branch_failure;
 	/* the onreply_route to be processed if registered to do so */
 	unsigned short on_reply;
 }ua_client_type;
@@ -439,6 +441,8 @@ typedef struct cell
 
 	/* the route to take if no final positive reply arrived */
 	unsigned short on_failure;
+	/* the route to take for all failure replies */
+	unsigned short on_branch_failure;
 	/* the onreply_route to be processed if registered to do so */
 	unsigned short on_reply;
 	 /* The route to take for each downstream branch separately */

+ 1 - 0
modules/tm/t_fwd.c

@@ -478,6 +478,7 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 	/* Set on_reply and on_negative handlers for this branch to the handlers in the transaction */
 	t->uac[branch].on_reply = t->on_reply;
 	t->uac[branch].on_failure = t->on_failure;
+	t->uac[branch].on_branch_failure = t->on_branch_failure;
 
 	/* check if send_sock is ok */
 	if (t->uac[branch].request.dst.send_sock==0) {

+ 1 - 0
modules/tm/t_lookup.c

@@ -1286,6 +1286,7 @@ static inline void init_new_t(struct cell *new_cell, struct sip_msg *p_msg)
 			lifetime=cfg_get(tm, tm_cfg, tm_max_noninv_lifetime);
 	}
 	new_cell->on_failure=get_on_failure();
+	new_cell->on_branch_failure=get_on_branch_failure();
 	new_cell->on_reply=get_on_reply();
 	new_cell->end_of_life=get_ticks_raw()+lifetime;;
 	new_cell->fr_timeout=(ticks_t)get_msgid_val(user_fr_timeout,

+ 32 - 9
modules/tm/t_reply.c

@@ -173,7 +173,7 @@ char *tm_tag_suffix;
 /* where to go if there is no positive reply (>=300) */
 static int goto_on_failure=0;
 /* where to go if a failure is returned on a branch */
-int goto_on_branch_failure=0;
+static int goto_on_branch_failure=0;
 /* where to go on receipt of reply */
 static int goto_on_reply=0;
 /* where to go on receipt of reply without transaction context */
@@ -264,6 +264,20 @@ void t_on_failure( unsigned int go_to )
 }
 
 
+void t_on_branch_failure( unsigned int go_to )
+{
+	struct cell *t = get_t();
+
+	/* in REPLY_ROUTE and FAILURE_ROUTE T will be set to current transaction;
+	 * in REQUEST_ROUTE T will be set only if the transaction was already
+	 * created; if not -> use the static variable */
+	if (!t || t==T_UNDEFINED )
+		goto_on_branch_failure=go_to;
+	else
+		t->on_branch_failure = go_to;
+}
+
+
 void t_on_reply( unsigned int go_to )
 {
 	struct cell *t = get_t();
@@ -282,6 +296,12 @@ unsigned int get_on_failure()
 {
 	return goto_on_failure;
 }
+
+unsigned int get_on_branch_failure()
+{
+	return goto_on_branch_failure;
+}
+
 unsigned int get_on_reply()
 {
 	return goto_on_reply;
@@ -1047,19 +1067,22 @@ int run_branch_failure_handlers(struct cell *t, struct sip_msg *rpl,
 {
 	static struct sip_msg faked_req;
 	struct sip_msg *shmem_msg = t->uas.request;
+	int on_branch_failure;
+
+	on_branch_failure = t->uac[picked_branch].on_branch_failure;
 
 	/* failure_route for a local UAC? */
 	if (!shmem_msg) {
 		LOG(L_WARN,"Warning: run_branch_failure_handlers: no UAC support (%d, %d) \n",
-			goto_on_branch_failure, t->tmcb_hl.reg_types);
+			on_branch_failure, t->tmcb_hl.reg_types);
 		return 0;
 	}
 
 	/* don't start faking anything if we don't have to */
-	if (unlikely((goto_on_branch_failure < 0) && !has_tran_tmcbs( t, TMCB_ON_BRANCH_FAILURE))) {
+	if (unlikely((on_branch_failure < 0) && !has_tran_tmcbs( t, TMCB_ON_BRANCH_FAILURE))) {
 		LOG(L_WARN,
 			"Warning: run_failure_handlers: no branch_failure handler (%d, %d)\n",
-			goto_on_branch_failure, t->tmcb_hl.reg_types);
+			on_branch_failure, t->tmcb_hl.reg_types);
 		return 1;
 	}
 
@@ -1076,10 +1099,11 @@ int run_branch_failure_handlers(struct cell *t, struct sip_msg *rpl,
 	if (unlikely(has_tran_tmcbs( t, TMCB_ON_BRANCH_FAILURE)) ) {
 		run_trans_callbacks( TMCB_ON_BRANCH_FAILURE, t, &faked_req, rpl, code);
 	}
-	if (goto_on_branch_failure >= 0) {
+	if (on_branch_failure >= 0) {
+		t->on_branch_failure = 0;
 		if (exec_pre_script_cb(&faked_req, BRANCH_FAILURE_CB_TYPE)>0) {
 			/* run a branch_failure_route action if some was marked */
-			if (run_top_route(event_rt.rlist[goto_on_branch_failure], &faked_req, 0)<0)
+			if (run_top_route(event_rt.rlist[on_branch_failure], &faked_req, 0)<0)
 				LOG(L_ERR, "ERROR: run_branch_failure_handlers: Error in run_top_route\n");
 			exec_post_script_cb(&faked_req, BRANCH_FAILURE_CB_TYPE);
 		}
@@ -1310,12 +1334,12 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
 
 		Trans->uac[branch].last_received=new_code;
 
-/* New branch failure route code */
 		/* also append the current reply to the transaction to
 		 * make it available in failure routes - a kind of "fake"
 		 * save of the final reply per branch */
 		Trans->uac[branch].reply = reply;
-		if (unlikely(goto_on_branch_failure > 0 )) {
+		if (unlikely(has_tran_tmcbs( Trans, TMCB_ON_BRANCH_FAILURE_RO|TMCB_ON_BRANCH_FAILURE)
+						|| (Trans->uac[picked_branch].on_branch_failure >= 0) )) {
 			extra_flags=
 				((Trans->uac[branch].request.flags & F_RB_TIMEOUT)?
 							FL_TIMEOUT:0) | 
@@ -1326,7 +1350,6 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
 			run_branch_failure_handlers( Trans, Trans->uac[branch].reply,
 									new_code, extra_flags);
 		}
-/* END - New branch failure route code */
 
 
 		/* if all_final return lowest */

+ 2 - 1
modules/tm/t_reply.h

@@ -61,7 +61,6 @@ enum rps {
 extern char tm_tags[TOTAG_VALUE_LEN];
 extern char *tm_tag_suffix;
 
-extern int goto_on_branch_failure;
 extern int goto_on_sl_reply;
 
 extern int failure_reply_mode;
@@ -215,6 +214,8 @@ void on_failure_reply( struct cell* t, struct sip_msg* msg,
 */
 void t_on_failure( unsigned int go_to );
 unsigned int get_on_failure(void);
+void t_on_branch_failure( unsigned int go_to );
+unsigned int get_on_branch_failure(void);
 void t_on_reply( unsigned int go_to );
 unsigned int get_on_reply(void);
 

+ 40 - 6
modules/tm/tm.c

@@ -190,6 +190,7 @@ MODULE_VERSION
 static int fixup_hostport2proxy(void** param, int param_no);
 static int fixup_proto_hostport2proxy(void** param, int param_no);
 static int fixup_on_failure(void** param, int param_no);
+static int fixup_on_branch_failure(void** param, int param_no);
 static int fixup_on_reply(void** param, int param_no);
 static int fixup_on_branch(void** param, int param_no);
 static int fixup_t_reply(void** param, int param_no);
@@ -272,6 +273,7 @@ inline static int w_t_forward_nonack_sctp(struct sip_msg*, char* str,char*);
 inline static int w_t_forward_nonack_to(struct sip_msg* msg, char* str,char*);
 inline static int w_t_relay_cancel(struct sip_msg *p_msg, char *_foo, char *_bar);
 inline static int w_t_on_failure(struct sip_msg* msg, char *go_to, char *foo);
+inline static int w_t_on_branch_failure(struct sip_msg* msg, char *go_to, char *foo);
 inline static int w_t_on_branch(struct sip_msg* msg, char *go_to, char *foo);
 inline static int w_t_on_reply(struct sip_msg* msg, char *go_to, char *foo );
 inline static int t_check_status(struct sip_msg* msg, char *match, char *foo);
@@ -409,12 +411,14 @@ static cmd_export_t cmds[]={
 			REQUEST_ROUTE},
 	{"t_on_failure",       w_t_on_failure,         1, fixup_on_failure,
 			REQUEST_ROUTE | FAILURE_ROUTE | TM_ONREPLY_ROUTE | BRANCH_ROUTE },
+	{"t_on_branch_failure",w_t_on_branch_failure,  1, fixup_on_branch_failure,
+			REQUEST_ROUTE | FAILURE_ROUTE | TM_ONREPLY_ROUTE | BRANCH_ROUTE },
 	{"t_on_reply",         w_t_on_reply,            1, fixup_on_reply,
 			REQUEST_ROUTE | FAILURE_ROUTE | TM_ONREPLY_ROUTE | BRANCH_ROUTE },
 	{"t_on_branch",       w_t_on_branch,         1, fixup_on_branch,
 			REQUEST_ROUTE | FAILURE_ROUTE },
 	{"t_check_status",     t_check_status,          1, fixup_t_check_status,
-			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_FAILURE_ROUTE},
+			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE},
 	{"t_write_req",       t_write_req,              2, fixup_t_write,
 			REQUEST_ROUTE | FAILURE_ROUTE },
 	{"t_write_unix",      t_write_unix,             2, fixup_t_write,
@@ -478,7 +482,7 @@ static cmd_export_t cmds[]={
 	{"t_next_contacts", t_next_contacts,            0, 0,
 			REQUEST_ROUTE | FAILURE_ROUTE},
 	{"t_next_contact_flow", t_next_contact_flow,            0, 0,
-			REQUEST_ROUTE | BRANCH_FAILURE_ROUTE},
+			REQUEST_ROUTE },
 
 	/* not applicable from the script */
 	{"load_tm",            (cmd_function)load_tm,           NO_SCRIPT,   0, 0},
@@ -602,6 +606,32 @@ static int fixup_on_failure(void** param, int param_no)
 	return 0;
 }
 
+#define BRANCH_FAILURE_ROUTE_PREFIX "tm:branch-failure"
+static int fixup_on_branch_failure(void** param, int param_no)
+{
+	char *full_route_name = NULL;
+	int len;
+	int ret = 0;
+	if (param_no==1){
+		if((len = strlen((char*)*param))<=1
+				&& (*(char*)(*param)==0 || *(char*)(*param)=='0')) {
+			*param = (void*)0;
+			return 0;
+		}
+		len += strlen(BRANCH_FAILURE_ROUTE_PREFIX) + 1;
+		if ((full_route_name = pkg_malloc(len+1)) == NULL)
+		{
+			LM_ERR("No memory left in branch_failure fixup\n");
+			return -1;
+		}
+		sprintf(full_route_name, "%s:%s", BRANCH_FAILURE_ROUTE_PREFIX, (char*)*param);
+		*param=(void*)full_route_name;
+		ret = fixup_routes("t_on_branch_failure", &event_rt, param);
+		pkg_free(full_route_name);
+	}
+	return ret;
+}
+
 
 static int fixup_on_reply(void** param, int param_no)
 {
@@ -734,6 +764,7 @@ static int script_init( struct sip_msg *foo, unsigned int flags, void *bar)
 		message's t_on_failure value
 	*/
 	t_on_failure( 0 );
+	t_on_branch_failure(0);
 	t_on_reply(0);
 	t_on_branch(0);
 	/* reset the kr status */
@@ -856,9 +887,6 @@ static int mod_init(void)
 	    return -1;
 	}
 
-	goto_on_branch_failure = route_lookup(&event_rt, "tm:branch-failure");
-	if (goto_on_branch_failure >= 0 && event_rt.rlist[goto_on_branch_failure]==0)
-		goto_on_branch_failure = -1; /* disable */
 #ifdef WITH_EVENT_LOCAL_REQUEST
 	goto_on_local_req=route_lookup(&event_rt, "tm:local-request");
 	if (goto_on_local_req>=0 && event_rt.rlist[goto_on_local_req]==0)
@@ -982,7 +1010,6 @@ static int t_check_status(struct sip_msg* msg, char *p1, char *foo)
 		status = int2str( lowest_status , 0);
 		break;
 	case BRANCH_FAILURE_ROUTE:
-#warning add the status for branch failure route
 		status = int2str(t->uac[get_t_branch()].last_received, 0);
 		break;
 	default:
@@ -1374,6 +1401,13 @@ inline static int w_t_on_failure( struct sip_msg* msg, char *go_to, char *foo)
 }
 
 
+inline static int w_t_on_branch_failure( struct sip_msg* msg, char *go_to, char *foo)
+{
+	t_on_branch_failure( (unsigned int )(long) go_to );
+	return 1;
+}
+
+
 inline static int w_t_on_branch( struct sip_msg* msg, char *go_to, char *foo)
 {
 	t_on_branch( (unsigned int )(long) go_to );