Index: pjproject/trunk/pjsip/src/pjsip-simple/evsub.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip-simple/evsub.c	(revision 201)
+++ pjproject/trunk/pjsip/src/pjsip-simple/evsub.c	(revision 212)
@@ -198,4 +198,5 @@
     pjsip_dialog	 *dlg;		/**< Underlying dialog.		    */
     struct evpkg	 *pkg;		/**< The event package.		    */
+    unsigned		  option;	/**< Options.			    */
     pjsip_evsub_user	  user;		/**< Callback.			    */
     pjsip_role_e	  role;		/**< UAC=subscriber, UAS=notifier   */
@@ -236,4 +237,5 @@
 static const pj_str_t STR_TIMEOUT    = { "timeout", 7};
 
+
 /*
  * On unload module.
@@ -246,4 +248,10 @@
     return PJ_SUCCESS;
 }
+
+/* Proto for pjsipsimple_strerror().
+ * Defined in errno.c
+ */
+PJ_DECL(pj_str_t) pjsipsimple_strerror( pj_status_t statcode, 
+				        char *buf, pj_size_t bufsize );
 
 /*
@@ -257,4 +265,7 @@
 	{ "NOTIFY", 6}
     };
+
+    pj_register_strerror(PJSIP_SIMPLE_ERRNO_START, PJ_ERRNO_SPACE_SIZE,
+			 &pjsipsimple_strerror);
 
     PJ_ASSERT_RETURN(endpt != NULL, PJ_EINVAL);
@@ -619,4 +630,5 @@
 				 const pjsip_evsub_user *user_cb,
 				 const pj_str_t *event,
+				 unsigned option,
 				 pjsip_evsub **p_evsub )
 {
@@ -641,4 +653,5 @@
     sub->pkg = pkg;
     sub->role = role;
+    sub->option = option;
     sub->state = PJSIP_EVSUB_STATE_NULL;
     sub->state_str = evsub_state_names[sub->state];
@@ -698,4 +711,5 @@
 					    const pjsip_evsub_user *user_cb,
 					    const pj_str_t *event,
+					    unsigned option,
 					    pjsip_evsub **p_evsub)
 {
@@ -706,10 +720,14 @@
 
     pjsip_dlg_inc_lock(dlg);
-    status = evsub_create(dlg, PJSIP_UAC_ROLE, user_cb, event, &sub);
+    status = evsub_create(dlg, PJSIP_UAC_ROLE, user_cb, event, option, &sub);
     if (status != PJ_SUCCESS)
 	goto on_return;
 
-    /* Add unique Id to Event header */
-    pj_create_unique_string(sub->pool, &sub->event->id_param);
+    /* Add unique Id to Event header, only when PJSIP_EVSUB_NO_EVENT_ID
+     * is not specified.
+     */
+    if ((option & PJSIP_EVSUB_NO_EVENT_ID) == 0) {
+	pj_create_unique_string(sub->pool, &sub->event->id_param);
+    }
 
     /* Increment dlg session. */
@@ -731,4 +749,5 @@
 					    const pjsip_evsub_user *user_cb,
 					    pjsip_rx_data *rdata,
+					    unsigned option,
 					    pjsip_evsub **p_evsub)
 {
@@ -758,6 +777,7 @@
     PJ_ASSERT_RETURN(user_cb->on_rx_refresh, PJ_EINVALIDOP);
 
-    /* Request MUST have "Event" header: */
-
+    /* Request MUST have "Event" header. We need the Event header to get 
+     * the package name (don't want to add more arguments in the function).
+     */
     event_hdr = (pjsip_event_hdr*) 
 	pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &STR_EVENT, NULL);
@@ -773,5 +793,5 @@
 
     status = evsub_create(dlg, PJSIP_UAS_ROLE, user_cb, 
-			  &event_hdr->event_type, &sub);
+			  &event_hdr->event_type, option, &sub);
     if (status != PJ_SUCCESS)
 	goto on_return;
@@ -1148,4 +1168,5 @@
     }
 
+
     switch (event->body.tsx_state.type) {
     case PJSIP_EVENT_RX_MSG:
@@ -1164,5 +1185,9 @@
     
     if (!msg) {
-	pj_assert(!"First transaction event is not TX or RX!");
+	//Note:
+	// this transaction can be other transaction in the dialog.
+	// The assertion below probably only valid for dialog that
+	// only has one event subscription usage.
+	//pj_assert(!"First transaction event is not TX or RX!");
 	return NULL;
     }
@@ -1188,10 +1213,41 @@
     while (dlgsub != dlgsub_head) {
 
-	/* Match event type and Id */
-	if (pj_strcmp(&dlgsub->sub->event->id_param, &event_hdr->id_param)==0 &&
-	    pj_stricmp(&dlgsub->sub->event->event_type, &event_hdr->event_type)==0)
+	if (pj_stricmp(&dlgsub->sub->event->event_type, 
+		       &event_hdr->event_type)==0)
 	{
-	    break;
-	}
+	    /* Event type matched. 
+	     * Check if event ID matched too.
+	     */
+	    if (pj_strcmp(&dlgsub->sub->event->id_param, 
+			  &event_hdr->id_param)==0)
+	    {
+		
+		break;
+
+	    }
+	    /*
+	     * Otherwise if it is an UAC subscription, AND
+	     * PJSIP_EVSUB_NO_EVENT_ID flag is set, AND
+	     * the session's event id is NULL, AND
+	     * the incoming request is NOTIFY with event ID, then
+	     * we consider it as a match, and update the
+	     * session's event id.
+	     */
+	    else if (dlgsub->sub->role == PJSIP_ROLE_UAC &&
+		     (dlgsub->sub->option & PJSIP_EVSUB_NO_EVENT_ID)!=0 &&
+		     dlgsub->sub->event->id_param.slen==0 &&
+		     !pjsip_method_cmp(&tsx->method, &pjsip_notify_method))
+	    {
+		/* Update session's event id. */
+		pj_strdup(dlgsub->sub->pool, 
+			  &dlgsub->sub->event->id_param,
+			  &event_hdr->id_param);
+
+		break;
+	    }
+	}
+	
+
+
 	dlgsub = dlgsub->next;
     }
@@ -1201,4 +1257,6 @@
 	PJ_LOG(4,(THIS_FILE, 
 		  "Subscription not found for %.*s, event=%.*s;id=%.*s",
+		  (int)tsx->method.name.slen,
+		  tsx->method.name.ptr,
 		  (int)event_hdr->event_type.slen,
 		  event_hdr->event_type.ptr,
@@ -1738,5 +1796,16 @@
 		set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL);
 	    }
-	} 
+
+	}
+	/*
+	 * Terminate event usage if we receive 481, 408, and 7 class
+	 * responses.
+	 */
+	if (sub->state != PJSIP_EVSUB_STATE_TERMINATED &&
+	    (tsx->status_code==481 || tsx->status_code==408 ||
+	     tsx->status_code/100 == 7))
+	{
+	    set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, event);
+	}
 
     } else {
