tm/tm.c

Go to the documentation of this file.
00001 /*
00002  * $Id: tm.c 5723 2009-03-19 09:27:41Z miconda $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * --------
00024  *  2003-02-18  added t_forward_nonack_{udp, tcp}, t_relay_to_{udp,tcp},
00025  *               t_replicate_{udp, tcp} (andrei)
00026  *  2003-02-19  added t_rely_{udp, tcp} (andrei)
00027  *  2003-03-06  voicemail changes accepted (jiri)
00028  *  2003-03-10  module export interface updated to the new format (andrei)
00029  *  2003-03-16  flags export parameter added (janakj)
00030  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
00031  *  2003-03-30  set_kr for requests only (jiri)
00032  *  2003-04-05  s/reply_route/failure_route, onreply_route introduced (jiri)
00033  *  2003-04-14  use protocol from uri (jiri)
00034  *  2003-07-07  added t_relay_to_tls, t_replicate_tls, t_forward_nonack_tls
00035  *              added #ifdef USE_TCP, USE_TLS
00036  *              removed t_relay_{udp,tcp,tls} (andrei)
00037  *  2003-09-26  added t_forward_nonack_uri() - same as t_forward_nonack() but
00038  *              takes no parameters -> forwards to uri (bogdan)
00039  *  2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
00040  *  2004-02-18  t_reply exported via FIFO - imported from VM (bogdan)
00041  *  2004-10-01  added a new param.: restart_fr_on_each_reply (andrei)
00042  *  2005-05-30  light version of tm_load - find_export dropped -> module 
00043  *              interface dosen't need to export internal functions (bogdan)
00044  *  2006-01-15  merged functions which diff only via proto (like t_relay,
00045  *              t_replicate and t_forward_nonack) (bogdan)
00046  *  2007-01-25  t_forward_nonack removed as it merged into t_relay,
00047  *              t_replicate also accepts flags for controlling DNS failover
00048  *              (bogdan)
00049  *  2008-04-04  added support for local and remote dispaly name in TM dialogs
00050  *              (by Andrei Pisau <andrei.pisau at voice-system dot ro> )
00051  *  2009-03-14  new modparam "auto_inv_100_reason" added (aheise)
00052  */
00053 
00054 /*! \file
00055  * \brief TM :: module core
00056  *
00057  * \ingroup tm
00058  * - Module: \ref tm
00059  */
00060 
00061 /*! \defgroup tm TM :: Stateful transaction handling
00062  *
00063  * The TM module enables stateful processing of SIP transactions. The
00064  * main use of stateful logic, which is costly in terms of memory
00065  * and CPU, is some services inherently need state.
00066  */
00067 
00068 
00069 
00070 #include <stdio.h>
00071 #include <string.h>
00072 #include <netdb.h>
00073 
00074 #include "../../sr_module.h"
00075 #include "../../dprint.h"
00076 #include "../../error.h"
00077 #include "../../ut.h"
00078 #include "../../script_cb.h"
00079 #include "../../mi/mi.h"
00080 #include "../../usr_avp.h"
00081 #include "../../mem/mem.h"
00082 #include "../../pvar.h"
00083 #include "../../mod_fix.h"
00084 
00085 #include "sip_msg.h"
00086 #include "h_table.h"
00087 #include "ut.h"
00088 #include "t_reply.h"
00089 #include "t_fwd.h"
00090 #include "t_lookup.h"
00091 #include "callid.h"
00092 #include "t_cancel.h"
00093 #include "t_fifo.h"
00094 #include "mi.h"
00095 #include "tm_load.h"
00096 #include "t_serial.h"
00097 #include "t_var.h"
00098 
00099 MODULE_VERSION
00100 
00101 /* item functions */
00102 static int pv_get_tm_branch_idx(struct sip_msg *msg, pv_param_t *param,
00103       pv_value_t *res);
00104 static int pv_get_tm_reply_code(struct sip_msg *msg, pv_param_t *param,
00105       pv_value_t *res);
00106 
00107 /* fixup functions */
00108 static int fixup_t_send_reply(void** param, int param_no);
00109 static int fixup_local_replied(void** param, int param_no);
00110 static int fixup_t_relay1(void** param, int param_no);
00111 static int fixup_t_relay2(void** param, int param_no);
00112 static int fixup_t_replicate(void** param, int param_no);
00113 static int fixup_cancel_branches(void** param, int param_no);
00114 
00115 
00116 /* init functions */
00117 static int mod_init(void);
00118 static int child_init(int rank);
00119 
00120 
00121 /* exported functions */
00122 inline static int w_t_release(struct sip_msg* msg, char* , char* );
00123 inline static int w_t_newtran(struct sip_msg* p_msg, char* , char* );
00124 inline static int w_t_reply(struct sip_msg *msg, char* code, char* text);
00125 inline static int w_pv_t_reply(struct sip_msg *msg, char* code, char* text);
00126 inline static int w_t_relay(struct sip_msg *p_msg , char *proxy, char* flags);
00127 inline static int w_t_replicate(struct sip_msg *p_msg, char *dst,char* );
00128 inline static int w_t_on_negative(struct sip_msg* msg, char *go_to, char* );
00129 inline static int w_t_on_reply(struct sip_msg* msg, char *go_to, char* );
00130 inline static int w_t_on_branch(struct sip_msg* msg, char *go_to, char* );
00131 inline static int t_check_status(struct sip_msg* msg, char *regexp, char* );
00132 inline static int t_flush_flags(struct sip_msg* msg, char*, char* );
00133 inline static int t_local_replied(struct sip_msg* msg, char *type, char* );
00134 inline static int t_check_trans(struct sip_msg* msg, char* , char* );
00135 inline static int t_was_cancelled(struct sip_msg* msg, char* , char* );
00136 inline static int t_cancel_branches(struct sip_msg* msg, char* , char* );
00137 
00138 
00139 /* strings with avp definition */
00140 static char *fr_timer_param = NULL;
00141 static char *fr_inv_timer_param = NULL;
00142 static char *contacts_avp_param = NULL;
00143 
00144 /* module parameteres */
00145 int tm_enable_stats = 1;
00146 str auto_inv_100_reason = str_init("Giving a Try");
00147 
00148 /* statistic variables */
00149 stat_var *tm_rcv_rpls;
00150 stat_var *tm_rld_rpls;
00151 stat_var *tm_loc_rpls;
00152 stat_var *tm_uas_trans;
00153 stat_var *tm_uac_trans;
00154 stat_var *tm_trans_2xx;
00155 stat_var *tm_trans_3xx;
00156 stat_var *tm_trans_4xx;
00157 stat_var *tm_trans_5xx;
00158 stat_var *tm_trans_6xx;
00159 stat_var *tm_trans_inuse;
00160 
00161 
00162 static cmd_export_t cmds[]={
00163    {"t_newtran",       (cmd_function)w_t_newtran,      0, 0,
00164          0, REQUEST_ROUTE},
00165    {"t_reply",         (cmd_function)w_pv_t_reply,     2, fixup_t_send_reply,
00166          0, REQUEST_ROUTE | FAILURE_ROUTE },
00167    {"t_release",       (cmd_function)w_t_release,      0, 0,
00168          0, REQUEST_ROUTE},
00169    {"t_replicate",     (cmd_function)w_t_replicate,    1, fixup_t_replicate,
00170          0, REQUEST_ROUTE},
00171    {"t_replicate",     (cmd_function)w_t_replicate,    2, fixup_t_replicate,
00172          0, REQUEST_ROUTE},
00173    {"t_relay",         (cmd_function)w_t_relay,        0, 0,
00174          0, REQUEST_ROUTE | FAILURE_ROUTE },
00175    {"t_relay",         (cmd_function)w_t_relay,        1, fixup_t_relay1,
00176          0, REQUEST_ROUTE | FAILURE_ROUTE },
00177    {"t_relay",         (cmd_function)w_t_relay,        2, fixup_t_relay2,
00178          0, REQUEST_ROUTE | FAILURE_ROUTE },
00179    {"t_on_failure",    (cmd_function)w_t_on_negative,  1, fixup_uint_null,
00180          0, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00181    {"t_on_reply",      (cmd_function)w_t_on_reply,     1, fixup_uint_null,
00182          0, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00183    {"t_on_branch",     (cmd_function)w_t_on_branch,    1, fixup_uint_null,
00184          0, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00185    {"t_check_status",  (cmd_function)t_check_status,   1, fixup_regexp_null,
00186          0, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00187    {"t_write_req",     (cmd_function)t_write_req,      2, fixup_t_write,
00188          0, REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE },
00189    {"t_write_unix",    (cmd_function)t_write_unix,     2, fixup_t_write,
00190          0, REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE },
00191    {"t_flush_flags",   (cmd_function)t_flush_flags,    0, 0,
00192          0, REQUEST_ROUTE | BRANCH_ROUTE  },
00193    {"t_local_replied", (cmd_function)t_local_replied,  1, fixup_local_replied,
00194          0, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE },
00195    {"t_check_trans",   (cmd_function)t_check_trans,    0, 0,
00196          0, REQUEST_ROUTE | BRANCH_ROUTE | ONREPLY_ROUTE },
00197    {"t_was_cancelled", (cmd_function)t_was_cancelled,  0, 0,
00198          0, FAILURE_ROUTE | ONREPLY_ROUTE },
00199    {"load_tm",         (cmd_function)load_tm,          0, 0,
00200          0, 0},
00201    {"t_load_contacts", (cmd_function)t_load_contacts, 0, 0,
00202                    0, REQUEST_ROUTE | FAILURE_ROUTE},
00203    {"t_next_contacts", (cmd_function)t_next_contacts, 0, 0,
00204                    0, REQUEST_ROUTE | FAILURE_ROUTE},
00205    {"t_cancel_branches", (cmd_function)t_cancel_branches,  1,
00206       fixup_cancel_branches, 0, ONREPLY_ROUTE },
00207    {0,0,0,0,0,0}
00208 };
00209 
00210 
00211 static param_export_t params[]={
00212    {"ruri_matching",             INT_PARAM,
00213       &ruri_matching},
00214    {"via1_matching",             INT_PARAM,
00215       &via1_matching},
00216    {"fr_timer",                  INT_PARAM,
00217       &(timer_id2timeout[FR_TIMER_LIST])},
00218    {"fr_inv_timer",              INT_PARAM,
00219       &(timer_id2timeout[FR_INV_TIMER_LIST])},
00220    {"wt_timer",                  INT_PARAM,
00221       &(timer_id2timeout[WT_TIMER_LIST])},
00222    {"delete_timer",              INT_PARAM,
00223       &(timer_id2timeout[DELETE_LIST])},
00224    {"T1_timer",                  INT_PARAM,
00225       &(timer_id2timeout[RT_T1_TO_1])},
00226    {"T2_timer",                  INT_PARAM,
00227       &(timer_id2timeout[RT_T2])},
00228    {"unix_tx_timeout",           INT_PARAM,
00229       &tm_unix_tx_timeout},
00230    {"restart_fr_on_each_reply",  INT_PARAM,
00231       &restart_fr_on_each_reply},
00232    {"fr_timer_avp",              STR_PARAM,
00233       &fr_timer_param},
00234    {"fr_inv_timer_avp",          STR_PARAM,
00235       &fr_inv_timer_param},
00236    {"tw_append",                 STR_PARAM|USE_FUNC_PARAM,
00237       (void*)parse_tw_append },
00238    { "enable_stats",             INT_PARAM,
00239       &tm_enable_stats },
00240    { "pass_provisional_replies", INT_PARAM,
00241       &pass_provisional_replies },
00242    { "syn_branch",               INT_PARAM,
00243       &syn_branch },
00244    { "onreply_avp_mode",         INT_PARAM,
00245       &onreply_avp_mode },
00246    { "disable_6xx_block",        INT_PARAM,
00247       &disable_6xx_block },
00248    {"fr_inv_timer_next",         INT_PARAM,
00249            &fr_inv_timer_next },
00250    {"contacts_avp",              STR_PARAM,
00251       &contacts_avp_param},
00252    { "drop_stateless_replies",   INT_PARAM,
00253       &drop_stateless_replies },
00254    {"auto_inv_100_reason",          STR_PARAM,
00255       &auto_inv_100_reason.s},
00256    {0,0,0}
00257 };
00258 
00259 
00260 static stat_export_t mod_stats[] = {
00261    {"received_replies" ,    0,              &tm_rcv_rpls    },
00262    {"relayed_replies" ,     0,              &tm_rld_rpls    },
00263    {"local_replies" ,       0,              &tm_loc_rpls    },
00264    {"UAS_transactions" ,    0,              &tm_uas_trans   },
00265    {"UAC_transactions" ,    0,              &tm_uac_trans   },
00266    {"2xx_transactions" ,    0,              &tm_trans_2xx   },
00267    {"3xx_transactions" ,    0,              &tm_trans_3xx   },
00268    {"4xx_transactions" ,    0,              &tm_trans_4xx   },
00269    {"5xx_transactions" ,    0,              &tm_trans_5xx   },
00270    {"6xx_transactions" ,    0,              &tm_trans_6xx   },
00271    {"inuse_transactions" ,  STAT_NO_RESET,  &tm_trans_inuse },
00272    {0,0,0}
00273 };
00274 
00275 
00276 /**
00277  * pseudo-variables exported by TM module
00278  */
00279 static pv_export_t mod_items[] = {
00280    { {"T_branch_idx", sizeof("T_branch_idx")-1}, PVT_OTHER, pv_get_tm_branch_idx, 0,
00281        0, 0, 0, 0 },
00282    { {"T_reply_code", sizeof("T_reply_code")-1}, PVT_OTHER, pv_get_tm_reply_code, 0,
00283        0, 0, 0, 0 },
00284    { {"T_req", sizeof("T_req")-1}, PVT_OTHER, pv_get_t_var_req, 0,
00285       pv_parse_t_var_name, 0, 0, 0 },
00286    { {"T_rpl", sizeof("T_rpl")-1}, PVT_OTHER, pv_get_t_var_rpl, 0,
00287       pv_parse_t_var_name, 0, 0, 0 },
00288    { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
00289 };
00290 
00291 
00292 static mi_export_t mi_cmds [] = {
00293    {MI_TM_UAC,     mi_tm_uac_dlg,   MI_ASYNC_RPL_FLAG,  0,  0 },
00294    {MI_TM_CANCEL,  mi_tm_cancel,    0,                  0,  0 },
00295    {MI_TM_HASH,    mi_tm_hash,      MI_NO_INPUT_FLAG,   0,  0 },
00296    {MI_TM_REPLY,   mi_tm_reply,     0,                  0,  0 },
00297    {0,0,0,0,0}
00298 };
00299 
00300 
00301 struct module_exports exports= {
00302    "tm",      /* module name*/
00303    DEFAULT_DLFLAGS, /* dlopen flags */
00304    cmds,      /* exported functions */
00305    params,    /* exported variables */
00306    mod_stats, /* exported statistics */
00307    mi_cmds,   /* exported MI functions */
00308    mod_items, /* exported pseudo-variables */
00309    0,         /* extra processes */
00310    mod_init,  /* module initialization function */
00311    (response_function) reply_received,
00312    (destroy_function) tm_shutdown,
00313    child_init /* per-child init function */
00314 };
00315 
00316 
00317 
00318 /**************************** fixup functions ******************************/
00319 static int flag_fixup(void** param, int param_no)
00320 {
00321    unsigned int flags;
00322    str s;
00323 
00324    if (param_no == 1) {
00325       s.s = (char*)*param;
00326       s.len = strlen(s.s);
00327       flags = 0;
00328       if ( strno2int(&s, &flags )<0 ) {
00329          return -1;
00330       }
00331       pkg_free(*param);
00332       *param = (void*)(unsigned long int)(flags<<1);
00333    }
00334    return 0;
00335 }
00336 
00337 
00338 static int fixup_t_replicate(void** param, int param_no)
00339 {
00340    str *s;
00341 
00342    if (param_no == 1) {
00343       /* string */
00344       s = (str*)pkg_malloc( sizeof(str) );
00345       if (s==0) {
00346          LM_ERR("no more pkg mem\n");
00347          return E_OUT_OF_MEM;
00348       }
00349       s->s = (char*)*param;
00350       s->len = strlen(s->s);
00351       *param = (void*)s;
00352    } else {
00353       /* flags */
00354       if (flag_fixup( param, 1)!=0) {
00355          LM_ERR("bad flags <%s>\n", (char *)(*param));
00356          return E_CFG;
00357       }
00358    }
00359    return 0;
00360 }
00361 
00362 
00363 static int fixup_phostport2proxy(void** param, int param_no)
00364 {
00365    struct proxy_l *proxy;
00366    char *s;
00367    int port;
00368    int proto;
00369    str host;
00370 
00371    if (param_no!=1) {
00372       LM_CRIT("called with more than  one parameter\n");
00373       return E_BUG;
00374    }
00375 
00376    s = (char *) (*param);
00377    if (s==0 || *s==0) {
00378       LM_CRIT("empty parameter\n");
00379       return E_UNSPEC;
00380    }
00381 
00382    if (parse_phostport( s, strlen(s), &host.s, &host.len, &port, &proto)!=0){
00383       LM_CRIT("invalid parameter <%s>\n",s);
00384       return E_UNSPEC;
00385    }
00386 
00387    proxy = mk_proxy( &host, port, proto, 0);
00388    if (proxy==0) {
00389       LM_ERR("failed to resolve <%.*s>\n", host.len, host.s );
00390       return ser_error;
00391    }
00392    *(param)=proxy;
00393    return 0;
00394 }
00395 
00396 
00397 static int fixup_t_relay1(void** param, int param_no)
00398 {
00399    if (flag_fixup( param, 1)==0) {
00400       /* param is flag -> move it as second param */
00401       *((void**)(((char*)param)+sizeof(action_elem_t))) = *param;
00402       *param = 0;
00403       return 0;
00404    } else if (fixup_phostport2proxy( param, 1)==0 ) {
00405       /* param is OBP -> nothing else to do */
00406       return 0;
00407    } else {
00408       LM_ERR("param is neither flag, nor OBP <%s>\n",(char *)(*param));
00409       return E_CFG;
00410    }
00411 }
00412 
00413 
00414 static int fixup_t_relay2(void** param, int param_no)
00415 {
00416    if (param_no==1) {
00417       return fixup_phostport2proxy( param, param_no);
00418    } else if (param_no==2) {
00419       if (flag_fixup( param, 1)!=0) {
00420          LM_ERR("bad flags <%s>\n", (char *)(*param));
00421          return E_CFG;
00422       }
00423    }
00424    return 0;
00425 }
00426 
00427 
00428 static int fixup_t_send_reply(void** param, int param_no)
00429 {
00430    pv_elem_t *model=NULL;
00431    str s;
00432 
00433    /* convert to str */
00434    s.s = (char*)*param;
00435    s.len = strlen(s.s);
00436    if (s.len==0) {
00437       LM_ERR("param no. %d is empty!\n", param_no);
00438       return E_CFG;
00439    }
00440 
00441    model=NULL;
00442    if (param_no==1 || param_no==2) {
00443       if(pv_parse_format(&s ,&model) || model==NULL) {
00444          LM_ERR("wrong format [%s] for param no %d!\n", s.s, param_no);
00445          return E_CFG;
00446       }
00447       if(model->spec.getf==NULL && param_no==1) {
00448          if(str2int(&s,
00449          (unsigned int*)&model->spec.pvp.pvn.u.isname.name.n)!=0
00450          || model->spec.pvp.pvn.u.isname.name.n<100
00451          || model->spec.pvp.pvn.u.isname.name.n>699) {
00452             LM_ERR("wrong value [%s] for param no %d! - Allowed only"
00453                " 1xx - 6xx \n", s.s, param_no);
00454             return E_CFG;
00455          }
00456       }
00457       *param = (void*)model;
00458    }
00459 
00460    return 0;
00461 }
00462 
00463 
00464 static int fixup_local_replied(void** param, int param_no)
00465 {
00466    char *val;
00467    int n = 0;
00468 
00469    if (param_no==1) {
00470       val = (char*)*param;
00471       if (strcasecmp(val,"all")==0) {
00472          n = 0;
00473       } else if (strcasecmp(val,"branch")==0) {
00474          n = 1;
00475       } else if (strcasecmp(val,"last")==0) {
00476          n = 2;
00477       } else {
00478          LM_ERR("invalid param \"%s\"\n", val);
00479          return E_CFG;
00480       }
00481       /* free string */
00482       pkg_free(*param);
00483       /* replace it with the compiled re */
00484       *param=(void*)(long)n;
00485    } else {
00486       LM_ERR("called with parameter != 1\n");
00487       return E_BUG;
00488    }
00489    return 0;
00490 }
00491 
00492 
00493 
00494 /***************************** init functions *****************************/
00495 int load_tm( struct tm_binds *tmb)
00496 {
00497    tmb->register_tmcb = register_tmcb;
00498 
00499    /* relay function */
00500    tmb->t_relay = (cmd_function)w_t_relay;
00501    /* reply functions */
00502    tmb->t_reply = (treply_f)w_t_reply;
00503    tmb->t_reply_with_body = t_reply_with_body;
00504 
00505    /* transaction location/status functions */
00506    tmb->t_newtran = t_newtran;
00507    tmb->t_is_local = t_is_local;
00508    tmb->t_get_trans_ident = t_get_trans_ident;
00509    tmb->t_lookup_ident = t_lookup_ident;
00510    tmb->t_gett = get_t;
00511    tmb->t_get_picked = t_get_picked_branch;
00512 
00513    tmb->t_lookup_original_t = t_lookupOriginalT;
00514    tmb->t_cancel_uac = t_uac_cancel;
00515    tmb->unref_cell = t_unref_cell;
00516    tmb->t_setkr = set_kr;
00517 
00518    /* tm uac functions */
00519    tmb->t_addblind = add_blind_uac;
00520    tmb->t_request_within = req_within;
00521    tmb->t_request_outside = req_outside;
00522    tmb->t_request = request;
00523    tmb->new_dlg_uac = new_dlg_uac;
00524    tmb->dlg_add_extra = dlg_add_extra;
00525    tmb->dlg_response_uac = dlg_response_uac;
00526    tmb->new_dlg_uas = new_dlg_uas;
00527    tmb->dlg_request_uas = dlg_request_uas;
00528    tmb->free_dlg = free_dlg;
00529    tmb->print_dlg = print_dlg;
00530    tmb->t_get_reply_totag = t_get_reply_totag;
00531 
00532    return 1;
00533 }
00534 
00535 
00536 static int do_t_unref( struct sip_msg *foo, void *bar)
00537 {
00538    struct cell *t;
00539 
00540    t = get_cancelled_t();
00541    if (t!=NULL && t!=T_UNDEFINED)
00542       t_unref_cell(t);
00543 
00544    t = get_e2eack_t();
00545    if (t!=NULL && t!=T_UNDEFINED)
00546       t_unref_cell(t);
00547 
00548    return t_unref(foo);
00549 }
00550 
00551 
00552 static int script_init( struct sip_msg *foo, void *bar)
00553 {
00554    /* we primarily reset all private memory here to make sure
00555     * private values left over from previous message will
00556     * not be used again */
00557 
00558    /* make sure the new message will not inherit previous
00559     * message's t_on_negative value
00560     */
00561    t_on_negative( 0 );
00562    t_on_reply(0);
00563    t_on_branch(0);
00564    set_t(T_UNDEFINED);
00565    reset_cancelled_t();
00566    reset_e2eack_t();
00567    /* reset the kr status */
00568    reset_kr();
00569    return 1;
00570 }
00571 
00572 
00573 static int mod_init(void)
00574 {
00575    /* checking if we have sufficient bitmap capacity for given
00576       maximum number of  branches */
00577    if (MAX_BRANCHES+1>31) {
00578       LM_CRIT("Too many max UACs for UAC branch_bm_t bitmap: %d\n",
00579          MAX_BRANCHES );
00580       return -1;
00581    }
00582 
00583    /* if statistics are disabled, prevent their registration to core */
00584    if (tm_enable_stats==0)
00585       exports.stats = 0;
00586 
00587    if (init_callid() < 0) {
00588       LM_CRIT("Error while initializing Call-ID generator\n");
00589       return -1;
00590    }
00591 
00592    /* building the hash table*/
00593    if (!init_hash_table()) {
00594       LM_ERR("initializing hash_table failed\n");
00595       return -1;
00596    }
00597 
00598    /* init static hidden values */
00599    init_t();
00600 
00601    if (!tm_init_timers()) {
00602       LM_ERR("timer init failed\n");
00603       return -1;
00604    }
00605 
00606    /* register the timer functions */
00607    if (register_timer( timer_routine , 0, 1 )<0) {
00608       LM_ERR("failed to register timer\n");
00609       return -1;
00610    }
00611    if (register_utimer( utimer_routine , 0, 100*1000 )<0) {
00612       LM_ERR("failed to register utimer\n");
00613       return -1;
00614    }
00615 
00616    if (uac_init()==-1) {
00617       LM_ERR("uac_init failed\n");
00618       return -1;
00619    }
00620 
00621    if (init_tmcb_lists()!=1) {
00622       LM_CRIT("failed to init tmcb lists\n");
00623       return -1;
00624    }
00625 
00626    tm_init_tags();
00627    init_twrite_lines();
00628    if (init_twrite_sock() < 0) {
00629       LM_ERR("failed to create socket\n");
00630       return -1;
00631    }
00632 
00633    /* register post-script clean-up function */
00634    if (register_script_cb( do_t_unref, POST_SCRIPT_CB|REQ_TYPE_CB, 0)<0 ) {
00635       LM_ERR("failed to register POST request callback\n");
00636       return -1;
00637    }
00638    if (register_script_cb( script_init, PRE_SCRIPT_CB|REQ_TYPE_CB , 0)<0 ) {
00639       LM_ERR("failed to register PRE request callback\n");
00640       return -1;
00641    }
00642 
00643    if (init_avp_params(fr_timer_param, fr_inv_timer_param,
00644              contacts_avp_param) < 0) {
00645       LM_ERR("failed to process AVP params\n");
00646       return -1;
00647    }
00648 
00649    LM_INFO("fr_inv_timer_next value is <%u>\n", fr_inv_timer_next);
00650 
00651    /* update len for modparam "auto_inv_100_reason" */
00652    auto_inv_100_reason.len = strlen(auto_inv_100_reason.s);
00653    
00654    /* log "auto_inv_100_reason" if value is not default */
00655    if (strcmp(auto_inv_100_reason.s, "Giving a Try"))
00656       LM_INFO("auto_inv_100_reason value is <%s>\n", auto_inv_100_reason.s);
00657 
00658    return 0;
00659 }
00660 
00661 
00662 static int child_init(int rank)
00663 {
00664    if (child_init_callid(rank) < 0) {
00665       LM_ERR("failed to initialize Call-ID generator\n");
00666       return -2;
00667    }
00668 
00669    return 0;
00670 }
00671 
00672 
00673 
00674 
00675 /**************************** wrapper functions ***************************/
00676 static int t_check_status(struct sip_msg* msg, char *regexp, char *foo)
00677 {
00678    regmatch_t pmatch;
00679    struct cell *t;
00680    char *status;
00681    char backup;
00682    int branch;
00683    int n;
00684 
00685    /* first get the transaction */
00686    t = get_t();
00687    if ( t==0 || t==T_UNDEFINED ) {
00688       LM_ERR("cannot check status for a reply which"
00689             " has no transaction-state established\n");
00690       return -1;
00691    }
00692    backup = 0;
00693 
00694    switch (route_type) {
00695       case REQUEST_ROUTE:
00696          /* use the status of the last sent reply */
00697          status = int2str( t->uas.status, 0);
00698          break;
00699       case ONREPLY_ROUTE:
00700          /* use the status of the current reply */
00701          status = msg->first_line.u.reply.status.s;
00702          backup = status[msg->first_line.u.reply.status.len];
00703          status[msg->first_line.u.reply.status.len] = 0;
00704          break;
00705       case FAILURE_ROUTE:
00706          /* use the status of the winning reply */
00707          if ( (branch=t_get_picked_branch())<0 ) {
00708             LM_CRIT("no picked branch (%d) for a final response"
00709                   " in MODE_ONFAILURE\n", branch);
00710             return -1;
00711          }
00712          status = int2str( t->uac[branch].last_received , 0);
00713          break;
00714       default:
00715          LM_ERR("unsupported route_type %d\n", route_type);
00716          return -1;
00717    }
00718 
00719    LM_DBG("checked status is <%s>\n",status);
00720    /* do the checking */
00721    n = regexec((regex_t*)regexp, status, 1, &pmatch, 0);
00722 
00723    if (backup) status[msg->first_line.u.reply.status.len] = backup;
00724    if (n!=0) return -1;
00725    return 1;
00726 }
00727 
00728 
00729 inline static int t_check_trans(struct sip_msg* msg, char *foo, char *bar)
00730 {
00731    struct cell *trans;
00732    int branch;
00733 
00734    if ( msg->first_line.type==SIP_REPLY ) {
00735       if (t_check(msg, &branch ) == -1)
00736          return -1;
00737 
00738       trans = get_t();
00739       if ((trans == 0) || (trans == T_UNDEFINED))
00740          return -1;
00741       msg->branch_index = branch+1;
00742       return 1;
00743    }
00744    
00745    if (msg->REQ_METHOD==METHOD_CANCEL) {
00746       /* parse needed hdrs*/
00747       if (check_transaction_quadruple(msg)==0) {
00748          LM_ERR("too few headers\n");
00749          return 0; /*drop request!*/
00750       }
00751       if (!msg->hash_index)
00752          msg->hash_index = tm_hash(msg->callid->body,get_cseq(msg)->number);
00753       /* performe lookup */
00754       trans = t_lookupOriginalT(  msg );
00755       return trans?1:-1;
00756    } else {
00757       trans = get_t();
00758       if (trans==NULL)
00759          return -1;
00760       if (trans!=T_UNDEFINED)
00761          return 1;
00762       switch ( t_lookup_request( msg , 0) ) {
00763          case 1:
00764             /* transaction found -> is it local ACK? */
00765             if (msg->REQ_METHOD==METHOD_ACK)
00766                return 1;
00767             /* .... else -> retransmission */
00768             trans = get_t();
00769             t_retransmit_reply(trans);
00770             UNREF(trans);
00771             set_t(0);
00772             return 0;
00773          case -2:
00774          case -3:
00775             /* e2e/dlg-local ACK found */
00776             return 1;
00777          default:
00778             /* notfound */
00779             return -1;
00780       }
00781    }
00782 }
00783 
00784 
00785 static int t_flush_flags(struct sip_msg* msg, char *foo, char *bar)
00786 {
00787    struct cell *t;
00788 
00789    /* first get the transaction */
00790    t = get_t();
00791    if ( t==0 || t==T_UNDEFINED) {
00792       LM_ERR("failed to flush flags for a message which has"
00793             " no transaction-state established\n");
00794       return -1;
00795    }
00796 
00797    /* do the flush */
00798    t->uas.request->flags = msg->flags;
00799    return 1;
00800 }
00801 
00802 
00803 inline static int t_local_replied(struct sip_msg* msg, char *type, char *bar)
00804 {
00805    struct cell *t;
00806    int branch;
00807    int i;
00808 
00809    t = get_t();
00810    if (t==0 || t==T_UNDEFINED) {
00811       LM_ERR("no trasaction created\n");
00812       return -1;
00813    }
00814 
00815    switch ( (int)(long)type ) {
00816       /* check all */
00817       case 0:
00818          for( i=t->first_branch ; i<t->nr_of_outgoings ; i++ ) {
00819             if (t->uac[i].flags&T_UAC_HAS_RECV_REPLY)
00820                return -1;
00821          }
00822          return 1;
00823       /* check branch */
00824       case 1:
00825          if (route_type==FAILURE_ROUTE) {
00826             /* use the winning reply */
00827             if ( (branch=t_get_picked_branch())<0 ) {
00828                LM_CRIT("no picked branch (%d) for"
00829                   " a final response in MODE_ONFAILURE\n", branch);
00830                return -1;
00831             }
00832             if (t->uac[branch].flags&T_UAC_HAS_RECV_REPLY)
00833                return -1;
00834             return 1;
00835          }
00836          return -1;
00837       /* check last */
00838       case 2:
00839          if (route_type==FAILURE_ROUTE) {
00840             /* use the winning reply */
00841             if ( (branch=t_get_picked_branch())<0 ) {
00842                LM_CRIT("no picked branch (%d) for"
00843                   " a final response in MODE_ONFAILURE\n", branch);
00844                return -1;
00845             }
00846             if (t->uac[branch].reply==FAKED_REPLY)
00847                return 1;
00848             return -1;
00849          }
00850          return (t->relayed_reply_branch==-2)?1:-1;
00851       default:
00852          return -1;
00853    }
00854 }
00855 
00856 
00857 static int t_was_cancelled(struct sip_msg* msg, char *foo, char *bar)
00858 {
00859    struct cell *t;
00860 
00861    /* first get the transaction */
00862    t = get_t();
00863    if ( t==0 || t==T_UNDEFINED ) {
00864       LM_ERR("failed to check cancel flag for a reply"
00865             " without a transaction\n");
00866       return -1;
00867    }
00868    return was_cancelled(t)?1:-1;
00869 }
00870 
00871 
00872 inline static int w_t_reply(struct sip_msg* msg, char* str1, char* str2)
00873 {
00874    struct cell *t;
00875 
00876    if (msg->REQ_METHOD==METHOD_ACK) {
00877       LM_WARN("ACKs are not replied\n");
00878       return -1;
00879    }
00880    t=get_t();
00881    if ( t==0 || t==T_UNDEFINED ) {
00882       LM_ERR("failed to send a t_reply to a message for which no "
00883          "transaction-state has been established\n");
00884       return -1;
00885    }
00886    /* if called from reply_route, make sure that unsafe version
00887     * is called; we are already in a mutex and another mutex in
00888     * the safe version would lead to a deadlock
00889     */
00890    switch (route_type) {
00891       case FAILURE_ROUTE:
00892          LM_DBG("t_reply_unsafe called from w_t_reply\n");
00893          return t_reply_unsafe(t, msg, (unsigned int)(long)str1,(str*)str2);
00894       case REQUEST_ROUTE:
00895          return t_reply( t, msg, (unsigned int)(long) str1, (str*)str2);
00896       default:
00897          LM_CRIT("unsupported route_type (%d)\n", route_type);
00898          return -1;
00899    }
00900 }
00901 
00902 
00903 inline static int w_pv_t_reply(struct sip_msg *msg, char* code, char* text)
00904 {
00905    str code_s;
00906    unsigned int code_i;
00907 
00908    if(((pv_elem_p)code)->spec.getf!=NULL) {
00909       if(pv_printf_s(msg, (pv_elem_p)code, &code_s)!=0)
00910          return -1;
00911       if(str2int(&code_s, &code_i)!=0 || code_i<100 || code_i>699)
00912          return -1;
00913    } else {
00914       code_i = ((pv_elem_p)code)->spec.pvp.pvn.u.isname.name.n;
00915    }
00916 
00917    if(((pv_elem_p)text)->spec.getf!=NULL) {
00918       if(pv_printf_s(msg, (pv_elem_p)text, &code_s)!=0 || code_s.len <=0)
00919          return -1;
00920    } else {
00921       code_s = ((pv_elem_p)text)->text;
00922    }
00923 
00924    return w_t_reply(msg, (char*)(unsigned long)code_i, (char*)&code_s);
00925 }
00926 
00927 
00928 inline static int w_t_release(struct sip_msg* msg, char* str, char* str2)
00929 {
00930    struct cell *t;
00931 
00932    t=get_t();
00933    if ( t && t!=T_UNDEFINED ) 
00934       return t_release_transaction( t );
00935    return 1;
00936 }
00937 
00938 
00939 inline static int w_t_newtran( struct sip_msg* p_msg, char* foo, char* bar ) 
00940 {
00941    /* t_newtran returns 0 on error (negative value means
00942       'transaction exists' */
00943    return t_newtran( p_msg );
00944 }
00945 
00946 
00947 inline static int w_t_on_negative( struct sip_msg* msg, char *go_to, char *foo)
00948 {
00949    t_on_negative( (unsigned int )(long) go_to );
00950    return 1;
00951 }
00952 
00953 
00954 inline static int w_t_on_reply( struct sip_msg* msg, char *go_to, char *foo )
00955 {
00956    t_on_reply( (unsigned int )(long) go_to );
00957    return 1;
00958 }
00959 
00960 
00961 inline static int w_t_on_branch( struct sip_msg* msg, char *go_to, char *foo )
00962 {
00963    t_on_branch( (unsigned int )(long) go_to );
00964    return 1;
00965 }
00966 
00967 
00968 inline static int w_t_replicate(struct sip_msg *p_msg, char *dst, char *flags)
00969 {
00970    return t_replicate( p_msg, (str*)dst, (int)(long)flags);
00971 }
00972 
00973 static inline int t_relay_inerr2scripterr(void)
00974 {
00975    switch (ser_error) {
00976       case E_BAD_URI:
00977       case E_BAD_REQ:
00978       case E_BAD_TO:
00979       case E_INVALID_PARAMS:
00980          /* bad message */
00981          return -2;
00982       case E_NO_DESTINATION:
00983          /* no available destination */
00984          return -3;
00985       case E_BAD_ADDRESS:
00986          /* bad destination */
00987          return -4;
00988       case E_IP_BLOCKED:
00989          /* destination filtered */
00990          return -5;
00991       case E_NO_SOCKET:
00992       case E_SEND:
00993          /* send failed */
00994          return -6;
00995       default:
00996          /* generic internal error */
00997          return -1;
00998    }
00999 }
01000 
01001 
01002 inline static int w_t_relay( struct sip_msg  *p_msg , char *proxy, char *flags)
01003 {
01004    struct cell *t;
01005    int ret;
01006 
01007    t=get_t();
01008 
01009    if (!t || t==T_UNDEFINED) {
01010       /* no transaction yet */
01011       if (route_type==FAILURE_ROUTE) {
01012          LM_CRIT(" BUG - undefined transaction in failure route\n");
01013          return -1;
01014       }
01015       ret = t_relay_to( p_msg, (struct proxy_l *)proxy, (int)(long)flags );
01016       if (ret<0) {
01017          return t_relay_inerr2scripterr();
01018       }
01019       return ret;
01020    } else {
01021       /* transaction already created */
01022 
01023       if ( route_type!=REQUEST_ROUTE && route_type!=FAILURE_ROUTE )
01024          goto route_err;
01025 
01026       if (p_msg->REQ_METHOD==METHOD_ACK) {
01027          /* local ACK*/
01028          t_release_transaction(t);
01029          return 1;
01030       }
01031 
01032       if (((int)(long)flags)&TM_T_REPLY_nodnsfo_FLAG)
01033          t->flags|=T_NO_DNS_FAILOVER_FLAG;
01034 
01035       ret = t_forward_nonack( t, p_msg, (struct proxy_l *)proxy);
01036       if (ret<=0 ) {
01037          LM_ERR("t_forward_nonack failed\n");
01038          return t_relay_inerr2scripterr();
01039       }
01040       return ret;
01041    }
01042 
01043 route_err:
01044    LM_CRIT("unsupported route type: %d\n", route_type);
01045    return 0;
01046 }
01047 
01048 
01049 
01050 extern int _tm_branch_index;
01051 /* item functions */
01052 static int pv_get_tm_branch_idx(struct sip_msg *msg, pv_param_t *param,
01053       pv_value_t *res)
01054 {
01055    int l = 0;
01056    char *ch = NULL;
01057 
01058    if(msg==NULL || res==NULL)
01059       return -1;
01060    
01061    ch = int2str(_tm_branch_index, &l);
01062 
01063    res->rs.s = ch;
01064    res->rs.len = l;
01065 
01066    res->ri = _tm_branch_index;
01067    res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
01068 
01069    return 0;
01070 }
01071 
01072 static int pv_get_tm_reply_code(struct sip_msg *msg, pv_param_t *param,
01073       pv_value_t *res)
01074 {
01075    struct cell *t;
01076    int code;
01077    int branch;
01078 
01079    if(msg==NULL || res==NULL)
01080       return -1;
01081 
01082    /* first get the transaction */
01083    if (t_check( msg , 0 )==-1) return -1;
01084    if ( (t=get_t())==0) {
01085       /* no T */
01086       code = 0;
01087    } else {
01088       switch (route_type) {
01089          case REQUEST_ROUTE:
01090             /* use the status of the last sent reply */
01091             code = t->uas.status;
01092             break;
01093          case ONREPLY_ROUTE:
01094             /* use the status of the current reply */
01095             code = msg->first_line.u.reply.statuscode;
01096             break;
01097          case FAILURE_ROUTE:
01098             /* use the status of the winning reply */
01099             if ( (branch=t_get_picked_branch())<0 ) {
01100                LM_CRIT("no picked branch (%d) for a final response"
01101                      " in MODE_ONFAILURE\n", branch);
01102                code = 0;
01103             } else {
01104                code = t->uac[branch].last_received;
01105             }
01106             break;
01107          default:
01108             LM_ERR("unsupported route_type %d\n", route_type);
01109             code = 0;
01110       }
01111    }
01112 
01113    LM_DBG("reply code is <%d>\n",code);
01114 
01115    res->rs.s = int2str( code, &res->rs.len);
01116 
01117    res->ri = code;
01118    res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
01119    return 0;
01120 }
01121 
01122 static int fixup_cancel_branches(void** param, int param_no)
01123 {
01124    char *val;
01125    int n = 0;
01126 
01127    if (param_no==1) {
01128       val = (char*)*param;
01129       if (strcasecmp(val,"all")==0) {
01130          n = 0;
01131       } else if (strcasecmp(val,"others")==0) {
01132          n = 1;
01133       } else if (strcasecmp(val,"this")==0) {
01134          n = 2;
01135       } else {
01136          LM_ERR("invalid param \"%s\"\n", val);
01137          return E_CFG;
01138       }
01139       pkg_free(*param);
01140       *param=(void*)(long)n;
01141    } else {
01142       LM_ERR("called with parameter != 1\n");
01143       return E_BUG;
01144    }
01145    return 0;
01146 }
01147 
01148 inline static int t_cancel_branches(struct sip_msg* msg, char *k, char *s2)
01149 {
01150    branch_bm_t cb = 0;
01151    struct cell *t = 0;
01152    int n=0;
01153    t=get_t();
01154    if (t==NULL || t==T_UNDEFINED || !is_invite(t))
01155       return -1;
01156    n = (int)k;
01157    switch(n) {
01158       case 1:
01159          LOCK_REPLIES(t);
01160          which_cancel(t, &cb);
01161          if(t->uac[_tm_branch_index].local_cancel.buffer.s==BUSY_BUFFER)
01162             t->uac[_tm_branch_index].local_cancel.buffer.s=NULL;
01163          UNLOCK_REPLIES(t);
01164          cb &= ~(1<<_tm_branch_index);
01165       case 2:
01166          if(msg->first_line.u.reply.statuscode>=200)
01167             break;
01168          cb = 1<<_tm_branch_index;
01169       break;
01170       default:
01171          LOCK_REPLIES(t);
01172          which_cancel(t, &cb);
01173          UNLOCK_REPLIES(t);
01174          if (msg->first_line.u.reply.statuscode>=200)
01175             cb &= ~(1<<_tm_branch_index);
01176    }
01177    LM_DBG("canceling %d/%d\n", n, (int)cb);
01178    if(cb==0)
01179       return -1;
01180    cancel_uacs(t, cb);
01181    return 1;
01182 }
01183 

Generated on Thu May 24 20:00:33 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6