Module: sip-router Branch: master Commit: 7f56004e206cf0f9ae7b3d500dd48407998802cd URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=7f56004e...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com Date: Tue May 11 15:03:19 2010 +0200
tmx: two new functions for transaction control
- t_cancel_callid(callid, cseq, flag) - cancel the INVITE transaction sharing the callid and cseq. It set the flag for invite transaction if the value is greater than 0 - t_reply_callid(callid, cseq, code, reason) - send a reply to an INVITE transaction sharing callid and csec - the functions are useful for remote control of invite transaction (via xmlrpc or out-of-dialog sip request) - an useful application - call pickup: - INVITE comes in, callee is in a pickup group - store callid, cseq, etc in database or notify the other phones in the group (easy to do for snom phones and extra programmable buttons) via uac_req_send() - send a remote control command telling which call to pickup (callid, cseq) and where to redirect. In config, call t_cancel_callid(). in failure route for INVITE catch the cancelled transaction (flag is set), get the new destination (e.g., stored in htable) and forward the invite there
---
modules_k/tmx/tmx_mod.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 139 insertions(+), 0 deletions(-)
diff --git a/modules_k/tmx/tmx_mod.c b/modules_k/tmx/tmx_mod.c index 0c3af19..420cb30 100644 --- a/modules_k/tmx/tmx_mod.c +++ b/modules_k/tmx/tmx_mod.c @@ -46,6 +46,11 @@ static void destroy(void);
static int t_cancel_branches(struct sip_msg* msg, char *k, char *s2); static int fixup_cancel_branches(void** param, int param_no); +static int t_cancel_callid(struct sip_msg* msg, char *cid, char *cseq, char *flag); +static int fixup_cancel_callid(void** param, int param_no); +static int t_reply_callid(struct sip_msg* msg, char *cid, char *cseq, + char *rc, char *rs); +static int fixup_reply_callid(void** param, int param_no);
/* statistic variables */ stat_var *tm_rcv_rpls; @@ -125,6 +130,10 @@ static mi_export_t mi_cmds [] = { static cmd_export_t cmds[]={ {"t_cancel_branches", (cmd_function)t_cancel_branches, 1, fixup_cancel_branches, 0, ONREPLY_ROUTE }, + {"t_cancel_callid", (cmd_function)t_cancel_callid, 3, + fixup_cancel_callid, 0, ANY_ROUTE }, + {"t_reply_callid", (cmd_function)t_reply_callid, 4, + fixup_reply_callid, 0, ANY_ROUTE }, {0,0,0,0,0,0} };
@@ -189,6 +198,9 @@ static void destroy(void) return; }
+/** + * + */ static int fixup_cancel_branches(void** param, int param_no) { char *val; @@ -215,6 +227,9 @@ static int fixup_cancel_branches(void** param, int param_no) return 0; }
+/** + * + */ static int t_cancel_branches(struct sip_msg* msg, char *k, char *s2) { branch_bm_t cb = 0; @@ -252,6 +267,130 @@ static int t_cancel_branches(struct sip_msg* msg, char *k, char *s2) return 1; }
+/** + * + */ +static int fixup_cancel_callid(void** param, int param_no) +{ + if (param_no==1 || param_no==2) { + return fixup_spve_null(param, 1); + } + if (param_no==3) { + return fixup_igp_null(param, 1); + } + return 0; +} + +/** + * + */ +static int t_cancel_callid(struct sip_msg* msg, char *cid, char *cseq, char *flag) +{ + struct cell *trans; + branch_bm_t cancel_bm; + str cseq_s; + str callid_s; + int fl; + + cancel_bm=0; + fl = -1; + + if(fixup_get_svalue(msg, (gparam_p)cid, &callid_s)<0) + { + LM_ERR("cannot get callid\n"); + return -1; + } + + if(fixup_get_svalue(msg, (gparam_p)cseq, &cseq_s)<0) + { + LM_ERR("cannot get cseq\n"); + return -1; + } + + if(fixup_get_ivalue(msg, (gparam_p)flag, &fl)<0) + { + LM_ERR("cannot get flag\n"); + return -1; + } + + if( _tmx_tmb.t_lookup_callid(&trans, callid_s, cseq_s) < 0 ) { + DBG("Lookup failed - no transaction\n"); + return -1; + } + + DBG("Now calling cancel_uacs\n"); + if(trans->uas.request && fl>0 && fl<32) + setflag(trans->uas.request, fl); + _tmx_tmb.prepare_to_cancel(trans, &cancel_bm, 0); + _tmx_tmb.cancel_uacs(trans, cancel_bm, 0); + + //_tmx_tmb.unref_cell(trans); + + return 1; +} + +/** + * + */ +static int fixup_reply_callid(void** param, int param_no) +{ + if (param_no==1 || param_no==2 || param_no==4) { + return fixup_spve_null(param, 1); + } + if (param_no==3) { + return fixup_igp_null(param, 1); + } + return 0; +} + +/** + * + */ +static int t_reply_callid(struct sip_msg* msg, char *cid, char *cseq, + char *rc, char *rs) +{ + struct cell *trans; + str cseq_s; + str callid_s; + str status_s; + unsigned int code; + + if(fixup_get_svalue(msg, (gparam_p)cid, &callid_s)<0) + { + LM_ERR("cannot get callid\n"); + return -1; + } + + if(fixup_get_svalue(msg, (gparam_p)cseq, &cseq_s)<0) + { + LM_ERR("cannot get cseq\n"); + return -1; + } + + if(fixup_get_ivalue(msg, (gparam_p)rc, (int*)&code)<0) + { + LM_ERR("cannot get reply code\n"); + return -1; + } + + if(fixup_get_svalue(msg, (gparam_p)rs, &status_s)<0) + { + LM_ERR("cannot get reply status\n"); + return -1; + } + + if(_tmx_tmb.t_lookup_callid(&trans, callid_s, cseq_s) < 0 ) + { + DBG("Lookup failed - no transaction\n"); + return -1; + } + + DBG("Now calling internal replay\n"); + if(_tmx_tmb.t_reply_trans(trans, trans->uas.request, code, status_s.s)>0) + return 1; + + return -1; +}
#ifdef STATISTICS