From 23a3481302d5aca04be0e8d10f6d4ce23dbc36aa Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Fri, 18 Mar 2016 13:23:06 +0100 Subject: [PATCH] dialog: force cleanup of aged terminated dialogs - reported by Dmitri Savolainen, GH #545 --- modules/dialog/dlg_db_handler.c | 4 ++++ modules/dialog/dlg_handlers.c | 16 +++++++++++++--- modules/dialog/dlg_hash.c | 7 +++++++ modules/dialog/dlg_hash.h | 1 + 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/modules/dialog/dlg_db_handler.c b/modules/dialog/dlg_db_handler.c index dcb5ebcd691..e27f8b2a7a5 100644 --- a/modules/dialog/dlg_db_handler.c +++ b/modules/dialog/dlg_db_handler.c @@ -425,6 +425,10 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows) srjson_DestroyDoc(&jdoc); } dlg->iflags = (unsigned int)VAL_INT(values+22); + if(dlg->state==DLG_STATE_DELETED) { + /* end_ts used for force clean up not stored - set it to now */ + dlg->end_ts = (unsigned int)time(0); + } /*restore the timer values */ if (0 != insert_dlg_timer( &(dlg->tl), (int)dlg->tl.timeout )) { LM_CRIT("Unable to insert dlg %p [%u:%u] " diff --git a/modules/dialog/dlg_handlers.c b/modules/dialog/dlg_handlers.c index 0cd97ece74b..36a807f347e 100644 --- a/modules/dialog/dlg_handlers.c +++ b/modules/dialog/dlg_handlers.c @@ -524,6 +524,11 @@ static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) goto done; } + if(new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) { + /* set end time */ + dlg->end_ts = (unsigned int)(time(0)); + } + if ( new_state==DLG_STATE_DELETED && (old_state==DLG_STATE_UNCONFIRMED || old_state==DLG_STATE_EARLY) ) { @@ -1280,7 +1285,7 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param) iuid = NULL; } } - + /* run state machine */ switch ( req->first_line.u.request.method_value ) { case METHOD_PRACK: @@ -1304,6 +1309,8 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param) /* delay deletion of dialog until transaction has died off in order * to absorb in-air messages */ if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) { + /* set end time */ + dlg->end_ts = (unsigned int)(time(0)); iuid = dlg_get_iuid_shm_clone(dlg); if(iuid!=NULL) { if ( d_tmb.register_tmcb(req, NULL, TMCB_DESTROY, @@ -1478,7 +1485,7 @@ void dlg_ontimeout(struct dlg_tl *tl) dlg_set_ctx_iuid(dlg); if(dlg_bye_all(dlg, NULL)<0) dlg_unref(dlg, 1); - dlg_reset_ctx_iuid(); + dlg_reset_ctx_iuid(); dlg_unref(dlg, 1); if_update_stat(dlg_enable_stats, expired_dlgs, 1); @@ -1490,7 +1497,7 @@ void dlg_ontimeout(struct dlg_tl *tl) /* used for computing duration for timed out acknowledged dialog */ if (DLG_STATE_CONFIRMED == old_state) { timeout_cb = (void *)CONFIRMED_DIALOG_STATE; - } + } dlg_run_event_route(dlg, NULL, old_state, new_state); @@ -1500,6 +1507,9 @@ void dlg_ontimeout(struct dlg_tl *tl) dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s); + /* set end time */ + dlg->end_ts = (unsigned int)(time(0)); + /* dialog timeout */ run_dlg_callbacks( DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, timeout_cb); diff --git a/modules/dialog/dlg_hash.c b/modules/dialog/dlg_hash.c index 55aa14fb124..9a96f1b2c16 100644 --- a/modules/dialog/dlg_hash.c +++ b/modules/dialog/dlg_hash.c @@ -239,6 +239,13 @@ int dlg_clean_run(ticks_t ti) tdlg->lifetime = 10; tdlg->dflags |= DLG_FLAG_CHANGED; } + if(tdlg->state==DLG_STATE_DELETED && tdlg->end_tsref); + unlink_unsafe_dlg(&d_table->entries[i], tdlg); + destroy_dlg(tdlg); + } } dlg_unlock(d_table, &d_table->entries[i]); } diff --git a/modules/dialog/dlg_hash.h b/modules/dialog/dlg_hash.h index ef945143955..954a7d4ccaf 100644 --- a/modules/dialog/dlg_hash.h +++ b/modules/dialog/dlg_hash.h @@ -108,6 +108,7 @@ typedef struct dlg_cell unsigned int lifetime; /*!< dialog lifetime */ unsigned int init_ts; /*!< init (creation) time (absolute UNIX ts)*/ unsigned int start_ts; /*!< start time (absolute UNIX ts)*/ + unsigned int end_ts; /*!< end time (absolute UNIX ts)*/ unsigned int dflags; /*!< internal dialog memory flags */ unsigned int iflags; /*!< internal dialog persistent flags */ unsigned int sflags; /*!< script dialog persistent flags */