Module: sip-router
Branch: master
Commit: d1693b2c64dfc44f0271bdd1c38315578ebe7135
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d1693b2…
Author: Timo Reimann <timo.reimann(a)1und1.de>
Committer: Timo Reimann <timo.reimann(a)1und1.de>
Date: Thu Aug 5 17:48:30 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.
---
modules_k/dialog/dialog.c | 4 ++--
modules_k/dialog/dlg_handlers.c | 20 +++++++++++++++++---
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, 41 insertions(+), 13 deletions(-)
diff --git a/modules_k/dialog/dialog.c b/modules_k/dialog/dialog.c
index f965a06..0ca60b4 100644
--- a/modules_k/dialog/dialog.c
+++ b/modules_k/dialog/dialog.c
@@ -1064,7 +1064,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;
@@ -1351,7 +1351,7 @@ static void rpc_end_dlg_entry_id(rpc_t *rpc, void *c) {
if (rpc->scan(c, "ddS", &h_entry, &h_id, &rpc_extra_hdrs) <
2) return;
- dlg = lookup_dlg(h_entry, h_id);
+ dlg = lookup_dlg(h_entry, h_id, NULL);
if(dlg){
dlg_bye_all(dlg, (rpc_extra_hdrs.len>0)?&rpc_extra_hdrs:NULL);
unref_dlg(dlg, 1);
diff --git a/modules_k/dialog/dlg_handlers.c b/modules_k/dialog/dlg_handlers.c
index 1e9a1b3..ef1e23f 100644
--- a/modules_k/dialog/dlg_handlers.c
+++ b/modules_k/dialog/dlg_handlers.c
@@ -542,6 +542,7 @@ void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
str ftag;
str ttag;
unsigned int dir;
+ unsigned int del;
struct sip_msg *req = param->req;
if((req->flags&dlg_flag)!=dlg_flag)
@@ -565,7 +566,11 @@ void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
LM_WARN("pre-matching failed\n");
return;
}
- 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, must be a new dialog\n",
req->callid->body.len, req->callid->body.s);
@@ -837,6 +842,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)
@@ -865,7 +871,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",
@@ -913,7 +923,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