h_table.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. *
  6. * This file is part of ser, a free SIP server.
  7. *
  8. * ser 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. * For a license to use the ser software under conditions
  14. * other than those described here, or to purchase support for this
  15. * software, please contact iptel.org by e-mail at the following addresses:
  16. * [email protected]
  17. *
  18. * ser is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  26. *
  27. * History
  28. * -------
  29. * 2003-03-06 200/INV to-tag list deallocation added;
  30. * setting "kill_reason" moved in here -- it is moved
  31. * from transaction state to a static var(jiri)
  32. * 2003-03-16 removed _TOTAG (jiri)
  33. * 2003-03-30 set_kr for requests only (jiri)
  34. * 2003-04-04 bug_fix: REQ_IN callback not called for local
  35. * UAC transactions (jiri)
  36. * 2003-09-12 timer_link->tg will be set only if EXTRA_DEBUG (andrei)
  37. * 2003-12-04 global callbacks replaceed with callbacks per transaction;
  38. * completion callback merged into them as LOCAL_COMPETED (bogdan)
  39. * 2004-02-11 FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
  40. * 2004-02-13 t->is_invite and t->local replaced with flags;
  41. * timer_link.payload removed (bogdan)
  42. * 2004-08-23 avp support added - move and remove avp list to/from
  43. * transactions (bogdan)
  44. */
  45. #include <stdlib.h>
  46. #include "../../mem/shm_mem.h"
  47. #include "../../hash_func.h"
  48. #include "../../dprint.h"
  49. #include "../../md5utils.h"
  50. #include "../../ut.h"
  51. #include "../../globals.h"
  52. #include "../../error.h"
  53. #include "../../fifo_server.h"
  54. #include "../../unixsock_server.h"
  55. #include "defs.h"
  56. #include "t_reply.h"
  57. #include "t_cancel.h"
  58. #include "t_stats.h"
  59. #include "h_table.h"
  60. #include "fix_lumps.h" /* free_via_clen_lump */
  61. static enum kill_reason kr;
  62. /* pointer to the big table where all the transaction data
  63. lives */
  64. static struct s_table* tm_table;
  65. void set_kr( enum kill_reason _kr )
  66. {
  67. kr|=_kr;
  68. }
  69. enum kill_reason get_kr() {
  70. return kr;
  71. }
  72. void lock_hash(int i)
  73. {
  74. lock(&tm_table->entrys[i].mutex);
  75. }
  76. void unlock_hash(int i)
  77. {
  78. unlock(&tm_table->entrys[i].mutex);
  79. }
  80. struct s_table* get_tm_table()
  81. {
  82. return tm_table;
  83. }
  84. unsigned int transaction_count( void )
  85. {
  86. unsigned int i;
  87. unsigned int count;
  88. count=0;
  89. for (i=0; i<TABLE_ENTRIES; i++)
  90. count+=tm_table->entrys[i].cur_entries;
  91. return count;
  92. }
  93. void free_cell( struct cell* dead_cell )
  94. {
  95. char *b;
  96. int i;
  97. struct sip_msg *rpl;
  98. struct totag_elem *tt, *foo;
  99. struct tm_callback *cbs, *cbs_tmp;
  100. release_cell_lock( dead_cell );
  101. shm_lock();
  102. /* UA Server */
  103. if ( dead_cell->uas.request )
  104. sip_msg_free_unsafe( dead_cell->uas.request );
  105. if ( dead_cell->uas.response.buffer )
  106. shm_free_unsafe( dead_cell->uas.response.buffer );
  107. /* callbacks */
  108. for( cbs=dead_cell->tmcb_hl.first ; cbs ; ) {
  109. cbs_tmp = cbs;
  110. cbs = cbs->next;
  111. shm_free_unsafe( cbs_tmp );
  112. }
  113. /* UA Clients */
  114. for ( i =0 ; i<dead_cell->nr_of_outgoings; i++ )
  115. {
  116. /* retransmission buffer */
  117. if ( (b=dead_cell->uac[i].request.buffer) )
  118. shm_free_unsafe( b );
  119. b=dead_cell->uac[i].local_cancel.buffer;
  120. if (b!=0 && b!=BUSY_BUFFER)
  121. shm_free_unsafe( b );
  122. rpl=dead_cell->uac[i].reply;
  123. if (rpl && rpl!=FAKED_REPLY && rpl->msg_flags&FL_SHM_CLONE) {
  124. sip_msg_free_unsafe( rpl );
  125. }
  126. }
  127. /* collected to tags */
  128. tt=dead_cell->fwded_totags;
  129. while(tt) {
  130. foo=tt->next;
  131. shm_free_unsafe(tt->tag.s);
  132. shm_free_unsafe(tt);
  133. tt=foo;
  134. }
  135. /* free the avp list */
  136. if (dead_cell->user_avps)
  137. destroy_avp_list_unsafe( &dead_cell->user_avps );
  138. /* the cell's body */
  139. shm_free_unsafe( dead_cell );
  140. shm_unlock();
  141. }
  142. static inline void init_synonym_id( struct cell *t )
  143. {
  144. struct sip_msg *p_msg;
  145. int size;
  146. char *c;
  147. unsigned int myrand;
  148. if (!syn_branch) {
  149. p_msg=t->uas.request;
  150. if (p_msg) {
  151. /* char value of a proxied transaction is
  152. calculated out of header-fields forming
  153. transaction key
  154. */
  155. char_msg_val( p_msg, t->md5 );
  156. } else {
  157. /* char value for a UAC transaction is created
  158. randomly -- UAC is an originating stateful element
  159. which cannot be refreshed, so the value can be
  160. anything
  161. */
  162. /* HACK : not long enough */
  163. myrand=rand();
  164. c=t->md5;
  165. size=MD5_LEN;
  166. memset(c, '0', size );
  167. int2reverse_hex( &c, &size, myrand );
  168. }
  169. }
  170. }
  171. static void inline init_branches(struct cell *t)
  172. {
  173. unsigned int i;
  174. struct ua_client *uac;
  175. for(i=0;i<MAX_BRANCHES;i++)
  176. {
  177. uac=&t->uac[i];
  178. uac->request.my_T = t;
  179. uac->request.branch = i;
  180. #ifdef EXTRA_DEBUG
  181. uac->request.fr_timer.tg = TG_FR;
  182. uac->request.retr_timer.tg = TG_RT;
  183. #endif
  184. uac->local_cancel=uac->request;
  185. }
  186. }
  187. struct cell* build_cell( struct sip_msg* p_msg )
  188. {
  189. struct cell* new_cell;
  190. int sip_msg_len;
  191. struct usr_avp **old;
  192. /* allocs a new cell */
  193. new_cell = (struct cell*)shm_malloc( sizeof( struct cell ) );
  194. if ( !new_cell ) {
  195. ser_error=E_OUT_OF_MEM;
  196. return NULL;
  197. }
  198. /* filling with 0 */
  199. memset( new_cell, 0, sizeof( struct cell ) );
  200. /* UAS */
  201. #ifdef EXTRA_DEBUG
  202. new_cell->uas.response.retr_timer.tg=TG_RT;
  203. new_cell->uas.response.fr_timer.tg=TG_FR;
  204. #endif
  205. new_cell->uas.response.my_T=new_cell;
  206. /* move the current avp list to transaction -bogdan */
  207. old = set_avp_list( &new_cell->user_avps );
  208. new_cell->user_avps = *old;
  209. *old = 0;
  210. /* enter callback, which may potentially want to parse some stuff,
  211. * before the request is shmem-ized */
  212. if ( p_msg && has_reqin_tmcbs() )
  213. run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD);
  214. if (p_msg) {
  215. /* clean possible previous added vias/clen header or else they would
  216. * get propagated in the failure routes */
  217. free_via_clen_lump(&p_msg->add_rm);
  218. new_cell->uas.request = sip_msg_cloner(p_msg,&sip_msg_len);
  219. if (!new_cell->uas.request)
  220. goto error;
  221. new_cell->uas.end_request=((char*)new_cell->uas.request)+sip_msg_len;
  222. }
  223. /* UAC */
  224. init_branches(new_cell);
  225. new_cell->relaied_reply_branch = -1;
  226. /* new_cell->T_canceled = T_UNDEFINED; */
  227. #ifdef EXTRA_DEBUG
  228. new_cell->wait_tl.tg=TG_WT;
  229. new_cell->dele_tl.tg=TG_DEL;
  230. #endif
  231. init_synonym_id(new_cell);
  232. init_cell_lock( new_cell );
  233. return new_cell;
  234. error:
  235. shm_free(new_cell);
  236. /* unlink transaction AVP list and link back the global AVP list (bogdan)*/
  237. reset_avps();
  238. return NULL;
  239. }
  240. /* Release all the data contained by the hash table. All the aux. structures
  241. * as sems, lists, etc, are also released */
  242. void free_hash_table( )
  243. {
  244. struct cell* p_cell;
  245. struct cell* tmp_cell;
  246. int i;
  247. if (tm_table)
  248. {
  249. /* remove the data contained by each entry */
  250. for( i = 0 ; i<TABLE_ENTRIES; i++)
  251. {
  252. release_entry_lock( (tm_table->entrys)+i );
  253. /* delete all synonyms at hash-collision-slot i */
  254. p_cell=tm_table->entrys[i].first_cell;
  255. for( ; p_cell; p_cell = tmp_cell )
  256. {
  257. tmp_cell = p_cell->next_cell;
  258. free_cell( p_cell );
  259. }
  260. }
  261. shm_free(tm_table);
  262. }
  263. }
  264. /*
  265. */
  266. struct s_table* init_hash_table()
  267. {
  268. int i;
  269. /*allocs the table*/
  270. tm_table= (struct s_table*)shm_malloc( sizeof( struct s_table ) );
  271. if ( !tm_table) {
  272. LOG(L_ERR, "ERROR: init_hash_table: no shmem for TM table\n");
  273. goto error0;
  274. }
  275. memset( tm_table, 0, sizeof (struct s_table ) );
  276. /* try first allocating all the structures needed for syncing */
  277. if (lock_initialize()==-1)
  278. goto error1;
  279. /* inits the entrys */
  280. for( i=0 ; i<TABLE_ENTRIES; i++ )
  281. {
  282. init_entry_lock( tm_table, (tm_table->entrys)+i );
  283. tm_table->entrys[i].next_label = rand();
  284. }
  285. return tm_table;
  286. error1:
  287. free_hash_table( );
  288. error0:
  289. return 0;
  290. }
  291. /* Takes an already created cell and links it into hash table on the
  292. * appropriate entry. */
  293. void insert_into_hash_table_unsafe( struct cell * p_cell, unsigned int _hash )
  294. {
  295. struct entry* p_entry;
  296. p_cell->hash_index=_hash;
  297. /* locates the appropriate entry */
  298. p_entry = &tm_table->entrys[ _hash ];
  299. p_cell->label = p_entry->next_label++;
  300. if ( p_entry->last_cell )
  301. {
  302. p_entry->last_cell->next_cell = p_cell;
  303. p_cell->prev_cell = p_entry->last_cell;
  304. } else p_entry->first_cell = p_cell;
  305. p_entry->last_cell = p_cell;
  306. /* update stats */
  307. p_entry->cur_entries++;
  308. p_entry->acc_entries++;
  309. t_stats_new( is_local(p_cell) );
  310. }
  311. #ifdef _OBSOLETED
  312. void insert_into_hash_table( struct cell * p_cell)
  313. {
  314. LOCK_HASH(p_cell->hash_index);
  315. insert_into_hash_table_unsafe( p_cell );
  316. UNLOCK_HASH(p_cell->hash_index);
  317. }
  318. #endif
  319. /* Un-link a cell from hash_table, but the cell itself is not released */
  320. void remove_from_hash_table_unsafe( struct cell * p_cell)
  321. {
  322. struct entry* p_entry = &(tm_table->entrys[p_cell->hash_index]);
  323. /* unlink the cell from entry list */
  324. /* lock( &(p_entry->mutex) ); */
  325. if ( p_cell->prev_cell )
  326. p_cell->prev_cell->next_cell = p_cell->next_cell;
  327. else
  328. p_entry->first_cell = p_cell->next_cell;
  329. if ( p_cell->next_cell )
  330. p_cell->next_cell->prev_cell = p_cell->prev_cell;
  331. else
  332. p_entry->last_cell = p_cell->prev_cell;
  333. /* update stats */
  334. # ifdef EXTRA_DEBUG
  335. if (p_entry->cur_entries==0) {
  336. LOG(L_CRIT, "BUG: bad things happened: cur_entries=0\n");
  337. abort();
  338. }
  339. # endif
  340. p_entry->cur_entries--;
  341. t_stats_deleted( is_local(p_cell) );
  342. /* unlock( &(p_entry->mutex) ); */
  343. }
  344. /* print accumulated distribution of the hash table */
  345. int fifo_hash( FILE *stream, char *response_file )
  346. {
  347. FILE *reply_file;
  348. unsigned int i;
  349. reply_file=open_reply_pipe(response_file);
  350. if (reply_file==0) {
  351. LOG(L_ERR, "ERROR: fifo_hash: file '%s' not opened\n",
  352. response_file);
  353. return -1;
  354. }
  355. fputs( "200 ok\n\tcurrent\ttotal\n", reply_file);
  356. for (i=0; i<TABLE_ENTRIES; i++) {
  357. fprintf(reply_file, "%d.\t%lu\t%lu\n",
  358. i, tm_table->entrys[i].cur_entries ,
  359. tm_table->entrys[i].acc_entries );
  360. }
  361. fclose(reply_file);
  362. return 1;
  363. }
  364. int unixsock_hash(str* msg)
  365. {
  366. unsigned int i, ret;
  367. ret = 0;
  368. unixsock_reply_asciiz( "200 OK\n\tcurrent\ttotal\n");
  369. for (i = 0; i < TABLE_ENTRIES; i++) {
  370. if (unixsock_reply_printf("%d.\t%lu\t%lu\n",
  371. i, tm_table->entrys[i].cur_entries,
  372. tm_table->entrys[i].acc_entries
  373. ) < 0) {
  374. unixsock_reply_reset();
  375. unixsock_reply_asciiz("500 Error while creating reply\n");
  376. ret = -1;
  377. break;
  378. }
  379. }
  380. if (unixsock_reply_send() < 0) {
  381. ret = -1;
  382. }
  383. return ret;
  384. }