dlg_hash.h

Go to the documentation of this file.
00001 /*
00002  * $Id: dlg_hash.h 5529 2009-01-28 21:51:20Z miconda $
00003  *
00004  * Copyright (C) 2006 Voice System SRL
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio 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  * Kamailio 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  * 2006-04-14  initial version (bogdan)
00025  * 2006-11-28  Added num_100s and num_200s to dlg_cell, to aid in adding 
00026  *             statistics tracking of the number of early, and active dialogs.
00027  *             (Jeffrey Magder - SOMA Networks)
00028  * 2007-03-06  syncronized state machine added for dialog state. New tranzition
00029  *             design based on events; removed num_1xx and num_2xx (bogdan)
00030  * 2007-07-06  added flags, cseq, contact, route_set and bind_addr 
00031  *             to struct dlg_cell in order to store these information into db
00032  *             (ancuta)
00033  * 2008-04-17  added new dialog flag to avoid state tranzitions from DELETED to
00034  *             CONFIRMED_NA due delayed "200 OK" (bogdan)
00035  */
00036 
00037 
00038 #ifndef _DIALOG_DLG_HASH_H_
00039 #define _DIALOG_DLG_HASH_H_
00040 
00041 #include "../../locking.h"
00042 #include "../../mi/mi.h"
00043 #include "dlg_timer.h"
00044 #include "dlg_cb.h"
00045 
00046 
00047 #define DLG_STATE_UNCONFIRMED  1
00048 #define DLG_STATE_EARLY        2
00049 #define DLG_STATE_CONFIRMED_NA 3
00050 #define DLG_STATE_CONFIRMED    4
00051 #define DLG_STATE_DELETED      5
00052 
00053 #define DLG_EVENT_TDEL         1
00054 #define DLG_EVENT_RPL1xx       2
00055 #define DLG_EVENT_RPL2xx       3
00056 #define DLG_EVENT_RPL3xx       4
00057 #define DLG_EVENT_REQPRACK     5
00058 #define DLG_EVENT_REQACK       6
00059 #define DLG_EVENT_REQBYE       7
00060 #define DLG_EVENT_REQ          8
00061 
00062 #define DLG_FLAG_NEW           (1<<0)
00063 #define DLG_FLAG_CHANGED       (1<<1)
00064 #define DLG_FLAG_HASBYE        (1<<2)
00065 #define DLG_FLAG_TOBYE         (1<<3)
00066 #define DLG_FLAG_CALLERBYE     (1<<4)
00067 #define DLG_FLAG_CALLEEBYE     (1<<5)
00068 #define DLG_FLAG_LOCALDLG      (1<<6)
00069 
00070 #define DLG_CALLER_LEG         0
00071 #define DLG_CALLEE_LEG         1
00072 
00073 #define DLG_DIR_NONE           0
00074 #define DLG_DIR_DOWNSTREAM     1
00075 #define DLG_DIR_UPSTREAM       2
00076 
00077 
00078 
00079 struct dlg_cell
00080 {
00081    volatile int         ref;
00082    struct dlg_cell      *next;
00083    struct dlg_cell      *prev;
00084    unsigned int         h_id;
00085    unsigned int         h_entry;
00086    unsigned int         state;
00087    unsigned int         lifetime;
00088    unsigned int         start_ts;    /* start time  (absolute UNIX ts)*/
00089    unsigned int         dflags;
00090    unsigned int         sflags;
00091    unsigned int         toroute;
00092    unsigned int         from_rr_nb;
00093    struct dlg_tl        tl;
00094    str                  callid;
00095    str                  from_uri;
00096    str                  to_uri;
00097    str                  tag[2];
00098    str                  cseq[2];
00099    str                  route_set[2];
00100    str                  contact[2];
00101    struct socket_info * bind_addr[2];
00102    struct dlg_head_cbl  cbs;
00103    struct dlg_profile_link *profile_links;
00104 };
00105 
00106 
00107 struct dlg_entry
00108 {
00109    struct dlg_cell    *first;
00110    struct dlg_cell    *last;
00111    unsigned int        next_id;
00112    unsigned int       lock_idx;
00113 };
00114 
00115 
00116 
00117 struct dlg_table
00118 {
00119    unsigned int       size;
00120    struct dlg_entry   *entries;
00121    unsigned int       locks_no;
00122    gen_lock_set_t     *locks;
00123 };
00124 
00125 
00126 extern struct dlg_table *d_table;
00127 extern struct dlg_cell  *current_dlg_pointer;
00128 
00129 #define dlg_lock(_table, _entry) \
00130       lock_set_get( (_table)->locks, (_entry)->lock_idx);
00131 #define dlg_unlock(_table, _entry) \
00132       lock_set_release( (_table)->locks, (_entry)->lock_idx);
00133 
00134 inline void unlink_unsafe_dlg(struct dlg_entry *d_entry, struct dlg_cell *dlg);
00135 inline void destroy_dlg(struct dlg_cell *dlg);
00136 
00137 #define ref_dlg_unsafe(_dlg,_cnt)     \
00138    do { \
00139       (_dlg)->ref += (_cnt); \
00140       LM_DBG("ref dlg %p with %d -> %d\n", \
00141          (_dlg),(_cnt),(_dlg)->ref); \
00142    }while(0)
00143 
00144 #define unref_dlg_unsafe(_dlg,_cnt,_d_entry)   \
00145    do { \
00146       (_dlg)->ref -= (_cnt); \
00147       LM_DBG("unref dlg %p with %d -> %d\n",\
00148          (_dlg),(_cnt),(_dlg)->ref);\
00149       if ((_dlg)->ref<0) {\
00150          LM_CRIT("bogus ref %d with cnt %d for dlg %p [%u:%u] "\
00151             "with clid '%.*s' and tags '%.*s' '%.*s'\n",\
00152             (_dlg)->ref, _cnt, _dlg,\
00153             (_dlg)->h_entry, (_dlg)->h_id,\
00154             (_dlg)->callid.len, (_dlg)->callid.s,\
00155             (_dlg)->tag[DLG_CALLER_LEG].len,\
00156             (_dlg)->tag[DLG_CALLER_LEG].s,\
00157             (_dlg)->tag[DLG_CALLEE_LEG].len,\
00158             (_dlg)->tag[DLG_CALLEE_LEG].s); \
00159       }\
00160       if ((_dlg)->ref<=0) { \
00161          unlink_unsafe_dlg( _d_entry, _dlg);\
00162          LM_DBG("ref <=0 for dialog %p\n",_dlg);\
00163          destroy_dlg(_dlg);\
00164       }\
00165    }while(0)
00166 
00167 
00168 int init_dlg_table(unsigned int size);
00169 
00170 void destroy_dlg_table(void);
00171 
00172 struct dlg_cell* build_new_dlg(str *callid, str *from_uri,
00173       str *to_uri, str *from_tag);
00174 
00175 int dlg_set_leg_info(struct dlg_cell *dlg, str* tag, str *rr, str *contact,
00176       str *cseq, unsigned int leg);
00177 
00178 int dlg_update_cseq(struct dlg_cell *dlg, unsigned int leg, str *cseq);
00179 
00180 struct dlg_cell* lookup_dlg( unsigned int h_entry, unsigned int h_id);
00181 
00182 struct dlg_cell* get_dlg(str *callid, str *ftag, str *ttag, unsigned int *dir);
00183 
00184 void link_dlg(struct dlg_cell *dlg, int n);
00185 
00186 void unref_dlg(struct dlg_cell *dlg, unsigned int cnt);
00187 
00188 void ref_dlg(struct dlg_cell *dlg, unsigned int cnt);
00189 
00190 void next_state_dlg(struct dlg_cell *dlg, int event,
00191       int *old_state, int *new_state, int *unref);
00192 
00193 struct mi_root * mi_print_dlgs(struct mi_root *cmd, void *param );
00194 struct mi_root * mi_print_dlgs_ctx(struct mi_root *cmd, void *param );
00195 
00196 static inline int match_dialog(struct dlg_cell *dlg, str *callid,
00197                         str *ftag, str *ttag, unsigned int *dir) {
00198    if (dlg->tag[DLG_CALLEE_LEG].len == 0) {
00199         // dialog to tag is undetermined ATM.
00200       if (*dir==DLG_DIR_DOWNSTREAM) {
00201          if (dlg->callid.len == callid->len &&
00202             dlg->tag[DLG_CALLER_LEG].len == ftag->len &&
00203             strncmp(dlg->callid.s, callid->s, callid->len)==0 &&
00204             strncmp(dlg->tag[DLG_CALLER_LEG].s, ftag->s, ftag->len)==0) {
00205             return 1;
00206          }
00207       } else if (*dir==DLG_DIR_UPSTREAM) {
00208          if (dlg->callid.len == callid->len &&
00209             dlg->tag[DLG_CALLER_LEG].len == ttag->len &&
00210             strncmp(dlg->callid.s, callid->s, callid->len)==0 &&
00211             strncmp(dlg->tag[DLG_CALLER_LEG].s, ttag->s, ttag->len)==0) {
00212             return 1;
00213          }
00214       } else {
00215          if (dlg->callid.len != callid->len)
00216             return 0;
00217 
00218          if (dlg->tag[DLG_CALLER_LEG].len == ttag->len &&
00219             strncmp(dlg->tag[DLG_CALLER_LEG].s, ttag->s, ttag->len)==0 &&
00220             strncmp(dlg->callid.s, callid->s, callid->len)==0) {
00221 
00222             *dir = DLG_DIR_UPSTREAM;
00223             return 1;
00224          } else if (dlg->tag[DLG_CALLER_LEG].len == ftag->len &&
00225                   strncmp(dlg->tag[DLG_CALLER_LEG].s, ftag->s, ftag->len)==0 &&
00226                   strncmp(dlg->callid.s, callid->s, callid->len)==0) {
00227 
00228             *dir = DLG_DIR_DOWNSTREAM;
00229             return 1;
00230          }
00231       }
00232    } else {
00233       if (*dir==DLG_DIR_DOWNSTREAM) {
00234          if (dlg->callid.len == callid->len &&
00235             dlg->tag[DLG_CALLER_LEG].len == ftag->len &&
00236             dlg->tag[DLG_CALLEE_LEG].len == ttag->len &&
00237             strncmp(dlg->callid.s, callid->s, callid->len)==0 &&
00238             strncmp(dlg->tag[DLG_CALLER_LEG].s, ftag->s, ftag->len)==0 &&
00239             strncmp(dlg->tag[DLG_CALLEE_LEG].s, ttag->s, ttag->len)==0) {
00240             return 1;
00241          }
00242       } else if (*dir==DLG_DIR_UPSTREAM) {
00243          if (dlg->callid.len == callid->len &&
00244             dlg->tag[DLG_CALLEE_LEG].len == ftag->len &&
00245             dlg->tag[DLG_CALLER_LEG].len == ttag->len &&
00246             strncmp(dlg->callid.s, callid->s, callid->len)==0 &&
00247             strncmp(dlg->tag[DLG_CALLEE_LEG].s, ftag->s, ftag->len)==0 &&
00248             strncmp(dlg->tag[DLG_CALLER_LEG].s, ttag->s, ttag->len)==0) {
00249             return 1;
00250          }
00251       } else {
00252          if (dlg->callid.len != callid->len)
00253             return 0;
00254 
00255          if (dlg->tag[DLG_CALLEE_LEG].len == ftag->len &&
00256             dlg->tag[DLG_CALLER_LEG].len == ttag->len &&
00257             strncmp(dlg->tag[DLG_CALLEE_LEG].s, ftag->s, ftag->len)==0 &&
00258             strncmp(dlg->tag[DLG_CALLER_LEG].s, ttag->s, ttag->len)==0 &&
00259             strncmp(dlg->callid.s, callid->s, callid->len)==0) {
00260 
00261             *dir = DLG_DIR_UPSTREAM;
00262             return 1;
00263          } else if (dlg->tag[DLG_CALLER_LEG].len == ftag->len &&
00264                   dlg->tag[DLG_CALLEE_LEG].len == ttag->len &&
00265                   strncmp(dlg->tag[DLG_CALLER_LEG].s, ftag->s, ftag->len)==0 &&
00266                   strncmp(dlg->tag[DLG_CALLEE_LEG].s, ttag->s, ttag->len)==0 &&
00267                   strncmp(dlg->callid.s, callid->s, callid->len)==0) {
00268 
00269             *dir = DLG_DIR_DOWNSTREAM;
00270             return 1;
00271          }
00272       }
00273    }
00274 
00275    return 0;
00276 }
00277 
00278 static inline int match_downstream_dialog(struct dlg_cell *dlg, str *callid, str *ftag)
00279 {
00280    if (dlg->callid.len!=callid->len ||
00281       dlg->tag[DLG_CALLER_LEG].len!=ftag->len  ||
00282       strncmp(dlg->callid.s,callid->s,callid->len)!=0 ||
00283       strncmp(dlg->tag[DLG_CALLER_LEG].s,ftag->s,ftag->len)!=0)
00284       return 0;
00285    return 1;
00286 }
00287 
00288 
00289 int mi_print_dlg(struct mi_node *rpl, struct dlg_cell *dlg, int with_context);
00290 
00291 #endif

Generated on Tue May 22 16:00:26 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6