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
00052 #include <stdlib.h>
00053 #include <string.h>
00054
00055 #include "../../dprint.h"
00056 #include "../../ut.h"
00057 #include "../../hashes.h"
00058 #include "../../lib/kmi/mi.h"
00059 #include "dlg_timer.h"
00060 #include "dlg_var.h"
00061 #include "dlg_hash.h"
00062 #include "dlg_profile.h"
00063 #include "dlg_req_within.h"
00064 #include "dlg_db_handler.h"
00065
00066 #define MAX_LDG_LOCKS 2048
00067 #define MIN_LDG_LOCKS 2
00068
00069 extern int dlg_ka_interval;
00070
00072 struct dlg_table *d_table = 0;
00073
00074 dlg_ka_t **dlg_ka_list_head = NULL;
00075 dlg_ka_t **dlg_ka_list_tail = NULL;
00076 gen_lock_t *dlg_ka_list_lock = NULL;
00077
00083 #define ref_dlg_unsafe(_dlg,_cnt) \
00084 do { \
00085 (_dlg)->ref += (_cnt); \
00086 LM_DBG("ref dlg %p with %d -> %d\n", \
00087 (_dlg),(_cnt),(_dlg)->ref); \
00088 }while(0)
00089
00090
00097 #define unref_dlg_unsafe(_dlg,_cnt,_d_entry) \
00098 do { \
00099 if((_dlg)->ref <= 0 ) { \
00100 LM_WARN("invalid unref'ing dlg %p with ref %d by %d\n",\
00101 (_dlg),(_dlg)->ref,(_cnt));\
00102 break; \
00103 } \
00104 (_dlg)->ref -= (_cnt); \
00105 LM_DBG("unref dlg %p with %d -> %d\n",\
00106 (_dlg),(_cnt),(_dlg)->ref);\
00107 if ((_dlg)->ref<0) {\
00108 LM_CRIT("bogus ref %d with cnt %d for dlg %p [%u:%u] "\
00109 "with clid '%.*s' and tags '%.*s' '%.*s'\n",\
00110 (_dlg)->ref, _cnt, _dlg,\
00111 (_dlg)->h_entry, (_dlg)->h_id,\
00112 (_dlg)->callid.len, (_dlg)->callid.s,\
00113 (_dlg)->tag[DLG_CALLER_LEG].len,\
00114 (_dlg)->tag[DLG_CALLER_LEG].s,\
00115 (_dlg)->tag[DLG_CALLEE_LEG].len,\
00116 (_dlg)->tag[DLG_CALLEE_LEG].s); \
00117 }\
00118 if ((_dlg)->ref<=0) { \
00119 unlink_unsafe_dlg( _d_entry, _dlg);\
00120 LM_DBG("ref <=0 for dialog %p\n",_dlg);\
00121 destroy_dlg(_dlg);\
00122 }\
00123 }while(0)
00124
00129 int dlg_ka_add(dlg_cell_t *dlg)
00130 {
00131 dlg_ka_t *dka;
00132
00133 if(dlg_ka_interval<=0)
00134 return 0;
00135 if(!(dlg->iflags & (DLG_IFLAG_KA_SRC | DLG_IFLAG_KA_SRC)))
00136 return 0;
00137
00138 dka = (dlg_ka_t*)shm_malloc(sizeof(dlg_ka_t));
00139 if(dka==NULL) {
00140 LM_ERR("no more shm mem\n");
00141 return -1;
00142 }
00143 memset(dka, 0, sizeof(dlg_ka_t));
00144 dka->katime = get_ticks() + dlg_ka_interval;
00145 dka->iuid.h_entry = dlg->h_entry;
00146 dka->iuid.h_id = dlg->h_id;
00147 dka->iflags = dlg->iflags;
00148
00149 lock_get(dlg_ka_list_lock);
00150 if(*dlg_ka_list_tail!=NULL)
00151 (*dlg_ka_list_tail)->next = dka;
00152 if(*dlg_ka_list_head==NULL)
00153 *dlg_ka_list_head = dka;
00154 *dlg_ka_list_tail = dka;
00155 lock_release(dlg_ka_list_lock);
00156 LM_DBG("added dlg[%d,%d] to KA list\n", dlg->h_entry, dlg->h_id);
00157 return 0;
00158 }
00159
00164 int dlg_ka_run(ticks_t ti)
00165 {
00166 dlg_ka_t *dka;
00167 dlg_cell_t *dlg;
00168
00169 if(dlg_ka_interval<=0)
00170 return 0;
00171
00172 while(1) {
00173
00174 lock_get(dlg_ka_list_lock);
00175 if(*dlg_ka_list_head==NULL) {
00176 lock_release(dlg_ka_list_lock);
00177 return 0;
00178 }
00179 dka = *dlg_ka_list_head;
00180 #if 0
00181 LM_DBG("dlg ka timer at %lu for"
00182 " dlg[%u,%u] on %lu\n", (unsigned long)ti,
00183 dka->iuid.h_entry, dka->iuid.h_id,
00184 (unsigned long)dka->katime);
00185 #endif
00186 if(dka->katime>ti) {
00187 lock_release(dlg_ka_list_lock);
00188 return 0;
00189 }
00190 if(*dlg_ka_list_head == *dlg_ka_list_tail) {
00191 *dlg_ka_list_head = NULL;
00192 *dlg_ka_list_head = NULL;
00193 }
00194 *dlg_ka_list_head = dka->next;
00195 lock_release(dlg_ka_list_lock);
00196
00197
00198 dlg = dlg_get_by_iuid(&dka->iuid);
00199 if(dlg==NULL) {
00200 shm_free(dka);
00201 dka = NULL;
00202 } else {
00203 if(dka->iflags & DLG_IFLAG_KA_SRC)
00204 dlg_send_ka(dlg, DLG_CALLER_LEG, 0);
00205 if(dka->iflags & DLG_IFLAG_KA_DST)
00206 dlg_send_ka(dlg, DLG_CALLEE_LEG, 0);
00207 dlg_release(dlg);
00208 }
00209
00210 if(dka!=NULL)
00211 {
00212 lock_get(dlg_ka_list_lock);
00213 if(*dlg_ka_list_tail!=NULL)
00214 (*dlg_ka_list_tail)->next = dka;
00215 if(*dlg_ka_list_head==NULL)
00216 *dlg_ka_list_tail = dka;
00217 *dlg_ka_list_tail = dka;
00218 lock_release(dlg_ka_list_lock);
00219 }
00220 }
00221
00222 return 0;
00223 }
00224
00230 int init_dlg_table(unsigned int size)
00231 {
00232 unsigned int n;
00233 unsigned int i;
00234
00235 dlg_ka_list_head = (dlg_ka_t **)shm_malloc(sizeof(dlg_ka_t *));
00236 if(dlg_ka_list_head==NULL) {
00237 LM_ERR("no more shm mem (h)\n");
00238 goto error0;
00239 }
00240 dlg_ka_list_tail = (dlg_ka_t **)shm_malloc(sizeof(dlg_ka_t *));
00241 if(dlg_ka_list_tail==NULL) {
00242 LM_ERR("no more shm mem (t)\n");
00243 goto error0;
00244 }
00245 *dlg_ka_list_head = NULL;
00246 *dlg_ka_list_tail = NULL;
00247 dlg_ka_list_lock = (gen_lock_t*)shm_malloc(sizeof(gen_lock_t));
00248 if(dlg_ka_list_lock==NULL) {
00249 LM_ERR("no more shm mem (l)\n");
00250 goto error0;
00251 }
00252 lock_init(dlg_ka_list_lock);
00253
00254 d_table = (struct dlg_table*)shm_malloc
00255 ( sizeof(struct dlg_table) + size*sizeof(struct dlg_entry));
00256 if (d_table==0) {
00257 LM_ERR("no more shm mem (1)\n");
00258 goto error0;
00259 }
00260
00261 memset( d_table, 0, sizeof(struct dlg_table) );
00262 d_table->size = size;
00263 d_table->entries = (struct dlg_entry*)(d_table+1);
00264
00265 n = (size<MAX_LDG_LOCKS)?size:MAX_LDG_LOCKS;
00266 for( ; n>=MIN_LDG_LOCKS ; n-- ) {
00267 d_table->locks = lock_set_alloc(n);
00268 if (d_table->locks==0)
00269 continue;
00270 if (lock_set_init(d_table->locks)==0) {
00271 lock_set_dealloc(d_table->locks);
00272 d_table->locks = 0;
00273 continue;
00274 }
00275 d_table->locks_no = n;
00276 break;
00277 }
00278
00279 if (d_table->locks==0) {
00280 LM_ERR("unable to allocted at least %d locks for the hash table\n",
00281 MIN_LDG_LOCKS);
00282 goto error1;
00283 }
00284
00285 for( i=0 ; i<size; i++ ) {
00286 memset( &(d_table->entries[i]), 0, sizeof(struct dlg_entry) );
00287 d_table->entries[i].next_id = rand() % (3*size);
00288 d_table->entries[i].lock_idx = i % d_table->locks_no;
00289 }
00290
00291 return 0;
00292 error1:
00293 shm_free( d_table );
00294 d_table = NULL;
00295 error0:
00296 if(dlg_ka_list_head!=NULL)
00297 shm_free(dlg_ka_list_head);
00298 if(dlg_ka_list_tail!=NULL)
00299 shm_free(dlg_ka_list_tail);
00300 dlg_ka_list_head = NULL;
00301 dlg_ka_list_tail = NULL;
00302 return -1;
00303 }
00304
00305
00310 inline void destroy_dlg(struct dlg_cell *dlg)
00311 {
00312 int ret = 0;
00313 struct dlg_var *var;
00314
00315 LM_DBG("destroying dialog %p (ref %d)\n", dlg, dlg->ref);
00316
00317 ret = remove_dialog_timer(&dlg->tl);
00318 if (ret < 0) {
00319 LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
00320 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
00321 dlg, dlg->h_entry, dlg->h_id,
00322 dlg->callid.len, dlg->callid.s,
00323 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00324 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00325 } else if (ret > 0) {
00326 LM_DBG("removed timer for dlg %p [%u:%u] "
00327 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
00328 dlg, dlg->h_entry, dlg->h_id,
00329 dlg->callid.len, dlg->callid.s,
00330 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00331 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00332 }
00333
00334 run_dlg_callbacks( DLGCB_DESTROY , dlg, NULL, NULL, DLG_DIR_NONE, 0);
00335
00336
00337
00338 if (dlg_db_mode)
00339 remove_dialog_from_db(dlg);
00340
00341 if (dlg->cbs.first)
00342 destroy_dlg_callbacks_list(dlg->cbs.first);
00343
00344 if (dlg->profile_links)
00345 destroy_linkers(dlg->profile_links);
00346
00347 if (dlg->tag[DLG_CALLER_LEG].s)
00348 shm_free(dlg->tag[DLG_CALLER_LEG].s);
00349
00350 if (dlg->tag[DLG_CALLEE_LEG].s)
00351 shm_free(dlg->tag[DLG_CALLEE_LEG].s);
00352
00353 if (dlg->cseq[DLG_CALLER_LEG].s)
00354 shm_free(dlg->cseq[DLG_CALLER_LEG].s);
00355
00356 if (dlg->cseq[DLG_CALLEE_LEG].s)
00357 shm_free(dlg->cseq[DLG_CALLEE_LEG].s);
00358
00359 if (dlg->toroute_name.s)
00360 shm_free(dlg->toroute_name.s);
00361
00362
00363 while (dlg->vars) {
00364 var = dlg->vars;
00365 dlg->vars = dlg->vars->next;
00366 shm_free(var->key.s);
00367 shm_free(var->value.s);
00368 shm_free(var);
00369 }
00370
00371
00372 shm_free(dlg);
00373 dlg = 0;
00374 }
00375
00376
00380 void destroy_dlg_table(void)
00381 {
00382 struct dlg_cell *dlg, *l_dlg;
00383 unsigned int i;
00384
00385 if (d_table==0)
00386 return;
00387
00388 if (d_table->locks) {
00389 lock_set_destroy(d_table->locks);
00390 lock_set_dealloc(d_table->locks);
00391 }
00392
00393 for( i=0 ; i<d_table->size; i++ ) {
00394 dlg = d_table->entries[i].first;
00395 while (dlg) {
00396 l_dlg = dlg;
00397 dlg = dlg->next;
00398 destroy_dlg(l_dlg);
00399 }
00400
00401 }
00402
00403 shm_free(d_table);
00404 d_table = 0;
00405
00406 return;
00407 }
00408
00409
00419 struct dlg_cell* build_new_dlg( str *callid, str *from_uri, str *to_uri,
00420 str *from_tag, str *req_uri)
00421 {
00422 struct dlg_cell *dlg;
00423 int len;
00424 char *p;
00425
00426 len = sizeof(struct dlg_cell) + callid->len + from_uri->len +
00427 to_uri->len + req_uri->len;
00428 dlg = (struct dlg_cell*)shm_malloc( len );
00429 if (dlg==0) {
00430 LM_ERR("no more shm mem (%d)\n",len);
00431 return 0;
00432 }
00433
00434 memset( dlg, 0, len);
00435 dlg->state = DLG_STATE_UNCONFIRMED;
00436
00437 dlg->h_entry = core_hash( callid, 0, d_table->size);
00438 LM_DBG("new dialog on hash %u\n",dlg->h_entry);
00439
00440 p = (char*)(dlg+1);
00441
00442 dlg->callid.s = p;
00443 dlg->callid.len = callid->len;
00444 memcpy( p, callid->s, callid->len);
00445 p += callid->len;
00446
00447 dlg->from_uri.s = p;
00448 dlg->from_uri.len = from_uri->len;
00449 memcpy( p, from_uri->s, from_uri->len);
00450 p += from_uri->len;
00451
00452 dlg->to_uri.s = p;
00453 dlg->to_uri.len = to_uri->len;
00454 memcpy( p, to_uri->s, to_uri->len);
00455 p += to_uri->len;
00456
00457 dlg->req_uri.s = p;
00458 dlg->req_uri.len = req_uri->len;
00459 memcpy( p, req_uri->s, req_uri->len);
00460 p += req_uri->len;
00461
00462 if ( p!=(((char*)dlg)+len) ) {
00463 LM_CRIT("buffer overflow\n");
00464 shm_free(dlg);
00465 return 0;
00466 }
00467
00468 return dlg;
00469 }
00470
00471
00482 int dlg_set_leg_info(struct dlg_cell *dlg, str* tag, str *rr, str *contact,
00483 str *cseq, unsigned int leg)
00484 {
00485 char *p;
00486
00487 dlg->tag[leg].s = (char*)shm_malloc( tag->len + rr->len + contact->len );
00488 dlg->cseq[leg].s = (char*)shm_malloc( cseq->len );
00489 if ( dlg->tag[leg].s==NULL || dlg->cseq[leg].s==NULL) {
00490 LM_ERR("no more shm mem\n");
00491 if (dlg->tag[leg].s)
00492 {
00493 shm_free(dlg->tag[leg].s);
00494 dlg->tag[leg].s = NULL;
00495 }
00496 if (dlg->cseq[leg].s)
00497 {
00498 shm_free(dlg->cseq[leg].s);
00499 dlg->cseq[leg].s = NULL;
00500 }
00501 return -1;
00502 }
00503 p = dlg->tag[leg].s;
00504
00505
00506 dlg->tag[leg].len = tag->len;
00507 memcpy( p, tag->s, tag->len);
00508 p += tag->len;
00509
00510 dlg->contact[leg].s = p;
00511 dlg->contact[leg].len = contact->len;
00512 memcpy( p, contact->s, contact->len);
00513 p += contact->len;
00514
00515 if (rr->len) {
00516 dlg->route_set[leg].s = p;
00517 dlg->route_set[leg].len = rr->len;
00518 memcpy( p, rr->s, rr->len);
00519 }
00520
00521
00522 dlg->cseq[leg].len = cseq->len;
00523 memcpy( dlg->cseq[leg].s, cseq->s, cseq->len);
00524
00525 return 0;
00526 }
00527
00528
00536 int dlg_update_cseq(struct dlg_cell * dlg, unsigned int leg, str *cseq)
00537 {
00538 if ( dlg->cseq[leg].s ) {
00539 if (dlg->cseq[leg].len < cseq->len) {
00540 shm_free(dlg->cseq[leg].s);
00541 dlg->cseq[leg].s = (char*)shm_malloc(cseq->len);
00542 if (dlg->cseq[leg].s==NULL)
00543 goto error;
00544 }
00545 } else {
00546 dlg->cseq[leg].s = (char*)shm_malloc(cseq->len);
00547 if (dlg->cseq[leg].s==NULL)
00548 goto error;
00549 }
00550
00551 memcpy( dlg->cseq[leg].s, cseq->s, cseq->len );
00552 dlg->cseq[leg].len = cseq->len;
00553
00554 LM_DBG("cseq is %.*s\n", dlg->cseq[leg].len, dlg->cseq[leg].s);
00555 return 0;
00556 error:
00557 LM_ERR("not more shm mem\n");
00558 return -1;
00559 }
00560
00561
00571 dlg_cell_t *dlg_lookup( unsigned int h_entry, unsigned int h_id)
00572 {
00573 dlg_cell_t *dlg;
00574 dlg_entry_t *d_entry;
00575
00576 if(d_table==NULL)
00577 return 0;
00578
00579 if (h_entry>=d_table->size)
00580 goto not_found;
00581
00582 d_entry = &(d_table->entries[h_entry]);
00583
00584 dlg_lock( d_table, d_entry);
00585
00586 for( dlg=d_entry->first ; dlg ; dlg=dlg->next ) {
00587 if (dlg->h_id == h_id) {
00588 ref_dlg_unsafe(dlg, 1);
00589 dlg_unlock( d_table, d_entry);
00590 LM_DBG("dialog id=%u found on entry %u\n", h_id, h_entry);
00591 return dlg;
00592 }
00593 }
00594
00595 dlg_unlock( d_table, d_entry);
00596 not_found:
00597 LM_DBG("no dialog id=%u found on entry %u\n", h_id, h_entry);
00598 return 0;
00599 }
00600
00601
00610 dlg_cell_t* dlg_get_by_iuid(dlg_iuid_t *diuid)
00611 {
00612 if(diuid==NULL)
00613 return NULL;
00614 if(diuid->h_id==0)
00615 return NULL;
00616
00617 return dlg_lookup(diuid->h_entry, diuid->h_id);
00618 }
00619
00630 static inline struct dlg_cell* internal_get_dlg(unsigned int h_entry,
00631 str *callid, str *ftag, str *ttag, unsigned int *dir)
00632 {
00633 struct dlg_cell *dlg;
00634 struct dlg_entry *d_entry;
00635
00636 d_entry = &(d_table->entries[h_entry]);
00637
00638 dlg_lock( d_table, d_entry);
00639
00640 for( dlg = d_entry->first ; dlg ; dlg = dlg->next ) {
00641
00642 if (match_dialog( dlg, callid, ftag, ttag, dir)==1) {
00643 ref_dlg_unsafe(dlg, 1);
00644 dlg_unlock( d_table, d_entry);
00645 LM_DBG("dialog callid='%.*s' found\n on entry %u, dir=%d\n",
00646 callid->len, callid->s,h_entry,*dir);
00647 return dlg;
00648 }
00649 }
00650
00651 dlg_unlock( d_table, d_entry);
00652 LM_DBG("no dialog callid='%.*s' found\n", callid->len, callid->s);
00653 return 0;
00654 }
00655
00656
00657
00674 struct dlg_cell* get_dlg( str *callid, str *ftag, str *ttag, unsigned int *dir)
00675 {
00676 struct dlg_cell *dlg;
00677 unsigned int he;
00678
00679 he = core_hash(callid, 0, d_table->size);
00680 dlg = internal_get_dlg(he, callid, ftag, ttag, dir);
00681
00682 if (dlg == 0) {
00683 LM_DBG("no dialog callid='%.*s' found\n", callid->len, callid->s);
00684 return 0;
00685 }
00686 return dlg;
00687 }
00688
00689
00695 void link_dlg(struct dlg_cell *dlg, int n)
00696 {
00697 struct dlg_entry *d_entry;
00698
00699 d_entry = &(d_table->entries[dlg->h_entry]);
00700
00701 dlg_lock( d_table, d_entry);
00702
00703
00704 dlg->h_id = 1 + d_entry->next_id++;
00705 if(dlg->h_id == 0) dlg->h_id = 1;
00706 LM_DBG("linking dialog [%u:%u]\n", dlg->h_entry, dlg->h_id);
00707 if (d_entry->first==0) {
00708 d_entry->first = d_entry->last = dlg;
00709 } else {
00710 d_entry->last->next = dlg;
00711 dlg->prev = d_entry->last;
00712 d_entry->last = dlg;
00713 }
00714
00715 ref_dlg_unsafe(dlg, 1+n);
00716
00717 dlg_unlock( d_table, d_entry);
00718 return;
00719 }
00720
00721
00728 void dlg_ref(dlg_cell_t *dlg, unsigned int cnt)
00729 {
00730 dlg_entry_t *d_entry;
00731
00732 d_entry = &(d_table->entries[dlg->h_entry]);
00733
00734 dlg_lock( d_table, d_entry);
00735 ref_dlg_unsafe( dlg, cnt);
00736 dlg_unlock( d_table, d_entry);
00737 }
00738
00739
00746 void dlg_unref(dlg_cell_t *dlg, unsigned int cnt)
00747 {
00748 dlg_entry_t *d_entry;
00749
00750 d_entry = &(d_table->entries[dlg->h_entry]);
00751
00752 dlg_lock( d_table, d_entry);
00753 unref_dlg_unsafe( dlg, cnt, d_entry);
00754 dlg_unlock( d_table, d_entry);
00755 }
00756
00757
00763 void dlg_release(dlg_cell_t *dlg)
00764 {
00765 if(dlg==NULL)
00766 return;
00767 dlg_unref(dlg, 1);
00768 }
00769
00770
00777 static inline void log_next_state_dlg(const int event, const struct dlg_cell *dlg) {
00778 LM_CRIT("bogus event %d in state %d for dlg %p [%u:%u] with clid '%.*s' and tags "
00779 "'%.*s' '%.*s'\n", event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
00780 dlg->callid.len, dlg->callid.s,
00781 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00782 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00783 }
00784
00785
00799 void next_state_dlg(dlg_cell_t *dlg, int event,
00800 int *old_state, int *new_state, int *unref)
00801 {
00802 dlg_entry_t *d_entry;
00803
00804 d_entry = &(d_table->entries[dlg->h_entry]);
00805
00806 *unref = 0;
00807
00808 dlg_lock( d_table, d_entry);
00809
00810 *old_state = dlg->state;
00811
00812 switch (event) {
00813 case DLG_EVENT_TDEL:
00814 switch (dlg->state) {
00815 case DLG_STATE_UNCONFIRMED:
00816 case DLG_STATE_EARLY:
00817 dlg->state = DLG_STATE_DELETED;
00818 unref_dlg_unsafe(dlg,1,d_entry);
00819 *unref = 1;
00820 break;
00821 case DLG_STATE_CONFIRMED_NA:
00822 case DLG_STATE_CONFIRMED:
00823 unref_dlg_unsafe(dlg,1,d_entry);
00824 break;
00825 case DLG_STATE_DELETED:
00826 *unref = 1;
00827 break;
00828 default:
00829 log_next_state_dlg(event, dlg);
00830 }
00831 break;
00832 case DLG_EVENT_RPL1xx:
00833 switch (dlg->state) {
00834 case DLG_STATE_UNCONFIRMED:
00835 case DLG_STATE_EARLY:
00836 dlg->state = DLG_STATE_EARLY;
00837 break;
00838 default:
00839 log_next_state_dlg(event, dlg);
00840 }
00841 break;
00842 case DLG_EVENT_RPL3xx:
00843 switch (dlg->state) {
00844 case DLG_STATE_UNCONFIRMED:
00845 case DLG_STATE_EARLY:
00846 dlg->state = DLG_STATE_DELETED;
00847 *unref = 1;
00848 break;
00849 default:
00850 log_next_state_dlg(event, dlg);
00851 }
00852 break;
00853 case DLG_EVENT_RPL2xx:
00854 switch (dlg->state) {
00855 case DLG_STATE_DELETED:
00856 if (dlg->dflags&DLG_FLAG_HASBYE) {
00857 LM_CRIT("bogus event %d in state %d (with BYE) "
00858 "for dlg %p [%u:%u] with clid '%.*s' and tags '%.*s' '%.*s'\n",
00859 event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
00860 dlg->callid.len, dlg->callid.s,
00861 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00862 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00863 break;
00864 }
00865 ref_dlg_unsafe(dlg,1);
00866 case DLG_STATE_UNCONFIRMED:
00867 case DLG_STATE_EARLY:
00868 dlg->state = DLG_STATE_CONFIRMED_NA;
00869 break;
00870 case DLG_STATE_CONFIRMED_NA:
00871 case DLG_STATE_CONFIRMED:
00872 break;
00873 default:
00874 log_next_state_dlg(event, dlg);
00875 }
00876 break;
00877 case DLG_EVENT_REQACK:
00878 switch (dlg->state) {
00879 case DLG_STATE_CONFIRMED_NA:
00880 dlg->state = DLG_STATE_CONFIRMED;
00881 break;
00882 case DLG_STATE_CONFIRMED:
00883 break;
00884 case DLG_STATE_DELETED:
00885 break;
00886 default:
00887 log_next_state_dlg(event, dlg);
00888 }
00889 break;
00890 case DLG_EVENT_REQBYE:
00891 switch (dlg->state) {
00892 case DLG_STATE_CONFIRMED_NA:
00893 case DLG_STATE_CONFIRMED:
00894 dlg->dflags |= DLG_FLAG_HASBYE;
00895 dlg->state = DLG_STATE_DELETED;
00896 *unref = 1;
00897 break;
00898 case DLG_STATE_EARLY:
00899 case DLG_STATE_DELETED:
00900 break;
00901 default:
00902 log_next_state_dlg(event, dlg);
00903 }
00904 break;
00905 case DLG_EVENT_REQPRACK:
00906 switch (dlg->state) {
00907 case DLG_STATE_EARLY:
00908 case DLG_STATE_CONFIRMED_NA:
00909 case DLG_STATE_DELETED:
00910 break;
00911 default:
00912 log_next_state_dlg(event, dlg);
00913 }
00914 break;
00915 case DLG_EVENT_REQ:
00916 switch (dlg->state) {
00917 case DLG_STATE_EARLY:
00918 case DLG_STATE_CONFIRMED_NA:
00919 case DLG_STATE_CONFIRMED:
00920 case DLG_STATE_DELETED:
00921 break;
00922 default:
00923 log_next_state_dlg(event, dlg);
00924 }
00925 break;
00926 default:
00927 LM_CRIT("unknown event %d in state %d "
00928 "for dlg %p [%u:%u] with clid '%.*s' and tags '%.*s' '%.*s'\n",
00929 event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
00930 dlg->callid.len, dlg->callid.s,
00931 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00932 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00933 }
00934 *new_state = dlg->state;
00935
00936 dlg_unlock( d_table, d_entry);
00937
00938 LM_DBG("dialog %p changed from state %d to "
00939 "state %d, due event %d (ref %d)\n", dlg, *old_state, *new_state, event,
00940 dlg->ref);
00941 }
00942
00946 int dlg_set_toroute(struct dlg_cell *dlg, str *route)
00947 {
00948 if(dlg==NULL || route==NULL || route->len<=0)
00949 return 0;
00950 if(dlg->toroute_name.s!=NULL) {
00951 shm_free(dlg->toroute_name.s);
00952 dlg->toroute_name.s = NULL;
00953 dlg->toroute_name.len = 0;
00954 }
00955 dlg->toroute_name.s = (char*)shm_malloc((route->len+1)*sizeof(char));
00956 if(dlg->toroute_name.s==NULL) {
00957 LM_ERR("no more shared memory\n");
00958 return -1;
00959 }
00960 memcpy(dlg->toroute_name.s, route->s, route->len);
00961 dlg->toroute_name.len = route->len;
00962 dlg->toroute_name.s[dlg->toroute_name.len] = '\0';
00963 dlg->toroute = route_lookup(&main_rt, dlg->toroute_name.s);
00964 return 0;
00965 }
00966
00967
00976 static inline int internal_mi_print_dlg(struct mi_node *rpl,
00977 struct dlg_cell *dlg, int with_context)
00978 {
00979 struct mi_node* node= NULL;
00980 struct mi_node* node1 = NULL;
00981 struct mi_attr* attr= NULL;
00982 int len;
00983 char* p;
00984
00985 node = add_mi_node_child(rpl, 0, "dialog",6 , 0, 0 );
00986 if (node==0)
00987 goto error;
00988
00989 attr = addf_mi_attr( node, 0, "hash", 4, "%u:%u",
00990 dlg->h_entry, dlg->h_id );
00991 if (attr==0)
00992 goto error;
00993
00994 p= int2str((unsigned long)dlg->state, &len);
00995 node1 = add_mi_node_child( node, MI_DUP_VALUE, "state", 5, p, len);
00996 if (node1==0)
00997 goto error;
00998
00999 p= int2str((unsigned long)dlg->ref, &len);
01000 node1 = add_mi_node_child( node, MI_DUP_VALUE, "ref_count", 9, p, len);
01001 if (node1==0)
01002 goto error;
01003
01004 p= int2str((unsigned long)dlg->start_ts, &len);
01005 node1 = add_mi_node_child(node,MI_DUP_VALUE,"timestart",9, p, len);
01006 if (node1==0)
01007 goto error;
01008
01009 p= int2str((unsigned long)dlg->tl.timeout, &len);
01010 node1 = add_mi_node_child(node,MI_DUP_VALUE, "timeout", 7, p, len);
01011 if (node1==0)
01012 goto error;
01013
01014 node1 = add_mi_node_child(node, MI_DUP_VALUE, "callid", 6,
01015 dlg->callid.s, dlg->callid.len);
01016 if(node1 == 0)
01017 goto error;
01018
01019 node1 = add_mi_node_child(node, MI_DUP_VALUE, "from_uri", 8,
01020 dlg->from_uri.s, dlg->from_uri.len);
01021 if(node1 == 0)
01022 goto error;
01023
01024 node1 = add_mi_node_child(node, MI_DUP_VALUE, "from_tag", 8,
01025 dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLER_LEG].len);
01026 if(node1 == 0)
01027 goto error;
01028
01029 node1 = add_mi_node_child(node, MI_DUP_VALUE, "caller_contact", 14,
01030 dlg->contact[DLG_CALLER_LEG].s,
01031 dlg->contact[DLG_CALLER_LEG].len);
01032 if(node1 == 0)
01033 goto error;
01034
01035 node1 = add_mi_node_child(node, MI_DUP_VALUE, "caller_cseq", 11,
01036 dlg->cseq[DLG_CALLER_LEG].s,
01037 dlg->cseq[DLG_CALLER_LEG].len);
01038 if(node1 == 0)
01039 goto error;
01040
01041 node1 = add_mi_node_child(node, MI_DUP_VALUE,"caller_route_set",16,
01042 dlg->route_set[DLG_CALLER_LEG].s,
01043 dlg->route_set[DLG_CALLER_LEG].len);
01044 if(node1 == 0)
01045 goto error;
01046
01047 if (dlg->bind_addr[DLG_CALLER_LEG]) {
01048 node1 = add_mi_node_child(node, 0,
01049 "caller_bind_addr",16,
01050 dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s,
01051 dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len);
01052 } else {
01053 node1 = add_mi_node_child(node, 0,
01054 "caller_bind_addr",16,0,0);
01055 }
01056
01057 if (dlg->bind_addr[DLG_CALLEE_LEG]) {
01058 node1 = add_mi_node_child(node, 0,
01059 "callee_bind_addr",16,
01060 dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s,
01061 dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len);
01062 } else {
01063 node1 = add_mi_node_child(node, 0,
01064 "callee_bind_addr",16,0,0);
01065 }
01066
01067 node1 = add_mi_node_child(node, MI_DUP_VALUE, "to_uri", 6,
01068 dlg->to_uri.s, dlg->to_uri.len);
01069 if(node1 == 0)
01070 goto error;
01071
01072 node1 = add_mi_node_child(node, MI_DUP_VALUE, "to_tag", 6,
01073 dlg->tag[DLG_CALLEE_LEG].s, dlg->tag[DLG_CALLEE_LEG].len);
01074 if(node1 == 0)
01075 goto error;
01076
01077 node1 = add_mi_node_child(node, MI_DUP_VALUE, "callee_contact", 14,
01078 dlg->contact[DLG_CALLEE_LEG].s,
01079 dlg->contact[DLG_CALLEE_LEG].len);
01080 if(node1 == 0)
01081 goto error;
01082
01083 node1 = add_mi_node_child(node, MI_DUP_VALUE, "callee_cseq", 11,
01084 dlg->cseq[DLG_CALLEE_LEG].s,
01085 dlg->cseq[DLG_CALLEE_LEG].len);
01086 if(node1 == 0)
01087 goto error;
01088
01089 node1 = add_mi_node_child(node, MI_DUP_VALUE,"callee_route_set",16,
01090 dlg->route_set[DLG_CALLEE_LEG].s,
01091 dlg->route_set[DLG_CALLEE_LEG].len);
01092 if(node1 == 0)
01093 goto error;
01094
01095 if (with_context) {
01096 node1 = add_mi_node_child(node, 0, "context", 7, 0, 0);
01097 if(node1 == 0)
01098 goto error;
01099 run_dlg_callbacks( DLGCB_MI_CONTEXT,
01100 dlg,
01101 NULL,
01102 NULL,
01103 DLG_DIR_NONE,
01104 (void *)node1);
01105 }
01106 return 0;
01107
01108 error:
01109 LM_ERR("failed to add node\n");
01110 return -1;
01111 }
01112
01113
01121 int mi_print_dlg(struct mi_node *rpl, struct dlg_cell *dlg, int with_context)
01122 {
01123 return internal_mi_print_dlg( rpl, dlg, with_context);
01124 }
01125
01133 static int internal_mi_print_dlgs(struct mi_node *rpl, int with_context)
01134 {
01135 struct dlg_cell *dlg;
01136 unsigned int i;
01137
01138 LM_DBG("printing %i dialogs\n", d_table->size);
01139
01140 for( i=0 ; i<d_table->size ; i++ ) {
01141 dlg_lock( d_table, &(d_table->entries[i]) );
01142
01143 for( dlg=d_table->entries[i].first ; dlg ; dlg=dlg->next ) {
01144 if (internal_mi_print_dlg(rpl, dlg, with_context)!=0)
01145 goto error;
01146 }
01147 dlg_unlock( d_table, &(d_table->entries[i]) );
01148 }
01149 return 0;
01150
01151 error:
01152 dlg_unlock( d_table, &(d_table->entries[i]) );
01153 LM_ERR("failed to print dialog\n");
01154 return -1;
01155 }
01156
01157
01158 static inline struct mi_root* process_mi_params(struct mi_root *cmd_tree,
01159 struct dlg_cell **dlg_p)
01160 {
01161 struct mi_node* node;
01162 struct dlg_entry *d_entry;
01163 struct dlg_cell *dlg;
01164 str *callid;
01165 str *from_tag;
01166 unsigned int h_entry;
01167
01168 node = cmd_tree->node.kids;
01169 if (node == NULL) {
01170
01171 *dlg_p = NULL;
01172 return NULL;
01173 }
01174
01175
01176 callid = &node->value;
01177 LM_DBG("callid='%.*s'\n", callid->len, callid->s);
01178
01179 node = node->next;
01180 if ( !node || !node->value.s || !node->value.len) {
01181 from_tag = NULL;
01182 } else {
01183 from_tag = &node->value;
01184 LM_DBG("from_tag='%.*s'\n", from_tag->len, from_tag->s);
01185 if ( node->next!=NULL )
01186 return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
01187 }
01188
01189 h_entry = core_hash( callid, 0, d_table->size);
01190
01191 d_entry = &(d_table->entries[h_entry]);
01192 dlg_lock( d_table, d_entry);
01193
01194 for( dlg = d_entry->first ; dlg ; dlg = dlg->next ) {
01195 if (match_downstream_dialog( dlg, callid, from_tag)==1) {
01196 if (dlg->state==DLG_STATE_DELETED) {
01197 *dlg_p = NULL;
01198 break;
01199 } else {
01200 *dlg_p = dlg;
01201 dlg_unlock( d_table, d_entry);
01202 return 0;
01203 }
01204 }
01205 }
01206 dlg_unlock( d_table, d_entry);
01207
01208 return init_mi_tree( 404, MI_SSTR("Nu such dialog"));
01209 }
01210
01211
01218 struct mi_root * mi_print_dlgs(struct mi_root *cmd_tree, void *param )
01219 {
01220 struct mi_root* rpl_tree= NULL;
01221 struct mi_node* rpl = NULL;
01222 struct dlg_cell* dlg = NULL;
01223
01224 rpl_tree = process_mi_params( cmd_tree, &dlg);
01225 if (rpl_tree)
01226
01227 return rpl_tree;
01228
01229 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
01230 if (rpl_tree==0)
01231 return 0;
01232 rpl = &rpl_tree->node;
01233
01234 if (dlg==NULL) {
01235 if ( internal_mi_print_dlgs(rpl,0)!=0 )
01236 goto error;
01237 } else {
01238 if ( internal_mi_print_dlg(rpl,dlg,0)!=0 )
01239 goto error;
01240 }
01241
01242 return rpl_tree;
01243 error:
01244 free_mi_tree(rpl_tree);
01245 return NULL;
01246 }
01247
01248
01255 struct mi_root * mi_print_dlgs_ctx(struct mi_root *cmd_tree, void *param )
01256 {
01257 struct mi_root* rpl_tree= NULL;
01258 struct mi_node* rpl = NULL;
01259 struct dlg_cell* dlg = NULL;
01260
01261 rpl_tree = process_mi_params( cmd_tree, &dlg);
01262 if (rpl_tree)
01263
01264 return rpl_tree;
01265
01266 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
01267 if (rpl_tree==0)
01268 return 0;
01269 rpl = &rpl_tree->node;
01270
01271 if (dlg==NULL) {
01272 if ( internal_mi_print_dlgs(rpl,1)!=0 )
01273 goto error;
01274 } else {
01275 if ( internal_mi_print_dlg(rpl,dlg,1)!=0 )
01276 goto error;
01277 }
01278
01279 return rpl_tree;
01280 error:
01281 free_mi_tree(rpl_tree);
01282 return NULL;
01283 }
01284
01291 struct mi_root * mi_terminate_dlgs(struct mi_root *cmd_tree, void *param )
01292 {
01293 struct mi_root* rpl_tree= NULL;
01294 struct dlg_cell* dlg = NULL;
01295 str headers = {0, 0};
01296
01297 rpl_tree = process_mi_params( cmd_tree, &dlg);
01298 if (rpl_tree)
01299
01300 return rpl_tree;
01301 if (dlg==NULL)
01302 return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
01303
01304 rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
01305 if (rpl_tree==0)
01306 return 0;
01307 if (dlg_bye_all(dlg, &headers)!=0)
01308 goto error;
01309 return rpl_tree;
01310 error:
01311 free_mi_tree(rpl_tree);
01312 return NULL;
01313 }
01314
01315