2
0

t_mi.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. /*
  2. * $Id: mi.c 5299 2008-12-04 18:12:33Z henningw $
  3. *
  4. * Header file for TM MI functions
  5. *
  6. * Copyright (C) 2001-2003 FhG Fokus
  7. * Copyright (C) 2006 Voice Sistem SRL
  8. *
  9. * This file is part of Kamailio, a free SIP server.
  10. *
  11. * Kamailio is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version
  15. *
  16. * Kamailio is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * History:
  26. * --------
  27. * 2006-12-04 created (bogdan)
  28. */
  29. /*! \file
  30. * \brief TM :: MI functions
  31. *
  32. * \ingroup tm
  33. * - Module: \ref tm
  34. */
  35. #include <stdlib.h>
  36. #include "../../parser/parse_from.h"
  37. #include "../../modules/tm/ut.h"
  38. #include "../../lib/kmi/mi.h"
  39. #include "../../str_list.h"
  40. #include "tmx_mod.h"
  41. /*!
  42. * \brief Convert a URI into socket address.
  43. *
  44. * Convert a URI into a socket address. Create a temporary proxy.
  45. * \param uri input URI
  46. * \param to_su target structure
  47. * \param proto protocol
  48. * \return choosen protocol
  49. */
  50. static inline int uri2su(str *uri, union sockaddr_union *to_su, int proto)
  51. {
  52. struct proxy_l *proxy;
  53. proxy = uri2proxy(uri, proto);
  54. if (!proxy) {
  55. ser_error = E_BAD_ADDRESS;
  56. LM_ERR("failed create a dst proxy\n");
  57. return -1;
  58. }
  59. hostent2su(to_su, &proxy->host, proxy->addr_idx,
  60. (proxy->port) ? proxy->port : SIP_PORT);
  61. proto = proxy->proto;
  62. free_proxy(proxy);
  63. pkg_free(proxy);
  64. return proto;
  65. }
  66. /* should be replaced by tm's uri2dst instead */
  67. static inline struct socket_info *uri2sock(struct sip_msg* msg, str *uri,
  68. union sockaddr_union *to_su, int proto)
  69. {
  70. struct socket_info* send_sock;
  71. if ( (proto=uri2su(uri, to_su, proto))==-1 )
  72. return 0;
  73. send_sock = get_send_socket(msg, to_su, proto);
  74. if (!send_sock) {
  75. LM_ERR("no corresponding socket for af %d\n", to_su->s.sa_family);
  76. ser_error = E_NO_SOCKET;
  77. }
  78. return send_sock;
  79. }
  80. /************** Helper functions (from previous FIFO impl) *****************/
  81. /*!
  82. * \brief Check if the request pushed via MI is correctly formed
  83. *
  84. * Check if the request pushed via MI is correctly formed. Test if
  85. * necessary SIP header fileds are included, could be parsed and the
  86. * CSEQ is correct.
  87. * \param msg SIP message
  88. * \param method SIP method
  89. * \param body SIP body
  90. * \param cseq SIP CSEQ value
  91. * \param callid SIP callid, optional
  92. * \return zero on success, or a mi_root with an error message included otherwise
  93. */
  94. static inline struct mi_root* mi_check_msg(struct sip_msg* msg, str* method,
  95. str* body, int* cseq, str* callid)
  96. {
  97. struct cseq_body *parsed_cseq;
  98. if (body && body->len && !msg->content_type)
  99. return init_mi_tree( 400, "Content-Type missing", 19);
  100. if (body && body->len && msg->content_length)
  101. return init_mi_tree( 400, "Content-Length disallowed", 24);
  102. if (!msg->to)
  103. return init_mi_tree( 400, "To missing", 10);
  104. if (!msg->from)
  105. return init_mi_tree( 400, "From missing", 12);
  106. /* we also need to know if there is from-tag and add it otherwise */
  107. if (parse_from_header(msg) < 0)
  108. return init_mi_tree( 400, "Error in From", 13);
  109. if (msg->cseq && (parsed_cseq = get_cseq(msg))) {
  110. if (str2int( &parsed_cseq->number, (unsigned int*)cseq)!=0)
  111. return init_mi_tree( 400, "Bad CSeq number", 15);
  112. if (parsed_cseq->method.len != method->len
  113. || memcmp(parsed_cseq->method.s, method->s, method->len) !=0 )
  114. return init_mi_tree( 400, "CSeq method mismatch", 20);
  115. } else {
  116. *cseq = -1;
  117. }
  118. if (msg->callid) {
  119. callid->s = msg->callid->body.s;
  120. callid->len = msg->callid->body.len;
  121. } else {
  122. callid->s = 0;
  123. callid->len = 0;
  124. }
  125. return 0;
  126. }
  127. /*!
  128. * \brief Convert a header field block to char array
  129. *
  130. * Convert a header field block to char array, allocated in
  131. * pkg_mem.
  132. * \param uri SIP URI
  133. * \param hf header field
  134. * \param l
  135. * \param send_sock socket information
  136. * \return new allocated char array on success, zero otherwise
  137. */
  138. static inline char *get_hfblock( str *uri, struct hdr_field *hf, int *l, struct socket_info** send_sock)
  139. {
  140. struct str_list sl, *last, *new, *i, *foo;
  141. int hf_avail, frag_len, total_len;
  142. char *begin, *needle, *dst, *ret, *d;
  143. str *sock_name, *portname;
  144. union sockaddr_union to_su;
  145. ret=0; /* pessimist: assume failure */
  146. total_len=0;
  147. last=&sl;
  148. last->next=0;
  149. portname=sock_name=0;
  150. for (; hf; hf=hf->next) {
  151. if (tm_skip_hf(hf)) continue;
  152. begin=needle=hf->name.s;
  153. hf_avail=hf->len;
  154. /* substitution loop */
  155. while(hf_avail) {
  156. d=memchr(needle, SUBST_CHAR, hf_avail);
  157. if (!d || d+1>=needle+hf_avail) { /* nothing to substitute */
  158. new=append_str_list(begin, hf_avail, &last, &total_len);
  159. if (!new) goto error;
  160. break;
  161. } else {
  162. frag_len=d-begin;
  163. d++; /* d not at the second substitution char */
  164. switch(*d) {
  165. case SUBST_CHAR: /* double SUBST_CHAR: IP */
  166. /* string before substitute */
  167. new=append_str_list(begin, frag_len, &last, &total_len);
  168. if (!new) goto error;
  169. /* substitute */
  170. if (!sock_name) {
  171. if (*send_sock==0){
  172. *send_sock=uri2sock(0, uri, &to_su,PROTO_NONE);
  173. if (!*send_sock) {
  174. LM_ERR("send_sock failed\n");
  175. goto error;
  176. }
  177. }
  178. sock_name=&(*send_sock)->address_str;
  179. portname=&(*send_sock)->port_no_str;
  180. }
  181. new=append_str_list(sock_name->s, sock_name->len,
  182. &last, &total_len );
  183. if (!new) goto error;
  184. /* inefficient - FIXME --andrei*/
  185. new=append_str_list(":", 1, &last, &total_len);
  186. if (!new) goto error;
  187. new=append_str_list(portname->s, portname->len,
  188. &last, &total_len );
  189. if (!new) goto error;
  190. /* keep going ... */
  191. begin=needle=d+1;hf_avail-=frag_len+2;
  192. continue;
  193. default:
  194. /* no valid substitution char -- keep going */
  195. hf_avail-=frag_len+1;
  196. needle=d;
  197. }
  198. } /* possible substitute */
  199. } /* substitution loop */
  200. /* proceed to next header */
  201. /* new=append_str_list(CRLF, CRLF_LEN, &last, &total_len );
  202. if (!new) goto error; */
  203. LM_DBG("one more hf processed\n");
  204. } /* header loop */
  205. /* construct a single header block now */
  206. ret=pkg_malloc(total_len);
  207. if (!ret) {
  208. LM_ERR("no pkg mem for hf block\n");
  209. goto error;
  210. }
  211. i=sl.next;
  212. dst=ret;
  213. while(i) {
  214. foo=i;
  215. i=i->next;
  216. memcpy(dst, foo->s.s, foo->s.len);
  217. dst+=foo->s.len;
  218. pkg_free(foo);
  219. }
  220. *l=total_len;
  221. return ret;
  222. error:
  223. i=sl.next;
  224. while(i) {
  225. foo=i;
  226. i=i->next;
  227. pkg_free(foo);
  228. }
  229. *l=0;
  230. return 0;
  231. }
  232. /*!
  233. * \brief Print routes
  234. *
  235. * Print route to MI node, allocate temporary memory in pkg_mem.
  236. * \param node MI node
  237. * \param dlg route set
  238. */
  239. static inline void mi_print_routes( struct mi_node *node, dlg_t* dlg)
  240. {
  241. #define MI_ROUTE_PREFIX_S "Route: "
  242. #define MI_ROUTE_PREFIX_LEN (sizeof(MI_ROUTE_PREFIX_S)-1)
  243. #define MI_ROUTE_SEPARATOR_S ", "
  244. #define MI_ROUTE_SEPARATOR_LEN (sizeof(MI_ROUTE_SEPARATOR_S)-1)
  245. rr_t* ptr;
  246. int len;
  247. char *p, *s;
  248. ptr = dlg->hooks.first_route;
  249. if (ptr==NULL) {
  250. add_mi_node_child( node, 0, 0, 0, ".",1);
  251. return;
  252. }
  253. len = MI_ROUTE_PREFIX_LEN;
  254. for( ; ptr ; ptr=ptr->next)
  255. len += ptr->len + MI_ROUTE_SEPARATOR_LEN*(ptr->next!=NULL);
  256. if (dlg->hooks.last_route)
  257. len += dlg->hooks.last_route->len + 2;
  258. s = pkg_malloc( len );
  259. if (s==0) {
  260. LM_ERR("no more pkg mem\n");
  261. return;
  262. }
  263. p = s;
  264. memcpy( p, MI_ROUTE_PREFIX_S, MI_ROUTE_PREFIX_LEN);
  265. p += MI_ROUTE_PREFIX_LEN;
  266. for( ptr = dlg->hooks.first_route ; ptr ; ptr=ptr->next) {
  267. memcpy( p, ptr->nameaddr.name.s, ptr->len);
  268. p += ptr->len;
  269. if (ptr->next) {
  270. memcpy( p, MI_ROUTE_SEPARATOR_S, MI_ROUTE_SEPARATOR_LEN);
  271. p += MI_ROUTE_SEPARATOR_LEN;
  272. }
  273. }
  274. if (dlg->hooks.last_route) {
  275. *(p++) = '<';
  276. memcpy( p, dlg->hooks.last_route->s, dlg->hooks.last_route->len);
  277. p += dlg->hooks.last_route->len;
  278. *(p++) = '>';
  279. }
  280. add_mi_node_child( node, MI_DUP_VALUE, 0, 0, s, len);
  281. pkg_free(s);
  282. }
  283. /*!
  284. * \brief Print URIs
  285. *
  286. * Print URIs to MI node, allocate temporary memory in shm_mem.
  287. * \param node MI node
  288. * \param reply SIP reply
  289. * \return zero on success, -1 on errors
  290. */
  291. static inline int mi_print_uris( struct mi_node *node, struct sip_msg* reply)
  292. {
  293. dlg_t* dlg;
  294. if (reply==0)
  295. goto empty;
  296. dlg = (dlg_t*)shm_malloc(sizeof(dlg_t));
  297. if (!dlg) {
  298. LM_ERR("no shm memory left\n");
  299. return -1;
  300. }
  301. memset(dlg, 0, sizeof(dlg_t));
  302. if (_tmx_tmb.dlg_response_uac(dlg, reply, TARGET_REFRESH_UNKNOWN) < 0) {
  303. LM_ERR("failed to create dialog\n");
  304. _tmx_tmb.free_dlg(dlg);
  305. return -1;
  306. }
  307. if (dlg->state != DLG_CONFIRMED) {
  308. _tmx_tmb.free_dlg(dlg);
  309. goto empty;
  310. }
  311. if (dlg->hooks.request_uri->s) {
  312. add_mi_node_child( node, MI_DUP_VALUE, 0, 0,
  313. dlg->hooks.request_uri->s, dlg->hooks.request_uri->len);
  314. } else {
  315. add_mi_node_child( node, 0, 0, 0, ".",1);
  316. }
  317. if (dlg->hooks.next_hop->s) {
  318. add_mi_node_child( node, MI_DUP_VALUE, 0, 0,
  319. dlg->hooks.next_hop->s, dlg->hooks.next_hop->len);
  320. } else {
  321. add_mi_node_child( node, 0, 0, 0, ".",1);
  322. }
  323. mi_print_routes( node, dlg);
  324. _tmx_tmb.free_dlg(dlg);
  325. return 0;
  326. empty:
  327. add_mi_node_child( node, 0, 0, 0, ".",1);
  328. add_mi_node_child( node, 0, 0, 0, ".",1);
  329. add_mi_node_child( node, 0, 0, 0, ".",1);
  330. return 0;
  331. }
  332. static void mi_uac_dlg_hdl( struct cell *t, int type, struct tmcb_params *ps )
  333. {
  334. struct mi_handler *mi_hdl;
  335. struct mi_root *rpl_tree;
  336. str text;
  337. LM_DBG("MI UAC generated status %d\n", ps->code);
  338. if (!*ps->param)
  339. return;
  340. mi_hdl = (struct mi_handler *)(*ps->param);
  341. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  342. if (rpl_tree==0)
  343. goto done;
  344. if (ps->rpl==FAKED_REPLY) {
  345. get_reply_status( &text, ps->rpl, ps->code);
  346. if (text.s==0) {
  347. LM_ERR("get_reply_status failed\n");
  348. rpl_tree = 0;
  349. goto done;
  350. }
  351. add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE, 0, 0,
  352. text.s, text.len);
  353. pkg_free(text.s);
  354. mi_print_uris( &rpl_tree->node, 0 );
  355. add_mi_node_child( &rpl_tree->node, 0, 0, 0, ".",1);
  356. } else {
  357. addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%d %.*s",
  358. ps->rpl->first_line.u.reply.statuscode,
  359. ps->rpl->first_line.u.reply.reason.len,
  360. ps->rpl->first_line.u.reply.reason.s);
  361. mi_print_uris( &rpl_tree->node, ps->rpl);
  362. add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE, 0, 0,
  363. ps->rpl->headers->name.s,
  364. ps->rpl->len-(ps->rpl->headers->name.s - ps->rpl->buf));
  365. }
  366. LM_DBG("mi_callback successfully completed\n");
  367. done:
  368. if (ps->code >= 200) {
  369. mi_hdl->handler_f( rpl_tree, mi_hdl, 1 /*done*/ );
  370. *ps->param = 0;
  371. } else {
  372. mi_hdl->handler_f( rpl_tree, mi_hdl, 0 );
  373. }
  374. }
  375. /**************************** MI functions ********************************/
  376. /*
  377. Syntax of "t_uac_dlg" :
  378. method
  379. RURI
  380. NEXT_HOP
  381. socket
  382. headers
  383. [Body]
  384. */
  385. struct mi_root* mi_tm_uac_dlg(struct mi_root* cmd_tree, void* param)
  386. {
  387. static char err_buf[MAX_REASON_LEN];
  388. static struct sip_msg tmp_msg;
  389. static dlg_t dlg;
  390. struct mi_root *rpl_tree;
  391. struct mi_node *node;
  392. struct sip_uri pruri;
  393. struct sip_uri pnexthop;
  394. struct socket_info* sock;
  395. str *method;
  396. str *ruri;
  397. str *nexthop;
  398. str *socket;
  399. str *hdrs;
  400. str *body;
  401. str s;
  402. str callid = {0,0};
  403. int sip_error;
  404. int proto;
  405. int port;
  406. int cseq;
  407. int n;
  408. uac_req_t uac_r;
  409. for( n=0,node = cmd_tree->node.kids; n<6 && node ; n++,node=node->next );
  410. if ( !(n==5 || n==6) || node!=0)
  411. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  412. cseq = -1;
  413. /* method name (param 1) */
  414. node = cmd_tree->node.kids;
  415. method = &node->value;
  416. /* RURI (param 2) */
  417. node = node->next;
  418. ruri = &node->value;
  419. if (parse_uri( ruri->s, ruri->len, &pruri) < 0 )
  420. return init_mi_tree( 400, "Invalid RURI", 12);
  421. /* nexthop RURI (param 3) */
  422. node = node->next;
  423. nexthop = &node->value;
  424. if (nexthop->len==1 && nexthop->s[0]=='.') {
  425. nexthop = 0;
  426. } else {
  427. if (parse_uri( nexthop->s, nexthop->len, &pnexthop) < 0 )
  428. return init_mi_tree( 400, "Invalid NEXTHOP", 15);
  429. }
  430. /* socket (param 4) */
  431. node = node->next;
  432. socket = &node->value;
  433. if (socket->len==1 && socket->s[0]=='.' ) {
  434. sock = 0;
  435. } else {
  436. if (parse_phostport( socket->s, &s.s, &s.len,
  437. &port,&proto)!=0)
  438. return init_mi_tree( 404, "Invalid local socket", 20);
  439. sock = grep_sock_info( &s, (unsigned short)port, proto);
  440. if (sock==0)
  441. return init_mi_tree( 404, "Local socket not found", 22);
  442. }
  443. /* new headers (param 5) */
  444. node = node->next;
  445. if (node->value.len==1 && node->value.s[0]=='.')
  446. hdrs = 0;
  447. else {
  448. hdrs = &node->value;
  449. /* use SIP parser to look at what is in the FIFO request */
  450. memset( &tmp_msg, 0, sizeof(struct sip_msg));
  451. tmp_msg.len = hdrs->len;
  452. tmp_msg.buf = tmp_msg.unparsed = hdrs->s;
  453. if (parse_headers( &tmp_msg, HDR_EOH_F, 0) == -1 )
  454. return init_mi_tree( 400, "Bad headers", 11);
  455. }
  456. /* body (param 5 - optional) */
  457. node = node->next;
  458. if (node)
  459. body = &node->value;
  460. else
  461. body = 0;
  462. /* at this moment, we collected all the things we got, let's
  463. * verify user has not forgotten something */
  464. rpl_tree = mi_check_msg( &tmp_msg, method, body, &cseq, &callid);
  465. if (rpl_tree) {
  466. if (tmp_msg.headers) free_hdr_field_lst(tmp_msg.headers);
  467. return rpl_tree;
  468. }
  469. s.s = get_hfblock( nexthop ? nexthop : ruri,
  470. tmp_msg.headers, &s.len, &sock);
  471. if (s.s==0) {
  472. if (tmp_msg.headers) free_hdr_field_lst(tmp_msg.headers);
  473. return 0;
  474. }
  475. memset( &dlg, 0, sizeof(dlg_t));
  476. /* Fill in Call-ID, use given Call-ID if
  477. * present and generate it if not present */
  478. if (callid.s && callid.len)
  479. dlg.id.call_id = callid;
  480. else
  481. _tmx_tmb.generate_callid(&dlg.id.call_id);
  482. /* We will not fill in dlg->id.rem_tag because
  483. * if present it will be printed within To HF */
  484. /* Generate fromtag if not present */
  485. if (!(get_from(&tmp_msg)->tag_value.len&&get_from(&tmp_msg)->tag_value.s))
  486. _tmx_tmb.generate_fromtag(&dlg.id.loc_tag, &dlg.id.call_id);
  487. /* Fill in CSeq */
  488. if (cseq!=-1)
  489. dlg.loc_seq.value = cseq;
  490. else
  491. dlg.loc_seq.value = DEFAULT_CSEQ;
  492. dlg.loc_seq.is_set = 1;
  493. dlg.loc_uri = tmp_msg.from->body;
  494. dlg.rem_uri = tmp_msg.to->body;
  495. dlg.rem_target = *ruri;
  496. if (nexthop)
  497. dlg.dst_uri = *nexthop;
  498. dlg.send_sock = sock;
  499. memset(&uac_r, 0, sizeof(uac_req_t));
  500. uac_r.method = method;
  501. uac_r.body = body;
  502. uac_r.headers = &s;
  503. uac_r.dialog = &dlg;
  504. if (cmd_tree->async_hdl!=NULL)
  505. {
  506. uac_r.cb = mi_uac_dlg_hdl;
  507. uac_r.cbp = (void*)cmd_tree->async_hdl;
  508. uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
  509. }
  510. n = _tmx_tmb.t_uac(&uac_r);
  511. pkg_free(s.s);
  512. if (tmp_msg.headers) free_hdr_field_lst(tmp_msg.headers);
  513. if (n<=0) {
  514. /* error */
  515. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  516. if (rpl_tree==0)
  517. return 0;
  518. n = err2reason_phrase( n, &sip_error, err_buf, sizeof(err_buf),
  519. "MI/UAC") ;
  520. if (n > 0 )
  521. addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%d %.*s",
  522. sip_error, n, err_buf);
  523. else
  524. add_mi_node_child( &rpl_tree->node, 0, 0, 0,
  525. "500 MI/UAC failed", 17);
  526. return rpl_tree;
  527. } else {
  528. if (cmd_tree->async_hdl==NULL)
  529. return init_mi_tree( 202, "Accepted", 8);
  530. else
  531. return MI_ROOT_ASYNC_RPL;
  532. }
  533. }
  534. /*
  535. Syntax of "t_uac_cancel" :
  536. callid
  537. cseq
  538. */
  539. struct mi_root* mi_tm_cancel(struct mi_root* cmd_tree, void* param)
  540. {
  541. struct cancel_info cancel_data;
  542. struct mi_node *node;
  543. struct cell *trans;
  544. node = cmd_tree->node.kids;
  545. if ( !node || !node->next || node->next->next)
  546. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  547. if( _tmx_tmb.t_lookup_callid( &trans, node->value, node->next->value) < 0 )
  548. return init_mi_tree( 481, "No such transaction", 19);
  549. /* cancel the call */
  550. LM_DBG("cancelling transaction %p\n",trans);
  551. init_cancel_info(&cancel_data);
  552. cancel_data.cancel_bitmap = ~0; /*all branches*/
  553. _tmx_tmb.cancel_uacs(trans, &cancel_data, 0);
  554. _tmx_tmb.unref_cell(trans);
  555. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  556. }
  557. /*
  558. Syntax of "t_hash" :
  559. no nodes
  560. */
  561. struct mi_root* mi_tm_hash(struct mi_root* cmd_tree, void* param)
  562. {
  563. #ifndef TM_HASH_STATS
  564. return init_mi_tree( 500, "No TM hash stats", 16);
  565. #else
  566. struct mi_root* rpl_tree= NULL;
  567. struct mi_node* rpl;
  568. struct mi_node* node;
  569. struct mi_attr* attr;
  570. struct s_table* tm_t;
  571. char *p;
  572. int i;
  573. int len;
  574. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  575. if (rpl_tree==0)
  576. return 0;
  577. rpl = &rpl_tree->node;
  578. tm_t = _tmx_tmb.get_table();
  579. for (i=0; i<TABLE_ENTRIES; i++) {
  580. if(tm_t->entries[i].cur_entries==0
  581. && tm_t->entries[i].acc_entries==0)
  582. continue;
  583. p = int2str((unsigned long)i, &len );
  584. node = add_mi_node_child(rpl, MI_DUP_VALUE , 0, 0, p, len);
  585. if(node == NULL)
  586. goto error;
  587. p = int2str((unsigned long)tm_t->entries[i].cur_entries, &len );
  588. attr = add_mi_attr(node, MI_DUP_VALUE, "Current", 7, p, len );
  589. if(attr == NULL)
  590. goto error;
  591. p = int2str((unsigned long)tm_t->entries[i].acc_entries, &len );
  592. attr = add_mi_attr(node, MI_DUP_VALUE, "Total", 5, p, len );
  593. if(attr == NULL)
  594. goto error;
  595. }
  596. return rpl_tree;
  597. error:
  598. free_mi_tree(rpl_tree);
  599. return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
  600. #endif
  601. }
  602. /*
  603. Syntax of "t_reply" :
  604. code
  605. reason
  606. trans_id
  607. to_tag
  608. new headers
  609. [Body]
  610. */
  611. struct mi_root* mi_tm_reply(struct mi_root* cmd_tree, void* param)
  612. {
  613. struct mi_node* node;
  614. unsigned int hash_index;
  615. unsigned int hash_label;
  616. unsigned int rpl_code;
  617. struct cell *trans;
  618. str reason = {0, 0};
  619. str totag = {0, 0};
  620. str new_hdrs = {0, 0};
  621. str body = {0, 0};
  622. str tmp = {0, 0};
  623. char *p;
  624. int n;
  625. for( n=0,node = cmd_tree->node.kids; n<6 && node ; n++,node=node->next );
  626. if ( !(n==5 || n==6) || node!=0)
  627. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  628. /* get all info from the command */
  629. /* reply code (param 1) */
  630. node = cmd_tree->node.kids;
  631. if (str2int( &node->value, &rpl_code)!=0 || rpl_code>=700)
  632. return init_mi_tree( 400, "Invalid reply code", 18);
  633. /* reason text (param 2) */
  634. node = node->next;
  635. reason = node->value;
  636. /* trans_id (param 3) */
  637. node = node->next;
  638. tmp = node->value;
  639. p = memchr( tmp.s, ':', tmp.len);
  640. if(p==NULL)
  641. return init_mi_tree( 400, "Invalid trans_id", 16);
  642. tmp.len = p-tmp.s;
  643. if(str2int(&tmp, &hash_index)!=0)
  644. return init_mi_tree( 400, "Invalid index in trans_id", 25);
  645. tmp.s = p+1;
  646. tmp.len = (node->value.s+node->value.len) - tmp.s;
  647. if(str2int(&tmp, &hash_label)!=0)
  648. return init_mi_tree( 400, "Invalid label in trans_id", 25);
  649. if(_tmx_tmb.t_lookup_ident( &trans, hash_index, hash_label)<0)
  650. return init_mi_tree( 404, "Transaction not found", 21);
  651. /* to_tag (param 4) */
  652. node = node->next;
  653. totag = node->value;
  654. /* new headers (param 5) */
  655. node = node->next;
  656. if (!(node->value.len==1 && node->value.s[0]=='.'))
  657. new_hdrs = node->value;
  658. /* body (param 5 - optional) */
  659. node = node->next;
  660. if (node)
  661. body = node->value;
  662. /* it's refcounted now, t_reply_with body unrefs for me -- I can
  663. * continue but may not use T anymore */
  664. n = _tmx_tmb.t_reply_with_body(trans, rpl_code, &reason, &body,
  665. &new_hdrs, &totag);
  666. if (n<0)
  667. return init_mi_tree( 500, "Reply failed", 12);
  668. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  669. }
  670. /*
  671. Syntax of "t_reply_callid" :
  672. code
  673. reason
  674. callid
  675. cseq
  676. to_tag
  677. new headers
  678. [Body]
  679. */
  680. struct mi_root* mi_tm_reply_callid(struct mi_root* cmd_tree, void* param)
  681. {
  682. struct mi_node* node;
  683. unsigned int rpl_code;
  684. struct cell *trans;
  685. str reason = {0, 0};
  686. str totag = {0, 0};
  687. str new_hdrs = {0, 0};
  688. str body = {0, 0};
  689. str callid = {0, 0};
  690. str cseq = {0, 0};
  691. int n;
  692. for( n=0,node = cmd_tree->node.kids; n<7 && node ; n++,node=node->next );
  693. if ( !(n==6 || n==7) || node!=0)
  694. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  695. /* get all info from the command */
  696. /* reply code (param 1) */
  697. node = cmd_tree->node.kids;
  698. if (str2int( &node->value, &rpl_code)!=0 || rpl_code>=700)
  699. return init_mi_tree( 400, "Invalid reply code", 18);
  700. /* reason text (param 2) */
  701. node = node->next;
  702. reason = node->value;
  703. /* callid (param 3) */
  704. node = node->next;
  705. callid = node->value;
  706. /* cseq (param 4) */
  707. node = node->next;
  708. cseq = node->value;
  709. if(_tmx_tmb.t_lookup_callid( &trans, callid, cseq) < 0 )
  710. return init_mi_tree( 400, "Lookup failed - no transaction", 30);
  711. /* to_tag (param 5) */
  712. node = node->next;
  713. totag = node->value;
  714. /* new headers (param 6) */
  715. node = node->next;
  716. if (!(node->value.len==1 && node->value.s[0]=='.'))
  717. new_hdrs = node->value;
  718. /* body (param 7 - optional) */
  719. node = node->next;
  720. if (node)
  721. body = node->value;
  722. /* it's refcounted now, t_reply_with body unrefs for me -- I can
  723. * continue but may not use T anymore */
  724. n = _tmx_tmb.t_reply_with_body(trans, rpl_code, &reason, &body,
  725. &new_hdrs, &totag);
  726. if (n<0)
  727. return init_mi_tree( 500, "Reply failed", 12);
  728. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  729. }