浏览代码

tm: fix/support changing r-uris and path in branch routes

- changing the r-uri in a branch route is now safe and the change
  will propagate to branches created due to dns failover.
- changing path in a branch route is now allowed and it will
  propagate to possible dns failover branches.
- optimize the no branch route & no callback case.
- build the branch buffer directly into shm mem.
- s/prepare_uac_request/prepare_new_uac/
- prepare_new_uac() takes care now also of setting the branch
  retr. buffer, uri and path (functionality moved from add_uac())
Andrei Pelinescu-Onciul 16 年之前
父节点
当前提交
610cb930be
共有 1 个文件被更改,包括 247 次插入170 次删除
  1. 247 170
      modules/tm/t_fwd.c

+ 247 - 170
modules/tm/t_fwd.c

@@ -81,7 +81,9 @@
  * 2009-06-01  Pre- and post-script callbacks of branch route are 
  * 2009-06-01  Pre- and post-script callbacks of branch route are 
  *             executed (Miklos)
  *             executed (Miklos)
  * 2009-10-26  support for changing dst_uri in branch routes,
  * 2009-10-26  support for changing dst_uri in branch routes,
- *             s/print_uac_request/prepare_uac_request/ (andrei)
+ *             s/print_uac_request/prepare_new_uac/ (andrei)
+ * 2009-10-28  support for changing r-uris and path in branch routes; more of
+ *             add_uac() functionality moved into prepare_new_uac()  (andrei)
  */
  */
 
 
 #include "defs.h"
 #include "defs.h"
@@ -148,17 +150,18 @@ unsigned int get_on_branch(void)
 
 
 
 
 
 
-/* prepare_uac_request flags */
+/* prepare_new_uac flags */
 #define UAC_DNS_FAILOVER_F 1 /**< new branch due to dns failover */
 #define UAC_DNS_FAILOVER_F 1 /**< new branch due to dns failover */
 
 
 
 
-/** create a branch "buffer".
- * Creates the buffer used in the branch rb, fills the sending information
- * (t->uac[branch].request.dst) if next_hop!=0 and runs the on_branch route.
+/** prepares a new branch "buffer".
+ * Creates the buffer used in the branch rb, fills everything needed (
+   the sending information: t->uac[branch].request.dst, branch buffer, uri
+   path vector a.s.o.) and runs the on_branch route.
  * t->uac[branch].request.dst will be filled if next_hop !=0 with the result
  * t->uac[branch].request.dst will be filled if next_hop !=0 with the result
  * of the DNS resolution (next_hop and fproto).
  * of the DNS resolution (next_hop and fproto).
  * If next_hop is 0 all the dst members except the send_flags are read-only
  * If next_hop is 0 all the dst members except the send_flags are read-only
- * (send_flags it's updated).
+ * (send_flags it's updated) and are supposed to be pre-filled.
  *
  *
  * @param t  - transaction
  * @param t  - transaction
  * @param i_req - corresponding sip_msg, must be non-null, flags might be
  * @param i_req - corresponding sip_msg, must be non-null, flags might be
@@ -173,39 +176,42 @@ unsigned int get_on_branch(void)
  *              a pre-filled valid request.dst.
  *              a pre-filled valid request.dst.
  * @param fproto - forced proto for forwarding. Used only if next_hop!=0.
  * @param fproto - forced proto for forwarding. Used only if next_hop!=0.
  * @param flags - 0 or UAC_DNS_FAILOVER_F for now.
  * @param flags - 0 or UAC_DNS_FAILOVER_F for now.
- * @param len - resul parameter, it will be filled with the created buffer 
- *              length.
- * @return pointer to shm alloc'ed buffer on success (*len and dst
- *  are filled/modified), 0 on failure and sets ser_error.
+ *
+ * @return  0 on success, < 0 (ser_errror E***) on failure.
  */
  */
