diff -r 000000000000 -r 094583676ce7 IMPSengine/client/src/impshandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IMPSengine/client/src/impshandler.cpp Thu Dec 17 08:41:52 2009 +0200 @@ -0,0 +1,489 @@ +/* +* Copyright (c) 2002-2005 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: +* handler class for imps common client. +* +*/ + + +// INCLUDE FILES +#include + +#include "impsclient.h" +#include "impsfields.h" +#include "impspacked.h" +#include "impskey.h" +#include "impshandler.h" +#include "impsutils.h" +#include "impsservercommon.h" +#include "impserrors.h" +#include "impsdetailed.h" +#include "impsdataaccessor.h" +#include "impscdatautils.h" + +// MACROS +#ifndef _DEBUG +#define _NO_IMPS_LOGGING_ +#endif + +// ================= MEMBER FUNCTIONS ======================= + +// ----------------------------------------------------------------------------- +// TWvBuf::TWvBuf +// ----------------------------------------------------------------------------- + +TWvBuf::TWvBuf( HBufC8* aBuf ) : + iPtr( aBuf->Des() ) + {} + +// ---------------------------------------------------------------------------- +// CImpsHandler2::CImpsHandler2() +// ---------------------------------------------------------------------------- +CImpsHandler2::CImpsHandler2( + TInt aPriority, + RImpsClient2& aClient ) : + CActive( aPriority ), + iClient( aClient ), + iBody( NULL ), + iPtrStore( NULL ) + { + CActiveScheduler::Add( this ); + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::~CImpsHandler2() +// ---------------------------------------------------------------------------- + CImpsHandler2::~CImpsHandler2() + { + + delete iBody; + delete iFields; + delete iPtrStore; + delete iBusyTimer; + + if ( iDestroyedPtr ) + { + // We are called via own RunL! + *iDestroyedPtr = ETrue; + iDestroyedPtr = NULL; + } + + // Do not call Cancel() here, because of it is called outside if needed. + // This is observer for server thread, so do not cancel yourself! + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::StartRun() +// ---------------------------------------------------------------------------- +void CImpsHandler2::StartRun() + { + + // Start to wait push messages from the server + iStatus = KRequestPending; + SetActive(); + iFields->Reset(); + + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::RunL() +// ---------------------------------------------------------------------------- +void CImpsHandler2::RunL() + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log(_L("CImpsHandler2::RunL begin status=%d h=%d cli=%d"), + iStatus.Int(), (TInt)this, (TInt)&iClient ); +#endif + + // Set the member to point to stack variable + TBool destroyed( EFalse ); + iDestroyedPtr = &destroyed; + // Is the event handled + TBool handled( EFalse ); + TInt err = KErrNone; + + + // Server is busy + if ( iStatus == KErrServerBusy ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log(_L("CImpsHandler2::Starting timer") ); +#endif + iBusyTimer->Start(); + return; + } + + // Server is cancelled + if ( iStatus == KErrCancel || iStatus == KErrServerTerminated ) + { + return; + } + + // special "error" codes for status changes + if ( iStatus == KImpsOnlineStatus || + iStatus == KImpsOfflineStatus || + iStatus == KImpsNotLoggedStatus || + iStatus == KImpsErrorShuttingDown ) + { + TImpsServiceStatus newStatus = EImps_ON_LINE; + if ( iStatus == KImpsNotLoggedStatus ) + { + newStatus = EImps_NOT_LOGGED; + } + else if ( iStatus == KImpsErrorShuttingDown ) + { + newStatus = EImps_SHUTTING_DOWN; + } + if ( iStatusHandler ) + { + TInt err ( KErrNone ); + TRAP( err, iStatusHandler->HandleStatusChangeL( newStatus , *iClient.CspIdentifier() )); + handled = ETrue; + } + } + + // Destructor sets this to ETrue. An application may have called unregister + if ( destroyed ) + { + return; + } + + TInt dataLength = iStatus.Int(); + + // Check first if a special OOM error event + if ( dataLength > 0 && ( dataLength & KImpsOOMReply ) ) + { + TInt errId = dataLength & KImpsOOMReplyOpId; + dataLength = 0; + err = KErrNoMemory; + // This cannot leave with NULL fields parameter + HandleErrorEventL( errId, KErrNoMemory, NULL ); + } + + // Read the data if any to iFields + // Check if need to read message body separately + TBool comp( ETrue ); + if ( dataLength > 0 ) + { + TRAP( err, comp = ReadDataL( dataLength ) ); + } + + if ( !err && !handled && comp ) + { + // Not here if reading of data fails + CImpsFields* errF = ( dataLength > 0 ? iFields : NULL ); + { // These parenthises must be here. + // Otherwise the program will crash + // This is releated to the destroying this object + // and trap frame. + + // this trap handles all internal errors + // errors caused by callbacks are trapped elsewhere + TRAP( err, HandleEventL( errF ) ); + if ( err != KErrNone ) + { + SImpsEventData* event = (SImpsEventData*)iEventData.Ptr(); + HandleErrorEventL( event->iOpCode, err, NULL ); + } + } + } + + // Destructor sets this to ETrue, nice trick. + if ( !destroyed ) + { + // Activate again and reset data. + // This must not leave but has to ask for more by + // calling either EventHandled() or EventBody(). + StartRun(); + TInt bufSize = CurrentSize(); +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log(_L("CImpsHandler2: comp=%d bufSize=%d h=%d cli=%d"), + comp, bufSize, (TInt)this, (TInt)&iClient ); +#endif + if ( comp ) + { + // Message handling is complete. Free the buffer if the + // message was a big one. + if ( bufSize > KImpsIPCThreshold ) + { + ResetBuffers(); + } + EventHandled(); + } + else + { + if ( CurrentSize() < dataLength ) + { + // allocate memory if needed + ResetBuffers(); + TRAP( err, + { + iBody = HBufC8::NewL( dataLength ); + iPtrStore = new (ELeave) TWvBuf( iBody ); + } ); + } + if ( err ) + { + ResetBuffers(); + EventHandled(); + } + else + { + // Ask rest of the message + EventBody(); + } + } + } + else + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log(_L("CImpsHandler2: DESTROYED **** cli=%d"), (TInt)&iClient ); +#endif + } + + iDestroyedPtr = NULL; + +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log(_L("CImpsHandler2: RunL ends cli=%d"), (TInt)&iClient); +#endif + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::ReadDataL() +// ---------------------------------------------------------------------------- +TBool CImpsHandler2::ReadDataL( TInt aLength ) + { + // Event data has been given in next event request + SImpsEventData* event = (SImpsEventData*)iEventData.Ptr(); + + if ( event->iMessageBody ) + { + // verify iBody.Length and aLength + __ASSERT_DEBUG( iBody && aLength > 0 && iBody->Des().Length() == aLength, + User::Panic( KImpsPanicCategory, EImpsCorrupted ) ); + + // Unpack the streaming + iFields->Reset(); + TImpsPackedEntity packed( iBody ); + packed.UnpackEntityL( *iFields ); + } + else if ( aLength > CurrentSize() ) + { + // This means event without body + return EFalse; + } + + return ETrue; + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::DoCancel() +// ---------------------------------------------------------------------------- +void CImpsHandler2::DoCancel() + { + + // Complete the request with error + TRequestStatus* s = &iStatus; + User::RequestComplete( s, KErrCancel ); + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2:: SetStatusHandlerL +// ---------------------------------------------------------------------------- +void CImpsHandler2::SetStatusHandlerL( MImpsStatusHandler2* aObs) + { + + iStatusHandler = aObs; + // register new handler + if ( iStatusHandler ) + { + DoRegisterStatusHandlerL( ); + } + else + { + DoUnregisterStatusHandlerL( ); + } + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2:: SetErrorHandlerL +// ---------------------------------------------------------------------------- +void CImpsHandler2::SetErrorHandlerL( MImpsErrorHandler2* aObs) + { + + iErrorHandler = aObs; + // register new handler + if ( iErrorHandler ) + { + DoRegisterErrorHandlerL( ); + } + else + { + DoUnregisterErrorHandlerL( ); + } + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::DoRegisterStatusHandlerL +// ---------------------------------------------------------------------------- +void CImpsHandler2::DoRegisterStatusHandlerL( ) + { + TInt ret = iClient.SendReceive( EImpsServStatusReg, TIpcArgs() ); + User::LeaveIfError( ret ); + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::DoUnregisterStatusHandlerL +// ---------------------------------------------------------------------------- +void CImpsHandler2::DoUnregisterStatusHandlerL( ) + { + TInt ret = iClient.SendReceive( EImpsServStatusUnreg, TIpcArgs() ); + User::LeaveIfError( ret ); + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::DoRegisterErrorHandlerL +// ---------------------------------------------------------------------------- +void CImpsHandler2::DoRegisterErrorHandlerL( ) + { + TInt ret = iClient.SendReceive( EImpsServDetailedReg, TIpcArgs() ); + User::LeaveIfError( ret ); + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::DoUnregisterErrorHandlerL +// ---------------------------------------------------------------------------- +void CImpsHandler2::DoUnregisterErrorHandlerL( ) + { + TInt ret = iClient.SendReceive( EImpsServDetailedUnreg, TIpcArgs() ); + User::LeaveIfError( ret ); + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::HandleErrorEventL +// ---------------------------------------------------------------------------- +void CImpsHandler2::HandleErrorEventL( + TInt aOpCode, TInt aStatus, CImpsFields* aFields) + { + +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log(_L("CImpsHandler2: HandleErrorEventL opid=%d stat=%d cli=%d"), + aOpCode, aStatus, (TInt)&iClient ); +#endif + + + if ( !iErrorHandler ) + { + // handler should exist + return; + } + + if ( aFields == NULL ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log(_L("CImpsHandler2: HandleError call")); +#endif + // This has been internal error + iErrorHandler->HandleErrorL( + aStatus, + aOpCode, + NULL, + NULL, + *iClient.CspIdentifier() ); + return; + } + + + CImpsDetailed* myDet = new (ELeave) CImpsDetailed(4); + CleanupStack::PushL( myDet ); // <<< myDet + TPtrC descr; + descr.Set( KNullDesC ); + + CImpsKey* myKey = CImpsKey::NewLC(); // <<< myKey + CImpsDataAccessor* myAc = CImpsDataAccessor::NewL( aFields ); + CleanupStack::PushL( myAc ); // <<< myAc + + TImpsCDataUtils::GetDetailedResultL( myKey, myAc, descr, myDet ); + CleanupStack::PopAndDestroy(2); // >>> myKey, myAc + +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log(_L("CImpsHandler2: HandleError call"), + aOpCode, aStatus ); +#endif + + iErrorHandler->HandleErrorL( + aStatus, + aOpCode, + &descr, + myDet, + *iClient.CspIdentifier() ); + + CleanupStack::PopAndDestroy(1); // >>> myDet + } + +// ----------------------------------------------------------------------------- +// CImpsHandler2::ConstructL +// ----------------------------------------------------------------------------- +void CImpsHandler2::ConstructL() + { + iFields = CImpsFields::NewL(); + iBusyTimer = new (ELeave) CImpsHandlerTimer( CActive::EPriorityStandard, *this); + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::EventHandled() +// ---------------------------------------------------------------------------- +void CImpsHandler2::EventHandled() + { + TInt bufSize = CurrentSize(); +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log(_L("CImpsHandler2: EImpsServNextEvent bufSize=%d h=%d cli=%d"), + bufSize, (TInt)this, (TInt)&iClient ); +#endif + iArgs.Set( 0, &iEventData ); + iArgs.Set( 1, &iPtrStore->iPtr ); + iArgs.Set( 2, bufSize ); + iClient.SendReceive( EImpsServNextEvent, iArgs, iStatus ); + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::EventBody() +// ---------------------------------------------------------------------------- +void CImpsHandler2::EventBody() + { + __ASSERT_DEBUG( iBody && iPtrStore, + User::Panic( KImpsPanicCategory, EImpsCorrupted ) ); + TInt bufSize = CurrentSize(); +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log(_L("CImpsHandler2: EImpsServEventBody bufSize=%d h=%d cli=%d"), + bufSize, (TInt)this, (TInt)&iClient ); +#endif + iArgs.Set( 0, &iEventData ); + iArgs.Set( 1, &iPtrStore->iPtr ); + iArgs.Set( 2, bufSize ); + iClient.SendReceive( EImpsServEventBody, iArgs, iStatus ); + } + +// ---------------------------------------------------------------------------- +// CImpsHandler2::ResetBuffers() +// ---------------------------------------------------------------------------- +void CImpsHandler2::ResetBuffers() + { + delete iPtrStore; + iPtrStore = NULL; + delete iBody; + iBody = NULL; + } + +// End of File