2
0

tmx_mod.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. /**
  2. * $Id$
  3. *
  4. * Copyright (C) 2009
  5. *
  6. * This file is part of SIP-Router.org, a free SIP server.
  7. *
  8. * SIP-Router is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include "../../sr_module.h"
  26. #include "../../dprint.h"
  27. #include "../../mod_fix.h"
  28. #include "../../route.h"
  29. #include "../../script_cb.h"
  30. #include "../../modules/tm/tm_load.h"
  31. #include "../../lib/kcore/kstats_wrapper.h"
  32. #include "../../dset.h"
  33. #include "t_var.h"
  34. #include "t_mi.h"
  35. #include "tmx_pretran.h"
  36. #include "api.h"
  37. MODULE_VERSION
  38. /** TM bind */
  39. struct tm_binds _tmx_tmb;
  40. /** parameters */
  41. /** module functions */
  42. static int mod_init(void);
  43. static int child_init(int rank);
  44. static void destroy(void);
  45. static int t_cancel_branches(struct sip_msg* msg, char *k, char *s2);
  46. static int fixup_cancel_branches(void** param, int param_no);
  47. static int w_t_cancel_callid_3(struct sip_msg* msg, char *cid, char *cseq,
  48. char *flag);
  49. static int w_t_cancel_callid_4(struct sip_msg* msg, char *cid, char *cseq,
  50. char *flag, char *creason);
  51. static int fixup_cancel_callid(void** param, int param_no);
  52. static int t_reply_callid(struct sip_msg* msg, char *cid, char *cseq,
  53. char *rc, char *rs);
  54. static int fixup_reply_callid(void** param, int param_no);
  55. static int t_flush_flags(struct sip_msg* msg, char*, char* );
  56. static int t_is_failure_route(struct sip_msg* msg, char*, char* );
  57. static int t_is_branch_route(struct sip_msg* msg, char*, char* );
  58. static int t_is_reply_route(struct sip_msg* msg, char*, char*);
  59. static int w_t_suspend(struct sip_msg* msg, char*, char*);
  60. static int w_t_continue(struct sip_msg* msg, char *idx, char *lbl, char *rtn);
  61. static int w_t_reuse_branch(struct sip_msg* msg, char*, char*);
  62. static int fixup_t_continue(void** param, int param_no);
  63. static int w_t_precheck_trans(sip_msg_t*, char*, char*);
  64. static int tmx_cfg_callback(sip_msg_t *msg, unsigned int flags, void *cbp);
  65. static int bind_tmx(tmx_api_t* api);
  66. static int _tmx_precheck_trans = 1;
  67. /* statistic variables */
  68. stat_var *tm_rcv_rpls;
  69. stat_var *tm_rld_rpls;
  70. stat_var *tm_loc_rpls;
  71. stat_var *tm_uas_trans;
  72. stat_var *tm_uac_trans;
  73. stat_var *tm_trans_2xx;
  74. stat_var *tm_trans_3xx;
  75. stat_var *tm_trans_4xx;
  76. stat_var *tm_trans_5xx;
  77. stat_var *tm_trans_6xx;
  78. stat_var *tm_trans_inuse;
  79. #ifdef STATISTICS
  80. unsigned long tmx_stats_uas_trans(void);
  81. unsigned long tmx_stats_uac_trans(void);
  82. unsigned long tmx_stats_trans_2xx(void);
  83. unsigned long tmx_stats_trans_3xx(void);
  84. unsigned long tmx_stats_trans_4xx(void);
  85. unsigned long tmx_stats_trans_5xx(void);
  86. unsigned long tmx_stats_trans_6xx(void);
  87. unsigned long tmx_stats_trans_inuse(void);
  88. unsigned long tmx_stats_trans_active(void);
  89. unsigned long tmx_stats_rcv_rpls(void);
  90. unsigned long tmx_stats_rld_rpls(void);
  91. unsigned long tmx_stats_loc_rpls(void);
  92. static stat_export_t mod_stats[] = {
  93. {"UAS_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_uas_trans },
  94. {"UAC_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_uac_trans },
  95. {"2xx_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_2xx },
  96. {"3xx_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_3xx },
  97. {"4xx_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_4xx },
  98. {"5xx_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_5xx },
  99. {"6xx_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_6xx },
  100. {"inuse_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_inuse },
  101. {"active_transactions" , STAT_IS_FUNC, (stat_var**)tmx_stats_trans_active},
  102. {"received_replies" , STAT_IS_FUNC, (stat_var**)tmx_stats_rcv_rpls },
  103. {"relayed_replies" , STAT_IS_FUNC, (stat_var**)tmx_stats_rld_rpls },
  104. {"local_replies" , STAT_IS_FUNC, (stat_var**)tmx_stats_loc_rpls },
  105. {0,0,0}
  106. };
  107. #endif
  108. /**
  109. * pseudo-variables exported by TM module
  110. */
  111. static pv_export_t mod_pvs[] = {
  112. { {"T_branch_idx", sizeof("T_branch_idx")-1}, PVT_OTHER,
  113. pv_get_tm_branch_idx, 0,
  114. 0, 0, 0, 0 },
  115. { {"T_reply_ruid", sizeof("T_reply_ruid")-1}, PVT_OTHER,
  116. pv_get_tm_reply_ruid, 0,
  117. 0, 0, 0, 0 },
  118. { {"T_reply_code", sizeof("T_reply_code")-1}, PVT_OTHER,
  119. pv_get_tm_reply_code, 0,
  120. 0, 0, 0, 0 },
  121. { {"T_reply_reason", sizeof("T_reply_reason")-1}, PVT_OTHER,
  122. pv_get_tm_reply_reason, 0,
  123. 0, 0, 0, 0 },
  124. { {"T_reply_last", sizeof("T_reply_last")-1}, PVT_OTHER,
  125. pv_get_tm_reply_last_received, 0,
  126. 0, 0, 0, 0 },
  127. { {"T_inv", sizeof("T_inv")-1}, PVT_OTHER, pv_get_t_var_inv, 0,
  128. pv_parse_t_var_name, 0, 0, 0 },
  129. { {"T_req", sizeof("T_req")-1}, PVT_OTHER, pv_get_t_var_req, 0,
  130. pv_parse_t_var_name, 0, 0, 0 },
  131. { {"T_rpl", sizeof("T_rpl")-1}, PVT_OTHER, pv_get_t_var_rpl, 0,
  132. pv_parse_t_var_name, 0, 0, 0 },
  133. { {"T", sizeof("T")-1}, PVT_OTHER, pv_get_t, 0,
  134. pv_parse_t_name, 0, 0, 0 },
  135. { {"T_branch", sizeof("T_branch")-1}, PVT_OTHER, pv_get_t_branch, 0,
  136. pv_parse_t_name, 0, 0, 0 },
  137. { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
  138. };
  139. static mi_export_t mi_cmds [] = {
  140. {MI_TM_UAC, mi_tm_uac_dlg, MI_ASYNC_RPL_FLAG, 0, 0 },
  141. {MI_TM_CANCEL, mi_tm_cancel, 0, 0, 0 },
  142. {MI_TM_HASH, mi_tm_hash, MI_NO_INPUT_FLAG, 0, 0 },
  143. {MI_TM_REPLY, mi_tm_reply, 0, 0, 0 },
  144. {MI_TM_REPLY_CALLID, mi_tm_reply_callid, 0, 0, 0 },
  145. {0,0,0,0,0}
  146. };
  147. static cmd_export_t cmds[]={
  148. {"t_cancel_branches", (cmd_function)t_cancel_branches, 1,
  149. fixup_cancel_branches, 0, ONREPLY_ROUTE },
  150. {"t_cancel_callid", (cmd_function)w_t_cancel_callid_3, 3,
  151. fixup_cancel_callid, 0, ANY_ROUTE },
  152. {"t_cancel_callid", (cmd_function)w_t_cancel_callid_4, 4,
  153. fixup_cancel_callid, 0, ANY_ROUTE },
  154. {"t_reply_callid", (cmd_function)t_reply_callid, 4,
  155. fixup_reply_callid, 0, ANY_ROUTE },
  156. {"t_flush_flags", (cmd_function)t_flush_flags, 0, 0,
  157. 0, ANY_ROUTE },
  158. {"t_is_failure_route", (cmd_function)t_is_failure_route, 0, 0,
  159. 0, ANY_ROUTE },
  160. {"t_is_branch_route", (cmd_function)t_is_branch_route, 0, 0,
  161. 0, ANY_ROUTE },
  162. {"t_is_reply_route", (cmd_function)t_is_reply_route, 0, 0,
  163. 0, ANY_ROUTE },
  164. {"t_suspend", (cmd_function)w_t_suspend, 0, 0,
  165. 0, ANY_ROUTE },
  166. {"t_continue", (cmd_function)w_t_continue, 3,
  167. fixup_t_continue, 0, ANY_ROUTE },
  168. {"t_reuse_branch", (cmd_function)w_t_reuse_branch, 0, 0, 0,
  169. EVENT_ROUTE },
  170. {"t_precheck_trans", (cmd_function)w_t_precheck_trans, 0, 0, 0,
  171. REQUEST_ROUTE },
  172. {"bind_tmx", (cmd_function)bind_tmx, 1,
  173. 0, 0, ANY_ROUTE },
  174. {0,0,0,0,0,0}
  175. };
  176. static param_export_t params[]={
  177. {"precheck_trans", PARAM_INT, &_tmx_precheck_trans},
  178. {0,0,0}
  179. };
  180. /** module exports */
  181. struct module_exports exports= {
  182. "tmx",
  183. DEFAULT_DLFLAGS, /* dlopen flags */
  184. cmds,
  185. params,
  186. #ifdef STATISTICS
  187. mod_stats, /* exported statistics */
  188. #else
  189. 0,
  190. #endif
  191. mi_cmds, /* exported MI functions */
  192. mod_pvs, /* exported pseudo-variables */
  193. 0, /* extra processes */
  194. mod_init, /* module initialization function */
  195. 0,
  196. (destroy_function) destroy,
  197. child_init /* per-child init function */
  198. };
  199. /**
  200. * init module function
  201. */
  202. static int mod_init(void)
  203. {
  204. /* load the TM API */
  205. if (load_tm_api(&_tmx_tmb)!=0) {
  206. LM_ERR("can't load TM API\n");
  207. return -1;
  208. }
  209. if(register_mi_mod(exports.name, mi_cmds)!=0)
  210. {
  211. LM_ERR("failed to register MI commands\n");
  212. return -1;
  213. }
  214. #ifdef STATISTICS
  215. /* register statistics */
  216. if (register_module_stats( exports.name, mod_stats)!=0 ) {
  217. LM_ERR("failed to register statistics\n");
  218. return -1;
  219. }
  220. #endif
  221. pv_tmx_data_init();
  222. if (register_script_cb(tmx_cfg_callback,
  223. POST_SCRIPT_CB|REQUEST_CB,0)<0) {
  224. LM_ERR("cannot register post-script callback\n");
  225. return -1;
  226. }
  227. return 0;
  228. }
  229. /**
  230. * child init function
  231. */
  232. static int child_init(int rank)
  233. {
  234. LM_DBG("rank is (%d)\n", rank);
  235. if (rank==PROC_INIT) {
  236. if(_tmx_precheck_trans!=0)
  237. return tmx_init_pretran_table();
  238. }
  239. return 0;
  240. }
  241. /**
  242. * destroy function
  243. */
  244. static void destroy(void)
  245. {
  246. return;
  247. }
  248. /**
  249. *
  250. */
  251. static int fixup_cancel_branches(void** param, int param_no)
  252. {
  253. char *val;
  254. int n = 0;
  255. if (param_no==1) {
  256. val = (char*)*param;
  257. if (strcasecmp(val,"all")==0) {
  258. n = 0;
  259. } else if (strcasecmp(val,"others")==0) {
  260. n = 1;
  261. } else if (strcasecmp(val,"this")==0) {
  262. n = 2;
  263. } else {
  264. LM_ERR("invalid param \"%s\"\n", val);
  265. return E_CFG;
  266. }
  267. pkg_free(*param);
  268. *param=(void*)(long)n;
  269. } else {
  270. LM_ERR("called with parameter != 1\n");
  271. return E_BUG;
  272. }
  273. return 0;
  274. }
  275. /**
  276. *
  277. */
  278. static int t_cancel_branches(struct sip_msg* msg, char *k, char *s2)
  279. {
  280. struct cancel_info cancel_data;
  281. struct cell *t = 0;
  282. tm_ctx_t *tcx = 0;
  283. int n=0;
  284. int idx = 0;
  285. t=_tmx_tmb.t_gett();
  286. if (t==NULL || t==T_UNDEFINED || !is_invite(t))
  287. return -1;
  288. tcx = _tmx_tmb.tm_ctx_get();
  289. if(tcx != NULL)
  290. idx = tcx->branch_index;
  291. n = (int)(long)k;
  292. init_cancel_info(&cancel_data);
  293. switch(n) {
  294. case 1:
  295. /* prepare cancel for every branch except idx */
  296. _tmx_tmb.prepare_to_cancel(t,
  297. &cancel_data.cancel_bitmap, 1<<idx);
  298. case 2:
  299. if(msg->first_line.u.reply.statuscode>=200)
  300. break;
  301. cancel_data.cancel_bitmap = 1<<idx;
  302. break;
  303. default:
  304. if (msg->first_line.u.reply.statuscode>=200)
  305. /* prepare cancel for every branch except idx */
  306. _tmx_tmb.prepare_to_cancel(t,
  307. &cancel_data.cancel_bitmap, 1<<idx);
  308. else
  309. _tmx_tmb.prepare_to_cancel(t,
  310. &cancel_data.cancel_bitmap, 0);
  311. }
  312. LM_DBG("canceling %d/%d\n", n, (int)cancel_data.cancel_bitmap);
  313. if(cancel_data.cancel_bitmap==0)
  314. return -1;
  315. _tmx_tmb.cancel_uacs(t, &cancel_data, 0);
  316. return 1;
  317. }
  318. /**
  319. *
  320. */
  321. static int fixup_cancel_callid(void** param, int param_no)
  322. {
  323. if (param_no==1 || param_no==2) {
  324. return fixup_spve_null(param, 1);
  325. }
  326. if (param_no==3) {
  327. return fixup_igp_null(param, 1);
  328. }
  329. return 0;
  330. }
  331. /**
  332. *
  333. */
  334. static int t_cancel_callid(struct sip_msg* msg, char *cid, char *cseq, char *flag, char *creason)
  335. {
  336. struct cell *trans;
  337. struct cell *bkt;
  338. int bkb;
  339. struct cancel_info cancel_data;
  340. str cseq_s;
  341. str callid_s;
  342. int fl;
  343. int rcode;
  344. rcode = 0;
  345. fl = -1;
  346. if(fixup_get_svalue(msg, (gparam_p)cid, &callid_s)<0)
  347. {
  348. LM_ERR("cannot get callid\n");
  349. return -1;
  350. }
  351. if(fixup_get_svalue(msg, (gparam_p)cseq, &cseq_s)<0)
  352. {
  353. LM_ERR("cannot get cseq\n");
  354. return -1;
  355. }
  356. if(fixup_get_ivalue(msg, (gparam_p)flag, &fl)<0)
  357. {
  358. LM_ERR("cannot get flag\n");
  359. return -1;
  360. }
  361. if(creason!=NULL && fixup_get_ivalue(msg, (gparam_p)creason, &rcode)<0)
  362. {
  363. LM_ERR("cannot get flag\n");
  364. return -1;
  365. }
  366. if(rcode<100 || rcode>699)
  367. rcode = 0;
  368. bkt = _tmx_tmb.t_gett();
  369. bkb = _tmx_tmb.t_gett_branch();
  370. if( _tmx_tmb.t_lookup_callid(&trans, callid_s, cseq_s) < 0 ) {
  371. DBG("Lookup failed - no transaction\n");
  372. return -1;
  373. }
  374. DBG("Now calling cancel_uacs\n");
  375. if(trans->uas.request && fl>0 && fl<32)
  376. setflag(trans->uas.request, fl);
  377. init_cancel_info(&cancel_data);
  378. cancel_data.reason.cause = rcode;
  379. cancel_data.cancel_bitmap = 0;
  380. _tmx_tmb.prepare_to_cancel(trans, &cancel_data.cancel_bitmap, 0);
  381. _tmx_tmb.cancel_uacs(trans, &cancel_data, 0);
  382. //_tmx_tmb.unref_cell(trans);
  383. _tmx_tmb.t_sett(bkt, bkb);
  384. return 1;
  385. }
  386. /**
  387. *
  388. */
  389. static int w_t_cancel_callid_3(struct sip_msg* msg, char *cid, char *cseq, char *flag)
  390. {
  391. return t_cancel_callid(msg, cid, cseq, flag, NULL);
  392. }
  393. /**
  394. *
  395. */
  396. static int w_t_cancel_callid_4(struct sip_msg* msg, char *cid, char *cseq, char *flag, char *creason)
  397. {
  398. return t_cancel_callid(msg, cid, cseq, flag, creason);
  399. }
  400. /**
  401. *
  402. */
  403. static int fixup_reply_callid(void** param, int param_no)
  404. {
  405. if (param_no==1 || param_no==2 || param_no==4) {
  406. return fixup_spve_null(param, 1);
  407. }
  408. if (param_no==3 || param_no==4) {
  409. return fixup_igp_null(param, 1);
  410. }
  411. return 0;
  412. }
  413. /**
  414. *
  415. */
  416. static int t_reply_callid(struct sip_msg* msg, char *cid, char *cseq,
  417. char *rc, char *rs)
  418. {
  419. struct cell *trans;
  420. str cseq_s;
  421. str callid_s;
  422. str status_s;
  423. unsigned int code;
  424. if(fixup_get_svalue(msg, (gparam_p)cid, &callid_s)<0)
  425. {
  426. LM_ERR("cannot get callid\n");
  427. return -1;
  428. }
  429. if(fixup_get_svalue(msg, (gparam_p)cseq, &cseq_s)<0)
  430. {
  431. LM_ERR("cannot get cseq\n");
  432. return -1;
  433. }
  434. if(fixup_get_ivalue(msg, (gparam_p)rc, (int*)&code)<0)
  435. {
  436. LM_ERR("cannot get reply code\n");
  437. return -1;
  438. }
  439. if(fixup_get_svalue(msg, (gparam_p)rs, &status_s)<0)
  440. {
  441. LM_ERR("cannot get reply status\n");
  442. return -1;
  443. }
  444. if(_tmx_tmb.t_lookup_callid(&trans, callid_s, cseq_s) < 0 )
  445. {
  446. DBG("Lookup failed - no transaction\n");
  447. return -1;
  448. }
  449. DBG("Now calling internal replay\n");
  450. if(_tmx_tmb.t_reply_trans(trans, trans->uas.request, code, status_s.s)>0)
  451. return 1;
  452. return -1;
  453. }
  454. /**
  455. *
  456. */
  457. static int t_flush_flags(struct sip_msg* msg, char *foo, char *bar)
  458. {
  459. struct cell *t;
  460. t=_tmx_tmb.t_gett();
  461. if ( t==0 || t==T_UNDEFINED) {
  462. LM_ERR("failed to flush flags - no transaction found\n");
  463. return -1;
  464. }
  465. t->uas.request->flags = msg->flags;
  466. return 1;
  467. }
  468. /**
  469. *
  470. */
  471. static int t_is_failure_route(struct sip_msg* msg, char *foo, char *bar)
  472. {
  473. if(route_type==FAILURE_ROUTE)
  474. return 1;
  475. return -1;
  476. }
  477. /**
  478. *
  479. */
  480. static int t_is_branch_route(struct sip_msg* msg, char *foo, char *bar)
  481. {
  482. if(route_type==BRANCH_ROUTE)
  483. return 1;
  484. return -1;
  485. }
  486. /**
  487. *
  488. */
  489. static int t_is_reply_route(struct sip_msg* msg, char *foo, char *bar)
  490. {
  491. if(route_type & ONREPLY_ROUTE)
  492. return 1;
  493. return -1;
  494. }
  495. /**
  496. *
  497. */
  498. static int w_t_suspend(struct sip_msg* msg, char *p1, char *p2)
  499. {
  500. unsigned int tindex;
  501. unsigned int tlabel;
  502. tm_cell_t *t = 0;
  503. t=_tmx_tmb.t_gett();
  504. if (t==NULL || t==T_UNDEFINED)
  505. {
  506. if(_tmx_tmb.t_newtran(msg)<0)
  507. {
  508. LM_ERR("cannot create the transaction\n");
  509. return -1;
  510. }
  511. t = _tmx_tmb.t_gett();
  512. if (t==NULL || t==T_UNDEFINED)
  513. {
  514. LM_ERR("cannot lookup the transaction\n");
  515. return -1;
  516. }
  517. }
  518. if(_tmx_tmb.t_suspend(msg, &tindex, &tlabel)<0)
  519. {
  520. LM_ERR("failed to suppend the processing\n");
  521. return -1;
  522. }
  523. LM_DBG("transaction suspended [%u:%u]\n", tindex, tlabel);
  524. return 1;
  525. }
  526. /**
  527. *
  528. */
  529. static int w_t_continue(struct sip_msg* msg, char *idx, char *lbl, char *rtn)
  530. {
  531. unsigned int tindex;
  532. unsigned int tlabel;
  533. str rtname;
  534. cfg_action_t *act;
  535. int ri;
  536. if(fixup_get_ivalue(msg, (gparam_p)idx, (int*)&tindex)<0)
  537. {
  538. LM_ERR("cannot get transaction index\n");
  539. return -1;
  540. }
  541. if(fixup_get_ivalue(msg, (gparam_p)lbl, (int*)&tlabel)<0)
  542. {
  543. LM_ERR("cannot get transaction label\n");
  544. return -1;
  545. }
  546. if(fixup_get_svalue(msg, (gparam_p)rtn, &rtname)<0)
  547. {
  548. LM_ERR("cannot get route block name\n");
  549. return -1;
  550. }
  551. ri = route_get(&main_rt, rtname.s);
  552. if(ri<0)
  553. {
  554. LM_ERR("unable to find route block [%.*s]\n", rtname.len, rtname.s);
  555. return -1;
  556. }
  557. act = main_rt.rlist[ri];
  558. if(act==NULL)
  559. {
  560. LM_ERR("empty action lists in route block [%.*s]\n",
  561. rtname.len, rtname.s);
  562. return -1;
  563. }
  564. if(_tmx_tmb.t_continue(tindex, tlabel, act)<0)
  565. {
  566. LM_ERR("resuming the processing of transaction [%u:%u] failed\n",
  567. tindex, tlabel);
  568. return -1;
  569. }
  570. return 1;
  571. }
  572. /**
  573. * Creates new "main" branch by making copy of branch-failure branch.
  574. * Currently the following branch attributes are included:
  575. * request-uri, ruid, path, instance, and branch flags.
  576. */
  577. static int w_t_reuse_branch(struct sip_msg* msg, char *p1, char *p2)
  578. {
  579. struct cell *t;
  580. int branch;
  581. if (msg == NULL) return -1;
  582. /* first get the transaction */
  583. if (_tmx_tmb.t_check(msg, 0) == -1) return -1;
  584. if ((t = _tmx_tmb.t_gett()) == 0) {
  585. LM_ERR("no transaction\n");
  586. return -1;
  587. }
  588. switch (get_route_type()) {
  589. case BRANCH_FAILURE_ROUTE:
  590. /* use the reason of the winning reply */
  591. if ((branch = _tmx_tmb.t_get_picked_branch()) < 0) {
  592. LM_CRIT("no picked branch (%d) for a final response"
  593. " in MODE_ONFAILURE\n", branch);
  594. return -1;
  595. }
  596. rewrite_uri(msg, &(t->uac[branch].uri));
  597. set_ruid(msg, &(t->uac[branch].ruid));
  598. if (t->uac[branch].path.len) {
  599. set_path_vector(msg, &(t->uac[branch].path));
  600. } else {
  601. reset_path_vector(msg);
  602. }
  603. setbflagsval(0, t->uac[branch].branch_flags);
  604. set_instance(msg, &(t->uac[branch].instance));
  605. return 1;
  606. default:
  607. LM_ERR("unsupported route_type %d\n", get_route_type());
  608. return -1;
  609. }
  610. }
  611. /**
  612. *
  613. */
  614. static int fixup_t_continue(void** param, int param_no)
  615. {
  616. if (param_no==1 || param_no==2) {
  617. return fixup_igp_null(param, 1);
  618. }
  619. if (param_no==3) {
  620. return fixup_spve_null(param, 1);
  621. }
  622. return 0;
  623. }
  624. /**
  625. *
  626. */
  627. static int w_t_precheck_trans(sip_msg_t *msg, char *p1, char *p2)
  628. {
  629. int ret;
  630. ret = tmx_check_pretran(msg);
  631. if(ret>0)
  632. return 1;
  633. return (ret-1);
  634. }
  635. /**
  636. *
  637. */
  638. static int tmx_cfg_callback(sip_msg_t *msg, unsigned int flags, void *cbp)
  639. {
  640. if(flags&POST_SCRIPT_CB) {
  641. tmx_pretran_unlink();
  642. }
  643. return 1;
  644. }
  645. static int bind_tmx(tmx_api_t* api)
  646. {
  647. if (!api)
  648. return -1;
  649. api->t_suspend = w_t_suspend;
  650. return 0;
  651. }
  652. #ifdef STATISTICS
  653. /*** tm stats ***/
  654. static struct t_proc_stats _tmx_stats_all;
  655. static ticks_t _tmx_stats_tm = 0;
  656. void tmx_stats_update(void)
  657. {
  658. ticks_t t;
  659. t = get_ticks();
  660. if(t>_tmx_stats_tm+1) {
  661. _tmx_tmb.get_stats(&_tmx_stats_all);
  662. _tmx_stats_tm = t;
  663. }
  664. }
  665. unsigned long tmx_stats_uas_trans(void)
  666. {
  667. tmx_stats_update();
  668. return _tmx_stats_all.transactions;
  669. }
  670. unsigned long tmx_stats_uac_trans(void)
  671. {
  672. tmx_stats_update();
  673. return _tmx_stats_all.client_transactions;
  674. }
  675. unsigned long tmx_stats_trans_2xx(void)
  676. {
  677. tmx_stats_update();
  678. return _tmx_stats_all.completed_2xx;
  679. }
  680. unsigned long tmx_stats_trans_3xx(void)
  681. {
  682. tmx_stats_update();
  683. return _tmx_stats_all.completed_3xx;
  684. }
  685. unsigned long tmx_stats_trans_4xx(void)
  686. {
  687. tmx_stats_update();
  688. return _tmx_stats_all.completed_4xx;
  689. }
  690. unsigned long tmx_stats_trans_5xx(void)
  691. {
  692. tmx_stats_update();
  693. return _tmx_stats_all.completed_5xx;
  694. }
  695. unsigned long tmx_stats_trans_6xx(void)
  696. {
  697. tmx_stats_update();
  698. return _tmx_stats_all.completed_6xx;
  699. }
  700. unsigned long tmx_stats_trans_inuse(void)
  701. {
  702. tmx_stats_update();
  703. return (_tmx_stats_all.transactions - _tmx_stats_all.deleted);
  704. }
  705. unsigned long tmx_stats_trans_active(void)
  706. {
  707. tmx_stats_update();
  708. return (_tmx_stats_all.transactions - _tmx_stats_all.waiting);
  709. }
  710. unsigned long tmx_stats_rcv_rpls(void)
  711. {
  712. tmx_stats_update();
  713. return _tmx_stats_all.completed_6xx
  714. + _tmx_stats_all.completed_5xx
  715. + _tmx_stats_all.completed_4xx
  716. + _tmx_stats_all.completed_3xx
  717. + _tmx_stats_all.completed_2xx;
  718. }
  719. unsigned long tmx_stats_rld_rpls(void)
  720. {
  721. tmx_stats_update();
  722. return _tmx_stats_all.completed_6xx
  723. + _tmx_stats_all.completed_5xx
  724. + _tmx_stats_all.completed_4xx
  725. + _tmx_stats_all.completed_3xx
  726. + _tmx_stats_all.completed_2xx
  727. - _tmx_stats_all.replied_locally;
  728. }
  729. unsigned long tmx_stats_loc_rpls(void)
  730. {
  731. tmx_stats_update();
  732. return _tmx_stats_all.replied_locally;
  733. }
  734. #endif