Skip to content

Commit

Permalink
tm: deep cloning of the request for fake environment
Browse files Browse the repository at this point in the history
  • Loading branch information
linuxmaniac committed Feb 14, 2017
1 parent e534709 commit edb9df8
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 69 deletions.
23 changes: 12 additions & 11 deletions src/modules/tm/t_append_branches.c
Expand Up @@ -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;

Expand Down Expand Up @@ -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();
Expand All @@ -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);

Expand All @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -218,7 +219,7 @@ int t_append_branches(void) {
/* 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 */
Expand All @@ -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;
Expand Down
104 changes: 59 additions & 45 deletions src/modules/tm/t_reply.c
Expand Up @@ -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"
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -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;
}

Expand All @@ -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;
Expand All @@ -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;
}

Expand Down
6 changes: 3 additions & 3 deletions src/modules/tm/t_reply.h
Expand Up @@ -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);
Expand Down
24 changes: 14 additions & 10 deletions src/modules/tm/t_suspend.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit edb9df8

Please sign in to comment.