-static char *prepare_uac_request( struct cell *t, struct sip_msg *i_req,
+static int prepare_new_uac( struct cell *t, struct sip_msg *i_req,
 									int branch, str *uri, str* path,
 									int branch, str *uri, str* path,
 									str* next_hop, int fproto,
 									str* next_hop, int fproto,
-									int flags,
-									unsigned int *len)
+									int flags)
 {
 {
-	char *buf, *shbuf;
-	str* msg_uri;
+	char *shbuf;
 	struct lump* add_rm_backup, *body_lumps_backup;
 	struct lump* add_rm_backup, *body_lumps_backup;
 	struct sip_uri parsed_uri_bak;
 	struct sip_uri parsed_uri_bak;
-	int parsed_uri_ok_bak, uri_backed_up;
+	int ret;
+	unsigned int len;
+	int parsed_uri_ok_bak, free_new_uri;
 	str msg_uri_bak;
 	str msg_uri_bak;
 	str dst_uri_bak;
 	str dst_uri_bak;
+	int dst_uri_backed_up;
 	str path_bak;
 	str path_bak;
-	int path_backed_up;
+	int free_path;
 	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;
 	struct dest_info *dst;
 	struct dest_info *dst;
 
 
 	shbuf=0;
 	shbuf=0;
+	ret=E_UNSPEC;
 	msg_uri_bak.s=0; /* kill warnings */
 	msg_uri_bak.s=0; /* kill warnings */
 	msg_uri_bak.len=0;
 	msg_uri_bak.len=0;
 	parsed_uri_ok_bak=0;
 	parsed_uri_ok_bak=0;
-	uri_backed_up=0;
+	free_new_uri=0;
+	dst_uri_bak.s=0;
+	dst_uri_bak.len=0;
+	dst_uri_backed_up=0;
 	path_bak.s=0;
 	path_bak.s=0;
 	path_bak.len=0;
 	path_bak.len=0;
-	path_backed_up=0;
+	free_path=0;
 	dst=&t->uac[branch].request.dst;
 	dst=&t->uac[branch].request.dst;
 
 
 	/* ... we calculate branch ... */	
 	/* ... we calculate branch ... */	
@@ -213,39 +219,12 @@ static char *prepare_uac_request( struct cell *t, struct sip_msg *i_req,
 			&i_req->add_to_branch_len ))
 			&i_req->add_to_branch_len ))
 	{
 	{
 		LOG(L_ERR, "ERROR: print_uac_request: branch computation failed\n");
 		LOG(L_ERR, "ERROR: print_uac_request: branch computation failed\n");
-		ser_error=E_UNSPEC;
+		ret=E_UNSPEC;
 		goto error00;
 		goto error00;
 	}
 	}
-	
-	/* ... update uri ... */
-	msg_uri=GET_RURI(i_req);
-	if ((msg_uri->s!=uri->s) || (msg_uri->len!=uri->len)){
-		msg_uri_bak=i_req->new_uri;
-		parsed_uri_ok_bak=i_req->parsed_uri_ok;
-		parsed_uri_bak=i_req->parsed_uri;
-		i_req->new_uri=*uri;
-		i_req->parsed_uri_ok=0;
-		uri_backed_up=1;
-	}
-	/* update path_vec */
-	if (unlikely((i_req->path_vec.s!=path->s) ||
-					(i_req->path_vec.len!=path->len))){
-		path_bak=i_req->path_vec;
-		i_req->path_vec=*path;
-		path_backed_up=1;
-	}
-	/* backup dst uri  & zero it*/
-	dst_uri_bak=i_req->dst_uri;
-	i_req->dst_uri.s=0;
-	i_req->dst_uri.len=0;
-	if (likely(next_hop)){
-		/* set dst uri to next_hop for the on_branch route */
-		if (unlikely(set_dst_uri(i_req, next_hop)<0)){
-			ser_error=E_OUT_OF_MEM;
-			goto error03;
-		}
-	}
 
 
+	/* dup lumps
+	 * TODO: clone lumps only if needed */
 #ifdef POSTPONE_MSG_CLONING
 #ifdef POSTPONE_MSG_CLONING
 	/* lumps can be set outside of the lock, make sure that we read
 	/* lumps can be set outside of the lock, make sure that we read
 	 * the up-to-date values */
 	 * the up-to-date values */
