diff -r 000000000000 -r 2e3d3ce01487 contextframework/cfw/src/cfserver/CFMessageHandlerContext.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contextframework/cfw/src/cfserver/CFMessageHandlerContext.cpp Tue Feb 02 10:12:00 2010 +0200 @@ -0,0 +1,1333 @@ +/* +* Copyright (c) 2006-2008 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: Message handler context class implementation. +* +*/ + + +#include +#include +#include +#include + +#include "CFMessageHandlerContext.h" +#include "CFContextObjectImpl.h" +#include "cfextendedcontextinterface.h" +#include "CFScriptInterface.h" +#include "CFContextSubscriptionImpl.h" +#include "cfcontextindication.h" +#include "CFContextIndicationImpl.h" +#include "CFServSession.h" +#include "CFContextQueryImpl.h" +#include "cfcommon.h" +#include "cftrace.h" +#include "CFContextDataProxy.h" +#include "cfserviceutils.h" + +// CONSTANTS + +#ifdef _DEBUG +LOCAL_C void Panic( const RMessage2& aMessage, TInt aCode ) + { + CCFServSession::PanicClient( aMessage, aCode ); + } +#endif + +// Local function to clean up RContextQueryArray +LOCAL_C void CleanupContextQueryArray( TAny* aArray ) + { + RContextQueryArray* array = static_cast( aArray ); + array->ResetAndDestroy(); + } + +// Puts RContextQueryArray in clean up stack +LOCAL_C void CleanupResetAndDestroyPushL( RContextQueryArray& aArray ) + { + TCleanupItem item( CleanupContextQueryArray, &aArray ); + CleanupStack::PushL( item ); + } + +// METHODS + +CCFMessageHandlerContext* CCFMessageHandlerContext::NewL( + MCFExtendedContextInterface& aCFContext, + MCFActionInterface& aCFAction, + MCFScriptInterface& aScriptInterface ) + { + FUNC_LOG; + + CCFMessageHandlerContext* self = CCFMessageHandlerContext::NewLC( + aCFContext, + aCFAction, + aScriptInterface ); + CleanupStack::Pop( self ); + + return self; + } + +CCFMessageHandlerContext* CCFMessageHandlerContext::NewLC( + MCFExtendedContextInterface& aCFContext, + MCFActionInterface& aCFAction, + MCFScriptInterface& aScriptInterface ) + { + FUNC_LOG; + + CCFMessageHandlerContext* self = new( ELeave ) CCFMessageHandlerContext( + aCFContext, + aCFAction, + aScriptInterface ); + CleanupStack::PushL( self ); + self->ConstructL(); + + return self; + } + +CCFMessageHandlerContext::~CCFMessageHandlerContext() + { + FUNC_LOG; + + // Cancel outsanding request from client + CancelReceiveContextIndicationMessage(); + + // Remove all subscriptions from this session + iCFContext.UnsubscribeContexts( *this ); + iCFContext.DeregisterPublisher( *this ); + + // Clean buffers + iIndicationQueue.ResetAndDestroy(); + TInt count = iSubscriptionErrors.Count(); + for( TInt i = 0; i < count; i++ ) + { + delete iSubscriptionErrors[i].iContext; + } + + // Close arrays which context are not owned + iContextRequestBuffer.Close(); + } + +CCFMessageHandlerContext::CCFMessageHandlerContext( + MCFExtendedContextInterface& aCFContext, + MCFActionInterface& aCFAction, + MCFScriptInterface& aScriptInterface ) + : CCFMessageHandlerBase( aCFContext, aCFAction, aScriptInterface ) + { + FUNC_LOG; + } + +void CCFMessageHandlerContext::ConstructL() + { + FUNC_LOG; + } + +// METHODS + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::HandleMessageL +//----------------------------------------------------------------------------- +// +TBool CCFMessageHandlerContext::HandleMessageL( const RMessage2& aMessage ) + { + FUNC_LOG; + + INFO_1( "[MessageHandlerContext] Handling IPC message: %d", aMessage.Function() ); + + TBool handled = ETrue; + switch( aMessage.Function() ) + { + + // Slot[0] = TDesC - CCFContextObject + case EPublishContext: + { + INFO( "Handling IPC message [EPublishContext]" ); + + // Stream context from client buffer + CCFContextObjectImpl* context = CCFContextObjectImpl::NewLC(); + TInt length = aMessage.GetDesLengthL( 0 ); + HBufC8* buffer = HBufC8::NewLC( length ); + TPtr8 bufferPtr = buffer->Des(); + aMessage.ReadL( 0, bufferPtr ); + RDesReadStream readStream( bufferPtr ); + readStream.PushL(); + context->InternalizeL( readStream ); + + // Clean up + CleanupStack::PopAndDestroy( &readStream ); + CleanupStack::PopAndDestroy( buffer ); + + // Send request to CF Engine + RThread clientThread; + aMessage.ClientL( clientThread ); + CleanupClosePushL( clientThread ); + TInt err = PublishContext( *context, clientThread ); + + // Clean up + CleanupStack::PopAndDestroy( &clientThread ); + CleanupStack::PopAndDestroy( context ); + + // Complete + aMessage.Complete( err ); + + INFO( "Handled IPC message [EPublishContext]" ); + + break; + } + + // Slot[0] = TDesC - CCFContextSubscription + case EAddSubscription: + { + INFO( "Handling IPC message [EAddSubscription]" ); + + // Stream subscription from client buffer + CCFContextSubscriptionImpl* subscription = + CCFContextSubscriptionImpl::NewLC(); + TInt length = aMessage.GetDesLengthL( 0 ); + HBufC8* buffer = HBufC8::NewLC( length ); + TPtr8 bufferPtr = buffer->Des(); + aMessage.ReadL( 0, bufferPtr ); + RDesReadStream readStream( bufferPtr ); + readStream.PushL(); + subscription->InternalizeL( readStream ); + + // Clean up + CleanupStack::PopAndDestroy( &readStream ); + CleanupStack::PopAndDestroy( buffer ); + + // Send request to CF Engine + RThread clientThread; + aMessage.ClientL( clientThread ); + CleanupClosePushL( clientThread ); + TInt err = AddSubscription( subscription, clientThread ); + + // Clean up + CleanupStack::PopAndDestroy( &clientThread ); + CleanupStack::Pop( subscription ); + + // Handle results + if( err != KErrNone ) + { + // Notify error + DoHandleContextSubscriptionErrorL( err, + subscription->ContextSource(), + subscription->ContextType() ); + } + + // Complete + aMessage.Complete( KErrNone ); + + INFO( "Handled IPC message [EAddSubscription]" ); + + break; + } + + // Slot[0] = TDesC - CCFContextSubscription + case ERemoveSubscription: + { + INFO( "Handling IPC message [ERemoveSubscription]" ); + + // Stream subscription from client buffer + CCFContextSubscriptionImpl* subscription = + CCFContextSubscriptionImpl::NewLC(); + TInt length = aMessage.GetDesLengthL( 0 ); + HBufC8* buffer = HBufC8::NewLC( length ); + TPtr8 bufferPtr = buffer->Des(); + aMessage.ReadL( 0, bufferPtr ); + RDesReadStream readStream( bufferPtr ); + readStream.PushL(); + subscription->InternalizeL( readStream ); + + // Clean up + CleanupStack::PopAndDestroy( &readStream ); + CleanupStack::PopAndDestroy( buffer ); + + // Send request to CF Engine + RemoveSubscription( *subscription ); + + // Clean up + CleanupStack::PopAndDestroy( subscription ); + + // Complete + aMessage.Complete( KErrNone ); + + INFO( "Handled IPC message [ERemoveSubscription]" ); + + break; + } + + // Slot[0] = TDes - Buffer + // Slot[1] = TPckg - Buffer size + case EReceiveContextIndicationMessage: + { + INFO( "Handling IPC message [EReceiveContextIndicationMessage]" ); + + ReceiveContextIndicationMessageL( aMessage ); + + INFO( "Handled IPC message [EReceiveContextIndicationMessage]" ); + + break; + } + + // Slot[0] = TDes - Buffer + // Slot[1] = TPckg - Buffer size + case EReceiveMessage: + { + INFO( "Handling IPC message [EReceiveMessage]" ); + + ReceiveMessageL( aMessage ); + + INFO( "Handled IPC message [EReceiveMessage]" ); + + break; + } + + // Slot[0] = TDes - Buffer + case EGetContextIndication: + { + INFO( "Handling IPC message [EGetContextIndication]" ); + + // Client has increased buffer size + // Get next indication from queue + // Message will be completed in the method + CompleteNextIndicationFromQueueL( aMessage ); + + INFO( "Handled IPC message [EGetContextIndication]" ); + + break; + } + + // Slot[0] = TDes - Buffer + case EGetMessage: + { + INFO( "Handling IPC message [EGetMessage]" ); + + // Client has increased buffer size + // Get next indication from queue + // Message will be completed in the method + CompleteNextMessageFromQueueL( aMessage ); + + INFO( "Handled IPC message [EGetMessage]" ); + + break; + } + + + // No parameters + case ECancelReceiveContextIndicationMessage: + { + INFO( "Handling IPC message [ECancelReceiveContextIndicationMessage]" ); + + CancelReceiveContextIndicationMessage(); + aMessage.Complete( KErrNone ); + + INFO( "Handled IPC message [ECancelReceiveContextIndicationMessage]" ); + + break; + } + + // No parameters + case ECancelReceiveMessage: + { + INFO( "Handling IPC message [ECancelReceiveContextIndicationMessage]" ); + + CancelReceiveMessage(); + aMessage.Complete( KErrNone ); + + INFO( "Handled IPC message [ECancelReceiveContextIndicationMessage]" ); + + break; + } + + + // Slot[0] = TDes - Result buffer + // Slot[1] = TDesC - CCFContextQuery + // Slot[2] = TPckg - Buffer size + case ERequestContext: + { + INFO( "Handling IPC message [ERequestContext]" ); + + TInt err = KErrNone; + + // Check if the client has already requested contexts but + // has failed due too small buffer size + if( iContextRequestBuffer.Count() ) + { + // Write request result into client side buffer + CompleteRequestContextL( aMessage ); + + // Reset buffer + iContextRequestBuffer.Reset(); + } + else + { + // New request + // Stream query + CCFContextQueryImpl* query = + CCFContextQueryImpl::NewLC( KNullDesC, KNullDesC ); + TInt bufferSize = aMessage.GetDesLengthL( 1 ); + HBufC8* buffer = HBufC8::NewLC( bufferSize ); + TPtr8 bufferPtr = buffer->Des(); + aMessage.ReadL( 1, bufferPtr ); + RDesReadStream readStream( bufferPtr ); + readStream.PushL(); + query->InternalizeL( readStream ); + + // Clean up + CleanupStack::PopAndDestroy( &readStream ); + CleanupStack::PopAndDestroy( buffer ); + + // Send request to CF Engine + RThread clientThread; + aMessage.ClientL( clientThread ); + CleanupClosePushL( clientThread ); + err = RequestContext( *query, clientThread ); + + // Clean up + CleanupStack::PopAndDestroy( &clientThread ); + CleanupStack::PopAndDestroy( query ); + + // Handle request context results + if( err == KErrNone && iContextRequestBuffer.Count() ) + { + // Write request result into client side buffer if + // request succesfull + CompleteRequestContextL( aMessage ); + } + else + { + // Complete with error code + aMessage.Complete( err ); + } + } + + INFO( "Handled IPC message [ERequestContext]" ); + + break; + } + + // Slot[0] = TDes - Result buffer + // Slot[1] = TDesC - CCFContextQuery + // Slot[2] = TPckg - Buffer size + case ERequestContextSet: + { + INFO( "Handling IPC message [ERequestContextSet]" ); + + TInt err = KErrNone; + + // Check if the client has already requested contexts but + // has failed due too small buffer size + if( iContextRequestBuffer.Count() ) + { + // Write request result into client side buffer + CompleteRequestContextL( aMessage ); + + // Reset buffer + iContextRequestBuffer.Reset(); + } + else + { + // New request + // Stream query + RContextQueryArray queryArray; + CleanupResetAndDestroyPushL( queryArray ); + TInt bufferSize = aMessage.GetDesLengthL( 1 ); + HBufC8* buffer = HBufC8::NewLC( bufferSize ); + TPtr8 bufferPtr = buffer->Des(); + aMessage.ReadL( 1, bufferPtr ); + RDesReadStream readStream( bufferPtr ); + readStream.PushL(); + TInt count = readStream.ReadInt16L(); + for( TInt i = 0; i < count; i++ ) + { + CCFContextQueryImpl* query = + CCFContextQueryImpl::NewLC( KNullDesC, KNullDesC ); + query->InternalizeL( readStream ); + queryArray.AppendL( query ); + CleanupStack::Pop( query ); + } + + // Clean up + CleanupStack::PopAndDestroy( &readStream ); + CleanupStack::PopAndDestroy( buffer ); + + // Send request to CF Engine + RThread clientThread; + aMessage.ClientL( clientThread ); + CleanupClosePushL( clientThread ); + count = queryArray.Count(); + for( TInt i = 0; i < count; i++ ) + { + RequestContext( *queryArray[i], clientThread ); + } + + // Clean up + CleanupStack::PopAndDestroy( &clientThread ); + CleanupStack::PopAndDestroy( &queryArray ); + + // Handle request context results + if( err == KErrNone && iContextRequestBuffer.Count() ) + { + // Write request result into client side buffer if + // request succesfull + CompleteRequestContextL( aMessage ); + } + else + { + // Complete with error code + aMessage.Complete( err ); + } + } + + INFO( "Handled IPC message [ERequestContextSet]" ); + + break; + } + + // Slot[0] = TDesC& + // Slot[1] = TDesC& + // Slot[2] = TSecurityPolicyBuf - read policy + // Slot[3] = TSecurityPolicyBuf - write policy + case EDefineContext: + { + INFO( "Handling IPC message [EDefineContext]" ); + + TInt err = KErrNone; + + // Read context source + HBufC* contextSource = HBufC::NewLC( aMessage.GetDesLengthL( 0 ) ); + TPtr contextSourcePtr = contextSource->Des(); + aMessage.ReadL( 0, contextSourcePtr ); + + // Read context type + HBufC* contextType = HBufC::NewLC( aMessage.GetDesLengthL( 1 ) ); + TPtr contextTypePtr = contextType->Des(); + aMessage.ReadL( 1, contextTypePtr ); + + // Read security policy + TSecurityPolicyBuf readSecPolicyBuf; + aMessage.ReadL( 2, readSecPolicyBuf ); + TSecurityPolicy readSecPolicy; + User::LeaveIfError( readSecPolicy.Set( readSecPolicyBuf ) ); // verifies the security policy + + TSecurityPolicyBuf writeSecPolicyBuf; + aMessage.ReadL( 3, writeSecPolicyBuf ); + TSecurityPolicy writeSecPolicy; + User::LeaveIfError( writeSecPolicy.Set( writeSecPolicyBuf ) ); // verifies the security policy + + + RThread clientThread; + aMessage.ClientL( clientThread ); + CleanupClosePushL( clientThread ); + + // Define context in CF + err = iCFContext.DefineContext( contextSourcePtr, + contextTypePtr, + readSecPolicy, + writeSecPolicy, + this, + clientThread.SecureId() ); + + // Clean up + CleanupStack::PopAndDestroy( &clientThread ); + + // Cleanup + CleanupStack::PopAndDestroy( contextType ); + CleanupStack::PopAndDestroy( contextSource ); + + aMessage.Complete( err ); + + INFO( "Handled IPC message [EDefineContext]" ); + + break; + } + + // Slot[0] = TDes - Buffer + case EGetContextSubscriptionError: + { + INFO( "Handling IPC message [EGetContextSubscriptionError]" ); + + // Check that we actually have errors in the list + TInt err = KErrNone; + if( iSubscriptionErrors.Count() ) + { + // We have a context subscription error, send it to client + CCFContextObjectImpl* context = iSubscriptionErrors[0].iContext; + iSubscriptionErrors.Remove( 0 ); + CleanupStack::PushL( context ); + HBufC8* buffer = HBufC8::NewLC( aMessage.GetDesMaxLengthL( 0 ) ); + TPtr8 bufferPtr = buffer->Des(); + RDesWriteStream writeStream( bufferPtr ); + writeStream.PushL(); + context->ExternalizeL( writeStream ); + + // Write content into client side buffer + aMessage.WriteL( 0, bufferPtr ); + + // Clean up + CleanupStack::PopAndDestroy( &writeStream ); + CleanupStack::PopAndDestroy( buffer ); + CleanupStack::PopAndDestroy( context ); + } + else + { + // No errors found + err = KErrNotFound; + } + + // Complete + aMessage.Complete( err ); + + INFO( "Handled IPC message [EGetContextSubscriptionError]" ); + + break; + } + + // Slot[0]= TDesC - Context + // Slot[1]= TDesC - Context data + // Slot[2]= TPckg - Context data UID + case EPublishContextWithData: + { + INFO( "Handling IPC message [EPublishContextWithData]" ); + + // Get context + CCFContextObjectImpl* context = CCFContextObjectImpl::NewLC(); + TInt len = aMessage.GetDesLengthL( 0 ); + HBufC8* contextBuf = HBufC8::NewLC( len ); + TPtr8 contextBufPtr( contextBuf->Des() ); + aMessage.ReadL( 0, contextBufPtr ); + RDesReadStream readStream( contextBufPtr ); + readStream.PushL(); + context->InternalizeL( readStream ); + CleanupStack::PopAndDestroy( &readStream ); + CleanupStack::PopAndDestroy( contextBuf ); + + // Get context data + CCFContextDataProxy* contextData = CCFContextDataProxy::NewLC(); + len = aMessage.GetDesLengthL( 1 ); + HBufC8* contextDataBuf = HBufC8::NewLC( len ); + TPtr8 contextDataBufPtr( contextDataBuf->Des() ); + aMessage.ReadL( 1, contextDataBufPtr ); + TPckgBuf uidPckgBuf; + aMessage.ReadL( 2, uidPckgBuf ); + + contextData->SetContextData( contextDataBuf ); + contextData->SetContextDataUid( uidPckgBuf() ); + CleanupStack::Pop( contextDataBuf ); + + // Publish context + RThread clientThread; + aMessage.ClientL( clientThread ); + CleanupClosePushL( clientThread ); + TInt err = iCFContext.PublishContext( *context, + *contextData, + clientThread ); + CleanupStack::PopAndDestroy( &clientThread ); + + // Clean up + CleanupStack::PopAndDestroy( contextData ); + CleanupStack::PopAndDestroy( context ); + + // Complete + aMessage.Complete( err ); + + INFO( "Handled IPC message [EPublishContextWithData]" ); + + break; + } + + // Slot[0] = RFs handle + // Slot[1] = RFile handle + // Slot[2] = TPckgC< TUid > - Context Source UID + case EInstallSourceSetting: + { + RFile settingFile; + TInt err = settingFile.AdoptFromClient( aMessage, 0, 1 ); + CleanupClosePushL( settingFile ); // CLEANUP<< settingFile + if ( err == KErrNone ) + { + TPckgBuf< TUid > uidPckgBuf; + aMessage.ReadL( 2, uidPckgBuf ); + + RThread client; + aMessage.ClientL( client ); + + // Install setting + err = iCFContext.InstallContextSourceSetting( settingFile, + uidPckgBuf(), + client ); + + client.Close(); + } + CleanupStack::PopAndDestroy( &settingFile );// CLEANUP>> settingFile + aMessage.Complete( err ); + + break; + } + + // Slot[0] = TDesC& - Setting filename + // Slot[1] = TPckgC< TUid > - Context Source UID + case EUninstallSourceSetting: + { + // Read setting filename // CLEANUP<< filename + HBufC* filename = HBufC::NewLC( aMessage.GetDesLengthL( 0 ) ); + TPtr filenamePtr = filename->Des(); + aMessage.ReadL( 0, filenamePtr ); + + TPckgBuf< TUid > uidPckgBuf; + aMessage.ReadL( 1, uidPckgBuf ); + + RThread client; + aMessage.ClientL( client ); + + // Uninstall setting + TInt err = iCFContext.UninstallContextSourceSetting( *filename, + uidPckgBuf(), + client ); + + client.Close(); + CleanupStack::PopAndDestroy( filename ); // CLEANUP>> filename + aMessage.Complete( err ); + + break; + } + + // Slot[0] = TPckgC< TUid > - Context Source UID + case EUninstallSourceSettings: + { + // Read context source UID + TPckgBuf< TUid > uidPckgBuf; + aMessage.ReadL( 0, uidPckgBuf ); + + RThread client; + aMessage.ClientL( client ); + + // Uninstall setting + TInt err = iCFContext.UninstallContextSourceSettings( uidPckgBuf(), + client ); + + client.Close(); + aMessage.Complete( err ); + + break; + } + + default: + { + // Message not handled + handled = EFalse; + } + } + + INFO_1( "Handled IPC message: %d", handled ); + + return handled; + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::ContextIndicationL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::ContextIndicationL( + CCFContextIndication* aIndication ) + { + FUNC_LOG; + + INFO_2( "Received context indication: %S: %S", + &aIndication->Context().Source(), + &aIndication->Context().Type() ); + + CCFContextIndicationImpl* indication = + static_cast( aIndication ); + iIndicationQueue.AppendL( indication ); + CheckContextIndicationQueueL(); + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::Client +//----------------------------------------------------------------------------- +// +TInt CCFMessageHandlerContext::Client( RThread& aThread ) const + { + FUNC_LOG; + + TInt err = KErrNone; + if( !iReceiveMessage.IsNull() ) + { + // We have a message pending + err = iReceiveMessage.Client( aThread ); + } + else + { + err = KErrNotFound; + } + + return err; + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::HandleContextSubscriptionError +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::HandleContextSubscriptionError( TInt aError, + const TDesC& aSource, + const TDesC& aType ) + { + FUNC_LOG; + + // Client will not get notified about error if this fails + // Failure only due to OOM + TRAP_IGNORE( DoHandleContextSubscriptionErrorL( aError, aSource, aType ) ); + } + + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::Subscribers +//----------------------------------------------------------------------------- +// +// from MCFContextSource +void CCFMessageHandlerContext::Subscribers( const TDesC& aContextSource, + const TDesC& aContextType ) + { + FUNC_LOG; + + INFO_2( "Received subscribers indication: %S: %S", + &aContextSource, + &aContextType ); + + TRAPD( err, SubscribersL( aContextSource, aContextType ) ); + if( err != KErrNone ) + { + ERROR_2( err, "Failed to notify subscribers to client: [%S, %S]", + &aContextSource, &aContextType ); + } + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::PublishContext +//----------------------------------------------------------------------------- +// +// from MCFContextSource +void CCFMessageHandlerContext::NoSubscribers( const TDesC& aContextSource, + const TDesC& aContextType ) + { + FUNC_LOG; + + INFO_2( "Received no subscribers indication: %S: %S", + &aContextSource, + &aContextType ); + + TRAPD( err, NoSubscribersL( aContextSource, aContextType ) ); + if( err != KErrNone ) + { + ERROR_2( err, "Failed to notify no subscribers to client: [%S, %S]", + &aContextSource, &aContextType ); + } + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::HandleCommand +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::HandleCommand( + const CCFContextSourceCommand& aCommand ) + { + FUNC_LOG; + + TPtrC commandName( aCommand.Name() ); + INFO_1( "Received handle command action: %S", &commandName ); + + TRAPD( err, HandleCommandL( aCommand ) ); + if( err != KErrNone ) + { + ERROR_2( err, "Failed to notify handle command action [%S] to client: [%x]", + &commandName, + aCommand.SourceUid() ); + } + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::PublishContext +//----------------------------------------------------------------------------- +// +TInt CCFMessageHandlerContext::PublishContext( CCFContextObject& aContext, + RThread& aClientThread ) + { + FUNC_LOG; + + return iCFContext.PublishContext( aContext, aClientThread ); + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::AddSubscription +//----------------------------------------------------------------------------- +// +TInt CCFMessageHandlerContext::AddSubscription( CCFContextSubscription* aSubscription, + RThread& aClientThread ) + { + FUNC_LOG; + + return iCFContext.SubscribeContext( aSubscription, this, aClientThread ); + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::RemoveSubscriptionL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::RemoveSubscription( + CCFContextSubscription& aSubscription ) + { + FUNC_LOG; + + iCFContext.UnsubscribeContext( aSubscription, *this ); + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::CancelReceiveContextIndicationMessage +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::CancelReceiveContextIndicationMessage() + { + FUNC_LOG; + + if( !iReceiveMessage.IsNull() ) + { + iReceiveMessage.Complete( KErrCancel ); + } + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::CancelReceiveMessage +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::CancelReceiveMessage() + { + FUNC_LOG; + + if( !iReceiveContextSourceMsg.IsNull() ) + { + iReceiveContextSourceMsg.Complete( KErrCancel ); + } + } + + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::RequestContext +//----------------------------------------------------------------------------- +// +TInt CCFMessageHandlerContext::RequestContext( CCFContextQuery& aContextQuery, + RThread& aClientThread ) + { + FUNC_LOG; + + // request the context + return iCFContext.RequestContext( iContextRequestBuffer, + aContextQuery, + aClientThread ); + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::ReceiveContextIndicationMessageL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::ReceiveContextIndicationMessageL( + const RMessage2& aMessage) + { + FUNC_LOG; + + __ASSERT_DEBUG( iReceiveMessage.IsNull(), + CCFServSession::PanicClient( aMessage, EReceiveReceiveAlreadyActive ) ); + + // Store message + iReceiveMessage = aMessage; + + // First check if we have subscription errors in the queue + if( iSubscriptionErrors.Count() ) + { + IndicateSubscriptionErrorL(); + } + + // Check indications + else if( iIndicationQueue.Count() ) + { + CheckContextIndicationQueueL(); + } + } + + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::ReceiveMessageL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::ReceiveMessageL( const RMessage2& aMessage ) + { + FUNC_LOG; + + __ASSERT_DEBUG( iReceiveContextSourceMsg.IsNull(), + CCFServSession::PanicClient( aMessage, EReceiveReceiveAlreadyActive ) ); + + // Store message + iReceiveContextSourceMsg = aMessage; + + // Check if we have messages in the queue + if( iMessageQueue.Count() ) + { + CheckMessageQueueL(); + } + } + + + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::IndicateSubscriptionErrorL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::IndicateSubscriptionErrorL() + { + FUNC_LOG; + + // Get next error, client will request the context related to the error + TSubscriptionError error = iSubscriptionErrors[0]; + TPckgBuf sizeBuf( error.iContext->Size() ); + iReceiveMessage.WriteL( 1, sizeBuf ); + iReceiveMessage.Complete( error.iError ); + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::CompleteNextIndicationFromQueueL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::CompleteNextIndicationFromQueueL( + const RMessage2& aMessage ) + { + FUNC_LOG; + + // Leave if the aMessage is null + if( aMessage.IsNull() ) + { + User::Leave( KErrArgument ); + } + + // Check that we have indications in queue + else if( iIndicationQueue.Count() ) + { + CCFContextIndicationImpl* indication = iIndicationQueue[0]; + HBufC8* buffer = HBufC8::NewLC( indication->Size() ); + TPtr8 bufferPtr = buffer->Des(); + RDesWriteStream writeStream( bufferPtr ); + writeStream.PushL(); + indication->ExternalizeL( writeStream ); + CleanupStack::PopAndDestroy( &writeStream ); + + // Write buffer into client side and complete + aMessage.WriteL( 0, bufferPtr ); + aMessage.Complete( KErrNone ); + + // Remove indication from queue + delete indication; + iIndicationQueue.Remove( 0 ); + + // Clean up + CleanupStack::PopAndDestroy( buffer ); + } + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::CheckContextIndicationQueueL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::CheckContextIndicationQueueL() + { + FUNC_LOG; + + // We must have something in the queue and receive message pending + if( iIndicationQueue.Count() && !iReceiveMessage.IsNull() ) + { + // First check that client side buffer is big enough + CCFContextIndicationImpl* indication = iIndicationQueue[0]; + TInt clientBufferSize = iReceiveMessage.GetDesMaxLengthL( 0 ); + TInt indicationSize = indication->Size(); + if( indicationSize <= clientBufferSize ) + { + // Client has sufficient buffer + CompleteNextIndicationFromQueueL( iReceiveMessage ); + } + else + { + // Client has insufficient buffer size + // Write new buffer size in client memory and complete + TPckgBuf sizeBuf( indicationSize ); + iReceiveMessage.WriteL( 1, sizeBuf ); + iReceiveMessage.Complete( KErrTooBig ); + } + } + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::CompleteNextMessageFromQueueL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::CompleteNextMessageFromQueueL( + const RMessage2& aMessage ) + { + FUNC_LOG; + + __ASSERT_DEBUG( iMessageQueue.Count(), Panic( aMessage, KErrNotFound ) ); + __ASSERT_DEBUG( !aMessage.IsNull(), Panic( aMessage, KErrArgument ) ); + + if( iMessageQueue.Count() ) + { + // Write buffer into client side and complete + HBufC8* messageBuffer = iMessageQueue[0]; + aMessage.WriteL( 0, *messageBuffer ); + aMessage.Complete( KErrNone ); + + // Remove indication from queue + delete messageBuffer; + iMessageQueue.Remove( 0 ); + } + } + + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::CheckMessageQueueL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::CheckMessageQueueL() + { + FUNC_LOG; + + // We must have something in the queue and receive message pending + if( iMessageQueue.Count() && !iReceiveContextSourceMsg.IsNull() ) + { + // First check that client side buffer is big enough + TInt clientBufferSize = iReceiveContextSourceMsg.GetDesMaxLengthL( 0 ); + TInt indicationSize = iMessageQueue[0]->Size(); + if( indicationSize <= clientBufferSize ) + { + // Client has sufficient buffer + // Write buffer into client side and complete + HBufC8* messageBuffer = iMessageQueue[0]; + iReceiveContextSourceMsg.WriteL( 0, *messageBuffer ); + iReceiveContextSourceMsg.Complete( KErrNone ); + + // Remove indication from queue + delete messageBuffer; + iMessageQueue.Remove( 0 ); + + } + else + { + // Client has insufficient buffer size + // Write new buffer size in client memory and complete + TPckgBuf sizeBuf( indicationSize ); + iReceiveContextSourceMsg.WriteL( 1, sizeBuf ); + iReceiveContextSourceMsg.Complete( KErrTooBig ); + } + } + } + + + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::CompleteRequestContextL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::CompleteRequestContextL( + const RMessage2& aMessage ) + { + FUNC_LOG; + + // Check if client has a sufficient buffer + TInt resultArraySize = 0; + resultArraySize += sizeof( TInt ); + TInt count = iContextRequestBuffer.Count(); + CCFContextObjectImpl* context = NULL; + for( TInt i = 0; i < count; i++ ) + { + context = static_cast( + iContextRequestBuffer[i] ); + resultArraySize += context->Size(); + } + TInt clientBufferSize = aMessage.GetDesMaxLengthL( 0 ); + if( resultArraySize <= clientBufferSize ) + { + // Client has a sufficient buffer + HBufC8* buffer = HBufC8::NewLC( resultArraySize ); + TPtr8 bufferPtr = buffer->Des(); + RDesWriteStream writeStream( bufferPtr ); + writeStream.PushL(); + writeStream.WriteInt16L( count ); + for( TInt i = 0; i < count; i++ ) + { + context = static_cast( + iContextRequestBuffer[i] ); + context->ExternalizeL( writeStream ); + } + writeStream.CommitL(); + aMessage.WriteL( 0, bufferPtr ); + + // Clean up + CleanupStack::PopAndDestroy( &writeStream ); + CleanupStack::PopAndDestroy( buffer ); + + // Reset context request buffer + iContextRequestBuffer.Reset(); + + // Complete message + aMessage.Complete( KErrNone ); + } + else + { + // Client has an insufficient buffer + TPckgBuf resultArraySizeBuf( resultArraySize ); + aMessage.WriteL( 2, resultArraySizeBuf ); + + // Complete message + aMessage.Complete( KErrTooBig ); + } + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerContext::DoHandleContextSubscriptionErrorL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerContext::DoHandleContextSubscriptionErrorL( TInt aError, + const TDesC& aSource, + const TDesC& aType ) + { + FUNC_LOG; + + // Context related to error + CCFContextObjectImpl* context = CCFContextObjectImpl::NewLC(); + context->SetSourceL( aSource ); + context->SetTypeL( aType ); + + // Append error to queue + TSubscriptionError error; + error.iError = aError; + error.iContext = context; + + // Ignore append errors + iSubscriptionErrors.AppendL( error ); + CleanupStack::Pop( context ); + if( !iReceiveMessage.IsNull() ) + { + // Can only fail due OOM + IndicateSubscriptionErrorL(); + } + } + +//------------------------------------------------------------------------------ +// CCFMessageHandlerContext::SubscribersL +//------------------------------------------------------------------------------ +// +void CCFMessageHandlerContext::SubscribersL( const TDesC& aContextSource, + const TDesC& aContextType ) + { + FUNC_LOG; + + // calculate message length + TInt size = 0; + size += sizeof( TInt ); // message type + size += sizeof( TInt ) + aContextSource.Size(); + size += sizeof( TInt ) + aContextType.Size(); + + // create a required buffer and stream + HBufC8* buffer = HBufC8::NewLC( size ); // CLEANUP << buffer + TPtr8 bufferPtr = buffer->Des(); + RDesWriteStream writeStream( bufferPtr ); + writeStream.PushL(); // CLEANUP << writeStream + + // write message to the buffer + writeStream.WriteInt32L( ESubscribers ); + writeStream.WriteInt32L( aContextSource.Length() ); + writeStream.WriteL( aContextSource, aContextSource.Length() ); + writeStream.WriteInt32L( aContextType.Length() ); + writeStream.WriteL( aContextType, aContextType.Length() ); + writeStream.CommitL(); + + CleanupStack::PopAndDestroy( &writeStream ); // CLEANUP >> writeStream + + // append pointer to the message array + iMessageQueue.AppendL( buffer ); + CleanupStack::Pop( buffer ); // CLEANUP >> buffer + + CheckMessageQueueL(); + } + +//------------------------------------------------------------------------------ +// CCFMessageHandlerContext::NoSubscribersL +//------------------------------------------------------------------------------ +// +void CCFMessageHandlerContext::NoSubscribersL( const TDesC& aContextSource, + const TDesC& aContextType ) + { + FUNC_LOG; + + // calculate message length + TInt size = 0; + size += sizeof( TInt ); // message type + size += sizeof( TInt ) + aContextSource.Size(); + size += sizeof( TInt ) + aContextType.Size(); + + // create a required buffer and stream + HBufC8* buffer = HBufC8::NewLC( size ); // CLEANUP << buffer + TPtr8 bufferPtr = buffer->Des(); + RDesWriteStream writeStream( bufferPtr ); + writeStream.PushL(); // CLEANUP << writeStream + + // write message to the buffer + writeStream.WriteInt32L( ENoSubscribers ); + writeStream.WriteInt32L( aContextSource.Length() ); + writeStream.WriteL( aContextSource, aContextSource.Length() ); + writeStream.WriteInt32L( aContextType.Length() ); + writeStream.WriteL( aContextType, aContextType.Length() ); + writeStream.CommitL(); + + CleanupStack::PopAndDestroy( &writeStream ); // CLEANUP >> writeStream + + // append pointer to the message array + iMessageQueue.AppendL( buffer ); + CleanupStack::Pop( buffer ); // CLEANUP >> buffer + + CheckMessageQueueL(); + } + +void CCFMessageHandlerContext::HandleCommandL( + const CCFContextSourceCommand& aCommand ) + { + FUNC_LOG; + + TInt size = sizeof( TInt ); // message type + size += aCommand.Size(); // the command + + // Stream command into descriptor + HBufC8* buffer = HBufC8::NewLC( size ); // CLEANUP<< buffer + TPtr8 bufferPtr = buffer->Des(); + RDesWriteStream stream( bufferPtr ); + stream.PushL(); // CLEANUP<< stream + + // Write message to the buffer + stream.WriteInt32L( EHandleCommand ); + aCommand.ExternalizeL( stream ); + stream.CommitL(); + + CleanupStack::PopAndDestroy( &stream ); // CLEANUP>> stream + + // Append buffer to the message array + iMessageQueue.AppendL( buffer ); + CleanupStack::Pop( buffer ); // CLEANUP>> buffer + + CheckMessageQueueL(); + } + +// End of File