From 35e6db8a73296c93d43f6dd2dc83aa7a204c9f73 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Mon, 6 Feb 2017 14:40:57 +0100 Subject: [PATCH] tm: deep cloning of the request for fake environment (cherry picked from commit edb9df8ace8ff74e11e025a37645aebe5b25634e) --- src/modules/tm/t_append_branches.c | 23 ++++--- src/modules/tm/t_reply.c | 104 ++++++++++++++++------------- src/modules/tm/t_reply.h | 6 +- src/modules/tm/t_suspend.c | 24 ++++--- 4 files changed, 88 insertions(+), 69 deletions(-) diff --git a/src/modules/tm/t_append_branches.c b/src/modules/tm/t_append_branches.c index 6f0d5e7bc9e..9477f8f6b0d 100644 --- a/src/modules/tm/t_append_branches.c +++ b/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, ¤t_uri, + new_branch=add_uac( t, faked_req, ¤t_uri, (dst_uri.len) ? (&dst_uri) : ¤t_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; inr_of_outgoings; i++) { if (added_branches & (1<=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<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 @@ int t_append_branches(void) { 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; diff --git a/src/modules/tm/t_reply.c b/src/modules/tm/t_reply.c index 61f590814da..6163240cc3e 100644 --- a/src/modules/tm/t_reply.c +++ b/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 @@ int fake_req(struct sip_msg *faked_req, 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->parsedparsed>=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; } diff --git a/src/modules/tm/t_reply.h b/src/modules/tm/t_reply.h index 57501a1c7a3..38c8111cce4 100644 --- a/src/modules/tm/t_reply.h +++ b/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); diff --git a/src/modules/tm/t_suspend.c b/src/modules/tm/t_suspend.c index 57034933bf9..f612efcbe30 100644 --- a/src/modules/tm/t_suspend.c +++ b/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.