diff -r 000000000000 -r 2e3d3ce01487 contextframework/cfw/src/cfserver/CFMessageHandlerAction.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contextframework/cfw/src/cfserver/CFMessageHandlerAction.cpp Tue Feb 02 10:12:00 2010 +0200 @@ -0,0 +1,455 @@ +/* +* Copyright (c) 2006-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: Message handler context class implementation. +* +*/ + + +#include + +#include "CFMessageHandlerAction.h" +#include "cfcommon.h" +#include "CFActionInterface.h" +#include "CFActionSubscriptionImpl.h" +#include "CFActionIndicationImpl.h" +#include "CFServSession.h" +#include "cftrace.h" + +// CONSTANTS + +#ifdef _DEBUG + +LOCAL_C void Panic( const RMessage2& aMessage, TInt aCode ) + { + CCFServSession::PanicClient( aMessage, aCode ); + } + +#endif + +CCFMessageHandlerAction* CCFMessageHandlerAction::NewL( + MCFExtendedContextInterface& aCFContext, + MCFActionInterface& aCFAction, + MCFScriptInterface& aScriptInterface ) + { + FUNC_LOG; + + CCFMessageHandlerAction* self = CCFMessageHandlerAction::NewLC( + aCFContext, + aCFAction, + aScriptInterface ); + CleanupStack::Pop( self ); + + return self; + } + +CCFMessageHandlerAction* CCFMessageHandlerAction::NewLC( + MCFExtendedContextInterface& aCFContext, + MCFActionInterface& aCFAction, + MCFScriptInterface& aScriptInterface ) + { + FUNC_LOG; + + CCFMessageHandlerAction* self = new( ELeave ) CCFMessageHandlerAction( + aCFContext, + aCFAction, + aScriptInterface ); + CleanupStack::PushL( self ); + self->ConstructL(); + + return self; + } + +CCFMessageHandlerAction::~CCFMessageHandlerAction() + { + FUNC_LOG; + + if( !iSubscriptionListenMessage.IsNull() ) + { + // Need to complete message + iSubscriptionListenMessage.Complete( KErrCancel ); + } + iCFAction.UnsubscribeActions( *this ); + iCFAction.DeregisterActions( this ); + iActionQueue.ResetAndDestroy(); + delete iCurrentAction; + } + +CCFMessageHandlerAction::CCFMessageHandlerAction( + MCFExtendedContextInterface& aCFContext, + MCFActionInterface& aCFAction, + MCFScriptInterface& aScriptInterface ): + CCFMessageHandlerBase( aCFContext, aCFAction, aScriptInterface ) + { + FUNC_LOG; + } + +void CCFMessageHandlerAction::ConstructL() + { + FUNC_LOG; + } + +// METHODS + +//----------------------------------------------------------------------------- +// CCFMessageHandlerAction::HandleMessageL +//----------------------------------------------------------------------------- +// +TBool CCFMessageHandlerAction::HandleMessageL( const RMessage2& aMessage ) + { + FUNC_LOG; + + TBool handled = ETrue; + switch( aMessage.Function() ) + { + // Slot[0] = TDesC + // Slot[1] = TSecurityPolicyBuf + case EDefineAction: + { + INFO( "Handling IPC message [EDefineAction]" ); + + // Read action identifier + HBufC* actionId = HBufC::NewLC( aMessage.GetDesLengthL( 0 ) ); + TPtr actionIdPtr = actionId->Des(); + aMessage.ReadL( 0, actionIdPtr ); + + // Read security policy + TSecurityPolicyBuf secPolicyBuf; + aMessage.ReadL( 1, secPolicyBuf ); + TSecurityPolicy secPolicy; + User::LeaveIfError( secPolicy.Set( secPolicyBuf ) ); + + // Get client thread + RThread client; + aMessage.ClientL( client ); + CleanupClosePushL( client ); + + // Define action + TInt err = iCFAction.DefineAction( actionIdPtr, secPolicy, + client.SecureId(), this ); + + // Cleanup + CleanupStack::PopAndDestroy( &client ); + CleanupStack::PopAndDestroy( actionId ); + + // Complete message and return + aMessage.Complete( err ); + + INFO( "Handled IPC message [EDefineAction]" ); + + break; + } + + // Slot[0] = TDesC - CCFActionSubscription + case ESubscribeAction: + { + INFO( "Handling IPC message [ESubscribeAction]" ); + + // Read subscription + // Start with buffer + HBufC8* buf = HBufC8::NewLC( aMessage.GetDesLengthL( 0 ) ); + TPtr8 bufPtr = buf->Des(); + aMessage.ReadL( 0, bufPtr ); + + // Open stream and fetch client thread + RDesReadStream stream; + stream.Open( bufPtr ); + stream.PushL(); + RThread client; + aMessage.ClientL( client ); + CleanupClosePushL( client ); + + // Create subscription from stream + CCFActionSubscriptionImpl* subscription = static_cast + ( CCFActionSubscription::NewLC() ); + subscription->InternalizeL( stream ); + CleanupStack::Pop( subscription ); + + // Set subscription + TInt err = iCFAction.SubscribeAction( subscription, this, client ); + + // Cleanup + CleanupStack::PopAndDestroy( &client ); + CleanupStack::PopAndDestroy( &stream ); + CleanupStack::PopAndDestroy( buf ); + + // Complete message and return + aMessage.Complete( err ); + + INFO( "Handled IPC message [ESubscribeAction]" ); + + break; + } + + // Slot[0] = TDesC - CCFActionSubscription + case EUnsubscribeAction: + { + INFO( "Handling IPC message [EUnsubscribeAction]" ); + + // Read subscription + // Start with buffer + HBufC8* buf = HBufC8::NewLC( aMessage.GetDesLengthL( 0 ) ); + TPtr8 bufPtr = buf->Des(); + aMessage.ReadL( 0, bufPtr ); + + // Open stream and fetch client thread + RDesReadStream stream; + stream.Open( bufPtr ); + stream.PushL(); + RThread client; + aMessage.ClientL( client ); + CleanupClosePushL( client ); + + // Create subscription from stream + CCFActionSubscriptionImpl* subscription = static_cast + ( CCFActionSubscription::NewLC() ); + subscription->InternalizeL( stream ); + + // Set subscription + iCFAction.UnsubscribeAction( *subscription, *this ); + + // Cleanup + CleanupStack::PopAndDestroy( subscription ); + CleanupStack::PopAndDestroy( &client ); + CleanupStack::PopAndDestroy( &stream ); + CleanupStack::PopAndDestroy( buf ); + + // Complete message and return + aMessage.Complete( KErrNone ); + + INFO( "Handled IPC message [EUnsubscribeAction]" ); + + break; + } + + // Slot[0] = TDesC - Action indication buffer + // Slot[1] = TDesC - Buffer size if current too small + case EListenActionSubscription: + { + INFO( "Handling IPC message [EListenActionSubscription]" ); + + // Store message and check if there is action indication + // waiting + iSubscriptionListenMessage = aMessage; + CheckActionQueueL(); + + INFO( "Handled IPC message [EListenActionSubscription]" ); + + break; + } + + // Slot[0] = TDesC - Action indication buffer + case EGetActionIndication: + { + INFO( "Handling IPC message [EGetActionIndication]" ); + + TInt err = KErrNone; + + // check that we really have an action indication waiting + if( iCurrentAction ) + { + // Indicate current action to client + // This should not fail since we are here with this op code + // only if server side has requested client to increase buffer. + HBufC8* buffer = ExternalizeIndicationLC( *iCurrentAction ); + TPtr8 bufferPtr = buffer->Des(); + + // Write message + aMessage.WriteL( 0, bufferPtr ); + + // Cleanup + CleanupStack::PopAndDestroy( buffer ); + + // Current action processed, delete and zero + delete iCurrentAction; + iCurrentAction = NULL; + } + else + { + // No action indications found + err = KErrNotFound; + } + + // Complete message and return + aMessage.Complete( err ); + + INFO( "Handled IPC message [EGetActionIndication]" ); + + break; + } + + case ECancelListenActionSubscription: + { + INFO( "Handling IPC message [ECancelListenActionSubscription]" ); + + // Check if subscription message has not been completed yet + if( !iSubscriptionListenMessage.IsNull() ) + { + iSubscriptionListenMessage.Complete( KErrCancel ); + } + aMessage.Complete( KErrNone ); + + INFO( "Handled IPC message [ECancelListenActionSubscription]" ); + + break; + } + + default: + { + // Message not handled + handled = EFalse; + break; + } + } + + return handled; + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerAction::ActionIndicationL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerAction::ActionIndicationL( + CCFActionIndication* aIndication ) + { + FUNC_LOG; + + INFO_1( "Received action indication: %S", &aIndication->Identifier() ); + + // Append action indication in queue and check queue + TInt err = iActionQueue.Append( aIndication ); + if( err == KErrNone ) + { + CheckActionQueueL(); + } + else + { + // Something odd happened, try to serve this indication + // We still need to have request message pending + if( !iSubscriptionListenMessage.IsNull() && !iCurrentAction ) + { + iCurrentAction = aIndication; + IndicateCurrentActionL(); + } + else + { + // Cannot serve this, delete + delete aIndication; + } + } + } + +//------------------------------------------------------------------------------ +// CCFMessageHandlerAction::ActionOwner +//------------------------------------------------------------------------------ +// +MCFActionOwner::TCFActionOwner CCFMessageHandlerAction::ActionOwner() const + { + FUNC_LOG; + + return MCFActionOwner::ECFExternalAction; + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerAction::CheckActionQueueL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerAction::CheckActionQueueL() + { + FUNC_LOG; + + // If we have: + // - Actions in the queue + // - Currently not processing any actions + // - Listen message outstanding + if( iActionQueue.Count() && + !iCurrentAction && + !iSubscriptionListenMessage.IsNull() ) + { + // Get latest action + iCurrentAction = iActionQueue[0]; + iActionQueue.Remove( 0 ); + + // Indicate current action to client + IndicateCurrentActionL(); + } + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerAction::IndicateCurrentActionL +//----------------------------------------------------------------------------- +// +void CCFMessageHandlerAction::IndicateCurrentActionL() + { + FUNC_LOG; + + __ASSERT_DEBUG( iCurrentAction, + Panic( iSubscriptionListenMessage, ENoCurrentAction ) ); + + // Check client buffer + TInt err = KErrNone; + CCFActionIndicationImpl* indication = + static_cast( iCurrentAction ); + TInt indicationSize = indication->Size(); + TInt clientBufSize = iSubscriptionListenMessage.GetDesMaxLengthL( 0 ); + if( indicationSize > clientBufSize ) + { + // Client buffer too small + // Write new buffer size in Slot[1] + TPckgBuf indicationSizeBuf( indicationSize ); + iSubscriptionListenMessage.WriteL( 1, indicationSizeBuf ); + err = KErrTooBig; + } + else + { + // Client buffer sufficient + // Stream indication into descriptor + HBufC8* buffer = ExternalizeIndicationLC( *indication ); + TPtr8 bufferPtr = buffer->Des(); + + // Write message + iSubscriptionListenMessage.WriteL( 0, bufferPtr ); + + // Cleanup + CleanupStack::PopAndDestroy( buffer ); + delete iCurrentAction; + iCurrentAction = NULL; + } + + // Complete message + iSubscriptionListenMessage.Complete( err ); + } + +//----------------------------------------------------------------------------- +// CCFMessageHandlerAction::ExternalizeIndicationL +//----------------------------------------------------------------------------- +// +HBufC8* CCFMessageHandlerAction::ExternalizeIndicationLC( + CCFActionIndication& aIndication ) + { + FUNC_LOG; + + CCFActionIndicationImpl& indication = + static_cast( aIndication ); + + HBufC8* buffer = HBufC8::NewLC( indication.Size() ); + TPtr8 bufferPtr = buffer->Des(); + RDesWriteStream stream( bufferPtr ); + stream.PushL(); + indication.ExternalizeL( stream ); + + // Cleanup + CleanupStack::PopAndDestroy( &stream ); + + return buffer; + }