Index: pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h	(revision 2868)
+++ pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h	(revision 2869)
@@ -319,9 +319,37 @@
 /**
  * This structure describes the invite session.
+ *
+ * Note regarding the invite session's pools. The inv_sess used to have
+ * only one pool, which is just a pointer to the dialog's pool. Ticket
+ * http://trac.pjsip.org/repos/ticket/877 has found that the memory
+ * usage will grow considerably everytime re-INVITE or UPDATE is
+ * performed.
+ *
+ * Ticket #877 then created two more memory pools for the inv_sess, so
+ * now we have three memory pools:
+ *  - pool: to be used to allocate long term data for the session
+ *  - pool_prov and pool_active: this is a flip-flop pools to be used
+ *     interchangably during re-INVITE and UPDATE. pool_prov is
+ *     "provisional" pool, used to allocate SDP offer or answer for
+ *     the re-INVITE and UPDATE. Once SDP negotiation is done, the
+ *     provisional pool will be made as the active pool, then the
+ *     existing active pool will be reset, to release the memory
+ *     back to the OS. So these pool's lifetime is synchronized to
+ *     the SDP offer-answer negotiation.
+ *
+ * Higher level application such as PJSUA-LIB has been modified to
+ * make use of these flip-flop pools, i.e. by creating media objects
+ * from the provisional pool rather than from the long term pool.
+ *
+ * Other applications that want to use these pools must understand
+ * that the flip-flop pool's lifetimes are synchronized to the
+ * SDP offer-answer negotiation.
  */
 struct pjsip_inv_session
 {
     char		 obj_name[PJ_MAX_OBJ_NAME]; /**< Log identification */
-    pj_pool_t		*pool;			    /**< Dialog's pool.	    */
+    pj_pool_t		*pool;			    /**< Long term pool.    */
+    pj_pool_t		*pool_prov;		    /**< Provisional pool   */
+    pj_pool_t		*pool_active;		    /**< Active/current pool*/
     pjsip_inv_state	 state;			    /**< Invite sess state. */
     pj_bool_t		 cancelling;		    /**< CANCEL requested   */
Index: pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 2868)
+++ pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 2869)
@@ -78,4 +78,7 @@
 };
 
+#define POOL_INIT_SIZE	256
+#define POOL_INC_SIZE	256
+
 /*
  * Static prototypes.
@@ -235,4 +238,8 @@
 	pjsip_timer_end_session(inv);
 	pjsip_dlg_dec_session(inv->dlg, &mod_inv.mod);
+
+	/* Release the flip-flop pools */
+	pj_pool_release(inv->pool_prov);
+	pj_pool_release(inv->pool_active);
     }
 }
@@ -670,4 +677,12 @@
     inv->cause = (pjsip_status_code) 0;
 
+    /* Create flip-flop pool (see ticket #877) */
+    /* (using inv->obj_name as temporary variable for pool names */
+    pj_ansi_snprintf(inv->obj_name, PJ_MAX_OBJ_NAME, "inv%p", dlg->pool);
+    inv->pool_prov = pjsip_endpt_create_pool(dlg->endpt, inv->obj_name,
+					     POOL_INIT_SIZE, POOL_INC_SIZE);
+    inv->pool_active = pjsip_endpt_create_pool(dlg->endpt, inv->obj_name,
+					       POOL_INIT_SIZE, POOL_INC_SIZE);
+
     /* Object name will use the same dialog pointer. */
     pj_ansi_snprintf(inv->obj_name, PJ_MAX_OBJ_NAME, "inv%p", dlg);
