Index: pjproject/trunk/pjsip/include/pjsip/sip_dialog.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_dialog.h	(revision 195)
+++ pjproject/trunk/pjsip/include/pjsip/sip_dialog.h	(revision 196)
@@ -208,14 +208,7 @@
  * the value directly by accessing dlg->mod_data[module_id].
  */
-PJ_INLINE(pj_status_t) pjsip_dlg_set_mod_data( pjsip_dialog *dlg,
-					       int mod_id,
-					       void *data )
-{
-    PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
-    PJ_ASSERT_RETURN(mod_id >= 0 && mod_id < PJSIP_MAX_MODULE,
-		     PJ_EINVAL);
-    dlg->mod_data[mod_id] = data;
-    return PJ_SUCCESS;
-}
+PJ_DECL(pj_status_t) pjsip_dlg_set_mod_data( pjsip_dialog *dlg,
+					     int mod_id,
+					     void *data );
 
 /**
@@ -223,13 +216,19 @@
  * can also get value directly by accessing dlg->mod_data[module_id].
  */
-PJ_INLINE(void*) pjsip_dlg_get_mod_data(pjsip_dialog *dlg,
-					int mod_id)
-{
-    PJ_ASSERT_RETURN(dlg, NULL);
-    PJ_ASSERT_RETURN(mod_id >= 0 && mod_id < PJSIP_MAX_MODULE,
-		     NULL);
-    return dlg->mod_data[mod_id];
-}
-
+PJ_DECL(void*) pjsip_dlg_get_mod_data( pjsip_dialog *dlg,
+				       int mod_id);
+
+
+/**
+ * Lock dialog and increment session counter termporarily, to prevent it 
+ * from being destroyed.
+ */
+PJ_DECL(void) pjsip_dlg_inc_lock( pjsip_dialog *dlg );
+
+/**
+ * Unlock dialog and decrement temporary session counter. After this function
+ * is called, dialog may be destroyed.
+ */
+PJ_DECL(void) pjsip_dlg_dec_lock( pjsip_dialog *dlg );
 
 
Index: pjproject/trunk/pjsip/src/pjsip/sip_dialog.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_dialog.c	(revision 195)
+++ pjproject/trunk/pjsip/src/pjsip/sip_dialog.c	(revision 196)
@@ -42,10 +42,12 @@
 PJ_DEF(pj_bool_t) pjsip_method_creates_dialog(const pjsip_method *m)
 {
-    pjsip_method subscribe = { PJSIP_OTHER_METHOD, {"SUBSCRIBE", 10}};
-    pjsip_method refer = { PJSIP_OTHER_METHOD, {"REFER", 5}};
+    const pjsip_method subscribe = { PJSIP_OTHER_METHOD, {"SUBSCRIBE", 9}};
+    const pjsip_method refer = { PJSIP_OTHER_METHOD, {"REFER", 5}};
+    const pjsip_method notify = { PJSIP_OTHER_METHOD, {"NOTIFY", 6}};
 
     return m->id == PJSIP_INVITE_METHOD ||
 	   (pjsip_method_cmp(m, &subscribe)==0) ||
-	   (pjsip_method_cmp(m, &refer)==0);
+	   (pjsip_method_cmp(m, &refer)==0) ||
+	   (pjsip_method_cmp(m, &notify)==0);
 }
 
@@ -598,4 +600,33 @@
 
 /*
+ * Lock dialog and increment session counter temporarily
+ * to prevent it from being deleted.
+ */
+PJ_DEF(void) pjsip_dlg_inc_lock(pjsip_dialog *dlg)
+{
+    pj_mutex_lock(dlg->mutex);
+    dlg->sess_count++;
+}
+
+
+/*
+ * Unlock dialog and decrement session counter.
+ * It may delete the dialog!
+ */
+PJ_DEF(void) pjsip_dlg_dec_lock(pjsip_dialog *dlg)
+{
+    pj_assert(dlg->sess_count > 0);
+    --dlg->sess_count;
+
+    if (dlg->sess_count==0 && dlg->tsx_count==0)
+	unregister_and_destroy_dialog(dlg);
+    else {
+	pj_mutex_unlock(dlg->mutex);
+    }
+}
+
+
+
+/*
  * Decrement session counter.
  */
