📄 tm.c
字号:
} l = strtoll( bf_mask, &end, 10); if (*end==0 && errno==0) goto ok; return -1;ok: gflags_mask = ~((unsigned int)l); DBG("DEBUG:tm:init_gf_mask: gflags_mask is %x\n",gflags_mask); return 0;}static int mod_init(void){ LOG(L_INFO,"TM - initializing...\n"); /* checking if we have sufficient bitmap capacity for given maximum number of branches */ if (MAX_BRANCHES+1>31) { LOG(L_CRIT, "Too many max UACs for UAC branch_bm_t bitmap: %d\n", MAX_BRANCHES ); return -1; } /* if statistics are disabled, prevent their registration to core */ if (tm_enable_stats==0)#ifdef STATIC_TM tm_exports.stats = 0;#else exports.stats = 0;#endif if (init_callid() < 0) { LOG(L_CRIT, "Error while initializing Call-ID generator\n"); return -1; } if (register_fifo_cmd(fifo_uac, "t_uac_dlg", 0) < 0) { LOG(L_CRIT, "cannot register fifo t_uac\n"); return -1; } if (register_fifo_cmd(fifo_uac_cancel, "t_uac_cancel", 0) < 0) { LOG(L_CRIT, "cannot register fifo t_uac_cancel\n"); return -1; } if (register_fifo_cmd(fifo_hash, "t_hash", 0)<0) { LOG(L_CRIT, "cannot register hash\n"); return -1; } if (register_fifo_cmd(fifo_t_reply, "t_reply", 0)<0) { LOG(L_CRIT, "cannot register t_reply\n"); return -1; } if (unixsock_register_cmd("t_uac_dlg", unixsock_uac) < 0) { LOG(L_CRIT, "cannot register t_uac with the unix server\n"); return -1; } if (unixsock_register_cmd("t_uac_cancel", unixsock_uac_cancel) < 0) { LOG(L_CRIT, "cannot register t_uac_cancel with the unix server\n"); return -1; } if (unixsock_register_cmd("t_hash", unixsock_hash) < 0) { LOG(L_CRIT, "cannot register t_hash with the unix server\n"); return -1; } if (unixsock_register_cmd("t_reply", unixsock_t_reply) < 0) { LOG(L_CRIT, "cannot register t_reply with the unix server\n"); return -1; } /* building the hash table*/ if (!init_hash_table()) { LOG(L_ERR, "ERROR: mod_init: initializing hash_table failed\n"); return -1; } /* init static hidden values */ init_t(); if (!tm_init_timers()) { LOG(L_ERR, "ERROR: mod_init: timer init failed\n"); return -1; } /* register the timer function */ register_timer( timer_routine , 0 /* empty attr */, 1 ); if (uac_init()==-1) { LOG(L_ERR, "ERROR: mod_init: uac_init failed\n"); return -1; } if (init_tmcb_lists()!=1) { LOG(L_CRIT, "ERROR:tm:mod_init: failed to init tmcb lists\n"); return -1; } tm_init_tags(); init_twrite_lines(); if (init_twrite_sock() < 0) { LOG(L_ERR, "ERROR:tm:mod_init: Unable to create socket\n"); return -1; } /* register post-script clean-up function */ if (register_script_cb( w_t_unref, POST_SCRIPT_CB|REQ_TYPE_CB, 0)<0 ) { LOG(L_ERR,"ERROR:tm:mod_init: failed to register POST request " "callback\n"); return -1; } if (register_script_cb( script_init, PRE_SCRIPT_CB|REQ_TYPE_CB , 0)<0 ) { LOG(L_ERR,"ERROR:tm:mod_init: failed to register PRE request " "callback\n"); return -1; } if ( init_avp_params( fr_timer_param, fr_inv_timer_param)<0 ){ LOG(L_ERR,"ERROR:tm:mod_init: failed to process timer AVPs\n"); return -1; } if ( init_gf_mask( bf_mask_param )<0 ) { LOG(L_ERR,"ERROR:tm:mod_init: failed to process " "\"branch_flag_mask\" param\n"); return -1; } if(xl_add_extra("T_branch_idx", it_get_tm_branch_idx, 100, NULL)!=0) { LOG(L_ERR,"ERROR:tm:mod_init: failed to register pvar " "[T_branch_idx]\n"); return -1; } return 0;}static int child_init(int rank){ if (child_init_callid(rank) < 0) { LOG(L_ERR, "ERROR:tm:child_init: Error while initializing " "Call-ID generator\n"); return -2; } return 0;}/**************************** wrapper functions ***************************/static int t_check_status(struct sip_msg* msg, char *regexp, char *foo){ regmatch_t pmatch; struct cell *t; char *status; char backup; int branch; int n; /* first get the transaction */ if (t_check( msg , 0 )==-1) return -1; if ( (t=get_t())==0) { LOG(L_ERR, "ERROR: t_check_status: cannot check status for a reply " "which has no T-state established\n"); return -1; } backup = 0; switch (route_type) { case REQUEST_ROUTE: /* use the status of the last sent reply */ status = int2str( t->uas.status, 0); break; case ONREPLY_ROUTE: /* use the status of the current reply */ status = msg->first_line.u.reply.status.s; backup = status[msg->first_line.u.reply.status.len]; status[msg->first_line.u.reply.status.len] = 0; break; case FAILURE_ROUTE: /* use the status of the winning reply */ if ( (branch=t_get_picked_branch())<0 ) { LOG(L_CRIT,"BUG:t_check_status: no picked branch (%d) for" " a final response in MODE_ONFAILURE\n", branch); return -1; } status = int2str( t->uac[branch].last_received , 0); break; default: LOG(L_ERR,"ERROR:t_check_status: unsupported route_type %d\n", route_type); return -1; } DBG("DEBUG:t_check_status: checked status is <%s>\n",status); /* do the checking */ n = regexec((regex_t*)regexp, status, 1, &pmatch, 0); if (backup) status[msg->first_line.u.reply.status.len] = backup; if (n!=0) return -1; return 1;}inline static int t_check_trans(struct sip_msg* msg, char *foo, char *bar){ struct cell *trans; struct cell *bkup; int ret; if (msg->REQ_METHOD==METHOD_CANCEL) { /* parse needed hdrs*/ if (check_transaction_quadruple(msg)==0) { LOG(L_ERR, "ERROR:tm:t_check_trans: too few headers\n"); return 0; /*drop request!*/ } if (!msg->hash_index) msg->hash_index = tm_hash(msg->callid->body,get_cseq(msg)->number); /* performe lookup */ trans = t_lookupOriginalT( msg ); if (trans) { UNREF( trans ); return 1; } else { return -1; } } else { bkup = get_t(); ret = t_lookup_request( msg , 0); if ( (trans=get_t())!=0 ) UNREF(trans); set_t( bkup ); switch (ret) { case 1: /* transaction found */ return 1; case -2: /* e2e ACK found */ return 1; default: /* notfound */ return -1; } } return ret;}static int t_flush_flags(struct sip_msg* msg, char *foo, char *bar){ struct cell *t; /* first get the transaction */ t = get_t(); if ( t==0 || t==T_UNDEFINED) { LOG(L_ERR, "ERROR: t_flush_flags: cannot flush flags for a message " "which has no T-state established\n"); return -1; } /* do the flush */ t->uas.request->flags = msg->flags&gflags_mask; return 1;}inline static int t_local_replied(struct sip_msg* msg, char *all, char *bar){ struct cell *t; int all_rpls; int i; if (t_check( msg , 0 )!=1) { LOG(L_ERR, "ERROR:t_local_replied: no transaction was set up\n"); return -1; } t = get_t(); all_rpls = (int)(long)all; /* is last reply local ? */ if (t->relaied_reply_branch!=-2) return -1; /* were all replies local or none */ if (all_rpls) { for( i=t->first_branch ; i<t->nr_of_outgoings ; i++ ) { if (t->uac[i].flags&T_UAC_HAS_RECV_REPLY) return -1; } } return 1;}static int t_was_cancelled(struct sip_msg* msg, char *foo, char *bar){ struct cell *t; /* first get the transaction */ if (t_check( msg , 0 )==-1) return -1; if ( (t=get_t())==0) { LOG(L_ERR, "ERROR:tm:t_was_cancelled: cannot check cancel flag for " "a reply without a transaction\n"); return -1; } return (t->flags&T_WAS_CANCELLED_FLAG)?1:-1;}inline static int w_t_check(struct sip_msg* msg, char* str, char* str2){ return t_check( msg , 0 ) ? 1 : -1;}inline static int w_t_forward_nonack( struct sip_msg* msg, char* proxy, char* foo){ struct cell *t; if (t_check( msg , 0 )!=1) { LOG(L_ERR, "ERROR:tm:w_t_forward_nonack: " "can't forward when no transaction was set up\n"); return -1; } t=get_t(); if (msg->REQ_METHOD==METHOD_ACK) { LOG(L_WARN,"WARNING:tm:w_t_forward_nonack: you don't really " "want to fwd hbh ACK\n"); return -1; } return t_forward_nonack( t, msg, ( struct proxy_l *)proxy);}inline static int w_t_reply(struct sip_msg* msg, char* str, char* str2){ struct cell *t; if (msg->REQ_METHOD==METHOD_ACK) { LOG(L_WARN, "WARNING: t_reply: ACKs are not replied\n"); return -1; } if (t_check( msg , 0 )==-1) return -1; t=get_t(); if (!t) { LOG(L_ERR, "ERROR: t_reply: cannot send a t_reply to a message " "for which no T-state has been established\n"); return -1; } /* if called from reply_route, make sure that unsafe version * is called; we are already in a mutex and another mutex in * the safe version would lead to a deadlock */ switch (route_type) { case FAILURE_ROUTE: DBG("DEBUG: t_reply_unsafe called from w_t_reply\n"); return t_reply_unsafe(t, msg, (unsigned int)(long) str, str2); case REQUEST_ROUTE: return t_reply( t, msg, (unsigned int)(long) str, str2); default: LOG(L_CRIT, "BUG:tm:w_t_reply: unsupported route_type (%d)\n", route_type); return -1; }}inline static int w_t_release(struct sip_msg* msg, char* str, char* str2){ struct cell *t; if (t_check( msg , 0 )==-1) return -1; t=get_t(); if ( t && t!=T_UNDEFINED ) return t_release_transaction( t ); return 1;}inline static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar){ struct cell *t; if (t_check( p_msg , 0 )==-1) return 1; t=get_t(); if (t) { if (p_msg->REQ_METHOD==METHOD_ACK) { LOG(L_WARN, "WARNING: : ACKs transmit_replies not replied\n"); return -1; } return t_retransmit_reply( t ); } else return -1;}inline static int w_t_newtran( struct sip_msg* p_msg, char* foo, char* bar ) { /* t_newtran returns 0 on error (negative value means 'transaction exists' */ return t_newtran( p_msg );}inline static int w_t_on_negative( struct sip_msg* msg, char *go_to, char *foo){ t_on_negative( (unsigned int )(long) go_to ); return 1;}inline static int w_t_on_reply( struct sip_msg* msg, char *go_to, char *foo ){ t_on_reply( (unsigned int )(long) go_to ); return 1;}inline static int w_t_on_branch( struct sip_msg* msg, char *go_to, char *foo ){ t_on_branch( (unsigned int )(long) go_to ); return 1;}inline static int w_t_replicate(struct sip_msg *p_msg, char *dst, char *_bar){ return t_replicate( p_msg, (str*)dst );}inline static int w_t_relay( struct sip_msg *p_msg , char *proxy, char *foo){ struct cell *t; if (route_type==FAILURE_ROUTE) { t=get_t(); if (!t || t==T_UNDEFINED) { LOG(L_CRIT, "BUG:tm:w_t_relay: undefined T\n"); return -1; } if (t_forward_nonack( t, p_msg, (struct proxy_l *)proxy)<=0 ) { LOG(L_ERR, "ERROR:tm:w_t_relay: t_forward_nonack failed\n"); return -1; } return 1; } if (route_type==REQUEST_ROUTE) { return t_relay_to( p_msg, (struct proxy_l *)proxy, 0 /* no replication */ ); } LOG(L_CRIT, "ERROR:tm:w_t_relay: unsupported route type: %d\n", route_type); return 0;}/* item functions */static int it_get_tm_branch_idx(struct sip_msg *msg, xl_value_t *res, xl_param_t *param, int flags){ extern int _tm_branch_index; int l = 0; char *ch = NULL; if(msg==NULL || res==NULL) return -1; ch = int2str(_tm_branch_index, &l); res->rs.s = ch; res->rs.len = l; res->ri = _tm_branch_index; res->flags = XL_VAL_STR|XL_VAL_INT|XL_TYPE_INT; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -