Index: /pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h	(revision 5434)
+++ /pjproject/trunk/pjsip/include/pjsip-ua/sip_inv.h	(revision 5435)
@@ -384,4 +384,9 @@
  * that the flip-flop pool's lifetimes are synchronized to the
  * SDP offer-answer negotiation.
+ *
+ * The lifetime of this session is controlled by the reference counter in this
+ * structure, which is manipulated by calling #pjsip_inv_add_ref and
+ * #pjsip_inv_dec_ref. When the reference counter has reached zero, then
+ * this session will be destroyed.
  */
 struct pjsip_inv_session
@@ -413,4 +418,5 @@
     pj_bool_t		 following_fork;	    /**< Internal, following
 							 forked media?	    */
+    pj_atomic_t		*ref_cnt;		    /**< Reference counter. */
 };
 
@@ -629,4 +635,28 @@
 					  unsigned options,
 					  pjsip_inv_session **p_inv);
+
+
+/**
+ * Add reference counter to the INVITE session. The reference counter controls
+ * the life time of the session, ie. when the counter reaches zero, then it 
+ * will be destroyed.
+ *
+ * @param inv       The INVITE session.
+ * @return          PJ_SUCCESS if the INVITE session reference counter
+ *                  was increased.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv );
+
+/**
+ * Decrement reference counter of the INVITE session.
+ * When the session is no longer used, it will be destroyed and
+ * caller is informed with PJ_EGONE return status.
+ *
+ * @param inv       The INVITE session.
+ * @return          PJ_SUCCESS if the INVITE session reference counter
+ *                  was decreased. A status PJ_EGONE will be returned to 
+ *                  inform that session is destroyed.
+ */
+PJ_DECL(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv );
 
 
Index: /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 5434)
+++ /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 5435)
@@ -196,4 +196,63 @@
 
 /*
+ * Add reference to INVITE session.
+ */
+PJ_DEF(pj_status_t) pjsip_inv_add_ref( pjsip_inv_session *inv )
+{
+    PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL);
+
+    pj_atomic_inc(inv->ref_cnt);
+
+    return PJ_SUCCESS;
+}
+
+static void inv_session_destroy(pjsip_inv_session *inv)
+{
+    if (inv->last_ack) {
+	pjsip_tx_data_dec_ref(inv->last_ack);
+	inv->last_ack = NULL;
+    }
+    if (inv->invite_req) {
+	pjsip_tx_data_dec_ref(inv->invite_req);
+	inv->invite_req = NULL;
+    }
+    if (inv->pending_bye) {
+	pjsip_tx_data_dec_ref(inv->pending_bye);
+	inv->pending_bye = NULL;
+    }
+    pjsip_100rel_end_session(inv);
+    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);
+    inv->pool_prov = NULL;
+    pj_pool_release(inv->pool_active);
+    inv->pool_active = NULL;
+
+    pj_atomic_destroy(inv->ref_cnt);
+    inv->ref_cnt = NULL;
+}
+
+/*
+ * Decrease INVITE session reference, destroy it when the reference count
+ * reaches zero.
+ */
+PJ_DEF(pj_status_t) pjsip_inv_dec_ref( pjsip_inv_session *inv )
+{
+    pj_atomic_value_t ref_cnt;
+
+    PJ_ASSERT_RETURN(inv && inv->ref_cnt, PJ_EINVAL);
+
+    ref_cnt = pj_atomic_dec_and_get(inv->ref_cnt);
+    pj_assert( ref_cnt >= 0);
+    if (ref_cnt == 0) {
+        inv_session_destroy(inv);
+        return PJ_EGONE;
+    } 
+    return PJ_SUCCESS;    
+}
+
+/*
  * Set session state.
  */
@@ -262,25 +321,5 @@
 	prev_state != PJSIP_INV_STATE_DISCONNECTED) 
     {
-	if (inv->last_ack) {
-	    pjsip_tx_data_dec_ref(inv->last_ack);
-	    inv->last_ack = NULL;
-	}
-	if (inv->invite_req) {
-	    pjsip_tx_data_dec_ref(inv->invite_req);
-	    inv->invite_req = NULL;
-	}
-	if (inv->pending_bye) {
-	    pjsip_tx_data_dec_ref(inv->pending_bye);
-	    inv->pending_bye = NULL;
-	}
-	pjsip_100rel_end_session(inv);
-	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);
-	inv->pool_prov = NULL;
-	pj_pool_release(inv->pool_active);
-	inv->pool_active = NULL;
+	pjsip_inv_dec_ref(inv);
     }
 }
@@ -839,4 +878,10 @@
     pj_assert(inv != NULL);
 
+    status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt);
+    if (status != PJ_SUCCESS) {
+	pjsip_dlg_dec_lock(dlg);
+	return status;
+    }
+
     inv->pool = dlg->pool;
     inv->role = PJSIP_ROLE_UAC;
@@ -882,4 +927,5 @@
 
     /* Done */
+    pjsip_inv_add_ref(inv);
     *p_inv = inv;
 
@@ -1472,4 +1518,10 @@
     pj_assert(inv != NULL);
 
+    status = pj_atomic_create(dlg->pool, 0, &inv->ref_cnt);
+    if (status != PJ_SUCCESS) {
+	pjsip_dlg_dec_lock(dlg);
+	return status;
+    }
+
     inv->pool = dlg->pool;
     inv->role = PJSIP_ROLE_UAS;
@@ -1541,4 +1593,5 @@
 
     /* Done */
+    pjsip_inv_add_ref(inv);
     pjsip_dlg_dec_lock(dlg);
     *p_inv = inv;
