Forráskód Böngészése

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 éve
szülő
commit
2f85ac8828

+ 1 - 4
modules/tm/h_table.h

@@ -229,6 +229,7 @@ typedef struct ua_client
 #endif
 #endif
 	str uri;
 	str uri;
 	str path;
 	str path;
+	str instance;
 	/* if we don't store, we at least want to know the status */
 	/* if we don't store, we at least want to know the status */
 	int             last_received;
 	int             last_received;
 
 
@@ -249,8 +250,6 @@ typedef struct ua_client
 #endif
 #endif
 	/* the route to take if no final positive reply arrived */
 	/* the route to take if no final positive reply arrived */
 	unsigned short on_failure;
 	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 */
 	/* the onreply_route to be processed if registered to do so */
 	unsigned short on_reply;
 	unsigned short on_reply;
 }ua_client_type;
 }ua_client_type;
@@ -443,8 +442,6 @@ typedef struct cell
 	unsigned short on_reply;
 	unsigned short on_reply;
 	 /* The route to take for each downstream branch separately */
 	 /* The route to take for each downstream branch separately */
 	unsigned short on_branch;
 	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) */
 	/* 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*/
 	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,
 									str* next_hop,
 									struct socket_info* fsocket,
 									struct socket_info* fsocket,
 									snd_flags_t snd_flags,
 									snd_flags_t snd_flags,
