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