script parsing: fix bug in expression error checking
[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 #include <stdlib.h>
46 #include <string.h>
47
48 #include "../../dprint.h"
49 #include "../../ut.h"
50 #include "../../lib/kcore/hash_func.h"
51 #include "../../lib/kmi/mi.h"
52 #include "dlg_timer.h"
53 #include "dlg_hash.h"
54 #include "dlg_profile.h"
55
56 #define MAX_LDG_LOCKS  2048
57 #define MIN_LDG_LOCKS  2
58
59
60 struct dlg_table *d_table = 0;
61
62 int init_dlg_table(unsigned int size)
63 {
64         unsigned int n;
65         unsigned int i;
66
67         d_table = (struct dlg_table*)shm_malloc
68                 ( sizeof(struct dlg_table) + size*sizeof(struct dlg_entry));
69         if (d_table==0) {
70                 LM_ERR("no more shm mem (1)\n");
71                 goto error0;
72         }
73
74         memset( d_table, 0, sizeof(struct dlg_table) );
75         d_table->size = size;
76         d_table->entries = (struct dlg_entry*)(d_table+1);
77
78         n = (size<MAX_LDG_LOCKS)?size:MAX_LDG_LOCKS;
79         for(  ; n>=MIN_LDG_LOCKS ; n-- ) {
80                 d_table->locks = lock_set_alloc(n);
81                 if (d_table->locks==0)
82                         continue;
83                 if (lock_set_init(d_table->locks)==0) {
84                         lock_set_dealloc(d_table->locks);
85                         d_table->locks = 0;
86                         continue;
87                 }
88                 d_table->locks_no = n;
89                 break;
90         }
91
92         if (d_table->locks==0) {
93                 LM_ERR("unable to allocted at least %d locks for the hash table\n",
94                         MIN_LDG_LOCKS);
95                 goto error1;
96         }
97
98         for( i=0 ; i<size; i++ ) {
99                 memset( &(d_table->entries[i]), 0, sizeof(struct dlg_entry) );
100                 d_table->entries[i].next_id = rand();
101                 d_table->entries[i].lock_idx = i % d_table->locks_no;
102         }
103
104         return 0;
105 error1:
106         shm_free( d_table );
107 error0:
108         return -1;
109 }
110
111
112
113 inline void destroy_dlg(struct dlg_cell *dlg)
114 {
115         int ret = 0;
116
117         LM_DBG("destroing dialog %p\n",dlg);
118
119         ret = remove_dialog_timer(&dlg->tl);
120         if (ret < 0) {
121                 LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
122                         "with clid '%.*s' and tags '%.*s' '%.*s'\n",
123                         dlg, dlg->h_entry, dlg->h_id,
124                         dlg->callid.len, dlg->callid.s,
125                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
126                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
127         } else if (ret > 0) {
128                 LM_DBG("removed timer for dlg %p [%u:%u] "
129                         "with clid '%.*s' and tags '%.*s' '%.*s'\n",
130                         dlg, dlg->h_entry, dlg->h_id,
131                         dlg->callid.len, dlg->callid.s,
132                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
133                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
134         }
135
136         run_dlg_callbacks( DLGCB_DESTROY , dlg, 0, DLG_DIR_NONE, 0);
137
138         if (dlg->cbs.first)
139                 destroy_dlg_callbacks_list(dlg->cbs.first);
140
141         if (dlg->profile_links)
142                 destroy_linkers(dlg->profile_links);
143
144         if (dlg->tag[DLG_CALLER_LEG].s)
145                 shm_free(dlg->tag[DLG_CALLER_LEG].s);
146
147         if (dlg->tag[DLG_CALLEE_LEG].s)
148                 shm_free(dlg->tag[DLG_CALLEE_LEG].s);
149
150         if (dlg->cseq[DLG_CALLER_LEG].s)
151                 shm_free(dlg->cseq[DLG_CALLER_LEG].s);
152
153         if (dlg->cseq[DLG_CALLEE_LEG].s)
154                 shm_free(dlg->cseq[DLG_CALLEE_LEG].s);
155
156         shm_free(dlg);
157 }
158
159
160
161 void destroy_dlg_table(void)
162 {
163         struct dlg_cell *dlg, *l_dlg;
164         unsigned int i;
165
166         if (d_table==0)
167                 return;
168
169         if (d_table->locks) {
170                 lock_set_destroy(d_table->locks);
171                 lock_set_dealloc(d_table->locks);
172         }
173
174         for( i=0 ; i<d_table->size; i++ ) {
175                 dlg = d_table->entries[i].first;
176                 while (dlg) {
177                         l_dlg = dlg;
178                         dlg = dlg->next;
179                         destroy_dlg(l_dlg);
180                 }
181
182         }
183
184         shm_free(d_table);
185         d_table = 0;
186
187         return;
188 }
189
190
191
192 struct dlg_cell* build_new_dlg( str *callid, str *from_uri, str *to_uri,
193                                                                                                                                 str *from_tag)
194 {
195         struct dlg_cell *dlg;
196         int len;
197         char *p;
198
199         len = sizeof(struct dlg_cell) + callid->len + from_uri->len +
200                 to_uri->len;
201         dlg = (struct dlg_cell*)shm_malloc( len );
202         if (dlg==0) {
203                 LM_ERR("no more shm mem (%d)\n",len);
204                 return 0;
205         }
206
207         memset( dlg, 0, len);
208         dlg->state = DLG_STATE_UNCONFIRMED;
209
210         dlg->h_entry = core_hash( callid, from_tag->len?from_tag:0, d_table->size);
211         LM_DBG("new dialog on hash %u\n",dlg->h_entry);
212
213         p = (char*)(dlg+1);
214
215         dlg->callid.s = p;
216         dlg->callid.len = callid->len;
217         memcpy( p, callid->s, callid->len);
218         p += callid->len;
219
220         dlg->from_uri.s = p;
221         dlg->from_uri.len = from_uri->len;
222         memcpy( p, from_uri->s, from_uri->len);
223         p += from_uri->len;
224
225         dlg->to_uri.s = p;
226         dlg->to_uri.len = to_uri->len;
227         memcpy( p, to_uri->s, to_uri->len);
228         p += to_uri->len;
229
230         if ( p!=(((char*)dlg)+len) ) {
231                 LM_CRIT("buffer overflow\n");
232                 shm_free(dlg);
233                 return 0;
234         }
235
236         return dlg;
237 }
238
239
240
241 int dlg_set_leg_info(struct dlg_cell *dlg, str* tag, str *rr, str *contact,
242                                         str *cseq, unsigned int leg)
243 {
244         char *p;
245
246         dlg->tag[leg].s = (char*)shm_malloc( tag->len + rr->len + contact->len );
247         dlg->cseq[leg].s = (char*)shm_malloc( cseq->len );
248         if ( dlg->tag[leg].s==NULL || dlg->cseq[leg].s==NULL) {
249                 LM_ERR("no more shm mem\n");
250                 if (dlg->tag[leg].s) shm_free(dlg->tag[leg].s);
251                 if (dlg->cseq[leg].s) shm_free(dlg->cseq[leg].s);
252                 return -1;
253         }
254         p = dlg->tag[leg].s;
255
256         /* tag */
257         dlg->tag[leg].len = tag->len;
258         memcpy( p, tag->s, tag->len);
259         p += tag->len;
260         /* contact */
261         dlg->contact[leg].s = p;
262         dlg->contact[leg].len = contact->len;
263         memcpy( p, contact->s, contact->len);
264         p += contact->len;
265         /* rr */
266         if (rr->len) {
267                 dlg->route_set[leg].s = p;
268                 dlg->route_set[leg].len = rr->len;
269                 memcpy( p, rr->s, rr->len);
270         }
271
272         /* cseq */
273         dlg->cseq[leg].len = cseq->len;
274         memcpy( dlg->cseq[leg].s, cseq->s, cseq->len);
275
276         return 0;
277 }
278
279
280
281 int dlg_update_cseq(struct dlg_cell * dlg, unsigned int leg, str *cseq)
282 {
283         if ( dlg->cseq[leg].s ) {
284                 if (dlg->cseq[leg].len < cseq->len) {
285                         shm_free(dlg->cseq[leg].s);
286                         dlg->cseq[leg].s = (char*)shm_malloc(cseq->len);
287                         if (dlg->cseq[leg].s==NULL)
288                                 goto error;
289                 }
290         } else {
291                 dlg->cseq[leg].s = (char*)shm_malloc(cseq->len);
292                 if (dlg->cseq[leg].s==NULL)
293                         goto error;
294         }
295
296         memcpy( dlg->cseq[leg].s, cseq->s, cseq->len );
297         dlg->cseq[leg].len = cseq->len;
298
299         LM_DBG("cseq is %.*s\n", dlg->cseq[leg].len, dlg->cseq[leg].s);
300         return 0;
301 error:
302         LM_ERR("not more shm mem\n");
303         return -1;
304 }
305
306
307
308 struct dlg_cell* lookup_dlg( unsigned int h_entry, unsigned int h_id)
309 {
310         struct dlg_cell *dlg;
311         struct dlg_entry *d_entry;
312
313         if (h_entry>=d_table->size)
314                 goto not_found;
315
316         d_entry = &(d_table->entries[h_entry]);
317
318         dlg_lock( d_table, d_entry);
319
320         for( dlg=d_entry->first ; dlg ; dlg=dlg->next ) {
321                 if (dlg->h_id == h_id) {
322                         if (dlg->state==DLG_STATE_DELETED) {
323                                 dlg_unlock( d_table, d_entry);
324                                 goto not_found;
325                         }
326                         dlg->ref++;
327                         LM_DBG("ref dlg %p with 1 -> %d\n", dlg, dlg->ref);
328                         dlg_unlock( d_table, d_entry);
329                         LM_DBG("dialog id=%u found on entry %u\n", h_id, h_entry);
330                         return dlg;
331                 }
332         }
333
334         dlg_unlock( d_table, d_entry);
335 not_found:
336         LM_DBG("no dialog id=%u found on entry %u\n", h_id, h_entry);
337         return 0;
338 }
339
340
341
342 static inline struct dlg_cell* internal_get_dlg(unsigned int h_entry,
343                                                 str *callid, str *ftag, str *ttag, unsigned int *dir)
344 {
345         struct dlg_cell *dlg;
346         struct dlg_entry *d_entry;
347
348         d_entry = &(d_table->entries[h_entry]);
349
350         dlg_lock( d_table, d_entry);
351
352         for( dlg = d_entry->first ; dlg ; dlg = dlg->next ) {
353                 /* Check callid / fromtag / totag */
354                 if (match_dialog( dlg, callid, ftag, ttag, dir)==1) {
355                         if (dlg->state==DLG_STATE_DELETED) {
356                                 dlg_unlock( d_table, d_entry);
357                                 goto not_found;
358                         }
359                         dlg->ref++;
360                         LM_DBG("ref dlg %p with 1 -> %d\n", dlg, dlg->ref);
361                         dlg_unlock( d_table, d_entry);
362                         LM_DBG("dialog callid='%.*s' found\n on entry %u, dir=%d\n",
363                                 callid->len, callid->s,h_entry,*dir);
364                         return dlg;
365                 }
366         }
367
368         dlg_unlock( d_table, d_entry);
369
370 not_found:
371         LM_DBG("no dialog callid='%.*s' found\n", callid->len, callid->s);
372         return 0;
373 }
374
375
376
377 /* Get dialog that correspond to CallId, From Tag and To Tag         */
378 /* See RFC 3261, paragraph 4. Overview of Operation:                 */
379 /* "The combination of the To tag, From tag, and Call-ID completely  */
380 /* defines a peer-to-peer SIP relationship between [two UAs] and is  */
381 /* referred to as a dialog."*/
382 struct dlg_cell* get_dlg( str *callid, str *ftag, str *ttag, unsigned int *dir)
383 {
384         struct dlg_cell *dlg;
385
386         if ((dlg = internal_get_dlg(core_hash(callid, ftag->len?ftag:0,
387                         d_table->size), callid, ftag, ttag, dir)) == 0 &&
388                         (dlg = internal_get_dlg(core_hash(callid, ttag->len
389                         ?ttag:0, d_table->size), callid, ftag, ttag, dir)) == 0) {
390                 LM_DBG("no dialog callid='%.*s' found\n", callid->len, callid->s);
391                 return 0;
392         }
393         return dlg;
394 }
395
396
397
398 void link_dlg(struct dlg_cell *dlg, int n)
399 {
400         struct dlg_entry *d_entry;
401
402         d_entry = &(d_table->entries[dlg->h_entry]);
403
404         dlg_lock( d_table, d_entry);
405
406         dlg->h_id = d_entry->next_id++;
407         if (d_entry->first==0) {
408                 d_entry->first = d_entry->last = dlg;
409         } else {
410                 d_entry->last->next = dlg;
411                 dlg->prev = d_entry->last;
412                 d_entry->last = dlg;
413         }
414
415         dlg->ref += 1 + n;
416
417         LM_DBG("ref dlg %p with %d -> %d\n", dlg, n+1, dlg->ref);
418
419         dlg_unlock( d_table, d_entry);
420         return;
421 }
422
423
424
425 inline void unlink_unsafe_dlg(struct dlg_entry *d_entry,
426                                                                                                         struct dlg_cell *dlg)
427 {
428         if (dlg->next)
429                 dlg->next->prev = dlg->prev;
430         else
431                 d_entry->last = dlg->prev;
432         if (dlg->prev)
433                 dlg->prev->next = dlg->next;
434         else
435                 d_entry->first = dlg->next;
436
437         dlg->next = dlg->prev = 0;
438
439         return;
440 }
441
442
443 void ref_dlg(struct dlg_cell *dlg, unsigned int cnt)
444 {
445         struct dlg_entry *d_entry;
446
447         d_entry = &(d_table->entries[dlg->h_entry]);
448
449         dlg_lock( d_table, d_entry);
450         ref_dlg_unsafe( dlg, cnt);
451         dlg_unlock( d_table, d_entry);
452 }
453
454
455 void unref_dlg(struct dlg_cell *dlg, unsigned int cnt)
456 {
457         struct dlg_entry *d_entry;
458
459         d_entry = &(d_table->entries[dlg->h_entry]);
460
461         dlg_lock( d_table, d_entry);
462         unref_dlg_unsafe( dlg, cnt, d_entry);
463         dlg_unlock( d_table, d_entry);
464 }
465
466
467 /**
468  * Small logging helper functions for next_state_dlg.
469  * \param event logged event
470  * \param dlg dialog data
471  * \see next_state_dlg
472  */
473 static inline void log_next_state_dlg(const int event, const struct dlg_cell *dlg) {
474         LM_CRIT("bogus event %d in state %d for dlg %p [%u:%u] with clid '%.*s' and tags "
475                 "'%.*s' '%.*s'\n", event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
476                 dlg->callid.len, dlg->callid.s,
477                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
478                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
479 }
480
481
482 void next_state_dlg(struct dlg_cell *dlg, int event,
483                                                                 int *old_state, int *new_state, int *unref)
484 {
485         struct dlg_entry *d_entry;
486
487         d_entry = &(d_table->entries[dlg->h_entry]);
488
489         *unref = 0;
490
491         dlg_lock( d_table, d_entry);
492
493         *old_state = dlg->state;
494
495         switch (event) {
496                 case DLG_EVENT_TDEL:
497                         switch (dlg->state) {
498                                 case DLG_STATE_UNCONFIRMED:
499                                 case DLG_STATE_EARLY:
500                                         dlg->state = DLG_STATE_DELETED;
501                                         unref_dlg_unsafe(dlg,1,d_entry);
502                                         *unref = 1;
503                                         break;
504                                 case DLG_STATE_CONFIRMED_NA:
505                                 case DLG_STATE_CONFIRMED:
506                                         unref_dlg_unsafe(dlg,1,d_entry);
507                                         break;
508                                 case DLG_STATE_DELETED:
509                                         *unref = 1;
510                                         break;
511                                 default:
512                                         log_next_state_dlg(event, dlg);
513                         }
514                         break;
515                 case DLG_EVENT_RPL1xx:
516                         switch (dlg->state) {
517                                 case DLG_STATE_UNCONFIRMED:
518                                 case DLG_STATE_EARLY:
519                                         dlg->state = DLG_STATE_EARLY;
520                                         break;
521                                 default:
522                                         log_next_state_dlg(event, dlg);
523                         }
524                         break;
525                 case DLG_EVENT_RPL3xx:
526                         switch (dlg->state) {
527                                 case DLG_STATE_UNCONFIRMED:
528                                 case DLG_STATE_EARLY:
529                                         dlg->state = DLG_STATE_DELETED;
530                                         *unref = 1;
531                                         break;
532                                 default:
533                                         log_next_state_dlg(event, dlg);
534                         }
535                         break;
536                 case DLG_EVENT_RPL2xx:
537                         switch (dlg->state) {
538                                 case DLG_STATE_DELETED:
539                                         if (dlg->dflags&DLG_FLAG_HASBYE) {
540                                                 LM_CRIT("bogus event %d in state %d (with BYE) "
541                                                         "for dlg %p [%u:%u] with clid '%.*s' and tags '%.*s' '%.*s'\n",
542                                                         event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
543                                                         dlg->callid.len, dlg->callid.s,
544                                                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
545                                                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
546                                                 break;
547                                         }
548                                         ref_dlg_unsafe(dlg,1);
549                                 case DLG_STATE_UNCONFIRMED:
550                                 case DLG_STATE_EARLY:
551                                         dlg->state = DLG_STATE_CONFIRMED_NA;
552                                         break;
553                                 case DLG_STATE_CONFIRMED_NA:
554                                 case DLG_STATE_CONFIRMED:
555                                         break;
556                                 default:
557                                         log_next_state_dlg(event, dlg);
558                         }
559                         break;
560                 case DLG_EVENT_REQACK:
561                         switch (dlg->state) {
562                                 case DLG_STATE_CONFIRMED_NA:
563                                         dlg->state = DLG_STATE_CONFIRMED;
564                                         break;
565                                 case DLG_STATE_CONFIRMED:
566                                         break;
567                                 case DLG_STATE_DELETED:
568                                         break;
569                                 default:
570                                         log_next_state_dlg(event, dlg);
571                         }
572                         break;
573                 case DLG_EVENT_REQBYE:
574                         switch (dlg->state) {
575                                 case DLG_STATE_CONFIRMED_NA:
576                                 case DLG_STATE_CONFIRMED:
577                                         dlg->dflags |= DLG_FLAG_HASBYE;
578                                         dlg->state = DLG_STATE_DELETED;
579                                         *unref = 1;
580                                         break;
581                                 case DLG_STATE_DELETED:
582                                         break;
583                                 default:
584                                         log_next_state_dlg(event, dlg);
585                         }
586                         break;
587                 case DLG_EVENT_REQPRACK:
588                         switch (dlg->state) {
589                                 case DLG_STATE_EARLY:
590                                 case DLG_STATE_CONFIRMED_NA:
591                                         break;
592                                 default:
593                                         log_next_state_dlg(event, dlg);
594                         }
595                         break;
596                 case DLG_EVENT_REQ:
597                         switch (dlg->state) {
598                                 case DLG_STATE_CONFIRMED_NA:
599                                 case DLG_STATE_CONFIRMED:
600                                         break;
601                                 default:
602                                         log_next_state_dlg(event, dlg);
603                         }
604                         break;
605                 default:
606                         LM_CRIT("unknown event %d in state %d "
607                                 "for dlg %p [%u:%u] with clid '%.*s' and tags '%.*s' '%.*s'\n",
608                                 event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
609                                 dlg->callid.len, dlg->callid.s,
610                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
611                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
612         }
613         *new_state = dlg->state;
614
615         dlg_unlock( d_table, d_entry);
616
617         LM_DBG("dialog %p changed from state %d to "
618                 "state %d, due event %d\n",dlg,*old_state,*new_state,event);
619 }
620
621
622 /**************************** MI functions ******************************/
623 static inline int internal_mi_print_dlg(struct mi_node *rpl,
624                                                                         struct dlg_cell *dlg, int with_context)
625 {
626         struct mi_node* node= NULL;
627         struct mi_node* node1 = NULL;
628         struct mi_attr* attr= NULL;
629         int len;
630         char* p;
631
632         node = add_mi_node_child(rpl, 0, "dialog",6 , 0, 0 );
633         if (node==0)
634                 goto error;
635
636         attr = addf_mi_attr( node, 0, "hash", 4, "%u:%u",
637                         dlg->h_entry, dlg->h_id );
638         if (attr==0)
639                 goto error;
640
641         p= int2str((unsigned long)dlg->state, &len);
642         node1 = add_mi_node_child( node, MI_DUP_VALUE, "state", 5, p, len);
643         if (node1==0)
644                 goto error;
645
646         p= int2str((unsigned long)dlg->start_ts, &len);
647         node1 = add_mi_node_child(node,MI_DUP_VALUE,"timestart",9, p, len);
648         if (node1==0)
649                 goto error;
650
651         p= int2str((unsigned long)dlg->tl.timeout, &len);
652         node1 = add_mi_node_child(node,MI_DUP_VALUE, "timeout", 7, p, len);
653         if (node1==0)
654                 goto error;
655
656         node1 = add_mi_node_child(node, MI_DUP_VALUE, "callid", 6,
657                         dlg->callid.s, dlg->callid.len);
658         if(node1 == 0)
659                 goto error;
660
661         node1 = add_mi_node_child(node, MI_DUP_VALUE, "from_uri", 8,
662                         dlg->from_uri.s, dlg->from_uri.len);
663         if(node1 == 0)
664                 goto error;
665
666         node1 = add_mi_node_child(node, MI_DUP_VALUE, "from_tag", 8,
667                         dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLER_LEG].len);
668         if(node1 == 0)
669                 goto error;
670
671         node1 = add_mi_node_child(node, MI_DUP_VALUE, "caller_contact", 14,
672                         dlg->contact[DLG_CALLER_LEG].s,
673                         dlg->contact[DLG_CALLER_LEG].len);
674         if(node1 == 0)
675                 goto error;
676
677         node1 = add_mi_node_child(node, MI_DUP_VALUE, "caller_cseq", 11,
678                         dlg->cseq[DLG_CALLER_LEG].s,
679                         dlg->cseq[DLG_CALLER_LEG].len);
680         if(node1 == 0)
681                 goto error;
682
683         node1 = add_mi_node_child(node, MI_DUP_VALUE,"caller_route_set",16,
684                         dlg->route_set[DLG_CALLER_LEG].s,
685                         dlg->route_set[DLG_CALLER_LEG].len);
686         if(node1 == 0)
687                 goto error;
688
689         node1 = add_mi_node_child(node, 0,"caller_bind_addr",16,
690                         dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s, 
691                         dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len);
692         if(node1 == 0)
693                 goto error;
694
695         node1 = add_mi_node_child(node, MI_DUP_VALUE, "to_uri", 6,
696                         dlg->to_uri.s, dlg->to_uri.len);
697         if(node1 == 0)
698                 goto error;
699
700         node1 = add_mi_node_child(node, MI_DUP_VALUE, "to_tag", 6,
701                         dlg->tag[DLG_CALLEE_LEG].s, dlg->tag[DLG_CALLEE_LEG].len);
702         if(node1 == 0)
703                 goto error;
704
705         node1 = add_mi_node_child(node, MI_DUP_VALUE, "callee_contact", 14,
706                         dlg->contact[DLG_CALLEE_LEG].s,
707                         dlg->contact[DLG_CALLEE_LEG].len);
708         if(node1 == 0)
709                 goto error;
710
711         node1 = add_mi_node_child(node, MI_DUP_VALUE, "callee_cseq", 11,
712                         dlg->cseq[DLG_CALLEE_LEG].s,
713                         dlg->cseq[DLG_CALLEE_LEG].len);
714         if(node1 == 0)
715                 goto error;
716
717         node1 = add_mi_node_child(node, MI_DUP_VALUE,"callee_route_set",16,
718                         dlg->route_set[DLG_CALLEE_LEG].s,
719                         dlg->route_set[DLG_CALLEE_LEG].len);
720         if(node1 == 0)
721                 goto error;
722
723         if (dlg->bind_addr[DLG_CALLEE_LEG]) {
724                 node1 = add_mi_node_child(node, 0,
725                         "callee_bind_addr",16,
726                         dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s, 
727                         dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len);
728         } else {
729                 node1 = add_mi_node_child(node, 0,
730                         "callee_bind_addr",16,0,0);
731         }
732         if(node1 == 0)
733                 goto error;
734
735         if (with_context) {
736                 node1 = add_mi_node_child(node, 0, "context", 7, 0, 0);
737                 if(node1 == 0)
738                         goto error;
739                 run_dlg_callbacks( DLGCB_MI_CONTEXT, dlg, NULL, 
740                         DLG_DIR_NONE, (void *)node1);
741         }
742         return 0;
743
744 error:
745         LM_ERR("failed to add node\n");
746         return -1;
747 }
748
749
750 int mi_print_dlg(struct mi_node *rpl, struct dlg_cell *dlg, int with_context)
751 {
752         return internal_mi_print_dlg( rpl, dlg, with_context);
753 }
754
755
756 static int internal_mi_print_dlgs(struct mi_node *rpl, int with_context)
757 {
758         struct dlg_cell *dlg;
759         unsigned int i;
760
761         LM_DBG("printing %i dialogs\n", d_table->size);
762
763         for( i=0 ; i<d_table->size ; i++ ) {
764                 dlg_lock( d_table, &(d_table->entries[i]) );
765
766                 for( dlg=d_table->entries[i].first ; dlg ; dlg=dlg->next ) {
767                         if (internal_mi_print_dlg(rpl, dlg, with_context)!=0)
768                                 goto error;
769                 }
770                 dlg_unlock( d_table, &(d_table->entries[i]) );
771         }
772         return 0;
773
774 error:
775         dlg_unlock( d_table, &(d_table->entries[i]) );
776         LM_ERR("failed to print dialog\n");
777         return -1;
778 }
779
780
781 static inline struct mi_root* process_mi_params(struct mi_root *cmd_tree,
782                                                                                                         struct dlg_cell **dlg_p)
783 {
784         struct mi_node* node;
785         struct dlg_entry *d_entry;
786         struct dlg_cell *dlg;
787         str *callid;
788         str *from_tag;
789         unsigned int h_entry;
790
791         node = cmd_tree->node.kids;
792         if (node == NULL) {
793                 /* no parameters at all */
794                 *dlg_p = NULL;
795                 return NULL;
796         }
797
798         /* we have params -> get callid and fromtag */
799         callid = &node->value;
800         LM_DBG("callid='%.*s'\n", callid->len, callid->s);
801
802         node = node->next;
803         if ( !node || !node->value.s || !node->value.len) {
804                 from_tag = NULL;
805         } else {
806                 from_tag = &node->value;
807                 LM_DBG("from_tag='%.*s'\n", from_tag->len, from_tag->s);
808                 if ( node->next!=NULL )
809                         return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
810         }
811
812         h_entry = core_hash( callid, from_tag, d_table->size);
813
814         d_entry = &(d_table->entries[h_entry]);
815         dlg_lock( d_table, d_entry);
816
817         for( dlg = d_entry->first ; dlg ; dlg = dlg->next ) {
818                 if (match_downstream_dialog( dlg, callid, from_tag)==1) {
819                         if (dlg->state==DLG_STATE_DELETED) {
820                                 *dlg_p = NULL;
821                                 break;
822                         } else {
823                                 *dlg_p = dlg;
824                                 dlg_unlock( d_table, d_entry);
825                                 return 0;
826                         }
827                 }
828         }
829         dlg_unlock( d_table, d_entry);
830
831         return init_mi_tree( 404, MI_SSTR("Nu such dialog"));
832 }
833
834
835 struct mi_root * mi_print_dlgs(struct mi_root *cmd_tree, void *param )
836 {
837         struct mi_root* rpl_tree= NULL;
838         struct mi_node* rpl = NULL;
839         struct dlg_cell* dlg = NULL;
840
841         rpl_tree = process_mi_params( cmd_tree, &dlg);
842         if (rpl_tree)
843                 /* param error */
844                 return rpl_tree;
845
846         rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
847         if (rpl_tree==0)
848                 return 0;
849         rpl = &rpl_tree->node;
850
851         if (dlg==NULL) {
852                 if ( internal_mi_print_dlgs(rpl,0)!=0 )
853                         goto error;
854         } else {
855                 if ( internal_mi_print_dlg(rpl,dlg,0)!=0 )
856                         goto error;
857         }
858
859         return rpl_tree;
860 error:
861         free_mi_tree(rpl_tree);
862         return NULL;
863 }
864
865
866 struct mi_root * mi_print_dlgs_ctx(struct mi_root *cmd_tree, void *param )
867 {
868         struct mi_root* rpl_tree= NULL;
869         struct mi_node* rpl = NULL;
870         struct dlg_cell* dlg = NULL;
871
872         rpl_tree = process_mi_params( cmd_tree, &dlg);
873         if (rpl_tree)
874                 /* param error */
875                 return rpl_tree;
876
877         rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
878         if (rpl_tree==0)
879                 return 0;
880         rpl = &rpl_tree->node;
881
882         if (dlg==NULL) {
883                 if ( internal_mi_print_dlgs(rpl,1)!=0 )
884                         goto error;
885         } else {
886                 if ( internal_mi_print_dlg(rpl,dlg,1)!=0 )
887                         goto error;
888         }
889
890         return rpl_tree;
891 error:
892         free_mi_tree(rpl_tree);
893         return NULL;
894 }
895
896
897