Module: sip-router Branch: kamailio_3.0 Commit: 7dfea988c61544752b4c5fef642d9599c20f36c6 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=7dfea988...
Author: Timo Reimann timo.reimann@1und1.de Committer: Timo Reimann timo.reimann@1und1.de Date: Thu Aug 5 18:12:17 2010 +0200
modules_k/dialog: Provide new fix to prevent "unable to find dialog" WARN messages caused by accessing a dialog in the "deleted" state (often happens with simultaneous BYE requests when both UAs hang up at the same time).
This commit uses a different approach where a "deleted" flag is set in get_dlg() and lookup_dlg() which callers may evaluate. Callers who only care about existing dialogs can ignore the flag by passing a NULL argument.
The commit "replaces" 9b7f25d7 and follows up 0723496c. (cherry picked from commit d1693b2c64dfc44f0271bdd1c38315578ebe7135)
---
modules_k/dialog/dialog.c | 2 +- modules_k/dialog/dlg_handlers.c | 13 +++++++++++-- modules_k/dialog/dlg_hash.c | 22 +++++++++++++++++----- modules_k/dialog/dlg_hash.h | 6 ++++-- modules_k/dialog/dlg_req_within.c | 2 +- 5 files changed, 34 insertions(+), 11 deletions(-)
diff --git a/modules_k/dialog/dialog.c b/modules_k/dialog/dialog.c index e2bff0b..d58ea4b 100644 --- a/modules_k/dialog/dialog.c +++ b/modules_k/dialog/dialog.c @@ -1048,7 +1048,7 @@ static int w_dlg_get(struct sip_msg *msg, char *ci, char *ft, char *tt) return -1; }
- dlg = get_dlg(&sc, &sf, &st, &dir); + dlg = get_dlg(&sc, &sf, &st, &dir, NULL); if(dlg==NULL) return -1; current_dlg_pointer = dlg; diff --git a/modules_k/dialog/dlg_handlers.c b/modules_k/dialog/dlg_handlers.c index 976ac0f..5e5e3c5 100644 --- a/modules_k/dialog/dlg_handlers.c +++ b/modules_k/dialog/dlg_handlers.c @@ -795,6 +795,7 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param) str val, callid, ftag, ttag; int h_entry, h_id, new_state, old_state, unref, event, timeout; unsigned int dir; + unsigned int del; int ret = 0;
if (current_dlg_pointer!=NULL) @@ -823,7 +824,11 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param) if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 ) return;
- dlg = lookup_dlg( h_entry, h_id); + dlg = lookup_dlg( h_entry, h_id, &del); + if (del == 1) { + LM_DBG("dialog marked for deletion, ignoring\n"); + return; + } if (dlg==0) { LM_WARN("unable to find dialog for %.*s " "with route param '%.*s' [%u:%u]\n", @@ -871,7 +876,11 @@ void dlg_onroute(struct sip_msg* req, str *route_params, void *param) return; /* TODO - try to use the RR dir detection to speed up here the * search -bogdan */ - dlg = get_dlg(&callid, &ftag, &ttag, &dir); + dlg = get_dlg(&callid, &ftag, &ttag, &dir, &del); + if (del == 1) { + LM_DBG("dialog marked for deletion, ignoring\n"); + return; + } if (!dlg){ LM_DBG("Callid '%.*s' not found\n", req->callid->body.len, req->callid->body.s); diff --git a/modules_k/dialog/dlg_hash.c b/modules_k/dialog/dlg_hash.c index 6df21e3..58332a6 100644 --- a/modules_k/dialog/dlg_hash.c +++ b/modules_k/dialog/dlg_hash.c @@ -362,11 +362,14 @@ error: * \param h_id id of the hash table entry * \return dialog on success, NULL on failure */ -struct dlg_cell* lookup_dlg( unsigned int h_entry, unsigned int h_id) +struct dlg_cell* lookup_dlg( unsigned int h_entry, unsigned int h_id, unsigned int *del) { struct dlg_cell *dlg; struct dlg_entry *d_entry;
+ if (del != NULL) + *del = 0; + if (h_entry>=d_table->size) goto not_found;
@@ -377,6 +380,8 @@ struct dlg_cell* lookup_dlg( unsigned int h_entry, unsigned int h_id) for( dlg=d_entry->first ; dlg ; dlg=dlg->next ) { if (dlg->h_id == h_id) { if (dlg->state==DLG_STATE_DELETED) { + if (del != NULL) + *del = 1; dlg_unlock( d_table, d_entry); goto not_found; } @@ -405,11 +410,15 @@ not_found: * \return dialog structure on success, NULL on failure */ static inline struct dlg_cell* internal_get_dlg(unsigned int h_entry, - str *callid, str *ftag, str *ttag, unsigned int *dir) + str *callid, str *ftag, str *ttag, unsigned int *dir, + unsigned int *del) { struct dlg_cell *dlg; struct dlg_entry *d_entry;
+ if (del != NULL) + *del = 0; + d_entry = &(d_table->entries[h_entry]);
dlg_lock( d_table, d_entry); @@ -418,6 +427,8 @@ static inline struct dlg_cell* internal_get_dlg(unsigned int h_entry, /* Check callid / fromtag / totag */ if (match_dialog( dlg, callid, ftag, ttag, dir)==1) { if (dlg->state==DLG_STATE_DELETED) { + if (del != NULL) + *del = 1; dlg_unlock( d_table, d_entry); goto not_found; } @@ -453,14 +464,15 @@ not_found: * \param dir direction * \return dialog structure on success, NULL on failure */ -struct dlg_cell* get_dlg( str *callid, str *ftag, str *ttag, unsigned int *dir) +struct dlg_cell* get_dlg( str *callid, str *ftag, str *ttag, unsigned int *dir, + unsigned int *del) { struct dlg_cell *dlg;
if ((dlg = internal_get_dlg(core_hash(callid, ftag->len?ftag:0, - d_table->size), callid, ftag, ttag, dir)) == 0 && + d_table->size), callid, ftag, ttag, dir, del)) == 0 && (dlg = internal_get_dlg(core_hash(callid, ttag->len - ?ttag:0, d_table->size), callid, ftag, ttag, dir)) == 0) { + ?ttag:0, d_table->size), callid, ftag, ttag, dir, del)) == 0) { LM_DBG("no dialog callid='%.*s' found\n", callid->len, callid->s); return 0; } diff --git a/modules_k/dialog/dlg_hash.h b/modules_k/dialog/dlg_hash.h index 889a318..e555837 100644 --- a/modules_k/dialog/dlg_hash.h +++ b/modules_k/dialog/dlg_hash.h @@ -243,9 +243,10 @@ int dlg_update_cseq(struct dlg_cell *dlg, unsigned int leg, str *cseq); * \brief Lookup a dialog in the global list * \param h_entry number of the hash table entry * \param h_id id of the hash table entry + * \param del unless null, flag that is set if dialog is in "deleted" state * \return dialog on success, NULL on failure */ -struct dlg_cell* lookup_dlg( unsigned int h_entry, unsigned int h_id); +struct dlg_cell* lookup_dlg( unsigned int h_entry, unsigned int h_id, unsigned int *del);
/*! @@ -260,9 +261,10 @@ struct dlg_cell* lookup_dlg( unsigned int h_entry, unsigned int h_id); * \param ftag from tag * \param ttag to tag * \param dir direction + * \param del unless null, flag that is set if dialog is in "deleted" state * \return dialog structure on success, NULL on failure */ -struct dlg_cell* get_dlg(str *callid, str *ftag, str *ttag, unsigned int *dir); +struct dlg_cell* get_dlg(str *callid, str *ftag, str *ttag, unsigned int *dir, unsigned int *del);
/*! diff --git a/modules_k/dialog/dlg_req_within.c b/modules_k/dialog/dlg_req_within.c index aae12fd..3b6c57d 100644 --- a/modules_k/dialog/dlg_req_within.c +++ b/modules_k/dialog/dlg_req_within.c @@ -317,7 +317,7 @@ struct mi_root * mi_terminate_dlg(struct mi_root *cmd_tree, void *param ){
LM_DBG("h_entry %u h_id %u\n", h_entry, h_id);
- dlg = lookup_dlg(h_entry, h_id); + dlg = lookup_dlg(h_entry, h_id, NULL);
// lookup_dlg has incremented the reference count