瀏覽代碼

modules/tm: Initial revision of branch_failure_route

- New branch_failure_route defined
- cfg route is called but xlog() causes segfault
Hugh Waite 12 年之前
父節點
當前提交
4e0cf550f7
共有 9 個文件被更改,包括 145 次插入1 次删除
  1. 4 0
      modules/tm/h_table.h
  2. 1 0
      modules/tm/t_fwd.c
  3. 5 1
      modules/tm/t_hooks.h
  4. 1 0
      modules/tm/t_lookup.c
  5. 97 0
      modules/tm/t_reply.c
  6. 7 0
      modules/tm/t_reply.h
  7. 27 0
      modules/tm/tm.c
  8. 1 0
      modules/tm/tm_load.c
  9. 2 0
      modules/tm/tm_load.h

+ 4 - 0
modules/tm/h_table.h

@@ -249,6 +249,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 each downstream branch failure */
+	unsigned short on_branch_failure;
 	/* the onreply_route to be processed if registered to do so */
 	unsigned short on_reply;
 }ua_client_type;
@@ -441,6 +443,8 @@ typedef struct cell
 	unsigned short on_reply;
 	 /* The route to take for each downstream branch separately */
 	unsigned short on_branch;
+	 /* The route to take for each downstream branch failure */
+	unsigned short on_branch_failure;
 
 	/* place holder for MD5checksum  (meaningful only if syn_branch=0) */
 	char md5[0]; /* if syn_branch==0 then MD5_LEN bytes are extra alloc'ed*/

+ 1 - 0
modules/tm/t_fwd.c

@@ -420,6 +420,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) {

+ 5 - 1
modules/tm/t_hooks.h

@@ -82,7 +82,9 @@ struct cell;
 #endif
 #define TMCB_REQUEST_SENT_N     22
 #define TMCB_RESPONSE_SENT_N    23
-#define TMCB_MAX_N              23
+#define TMCB_ON_BRANCH_FAILURE_RO_N 24
+#define TMCB_ON_BRANCH_FAILURE_N 25
+#define TMCB_MAX_N              25
 
 
 #define TMCB_REQUEST_IN       (1<<TMCB_REQUEST_IN_N)
@@ -111,6 +113,8 @@ struct cell;
 #endif
 #define TMCB_REQUEST_SENT      (1<<TMCB_REQUEST_SENT_N)
 #define TMCB_RESPONSE_SENT     (1<<TMCB_RESPONSE_SENT_N)
+#define TMCB_ON_BRANCH_FAILURE (1<<TMCB_ON_BRANCH_FAILURE_N)
+#define TMCB_ON_BRANCH_FAILURE_RO (1<<TMCB_ON_BRANCH_FAILURE_RO_N)
 #define TMCB_MAX              ((1<<(TMCB_MAX_N+1))-1)
 
 

+ 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,

+ 97 - 0
modules/tm/t_reply.c

@@ -172,6 +172,8 @@ 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 */
+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 */
@@ -262,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();
@@ -280,6 +296,10 @@ 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;
@@ -1039,6 +1059,67 @@ int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
 }
 
 
+/* return 1 if a failure_route processes */
+int run_branch_failure_handlers(struct cell *t, struct sip_msg *rpl,
+					int code, int extra_flags)
+{
+	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",
+			on_branch_failure, t->tmcb_hl.reg_types);
+		return 0;
+	}
+
+	/* don't start faking anything if we don't have to */
+	if (unlikely(!on_branch_failure && !has_tran_tmcbs( t, TMCB_ON_BRANCH_FAILURE))) {
+		LOG(L_WARN,
+			"Warning: run_failure_handlers: no branch_failure handler (%d, %d)\n",
+			on_branch_failure, t->tmcb_hl.reg_types);
+		return 1;
+	}
+
+	if (!fake_req(&faked_req, shmem_msg, extra_flags, &t->uac[picked_branch])) {
+		LOG(L_ERR, "ERROR: run_branch_failure_handlers: fake_req failed\n");
+		return 0;
+	}
+	/* fake also the env. conforming to the fake msg */
+	faked_env( t, &faked_req);
+	/* DONE with faking ;-) -> run the branch_failure handlers */
+
+	if (unlikely(has_tran_tmcbs( t, TMCB_ON_BRANCH_FAILURE)) ) {
+		run_trans_callbacks( TMCB_ON_BRANCH_FAILURE, t, &faked_req, rpl, code);
+	}
+	if (on_branch_failure) {
+		/* avoid recursion -- if branch_failure_route forwards, and does not
+		 * set next branch failure route, branch_failure_route will not be reentered
+		 * on branch failure */
+		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(branch_failure_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);
+		}
+		/* update message flags, if changed in branch_failure route */
+		t->uas.request->flags = faked_req.flags;
+	}
+
+	/* restore original environment and free the fake msg */
+	faked_env( t, 0);
+	free_faked_req(&faked_req,t);
+
+	/* if branch_failure handler changed flag, update transaction context */
+	shmem_msg->flags = faked_req.flags;
+	return 1;
+}
+
+
 
 /* 401, 407, 415, 420, and 484 have priority over the other 4xx*/
 inline static short int get_4xx_prio(unsigned char xx)
