Index: /pjproject/trunk/pjsip/src/pjsip/sip_dialog.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_dialog.c	(revision 131)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_dialog.c	(revision 132)
@@ -217,4 +217,5 @@
     pjsip_hdr *contact_hdr;
     pjsip_rr_hdr *rr;
+    pjsip_transaction *tsx = NULL;
     pjsip_dialog *dlg;
 
@@ -347,4 +348,15 @@
 	goto on_error;
 
+    /* Create UAS transaction for this request. */
+    status = pjsip_tsx_create_uas(dlg->ua, rdata, &tsx);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    /* Associate this dialog to the transaction. */
+    tsx->mod_data[dlg->ua->id] = dlg;
+
+    /* Increment tsx counter */
+    ++dlg->tsx_count;
+
     /* Calculate hash value of remote tag. */
     dlg->remote.tag_hval = pj_hash_calc(0, dlg->remote.info->tag.ptr, 
@@ -366,4 +378,9 @@
 
 on_error:
+    if (tsx) {
+	pjsip_tsx_terminate(tsx, 500);
+	--dlg->tsx_count;
+    }
+
     destroy_dialog(dlg);
     return status;
@@ -559,4 +576,5 @@
     pj_mutex_lock(dlg->mutex);
 
+    pj_assert(dlg->sess_count > 0);
     --dlg->sess_count;
 
@@ -734,13 +752,20 @@
 
 /*
- * Update CSeq in outgoing request to reflect the dialog.
- * Then increment local CSeq.
- */
-static void update_cseq( pjsip_dialog *dlg,
-			 pjsip_tx_data *tdata )
-{
+ * Send request statefully, and update dialog'c CSeq.
+ */
+PJ_DEF(pj_status_t) pjsip_dlg_send_request( pjsip_dialog *dlg,
+					    pjsip_tx_data *tdata,
+					    pjsip_transaction **p_tsx )
+{
+    pjsip_transaction *tsx;
     pjsip_msg *msg = tdata->msg;
-
-    /* Start locking the dialog. */
+    pj_status_t status;
+
+    /* Check arguments. */
+    PJ_ASSERT_RETURN(dlg && tdata && tdata->msg, PJ_EINVAL);
+    PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG,
+		     PJSIP_ENOTREQUESTMSG);
+
+    /* Update CSeq */
     pj_mutex_lock(dlg->mutex);
 
@@ -754,5 +779,5 @@
 	
 	ch = PJSIP_MSG_CSEQ_HDR(msg);
-	PJ_ASSERT_ON_FAIL(ch!=NULL, return);
+	PJ_ASSERT_RETURN(ch!=NULL, PJ_EBUG);
 
 	ch->cseq = dlg->local.cseq++;
@@ -762,48 +787,37 @@
     }
 
-}
-
-/*
- * Send request statefully, and update dialog'c CSeq.
- */
-PJ_DEF(pj_status_t) pjsip_dlg_send_request( pjsip_dialog *dlg,
-					    pjsip_tx_data *tdata,
-					    pjsip_transaction **p_tsx )
-{
-    pjsip_transaction *tsx;
-    pj_status_t status;
-
-    /* Check arguments. */
-    PJ_ASSERT_RETURN(dlg && tdata && tdata->msg, PJ_EINVAL);
-    PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG,
-		     PJSIP_ENOTREQUESTMSG);
-
-    /* Update CSeq */
-    update_cseq(dlg, tdata);
-
-    /* Create a new transaction. 
+    /* Create a new transaction if method is not ACK.
      * The transaction user is the user agent module.
      */
-    status = pjsip_tsx_create_uac(dlg->ua, tdata, &tsx);
-    if (status != PJ_SUCCESS)
-	goto on_error;
-
-    /* Attach this dialog to the transaction, so that user agent
-     * will dispatch events to this dialog.
-     */
-    tsx->mod_data[dlg->ua->id] = dlg;
-
-    /* Increment transaction counter. */
-    ++dlg->tsx_count;
-
-    /* Send the message. */
-    status = pjsip_tsx_send_msg(tsx, tdata);
-    if (status != PJ_SUCCESS) {
-	pjsip_tsx_terminate(tsx, tsx->status_code);
-	goto on_error;
-    }
-
-    /* Done. */
-    *p_tsx = tsx;
+    if (msg->line.req.method.id != PJSIP_ACK_METHOD) {
+	status = pjsip_tsx_create_uac(dlg->ua, tdata, &tsx);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+	/* Attach this dialog to the transaction, so that user agent
+	 * will dispatch events to this dialog.
+	 */
+	tsx->mod_data[dlg->ua->id] = dlg;
+
+	/* Increment transaction counter. */
+	++dlg->tsx_count;
+
+	/* Send the message. */
+	status = pjsip_tsx_send_msg(tsx, tdata);
+	if (status != PJ_SUCCESS) {
+	    pjsip_tsx_terminate(tsx, tsx->status_code);
+	    goto on_error;
+	}
+
+	*p_tsx = tsx;
+
+    } else {
+	status = pjsip_endpt_send_request_stateless(
+		    pjsip_ua_get_endpt(dlg->ua), tdata, NULL, NULL);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+	*p_tsx = NULL;
+    }
 
     /* Unlock dialog. */
@@ -994,4 +1008,35 @@
 
 
+/*
+ * Combo function to create and send response statefully.
+ */
+PJ_DEF(pj_status_t) pjsip_dlg_respond(  pjsip_dialog *dlg,
+					pjsip_rx_data *rdata,
+					int st_code,
+					const pj_str_t *st_text )
+{
+    pj_status_t status;
+    pjsip_tx_data *tdata;
+
+    /* Sanity check. */
+    PJ_ASSERT_RETURN(dlg && rdata && rdata->msg_info.msg, PJ_EINVAL);
+    PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,
+		     PJSIP_ENOTREQUESTMSG);
+
+    /* The transaction must belong to this dialog.  */
+    PJ_ASSERT_RETURN(pjsip_rdata_get_tsx(rdata) &&
+		     pjsip_rdata_get_tsx(rdata)->mod_data[dlg->ua->id] == dlg,
+		     PJ_EINVALIDOP);
+
+    /* Create the response. */
+    status = pjsip_dlg_create_response(dlg, rdata, st_code, st_text, &tdata);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* Send the response. */
+    return pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), tdata);
+}
+
+
 /* This function is called by user agent upon receiving incoming response
  * message.
@@ -1005,4 +1050,18 @@
     /* Lock the dialog. */
     pj_mutex_lock(dlg->mutex);
+
+    /* Check CSeq */
+    if (rdata->msg_info.cseq->cseq <= dlg->remote.cseq) {
+	/* Invalid CSeq.
+	 * Respond statelessly with 500 (Internal Server Error)
+	 */
+	pj_mutex_unlock(dlg->mutex);
+	pjsip_endpt_respond_stateless(pjsip_ua_get_endpt(dlg->ua),
+				      rdata, 500, NULL, NULL, NULL);
+	return;
+    }
+
+    /* Update CSeq. */
+    dlg->remote.cseq = rdata->msg_info.cseq->cseq;
 
     /* Create UAS transaction for this request. */
