Index: pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 2879)
+++ pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 2951)
@@ -109,4 +109,8 @@
 				   const pjmedia_sdp_session *local_sdp);
 
+static pj_status_t handle_timer_response(pjsip_inv_session *inv,
+				         const pjsip_rx_data *rdata,
+				         pj_bool_t end_sess_on_failure);
+
 static void (*inv_state_handler[])( pjsip_inv_session *inv, pjsip_event *e) = 
 {
@@ -478,4 +482,27 @@
 }
 
+/* This function will process Session Timer headers in received 
+ * 2xx or 422 response of INVITE/UPDATE request.
+ */
+static pj_status_t handle_timer_response(pjsip_inv_session *inv,
+				         const pjsip_rx_data *rdata,
+					 pj_bool_t end_sess_on_failure)
+{
+    pjsip_status_code st_code;
+    pj_status_t status;
+
+    status = pjsip_timer_process_resp(inv, rdata, &st_code);
+    if (status != PJ_SUCCESS && end_sess_on_failure) {
+	pjsip_tx_data *tdata;
+	pj_status_t status2;
+
+	status2 = pjsip_inv_end_session(inv, st_code, NULL, &tdata);
+	if (tdata && status2 == PJ_SUCCESS)
+	    pjsip_inv_send_msg(inv, tdata);
+    }
+
+    return status;
+}
+
 /*
  * Module on_rx_response().
@@ -491,6 +518,4 @@
     pjsip_inv_session *inv;
     pjsip_msg *msg = rdata->msg_info.msg;
-    pj_status_t status;
-    pjsip_status_code st_code;
 
     dlg = pjsip_rdata_get_dlg(rdata);
@@ -518,20 +543,4 @@
 	return PJ_TRUE;
 
-    }
-
-    /* Pass response to timer session module */
-    status = pjsip_timer_process_resp(inv, rdata, &st_code);
-    if (status != PJ_SUCCESS) {
-	pjsip_event e;
-	pjsip_tx_data *tdata;
-
-	PJSIP_EVENT_INIT_RX_MSG(e, rdata);
-	inv_send_ack(inv, &e);
-
-	status = pjsip_inv_end_session(inv, st_code, NULL, &tdata);
-	if (tdata && status == PJ_SUCCESS)
-	    pjsip_inv_send_msg(inv, tdata);
-
-	return PJ_TRUE;
     }
 
@@ -2775,6 +2784,6 @@
     /* Handle 401/407 challenge. */
     if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&
-	(tsx->status_code == 401 || tsx->status_code == 407)) {
-
+	(tsx->status_code == 401 || tsx->status_code == 407))
+    {
 	pjsip_tx_data *tdata;
 	
@@ -2799,15 +2808,28 @@
 	    status = pjsip_inv_send_msg(inv, tdata);
 	}
+    }
+
+    /* Process 422 response */
+    else if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&
+	     tsx->status_code == 422)
+    {
+	status = handle_timer_response(inv, e->body.tsx_state.src.rdata,
+				       PJ_FALSE);
+    }
 
     /* Process 2xx response */
