IMPSengine/client/src/impshandler.cpp
changeset 0 094583676ce7
--- /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 <e32std.h>
+
+#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