📄 tm.c
字号:
/* * $Id: tm.c,v 1.34 2006/05/19 14:55:19 bogdan_iancu Exp $ * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of openser, a free SIP server. * * openser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * openser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * History: * -------- * 2003-02-18 added t_forward_nonack_{udp, tcp}, t_relay_to_{udp,tcp}, * t_replicate_{udp, tcp} (andrei) * 2003-02-19 added t_rely_{udp, tcp} (andrei) * 2003-03-06 voicemail changes accepted (jiri) * 2003-03-10 module export interface updated to the new format (andrei) * 2003-03-16 flags export parameter added (janakj) * 2003-03-19 replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei) * 2003-03-30 set_kr for requests only (jiri) * 2003-04-05 s/reply_route/failure_route, onreply_route introduced (jiri) * 2003-04-14 use protocol from uri (jiri) * 2003-07-07 added t_relay_to_tls, t_replicate_tls, t_forward_nonack_tls * added #ifdef USE_TCP, USE_TLS * removed t_relay_{udp,tcp,tls} (andrei) * 2003-09-26 added t_forward_nonack_uri() - same as t_forward_nonack() but * takes no parameters -> forwards to uri (bogdan) * 2004-02-11 FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri) * 2004-02-18 t_reply exported via FIFO - imported from VM (bogdan) * 2004-10-01 added a new param.: restart_fr_on_each_reply (andrei) * 2005-05-30 light version of tm_load - find_export dropped -> module * interface dosen't need to export internal functions (bogdan) * 2006-01-15 merged functions which diff only via proto (like t_relay, * t_replicate and t_forward_nonack) (bogdan) */#include <stdio.h>#include <string.h>#include <netdb.h>#include "../../sr_module.h"#include "../../dprint.h"#include "../../error.h"#include "../../ut.h"#include "../../script_cb.h"#include "../../fifo_server.h"#include "../../usr_avp.h"#include "../../mem/mem.h"#include "../../unixsock_server.h"#include "../../items.h"#include "sip_msg.h"#include "h_table.h"#include "ut.h"#include "t_reply.h"#include "uac_fifo.h"#include "uac_unixsock.h"#include "t_fwd.h"#include "t_lookup.h"#include "callid.h"#include "t_cancel.h"#include "t_fifo.h"#include "tm_load.h"MODULE_VERSION/* item functions */static int it_get_tm_branch_idx(struct sip_msg *msg, xl_value_t *res, xl_param_t *param, int flags);/* fixup functions */static int fixup_t_send_reply(void** param, int param_no);static int fixup_str(void** param, int param_no);static int fixup_str2int( void** param, int param_no);static int fixup_phostport2proxy(void** param, int param_no);static int fixup_str2regexp(void** param, int param_no);static int fixup_local_replied(void** param, int param_no);/* init functions */static int mod_init(void);static int child_init(int rank);/* exported functions */inline static int w_t_check(struct sip_msg* msg, char* , char* );inline static int w_t_release(struct sip_msg* msg, char* , char* );inline static int w_t_retransmit_reply(struct sip_msg* p_msg, char* ,char* );inline static int w_t_newtran(struct sip_msg* p_msg, char* , char* );inline static int w_t_reply(struct sip_msg *msg, char* code, char* text);inline static int w_t_relay(struct sip_msg *p_msg , char *proxy, char* );inline static int w_t_replicate(struct sip_msg *p_msg, char *dst,char* );inline static int w_t_forward_nonack(struct sip_msg* msg, char* proxy, char* );inline static int w_t_on_negative(struct sip_msg* msg, char *go_to, char* );inline static int w_t_on_reply(struct sip_msg* msg, char *go_to, char* );inline static int w_t_on_branch(struct sip_msg* msg, char *go_to, char* );inline static int t_check_status(struct sip_msg* msg, char *regexp, char* );inline static int t_flush_flags(struct sip_msg* msg, char*, char* );inline static int t_local_replied(struct sip_msg* msg, char *type, char* );inline static int t_check_trans(struct sip_msg* msg, char* , char* );inline static int t_was_cancelled(struct sip_msg* msg, char* , char* );/* strings with avp definition */static char *fr_timer_param = FR_TIMER_AVP;static char *fr_inv_timer_param = FR_INV_TIMER_AVP;/* module parameteres */static char *bf_mask_param = NULL;int tm_enable_stats = 1;/* statistic variables */stat_var *tm_rcv_rpls;stat_var *tm_rld_rpls;stat_var *tm_loc_rpls;stat_var *tm_uas_trans;stat_var *tm_uac_trans;stat_var *tm_trans_2xx;stat_var *tm_trans_3xx;stat_var *tm_trans_4xx;stat_var *tm_trans_5xx;stat_var *tm_trans_6xx;stat_var *tm_trans_inuse;static cmd_export_t cmds[]={ {"t_newtran", w_t_newtran, 0, 0, REQUEST_ROUTE}, {"t_lookup_request", w_t_check, 0, 0, REQUEST_ROUTE}, {"t_reply", w_t_reply, 2, fixup_t_send_reply, REQUEST_ROUTE | FAILURE_ROUTE }, {"t_retransmit_reply", w_t_retransmit_reply, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE }, {"t_release", w_t_release, 0, 0, REQUEST_ROUTE}, {"t_replicate", w_t_replicate, 1, fixup_str, REQUEST_ROUTE}, {"t_relay", w_t_relay, 0, 0, REQUEST_ROUTE | FAILURE_ROUTE }, {"t_relay", w_t_relay, 1,fixup_phostport2proxy, REQUEST_ROUTE | FAILURE_ROUTE }, {"t_forward_nonack", w_t_forward_nonack, 0, 0, REQUEST_ROUTE}, {"t_forward_nonack", w_t_forward_nonack, 1,fixup_phostport2proxy, REQUEST_ROUTE}, {"t_on_failure", w_t_on_negative, 1, fixup_str2int, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE }, {"t_on_reply", w_t_on_reply, 1, fixup_str2int, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE }, {"t_on_branch", w_t_on_branch, 1, fixup_str2int, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE }, {"t_check_status", t_check_status, 1, fixup_str2regexp, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE }, {"t_write_req", t_write_req, 2, fixup_t_write, REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE }, {"t_write_unix", t_write_unix, 2, fixup_t_write, REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE }, {"t_flush_flags", t_flush_flags, 0, 0, REQUEST_ROUTE | BRANCH_ROUTE }, {"t_local_replied", t_local_replied, 1, fixup_local_replied, REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE }, {"t_check_trans", t_check_trans, 0, 0, REQUEST_ROUTE | BRANCH_ROUTE }, {"t_was_cancelled", t_was_cancelled, 0, 0, FAILURE_ROUTE | ONREPLY_ROUTE }, {"load_tm", (cmd_function)load_tm, 0, 0, 0}, {0,0,0,0,0}};static param_export_t params[]={ {"ruri_matching", INT_PARAM, &ruri_matching}, {"via1_matching", INT_PARAM, &via1_matching}, {"fr_timer", INT_PARAM, &(timer_id2timeout[FR_TIMER_LIST])}, {"fr_inv_timer", INT_PARAM, &(timer_id2timeout[FR_INV_TIMER_LIST])}, {"wt_timer", INT_PARAM, &(timer_id2timeout[WT_TIMER_LIST])}, {"delete_timer", INT_PARAM, &(timer_id2timeout[DELETE_LIST])}, {"retr_timer1p1", INT_PARAM, &(timer_id2timeout[RT_T1_TO_1])}, {"retr_timer1p2", INT_PARAM, &(timer_id2timeout[RT_T1_TO_2])}, {"retr_timer1p3", INT_PARAM, &(timer_id2timeout[RT_T1_TO_3])}, {"retr_timer2", INT_PARAM, &(timer_id2timeout[RT_T2])}, {"noisy_ctimer", INT_PARAM, &noisy_ctimer}, {"unix_tx_timeout", INT_PARAM, &tm_unix_tx_timeout}, {"restart_fr_on_each_reply", INT_PARAM, &restart_fr_on_each_reply}, {"fr_timer_avp", STR_PARAM, &fr_timer_param}, {"fr_inv_timer_avp", STR_PARAM, &fr_inv_timer_param}, {"tw_append", STR_PARAM|USE_FUNC_PARAM, (void*)parse_tw_append }, {"branch_flag_mask", STR_PARAM, &bf_mask_param }, { "enable_stats", INT_PARAM, &tm_enable_stats }, { "pass_provisional_replies", INT_PARAM, &pass_provisional_replies }, {0,0,0}};stat_export_t mod_stats[] = { {"received_replies" , 0, &tm_rcv_rpls }, {"relayed_replies" , 0, &tm_rld_rpls }, {"local_replies" , 0, &tm_loc_rpls }, {"UAS_transactions" , 0, &tm_uas_trans }, {"UAC_transactions" , 0, &tm_uac_trans }, {"2xx_transactions" , 0, &tm_trans_2xx }, {"3xx_transactions" , 0, &tm_trans_3xx }, {"4xx_transactions" , 0, &tm_trans_4xx }, {"5xx_transactions" , 0, &tm_trans_5xx }, {"6xx_transactions" , 0, &tm_trans_6xx }, {"inuse_transactions" , STAT_NO_RESET, &tm_trans_inuse }, {0,0,0}};#ifdef STATIC_TMstruct module_exports tm_exports = {#elsestruct module_exports exports= {#endif "tm", /* module name*/ cmds, /* exported functions */ params, /* exported variables */ mod_stats, /* exported statistics */ mod_init, /* module initialization function */ (response_function) reply_received, (destroy_function) tm_shutdown, child_init /* per-child init function */};/**************************** fixup functions ******************************/static int fixup_str(void** param, int param_no){ str *s; if (param_no == 1) { s = (str*)pkg_malloc( sizeof(str) ); if (s==0) { LOG(L_ERR,"ERROR:tm:fixup_str: no more pkg mem\n"); return E_OUT_OF_MEM; } s->s = (char*)*param; s->len = strlen(s->s); *param = (void*)s; } return 0;}static int fixup_str2int( void** param, int param_no){ unsigned long go_to; int err; if (param_no==1) { go_to=str2s(*param, strlen(*param), &err ); if (err==0) { pkg_free(*param); *param=(void *)go_to; return 0; } else { LOG(L_ERR, "ERROR:tm:fixup_str2int: bad number <%s>\n", (char *)(*param)); return E_CFG; } } return 0;}static int fixup_phostport2proxy(void** param, int param_no){ struct proxy_l *proxy; char *s; int port; int proto; str host; if (param_no!=1) { LOG(L_CRIT,"BUG:tm:fixup_phostport2proxy: called with more than " " one parameter\n"); return E_BUG; } s = (char *) (*param); if (s==0 || *s==0) { LOG(L_CRIT,"ERROR:tm:fixup_phostport2proxy: empty parameter\n"); return E_UNSPEC; } if (parse_phostport( s, strlen(s), &host.s, &host.len, &port, &proto)!=0){ LOG(L_CRIT,"ERROR:tm:fixup_phostport2proxy: invalid parameter " "<%s>\n",s); return E_UNSPEC; } proxy = mk_proxy( &host, port, proto, 0); if (proxy==0) { LOG(L_ERR, "ERROR:tm:fixup_phostport2proxy: failed to resolve " "<%.*s>\n", host.len, host.s ); return ser_error; } *(param)=proxy; return 0;}/* (char *code, char *reason_phrase)==>(int code, r_p as is) */static int fixup_t_send_reply(void** param, int param_no){ unsigned long code; int err; if (param_no==1){ code=str2s(*param, strlen(*param), &err); if (err==0){ pkg_free(*param); *param=(void*)code; return 0; }else{ LOG(L_ERR, "TM module:fixup_t_send_reply: bad number <%s>\n", (char*)(*param)); return E_UNSPEC; } } /* second param => no conversion*/ return 0;}static int fixup_str2regexp(void** param, int param_no){ regex_t* re; if (param_no==1) { if ((re=pkg_malloc(sizeof(regex_t)))==0) return E_OUT_OF_MEM; if (regcomp(re, *param, REG_EXTENDED|REG_ICASE|REG_NEWLINE) ) { pkg_free(re); LOG(L_ERR,"ERROR: %s : bad re %s\n", exports.name, (char*)*param); return E_BAD_RE; } /* free string */ pkg_free(*param); /* replace it with the compiled re */ *param=re; } else { LOG(L_ERR,"ERROR: fixup_str2regexp called with parameter != 1\n"); return E_BUG; } return 0;}static int fixup_local_replied(void** param, int param_no){ char *val; int n = 0; if (param_no==1) { val = (char*)*param; if (strcasecmp(val,"all")==0) { n = 1; } else if (strcasecmp(val,"last")==0) { n = 0; } else { LOG(L_ERR,"ERROR:tm:fixup_local_replied: invalid param \"%s\"\n", val); return E_UNSPEC; } /* free string */ pkg_free(*param); /* replace it with the compiled re */ *param=(void*)(long)n; } else { LOG(L_ERR,"ERROR:fixup_local_replied: called with parameter != 1\n"); return E_BUG; } return 0;}/***************************** init functions *****************************/int load_tm( struct tm_binds *tmb){ tmb->register_tmcb = register_tmcb; /* replicate function */ tmb->t_replicate = w_t_replicate; /* relay/forward functions */ tmb->t_relay = w_t_relay; tmb->t_forward_nonack = (tfwd_f)w_t_forward_nonack; /* reply functions */ tmb->t_reply = (treply_f)w_t_reply; tmb->t_reply_with_body = t_reply_with_body; /* transaction location/status functions */ tmb->t_newtran = t_newtran; tmb->t_is_local = t_is_local; tmb->t_get_trans_ident = t_get_trans_ident; tmb->t_lookup_ident = t_lookup_ident; tmb->t_gett = get_t; tmb->t_get_picked = t_get_picked_branch; /* tm uac functions */ tmb->t_addblind = add_blind_uac; tmb->t_request_within = req_within; tmb->t_request_outside = req_outside; tmb->t_request = request; tmb->new_dlg_uac = new_dlg_uac; tmb->dlg_response_uac = dlg_response_uac; tmb->new_dlg_uas = new_dlg_uas; tmb->dlg_request_uas = dlg_request_uas; tmb->free_dlg = free_dlg; tmb->print_dlg = print_dlg; return 1;}static int w_t_unref( struct sip_msg *foo, void *bar){ return t_unref(foo);}static int script_init( struct sip_msg *foo, void *bar){ /* we primarily reset all private memory here to make sure * private values left over from previous message will * not be used again */ /* make sure the new message will not inherit previous * message's t_on_negative value */ t_on_negative( 0 ); t_on_reply(0); t_on_branch(0); set_t(T_UNDEFINED); /* reset the kr status */ set_kr(0); return 1;}static int init_gf_mask( char* bf_mask ){ long long int l; char *end; if (bf_mask==0) return 0; errno = 0; /* try bases 2, 10 and 16 */ if (bf_mask[0]=='b' || bf_mask[0]=='B') { l = strtoll( bf_mask+1, &end, 2); if (*end==0 && errno==0) goto ok; } if (bf_mask[0]=='0' && bf_mask[1]=='x') { l = strtoll( bf_mask+2, &end, 16); if (*end==0 && errno==0) goto ok;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -