1 /*
2 * Copyright (C) 2006 Voice System SRL
3 * Copyright (C) 2011 Carsten Bock, carsten@ng-voice.com
4 *
5 * This file is part of Kamailio, a free SIP server.
6 *
7 * Kamailio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version
11 *
12 * Kamailio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 /*!
24 * \file
25 * \brief Functions and definitions related to dialog creation and searching
26 * \ingroup dialog
27 * Module: \ref dialog
28 */
29
30 #ifndef _DIALOG_DLG_HASH_H_
31 #define _DIALOG_DLG_HASH_H_
32
33 #include "../../core/locking.h"
34 #include "../../core/timer.h"
35 #include "../../core/atomic_ops.h"
36 #include "dlg_timer.h"
37 #include "dlg_cb.h"
38
39
40 /* states of a dialog */
41 #define DLG_STATE_UNCONFIRMED 1 /*!< unconfirmed dialog */
42 #define DLG_STATE_EARLY 2 /*!< early dialog */
43 #define DLG_STATE_CONFIRMED_NA 3 /*!< confirmed dialog without a ACK yet */
44 #define DLG_STATE_CONFIRMED 4 /*!< confirmed dialog */
45 #define DLG_STATE_DELETED 5 /*!< deleted dialog */
46
47 /* events for dialog processing */
48 #define DLG_EVENT_TDEL 1 /*!< transaction was destroyed */
49 #define DLG_EVENT_RPL1xx 2 /*!< 1xx request */
50 #define DLG_EVENT_RPL2xx 3 /*!< 2xx request */
51 #define DLG_EVENT_RPL3xx 4 /*!< 3xx request */
52 #define DLG_EVENT_REQPRACK 5 /*!< PRACK request */
53 #define DLG_EVENT_REQACK 6 /*!< ACK request */
54 #define DLG_EVENT_REQBYE 7 /*!< BYE request */
55 #define DLG_EVENT_REQ 8 /*!< other requests */
56
57 /* dialog internal flags only in memory */
58 #define DLG_FLAG_NEW (1<<0) /*!< new dialog */
59 #define DLG_FLAG_CHANGED (1<<1) /*!< dialog was changed */
60 #define DLG_FLAG_HASBYE (1<<2) /*!< bye was received */
61 #define DLG_FLAG_CALLERBYE (1<<4) /*!< bye from caller */
62 #define DLG_FLAG_CALLEEBYE (1<<5) /*!< bye from callee */
63 #define DLG_FLAG_LOCALDLG (1<<6) /*!< local dialog, unused */
64 #define DLG_FLAG_CHANGED_VARS (1<<7) /*!< dialog-variables changed */
65
66 /* dialog-variable flags (in addition to dialog-flags) */
67 #define DLG_FLAG_DEL (1<<8) /*!< delete this var */
68
69 #define DLG_FLAG_TM (1<<9) /*!< dialog is set in transaction */
70 #define DLG_FLAG_EXPIRED (1<<10)/*!< dialog is expired */
71 #define DLG_FLAG_CHANGED_PROF (1<<10)/*!< dialog-profiles changed DMQ*/
72 #define DLG_FLAG_DB_LOAD_EXTRA (1<<12)/*!< dialog loaded extra from db */
73
74 /* internal flags stored in db */
75 #define DLG_IFLAG_TIMEOUTBYE (1<<0) /*!< send bye on time-out */
76 #define DLG_IFLAG_KA_SRC (1<<1) /*!< send keep alive to src */
77 #define DLG_IFLAG_KA_DST (1<<2) /*!< send keep alive to dst */
78 #define DLG_IFLAG_TIMER_NORESET (1<<3) /*!< don't reset dialog timers on in-dialog messages reception */
79 #define DLG_IFLAG_CSEQ_DIFF (1<<4) /*!< CSeq changed in dialog */
80 #define DLG_IFLAG_PRACK (1<<5) /*!< PRACK was routed during initial state */
81 #define DLG_IFLAG_DMQ_SYNC (1<<6) /*!< sync this dialog via dmq DMQ*/
82
83 #define DLG_CALLER_LEG 0 /*!< attribute that belongs to a caller leg */
84 #define DLG_CALLEE_LEG 1 /*!< attribute that belongs to a callee leg */
85
86 #define DLG_DIR_NONE 0 /*!< dialog has no direction */
87 #define DLG_DIR_DOWNSTREAM 1 /*!< dialog has downstream direction */
88 #define DLG_DIR_UPSTREAM 2 /*!< dialog has upstream direction */
89
90 #define DLG_EVENTRT_START 0
91 #define DLG_EVENTRT_END 1
92 #define DLG_EVENTRT_FAILED 2
93 #define DLG_EVENTRT_MAX 3
94
95 /*! internal unique ide per dialog */
96 typedef struct dlg_iuid {
97 unsigned int h_id; /*!< id in the hash table entry (seq nr in slot) */
98 unsigned int h_entry; /*!< index of hash table entry (the slot number) */
99 } dlg_iuid_t;
100
101 /*! entries in the dialog list */
102 typedef struct dlg_cell
103 {
104 volatile int ref; /*!< reference counter */
105 struct dlg_cell *next; /*!< next entry in the list */
106 struct dlg_cell *prev; /*!< previous entry in the list */
107 unsigned int h_id; /*!< id in the hash table entry (seq nr in slot) */
108 unsigned int h_entry; /*!< index of hash table entry (the slot number) */
109 unsigned int state; /*!< dialog state */
110 unsigned int lifetime; /*!< dialog lifetime */
111 unsigned int init_ts; /*!< init (creation) time (absolute UNIX ts)*/
112 unsigned int start_ts; /*!< start time (absolute UNIX ts)*/
113 unsigned int end_ts; /*!< end time (absolute UNIX ts)*/
114 unsigned int dflags; /*!< internal dialog memory flags */
115 unsigned int iflags; /*!< internal dialog persistent flags */
116 unsigned int sflags; /*!< script dialog persistent flags */
117 int toroute; /*!< index of route that is executed on timeout */
118 str toroute_name; /*!< name of route that is executed on timeout */
119 unsigned int from_rr_nb; /*!< information from record routing */
120 struct dlg_tl tl; /*!< dialog timer list */
121 str callid; /*!< callid from SIP message */
122 str from_uri; /*!< from uri from SIP message */
123 str to_uri; /*!< to uri from SIP message */
124 str req_uri; /*!< r-uri from SIP message */
125 str tag[2]; /*!< from tags of caller and to tag of callee */
126 str cseq[2]; /*!< CSEQ of caller and callee */
127 str route_set[2]; /*!< route set of caller and callee */
128 str contact[2]; /*!< contact of caller and callee */
129 struct socket_info * bind_addr[2]; /*! binded address of caller and callee */
130 struct dlg_head_cbl cbs; /*!< dialog callbacks */
131 struct dlg_profile_link *profile_links; /*!< dialog profiles */
132 struct dlg_var *vars; /*!< dialog variables */
133 unsigned int ka_src_counter; /*!< keepalive src (caller) counter */
134 unsigned int ka_dst_counter; /*!< keepalive dst (callee) counter */
135 } dlg_cell_t;
136
137
138 /*! entries in the main dialog table */
139 typedef struct dlg_entry
140 {
141 struct dlg_cell *first; /*!< dialog list */
142 struct dlg_cell *last; /*!< optimisation, end of the dialog list */
143 unsigned int next_id; /*!< next id */
144 gen_lock_t lock; /* mutex to access items in the slot */
145 atomic_t locker_pid; /* pid of the process that holds the lock */
146 int rec_lock_level; /* recursive lock count */
147 } dlg_entry_t;
148
149
150 /*! main dialog table */
151 typedef struct dlg_table
152 {
153 unsigned int size; /*!< size of the dialog table */
154 struct dlg_entry *entries; /*!< dialog hash table */
155 } dlg_table_t;
156
157
158 typedef struct dlg_ka {
159 dlg_iuid_t iuid;
160 ticks_t katime;
161 unsigned iflags;
162 struct dlg_ka *next;
163 } dlg_ka_t;
164
165 /*! global dialog table */
166 extern dlg_table_t *d_table;
167
168
169 /*!
170 * \brief Set a dialog lock (re-entrant)
171 * \param _table dialog table
172 * \param _entry locked entry
173 */
174 #define dlg_lock(_table, _entry) \
175 do { \
176 int mypid; \
177 mypid = my_pid(); \
178 if (likely(atomic_get( &(_entry)->locker_pid) != mypid)) { \
179 lock_get( &(_entry)->lock); \
180 atomic_set( &(_entry)->locker_pid, mypid); \
181 } else { \
182 /* locked within the same process that executed us */ \
183 (_entry)->rec_lock_level++; \
184 } \
185 } while(0)
186
187
188 /*!
189 * \brief Release a dialog lock
190 * \param _table dialog table
191 * \param _entry locked entry
192 */
193 #define dlg_unlock(_table, _entry) \
194 do { \
195 if (likely((_entry)->rec_lock_level == 0)) { \
196 atomic_set( &(_entry)->locker_pid, 0); \
197 lock_release( &(_entry)->lock); \
198 } else { \
199 /* recursive locked => decrease lock count */ \
200 (_entry)->rec_lock_level--; \
201 } \
202 } while(0)
203
204 /*!
205 * \brief Set a dialog lock (re-entrant)
206 * \param _dlg dialog cell
207 */
208 #define dlg_cell_lock(_dlg) \
209 dlg_lock(d_table, &(d_table->entries[(_dlg)->h_entry]))
210
211 /*!
212 * \brief Set a dialog lock (re-entrant)
213 * \param _dlg dialog cell
214 */
215 #define dlg_cell_unlock(_dlg) \
216 dlg_unlock(d_table, &(d_table->entries[(_dlg)->h_entry]))
217
218
219 /*!
220 * \brief Unlink a dialog from the list without locking
221 * \see unref_dlg_unsafe
222 * \param d_entry unlinked entry
223 * \param dlg unlinked dialog
224 */
unlink_unsafe_dlg(dlg_entry_t * d_entry,dlg_cell_t * dlg)225 static inline void unlink_unsafe_dlg(dlg_entry_t *d_entry, dlg_cell_t *dlg)
226 {
227 if (dlg->next)
228 dlg->next->prev = dlg->prev;
229 else
230 d_entry->last = dlg->prev;
231 if (dlg->prev)
232 dlg->prev->next = dlg->next;
233 else
234 d_entry->first = dlg->next;
235
236 dlg->next = dlg->prev = 0;
237
238 return;
239 }
240
241
242 /*!
243 * \brief Destroy a dialog, run callbacks and free memory
244 * \param dlg destroyed dialog
245 */
246 void destroy_dlg(dlg_cell_t *dlg);
247
248
249 /*!
250 * \brief Initialize the global dialog table
251 * \param size size of the table
252 * \return 0 on success, -1 on failure
253 */
254 int init_dlg_table(unsigned int size);
255
256
257 /*!
258 * \brief Destroy the global dialog table
259 */
260 void destroy_dlg_table(void);
261
262
263 /*!
264 * \brief Create a new dialog structure for a SIP dialog
265 * \param callid dialog callid
266 * \param from_uri dialog from uri
267 * \param to_uri dialog to uri
268 * \param from_tag dialog from tag
269 * \param req_uri dialog r-uri
270 * \return created dialog structure on success, NULL otherwise
271 */
272 dlg_cell_t* build_new_dlg(str *callid, str *from_uri,
273 str *to_uri, str *from_tag, str *req_uri);
274
275
276 /*!
277 * \brief Set the leg information for an existing dialog
278 * \param dlg dialog
279 * \param tag from tag or to tag
280 * \param rr record-routing information
281 * \param contact caller or callee contact
282 * \param cseq CSEQ of caller or callee
283 * \param leg must be either DLG_CALLER_LEG, or DLG_CALLEE_LEG
284 * \return 0 on success, -1 on failure
285 */
286 int dlg_set_leg_info(dlg_cell_t *dlg, str* tag, str *rr, str *contact,
287 str *cseq, unsigned int leg);
288
289
290 /*!
291 * \brief Update or set the Contact for an existing dialog
292 * \param dlg dialog
293 * \param leg must be either DLG_CALLER_LEG, or DLG_CALLEE_LEG
294 * \param ct Contact of caller or callee
295 * \return 0 on success, -1 on failure
296 */
297 int dlg_update_contact(struct dlg_cell * dlg, unsigned int leg, str *ct);
298
299
300 /*!
301 * \brief Update or set the CSEQ for an existing dialog
302 * \param dlg dialog
303 * \param leg must be either DLG_CALLER_LEG, or DLG_CALLEE_LEG
304 * \param cseq CSEQ of caller or callee
305 * \return 0 on success, -1 on failure
306 */
307 int dlg_update_cseq(dlg_cell_t *dlg, unsigned int leg, str *cseq);
308
309 /*!
310 * \brief Update or set the routeset for an existing dialog
311 * \param dlg dialog
312 * \param leg must be either DLG_CALLER_LEG, or DLG_CALLEE_LEG
313 * \param rr routeset
314 * \return 0 on success, -1 on failure
315 */
316 int dlg_update_rr_set(struct dlg_cell * dlg, unsigned int leg, str *rr);
317
318 /*!
319 * \brief Set time-out route
320 * \param dlg dialog
321 * \param route name of route
322 * \return 0 on success, -1 on failure
323 */
324 int dlg_set_toroute(dlg_cell_t *dlg, str *route);
325
326
327 /*!
328 * \brief Lookup a dialog in the global list
329 *
330 * Note that the caller is responsible for decrementing (or reusing)
331 * the reference counter by one again iff a dialog has been found.
332 * \param h_entry number of the hash table entry
333 * \param h_id id of the hash table entry
334 * \param lmode id if 0, then dlg table entry is unlocked, otherwise is locked
335 * \return dialog structure on success, NULL on failure
336 */
337 dlg_cell_t *dlg_lookup_mode(unsigned int h_entry, unsigned int h_id, int lmode);
338
339 /*!
340 * \brief Lookup a dialog in the global list
341 *
342 * Note that the caller is responsible for decrementing (or reusing)
343 * the reference counter by one again if a dialog has been found.
344 * \param h_entry number of the hash table entry
345 * \param h_id id of the hash table entry
346 * \return dialog structure on success, NULL on failure
347 */
348 dlg_cell_t* dlg_lookup(unsigned int h_entry, unsigned int h_id);
349
350 /*!
351 * \brief Search a dialog in the global list by iuid
352 *
353 * Note that the caller is responsible for decrementing (or reusing)
354 * the reference counter by one again if a dialog has been found.
355 * \param diuid internal unique id per dialog
356 * \param lmode id if 0, then dlg table entry is unlocked, otherwise is locked
357 * \return dialog structure on success, NULL on failure
358 */
359 dlg_cell_t* dlg_get_by_iuid_mode(dlg_iuid_t *diuid, int lmode);
360
361 /*!
362 * \brief Search and return dialog in the global list by iuid
363 *
364 * Note that the caller is responsible for decrementing (or reusing)
365 * the reference counter by one again if a dialog has been found.
366 * \param diuid internal unique id per dialog
367 * \return dialog structure on success, NULL on failure
368 */
369 dlg_cell_t* dlg_get_by_iuid(dlg_iuid_t *diuid);
370
371
372 /*!
373 * \brief Get dialog that correspond to CallId, From Tag and To Tag
374 *
375 * Get dialog that correspond to CallId, From Tag and To Tag.
376 * See RFC 3261, paragraph 4. Overview of Operation:
377 * "The combination of the To tag, From tag, and Call-ID completely
378 * defines a peer-to-peer SIP relationship between [two UAs] and is
379 * referred to as a dialog."
380 * Note that the caller is responsible for decrementing (or reusing)
381 * the reference counter by one again iff a dialog has been found.
382 * \param callid callid
383 * \param ftag from tag
384 * \param ttag to tag
385 * \param dir direction
386 * \return dialog structure on success, NULL on failure
387 */
388 dlg_cell_t* get_dlg(str *callid, str *ftag, str *ttag, unsigned int *dir);
389
390
391 /*!
392 * \brief Search dialog that corresponds to CallId, From Tag and To Tag
393 *
394 * Get dialog that correspond to CallId, From Tag and To Tag.
395 * See RFC 3261, paragraph 4. Overview of Operation:
396 * "The combination of the To tag, From tag, and Call-ID completely
397 * defines a peer-to-peer SIP relationship between [two UAs] and is
398 * referred to as a dialog."
399 * Note that the caller is responsible for decrementing (or reusing)
400 * the reference counter by one again if a dialog has been found.
401 * Important: the hash slot is left locked (e.g., needed to allow
402 * linking the structure of a new dialog).
403 * \param callid callid
404 * \param ftag from tag
405 * \param ttag to tag
406 * \param dir direction
407 * \return dialog structure on success, NULL on failure (and slot locked)
408 */
409 dlg_cell_t* dlg_search(str *callid, str *ftag, str *ttag, unsigned int *dir);
410
411
412 /*!
413 * \brief Lock hash table slot by call-id
414 * \param callid call-id value
415 */
416 void dlg_hash_lock(str *callid);
417
418
419 /*!
420 * \brief Release hash table slot by call-id
421 * \param callid call-id value
422 */
423 void dlg_hash_release(str *callid);
424
425
426 /*!
427 * \brief Link a dialog structure
428 * \param dlg dialog
429 * \param n extra increments for the reference counter
430 * \param mode link in safe mode (0 - lock slot; 1 - don't)
431 */
432 void link_dlg(struct dlg_cell *dlg, int n, int mode);
433
434
435 /*!
436 * \brief Unreference a dialog with locking
437 * \see unref_dlg_unsafe
438 * \param dlg dialog
439 * \param cnt decrement for the reference counter
440 */
441 void dlg_unref_helper(dlg_cell_t *dlg, unsigned int cnt, const char *fname,
442 int fline);
443
444 #define dlg_unref(dlg, cnt) dlg_unref_helper((dlg), (cnt), __FILE__, __LINE__)
445
446 /*!
447 * \brief Refefence a dialog with locking
448 * \see ref_dlg_unsafe
449 * \param dlg dialog
450 * \param cnt increment for the reference counter
451 */
452 void dlg_ref_helper(dlg_cell_t *dlg, unsigned int cnt, const char *fname,
453 int fline);
454
455 #define dlg_ref(dlg, cnt) dlg_ref_helper((dlg), (cnt), __FILE__, __LINE__)
456
457 /*!
458 * \brief Release a dialog from ref counter by 1
459 * \see dlg_unref
460 * \param dlg dialog
461 */
462 void dlg_release(dlg_cell_t *dlg);
463
464 /*!
465 * \brief Update a dialog state according a event and the old state
466 *
467 * This functions implement the main state machine that update a dialog
468 * state according a processed event and the current state. If necessary
469 * it will delete the processed dialog. The old and new state are also
470 * saved for reference.
471 * \param dlg updated dialog
472 * \param event current event
473 * \param old_state old dialog state
474 * \param new_state new dialog state
475 * \param unref set to 1 when the dialog was deleted, 0 otherwise
476 */
477 void next_state_dlg(dlg_cell_t *dlg, int event,
478 int *old_state, int *new_state, int *unref);
479
480
481 /*!
482 * \brief Check if a dialog structure matches to a SIP message dialog
483 * \param dlg dialog structure
484 * \param callid SIP message Call-ID
485 * \param ftag SIP message from tag
486 * \param ttag SIP message to tag
487 * \param dir direction of the message, if DLG_DIR_NONE it will set
488 * \return 1 if dialog structure and message content matches, 0 otherwise
489 */
match_dialog(dlg_cell_t * dlg,str * callid,str * ftag,str * ttag,unsigned int * dir)490 static inline int match_dialog(dlg_cell_t *dlg, str *callid,
491 str *ftag, str *ttag, unsigned int *dir)
492 {
493 if (dlg->tag[DLG_CALLEE_LEG].len == 0) {
494 // dialog to tag is undetermined ATM.
495 if (*dir==DLG_DIR_DOWNSTREAM) {
496 if (dlg->callid.len == callid->len &&
497 dlg->tag[DLG_CALLER_LEG].len == ftag->len &&
498 strncmp(dlg->callid.s, callid->s, callid->len)==0 &&
499 strncmp(dlg->tag[DLG_CALLER_LEG].s, ftag->s, ftag->len)==0) {
500 return 1;
501 }
502 } else if (*dir==DLG_DIR_UPSTREAM) {
503 if (dlg->callid.len == callid->len &&
504 dlg->tag[DLG_CALLER_LEG].len == ttag->len &&
505 strncmp(dlg->callid.s, callid->s, callid->len)==0 &&
506 strncmp(dlg->tag[DLG_CALLER_LEG].s, ttag->s, ttag->len)==0) {
507 return 1;
508 }
509 } else {
510 if (dlg->callid.len != callid->len)
511 return 0;
512
513 if (dlg->tag[DLG_CALLER_LEG].len == ttag->len &&
514 strncmp(dlg->tag[DLG_CALLER_LEG].s, ttag->s, ttag->len)==0 &&
515 strncmp(dlg->callid.s, callid->s, callid->len)==0) {
516
517 *dir = DLG_DIR_UPSTREAM;
518 return 1;
519 } else if (dlg->tag[DLG_CALLER_LEG].len == ftag->len
520 && strncmp(dlg->tag[DLG_CALLER_LEG].s, ftag->s, ftag->len)==0
521 && strncmp(dlg->callid.s, callid->s, callid->len)==0) {
522
523 *dir = DLG_DIR_DOWNSTREAM;
524 return 1;
525 }
526 }
527 } else {
528 if (*dir==DLG_DIR_DOWNSTREAM) {
529 if (dlg->callid.len == callid->len &&
530 dlg->tag[DLG_CALLER_LEG].len == ftag->len &&
531 dlg->tag[DLG_CALLEE_LEG].len == ttag->len &&
532 strncmp(dlg->callid.s, callid->s, callid->len)==0 &&
533 strncmp(dlg->tag[DLG_CALLER_LEG].s, ftag->s, ftag->len)==0 &&
534 strncmp(dlg->tag[DLG_CALLEE_LEG].s, ttag->s, ttag->len)==0) {
535 return 1;
536 }
537 } else if (*dir==DLG_DIR_UPSTREAM) {
538 if (dlg->callid.len == callid->len &&
539 dlg->tag[DLG_CALLEE_LEG].len == ftag->len &&
540 dlg->tag[DLG_CALLER_LEG].len == ttag->len &&
541 strncmp(dlg->callid.s, callid->s, callid->len)==0 &&
542 strncmp(dlg->tag[DLG_CALLEE_LEG].s, ftag->s, ftag->len)==0 &&
543 strncmp(dlg->tag[DLG_CALLER_LEG].s, ttag->s, ttag->len)==0) {
544 return 1;
545 }
546 } else {
547 if (dlg->callid.len != callid->len)
548 return 0;
549
550 if (dlg->tag[DLG_CALLEE_LEG].len == ftag->len &&
551 dlg->tag[DLG_CALLER_LEG].len == ttag->len &&
552 strncmp(dlg->tag[DLG_CALLEE_LEG].s, ftag->s, ftag->len)==0 &&
553 strncmp(dlg->tag[DLG_CALLER_LEG].s, ttag->s, ttag->len)==0 &&
554 strncmp(dlg->callid.s, callid->s, callid->len)==0) {
555
556 *dir = DLG_DIR_UPSTREAM;
557 return 1;
558 } else if (dlg->tag[DLG_CALLER_LEG].len == ftag->len &&
559 dlg->tag[DLG_CALLEE_LEG].len == ttag->len &&
560 strncmp(dlg->tag[DLG_CALLER_LEG].s, ftag->s, ftag->len)==0 &&
561 strncmp(dlg->tag[DLG_CALLEE_LEG].s, ttag->s, ttag->len)==0 &&
562 strncmp(dlg->callid.s, callid->s, callid->len)==0) {
563
564 *dir = DLG_DIR_DOWNSTREAM;
565 return 1;
566 }
567 /* if no ACK yet, might be a lookup of dlg from a TM callback that
568 * runs on 200ok but with initial INVITE that has no to-tag */
569 if(ttag->len==0 && dlg->state==DLG_STATE_CONFIRMED_NA
570 && dlg->tag[DLG_CALLER_LEG].len == ftag->len &&
571 strncmp(dlg->tag[DLG_CALLER_LEG].s, ftag->s, ftag->len)==0 &&
572 strncmp(dlg->callid.s, callid->s, callid->len)==0) {
573
574 *dir = DLG_DIR_DOWNSTREAM;
575 return 1;
576 }
577 }
578 }
579
580 return 0;
581 }
582
583
584 /*!
585 * \brief Check if a downstream dialog structure matches a SIP message dialog
586 * \param dlg dialog structure
587 * \param callid SIP message callid
588 * \param ftag SIP message from tag
589 * \return 1 if dialog structure matches the SIP dialog, 0 otherwise
590 */
match_downstream_dialog(dlg_cell_t * dlg,str * callid,str * ftag)591 static inline int match_downstream_dialog(dlg_cell_t *dlg, str *callid, str *ftag)
592 {
593 if(dlg==NULL || callid==NULL)
594 return 0;
595 if (ftag==NULL) {
596 if (dlg->callid.len!=callid->len ||
597 strncmp(dlg->callid.s,callid->s,callid->len)!=0)
598 return 0;
599 } else {
600 if (dlg->callid.len!=callid->len ||
601 dlg->tag[DLG_CALLER_LEG].len!=ftag->len ||
602 strncmp(dlg->callid.s,callid->s,callid->len)!=0 ||
603 strncmp(dlg->tag[DLG_CALLER_LEG].s,ftag->s,ftag->len)!=0)
604 return 0;
605 }
606 return 1;
607 }
608
609 /*!
610 *
611 */
612 int dlg_run_event_route(dlg_cell_t *dlg, sip_msg_t *msg, int ostate, int nstate);
613
614
615 int dlg_ka_add(dlg_cell_t *dlg);
616
617 int dlg_ka_run(ticks_t ti);
618
619 int dlg_clean_run(ticks_t ti);
620
621 /*!
622 * \brief Update dialog lifetime - for internal callers.
623 */
624
625 int update_dlg_timeout(dlg_cell_t *, int);
626
627 #endif
628