Quellcode durchsuchen

tm: deep cloning of the request for fake environment

Victor Seva vor 8 Jahren
Ursprung
Commit
edb9df8ace
4 geänderte Dateien mit 88 neuen und 69 gelöschten Zeilen
  1. 12 11
      src/modules/tm/t_append_branches.c
  2. 59 45
      src/modules/tm/t_reply.c
  3. 3 3
      src/modules/tm/t_reply.h
  4. 14 10
      src/modules/tm/t_suspend.c

+ 12 - 11
src/modules/tm/t_append_branches.c

@@ -49,7 +49,8 @@
 int t_append_branches(void) {
 	struct cell *t = NULL;
 	struct sip_msg *orig_msg = NULL;
-	static struct sip_msg faked_req;
+	struct sip_msg *faked_req;
+	int faked_req_len = 0;
 
 	short outgoings;
 
@@ -108,14 +109,14 @@ int t_append_branches(void) {
 		/* tell add_uac that it should run branch route actions */
 		set_branch_route(t->on_branch_delayed);
 	}
-
-	if (!fake_req(&faked_req, orig_msg, 0, NULL)) {
+	faked_req = fake_req(orig_msg, 0, NULL,	&faked_req_len);
+	if (faked_req==NULL) {
 		LM_ERR("fake_req failed\n");
 		return -1;
 	}
 
 	/* fake also the env. conforming to the fake msg */
-	faked_env( t, &faked_req, 0);
+	faked_env( t, faked_req, 0);
 
 	/* DONE with faking ;-) -> run the failure handlers */
 	init_branch_iterator();
@@ -139,9 +140,9 @@ int t_append_branches(void) {
 			continue;
 
 		setbflagsval(0, bflags);
-		new_branch=add_uac( t, &faked_req, &current_uri,
+		new_branch=add_uac( t, faked_req, &current_uri,
 					(dst_uri.len) ? (&dst_uri) : &current_uri,
-					&path, 0, si, faked_req.fwd_send_flags,
+					&path, 0, si, faked_req->fwd_send_flags,
 					PROTO_NONE, (dst_uri.len)?0:UAC_SKIP_BR_DST_F, &instance,
 					&ruid, &location_ua);
 
@@ -164,7 +165,7 @@ int t_append_branches(void) {
 	setbflagsval(0, backup_bflags);
 
 	/* update message flags, if changed in branch route */
-	t->uas.request->flags = faked_req.flags;
+	t->uas.request->flags = faked_req->flags;
 
 	if (added_branches==0) {
 		if(lowest_ret!=E_CFG)
@@ -181,14 +182,14 @@ int t_append_branches(void) {
 
 	for (i=outgoings; i<t->nr_of_outgoings; i++) {
 		if (added_branches & (1<<i)) {
-			branch_ret=t_send_branch(t, i, &faked_req , 0, 0 /* replies are already locked */ );
+			branch_ret=t_send_branch(t, i, faked_req , 0, 0 /* replies are already locked */ );
 			if (branch_ret>=0){ /* some kind of success */
 				if (branch_ret==i) { /* success */
 					success_branch++;
 					if (unlikely(has_tran_tmcbs(t, TMCB_REQUEST_OUT)))
 						run_trans_callbacks_with_buf( TMCB_REQUEST_OUT,
 								&t->uac[nr_branches].request,
-								&faked_req, 0, -orig_msg->REQ_METHOD);
+								faked_req, 0, -orig_msg->REQ_METHOD);
 				}
 				else /* new branch added */
 					added_branches |= 1<<branch_ret;
@@ -218,7 +219,7 @@ canceled:
 	/* restore backup flags from initial env */
 	setbflagsval(0, backup_bflags);
 	/* update message flags, if changed in branch route */
-	t->uas.request->flags = faked_req.flags;
+	t->uas.request->flags = faked_req->flags;
 	/* if needed unlock transaction's replies */
 		/* restore the number of outgoing branches
 		 * since new branches have not been completed */
@@ -228,7 +229,7 @@ canceled:
 done:
 	/* restore original environment and free the fake msg */
 	faked_env( t, 0, 0);
-	free_faked_req(&faked_req,t);
+	free_faked_req(faked_req, faked_req_len);
 
 	if (likely(replies_locked)) {
 		replies_locked = 0;

+ 59 - 45
src/modules/tm/t_reply.c

@@ -70,6 +70,7 @@
 #include "t_lookup.h"
 #include "t_fwd.h"
 #include "../../core/fix_lumps.h"
+#include "../../core/sip_msg_clone.h"
 #include "../../core/sr_compat.h"
 #include "../../core/receive.h"
 #include "../../core/onsend.h"
@@ -798,17 +799,20 @@ int fake_req_clone_str_helper(str *src, str *dst, char *txt)
 }
 
 /**
- * fake a semi-private sip message using transaction's shared memory message
+ * fake a private sip message using transaction's shared memory message
  */
-int fake_req(struct sip_msg *faked_req,
-		struct sip_msg *shmem_msg, int extra_flags, struct ua_client *uac)
+struct sip_msg * fake_req(struct sip_msg *shmem_msg, int extra_flags,
+	struct ua_client *uac, int *len)
 {
-	/* on_failure_reply faked msg now copied from shmem msg (as opposed
-	 * to zero-ing) -- more "read-only" actions (exec in particular) will
-	 * work from reply_route as they will see msg->from, etc.; caution,
-	 * rw actions may append some pkg stuff to msg, which will possibly be
-	 * never released (shmem is released in a single block) */
-	memcpy( faked_req, shmem_msg, sizeof(struct sip_msg));
+	struct sip_msg *faked_req;
+	/* make a clone so eventual new parsed headers in pkg are not visible
+     * to other processes -- other attributes should be already parsed,
+     * available in the req structure and propagated by cloning */
+	faked_req = sip_msg_shm_clone(shmem_msg, len, 1);
+	if(faked_req==NULL) {
+		LM_ERR("failed to clone the request\n");
+		return NULL;
+	}
 
 	/* if we set msg_id to something different from current's message
 	 * id, the first t_fork will properly clean new branch URIs */
@@ -838,7 +842,7 @@ int fake_req(struct sip_msg *faked_req,
 	if(uac) setbflagsval(0, uac->branch_flags);
 	else setbflagsval(0, 0);
 
-	return 1;
+	return faked_req;
 
 error02:
 	if (faked_req->dst_uri.s) {
@@ -853,12 +857,15 @@ error01:
 		faked_req->path_vec.len = 0;
 	}
 error00:
-	return 0;
+	shm_free(faked_req);
+	return NULL;
 }
 
-void free_faked_req(struct sip_msg *faked_req, struct cell *t)
+void free_faked_req(struct sip_msg *faked_req, int len)
 {
 	struct hdr_field *hdr;
+	void *mstart = faked_req;
+	void *mend =((char *) faked_req) + len;
 
 	reset_new_uri(faked_req);
 	reset_dst_uri(faked_req);
@@ -871,12 +878,10 @@ void free_faked_req(struct sip_msg *faked_req, struct cell *t)
 	/* free header's parsed structures that were added by failure handlers */
 	for( hdr=faked_req->headers ; hdr ; hdr=hdr->next ) {
 		if ( hdr->parsed && hdr_allocs_parse(hdr) &&
-		(hdr->parsed<(void*)t->uas.request ||
-		hdr->parsed>=(void*)t->uas.end_request)) {
-			/* header parsed filed doesn't point inside uas.request memory
+		(hdr->parsed<mstart || hdr->parsed>=mend)) {
+			/* header parsed filed doesn't point inside fake memory
 			 * chunck -> it was added by failure funcs.-> free it as pkg */
-			LM_DBG("removing hdr->parsed %d\n",
-					hdr->type);
+			LM_DBG("removing hdr->parsed %d\n",	hdr->type);
 			clean_hdr_field(hdr);
 			hdr->parsed = 0;
 		}
@@ -894,14 +899,17 @@ void free_faked_req(struct sip_msg *faked_req, struct cell *t)
 	reset_ruid(faked_req);
 	reset_ua(faked_req);
 	msg_ldata_reset(faked_req);
-}
 
+	/* free shared block */
+	shm_free(faked_req);
+}
 
 /* return 1 if a failure_route processes */
 int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
 					int code, int extra_flags)
 {
-	static struct sip_msg faked_req;
+	struct sip_msg *faked_req;
+	int faked_req_len = 0;
 	struct sip_msg *shmem_msg = t->uas.request;
 	int on_failure;
 	sr_kemi_eng_t *keng = NULL;
@@ -920,17 +928,18 @@ int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
 				t->tmcb_hl.reg_types);
 		return 1;
 	}
-
-	if (!fake_req(&faked_req, shmem_msg, extra_flags, &t->uac[picked_branch])) {
+	faked_req = fake_req(shmem_msg, extra_flags, &t->uac[picked_branch],
+		&faked_req_len);
+	if (faked_req==NULL) {
 		LM_ERR("fake_req failed\n");
 		return 0;
 	}
 	/* fake also the env. conforming to the fake msg */
-	faked_env( t, &faked_req, 0);
+	faked_env( t, faked_req, 0);
 	/* DONE with faking ;-) -> run the failure handlers */
 
 	if (unlikely(has_tran_tmcbs( t, TMCB_ON_FAILURE)) ) {
-		run_trans_callbacks( TMCB_ON_FAILURE, t, &faked_req, rpl, code);
+		run_trans_callbacks( TMCB_ON_FAILURE, t, faked_req, rpl, code);
 	}
 	if (on_failure) {
 		/* avoid recursion -- if failure_route forwards, and does not
@@ -939,30 +948,31 @@ int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
 		t->on_failure=0;
 		/* if continuing on timeout of a suspended transaction, reset the flag */
 		t->flags &= ~T_ASYNC_SUSPENDED;
-		if (exec_pre_script_cb(&faked_req, FAILURE_CB_TYPE)>0) {
+		if (exec_pre_script_cb(faked_req, FAILURE_CB_TYPE)>0) {
 			/* run a failure_route action if some was marked */
 			keng = sr_kemi_eng_get();
 			if(unlikely(keng!=NULL)) {
-				if(keng->froute(&faked_req, FAILURE_ROUTE,
+				if(keng->froute(faked_req, FAILURE_ROUTE,
 						sr_kemi_cbname_lookup_idx(on_failure), NULL)<0) {
 					LM_ERR("error running failure route kemi callback\n");
 				}
 			} else {
-				if (run_top_route(failure_rt.rlist[on_failure], &faked_req, 0)<0)
+				if (run_top_route(failure_rt.rlist[on_failure], faked_req, 0)<0)
 					LM_ERR("error running run_top_route for failure handler\n");
 			}
-			exec_post_script_cb(&faked_req, FAILURE_CB_TYPE);
+			exec_post_script_cb(faked_req, FAILURE_CB_TYPE);
 		}
 		/* update message flags, if changed in failure route */
-		t->uas.request->flags = faked_req.flags;
+		t->uas.request->flags = faked_req->flags;
 	}
 
-	/* restore original environment and free the fake msg */
+	/* restore original environment */
 	faked_env( t, 0, 0);
-	free_faked_req(&faked_req,t);
-
 	/* if failure handler changed flag, update transaction context */
-	shmem_msg->flags = faked_req.flags;
+	shmem_msg->flags = faked_req->flags;
+	/* free the fake msg */
+	free_faked_req(faked_req, faked_req_len);
+
 	return 1;
 }
 
@@ -971,7 +981,8 @@ int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
 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 *faked_req;
+	int faked_req_len = 0;
 	struct sip_msg *shmem_msg = t->uas.request;
 	int on_branch_failure;
 	sr_kemi_eng_t *keng = NULL;
@@ -993,46 +1004,49 @@ int run_branch_failure_handlers(struct cell *t, struct sip_msg *rpl,
 		return 1;
 	}
 
-	if (!fake_req(&faked_req, shmem_msg, extra_flags, &t->uac[picked_branch])) {
+	faked_req = fake_req(shmem_msg, extra_flags, &t->uac[picked_branch],
+		&faked_req_len);
+	if (faked_req==NULL) {
 		LM_ERR("fake_req failed\n");
 		return 0;
 	}
 	/* fake also the env. conforming to the fake msg */
-	faked_env( t, &faked_req, 0);
+	faked_env( t, faked_req, 0);
 	set_route_type(BRANCH_FAILURE_ROUTE);
 	set_t(t, picked_branch);
 	/* 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);
+		run_trans_callbacks( TMCB_ON_BRANCH_FAILURE, t, faked_req, rpl, code);
 	}
 	if (on_branch_failure >= 0) {
 		t->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 */
 			keng = sr_kemi_eng_get();
 			if(unlikely(keng!=NULL)) {
-				if(keng->froute(&faked_req, BRANCH_FAILURE_ROUTE,
+				if(keng->froute(faked_req, BRANCH_FAILURE_ROUTE,
 						sr_kemi_cbname_lookup_idx(on_branch_failure), NULL)<0) {
 					LM_ERR("error running branch failure route kemi callback\n");
 				}
 			} else {
 				if (run_top_route(event_rt.rlist[on_branch_failure],
-							&faked_req, 0)<0)
+							faked_req, 0)<0)
 					LM_ERR("error in run_top_route\n");
 			}
-			exec_post_script_cb(&faked_req, BRANCH_FAILURE_CB_TYPE);
+			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;
+		t->uas.request->flags = faked_req->flags;
 	}
 
-	/* restore original environment and free the fake msg */
+	/* restore original environment */
 	faked_env( t, 0, 0);
-	free_faked_req(&faked_req,t);
-
 	/* if branch_failure handler changed flag, update transaction context */
-	shmem_msg->flags = faked_req.flags;
+	shmem_msg->flags = faked_req->flags;
+	/* free the fake msg */
+	free_faked_req(faked_req, faked_req_len);
+
 	return 1;
 }
 

+ 3 - 3
src/modules/tm/t_reply.h

@@ -228,10 +228,10 @@ void rpc_reply(rpc_t* rpc, void* c);
 void rpc_reply_callid(rpc_t* rpc, void* c);
 
 void faked_env( struct cell *t,struct sip_msg *msg, int is_async_env);
-int fake_req(struct sip_msg *faked_req,
-		struct sip_msg *shmem_msg, int extra_flags, struct ua_client *uac);
+struct sip_msg * fake_req(struct sip_msg *shmem_msg,
+	int extra_flags, struct ua_client *uac, int *len);
 
-void free_faked_req(struct sip_msg *faked_req, struct cell *t);
+void free_faked_req(struct sip_msg *faked_req, int len);
 
 typedef int (*tget_picked_f)(void);
 int t_get_picked_branch(void);

+ 14 - 10
src/modules/tm/t_suspend.c

@@ -167,7 +167,8 @@ int t_continue(unsigned int hash_index, unsigned int label,
 		struct action *route)
 {
 	struct cell	*t;
-	struct sip_msg	faked_req;
+	struct sip_msg *faked_req;
+	int faked_req_len = 0;
 	struct cancel_info cancel_data;
 	int	branch;
 	struct ua_client *uac =NULL;
@@ -268,31 +269,34 @@ int t_continue(unsigned int hash_index, unsigned int label,
 		 */
 
 		/* fake the request and the environment, like in failure_route */
-		if (!fake_req(&faked_req, t->uas.request, 0 /* extra flags */, uac)) {
+		faked_req = fake_req(t->uas.request, 0 /* extra flags */, uac,
+			&faked_req_len);
+		if (faked_req==NULL) {
 			LM_ERR("building fake_req failed\n");
 			ret = -1;
 			goto kill_trans;
 		}
-		faked_env( t, &faked_req, 1);
+		faked_env( t, faked_req, 1);
 
 		route_type_bk = get_route_type();
 		set_route_type(FAILURE_ROUTE);
 		/* execute the pre/post -script callbacks based on original route block */
-		if (exec_pre_script_cb(&faked_req, cb_type)>0) {
-			if (run_top_route(route, &faked_req, 0)<0)
+		if (exec_pre_script_cb(faked_req, cb_type)>0) {
+			if (run_top_route(route, faked_req, 0)<0)
 				LM_ERR("failure inside run_top_route\n");
-			exec_post_script_cb(&faked_req, cb_type);
+			exec_post_script_cb(faked_req, cb_type);
 		}
 		set_route_type(route_type_bk);
 
 		/* TODO: save_msg_lumps should clone the lumps to shm mem */
 
-		/* restore original environment and free the fake msg */
+		/* restore original environment */
 		faked_env( t, 0, 1);
-		free_faked_req(&faked_req, t);
-
 		/* update the flags */
-		t->uas.request->flags = faked_req.flags;
+		t->uas.request->flags = faked_req->flags;
+		/* free the fake msg */
+		free_faked_req(faked_req, faked_req_len);
+
 
 		if (t->uas.status < 200) {
 			/* No final reply has been sent yet.