backupandrestore/backupengine/src/absession.cpp
changeset 0 d0791faffa3f
child 13 81da3301b632
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backupandrestore/backupengine/src/absession.cpp	Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,1238 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implementation of CABSession class.
+// 
+//
+
+/**
+ @file
+*/
+
+#include <e32base.h>
+#include "abserver.h"
+#include "absession.h"
+#include <connect/abclientserver.h>
+#include "sbedataownermanager.h"
+#include "sbedataowner.h"
+#include <connect/sbtypes.h>
+#include <connect/panic.h>
+#include "sblog.h"
+
+namespace conn
+	{
+	CABSession* CABSession::NewL(TSecureId aSecureId)
+	/**
+	Symbian first phase constructor
+	
+	@param aSecureId The SID of the client that's connecting to this session
+	*/
+		{
+		CABSession* self = new (ELeave) CABSession(aSecureId);
+		CleanupStack::PushL(self);
+		self->ConstructL();
+		CleanupStack::Pop(self);
+		return self;
+		}
+		
+	void CABSession::ConstructL()
+	/**
+	Symbian second phase constructor. Initialise some more of the data members
+	*/
+		{
+		iActiveSchedulerWait = new (ELeave) CActiveSchedulerWait;
+		__LOG1("CABSession::ConstructL() [0x%08x]", iClientSID.iId);
+		}
+		
+	CABSession::CABSession(TSecureId aSecureId) : iClientSID(aSecureId), 
+		iCallbackWatchdog(NULL), iActiveSchedulerWait(NULL), iABClientLeaveCode(KErrNone), 
+		iReceiveFromClientFinished(ETrue), iSendToClientBuffer(NULL, 0), 
+		iWatchdogHandler(ABSessionStaticWatchdogCaller, static_cast<TAny*>(this)), iMisbehavingClient(EFalse),
+		iInvalid(EFalse)
+    /**
+    Class Constructor
+    
+	@param aSecureId The SID of the client that's connecting to this session
+    */
+		{
+		}
+		
+	CDataOwner& CABSession::DataOwnerL() const
+	/**
+	Return the active data owner
+	
+	@return A reference to the active data owner
+	*/
+		{
+		return Server().DataOwnerManager().DataOwnerL(iClientSID);
+		}
+		
+	TInt CABSession::ABSessionStaticWatchdogCaller(TAny* aWatchdoggingObject)
+	/**
+	CPeriodic only accepts a TCallBack style function pointer which must be a pointer to a static or
+	non-member function. As we need to have watchdogs per session object instead of per class, we 
+	must make the call to the particular object from within this static method.
+	
+	@param aWatchdoggingObject CABSession* to the object that watchdogged
+	@return Any error code - enforced return, not necessarily used by this function
+	@see TCallBack
+	*/
+		{
+		return (static_cast<CABSession*>(aWatchdoggingObject))->WatchdogExpired();
+		}
+		
+	TInt CABSession::WatchdogExpired()
+	/**
+	Called by ABSessionStaticWatchdogCaller to indicate that the watchdog has expired on this particular 
+	session as a result of the callback not being returned from by the client
+	
+	@return An error code
+	*/
+		{
+		__LOG1("CABSession::WatchdogExpired() - [0x%08x] Watchdog expired on session", iClientSID.iId);
+		
+		iMisbehavingClient = ETrue;			// Flag the client as having not responded
+		
+		// Inform the Data Owner of the new status
+		TRAP_IGNORE(DataOwnerL().SetReadyState(EDataOwnerFailed));
+		
+		if (iActiveSchedulerWait->IsStarted())
+			{
+			iABClientLeaveCode = KErrTimedOut;
+			ReturnFromCallback();
+			}
+		else
+			{
+			// We should never get here - only a callback call should time out
+			Panic(KErrTimedOut);
+			}
+			
+		return KErrTimedOut;
+		}
+
+	TBool CABSession::ConfirmedReadyForBUR() const
+	/** Accessor to get the state from an already existing connection
+	
+	@return ETrue if the active client has previously confirmed that it's ready for a backup or restore
+	*/
+		{
+		return iConfirmedReadyForBUR;
+		}
+		
+	TBool CABSession::CallbackInterfaceAvailable() const
+	/** Accessor to indicate whether or not the client has enabled the callback interface or not
+	
+	@return ETrue if the callback interface is available
+	*/
+		{
+		return !iMessage.IsNull();
+		}
+		
+	CABSession::~CABSession()
+    /**
+    Class destructor
+    */
+		{
+		__LOG1("~CABSession for sid:0x%08x", iClientSID.iId);
+		delete iCallbackWatchdog;
+		iCallbackWatchdog = NULL;
+		
+		// Remove this session from the server's session map
+		Server().RemoveElement(iClientSID);
+		
+		// Clear up any outstanding message
+		HandleIPCClosingDownCallback();
+		
+		delete iActiveSchedulerWait;
+
+		//
+		// If the client has detached properly, they should
+		// have done this - but just in case.
+		//DoCancelWaitForCallback();
+		Server().DropSession();
+		}
+		
+	void CABSession::CreateL()
+	/**
+	Creates a connection between active backup server and the active backup session.
+	Increments the server's session count
+	*/
+		{
+		//
+		// Increase the servers session count.
+		Server().AddSession();
+		}
+
+	void CABSession::RestoreCompleteL(TDriveNumber aDriveNumber)
+	/**
+	Signal the client that the restore operation is complete
+
+	@param aDriveNumber The drive that has finished being backed up
+	*/
+		{
+		MakeCallbackRestoreCompleteL(aDriveNumber);
+		}
+
+	void CABSession::AllSnapshotsSuppliedL()
+	/**
+	Lets the session know that all snapshots have been supplied.
+	
+	*/
+		{
+		MakeCallbackAllSnapshotsSuppliedL();
+		}
+
+	void CABSession::GetExpectedDataSizeL(TDriveNumber aDriveNumber, TUint& aSize)
+	/**
+	Get the expected data size from the active backup client
+
+	@param aDriveNumber The drive number of the data
+	@param aSize Upon exit, this parameter will indicate the expected data size
+	*/
+		{
+		aSize = MakeCallbackGetExpectedDataSizeL(aDriveNumber);
+		}
+		
+	void CABSession::SupplyDataL(TDriveNumber aDriveNumber, TTransferDataType aTransferType, TDesC8& aBuffer,
+			TBool aLastSection, TBool aSuppressInitDataOwner, TSecureId aProxySID)
+	/**
+	Supply data to the active backup client
+
+	@param aDriveNumber The drive number of the data
+	@param aTransferType Specifies the type of data to get the expected data size of
+	@param aBuffer The data to send to the Active Backup Client
+	@param aLastSection Specifies whether or not additional SupplyDataL calls will be made (multi-part)
+	@param aSuppressInitDataOwner Suppress the initialisation of Data Owner
+	@param aProxySID The secure ID of the proxy
+	*/
+		{
+		TInt dataSizeTransferred = 0;
+		TInt remainingBlockSize = 0;
+		TBool lastSection;
+		TPtrC8 transferBlock;
+
+		// Repeat the data transfer until all data has been sent
+		while (dataSizeTransferred < aBuffer.Size())
+			{
+			remainingBlockSize = aBuffer.Size() - dataSizeTransferred;
+			
+			if (remainingBlockSize > KIPCMessageSize)
+				{
+				remainingBlockSize = KIPCMessageSize;
+				lastSection = EFalse;
+				}
+			else
+				{
+				lastSection = aLastSection;
+				}
+				
+			// Create a temporary descriptor representing the next block to send
+			transferBlock.Set(aBuffer.Mid(dataSizeTransferred, remainingBlockSize));
+			
+			dataSizeTransferred += transferBlock.Size();
+
+			// If we're sending
+			if ((transferBlock.Size() <= KIPCMessageSize) && (dataSizeTransferred != aBuffer.Size()))
+				{
+				lastSection = EFalse;
+				}
+			else
+				{
+				lastSection = aLastSection;
+				}
+			
+			__LOG2("CABSession::SupplyDataL() - [0x%08x] Supplying data to ABClient, %d bytes transferred", iClientSID.iId, dataSizeTransferred);
+	
+			switch(aTransferType)
+				{
+				case EActiveSnapshotData:
+					{
+					MakeCallbackReceiveSnapshotDataL(aDriveNumber, transferBlock, lastSection);
+					} break;
+				case EActiveBaseData:
+					{
+					if (!aSuppressInitDataOwner)
+						{
+						if (aProxySID != KNullABSid)
+							{
+							MakeCallbackInitialiseRestoreProxyBaseDataL(aProxySID, aDriveNumber);
+							}
+						else
+							{
+							MakeCallbackInitialiseRestoreBaseDataL(aDriveNumber);
+							}
+						}
+					MakeCallbackRestoreBaseDataSectionL(transferBlock, lastSection);
+					} break;
+				case EActiveIncrementalData:
+					{
+					if (!aSuppressInitDataOwner)
+						{
+						MakeCallbackInitialiseRestoreIncrementDataL(aDriveNumber);
+						}
+					MakeCallbackRestoreIncrementDataSectionL(transferBlock, lastSection);
+					} break;
+				default:
+					{
+					User::Leave(KErrNotSupported);
+					}
+				}
+			
+			// Even if we were supposed to suppress it first time round, for a multipart supply, it 
+			// shouldn't be sent again
+			aSuppressInitDataOwner = ETrue;
+			}
+		}
+			
+	void CABSession::RequestDataL(TDriveNumber aDriveNumber, TTransferDataType aTransferType, TPtr8& aBuffer,
+			TBool& aLastSection, TBool aSuppressInitDataOwner, TSecureId aProxySID)
+	/**
+	Request data from the active backup client
+
+	@param aDriveNumber The drive number of the data 
+	@param aTransferType Specifies the type of data to get the expected data size of
+	@param aBuffer This buffer will be filled by the Active Backup Client upon return
+	@param aLastSection Upon return indicates whether or not additional RequestDataL calls will be made (multi-part)
+	@param aSuppressInitDataOwner Suppress the initialisation of Data Owner
+	@param aProxySID The secure ID of the proxy
+	*/
+		{
+        __LOG5("CABSession::RequestDataL() - START - aDrive: %c, aTType: %d, aBuffer.Ptr(): 0x%08x, aBuffer.Length(): %d, aProxySID: 0x%08x", 
+            aDriveNumber + 'A', aTransferType, aBuffer.Ptr(), aBuffer.Length(), aProxySID.iId );
+
+        TInt dataSizeTransferred = 0;
+		TInt remainingBlockSize = 0;
+		TBool lastSection = EFalse;
+		TPtr8 transferBlock(NULL, 0);
+		
+		// While there is space left in aBuffer and the client hasn't finished, keep requesting data
+		do
+			{
+			// Set max for the MidTPtr call to work. Length of this buffer is reset after each data transfer
+			aBuffer.SetMax();
+
+			remainingBlockSize = aBuffer.MaxSize() - dataSizeTransferred;
+			__LOG2("CABSession::RequestDataL() - dataSizeTransferred: %d, remainingBlockSize: %d", dataSizeTransferred, remainingBlockSize);
+
+			if (remainingBlockSize > KIPCMessageSize)
+				{
+				remainingBlockSize = KIPCMessageSize;
+				}
+				
+			transferBlock.Set(aBuffer.MidTPtr(dataSizeTransferred, remainingBlockSize));
+			__LOG2("CABSession::RequestDataL() - transferBlock: 0x%08x (%d)", transferBlock.Ptr(), transferBlock.Length());
+
+			switch(aTransferType)
+				{
+				case EActiveSnapshotData:
+					{
+					MakeCallbackGetSnapshotDataL(aDriveNumber, transferBlock, lastSection);
+					} break;
+				case EActiveBaseData:
+				case EActiveIncrementalData:
+					{
+					if (!aSuppressInitDataOwner)
+						{
+						if (aProxySID != KNullABSid)
+							{
+							MakeCallbackInitialiseGetProxyBackupDataL(aProxySID, aDriveNumber);
+							}
+						else
+							{
+							MakeCallbackInitialiseGetBackupDataL(aDriveNumber);
+							}
+						}
+					MakeCallbackGetBackupDataSectionL(transferBlock, lastSection);
+					} break;
+				default:
+					{
+					User::Leave(KErrNotSupported);
+					}
+				}
+			
+			// Even if we were supposed to suppress it first time round, for a multipart get, it 
+			// shouldn't be sent again
+			aSuppressInitDataOwner = ETrue;
+
+			// update our count to reflect the new data supplied by the client
+			dataSizeTransferred += transferBlock.Size();
+
+            __LOG2("CABSession::RequestDataL() - received data so far: %d, buffer start address: 0x%08x", dataSizeTransferred, aBuffer.Ptr());
+            //__LOGDATA("CABSession::RequestDataL() - total received data - %S", aBuffer.Ptr(), dataSizeTransferred);
+
+			__LOG2("CABSession::RequestDataL() - [0x%08x] Requesting data from ABClient %d bytes so far)", iClientSID.iId, dataSizeTransferred);
+			
+			aBuffer.SetLength(dataSizeTransferred);
+			} while (!lastSection && (dataSizeTransferred < aBuffer.MaxSize()));
+		
+		aLastSection = lastSection;
+		}
+		
+	void CABSession::TerminateMultiStageOperationL()
+	/**
+	Instruct the client that copying of data has been aborted and it should clean up
+	*/
+		{
+		MakeCallbackTerminateMultiStageOperationL();
+		}
+		
+	TUint CABSession::GetDataChecksumL(TDriveNumber aDrive)
+	/**
+	Test method for validating data
+	
+	@param aDrive The drive from which the data is backed up from
+	@return The checksum
+	*/
+		{
+		return MakeCallbackGetDataChecksumL(aDrive);
+		}
+
+	void CABSession::CleanupClientSendState()
+	/**
+	Delete the client sending buffer and reset multipart flag
+	*/
+		{
+		iReceiveFromClientFinished = ETrue;
+		}
+		
+	void CABSession::MadeCallback()
+	/**
+	Start the CActiveSchedulerWait() object. The ABServer will stop this wait object when it's callback 
+	has returned, this way the thread's AS still processes ABServer ServiceL's etc. but it appears as 
+	though the request to the ABClient is synchronous. This method will be called from the ABServer inside 
+	the call from the Data Owner requesting an operation
+	
+	@see CDataOwner::ReturnFromActiveCall()
+	*/
+		{
+		// Reset the leave flag
+		iABClientLeaveCode = KErrNone;
+		
+		
+		#ifndef _DEBUG
+		// Start the callback timer only in release builds
+		delete iCallbackWatchdog;
+		iCallbackWatchdog = NULL;
+		iCallbackWatchdog = CPeriodic::NewL(EPriorityHigh);
+		TTimeIntervalMicroSeconds32 KWatchdogIntervalNone = 0;
+		iCallbackWatchdog->Start(KABCallbackWatchdogTimeout, KWatchdogIntervalNone, iWatchdogHandler);
+		#endif
+
+		// Send the message back to the callback handler
+		iMessage.Complete(KErrNone);
+		
+		__LOG1("CABSession::MadeCallback() - [0x%08x] Calling ABClient to process callback", iClientSID.iId);
+
+		// Set the timeout for the callback
+		iActiveSchedulerWait->Start();
+		}
+		
+	void CABSession::ReturnFromCallback()
+	/**
+	This method is called by the ABServer once it's completed it's request from the Active Backup Client 
+	so that the Data Owner appears to have made a synchronous call into the ABServer
+	*/
+		{
+		if (iCallbackWatchdog)
+			{
+			if (iCallbackWatchdog->IsActive())
+				{
+				iCallbackWatchdog->Cancel();
+
+				delete iCallbackWatchdog;
+				iCallbackWatchdog = NULL;
+				}
+			}
+
+		if (iActiveSchedulerWait->IsStarted())
+			{
+			__LOG1("CABSession::MadeCallback() - [0x%08x] has returned from callback - CASW::AsyncStop()", iClientSID.iId);
+			iActiveSchedulerWait->AsyncStop();
+			}
+		}
+
+	void CABSession::TakeOwnershipOfIPCMessage(const RMessage2& aMessage)
+	/**
+	Take ownership of the IPC message so that we're able to signal the Active Backup Callback Handler
+	
+	@param aMessage The IPC message that we're going to take ownership of
+	*/
+		{
+		iMessage = aMessage;
+		}
+	
+	void CABSession::HandleIPCBURModeInfoL(const RMessage2& aMessage)
+	/**
+	Return information about the backup and restore mode to the active backup client
+
+	@param aMessage The IPC message
+	*/
+		{
+		__LOG1("CABSession::HandleIPCBURModeInfoL() - [0x%08x] Received IPC IPCBURModeInfo", iClientSID.iId);
+
+		TPckgC<TBURPartType> partType(Server().DataOwnerManager().BURType());
+		TPckgC<TBackupIncType> incType(Server().DataOwnerManager().IncType());
+		
+		// Return the backup and restore settings to the client
+		aMessage.WriteL(0, Server().DataOwnerManager().DriveList());
+		aMessage.WriteL(1, partType);
+		aMessage.WriteL(2, incType);
+		}
+		
+	void CABSession::HandleIPCDoesPartialBURAffectMeL(const RMessage2& aMessage)
+	/**
+	Return information about the backup and restore mode to the active backup client
+
+	@param aMessage The IPC message
+	*/
+		{
+		__LOG1("CABSession::HandleIPCDoesPartialBURAffectMeL() - [0x%08x] Received IPC DoesPartialBURAffectMe", iClientSID.iId);
+
+		TPckgC<TBool> resultPkg(Server().DataOwnerManager().IsSetForPartialL(iClientSID));
+		aMessage.WriteL(0, resultPkg);
+		}
+
+	void CABSession::HandleIPCConfirmReadyForBURL(const RMessage2& aMessage)
+	/**
+	Respond to an event from abclient informing us that it's prepared it's data and is ready for backup
+
+	@param aMessage The IPC message
+	*/
+		{
+		TInt errorCode = aMessage.Int0();
+		__LOG2("CABSession::HandleIPCConfirmReadyForBURL() - [0x%08x] Received IPC ConfirmReadyForBUR, errorCode: %d", iClientSID.iId, errorCode);
+		
+		// Set our internal state to indicate that the client has confirmed ready for BUR
+		iConfirmedReadyForBUR = ETrue;
+
+		TDataOwnerStatus status;
+
+		if (errorCode == KErrNone)
+			{
+			if (CallbackInterfaceAvailable())
+				{
+				status = EDataOwnerReady;
+				}
+			else
+				{
+				status = EDataOwnerReadyNoImpl;
+				}
+			}
+		else				
+			{
+			status = EDataOwnerFailed;
+			}
+		
+		// Inform the Data Owner of the new status
+		TRAP_IGNORE(DataOwnerL().SetReadyState(status));
+		}
+
+	void CABSession::HandleIPCPropagateLeaveL(const RMessage2& aMessage)
+	/** Leave with the propagated leave code
+
+	@param aMessage The IPC message
+	*/
+		{
+		// Leave with the propagated leave code, but not inside this ServiceL, it'll leave to the client again 
+		// We need to ensure that it leaves through SBEngine back to SBEClient. Leave code will be checked 
+		// after the callback has been made and leave will be made then if necessary
+		iABClientLeaveCode = aMessage.Int0();
+
+		__LOG2("CABSession::HandleIPCPropagateLeaveL() - [0x%08x] Received IPC Leave(%d)", iClientSID.iId, iABClientLeaveCode);
+		}
+
+	TInt CABSession::HandleIPCGetDataSyncL(const RMessage2& aMessage)
+	/**
+	Handles the synchronous method called by the client to get it's data transferred
+
+	@param aMessage The IPC message
+	@return KErrNone if OK, standard error code otherwise
+	*/
+		{
+		__LOG1("CABSession::HandleIPCGetDataSyncL() - [0x%08x] has requested data over IPC", iClientSID.iId);
+
+		TInt completionCode = KErrNone;
+		
+		if (iCallbackInProgress == static_cast<TABCallbackCommands>(aMessage.Int0()))
+			{
+			// Write the clients data into the buffer
+			aMessage.WriteL(1, iSendToClientBuffer);
+			}
+		else
+			{
+			completionCode = KErrCorrupt;
+			}
+			
+		__LOG2("CABSession::HandleIPCGetDataSyncL() - [0x%08x] completion code: %d", iClientSID.iId, completionCode);
+		return completionCode;
+		}
+
+	TInt CABSession::HandleIPCSendDataLengthL(const RMessage2& aMessage)
+	/**
+	Synchronous IPC call from the ABClient to inform the server about the data that is being returned from it
+
+	@param aMessage The IPC message
+	@return KErrNone if OK, standard error code otherwise
+	*/
+		{
+		__LOG1("CABSession::HandleIPCSendDataLengthL() - [0x%08x] is informing server of the data length coming back", iClientSID.iId);
+
+		TInt completionCode = KErrNone;
+
+		// Check that this operation is as part of our expected callback
+		if (iCallbackInProgress == static_cast<TABCallbackCommands>(aMessage.Int2()))
+			{
+			CleanupClientSendState();
+			// Ignore the size returned from the client (Int0()) because we've told it how much it can send
+			iReceiveFromClientFinished = static_cast<TBool>(aMessage.Int1());
+			}
+		else
+			{
+			completionCode = KErrCorrupt;
+			}
+			
+		return completionCode;
+		}
+
+	TInt CABSession::HandleIPCClosingDownCallback()
+	/**
+	Respond to the client, informing it that the server is closing down the callback interface
+
+	@return KErrNone if OK, standard error code otherwise
+	*/
+		{
+		TInt completionCode = KErrNotFound;
+		__LOG1("CABSession::HandleIPCClosingDownCallback() - [0x%08x] is closing down the callback interface", iClientSID.iId);
+		if (!iMessage.IsNull())
+			{
+			completionCode = KErrNone;
+			iMessage.Complete(KErrCancel);
+			}
+
+		return completionCode;
+		}
+
+	void CABSession::ServiceL(const RMessage2& aMessage)
+	/**
+	Called by the client server framework to service a message request
+	from a client.
+
+    @param aMessage  Reference to a RMessage2 object
+	*/
+		{
+ 		const TInt ipcMessageFn = aMessage.Function();
+ 		TInt completionCode = KErrNone;			// Complete the aMessage with this code
+
+	#if defined(SBE_LOGGING_ENABLED)
+		RThread client;
+		aMessage.Client(client);
+		const TFullName name(client.FullName());
+		client.Close();
+		__LOG5("CABSession::ServiceL() - START - [0x%08x] function: %d from client: %S, iMisbehavingClient: %d, iConfirmedReadyForBUR: %d", iClientSID.iId, ipcMessageFn, &name, iMisbehavingClient, iConfirmedReadyForBUR);
+	#endif
+		
+		switch(ipcMessageFn)
+			{
+			case EABMsgBURModeInfo:
+	            __LOG("CABSession::ServiceL() - EABMsgBURModeInfo");
+				{
+				HandleIPCBURModeInfoL(aMessage);
+				break;
+				}
+			case EABMsgDoesPartialAffectMe:
+	            __LOG("CABSession::ServiceL() - EABMsgDoesPartialAffectMe");
+				{
+				HandleIPCDoesPartialBURAffectMeL(aMessage);
+				break;
+				}
+			case EABMsgConfirmReadyForBUR:
+	            __LOG("CABSession::ServiceL() - EABMsgConfirmReadyForBUR");
+				{
+				if (iMisbehavingClient)
+					{
+					completionCode = KErrTimedOut;
+					}
+				else
+					{
+					HandleIPCConfirmReadyForBURL(aMessage);
+					}
+					
+				break;
+				}
+			case EABMsgPrimeForCallback:
+			case EABMsgPrimeForCallbackAndResponse:
+			case EABMsgPrimeForCallbackAndResponseDes:
+	            __LOG("CABSession::ServiceL() - EABMsgPrimeForCallback/EABMsgPrimeForCallbackAndResponse/EABMsgPrimeForCallbackAndResponseDes");
+				{
+				CDataOwner* dataOwner = NULL;
+				TRAPD(err, dataOwner = &DataOwnerL());
+				// Close down the entire callback interface on a misbehaving client
+				if (iMisbehavingClient)
+					{
+					completionCode = KErrTimedOut;
+					if (err == KErrNone)
+						{
+						dataOwner->SetReadyState(EDataOwnerNotConnected);
+						}
+					else
+						{
+						if (err != KErrNotFound)
+							{
+							User::Leave(err);
+							}
+						}
+					}
+				else
+					{
+					TakeOwnershipOfIPCMessage(aMessage);
+					if (err == KErrNone)
+						{
+						if (dataOwner->ReadyState() == EDataOwnerNotConnected)
+							{
+							dataOwner->SetReadyState(EDataOwnerNotReady);
+							}
+						}
+					else
+						{
+						if (err != KErrNotFound)
+							{
+							User::Leave(err);
+							}
+						}
+						
+					// Return to the method that initiated the callback
+					ReturnFromCallback();
+					}
+
+				break;
+				}
+			case EABMsgPropagateLeave:
+	            __LOG("CABSession::ServiceL() - EABMsgPropagateLeave");
+				{
+				if (iMisbehavingClient)
+					{
+					completionCode = KErrTimedOut;
+					}
+				else
+					{
+					HandleIPCPropagateLeaveL(aMessage);
+					}
+				break;
+				}
+			case EABMsgGetDataSync:
+	            __LOG("CABSession::ServiceL() - EABMsgGetDataSync");
+				{
+				if (iMisbehavingClient)
+					{
+					completionCode = KErrTimedOut;
+					}
+				else
+					{
+					completionCode = HandleIPCGetDataSyncL(aMessage);
+					}
+				break;
+				}
+			case EABMsgSendDataLength:
+	            __LOG("CABSession::ServiceL() - EABMsgSendDataLength");
+				{
+				if (iMisbehavingClient)
+					{
+					completionCode = KErrTimedOut;
+					}
+				else
+					{
+					completionCode = HandleIPCSendDataLengthL(aMessage);
+					}
+				break;
+				}
+			case EABMsgClosingDownCallback:
+	            __LOG("CABSession::ServiceL() - EABMsgClosingDownCallback");
+				{
+				completionCode = HandleIPCClosingDownCallback();
+
+				CDataOwner* dataOwner = NULL;
+				TRAPD(err, dataOwner = &DataOwnerL());
+				if (err == KErrNone && ( dataOwner->ReadyState() == EDataOwnerReady || dataOwner->ReadyState() == EDataOwnerReadyNoImpl ))
+					{
+					dataOwner->SetReadyState(EDataOwnerNotConnected);
+					}
+				break;
+				}
+			case EABMsgGetDriveNumForSuppliedSnapshot:
+	            __LOG("CABSession::ServiceL() - EABMsgGetDriveNumForSuppliedSnapshot");
+				{
+				// Return the drive number to the client
+				completionCode = static_cast<TInt>(iSuppliedSnapshotDriveNum);
+				break;
+				}
+			//
+			// Connection config getting/setting.
+			default:
+				{
+				Panic(KErrNotSupported);
+				break;
+				}
+			}
+		
+		if ((ipcMessageFn != EABMsgPrimeForCallback) &&
+			(ipcMessageFn != EABMsgPrimeForCallbackAndResponse) &&
+			(ipcMessageFn != EABMsgPrimeForCallbackAndResponseDes))
+			{
+			// If the message was a synchrnous one and has not already been completed, then complete
+			if (!aMessage.IsNull())
+				{
+				aMessage.Complete(completionCode);
+		        __LOG3("CABSession::ServiceL() - END - function: %d from client: %S - COMPLETED (%d)", aMessage.Function(), &name, completionCode);
+				}
+			}
+
+	#if defined(SBE_LOGGING_ENABLED)
+		if	(!aMessage.IsNull())
+			{
+			__LOG2("CABSession::ServiceL() - END - function: %d from client: %S - ASYNCH -> NOT COMPLETED", aMessage.Function(), &name);
+			}
+	#endif
+		}
+
+	inline CABServer& CABSession::Server() const
+	/**
+	Returns a non-cost reference to this CServer object.
+
+	@return The non-const reference to this.
+	*/
+		{
+		return *static_cast<CABServer*>(const_cast<CServer2*>(CSession2::Server()));
+		}
+
+	void CABSession::CheckCallbackAvailableL()
+	/**
+	Leave if the callback is not available
+	
+	@leave KErrNotReady if the callback hasn't been primed
+	*/
+		{
+		TBool primed = !iMessage.IsNull();
+		
+		__LOG2("CABSession::CheckCallbackAvailableL() - [0x%08x] primed: %d", iClientSID.iId, static_cast<TInt>(primed));
+		
+		if (iMisbehavingClient)
+			{
+			User::Leave(KErrAccessDenied);
+			}
+
+		if (!primed)
+			{
+			User::Leave(KErrNotReady);
+			}
+		}
+		
+	void CABSession::MakeCallbackAllSnapshotsSuppliedL()
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackAllSnapshotsSuppliedL() - [0x%08x] Calling AllSnapshotsSuppliedL", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackAllSnapshotsSupplied);
+
+		CheckCallbackAvailableL();
+		
+		// Make the callback
+		iMessage.WriteL(0, callbackPkg);
+		MadeCallback();
+		}
+	
+	void CABSession::MakeCallbackReceiveSnapshotDataL(TDriveNumber aDrive, TDesC8& aBuffer, 
+		TBool aLastSection)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aDrive Drive number that the snapshot relates to
+	@param aBuffer The snapshot
+	@param aLastSection Flag to indicate to the client whether this is the last of a multipart snapshot
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackReceiveSnapshotDataL() - [0x%08x] Calling ReceiveSnapshotData", iClientSID.iId);
+		
+		iSuppliedSnapshotDriveNum = aDrive;
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackReceiveSnapshotData);
+		TPckgC<TInt> sizePkg(aBuffer.Size());
+		TPckgC<TBool> lastSectionPkg(aLastSection);
+
+		iCallbackInProgress = EABCallbackReceiveSnapshotData;
+
+		iSendToClientBuffer.Set(aBuffer);
+		
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, sizePkg);
+		iMessage.WriteL(2, lastSectionPkg);
+		MadeCallback();
+
+		User::LeaveIfError(iABClientLeaveCode);
+		}
+
+	TUint CABSession::MakeCallbackGetExpectedDataSizeL(TDriveNumber aDrive)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aDrive The drive to get the expected data size for
+	@return The size of the data that will be transferred
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackGetExpectedDataSizeL() - [0x%08x] Calling GetExpectedDataSize", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackGetExpectedDataSize);
+		TPckgC<TDriveNumber> drivePkg(aDrive);
+		TUint returnedSize;
+
+		iCallbackInProgress = EABCallbackGetExpectedDataSize;
+
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, drivePkg);
+		MadeCallback();
+		
+		// Check that a response has been received
+		CheckCallbackAvailableL();
+		returnedSize = iMessage.Int3();
+		
+		return returnedSize;
+		}
+
+	void CABSession::MakeCallbackGetSnapshotDataL(TDriveNumber aDrive, TPtr8& aBuffer, TBool& aFinished)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aDrive Drive number that the snapshot is required for
+	@param aBuffer The snapshot
+	@param aFinished Flag to indicate to the client whether this is the last of a multipart snapshot
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackGetSnapshotDataL() - [0x%08x] Calling GetSnapshotData", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackGetSnapshotData);
+		TPckgC<TDriveNumber> drivePkg(aDrive);
+		TPckgC<TInt> size(aBuffer.Size());
+		
+		iCallbackInProgress = EABCallbackGetSnapshotData;
+
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, size);
+		iMessage.WriteL(2, drivePkg);
+		MadeCallback();
+
+		User::LeaveIfError(iABClientLeaveCode);
+		
+		// Read the buffer from the client
+		CheckCallbackAvailableL();
+
+		TInt bufLength = iMessage.GetDesLengthL(3);
+		aBuffer.SetLength(bufLength);
+
+		iMessage.ReadL(3, aBuffer);
+		aFinished = iReceiveFromClientFinished;
+		}
+
+	void CABSession::MakeCallbackInitialiseGetBackupDataL(TDriveNumber aDrive)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aDrive the Drive Number
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackInitialiseGetBackupDataL() - [0x%08x] Calling InitGetBackupData", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackInitialiseGetBackupData);
+		TPckgC<TDriveNumber> drivePkg(aDrive);
+		
+		iCallbackInProgress = EABCallbackInitialiseGetBackupData;
+		
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, drivePkg);
+		MadeCallback();
+
+		User::LeaveIfError(iABClientLeaveCode);
+		}
+
+	void CABSession::MakeCallbackGetBackupDataSectionL(TPtr8& aBuffer, TBool& aFinished)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aBuffer Data returned from the client 
+	@param aFinished Does the client have more data to send? 
+	*/
+		{
+        __LOG2("CABSession::MakeCallbackGetBackupDataSectionL() - START - aBuffer.Ptr(): 0x%08x, aBuffer.Length(): %d", aBuffer.Ptr(), aBuffer.Length());
+
+        __LOG1("CABSession::MakeCallbackGetBackupDataSectionL() - [0x%08x] Calling GetBackupDataSection", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackGetBackupDataSection);
+		TPckgC<TInt> sizePkg(aBuffer.Size());
+		
+		iCallbackInProgress = EABCallbackGetBackupDataSection;
+		
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, sizePkg);
+		MadeCallback();
+
+		User::LeaveIfError(iABClientLeaveCode);
+		CheckCallbackAvailableL();
+		
+		TInt bufLength = iMessage.GetDesLengthL(3);
+		aBuffer.SetLength(bufLength);
+        iMessage.ReadL(3, aBuffer);
+		aFinished = iReceiveFromClientFinished;
+ 
+        //__LOGDATA("CABSession::MakeCallbackGetBackupDataSectionL() - received %S", aBuffer.Ptr(), aBuffer.Length());
+
+        __LOG2("CABSession::MakeCallbackGetBackupDataSectionL() - END - aBuffer.Ptr(): 0x%08x, aBuffer.Length(): %d", aBuffer.Ptr(), aBuffer.Length());
+        }
+
+	void CABSession::MakeCallbackInitialiseRestoreBaseDataL(TDriveNumber aDrive)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aDrive The drive that's affected by the operation
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackInitialiseRestoreBaseDataL() - [0x%08x] Calling InitRestoreBaseData", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackInitialiseRestoreBaseDataSection);
+		TPckgC<TDriveNumber> drivePkg(aDrive);
+
+		iCallbackInProgress = EABCallbackInitialiseRestoreBaseDataSection;
+
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, drivePkg);
+		MadeCallback();
+
+		User::LeaveIfError(iABClientLeaveCode);
+		}
+
+	void CABSession::MakeCallbackRestoreBaseDataSectionL(TDesC8& aBuffer, TBool aFinished)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aBuffer The data to restore
+	@param aFinished Is this the last of a multi-part data call
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackRestoreBaseDataSectionL() - [0x%08x] Calling RestoreBaseDataSection", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackRestoreBaseDataSection);
+		TPckgC<TInt> sizePkg(aBuffer.Size());
+		TPckgC<TBool> lastSectionPkg(aFinished);
+		
+		iCallbackInProgress = EABCallbackRestoreBaseDataSection;
+
+		iSendToClientBuffer.Set(aBuffer);
+		
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, sizePkg);
+		iMessage.WriteL(2, lastSectionPkg);
+		MadeCallback();
+
+		User::LeaveIfError(iABClientLeaveCode);
+		}
+
+	void CABSession::MakeCallbackInitialiseRestoreIncrementDataL(TDriveNumber aDrive)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aDrive The drive that's affected by the operation
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackInitialiseRestoreIncrementDataL() - [0x%08x] Calling InitRestoreIncrementData", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackInitialiseRestoreIncrementData);
+		TPckgC<TDriveNumber> drivePkg(aDrive);
+
+		iCallbackInProgress = EABCallbackInitialiseRestoreIncrementData;
+
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, drivePkg);
+		MadeCallback();
+
+		User::LeaveIfError(iABClientLeaveCode);
+		}
+
+	void CABSession::MakeCallbackRestoreIncrementDataSectionL(TDesC8& aBuffer, TBool aFinished)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aBuffer The data to restore
+	@param aFinished Is this the last of a multi-part data call
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackRestoreIncrementDataSectionL() - [0x%08x] Calling RestoreIncrementData", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackRestoreIncrementDataSection);
+		TPckgC<TInt> sizePkg(aBuffer.Size());
+		TPckgC<TBool> lastSectionPkg(aFinished);
+
+		iCallbackInProgress = EABCallbackRestoreIncrementDataSection;
+
+		iSendToClientBuffer.Set(aBuffer);
+		
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, sizePkg);
+		iMessage.WriteL(2, lastSectionPkg);
+		MadeCallback();
+
+		User::LeaveIfError(iABClientLeaveCode);
+		}
+
+	void CABSession::MakeCallbackRestoreCompleteL(TDriveNumber aDrive)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aDrive The drive that's affected by the operation
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackRestoreCompleteL() - [0x%08x] Calling RestoreComplete", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackRestoreComplete);
+		TPckgC<TDriveNumber> drivePkg(aDrive);
+
+		iCallbackInProgress = EABCallbackRestoreComplete;
+
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, drivePkg);
+		MadeCallback();
+		}
+
+	void CABSession::MakeCallbackInitialiseGetProxyBackupDataL(TSecureId aSID, TDriveNumber aDrive)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aSID The SecureId of the Proxy
+	@param aDrive The drive that's affected by the operation
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackInitialiseGetProxyBackupDataL() - [0x%08x] Calling InitGetProxyBackupData", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackInitialiseGetProxyBackupData);
+		TPckgC<TSecureId> sidPkg(aSID);
+		TPckgC<TDriveNumber> drivePkg(aDrive);
+
+		iCallbackInProgress = EABCallbackInitialiseGetProxyBackupData;
+
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, sidPkg);
+		iMessage.WriteL(2, drivePkg);
+		MadeCallback();
+
+		User::LeaveIfError(iABClientLeaveCode);
+		}
+
+	void CABSession::MakeCallbackInitialiseRestoreProxyBaseDataL(TSecureId aSID, TDriveNumber aDrive)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aSID The SecureId of the Proxy
+	@param aDrive The drive that's affected by the operation
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackInitialiseRestoreProxyBaseDataL() - [0x%08x] Calling InitRestoreProxyBaseData", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackInitialiseRestoreProxyBaseData);
+		TPckgC<TSecureId> sidPkg(aSID);
+		TPckgC<TDriveNumber> drivePkg(aDrive);
+
+		iCallbackInProgress = EABCallbackInitialiseRestoreProxyBaseData;
+
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, sidPkg);
+		iMessage.WriteL(2, drivePkg);
+		MadeCallback();
+
+		User::LeaveIfError(iABClientLeaveCode);
+		}
+
+	void CABSession::MakeCallbackTerminateMultiStageOperationL()
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackTerminateMultiStageOperationL() - [0x%08x] Calling TermiateMultiStageOp", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackTerminateMultiStageOperation);
+
+		iCallbackInProgress = EABCallbackTerminateMultiStageOperation;
+
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		MadeCallback();
+		}
+
+	TUint CABSession::MakeCallbackGetDataChecksumL(TDriveNumber aDrive)
+	/**
+	Synchronous call to make the callback on the active backup client
+	
+	@param aDrive The drive that's affected by the operation
+	@return The checksum of the data
+	*/
+		{
+		__LOG1("CABSession::MakeCallbackGetDataChecksumL() - [0x%08x] Calling GetDataChecksum", iClientSID.iId);
+
+		TPckgC<TABCallbackCommands> callbackPkg(EABCallbackGetDataChecksum);
+		TPckgC<TDriveNumber> drivePkg(aDrive);
+		TPckgBuf<TUint> returnPkg;
+
+		iCallbackInProgress = EABCallbackGetDataChecksum;
+
+		CheckCallbackAvailableL();
+		iMessage.WriteL(0, callbackPkg);
+		iMessage.WriteL(1, drivePkg);
+		MadeCallback();
+		
+		iMessage.ReadL(3, returnPkg);
+		
+		return returnPkg();
+		}
+	
+	void CABSession::SetInvalid()
+	/** 
+	Invalidate this session, so that this session can not be 
+	used in sequent backup/restore event
+	*/
+		{
+		iInvalid = ETrue;
+		}
+		
+	TBool CABSession::Invalidated()
+	/** 
+	Return whether this session has been invalidated
+		 
+	@Return ETrue if this session aleady be invalidated;otherwise EFalse
+	*/
+		{
+		return iInvalid;
+		}
+	}
+
+