@@ -253,45 +232,149 @@ static char *prepare_uac_request( struct cell *t, struct sip_msg *i_req,
 #endif
 #endif
 	add_rm_backup = i_req->add_rm;
 	add_rm_backup = i_req->add_rm;
 	body_lumps_backup = i_req->body_lumps;
 	body_lumps_backup = i_req->body_lumps;
-	i_req->add_rm = dup_lump_list(i_req->add_rm);
-	i_req->body_lumps = dup_lump_list(i_req->body_lumps);
-
-	if (unlikely(branch_route)) {
-		/* run branch_route actions if provided */
-		backup_route_type = get_route_type();
-		set_route_type(BRANCH_ROUTE);
-		tm_ctx_set_branch_index(branch+1);
-		if (exec_pre_script_cb(i_req, BRANCH_CB_TYPE)>0) {
-			/* backup ireq msg send flags */
-			fwd_snd_flags_bak=i_req->fwd_send_flags;;
-			rpl_snd_flags_bak=i_req->rpl_send_flags;
-			i_req->fwd_send_flags=dst->send_flags /* intial value  */;
-			if (run_top_route(branch_rt.rlist[branch_route], i_req, 0) < 0) {
-				LOG(L_ERR, "Error in run_top_route\n");
-			}
-			/* update dst send_flags */
-			dst->send_flags=i_req->fwd_send_flags;
-			/* restore ireq_msg flags */
-			i_req->fwd_send_flags=fwd_snd_flags_bak;
-			i_req->rpl_send_flags=rpl_snd_flags_bak;
-			exec_post_script_cb(i_req, BRANCH_CB_TYPE);
+	i_req->add_rm=0;
+	i_req->body_lumps=0;
+	if (unlikely(i_req->add_rm)){
+		i_req->add_rm = dup_lump_list(i_req->add_rm);
+		if (unlikely(i_req->add_rm==0)){
+			ret=E_OUT_OF_MEM;
+			goto error04;
 		}
 		}
-		tm_ctx_set_branch_index(0);
-		set_route_type(backup_route_type);
 	}
 	}
-
-	/* run the specific callbacks for this transaction */
-	if (unlikely(has_tran_tmcbs(t, TMCB_REQUEST_FWDED)))
-		run_trans_callbacks( TMCB_REQUEST_FWDED , t, i_req, 0,
-								-i_req->REQ_METHOD);
+	if (unlikely(i_req->body_lumps)){
+		i_req->body_lumps = dup_lump_list(i_req->body_lumps);
+		if (unlikely(i_req->body_lumps==0)){
+			ret=E_OUT_OF_MEM;
+			goto error04;
+		}
+	}
+	/* backup uri & path: we need to change them so that build_req...()
+	   will use uri & path and not the ones in the original msg (i_req)
+	   => we must back them up so that we can restore them to the original
+	   value after building the send buffer */
+	msg_uri_bak=i_req->new_uri;
+	parsed_uri_bak=i_req->parsed_uri;
+	parsed_uri_ok_bak=i_req->parsed_uri_ok;
+	path_bak=i_req->path_vec;
 	
 	
-	if (likely( !(flags & UAC_DNS_FAILOVER_F) && i_req->dst_uri.s &&
-				i_req->dst_uri.len)){
-		/* no dns failover and non-empty dst_uri => use it as dst
-		  (on dns failover dns_h will be non-empty => next_hop will be
-		   ignored) */
-		next_hop=&i_req->dst_uri;
+	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 */
+		/* ... set ruri ... */
+		/* if uri points to new_uri, it needs to be "fixed" so that we can
+		   change msg->new_uri */
+		if (uri==&i_req->new_uri)
+			uri=&msg_uri_bak;
+		i_req->parsed_uri_ok=0;
+		i_req->new_uri.s=pkg_malloc(uri->len);
+		if (unlikely(i_req->new_uri.s==0)){
+			ret=E_OUT_OF_MEM;
+			goto error03;
+		}
+		free_new_uri=1;
+		memcpy(i_req->new_uri.s, uri->s, uri->len);
+		i_req->new_uri.len=uri->len;
+	
+		/* update path_vec */
+		/* if path points to msg path_vec, it needs to be "fixed" so that we 
+		   can change/update msg->path_vec */
+		if (path==&i_req->path_vec)
+			path=&path_bak;
+		/* zero it first so that set_path_vector will work */
+		i_req->path_vec.s=0;
+		i_req->path_vec.len=0;
+		if (unlikely(path)){
+			if (unlikely(set_path_vector(i_req, path)<0)){
+				ret=E_OUT_OF_MEM;
+				goto error03;
+			}
+			free_path=1;
+		}
+	
+		/* backup dst uri  & zero it*/
+		dst_uri_bak=i_req->dst_uri;
+		dst_uri_backed_up=1;
+		/* if next_hop points to dst_uri, it needs to be "fixed" so that we
+		   can change msg->dst_uri */
+		if (next_hop==&i_req->dst_uri)
+			next_hop=&dst_uri_bak;
+		/* zero it first so that set_dst_uri will work */
+		i_req->dst_uri.s=0;
+		i_req->dst_uri.len=0;
+		if (likely(next_hop)){
+			/* set dst uri to next_hop for the on_branch route */
+			if (unlikely(set_dst_uri(i_req, next_hop)<0)){
+				ret=E_OUT_OF_MEM;
+				goto error03;
+			}
+		}
+
+		if (likely(branch_route)) {
+			/* run branch_route actions if provided */
+			backup_route_type = get_route_type();
+			set_route_type(BRANCH_ROUTE);
+			tm_ctx_set_branch_index(branch+1);
+			/* no need to backup/set avp lists: the on_branch route is run
+			   only in the main route context (e.g. t_relay() in the main
+			   route) or in the failure route context (e.g. append_branch &
+			   t_relay()) and in both cases the avp lists are properly set
+			   Note: the branch route is not run on delayed dns failover 
+			   (for that to work one would have to set branch_route prior to
+			   calling add_uac(...) and then reset it afterwards).
+			   (
+			 */
+			if (exec_pre_script_cb(i_req, BRANCH_CB_TYPE)>0) {
+				/* backup ireq msg send flags */
+				fwd_snd_flags_bak=i_req->fwd_send_flags;;
+				rpl_snd_flags_bak=i_req->rpl_send_flags;
+				i_req->fwd_send_flags=dst->send_flags /* intial value  */;
+				if (run_top_route(branch_rt.rlist[branch_route], i_req, 0) < 0)
+				{
+					LOG(L_ERR, "Error in run_top_route\n");
+				}
+				/* update dst send_flags */
+				dst->send_flags=i_req->fwd_send_flags;
+				/* restore ireq_msg flags */
+				i_req->fwd_send_flags=fwd_snd_flags_bak;
+				i_req->rpl_send_flags=rpl_snd_flags_bak;
+				exec_post_script_cb(i_req, BRANCH_CB_TYPE);
+			}
+			tm_ctx_set_branch_index(0);
+			set_route_type(backup_route_type);
+		}
+
+		/* run the specific callbacks for this transaction */
+		if (unlikely(has_tran_tmcbs(t, TMCB_REQUEST_FWDED)))
+			run_trans_callbacks( TMCB_REQUEST_FWDED , t, i_req, 0,
+									-i_req->REQ_METHOD);
+		
+		if (likely( !(flags & UAC_DNS_FAILOVER_F) && i_req->dst_uri.s &&
+					i_req->dst_uri.len)){
+			/* no dns failover and non-empty dst_uri => use it as dst
+			  (on dns failover dns_h will be non-empty => next_hop will be
+			   ignored) */
+			next_hop=&i_req->dst_uri;
+		}
+	}else{
+		/* no branch route and no TMCB_REQUEST_FWDED callback => set
+		   msg uri and path to the new values (if needed) */
+		if (unlikely((uri->s!=i_req->new_uri.s || uri->len!=i_req->new_uri.len)
+					&& (i_req->new_uri.s!=0 ||
+						uri->s!=i_req->first_line.u.request.uri.s ||
+						uri->len!=i_req->first_line.u.request.uri.len) )){
+			/* uri is different from i_req uri => replace i_req uri and force
+			   uri re-parsing */
+			i_req->new_uri=*uri;
+			i_req->parsed_uri_ok=0;
+		}
+		if (unlikely(path && (i_req->path_vec.s!=path->s ||
+							  i_req->path_vec.len!=path->len))){
+			i_req->path_vec=*path;
+		}else if (unlikely(path==0 && i_req->path_vec.len!=0)){
+			i_req->path_vec.s=0;
+			i_req->path_vec.len=0;
+		}
 	}
 	}
