diff -r 000000000000 -r dfb7c4ff071f datacommsserver/esockserver/ssock/ss_connstates.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/datacommsserver/esockserver/ssock/ss_connstates.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,1720 @@ +// 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: +// + +#include "SS_conn.H" +#include "ss_connstates.h" +#include +#include +#include +#include "ss_subconn.h" +#include +#include +#include //TCommDbConnPref +#include //TCommDbConnPref +#include //TConnPrefList +#include +#include +#include //TConnAPPref +#include //TConnCSRPref + +#include // CConnectionServParameterBundle +#include // TAccessPointStatusFilter +#include // XAccessPointGenericParameterSet +#include + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SYMBIAN_NETWORKING_UPS + +#ifdef SYMBIAN_NETWORKING_UPS +#include +#include +#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) +_LIT(KSpecAssert_ESockSSockscnsts, "ESockSSockscnsts"); +#endif + +using namespace ESock; +using namespace SubSessActivities; +using namespace NetStateMachine; +using namespace ConnStates; +using namespace ConnActivities; +using namespace ConnectionServ; +using namespace Elements; +using namespace Messages; +using namespace MeshMachine; + +//#ifdef LOG +// #define KESockActivityTag KESockCoreProviderTag +// _LIT8(KESockActivitySubTag, "esockactivity"); +//#endif + +_LIT (KCConnectionPanic,"CConnectionPanic"); + +void ConnPanic(TInt aCode) + { + User::Panic(KCConnectionPanic, aCode); + } + +// +//Start + +DEFINE_SMELEMENT(ConnStates::TErrorIfAlreadyStartedAttached, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TErrorIfAlreadyStartedAttached::DoL() + { + __ASSERT_DEBUG((subsessmessage_cast(&iContext.iMessage)) + || (subsessmessage_cast(&iContext.iMessage)), + ConnPanic(KPanicIncorrectMessage)); + RNodeInterface* sp = iContext.Node().ServiceProvider(); + User::LeaveIfError(sp? KErrAlreadyExists : KErrNone); + } + +DEFINE_SMELEMENT(ConnStates::TParseECNStart, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TParseECNStart::DoL() + { + __ASSERT_DEBUG((subsessmessage_cast(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage)); + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + ConnActivities::CStartAttachActivity& ac = static_cast(*iContext.iNodeActivity); + + if (ac.Function() == ECNSetStartPrefs) + { + //Extract preferences if ECNSetStartPrefs + TConnPref prefs; + ac.ReadL(0, prefs); + + if(prefs.ExtensionId() != TConnPref::EConnPrefEComList) + { + ac.SelectionPrefs().SetPrefs(prefs); + } + else + { + RBuf8 buffer; + TInt length = ac.GetDesLengthL(0); + buffer.CreateL(length); + CleanupClosePushL(buffer); + ac.ReadL(0, buffer); + + TConnPrefList* prefsList = TConnPrefList::NewL(); + CleanupStack::PushL(prefsList); + TPtrC8 ptr(buffer); + TInt ret = prefsList->Load(ptr); + User::LeaveIfError(ret); + + //This loop is used to check that there is no more than 1 instance + //of TConnAPPref in the list passed to the CSR. This is not allowed + //(as it may have adverse effects in the construction of the stack) + //KErrArugment is returned if there is more than 1 instance present + TInt instances = 0; + for(TInt i=0; iCount(); i++) + { + TConnAPPref* pref = smetadata_cast((*prefsList)[i]); + if(pref) + { + instances++; + } + } + if(instances > 1) + { + User::Leave(KErrArgument); + } + + TConnCSRPref* csr = TConnCSRPref::NewL(); + CleanupStack::PushL(csr); + ac.SetCSRPreferences(csr); + csr->SetScope(TSelectionPrefs::EExplicitConnection); + prefsList->AppendL(csr); + + ac.SelectionPrefs().SetPrefs(*prefsList); + ac.SetConnPrefList(prefsList); + + CleanupStack::Pop(csr); + CleanupStack::Pop(prefsList); + CleanupStack::PopAndDestroy(&buffer); + } + + // Complete the ECNSetStartPrefs, activity will be held until the 2nd IPC of the Start with Prefs + // call is received. Null iSubSession so that the 2nd IPC can be aquired by the activity. + ac.iMessage.Complete(KErrNone); + ac.iSubSession = NULL; + } + else + { + ac.SetSelectionScope(TSelectionPrefs::EExplicitConnection); + } + } + +DEFINE_SMELEMENT(ConnStates::TSendStartingSelectionStateChange, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TSendStartingSelectionStateChange::DoL() + { + //Send the relevant progress (don't use ReceivedL or you will warp), also use Null Activity id. + RNodeInterface::OpenPostMessageClose(iContext.NodeId(), iContext.NodeId(), TCFMessage::TStateChange(TStateChange(KStartingSelection,KErrNone)).CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TClearProgressQueue, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TClearProgressQueue::DoL() + { + iContext.Node().iProgressQueue.Reset(); // clear progress notification cache + iContext.Node().ResetLastProgressError(); // clear last progress in error + // Initialise iLastProgress with an invalid progress rather than 0 (which is actually KConnectionUninitialised) + // otherwise we can end up unintentionally filtering out a KConnectionUninitialised progress. + const TInt KInvalidProgress = -1; + iContext.Node().iLastProgress = TStateChange(KInvalidProgress, 0); + iContext.Node().iLastProgressError = TStateChange(); + } + +DEFINE_SMELEMENT(ConnStates::TRequestCSRCreation, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TRequestCSRCreation::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + __ASSERT_DEBUG(static_cast(*iContext.iNodeActivity).CSR().IsNull(), ConnPanic(KPanicExpectedNoCSR)); + iContext.iNodeActivity->PostRequestTo(SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::ETierMgrPlane)), TCFInternalEsock::TCreateCSR(iContext.Node().iTierId).CRef(), EFalse); + } + +DEFINE_SMELEMENT(ConnStates::TProcessCSRCreation, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TProcessCSRCreation::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + ConnActivities::CStartAttachActivity& ac = static_cast(*iContext.iNodeActivity); + __ASSERT_DEBUG(ac.CSR().IsNull(), User::Panic(KSpecAssert_ESockSSockscnsts, 1)); + ac.SetCSR(message_cast(iContext.iMessage).iNodeId); + + + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), ac.CSR(), + TCFMessage::TProvisionConnectionInfo(iContext.Node().ConnectionInfo()).CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TSelectMetaPlane, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TSelectMetaPlane::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + ConnActivities::CStartAttachActivity& ac = static_cast(*iContext.iNodeActivity); + + //Diagnostic only. If attach then it must be ESelectFromExisting + __ASSERT_DEBUG(!iContext.Node().IsMonitor() + || ac.SelectionPrefs().Scope() & TSelectionPrefs::ESelectFromExisting, User::Panic(KSpecAssert_ESockSSockscnsts, 2)); + + if(ac.SelectionPrefs().Prefs().ExtensionId() != TConnPref::EConnPrefEComList) + { + ac.SelectionPrefs().SetSubSessionUniqueId(iContext.Node().UniqueId()); + iContext.iNodeActivity->PostRequestTo( + ac.CSR(), + TCFSelector::TSimpleSelect(ac.SelectionPrefs()).CRef() + ); + } + else + { + ac.CSRPreferences()->SetSubSessionUniqueId(iContext.Node().UniqueId()); + RConnPrefList handle; + handle.Open(ac.ConnPrefList()); + + iContext.iNodeActivity->PostRequestTo( + ac.CSR(), + TCFSelector::TSelect(handle).CRef() + ); + } + } + +DEFINE_SMELEMENT(ConnStates::TSendFinishedSelectionStateChange, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TSendFinishedSelectionStateChange::DoL() + { + //Send the relevant progress (don't use ReceivedL or you will warp), also use Null Activity id. + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.NodeId(), + TCFMessage::TStateChange(TStateChange(KFinishedSelection,KErrNone)).CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TJoinReceivedCpr, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TJoinReceivedCpr::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + __ASSERT_DEBUG(iContext.Node().ServiceProvider()==NULL, ConnPanic(KPanicExpectedNoServiceProvider)); + + TCFDataClient::TBindTo& bt = message_cast(iContext.iMessage); + iContext.Node().AddClientL(bt.iNodeId, TClientType(TCFClientType::EServProvider, TCFClientType::EActive)); + + //If this is attach, we need to see if we are a monitor or not + TClientType clientType(TCFClientType::ECtrl); + + TUint selPrefs = static_cast(*iContext.iNodeActivity).SelectionPrefs().Flags(); + if (selPrefs & TSelectionPrefs::EMonitor) + { + clientType.SetFlags(TCFClientType::EMonitor); + iContext.Node().iIsMonitor = ETrue; + } + + // If it is an attach set the flag cause it is used by NetUPS to check if a JoinRequest comes from an RConnection::Attach + if (selPrefs & TSelectionPrefs::EAttach) + { + clientType.SetFlags(TCFClientType::EAttach); + } + iContext.iNodeActivity->PostRequestTo(bt.iNodeId, + TCFServiceProvider::TJoinRequest(iContext.NodeId(), clientType).CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TJoinReceivedSCpr, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TJoinReceivedSCpr::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + __ASSERT_DEBUG(iContext.iPeer == iContext.Node().ServiceProvider(), ConnPanic(KPanicExpectedNoServiceProvider)); + + TCFServiceProvider::TCommsBinderResponse& br = message_cast(iContext.iMessage); + iContext.Node().AddClientL(br.iNodeId, TClientType(TCFClientType::EServProvider, TCFClientType::EDefault)); + + //If this is attach, we need to see if we are a monitor or not + TCFClientType clientType(TCFClientType::ECtrl); + + TUint selPrefs = static_cast(*iContext.iNodeActivity).SelectionPrefs().Flags(); + if (selPrefs & TSelectionPrefs::EMonitor) + { + clientType.SetFlags(TCFClientType::EMonitor); + } + + // If it is an attach set the flag cause it is used by NetUPS to check if a JoinRequest comes from an RConnection::Attach + if (selPrefs & TSelectionPrefs::EAttach) + { + clientType.SetFlags(TCFClientType::EAttach); + } + + iContext.iNodeActivity->PostRequestTo(br.iNodeId, + TCFServiceProvider::TJoinRequest(iContext.NodeId(), clientType).CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TJoinReceivedMcpr, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TJoinReceivedMcpr::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + __ASSERT_DEBUG(iContext.Node().ServiceProvider()==NULL, ConnPanic(KPanicExpectedNoServiceProvider)); + + TCFSelector::TSelectComplete& sc = message_cast(iContext.iMessage); + iContext.Node().AddClientL(sc.iNodeId,TClientType(TCFClientType::EServProvider, TCFClientType::EAvailabilityProvider)); + + + iContext.iNodeActivity->PostRequestTo(sc.iNodeId, + TCFServiceProvider::TJoinRequest(iContext.NodeId(), TCFClientType(TCFClientType::ECtrl)).CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TRequestCommsBinder, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TRequestCommsBinder::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + RNodeInterface* sp = iContext.Node().ServiceProvider(); + __ASSERT_DEBUG(sp, ConnPanic(KPanicNoServiceProvider)); + iContext.iNodeActivity->PostRequestTo(*sp, + TCFServiceProvider::TCommsBinderRequest(TSubConnOpen::EAttachToDefault).CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TRequestCommsBinderFromMcpr, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TRequestCommsBinderFromMcpr::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EServProvider, TCFClientType::EAvailabilityProvider)); + RNodeInterface* mcpr = iter[0]; + __ASSERT_DEBUG(mcpr, ConnPanic(KPanicNoAvailabilityProvider)); + iContext.iNodeActivity->PostRequestTo(*mcpr, + TCFServiceProvider::TCommsBinderRequest().CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TProcessBinderResponseForCpr, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TProcessBinderResponseForCpr::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + __ASSERT_DEBUG(iContext.Node().ServiceProvider()==NULL, ConnPanic(KPanicExpectedNoServiceProvider)); + + TCFServiceProvider::TCommsBinderResponse& br = message_cast(iContext.iMessage); + + iContext.Node().AddClientL(br.iNodeId, TClientType(TCFClientType::EServProvider, TCFClientType::EActive)); + + //If this is attach, we need to see if we are a monitor or not + TCFClientType clientType; + + TUint selPrefs = static_cast(*iContext.iNodeActivity).SelectionPrefs().Flags(); + if (selPrefs & TSelectionPrefs::EMonitor) + { + clientType.SetFlags(TCFClientType::EMonitor); + iContext.Node().iIsMonitor = ETrue; + } + + if (selPrefs & TSelectionPrefs::EAttach) + { + clientType.SetFlags(TCFClientType::EAttach); + } + + iContext.iNodeActivity->PostRequestTo(br.iNodeId, + TCFServiceProvider::TJoinRequest(iContext.NodeId(), clientType).CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TStartConnection, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TStartConnection::DoL() + { + RNodeInterface* cpr = iContext.Node().ServiceProvider(); + __ASSERT_DEBUG(cpr, ConnPanic(KPanicNoServiceProvider)); + + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + iContext.iNodeActivity->PostRequestTo(*cpr, TCFServiceProvider::TStart().CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TErrorOrCancel, NetStateMachine::MStateFork, ConnStates::TContext) +/** +If the activity has been cancelled, return KCancelTag else return KErrorTag + */ +TInt ConnStates::TErrorOrCancel::TransitionTag() + { + if (iContext.Activity()->Error() == KErrCancel) + { + return ConnActivities::CStartAttachActivity::KCancelTag; + } + else + { + __ASSERT_DEBUG(iContext.Activity()->Error() != KErrNone, User::Panic(KSpecAssert_ESockSSockscnsts, 3)); // meant to be called in error conditions only + return KErrorTag; + } + } + +// +//Attach +DEFINE_SMELEMENT(ConnStates::TParseECNAttach, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TParseECNAttach::DoL() + { + __ASSERT_DEBUG((subsessmessage_cast(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage)); + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + ConnActivities::CStartAttachActivity& ac = static_cast(*iContext.iNodeActivity); + + //Read preferences + const TUint KMaxConnectionInfoLength = 32; + TBuf8 info; + ac.ReadL(1,info); + if (info.Length() < KConnInfoPart) + { + User::Leave(KErrArgument); + } + + TUint monitorMode = (RConnection::TConnAttachType)ac.Int0() == RConnection::EAttachTypeMonitor? + TSelectionPrefs::EMonitor : 0; + // The attach flag should always be set since it is used by NetUPS to check if a JoinRequest comes from an RConnection::Attach + ac.SetSelectionFlags(monitorMode | TSelectionPrefs::EAttach); + + TConnArgBase& connInfo = *((TConnArgBase*)&info[0]); + if (connInfo.Version() < KConnArgVersion3) + { + TConnectionInfo& connI = static_cast(connInfo); + TCommDbConnPref pref; + pref.SetIapId(connI.iIapId); + ac.SelectionPrefs().SetPrefs(pref); + ac.SetSelectionScope(TSelectionPrefs::ESelectFromExisting | TSelectionPrefs::EExplicitConnection); + } + else + { + __ASSERT_DEBUG(connInfo.Version() == KConnArgVersion3, User::Panic(KSpecAssert_ESockSSockscnsts, 4)); //Currently no support for > KConnArgVersion3; + TConnProviderInfo& provinfo = static_cast(connInfo); + __ASSERT_DEBUG(iContext.Node().iTierId.iUid == provinfo.iInfo[0], User::Panic(KSpecAssert_ESockSSockscnsts, 5)); + ac.SelectionPrefs().SetPrefs(TConnProviderInfoPref(provinfo)); + ac.SetSelectionScope(TSelectionPrefs::ESelectFromExisting); + } + } + +DEFINE_SMELEMENT(ConnStates::TCompleteLegacyAttach, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TCompleteLegacyAttach::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + iContext.Node().iLegacyConnection.CompleteAttachL(static_cast(*iContext.iNodeActivity).SelectionPrefs()); + } + + +// +//WaitForIncoming +DEFINE_SMELEMENT(ConnStates::TRequestIncomingConnection, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TRequestIncomingConnection::DoL() + { + __ASSERT_DEBUG((subsessmessage_cast(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage)); + RNodeInterface* sp = iContext.Node().ServiceProvider(); + User::LeaveIfError(sp ? KErrNone : KErrNotReady); + + iContext.iNodeActivity->PostRequestTo(*sp, + TCFServiceProvider::TCommsBinderRequest(TSubConnOpen::EWaitForIncoming).CRef()); + } + +DEFINE_SMELEMENT(ConnStates::TProcessIncomingConnection, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TProcessIncomingConnection::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + CSubConnection* waitingSubConn = iContext.Node().Session()->CSubConnectionFromHandle(static_cast(*iContext.iNodeActivity).Int0()); + User::LeaveIfError(waitingSubConn != NULL ? KErrNone : KErrCancel); + + TCFServiceProvider::TCommsBinderResponse& binderResp = message_cast(iContext.iMessage); + iContext.iNodeActivity->PostRequestTo(waitingSubConn->Id(), + TCFDataClient::TBindTo(binderResp.iNodeId).CRef()); + } + + +// +//Stop +DEFINE_SMELEMENT(ConnStates::TSendStopConnection, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TSendStopConnection::DoL() + { + __ASSERT_DEBUG((subsessmessage_cast(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage)); + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + CESockClientActivityBase& ac = static_cast(*iContext.iNodeActivity); + + //Convert the received enum (the stop type) into an error code that will be passed to the interface clients + TInt stopCode = KErrCancel; + switch (ac.Int0()) + { + case RConnection::EStopNormal: + stopCode = KErrCancel; + break; + case RConnection::EStopAuthoritative: + stopCode = KErrConnectionTerminated; + break; + default: + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSockscnsts, 6)); + } + + RNodeInterface* sp = iContext.Node().ServiceProvider(); + if(sp) + { // We can only post the 'stop' if we've got a service provider and its not already leaving (e.g., gone down). + if (!(sp->Flags() & TClientType::ELeaving)) + { + sp->PostMessage(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), TCFServiceProvider::TStop(stopCode).CRef()); + } + else + { + MESH_LOG((KESockConnectionTag, _L8("ConnStates::TSendStopConnection:\tDoL - IGNORING POST!"))); + } + } + else + { // Otherwise just set the activity idle and bail out. + iContext.Activity()->SetIdle(); + } + } + +DEFINE_SMELEMENT(ConnStates::TConnectionSendStopSCPR, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TConnectionSendStopSCPR::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + + TInt stopCode = 0; + + switch (static_cast(iContext.iNodeActivity)->Int1()) + { + case RConnection::EStopNormal: + stopCode = KErrCancel; + break; + + case RConnection::EStopAuthoritative: + stopCode = KErrConnectionTerminated; + break; + + default: + __ASSERT_DEBUG( false , User::Panic(KSpecAssert_ESockSSockscnsts, 7)); // CConnection should have verified the parameters before stopping the subconnection + } + + // Send the stop message to the subconnection. + RNodeInterface* scpr = static_cast(iContext.Node()).DefaultSubConnectionServiceProvider(); + __ASSERT_DEBUG( scpr , User::Panic(KSpecAssert_ESockSSockscnsts, 8)); // subconnection must exist or the stop operation should not have been initiated + scpr->PostMessage( + TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), + TCFServiceProvider::TStop(stopCode).CRef() + ); + } + +DEFINE_SMELEMENT(ConnStates::TCancelStartOrAttachConnection, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TCancelStartOrAttachConnection::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + + if (iContext.Node().FindActivityById(ECFActivityStart)) + { + RClientInterface::OpenPostMessageClose( + TNodeCtxId(ECNStart, iContext.NodeId()), + TNodeCtxId(ECNStart, iContext.NodeId()), + TEBase::TCancel().CRef()); + } + else if (iContext.Node().FindActivityById(ECFActivityConnectionAttach)) + { + RClientInterface::OpenPostMessageClose( + TNodeCtxId(ECNAttach, iContext.NodeId()), + TNodeCtxId(ECNAttach, iContext.NodeId()), + TEBase::TCancel().CRef()); + } + } + +// +//Close +DEFINE_SMELEMENT(ConnStates::TDetachDataClients, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TDetachDataClients::DoL() + { + while (ETrue) + { + TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EData)); + RNodeInterface* client = iter[0]; + if (client) + { +#if defined(__GCCXML__) + CSubConnection& subconn = *reinterpret_cast(&client->RecipientId().Node()); +#else + CSubConnection& subconn = *mcfnode_cast(&client->RecipientId().Node()); +#endif + iContext.Node().RemoveClient(subconn.Id()); + subconn.RemoveClient(iContext.NodeId()); + } + else + { + break; + } + } + } + +DEFINE_SMELEMENT(ConnStates::TStartOrAttachActive, NetStateMachine::MStateFork, ConnStates::TContext) +TInt ConnStates::TStartOrAttachActive::TransitionTag() + { + if (iContext.Node().FindActivityById(ECFActivityStart) || iContext.Node().FindActivityById(ECFActivityConnectionAttach)) + { + return MeshMachine::KActiveTag; + } + return KNoTag; + } + +DEFINE_SMELEMENT(ConnStates::TAwaitingGoneDown, NetStateMachine::MState, ConnStates::TContext) +TBool ConnStates::TAwaitingGoneDown::Accept() + { + if (!iContext.iMessage.IsMessage()) + { + return EFalse; + } + + //TODO - fix this defect: + //1) TGoneDown should not be sent when stopping or closing + //2) FindActivityById(ECFActivityStop) is not safe + //3) why the condition iContext.Node().ServiceProvider()? Who can be sending TGoneDown if not the service provider? + bool stoppingOrClosing = iContext.Node().FindActivityById(ECFActivityStop) || iContext.Node().FindActivityById(ECFActivityDestroy); + if (!stoppingOrClosing && iContext.Node().ServiceProvider() && + *iContext.Node().ServiceProvider() == iContext.iSender) + { + return ETrue; + } + iContext.iMessage.ClearMessageId(); + return EFalse; + } + +DEFINE_SMELEMENT(ConnStates::TGenerateConnectionUpProgress, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TGenerateConnectionUpProgress::DoL() + { + TCFMessage::TStateChange msg(TStateChange(KConnectionUp, KErrNone)); + RNodeInterface::OpenPostMessageClose(iContext.Node().Id(), iContext.Node().Id(), msg); + } + +DEFINE_SMELEMENT(ConnStates::TGenerateConnectionDownProgress, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TGenerateConnectionDownProgress::DoL() + { + // Do not self-post a message if there is a pending ConnectionClose activity. When the ConnectionGoingDown + // activity (calling this method) terminates, the ConnectionClose activity unparks (being synchronised + // against ConnectionGoingDown), the CConnection is destroyed, and the subsequent self-dispatch + // will panic. + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + TInt error = iContext.iNodeActivity->Error(); + + if (error == KErrNone && iContext.iMessage.IsMessage()) + { + error = message_cast(iContext.iMessage).iValue; + } + + __ASSERT_DEBUG(error != KErrNone, ConnPanic(KPanicIncorrectState)); + + if (iContext.Node().CountActivities(ECFActivityDestroy) == 0) + { + TCFMessage::TStateChange msg(TStateChange(KConnectionDown, error)); + CConnection& cc = iContext.Node(); + RNodeInterface::OpenPostMessageClose(cc.Id(), cc.Id(), msg); + } + } + +// +//Progress & Progress Request +DEFINE_SMELEMENT(ConnStates::TProcessStateChange, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TProcessStateChange::DoL() + { + TStateChange& progress = message_cast(iContext.iMessage).iStateChange; + + //Check whether KDataTransferUnblocked is received and if yes, then traslate it to KConnectionUp (== KLinkLayerOpen) + // the log only sees the translated version, this goes into the queue, so it alright I suppose. + if (progress.iStage == KDataTransferUnblocked ) + { + progress.iStage = KConnectionUp; // KLinkLayerOpen + } + + LOG( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tProgressNotification(TInt aStage %d, TInt aError %d)"), + &(iContext.Node()), progress.iStage, progress.iError) ); + + //Diagnostic assertion. + //If ECFActivityConnectionStateChangeRequest is running, it has not been + //presented with the TStateChange message (channel activity id != 0?) which is a serious mistake. + __ASSERT_DEBUG(iContext.Node().CountActivities(ECFActivityConnectionStateChangeRequest)==0, User::Panic(KSpecAssert_ESockSSockscnsts, 9)); + + CConnection& cc = iContext.Node(); + if (cc.iLastProgress == progress) + { + return; //ignore this duplicate + } + cc.iLastProgress = progress; + + if (progress.iError != KErrNone) + { + cc.iLastProgressError = progress; //Save last progress in error for use by LastProgressErrorL() + } + + #ifdef ESOCK_LOGGING_ACTIVE + // Check to see if the progress queue is full causing older progress to be discarded. + // This has the potential to cause problems if a critical progress item is lost. + // Normally the queue is large enough such that this doesn't happen but this log entry + // serves as a warning if it ever does. + if( cc.iProgressQueue.IsFull() ) + { + LOG( ESockLog::Printf(KESockConnectionTag, _L("CConnection %08x:\tThe maximum progress queue size of %d has been exceeded - discarding old progress to make space for new item"), this, KMaxProgressQueueLength); ) + } + #endif + + //Add the progress to queue + cc.iProgressQueue.Enque(progress); + } + +DEFINE_SMELEMENT(ConnStates::TProcessProgressRequest, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TProcessProgressRequest::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + CESockClientActivityBase& ac = static_cast(*iContext.iNodeActivity); + TUint selectedProgressStage = ac.Int1(); + + TStateChange progress; + TBool found = EFalse; + + //Are we here as a result of receiving TStateChange (rather than ECNProgressNotification)? + TCFMessage::TStateChange* msg = message_cast(&iContext.iMessage); + if (msg) + { //Yes, we have been triggered by a TStateChange message + //Check if this is the progress we are waiting for, otherwise dump the progress + //Check whether KDataTransferUnblocked is received and if yes, then traslate it to KConnectionUp (== KLinkLayerOpen) + if (msg->iStateChange.iStage == KDataTransferUnblocked ) + { + msg->iStateChange.iStage = KConnectionUp; // KLinkLayerOpen + } + if (selectedProgressStage == KConnProgressDefault + || selectedProgressStage == msg->iStateChange.iStage + || KErrNone != msg->iStateChange.iError) + { + progress = msg->iStateChange; + found = ETrue; + } + } + else + { //No, we must have been triggered by a ECNProgressNotification message + __ASSERT_DEBUG((subsessmessage_cast(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage)); + + //Process the queue looking for the progress of interest + found = iContext.Node().iProgressQueue.Deque(progress); + if (found && selectedProgressStage != KConnProgressDefault) + { + // For a selected progress request, dequeue entries until we find one which + // matches the criteria. If we dequeue all entries, fall through without + // completing the message. It it not considered useful to retain un-matching + // entries on the queue if a selected progress request is pending. + while (found) + { + if (progress.iStage == selectedProgressStage || progress.iError != KErrNone) + { + break; + } + found = iContext.Node().iProgressQueue.Deque(progress); + } + } + } + + if (found) + { + //We have found a progress of interest, finish + TPckg progressPkg(progress); + ac.WriteL(0,progressPkg); + ac.SetIdle(); //We are done + } + } + + +// +//Legacy enumeration +DEFINE_SMELEMENT(ConnStates::TAwaitingEnumResponse, NetStateMachine::MState, ConnStates::TContext) +TBool ConnStates::TAwaitingEnumResponse::Accept() + { + return iContext.iMessage.IsMessage(); + } + +DEFINE_SMELEMENT(ConnStates::TProcessEnumResponse, NetStateMachine::MStateTransition, ConnStates::TContext) +void ConnStates::TProcessEnumResponse::DoL() + { + TCFInternalEsock::TLegacyConnectionEnumResponse& msg = message_cast(iContext.iMessage); + iContext.Node().iLegacyConnection.CompleteDataPlaneEnumeration(address_cast(iContext.iSender), msg.iValue1, reinterpret_cast(msg.iValue2), msg.iValue3); + } + + +// +//CStartAttachActivity +MeshMachine::CNodeActivityBase* ConnActivities::CStartAttachActivity::NewWaitForIncomingConnectionActivityL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + //Leave from here will complete the client message + User::LeaveIfError(aNode.CountActivities(ECFActivityStart)? KErrInUse : KErrNone); + User::LeaveIfError(aNode.CountActivities(ECFActivityConnectionAttach)? KErrInUse : KErrNone); + + // When waiting for an incoming connection we will additionally check that the connection is already started + User::LeaveIfError(aNode.CountClients(TClientType(TCFClientType::EServProvider)) > 0 ? KErrNone : KErrNotReady ); + + return new (ELeave) ConnActivities::CStartAttachActivity(aActivitySig,aNode); + } + +MeshMachine::CNodeActivityBase* ConnActivities::CStartAttachActivity::NewStartConnectionActivityL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + //Leave from here will complete the client message + User::LeaveIfError(aNode.CountActivities(ECFActivityStart)? KErrInUse : KErrNone); + User::LeaveIfError(aNode.CountActivities(ECFActivityConnectionAttach)? KErrInUse : KErrNone); + + // When starting a connection we will additionally check that the connection is not already started + User::LeaveIfError(aNode.CountClients(TClientType(TCFClientType::EServProvider)) > 0 ? KErrInUse : KErrNone); + + return new (ELeave) ConnActivities::CStartAttachActivity(aActivitySig,aNode); + } + +ConnActivities::CStartAttachActivity::~CStartAttachActivity() + { + // Call ABindingActivity base class to send TBindToComplete (before TDestroy) + FinalReplyToOriginator(KErrAbort); + + if (!iCSR.IsNull()) + { +#ifndef __GCCXML__ + RNodeInterface::OpenPostMessageClose(TNodeCtxId(ActivityId(), iNode.Id()), iCSR, TEChild::TDestroy().CRef()); +#endif + iCSR.SetNull(); // = TNodeId::NullCommsId(); + } + + if(iConnPrefList) + { + while(iConnPrefList->Count() != 0) + { + SMetaData* pref = (*iConnPrefList)[0]; + if(pref != NULL) + delete pref; + iConnPrefList->Remove(0); + } + + delete iConnPrefList; + iConnPrefList = NULL; + } + } + + +TBool ConnActivities::CStartAttachActivity::Next(MeshMachine::TNodeContextBase& aContext) + { + // If the connection start preferences were set the activity will have completed the initial IPC and will + // now be waiting upon the async ECNStart IPC to arrive before proceeding. The TCFInternalEsock::TSubSess + // message will use the IPC number in the activity id part of aContext. MatchSender() will expect the + // activity Id and so will never give a match. Here we ensure that our second IPC is matched and accepted. + + TCFInternalEsock::TSubSess* msg = message_cast(&aContext.iMessage); + if (!msg || msg->iMessage.Function() != ECNStart) + { + return CNodeActivityBase::Next(aContext); + } + + MESH_LOG((KESockConnectionTag, _L8("CStartAttachActivity::Next:\tAccepted ECNStart IPC after ECNSetStartPrefs"))); + TBool nextRet = ACore::Next(&aContext); + if(nextRet) + { + MESH_LOG_ACTIVITY_EXT(KESockConnectionTag, this, &aContext, (_L8("CStartAttachActivity::Next:\tNext->transition"))); + } + return nextRet; + } + + +DEFINE_SMELEMENT(CStartAttachActivity::TNoTagOrStartPrefsSetTag, NetStateMachine::MStateFork, ConnStates::TContext) +TInt CStartAttachActivity::TNoTagOrStartPrefsSetTag::TransitionTag() + { + CStartAttachActivity& ac = static_cast(*iContext.iNodeActivity); + + if (ac.Function() == ECNSetStartPrefs) + { + return CStartAttachActivity::KStartPrefsSetTag | NetStateMachine::EForward; + } + return MeshMachine::KNoTag | NetStateMachine::EForward; + } + +DEFINE_SMELEMENT(CStartAttachActivity::TNoTagOrLegacyAttach, NetStateMachine::MStateFork, ConnStates::TContext) +TInt CStartAttachActivity::TNoTagOrLegacyAttach::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + const TConnPref& cp = static_cast(*iContext.iNodeActivity).SelectionPrefs().Prefs(); + if (cp.ExtensionId()==TConnPref::EConnPrefCommDb) + {//this is legacy attach + return CStartAttachActivity::KExecuteLegacyAttach; + } + return KNoTag; + } + +DEFINE_SMELEMENT(CStartAttachActivity::TNoTagOrWaitAvailable, NetStateMachine::MStateFork, ConnStates::TContext) +TInt CStartAttachActivity::TNoTagOrWaitAvailable::TransitionTag() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + ConnActivities::CStartAttachActivity& activity = static_cast(*iContext.iNodeActivity); + + TConnPrefList* prefsList = activity.ConnPrefList(); + if (prefsList) + { + TBool startAuto = EFalse; + for (TInt i = 0; i < prefsList->Count(); i++) + { + TConnAutoStartPref* pref = smetadata_cast((*prefsList)[i]); + if(pref) + { + startAuto = ETrue; + break; + } + } + if (startAuto) + { + TBool &autoStart = activity.AutoStartPresent(); + autoStart = ETrue; + iContext.iNodeActivity->ClearPostedTo(); + return KWaitAvailable; + } + + } + return KNoTag; + } + +DEFINE_SMELEMENT(CStartAttachActivity::TErrorTagOrWaitAvailableBackward, NetStateMachine::MStateFork, ConnStates::TContext) +TInt CStartAttachActivity::TErrorTagOrWaitAvailableBackward::TransitionTag() + { + __ASSERT_DEBUG((message_cast(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage)); + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + ConnActivities::CStartAttachActivity& activity = static_cast(*iContext.iNodeActivity); + + if (!activity.AutoStartPresent()) + { + return KErrorTag; + } + + TEBase::TError& msg = message_cast(iContext.iMessage); + if (msg.iValue == KErrUmtsMaxNumOfContextExceededByNetwork || + msg.iValue == KErrUmtsMaxNumOfContextExceededByPhone) + { + return KWaitAvailable | NetStateMachine::EBackward; + } + else + { + return KErrorTag; + } + } + +DEFINE_SMELEMENT(CStartAttachActivity::TAwaitingAvailableOrError, NetStateMachine::MState, TContext) +TInt CStartAttachActivity::TAwaitingAvailableOrError::Accept() + { + if (iContext.iMessage.IsMessage()) + { + TCFAvailabilityControlClient::TAvailabilityNotification& msg = message_cast(iContext.iMessage); + if (msg.iAvailabilityStatus.Score() > TAvailabilityStatus::EMinAvailabilityScore) + { + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.iSender, + TEBase::TCancel().CRef()); + return ETrue; + } + return EFalse; + } + else if (iContext.iMessage.IsMessage()) + { + TEBase::TError* msg = message_cast(&iContext.iMessage); + iContext.iNodeActivity->SetError(msg->iValue); + return ETrue; + } + return EFalse; + } + + +DEFINE_SMELEMENT(CStartAttachActivity::TSubscribeForAvailability, NetStateMachine::MStateTransition, TContext) +void CStartAttachActivity::TSubscribeForAvailability::DoL() + { + __ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity)); + ConnActivities::CStartAttachActivity& activity = static_cast(*iContext.iNodeActivity); + + TConnPrefList* connPrefList = activity.ConnPrefList(); + if (connPrefList && connPrefList->Count()>0) + { + TBool startAuto = EFalse; + for (TInt i = 0; i < connPrefList->Count(); i++) + { + TConnAutoStartPref* pref = smetadata_cast((*connPrefList)[i]); + if(pref) + { + startAuto = ETrue; + break; + } + } + if (startAuto) + { + TAvailabilitySubscriptionOptions subscriptionOptions; + TClientIter iter = iContext.Node().GetClientIter(TClientType(TCFClientType::EServProvider, TCFClientType::EAvailabilityProvider)); + RNodeInterface* mcpr = iter[0]; + __ASSERT_DEBUG(mcpr, ConnPanic(KPanicNoAvailabilityProvider)); + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), mcpr->RecipientId(), + TCFAvailabilityProvider::TAvailabilityNotificationRegistration(subscriptionOptions).CRef()); + } + } + } + +DEFINE_SMELEMENT(CStartAttachActivity::TAwaitingSelectCompleteOrError, NetStateMachine::MState, TContext) +TInt CStartAttachActivity::TAwaitingSelectCompleteOrError::Accept() + { + if (iContext.iMessage.IsMessage()) + { + return ETrue; + } + else if(iContext.iMessage.IsMessage()) + { + TEBase::TError& errorMsg = message_cast(iContext.iMessage); + iContext.Activity()->SetError(errorMsg.iValue); + return ETrue; + } + + return EFalse; + } + + +#ifdef SYMBIAN_NETWORKING_UPS + +DEFINE_SMELEMENT(CStartAttachActivity::TSendPolicyCheckRequestToServiceProvider, NetStateMachine::MStateTransition, ConnStates::TContext) +void CStartAttachActivity::TSendPolicyCheckRequestToServiceProvider::DoL() + { + MPlatsecApiExt* platsec = NULL; + iContext.Node().ReturnInterfacePtrL(platsec); // from CConnection + // TODO: what to do on an error (see TODO below) + __ASSERT_DEBUG(platsec, User::Panic(KSpecAssert_ESockSSockscnsts, 18)); + + TProcessId processId; + TThreadId threadId; + TInt err = platsec->GetProcessAndThreadId(processId, threadId); + if (err != KErrNone) + { + const TNodeId& self = iContext.Node().Id(); + iContext.Node().SelfInterface().PostMessage(self, TEBase::TError(err).CRef()); + iContext.Activity()->ClearPostedTo(); + } + else + { + // KErrCorrupt is a default value for the platsec result. The platsec result must be filled-in by the provider + // and not ESock because only the provider knows the (technology specific) policy to check against. + // Destination address is not valid in this context, so it is just a null descriptor. + + const TPolicyCheckRequestParams params(processId, threadId, KErrCorrupt, KNullDesC8(), TUpsDestinationAddrType(ETNone), iContext.NodeId()); + + const UpsMessage::TPolicyCheckRequest checkMsg(params); + + RNodeInterface* serviceProvider = iContext.Node().ServiceProvider(); + + __ASSERT_DEBUG(serviceProvider, User::Panic(KSpecAssert_ESockSSockscnsts, 19)); + iContext.Activity()->PostRequestTo(*serviceProvider, checkMsg); + } + } + +DEFINE_SMELEMENT(CStartAttachActivity::TNoTagOrUpsErrorTag, NetStateMachine::MStateFork, ConnStates::TContext) +TInt CStartAttachActivity::TNoTagOrUpsErrorTag::TransitionTag() + { + UpsMessage::TPolicyCheckResponse* policyCheckResponseMsg = message_cast(&iContext.iMessage); + if (policyCheckResponseMsg && policyCheckResponseMsg->iValue != KErrNone) + { + iContext.Activity()->SetError(policyCheckResponseMsg->iValue); + return KUpsErrorTag; + } + else + { + TEBase::TError* errorMsg = message_cast(&iContext.iMessage); + // TODO: there is already code for this isn't there? A template that checks for TError and + // sets the activity in error? + if (errorMsg) + { + iContext.Activity()->SetError(errorMsg->iValue); + return KUpsErrorTag; + } + } + return KNoTag; + } +#endif + +// +// CTierManagerActivity + +MeshMachine::CNodeActivityBase* ConnActivities::CTierManagerActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new(ELeave) ConnActivities::CTierManagerActivity(aActivitySig, aNode); + } + +// States + +DEFINE_SMELEMENT(CTierManagerActivity::TAwaitingTierManager, NetStateMachine::MState, TContext) +TInt CTierManagerActivity::TAwaitingTierManager::Accept() + { + if(iContext.iMessage.IsMessage()) + { + TCFFactory::TPeerFoundOrCreated& msg = message_cast(iContext.iMessage); + iContext.Activity()->iTierManager = msg.iNodeId; + iContext.Activity()->ClearPostedTo(); + + return ETrue; + } + else if(iContext.iMessage.IsMessage()) + { + iContext.Activity()->SetError(KErrCancel); + + return ETrue; + } + else if(iContext.iMessage.IsMessage()) + { + // Register the error + TEBase::TError& errorMsg = message_cast(iContext.iMessage); + iContext.Activity()->SetError(errorMsg.iValue); + + return ETrue; + } + + return EFalse; + } + +DEFINE_SMELEMENT(CTierManagerActivity::TAwaitingJoinComplete, NetStateMachine::MState, TContext) +TInt CTierManagerActivity::TAwaitingJoinComplete::Accept() + { + if(iContext.iMessage.IsMessage()) + { + return ETrue; + } + else if(iContext.iMessage.IsMessage()) + { + iContext.Activity()->SetError(KErrCancel); + + return ETrue; + } + else if(iContext.iMessage.IsMessage()) + { + // Register the error + TEBase::TError& errorMsg = message_cast(iContext.iMessage); + iContext.Activity()->SetError(errorMsg.iValue); + + return ETrue; + } + + return EFalse; + } + +// Transitions + +DEFINE_SMELEMENT(CTierManagerActivity::TFindTierManager, NetStateMachine::MStateTransition, TContext) +void CTierManagerActivity::TFindTierManager::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + // Find out if the tier UID has been set. + TBool tierUidIsNull = (iContext.Activity()->iTierUid == TUid::Null()); + + // Panic in UDEB, Leave in UREL. The tier UID should be set in the derived + // class's constructor + __ASSERT_DEBUG(!tierUidIsNull, User::Panic(KSpecAssert_ESockSSockscnsts, 10)); + User::LeaveIfError(tierUidIsNull ? KErrNotReady : KErrNone); + TAlwaysFindFactoryQuery query; + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::ETierMgrPlane)), + TCFFactory::TFindOrCreatePeer(TCFPlayerRole::ETierMgrPlane, iContext.Activity()->iTierUid, &query).CRef()); + } + +DEFINE_SMELEMENT(CTierManagerActivity::TJoinTierManager, NetStateMachine::MStateTransition, TContext) +void CTierManagerActivity::TJoinTierManager::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.Activity()->iTierManager, + TCFServiceProvider::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::EAdministrative)).CRef()); + + iContext.Node().AddClientL(iContext.Activity()->iTierManager, TClientType(TCFClientType::EServProvider)); + } + +// This solely exists separately from the other identical-looking version +// in this file +// ("AllInterfaceNotificationActivity::TLeaveTierManager::DoL()") because +// the activities referenced by its TContext have iTierManager +// at different offsets. This is because they have different parent +// classes and, as such, have different member variable. +// +// The terrible thing is, this is usable in the other place, +// and builds without complaint... then explodes when it tries +// to send messages to a garbage iTierManager. +// +// TAKE CARE OF IT!!! +DEFINE_SMELEMENT(CTierManagerActivity::TLeaveTierManager, NetStateMachine::MStateTransition, TContext) +void CTierManagerActivity::TLeaveTierManager::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.Activity()->iTierManager, + TEChild::TLeft().CRef()); + + iContext.Node().RemoveClient(iContext.Activity()->iTierManager); + } + +// +// CAllInterfaceNotificationActivity + +CNodeActivityBase* ConnActivities::CAllInterfaceNotificationActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new (ELeave) ConnActivities::CAllInterfaceNotificationActivity(aActivitySig, aNode); + } + +ConnActivities::CAllInterfaceNotificationActivity::~CAllInterfaceNotificationActivity() + { + //Remove the only client here + RNodeInterface* aux = iNode.GetFirstClient(TClientType(TCFClientType::EAux)); + if (aux) + { + iNode.RemoveClient(aux->RecipientId()); + } + delete iAllInterfaceNotificationWorker; //delete this node (why via iAllInterfaceNotificationWorker??) + } + +// States + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TAwaitingStart, NetStateMachine::MState, TContext) +TInt AllInterfaceNotificationActivity::TAwaitingStart::Accept() + { + return iContext.iMessage.IsMessage(); + } + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TAwaitingTierManager, NetStateMachine::MState, TContext) +TInt AllInterfaceNotificationActivity::TAwaitingTierManager::Accept() + { + if(iContext.iMessage.IsMessage()) + { + TCFFactory::TPeerFoundOrCreated& msg = message_cast(iContext.iMessage); + iContext.Activity()->iTierManager = msg.iNodeId; + iContext.Activity()->ClearPostedTo(); + + return ETrue; + } + return EFalse; + } + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TAwaitingJoinComplete, NetStateMachine::MState, TContext) +TInt AllInterfaceNotificationActivity::TAwaitingJoinComplete::Accept() + { + return iContext.iMessage.IsMessage(); + } + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TAwaitingLinkNotification, NetStateMachine::MState, TContext) +TInt AllInterfaceNotificationActivity::TAwaitingLinkNotification::Accept() + { + return (iContext.iMessage.IsMessage() || + iContext.iMessage.IsMessage() || + iContext.iMessage.IsMessage() ); + } + +void AllInterfaceNotificationActivity::TAwaitingLinkNotification::Cancel() + { + __ASSERT_DEBUG(0, User::Panic(KSpecAssert_ESockSSockscnsts, 11)); + } + + +// for shutdown +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TAwaitingLinkNotificationError, NetStateMachine::MState, TContext) +TInt AllInterfaceNotificationActivity::TAwaitingLinkNotificationError::Accept() + { + if(iContext.iMessage.IsMessage()) + { + // we're already shutting down. so have detached from CConnection. + // so we have to delete the enclosed object instead. + LOG( ESockLog::Printf(KESockConnectionTag, _L("AllInterfaceNotification received bundle when already shutting down so deleting it"))); + TCFTierStatusProvider::TTierNotification& msg = message_cast(iContext.iMessage); + msg.iBundle->Close(); + iContext.iMessage.ClearMessageId(); + } + else if(iContext.iMessage.IsMessage()) + { + LOG( ESockLog::Printf(KESockConnectionTag, _L("AllInterfaceNotification received TCancel when already shutting down so discarding it"))); + iContext.iMessage.ClearMessageId(); + } + + return iContext.iMessage.IsMessage(); + } + + +// Transitions + +DEFINE_SMELEMENT(ConnectionGoingDownActivity::TStoreGoneDownError, NetStateMachine::MStateTransition, TContext) +void ConnectionGoingDownActivity::TStoreGoneDownError::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + TCFControlClient::TGoneDown& goneDownMessage = message_cast(iContext.iMessage); + LOG( ESockLog::Printf(KESockConnectionTag, _L("TStoreGoneDownError. error:%d"), goneDownMessage.iValue1)); + iContext.Activity()->SetError(goneDownMessage.iValue1); + } + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TAddClient, NetStateMachine::MStateTransition, TContext) +void AllInterfaceNotificationActivity::TAddClient::DoL() + { + __ASSERT_DEBUG(iContext.Activity() == NULL, ConnPanic(KPanicNoActivity)); + __ASSERT_DEBUG(iContext.iPeer == NULL, User::Panic(KSpecAssert_ESockSSockscnsts, 12)); + iContext.iPeer = iContext.Node().AddClientL(address_cast(iContext.iSender), TClientType(TCFClientType::EAux)); + } + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TFindTierManager, NetStateMachine::MStateTransition, TContext) +void AllInterfaceNotificationActivity::TFindTierManager::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + // Find out if the tier UID has been set. + TBool tierUidIsNull = (iContext.Activity()->iTierUid == TUid::Null()); + + // Panic in UDEB, Leave in UREL. The tier UID should be set in the derived + // class's constructor + __ASSERT_DEBUG(!tierUidIsNull, User::Panic(KSpecAssert_ESockSSockscnsts, 13)); + User::LeaveIfError(tierUidIsNull ? KErrNotReady : KErrNone); + + TAlwaysFindFactoryQuery query; + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), SockManGlobals::Get()->GetPlaneFC(TCFPlayerRole(TCFPlayerRole::ETierMgrPlane)), + TCFFactory::TFindOrCreatePeer(TCFPlayerRole::ETierMgrPlane, iContext.Activity()->iTierUid, &query).CRef()); + } + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TJoinTierManager, NetStateMachine::MStateTransition, TContext) +void AllInterfaceNotificationActivity::TJoinTierManager::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.Activity()->iTierManager, + TCFServiceProvider::TJoinRequest(iContext.NodeId(), TClientType(TCFClientType::EAdministrative)).CRef()); + + iContext.Node().AddClientL(iContext.Activity()->iTierManager, TClientType(TCFClientType::EServProvider)); + } + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TStartLinkNotification, NetStateMachine::MStateTransition, TContext) +void AllInterfaceNotificationActivity::TStartLinkNotification::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + CConnectionServParameterBundle* queryBundle = CConnectionServParameterBundle::NewL(); + CleanupStack::PushL(queryBundle); + CRefCountOwnedParameterBundle* bundleOwner = new(ELeave)CRefCountOwnedParameterBundle(queryBundle); + CleanupStack::Pop(); + bundleOwner->Open(); + CleanupClosePushL(*bundleOwner); + + CParameterSetContainer* psc = CParameterSetContainer::NewL(*queryBundle); + + // Set up a status filter for connected access points only + TAccessPointStatusFilter availFilter; + availFilter.Configured(EAccessPointFlagIgnore); + availFilter.Restricted(EAccessPointFlagIgnore); + availFilter.Available(EAccessPointFlagIgnore); + availFilter.Started(EAccessPointFlagIgnore); + availFilter.Active(EAccessPointFlagMatchAny); + queryBundle->AddMatchConditionL(availFilter); + queryBundle->AddParameterSetToReturnL(XAccessPointGenericParameterSet::Type()); + queryBundle->AddParameterSetToReturnL(XIpProtoAccessPointParameterSet::Type()); + + const CAllInterfaceNotificationWorker* worker = iContext.Activity()->iAllInterfaceNotificationWorker; + const RMessage2* rm2 = &(iContext.Activity()->iAllInterfaceNotificationWorker->iConnection.Message()); + + RClientInterface::OpenPostMessageClose(worker->Id(), iContext.Activity()->iTierManager, + TCFTierStatusProvider::TTierNotificationRegistration(bundleOwner, rm2).CRef()); + CleanupStack::Pop(); // bundleOwner + } + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TEnqueueNotification, NetStateMachine::MStateTransition, TContext) +void AllInterfaceNotificationActivity::TEnqueueNotification::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + TCFTierStatusProvider::TTierNotification& msg = message_cast(iContext.iMessage); + + __ASSERT_DEBUG(msg.iBundle, User::Panic(KSpecAssert_ESockSSockscnsts, 14)); + if(msg.iBundle->PtrL()->CountParamSetContainers() > 0) + { + TInt i = 0; + TBool found = EFalse; + while(const CConnectionServParameterSetContainer* container = static_cast(msg.iBundle->Ptr()->GetParamSetContainer(i++))) + { + const XAccessPointGenericParameterSet* status = XAccessPointGenericParameterSet::FindInParamSetContainer(*container); + + TConnInterfaceState interfaceState; + if (status->AccessPointStatus().Active() == ConnectionServ::EAccessPointFlagTrue) + { + interfaceState = EInterfaceUp; + } + else + { + interfaceState = EInterfaceDown; + } + + const XIpProtoAccessPointParameterSet* ipApParams = XIpProtoAccessPointParameterSet::FindInParamSetContainer(*container); +// ASSERT(ipApParams); + if (ipApParams) // commsdat might be broken so XIpProtoAccessPointParameterSet not available + { + TConnectionInfo connectionInfo(ipApParams->IapId(), ipApParams->NetworkId()); + + TInterfaceNotification notification = { connectionInfo, interfaceState }; + + iContext.Node().iConnection.iLegacyConnection.iNotificationQueue.Enque(notification); + + found = ETrue; + } + } + if (found) + iContext.Node().iConnection.iLegacyConnection.CompleteAllInterfaceNotificationL(KErrNone); + + } + + msg.iBundle->Close(); + } + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TCancelLinkNotification, NetStateMachine::MStateTransition, TContext) +void AllInterfaceNotificationActivity::TCancelLinkNotification::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + TNodeId goo = iContext.Activity()->iTierManager; + + const CAllInterfaceNotificationWorker* worker = iContext.Activity()->iAllInterfaceNotificationWorker; + + RNodeInterface::OpenPostMessageClose(worker->Id(), iContext.Activity()->iTierManager, + TEBase::TCancel().CRef()); + } + +// This solely exists separately from the other identical-looking version +// in this file ("CTierManagerActivity::TLeaveTierManager::DoL()") because +// the activities referenced by its TContext have iTierManager +// at different offsets. This is because they have different parent +// classes and, as such, have different member variable. +// +// The terrible thing is, this is usable in the other place, +// and builds without complaint... then explodes when it tries +// to send messages to a garbage iTierManager. +// +// TAKE CARE OF IT!!! +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TLeaveTierManager, NetStateMachine::MStateTransition, TContext) +void AllInterfaceNotificationActivity::TLeaveTierManager::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.Activity()->iTierManager, + TEChild::TLeft().CRef()); + + iContext.Node().RemoveClient(iContext.Activity()->iTierManager); + } + +DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TSendErrorToConnection, NetStateMachine::MStateTransition, TContext) +void AllInterfaceNotificationActivity::TSendErrorToConnection::DoL() + { + // Send a TError to the CConnection to complete the shutdown handshake. + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.Node().iConnection.Id(), TEBase::TError(iContext.Activity()->KickOffMessageId(), KErrCancel).CRef()); + } + +DEFINE_SMELEMENT(TNoTagOrCancelAllInterfaceWorker, NetStateMachine::MStateFork, TContext) +TInt TNoTagOrCancelAllInterfaceWorker::TransitionTag() + { + // If this CConnection has an AllInterfaceNotificationWorker, return KCancelAllInterfaceWorker else return KNoTag. + AConnectionLegacy& cl = iContext.Node().iLegacyConnection; + return cl.iAllInterfaceNotificationWorker.IsNull() ? KNoTag : KCancelAllInterfaceWorker; + } + +DEFINE_SMELEMENT(TCancelAllInterfaceNotificationWorker, NetStateMachine::MStateTransition, TContext) +void TCancelAllInterfaceNotificationWorker::DoL() + { + CConnection& cc = iContext.Node(); + AConnectionLegacy& cl = cc.iLegacyConnection; + // If this CConnection has an AllInterfaceNotificationWorker, send a TCancel to it to begin + // the shutdown handshake. + if(!cl.iAllInterfaceNotificationWorker.IsNull()) + { + TNodeCtxId dest(ECFActivityConnectionAllInterfaceNotification, cl.iAllInterfaceNotificationWorker); + RNodeInterface::OpenPostMessageClose(cc.Id(), dest, TEBase::TCancel().CRef()); + cl.iAllInterfaceNotificationWorker.SetNull(); + } + } + +// +// CEnumerateConnectionsActivity + +MeshMachine::CNodeActivityBase* ConnActivities::CEnumerateConnectionsActivity::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new(ELeave) ConnActivities::CEnumerateConnectionsActivity(aActivitySig, aNode); + } + +// States + +DEFINE_SMELEMENT(EnumerateConnectionsActivity::TAwaitingTierStatus, NetStateMachine::MState, TContext) +TInt EnumerateConnectionsActivity::TAwaitingTierStatus::Accept() + { + TBool isTierStatus = iContext.iMessage.IsMessage(); + TBool isError = iContext.iMessage.IsMessage(); + + if(isTierStatus || isError) + { + // Leave the tier manager + RNodeInterface::OpenPostMessageClose(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.Activity()->iTierManager, + TEChild::TLeft().CRef()); + + iContext.Node().RemoveClient(iContext.Activity()->iTierManager); + } + + return isTierStatus; + } + +// Transitions + +DEFINE_SMELEMENT(EnumerateConnectionsActivity::TQueryTierStatus, NetStateMachine::MStateTransition, TContext) +void EnumerateConnectionsActivity::TQueryTierStatus::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + // Clear the connection info cache + iContext.Node().iLegacyConnection.iConnectionInfoPtrArray.ResetAndDestroy(); + + CConnectionServParameterBundle* queryBundle = CConnectionServParameterBundle::NewL(); + CleanupStack::PushL(queryBundle); + CRefCountOwnedParameterBundle* bundleOwner = new (ELeave)CRefCountOwnedParameterBundle(queryBundle); + CleanupStack::Pop(queryBundle); + bundleOwner->Open(); + CleanupClosePushL(*bundleOwner); + + // Set up a status filter for connected access points only + TAccessPointStatusFilter availFilter; + availFilter.Configured(EAccessPointFlagIgnore); + availFilter.Restricted(EAccessPointFlagIgnore); + availFilter.Available(EAccessPointFlagIgnore); + availFilter.Started(EAccessPointFlagIgnore); + availFilter.Active(EAccessPointFlagMatchTrue); + + queryBundle->AddMatchConditionL(availFilter); + queryBundle->AddParameterSetToReturnL(XIpProtoAccessPointParameterSet::Type()); + + RClientInterface::OpenPostMessageClose(iContext.NodeId(), iContext.Activity()->iTierManager, + TCFTierStatusProvider::TTierStatusQuery(bundleOwner, &iContext.Activity()->iMessage).CRef()); + CleanupStack::Pop(); // bundleOwner + } + +DEFINE_SMELEMENT(EnumerateConnectionsActivity::TCompleteClient, NetStateMachine::MStateTransition, TContext) +void EnumerateConnectionsActivity::TCompleteClient::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + TPckg pckg(iContext.Node().iLegacyConnection.iConnectionInfoPtrArray.Count()); + iContext.Activity()->WriteL(0, pckg); + } + +DEFINE_SMELEMENT(EnumerateConnectionsActivity::TCacheConnectionInfo, NetStateMachine::MStateTransition, TContext) +void EnumerateConnectionsActivity::TCacheConnectionInfo::DoL() + { + __ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity)); + + TCFTierStatusProvider::TTierStatus& msg = message_cast(iContext.iMessage); + + const CConnectionServParameterSetContainer* container; + const XIpProtoAccessPointParameterSet* ipApParams; + + for (TInt i=0; iPtrL()->CountParamSetContainers(); i++) + { + container = static_cast(msg.iBundle->Ptr()->GetParamSetContainer(i)); + + ipApParams = XIpProtoAccessPointParameterSet::FindInParamSetContainer(*container); + __ASSERT_DEBUG(ipApParams, User::Panic(KSpecAssert_ESockSSockscnsts, 16)); + + TSourcedConnectionInfo* connInfo = new(ELeave) TSourcedConnectionInfo(ipApParams->IapId(), ipApParams->NetworkId(), ipApParams->ConnectionType(), ipApParams->ControlClientId()); + iContext.Node().iLegacyConnection.iConnectionInfoPtrArray.AppendL(connInfo); + } + + msg.iBundle->Close(); + } + +DEFINE_SMELEMENT(ConnectionCleanupActivities::TNoTagOrNoTagBackwards, NetStateMachine::MStateFork, TContext) +TInt ConnectionCleanupActivities::TNoTagOrNoTagBackwards::TransitionTag() + { + if ( iContext.iMessage.IsMessage() ) + { +// __ASSERT_DEBUG(iContext.Node().GetClientIter(RNodeInterface::ECtrl|RNodeInterface::EData)[0] == NULL, +// User::Panic(KCorePRPanic, KPanicClientsStillPresent)); + if (iContext.Node().GetFirstClient(TCFClientType(TCFClientType::EServProvider)) == NULL) + { // This was the last service provider + return NetStateMachine::EForward | MeshMachine::KNoTag; + } + // There are more service providers to expect 'leave complete' from so + // loop round and wait for the next one. + return NetStateMachine::EBackward | MeshMachine::KNoTag; + } + __ASSERT_DEBUG(EFalse, User::Panic(KSpecAssert_ESockSSockscnsts, 17)); + return KNoTag; + } + +DEFINE_SMELEMENT(ConnSubConnEventsActivity::TAwaitingSubConnEvent, NetStateMachine::MState, TContext) +TInt ConnSubConnEventsActivity::TAwaitingSubConnEvent::Accept() + { + if(iContext.iMessage.IsMessage() || + iContext.iMessage.IsMessage()) + { + return ETrue; + } + return EFalse; + } + +DEFINE_SMELEMENT(ConnSubConnEventsActivity::TProcessSubConnEvent, NetStateMachine::MStateTransition, TContext) +void ConnSubConnEventsActivity::TProcessSubConnEvent::DoL() + { + CConnection& conn = static_cast(iContext.Node()); + + if(iContext.iMessage.IsMessage()) + { + const TCFInternalEsock::TSubConnectionOpenedEvent& msg = message_cast(iContext.iMessage); + conn.iLegacyConnection.SubConnectionEvent(msg.iSubConnectionOpenedEvent); + } + else + { + const TCFInternalEsock::TSubConnectionClosedEvent& msg = message_cast(iContext.iMessage); + conn.iLegacyConnection.SubConnectionEvent(msg.iSubConnectionClosedEvent); + } + } + +CNodeActivityBase* CConnLegacyRMessage2Activity::NewL( const TNodeActivity& aActivitySig, AMMNodeBase& aNode ) + { + TUint c = GetNextActivityCountL(aActivitySig,aNode); + return new (ELeave) CConnLegacyRMessage2Activity( aActivitySig, aNode, c); + } + +CConnLegacyRMessage2Activity::CConnLegacyRMessage2Activity( const TNodeActivity& aActivitySig, AMMNodeBase& aNode, TUint aNextActivityCount) + : MeshMachine::CNodeParallelMessageStoreActivityBase(aActivitySig, aNode, aNextActivityCount) + { + } + +CConnLegacyRMessage2Activity::~CConnLegacyRMessage2Activity() + { + if (Error() != KErrNone) + { + Complete(Error()); + } + if (!iCancelMessage.IsNull()) + { + iCancelMessage.Complete(KErrNone); + } + SetError(KErrNone); + } + +void CConnLegacyRMessage2Activity::PanicClient(const TDesC& aCatagory, TInt aCode) + { + if (!iSafeMessage.IsNull()) + { + iSafeMessage.PanicClient(aCatagory, aCode); + } + } + +void CConnLegacyRMessage2Activity::Complete(TInt aCode) + { + if (!iSafeMessage.IsNull()) + { + iSafeMessage.Complete(aCode); + } + } + +void CConnLegacyRMessage2Activity::SetCancelRequest(const Den::RSafeMessage& aMessage) + { + iCancelMessage.Duplicate(aMessage); + } + + +DEFINE_SMELEMENT(TProcessLegacyRMessage2, NetStateMachine::MStateTransition, TContext) +void TProcessLegacyRMessage2::DoL() + { + ASSERT(iContext.iMessage.IsTypeOf(Meta::STypeId::CreateSTypeId(TCFSigLegacyRMessage2Ext::EUid, TCFSigLegacyRMessage2Ext::ETypeId))); + // static_cast as it will be a derivative and message_cast won't work + CConnLegacyRMessage2Activity* act = static_cast(iContext.Activity()); + TCFSigLegacyRMessage2Ext& msg = static_cast(iContext.iMessage); + act->iSafeMessage.Duplicate(msg.iMessage); + + if (msg.CanProcess(iContext)) + { + msg.ProcessL(iContext); + } + else + { + msg.ForwardL(iContext); + } + } + +DEFINE_SMELEMENT(TCompleteRMessage2, NetStateMachine::MStateTransition, TContext) +void TCompleteRMessage2::DoL() + { + TCFLegacyMessage::TLegacyRMessage2Processed& msg = message_cast(iContext.iMessage); + CConnLegacyRMessage2Activity* act = static_cast(iContext.Activity()); + + if (msg.iResponse.iType == TLegacyRMessage2Response::EPanic) + { + act->PanicClient(msg.iResponse.iCatagory, msg.iResponse.iCode); + } + else + { + ASSERT(act->Message().IsTypeOf(Meta::STypeId::CreateSTypeId(TCFSigLegacyRMessage2Ext::EUid, TCFSigLegacyRMessage2Ext::ETypeId))); + TInt error = static_cast(act->Message()).CheckError(iContext, msg.iResponse.iCode); + act->Complete(error); + } + } + +DEFINE_SMELEMENT(THandleRMessage2Error, NetStateMachine::MStateTransition, ConnStates::TContext) +void THandleRMessage2Error::DoL() + { + CConnLegacyRMessage2Activity* act = static_cast(iContext.Activity()); + + ASSERT(act->Message().IsTypeOf(Meta::STypeId::CreateSTypeId(TCFSigLegacyRMessage2Ext::EUid, TCFSigLegacyRMessage2Ext::ETypeId))); + TInt error = static_cast(act->Message()).CheckError(iContext, act->Error()); + act->SetError(error); + act->Complete(error); + } + + +DEFINE_SMELEMENT(TCancelAllLegacyRMessage2Activities, NetStateMachine::MStateTransition, TContext) +void TCancelAllLegacyRMessage2Activities::DoL() + { + const RPointerArray& activities = iContext.Node().Activities(); + + for (TInt i = 0; i < activities.Count(); i++) + { + if (activities[i]->ActivitySigId() == ESock::ECFActivityConnectionLegacyRMessage2Handler) + { + activities[i]->Cancel(iContext); + } + } + } + +