00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include <stdlib.h>
00046 #include <string.h>
00047
00048 #include "../../dprint.h"
00049 #include "../../ut.h"
00050 #include "../../hash_func.h"
00051 #include "../../mi/mi.h"
00052 #include "dlg_timer.h"
00053 #include "dlg_hash.h"
00054 #include "dlg_profile.h"
00055
00056 #define MAX_LDG_LOCKS 2048
00057 #define MIN_LDG_LOCKS 2
00058
00059
00060 struct dlg_table *d_table = 0;
00061
00062 int init_dlg_table(unsigned int size)
00063 {
00064 unsigned int n;
00065 unsigned int i;
00066
00067 d_table = (struct dlg_table*)shm_malloc
00068 ( sizeof(struct dlg_table) + size*sizeof(struct dlg_entry));
00069 if (d_table==0) {
00070 LM_ERR("no more shm mem (1)\n");
00071 goto error0;
00072 }
00073
00074 memset( d_table, 0, sizeof(struct dlg_table) );
00075 d_table->size = size;
00076 d_table->entries = (struct dlg_entry*)(d_table+1);
00077
00078 n = (size<MAX_LDG_LOCKS)?size:MAX_LDG_LOCKS;
00079 for( ; n>=MIN_LDG_LOCKS ; n-- ) {
00080 d_table->locks = lock_set_alloc(n);
00081 if (d_table->locks==0)
00082 continue;
00083 if (lock_set_init(d_table->locks)==0) {
00084 lock_set_dealloc(d_table->locks);
00085 d_table->locks = 0;
00086 continue;
00087 }
00088 d_table->locks_no = n;
00089 break;
00090 }
00091
00092 if (d_table->locks==0) {
00093 LM_ERR("unable to allocted at least %d locks for the hash table\n",
00094 MIN_LDG_LOCKS);
00095 goto error1;
00096 }
00097
00098 for( i=0 ; i<size; i++ ) {
00099 memset( &(d_table->entries[i]), 0, sizeof(struct dlg_entry) );
00100 d_table->entries[i].next_id = rand();
00101 d_table->entries[i].lock_idx = i % d_table->locks_no;
00102 }
00103
00104 return 0;
00105 error1:
00106 shm_free( d_table );
00107 error0:
00108 return -1;
00109 }
00110
00111
00112
00113 inline void destroy_dlg(struct dlg_cell *dlg)
00114 {
00115 int ret = 0;
00116
00117 LM_DBG("destroing dialog %p\n",dlg);
00118
00119 ret = remove_dialog_timer(&dlg->tl);
00120 if (ret < 0) {
00121 LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
00122 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
00123 dlg, dlg->h_entry, dlg->h_id,
00124 dlg->callid.len, dlg->callid.s,
00125 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00126 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00127 } else if (ret > 0) {
00128 LM_DBG("removed timer for dlg %p [%u:%u] "
00129 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
00130 dlg, dlg->h_entry, dlg->h_id,
00131 dlg->callid.len, dlg->callid.s,
00132 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00133 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00134 }
00135
00136 run_dlg_callbacks( DLGCB_DESTROY , dlg, 0, DLG_DIR_NONE, 0);
00137
00138 if (dlg->cbs.first)
00139 destroy_dlg_callbacks_list(dlg->cbs.first);
00140
00141 if (dlg->profile_links)
00142 destroy_linkers(dlg->profile_links);
00143
00144 if (dlg->tag[DLG_CALLER_LEG].s)
00145 shm_free(dlg->tag[DLG_CALLER_LEG].s);
00146
00147 if (dlg->tag[DLG_CALLEE_LEG].s)
00148 shm_free(dlg->tag[DLG_CALLEE_LEG].s);
00149
00150 if (dlg->cseq[DLG_CALLER_LEG].s)
00151 shm_free(dlg->cseq[DLG_CALLER_LEG].s);
00152
00153 if (dlg->cseq[DLG_CALLEE_LEG].s)
00154 shm_free(dlg->cseq[DLG_CALLEE_LEG].s);
00155
00156 shm_free(dlg);
00157 }
00158
00159
00160
00161 void destroy_dlg_table(void)
00162 {
00163 struct dlg_cell *dlg, *l_dlg;
00164 unsigned int i;
00165
00166 if (d_table==0)
00167 return;
00168
00169 if (d_table->locks) {
00170 lock_set_destroy(d_table->locks);
00171 lock_set_dealloc(d_table->locks);
00172 }
00173
00174 for( i=0 ; i<d_table->size; i++ ) {
00175 dlg = d_table->entries[i].first;
00176 while (dlg) {
00177 l_dlg = dlg;
00178 dlg = dlg->next;
00179 destroy_dlg(l_dlg);
00180 }
00181
00182 }
00183
00184 shm_free(d_table);
00185 d_table = 0;
00186
00187 return;
00188 }
00189
00190
00191
00192 struct dlg_cell* build_new_dlg( str *callid, str *from_uri, str *to_uri,
00193 str *from_tag)
00194 {
00195 struct dlg_cell *dlg;
00196 int len;
00197 char *p;
00198
00199 len = sizeof(struct dlg_cell) + callid->len + from_uri->len +
00200 to_uri->len;
00201 dlg = (struct dlg_cell*)shm_malloc( len );
00202 if (dlg==0) {
00203 LM_ERR("no more shm mem (%d)\n",len);
00204 return 0;
00205 }
00206
00207 memset( dlg, 0, len);
00208 dlg->state = DLG_STATE_UNCONFIRMED;
00209
00210 dlg->h_entry = core_hash( callid, from_tag->len?from_tag:0, d_table->size);
00211 LM_DBG("new dialog on hash %u\n",dlg->h_entry);
00212
00213 p = (char*)(dlg+1);
00214
00215 dlg->callid.s = p;
00216 dlg->callid.len = callid->len;
00217 memcpy( p, callid->s, callid->len);
00218 p += callid->len;
00219
00220 dlg->from_uri.s = p;
00221 dlg->from_uri.len = from_uri->len;
00222 memcpy( p, from_uri->s, from_uri->len);
00223 p += from_uri->len;
00224
00225 dlg->to_uri.s = p;
00226 dlg->to_uri.len = to_uri->len;
00227 memcpy( p, to_uri->s, to_uri->len);
00228 p += to_uri->len;
00229
00230 if ( p!=(((char*)dlg)+len) ) {
00231 LM_CRIT("buffer overflow\n");
00232 shm_free(dlg);
00233 return 0;
00234 }
00235
00236 return dlg;
00237 }
00238
00239
00240
00241 int dlg_set_leg_info(struct dlg_cell *dlg, str* tag, str *rr, str *contact,
00242 str *cseq, unsigned int leg)
00243 {
00244 char *p;
00245
00246 dlg->tag[leg].s = (char*)shm_malloc( tag->len + rr->len + contact->len );
00247 dlg->cseq[leg].s = (char*)shm_malloc( cseq->len );
00248 if ( dlg->tag[leg].s==NULL || dlg->cseq[leg].s==NULL) {
00249 LM_ERR("no more shm mem\n");
00250 if (dlg->tag[leg].s) shm_free(dlg->tag[leg].s);
00251 if (dlg->cseq[leg].s) shm_free(dlg->cseq[leg].s);
00252 return -1;
00253 }
00254 p = dlg->tag[leg].s;
00255
00256
00257 dlg->tag[leg].len = tag->len;
00258 memcpy( p, tag->s, tag->len);
00259 p += tag->len;
00260
00261 dlg->contact[leg].s = p;
00262 dlg->contact[leg].len = contact->len;
00263 memcpy( p, contact->s, contact->len);
00264 p += contact->len;
00265
00266 if (rr->len) {
00267 dlg->route_set[leg].s = p;
00268 dlg->route_set[leg].len = rr->len;
00269 memcpy( p, rr->s, rr->len);
00270 }
00271
00272
00273 dlg->cseq[leg].len = cseq->len;
00274 memcpy( dlg->cseq[leg].s, cseq->s, cseq->len);
00275
00276 return 0;
00277 }
00278
00279
00280
00281 int dlg_update_cseq(struct dlg_cell * dlg, unsigned int leg, str *cseq)
00282 {
00283 if ( dlg->cseq[leg].s ) {
00284 if (dlg->cseq[leg].len < cseq->len) {
00285 shm_free(dlg->cseq[leg].s);
00286 dlg->cseq[leg].s = (char*)shm_malloc(cseq->len);
00287 if (dlg->cseq[leg].s==NULL)
00288 goto error;
00289 }
00290 } else {
00291 dlg->cseq[leg].s = (char*)shm_malloc(cseq->len);
00292 if (dlg->cseq[leg].s==NULL)
00293 goto error;
00294 }
00295
00296 memcpy( dlg->cseq[leg].s, cseq->s, cseq->len );
00297 dlg->cseq[leg].len = cseq->len;
00298
00299 LM_DBG("cseq is %.*s\n", dlg->cseq[leg].len, dlg->cseq[leg].s);
00300 return 0;
00301 error:
00302 LM_ERR("not more shm mem\n");
00303 return -1;
00304 }
00305
00306
00307
00308 struct dlg_cell* lookup_dlg( unsigned int h_entry, unsigned int h_id)
00309 {
00310 struct dlg_cell *dlg;
00311 struct dlg_entry *d_entry;
00312
00313 if (h_entry>=d_table->size)
00314 goto not_found;
00315
00316 d_entry = &(d_table->entries[h_entry]);
00317
00318 dlg_lock( d_table, d_entry);
00319
00320 for( dlg=d_entry->first ; dlg ; dlg=dlg->next ) {
00321 if (dlg->h_id == h_id) {
00322 if (dlg->state==DLG_STATE_DELETED) {
00323 dlg_unlock( d_table, d_entry);
00324 goto not_found;
00325 }
00326 dlg->ref++;
00327 LM_DBG("ref dlg %p with 1 -> %d\n", dlg, dlg->ref);
00328 dlg_unlock( d_table, d_entry);
00329 LM_DBG("dialog id=%u found on entry %u\n", h_id, h_entry);
00330 return dlg;
00331 }
00332 }
00333
00334 dlg_unlock( d_table, d_entry);
00335 not_found:
00336 LM_DBG("no dialog id=%u found on entry %u\n", h_id, h_entry);
00337 return 0;
00338 }
00339
00340
00341
00342 static inline struct dlg_cell* internal_get_dlg(unsigned int h_entry,
00343 str *callid, str *ftag, str *ttag, unsigned int *dir)
00344 {
00345 struct dlg_cell *dlg;
00346 struct dlg_entry *d_entry;
00347
00348 d_entry = &(d_table->entries[h_entry]);
00349
00350 dlg_lock( d_table, d_entry);
00351
00352 for( dlg = d_entry->first ; dlg ; dlg = dlg->next ) {
00353
00354 if (match_dialog( dlg, callid, ftag, ttag, dir)==1) {
00355 if (dlg->state==DLG_STATE_DELETED) {
00356 dlg_unlock( d_table, d_entry);
00357 goto not_found;
00358 }
00359 dlg->ref++;
00360 LM_DBG("ref dlg %p with 1 -> %d\n", dlg, dlg->ref);
00361 dlg_unlock( d_table, d_entry);
00362 LM_DBG("dialog callid='%.*s' found\n on entry %u, dir=%d\n",
00363 callid->len, callid->s,h_entry,*dir);
00364 return dlg;
00365 }
00366 }
00367
00368 dlg_unlock( d_table, d_entry);
00369
00370 not_found:
00371 LM_DBG("no dialog callid='%.*s' found\n", callid->len, callid->s);
00372 return 0;
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382 struct dlg_cell* get_dlg( str *callid, str *ftag, str *ttag, unsigned int *dir)
00383 {
00384 struct dlg_cell *dlg;
00385
00386 if ((dlg = internal_get_dlg(core_hash(callid, ftag->len?ftag:0,
00387 d_table->size), callid, ftag, ttag, dir)) == 0 &&
00388 (dlg = internal_get_dlg(core_hash(callid, ttag->len
00389 ?ttag:0, d_table->size), callid, ftag, ttag, dir)) == 0) {
00390 LM_DBG("no dialog callid='%.*s' found\n", callid->len, callid->s);
00391 return 0;
00392 }
00393 return dlg;
00394 }
00395
00396
00397
00398 void link_dlg(struct dlg_cell *dlg, int n)
00399 {
00400 struct dlg_entry *d_entry;
00401
00402 d_entry = &(d_table->entries[dlg->h_entry]);
00403
00404 dlg_lock( d_table, d_entry);
00405
00406 dlg->h_id = d_entry->next_id++;
00407 if (d_entry->first==0) {
00408 d_entry->first = d_entry->last = dlg;
00409 } else {
00410 d_entry->last->next = dlg;
00411 dlg->prev = d_entry->last;
00412 d_entry->last = dlg;
00413 }
00414
00415 dlg->ref += 1 + n;
00416
00417 LM_DBG("ref dlg %p with %d -> %d\n", dlg, n+1, dlg->ref);
00418
00419 dlg_unlock( d_table, d_entry);
00420 return;
00421 }
00422
00423
00424
00425 inline void unlink_unsafe_dlg(struct dlg_entry *d_entry,
00426 struct dlg_cell *dlg)
00427 {
00428 if (dlg->next)
00429 dlg->next->prev = dlg->prev;
00430 else
00431 d_entry->last = dlg->prev;
00432 if (dlg->prev)
00433 dlg->prev->next = dlg->next;
00434 else
00435 d_entry->first = dlg->next;
00436
00437 dlg->next = dlg->prev = 0;
00438
00439 return;
00440 }
00441
00442
00443 void ref_dlg(struct dlg_cell *dlg, unsigned int cnt)
00444 {
00445 struct dlg_entry *d_entry;
00446
00447 d_entry = &(d_table->entries[dlg->h_entry]);
00448
00449 dlg_lock( d_table, d_entry);
00450 ref_dlg_unsafe( dlg, cnt);
00451 dlg_unlock( d_table, d_entry);
00452 }
00453
00454
00455 void unref_dlg(struct dlg_cell *dlg, unsigned int cnt)
00456 {
00457 struct dlg_entry *d_entry;
00458
00459 d_entry = &(d_table->entries[dlg->h_entry]);
00460
00461 dlg_lock( d_table, d_entry);
00462 unref_dlg_unsafe( dlg, cnt, d_entry);
00463 dlg_unlock( d_table, d_entry);
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473 static inline void log_next_state_dlg(const int event, const struct dlg_cell *dlg) {
00474 LM_CRIT("bogus event %d in state %d for dlg %p [%u:%u] with clid '%.*s' and tags "
00475 "'%.*s' '%.*s'\n", event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
00476 dlg->callid.len, dlg->callid.s,
00477 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00478 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00479 }
00480
00481
00482 void next_state_dlg(struct dlg_cell *dlg, int event,
00483 int *old_state, int *new_state, int *unref)
00484 {
00485 struct dlg_entry *d_entry;
00486
00487 d_entry = &(d_table->entries[dlg->h_entry]);
00488
00489 *unref = 0;
00490
00491 dlg_lock( d_table, d_entry);
00492
00493 *old_state = dlg->state;
00494
00495 switch (event) {
00496 case DLG_EVENT_TDEL:
00497 switch (dlg->state) {
00498 case DLG_STATE_UNCONFIRMED:
00499 case DLG_STATE_EARLY:
00500 dlg->state = DLG_STATE_DELETED;
00501 unref_dlg_unsafe(dlg,1,d_entry);
00502 *unref = 1;
00503 break;
00504 case DLG_STATE_CONFIRMED_NA:
00505 case DLG_STATE_CONFIRMED:
00506 unref_dlg_unsafe(dlg,1,d_entry);
00507 break;
00508 case DLG_STATE_DELETED:
00509 *unref = 1;
00510 break;
00511 default:
00512 log_next_state_dlg(event, dlg);
00513 }
00514 break;
00515 case DLG_EVENT_RPL1xx:
00516 switch (dlg->state) {
00517 case DLG_STATE_UNCONFIRMED:
00518 case DLG_STATE_EARLY:
00519 dlg->state = DLG_STATE_EARLY;
00520 break;
00521 default:
00522 log_next_state_dlg(event, dlg);
00523 }
00524 break;
00525 case DLG_EVENT_RPL3xx:
00526 switch (dlg->state) {
00527 case DLG_STATE_UNCONFIRMED:
00528 case DLG_STATE_EARLY:
00529 dlg->state = DLG_STATE_DELETED;
00530 *unref = 1;
00531 break;
00532 default:
00533 log_next_state_dlg(event, dlg);
00534 }
00535 break;
00536 case DLG_EVENT_RPL2xx:
00537 switch (dlg->state) {
00538 case DLG_STATE_DELETED:
00539 if (dlg->dflags&DLG_FLAG_HASBYE) {
00540 LM_CRIT("bogus event %d in state %d (with BYE) "
00541 "for dlg %p [%u:%u] with clid '%.*s' and tags '%.*s' '%.*s'\n",
00542 event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
00543 dlg->callid.len, dlg->callid.s,
00544 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00545 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00546 break;
00547 }
00548 ref_dlg_unsafe(dlg,1);
00549 case DLG_STATE_UNCONFIRMED:
00550 case DLG_STATE_EARLY:
00551 dlg->state = DLG_STATE_CONFIRMED_NA;
00552 break;
00553 case DLG_STATE_CONFIRMED_NA:
00554 case DLG_STATE_CONFIRMED:
00555 break;
00556 default:
00557 log_next_state_dlg(event, dlg);
00558 }
00559 break;
00560 case DLG_EVENT_REQACK:
00561 switch (dlg->state) {
00562 case DLG_STATE_CONFIRMED_NA:
00563 dlg->state = DLG_STATE_CONFIRMED;
00564 break;
00565 case DLG_STATE_CONFIRMED:
00566 break;
00567 case DLG_STATE_DELETED:
00568 break;
00569 default:
00570 log_next_state_dlg(event, dlg);
00571 }
00572 break;
00573 case DLG_EVENT_REQBYE:
00574 switch (dlg->state) {
00575 case DLG_STATE_CONFIRMED_NA:
00576 case DLG_STATE_CONFIRMED:
00577 dlg->dflags |= DLG_FLAG_HASBYE;
00578 dlg->state = DLG_STATE_DELETED;
00579 *unref = 1;
00580 break;
00581 case DLG_STATE_DELETED:
00582 break;
00583 default:
00584 log_next_state_dlg(event, dlg);
00585 }
00586 break;
00587 case DLG_EVENT_REQPRACK:
00588 switch (dlg->state) {
00589 case DLG_STATE_EARLY:
00590 case DLG_STATE_CONFIRMED_NA:
00591 break;
00592 default:
00593 log_next_state_dlg(event, dlg);
00594 }
00595 break;
00596 case DLG_EVENT_REQ:
00597 switch (dlg->state) {
00598 case DLG_STATE_CONFIRMED_NA:
00599 case DLG_STATE_CONFIRMED:
00600 break;
00601 default:
00602 log_next_state_dlg(event, dlg);
00603 }
00604 break;
00605 default:
00606 LM_CRIT("unknown event %d in state %d "
00607 "for dlg %p [%u:%u] with clid '%.*s' and tags '%.*s' '%.*s'\n",
00608 event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
00609 dlg->callid.len, dlg->callid.s,
00610 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00611 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00612 }
00613 *new_state = dlg->state;
00614
00615 dlg_unlock( d_table, d_entry);
00616
00617 LM_DBG("dialog %p changed from state %d to "
00618 "state %d, due event %d\n",dlg,*old_state,*new_state,event);
00619 }
00620
00621
00622
00623 static inline int internal_mi_print_dlg(struct mi_node *rpl,
00624 struct dlg_cell *dlg, int with_context)
00625 {
00626 struct mi_node* node= NULL;
00627 struct mi_node* node1 = NULL;
00628 struct mi_attr* attr= NULL;
00629 int len;
00630 char* p;
00631
00632 node = add_mi_node_child(rpl, 0, "dialog",6 , 0, 0 );
00633 if (node==0)
00634 goto error;
00635
00636 attr = addf_mi_attr( node, 0, "hash", 4, "%u:%u",
00637 dlg->h_entry, dlg->h_id );
00638 if (attr==0)
00639 goto error;
00640
00641 p= int2str((unsigned long)dlg->state, &len);
00642 node1 = add_mi_node_child( node, MI_DUP_VALUE, "state", 5, p, len);
00643 if (node1==0)
00644 goto error;
00645
00646 p= int2str((unsigned long)dlg->start_ts, &len);
00647 node1 = add_mi_node_child(node,MI_DUP_VALUE,"timestart",9, p, len);
00648 if (node1==0)
00649 goto error;
00650
00651 p= int2str((unsigned long)dlg->tl.timeout, &len);
00652 node1 = add_mi_node_child(node,MI_DUP_VALUE, "timeout", 7, p, len);
00653 if (node1==0)
00654 goto error;
00655
00656 node1 = add_mi_node_child(node, MI_DUP_VALUE, "callid", 6,
00657 dlg->callid.s, dlg->callid.len);
00658 if(node1 == 0)
00659 goto error;
00660
00661 node1 = add_mi_node_child(node, MI_DUP_VALUE, "from_uri", 8,
00662 dlg->from_uri.s, dlg->from_uri.len);
00663 if(node1 == 0)
00664 goto error;
00665
00666 node1 = add_mi_node_child(node, MI_DUP_VALUE, "from_tag", 8,
00667 dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLER_LEG].len);
00668 if(node1 == 0)
00669 goto error;
00670
00671 node1 = add_mi_node_child(node, MI_DUP_VALUE, "caller_contact", 14,
00672 dlg->contact[DLG_CALLER_LEG].s,
00673 dlg->contact[DLG_CALLER_LEG].len);
00674 if(node1 == 0)
00675 goto error;
00676
00677 node1 = add_mi_node_child(node, MI_DUP_VALUE, "caller_cseq", 11,
00678 dlg->cseq[DLG_CALLER_LEG].s,
00679 dlg->cseq[DLG_CALLER_LEG].len);
00680 if(node1 == 0)
00681 goto error;
00682
00683 node1 = add_mi_node_child(node, MI_DUP_VALUE,"caller_route_set",16,
00684 dlg->route_set[DLG_CALLER_LEG].s,
00685 dlg->route_set[DLG_CALLER_LEG].len);
00686 if(node1 == 0)
00687 goto error;
00688
00689 node1 = add_mi_node_child(node, 0,"caller_bind_addr",16,
00690 dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s,
00691 dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len);
00692 if(node1 == 0)
00693 goto error;
00694
00695 node1 = add_mi_node_child(node, MI_DUP_VALUE, "to_uri", 6,
00696 dlg->to_uri.s, dlg->to_uri.len);
00697 if(node1 == 0)
00698 goto error;
00699
00700 node1 = add_mi_node_child(node, MI_DUP_VALUE, "to_tag", 6,
00701 dlg->tag[DLG_CALLEE_LEG].s, dlg->tag[DLG_CALLEE_LEG].len);
00702 if(node1 == 0)
00703 goto error;
00704
00705 node1 = add_mi_node_child(node, MI_DUP_VALUE, "callee_contact", 14,
00706 dlg->contact[DLG_CALLEE_LEG].s,
00707 dlg->contact[DLG_CALLEE_LEG].len);
00708 if(node1 == 0)
00709 goto error;
00710
00711 node1 = add_mi_node_child(node, MI_DUP_VALUE, "callee_cseq", 11,
00712 dlg->cseq[DLG_CALLEE_LEG].s,
00713 dlg->cseq[DLG_CALLEE_LEG].len);
00714 if(node1 == 0)
00715 goto error;
00716
00717 node1 = add_mi_node_child(node, MI_DUP_VALUE,"callee_route_set",16,
00718 dlg->route_set[DLG_CALLEE_LEG].s,
00719 dlg->route_set[DLG_CALLEE_LEG].len);
00720 if(node1 == 0)
00721 goto error;
00722
00723 if (dlg->bind_addr[DLG_CALLEE_LEG]) {
00724 node1 = add_mi_node_child(node, 0,
00725 "callee_bind_addr",16,
00726 dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s,
00727 dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len);
00728 } else {
00729 node1 = add_mi_node_child(node, 0,
00730 "callee_bind_addr",16,0,0);
00731 }
00732 if(node1 == 0)
00733 goto error;
00734
00735 if (with_context) {
00736 node1 = add_mi_node_child(node, 0, "context", 7, 0, 0);
00737 if(node1 == 0)
00738 goto error;
00739 run_dlg_callbacks( DLGCB_MI_CONTEXT, dlg, NULL,
00740 DLG_DIR_NONE, (void *)node1);
00741 }
00742 return 0;
00743
00744 error:
00745 LM_ERR("failed to add node\n");
00746 return -1;
00747 }
00748
00749
00750 int mi_print_dlg(struct mi_node *rpl, struct dlg_cell *dlg, int with_context)
00751 {
00752 return internal_mi_print_dlg( rpl, dlg, with_context);
00753 }
00754
00755
00756 static int internal_mi_print_dlgs(struct mi_node *rpl, int with_context)
00757 {
00758 struct dlg_cell *dlg;
00759 unsigned int i;
00760
00761 LM_DBG("printing %i dialogs\n", d_table->size);
00762
00763 for( i=0 ; i<d_table->size ; i++ ) {
00764 dlg_lock( d_table, &(d_table->entries[i]) );
00765
00766 for( dlg=d_table->entries[i].first ; dlg ; dlg=dlg->next ) {
00767 if (internal_mi_print_dlg(rpl, dlg, with_context)!=0)
00768 goto error;
00769 }
00770 dlg_unlock( d_table, &(d_table->entries[i]) );
00771 }
00772 return 0;
00773
00774 error:
00775 dlg_unlock( d_table, &(d_table->entries[i]) );
00776 LM_ERR("failed to print dialog\n");
00777 return -1;
00778 }
00779
00780
00781 static inline struct mi_root* process_mi_params(struct mi_root *cmd_tree,
00782 struct dlg_cell **dlg_p)
00783 {
00784 struct mi_node* node;
00785 struct dlg_entry *d_entry;
00786 struct dlg_cell *dlg;
00787 str *callid;
00788 str *from_tag;
00789 unsigned int h_entry;
00790
00791 node = cmd_tree->node.kids;
00792 if (node == NULL) {
00793
00794 *dlg_p = NULL;
00795 return NULL;
00796 }
00797
00798
00799 callid = &node->value;
00800 LM_DBG("callid='%.*s'\n", callid->len, callid->s);
00801
00802 node = node->next;
00803 if ( !node || !node->value.s || !node->value.len) {
00804 from_tag = NULL;
00805 } else {
00806 from_tag = &node->value;
00807 LM_DBG("from_tag='%.*s'\n", from_tag->len, from_tag->s);
00808 if ( node->next!=NULL )
00809 return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
00810 }
00811
00812 h_entry = core_hash( callid, from_tag, d_table->size);
00813
00814 d_entry = &(d_table->entries[h_entry]);
00815 dlg_lock( d_table, d_entry);
00816
00817 for( dlg = d_entry->first ; dlg ; dlg = dlg->next ) {
00818 if (match_downstream_dialog( dlg, callid, from_tag)==1) {
00819 if (dlg->state==DLG_STATE_DELETED) {
00820 *dlg_p = NULL;
00821 break;
00822 } else {
00823 *dlg_p = dlg;
00824 dlg_unlock( d_table, d_entry);
00825 return 0;
00826 }
00827 }
00828 }
00829 dlg_unlock( d_table, d_entry);
00830
00831 return init_mi_tree( 404, MI_SSTR("Nu such dialog"));
00832 }
00833
00834
00835 struct mi_root * mi_print_dlgs(struct mi_root *cmd_tree, void *param )
00836 {
00837 struct mi_root* rpl_tree= NULL;
00838 struct mi_node* rpl = NULL;
00839 struct dlg_cell* dlg = NULL;
00840
00841 rpl_tree = process_mi_params( cmd_tree, &dlg);
00842 if (rpl_tree)
00843
00844 return rpl_tree;
00845
00846 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00847 if (rpl_tree==0)
00848 return 0;
00849 rpl = &rpl_tree->node;
00850
00851 if (dlg==NULL) {
00852 if ( internal_mi_print_dlgs(rpl,0)!=0 )
00853 goto error;
00854 } else {
00855 if ( internal_mi_print_dlg(rpl,dlg,0)!=0 )
00856 goto error;
00857 }
00858
00859 return rpl_tree;
00860 error:
00861 free_mi_tree(rpl_tree);
00862 return NULL;
00863 }
00864
00865
00866 struct mi_root * mi_print_dlgs_ctx(struct mi_root *cmd_tree, void *param )
00867 {
00868 struct mi_root* rpl_tree= NULL;
00869 struct mi_node* rpl = NULL;
00870 struct dlg_cell* dlg = NULL;
00871
00872 rpl_tree = process_mi_params( cmd_tree, &dlg);
00873 if (rpl_tree)
00874
00875 return rpl_tree;
00876
00877 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00878 if (rpl_tree==0)
00879 return 0;
00880 rpl = &rpl_tree->node;
00881
00882 if (dlg==NULL) {
00883 if ( internal_mi_print_dlgs(rpl,1)!=0 )
00884 goto error;
00885 } else {
00886 if ( internal_mi_print_dlg(rpl,dlg,1)!=0 )
00887 goto error;
00888 }
00889
00890 return rpl_tree;
00891 error:
00892 free_mi_tree(rpl_tree);
00893 return NULL;
00894 }
00895
00896
00897