mirror of https://github.com/sipwise/kamailio.git
Change-Id: Iedf68425ea66e676b434cb368a909c4d15f38b26changes/39/11139/3
parent
37a79ead36
commit
86e3621307
@ -0,0 +1,397 @@
|
||||
From 2e2f75c04e22c9f9dfdf55338212dfeb2e0bbf47 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Seva <linuxmaniac@torreviejawireless.org>
|
||||
Date: Mon, 6 Feb 2017 19:41:15 +0100
|
||||
Subject: [PATCH] tm: deep cloning of the request for fake environment
|
||||
|
||||
---
|
||||
modules/tm/t_append_branches.c | 24 ++++++-----
|
||||
modules/tm/t_reply.c | 96 ++++++++++++++++++++++++------------------
|
||||
modules/tm/t_reply.h | 6 +--
|
||||
modules/tm/t_suspend.c | 24 ++++++-----
|
||||
4 files changed, 86 insertions(+), 64 deletions(-)
|
||||
|
||||
diff --git a/modules/tm/t_append_branches.c b/modules/tm/t_append_branches.c
|
||||
index f745e755d..96cd40f78 100644
|
||||
--- a/modules/tm/t_append_branches.c
|
||||
+++ b/modules/tm/t_append_branches.c
|
||||
@@ -49,8 +49,9 @@
|
||||
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;
|
||||
|
||||
int success_branch;
|
||||
@@ -109,13 +110,14 @@ int t_append_branches(void) {
|
||||
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) {
|
||||
LOG(L_ERR, "ERROR: t_append_branches: 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 +141,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);
|
||||
|
||||
@@ -163,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)
|
||||
@@ -180,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;
|
||||
@@ -217,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 */
|
||||
@@ -227,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;
|
||||
diff --git a/modules/tm/t_reply.c b/modules/tm/t_reply.c
|
||||
index cf56de701..c407ec9a7 100644
|
||||
--- a/modules/tm/t_reply.c
|
||||
+++ b/modules/tm/t_reply.c
|
||||
@@ -70,6 +70,7 @@
|
||||
#include "t_lookup.h"
|
||||
#include "t_fwd.h"
|
||||
#include "../../fix_lumps.h"
|
||||
+#include "../../sip_msg_clone.h"
|
||||
#include "../../sr_compat.h"
|
||||
#include "../../receive.h"
|
||||
#include "../../onsend.h"
|
||||
@@ -843,17 +844,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 */
|
||||
@@ -883,7 +887,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) {
|
||||
@@ -898,12 +902,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);
|
||||
@@ -916,9 +923,8 @@ 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 */
|
||||
DBG("DBG:free_faked_req: removing hdr->parsed %d\n",
|
||||
hdr->type);
|
||||
@@ -939,14 +945,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;
|
||||
|
||||
@@ -967,16 +976,18 @@ int run_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) {
|
||||
LOG(L_ERR, "ERROR: run_failure_handlers: 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
|
||||
@@ -985,22 +996,23 @@ 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 */
|
||||
- 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)
|
||||
LOG(L_ERR, "ERROR: run_failure_handlers: Error in run_top_route\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;
|
||||
}
|
||||
|
||||
@@ -1009,7 +1021,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;
|
||||
|
||||
@@ -1030,37 +1043,40 @@ 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) {
|
||||
LOG(L_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 */
|
||||
- if (run_top_route(event_rt.rlist[on_branch_failure], &faked_req, 0)<0)
|
||||
+ if (run_top_route(event_rt.rlist[on_branch_failure], faked_req, 0)<0)
|
||||
LOG(L_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/modules/tm/t_reply.h b/modules/tm/t_reply.h
|
||||
index 91b2ac839..af99187e7 100644
|
||||
--- a/modules/tm/t_reply.h
|
||||
+++ b/modules/tm/t_reply.h
|
||||
@@ -227,10 +227,10 @@ void t_drop_replies(int v);
|
||||
void rpc_reply(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/modules/tm/t_suspend.c b/modules/tm/t_suspend.c
|
||||
index 6bb25473b..27f54569a 100644
|
||||
--- a/modules/tm/t_suspend.c
|
||||
+++ b/modules/tm/t_suspend.c
|
||||
@@ -166,7 +166,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;
|
||||
@@ -267,31 +268,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.
|
||||
--
|
||||
2.11.0
|
||||
|
Loading…
Reference in new issue