瀏覽代碼

modules/tm: Enable retrieving of branch instance id from uac structure

- Add instance to uac structure and populate when uac created
- Add get_this_branch_instance function to retrieve instance in a branch failure route
Hugh Waite 12 年之前
父節點
當前提交
2f85ac8828
共有 8 個文件被更改,包括 118 次插入36 次删除
  1. 1 4
      modules/tm/h_table.h
  2. 68 12
      modules/tm/t_fwd.c
  3. 0 1
      modules/tm/t_lookup.c
  4. 29 8
      modules/tm/t_reply.c
  5. 2 2
      modules/tm/t_reply.h
  6. 18 6
      modules/tm/t_serial.c
  7. 0 2
      modules/tm/tm.c
  8. 0 1
      modules/tm/tm_load.h

+ 1 - 4
modules/tm/h_table.h

@@ -229,6 +229,7 @@ typedef struct ua_client
 #endif
 	str uri;
 	str path;
+	str instance;
 	/* if we don't store, we at least want to know the status */
 	int             last_received;
 
@@ -249,8 +250,6 @@ 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;
@@ -443,8 +442,6 @@ 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*/

+ 68 - 12
modules/tm/t_fwd.c

@@ -187,7 +187,8 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 									str* next_hop,
 									struct socket_info* fsocket,
 									snd_flags_t snd_flags,
-									int fproto, int flags)
+									int fproto, int flags,
+									str *instance)
 {
 	char *shbuf;
 	struct lump* add_rm_backup, *body_lumps_backup;
@@ -200,6 +201,8 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 	int dst_uri_backed_up;
 	str path_bak;
 	int free_path;
+	str instance_bak;
+	int free_instance;
 	int backup_route_type;
 	snd_flags_t fwd_snd_flags_bak;
 	snd_flags_t rpl_snd_flags_bak;
@@ -219,6 +222,9 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 	path_bak.s=0;
 	path_bak.len=0;
 	free_path=0;
+	instance_bak.s=0;
+	instance_bak.len=0;
+	free_instance=0;
 	dst=&t->uac[branch].request.dst;
 
 	/* ... we calculate branch ... */	
@@ -259,6 +265,7 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 	parsed_uri_bak=i_req->parsed_uri;
 	parsed_uri_ok_bak=i_req->parsed_uri_ok;
 	path_bak=i_req->path_vec;
+	instance_bak=i_req->instance;
 	
 	if (unlikely(branch_route || has_tran_tmcbs(t, TMCB_REQUEST_FWDED))){
 		/* dup uris, path a.s.o. if we have a branch route or callback */
@@ -292,6 +299,21 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 			}
 			free_path=1;
 		}
+		/* update instance */
+		/* if instance points to msg instance, it needs to be "fixed" so that we 
+		   can change/update msg->instance */
+		if (instance==&i_req->instance)
+			instance=&instance_bak;
+		/* zero it first so that set_instancetor will work */
+		i_req->instance.s=0;
+		i_req->instance.len=0;
+		if (unlikely(instance)){
+			if (unlikely(set_instance(i_req, instance)<0)){
+				ret=E_OUT_OF_MEM;
+				goto error03;
+			}
+			free_instance=1;
+		}
 	
 		/* backup dst uri  & zero it*/
 		dst_uri_bak=i_req->dst_uri;
@@ -420,7 +442,6 @@ 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) {
@@ -464,6 +485,21 @@ static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 		t->uac[branch].path.s[i_req->path_vec.len]=0;
 		memcpy( t->uac[branch].path.s, i_req->path_vec.s, i_req->path_vec.len);
 	}
+	if (unlikely(i_req->instance.s && i_req->instance.len)){
+		t->uac[branch].instance.s=shm_malloc(i_req->instance.len+1);
+		if (unlikely(t->uac[branch].instance.s==0)) {
+			shm_free(shbuf);
+			t->uac[branch].request.buffer=0;
+			t->uac[branch].request.buffer_len=0;
+			t->uac[branch].uri.s=0;
+			t->uac[branch].uri.len=0;
+			ret=E_OUT_OF_MEM;
+			goto error01;
+		}
+		t->uac[branch].instance.len=i_req->instance.len;
+		t->uac[branch].instance.s[i_req->instance.len]=0;
+		memcpy( t->uac[branch].instance.s, i_req->instance.s, i_req->instance.len);
+	}
 	ret=0;
 
 error01:
