7570a830f56880585470d9b0a63bd6887640cae9
[sip-router] / modules / tm / h_table.c
1 /*
2  * $Id$
3  */
4
5 #include "hash_func.h"
6 #include "h_table.h"
7 #include "../../dprint.h"
8 #include "sh_malloc.h"
9
10
11 /*   Frees the all the containes of a cell and the cell's body itself
12   */
13 void free_cell( struct cell* dead_cell )
14 {
15         int i;
16         struct retrans_buff* rb;
17         char *b;
18
19         DBG("DEBUG: free_cell: start\n");
20         /* UA Server */
21         DBG("DEBUG: free_cell: inbound request %p\n",dead_cell->inbound_request);
22         if ( dead_cell->inbound_request )
23                 sip_msg_free( dead_cell->inbound_request );
24         DBG("DEBUG: free_cell: outbound response %p\n",dead_cell->outbound_response);
25         if (b=dead_cell->outbound_response.retr_buffer) sh_free( b );
26
27         /* UA Clients */
28         for ( i =0 ; i<dead_cell->nr_of_outgoings;  i++ )
29         {
30                 /* outbound requests*/
31                 DBG("DEBUG: free_cell: outbound_request[%d] %p\n",i,dead_cell->outbound_request[i]);
32                 if ( rb=dead_cell->outbound_request[i] )
33                 {
34                         if (rb->retr_buffer) sh_free( rb->retr_buffer );
35                         dead_cell->outbound_request[i] = NULL;
36                         sh_free( rb );
37                 }
38                 /* outbound requests*/
39                 DBG("DEBUG: free_cell: inbound_response[%d] %p\n",i,dead_cell->inbound_response[i]);
40                 if ( dead_cell -> inbound_response[i] )
41                         sip_msg_free( dead_cell->inbound_response[i] );
42         }
43         /* mutex */
44         /* release_cell_lock( dead_cell ); */
45         /* the cell's body */
46         sh_free( dead_cell );
47         DBG("DEBUG: free_cell: done\n");
48 }
49
50
51
52
53 /* Release all the data contained by the hash table. All the aux. structures
54   *  as sems, lists, etc, are also released
55   */
56 void free_hash_table( struct s_table *hash_table )
57 {
58    struct cell* p_cell;
59    struct cell* tmp_cell;
60    int   i;
61
62    if (hash_table)
63    {
64       /* remove the data contained by each entry */
65       for( i = 0 ; i<TABLE_ENTRIES; i++)
66       {
67          release_entry_lock( (hash_table->entrys)+i );
68          /* delete all synonyms at hash-collision-slot i */
69          for( p_cell = hash_table->entrys[i].first_cell; p_cell; p_cell = tmp_cell )
70          {
71             tmp_cell = p_cell->next_cell;
72             free_cell( p_cell );
73          }
74       }
75
76       /* the mutexs for sync the lists are released*/
77       for ( i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
78          release_timerlist_lock( &(hash_table->timers[i]) );
79
80       sh_free( hash_table );
81    }
82 }
83
84
85
86
87 /*
88   */
89 struct s_table* init_hash_table()
90 {
91    struct s_table*  hash_table;
92    pthread_t  thread;
93    int       i;
94
95    /*allocs the table*/
96    hash_table = (struct s_table*)sh_malloc( sizeof( struct s_table ) );
97    if ( !hash_table )
98       goto error;
99
100    memset( hash_table, 0, sizeof (struct s_table ) );
101
102    /* try first allocating all the structures needed for syncing */
103    if (lock_initialize()==-1)
104      goto error;
105
106    /* inits the entrys */
107    for(  i=0 ; i<TABLE_ENTRIES; i++ )
108       init_entry_lock( hash_table , (hash_table->entrys)+i );
109
110    /* inits the timers*/
111    for(  i=0 ; i<NR_OF_TIMER_LISTS ; i++ )
112       init_timer_list( hash_table, i );
113
114    return  hash_table;
115
116 error:
117    free_hash_table( hash_table );
118    lock_cleanup();
119    return 0;
120 }
121
122
123
124 struct cell*  build_cell( struct sip_msg* p_msg )
125 {
126    struct cell*  new_cell;
127    int                i;
128
129     DBG("DEBUG: build_cell : start\n");
130     /* do we have the source for the build process? */
131    if (!p_msg)
132       return NULL;
133
134    /* allocs a new cell */
135    new_cell = (struct cell*)sh_malloc( sizeof( struct cell ) );
136    DBG("DEBUG: build_cell : malloc done\n");
137    if  ( !new_cell )
138       return NULL;
139
140    /* filling with 0 */
141    memset( new_cell, 0, sizeof( struct cell ) );
142    /* hash index of the entry */
143    new_cell->hash_index = hash( p_msg->callid->body , get_cseq(p_msg)->number );
144    /* mutex */
145    /* ref counter is 0 */
146    /* all pointers from timers list tl are NULL */
147    new_cell->wait_tl.payload = new_cell;
148    new_cell->dele_tl.payload = new_cell;
149
150    /* inbound request */
151    /* force parsing all the needed headers*/
152    if (parse_headers(p_msg, HDR_EOH )==-1)
153         goto error;
154    new_cell->inbound_request =  sip_msg_cloner(p_msg) ;
155    DBG("DEBUG: build_cell : clone done\n");
156    if (!new_cell->inbound_request)
157         goto error;
158    /* inbound response is NULL*/
159    /* status is 0 */
160    /* tag pointer is NULL */
161    //if ( p_msg->tag )      TO DO !!!!!!!!!!!!!!!!!!!!!!
162    //   new_cell->tag  =  &(new_cell->inbound_request->tag->body);
163    /* nr of outbound requests is 0 */
164    /* all pointers from outbound_request array are NULL */
165    /* all pointers from outbound_response array are NULL */
166    /*init the links with the canceled / canceler transaction */
167    new_cell->relaied_reply_branch   = -1;
168    new_cell->T_canceled  = T_UNDEFINED;
169    new_cell->T_canceler  = T_UNDEFINED;
170
171    /* init_cell_lock(  new_cell ); */
172
173    DBG("DEBUG: build_cell : done\n");
174    return new_cell;
175
176 error:
177         sh_free(new_cell);
178         return NULL;
179 }
180
181
182
183
184 /*  Takes an already created cell and links it into hash table on the
185   *  appropiate entry.
186   */
187 void    insert_into_hash_table( struct s_table *hash_table,  struct cell * p_cell )
188 {
189    struct entry* p_entry;
190
191    /* do we have or not something to insert? */
192    if (!p_cell)
193       return;
194
195    /* locates the apropiate entry */
196    p_entry = &hash_table->entrys[ p_cell->hash_index ];
197
198    /* critical region - inserting the cell at the end of the list */
199    lock( p_entry->mutex );
200
201    p_cell->label = p_entry->next_label++;
202    if ( p_entry->last_cell )
203    {
204       p_entry->last_cell->next_cell = p_cell;
205       p_cell->prev_cell = p_entry->last_cell;
206    }
207    else
208       p_entry->first_cell = p_cell;
209    p_entry->last_cell = p_cell;
210
211    unlock( p_entry->mutex );
212 }
213
214
215
216
217 /*  Un-link a  cell from hash_table, but the cell itself is not released
218   */
219 void remove_from_hash_table( struct s_table *hash_table,  struct cell * p_cell )
220 {
221    struct entry*  p_entry  = &(hash_table->entrys[p_cell->hash_index]);
222
223    /*update the canceler and canceled links*/
224    if ( p_cell->T_canceled!=T_NULL && p_cell->T_canceled!=T_UNDEFINED)
225       p_cell->T_canceled->T_canceler = T_NULL;
226    if ( p_cell->T_canceler!=T_NULL && p_cell->T_canceler!=T_UNDEFINED)
227       p_cell->T_canceler->T_canceled = T_NULL;
228
229    /* unlink the cell from entry list */
230    lock( p_entry->mutex );
231
232    if ( p_cell->prev_cell )
233       p_cell->prev_cell->next_cell = p_cell->next_cell;
234    else
235       p_entry->first_cell = p_cell->next_cell;
236
237    if ( p_cell->next_cell )
238       p_cell->next_cell->prev_cell = p_cell->prev_cell;
239    else
240       p_entry->last_cell = p_cell->prev_cell;
241
242    unlock( p_entry->mutex );
243 }
244
245
246
247
248
249