h_table.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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. #include "../../mem/shm_mem.h"
  28. #include "../../hash_func.h"
  29. #include "h_table.h"
  30. #include "../../dprint.h"
  31. #include "../../md5utils.h"
  32. /* bogdan test */
  33. #include "../../ut.h"
  34. #include "../../globals.h"
  35. #include "../../error.h"
  36. #include "t_reply.h"
  37. #include "t_cancel.h"
  38. #include "t_stats.h"
  39. /* pointer to the big table where all the transaction data
  40. lives
  41. */
  42. static struct s_table* tm_table;
  43. void lock_hash(int i)
  44. {
  45. lock(&tm_table->entrys[i].mutex);
  46. }
  47. void unlock_hash(int i)
  48. {
  49. unlock(&tm_table->entrys[i].mutex);
  50. }
  51. struct s_table* get_tm_table()
  52. {
  53. return tm_table;
  54. }
  55. unsigned int transaction_count( void )
  56. {
  57. unsigned int i;
  58. unsigned int count;
  59. count=0;
  60. for (i=0; i<TABLE_ENTRIES; i++)
  61. count+=tm_table->entrys[i].entries;
  62. return count;
  63. }
  64. void free_cell( struct cell* dead_cell )
  65. {
  66. char *b;
  67. int i;
  68. struct sip_msg *rpl;
  69. release_cell_lock( dead_cell );
  70. shm_lock();
  71. /* UA Server */
  72. if ( dead_cell->uas.request )
  73. sip_msg_free_unsafe( dead_cell->uas.request );
  74. if ( dead_cell->uas.response.buffer )
  75. shm_free_unsafe( dead_cell->uas.response.buffer );
  76. if (dead_cell->uas.to_tag.s)
  77. shm_free_unsafe(dead_cell->uas.to_tag.s);
  78. /* completion callback */
  79. if (dead_cell->cbp) shm_free_unsafe(dead_cell->cbp);
  80. /* UA Clients */
  81. for ( i =0 ; i<dead_cell->nr_of_outgoings; i++ )
  82. {
  83. /* retransmission buffer */
  84. if ( (b=dead_cell->uac[i].request.buffer) )
  85. shm_free_unsafe( b );
  86. #ifdef OLD_CANCEL
  87. if ( (b=dead_cell->uac[i].request.ack) )
  88. shm_free_unsafe( b );
  89. if ( (b=dead_cell->uac[i].request.cancel) )
  90. shm_free_unsafe( b );
  91. #endif
  92. b=dead_cell->uac[i].local_cancel.buffer;
  93. if (b!=0 && b!=BUSY_BUFFER)
  94. shm_free_unsafe( b );
  95. rpl=dead_cell->uac[i].reply;
  96. if (rpl && rpl!=FAKED_REPLY) {
  97. sip_msg_free_unsafe( rpl );
  98. }
  99. #ifdef _OBSOLETED
  100. if ( (b=dead_cell->uac[i].rpl_buffer.s) )
  101. shm_free_unsafe( b );
  102. #endif
  103. }
  104. /* the cell's body */
  105. shm_free_unsafe( dead_cell );
  106. shm_unlock();
  107. }
  108. struct cell* build_cell( struct sip_msg* p_msg )
  109. {
  110. struct cell* new_cell;
  111. unsigned int i;
  112. unsigned int rand;
  113. int size;
  114. char *c;
  115. struct ua_client *uac;
  116. /* avoid 'unitialized var use' warning */
  117. rand=0;
  118. /* allocs a new cell */
  119. new_cell = (struct cell*)shm_malloc( sizeof( struct cell ) );
  120. if ( !new_cell ) {
  121. ser_error=E_OUT_OF_MEM;
  122. return NULL;
  123. }
  124. /* filling with 0 */
  125. memset( new_cell, 0, sizeof( struct cell ) );
  126. /* UAS */
  127. new_cell->uas.response.retr_timer.tg=TG_RT;
  128. new_cell->uas.response.fr_timer.tg=TG_FR;
  129. new_cell->uas.response.fr_timer.payload =
  130. new_cell->uas.response.retr_timer.payload = &(new_cell->uas.response);
  131. new_cell->uas.response.my_T=new_cell;
  132. /* bogdan - debug */
  133. /*fprintf(stderr,"before clone VIA |%.*s|\n",via_len(p_msg->via1),
  134. via_s(p_msg->via1,p_msg));*/
  135. if (p_msg) {
  136. new_cell->uas.request = sip_msg_cloner(p_msg);
  137. if (!new_cell->uas.request)
  138. goto error;
  139. }
  140. /* new_cell->uas.to_tag = &( get_to(new_cell->uas.request)->tag_value ); */
  141. new_cell->uas.response.my_T = new_cell;
  142. /* UAC */
  143. for(i=0;i<MAX_BRANCHES;i++)
  144. {
  145. uac=&new_cell->uac[i];
  146. uac->request.my_T = new_cell;
  147. uac->request.branch = i;
  148. uac->request.fr_timer.tg = TG_FR;
  149. uac->request.retr_timer.tg = TG_RT;
  150. uac->request.retr_timer.payload =
  151. uac->request.fr_timer.payload =
  152. &uac->request;
  153. uac->local_cancel=uac->request;
  154. }
  155. /* global data for transaction */
  156. if (p_msg) {
  157. new_cell->hash_index = p_msg->hash_index;
  158. } else {
  159. rand = random();
  160. new_cell->hash_index = rand % TABLE_ENTRIES ;
  161. }
  162. new_cell->wait_tl.payload = new_cell;
  163. new_cell->dele_tl.payload = new_cell;
  164. new_cell->relaied_reply_branch = -1;
  165. /* new_cell->T_canceled = T_UNDEFINED; */
  166. new_cell->wait_tl.tg=TG_WT;
  167. new_cell->dele_tl.tg=TG_DEL;
  168. if (!syn_branch) {
  169. if (p_msg) {
  170. /* char value of a proxied transaction is
  171. calculated out of header-fileds forming
  172. transaction key
  173. */
  174. char_msg_val( p_msg, new_cell->md5 );
  175. } else {
  176. /* char value for a UAC transaction is created
  177. randomly -- UAC is an originating stateful element
  178. which cannot be refreshed, so the value can be
  179. anything
  180. */
  181. /* HACK : not long enough */
  182. c=new_cell->md5;
  183. size=MD5_LEN;
  184. memset(c, '0', size );
  185. int2reverse_hex( &c, &size, rand );
  186. }
  187. }
  188. init_cell_lock( new_cell );
  189. return new_cell;
  190. error:
  191. shm_free(new_cell);
  192. return NULL;
  193. }
  194. /* Release all the data contained by the hash table. All the aux. structures
  195. * as sems, lists, etc, are also released */
  196. void free_hash_table( )
  197. {
  198. struct cell* p_cell;
  199. struct cell* tmp_cell;
  200. int i;
  201. if (tm_table)
  202. {
  203. /* remove the data contained by each entry */
  204. for( i = 0 ; i<TABLE_ENTRIES; i++)
  205. {
  206. release_entry_lock( (tm_table->entrys)+i );
  207. /* delete all synonyms at hash-collision-slot i */
  208. p_cell=tm_table->entrys[i].first_cell;
  209. for( ; p_cell; p_cell = tmp_cell )
  210. {
  211. tmp_cell = p_cell->next_cell;
  212. free_cell( p_cell );
  213. }
  214. }
  215. }
  216. }
  217. /*
  218. */
  219. struct s_table* init_hash_table()
  220. {
  221. int i;
  222. /*allocs the table*/
  223. tm_table= (struct s_table*)shm_malloc( sizeof( struct s_table ) );
  224. if ( !tm_table) {
  225. LOG(L_ERR, "ERROR: init_hash_table: no shmem for TM table\n");
  226. goto error0;
  227. }
  228. memset( tm_table, 0, sizeof (struct s_table ) );
  229. /* try first allocating all the structures needed for syncing */
  230. if (lock_initialize()==-1)
  231. goto error1;
  232. /* inits the entrys */
  233. for( i=0 ; i<TABLE_ENTRIES; i++ )
  234. {
  235. init_entry_lock( tm_table, (tm_table->entrys)+i );
  236. tm_table->entrys[i].next_label = rand();
  237. }
  238. return tm_table;
  239. #ifdef _OBSO
  240. error2:
  241. lock_cleanup();
  242. #endif
  243. error1:
  244. free_hash_table( );
  245. error0:
  246. return 0;
  247. }
  248. /* Takes an already created cell and links it into hash table on the
  249. * appropiate entry. */
  250. void insert_into_hash_table_unsafe( struct cell * p_cell )
  251. {
  252. struct entry* p_entry;
  253. /* locates the apropiate entry */
  254. p_entry = &tm_table->entrys[ p_cell->hash_index ];
  255. p_cell->label = p_entry->next_label++;
  256. if ( p_entry->last_cell )
  257. {
  258. p_entry->last_cell->next_cell = p_cell;
  259. p_cell->prev_cell = p_entry->last_cell;
  260. } else p_entry->first_cell = p_cell;
  261. p_entry->last_cell = p_cell;
  262. /* update stats */
  263. p_entry->entries++;
  264. cur_stats->transactions++;
  265. acc_stats->transactions++;
  266. if (p_cell->local) {
  267. cur_stats->client_transactions++;
  268. acc_stats->client_transactions++;
  269. }
  270. }
  271. void insert_into_hash_table( struct cell * p_cell)
  272. {
  273. LOCK_HASH(p_cell->hash_index);
  274. insert_into_hash_table_unsafe( p_cell );
  275. UNLOCK_HASH(p_cell->hash_index);
  276. }
  277. /* Un-link a cell from hash_table, but the cell itself is not released */
  278. void remove_from_hash_table_unsafe( struct cell * p_cell)
  279. {
  280. struct entry* p_entry = &(tm_table->entrys[p_cell->hash_index]);
  281. /* unlink the cell from entry list */
  282. /* lock( &(p_entry->mutex) ); */
  283. if ( p_cell->prev_cell )
  284. p_cell->prev_cell->next_cell = p_cell->next_cell;
  285. else
  286. p_entry->first_cell = p_cell->next_cell;
  287. if ( p_cell->next_cell )
  288. p_cell->next_cell->prev_cell = p_cell->prev_cell;
  289. else
  290. p_entry->last_cell = p_cell->prev_cell;
  291. /* update stats */
  292. p_entry->entries--;
  293. cur_stats->transactions--;
  294. if (p_cell->local) cur_stats->client_transactions--;
  295. cur_stats->waiting--;
  296. /* unlock( &(p_entry->mutex) ); */
  297. }