+	
 	if (likely(next_hop!=0 || (flags & UAC_DNS_FAILOVER_F))){
 	if (likely(next_hop!=0 || (flags & UAC_DNS_FAILOVER_F))){
 		/* next_hop present => use it for dns resolution */
 		/* next_hop present => use it for dns resolution */
 #ifdef USE_DNS_FAILOVER
 #ifdef USE_DNS_FAILOVER
@@ -302,7 +385,7 @@ static char *prepare_uac_request( struct cell *t, struct sip_msg *i_req,
 		if (uri2dst(dst, i_req, next_hop?next_hop:uri, fproto)==0)
 		if (uri2dst(dst, i_req, next_hop?next_hop:uri, fproto)==0)
 #endif
 #endif
 		{
 		{
-			ser_error=E_BAD_ADDRESS;
+			ret=E_BAD_ADDRESS;
 			goto error01;
 			goto error01;
 		}
 		}
 	} /* else next_hop==0 =>
 	} /* else next_hop==0 =>
@@ -314,59 +397,77 @@ static char *prepare_uac_request( struct cell *t, struct sip_msg *i_req,
 		LOG(L_ERR, "ERROR: can't fwd to af %d, proto %d "
 		LOG(L_ERR, "ERROR: can't fwd to af %d, proto %d "
 			" (no corresponding listening socket)\n",
 			" (no corresponding listening socket)\n",
 			dst->to.s.sa_family, dst->proto );
 			dst->to.s.sa_family, dst->proto );
-		ser_error=E_NO_SOCKET;
+		ret=E_NO_SOCKET;
 		goto error01;
 		goto error01;
 	}
 	}
 	/* ... and build it now */
 	/* ... and build it now */
-	buf=build_req_buf_from_sip_req( i_req, len, dst, 0);
+	shbuf=build_req_buf_from_sip_req( i_req, &len, dst, BUILD_IN_SHM);
+	if (!shbuf) {
+		LOG(L_ERR, "ERROR: print_uac_request: no shm mem\n"); 
+		ret=E_OUT_OF_MEM;
+		goto error01;
+	}
 #ifdef DBG_MSG_QA
 #ifdef DBG_MSG_QA
-	if (buf[*len-1]==0) {
+	if (shbuf[len-1]==0) {
 		LOG(L_ERR, "ERROR: print_uac_request: sanity check failed\n");
 		LOG(L_ERR, "ERROR: print_uac_request: sanity check failed\n");
 		abort();
 		abort();
 	}
 	}
 #endif
 #endif
-	if (!buf) {
-		LOG(L_ERR, "ERROR: print_uac_request: no pkg_mem\n"); 
-		ser_error=E_OUT_OF_MEM;
-		goto error01;
-	}
-
-	shbuf=(char *)shm_malloc(*len);
-	if (!shbuf) {
-		ser_error=E_OUT_OF_MEM;
-		LOG(L_ERR, "ERROR: print_uac_request: no shmem\n");
-		goto error02;
+	/* things went well, move ahead and install new buffer! */
+	t->uac[branch].request.buffer=shbuf;
+	t->uac[branch].request.buffer_len=len;
+	t->uac[branch].uri.s=t->uac[branch].request.buffer+
+							i_req->first_line.u.request.method.len+1;
+	t->uac[branch].uri.len=GET_RURI(i_req)->len;
+	if (unlikely(i_req->path_vec.s && i_req->path_vec.len)){
+		t->uac[branch].path.s=shm_malloc(i_req->path_vec.len+1);
+		if (unlikely(t->uac[branch].path.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].path.len=i_req->path_vec.len;
+		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( shbuf, buf, *len );
+	ret=0;
 
 
-error02:
-	pkg_free( buf );
 error01:
 error01:
-	     /* Delete the duplicated lump lists, this will also delete
-	      * all lumps created here, such as lumps created in per-branch
-	      * routing sections, Via, and Content-Length headers created in
-	      * build_req_buf_from_sip_req
-	      */
+error03:
+	/* restore the new_uri & path from the backup */
+	if (unlikely(free_new_uri && i_req->new_uri.s)){
+			pkg_free(i_req->new_uri.s);
+	}
+	if (unlikely(free_path)){
+		reset_path_vector(i_req);
+	}
+	if (dst_uri_backed_up){
+		reset_dst_uri(i_req); /* free dst_uri */
+		i_req->dst_uri=dst_uri_bak;
+	}
+	/* restore original new_uri and path values */
+	i_req->new_uri=msg_uri_bak;
+	i_req->parsed_uri=parsed_uri_bak;
+	i_req->parsed_uri_ok=parsed_uri_ok_bak;
+	i_req->path_vec=path_bak;
+	/* Delete the duplicated lump lists, this will also delete
+	 * all lumps created here, such as lumps created in per-branch
+	 * routing sections, Via, and Content-Length headers created in
+	 * build_req_buf_from_sip_req
+	 */
+error04:
 	free_duped_lump_list(i_req->add_rm);
 	free_duped_lump_list(i_req->add_rm);
 	free_duped_lump_list(i_req->body_lumps);
 	free_duped_lump_list(i_req->body_lumps);
 	     /* Restore the lists from backups */
 	     /* Restore the lists from backups */
 	i_req->add_rm = add_rm_backup;
 	i_req->add_rm = add_rm_backup;
 	i_req->body_lumps = body_lumps_backup;
 	i_req->body_lumps = body_lumps_backup;
-error03:
-	/* restore the new_uri from the backup */
-	if (uri_backed_up){
-		i_req->new_uri=msg_uri_bak;
-		i_req->parsed_uri=parsed_uri_bak;
-		i_req->parsed_uri_ok=parsed_uri_ok_bak;
-	}
-	if (unlikely(path_backed_up)){
-		i_req->path_vec=path_bak;
-	}
-	reset_dst_uri(i_req); /* free dst_uri */
-	i_req->dst_uri=dst_uri_bak;
 
 
 error00:
 error00:
-	return shbuf;
+	return ret;
 }
 }
 
 
 #ifdef USE_DNS_FAILOVER
 #ifdef USE_DNS_FAILOVER
@@ -506,8 +607,8 @@ int add_blind_uac( /*struct cell *t*/ )
  *                    next_hop/uri and it will be used for forwarding.
  *                    next_hop/uri and it will be used for forwarding.
  *  @param proto    - forced protocol for forwarding (overrides the protocol
  *  @param proto    - forced protocol for forwarding (overrides the protocol
  *                    in next_hop/uri or proxy if != PROTO_NONE).
  *                    in next_hop/uri or proxy if != PROTO_NONE).
- *  @param flags    - special flags passed to prepare_uac_request().
- *                    @see prepare_uac_request().
+ *  @param flags    - special flags passed to prepare_new_uac().
+ *                    @see prepare_new_uac().
  *  @returns branch id (>=0) or error (<0)
  *  @returns branch id (>=0) or error (<0)
 */
 */
 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,
@@ -517,8 +618,9 @@ static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
 
 
 	int ret;
 	int ret;
 	unsigned short branch;
 	unsigned short branch;
-	char *shbuf;
+#ifdef TM_UAC_FLAGS
 	unsigned int len;
 	unsigned int len;
+#endif /* TM_UAC_FLAGS */
 
 
 	branch=t->nr_of_outgoings;
 	branch=t->nr_of_outgoings;
 	if (branch==MAX_BRANCHES) {
 	if (branch==MAX_BRANCHES) {
@@ -552,34 +654,11 @@ static int add_uac( struct cell *t, struct sip_msg *request, str *uri,
 	}
 	}
 
 
 	/* now message printing starts ... */
 	/* now message printing starts ... */
-	shbuf=prepare_uac_request(t, request, branch, uri, path, next_hop,
-								proto, flags, &len);
-	if (!shbuf) {
-		ret=ser_error<0?ser_error:E_BUG;
+	if (unlikely( (ret=prepare_new_uac(t, request, branch, uri, path,
+											next_hop, proto, flags)) < 0)){
+		ser_error=ret;
 		goto error01;
 		goto error01;
 	}
 	}
-
-	/* things went well, move ahead and install new buffer! */
-	t->uac[branch].request.buffer=shbuf;
-	t->uac[branch].request.buffer_len=len;
-	t->uac[branch].uri.s=t->uac[branch].request.buffer+
-		request->first_line.u.request.method.len+1;
-	t->uac[branch].uri.len=uri->len;
-	if (unlikely(path && path->s)){
-		t->uac[branch].path.s=shm_malloc(path->len+1);
-		if (unlikely(t->uac[branch].path.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 error01;
-		}
-		t->uac[branch].path.len=path->len;
-		t->uac[branch].path.s[path->len]=0;
-		memcpy( t->uac[branch].path.s, path->s, path->len);
-	}
 #ifdef TM_UAC_FLAGS
 #ifdef TM_UAC_FLAGS
 	len = count_applied_lumps(request->add_rm, HDR_RECORDROUTE_T);
 	len = count_applied_lumps(request->add_rm, HDR_RECORDROUTE_T);
 	if(len==1)
 	if(len==1)
@@ -812,39 +891,37 @@ int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel,
 		}
 		}
 		shbuf=build_local_reparse( t_invite, branch, &len, CANCEL,
 		shbuf=build_local_reparse( t_invite, branch, &len, CANCEL,
 									CANCEL_LEN, &t_invite->to);
 									CANCEL_LEN, &t_invite->to);
-
+		if (unlikely(!shbuf)) {
+			LOG(L_ERR, "e2e_cancel_branch: printing e2e cancel failed\n");
+			ret=ser_error=E_OUT_OF_MEM;
+			goto error;
+		}
+		/* install buffer */
+		t_cancel->uac[branch].request.buffer=shbuf;
+		t_cancel->uac[branch].request.buffer_len=len;
+		t_cancel->uac[branch].uri.s=t_cancel->uac[branch].request.buffer+
+			cancel_msg->first_line.u.request.method.len+1;
+		t_cancel->uac[branch].uri.len=t_invite->uac[branch].uri.len;
 	} else {
 	} else {
-		/* buffer is constructed from the received CANCEL with applying lumps */
+		/* buffer is constructed from the received CANCEL with lumps applied */
 		/*  t_cancel...request.dst is already filled (see above) */
 		/*  t_cancel...request.dst is already filled (see above) */
-		shbuf=prepare_uac_request( 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, PROTO_NONE, 0,
-									&len);
-	}
-
-	if (!shbuf) {
-		LOG(L_ERR, "ERROR: e2e_cancel_branch: printing e2e cancel failed\n");
-		ret=ser_error=E_OUT_OF_MEM;
-		goto error;
+									0, PROTO_NONE, 0)) <0)){
+			ser_error=ret;
+			goto error;
+		}
 	}
 	}
-	
-	/* install buffer */
-	t_cancel->uac[branch].request.buffer=shbuf;
-	t_cancel->uac[branch].request.buffer_len=len;
-	t_cancel->uac[branch].uri.s=t_cancel->uac[branch].request.buffer+
-		cancel_msg->first_line.u.request.method.len+1;
-	t_cancel->uac[branch].uri.len=t_invite->uac[branch].uri.len;
-	
-
 	/* success */
 	/* success */
 	ret=1;
 	ret=1;
 
 
-
 error:
 error:
 	return ret;
 	return ret;
 }
 }
 
 
+
+
 void e2e_cancel( struct sip_msg *cancel_msg, 
 void e2e_cancel( struct sip_msg *cancel_msg, 
 	struct cell *t_cancel, struct cell *t_invite )
 	struct cell *t_cancel, struct cell *t_invite )
 {
 {