--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/engine/src/catalogsclientserverserversession.cpp Tue Jan 26 12:06:03 2010 +0200
@@ -0,0 +1,546 @@
+/*
+* Copyright (c) 2006 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 CCatalogsClientServerServerSession
+*
+*/
+
+
+#include <e32kpan.h>
+
+#include "catalogsclientserverserversession.h"
+#include "catalogsserverdefines.h"
+#include "catalogscommunicable.h"
+#include "catalogsbasemessageimpl.h"
+#include "catalogsincompletemessage.h"
+#include "catalogscontextimpl.h"
+#include "catalogsdebug.h"
+
+
+// ======== LOCAL FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Cleanupfunction for cleanupitem usage. Closes CObject based
+// object as many times as needed to destroy it when removed
+// from cleanupstack.
+// ---------------------------------------------------------------------------
+//
+void CCatalogsClientServerServerSession::CleanupCObjectBasedClass( TAny* aCObject )
+ {
+ CObject* convertedCObject = ( static_cast< CObject* > ( aCObject ) );
+ TInt accessCount = convertedCObject->AccessCount();
+ while ( accessCount > 0 )
+ {
+ convertedCObject->Close();
+ --accessCount;
+ }
+ // Now that last reference is closed, aCObject is destroyed
+ }
+
+
+// ======== MEMBER FUNCTIONS ========
+
+CCatalogsClientServerServerSession* CCatalogsClientServerServerSession::NewL(
+ RThread& aClient,
+ CCatalogsClientServerServer& aServer )
+ {
+ CCatalogsClientServerServerSession* self =
+ CCatalogsClientServerServerSession::NewLC( aClient, aServer );
+ CleanupStack::Pop(self) ;
+ return self ;
+ }
+
+CCatalogsClientServerServerSession* CCatalogsClientServerServerSession::
+ NewLC( RThread& aClient, CCatalogsClientServerServer& aServer )
+ {
+ CCatalogsClientServerServerSession* self =
+ new (ELeave) CCatalogsClientServerServerSession( aClient, aServer,
+ aServer.NewInstanceId() );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+CCatalogsClientServerServerSession::CCatalogsClientServerServerSession(
+ RThread& /*aClient*/,
+ CCatalogsClientServerServer& aServer,
+ TInt aInstanceId ) :
+ CSession2(),
+ iClientSideDownAnnounced( ENotInformed ),
+ iServer( aServer ),
+ iInstanceId( aInstanceId )
+ {
+ }
+
+CCatalogsClientServerServerSession::~CCatalogsClientServerServerSession()
+ {
+ DLTRACEIN((""));
+ ClientSideSessionDown();
+ DLTRACE(("Deleting context"));
+ delete iContext;
+ iServer.DecrementSessions();
+ DLTRACEOUT((""));
+ }
+
+void CCatalogsClientServerServerSession::ConstructL()
+ {
+ iServer.IncrementSessions();
+ iMessageHandlers = CObjectIx::NewL();
+ iIncompleteMessageContainer = iServer.NewContainerL();
+ iIncompleteMessages = CObjectIx::NewL();
+
+ }
+
+void CCatalogsClientServerServerSession::ClientSideSessionDown()
+ {
+ DLTRACEIN((""));
+ if ( iClientSideDownAnnounced == ENotInformed )
+ {
+ DLTRACE(("Delete incomplete messages"));
+ // Incomplete messages act as receivers of messages as well
+ // as nodes etc.
+ delete iIncompleteMessages;
+ iIncompleteMessages = NULL;
+
+ // In examples, container is simply deleted, but here
+ // this ends up making a KERN-EXEC 3. Probably container is
+ // removed for a second time when the container-index is removed.
+ if ( iIncompleteMessageContainer != NULL )
+ {
+ DLTRACE(("Remove container"));
+ iServer.RemoveContainer( iIncompleteMessageContainer );
+ DLTRACE(("Container removed"));
+ }
+ iIncompleteMessageContainer = NULL;
+
+
+ CloseMessageHandlers();
+
+ DLTRACE(("Handle session removal"));
+ // Inform possibly interested objects of session removal
+ // so they know that this session does not exist anymore
+ iServer.HandleSessionRemoval( *this );
+
+ iClientSideDownAnnounced = EInformed;
+ }
+
+ DLTRACEOUT((""));
+ }
+
+
+TInt CCatalogsClientServerServerSession::WriteToLargerDesL(
+ const TDesC8& aOutputData,
+ TInt aStatus )
+ {
+ CCatalogsIncompleteMessage* incompleteMessage =
+ CCatalogsIncompleteMessage::NewL();
+
+ // NOTICE: Because a CObject-derived object cannot be deleted
+ // when its reference count is not zero, we use a
+ // cleanup-item. Another way could be to do it in the
+ // destructor of the CObject-derived object, but
+ // it could enable unintended destruction of the object.?
+ TCleanupItem cleanupCObjectInfo( CleanupCObjectBasedClass,
+ incompleteMessage );
+ CleanupStack::PushL( cleanupCObjectInfo );
+
+ incompleteMessage->SetMessageL( aOutputData, aStatus );
+ iIncompleteMessageContainer->AddL( incompleteMessage );
+ TInt handle = iIncompleteMessages->AddL( incompleteMessage );
+
+ CleanupStack::Pop( incompleteMessage );
+ return handle;
+ }
+
+TInt CCatalogsClientServerServerSession::WriteToLargerDesL(
+ const TDesC16& aOutputData,
+ TInt aStatus )
+ {
+ CCatalogsIncompleteMessage* incompleteMessage =
+ CCatalogsIncompleteMessage::NewL();
+
+ // NOTICE: Because a CObject-derived object cannot be deleted
+ // when its reference count is not zero, we use a
+ // cleanup-item. Another way could be to do it in the
+ // destructor of the CObject-derived object, but
+ // it could enable unintended destruction of the object.?
+ TCleanupItem cleanupCObjectInfo( CleanupCObjectBasedClass,
+ incompleteMessage );
+ CleanupStack::PushL( cleanupCObjectInfo );
+
+ incompleteMessage->SetMessageL( aOutputData, aStatus );
+ iIncompleteMessageContainer->AddL( incompleteMessage );
+ TInt handle = iIncompleteMessages->AddL( incompleteMessage );
+
+ CleanupStack::Pop( incompleteMessage );
+ return handle;
+ }
+
+void CCatalogsClientServerServerSession::RemoveIncompleteMessage( TInt aHandle )
+ {
+ iIncompleteMessages->Remove( aHandle );
+ }
+
+void CCatalogsClientServerServerSession::ServiceL( const RMessage2& aMessage )
+ {
+ DLTRACEIN((""));
+
+ // If ServiceL leaves, the framework calls ServiceError which by default
+ // completes the message with the leave code if it has not been completed
+ // yet
+ HandleMessageL( aMessage );
+ }
+
+TInt CCatalogsClientServerServerSession::AddObjectL(
+ CObject* aObject )
+ {
+ iServer.AddObjectToContainerL( aObject );
+ TInt handle( iMessageHandlers->AddL( aObject ) );
+ // Because add to the ix does not call Open() of the CObject,
+ // we have to do it ourselves
+ User::LeaveIfError( aObject->Open() );
+ return handle;
+ }
+
+void CCatalogsClientServerServerSession::RemoveObject( TInt aHandle )
+ {
+ // This closes the CObject once.
+ iMessageHandlers->Remove( aHandle );
+ }
+
+MCatalogsContext& CCatalogsClientServerServerSession::Context()
+ {
+ return *iContext;
+ }
+
+
+const MCatalogsContext* CCatalogsClientServerServerSession::ContextPtr() const
+ {
+ return iContext;
+ }
+
+
+void CCatalogsClientServerServerSession::HandleMessageL(
+ const RMessage2& aMessage )
+ {
+ DLTRACEIN(("Function: %X", aMessage.Function() ));
+
+ // NOTICE: If aMessage has to be stored and used later
+ // then copy it and use the copy instead.
+
+ if ( iClientSideDownAnnounced == EInformed )
+ {
+ // Do not communicate to client anymore
+ // client-side session is going down
+ return;
+ }
+ else if( ( aMessage.Function() != ECatalogsCreateContext )
+ && ( iContext == NULL ) )
+ {
+ DLERROR(( "Completing message with KErrNotReady" ));
+ aMessage.Complete( KErrNotReady );
+ }
+
+
+ if( aMessage.Function() == ECatalogsExternalMessage
+ || aMessage.Function() == ECatalogsExternalAllocMessage )
+ {
+ HandleExternalMessageL( aMessage );
+ }
+ else
+ {
+ HandleInternalMessageL( aMessage );
+ }
+ DLTRACEOUT((""));
+ }
+
+void CCatalogsClientServerServerSession::HandleExternalMessageL(
+ const RMessage2& aMessage )
+ {
+ DLTRACEIN((""));
+ TPckgBuf<TInt> handle;
+ aMessage.ReadL( 1, handle );
+
+
+ CCatalogsCommunicable* receiver = ReceiverFromHandle( handle() );
+
+ DLTRACE(("Receiver for message: %X", receiver ));
+
+ if( !receiver )
+ {
+ PanicClient( aMessage, EBadHandle );
+ return;
+ }
+
+
+ CCatalogsBaseMessageImpl* baseMessage =
+ CCatalogsBaseMessageImpl::NewLC( aMessage,
+ *this,
+ handle() );
+ TPckgBuf<TInt> funcNumber;
+ aMessage.ReadL( 0, funcNumber );
+
+ CleanupStack::Pop( baseMessage );
+
+ DLTRACE(("Passing message"));
+
+ // Now the message is already passed to the receiver
+ // and it is its duty to use it to inform of possible
+ // error situations
+ // -> Nothing is done here
+ receiver->ReceiveMessage( baseMessage, funcNumber() );
+
+ DLTRACEOUT(("Message passed"));
+ }
+
+void CCatalogsClientServerServerSession::HandleInternalMessageL(
+ const RMessage2& aMessage )
+ {
+ DLTRACEIN((""));
+ switch( aMessage.Function() )
+ {
+ case ECatalogsCompleteMessage:
+ {
+ DLTRACE(("ECatalogsCompleteMessage"));
+ TPckgBuf<TInt> handle;
+ aMessage.ReadL( 1, handle );
+
+ CCatalogsIncompleteMessage* incompleteMessage =
+ IncompleteMessageFromHandle( handle() );
+ if( !incompleteMessage )
+ {
+ PanicClient( aMessage, EBadHandle );
+ return;
+ }
+
+ const TDesC8& message = incompleteMessage->Message();
+ TInt returnValue = incompleteMessage->ReturnValue();
+
+ DLINFO(( "Writing message" ));
+ TRAPD( error, aMessage.WriteL( 3, message ) );
+ if ( error != KErrNone )
+ {
+ RemoveIncompleteMessage( handle() );
+ User::Leave( error );
+ }
+
+ DLINFO(( "Completing message with %d", returnValue ));
+ aMessage.Complete( returnValue );
+
+ RemoveIncompleteMessage( handle() );
+ break;
+ }
+
+
+ case ECatalogsCompleteMessageWide:
+ {
+ DLTRACE(("ECatalogsCompleteMessageWide"));
+ TPckgBuf<TInt> handle;
+ aMessage.ReadL( 1, handle );
+
+ CCatalogsIncompleteMessage* incompleteMessage =
+ IncompleteMessageFromHandle( handle() );
+ if( !incompleteMessage )
+ {
+ PanicClient( aMessage, EBadHandle );
+ return;
+ }
+
+ const TDesC16& message = incompleteMessage->MessageWide();
+ TInt returnValue = incompleteMessage->ReturnValue();
+
+ DLINFO(( "Writing message" ));
+ TRAPD( error, aMessage.WriteL( 3, message ) );
+ if ( error != KErrNone )
+ {
+ RemoveIncompleteMessage( handle() );
+ User::Leave( error );
+ }
+
+ DLINFO(( "Completing message with %d", returnValue ));
+ aMessage.Complete( returnValue );
+ RemoveIncompleteMessage( handle() );
+ break;
+ }
+
+ case ECatalogsRemoveIncompleteMessage:
+ {
+ DLTRACE(("ECatalogsRemoveIncompleteMessage"));
+ TPckgBuf<TInt> handle;
+ aMessage.ReadL( 1, handle );
+ RemoveIncompleteMessage( handle() );
+ DLINFO(( "Completing message with KErrNone" ));
+ aMessage.Complete( KErrNone );
+
+ break;
+ }
+ case ECatalogsClientSideDown:
+ {
+ DLTRACE(("ECatalogsClientSideDown"));
+ ClientSideSessionDown();
+ DLINFO(( "Completing message with KErrNone" ));
+ aMessage.Complete( KErrNone );
+ break;
+ }
+
+ case ECatalogsCreateProvider:
+ {
+ DLTRACE(("Create Provider"));
+
+ CreateProviderL( aMessage );
+ DLTRACE(("Create Provider done"));
+ break;
+ }
+
+ case ECatalogsCreateContext:
+ {
+ DLTRACE(("ECatalogsCreateContext"));
+ CreateContextL( aMessage );
+ break;
+ }
+
+ default:
+ {
+ }
+ }
+ }
+
+void CCatalogsClientServerServerSession::CreateProviderL(
+ const RMessage2& aMessage )
+ {
+ DLTRACEIN((""));
+
+ TInt providerUid = aMessage.Int0();
+ TUint32 providerOptions = aMessage.Int2();
+
+ // We have to have a integer which contains the handle to be
+ // able to write it into client side later.
+ TInt tempHandle( 0 );
+
+ TRAPD( outcome,
+ iServer.CreateProviderL(
+ *this, providerUid, tempHandle, providerOptions ) );
+
+ // KErrNone and positive codes are a success. Cache cleaning
+ // can cause positive leaves
+ if ( outcome >= KErrNone )
+ {
+ DLTRACE(("Writing the provider handle to the message"));
+ TPckgBuf<TInt> handleBuf( tempHandle );
+
+ TRAPD( err, aMessage.WriteL( 1, handleBuf ) );
+ if ( err != KErrNone )
+ {
+ DLTRACE(("Couldn't pass the handle back"));
+ // If we can't pass the handle back, there is no use
+ // to try to continue normally.
+ RemoveObject( tempHandle );
+ outcome = err;
+ }
+ }
+ DLTRACE(("Completing message with: %d", outcome ));
+ aMessage.Complete( outcome );
+ }
+
+
+void CCatalogsClientServerServerSession::CreateContextL(
+ const RMessage2& aMessage )
+ {
+ DLTRACEIN((""));
+ if ( iContext != NULL )
+ {
+ DLERROR(( "Completing message with KErrAlreadyExists" ));
+ aMessage.Complete( KErrAlreadyExists );
+ return;
+ }
+
+ TInt familyIdTint = aMessage.Int0();
+ TUid familyIdUid = TUid::Uid( familyIdTint );
+ TSecureId secureId = aMessage.SecureId();
+
+ iContext = CCatalogsContextImpl::NewL( familyIdUid, secureId, iInstanceId );
+
+ // cancel shutdown operations for this family
+ iServer.OperateShutdownOperations( Context(), EFalse );
+
+ DLINFO(( "Completing message with KErrNone" ));
+ aMessage.Complete( KErrNone );
+ DLTRACEOUT((""));
+ }
+
+void CCatalogsClientServerServerSession::PanicClient(
+ const RMessage2& aMessage, TInt aPanic ) const
+ {
+ DLTRACEIN((""));
+ // NOTICE: KTxtCatalogsSession should not exceed 16 characters.
+ // If it does, it will result in USER 23. So it seems
+ // that RMEssage2::Panic does not truncate the characters
+ // that exceed those 16 characters.
+ _LIT( KTxtCatalogsSession,"CCatalogsSession" );
+ aMessage.Panic( KTxtCatalogsSession, aPanic );
+ }
+
+CCatalogsCommunicable*
+ CCatalogsClientServerServerSession::ReceiverFromHandle( TInt aHandle )
+ {
+ DLTRACEIN((""));
+ if ( iMessageHandlers == NULL )
+ {
+ return NULL;
+ }
+ // Normal situation
+ CCatalogsCommunicable* handler =
+ static_cast<CCatalogsCommunicable*>( iMessageHandlers->At( aHandle ) );
+ DLTRACEOUT((""));
+ return handler;
+ }
+
+CCatalogsIncompleteMessage*
+ CCatalogsClientServerServerSession::IncompleteMessageFromHandle( TInt aHandle )
+ {
+ DLTRACEIN((""));
+ if ( iIncompleteMessages == NULL )
+ {
+ return NULL;
+ }
+
+ // Normal situation
+ CCatalogsIncompleteMessage* message =
+ static_cast<CCatalogsIncompleteMessage*>(
+ iIncompleteMessages->At( aHandle ) );
+ DLTRACEOUT((""));
+ return message;
+ }
+
+void CCatalogsClientServerServerSession::CloseMessageHandlers()
+ {
+ DLTRACEIN((""));
+ TInt communicableCount( iMessageHandlers->Count() );
+ for ( TInt index = 0; index < communicableCount; ++index )
+ {
+ CCatalogsCommunicable* handler =
+ static_cast<CCatalogsCommunicable*>( ( *iMessageHandlers )[index] );
+ // If handlers have been removed, iMessageHandlers seem to contain
+ // null pointers in place of those removed handlers
+ if ( handler != NULL )
+ {
+ handler->CounterPartLost( *this );
+ }
+ }
+
+ // Deletion closes all referenced objects once
+ delete iMessageHandlers;
+ iMessageHandlers = NULL;
+
+ DLTRACEOUT((""));
+ }