@@ -1252,6 +1333,22 @@ 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 */
+		if (unlikely(has_tran_tmcbs( Trans, TMCB_ON_BRANCH_FAILURE_RO|TMCB_ON_BRANCH_FAILURE)
+						|| Trans->uac[branch].on_branch_failure )) {
+			extra_flags=
+				((Trans->uac[branch].request.flags & F_RB_TIMEOUT)?
+							FL_TIMEOUT:0) | 
+				((Trans->uac[branch].request.flags & F_RB_REPLIED)?
+						 	FL_REPLIED:0);
+			tm_ctx_set_branch_index(branch);
+			picked_branch = branch;
+			run_branch_failure_handlers( Trans, Trans->uac[branch].reply,
+									new_code, extra_flags);
+		}
+/* END - New branch failure route code */
+
+
 		/* if all_final return lowest */
 		picked_branch=t_pick_branch(branch,new_code, Trans, &picked_code);
 		if (picked_branch==-2) { /* branches open yet */

+ 7 - 0
modules/tm/t_reply.h

@@ -161,6 +161,11 @@ int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
 					int code, int extra_flags);
 typedef int (*run_failure_handlers_f)(struct cell*, struct sip_msg*, int, int);
 
+/* return 1 if a branch_failure_route processes */
+int run_branch_failure_handlers(struct cell *t, struct sip_msg *rpl,
+					int code, int extra_flags);
+typedef int (*run_branch_failure_handlers_f)(struct cell*, struct sip_msg*, int, int);
+
 
 /* Retransmits the last sent inbound reply.
  * Returns  -1 - error
@@ -209,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);
 

+ 27 - 0
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,6 +411,8 @@ 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,
@@ -601,6 +605,20 @@ static int fixup_on_failure(void** param, int param_no)
 }
 
 
+static int fixup_on_branch_failure(void** param, int param_no)
+{
+	if (param_no==1){
+		if(strlen((char*)*param)<=1
+				&& (*(char*)(*param)==0 || *(char*)(*param)=='0')) {
+			*param = (void*)0;
+			return 0;
+		}
+		return fixup_routes("t_on_branch_failure", &branch_failure_rt, param);
+	}
+	return 0;
+}
+
+
 
 static int fixup_on_reply(void** param, int param_no)
 {
@@ -733,6 +751,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 */
@@ -1368,6 +1387,12 @@ inline static int w_t_on_failure( struct sip_msg* msg, char *go_to, char *foo)
 	return 1;
 }
 
+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 );
@@ -1410,6 +1435,7 @@ static int w_t_is_set(struct sip_msg* msg, char *target, char *foo )
 			else
 				r = t->on_reply;
 			break;
+#warning need to add branch_failure_route
 	}
 	if(r) return 1;
 	return -1;
@@ -1423,6 +1449,7 @@ static int fixup_t_is_set(void** param, int param_no)
 		if((len==13 && strncmp((char*)*param, "failure_route", 13)==0)
 				|| (len==13 && strncmp((char*)*param, "onreply_route", 13)==0)
 				|| (len==12 && strncmp((char*)*param, "branch_route", 12)==0)) {
+#warning need to add branch_failure_route
 			return 0;
 		}
 

+ 1 - 0
modules/tm/tm_load.c

@@ -110,6 +110,7 @@ int load_tm( struct tm_binds *tmb)
 	tmb->t_uac_with_ids = t_uac_with_ids;
 	tmb->t_unref = t_unref;
 	tmb->run_failure_handlers = run_failure_handlers;
+	tmb->run_branch_failure_handlers = run_branch_failure_handlers;
 	tmb->cancel_uacs = cancel_uacs;
 	tmb->cancel_all_uacs = cancel_all_uacs;
 	tmb->prepare_request_within = prepare_req_within;

+ 2 - 0
modules/tm/tm_load.h

@@ -88,6 +88,7 @@ struct tm_binds {
 	trelease_f         t_release;
 	tunref_f           t_unref;
 	run_failure_handlers_f run_failure_handlers;
+	run_branch_failure_handlers_f run_branch_failure_handlers;
 	cancel_uacs_f      cancel_uacs;
 	cancel_all_uacs_f  cancel_all_uacs;
 	prepare_request_within_f  prepare_request_within;
@@ -176,6 +177,7 @@ int t_is_canceled(struct sip_msg* msg);
 
 typedef struct tm_xbinds {
 	t_on_route_f t_on_failure;
+	t_on_route_f t_on_branch_failure;
 	t_on_route_f t_on_branch;
 	t_on_route_f t_on_reply;
 	t_no_param_f t_check_trans;