a7327d97cb107fb5ca937125b12ac4c7aac65c4f
[sip-router] / modules / tm / h_table.c
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  *    info@iptel.org
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  * 2006-08-11  dns failover support (andrei)
45  * 2007-05-16  callbacks called on destroy (andrei)
46  * 2007-06-06  don't allocate extra space for md5 if not used: syn_branch==1 
47  *              (andrei)
48  * 2007-06-06  switched tm bucket list to a simpler and faster clist (andrei)
49  */
50
51 #include <stdlib.h>
52
53
54 #include "../../mem/shm_mem.h"
55 #include "../../hash_func.h"
56 #include "../../dprint.h"
57 #include "../../md5utils.h"
58 #include "../../ut.h"
59 #include "../../globals.h"
60 #include "../../error.h"
61 #include "defs.h"
62 #include "t_reply.h"
63 #include "t_cancel.h"
64 #include "t_stats.h"
65 #include "h_table.h"
66 #include "../../fix_lumps.h" /* free_via_clen_lump */
67 #include "timer.h"
68 #include "uac.h" /* free_local_ack */
69
70
71 static enum kill_reason kr;
72
73 /* pointer to the big table where all the transaction data
74    lives */
75 struct s_table*  _tm_table;
76
77
78 void reset_kr() {
79         kr=0;
80 }
81
82 void set_kr( enum kill_reason _kr )
83 {
84         kr|=_kr;
85 }
86
87
88 enum kill_reason get_kr() {
89         return kr;
90 }
91
92
93 void lock_hash(int i) 
94 {
95         lock(&_tm_table->entries[i].mutex);
96 }
97
98
99 void unlock_hash(int i) 
100 {
101         unlock(&_tm_table->entries[i].mutex);
102 }
103
104
105
106 #ifdef TM_HASH_STATS
107 unsigned int transaction_count( void )
108 {
109         unsigned int i;
110         unsigned int count;
111
112         count=0;        
113         for (i=0; i<TABLE_ENTRIES; i++) 
114                 count+=_tm_table->entries[i].cur_entries;
115         return count;
116 }
117 #endif
118
119
120
121 void free_cell( struct cell* dead_cell )
122 {
123         char *b;
124         int i;
125         struct sip_msg *rpl;
126         struct totag_elem *tt, *foo;
127         struct tm_callback *cbs, *cbs_tmp;
128
129         release_cell_lock( dead_cell );
130         if (unlikely(has_tran_tmcbs(dead_cell, TMCB_DESTROY)))
131                 run_trans_callbacks(TMCB_DESTROY, dead_cell, 0, 0, 0);
132
133         shm_lock();
134         /* UA Server */
135         if ( dead_cell->uas.request )
136                 sip_msg_free_unsafe( dead_cell->uas.request );
137         if ( dead_cell->uas.response.buffer )
138                 shm_free_unsafe( dead_cell->uas.response.buffer );
139
140         /* callbacks */
141         for( cbs=(struct tm_callback*)dead_cell->tmcb_hl.first ; cbs ; ) {
142                 cbs_tmp = cbs;
143                 cbs = cbs->next;
144                 if (cbs_tmp->release) {
145                         /* It is safer to release the shm memory lock
146                          * otherwise the release function must to be aware of
147                          * the lock state (Miklos)
148                          */
149                         shm_unlock();
150                         cbs_tmp->release(cbs_tmp->param);
151                         shm_lock();
152                 }
153                 shm_free_unsafe( cbs_tmp );
154         }
155
156         /* UA Clients */
157         for ( i =0 ; i<dead_cell->nr_of_outgoings;  i++ )
158         {
159                 /* retransmission buffer */
160                 if ( (b=dead_cell->uac[i].request.buffer) )
161                         shm_free_unsafe( b );
162                 b=dead_cell->uac[i].local_cancel.buffer;
163                 if (b!=0 && b!=BUSY_BUFFER)
164                         shm_free_unsafe( b );
165                 rpl=dead_cell->uac[i].reply;
166                 if (rpl && rpl!=FAKED_REPLY && rpl->msg_flags&FL_SHM_CLONE) {
167                         sip_msg_free_unsafe( rpl );
168                 }
169 #ifdef USE_DNS_FAILOVER
170                 if (dead_cell->uac[i].dns_h.a){
171                         DBG("branch %d -> dns_h.srv (%.*s) ref=%d,"
172                                                         " dns_h.a (%.*s) ref=%d\n", i,
173                                         dead_cell->uac[i].dns_h.srv?
174                                                                 dead_cell->uac[i].dns_h.srv->name_len:0,
175                                         dead_cell->uac[i].dns_h.srv?
176                                                                 dead_cell->uac[i].dns_h.srv->name:"",
177                                         dead_cell->uac[i].dns_h.srv?
178                                                                 dead_cell->uac[i].dns_h.srv->refcnt.val:0,
179                                         dead_cell->uac[i].dns_h.a->name_len,
180                                         dead_cell->uac[i].dns_h.a->name,
181                                         dead_cell->uac[i].dns_h.a->refcnt.val);
182                 }
183                 dns_srv_handle_put_shm_unsafe(&dead_cell->uac[i].dns_h);
184 #endif
185                 if (unlikely(dead_cell->uac[i].path.s)) {
186                         shm_free_unsafe(dead_cell->uac[i].path.s);
187                 }
188         }
189
190 #ifdef WITH_AS_SUPPORT
191         if (dead_cell->uac[0].local_ack)
192                 free_local_ack_unsafe(dead_cell->uac[0].local_ack);
193 #endif
194
195         /* collected to tags */
196         tt=dead_cell->fwded_totags;
197         while(tt) {
198                 foo=tt->next;
199                 shm_free_unsafe(tt->tag.s);
200                 shm_free_unsafe(tt);
201                 tt=foo;
202         }
203
204         /* free the avp list */
205         if (dead_cell->user_avps_from)
206                 destroy_avp_list_unsafe( &dead_cell->user_avps_from );
207         if (dead_cell->user_avps_to)
208                 destroy_avp_list_unsafe( &dead_cell->user_avps_to );
209         if (dead_cell->uri_avps_from)
210                 destroy_avp_list_unsafe( &dead_cell->uri_avps_from );
211         if (dead_cell->uri_avps_to)
212                 destroy_avp_list_unsafe( &dead_cell->uri_avps_to );
213
214         /* the cell's body */
215         shm_free_unsafe( dead_cell );
216
217         shm_unlock();
218         t_stats_freed();
219 }
220
221
222
223 static inline void init_synonym_id( struct cell *t )
224 {
225         struct sip_msg *p_msg;
226         int size;
227         char *c;
228         unsigned int myrand;
229
230         if (!syn_branch) {
231                 p_msg=t->uas.request;
232                 if (p_msg) {
233                         /* char value of a proxied transaction is
234                            calculated out of header-fields forming
235                            transaction key
236                         */
237                         char_msg_val( p_msg, t->md5 );
238                 } else {
239                         /* char value for a UAC transaction is created
240                            randomly -- UAC is an originating stateful element 
241                            which cannot be refreshed, so the value can be
242                            anything
243                         */
244                         /* HACK : not long enough */
245                         myrand=rand();
246                         c=t->md5;
247                         size=MD5_LEN;
248                         memset(c, '0', size );
249                         int2reverse_hex( &c, &size, myrand );
250                 }
251         }
252 }
253
254 static void inline init_branches(struct cell *t)
255 {
256         unsigned int i;
257         struct ua_client *uac;
258
259         for(i=0;i<MAX_BRANCHES;i++)
260         {
261                 uac=&t->uac[i];
262                 uac->request.my_T = t;
263                 uac->request.branch = i;
264                 init_rb_timers(&uac->request);
265                 uac->local_cancel=uac->request;
266 #ifdef USE_DNS_FAILOVER
267                 dns_srv_handle_init(&uac->dns_h);
268 #endif
269         }
270 }
271
272
273 struct cell*  build_cell( struct sip_msg* p_msg )
274 {
275         struct cell* new_cell;
276         int          sip_msg_len;
277         avp_list_t* old;
278         struct tm_callback *cbs, *cbs_tmp;
279
280         /* allocs a new cell */
281         /* if syn_branch==0 add space for md5 (MD5_LEN -sizeof(struct cell.md5)) */
282         new_cell = (struct cell*)shm_malloc( sizeof( struct cell )+
283                         ((MD5_LEN-sizeof(((struct cell*)0)->md5))&((syn_branch!=0)-1)) );
284         if  ( !new_cell ) {
285                 ser_error=E_OUT_OF_MEM;
286                 return NULL;
287         }
288
289         /* filling with 0 */
290         memset( new_cell, 0, sizeof( struct cell ) );
291
292         /* UAS */
293         new_cell->uas.response.my_T=new_cell;
294         init_rb_timers(&new_cell->uas.response);
295         /* timers */
296         init_cell_timers(new_cell);
297
298         old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, 
299                         &new_cell->uri_avps_from );
300         new_cell->uri_avps_from = *old;
301         *old = 0;
302
303         old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, 
304                         &new_cell->uri_avps_to );
305         new_cell->uri_avps_to = *old;
306         *old = 0;
307
308         old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, 
309                         &new_cell->user_avps_from );
310         new_cell->user_avps_from = *old;
311         *old = 0;
312
313         old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, 
314                         &new_cell->user_avps_to );
315         new_cell->user_avps_to = *old;
316         *old = 0;
317
318              /* We can just store pointer to domain avps in the transaction context,
319               * because they are read-only
320               */
321         new_cell->domain_avps_from = get_avp_list(AVP_TRACK_FROM | 
322                                                                 AVP_CLASS_DOMAIN);
323         new_cell->domain_avps_to = get_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN);
324
325         /* enter callback, which may potentially want to parse some stuff,
326          * before the request is shmem-ized */
327         if (p_msg) {
328                 set_early_tmcb_list(p_msg, new_cell);
329                 if(has_reqin_tmcbs())
330                         run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD);
331         }
332
333         if (p_msg) {
334 #ifndef POSTPONE_MSG_CLONING
335                 /* it makes no sense to clean the lumps when they are not cloned (Miklos) */
336
337                 /* clean possible previous added vias/clen header or else they would 
338                  * get propagated in the failure routes */
339                 free_via_clen_lump(&p_msg->add_rm);
340 #endif
341                 new_cell->uas.request = sip_msg_cloner(p_msg,&sip_msg_len);
342                 if (!new_cell->uas.request)
343                         goto error;
344                 new_cell->uas.end_request=((char*)new_cell->uas.request)+sip_msg_len;
345         }
346
347         /* UAC */
348         init_branches(new_cell);
349
350         new_cell->relayed_reply_branch   = -1;
351         /* new_cell->T_canceled = T_UNDEFINED; */
352
353         init_synonym_id(new_cell);
354         init_cell_lock(  new_cell );
355         t_stats_created();
356         return new_cell;
357
358 error:
359         /* Other modules may have already registered some
360          * transaction callbacks and may also allocated
361          * additional memory for their parameters,
362          * hence TMCB_DESTROY needs to be called. (Miklos)
363          */
364         if (unlikely(has_tran_tmcbs(new_cell, TMCB_DESTROY)))
365                 run_trans_callbacks(TMCB_DESTROY, new_cell, 0, 0, 0);
366
367         /* free the callback list */
368         for( cbs=(struct tm_callback*)new_cell->tmcb_hl.first ; cbs ; ) {
369                 cbs_tmp = cbs;
370                 cbs = cbs->next;
371                 if (cbs_tmp->release) {
372                         cbs_tmp->release(cbs_tmp->param);
373                 }
374                 shm_free( cbs_tmp );
375         }
376         
377         destroy_avp_list(&new_cell->user_avps_from);
378         destroy_avp_list(&new_cell->user_avps_to);
379         destroy_avp_list(&new_cell->uri_avps_from);
380         destroy_avp_list(&new_cell->uri_avps_to);
381         shm_free(new_cell);
382         /* unlink transaction AVP list and link back the global AVP list (bogdan)*/
383         reset_avps();
384         return NULL;
385 }
386
387
388
389 /* Release all the data contained by the hash table. All the aux. structures
390  *  as sems, lists, etc, are also released */
391 void free_hash_table(  )
392 {
393         struct cell* p_cell;
394         struct cell* tmp_cell;
395         int    i;
396
397         if (_tm_table)
398         {
399                 /* remove the data contained by each entry */
400                 for( i = 0 ; i<TABLE_ENTRIES; i++)
401                 {
402                         release_entry_lock( (_tm_table->entries)+i );
403                         /* delete all synonyms at hash-collision-slot i */
404                         clist_foreach_safe(&_tm_table->entries[i], p_cell, tmp_cell,
405                                                                         next_c){
406                                 free_cell(p_cell);
407                         }
408                 }
409                 shm_free(_tm_table);
410         }
411 }
412
413
414
415
416 /*
417  */
418 struct s_table* init_hash_table()
419 {
420         int              i;
421
422         /*allocs the table*/
423         _tm_table= (struct s_table*)shm_malloc( sizeof( struct s_table ) );
424         if ( !_tm_table) {
425                 LOG(L_ERR, "ERROR: init_hash_table: no shmem for TM table\n");
426                 goto error0;
427         }
428
429         memset( _tm_table, 0, sizeof (struct s_table ) );
430
431         /* try first allocating all the structures needed for syncing */
432         if (lock_initialize()==-1)
433                 goto error1;
434
435         /* inits the entriess */
436         for(  i=0 ; i<TABLE_ENTRIES; i++ )
437         {
438                 init_entry_lock( _tm_table, (_tm_table->entries)+i );
439                 _tm_table->entries[i].next_label = rand();
440                 /* init cell list */
441                 clist_init(&_tm_table->entries[i], next_c, prev_c);
442         }
443
444         return  _tm_table;
445
446 error1:
447         free_hash_table( );
448 error0:
449         return 0;
450 }
451
452
453