00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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;
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
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