@@ -603,6 +634,4 @@
 					   pjsip_module *mod)
 {
-    pj_status_t status;
-
     PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
 
@@ -611,18 +640,8 @@
 
     pj_mutex_lock(dlg->mutex);
-
-    pj_assert(dlg->sess_count > 0);
-    --dlg->sess_count;
-
-    if (dlg->sess_count==0 && dlg->tsx_count==0)
-	status = unregister_and_destroy_dialog(dlg);
-    else {
-	pj_mutex_unlock(dlg->mutex);
-	status = PJ_SUCCESS;
-    }
-
-    return status;
-}
-
+    pjsip_dlg_dec_lock(dlg);
+
+    return PJ_SUCCESS;
+}
 
 /*
@@ -640,6 +659,7 @@
     PJ_ASSERT_RETURN(dlg->usage_cnt < PJSIP_MAX_MODULE, PJ_EBUG);
 
-    PJ_LOG(5,(dlg->obj_name, "Module %.*s added as dialog usage",
-	      (int)mod->name.slen, mod->name.ptr));
+    PJ_LOG(5,(dlg->obj_name, 
+	      "Module %.*s added as dialog usage, data=%p",
+	      (int)mod->name.slen, mod->name.ptr, mod_data));
 
     pj_mutex_lock(dlg->mutex);
@@ -675,4 +695,33 @@
 
     return PJ_SUCCESS;
+}
+
+
+/*
+ * Attach module specific data to the dialog. Application can also set 
+ * the value directly by accessing dlg->mod_data[module_id].
+ */
+PJ_DEF(pj_status_t) pjsip_dlg_set_mod_data( pjsip_dialog *dlg,
+					    int mod_id,
+					    void *data )
+{
+    PJ_ASSERT_RETURN(dlg, PJ_EINVAL);
+    PJ_ASSERT_RETURN(mod_id >= 0 && mod_id < PJSIP_MAX_MODULE,
+		     PJ_EINVAL);
+    dlg->mod_data[mod_id] = data;
+    return PJ_SUCCESS;
+}
+
+/**
+ * Get module specific data previously attached to the dialog. Application
+ * can also get value directly by accessing dlg->mod_data[module_id].
+ */
+PJ_DEF(void*) pjsip_dlg_get_mod_data( pjsip_dialog *dlg,
+				      int mod_id)
+{
+    PJ_ASSERT_RETURN(dlg, NULL);
+    PJ_ASSERT_RETURN(mod_id >= 0 && mod_id < PJSIP_MAX_MODULE,
+		     NULL);
+    return dlg->mod_data[mod_id];
 }
 
@@ -814,6 +863,6 @@
 	      pjsip_tx_data_get_info(tdata)));
 
-    /* Update CSeq */
-    pj_mutex_lock(dlg->mutex);
+    /* Lock and increment session */
+    pjsip_dlg_inc_lock(dlg);
 
     /* Update dialog's CSeq and message's CSeq if request is not
@@ -870,12 +919,12 @@
     }
 
-    /* Unlock dialog. */
-    pj_mutex_unlock(dlg->mutex);
+    /* Unlock dialog, may destroy dialog. */
+    pjsip_dlg_dec_lock(dlg);
 
     return PJ_SUCCESS;
 
 on_error:
-    /* Unlock dialog. */
-    pj_mutex_unlock(dlg->mutex);
+    /* Unlock dialog, may destroy dialog. */
+    pjsip_dlg_dec_lock(dlg);
    
     /* Whatever happen delete the message. */
@@ -1004,5 +1053,6 @@
     PJ_ASSERT_RETURN(st_code >= 100 && st_code <= 699, PJ_EINVAL);
 
-    pj_mutex_lock(dlg->mutex);
+    /* Lock and increment session */
+    pjsip_dlg_inc_lock(dlg);
 
     /* Replace status code and reason */
@@ -1023,5 +1073,6 @@
     pjsip_tx_data_invalidate_msg(tdata);
 
