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