modules_k/dialog: Provide new fix to prevent "unable to find
authorTimo Reimann <timo.reimann@1und1.de>
Thu, 5 Aug 2010 15:48:30 +0000 (17:48 +0200)
committerTimo Reimann <timo.reimann@1und1.de>
Thu, 5 Aug 2010 15:48:30 +0000 (17:48 +0200)
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
modules_k/dialog/dlg_handlers.c
modules_k/dialog/dlg_hash.c
modules_k/dialog/dlg_hash.h
modules_k/dialog/dlg_req_within.c

index f965a06..0ca60b4 100644 (file)
@@ -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);
index 1e9a1b3..ef1e23f 100644 (file)
@@ -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);
index 6df21e3..58332a6 100644 (file)
@@ -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;
        }
index 889a318..e555837 100644 (file)
@@ -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);
 
 
 /*!
index aae12fd..3b6c57d 100644 (file)
@@ -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