Index: pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 1417)
+++ pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 1463)
@@ -18,4 +18,5 @@
  */
 #include <pjsip-ua/sip_inv.h>
+#include <pjsip-ua/sip_100rel.h>
 #include <pjsip/sip_module.h>
 #include <pjsip/sip_endpoint.h>
@@ -32,5 +33,5 @@
 
 
-#define THIS_FILE	"sip_invite_session.c"
+#define THIS_FILE	"sip_inv.c"
 
 static const char *inv_state_names[] =
@@ -306,4 +307,8 @@
 				inv->invite_tsx->status_code);
 	    inv->invite_tsx = NULL;
+	    if (inv->last_answer) {
+		    pjsip_tx_data_dec_ref(inv->last_answer);
+		    inv->last_answer = NULL;
+	    }
 	}
 
@@ -396,6 +401,11 @@
      * value as the INVITE (see http://www.pjsip.org/trac/ticket/113)
      */
-    if (tsx->state>=PJSIP_TSX_STATE_CONFIRMED && tsx == inv->invite_tsx)
+    if (tsx->state>=PJSIP_TSX_STATE_CONFIRMED && tsx == inv->invite_tsx) {
         inv->invite_tsx = NULL;
+	if (inv->last_answer) {
+		pjsip_tx_data_dec_ref(inv->last_answer);
+		inv->last_answer = NULL;
+	}
+    }
 }
 
@@ -482,4 +492,12 @@
     if (options & PJSIP_INV_REQUIRE_100REL)
 	options |= PJSIP_INV_SUPPORT_100REL;
+
+#if !PJSIP_HAS_100REL
+    /* options cannot specify 100rel if 100rel is disabled */
+    PJ_ASSERT_RETURN(
+	(options & (PJSIP_INV_REQUIRE_100REL | PJSIP_INV_SUPPORT_100REL))==0,
+	PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION));
+    
+#endif
 
     if (options & PJSIP_INV_REQUIRE_TIMER)
@@ -520,4 +538,9 @@
     /* Increment dialog session */
     pjsip_dlg_inc_session(dlg, &mod_inv.mod);
+
+#if PJSIP_HAS_100REL
+    /* Create 100rel handler */
+    pjsip_100rel_attach(inv);
+#endif
 
     /* Done */
@@ -830,4 +853,16 @@
     }
 
+    /* If remote Require something that we support, make us Require
+     * that feature too.
+     */
+    if (rem_option & PJSIP_INV_REQUIRE_100REL) {
+	    pj_assert(*options & PJSIP_INV_SUPPORT_100REL);
+	    *options |= PJSIP_INV_REQUIRE_100REL;
+    }
+    if (rem_option & PJSIP_INV_REQUIRE_TIMER) {
+	    pj_assert(*options & PJSIP_INV_SUPPORT_TIMER);
+	    *options |= PJSIP_INV_REQUIRE_TIMER;
+    }
+
 on_return:
 
@@ -908,4 +943,12 @@
     if (options & PJSIP_INV_REQUIRE_100REL)
 	options |= PJSIP_INV_SUPPORT_100REL;
+
+#if !PJSIP_HAS_100REL
+    /* options cannot specify 100rel if 100rel is disabled */
+    PJ_ASSERT_RETURN(
+	(options & (PJSIP_INV_REQUIRE_100REL | PJSIP_INV_SUPPORT_100REL))==0,
+	PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EXTENSION));
+    
+#endif
 
     if (options & PJSIP_INV_REQUIRE_TIMER)
@@ -978,4 +1021,11 @@
     inv->invite_tsx->mod_data[mod_inv.mod.id] = tsx_inv_data;
 
+#if PJSIP_HAS_100REL
+    /* Create 100rel handler */
+    if (inv->options & PJSIP_INV_REQUIRE_100REL) {
+	    pjsip_100rel_attach(inv);
+    }
+#endif
+
     /* Done */
     pjsip_dlg_dec_lock(dlg);
@@ -1169,5 +1219,13 @@
 
     /* Add Require header. */
-    PJ_TODO(INVITE_ADD_REQUIRE_HEADER);
+    if (inv->options & PJSIP_INV_REQUIRE_100REL) {
+	    const pj_str_t HREQ = { "Require", 7 };
+	    const pj_str_t tag_100rel = { "100rel", 6 };
+	    pjsip_generic_string_hdr *hreq;
+
+	    hreq = pjsip_generic_string_hdr_create(tdata->pool, &HREQ, 
+						   &tag_100rel);
+	    pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*) hreq);
+    }
 
     /* Done. */
@@ -1453,4 +1511,10 @@
     }
 
+    /* Save this answer */
+    inv->last_answer = tdata;
+    pjsip_tx_data_add_ref(inv->last_answer);
+    PJ_LOG(5,(inv->dlg->obj_name, "Initial answer %s",
+	      pjsip_tx_data_get_info(inv->last_answer)));
+
     *p_tdata = tdata;
 
@@ -1480,15 +1544,19 @@
     PJ_ASSERT_RETURN(inv->invite_tsx, PJ_EBUG);
 
-    /* INVITE transaction MUST have transmitted a response (e.g. 100) */
-    PJ_ASSERT_RETURN(inv->invite_tsx->last_tx, PJ_EINVALIDOP);
+    /* Must have created an answer before */
+    PJ_ASSERT_RETURN(inv->last_answer, PJ_EINVALIDOP);
 
     pjsip_dlg_inc_lock(inv->dlg);
 
     /* Modify last response. */
-    last_res = inv->invite_tsx->last_tx;
+    last_res = inv->last_answer;
     status = pjsip_dlg_modify_response(inv->dlg, last_res, st_code, st_text);
     if (status != PJ_SUCCESS)
 	goto on_return;
 
+    /* For non-2xx final response, strip message body */
+    if (st_code >= 300) {
+	last_res->msg->body = NULL;
+    }
 
     /* Process SDP in answer */
@@ -1765,5 +1833,13 @@
 			 PJ_EINVALIDOP);
 
-	status = pjsip_dlg_send_response(inv->dlg, inv->invite_tsx, tdata);
+#if PJSIP_HAS_100REL
+	if (inv->options & PJSIP_INV_REQUIRE_100REL) {
+		status = pjsip_100rel_tx_response(inv, tdata);
+	} else 
+#endif
+	{
+		status = pjsip_dlg_send_response(inv->dlg, inv->invite_tsx, tdata);
+	}
+
 	if (status != PJ_SUCCESS)
 	    return status;
@@ -2043,4 +2119,8 @@
 		    inv->state = PJSIP_INV_STATE_NULL;
 		    inv->invite_tsx = NULL;
+		    if (inv->last_answer) {
+			pjsip_tx_data_dec_ref(inv->last_answer);
+			inv->last_answer = NULL;
+		    }
 
 		    /* Send the request. */
