Index: pjproject/trunk/pjsip-apps/src/samples/pjsua2_demo.cpp
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/pjsua2_demo.cpp	(revision 5898)
+++ pjproject/trunk/pjsip-apps/src/samples/pjsua2_demo.cpp	(revision 5899)
@@ -40,4 +40,6 @@
     
     virtual void onCallState(OnCallStateParam &prm);
+    virtual void onCallTransferRequest(OnCallTransferRequestParam &prm);
+    virtual void onCallReplaced(OnCallReplacedParam &prm);
 };
 
@@ -55,4 +57,11 @@
         std::cout << "*** Account is being deleted: No of calls="
                   << calls.size() << std::endl;
+
+	for (std::vector<Call *>::iterator it = calls.begin();
+             it != calls.end(); )
+        {
+	    delete (*it);
+	    it = calls.erase(it);
+        }
     }
     
@@ -100,9 +109,22 @@
     
     if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
-        myAcc->removeCall(this);
+        //myAcc->removeCall(this);
         /* Delete the call */
-        delete this;
-    }
-}
+        //delete this;
+    }
+}
+
+void MyCall::onCallTransferRequest(OnCallTransferRequestParam &prm)
+{
+    /* Create new Call for call transfer */
+    prm.newCall = new MyCall(*myAcc);
+}
+
+void MyCall::onCallReplaced(OnCallReplacedParam &prm)
+{
+    /* Create new Call for call replace */
+    prm.newCall = new MyCall(*myAcc, prm.newCallId);
+}
+
 
 static void mainProg1(Endpoint &ep) throw(Error)
@@ -148,6 +170,5 @@
     // Destroy library
     std::cout << "*** PJSUA2 SHUTTING DOWN ***" << std::endl;
-    delete call;
-    delete acc;
+    delete acc; /* Will delete all calls too */
 }
 
@@ -347,5 +368,5 @@
 	ep.libCreate();
 
-	mainProg3(ep);
+	mainProg1(ep);
 	ret = PJ_SUCCESS;
     } catch (Error & err) {
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 5898)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 5899)
@@ -1037,5 +1037,5 @@
      *			transferred to.
      * @param code	Status code to be returned for the call transfer
-     *			request. On input, it contains status code 200.
+     *			request. On input, it contains status code 202.
      */
     void (*on_call_transfer_request)(pjsua_call_id call_id,
@@ -1054,5 +1054,5 @@
      *			transferred to.
      * @param code	Status code to be returned for the call transfer
-     *			request. On input, it contains status code 200.
+     *			request. On input, it contains status code 202.
      * @param opt	The current call setting, application can update
      *			this setting for the call being transferred.
Index: pjproject/trunk/pjsip/include/pjsua2/call.hpp
===================================================================
--- pjproject/trunk/pjsip/include/pjsua2/call.hpp	(revision 5898)
+++ pjproject/trunk/pjsip/include/pjsua2/call.hpp	(revision 5899)
@@ -785,11 +785,11 @@
      * The destination where the call will be transferred to.
      */
-    string              dstUri;
+    string               dstUri;
     
     /**
      * Status code to be returned for the call transfer request. On input,
-     * it contains status code 200.
-     */
-    pjsip_status_code   statusCode;
+     * it contains status code 202.
+     */
+    pjsip_status_code    statusCode;
     
     /**
@@ -797,5 +797,11 @@
      * for the call being transferred.
      */
-    CallSetting         opt;
+    CallSetting          opt;
+
+    /**
+     * New Call derived object instantiated by application when the call
+     * transfer is about to be accepted.
+     */
+    Call		*newCall;
 };
 
@@ -867,5 +873,10 @@
      * The new call id.
      */
-    pjsua_call_id       newCallId;
+    pjsua_call_id        newCallId;
+
+    /**
+     * New Call derived object instantiated by application.
+     */
+    Call		*newCall;
 };
 