@@ -475,6 +511,9 @@ error03:
 	if (unlikely(free_path)){
 		reset_path_vector(i_req);
 	}
+	if (unlikely(free_instance)){
+		reset_instance(i_req);
+	}
 	if (dst_uri_backed_up){
 		reset_dst_uri(i_req); /* free dst_uri */
 		i_req->dst_uri=dst_uri_bak;
@@ -484,6 +523,7 @@ error03:
 	i_req->parsed_uri=parsed_uri_bak;
 	i_req->parsed_uri_ok=parsed_uri_ok_bak;
 	i_req->path_vec=path_bak;
+	i_req->instance=instance_bak;
 	
 	/* Delete the duplicated lump lists, this will also delete
 	 * all lumps created here, such as lumps created in per-branch
@@ -647,7 +687,7 @@ int add_blind_uac( /*struct cell *t*/ )
 static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
 					str* next_hop, str* path, struct proxy_l *proxy,
 					struct socket_info* fsocket, snd_flags_t snd_flags,
-					int proto, int flags)
+					int proto, int flags, str *instance)
 {
 
 	int ret;
@@ -692,7 +732,7 @@ static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
 	/* now message printing starts ... */
 	if (unlikely( (ret=prepare_new_uac(t, request, branch, uri, path,
 										next_hop, fsocket, snd_flags,
-										proto, flags)) < 0)){
+										proto, flags, instance)) < 0)){
 		ser_error=ret;
 		goto error01;
 	}
@@ -732,7 +772,7 @@ static int add_uac_from_buf( struct cell *t, struct sip_msg *request,
 								struct socket_info* fsocket,
 								snd_flags_t send_flags,
 								int proto,
-								char *buf, short buf_len)
+								char *buf, short buf_len, str *instance)
 {
 
 	int ret;
@@ -803,6 +843,22 @@ static int add_uac_from_buf( struct cell *t, struct sip_msg *request,
 		t->uac[branch].path.s[path->len]=0;
 		memcpy( t->uac[branch].path.s, path->s, path->len);
 	}
+	/* copy the instance */
+	if (unlikely(instance && instance->s)){
+		t->uac[branch].instance.s=shm_malloc(instance->len+1);
+		if (unlikely(t->uac[branch].instance.s==0)) {
+			shm_free(shbuf);
+			t->uac[branch].request.buffer=0;
+			t->uac[branch].request.buffer_len=0;
+			t->uac[branch].uri.s=0;
+			t->uac[branch].uri.len=0;
+			ret=ser_error=E_OUT_OF_MEM;
+			goto error;
+		}
+		t->uac[branch].instance.len=instance->len;
+		t->uac[branch].instance.s[instance->len]=0;
+		memcpy( t->uac[branch].instance.s, instance->s, instance->len);
+	}
 	membar_write(); /* to allow lockless ops (e.g. prepare_to_cancel()) we want
 					   to be sure everything above is fully written before
 					   updating branches no. */
@@ -874,7 +930,7 @@ int add_uac_dns_fallback(struct cell *t, struct sip_msg* msg,
 							old_uac->request.dst.send_flags,
 							old_uac->request.dst.proto,
 							old_uac->request.buffer,
-							old_uac->request.buffer_len);
+							old_uac->request.buffer_len, NULL);
 			}else
 				/* add_uac will use dns_h => next_hop will be ignored.
 				 * Unfortunately we can't reuse the old buffer, the branch id
@@ -885,7 +941,7 @@ int add_uac_dns_fallback(struct cell *t, struct sip_msg* msg,
 								SND_F_FORCE_SOCKET)?
 									old_uac->request.dst.send_sock:0,
 							old_uac->request.dst.send_flags,
-							old_uac->request.dst.proto, UAC_DNS_FAILOVER_F);
+							old_uac->request.dst.proto, UAC_DNS_FAILOVER_F, &old_uac->instance);
 
 			if (ret<0){
 				/* failed, delete the copied dns_h */
@@ -960,7 +1016,7 @@ int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel,
 		if (unlikely((ret=prepare_new_uac( t_cancel, cancel_msg, branch,
 									&t_invite->uac[branch].uri,
 									&t_invite->uac[branch].path,
-									0, 0, snd_flags, PROTO_NONE, 0)) <0)){
+									0, 0, snd_flags, PROTO_NONE, 0, NULL)) <0)){
 			ser_error=ret;
 			goto error;
 		}
