t_var.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. /**
  2. * $Id$
  3. *
  4. * Copyright (C) 2008 Elena-Ramona Modroiu (asipto.com)
  5. *
  6. * This file is part of kamailio, a free SIP server.
  7. *
  8. * Kamailio 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 "../../mem/mem.h"
  23. #include "../../dset.h"
  24. #include "tmx_mod.h"
  25. #include "t_var.h"
  26. struct _pv_tmx_data {
  27. struct cell *T;
  28. struct sip_msg msg;
  29. struct sip_msg *tmsgp;
  30. unsigned int id;
  31. char *buf;
  32. int buf_size;
  33. };
  34. static struct _pv_tmx_data _pv_treq;
  35. static struct _pv_tmx_data _pv_trpl;
  36. static struct _pv_tmx_data _pv_tinv;
  37. static str _empty_str = {"", 0};
  38. void pv_tmx_data_init(void)
  39. {
  40. memset(&_pv_treq, 0, sizeof(struct _pv_tmx_data));
  41. memset(&_pv_trpl, 0, sizeof(struct _pv_tmx_data));
  42. memset(&_pv_tinv, 0, sizeof(struct _pv_tmx_data));
  43. }
  44. int pv_t_copy_msg(struct sip_msg *src, struct sip_msg *dst)
  45. {
  46. dst->id = src->id;
  47. dst->rcv = src->rcv;
  48. dst->set_global_address=src->set_global_address;
  49. dst->set_global_port=src->set_global_port;
  50. dst->flags = src->flags;
  51. dst->fwd_send_flags = src->fwd_send_flags;
  52. dst->rpl_send_flags = src->rpl_send_flags;
  53. dst->force_send_socket = src->force_send_socket;
  54. if (parse_msg(dst->buf, dst->len, dst)!=0)
  55. {
  56. LM_ERR("parse msg failed\n");
  57. return -1;
  58. }
  59. return 0;
  60. }
  61. int pv_t_update_req(struct sip_msg *msg)
  62. {
  63. struct cell * t;
  64. int branch;
  65. if(msg==NULL)
  66. return 1;
  67. if(msg!=FAKED_REPLY && msg->first_line.type!=SIP_REPLY)
  68. return 1;
  69. t = _tmx_tmb.t_gett();
  70. if(t==NULL || t==T_UNDEFINED)
  71. {
  72. if(msg==FAKED_REPLY)
  73. return 1;
  74. branch=-1;
  75. if (_tmx_tmb.t_check(msg, &branch ) == -1)
  76. return 1;
  77. t = _tmx_tmb.t_gett();
  78. if ((t == 0) || (t == T_UNDEFINED))
  79. return 1;
  80. }
  81. if(t->uas.request==NULL)
  82. return 1;
  83. if(_pv_treq.T==t && t->uas.request==_pv_treq.tmsgp
  84. && t->uas.request->id==_pv_treq.id)
  85. return 0;
  86. /* make a copy */
  87. if(_pv_treq.buf==NULL || _pv_treq.buf_size<t->uas.request->len+1)
  88. {
  89. if(_pv_treq.buf!=NULL)
  90. pkg_free(_pv_treq.buf);
  91. if(_pv_treq.tmsgp)
  92. free_sip_msg(&_pv_treq.msg);
  93. _pv_treq.tmsgp = NULL;
  94. _pv_treq.id = 0;
  95. _pv_treq.T = NULL;
  96. _pv_treq.buf_size = t->uas.request->len+1;
  97. _pv_treq.buf = (char*)pkg_malloc(_pv_treq.buf_size*sizeof(char));
  98. if(_pv_treq.buf==NULL)
  99. {
  100. LM_ERR("no more pkg\n");
  101. _pv_treq.buf_size = 0;
  102. return -1;
  103. }
  104. }
  105. if(_pv_treq.tmsgp)
  106. free_sip_msg(&_pv_treq.msg);
  107. memset(&_pv_treq.msg, 0, sizeof(struct sip_msg));
  108. memcpy(_pv_treq.buf, t->uas.request->buf, t->uas.request->len);
  109. _pv_treq.buf[t->uas.request->len] = '\0';
  110. _pv_treq.msg.len = t->uas.request->len;
  111. _pv_treq.msg.buf = _pv_treq.buf;
  112. _pv_treq.tmsgp = t->uas.request;
  113. _pv_treq.id = t->uas.request->id;
  114. _pv_treq.T = t;
  115. if(pv_t_copy_msg(t->uas.request, &_pv_treq.msg)!=0)
  116. {
  117. pkg_free(_pv_treq.buf);
  118. _pv_treq.buf_size = 0;
  119. _pv_treq.buf = NULL;
  120. _pv_treq.tmsgp = NULL;
  121. _pv_treq.T = NULL;
  122. return -1;
  123. }
  124. return 0;
  125. }
  126. int pv_t_update_rpl(struct sip_msg *msg)
  127. {
  128. struct cell * t;
  129. int branch;
  130. int cancel;
  131. if(msg==NULL)
  132. return 1;
  133. if(msg==FAKED_REPLY || msg->first_line.type!=SIP_REQUEST)
  134. return 1;
  135. t = _tmx_tmb.t_gett();
  136. if(t==NULL || t==T_UNDEFINED)
  137. {
  138. if(_tmx_tmb.t_lookup_request(msg, 0, &cancel)<=0)
  139. return 1;
  140. t = _tmx_tmb.t_gett();
  141. if(t==NULL || t==T_UNDEFINED)
  142. return 1;
  143. }
  144. if ( (branch=_tmx_tmb.t_get_picked_branch())<0 )
  145. return 1;
  146. if(t->uac[branch].reply==NULL || t->uac[branch].reply==FAKED_REPLY)
  147. return 1;
  148. if(_pv_trpl.T==t && t->uac[branch].reply==_pv_trpl.tmsgp
  149. && t->uac[branch].reply->id==_pv_trpl.id)
  150. return 0;
  151. /* make a copy */
  152. if(_pv_trpl.buf==NULL || _pv_trpl.buf_size<t->uac[branch].reply->len+1)
  153. {
  154. if(_pv_trpl.buf!=NULL)
  155. pkg_free(_pv_trpl.buf);
  156. if(_pv_trpl.tmsgp)
  157. free_sip_msg(&_pv_trpl.msg);
  158. _pv_trpl.tmsgp = NULL;
  159. _pv_trpl.id = 0;
  160. _pv_trpl.T = NULL;
  161. _pv_trpl.buf_size = t->uac[branch].reply->len+1;
  162. _pv_trpl.buf = (char*)pkg_malloc(_pv_trpl.buf_size*sizeof(char));
  163. if(_pv_trpl.buf==NULL)
  164. {
  165. LM_ERR("no more pkg\n");
  166. _pv_trpl.buf_size = 0;
  167. return -1;
  168. }
  169. }
  170. if(_pv_trpl.tmsgp)
  171. free_sip_msg(&_pv_trpl.msg);
  172. memset(&_pv_trpl.msg, 0, sizeof(struct sip_msg));
  173. memcpy(_pv_trpl.buf, t->uac[branch].reply->buf, t->uac[branch].reply->len);
  174. _pv_trpl.buf[t->uac[branch].reply->len] = '\0';
  175. _pv_trpl.msg.len = t->uac[branch].reply->len;
  176. _pv_trpl.msg.buf = _pv_trpl.buf;
  177. _pv_trpl.tmsgp = t->uac[branch].reply;
  178. _pv_trpl.id = t->uac[branch].reply->id;
  179. _pv_trpl.T = t;
  180. if(pv_t_copy_msg(t->uac[branch].reply, &_pv_trpl.msg)!=0)
  181. {
  182. pkg_free(_pv_trpl.buf);
  183. _pv_trpl.buf_size = 0;
  184. _pv_trpl.buf = NULL;
  185. _pv_trpl.tmsgp = NULL;
  186. _pv_trpl.T = NULL;
  187. return -1;
  188. }
  189. return 0;
  190. }
  191. int pv_t_update_inv(struct sip_msg *msg)
  192. {
  193. struct cell * t;
  194. if(msg==NULL)
  195. return 1;
  196. if (msg->REQ_METHOD!=METHOD_CANCEL)
  197. return 1;
  198. t = _tmx_tmb.t_lookup_original(msg);
  199. if(t==NULL || t==T_UNDEFINED)
  200. return 1;
  201. if(t->uas.request==NULL) {
  202. _tmx_tmb.unref_cell(t);
  203. return 1;
  204. }
  205. if(_pv_tinv.T==t && t->uas.request==_pv_tinv.tmsgp
  206. && t->uas.request->id==_pv_tinv.id)
  207. goto done;
  208. /* make a copy */
  209. if(_pv_tinv.buf==NULL || _pv_tinv.buf_size<t->uas.request->len+1)
  210. {
  211. if(_pv_tinv.buf!=NULL)
  212. pkg_free(_pv_tinv.buf);
  213. if(_pv_tinv.tmsgp)
  214. free_sip_msg(&_pv_tinv.msg);
  215. _pv_tinv.tmsgp = NULL;
  216. _pv_tinv.id = 0;
  217. _pv_tinv.T = NULL;
  218. _pv_tinv.buf_size = t->uas.request->len+1;
  219. _pv_tinv.buf = (char*)pkg_malloc(_pv_tinv.buf_size*sizeof(char));
  220. if(_pv_tinv.buf==NULL)
  221. {
  222. LM_ERR("no more pkg\n");
  223. _pv_tinv.buf_size = 0;
  224. goto error;
  225. }
  226. }
  227. if(_pv_tinv.tmsgp)
  228. free_sip_msg(&_pv_tinv.msg);
  229. memset(&_pv_tinv.msg, 0, sizeof(struct sip_msg));
  230. memcpy(_pv_tinv.buf, t->uas.request->buf, t->uas.request->len);
  231. _pv_tinv.buf[t->uas.request->len] = '\0';
  232. _pv_tinv.msg.len = t->uas.request->len;
  233. _pv_tinv.msg.buf = _pv_tinv.buf;
  234. _pv_tinv.tmsgp = t->uas.request;
  235. _pv_tinv.id = t->uas.request->id;
  236. _pv_tinv.T = t;
  237. if(pv_t_copy_msg(t->uas.request, &_pv_tinv.msg)!=0)
  238. {
  239. pkg_free(_pv_tinv.buf);
  240. _pv_tinv.buf_size = 0;
  241. _pv_tinv.buf = NULL;
  242. _pv_tinv.tmsgp = NULL;
  243. _pv_tinv.T = NULL;
  244. goto error;
  245. }
  246. done:
  247. _tmx_tmb.unref_cell(t);
  248. return 0;
  249. error:
  250. _tmx_tmb.unref_cell(t);
  251. return -1;
  252. }
  253. int pv_get_t_var_req(struct sip_msg *msg, pv_param_t *param,
  254. pv_value_t *res)
  255. {
  256. pv_spec_t *pv=NULL;
  257. if(pv_t_update_req(msg))
  258. return pv_get_null(msg, param, res);
  259. pv = (pv_spec_t*)param->pvn.u.dname;
  260. if(pv==NULL || pv_alter_context(pv))
  261. return pv_get_null(msg, param, res);
  262. return pv_get_spec_value(&_pv_treq.msg, pv, res);
  263. }
  264. int pv_get_t_var_rpl(struct sip_msg *msg, pv_param_t *param,
  265. pv_value_t *res)
  266. {
  267. pv_spec_t *pv=NULL;
  268. if(pv_t_update_rpl(msg))
  269. return pv_get_null(msg, param, res);
  270. pv = (pv_spec_t*)param->pvn.u.dname;
  271. if(pv==NULL || pv_alter_context(pv))
  272. return pv_get_null(msg, param, res);
  273. return pv_get_spec_value(&_pv_trpl.msg, pv, res);
  274. }
  275. int pv_get_t_var_branch(struct sip_msg *msg, pv_param_t *param,
  276. pv_value_t *res)
  277. {
  278. pv_spec_t *pv=NULL;
  279. if(pv_t_update_rpl(msg))
  280. return pv_get_null(msg, param, res);
  281. pv = (pv_spec_t*)param->pvn.u.dname;
  282. if(pv==NULL || pv_alter_context(pv))
  283. return pv_get_null(msg, param, res);
  284. return pv_get_spec_value(&_pv_trpl.msg, pv, res);
  285. }
  286. int pv_get_t_var_inv(struct sip_msg *msg, pv_param_t *param,
  287. pv_value_t *res)
  288. {
  289. pv_spec_t *pv=NULL;
  290. if(pv_t_update_inv(msg))
  291. return pv_get_null(msg, param, res);
  292. pv = (pv_spec_t*)param->pvn.u.dname;
  293. if(pv==NULL || pv_alter_context(pv))
  294. return pv_get_null(msg, param, res);
  295. return pv_get_spec_value(&_pv_tinv.msg, pv, res);
  296. }
  297. int pv_parse_t_var_name(pv_spec_p sp, str *in)
  298. {
  299. pv_spec_t *pv=NULL;
  300. if(in->s==NULL || in->len<=0)
  301. return -1;
  302. pv = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t));
  303. if(pv==NULL)
  304. return -1;
  305. memset(pv, 0, sizeof(pv_spec_t));
  306. if(pv_parse_spec(in, pv)==NULL)
  307. goto error;
  308. sp->pvp.pvn.u.dname = (void*)pv;
  309. sp->pvp.pvn.type = PV_NAME_PVAR;
  310. return 0;
  311. error:
  312. LM_ERR("invalid pv name [%.*s]\n", in->len, in->s);
  313. if(pv!=NULL)
  314. pkg_free(pv);
  315. return -1;
  316. }
  317. /* item functions */
  318. int pv_get_tm_branch_idx(struct sip_msg *msg, pv_param_t *param,
  319. pv_value_t *res)
  320. {
  321. int l = 0;
  322. char *ch = NULL;
  323. struct cell *t;
  324. tm_ctx_t *tcx = 0;
  325. int idx = T_BR_UNDEFINED;
  326. if(msg==NULL || res==NULL)
  327. return -1;
  328. /* statefull replies have the branch_index set */
  329. if(msg->first_line.type == SIP_REPLY && route_type != CORE_ONREPLY_ROUTE) {
  330. tcx = _tmx_tmb.tm_ctx_get();
  331. if(tcx != NULL)
  332. idx = tcx->branch_index;
  333. } else switch(route_type) {
  334. case BRANCH_ROUTE:
  335. case BRANCH_FAILURE_ROUTE:
  336. /* branch and branch_failure routes have their index set */
  337. tcx = _tmx_tmb.tm_ctx_get();
  338. if(tcx != NULL)
  339. idx = tcx->branch_index;
  340. break;
  341. case REQUEST_ROUTE:
  342. /* take the branch number from the number of added branches */
  343. idx = nr_branches;
  344. break;
  345. case FAILURE_ROUTE:
  346. /* first get the transaction */
  347. t = _tmx_tmb.t_gett();
  348. if ( t == NULL || t == T_UNDEFINED ) {
  349. return -1;
  350. }
  351. /* add the currently added branches to the number of
  352. * completed branches in the transaction
  353. */
  354. idx = t->nr_of_outgoings + nr_branches;
  355. break;
  356. }
  357. ch = sint2str(idx, &l);
  358. res->rs.s = ch;
  359. res->rs.len = l;
  360. res->ri = idx;
  361. res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
  362. return 0;
  363. }
  364. int pv_get_tm_reply_ruid(struct sip_msg *msg, pv_param_t *param,
  365. pv_value_t *res)
  366. {
  367. struct cell *t;
  368. int branch;
  369. if(msg==NULL || res==NULL)
  370. return -1;
  371. /* first get the transaction */
  372. if (_tmx_tmb.t_check( msg , 0 )==-1) return -1;
  373. if ( (t=_tmx_tmb.t_gett())==0) {
  374. /* no T */
  375. res->rs = _empty_str;
  376. } else {
  377. switch (get_route_type()) {
  378. case FAILURE_ROUTE:
  379. case BRANCH_FAILURE_ROUTE:
  380. /* use the reason of the winning reply */
  381. if ( (branch=_tmx_tmb.t_get_picked_branch())<0 ) {
  382. LM_CRIT("no picked branch (%d) for a final response"
  383. " in MODE_ONFAILURE\n", branch);
  384. return -1;
  385. }
  386. res->rs = t->uac[branch].ruid;
  387. break;
  388. default:
  389. LM_ERR("unsupported route_type %d\n", get_route_type());
  390. return -1;
  391. }
  392. }
  393. LM_DBG("reply ruid is [%.*s]\n", res->rs.len, res->rs.s);
  394. res->flags = PV_VAL_STR;
  395. return 0;
  396. }
  397. int pv_get_tm_reply_code(struct sip_msg *msg, pv_param_t *param,
  398. pv_value_t *res)
  399. {
  400. struct cell *t;
  401. int code;
  402. int branch;
  403. if(msg==NULL || res==NULL)
  404. return -1;
  405. /* first get the transaction */
  406. if (_tmx_tmb.t_check( msg , 0 )==-1) return -1;
  407. if ( (t=_tmx_tmb.t_gett())==0) {
  408. /* no T */
  409. code = 0;
  410. } else {
  411. switch (get_route_type()) {
  412. case REQUEST_ROUTE:
  413. case BRANCH_ROUTE:
  414. /* use the status of the last sent reply */
  415. code = t->uas.status;
  416. break;
  417. case CORE_ONREPLY_ROUTE:
  418. /* t_check() above has the side effect of setting T and
  419. REFerencing T => we must unref and unset it for the
  420. main/core onreply_route. */
  421. _tmx_tmb.t_unref(msg);
  422. /* no break */
  423. case TM_ONREPLY_ROUTE:
  424. /* use the status of the current reply */
  425. code = msg->first_line.u.reply.statuscode;
  426. break;
  427. case FAILURE_ROUTE:
  428. case BRANCH_FAILURE_ROUTE:
  429. /* use the status of the winning reply */
  430. if ( (branch=_tmx_tmb.t_get_picked_branch())<0 ) {
  431. LM_CRIT("no picked branch (%d) for a final response"
  432. " in MODE_ONFAILURE\n", branch);
  433. code = 0;
  434. } else {
  435. code = t->uac[branch].last_received;
  436. }
  437. break;
  438. default:
  439. LM_ERR("unsupported route_type %d\n", get_route_type());
  440. code = 0;
  441. }
  442. }
  443. LM_DBG("reply code is <%d>\n",code);
  444. res->rs.s = int2str( code, &res->rs.len);
  445. res->ri = code;
  446. res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
  447. return 0;
  448. }
  449. int pv_get_tm_reply_reason(struct sip_msg *msg, pv_param_t *param,
  450. pv_value_t *res)
  451. {
  452. struct cell *t;
  453. struct sip_msg *reply;
  454. int branch;
  455. if(msg==NULL || res==NULL)
  456. return -1;
  457. /* first get the transaction */
  458. if (_tmx_tmb.t_check( msg , 0 )==-1) return -1;
  459. if ( (t=_tmx_tmb.t_gett())==0) {
  460. /* no T */
  461. res->rs = _empty_str;
  462. } else {
  463. switch (get_route_type()) {
  464. case CORE_ONREPLY_ROUTE:
  465. /* t_check() above has the side effect of setting T and
  466. REFerencing T => we must unref and unset it for the
  467. main/core onreply_route. */
  468. _tmx_tmb.t_unref(msg);
  469. /* no break */
  470. case TM_ONREPLY_ROUTE:
  471. /* use the reason of the current reply */
  472. res->rs.s = msg->first_line.u.reply.reason.s;
  473. res->rs.len = msg->first_line.u.reply.reason.len;
  474. break;
  475. case FAILURE_ROUTE:
  476. /* use the reason of the winning reply */
  477. if ( (branch=_tmx_tmb.t_get_picked_branch())<0 ) {
  478. LM_CRIT("no picked branch (%d) for a final response"
  479. " in MODE_ONFAILURE\n", branch);
  480. return -1;
  481. }
  482. reply = t->uac[branch].reply;
  483. if (reply == FAKED_REPLY) {
  484. res->rs.s = error_text(t->uac[branch].last_received);
  485. res->rs.len = strlen(res->rs.s);
  486. } else {
  487. res->rs.s = reply->first_line.u.reply.reason.s;
  488. res->rs.len = reply->first_line.u.reply.reason.len;
  489. }
  490. break;
  491. default:
  492. LM_ERR("unsupported route_type %d\n", get_route_type());
  493. return -1;
  494. }
  495. }
  496. LM_DBG("reply reason is [%.*s]\n", res->rs.len, res->rs.s);
  497. res->flags = PV_VAL_STR;
  498. return 0;
  499. }
  500. int pv_get_tm_reply_last_received(struct sip_msg *msg, pv_param_t *param,
  501. pv_value_t *res)
  502. {
  503. struct cell *t;
  504. tm_ctx_t *tcx = 0;
  505. int code;
  506. if(msg==NULL || res==NULL)
  507. return -1;
  508. /* Only for TM reply route */
  509. if (get_route_type() != TM_ONREPLY_ROUTE) {
  510. LM_ERR("unsupported route_type %d\n", get_route_type());
  511. return -1;
  512. }
  513. /* first get the transaction */
  514. if (_tmx_tmb.t_check( msg , 0 )==-1) return -1;
  515. if ( (t=_tmx_tmb.t_gett())==0) {
  516. /* no T */
  517. LM_ERR("could not get transaction\n");
  518. return -1;
  519. }
  520. /* get the current branch index */
  521. tcx = _tmx_tmb.tm_ctx_get();
  522. if(tcx == NULL) {
  523. LM_ERR("could not get tm context\n");
  524. return -1;
  525. }
  526. /* get the last received reply code */
  527. code = t->uac[tcx->branch_index].last_received;
  528. LM_DBG("reply code is <%d>\n",code);
  529. res->rs.s = int2str( code, &res->rs.len);
  530. res->ri = code;
  531. res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
  532. return 0;
  533. }
  534. int pv_parse_t_name(pv_spec_p sp, str *in)
  535. {
  536. if(sp==NULL || in==NULL || in->len<=0)
  537. return -1;
  538. switch(in->len)
  539. {
  540. case 5:
  541. if(strncmp(in->s, "flags", 5) == 0)
  542. sp->pvp.pvn.u.isname.name.n = 5;
  543. else goto error;
  544. break;
  545. case 8:
  546. if(strncmp(in->s, "id_label", 8)==0)
  547. sp->pvp.pvn.u.isname.name.n = 0;
  548. else if(strncmp(in->s, "id_index", 8)==0)
  549. sp->pvp.pvn.u.isname.name.n = 1;
  550. else goto error;
  551. break;
  552. case 10:
  553. if(strncmp(in->s, "reply_code", 10)==0)
  554. sp->pvp.pvn.u.isname.name.n = 2;
  555. else if(strncmp(in->s, "reply_type", 10)==0)
  556. sp->pvp.pvn.u.isname.name.n = 3;
  557. else goto error;
  558. break;
  559. case 12:
  560. if(strncmp(in->s, "branch_index", 12)==0)
  561. sp->pvp.pvn.u.isname.name.n = 4;
  562. else goto error;
  563. break;
  564. default:
  565. goto error;
  566. }
  567. sp->pvp.pvn.type = PV_NAME_INTSTR;
  568. sp->pvp.pvn.u.isname.type = 0;
  569. return 0;
  570. error:
  571. LM_ERR("unknown PV name %.*s\n", in->len, in->s);
  572. return -1;
  573. }
  574. int pv_get_t(struct sip_msg *msg, pv_param_t *param,
  575. pv_value_t *res)
  576. {
  577. tm_cell_t *t;
  578. if(msg==NULL || param==NULL)
  579. return -1;
  580. /* aliases to old TM pvs */
  581. switch(param->pvn.u.isname.name.n)
  582. {
  583. case 2:
  584. return pv_get_tm_reply_code(msg, param, res);
  585. case 4:
  586. return pv_get_tm_branch_idx(msg, param, res);
  587. }
  588. t = _tmx_tmb.t_gett();
  589. if(t==NULL || t==T_UNDEFINED) {
  590. /* no T */
  591. return pv_get_null(msg, param, res);
  592. }
  593. switch(param->pvn.u.isname.name.n)
  594. {
  595. case 1:
  596. return pv_get_uintval(msg, param, res, t->hash_index);
  597. case 3:
  598. if(get_route_type()==FAILURE_ROUTE) {
  599. if(_tmx_tmb.t_get_picked_branch()<0 )
  600. return pv_get_uintval(msg, param, res, 0);
  601. if(t->uac[_tmx_tmb.t_get_picked_branch()].reply==FAKED_REPLY)
  602. return pv_get_uintval(msg, param, res, 1);
  603. }
  604. return pv_get_uintval(msg, param, res, 0);
  605. default:
  606. return pv_get_uintval(msg, param, res, t->label);
  607. }
  608. }
  609. int pv_get_t_branch(struct sip_msg *msg, pv_param_t *param,
  610. pv_value_t *res)
  611. {
  612. tm_cell_t *t;
  613. int branch;
  614. if ((msg == NULL) || (param == NULL)) return -1;
  615. t = _tmx_tmb.t_gett();
  616. if ((t == NULL) || (t == T_UNDEFINED)) {
  617. /* no T */
  618. return pv_get_null(msg, param, res);
  619. }
  620. switch(param->pvn.u.isname.name.n) {
  621. case 5:
  622. switch (get_route_type()) {
  623. case FAILURE_ROUTE:
  624. case BRANCH_FAILURE_ROUTE:
  625. /* use the reason of the winning reply */
  626. if ((branch=_tmx_tmb.t_get_picked_branch()) < 0) {
  627. LM_CRIT("no picked branch (%d) for a final response"
  628. " in MODE_ONFAILURE\n", branch);
  629. return -1;
  630. }
  631. res->ri = t->uac[branch].branch_flags;
  632. res->flags = PV_VAL_INT;
  633. LM_DBG("branch flags is [%u]\n", res->ri);
  634. break;
  635. default:
  636. LM_ERR("unsupported route_type %d\n", get_route_type());
  637. return -1;
  638. }
  639. }
  640. return 0;
  641. }