-    } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&
+    else if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&
 	tsx->status_code/100 == 2 &&
 	e->body.tsx_state.src.rdata->msg_info.msg->body)
     {
+	status = handle_timer_response(inv, e->body.tsx_state.src.rdata,
+				       PJ_FALSE);
 	status = inv_check_sdp_in_incoming_msg(inv, tsx, 
-					    e->body.tsx_state.src.rdata);
-
-    } else {
-	/* Get/attach invite session's transaction data */
+					     e->body.tsx_state.src.rdata);
+    }
+    
+    /* Get/attach invite session's transaction data */
+    else 
+    {
 	tsx_inv_data = (struct tsx_inv_data*)tsx->mod_data[mod_inv.mod.id];
 	if (tsx_inv_data == NULL) {
@@ -2975,4 +2997,5 @@
  *  - resend request on 401 or 407 response.
  *  - terminate dialog on 408 and 481 response.
+ *  - resend request on 422 response.
  */
 static pj_bool_t handle_uac_tsx_response(pjsip_inv_session *inv, 
@@ -3055,4 +3078,14 @@
 
 	return PJ_TRUE;	/* Handled */
+    }
+
+    /* Handle session timer 422 response. */
+    else if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&
+	     tsx->status_code == PJSIP_SC_SESSION_TIMER_TOO_SMALL) 
+    {
+	handle_timer_response(inv, e->body.tsx_state.src.rdata, 
+			      PJ_FALSE);
+
+	return PJ_TRUE;	/* Handled */
 
     } else {
@@ -3142,4 +3175,13 @@
 	}
 
+    } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&
+	       tsx->status_code == PJSIP_SC_SESSION_TIMER_TOO_SMALL) 
+    {
+	/* Handle session timer 422 response:
+	 * Resend the request with requested session timer setting.
+	 */
+	status = handle_timer_response(inv, e->body.tsx_state.src.rdata,
+				       PJ_TRUE);
+
     } else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 600)) {
 	/* Global error */
@@ -3213,9 +3255,17 @@
 	case PJSIP_TSX_STATE_COMPLETED:
 	    if (tsx->status_code/100 == 2) {
-		
+
 		/* This should not happen.
 		 * When transaction receives 2xx, it should be terminated
 		 */
 		pj_assert(0);
+
+		/* Process session timer response. */
+		status = handle_timer_response(inv,
+					       e->body.tsx_state.src.rdata,
+					       PJ_TRUE);
+		if (status != PJ_SUCCESS)
+		    break;
+
 		inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e);
     
@@ -3235,4 +3285,11 @@
 	    if (tsx->status_code/100 == 2) {
 		/* This must be receipt of 2xx response */
+
+		/* Process session timer response. */
+		status = handle_timer_response(inv,
+					       e->body.tsx_state.src.rdata,
+					       PJ_TRUE);
+		if (status != PJ_SUCCESS)
+		    break;
 
 		/* Set state to CONNECTING */
@@ -3387,4 +3444,13 @@
 		inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e);
 		if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
+		    pj_status_t status;
+
+		    /* Process session timer response. */
+		    status = handle_timer_response(inv, 
+						   e->body.tsx_state.src.rdata,
+						   PJ_TRUE);
+		    if (status != PJ_SUCCESS)
+			break;
+
 		    inv_check_sdp_in_incoming_msg(inv, tsx, 
 						  e->body.tsx_state.src.rdata);
@@ -3418,4 +3484,13 @@
 
 		if (e->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
+		    pj_status_t status;
+		    
+		    /* Process session timer response. */
+		    status = handle_timer_response(inv, 
+						   e->body.tsx_state.src.rdata,
+						   PJ_TRUE);
+		    if (status != PJ_SUCCESS)
+			break;
+
 		    inv_check_sdp_in_incoming_msg(inv, tsx, 
 						  e->body.tsx_state.src.rdata);
@@ -3886,6 +3961,14 @@
 		   tsx->status_code/100 == 2) 
 	{
+	    pj_status_t status;
 
 	    /* Re-INVITE was accepted. */
+
+	    /* Process session timer response. */
+	    status = handle_timer_response(inv, 
+					   e->body.tsx_state.src.rdata,
+					   PJ_TRUE);
+	    if (status != PJ_SUCCESS)
+		return;
 
 	    /* Process SDP */
@@ -3946,5 +4029,5 @@
     } else if (tsx->role == PJSIP_ROLE_UAC) {
 	/*
-	 * Handle 401/407/408/481 response
+	 * Handle 401/407/408/481/422 response
 	 */
 	handle_uac_tsx_response(inv, e);
@@ -3993,5 +4076,5 @@
     } else if (tsx->role == PJSIP_ROLE_UAC) {
 	/*
-	 * Handle 401/407/408/481 response
+	 * Handle 401/407/408/481/422 response
 	 */
 	handle_uac_tsx_response(inv, e);