@@ -1419,7 +1475,7 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 	int success_branch;
 	int try_new;
 	int lock_replies;
-	str dst_uri, path;
+	str dst_uri, path, instance;
 	struct socket_info* si;
 	flag_t backup_bflags = 0;
 	flag_t bflags = 0;
@@ -1485,7 +1541,7 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 		branch_ret=add_uac( t, p_msg, GET_RURI(p_msg), GET_NEXT_HOP(p_msg),
 							&p_msg->path_vec, proxy, p_msg->force_send_socket,
 							p_msg->fwd_send_flags, proto,
-							(p_msg->dst_uri.len)?0:UAC_SKIP_BR_DST_F);
+							(p_msg->dst_uri.len)?0:UAC_SKIP_BR_DST_F, &p_msg->instance);
 		if (branch_ret>=0) 
 			added_branches |= 1<<branch_ret;
 		else
@@ -1494,14 +1550,14 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 
 	init_branch_iterator();
 	while((current_uri.s=next_branch( &current_uri.len, &q, &dst_uri, &path,
-										&bflags, &si, 0))) {
+										&bflags, &si, 0, &instance))) {
 		try_new++;
 		setbflagsval(0, bflags);
 
 		branch_ret=add_uac( t, p_msg, &current_uri,
 							(dst_uri.len) ? (&dst_uri) : &current_uri,
 							&path, proxy, si, p_msg->fwd_send_flags,
-							proto, (dst_uri.len)?0:UAC_SKIP_BR_DST_F);
+							proto, (dst_uri.len)?0:UAC_SKIP_BR_DST_F, &instance);
 		/* pick some of the errors in case things go wrong;
 		   note that picking lowest error is just as good as
 		   any other algorithm which picks any other negative

+ 0 - 1
modules/tm/t_lookup.c

@@ -1286,7 +1286,6 @@ 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,

+ 29 - 8
modules/tm/t_reply.c

@@ -282,10 +282,6 @@ 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;
@@ -1051,7 +1047,6 @@ 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;
 
 	/* failure_route for a local UAC? */
 	if (!shmem_msg) {
@@ -1061,7 +1056,7 @@ int run_branch_failure_handlers(struct cell *t, struct sip_msg *rpl,
 	}
 
 	/* don't start faking anything if we don't have to */
-	if (unlikely(!goto_on_branch_failure && !has_tran_tmcbs( t, TMCB_ON_BRANCH_FAILURE))) {
+	if (unlikely((goto_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);
@@ -1081,7 +1076,7 @@ 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) {
+	if (goto_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)
@@ -1320,7 +1315,7 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
 		 * make it available in failure routes - a kind of "fake"
 		 * save of the final reply per branch */
 		Trans->uac[branch].reply = reply;
-		if (unlikely(Trans->uac[branch].on_branch_failure )) {
+		if (unlikely(goto_on_branch_failure > 0 )) {
 			extra_flags=
 				((Trans->uac[branch].request.flags & F_RB_TIMEOUT)?
 							FL_TIMEOUT:0) | 
@@ -2612,6 +2607,32 @@ void t_drop_replies(int v)
 	drop_replies = v;
 }
 
+int t_get_this_branch_instance(struct sip_msg *msg, str *instance)
+{
+	struct cell *t;
+	if (!msg || !instance)
+	{
+		LM_ERR("Invalid params\n");
+		return -1;
+	}
+	if (get_route_type() != BRANCH_FAILURE_ROUTE)
+	{
+		LM_ERR("Called t_get_this_branch_instance not in a branch_failure_route\n");
+		return -1;
+	}
+
+	t = 0;
+	/* first get the transaction */
+	if (t_check(msg, 0 ) == -1) return -1;
+	if ((t = get_t()) == 0) {
+		LOG(L_ERR, "ERROR: t_check_status: cannot check status for a reply "
+			"which has no T-state established\n");
+		return -1;
+	}
+	*instance = t->uac[get_t_branch()].instance;
+	return 1;
+}
+
 #if 0
 static int send_reply(struct cell *trans, unsigned int code, str* text, str* body, str* headers, str* to_tag)
 {

+ 2 - 2
modules/tm/t_reply.h

@@ -215,8 +215,6 @@ 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);
 
@@ -245,4 +243,6 @@ void free_faked_req(struct sip_msg *faked_req, struct cell *t);
 typedef int (*tget_picked_f)(void);
 int t_get_picked_branch(void);
 
+int t_get_this_branch_instance(struct sip_msg *msg, str *instance);
+
 #endif

+ 18 - 6
modules/tm/t_serial.c

@@ -365,7 +365,7 @@ void add_contact_flows_avp(str *uri, str *dst_uri, str *path, str *sock_str,
  * Adds to request a new destination set that includes highest
  * priority class contacts in contacts_avp, but only one contact with same
  * +sip.instance value is included.  Others are added to contact_flows_avp
- * for later consumption by next_contact_flows().
+ * for later consumption by next_contact_flow().
  * Request URI is rewritten with first contact and the remaining contacts
  * (if any) are added as branches. Removes all highest priority contacts
  * from contacts_avp.
@@ -461,6 +461,7 @@ int t_next_contacts(struct sip_msg* msg, char* key, char* value)
 	il->instance.len = instance.len;
 	memcpy(il->instance.s, instance.s, instance.len);
 	il->next = (struct instance_list *)0;
+	set_instance(msg, &instance);
     }
 
     vavp = xavp_get(&ruid_name, xavp->val.v.xavp);
@@ -588,6 +589,11 @@ int t_next_contacts(struct sip_msg* msg, char* key, char* value)
         vavp = xavp_get(&ruid_name, xavp->val.v.xavp);
         ruid = vavp->val.v.s;
 
+	LM_DBG("Appending branch uri-'%.*s' dst-'%.*s' path-'%.*s' inst-'%.*s'\n",
+		uri.len, uri.s,
+		dst_uri.len, dst_uri.s,
+		path.len, path.s,
+		instance.len, instance.s);
 	if (append_branch(msg, &uri, &dst_uri, &path, 0, flags, sock, &instance, 0,
 			  &ruid) != 1) {
 	    LM_ERR("appending branch failed\n");
@@ -626,13 +632,11 @@ int t_next_contact_flow(struct sip_msg* msg, char* key, char* value)
 {
     str uri, dst_uri, path, instance, host, ruid;
 	str this_instance;
-	int this_branch;
     struct socket_info *sock;
     unsigned int flags;
     sr_xavp_t *xavp_list, *xavp, *next_xavp, *vavp;
     char *tmp;
     int port, proto;
-	int q_dummy;
 
     /* Check if contact_flows_avp has been defined */
     if (contact_flows_avp.len == 0) {
@@ -642,9 +646,13 @@ int t_next_contact_flow(struct sip_msg* msg, char* key, char* value)
     }
 
     /* Load Request-URI and branches */
-	this_branch = get_t_branch();
-	uri.s = get_branch(this_branch, &uri.len, &q_dummy, NULL, NULL, NULL, NULL, &this_instance);
+	t_get_this_branch_instance(msg, &this_instance);
 
+	if (this_instance.len == 0)
+	{
+		LM_DBG("No instance on this branch\n");
+		return -2;
+	}
 	/* Find first contact_flows_avp value */
 	xavp_list = xavp_get(&contact_flows_avp, NULL);
 	if (!xavp_list) {
@@ -713,6 +721,11 @@ int t_next_contact_flow(struct sip_msg* msg, char* key, char* value)
 		vavp = xavp_get(&ruid_name, xavp->val.v.xavp);
 		ruid = vavp->val.v.s;
 
+		LM_DBG("Appending branch uri-'%.*s' dst-'%.*s' path-'%.*s' inst-'%.*s'\n",
+			uri.len, uri.s,
+			dst_uri.len, dst_uri.s,
+			path.len, path.s,
+			instance.len, instance.s);
 		if (append_branch(msg, &uri, &dst_uri, &path, 0, flags, sock, &instance, 0,
 			  &ruid) != 1) {
 			LM_ERR("appending branch failed\n");
@@ -725,6 +738,5 @@ next_xavp:
 		xavp = next_xavp;
 	}
 
-
 	return 1;
 }

+ 0 - 2
modules/tm/tm.c

@@ -896,8 +896,6 @@ static int child_init(int rank)
 
 
 
-
-
 /**************************** wrapper functions ***************************/
 static int t_check_status(struct sip_msg* msg, char *p1, char *foo)
 {

+ 0 - 1
modules/tm/tm_load.h

@@ -177,7 +177,6 @@ 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;