Index: /pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h	(revision 499)
+++ /pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h	(revision 500)
@@ -167,8 +167,9 @@
 struct pjsip_inv_session
 {
-    char		 obj_name[PJ_MAX_OBJ_NAME]; /**< Log identification. */
+    char		 obj_name[PJ_MAX_OBJ_NAME]; /**< Log identification */
     pj_pool_t		*pool;			    /**< Dialog's pool.	    */
     pjsip_inv_state	 state;			    /**< Invite sess state. */
     pjsip_status_code	 cause;			    /**< Disconnect cause.  */
+    pj_str_t		 cause_text;		    /**< Cause text.	    */
     pj_bool_t		 notify;		    /**< Internal.	    */
     pjsip_dialog	*dlg;			    /**< Underlying dialog. */
Index: /pjproject/trunk/pjsip/include/pjsip/sip_transaction.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip/sip_transaction.h	(revision 499)
+++ /pjproject/trunk/pjsip/include/pjsip/sip_transaction.h	(revision 500)
@@ -83,4 +83,5 @@
      */
     int				status_code;    /**< Last status code seen. */
+    pj_str_t			status_text;	/**< Last reason phrase.    */
     pjsip_tsx_state_e		state;          /**< State.                 */
     int				handle_200resp; /**< UAS 200/INVITE  retrsm.*/
Index: /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 499)
+++ /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 500)
@@ -159,4 +159,23 @@
 
 /*
+ * Set cause code.
+ */
+void inv_set_cause(pjsip_inv_session *inv, int cause_code,
+		   const pj_str_t *cause_text)
+{
+    if (cause_code > inv->cause) {
+	inv->cause = cause_code;
+	if (cause_text)
+	    pj_strdup(inv->pool, &inv->cause_text, cause_text);
+	else if (cause_code/100 == 2)
+	    inv->cause_text = pj_str("Normal call clearing");
+	else
+	    inv->cause_text = *pjsip_get_status_text(cause_code);
+    }
+}
+
+
+
+/*
  * Send ACK for 2xx response.
  */
@@ -899,5 +918,5 @@
 
     /* Set cause. */
-    inv->cause = st_code;
+    inv_set_cause(inv, st_code, NULL);
 
     /* Forcefully terminate the session if state is not DISCONNECTED */
@@ -1388,5 +1407,5 @@
 
     /* Set cause code. */
-    if (inv->cause==0) inv->cause = st_code;
+    inv_set_cause(inv, st_code, st_text);
 
     /* Create appropriate message. */
@@ -1698,5 +1717,5 @@
 
     if (inv->state != PJSIP_INV_STATE_DISCONNECTED) {
-	if (inv->cause==0) inv->cause=PJSIP_SC_OK;
+	inv_set_cause(inv, PJSIP_SC_OK, NULL);
 	inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
     }
@@ -1714,5 +1733,5 @@
     
     if (e->body.tsx_state.type != PJSIP_EVENT_RX_MSG) {
-	if (inv->cause==0) inv->cause=PJSIP_SC_OK;
+	inv_set_cause(inv, PJSIP_SC_OK, NULL);
 	inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	return;
@@ -1734,5 +1753,5 @@
 	     * End the session anyway.
 	     */
-	    if (inv->cause==0) inv->cause=PJSIP_SC_OK;
+	    inv_set_cause(inv, PJSIP_SC_OK, NULL);
 	    inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	    
@@ -1745,5 +1764,5 @@
 
 	/* End the session. */
-	if (inv->cause==0) inv->cause=PJSIP_SC_OK;
+	inv_set_cause(inv, PJSIP_SC_OK, NULL);
 	inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
     }
@@ -1863,5 +1882,5 @@
 		     * End the session.
 		     */
-		    if (inv->cause==0) inv->cause = tsx->status_code;
+		    inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 		    inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 
@@ -1878,5 +1897,5 @@
 	    } else {
 
-		if (inv->cause==0) inv->cause = tsx->status_code;
+		inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 		inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 
@@ -1906,5 +1925,5 @@
 
 	    } else  {
-		if (inv->cause==0) inv->cause = tsx->status_code;
+		inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 		inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	    }
@@ -1927,7 +1946,7 @@
 	    tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT ||
 	    tsx->status_code == PJSIP_SC_TSX_TIMEOUT ||
-	    PJSIP_SC_TSX_TRANSPORT_ERROR)
+	    tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR)
 	{
-	    if (inv->cause==0) inv->cause = tsx->status_code;
+	    inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 	    inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	}
@@ -1973,5 +1992,5 @@
 		inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e);
 	    } else {
-		if (inv->cause==0) inv->cause = tsx->status_code;
+		inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 		inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	    }
@@ -1983,5 +2002,5 @@
 	     * response)
 	     */
-	    if (inv->cause==0) inv->cause = tsx->status_code;
+	    inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 	    inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	    break;
@@ -2045,5 +2064,5 @@
 
 	    } else {
-		if (inv->cause==0) inv->cause = tsx->status_code;
+		inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 		inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	    }
@@ -2079,5 +2098,5 @@
 
 	    } else  {
-		if (inv->cause==0) inv->cause = tsx->status_code;
+		inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 		inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	    }
@@ -2113,7 +2132,7 @@
 	    tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT ||
 	    tsx->status_code == PJSIP_SC_TSX_TIMEOUT ||
