diff -r 000000000000 -r dfb7c4ff071f datacommsserver/esockserver/ssock/ss_conn.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/ssock/ss_conn.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,1044 @@ +// Copyright (c) 2005-2009 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: +// + +/** + @file + @internalTechnology +*/ + +#define SYMBIAN_NETWORKING_UPS + +#include +#include +#include +#include +#include +#include "SS_conn.H" +#include "ss_connstates.h" +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include //KAfInet only + +#include + +#include + +#ifdef SYMBIAN_NETWORKING_UPS +#include // reference from ESock to UpsCoreProviders - should we move the UPS messages into ESock? +#endif + +#ifdef _DEBUG +// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module +// (if it could happen through user error then you should give it an explicit, documented, category + code) +// UNCOMMENT IF INSERTING AN ASSERT +//_LIT(KSpecAssert_ESockSSocks_cn, "ESockSSocks_cn."); +#endif + + + +using namespace ESock; +using namespace SubSessActivities; +using namespace NetStateMachine; +using namespace ConnActivities; +using namespace SubSessStates; +using namespace CoreStates; +using namespace Elements; +using namespace Messages; +using namespace MeshMachine; +using namespace Den; + +//We reserve space for two preallocated activities that may start concurrently on the connection +//node: destroy (connection close) and connection stop. +static const TUint KDefaultMaxPreallocatedActivityCount = 2; +static const TUint KMaxPreallocatedActivitySize = sizeof(CNodeRetryParallelActivity) + sizeof(APreallocatedOriginators<4>); +static const TUint KConnectionPreallocatedActivityBufferSize = KDefaultMaxPreallocatedActivityCount * KMaxPreallocatedActivitySize; + +// +//Activities serving client (RConnection) requests +namespace ConnectionStartActivity +{ + //Synchronised activity, must wait for stop (exclusive with close) +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStart, ConnectionStart, TCFInternalEsock::TSubSess, ConnActivities::CStartAttachActivity::NewStartConnectionActivityL) + FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, MeshMachine::TNoTag) + + // If the IPC was ECNSetStartPrefs we expect another IPC to start the connection + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessStartBlockedByStop, ConnActivities::CStartAttachActivity::TNoTagOrStartPrefsSetTag) + NODEACTIVITY_ENTRY(ConnActivities::CStartAttachActivity::KStartPrefsSetTag, MeshMachine::TDoNothing, SubSessStates::TAwaitingIPC, ConnActivities::CStartAttachActivity::TStartPrefsSetTag) + THROUGH_NODEACTIVITY_ENTRY(ConnActivities::CStartAttachActivity::KStartPrefsSetTag, SubSessStates::TAcquireMessageOwnership, ConnActivities::CStartAttachActivity::TStartPrefsSetTag) + THROUGH_NODEACTIVITY_ENTRY(ConnActivities::CStartAttachActivity::KStartPrefsSetTag, ConnStates::TParseECNStart, MeshMachine::TNoTag) + + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TClearProgressQueue, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TSendStartingSelectionStateChange, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TRequestCSRCreation, TECABState, MeshMachine::TNoTag) + + + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessCSRCreation, MeshMachine::TNoTag) + + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TSelectMetaPlane, ConnActivities::CStartAttachActivity::TAwaitingSelectCompleteOrError, MeshMachine::TNoTagOrErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing) + + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TJoinReceivedMcpr, TECABState, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TRequestCommsBinderFromMcpr, TAcceptErrorState, MeshMachine::TNoTagOrErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, CoreActivities::ABindingActivity::TSendBindToComplete) //Terminate the activity + + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TSendFinishedSelectionStateChange, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessBinderResponseForCpr, TECABState, MeshMachine::TNoTag) + +#ifdef SYMBIAN_NETWORKING_UPS + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnActivities::CStartAttachActivity::TSendBindToComplete, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CStartAttachActivity::TSendPolicyCheckRequestToServiceProvider, TAcceptErrorState >, CStartAttachActivity::TNoTagOrUpsErrorTag) + // - requesting and joining the default scpr just to satisfy the subconn related datamonitoring API. + //If the default scpr isn't there, we'll ignore the error here but we will dissallow subscribing to subcon-related data monitoring. + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TRequestCommsBinder, TAcceptErrorState, MeshMachine::TNoTagOrErrorTag) + #endif + + +#ifndef SYMBIAN_NETWORKING_UPS + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnActivities::CStartAttachActivity::TSendBindToComplete, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TRequestCommsBinder, TAcceptErrorState, MeshMachine::TNoTagOrErrorTag) +#endif + + + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TJoinReceivedSCpr, TECABState, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreActivities::ABindingActivity::TSendBindToComplete, MeshMachine::TNoTag) + // Act on cancellation errors, ignore all others. + ROUTING_NODEACTIVITY_ENTRY(KErrorTag, ConnStates::TErrorOrCancel) + THROUGH_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TClearError, MeshMachine::TNoTag) + //> + + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnActivities::CStartAttachActivity::TSubscribeForAvailability, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, ConnActivities::CStartAttachActivity::TNoTagOrWaitAvailable) + NODEACTIVITY_ENTRY(ConnActivities::CStartAttachActivity::KWaitAvailable, MeshMachine::TDoNothing, ConnActivities::CStartAttachActivity::TAwaitingAvailableOrError, MeshMachine::TNoTag) + + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TStartConnection, TAcceptErrorState, CoreStates::TCancelOrErrorOrTag) + // Handle error during start + THROUGH_NODEACTIVITY_ENTRY(KErrorTag, ConnStates::TGenerateConnectionDownProgress, ConnActivities::CStartAttachActivity::TErrorTagOrWaitAvailableBackward) + + LAST_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TGenerateConnectionUpProgress ) + + // Handle error during start. + THROUGH_NODEACTIVITY_ENTRY(ConnActivities::CStartAttachActivity::KCancelTag, MeshMachine::TDoNothing, MeshMachine::TErrorTag) // just a tag +#ifdef SYMBIAN_NETWORKING_UPS + THROUGH_NODEACTIVITY_ENTRY(CStartAttachActivity::KUpsErrorTag, TDoNothing, MeshMachine::TErrorTag) +#endif + NODEACTIVITY_ENTRY(KErrorTag, CoreNetStates::TSendClientLeavingRequestToServiceProviders, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSetIdleIfNoServiceProviders, MeshMachine::TAwaitingLeaveComplete, ConnectionCleanupActivities::TNoTagOrNoTagBackwards) + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) +NODEACTIVITY_END() +} + +namespace ConnectionAttachActivity +{ +typedef SubSessStates::TAwaitingSecuredIpc, ECapabilityNetworkServices> TAwaitingSecuredAttachIpc; + +//Synchronised activity, must wait for stop (exclusive with close) +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityConnectionAttach, ConnectionAttach, TCFInternalEsock::TSubSess, ConnActivities::CStartAttachActivity::NewStartConnectionActivityL) +#ifdef SYMBIAN_NETWORKING_UPS + // UPS support. Platform Security check now takes place in the Cpr as part of the control client join activity. + FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC, MeshMachine::TNoTag) +#else + FIRST_NODEACTIVITY_ENTRY(TAwaitingSecuredAttachIpc, MeshMachine::TNoTag) +#endif + // NOTE: TAcquireMessageOwnership MUST occur before any blocking takes place, otherwise the Player will + // complete the message upon return from the blocked activity. + THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, CoreNetStates::TNoTagBlockedByStop) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessAttachBlockedByStop, TECABState, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessCSRCreation, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TSelectMetaPlane, ConnActivities::CStartAttachActivity::TAwaitingSelectCompleteOrError, MeshMachine::TNoTagOrErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing) + + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TJoinReceivedMcpr, TECABState, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TRequestCommsBinderFromMcpr, TAcceptErrorState, MeshMachine::TNoTagOrErrorTag) + LAST_NODEACTIVITY_ENTRY(KErrorTag, CoreActivities::ABindingActivity::TSendBindToComplete) //Terminate the activity + + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessBinderResponseForCpr, TECABState, CStartAttachActivity::TNoTagOrLegacyAttach) + + //New Attach - go here + LAST_NODEACTIVITY_ENTRY(KNoTag, ConnActivities::CStartAttachActivity::TSendBindToComplete) + //Legacy Attach - go here + LAST_NODEACTIVITY_ENTRY(CStartAttachActivity::KExecuteLegacyAttach, ConnActivities::CStartAttachActivity::TSendBindToCompleteAndCompleteLegacyAttach) +NODEACTIVITY_END() +} + +namespace ConnectionStopActivity +{ +//Synchronised activity, must wait for start to finish +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStop, ConnectionStop, TCFInternalEsock::TSubSess, CPreallocatedESockClientActivity::New) + FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC, MeshMachine::TNoTag) + // NOTE: TAcquireMessageOwnership MUST occur before any blocking takes place, otherwise the Player will + // complete the message upon return from the blocked activity. + THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, CoreNetStates::TActiveOrNoTagBlockedByGoneDown) + THROUGH_NODEACTIVITY_ENTRY(KActiveTag, ConnStates::TCancelStartOrAttachConnection, ConnStates::TNoTagOrNoBearerBlockedByStartOrAttach) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TCancelAndCloseZone0ClientExtIfaces, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TCancelAllLegacyRMessage2Activities, ConnStates::TNoTagBlockedByLegacyRMessage2Activities) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TSendStopConnection, TECABState, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TGenerateConnectionDownProgress, MeshMachine::TNoTag) + + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingRequestToServiceProviders, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSetIdleIfNoServiceProviders, MeshMachine::TAwaitingLeaveComplete, ConnectionCleanupActivities::TNoTagOrNoTagBackwards) + + LAST_NODEACTIVITY_ENTRY(CoreNetStates::KNoBearer, MeshMachine::TDoNothing) + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) +NODEACTIVITY_END() +} + +/** + Legacy RConnection::Stop(TSubConnectionUniqueId aSubConnectionUniqueId) implementation +*/ +namespace ConnectionStopSCPRActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityStopSCPR, ConnectionStopSCPR, TCFInternalEsock::TSubSess, CESockClientActivityBase::NewL) + FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TConnectionSendStopSCPR, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing, TECABState, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) +NODEACTIVITY_END() +} + +/** + Legacy RConnection::EnumerateConnections implementation +*/ +namespace EnumerateConnectionsActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityConnectionEnumerateConnections, EnumerateConnections, TCFInternalEsock::TSubSess, CEnumerateConnectionsActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, MeshMachine::TNoTag) + + // Find the tier manager and query it. + NODEACTIVITY_ENTRY(KNoTag, CTierManagerActivity::TFindTierManager, TECABState, MeshMachine::TErrorTagOr >) + LAST_NODEACTIVITY_ENTRY(KErrorTag, MeshMachine::TDoNothing) + + NODEACTIVITY_ENTRY(KNoTag, CTierManagerActivity::TJoinTierManager, TECABState, MeshMachine::TNoTag) + + NODEACTIVITY_ENTRY(KNoTag, TQueryTierStatus, TECABState, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, TCacheConnectionInfo, MeshMachine::TNoTag) + + LAST_NODEACTIVITY_ENTRY(KNoTag, TCompleteClient) +NODEACTIVITY_END() +} + +namespace ConnectionGoneUpActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityAny, ConnectionGoneUp, TCFControlClient::TGoneUp) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingGoneUp, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TGenerateConnectionUpProgress) +NODEACTIVITY_END() +} + +namespace ConnectionCloseActivity +{ //Cancells all other running activities +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityDestroy, ConnectionClose, TCFInternalEsock::TSubSess, CCloseActivity::New) + FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC, MeshMachine::TNoTag) + // NOTE: TAcquireMessageOwnership MUST occur before any blocking takes place, otherwise the Player will + // complete the message upon return from the blocked activity. + THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, ConnStates::TActiveOrNoTagBlockedByStopOrGoneDown) + THROUGH_NODEACTIVITY_ENTRY(KActiveTag, ConnStates::TCancelStartOrAttachConnection, ConnStates::TNoTagBlockedByStartOrAttach) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TCancelAndCloseClientExtIfaces, ConnStates::TNoTagOrCancelAllInterfaceWorker) + // Handshake a shutdown of AllInterfaceNotificationWorker (send TCancel, await TError). + NODEACTIVITY_ENTRY(ConnStates::KCancelAllInterfaceWorker, ConnStates::TCancelAllInterfaceNotificationWorker, TAwaitingMessageState, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TCancelAllLegacyRMessage2Activities, ConnStates::TNoTagBlockedByLegacyRMessage2Activities) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessClose, TECABState, MeshMachine::TNoTag) + //TDestroyAwaitingLeaveCompleteLoop loops back to its own triple if more SPs + NODEACTIVITY_ENTRY(KNoTag, TECABTransition, TECABState, CoreActivities::CDestroyActivity::TNoTagOrNoTagBackwards) + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) //Never gets here +NODEACTIVITY_END() +} + +namespace ConnectionStateChangeNotificationActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityConnectionStateChangeRequest, ConnectionStateChangeNotification, TCFInternalEsock::TSubSess, CESockClientActivityBase::NewL) + FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, MeshMachine::TNoTag) + //TAwaitingStateChangeLoop also cancels the activity when requested + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessProgressRequest, TECABState >, MeshMachine::TNoTagBackward) + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) //Never gets here +NODEACTIVITY_END() +} + +namespace ConnectionWaitForIncomingActivity +{ //Synchronised, waits for Start to complete +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityConnectionWaitForIncoming, ConnectionWaitForIncoming, TCFInternalEsock::TSubSess, CStartAttachActivity::NewWaitForIncomingConnectionActivityL) + FIRST_NODEACTIVITY_ENTRY(SubSessStates::TAwaitingIPC, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TAcquireMessageOwnership, MeshMachine::TNoTag) + //We use ConnStates::TAwaitingBinderResponse (not CoreStates) for custom handling of the Cancel message + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TRequestIncomingConnectionBlockedByStartAttach, TECABState, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessIncomingConnection, TECABState, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, ConnActivities::CStartAttachActivity::TSendBindToComplete) +NODEACTIVITY_END() +} + +// +//Activities serving framework requests +namespace ConnectionStateChangeActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityStateChange, ConnectionStateChange, TCFMessage::TStateChange) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessStateChange, MeshMachine::TAwaitingMessageState, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + + + +namespace ConnectionGoingDownActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityGoneDown, ConnectionGoingDown, TCFControlClient::TGoneDown, PRActivities::CGoneDownActivity::NewL) + FIRST_NODEACTIVITY_ENTRY(ConnStates::TAwaitingGoneDown, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnectionGoingDownActivity::TStoreGoneDownError, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TCancelAndCloseZone0ClientExtIfaces, MeshMachine::TNoTag) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TCancelAllLegacyRMessage2Activities, ConnStates::TNoTagBlockedByLegacyRMessage2Activities) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSendClientLeavingRequestToServiceProviders, MeshMachine::TAwaitingLeaveComplete, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::TSetIdleIfNoServiceProviders, MeshMachine::TAwaitingLeaveComplete, ConnectionCleanupActivities::TNoTagOrNoTagBackwards) + LAST_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TGenerateConnectionDownProgress) +NODEACTIVITY_END() +} + +// +//Activities serving framework requests for legacy actions +namespace ConnectionClientEnumActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityLegacyConnEnumResponse, ConnectionEnumResponse, TCFInternalEsock::TLegacyConnectionEnumResponse) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessEnumResponse, ConnStates::TAwaitingEnumResponse, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +// +//CConn usually is a cntrl client of a default subconnection. +//The subconnection will send events, which must be handled to avoid leakages +namespace ConnSubConnectionEventNotification +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityConnectionWaitForIncoming, SubConEvent, TCFSubConnControlClient::TSubConnNotification) + NODEACTIVITY_ENTRY(KNoTag, SubSessStates::TBinEvent, CoreNetStates::TAwaitingSubConEvent, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace ConnSubConnEventsActivity +{ +DECLARE_DEFINE_NODEACTIVITY(ECFActivityConnSubConnEvents, ConnSubConnEvents, TNodeSignal::TNullMessageId) + NODEACTIVITY_ENTRY(KNoTag, ConnSubConnEventsActivity::TProcessSubConnEvent, ConnSubConnEventsActivity::TAwaitingSubConnEvent, MeshMachine::TNoTag) +NODEACTIVITY_END() +} + +namespace ConnLegacyRMessage2Activity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityConnectionLegacyRMessage2Handler, ConnectionLegacyRMessage2, TNodeSignal::TNullMessageId, CConnLegacyRMessage2Activity::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingLegacyRMessage2Ext, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, ConnStates::TProcessLegacyRMessage2, TAcceptErrorState, MeshMachine::TNoTagOrErrorTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, ConnStates::TCompleteRMessage2) + LAST_NODEACTIVITY_ENTRY(KErrorTag, ConnStates::THandleRMessage2Error) +NODEACTIVITY_END() +} + +namespace ConnectionActivities +{ +DECLARE_DEFINE_ACTIVITY_MAP(connectionActivities) + //-----Framework originated activities-----// + ACTIVITY_MAP_ENTRY(ConnectionStateChangeActivity, ConnectionStateChange) + ACTIVITY_MAP_ENTRY(ConnectionGoingDownActivity, ConnectionGoingDown) + ACTIVITY_MAP_ENTRY(ConnSubConnectionEventNotification, SubConEvent) + ACTIVITY_MAP_ENTRY(ConnSubConnEventsActivity, ConnSubConnEvents) + ACTIVITY_MAP_ENTRY(ConnectionStopSCPRActivity, ConnectionStopSCPR) + ACTIVITY_MAP_ENTRY(ConnectionGoneUpActivity,ConnectionGoneUp) + //-----Client (IPC) originated activities-----// + ACTIVITY_MAP_ENTRY(ConnectionWaitForIncomingActivity, ConnectionWaitForIncoming) + ACTIVITY_MAP_ENTRY(ConnectionCloseActivity, ConnectionClose) + ACTIVITY_MAP_ENTRY(ConnectionStartActivity, ConnectionStart) + ACTIVITY_MAP_ENTRY(ConnectionAttachActivity, ConnectionAttach) + ACTIVITY_MAP_ENTRY(ConnectionStateChangeNotificationActivity, ConnectionStateChangeNotification) + ACTIVITY_MAP_ENTRY(ConnectionStopActivity, ConnectionStop) + + ACTIVITY_MAP_ENTRY(ConnLegacyRMessage2Activity, ConnectionLegacyRMessage2) + +#ifdef AVAILABILITY_READY + ACTIVITY_MAP_ENTRY(EnumerateConnectionsActivity, EnumerateConnections) +#endif + + //-----Responses from Data plane to legacy queries-----// + ACTIVITY_MAP_ENTRY(ConnectionClientEnumActivity, ConnectionEnumResponse) +ACTIVITY_MAP_END() +} + +// attribute table for CConnectionIfno +START_ATTRIBUTE_TABLE(CConnectionInfo, CConnectionInfo::EUid, CConnectionInfo::ETypeId) +END_ATTRIBUTE_TABLE() + + +namespace ESock +{ +CConnectionInfo* CConnectionInfo::NewL(const Den::TSubSessionUniqueId& aSubSessionId) + { + return new(ELeave) CConnectionInfo(aSubSessionId); + } +} + +/** +Constructor +*/ +CConnection::CConnection(CSockSession* aSession, CPlayer* aPlayer, TUid aTierId, const Den::TSubSessionUniqueId aSubSessionUniqueId) +: CMMSockSubSession(ConnectionActivities::connectionActivities::Self(), aSession, aPlayer, aSubSessionUniqueId), + ASubSessionPlatsecApiExt(UniqueId()), + TIfStaticFetcherNearestInHierarchy(this), + iTierId(aTierId), + iLegacyConnection(*this) + { + LOG_NODE_CREATE1(KESockConnectionTag, CConnection, ", session %08x", aSession); + } +/** +Destructor +*/ +CConnection::~CConnection() + { + //Do not call CConnection::FinalCompleteAllBlockedMessages from here! + //At this stage we must be completed. + iLegacyConnection.FinalCompleteAllBlockedMessages(KErrCancel); //complete any outstanding legacy messages + delete iConnectionInfo; + LOG_NODE_DESTROY(KESockConnectionTag, CConnection); + } + +//MZTODO - only client activities? Is this a shutdown? +//Signal from subsession to abbort all (client?) activities (always KErrAbort) +void CConnection::FinalCompleteAllBlockedMessages(TInt /*aResult*/) + { + TNodeNullContext ctx(*this); + AbortActivitiesOriginatedBy(ctx); //Abort all activities + iLegacyConnection.FinalCompleteAllBlockedMessages(KErrCancel); //complete any outstanding legacy messages + } + +void CConnection::Received(TNodeContextBase& aContext) + { + TNodeSignal::TMessageId noPeerIds[] = { + TCFInternalEsock::TSubSess::Id(), + TEBase::TError::Id(), //May be comming from the CSR + TCFInternalEsock::TLegacyConnectionEnumResponse::Id(), // self-dispatching helper from the data plane + TNodeSignal::TMessageId() // list terminator + }; + + MeshMachine::AMMNodeBase::Received(noPeerIds, aContext); + MeshMachine::AMMNodeBase::PostReceived(aContext); + } + +void CConnection::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aCFMessage) + { + ESOCK_DEBUG_MESSAGE_INTERCEPT(aSender, aCFMessage, Id()); + + //First check if this is not our own error + TEBase::TError* msg = message_cast(&aCFMessage); + if (msg && aSender == Id() && msg->iMsgId == TCFInternalEsock::TSubSess::Id()) + { + //This is our own error, generated from the client (IPC) activity + //It is safe to just ignore it here, as the activity is + //completed (and so is the client RMessage2). If the activity didn't have + //the chance to acquire ownership of the message it is still safe to ignore it + //because there was no call to DoNotCompleteCurrentMessage(). + return; + } + + TNodeContext ctx(*this, aCFMessage, aSender, aRecipient); + CConnection::Received(ctx); + User::LeaveIfError(ctx.iReturn); + } + +void CConnection::ForwardToServiceProviderL(const TSignalBase& aCFMessage) + { + RNodeInterface* sp = ServiceProvider(); + User::LeaveIfError(sp? KErrNone : KErrNotReady); + sp->PostMessage(Id(), aCFMessage); + } + +CConnection* CConnection::NewLC(CSockSession *aSession, CPlayer* aPlayer, TUid aId, const Den::TSubSessionUniqueId aSubSessionUniqueId) +/** +Create a new CConnection instance + +@param aSession Session under which CConnection was created +@param aId Type Id of CConnection +@return pointer to new CConnection instance on success +@exception leaves if could not allocate memory +*/ + { + CConnection* h = new (ELeave) CConnection(aSession, aPlayer, aId, aSubSessionUniqueId); + CleanupStack::PushL(h); + h->ConstructL(); + ESOCK_DEBUG_REGISTER_GENERAL_NODE(ESockDebug::KConnectionNodeUid, h); + return h; + } + +CConnection* CConnection::NewLC(CSockSession* aSession, CPlayer* aPlayer, const CConnection& aExistingConnection, const Den::TSubSessionUniqueId aSubSessionUniqueId) +/** +Create a new CConnection object associated with the same interface as that of an existing CConnection object. + +@param aSession Session under which CConnection was created +@param aExistingConnection Existing CConnection object whose interface to associate with +@return pointer to new CConnection instance on success +@exception leaves if could not allocate memory +*/ + { + CConnection* h = new (ELeave) CConnection(aSession, aPlayer, aExistingConnection.iTierId, aSubSessionUniqueId); + CleanupStack::PushL(h); + h->ConstructL(); + h->CloneL(aExistingConnection); + return h; + } + +void CConnection::ConstructL() + { + MeshMachine::AMMNodeBase::ConstructL(KConnectionPreallocatedActivityBufferSize); + CSockSubSession::ConstructL(NULL); + + iConnectionInfo = CConnectionInfo::NewL(UniqueId()); + } + +void CConnection::CloneL(const CConnection& aExistingConnection) +/** +Main body of CConnection::NewL(CSockSession* aSession, const CConnection& aExistingConnection) +*/ + { + RNodeInterface* sp = aExistingConnection.ServiceProvider(); + if (sp) + { + AddClientL(sp->RecipientId(), TClientType(TCFClientType::EServProvider, TCFClientType::EActive)); + + // TODO IK: This is the wrong message to be using here, should use JoinRequest/Complete handshake + sp->PostMessage(Id(), TCFFactory::TPeerFoundOrCreated(Id(), 0).CRef()); + } + else + { + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x CloneL KErrNotReady"), this) ); + User::Leave(KErrNotReady); + } + } + + +RNodeInterface* CConnection::DefaultSubConnectionServiceProvider() + { + RNodeInterface* dscp = GetClientIter(TClientType(TCFClientType::EServProvider,TCFClientType::EDefault))[0]; + return dscp; + } + +void CConnection::ProcessMessageL() +/** + Process RConnection messages + + @exception Leaves on any error processing the request +*/ + { + LOG_DETAILED( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tCommand %d"), this, aMessage.Function()) ); + + //Some of the client (RMessage2) messages may need to be posted, for most it + //will be sufficient to dispatch them directly via ReceivedL (advantage of posting + //rather than dispatching -> of course mesh logging!) + switch (Message().Function()) + { + case ECNReference: + GetReferenceL(); + break; + + case ECNStart: + case ECNSetStartPrefs: + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNStart aMessage %08x"), this, &Message()) ); + //If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave + CMMSockSubSession::ReceivedL(ECNStart, TCFInternalEsock::TSubSess(ECNStart,Message()).CRef()); + break; + + case ECNAttach: + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNAttach aMessage %08x"), this, &Message()) ); + //If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave + CMMSockSubSession::ReceivedL(ECNAttach, TCFInternalEsock::TSubSess(ECNAttach,Message()).CRef()); + break; + + case ECNStop: + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNStop aMessage %08x"), this, &Message()) ); + + //Legacy support - if there is nothing to stop, return KErrNotReady + if (ServiceProvider() == NULL && CountActivities(ECFActivityStart) == 0) + { + User::Leave(KErrNotReady); + } + + //If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave + CMMSockSubSession::ReceivedL(ECNStop, TCFInternalEsock::TSubSess(ECNStop,Message()).CRef()); + break; + + case ECNWaitForIncoming: + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNWaitForIncoming aMessage %08x"), this, &Message()) ); + //If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave + CMMSockSubSession::ReceivedL(ECNWaitForIncoming, TCFInternalEsock::TSubSess(ECNWaitForIncoming,Message()).CRef()); + break; + + case ECNCancelWaitForIncoming: + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNCancelWaitForIncoming aMessage %08x"), this, &Message()) ); + CMMSockSubSession::ReceivedL(ECNWaitForIncoming, TEBase::TCancel().CRef()); + //CANCELATION - Do not call DontCompleteCurrentRequest() for the ECNCancelWaitForIncoming to be completed! + break; + + case ECNProgressNotification: + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNProgressNotification aMessage %08x"), this, &Message()) ); + CMMSockSubSession::ReceivedL(ECNProgressNotification, TCFInternalEsock::TSubSess(ECNProgressNotification,Message()).CRef()); //the ownership of the RMessage2 is taken by the activity + break; + + case ECNCancelProgressNotification: + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNCancelProgressNotification aMessage %08x"), this, &Message()) ); + CMMSockSubSession::ReceivedL(ECNProgressNotification, TEBase::TCancel().CRef()); + //CANCELATION - Do not call DontCompleteCurrentRequest() for the ECNCancelProgressNotification to be completed! + break; + + case ECNIoctl: + { + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNIoctl aMessage %08x"), this, &Message()) ); + RNodeInterface* sp = ServiceProvider(); + User::LeaveIfError(sp? KErrNone : KErrNotReady); + + CMMSockSubSession::ReceivedL(SafeMessage().Function(), TCprSendIoctl(SafeMessage()).CRef()); + DontCompleteCurrentRequest(); //TLegacyControlMessage will complete the message + } + break; + + case ECNCancelIoctl: + { + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNCancelIoctl aMessage %08x"), this, &Message()) ); + RNodeInterface* sp = ServiceProvider(); + User::LeaveIfError(sp? KErrNone : KErrNotReady); + + CancelIoctl(); + } + break; + +#ifdef AVAILABILITY_READY + case ECNEnumerateConnections: + LOG(ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNEnumerateConnections aMessage %08x"), this, &Message())); + CMMSockSubSession::ReceivedL(ECFActivityConnectionEnumerateConnections, TCFInternalEsock::TSubSess(ECNEnumerateConnections, Message()).CRef()); + break; +#endif + + case ECNControl: + ControlL(); //Decides how message gets completed + break; + + case ECNProgress: + ProgressL(); + break; + + case ECNLastProgressError: + LastProgressErrorL(); + break; + + case ECNGetOrSetParameters: + GetOrSetParametersL(); + break; + + case ECNGetParametersResponseLength: + GetParametersResponseL(ETrue); + break; + + case ECNGetParametersResponse: + GetParametersResponseL(EFalse); + break; + + + case ECNClose: + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tECNClose aMessage %08x"), this, &Message()) ); + SetClosing(); + //If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed on leave + CMMSockSubSession::ReceivedL(ECNClose, TCFInternalEsock::TSubSess(ECNClose,Message()).CRef()); + break; + + case ESCPSStop: + { + LOG( ESockLog::Printf(KESockConnectionTag, _L8("CConnection %08x\tESCPSStop aMessage %08x"), this, &Message()) ); + + // The filters match the legacy behaviour - subconnection has + // to exist (implies Connection started). + // Note: CNifAgentRef used to throw away the error returned + // by the EMI compatibility layer hence we return KErrNone here. + TSubConnectionUniqueId subConnectionUniqueId = static_cast(Message().Int0()); + if (ServiceProvider() && + (ServiceProvider()->Type() & TCFClientType::EServProvider) && + subConnectionUniqueId <= KNifEntireConnectionSubConnectionId+1) + { + RNodeInterface* scpr = DefaultSubConnectionServiceProvider(); + + if(scpr) + { // We can only start the 'stop' activity if we've got a service provider. + RConnection::TConnStopType stopType = static_cast(Message().Int1()); + + // Validate the stop code. + switch (stopType) + { + case RConnection::EStopNormal: + case RConnection::EStopAuthoritative: + break; + + default: + User::Leave(KErrArgument); + } + + // We start an activity to stop the subconnection and wait for it to send the TStopped response + // message. We cannot simply post the subconnection a message to stop because it causes the + // response message to go stray as we would be performing an operation outside of an activity. + // If successful, the ownership of the RMessage2 is taken by the activity, otherwise completed + // on leave. + CMMSockSubSession::ReceivedL( + ESCPSStop, + TCFInternalEsock::TSubSess( + ESCPSStop, + Message() + ).CRef() + ); + } + else + { // Nothing to do + SetReturn(KErrNone); + } + } + else + { + User::Leave(KErrNotReady); + } + } + break; + + default: + //iLegacyConnection must handle lifetimes of its own RMessage2s. + iLegacyConnection.ProcessMessageL(Message()); + break; + } + } + +void CConnection::GetReferenceL() + { + TName name; + ComposeSubSessionName(this, name); + Message().WriteL(0, name); + } + +_LIT_SECURITY_POLICY_C1(NifmanPolicyNetworkControl, ECapabilityNetworkControl); + +/** + Control method to send a general command towards the interface. +*/ +void CConnection::ControlL() + { + TUint optionLevel = static_cast(Message().Int0()); + TUint optionName = static_cast(Message().Int1()); + + // Check that clients are not trying to use internal connection options + // make sure this doesn't colide with new control levels + User::LeaveIfError((optionName & KConnInternalOptionBit)? KErrAccessDenied : KErrNone); + + switch(optionLevel) + { + case KCOLInterface: + // This PlatSec check replaces that from Nifman's CNifSecureSession. + if(!NifmanPolicyNetworkControl.CheckPolicy(Message())) + { + User::Leave(KErrPermissionDenied); + } + break; + + case KCOLConnection: + switch(optionName) + { + case KCoEnableCloneOpen: + case KCoDisableCloneOpen: + SetCloneOpenPolicyL(optionName); + break; + + default: + iLegacyConnection.ControlL(optionName, optionLevel); //AConnectionLegacy decides when to complete message + DontCompleteCurrentRequest(); //TLegacyControlMessage will complete the message + } + // KCOLConnection is all legacy stuff; no providers can/should help with it + return; + } + + TInt optionLength = SafeMessage().GetDesLengthL(2); + if (optionName & (KConnReadUserDataBit | KConnWriteUserDataBit) && optionLength == 0) + { + User::Leave(KErrArgument); //No buffer for data + } + + RNodeInterface* sp = ServiceProvider(); + User::LeaveIfError(sp? KErrNone : KErrNotReady); + + TLegacyControlMessage msg(SafeMessage()); + CMMSockSubSession::ReceivedL(SafeMessage().Function(), msg); + DontCompleteCurrentRequest(); //TLegacyControlMessage will complete the message + } + + +void CConnection::ProgressL() + { + if (iLastProgress.iStage != KConnectionUp && iLastProgress.iStage != KConnectionDown) + { + RNodeInterface* sp = ServiceProvider(); + User::LeaveIfError(sp? KErrNone : KErrNotReady); + + TCprRetrieveProgress msg(SafeMessage(), iLastProgress); + CMMSockSubSession::ReceivedL(SafeMessage().Function(), msg); + DontCompleteCurrentRequest(); //TCprRetrieveProgress will complete the message + return; + } + + TPckgBuf progressBuf; + progressBuf().iStage = iLastProgress.iStage; + progressBuf().iError = iLastProgress.iError; + + Message().WriteL(0, progressBuf); + SetReturn(KErrNone); + } + +void CConnection::LastProgressErrorL() + { + if (iLastProgress.iStage != KConnectionUp && iLastProgress.iStage != KConnectionDown) + { + RNodeInterface* sp = ServiceProvider(); + User::LeaveIfError(sp? KErrNone : KErrNotReady); + + TCprRetrieveLastProgressError msg(SafeMessage(), iLastProgressError); + CMMSockSubSession::ReceivedL(SafeMessage().Function(), msg); + DontCompleteCurrentRequest(); //TCprRetrieveLastProgressError will complete the message + return; + } + + TPckgBuf progressBuf; + progressBuf().iStage = iLastProgressError.iStage; + progressBuf().iError = iLastProgressError.iError; + ResetLastProgressError(); + + Message().WriteL(0, progressBuf); + SetReturn(KErrNone); + } + + +void CConnection::GetOrSetParametersL() + { + if (ServiceProvider() == NULL) + { + SetReturn(KErrNotReady); + return; + } + + if (iCommsDataObject) + { + SetReturn(KErrInUse); + return; + } + + TInt cdoLength = Message().GetDesLengthL(0); + RBuf8 cdoBuffer; + cdoBuffer.CreateL(cdoLength); + CleanupClosePushL(cdoBuffer); + SafeMessage().ReadL(0, cdoBuffer); + + TPtrC8 des(cdoBuffer); + iCommsDataObject = static_cast(SMetaDataECom::LoadL(des)); + + // Last minute sanity check + if ((iCommsDataObject->OperationMode() == XCommsDataObject::EOperationGet + && !iCommsDataObject->IsGetSupported()) + || (iCommsDataObject->OperationMode() == XCommsDataObject::EOperationSet + && !iCommsDataObject->IsSetSupported())) + { + CleanupStack::PopAndDestroy(); // cdoBuffer + delete iCommsDataObject; + iCommsDataObject = NULL; + SetReturn(KErrCorrupt); + return; + } + + // iCommsDataObject passed as *& and will be updated by the TGetOrSetParameters message + // upon error + RNodeInterface* sp = ServiceProvider(); + if (sp == NULL) + { + delete iCommsDataObject; + iCommsDataObject = NULL; + SetReturn(KErrNotReady); + return; + } + + TGetOrSetParameters msg(SafeMessage(), iCommsDataObject); + CMMSockSubSession::ReceivedL(SafeMessage().Function(), msg); + DontCompleteCurrentRequest(); //TLegacyControlMessage will complete the message + CleanupStack::PopAndDestroy(); // cdoBuffer + } + + +void CConnection::GetParametersResponseL(TBool aReturnLength) + { + if (ServiceProvider() == NULL || !iCommsDataObject) + { + SetReturn(KErrNotReady); + return; + } + + if (aReturnLength) + { + // Client requesting required buffer length for the serialised object + iCommsDataObjectLength = iCommsDataObject->Length(); + SetReturn(iCommsDataObjectLength); + } + else + { + RBuf8 cdoBuffer; + cdoBuffer.CreateL(iCommsDataObjectLength); + CleanupClosePushL(cdoBuffer); + User::LeaveIfError(iCommsDataObject->Store(cdoBuffer)); + Message().WriteL(0, cdoBuffer); + CleanupStack::PopAndDestroy(); // queryBundleBuffer + + delete iCommsDataObject; + iCommsDataObject = NULL; + iCommsDataObjectLength = 0; + + SetReturn(KErrNone); + } + } + +void CConnection::CancelIoctl() + { + const RPointerArray& activities = Activities(); + for (TInt i = 0; i < activities.Count(); i++) + { + if (activities[i]->ActivitySigId() == ESock::ECFActivityConnectionLegacyRMessage2Handler) + { + ConnActivities::CConnLegacyRMessage2Activity* act = static_cast(activities[i]); + if (act->iSafeMessage.Function() == ECNIoctl) + { + act->SetCancelRequest(SafeMessage()); + CMMSockSubSession::ReceivedL(act->iSafeMessage.Function(), TEBase::TCancel().CRef()); + DontCompleteCurrentRequest(); + } + } + } + } + +void CConnection::SetCloneOpenPolicyL(TUint aOptionName) + { + const TInt policyParamIndex = 2; + + switch (aOptionName) + { + case KCoEnableCloneOpen: + { + // Enable the ability to perform a clone open towards this instance. Read the + // security policy passed in the option and store it in this instance. + TSecurityPolicyBuf cloneOpenPolicy; + SafeMessage().ReadL(policyParamIndex, cloneOpenPolicy); + User::LeaveIfError(iCloneOpenPolicy.Set(cloneOpenPolicy)); + iCloneOpenEnabled = ETrue; + break; + } + case KCoDisableCloneOpen: + { + // Disable the ability to perform a clone open towards this instance. + iCloneOpenEnabled = EFalse; + break; + } + } + } + +TInt CConnection::CheckCloneOpenPolicy(const RMessagePtr2& aMessage) const + { + if (iCloneOpenEnabled && iCloneOpenPolicy.CheckPolicy(aMessage)) + return KErrNone; + else + return KErrPermissionDenied; + } + + +/** +@internalTechnology +*/ +void CConnection::ReturnInterfacePtrL(MPlatsecApiExt*& aInterface) + { + aInterface = this; + } + +// AllInterfaceNotification + +/** + Legacy RConnection::AllInterfaceNotification implementation +*/ +namespace AllInterfaceNotificationActivity +{ +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityConnectionAllInterfaceNotification, AllInterfaceNotification, TCFServiceProvider::TStart, CAllInterfaceNotificationActivity::NewL) + NODEACTIVITY_ENTRY(KNoTag, TAddClient, TAwaitingStart, MeshMachine::TNoTag) + // Find the tier manager and request notification from it. + NODEACTIVITY_ENTRY(KNoTag, TFindTierManager, TAwaitingTierManager, MeshMachine::TNoTag) + NODEACTIVITY_ENTRY(KNoTag, TJoinTierManager, TAwaitingJoinComplete, MeshMachine::TNoTag) + + // Start the notification activity and wait for notification + NODEACTIVITY_ENTRY(KNoTag, TStartLinkNotification, TAwaitingLinkNotification, CoreStates::TCancelOrErrorOrTag) + + // Enqueue the notification and wait for the next one - we loop here forever + NODEACTIVITY_ENTRY(KNoTag, TEnqueueNotification, TAwaitingLinkNotification, CoreStates::TCancelOrErrorOrTag) + + THROUGH_TRIPLE_ENTRY(KErrorTag, MeshMachine::TStoreError, MeshMachine::TTag) + // If we received a TCancel from CConnection, reply with TError to complete shutdown handshake. + THROUGH_NODEACTIVITY_ENTRY(KCancelTag, TSendErrorToConnection, MeshMachine::TTag) + NODEACTIVITY_ENTRY(KCancelTag, TCancelLinkNotification, TAwaitingLinkNotificationError, MeshMachine::TNoTag) + LAST_NODEACTIVITY_ENTRY(KNoTag, TLeaveTierManager) // no other sessions with tier so can safely fire & forget this +NODEACTIVITY_END() +} + +namespace AllInterfaceNotificationActivities +{ +DECLARE_DEFINE_ACTIVITY_MAP(allInterfaceNotificationActivities) + ACTIVITY_MAP_ENTRY(AllInterfaceNotificationActivity, AllInterfaceNotification) +ACTIVITY_MAP_END() +} + +CAllInterfaceNotificationWorker::CAllInterfaceNotificationWorker(ESock::CConnection& aConnection) : + ACFMMNodeIdBase(AllInterfaceNotificationActivities::allInterfaceNotificationActivities::Self()), + iConnection(aConnection) + { + LOG_NODE_CREATE(KESockConnectionTag, CAllInterfaceNotificationWorker); + } + +CAllInterfaceNotificationWorker::~CAllInterfaceNotificationWorker() + { + LOG_NODE_DESTROY(KESockConnectionTag, CAllInterfaceNotificationWorker); + } + +void CAllInterfaceNotificationWorker::Received(TNodeContextBase& aContext) + { + TNodeSignal::TMessageId noPeerIds[] = { + TCFServiceProvider::TStart::Id(), + TNodeSignal::TMessageId() // list terminator + }; + MeshMachine::AMMNodeBase::Received(noPeerIds, aContext); + MeshMachine::AMMNodeBase::PostReceived(aContext); + } + +void CAllInterfaceNotificationWorker::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage) + { + TNodeContext ctx(*this, aMessage, aSender, aRecipient); + CAllInterfaceNotificationWorker::Received(ctx); + User::LeaveIfError(ctx.iReturn); + } + +