-									int fproto, int flags)
+									int fproto, int flags,
+									str *instance)
 {
 {
 	char *shbuf;
 	char *shbuf;
 	struct lump* add_rm_backup, *body_lumps_backup;
 	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;
 	int dst_uri_backed_up;
 	str path_bak;
 	str path_bak;
 	int free_path;
 	int free_path;
+	str instance_bak;
+	int free_instance;
 	int backup_route_type;
 	int backup_route_type;
 	snd_flags_t fwd_snd_flags_bak;
 	snd_flags_t fwd_snd_flags_bak;
 	snd_flags_t rpl_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.s=0;
 	path_bak.len=0;
 	path_bak.len=0;
 	free_path=0;
 	free_path=0;
+	instance_bak.s=0;
+	instance_bak.len=0;
+	free_instance=0;
 	dst=&t->uac[branch].request.dst;
 	dst=&t->uac[branch].request.dst;
 
 
 	/* ... we calculate branch ... */	
 	/* ... 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_bak=i_req->parsed_uri;
 	parsed_uri_ok_bak=i_req->parsed_uri_ok;
 	parsed_uri_ok_bak=i_req->parsed_uri_ok;
 	path_bak=i_req->path_vec;
 	path_bak=i_req->path_vec;
+	instance_bak=i_req->instance;
 	
 	
 	if (unlikely(branch_route || has_tran_tmcbs(t, TMCB_REQUEST_FWDED))){
 	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 */
 		/* 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;
 			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*/
 		/* backup dst uri  & zero it*/
 		dst_uri_bak=i_req->dst_uri;
 		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 */
 	/* 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_reply = t->on_reply;
 	t->uac[branch].on_failure = t->on_failure;
 	t->uac[branch].on_failure = t->on_failure;
-	t->uac[branch].on_branch_failure = t->on_branch_failure;
 
 
 	/* check if send_sock is ok */
 	/* check if send_sock is ok */
 	if (t->uac[branch].request.dst.send_sock==0) {
 	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;
 		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);
 		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;
 	ret=0;
 
 
 error01:
 error01:
@@ -475,6 +511,9 @@ error03:
 	if (unlikely(free_path)){
 	if (unlikely(free_path)){
 		reset_path_vector(i_req);
 		reset_path_vector(i_req);
 	}
 	}
+	if (unlikely(free_instance)){
+		reset_instance(i_req);
+	}
 	if (dst_uri_backed_up){
 	if (dst_uri_backed_up){
 		reset_dst_uri(i_req); /* free dst_uri */
 		reset_dst_uri(i_req); /* free dst_uri */
 		i_req->dst_uri=dst_uri_bak;
 		i_req->dst_uri=dst_uri_bak;
@@ -484,6 +523,7 @@ error03:
 	i_req->parsed_uri=parsed_uri_bak;
 	i_req->parsed_uri=parsed_uri_bak;
 	i_req->parsed_uri_ok=parsed_uri_ok_bak;
 	i_req->parsed_uri_ok=parsed_uri_ok_bak;
 	i_req->path_vec=path_bak;
 	i_req->path_vec=path_bak;
+	i_req->instance=instance_bak;
 	
 	
 	/* Delete the duplicated lump lists, this will also delete
 	/* Delete the duplicated lump lists, this will also delete
 	 * all lumps created here, such as lumps created in per-branch
 	 * 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,
 static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
 					str* next_hop, str* path, struct proxy_l *proxy,
 					str* next_hop, str* path, struct proxy_l *proxy,
 					struct socket_info* fsocket, snd_flags_t snd_flags,
 					struct socket_info* fsocket, snd_flags_t snd_flags,
-					int proto, int flags)
+					int proto, int flags, str *instance)
 {
 {
 
 
 	int ret;
 	int ret;
@@ -692,7 +732,7 @@ static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
 	/* now message printing starts ... */
 	/* now message printing starts ... */
 	if (unlikely( (ret=prepare_new_uac(t, request, branch, uri, path,
 	if (unlikely( (ret=prepare_new_uac(t, request, branch, uri, path,
 										next_hop, fsocket, snd_flags,
 										next_hop, fsocket, snd_flags,
-										proto, flags)) < 0)){
+										proto, flags, instance)) < 0)){
 		ser_error=ret;
 		ser_error=ret;
 		goto error01;
 		goto error01;
 	}
 	}
@@ -732,7 +772,7 @@ static int add_uac_from_buf( struct cell *t, struct sip_msg *request,
 								struct socket_info* fsocket,
 								struct socket_info* fsocket,
 								snd_flags_t send_flags,
 								snd_flags_t send_flags,
 								int proto,
 								int proto,
-								char *buf, short buf_len)
+								char *buf, short buf_len, str *instance)
 {
 {
 
 
 	int ret;
 	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;
 		t->uac[branch].path.s[path->len]=0;
 		memcpy( t->uac[branch].path.s, path->s, path->len);
 		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
 	membar_write(); /* to allow lockless ops (e.g. prepare_to_cancel()) we want
 					   to be sure everything above is fully written before
 					   to be sure everything above is fully written before
 					   updating branches no. */
 					   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.send_flags,
 							old_uac->request.dst.proto,
 							old_uac->request.dst.proto,
 							old_uac->request.buffer,
 							old_uac->request.buffer,
-							old_uac->request.buffer_len);
+							old_uac->request.buffer_len, NULL);
 			}else
 			}else
 				/* add_uac will use dns_h => next_hop will be ignored.
 				/* add_uac will use dns_h => next_hop will be ignored.
 				 * Unfortunately we can't reuse the old buffer, the branch id
 				 * 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)?
 								SND_F_FORCE_SOCKET)?
 									old_uac->request.dst.send_sock:0,
 									old_uac->request.dst.send_sock:0,
 							old_uac->request.dst.send_flags,
 							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){
 			if (ret<0){
 				/* failed, delete the copied dns_h */
 				/* 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,
 		if (unlikely((ret=prepare_new_uac( t_cancel, cancel_msg, branch,
 									&t_invite->uac[branch].uri,
 									&t_invite->uac[branch].uri,
 									&t_invite->uac[branch].path,
 									&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;
 			ser_error=ret;
 			goto error;
 			goto error;
 		}
 		}
@@ -1419,7 +1475,7 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 	int success_branch;
 	int success_branch;
 	int try_new;
 	int try_new;
 	int lock_replies;
 	int lock_replies;
-	str dst_uri, path;
+	str dst_uri, path, instance;
 	struct socket_info* si;
 	struct socket_info* si;
 	flag_t backup_bflags = 0;
 	flag_t backup_bflags = 0;
 	flag_t 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),
 		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->path_vec, proxy, p_msg->force_send_socket,
 							p_msg->fwd_send_flags, proto,
 							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) 
 		if (branch_ret>=0) 
 			added_branches |= 1<<branch_ret;
 			added_branches |= 1<<branch_ret;
 		else
 		else
@@ -1494,14 +1550,14 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 
 
 	init_branch_iterator();
 	init_branch_iterator();
 	while((current_uri.s=next_branch( &current_uri.len, &q, &dst_uri, &path,
 	while((current_uri.s=next_branch( &current_uri.len, &q, &dst_uri, &path,
-										&bflags, &si, 0))) {
+										&bflags, &si, 0, &instance))) {
 		try_new++;
 		try_new++;
 		setbflagsval(0, bflags);
 		setbflagsval(0, bflags);
 
 
 		branch_ret=add_uac( t, p_msg, &current_uri,
 		branch_ret=add_uac( t, p_msg, &current_uri,
 							(dst_uri.len) ? (&dst_uri) : &current_uri,
 							(dst_uri.len) ? (&dst_uri) : &current_uri,
 							&path, proxy, si, p_msg->fwd_send_flags,
 							&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;
 		/* pick some of the errors in case things go wrong;
 		   note that picking lowest error is just as good as
 		   note that picking lowest error is just as good as
 		   any other algorithm which picks any other negative
 		   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);
 			lifetime=cfg_get(tm, tm_cfg, tm_max_noninv_lifetime);
 	}
 	}
 	new_cell->on_failure=get_on_failure();
 	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->on_reply=get_on_reply();
 	new_cell->end_of_life=get_ticks_raw()+lifetime;;
 	new_cell->end_of_life=get_ticks_raw()+lifetime;;
 	new_cell->fr_timeout=(ticks_t)get_msgid_val(user_fr_timeout,
 	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;
 	return goto_on_failure;
 }
 }
-unsigned int get_on_branch_failure()
-{
-	return goto_on_branch_failure;
-}
 unsigned int get_on_reply()
 unsigned int get_on_reply()
 {
 {
 	return goto_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;
 	static struct sip_msg faked_req;
 	struct sip_msg *shmem_msg = t->uas.request;
 	struct sip_msg *shmem_msg = t->uas.request;
-	int on_branch_failure;
 
 
 	/* failure_route for a local UAC? */
 	/* failure_route for a local UAC? */
 	if (!shmem_msg) {
 	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 */
 	/* 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,
 		LOG(L_WARN,
 			"Warning: run_failure_handlers: no branch_failure handler (%d, %d)\n",
 			"Warning: run_failure_handlers: no branch_failure handler (%d, %d)\n",
 			goto_on_branch_failure, t->tmcb_hl.reg_types);
 			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)) ) {
 	if (unlikely(has_tran_tmcbs( t, TMCB_ON_BRANCH_FAILURE)) ) {
 		run_trans_callbacks( TMCB_ON_BRANCH_FAILURE, t, &faked_req, rpl, code);
 		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) {
 		if (exec_pre_script_cb(&faked_req, BRANCH_FAILURE_CB_TYPE)>0) {
 			/* run a branch_failure_route action if some was marked */
 			/* 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[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"
 		 * make it available in failure routes - a kind of "fake"
 		 * save of the final reply per branch */
 		 * save of the final reply per branch */
 		Trans->uac[branch].reply = reply;
 		Trans->uac[branch].reply = reply;
-		if (unlikely(Trans->uac[branch].on_branch_failure )) {
+		if (unlikely(goto_on_branch_failure > 0 )) {
 			extra_flags=
 			extra_flags=
 				((Trans->uac[branch].request.flags & F_RB_TIMEOUT)?
 				((Trans->uac[branch].request.flags & F_RB_TIMEOUT)?
 							FL_TIMEOUT:0) | 
 							FL_TIMEOUT:0) | 
@@ -2612,6 +2607,32 @@ void t_drop_replies(int v)
 	drop_replies = 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
 #if 0
 static int send_reply(struct cell *trans, unsigned int code, str* text, str* body, str* headers, str* to_tag)
 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 );
 void t_on_failure( unsigned int go_to );
 unsigned int get_on_failure(void);
 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 );
 void t_on_reply( unsigned int go_to );
 unsigned int get_on_reply(void);
 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);
 typedef int (*tget_picked_f)(void);
 int t_get_picked_branch(void);
 int t_get_picked_branch(void);
 
 
+int t_get_this_branch_instance(struct sip_msg *msg, str *instance);
+
 #endif
 #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
  * Adds to request a new destination set that includes highest
  * priority class contacts in contacts_avp, but only one contact with same
  * priority class contacts in contacts_avp, but only one contact with same
  * +sip.instance value is included.  Others are added to contact_flows_avp
  * +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
  * Request URI is rewritten with first contact and the remaining contacts
  * (if any) are added as branches. Removes all highest priority contacts
  * (if any) are added as branches. Removes all highest priority contacts
  * from contacts_avp.
  * from contacts_avp.
@@ -461,6 +461,7 @@ int t_next_contacts(struct sip_msg* msg, char* key, char* value)
 	il->instance.len = instance.len;
 	il->instance.len = instance.len;
 	memcpy(il->instance.s, instance.s, instance.len);
 	memcpy(il->instance.s, instance.s, instance.len);
 	il->next = (struct instance_list *)0;
 	il->next = (struct instance_list *)0;
+	set_instance(msg, &instance);
     }
     }
 
 
     vavp = xavp_get(&ruid_name, xavp->val.v.xavp);
     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);
         vavp = xavp_get(&ruid_name, xavp->val.v.xavp);
         ruid = vavp->val.v.s;
         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,
 	if (append_branch(msg, &uri, &dst_uri, &path, 0, flags, sock, &instance, 0,
 			  &ruid) != 1) {
 			  &ruid) != 1) {
 	    LM_ERR("appending branch failed\n");
 	    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 uri, dst_uri, path, instance, host, ruid;
 	str this_instance;
 	str this_instance;
-	int this_branch;
     struct socket_info *sock;
     struct socket_info *sock;
     unsigned int flags;
     unsigned int flags;
     sr_xavp_t *xavp_list, *xavp, *next_xavp, *vavp;
     sr_xavp_t *xavp_list, *xavp, *next_xavp, *vavp;
     char *tmp;
     char *tmp;
     int port, proto;
     int port, proto;
-	int q_dummy;
 
 
     /* Check if contact_flows_avp has been defined */
     /* Check if contact_flows_avp has been defined */
     if (contact_flows_avp.len == 0) {
     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 */
     /* 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 */
 	/* Find first contact_flows_avp value */
 	xavp_list = xavp_get(&contact_flows_avp, NULL);
 	xavp_list = xavp_get(&contact_flows_avp, NULL);
 	if (!xavp_list) {
 	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);
 		vavp = xavp_get(&ruid_name, xavp->val.v.xavp);
 		ruid = vavp->val.v.s;
 		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,
 		if (append_branch(msg, &uri, &dst_uri, &path, 0, flags, sock, &instance, 0,
 			  &ruid) != 1) {
 			  &ruid) != 1) {
 			LM_ERR("appending branch failed\n");
 			LM_ERR("appending branch failed\n");
@@ -725,6 +738,5 @@ next_xavp:
 		xavp = next_xavp;
 		xavp = next_xavp;
 	}
 	}
 
 
-
 	return 1;
 	return 1;
 }
 }

+ 0 - 2
modules/tm/tm.c

@@ -896,8 +896,6 @@ static int child_init(int rank)
 
 
 
 
 
 
-
-
 /**************************** wrapper functions ***************************/
 /**************************** wrapper functions ***************************/
 static int t_check_status(struct sip_msg* msg, char *p1, char *foo)
 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 {
 typedef struct tm_xbinds {
 	t_on_route_f t_on_failure;
 	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_branch;
 	t_on_route_f t_on_reply;
 	t_on_route_f t_on_reply;
 	t_no_param_f t_check_trans;
 	t_no_param_f t_check_trans;