@@ -675,6 +690,6 @@
     /* Create negotiator if local_sdp is specified. */
     if (local_sdp) {
-	status = pjmedia_sdp_neg_create_w_local_offer(dlg->pool, local_sdp,
-						      &inv->neg);
+	status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, 
+						      local_sdp, &inv->neg);
 	if (status != PJ_SUCCESS) {
 	    pjsip_dlg_dec_lock(dlg);
@@ -1130,4 +1145,12 @@
     inv->cause = (pjsip_status_code) 0;
 
+    /* Create flip-flop pool (see ticket #877) */
+    /* (using inv->obj_name as temporary variable for pool names */
+    pj_ansi_snprintf(inv->obj_name, PJ_MAX_OBJ_NAME, "inv%p", dlg->pool);
+    inv->pool_prov = pjsip_endpt_create_pool(dlg->endpt, inv->obj_name,
+					     POOL_INIT_SIZE, POOL_INC_SIZE);
+    inv->pool_active = pjsip_endpt_create_pool(dlg->endpt, inv->obj_name,
+					       POOL_INIT_SIZE, POOL_INC_SIZE);
+
     /* Object name will use the same dialog pointer. */
     pj_ansi_snprintf(inv->obj_name, PJ_MAX_OBJ_NAME, "inv%p", dlg);
@@ -1151,10 +1174,11 @@
     /* Create negotiator. */
     if (rem_sdp) {
-	status = pjmedia_sdp_neg_create_w_remote_offer(inv->pool, local_sdp,
-						       rem_sdp, &inv->neg);
+	status = pjmedia_sdp_neg_create_w_remote_offer(inv->pool, 
+						       local_sdp, rem_sdp, 
+						       &inv->neg);
 						
     } else if (local_sdp) {
-	status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, local_sdp,
-						      &inv->neg);
+	status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, 
+						      local_sdp, &inv->neg);
     } else {
 	status = PJ_SUCCESS;
@@ -1440,4 +1464,12 @@
 
 
+/* Util: swap pool */
+static void swap_pool(pj_pool_t **p1, pj_pool_t **p2)
+{
+    pj_pool_t *tmp = *p1;
+    *p1 = *p2;
+    *p2 = tmp;
+}
+
 /*
  * Initiate SDP negotiation in the SDP negotiator.
@@ -1451,5 +1483,5 @@
 		     PJMEDIA_SDPNEG_EINSTATE);
 
-    status = pjmedia_sdp_neg_negotiate(inv->pool, inv->neg, 0);
+    status = pjmedia_sdp_neg_negotiate(inv->pool_prov, inv->neg, 0);
 
     PJ_LOG(5,(inv->obj_name, "SDP negotiation done, status=%d", status));
@@ -1457,4 +1489,8 @@
     if (mod_inv.cb.on_media_update && inv->notify)
 	(*mod_inv.cb.on_media_update)(inv, status);
+
+    /* Swap the flip-flop pool, and reset the new provisional pool */
+    swap_pool(&inv->pool_prov, &inv->pool_active);
+    pj_pool_reset(inv->pool_prov);
 
     return status;
@@ -1535,5 +1571,6 @@
 
 	    /* Feed the original offer to negotiator */
-	    status = pjmedia_sdp_neg_modify_local_offer(inv->pool, inv->neg,
+	    status = pjmedia_sdp_neg_modify_local_offer(inv->pool_prov, 
+							inv->neg,
 						        reoffer_sdp);
 	    if (status != PJ_SUCCESS) {
@@ -1581,8 +1618,8 @@
 
 	if (inv->neg == NULL) {
-	    status=pjmedia_sdp_neg_create_w_remote_offer(inv->pool, NULL, 
+	    status=pjmedia_sdp_neg_create_w_remote_offer(inv->pool, NULL,
 							 rem_sdp, &inv->neg);
 	} else {
-	    status=pjmedia_sdp_neg_set_remote_offer(inv->pool, inv->neg, 
+	    status=pjmedia_sdp_neg_set_remote_offer(inv->pool_prov, inv->neg, 
 						    rem_sdp);
 	}
@@ -1616,5 +1653,5 @@
 		  pjsip_rx_data_get_info(rdata)));
 
-	status = pjmedia_sdp_neg_set_remote_answer(inv->pool, inv->neg, 
+	status = pjmedia_sdp_neg_set_remote_answer(inv->pool_prov, inv->neg,
 						   rem_sdp);
 
@@ -1669,10 +1706,11 @@
 
 	if (inv->neg == NULL) {
-	    status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, local_sdp,
+	    status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, 
+							  local_sdp,
 							  &inv->neg);
 	} else if (pjmedia_sdp_neg_get_state(inv->neg)==
 		   PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER)
 	{
-	    status = pjmedia_sdp_neg_set_local_answer(inv->pool, inv->neg,
+	    status = pjmedia_sdp_neg_set_local_answer(inv->pool_prov, inv->neg,
 						      local_sdp);
 	} else {
@@ -1879,5 +1917,5 @@
 
     pjsip_dlg_inc_lock(inv->dlg);
-    status = pjmedia_sdp_neg_set_local_answer( inv->pool, inv->neg, sdp);
+    status = pjmedia_sdp_neg_set_local_answer( inv->pool_prov, inv->neg, sdp);
     pjsip_dlg_dec_lock(inv->dlg);
 
@@ -2228,5 +2266,6 @@
     if (new_offer) {
 	if (!inv->neg) {
-	    status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, new_offer,
+	    status = pjmedia_sdp_neg_create_w_local_offer(inv->pool, 
+							  new_offer,
 							  &inv->neg);
 	    if (status != PJ_SUCCESS)
@@ -2247,5 +2286,6 @@
 
 	    case PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER:
-		status = pjmedia_sdp_neg_set_local_answer(inv->pool, inv->neg,
+		status = pjmedia_sdp_neg_set_local_answer(inv->pool_prov, 
+							  inv->neg,
 							  new_offer);
 		if (status != PJ_SUCCESS)
@@ -2260,5 +2300,6 @@
 
 	    case PJMEDIA_SDP_NEG_STATE_DONE:
-		status = pjmedia_sdp_neg_modify_local_offer(inv->pool,inv->neg,
+		status = pjmedia_sdp_neg_modify_local_offer(inv->pool_prov,
+							    inv->neg,
 							    new_offer);
 		if (status != PJ_SUCCESS)
@@ -2316,5 +2357,5 @@
      * with correct SDP origin.
      */
-    status = pjmedia_sdp_neg_modify_local_offer(inv->pool,inv->neg,
+    status = pjmedia_sdp_neg_modify_local_offer(inv->pool_prov, inv->neg,
 						offer);
     if (status != PJ_SUCCESS)
@@ -3745,7 +3786,8 @@
 			 * fix the offer with correct SDP origin.
 			 */
-			status = pjmedia_sdp_neg_modify_local_offer(dlg->pool,
-								    inv->neg,
-								    sdp);
+			status = 
+			    pjmedia_sdp_neg_modify_local_offer(inv->pool_prov,
+							       inv->neg,
+							       sdp);
 
 			/* Retrieve the "fixed" offer from negotiator */
@@ -3760,5 +3802,5 @@
 		if (sdp == NULL) {
 		    const pjmedia_sdp_session *active_sdp = NULL;
-		    status = pjmedia_sdp_neg_send_local_offer(dlg->pool, 
+		    status = pjmedia_sdp_neg_send_local_offer(inv->pool_prov,
 							      inv->neg, 
 							      &active_sdp);
Index: pjproject/trunk/pjsip/src/pjsip-ua/sip_timer.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip-ua/sip_timer.c	(revision 2868)
+++ pjproject/trunk/pjsip/src/pjsip-ua/sip_timer.c	(revision 2869)
@@ -360,5 +360,5 @@
 	    status = pjsip_inv_invite(inv, &tdata);
 	    if (status == PJ_SUCCESS)
-		status = pjmedia_sdp_neg_send_local_offer(inv->pool, 
+		status = pjmedia_sdp_neg_send_local_offer(inv->pool_prov, 
 							  inv->neg, &offer);
 	    if (status == PJ_SUCCESS)
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 2868)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 2869)
@@ -1597,5 +1597,6 @@
 	status = create_sdp_of_call_hold(call, &sdp);
     } else {
-	status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 
+	status = pjsua_media_channel_create_sdp(call->index, 
+						call->inv->pool_prov,
 						NULL, &sdp, NULL);
 	call->local_hold = PJ_FALSE;
@@ -1656,5 +1657,6 @@
 
     /* Create SDP */
-    status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 
+    status = pjsua_media_channel_create_sdp(call->index, 
+					    call->inv->pool_prov, 
 					    NULL, &sdp, NULL);
     if (status != PJ_SUCCESS) {
@@ -3201,6 +3203,6 @@
     pjmedia_sdp_session *sdp;
 
-    /* Use call's pool */
-    pool = call->inv->pool;
+    /* Use call's provisional pool */
+    pool = call->inv->pool_prov;
 
     /* Create new offer */
@@ -3268,5 +3270,6 @@
 	      call->index));
 
-    status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 
+    status = pjsua_media_channel_create_sdp(call->index, 
+					    call->inv->pool_prov, 
 					    offer, &answer, NULL);
     if (status != PJ_SUCCESS) {
@@ -3297,5 +3300,5 @@
 	 * (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1)
 	 */
-	attr = pjmedia_sdp_attr_create(call->inv->pool, "sendonly", NULL);
+	attr = pjmedia_sdp_attr_create(call->inv->pool_prov, "sendonly", NULL);
 	pjmedia_sdp_media_add_attr(answer->media[0], attr);
     }
@@ -3335,5 +3338,6 @@
 		  call->index));
 
-	status = pjsua_media_channel_create_sdp(call->index, call->inv->pool, 
+	status = pjsua_media_channel_create_sdp(call->index, 
+						call->inv->pool_prov, 
 					        NULL, offer, NULL);
     }
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 2868)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 2869)
@@ -1427,5 +1427,5 @@
     /* Create media session info based on SDP parameters. 
      */    
-    status = pjmedia_session_info_from_sdp( call->inv->dlg->pool, 
+    status = pjmedia_session_info_from_sdp( call->inv->pool_prov, 
 					    pjsua_var.med_endpt, 
 					    PJMEDIA_MAX_SDP_MEDIA, &sess_info,
@@ -1470,5 +1470,5 @@
 	/* Start/restart media transport */
 	status = pjmedia_transport_media_start(call->med_tp, 
-					       call->inv->pool,
+					       call->inv->pool_prov,
 					       local_sdp, remote_sdp, 0);
 	if (status != PJ_SUCCESS)
@@ -1573,5 +1573,6 @@
 		port_name = pj_str("call");
 	    }
-	    status = pjmedia_conf_add_port( pjsua_var.mconf, call->inv->pool,
+	    status = pjmedia_conf_add_port( pjsua_var.mconf, 
+					    call->inv->pool_prov,
 					    media_port, 
 					    &port_name,
