h_table.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #include <stdlib.h>
00051
00052
00053 #include "../../mem/shm_mem.h"
00054 #include "../../hash_func.h"
00055 #include "../../dprint.h"
00056 #include "../../md5utils.h"
00057 #include "../../ut.h"
00058 #include "../../error.h"
00059 #include "t_reply.h"
00060 #include "t_cancel.h"
00061 #include "t_stats.h"
00062 #include "h_table.h"
00063 #include "fix_lumps.h"
00064 #include "t_hooks.h"
00065 #include "t_fwd.h"
00066
00067 static enum kill_reason kr;
00068
00069
00070
00071 static struct s_table* tm_table;
00072
00073 int syn_branch = 1;
00074
00075
00076 void reset_kr(void)
00077 {
00078 kr = 0;
00079 }
00080
00081 void set_kr( enum kill_reason _kr )
00082 {
00083 kr|=_kr;
00084 }
00085
00086
00087 enum kill_reason get_kr(void) {
00088 return kr;
00089 }
00090
00091
00092 void lock_hash(int i)
00093 {
00094 lock(&tm_table->entrys[i].mutex);
00095 }
00096
00097
00098 void unlock_hash(int i)
00099 {
00100 unlock(&tm_table->entrys[i].mutex);
00101 }
00102
00103
00104 struct s_table* get_tm_table(void)
00105 {
00106 return tm_table;
00107 }
00108
00109
00110 unsigned int transaction_count( void )
00111 {
00112 unsigned int i;
00113 unsigned int count;
00114
00115 count=0;
00116 for (i=0; i<TM_TABLE_ENTRIES; i++)
00117 count+=tm_table->entrys[i].cur_entries;
00118 return count;
00119 }
00120
00121
00122
00123 void free_cell( struct cell* dead_cell )
00124 {
00125 char *b;
00126 int i;
00127 struct sip_msg *rpl;
00128 struct totag_elem *tt, *foo;
00129 struct proxy_l *p;
00130
00131 if ( has_tran_tmcbs( dead_cell, TMCB_TRANS_DELETED) )
00132 run_trans_callbacks( TMCB_TRANS_DELETED, dead_cell, 0, 0, 0);
00133
00134 empty_tmcb_list(&dead_cell->tmcb_hl);
00135
00136 shm_lock();
00137
00138
00139 if ( dead_cell->uas.request )
00140 sip_msg_free_unsafe( dead_cell->uas.request );
00141 if ( dead_cell->uas.response.buffer.s )
00142 shm_free_unsafe( dead_cell->uas.response.buffer.s );
00143
00144
00145 for ( i =0 ; i<dead_cell->nr_of_outgoings; i++ )
00146 {
00147
00148 if ( (b=dead_cell->uac[i].request.buffer.s) )
00149 shm_free_unsafe( b );
00150 b=dead_cell->uac[i].local_cancel.buffer.s;
00151 if (b!=0 && b!=BUSY_BUFFER)
00152 shm_free_unsafe( b );
00153 rpl=dead_cell->uac[i].reply;
00154 if (rpl && rpl!=FAKED_REPLY && rpl->msg_flags&FL_SHM_CLONE) {
00155 sip_msg_free_unsafe( rpl );
00156 }
00157 if ( (p=dead_cell->uac[i].proxy)!=NULL ) {
00158 if ( p->host.h_addr_list )
00159 shm_free_unsafe( p->host.h_addr_list );
00160 if ( p->dn ) {
00161 if ( p->dn->kids )
00162 shm_free_unsafe( p->dn->kids );
00163 shm_free_unsafe( p->dn );
00164 }
00165 shm_free_unsafe(p);
00166 }
00167 if (dead_cell->uac[i].path_vec.s) {
00168 shm_free_unsafe(dead_cell->uac[i].path_vec.s);
00169 }
00170 }
00171
00172
00173 tt=dead_cell->fwded_totags;
00174 while(tt) {
00175 foo=tt->next;
00176 shm_free_unsafe(tt->tag.s);
00177 shm_free_unsafe(tt);
00178 tt=foo;
00179 }
00180
00181
00182 if (dead_cell->user_avps)
00183 destroy_avp_list_unsafe( &dead_cell->user_avps );
00184
00185
00186 shm_free_unsafe( dead_cell );
00187
00188 shm_unlock();
00189 }
00190
00191
00192
00193 static inline void init_synonym_id( struct cell *t )
00194 {
00195 struct sip_msg *p_msg;
00196 int size;
00197 char *c;
00198 unsigned int myrand;
00199
00200 if (!syn_branch) {
00201 p_msg=t->uas.request;
00202 if (p_msg) {
00203
00204
00205
00206
00207 char_msg_val( p_msg, t->md5 );
00208 } else {
00209
00210
00211
00212
00213
00214
00215 myrand=rand();
00216 c=t->md5;
00217 size=MD5_LEN;
00218 memset(c, '0', size );
00219 int2reverse_hex( &c, &size, myrand );
00220 }
00221 }
00222 }
00223
00224 static inline void init_branches(struct cell *t)
00225 {
00226 unsigned int i;
00227 struct ua_client *uac;
00228
00229 for(i=0;i<MAX_BRANCHES;i++)
00230 {
00231 uac=&t->uac[i];
00232 uac->request.my_T = t;
00233 uac->request.branch = i;
00234 #ifdef EXTRA_DEBUG
00235 uac->request.fr_timer.tg = TG_FR;
00236 uac->request.retr_timer.tg = TG_RT;
00237 #endif
00238 uac->local_cancel=uac->request;
00239 }
00240 }
00241
00242
00243 struct cell* build_cell( struct sip_msg* p_msg )
00244 {
00245 struct cell* new_cell;
00246 int sip_msg_len;
00247 struct usr_avp **old;
00248 struct tm_callback *cbs, *cbs_tmp;
00249
00250
00251 new_cell = (struct cell*)shm_malloc( sizeof( struct cell ) );
00252 if ( !new_cell ) {
00253 ser_error=E_OUT_OF_MEM;
00254 return NULL;
00255 }
00256
00257
00258 memset( new_cell, 0, sizeof( struct cell ) );
00259
00260
00261 #ifdef EXTRA_DEBUG
00262 new_cell->uas.response.retr_timer.tg=TG_RT;
00263 new_cell->uas.response.fr_timer.tg=TG_FR;
00264 #endif
00265 new_cell->uas.response.my_T=new_cell;
00266
00267
00268
00269 if(p_msg) {
00270
00271 old = set_avp_list( &new_cell->user_avps );
00272 new_cell->user_avps = *old;
00273 *old = 0;
00274
00275
00276 if (p_msg->id==tmcb_pending_id) {
00277 new_cell->tmcb_hl = tmcb_pending_hl;
00278 tmcb_pending_hl.first = 0;
00279 }
00280
00281
00282
00283 if (has_reqin_tmcbs() )
00284 run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD);
00285
00286
00287
00288 free_via_clen_lump(&p_msg->add_rm);
00289 new_cell->uas.request = sip_msg_cloner(p_msg,&sip_msg_len);
00290 if (!new_cell->uas.request)
00291 goto error;
00292 new_cell->uas.end_request=((char*)new_cell->uas.request)+sip_msg_len;
00293 }
00294
00295
00296 init_branches(new_cell);
00297
00298 new_cell->relayed_reply_branch = -1;
00299
00300 #ifdef EXTRA_DEBUG
00301 new_cell->wait_tl.tg=TG_WT;
00302 new_cell->dele_tl.tg=TG_DEL;
00303 #endif
00304
00305 init_synonym_id(new_cell);
00306 init_cell_lock( new_cell );
00307 return new_cell;
00308
00309 error:
00310 if (new_cell->user_avps)
00311 destroy_avp_list( &new_cell->user_avps );
00312 if (new_cell->tmcb_hl.first) {
00313 for( cbs=new_cell->tmcb_hl.first ; cbs ; ) {
00314 cbs_tmp = cbs;
00315 cbs = cbs->next;
00316 shm_free( cbs_tmp );
00317 }
00318 }
00319 shm_free(new_cell);
00320
00321 reset_avps();
00322 return NULL;
00323 }
00324
00325
00326
00327
00328
00329 void free_hash_table(void)
00330 {
00331 struct cell* p_cell;
00332 struct cell* tmp_cell;
00333 int i;
00334
00335 if (tm_table)
00336 {
00337
00338 for( i = 0 ; i<TM_TABLE_ENTRIES; i++)
00339 {
00340
00341 p_cell=tm_table->entrys[i].first_cell;
00342 for( ; p_cell; p_cell = tmp_cell )
00343 {
00344 tmp_cell = p_cell->next_cell;
00345 free_cell( p_cell );
00346 }
00347 }
00348 shm_free(tm_table);
00349 }
00350 }
00351
00352
00353
00354
00355 struct s_table* init_hash_table(void)
00356 {
00357 int i;
00358
00359
00360 tm_table= (struct s_table*)shm_malloc( sizeof( struct s_table ) );
00361 if ( !tm_table) {
00362 LM_ERR("no more share memory\n");
00363 goto error0;
00364 }
00365
00366 memset( tm_table, 0, sizeof (struct s_table ) );
00367
00368
00369 if (lock_initialize()==-1)
00370 goto error1;
00371
00372
00373 for( i=0 ; i<TM_TABLE_ENTRIES; i++ )
00374 {
00375 init_entry_lock( tm_table, (tm_table->entrys)+i );
00376 tm_table->entrys[i].next_label = rand();
00377 }
00378
00379 return tm_table;
00380
00381 error1:
00382 free_hash_table( );
00383 error0:
00384 return 0;
00385 }
00386
00387
00388
00389
00390 void insert_into_hash_table_unsafe( struct cell * p_cell, unsigned int _hash )
00391 {
00392 struct entry* p_entry;
00393
00394 p_cell->hash_index=_hash;
00395
00396
00397 p_entry = &tm_table->entrys[ _hash ];
00398
00399 p_cell->label = p_entry->next_label++;
00400 if ( p_entry->last_cell )
00401 {
00402 p_entry->last_cell->next_cell = p_cell;
00403 p_cell->prev_cell = p_entry->last_cell;
00404 } else p_entry->first_cell = p_cell;
00405
00406 p_entry->last_cell = p_cell;
00407
00408
00409 p_entry->cur_entries++;
00410 p_entry->acc_entries++;
00411 stats_trans_new( is_local(p_cell) );
00412 }
00413
00414
00415
00416 void remove_from_hash_table_unsafe( struct cell * p_cell)
00417 {
00418 struct entry* p_entry = &(tm_table->entrys[p_cell->hash_index]);
00419
00420 if ( p_cell->prev_cell )
00421 p_cell->prev_cell->next_cell = p_cell->next_cell;
00422 else
00423 p_entry->first_cell = p_cell->next_cell;
00424
00425 if ( p_cell->next_cell )
00426 p_cell->next_cell->prev_cell = p_cell->prev_cell;
00427 else
00428 p_entry->last_cell = p_cell->prev_cell;
00429 # ifdef EXTRA_DEBUG
00430 if (p_entry->cur_entries==0) {
00431 LM_CRIT("bad things happened: cur_entries=0\n");
00432 abort();
00433 }
00434 # endif
00435
00436 p_entry->cur_entries--;
00437 if_update_stat(tm_enable_stats, tm_trans_inuse , -1 );
00438 }