@@ -1717,8 +1728,19 @@
     /**
      * Notify application on call being transferred (i.e. REFER is received).
-     * Application can decide to accept/reject transfer request
-     * by setting the code (default is 202). When this callback
-     * is not implemented, the default behavior is to accept the
-     * transfer.
+     * Application can decide to accept/reject transfer request by setting
+     * the code (default is 202). When this callback is not implemented,
+     * the default behavior is to accept the transfer.
+     *
+     * If application decides to accept the transfer request, it must also
+     * instantiate the new Call object for the transfer operation and return
+     * this new Call object to prm.newCall.
+     * 
+     * If application does not specify new Call object, library will reuse the
+     * existing Call object for initiating the new call (to the transfer
+     * destination). In this case, any events from both calls (transferred and
+     * transferring) will be delivered to the same Call object, where the call
+     * ID will be switched back and forth between callbacks. Application must
+     * be careful to not destroy the Call object when receiving disconnection
+     * event of the transferred call after the transfer process is completed.
      *
      * @param prm	Callback parameter.
@@ -1753,5 +1775,9 @@
      *
      * After this callback is called, normally PJSUA-API will disconnect
-     * this call and establish a new call \a newCallId.
+     * this call and establish a new call. To be able to control the call,
+     * e.g: hold, transfer, change media parameters, application must
+     * instantiate a new Call object for the new call using call ID
+     * specified in prm.newCallId, and return the Call object via
+     * prm.newCall.
      *
      * @param prm	Callback parameter.
@@ -1953,4 +1979,5 @@
     std::vector<Media *> medias;
     pj_pool_t		*sdp_pool;
+    Call		*child;	    /* New outgoing call in call transfer.  */
 };
 
Index: pjproject/trunk/pjsip/src/pjsua2/call.cpp
===================================================================
--- pjproject/trunk/pjsip/src/pjsua2/call.cpp	(revision 5898)
+++ pjproject/trunk/pjsip/src/pjsua2/call.cpp	(revision 5899)
@@ -450,5 +450,5 @@
 
 Call::Call(Account& account, int call_id)
-: acc(account), id(call_id)
+: acc(account), id(call_id), userData(NULL), sdp_pool(NULL), child(NULL)
 {
     if (call_id != PJSUA_INVALID_ID)
@@ -503,6 +503,12 @@
 {
     Call *call = (Call*)pjsua_call_get_user_data(call_id);
-    if (call)
-        call->id = call_id;
+    if (call && call_id != call->id) {
+	if (call->child && call->child->id == PJSUA_INVALID_ID) {
+	    /* This must be a new call from call transfer */
+	    call = call->child;
+	    pjsua_call_set_user_data(call_id, call);
+	}
+	call->id = call_id;
+    }
     return call;
 }
@@ -821,4 +827,7 @@
         }
         medias.clear();
+
+	/* Remove this Call object association */
+	pjsua_call_set_user_data(id, NULL);
     }
     
Index: pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp
===================================================================
--- pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp	(revision 5898)
+++ pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp	(revision 5899)
@@ -1192,4 +1192,5 @@
     prm.statusCode = *code;
     prm.opt.fromPj(*opt);
+    prm.newCall = NULL;
     
     call->onCallTransferRequest(prm);
@@ -1197,4 +1198,17 @@
     *code = prm.statusCode;
     *opt = prm.opt.toPj();
+    if (*code/100 <= 2) {
+	if (prm.newCall) {
+	    /* We don't manage (e.g: create, delete) the call child,
+	     * so let's just override any existing child.
+	     */
+	    call->child = prm.newCall;
+	    call->child->id = PJSUA_INVALID_ID;
+	} else {
+	    PJ_LOG(4,(THIS_FILE,
+		      "Warning: application reuses Call instance in "
+		      "call transfer (call ID:%d)", call_id));
+	}
+    }
 }
 
@@ -1255,6 +1269,19 @@
     OnCallReplacedParam prm;
     prm.newCallId = new_call_id;
+    prm.newCall = NULL;
     
     call->onCallReplaced(prm);
+
+    if (prm.newCall) {
+	/* Sanity checks */
+	pj_assert(prm.newCall->id == new_call_id);
+	pj_assert(prm.newCall->acc.getId() == call->acc.getId());
+	pj_assert(pjsua_call_get_user_data(new_call_id) == prm.newCall);
+    } else {
+	PJ_LOG(4,(THIS_FILE,
+		  "Warning: application has not created new Call instance "
+		  "for call replace (old call ID:%d, new call ID: %d)",
+		  old_call_id, new_call_id));
+    }
 }
 