-    pj_mutex_unlock(dlg->mutex);
+    /* Unlock dialog and dec session, may destroy dialog. */
+    pjsip_dlg_dec_lock(dlg);
 
     return PJ_SUCCESS;
@@ -1104,6 +1155,6 @@
 	      pjsip_rx_data_get_info(rdata)));
 
-    /* Lock the dialog. */
-    pj_mutex_lock(dlg->mutex);
+    /* Lock dialog and increment session. */
+    pjsip_dlg_inc_lock(dlg);
 
     /* Check CSeq */
@@ -1115,8 +1166,13 @@
 	 * Respond statelessly with 500 (Internal Server Error)
 	 */
-	pj_mutex_unlock(dlg->mutex);
+	pj_str_t warn_text;
+
+	/* Unlock dialog and dec session, may destroy dialog. */
+	pjsip_dlg_dec_lock(dlg);
+
 	pj_assert(pjsip_rdata_get_tsx(rdata) == NULL);
+	warn_text = pj_str("Invalid CSeq");
 	pjsip_endpt_respond_stateless(dlg->endpt,
-				      rdata, 500, NULL, NULL, NULL);
+				      rdata, 500, &warn_text, NULL, NULL);
 	return;
     }
@@ -1124,4 +1180,14 @@
     /* Update CSeq. */
     dlg->remote.cseq = rdata->msg_info.cseq->cseq;
+
+    /* Update To tag if necessary.
+     * This only happens if UAS sends a new request before answering
+     * our request (e.g. UAS sends NOTIFY before answering our
+     * SUBSCRIBE request).
+     */
+    if (dlg->remote.info->tag.slen == 0) {
+	pj_strdup(dlg->pool, &dlg->remote.info->tag,
+		  &rdata->msg_info.from->tag);
+    }
 
     /* Create UAS transaction for this request. */
@@ -1157,6 +1223,6 @@
 
 on_return:
-    /* Unlock dialog. */
-    pj_mutex_unlock(dlg->mutex);
+    /* Unlock dialog and dec session, may destroy dialog. */
+    pjsip_dlg_dec_lock(dlg);
 }
 
@@ -1172,6 +1238,6 @@
 	      pjsip_rx_data_get_info(rdata)));
 
-    /* Lock the dialog. */
-    pj_mutex_lock(dlg->mutex);
+    /* Lock the dialog and inc session. */
+    pjsip_dlg_inc_lock(dlg);
 
     /* Check that rdata already has dialog in mod_data. */
@@ -1265,6 +1331,6 @@
     }
 
-    /* Unlock dialog. */
-    pj_mutex_unlock(dlg->mutex);
+    /* Unlock dialog and dec session, may destroy dialog. */
+    pjsip_dlg_dec_lock(dlg);
 }
 
@@ -1281,12 +1347,6 @@
 	      tsx->obj_name, pjsip_tsx_state_str(tsx->state)));
 
-    /* Lock the dialog. */
-    pj_mutex_lock(dlg->mutex);
-
-    if (tsx->state == PJSIP_TSX_STATE_TERMINATED)
-	--dlg->tsx_count;
-
-    /* Increment session to prevent usages from destroying dialog. */
-    ++dlg->sess_count;
+    /* Lock the dialog and increment session. */
+    pjsip_dlg_inc_lock(dlg);
 
     /* Pass to dialog usages. */
@@ -1299,20 +1359,12 @@
     }
 
-    /* Decrement temporary session. */
-    --dlg->sess_count;
-
-    if (tsx->state == PJSIP_TSX_STATE_TERMINATED && dlg->tsx_count == 0 && 
-	dlg->sess_count == 0) 
-    {
-	/* Unregister this dialog from the transaction. */
+
+    if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
+	--dlg->tsx_count;
 	tsx->mod_data[dlg->ua->id] = NULL;
-
-	/* Time to destroy dialog. */
-	unregister_and_destroy_dialog(dlg);
-
-    } else {
-	/* Unlock dialog. */
-	pj_mutex_unlock(dlg->mutex);
-    }
-}
-
+    }
+
+    /* Unlock dialog and dec session, may destroy dialog. */
+    pjsip_dlg_dec_lock(dlg);
+}
+