-	    PJSIP_SC_TSX_TRANSPORT_ERROR)
+	    tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR)
 	{
-	    if (inv->cause==0) inv->cause = tsx->status_code;
+	    inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 	    inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	}
@@ -2149,5 +2168,5 @@
 	     */
 	    if (tsx->status_code/100 != 2) {
-		if (inv->cause==0) inv->cause = tsx->status_code;
+		inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 		inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	    }
@@ -2341,5 +2360,5 @@
 	     * Handle responses that terminates dialog.
 	     */
-	    if (inv->cause==0) inv->cause = tsx->status_code;
+	    inv_set_cause(inv, tsx->status_code, &tsx->status_text);
 	    inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e);
 	}
Index: /pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 499)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 500)
@@ -1327,4 +1327,18 @@
 
 /*
+ * Set transaction status code and reason.
+ */
+static tsx_set_status_code(pjsip_transaction *tsx,
+			   int code, const pj_str_t *reason)
+{
+    tsx->status_code = code;
+    if (reason)
+	pj_strdup(tsx->pool, &tsx->status_text, reason);
+    else
+	tsx->status_text = *pjsip_get_status_text(code);
+}
+
+
+/*
  * Forcely terminate transaction.
  */
@@ -1342,5 +1356,5 @@
 
     lock_tsx(tsx, &lck);
-    tsx->status_code = code;
+    tsx_set_status_code(tsx, code, NULL);
     tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, PJSIP_EVENT_USER, NULL);
     unlock_tsx(tsx, &lck);
@@ -1492,11 +1506,14 @@
 	if (!*cont) {
 	    char errmsg[PJ_ERR_MSG_SIZE];
+	    pj_str_t err;
 
 	    tsx->transport_err = -sent;
+
+	    err =pj_strerror(-sent, errmsg, sizeof(errmsg));
 
 	    PJ_LOG(4,(tsx->obj_name, 
 		      "Failed to send %s! err=%d (%s)",
 		      pjsip_tx_data_get_info(send_state->tdata), -sent,
-		      pj_strerror(-sent, errmsg, sizeof(errmsg)).ptr));
+		      errmsg));
 
 	    /* Clear pending transport flag. */
@@ -1507,5 +1524,5 @@
 
 	    /* Terminate transaction, if it's not already terminated. */
-	    tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR;
+	    tsx_set_status_code(tsx, PJSIP_SC_TSX_TRANSPORT_ERROR, &err);
 	    if (tsx->state != PJSIP_TSX_STATE_TERMINATED &&
 		tsx->state != PJSIP_TSX_STATE_DESTROYED)
@@ -1538,10 +1555,12 @@
 	struct tsx_lock_data lck;
 	char errmsg[PJ_ERR_MSG_SIZE];
+	pj_str_t err;
 
 	tsx->transport_err = -sent;
 
+	err = pj_strerror(-sent, errmsg, sizeof(errmsg));
+
 	PJ_LOG(4,(tsx->obj_name, "Transport failed to send %s! Err=%d (%s)",
-		  pjsip_tx_data_get_info(tdata), -sent,
-		  pj_strerror(-sent, errmsg, sizeof(errmsg)).ptr));
+		  pjsip_tx_data_get_info(tdata), -sent, errmsg));
 
 	lock_tsx(tsx, &lck);
@@ -1552,5 +1571,5 @@
 
 	/* Terminate transaction. */
-	tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR;
+	tsx_set_status_code(tsx, PJSIP_SC_TSX_TRANSPORT_ERROR, &err);
 	tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 
 		       PJSIP_EVENT_TRANSPORT_ERROR, tdata );
@@ -1622,4 +1641,5 @@
 	
 	char errmsg[PJ_ERR_MSG_SIZE];
+	pj_str_t err;
 
 	if (status == PJ_SUCCESS) {
@@ -1631,11 +1651,12 @@
 	 * Treat this as permanent transport error.
 	 */
+	err = pj_strerror(status, errmsg, sizeof(errmsg));
+
 	PJ_LOG(4,(tsx->obj_name, 
 		  "Transport error, terminating transaction. "
 		  "Err=%d (%s)",
-		  status, 
-		  pj_strerror(status, errmsg, sizeof(errmsg)).ptr));
-
-	tsx->status_code = PJSIP_SC_TSX_TRANSPORT_ERROR;
+		  status, errmsg));
+
+	tsx_set_status_code(tsx, PJSIP_SC_TSX_TRANSPORT_ERROR, &err);
 	tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 
 		       PJSIP_EVENT_TRANSPORT_ERROR, NULL );
@@ -1860,5 +1881,5 @@
 
 	/* Set status code */
-	tsx->status_code = PJSIP_SC_TSX_TIMEOUT;
+	tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL);
 
 	/* Inform TU. */
@@ -2002,5 +2023,6 @@
 
 	/* Update last status */
-	tsx->status_code = msg->line.status.code;
+	tsx_set_status_code(tsx, msg->line.status.code, 
+			    &msg->line.status.reason);
 
 	/* Discard the saved last response (it will be updated later as
@@ -2164,5 +2186,5 @@
 	pj_assert(!"Should not happen(?)");
 
-	tsx->status_code = PJSIP_SC_TSX_TIMEOUT;
+	tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL);
 
 	tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 
@@ -2211,7 +2233,9 @@
 	}
 
-	tsx->status_code = msg->line.status.code;
+	tsx_set_status_code(tsx, msg->line.status.code, 
+			    &msg->line.status.reason);
+
     } else {
-	tsx->status_code = PJSIP_SC_TSX_TIMEOUT;
+	tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL);
     }
 
@@ -2441,5 +2465,5 @@
 		 */
 
-		tsx->status_code = PJSIP_SC_TSX_TIMEOUT;
+		tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL);
 
 		tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 
