tmx_pretran.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /**
  2. * Copyright (C) 2014 Daniel-Constantin Mierla (asipto.com)
  3. *
  4. * This file is part of kamailio, a free SIP server.
  5. *
  6. * Kamailio is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * Kamailio is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include "../../dprint.h"
  24. #include "../../mem/shm_mem.h"
  25. #include "../../locking.h"
  26. #include "../../hashes.h"
  27. #include "../../config.h"
  28. #include "../../parser/parse_via.h"
  29. #include "../../parser/parse_from.h"
  30. #include "../../route.h"
  31. #include "../../trim.h"
  32. #include "../../pt.h"
  33. #include "tmx_pretran.h"
  34. typedef struct _pretran {
  35. unsigned int hid;
  36. unsigned int linked;
  37. str callid;
  38. str ftag;
  39. str cseqnum;
  40. str cseqmet;
  41. unsigned int cseqmetid;
  42. str vbranch;
  43. str dbuf;
  44. int pid;
  45. struct _pretran *next;
  46. struct _pretran *prev;
  47. } pretran_t;
  48. typedef struct pretran_slot {
  49. pretran_t *plist;
  50. gen_lock_t lock;
  51. } pretran_slot_t;
  52. static pretran_t *_tmx_proc_ptran = NULL;
  53. static pretran_slot_t *_tmx_ptran_table = NULL;
  54. static int _tmx_ptran_size = 0;
  55. /**
  56. *
  57. */
  58. int tmx_init_pretran_table(void)
  59. {
  60. int n;
  61. int pn;
  62. pn = get_max_procs();
  63. if(pn<=0)
  64. return -1;
  65. if(_tmx_ptran_table!=NULL)
  66. return -1;
  67. /* get the highest power of two less than number of processes */
  68. n = -1;
  69. while (pn >> ++n > 0);
  70. n--;
  71. if(n<=1) n = 2;
  72. if(n>8) n = 8;
  73. _tmx_ptran_size = 1<<n;
  74. _tmx_ptran_table = (pretran_slot_t*)shm_malloc(_tmx_ptran_size*sizeof(pretran_slot_t));
  75. if(_tmx_ptran_table == NULL) {
  76. LM_ERR("not enough shared memory\n");
  77. return -1;
  78. }
  79. memset(_tmx_ptran_table, 0, _tmx_ptran_size*sizeof(pretran_slot_t));
  80. for(n=0; n<_tmx_ptran_size; n++) {
  81. if(lock_init(&_tmx_ptran_table[n].lock)==NULL)
  82. {
  83. LM_ERR("cannot init the lock %d\n", n);
  84. n--;
  85. while(n>=0) {
  86. lock_destroy(&_tmx_ptran_table[n].lock);
  87. n--;
  88. }
  89. shm_free(_tmx_ptran_table);
  90. _tmx_ptran_table = 0;
  91. _tmx_ptran_size = 0;
  92. return -1;
  93. }
  94. }
  95. return 0;
  96. }
  97. /**
  98. *
  99. */
  100. void tmx_pretran_link_safe(int slotid)
  101. {
  102. if(_tmx_proc_ptran==NULL)
  103. return;
  104. if(_tmx_ptran_table[slotid].plist==NULL) {
  105. _tmx_ptran_table[slotid].plist = _tmx_proc_ptran;
  106. _tmx_proc_ptran->linked = 1;
  107. return;
  108. }
  109. _tmx_proc_ptran->next = _tmx_ptran_table[slotid].plist;
  110. _tmx_ptran_table[slotid].plist->prev = _tmx_proc_ptran;
  111. _tmx_ptran_table[slotid].plist = _tmx_proc_ptran;
  112. _tmx_proc_ptran->linked = 1;
  113. return;
  114. }
  115. /**
  116. *
  117. */
  118. void tmx_pretran_unlink_safe(int slotid)
  119. {
  120. if(_tmx_proc_ptran==NULL)
  121. return;
  122. if(_tmx_proc_ptran->linked == 0)
  123. return;
  124. if(_tmx_ptran_table[slotid].plist==NULL) {
  125. _tmx_proc_ptran->prev = _tmx_proc_ptran->next = NULL;
  126. _tmx_proc_ptran->linked = 0;
  127. return;
  128. }
  129. if(_tmx_proc_ptran->prev==NULL) {
  130. _tmx_ptran_table[slotid].plist = _tmx_proc_ptran->next;
  131. if(_tmx_ptran_table[slotid].plist!=NULL)
  132. _tmx_ptran_table[slotid].plist->prev = NULL;
  133. } else {
  134. _tmx_proc_ptran->prev->next = _tmx_proc_ptran->next;
  135. if(_tmx_proc_ptran->next)
  136. _tmx_proc_ptran->next->prev = _tmx_proc_ptran->prev;
  137. }
  138. _tmx_proc_ptran->prev = _tmx_proc_ptran->next = NULL;
  139. _tmx_proc_ptran->linked = 0;
  140. return;
  141. }
  142. /**
  143. *
  144. */
  145. void tmx_pretran_unlink(void)
  146. {
  147. int slotid;
  148. if(_tmx_proc_ptran==NULL)
  149. return;
  150. slotid = _tmx_proc_ptran->hid & (_tmx_ptran_size-1);
  151. lock_get(&_tmx_ptran_table[slotid].lock);
  152. tmx_pretran_unlink_safe(slotid);
  153. lock_release(&_tmx_ptran_table[slotid].lock);
  154. }
  155. /**
  156. * return:
  157. * - -1: error
  158. * - 0: not found
  159. * - 1: found
  160. */
  161. int tmx_check_pretran(sip_msg_t *msg)
  162. {
  163. unsigned int chid;
  164. unsigned int slotid;
  165. int dsize;
  166. struct via_param *vbr;
  167. str scallid;
  168. str scseqmet;
  169. str scseqnum;
  170. str sftag;
  171. str svbranch;
  172. pretran_t *it;
  173. if(_tmx_ptran_table==NULL) {
  174. LM_ERR("pretran hash table not intialized yet\n");
  175. return -1;
  176. }
  177. if(get_route_type()!=REQUEST_ROUTE) {
  178. LM_ERR("invalid usage - not in request route\n");
  179. return -1;
  180. }
  181. if(msg->first_line.type!=SIP_REQUEST) {
  182. LM_ERR("invalid usage - not a sip request\n");
  183. return -1;
  184. }
  185. if(parse_headers(msg, HDR_FROM_F|HDR_VIA1_F|HDR_CALLID_F|HDR_CSEQ_F, 0)<0) {
  186. LM_ERR("failed to parse required headers\n");
  187. return -1;
  188. }
  189. if(get_cseq(msg)->method_id==METHOD_ACK
  190. || get_cseq(msg)->method_id==METHOD_CANCEL) {
  191. LM_DBG("no pre-transaction management for ACK or CANCEL\n");
  192. return -1;
  193. }
  194. if (msg->via1==0) {
  195. LM_ERR("failed to get Via header\n");
  196. return -1;
  197. }
  198. if (parse_from_header(msg)<0 || get_from(msg)->tag_value.len==0) {
  199. LM_ERR("failed to get From header\n");
  200. return -1;
  201. }
  202. vbr = msg->via1->branch;
  203. scallid = msg->callid->body;
  204. trim(&scallid);
  205. scseqmet = get_cseq(msg)->method;
  206. trim(&scseqmet);
  207. scseqnum = get_cseq(msg)->number;
  208. trim(&scseqnum);
  209. sftag = get_from(msg)->tag_value;
  210. trim(&sftag);
  211. chid = get_hash1_raw(msg->callid->body.s, msg->callid->body.len);
  212. slotid = chid & (_tmx_ptran_size-1);
  213. if(unlikely(_tmx_proc_ptran == NULL)) {
  214. _tmx_proc_ptran = (pretran_t*)shm_malloc(sizeof(pretran_t));
  215. if(_tmx_proc_ptran == NULL) {
  216. LM_ERR("not enough memory for pretran structure\n");
  217. return -1;
  218. }
  219. memset(_tmx_proc_ptran, 0, sizeof(pretran_t));
  220. _tmx_proc_ptran->pid = my_pid();
  221. }
  222. dsize = scallid.len + scseqnum.len + scseqmet.len
  223. + sftag.len + 4;
  224. if(likely(vbr!=NULL)) {
  225. svbranch = vbr->value;
  226. trim(&svbranch);
  227. dsize += svbranch.len;
  228. }
  229. if(dsize<256) dsize = 256;
  230. tmx_pretran_unlink();
  231. if(dsize > _tmx_proc_ptran->dbuf.len) {
  232. if(_tmx_proc_ptran->dbuf.s) shm_free(_tmx_proc_ptran->dbuf.s);
  233. _tmx_proc_ptran->dbuf.s = (char*)shm_malloc(dsize);
  234. if(_tmx_proc_ptran->dbuf.s==NULL) {
  235. LM_ERR("not enough memory for pretran data\n");
  236. return -1;
  237. }
  238. _tmx_proc_ptran->dbuf.len = dsize;
  239. }
  240. _tmx_proc_ptran->hid = chid;
  241. _tmx_proc_ptran->cseqmetid = (get_cseq(msg))->method_id;
  242. _tmx_proc_ptran->callid.s = _tmx_proc_ptran->dbuf.s;
  243. memcpy(_tmx_proc_ptran->callid.s, scallid.s, scallid.len);
  244. _tmx_proc_ptran->callid.len = scallid.len;
  245. _tmx_proc_ptran->callid.s[_tmx_proc_ptran->callid.len] = '\0';
  246. _tmx_proc_ptran->ftag.s = _tmx_proc_ptran->callid.s
  247. + _tmx_proc_ptran->callid.len + 1;
  248. memcpy(_tmx_proc_ptran->ftag.s, sftag.s, sftag.len);
  249. _tmx_proc_ptran->ftag.len = sftag.len;
  250. _tmx_proc_ptran->ftag.s[_tmx_proc_ptran->ftag.len] = '\0';
  251. _tmx_proc_ptran->cseqnum.s = _tmx_proc_ptran->ftag.s
  252. + _tmx_proc_ptran->ftag.len + 1;
  253. memcpy(_tmx_proc_ptran->cseqnum.s, scseqnum.s, scseqnum.len);
  254. _tmx_proc_ptran->cseqnum.len = scseqnum.len;
  255. _tmx_proc_ptran->cseqnum.s[_tmx_proc_ptran->cseqnum.len] = '\0';
  256. _tmx_proc_ptran->cseqmet.s = _tmx_proc_ptran->cseqnum.s
  257. + _tmx_proc_ptran->cseqnum.len + 1;
  258. memcpy(_tmx_proc_ptran->cseqmet.s, scseqmet.s, scseqmet.len);
  259. _tmx_proc_ptran->cseqmet.len = scseqmet.len;
  260. _tmx_proc_ptran->cseqmet.s[_tmx_proc_ptran->cseqmet.len] = '\0';
  261. if(likely(vbr!=NULL)) {
  262. _tmx_proc_ptran->vbranch.s = _tmx_proc_ptran->cseqmet.s
  263. + _tmx_proc_ptran->cseqmet.len + 1;
  264. memcpy(_tmx_proc_ptran->vbranch.s, svbranch.s, svbranch.len);
  265. _tmx_proc_ptran->vbranch.len = svbranch.len;
  266. _tmx_proc_ptran->vbranch.s[_tmx_proc_ptran->vbranch.len] = '\0';
  267. } else {
  268. _tmx_proc_ptran->vbranch.s = NULL;
  269. _tmx_proc_ptran->vbranch.len = 0;
  270. }
  271. lock_get(&_tmx_ptran_table[slotid].lock);
  272. it = _tmx_ptran_table[slotid].plist;
  273. tmx_pretran_link_safe(slotid);
  274. for(; it!=NULL; it=it->next) {
  275. if(_tmx_proc_ptran->hid != it->hid
  276. || _tmx_proc_ptran->cseqmetid != it->cseqmetid
  277. || _tmx_proc_ptran->callid.len != it->callid.len
  278. || _tmx_proc_ptran->ftag.len != it->ftag.len
  279. || _tmx_proc_ptran->cseqmet.len != it->cseqmet.len
  280. || _tmx_proc_ptran->cseqnum.len != it->cseqnum.len)
  281. continue;
  282. if(_tmx_proc_ptran->vbranch.s != NULL && it->vbranch.s != NULL) {
  283. if(_tmx_proc_ptran->vbranch.len != it->vbranch.len)
  284. continue;
  285. /* shortcut - check last char in Via branch
  286. * - kamailio/ser adds there branch index => in case of paralel
  287. * forking by previous hop, catch it here quickly */
  288. if(_tmx_proc_ptran->vbranch.s[it->vbranch.len-1]
  289. != it->vbranch.s[it->vbranch.len-1])
  290. continue;
  291. if(memcmp(_tmx_proc_ptran->vbranch.s,
  292. it->vbranch.s, it->vbranch.len)!=0)
  293. continue;
  294. /* shall stop by matching magic cookie?
  295. if (vbr && vbr->value.s && vbr->value.len > MCOOKIE_LEN
  296. && memcmp(vbr->value.s, MCOOKIE, MCOOKIE_LEN)==0) {
  297. LM_DBG("rfc3261 cookie found in Via branch\n");
  298. }
  299. */
  300. }
  301. if(memcmp(_tmx_proc_ptran->callid.s,
  302. it->callid.s, it->callid.len)!=0
  303. || memcmp(_tmx_proc_ptran->ftag.s,
  304. it->ftag.s, it->ftag.len)!=0
  305. || memcmp(_tmx_proc_ptran->cseqnum.s,
  306. it->cseqnum.s, it->cseqnum.len)!=0)
  307. continue;
  308. if((it->cseqmetid==METHOD_OTHER || it->cseqmetid==METHOD_UNDEF)
  309. && memcmp(_tmx_proc_ptran->cseqmet.s,
  310. it->cseqmet.s, it->cseqmet.len)!=0)
  311. continue;
  312. LM_DBG("matched another pre-transaction by pid %d for [%.*s]\n",
  313. it->pid, it->callid.len, it->callid.s);
  314. lock_release(&_tmx_ptran_table[slotid].lock);
  315. return 1;
  316. }
  317. lock_release(&_tmx_ptran_table[slotid].lock);
  318. return 0;
  319. }