00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
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
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
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
00117 static int mod_init(void);
00118 static int child_init(int rank);
00119
00120
00121
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
00140 static char *fr_timer_param = NULL;
00141 static char *fr_inv_timer_param = NULL;
00142 static char *contacts_avp_param = NULL;
00143
00144
00145 int tm_enable_stats = 1;
00146 str auto_inv_100_reason = str_init("Giving a Try");
00147
00148
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
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",
00303 DEFAULT_DLFLAGS,
00304 cmds,
00305 params,
00306 mod_stats,
00307 mi_cmds,
00308 mod_items,
00309 0,
00310 mod_init,
00311 (response_function) reply_received,
00312 (destroy_function) tm_shutdown,
00313 child_init
00314 };
00315
00316
00317
00318
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
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
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
00401 *((void**)(((char*)param)+sizeof(action_elem_t))) = *param;
00402 *param = 0;
00403 return 0;
00404 } else if (fixup_phostport2proxy( param, 1)==0 ) {
00405
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
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
00482 pkg_free(*param);
00483
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
00495 int load_tm( struct tm_binds *tmb)
00496 {
00497 tmb->register_tmcb = register_tmcb;
00498
00499
00500 tmb->t_relay = (cmd_function)w_t_relay;
00501
00502 tmb->t_reply = (treply_f)w_t_reply;
00503 tmb->t_reply_with_body = t_reply_with_body;
00504
00505
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
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
00555
00556
00557
00558
00559
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
00568 reset_kr();
00569 return 1;
00570 }
00571
00572
00573 static int mod_init(void)
00574 {
00575
00576
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
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
00593 if (!init_hash_table()) {
00594 LM_ERR("initializing hash_table failed\n");
00595 return -1;
00596 }
00597
00598
00599 init_t();
00600
00601 if (!tm_init_timers()) {
00602 LM_ERR("timer init failed\n");
00603 return -1;
00604 }
00605
00606
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
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
00652 auto_inv_100_reason.len = strlen(auto_inv_100_reason.s);
00653
00654
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
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
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
00697 status = int2str( t->uas.status, 0);
00698 break;
00699 case ONREPLY_ROUTE:
00700
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
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
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
00747 if (check_transaction_quadruple(msg)==0) {
00748 LM_ERR("too few headers\n");
00749 return 0;
00750 }
00751 if (!msg->hash_index)
00752 msg->hash_index = tm_hash(msg->callid->body,get_cseq(msg)->number);
00753
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
00765 if (msg->REQ_METHOD==METHOD_ACK)
00766 return 1;
00767
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
00776 return 1;
00777 default:
00778
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
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
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
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
00824 case 1:
00825 if (route_type==FAILURE_ROUTE) {
00826
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
00838 case 2:
00839 if (route_type==FAILURE_ROUTE) {
00840
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
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
00887
00888
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
00942
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
00981 return -2;
00982 case E_NO_DESTINATION:
00983
00984 return -3;
00985 case E_BAD_ADDRESS:
00986
00987 return -4;
00988 case E_IP_BLOCKED:
00989
00990 return -5;
00991 case E_NO_SOCKET:
00992 case E_SEND:
00993
00994 return -6;
00995 default:
00996
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
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
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
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
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
01083 if (t_check( msg , 0 )==-1) return -1;
01084 if ( (t=get_t())==0) {
01085
01086 code = 0;
01087 } else {
01088 switch (route_type) {
01089 case REQUEST_ROUTE:
01090
01091 code = t->uas.status;
01092 break;
01093 case ONREPLY_ROUTE:
01094
01095 code = msg->first_line.u.reply.statuscode;
01096 break;
01097 case FAILURE_ROUTE:
01098
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