Merge commit 'origin/andrei/type_conversion'
[sip-router] / modules_k / dialog / dlg_hash.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2006 Voice System SRL
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License 
19  * along with this program; if not, write to the Free Software 
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  * History:
23  * --------
24  * 2006-04-14  initial version (bogdan)
25  * 2007-03-06  syncronized state machine added for dialog state. New tranzition
26  *             design based on events; removed num_1xx and num_2xx (bogdan)
27  * 2007-04-30  added dialog matching without DID (dialog ID), but based only
28  *             on RFC3261 elements - based on an original patch submitted 
29  *             by Michel Bensoussan <michel@extricom.com> (bogdan)
30  * 2007-07-06  additional information stored in order to save it in the db:
31  *             cseq, route_set, contact and sock_info for both caller and 
32  *             callee (ancuta)
33  * 2007-07-10  Optimized dlg_match_mode 2 (DID_NONE), it now employs a proper
34  *             hash table lookup and isn't dependant on the is_direction 
35  *             function (which requires an RR param like dlg_match_mode 0 
36  *             anyways.. ;) ; based on a patch from 
37  *             Tavis Paquette <tavis@galaxytelecom.net> 
38  *             and Peter Baer <pbaer@galaxytelecom.net>  (bogdan)
39  * 2008-04-17  added new type of callback to be triggered right before the
40  *              dialog is destroyed (deleted from memory) (bogdan)
41  * 2008-04-17  added new dialog flag to avoid state tranzitions from DELETED to
42  *             CONFIRMED_NA due delayed "200 OK" (bogdan)
43  */
44
45
46 /*!
47  * \file
48  * \brief Functions related to dialog creation and searching
49  * \ingroup dialog
50  * Module: \ref dialog
51  */
52
53 #include <stdlib.h>
54 #include <string.h>
55
56 #include "../../dprint.h"
57 #include "../../ut.h"
58 #include "../../lib/kcore/hash_func.h"
59 #include "../../lib/kmi/mi.h"
60 #include "dlg_timer.h"
61 #include "dlg_hash.h"
62 #include "dlg_profile.h"
63
64 #define MAX_LDG_LOCKS  2048
65 #define MIN_LDG_LOCKS  2
66
67
68 /*! global dialog table */
69 struct dlg_table *d_table = 0;
70
71
72 /*!
73  * \brief Initialize the global dialog table
74  * \param size size of the table
75  * \return 0 on success, -1 on failure
76  */
77 int init_dlg_table(unsigned int size)
78 {
79         unsigned int n;
80         unsigned int i;
81
82         d_table = (struct dlg_table*)shm_malloc
83                 ( sizeof(struct dlg_table) + size*sizeof(struct dlg_entry));
84         if (d_table==0) {
85                 LM_ERR("no more shm mem (1)\n");
86                 goto error0;
87         }
88
89         memset( d_table, 0, sizeof(struct dlg_table) );
90         d_table->size = size;
91         d_table->entries = (struct dlg_entry*)(d_table+1);
92
93         n = (size<MAX_LDG_LOCKS)?size:MAX_LDG_LOCKS;
94         for(  ; n>=MIN_LDG_LOCKS ; n-- ) {
95                 d_table->locks = lock_set_alloc(n);
96                 if (d_table->locks==0)
97                         continue;
98                 if (lock_set_init(d_table->locks)==0) {
99                         lock_set_dealloc(d_table->locks);
100                         d_table->locks = 0;
101                         continue;
102                 }
103                 d_table->locks_no = n;
104                 break;
105         }
106
107         if (d_table->locks==0) {
108                 LM_ERR("unable to allocted at least %d locks for the hash table\n",
109                         MIN_LDG_LOCKS);
110                 goto error1;
111         }
112
113         for( i=0 ; i<size; i++ ) {
114                 memset( &(d_table->entries[i]), 0, sizeof(struct dlg_entry) );
115                 d_table->entries[i].next_id = rand();
116                 d_table->entries[i].lock_idx = i % d_table->locks_no;
117         }
118
119         return 0;
120 error1:
121         shm_free( d_table );
122 error0:
123         return -1;
124 }
125
126
127 /*!
128  * \brief Destroy a dialog, run callbacks and free memory
129  * \param dlg destroyed dialog
130  */
131 inline void destroy_dlg(struct dlg_cell *dlg)
132 {
133         int ret = 0;
134
135         LM_DBG("destroing dialog %p\n",dlg);
136
137         ret = remove_dialog_timer(&dlg->tl);
138         if (ret < 0) {
139                 LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
140                         "with clid '%.*s' and tags '%.*s' '%.*s'\n",
141                         dlg, dlg->h_entry, dlg->h_id,
142                         dlg->callid.len, dlg->callid.s,
143                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
144                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
145         } else if (ret > 0) {
146                 LM_DBG("removed timer for dlg %p [%u:%u] "
147                         "with clid '%.*s' and tags '%.*s' '%.*s'\n",
148                         dlg, dlg->h_entry, dlg->h_id,
149                         dlg->callid.len, dlg->callid.s,
150                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
151                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
152         }
153
154         run_dlg_callbacks( DLGCB_DESTROY , dlg, 0, DLG_DIR_NONE, 0);
155
156         if (dlg->cbs.first)
157                 destroy_dlg_callbacks_list(dlg->cbs.first);
158
159         if (dlg->profile_links)
160                 destroy_linkers(dlg->profile_links);
161
162         if (dlg->tag[DLG_CALLER_LEG].s)
163                 shm_free(dlg->tag[DLG_CALLER_LEG].s);
164
165         if (dlg->tag[DLG_CALLEE_LEG].s)
166                 shm_free(dlg->tag[DLG_CALLEE_LEG].s);
167
168         if (dlg->cseq[DLG_CALLER_LEG].s)
169                 shm_free(dlg->cseq[DLG_CALLER_LEG].s);
170
171         if (dlg->cseq[DLG_CALLEE_LEG].s)
172                 shm_free(dlg->cseq[DLG_CALLEE_LEG].s);
173
174         shm_free(dlg);
175 }
176
177
178 /*!
179  * \brief Destroy the global dialog table
180  */
181 void destroy_dlg_table(void)
182 {
183         struct dlg_cell *dlg, *l_dlg;
184         unsigned int i;
185
186         if (d_table==0)
187                 return;
188
189         if (d_table->locks) {
190                 lock_set_destroy(d_table->locks);
191                 lock_set_dealloc(d_table->locks);
192         }
193
194         for( i=0 ; i<d_table->size; i++ ) {
195                 dlg = d_table->entries[i].first;
196                 while (dlg) {
197                         l_dlg = dlg;
198                         dlg = dlg->next;
199                         destroy_dlg(l_dlg);
200                 }
201
202         }
203
204         shm_free(d_table);
205         d_table = 0;
206
207         return;
208 }
209
210
211 /*!
212  * \brief Create a new dialog structure for a SIP dialog
213  * \param callid dialog callid
214  * \param from_uri dialog from uri
215  * \param to_uri dialog to uri
216  * \param from_tag dialog from tag
217  * \return created dialog structure on success, NULL otherwise
218  */
219 struct dlg_cell* build_new_dlg( str *callid, str *from_uri, str *to_uri,
220                 str *from_tag)
221 {
222         struct dlg_cell *dlg;
223         int len;
224         char *p;
225
226         len = sizeof(struct dlg_cell) + callid->len + from_uri->len +
227                 to_uri->len;
228         dlg = (struct dlg_cell*)shm_malloc( len );
229         if (dlg==0) {
230                 LM_ERR("no more shm mem (%d)\n",len);
231                 return 0;
232         }
233
234         memset( dlg, 0, len);
235         dlg->state = DLG_STATE_UNCONFIRMED;
236
237         dlg->h_entry = core_hash( callid, from_tag->len?from_tag:0, d_table->size);
238         LM_DBG("new dialog on hash %u\n",dlg->h_entry);
239
240         p = (char*)(dlg+1);
241
242         dlg->callid.s = p;
243         dlg->callid.len = callid->len;
244         memcpy( p, callid->s, callid->len);
245         p += callid->len;
246
247         dlg->from_uri.s = p;
248         dlg->from_uri.len = from_uri->len;
249         memcpy( p, from_uri->s, from_uri->len);
250         p += from_uri->len;
251
252         dlg->to_uri.s = p;
253         dlg->to_uri.len = to_uri->len;
254         memcpy( p, to_uri->s, to_uri->len);
255         p += to_uri->len;
256
257         if ( p!=(((char*)dlg)+len) ) {
258                 LM_CRIT("buffer overflow\n");
259                 shm_free(dlg);
260                 return 0;
261         }
262
263         return dlg;
264 }
265
266
267 /*!
268  * \brief Set the leg information for an existing dialog
269  * \param dlg dialog
270  * \param tag from tag or to tag
271  * \param rr record-routing information
272  * \param contact caller or callee contact
273  * \param cseq CSEQ of caller or callee
274  * \param leg must be either DLG_CALLER_LEG, or DLG_CALLEE_LEG
275  * \return 0 on success, -1 on failure
276  */
277 int dlg_set_leg_info(struct dlg_cell *dlg, str* tag, str *rr, str *contact,
278                                         str *cseq, unsigned int leg)
279 {
280         char *p;
281
282         dlg->tag[leg].s = (char*)shm_malloc( tag->len + rr->len + contact->len );
283         dlg->cseq[leg].s = (char*)shm_malloc( cseq->len );
284         if ( dlg->tag[leg].s==NULL || dlg->cseq[leg].s==NULL) {
285                 LM_ERR("no more shm mem\n");
286                 if (dlg->tag[leg].s) shm_free(dlg->tag[leg].s);
287                 if (dlg->cseq[leg].s) shm_free(dlg->cseq[leg].s);
288                 return -1;
289         }
290         p = dlg->tag[leg].s;
291
292         /* tag */
293         dlg->tag[leg].len = tag->len;
294         memcpy( p, tag->s, tag->len);
295         p += tag->len;
296         /* contact */
297         dlg->contact[leg].s = p;
298         dlg->contact[leg].len = contact->len;
299         memcpy( p, contact->s, contact->len);
300         p += contact->len;
301         /* rr */
302         if (rr->len) {
303                 dlg->route_set[leg].s = p;
304                 dlg->route_set[leg].len = rr->len;
305                 memcpy( p, rr->s, rr->len);
306         }
307
308         /* cseq */
309         dlg->cseq[leg].len = cseq->len;
310         memcpy( dlg->cseq[leg].s, cseq->s, cseq->len);
311
312         return 0;
313 }
314
315
316 /*!
317  * \brief Update or set the CSEQ for an existing dialog
318  * \param dlg dialog
319  * \param leg must be either DLG_CALLER_LEG, or DLG_CALLEE_LEG
320  * \param cseq CSEQ of caller or callee
321  * \return 0 on success, -1 on failure
322  */
323 int dlg_update_cseq(struct dlg_cell * dlg, unsigned int leg, str *cseq)
324 {
325         if ( dlg->cseq[leg].s ) {
326                 if (dlg->cseq[leg].len < cseq->len) {
327                         shm_free(dlg->cseq[leg].s);
328                         dlg->cseq[leg].s = (char*)shm_malloc(cseq->len);
329                         if (dlg->cseq[leg].s==NULL)
330                                 goto error;
331                 }
332         } else {
333                 dlg->cseq[leg].s = (char*)shm_malloc(cseq->len);
334                 if (dlg->cseq[leg].s==NULL)
335                         goto error;
336         }
337
338         memcpy( dlg->cseq[leg].s, cseq->s, cseq->len );
339         dlg->cseq[leg].len = cseq->len;
340
341         LM_DBG("cseq is %.*s\n", dlg->cseq[leg].len, dlg->cseq[leg].s);
342         return 0;
343 error:
344         LM_ERR("not more shm mem\n");
345         return -1;
346 }
347
348
349 /*!
350  * \brief Lookup a dialog in the global list
351  * \param h_entry number of the hash table entry
352  * \param h_id id of the hash table entry
353  * \return dialog on success, NULL on failure
354  */
355 struct dlg_cell* lookup_dlg( unsigned int h_entry, unsigned int h_id)
356 {
357         struct dlg_cell *dlg;
358         struct dlg_entry *d_entry;
359
360         if (h_entry>=d_table->size)
361                 goto not_found;
362
363         d_entry = &(d_table->entries[h_entry]);
364
365         dlg_lock( d_table, d_entry);
366
367         for( dlg=d_entry->first ; dlg ; dlg=dlg->next ) {
368                 if (dlg->h_id == h_id) {
369                         if (dlg->state==DLG_STATE_DELETED) {
370                                 dlg_unlock( d_table, d_entry);
371                                 goto not_found;
372                         }
373                         dlg->ref++;
374                         LM_DBG("ref dlg %p with 1 -> %d\n", dlg, dlg->ref);
375                         dlg_unlock( d_table, d_entry);
376                         LM_DBG("dialog id=%u found on entry %u\n", h_id, h_entry);
377                         return dlg;
378                 }
379         }
380
381         dlg_unlock( d_table, d_entry);
382 not_found:
383         LM_DBG("no dialog id=%u found on entry %u\n", h_id, h_entry);
384         return 0;
385 }
386
387
388 /*!
389  * \brief Helper function to get a dialog corresponding to a SIP message
390  * \see get_dlg
391  * \param callid callid
392  * \param ftag from tag
393  * \param ttag to tag
394  * \param dir direction
395  * \return dialog structure on success, NULL on failure
396  */
397 static inline struct dlg_cell* internal_get_dlg(unsigned int h_entry,
398                                                 str *callid, str *ftag, str *ttag, unsigned int *dir)
399 {
400         struct dlg_cell *dlg;
401         struct dlg_entry *d_entry;
402
403         d_entry = &(d_table->entries[h_entry]);
404
405         dlg_lock( d_table, d_entry);
406
407         for( dlg = d_entry->first ; dlg ; dlg = dlg->next ) {
408                 /* Check callid / fromtag / totag */
409                 if (match_dialog( dlg, callid, ftag, ttag, dir)==1) {
410                         if (dlg->state==DLG_STATE_DELETED) {
411                                 dlg_unlock( d_table, d_entry);
412                                 goto not_found;
413                         }
414                         dlg->ref++;
415                         LM_DBG("ref dlg %p with 1 -> %d\n", dlg, dlg->ref);
416                         dlg_unlock( d_table, d_entry);
417                         LM_DBG("dialog callid='%.*s' found\n on entry %u, dir=%d\n",
418                                 callid->len, callid->s,h_entry,*dir);
419                         return dlg;
420                 }
421         }
422
423         dlg_unlock( d_table, d_entry);
424
425 not_found:
426         LM_DBG("no dialog callid='%.*s' found\n", callid->len, callid->s);
427         return 0;
428 }
429
430
431
432 /*!
433  * \brief Get dialog that correspond to CallId, From Tag and To Tag
434  *
435  * Get dialog that correspond to CallId, From Tag and To Tag.
436  * See RFC 3261, paragraph 4. Overview of Operation:                 
437  * "The combination of the To tag, From tag, and Call-ID completely  
438  * defines a peer-to-peer SIP relationship between [two UAs] and is 
439  * referred to as a dialog."
440  * \param callid callid
441  * \param ftag from tag
442  * \param ttag to tag
443  * \param dir direction
444  * \return dialog structure on success, NULL on failure
445  */
446 struct dlg_cell* get_dlg( str *callid, str *ftag, str *ttag, unsigned int *dir)
447 {
448         struct dlg_cell *dlg;
449
450         if ((dlg = internal_get_dlg(core_hash(callid, ftag->len?ftag:0,
451                         d_table->size), callid, ftag, ttag, dir)) == 0 &&
452                         (dlg = internal_get_dlg(core_hash(callid, ttag->len
453                         ?ttag:0, d_table->size), callid, ftag, ttag, dir)) == 0) {
454                 LM_DBG("no dialog callid='%.*s' found\n", callid->len, callid->s);
455                 return 0;
456         }
457         return dlg;
458 }
459
460
461 /*!
462  * \brief Link a dialog structure
463  * \param dlg dialog
464  * \param n extra increments for the reference counter
465  */
466 void link_dlg(struct dlg_cell *dlg, int n)
467 {
468         struct dlg_entry *d_entry;
469
470         d_entry = &(d_table->entries[dlg->h_entry]);
471
472         dlg_lock( d_table, d_entry);
473
474         dlg->h_id = d_entry->next_id++;
475         if (d_entry->first==0) {
476                 d_entry->first = d_entry->last = dlg;
477         } else {
478                 d_entry->last->next = dlg;
479                 dlg->prev = d_entry->last;
480                 d_entry->last = dlg;
481         }
482
483         dlg->ref += 1 + n;
484
485         LM_DBG("ref dlg %p with %d -> %d\n", dlg, n+1, dlg->ref);
486
487         dlg_unlock( d_table, d_entry);
488         return;
489 }
490
491
492 /*!
493  * \brief Reference a dialog without locking
494  * \param _dlg dialog
495  * \param _cnt increment for the reference counter
496  */
497 #define ref_dlg_unsafe(_dlg,_cnt)     \
498         do { \
499                 (_dlg)->ref += (_cnt); \
500                 LM_DBG("ref dlg %p with %d -> %d\n", \
501                         (_dlg),(_cnt),(_dlg)->ref); \
502         }while(0)
503
504
505 /*!
506  * \brief Unreference a dialog without locking
507  * \param _dlg dialog
508  * \param _cnt decrement for the reference counter
509  */
510 #define unref_dlg_unsafe(_dlg,_cnt,_d_entry)   \
511         do { \
512                 (_dlg)->ref -= (_cnt); \
513                 LM_DBG("unref dlg %p with %d -> %d\n",\
514                         (_dlg),(_cnt),(_dlg)->ref);\
515                 if ((_dlg)->ref<0) {\
516                         LM_CRIT("bogus ref %d with cnt %d for dlg %p [%u:%u] "\
517                                 "with clid '%.*s' and tags '%.*s' '%.*s'\n",\
518                                 (_dlg)->ref, _cnt, _dlg,\
519                                 (_dlg)->h_entry, (_dlg)->h_id,\
520                                 (_dlg)->callid.len, (_dlg)->callid.s,\
521                                 (_dlg)->tag[DLG_CALLER_LEG].len,\
522                                 (_dlg)->tag[DLG_CALLER_LEG].s,\
523                                 (_dlg)->tag[DLG_CALLEE_LEG].len,\
524                                 (_dlg)->tag[DLG_CALLEE_LEG].s); \
525                 }\
526                 if ((_dlg)->ref<=0) { \
527                         unlink_unsafe_dlg( _d_entry, _dlg);\
528                         LM_DBG("ref <=0 for dialog %p\n",_dlg);\
529                         destroy_dlg(_dlg);\
530                 }\
531         }while(0)
532
533
534 /*!
535  * \brief Refefence a dialog with locking
536  * \see ref_dlg_unsafe
537  * \param dlg dialog
538  * \param cnt increment for the reference counter
539  */
540 void ref_dlg(struct dlg_cell *dlg, unsigned int cnt)
541 {
542         struct dlg_entry *d_entry;
543
544         d_entry = &(d_table->entries[dlg->h_entry]);
545
546         dlg_lock( d_table, d_entry);
547         ref_dlg_unsafe( dlg, cnt);
548         dlg_unlock( d_table, d_entry);
549 }
550
551
552 /*!
553  * \brief Unreference a dialog with locking
554  * \see unref_dlg_unsafe
555  * \param dlg dialog
556  * \param cnt decrement for the reference counter
557  */
558 void unref_dlg(struct dlg_cell *dlg, unsigned int cnt)
559 {
560         struct dlg_entry *d_entry;
561
562         d_entry = &(d_table->entries[dlg->h_entry]);
563
564         dlg_lock( d_table, d_entry);
565         unref_dlg_unsafe( dlg, cnt, d_entry);
566         dlg_unlock( d_table, d_entry);
567 }
568
569
570 /*!
571  * Small logging helper functions for next_state_dlg.
572  * \param event logged event
573  * \param dlg dialog data
574  * \see next_state_dlg
575  */
576 static inline void log_next_state_dlg(const int event, const struct dlg_cell *dlg) {
577         LM_CRIT("bogus event %d in state %d for dlg %p [%u:%u] with clid '%.*s' and tags "
578                 "'%.*s' '%.*s'\n", event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
579                 dlg->callid.len, dlg->callid.s,
580                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
581                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
582 }
583
584
585 /*!
586  * \brief Update a dialog state according a event and the old state
587  *
588  * This functions implement the main state machine that update a dialog
589  * state according a processed event and the current state. If necessary
590  * it will delete the processed dialog. The old and new state are also
591  * saved for reference.
592  * \param dlg updated dialog
593  * \param event current event
594  * \param old_state old dialog state
595  * \param new_state new dialog state
596  * \param unref set to 1 when the dialog was deleted, 0 otherwise
597  */
598 void next_state_dlg(struct dlg_cell *dlg, int event,
599                 int *old_state, int *new_state, int *unref)
600 {
601         struct dlg_entry *d_entry;
602
603         d_entry = &(d_table->entries[dlg->h_entry]);
604
605         *unref = 0;
606
607         dlg_lock( d_table, d_entry);
608
609         *old_state = dlg->state;
610
611         switch (event) {
612                 case DLG_EVENT_TDEL:
613                         switch (dlg->state) {
614                                 case DLG_STATE_UNCONFIRMED:
615                                 case DLG_STATE_EARLY:
616                                         dlg->state = DLG_STATE_DELETED;
617                                         unref_dlg_unsafe(dlg,1,d_entry);
618                                         *unref = 1;
619                                         break;
620                                 case DLG_STATE_CONFIRMED_NA:
621                                 case DLG_STATE_CONFIRMED:
622                                         unref_dlg_unsafe(dlg,1,d_entry);
623                                         break;
624                                 case DLG_STATE_DELETED:
625                                         *unref = 1;
626                                         break;
627                                 default:
628                                         log_next_state_dlg(event, dlg);
629                         }
630                         break;
631                 case DLG_EVENT_RPL1xx:
632                         switch (dlg->state) {
633                                 case DLG_STATE_UNCONFIRMED:
634                                 case DLG_STATE_EARLY:
635                                         dlg->state = DLG_STATE_EARLY;
636                                         break;
637                                 default:
638                                         log_next_state_dlg(event, dlg);
639                         }
640                         break;
641                 case DLG_EVENT_RPL3xx:
642                         switch (dlg->state) {
643                                 case DLG_STATE_UNCONFIRMED:
644                                 case DLG_STATE_EARLY:
645                                         dlg->state = DLG_STATE_DELETED;
646                                         *unref = 1;
647                                         break;
648                                 default:
649                                         log_next_state_dlg(event, dlg);
650                         }
651                         break;
652                 case DLG_EVENT_RPL2xx:
653                         switch (dlg->state) {
654                                 case DLG_STATE_DELETED:
655                                         if (dlg->dflags&DLG_FLAG_HASBYE) {
656                                                 LM_CRIT("bogus event %d in state %d (with BYE) "
657                                                         "for dlg %p [%u:%u] with clid '%.*s' and tags '%.*s' '%.*s'\n",
658                                                         event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
659                                                         dlg->callid.len, dlg->callid.s,
660                                                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
661                                                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
662                                                 break;
663                                         }
664                                         ref_dlg_unsafe(dlg,1);
665                                 case DLG_STATE_UNCONFIRMED:
666                                 case DLG_STATE_EARLY:
667                                         dlg->state = DLG_STATE_CONFIRMED_NA;
668                                         break;
669                                 case DLG_STATE_CONFIRMED_NA:
670                                 case DLG_STATE_CONFIRMED:
671                                         break;
672                                 default:
673                                         log_next_state_dlg(event, dlg);
674                         }
675                         break;
676                 case DLG_EVENT_REQACK:
677                         switch (dlg->state) {
678                                 case DLG_STATE_CONFIRMED_NA:
679                                         dlg->state = DLG_STATE_CONFIRMED;
680                                         break;
681                                 case DLG_STATE_CONFIRMED:
682                                         break;
683                                 case DLG_STATE_DELETED:
684                                         break;
685                                 default:
686                                         log_next_state_dlg(event, dlg);
687                         }
688                         break;
689                 case DLG_EVENT_REQBYE:
690                         switch (dlg->state) {
691                                 case DLG_STATE_CONFIRMED_NA:
692                                 case DLG_STATE_CONFIRMED:
693                                         dlg->dflags |= DLG_FLAG_HASBYE;
694                                         dlg->state = DLG_STATE_DELETED;
695                                         *unref = 1;
696                                         break;
697                                 case DLG_STATE_DELETED:
698                                         break;
699                                 default:
700                                         log_next_state_dlg(event, dlg);
701                         }
702                         break;
703                 case DLG_EVENT_REQPRACK:
704                         switch (dlg->state) {
705                                 case DLG_STATE_EARLY:
706                                 case DLG_STATE_CONFIRMED_NA:
707                                         break;
708                                 default:
709                                         log_next_state_dlg(event, dlg);
710                         }
711                         break;
712                 case DLG_EVENT_REQ:
713                         switch (dlg->state) {
714                                 case DLG_STATE_CONFIRMED_NA:
715                                 case DLG_STATE_CONFIRMED:
716                                         break;
717                                 default:
718                                         log_next_state_dlg(event, dlg);
719                         }
720                         break;
721                 default:
722                         LM_CRIT("unknown event %d in state %d "
723                                 "for dlg %p [%u:%u] with clid '%.*s' and tags '%.*s' '%.*s'\n",
724                                 event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
725                                 dlg->callid.len, dlg->callid.s,
726                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
727                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
728         }
729         *new_state = dlg->state;
730
731         dlg_unlock( d_table, d_entry);
732
733         LM_DBG("dialog %p changed from state %d to "
734                 "state %d, due event %d\n",dlg,*old_state,*new_state,event);
735 }
736
737
738 /**************************** MI functions ******************************/
739 /*!
740  * \brief Helper method that output a dialog via the MI interface
741  * \see mi_print_dlg
742  * \param rpl MI node that should be filled
743  * \param dlg printed dialog
744  * \param with_context if 1 then the dialog context will be also printed
745  * \return 0 on success, -1 on failure
746  */
747 static inline int internal_mi_print_dlg(struct mi_node *rpl,
748                                                                         struct dlg_cell *dlg, int with_context)
749 {
750         struct mi_node* node= NULL;
751         struct mi_node* node1 = NULL;
752         struct mi_attr* attr= NULL;
753         int len;
754         char* p;
755
756         node = add_mi_node_child(rpl, 0, "dialog",6 , 0, 0 );
757         if (node==0)
758                 goto error;
759
760         attr = addf_mi_attr( node, 0, "hash", 4, "%u:%u",
761                         dlg->h_entry, dlg->h_id );
762         if (attr==0)
763                 goto error;
764
765         p= int2str((unsigned long)dlg->state, &len);
766         node1 = add_mi_node_child( node, MI_DUP_VALUE, "state", 5, p, len);
767         if (node1==0)
768                 goto error;
769
770         p= int2str((unsigned long)dlg->start_ts, &len);
771         node1 = add_mi_node_child(node,MI_DUP_VALUE,"timestart",9, p, len);
772         if (node1==0)
773                 goto error;
774
775         p= int2str((unsigned long)dlg->tl.timeout, &len);
776         node1 = add_mi_node_child(node,MI_DUP_VALUE, "timeout", 7, p, len);
777         if (node1==0)
778                 goto error;
779
780         node1 = add_mi_node_child(node, MI_DUP_VALUE, "callid", 6,
781                         dlg->callid.s, dlg->callid.len);
782         if(node1 == 0)
783                 goto error;
784
785         node1 = add_mi_node_child(node, MI_DUP_VALUE, "from_uri", 8,
786                         dlg->from_uri.s, dlg->from_uri.len);
787         if(node1 == 0)
788                 goto error;
789
790         node1 = add_mi_node_child(node, MI_DUP_VALUE, "from_tag", 8,
791                         dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLER_LEG].len);
792         if(node1 == 0)
793                 goto error;
794
795         node1 = add_mi_node_child(node, MI_DUP_VALUE, "caller_contact", 14,
796                         dlg->contact[DLG_CALLER_LEG].s,
797                         dlg->contact[DLG_CALLER_LEG].len);
798         if(node1 == 0)
799                 goto error;
800
801         node1 = add_mi_node_child(node, MI_DUP_VALUE, "caller_cseq", 11,
802                         dlg->cseq[DLG_CALLER_LEG].s,
803                         dlg->cseq[DLG_CALLER_LEG].len);
804         if(node1 == 0)
805                 goto error;
806
807         node1 = add_mi_node_child(node, MI_DUP_VALUE,"caller_route_set",16,
808                         dlg->route_set[DLG_CALLER_LEG].s,
809                         dlg->route_set[DLG_CALLER_LEG].len);
810         if(node1 == 0)
811                 goto error;
812
813         node1 = add_mi_node_child(node, 0,"caller_bind_addr",16,
814                         dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s, 
815                         dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len);
816         if(node1 == 0)
817                 goto error;
818
819         node1 = add_mi_node_child(node, MI_DUP_VALUE, "to_uri", 6,
820                         dlg->to_uri.s, dlg->to_uri.len);
821         if(node1 == 0)
822                 goto error;
823
824         node1 = add_mi_node_child(node, MI_DUP_VALUE, "to_tag", 6,
825                         dlg->tag[DLG_CALLEE_LEG].s, dlg->tag[DLG_CALLEE_LEG].len);
826         if(node1 == 0)
827                 goto error;
828
829         node1 = add_mi_node_child(node, MI_DUP_VALUE, "callee_contact", 14,
830                         dlg->contact[DLG_CALLEE_LEG].s,
831                         dlg->contact[DLG_CALLEE_LEG].len);
832         if(node1 == 0)
833                 goto error;
834
835         node1 = add_mi_node_child(node, MI_DUP_VALUE, "callee_cseq", 11,
836                         dlg->cseq[DLG_CALLEE_LEG].s,
837                         dlg->cseq[DLG_CALLEE_LEG].len);
838         if(node1 == 0)
839                 goto error;
840
841         node1 = add_mi_node_child(node, MI_DUP_VALUE,"callee_route_set",16,
842                         dlg->route_set[DLG_CALLEE_LEG].s,
843                         dlg->route_set[DLG_CALLEE_LEG].len);
844         if(node1 == 0)
845                 goto error;
846
847         if (dlg->bind_addr[DLG_CALLEE_LEG]) {
848                 node1 = add_mi_node_child(node, 0,
849                         "callee_bind_addr",16,
850                         dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s, 
851                         dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len);
852         } else {
853                 node1 = add_mi_node_child(node, 0,
854                         "callee_bind_addr",16,0,0);
855         }
856         if(node1 == 0)
857                 goto error;
858
859         if (with_context) {
860                 node1 = add_mi_node_child(node, 0, "context", 7, 0, 0);
861                 if(node1 == 0)
862                         goto error;
863                 run_dlg_callbacks( DLGCB_MI_CONTEXT, dlg, NULL, 
864                         DLG_DIR_NONE, (void *)node1);
865         }
866         return 0;
867
868 error:
869         LM_ERR("failed to add node\n");
870         return -1;
871 }
872
873
874 /*!
875  * \brief Output a dialog via the MI interface
876  * \param rpl MI node that should be filled
877  * \param dlg printed dialog
878  * \param with_context if 1 then the dialog context will be also printed
879  * \return 0 on success, -1 on failure
880  */
881 int mi_print_dlg(struct mi_node *rpl, struct dlg_cell *dlg, int with_context)
882 {
883         return internal_mi_print_dlg( rpl, dlg, with_context);
884 }
885
886 /*!
887  * \brief Helper function that output all dialogs via the MI interface
888  * \see mi_print_dlgs
889  * \param rpl MI node that should be filled
890  * \param with_context if 1 then the dialog context will be also printed
891  * \return 0 on success, -1 on failure
892  */
893 static int internal_mi_print_dlgs(struct mi_node *rpl, int with_context)
894 {
895         struct dlg_cell *dlg;
896         unsigned int i;
897
898         LM_DBG("printing %i dialogs\n", d_table->size);
899
900         for( i=0 ; i<d_table->size ; i++ ) {
901                 dlg_lock( d_table, &(d_table->entries[i]) );
902
903                 for( dlg=d_table->entries[i].first ; dlg ; dlg=dlg->next ) {
904                         if (internal_mi_print_dlg(rpl, dlg, with_context)!=0)
905                                 goto error;
906                 }
907                 dlg_unlock( d_table, &(d_table->entries[i]) );
908         }
909         return 0;
910
911 error:
912         dlg_unlock( d_table, &(d_table->entries[i]) );
913         LM_ERR("failed to print dialog\n");
914         return -1;
915 }
916
917
918 static inline struct mi_root* process_mi_params(struct mi_root *cmd_tree,
919                                                                                                         struct dlg_cell **dlg_p)
920 {
921         struct mi_node* node;
922         struct dlg_entry *d_entry;
923         struct dlg_cell *dlg;
924         str *callid;
925         str *from_tag;
926         unsigned int h_entry;
927
928         node = cmd_tree->node.kids;
929         if (node == NULL) {
930                 /* no parameters at all */
931                 *dlg_p = NULL;
932                 return NULL;
933         }
934
935         /* we have params -> get callid and fromtag */
936         callid = &node->value;
937         LM_DBG("callid='%.*s'\n", callid->len, callid->s);
938
939         node = node->next;
940         if ( !node || !node->value.s || !node->value.len) {
941                 from_tag = NULL;
942         } else {
943                 from_tag = &node->value;
944                 LM_DBG("from_tag='%.*s'\n", from_tag->len, from_tag->s);
945                 if ( node->next!=NULL )
946                         return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
947         }
948
949         h_entry = core_hash( callid, from_tag, d_table->size);
950
951         d_entry = &(d_table->entries[h_entry]);
952         dlg_lock( d_table, d_entry);
953
954         for( dlg = d_entry->first ; dlg ; dlg = dlg->next ) {
955                 if (match_downstream_dialog( dlg, callid, from_tag)==1) {
956                         if (dlg->state==DLG_STATE_DELETED) {
957                                 *dlg_p = NULL;
958                                 break;
959                         } else {
960                                 *dlg_p = dlg;
961                                 dlg_unlock( d_table, d_entry);
962                                 return 0;
963                         }
964                 }
965         }
966         dlg_unlock( d_table, d_entry);
967
968         return init_mi_tree( 404, MI_SSTR("Nu such dialog"));
969 }
970
971
972 /*!
973  * \brief Output all dialogs via the MI interface
974  * \param cmd_tree MI command tree
975  * \param param unused
976  * \return mi node with the dialog information, or NULL on failure
977  */
978 struct mi_root * mi_print_dlgs(struct mi_root *cmd_tree, void *param )
979 {
980         struct mi_root* rpl_tree= NULL;
981         struct mi_node* rpl = NULL;
982         struct dlg_cell* dlg = NULL;
983
984         rpl_tree = process_mi_params( cmd_tree, &dlg);
985         if (rpl_tree)
986                 /* param error */
987                 return rpl_tree;
988
989         rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
990         if (rpl_tree==0)
991                 return 0;
992         rpl = &rpl_tree->node;
993
994         if (dlg==NULL) {
995                 if ( internal_mi_print_dlgs(rpl,0)!=0 )
996                         goto error;
997         } else {
998                 if ( internal_mi_print_dlg(rpl,dlg,0)!=0 )
999                         goto error;
1000         }
1001
1002         return rpl_tree;
1003 error:
1004         free_mi_tree(rpl_tree);
1005         return NULL;
1006 }
1007
1008
1009 /*!
1010  * \brief Print a dialog context via the MI interface
1011  * \param cmd_tree MI command tree
1012  * \param param unused
1013  * \return mi node with the dialog information, or NULL on failure
1014  */
1015 struct mi_root * mi_print_dlgs_ctx(struct mi_root *cmd_tree, void *param )
1016 {
1017         struct mi_root* rpl_tree= NULL;
1018         struct mi_node* rpl = NULL;
1019         struct dlg_cell* dlg = NULL;
1020
1021         rpl_tree = process_mi_params( cmd_tree, &dlg);
1022         if (rpl_tree)
1023                 /* param error */
1024                 return rpl_tree;
1025
1026         rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
1027         if (rpl_tree==0)
1028                 return 0;
1029         rpl = &rpl_tree->node;
1030
1031         if (dlg==NULL) {
1032                 if ( internal_mi_print_dlgs(rpl,1)!=0 )
1033                         goto error;
1034         } else {
1035                 if ( internal_mi_print_dlg(rpl,dlg,1)!=0 )
1036                         goto error;
1037         }
1038
1039         return rpl_tree;
1040 error:
1041         free_mi_tree(rpl_tree);
1042         return NULL;
1043 }