Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

h_table.h

Go to the documentation of this file.
00001 /*
00002  * $Id: h_table.h,v 1.102 2009/01/05 21:26:44 bpintea Exp $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * For a license to use the ser software under conditions
00014  * other than those described here, or to purchase support for this
00015  * software, please contact iptel.org by e-mail at the following addresses:
00016  *    info@iptel.org
00017  *
00018  * ser is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License 
00024  * along with this program; if not, write to the Free Software 
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  *
00027  * History:
00028  * --------
00029  * 2003-03-16  removed _TOTAG (jiri)
00030  * 2003-03-06  we keep a list of 200/INV to-tags now (jiri)
00031  * 2003-03-01  kr set through a function now (jiri)
00032  * 2003-12-04  callbacks per transaction added; completion callback
00033  *             merge into them as LOCAL_COMPETED (bogdan)
00034  * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
00035  * 2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced
00036  *             with flags (bogdan)
00037  * 2004-08-23  avp support added - avp list linked in transaction (bogdan)
00038  * 2005-11-03  updated to the new timer interface (dropped tm timers) (andrei)
00039  * 2006-08-11  dns failover support (andrei)
00040  * 2007-05-29  switch ref_count to atomic and delete a cell automatically on
00041  *             UNREF if the ref_count reaches 0 (andrei)
00042  * 2007-06-01  support for different retransmissions intervals per transaction;
00043  *             added maximum inv. and non-inv. transaction life time (andrei)
00044  * 2007-06-06  switched tm bucket list to a simpler and faster clist;
00045  *              inlined often used functions (andrei)
00046  */
00047 
00048 #ifndef _H_TABLE_H
00049 #define _H_TABLE_H
00050 
00051 #include "defs.h"
00052 #include "t_stats.h"
00053 
00054 #define TM_DEL_UNREF
00055 /* uncomment the next define if you wish to keep hash statistics*/
00056 /*
00057 #define TM_HASH_STATS
00058 */
00059 /* use hash stats always in debug mode */
00060 #ifdef EXTRA_DEBUG
00061 #ifndef TM_HASH_STATS
00062 #define TM_HASH_STATS
00063 #endif
00064 #endif
00065 
00066 
00067 #include "../../clist.h"
00068 #include "../../parser/msg_parser.h"
00069 #include "../../types.h"
00070 #include "../../md5utils.h"
00071 #include "../../usr_avp.h"
00072 #include "../../timer.h"
00073 #include "../../atomic_ops.h"
00074 #include "config.h"
00075 
00076 /* if TM_DIFF_RT_TIMEOUT is defined, different retransmissions timeouts
00077  * can be used for each transaction, at a small memory cost
00078  * (extra 4 bytes/transaction) */
00079 #define TM_DIFF_RT_TIMEOUT
00080 
00081 
00082 struct s_table;
00083 struct entry;
00084 struct cell;
00085 struct timer;
00086 struct retr_buf;
00087 
00088 #include "../../mem/shm_mem.h"
00089 #include "lock.h"
00090 #include "sip_msg.h"
00091 #include "t_reply.h"
00092 #include "t_hooks.h"
00093 #ifdef USE_DNS_FAILOVER
00094 #include "../../dns_cache.h"
00095 #endif
00096 
00097 
00098 #define LOCK_HASH(_h) lock_hash((_h))
00099 #define UNLOCK_HASH(_h) unlock_hash((_h))
00100 
00101 void lock_hash(int i);
00102 void unlock_hash(int i);
00103 
00104 
00105 #define NO_CANCEL       ( (char*) 0 )
00106 #define EXTERNAL_CANCEL ( (char*) -1)
00107 
00108 #define TYPE_LOCAL_ACK    -2
00109 #define TYPE_LOCAL_CANCEL -1
00110 #define TYPE_REQUEST       0
00111 
00112 /* to be able to assess whether a script writer forgot to
00113    release a transaction and leave it for ever in memory,
00114    we mark it with operations done over it; if none of these
00115    flags is set and script is being left, it is a sign of
00116    script error and we need to release on writer's
00117    behalf
00118 
00119    REQ_FWDED means there is a UAC with final response timer
00120              ticking. If it hits, transaction will be completed.
00121    REQ_RPLD means that a transaction has been replied -- either
00122             it implies going to wait state, or for invite transactions
00123             FR timer is ticking until ACK arrives
00124    REQ_RLSD means that a transaction was put on wait explicitly
00125             from t_release_transaction
00126    REQ_EXIST means that this request is a retransmission which does not
00127             affect transactional state
00128    REQ_ERR_DELAYED mean that tm wants to send  reply(ser_error) but it
00129             delayed it to end-of-script to allow it to be overriden.
00130             If this is set and all of the above flag are not => send reply
00131             on end of script. If any of the above flags is set, do not
00132             send (especially REQ_RPLD and REQ_RLSD).
00133 */
00134 enum kill_reason { REQ_FWDED=1, REQ_RPLD=2, REQ_RLSD=4, REQ_EXIST=8,
00135                                    REQ_ERR_DELAYED=16 };
00136 
00137 
00138 /* #define F_RB_T_ACTIVE                0x01  (obsolete) fr or retr active */
00139 #define F_RB_T2                         0x02
00140 #define F_RB_RETR_DISABLED      0x04 /* retransmission disabled */
00141 #define F_RB_FR_INV     0x08 /* timer switched to FR_INV */
00142 #define F_RB_TIMEOUT    0x10 /* timeout */
00143 #define F_RB_REPLIED    0x20 /* reply received */
00144 #define F_RB_CANCELED   0x40 /* rb/branch canceled */
00145 #define F_RB_DEL_TIMER  0x80 /* timer should be deleted if active */
00146 #define F_RB_NH_LOOSE   0x100 /* next hop is a loose router */
00147 #define F_RB_NH_STRICT  0x200 /* next hop is a strict router */
00148 /* must detect when neither loose nor strict flag is set -> two flags.
00149  * alternatively, 1x flag for strict/loose and 1x for loose|strict set/not */
00150 
00151 
00152 /* if canceled or intended to be canceled, return true */
00153 #define uac_dont_fork(uac)      ((uac)->local_cancel.buffer)
00154 
00155 
00156 typedef struct retr_buf
00157 {
00158         short activ_type;
00159         /* set to status code if the buffer is a reply,
00160         0 if request or -1 if local CANCEL */
00161         volatile unsigned short flags; /* DISABLED, T2 */
00162         volatile unsigned char t_active; /* timer active */
00163         unsigned short branch; /* no more then 65k branches :-) */
00164         short buffer_len;
00165         char *buffer;
00166         /*the cell that contains this retrans_buff*/
00167         struct cell* my_T;
00168         struct timer_ln timer;
00169         struct dest_info dst;
00170         ticks_t retr_expire;
00171         ticks_t fr_expire; /* ticks value after which fr. will fire */
00172 }retr_buf_type;
00173 
00174 
00175 
00176 /* User Agent Server content */
00177 
00178 typedef struct ua_server
00179 {
00180         struct sip_msg   *request;
00181         char             *end_request;
00182         struct retr_buf  response;
00183         /* keep to-tags for local 200 replies for INVITE -- 
00184          * we need them for dialog-wise matching of ACKs;
00185          * the pointer shows to shmem-ed reply */
00186         str                              local_totag;
00187         unsigned int     status;
00188 }ua_server_type;
00189 
00190 
00191 
00192 /* User Agent Client content */
00193 
00194 typedef struct ua_client
00195 {
00196         /* if we store a reply (branch picking), this is where it is */
00197         struct sip_msg  *reply;
00198         struct retr_buf  request;
00199         /* we maintain a separate copy of cancel rather than
00200            reuse the structure for original request; the 
00201            original request is no longer needed but its delayed
00202            timer may fire and interfere with whoever tries to
00203            rewrite it
00204         */
00205         struct retr_buf local_cancel;
00206         /* pointer to retransmission buffer where uri is printed;
00207            good for generating ACK/CANCEL */
00208 #ifdef USE_DNS_FAILOVER
00209         struct dns_srv_handle dns_h;
00210 #endif
00211         str              uri;
00212         /* if we don't store, we at least want to know the status */
00213         int             last_received;
00214 #ifdef WITH_AS_SUPPORT
00215 
00222         struct retr_buf *local_ack;
00223 #endif
00224 }ua_client_type;
00225 
00226 
00227 struct totag_elem {
00228         struct totag_elem *next;
00229         str tag;
00230         volatile int acked;
00231 };
00232 
00233 
00234 
00235 /* transaction's flags */
00236 /* is the transaction's request an INVITE? */
00237 #define T_IS_INVITE_FLAG     (1<<0)
00238 /* is this a transaction generated by local request? */
00239 #define T_IS_LOCAL_FLAG      (1<<1)
00240 /* set to one if you want to disallow silent transaction
00241    dropping when C timer hits */
00242 #define T_NOISY_CTIMER_FLAG  (1<<2)
00243 /* transaction canceled
00244  * WARNING: this flag can be set outside reply lock from e2e_cancel().
00245  * If a future flag could be affected by a race w/ e2e_cancel() the code
00246  * should be changed.*/
00247 #define T_CANCELED           (1<<3)
00248 /* 6xx received => stop forking */
00249 #define T_6xx            (1<<4) 
00250 
00251 #define T_IN_AGONY (1<<5) /* set if waiting to die (delete timer)
00252                              TODO: replace it with del on unref */
00253 #define T_AUTO_INV_100 (1<<6) /* send an 100 reply automatically  to inv. */
00254 #ifdef WITH_AS_SUPPORT
00255         /* don't generate automatically an ACK for local transaction */
00256 #       define T_NO_AUTO_ACK    (1<<7)
00257 #endif
00258 #define T_DONT_FORK   (T_CANCELED|T_6xx)
00259 
00260 /* unsigned short should be enough for a retr. timer: max. 65535 ticks =>
00261  * max  retr. = 1023 s for tick = 15 ms, which should be more then enough and
00262  * saves us 2*2 bytes */
00263 typedef unsigned short retr_timeout_t;
00264 
00265 /* transaction context */
00266 
00267 typedef struct cell
00268 {
00269         /* linking data */
00270         /* WARNING: don't move or change order of next_c or prev_c
00271          * or breakage will occur */
00272         struct cell*     next_c;
00273         struct cell*     prev_c;
00274         /* tells in which hash table entry the cell lives */
00275         unsigned int  hash_index;
00276         /* sequence number within hash collision slot */
00277         unsigned int  label;
00278         /* different information about the transaction */
00279         unsigned short flags;
00280         /* number of forks */
00281         short nr_of_outgoings;
00282 
00283 #ifdef TM_DEL_UNREF
00284         /* every time the transaction/cell is referenced from somewhere this
00285          * ref_count should be increased (via REF()) and every time the reference
00286          * is removed the ref_count should be decreased (via UNREF()).
00287          * This includes adding the cell to the hash table (REF() before adding)
00288          * and removing it from the hash table (UNREF_FREE() after unlinking).
00289          * Exception: it does not include starting/stopping timers (timers are 
00290          * forced-stopped every time when ref_count reaches 0)
00291          * If the cell is no longer referenced (ref_count==0 after an UNREF),
00292          * it will be automatically deleted by the UNREF() operation.
00293          */
00294         atomic_t ref_count;
00295 #else 
00296         /* how many processes are currently processing this transaction ;
00297            note that only processes working on a request/reply belonging
00298            to a transaction increase ref_count -- timers don't, since we
00299            rely on transaction state machine to clean-up all but wait timer
00300            when entering WAIT state and the wait timer is the only place
00301            from which a transaction can be deleted (if ref_count==0); good
00302            for protecting from conditions in which wait_timer hits and
00303            tries to delete a transaction whereas at the same time 
00304            a delayed message belonging to the transaction is received */
00305         volatile unsigned int ref_count;
00306 #endif
00307 
00308         /* needed for generating local ACK/CANCEL for local
00309            transactions; all but cseq_n include the entire
00310            header field value, cseq_n only Cseq number; with
00311            local transactions, pointers point to outbound buffer,
00312            with proxied transactions to inbound request */
00313         str from, callid, cseq_n, to;
00314         /* method shortcut -- for local transactions, pointer to
00315            outbound buffer, for proxies transactions pointer to
00316            original message; needed for reply matching */
00317         str method;
00318 
00319         /* head of callback list */
00320         struct tmcb_head_list tmcb_hl;
00321 
00322         /* bindings to wait and delete timer */
00323         struct timer_ln wait_timer; /* used also for delete */
00324 
00325         /* UA Server */
00326         struct ua_server  uas;
00327         /* UA Clients */
00328         struct ua_client  uac[ MAX_BRANCHES ];
00329         
00330         /* to-tags of 200/INVITEs which were received from downstream and 
00331          * forwarded or passed to UAC; note that there can be arbitrarily 
00332          * many due to downstream forking; */
00333         struct totag_elem *fwded_totags;
00334 
00335              /* list with avp */
00336         struct usr_avp *uri_avps_from;
00337         struct usr_avp *uri_avps_to;
00338         struct usr_avp *user_avps_from;
00339         struct usr_avp *user_avps_to;
00340         struct usr_avp *domain_avps_from;
00341         struct usr_avp *domain_avps_to;
00342         
00343         /* protection against concurrent reply processing */
00344         ser_lock_t   reply_mutex;
00345         
00346         ticks_t fr_timeout;     /* final response interval for retr_bufs */
00347         ticks_t fr_inv_timeout; /* final inv. response interval for retr_bufs */
00348 #ifdef TM_DIFF_RT_TIMEOUT
00349         retr_timeout_t rt_t1_timeout; /* start retr. interval for retr_bufs */
00350         retr_timeout_t rt_t2_timeout; /* maximum retr. interval for retr_bufs */
00351 #endif
00352         ticks_t end_of_life; /* maximum lifetime */
00353 
00354         /* nr of replied branch; 0..MAX_BRANCHES=branch value,
00355          * -1 no reply, -2 local reply */
00356         short relayed_reply_branch;
00357 
00358         /* the route to take if no final positive reply arrived */
00359         unsigned short on_negative;
00360         /* the onreply_route to be processed if registered to do so */
00361         unsigned short on_reply;
00362          /* The route to take for each downstream branch separately */
00363         unsigned short on_branch;
00364 
00365         /* place holder for MD5checksum  (meaningful only if syn_branch=0) */
00366         char md5[0]; /* if syn_branch==0 then MD5_LEN bytes are extra alloc'ed*/
00367 
00368 }cell_type;
00369 
00370 
00371 #if 0
00372 /* warning: padding too much => big size increase */
00373 #define ENTRY_PAD_TO  128 /* should be a multiple of cacheline size for 
00374                              best performance*/
00375 #define ENTRY_PAD_BYTES  \
00376         (ENTRY_PAD_TO-2*sizeof(struct cell*)+sizeof(ser_lock_t)+sizeof(int)+ \
00377                                         2*sizeof(long))
00378 #else
00379 #define ENTRY_PAD_BYTES 0
00380 #endif
00381 
00382 /* double-linked list of cells with hash synonyms */
00383 typedef struct entry
00384 {
00385         /* WARNING: don't move or change order of next_c or prev_c
00386          * or breakage will occur */
00387         struct cell*    next_c; 
00388         struct cell*    prev_c;
00389         /* sync mutex */
00390         ser_lock_t      mutex;
00391         /* currently highest sequence number in a synonym list */
00392         unsigned int    next_label;
00393 #ifdef TM_HASH_STATS
00394         unsigned long acc_entries;
00395         unsigned long cur_entries;
00396 #endif
00397         char _pad[ENTRY_PAD_BYTES];
00398 }entry_type;
00399 
00400 
00401 
00402 /* transaction table */
00403 struct s_table
00404 {
00405         /* table of hash entries; each of them is a list of synonyms  */
00406         struct entry   entries[ TABLE_ENTRIES ];
00407 };
00408 
00409 /* pointer to the big table where all the transaction data
00410    lives */
00411 struct s_table*  _tm_table; /* private internal stuff, don't touch directly */
00412 
00413 #define list_entry(ptr, type, member) \
00414         ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
00415 
00416 #define get_retr_timer_payload(_tl_) \
00417         list_entry( _tl_, struct retr_buf, retr_timer)
00418 #define get_fr_timer_payload(_tl_) \
00419         list_entry( _tl_, struct retr_buf, fr_timer)
00420 #define get_wait_timer_payload(_tl_) \
00421         list_entry( _tl_, struct cell, wait_tl)
00422 #define get_dele_timer_payload(_tl_) \
00423         list_entry( _tl_, struct cell, dele_tl)
00424 
00425 #define get_T_from_reply_rb(_rb_) \
00426         list_entry( list_entry( _rb_, (struct ua_server), response),\
00427                 struct cell, uas)
00428 #define get_T_from_request_rb(_rb_, _br_) \
00429         list_entry( list_entry( (rb_, (struct ua_client), request) - \
00430                 (_br_)*sizeof(struct retr_buf), struct cell, uas)
00431 #define get_T_from_cancel_rb(_rb_, _br_) \
00432         list_entry( list_entry( (rb_, (struct ua_client), local_cancel) - \
00433                 (_br_)*sizeof(struct retr_buf), struct cell, uas)
00434 
00435 #define is_invite(_t_)           ((_t_)->flags&T_IS_INVITE_FLAG)
00436 #define is_local(_t_)            ((_t_)->flags&T_IS_LOCAL_FLAG)
00437 #define has_noisy_ctimer(_t_)    ((_t_)->flags&T_NOISY_CTIMER_FLAG)
00438 
00439 
00440 void reset_kr();
00441 void set_kr( enum kill_reason kr );
00442 enum kill_reason get_kr();
00443 
00444 #define get_tm_table() (_tm_table)
00445 
00446 struct s_table* init_hash_table();
00447 void   free_hash_table( );
00448 void   free_cell( struct cell* dead_cell );
00449 struct cell*  build_cell( struct sip_msg* p_msg );
00450 
00451 #ifdef TM_HASH_STATS
00452 unsigned int transaction_count( void );
00453 #endif
00454 
00455 
00456 /*  Takes an already created cell and links it into hash table on the
00457  *  appropriate entry. */
00458 inline static void insert_into_hash_table_unsafe( struct cell * p_cell,
00459                                                                                                         unsigned int hash )
00460 {
00461         p_cell->label = _tm_table->entries[hash].next_label++;
00462 #ifdef EXTRA_DEBUG
00463         DEBUG("cell label: %u\n", p_cell->label);
00464 #endif
00465         p_cell->hash_index=hash;
00466         /* insert at the beginning */
00467         clist_insert(&_tm_table->entries[hash], p_cell, next_c, prev_c);
00468 
00469         /* update stats */
00470 #ifdef TM_HASH_STATS
00471         _tm_table->entries[hash].cur_entries++;
00472         _tm_table->entries[hash].acc_entries++;
00473 #endif
00474         t_stats_new( is_local(p_cell) );
00475 }
00476 
00477 
00478 
00479 /*  Un-link a  cell from hash_table, but the cell itself is not released */
00480 inline static void remove_from_hash_table_unsafe( struct cell * p_cell)
00481 {
00482         clist_rm(p_cell, next_c, prev_c);
00483 #       ifdef EXTRA_DEBUG
00484 #ifdef TM_HASH_STATS
00485         if (_tm_table->entries[p_cell->hash_index].cur_entries==0){
00486                 LOG(L_CRIT, "BUG: bad things happened: cur_entries=0\n");
00487                 abort();
00488         }
00489 #endif
00490 #       endif
00491 #ifdef TM_HASH_STATS
00492         _tm_table->entries[p_cell->hash_index].cur_entries--;
00493 #endif
00494         t_stats_deleted( is_local(p_cell) );
00495 }
00496 
00497 #endif
00498 
00499 

Generated on Tue Sep 7 04:16:09 2010 for SIPExpressRouter by  doxygen 1.3.9.1