diff -r 000000000000 -r 5a93021fdf25 connectionmonitoring/connmon/connectionmonitor/src/CPlugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/connectionmonitoring/connmon/connectionmonitor/src/CPlugin.cpp Thu Dec 17 08:55:21 2009 +0200 @@ -0,0 +1,826 @@ +/* +* Copyright (c) 2003-2007 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: Plug-in object subsession. +* +*/ + +#include "ConnMonServ.h" +#include "ConnMonIAP.h" +#include "CEventQueue.h" +#include "CPlugin.h" +#include "log.h" + +// ============================ MEMBER FUNCTIONS =============================== + +// Constructor +TAttributeRequest::TAttributeRequest( + TUint aType, + TUint aAttribute, + TUint aData ) + : + iType( aType ), + iAttribute( aAttribute ), + iData( aData ) + { + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CPlugin::CPlugin +// ----------------------------------------------------------------------------- +// +CPlugin::CPlugin() + { + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CPlugin::~CPlugin() + { + // Complete any outstanding plug-in request + CancelGetQuery(); + + // Close the attributes array + iAttributesSupported.Close(); + + // Complete all outstanding client requests + TInt count = iClientRequests.Count(); + + for ( TInt i = 0; i < count; i++ ) + { + const TClientRequest* req = &( iClientRequests[i] ); + + // Complete only asynchronous client requests + if ( req->iType == EReqGetIntAttribute || + req->iType == EReqGetUintAttribute || + req->iType == EReqGetBoolAttribute || + req->iType == EReqGetStringAttribute || + req->iType == EReqGetPckgAttribute ) + { + req->iMessage.Complete( KErrCancel ); + } + } + + iClientRequests.Close(); + + iSession = 0; + + LOGIT1("SERVER: Plugin destroyed, id <%d>", iPluginId ) + } + +// ----------------------------------------------------------------------------- +// CPlugin::NewL +// ----------------------------------------------------------------------------- +// +CPlugin* CPlugin::NewL( CConnMonSession* aSession, const TUint aPluginId ) + { + CPlugin* self = new ( ELeave ) CPlugin; + + CleanupStack::PushL( self ); + self->ConstructL( aSession, aPluginId ); + CleanupStack::Pop( self ); + + return self; + } + +// ----------------------------------------------------------------------------- +// CPlugin::ConstructL +// ----------------------------------------------------------------------------- +// +void CPlugin::ConstructL( CConnMonSession* aSession, const TUint aPluginId ) + { + TName name; + + name.Format( KPluginName, this ); + SetNameL( &name ); + + iSession = aSession; + iPluginId = aPluginId; + } + +// ----------------------------------------------------------------------------- +// CPlugin::RegisterAttribute +// ----------------------------------------------------------------------------- +// +TInt CPlugin::RegisterAttribute( const TUint aAttribute ) + { + LOGIT2("SERVER: EReqPluginRegisterAttribute, id <%d>, attr <%d>", iPluginId, aAttribute ) + + for ( TInt i = 0; i < iAttributesSupported.Count(); i++ ) + { + if ( iAttributesSupported[i] == aAttribute ) + { + // Attribute has already been registered + return ( KErrNone ); + } + } + + iAttributesSupported.Append( aAttribute ); + + // Check if the clients have set 'KBearerAvailabilityThreshold' earlier + if ( aAttribute == KBearerAvailabilityThreshold ) + { + TUint th( 0 ); + + // Have clients set the threshold earlier + iSession->iCmServer->CalculateThreshold( 0, EBearerAvailabilityThreshold, th ); + + if ( th == 1 ) + { + // Add the request (set threshold) to the queue (aPending is EFalse) + const RMessage2 dummy; + + TClientRequest clientReq( EReqInternalSetThreshold, EFalse, dummy ); + iClientRequests.Append( clientReq ); + } + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CPlugin::CancelRegisterAttribute +// ----------------------------------------------------------------------------- +// +TInt CPlugin::CancelRegisterAttribute( const TUint aAttribute ) + { + LOGIT2("SERVER: EReqPluginCancelRegisterAttribute, id <%d>, attr <%d>", iPluginId, aAttribute ) + + for ( TInt i = 0; i < iAttributesSupported.Count(); i++ ) + { + if ( iAttributesSupported[i] == aAttribute ) + { + // Complete any outstanding client requets + TInt count = iClientRequests.Count(); + + for ( TInt j = 0; j < count; j++ ) + { + const TClientRequest* req = &( iClientRequests[j] ); + + if ( static_cast< TInt >( aAttribute ) == req->iMessage.Int2( ) ) + { + // Complete only asynchronous client requests + if ( req->iType == EReqGetIntAttribute || + req->iType == EReqGetUintAttribute || + req->iType == EReqGetBoolAttribute || + req->iType == EReqGetStringAttribute || + req->iType == EReqGetPckgAttribute ) + { + req->iMessage.Complete( KErrCancel ); + } + iClientRequests.Remove( j ); + count--; + j--; + } + } + + iAttributesSupported.Remove( i ); + return ( KErrNone ); + } + } + + return KErrNotFound; + } + +// ----------------------------------------------------------------------------- +// CPlugin::Event +// ----------------------------------------------------------------------------- +// +TInt CPlugin::Event( + const RMessage2& aMessage, + TEventInfo& aEventInfo, + TUint8*& aPtr, + TInt& aSize ) const + { + TUint eventId = aMessage.Int0(); + + TUint desLen = aMessage.GetDesLength( 1 ); + + // Max allowed data size is 512 bytes + if ( desLen > KConnMonMaxPluginDataSize ) + { + return KErrTooBig; + } + + HBufC8* buf = HBufC8::New( desLen ); + + if ( !buf ) + { + return KErrNoMemory; + } + + TPtr8 initptr = buf->Des(); + + // Read the contents of the client pointer into a TPtr. + TInt res = aMessage.Read( 1, initptr ); + + if ( res != KErrNone ) + { + delete buf; + iSession->iCmServer->PanicClient( EBadDescriptor ); + return KErrBadHandle; + } + + // Create the event to be forwarded to the clients + aEventInfo.Reset(); + + aEventInfo.iEventType = eventId; + aEventInfo.iConnectionId = iPluginId; + + if ( ( eventId == EConnMonSignalStrengthChange ) && ( desLen == sizeof( TInt ) ) ) + { + // Signal strength changed event + aEventInfo.iData = static_cast( *initptr.Ptr() ); + } + else if ( ( eventId == EConnMonBearerAvailabilityChange ) && ( desLen == sizeof( TBool ) ) ) + { + // Bearer availability changed event + aEventInfo.iData = static_cast( *initptr.Ptr() ); + } + else if ( ( eventId == EConnMonIapAvailabilityChange ) && + ( desLen == sizeof( TConnMonIapInfo ) ) ) + { + // IAP availability changed event + TConnMonIapInfo* receivedIapInfo = + const_cast( + reinterpret_cast( initptr.Ptr() ) ); + + // Event contains only limited info on IAPs (= count + IDs) + TConnMonIapInfo* eventIaps( NULL ); + eventIaps = new TConnMonIapInfo; + + if ( eventIaps ) + { + aEventInfo.iData = receivedIapInfo->Count(); + + eventIaps->iCount = receivedIapInfo->Count(); + + for ( TInt i = 0; i < KConnMonMaxIAPCount && i < receivedIapInfo->Count(); i++ ) + { + eventIaps->iIap[i].iIapId = receivedIapInfo->iIap[i].iIapId; + } + + aPtr = reinterpret_cast( eventIaps ); + aSize = sizeof( TConnMonIapInfo ); + } + } + else if ( ( eventId >= EConnMonPluginEventBase ) && ( desLen == sizeof( TUint ) ) ) + { + // Plugin specific event. Only 32-bit data (desLen is 4 bytes) supported so far + aEventInfo.iData = static_cast( *initptr.Ptr() ); + aEventInfo.iData2 = desLen; + } + else + { + // Event is not supported + LOGIT2("SERVER: Plugin sent unsupported event or length of the data was invalid. -> id <%d>, event <%d>", iPluginId, eventId ) + + delete buf; + return KErrNotSupported; + } + + delete buf; + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CPlugin::Attribute +// ----------------------------------------------------------------------------- +// +TInt CPlugin::Attribute( const RMessage2& aMessage ) + { + TUint attribute( aMessage.Int0() ); + TInt returnCode( aMessage.Int1() ); + + TUint desLen = aMessage.GetDesLength( 2 ); + + // Max allowed data size is 512 bytes + if ( desLen > KConnMonMaxPluginDataSize ) + { + return KErrTooBig; + } + + // Allocate a buffer for reading + HBufC8* buf = HBufC8::New( desLen ); + TPtr8 initptr = buf->Des(); + + // read the contents of the client pointer into a TPtr. + TInt res = aMessage.Read( 2, initptr ); + + if ( res != KErrNone ) + { + delete buf; + iSession->iCmServer->PanicClient( EBadDescriptor ); + + return KErrBadHandle; + } + + TInt count = iClientRequests.Count(); + + // Complete all outstanding client request for this attribute + for ( TInt i = 0; i < count; i++ ) + { + const TClientRequest* req = &( iClientRequests[i] ); + + if ( static_cast< TInt >( attribute ) == req->iMessage.Int2( ) ) + { + // Found a request matching the attribute + switch ( req->iType ) + { + case EReqGetIntAttribute: + { + if ( desLen != sizeof( TInt ) ) + { + req->iMessage.Complete( KErrArgument ); + break; + } + + TInt value = static_cast< TInt >( *initptr.Ptr() ); + + LOGIT4("SERVER: Attribute from plugin, id <%d>, attr <%d>, -> value <%d>, ret <%d>", iPluginId, attribute, value, returnCode ) + + TPtr8 n( reinterpret_cast< TUint8* >( &value ), + sizeof( TInt ), + sizeof( TInt ) ); + + res = req->iMessage.Write( KAttributeParameterIndex, n ); + + if ( res != KErrNone ) + { + PanicWaitingClient( EBadDescriptor, req->iMessage ); + } + else + { + req->iMessage.Complete( returnCode ); + } + + break; + } + case EReqGetUintAttribute: + { + if ( desLen != sizeof( TUint ) ) + { + req->iMessage.Complete( KErrArgument ); + break; + } + + TUint value = static_cast< TUint >( *initptr.Ptr() ); + + LOGIT4("SERVER: Attribute from plugin, id <%d>, attr <%d>, -> value <%d>, ret <%d>", iPluginId, attribute, value, returnCode ) + + TPtr8 n( reinterpret_cast< TUint8* >( &value ), + sizeof( TUint ), + sizeof( TUint ) ); + + res = req->iMessage.Write( KAttributeParameterIndex, n ); + + if ( res != KErrNone ) + { + PanicWaitingClient( EBadDescriptor, req->iMessage ); + } + else + { + req->iMessage.Complete( returnCode ); + } + break; + } + case EReqGetBoolAttribute: + { + if ( desLen != sizeof( TBool ) ) + { + req->iMessage.Complete( KErrArgument ); + break; + } + + TBool value = static_cast< TBool >( *initptr.Ptr() ); + + LOGIT4("SERVER: Attribute from plugin, id <%d>, attr <%d>, -> value <%d>, ret <%d>", iPluginId, attribute, value, returnCode ) + + TPtr8 n( reinterpret_cast< TUint8* >( &value ), + sizeof( TBool ), + sizeof( TBool ) ); + + res = req->iMessage.Write( KAttributeParameterIndex, n ); + + if ( res != KErrNone ) + { + PanicWaitingClient( EBadDescriptor, req->iMessage ); + } + else + { + req->iMessage.Complete( returnCode ); + } + + break; + } + case EReqGetPckgAttribute: + { + // Write as such to the client area since this is TDes8 + LOGIT3("SERVER: Attribute from plugin, id <%d>, attr <%d>, -> ret <%d>", iPluginId, attribute, returnCode ) + + res = req->iMessage.Write( KAttributeParameterIndex, initptr ); + + if ( res != KErrNone ) + { + PanicWaitingClient( EBadDescriptor, req->iMessage ); + } + else + { + req->iMessage.Complete( returnCode ); + } + break; + } + case EReqGetStringAttribute: + { + // String is a 16-bit descriptor. + // Allocate a 16-bit buffer for reading the string. + HBufC* buf16 = HBufC::New( desLen ); + TPtr initptr16 = buf16->Des(); + + // read the contents of the client pointer into a TPtr. + res = aMessage.Read( 2, initptr16 ); + + if ( res != KErrNone ) + { + delete buf; + delete buf16; + iSession->iCmServer->PanicClient( EBadDescriptor ); + + return KErrBadHandle; + } + + LOGIT3("SERVER: Attribute from plugin, id <%d>, attr <%d>, -> ret <%d>", iPluginId, attribute, returnCode ) + + res = req->iMessage.Write( KAttributeParameterIndex, initptr16 ); + + if ( res != KErrNone ) + { + PanicWaitingClient( EBadDescriptor, req->iMessage ); + } + else + { + req->iMessage.Complete( returnCode ); + } + + delete buf16; + + break; + } + default: + { + delete buf; + return KErrNotSupported; + } + } // switch + + // Remove the query because it has been served + iClientRequests.Remove( i ); + count--; + i--; + } // if + } // For + + delete buf; + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CPlugin::GetQuery +// ----------------------------------------------------------------------------- +// +TInt CPlugin::GetQuery() + { + if ( !iPluginReqActive ) + { + return KErrNotReady; + } + + // Check if there is a client request waiting in the queue + TInt count = iClientRequests.Count(); + + for ( TInt i = 0; i < count; i++ ) + { + if ( !iClientRequests[i].iPending ) + { + TInt attribute( iClientRequests[i].iMessage.Int2() ); + TInt data( iClientRequests[i].iMessage.Int3() ); + + // Send the attribute request to the plug-in + TAttributeRequest req( iClientRequests[i].iType, attribute, 0 ); + + if ( req.iType == EReqSetIntAttribute || + req.iType == EReqSetUintAttribute || + req.iType == EReqSetBoolAttribute ) + { + req.iData = data; + } + else if ( req.iType == EReqInternalSetThreshold ) + { + req.iType = EReqSetUintAttribute; + req.iAttribute = KBearerAvailabilityThreshold; + req.iData = 1; + } + else if ( req.iType == EReqInternalResetThreshold ) + { + req.iType = EReqSetUintAttribute; + req.iAttribute = KBearerAvailabilityThreshold; + req.iData = 0; + } + + TPtr8 n( reinterpret_cast< TUint8* >( &req ), + sizeof( TAttributeRequest ), + sizeof( TAttributeRequest ) ); + + TInt res = iPluginReqMessage.Write( 0, n ); + + if ( res != KErrNone ) + { + iSession->iCmServer->PanicClient( EBadDescriptor ); + } + else + { + // Complete the message + iPluginReqMessage.Complete( KErrNone ); + } + + iPluginReqActive=EFalse; + + if ( req.iType == EReqSetIntAttribute || + req.iType == EReqSetUintAttribute || + req.iType == EReqSetBoolAttribute || + req.iType == EReqSetStringAttribute || + req.iType == EReqSetPckgAttribute ) + { + // This request is synchronous and has already been completed + iClientRequests.Remove( i ); + count--; + i--; + } + + return KErrNone; + } + } + + // Queue was empty. + // Just wait for a client request to arrive. + return KRequestPending; + } + +// ----------------------------------------------------------------------------- +// CPlugin::GetQuery +// ----------------------------------------------------------------------------- +// +TInt CPlugin::GetQuery( const RMessage2& aMessage ) + { + __ASSERT_DEBUG( !iPluginReqActive, PanicServer( EReceiveAlreadyActive ) ); + + LOGIT("SERVER: EReqPluginGetQuery") + + // Remember attribute request + iPluginReqMessage = aMessage; + iPluginReqBuffer = aMessage.Ptr0(); + iPluginReqActive = ETrue; + + return GetQuery(); + } + +// ----------------------------------------------------------------------------- +// CPlugin::CancelGetQuery +// ----------------------------------------------------------------------------- +// +TInt CPlugin::CancelGetQuery() + { + LOGIT("SERVER: EReqPluginCancelGetQuery") + + if ( iPluginReqActive ) + { + iPluginReqMessage.Complete( KErrCancel ); + iPluginReqActive = EFalse; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CPlugin::GetAttributeForClient +// From a CLIENT. +// ----------------------------------------------------------------------------- +// +TInt CPlugin::GetAttributeForClient( const TInt aType, const RMessage2& aMessage ) + { + LOGENTRFN("CPlugin::GetAttributeForClient()") + TUint connectionId( aMessage.Int0() ); + TUint attribute( aMessage.Int2() ); + TInt data( aMessage.Int3() ); + + if ( aType == EReqInternalSetThreshold || aType == EReqInternalResetThreshold ) + { + connectionId = iPluginId; + attribute = KBearerAvailabilityThreshold; + } + + if ( connectionId <= KMaxConnectionId ) + { + // Client is asking an attribute using a normal connectionID instead of pluginID. + TInt bearer( EBearerUnknown ); + TBearerInfo bearerInfo; + + TInt ret = iSession->iCmServer->Iap()->GetBearer( connectionId, bearer, bearerInfo ); + + if ( ret == KErrNone ) + { + // Find the corresponding pluginID + if ( bearer == EBearerWLAN ) + { + connectionId = EBearerIdWLAN; + } + else if ( bearer == EBearerLAN ) + { + connectionId = EBearerIdLAN; + } + } + } + + // Check that request is aimed to this plugin. + if ( connectionId != iPluginId ) + { + LOGEXITFN1("CPlugin::GetAttributeForClient()", KErrNotSupported) + return KErrNotSupported; + } + + if ( aType == EReqSetStringAttribute || aType == EReqSetPckgAttribute ) + { + // Setting string or packaged attributes is not supported + LOGEXITFN1("CPlugin::GetAttributeForClient()", KErrNotSupported) + return KErrNotSupported; + } + + for ( TInt i = 0; i < iAttributesSupported.Count(); i++ ) + { + if ( iAttributesSupported[i] == attribute ) + { + TAttributeRequest req( aType, attribute, 0 ); + + if ( aType == EReqSetIntAttribute || + aType == EReqSetUintAttribute || + aType == EReqSetBoolAttribute ) + { + req.iData = data; + } + else if ( aType == EReqInternalSetThreshold ) + { + req.iType = EReqSetUintAttribute; + req.iData = 1; + } + else if ( aType == EReqInternalResetThreshold ) + { + req.iType = EReqSetUintAttribute; + req.iData = 0; + } + + if ( iPluginReqActive ) + { + TBool pending( ETrue ); + + // Send the attribute request to the plug-in + TPtr8 n( reinterpret_cast< TUint8* >( &req ), + sizeof( TAttributeRequest ), + sizeof( TAttributeRequest ) ); + + TInt res = iPluginReqMessage.Write( 0, n ); + + if ( res != KErrNone ) + { + PanicWaitingClient( EBadDescriptor, iPluginReqMessage ); + pending = EFalse; + } + else + { + // Complete the message + iPluginReqMessage.Complete( KErrNone ); + } + + iPluginReqActive=EFalse; + + // Add the request to queue + // aPending is ETrue + if ( aType == EReqGetIntAttribute || + aType == EReqGetUintAttribute || + aType == EReqGetBoolAttribute || + aType == EReqGetStringAttribute || + aType == EReqGetPckgAttribute ) + { + TClientRequest clientReq( aType, pending, aMessage ); + iClientRequests.Append( clientReq ); + } + } + else + { + // Add the request to the queue + // aPending is EFalse + TClientRequest clientReq( aType, EFalse, aMessage ); + iClientRequests.Append( clientReq ); + } + + LOGEXITFN1("CPlugin::GetAttributeForClient()", KRequestPending) + return KRequestPending; + } + } + + LOGEXITFN1("CPlugin::GetAttributeForClient()", KErrNotSupported) + return KErrNotSupported; + } + +// ----------------------------------------------------------------------------- +// CPlugin::CancelGetAttributeForClient +// From a CLIENT. +// ----------------------------------------------------------------------------- +// +void CPlugin::CancelGetAttributeForClient( const RThread& aClient, const TInt aType ) + { + TInt count = iClientRequests.Count(); + + for ( TInt i = 0; i < count; i++ ) + { + const TClientRequest* req = &( iClientRequests[i] ); + + RThread client; + + TInt err = req->iMessage.Client( client ); + + if ( err == KErrNone ) + { + if ( ( static_cast< TUint >( aType ) == req->iType ) && + ( client.Id() == aClient.Id() ) ) + { + req->iMessage.Complete( KErrCancel ); + + iClientRequests.Remove( i ); + count--; + i--; + } + + client.Close(); + } + } + } + +// ----------------------------------------------------------------------------- +// CPlugin::SetAttributeForClient +// From a CLIENT. +// ----------------------------------------------------------------------------- +// +TInt CPlugin::SetAttributeForClient( const TInt aType, const RMessage2& aMessage ) + { + TInt ret = GetAttributeForClient( aType, aMessage ); + + if ( ret == KRequestPending ) + { + // Complete immediately + return KErrNone; + } + else + { + return ret; + } + } + +// ----------------------------------------------------------------------------- +// CPlugin::PanicWaitingClient +// ----------------------------------------------------------------------------- +// +void CPlugin::PanicWaitingClient( TInt aPanic, const RMessage2& aMessage ) const + { + // Let's have a look before we panic the client + __DEBUGGER() + + // Ok, go for it + RThread client; + + TInt err = aMessage.Client( client ); + + if ( err == KErrNone ) + { + _LIT( KPanicMessage, "ConnMonServ" ); + client.Panic( KPanicMessage, aPanic ); + client.Close(); + } + } + +// End-of-file