h_table.h

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