// 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 CActiveBackupClient class.
//
//
/**
@file
*/
#include "abachandler.h"
#include "abclientsession.h"
#include "panic.h"
namespace conn
{
CActiveBackupCallbackHandler* CActiveBackupCallbackHandler::NewL(MActiveBackupDataClient* aABDC,
RABClientSession& aClientSession)
/**
Symbian first phase constructor
@param aABDC pointer to the client's callback implementation
@param aClientSession reference to the client's session
@return Pointer to a created CActiveBackupCallbackHandler object
*/
{
CActiveBackupCallbackHandler* self = new (ELeave) CActiveBackupCallbackHandler(aABDC, aClientSession);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
CActiveBackupCallbackHandler::CActiveBackupCallbackHandler(MActiveBackupDataClient* aABDC,
RABClientSession& aClientSession) : CActive(EPriorityNormal), iActiveBackupDataClient(aABDC),
iClientSession(aClientSession), iTransferBuffer(NULL)
/**
C++ Constructor
@param aABDC pointer to the client's callback implementation
@param aClientSession reference to the client's session
@panic KErrArgument if the pointer aABDC is NULL
*/
{
__ASSERT_DEBUG(aABDC, Panic(KErrArgument));
}
CActiveBackupCallbackHandler::~CActiveBackupCallbackHandler()
/**
C++ Destructor
*/
{
// Cancel any outstanding Async requests (i.e. close down the callback interface)
Cancel();
delete iTransferBuffer;
}
void CActiveBackupCallbackHandler::RunL()
/**
Handle messages "initiated" by the server. Because of IPC limitations, the client primes the
server with a message containing modifiable package buffers that are filled with identifiers
and arguments for the callback interface
*/
{
if (iStatus == KErrNone)
{
switch(iCallbackCommand())
{
case EABCallbackAllSnapshotsSupplied:
{
iActiveBackupDataClient->AllSnapshotsSuppliedL();
PrimeServerForCallbackL();
} break;
case EABCallbackReceiveSnapshotData:
{
TDriveNumber driveNum = EDriveC; // Initialise to keep the compiler happy
HBufC8* pReceivedData = iClientSession.GetDataFromServerLC(iCallbackArg1(),
EABCallbackReceiveSnapshotData, driveNum);
// Call the client method for handling receipt of the snapshot
iActiveBackupDataClient->ReceiveSnapshotDataL(driveNum,
*pReceivedData, static_cast<TBool>(iCallbackArg2()));
// Reprime the server
PrimeServerForCallbackL();
CleanupStack::PopAndDestroy(pReceivedData);
} break;
case EABCallbackGetExpectedDataSize:
{
TUint dataSize = iActiveBackupDataClient->GetExpectedDataSize(static_cast<TDriveNumber>(iCallbackArg1()));
// Reprime the server
PrimeServerForCallbackWithResponseL(dataSize);
} break;
case EABCallbackGetSnapshotData:
{
// Create an empty TPtr8 to point at the buffer to fill
TPtr8 bufferToSend(CreateFixedBufferL());
TBool finished = ETrue;
// Zero our descriptor so that it can be refilled
bufferToSend.Zero();
// Callback the AB client to populate our descriptor
iActiveBackupDataClient->GetSnapshotDataL(static_cast<TDriveNumber>(iCallbackArg1()),
bufferToSend, finished);
// Send the length and some other info to the server to allow it to prepare for the actual transfer
iClientSession.SendDataLengthToServerL(bufferToSend, finished, EABCallbackGetSnapshotData);
iTransferBuffer->Des().SetLength(bufferToSend.Length());
// Send the actual data back to the server and prime for the next callback
PrimeServerForCallbackWithResponseL(*iTransferBuffer);
} break;
case EABCallbackInitialiseGetBackupData:
{
iActiveBackupDataClient->InitialiseGetBackupDataL(static_cast<TDriveNumber>(iCallbackArg1()));
// Reprime the server
PrimeServerForCallbackL();
} break;
case EABCallbackGetBackupDataSection:
{
// Create an empty TPtr8 to point at the buffer to fill
TPtr8 bufferToSend(CreateFixedBufferL());
TBool finished = ETrue;
// Zero our descriptor so that it can be refilled
bufferToSend.Zero();
// Callback the AB client to populate our descriptor
iActiveBackupDataClient->GetBackupDataSectionL(bufferToSend, finished);
// Send the length and some other info to the server to allow it to prepare for the actual transfer
iClientSession.SendDataLengthToServerL(bufferToSend, finished, EABCallbackGetBackupDataSection);
iTransferBuffer->Des().SetLength(bufferToSend.Length());
// Send the actual data back to the server and prime for the next callback
PrimeServerForCallbackWithResponseL(*iTransferBuffer);
} break;
case EABCallbackInitialiseRestoreBaseDataSection:
{
iActiveBackupDataClient->InitialiseRestoreBaseDataL(static_cast<TDriveNumber>(iCallbackArg1()));
// Reprime the server
PrimeServerForCallbackL();
} break;
case EABCallbackRestoreBaseDataSection:
{
HBufC8* pReceivedData = iClientSession.GetDataFromServerLC(iCallbackArg1(),
EABCallbackRestoreBaseDataSection);
// Call the client method for handling receipt of the snapshot
iActiveBackupDataClient->RestoreBaseDataSectionL(*pReceivedData,
static_cast<TBool>(iCallbackArg2()));
// Reprime the server
PrimeServerForCallbackL();
CleanupStack::PopAndDestroy(pReceivedData);
} break;
case EABCallbackInitialiseRestoreIncrementData:
{
iActiveBackupDataClient->InitialiseRestoreIncrementDataL(static_cast<TDriveNumber>(iCallbackArg1()));
// Reprime the server
PrimeServerForCallbackL();
} break;
case EABCallbackRestoreIncrementDataSection:
{
HBufC8* pReceivedData = iClientSession.GetDataFromServerLC(iCallbackArg1(),
EABCallbackRestoreIncrementDataSection);
// Call the client method for handling receipt of the snapshot
iActiveBackupDataClient->RestoreIncrementDataSectionL(*pReceivedData,
static_cast<TBool>(iCallbackArg2()));
// Reprime the server
PrimeServerForCallbackL();
CleanupStack::PopAndDestroy(pReceivedData);
} break;
case EABCallbackRestoreComplete:
{
iActiveBackupDataClient->RestoreComplete(static_cast<TDriveNumber>(iCallbackArg1()));
// Reprime the server
PrimeServerForCallbackL();
} break;
case EABCallbackTerminateMultiStageOperation:
{
iActiveBackupDataClient->TerminateMultiStageOperation();
// Reprime the server
PrimeServerForCallbackL();
} break;
case EABCallbackGetDataChecksum:
{
iActiveBackupDataClient->GetDataChecksum(static_cast<TDriveNumber>(iCallbackArg1()));
// Reprime the server
PrimeServerForCallbackL();
} break;
case EABCallbackInitialiseGetProxyBackupData:
{
iActiveBackupDataClient->InitialiseGetProxyBackupDataL(static_cast<TSecureId>(iCallbackArg1()),
static_cast<TDriveNumber>(iCallbackArg2()));
// Reprime the server
PrimeServerForCallbackL();
} break;
case EABCallbackInitialiseRestoreProxyBaseData:
{
iActiveBackupDataClient->InitialiseRestoreProxyBaseDataL(static_cast<TSecureId>(
iCallbackArg1()), static_cast<TDriveNumber>(iCallbackArg2()));
// Reprime the server
PrimeServerForCallbackL();
} break;
default:
{
// Call the server to leave with KErrNotSupported
User::Leave(KErrNotSupported);
}
}
// Set us up for another call
SetActive();
}
}
void CActiveBackupCallbackHandler::PrimeServerForCallbackL()
/**
Reprime the server with a new IPC message to respond to
*/
{
iClientSession.PrimeServerForCallbackL(iCallbackCommand, iCallbackArg1, iCallbackArg2, iStatus);
}
void CActiveBackupCallbackHandler::PrimeServerForCallbackWithResponseL(TInt aResponse)
/**
Reprime the server with a new IPC message to respond to, sending the result of the previous callback
@param aResponse The response to send back to the server i.e. the result of the last callback made
*/
{
iClientSession.PrimeServerForCallbackWithResponseL(iCallbackCommand, iCallbackArg1, iCallbackArg2, aResponse, iStatus);
}
void CActiveBackupCallbackHandler::PrimeServerForCallbackWithResponseL(TDesC8& aResponse)
/**
Reprime the server with a new IPC message to respond to, sending the result of the previous callback
@param aResponse The response to send back to the server i.e. the result of the last callback made
*/
{
iClientSession.PrimeServerForCallbackWithResponseL(iCallbackCommand, iCallbackArg1, iCallbackArg2, aResponse, iStatus);
}
TInt CActiveBackupCallbackHandler::RunError(TInt aError)
/**
Handle any leaves that occur from within the RunL and hence from the callback methods. In order
to propagate leaves over to the PC client, they must be sent to the backup engine to leave to the
client
@param aError The leave code that has been trapped from within the RunL. Propagate this code to the engine
@return Any unhandled leave code
*/
{
iClientSession.PropagateLeave(aError);
PrimeServerForCallbackL();
SetActive();
return KErrNone; // Is this correct or do we return the error code even though it's been handled?
}
void CActiveBackupCallbackHandler::DoCancel()
/**
Immediately cancel any outstanding calls to the backup engine
*/
{
// we can't do anything with the error code here
TRAP_IGNORE(iClientSession.CancelServerCallbackL());
}
void CActiveBackupCallbackHandler::ConstructL()
/**
Add this object to the scheduler
@panic KErrNotFound Debug only - If an ActiveScheduler is not installed
@leave Release only - If an ActiveScheduler is not installed
*/
{
if (!CActiveScheduler::Current())
{
__ASSERT_DEBUG(0, Panic(KErrNotFound));
}
// Add this AO to the scheduler
CActiveScheduler::Add(this);
SetActive();
}
void CActiveBackupCallbackHandler::StartListeningForServerMessagesL()
/**
Send an asynchronous IPC message to the server in order that it has a vehicle for "initiating"
a callback on iActiveBackupDataClient. This should only be called once as it will start the
active scheduler
*/
{
// Prime the server with the first prime for callback IPC message
PrimeServerForCallbackL();
}
TPtr8 CActiveBackupCallbackHandler::CreateFixedBufferL()
/**
Creates a buffer of the exact size.
*/
{
delete iTransferBuffer;
iTransferBuffer = NULL;
iTransferBuffer = HBufC8::NewL(iCallbackArg1());
return TPtr8(const_cast<TUint8*>(iTransferBuffer->Ptr()), iCallbackArg1());
}
}