// 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 <comms-infras/ss_log.h>
#include <comms-infras/ss_coreprstates.h>
#include <comms-infras/ss_corepractivities.h>
#include "ss_subconn.h"
#include <comms-infras/ss_mcprnodemessages.h>
#include <elements/sm_core.h>
#include <commdbconnpref.h> //TCommDbConnPref
#include <ss_glob.h> //TCommDbConnPref
#include <connpref.h> //TConnPrefList
#include <etelpckt.h>
#include <comms-infras/metadata.h>
#include <comms-infras/esock_params.h> //TConnAPPref
#include <comms-infras/esock_params_internal.h> //TConnCSRPref
#include <comms-infras/es_connectionservparameterbundle.h> // CConnectionServParameterBundle
#include <comms-infras/es_accesspointstatus.h> // TAccessPointStatusFilter
#include <comms-infras/cs_connservparams.h> // XAccessPointGenericParameterSet
#include <comms-infras/cs_connservparams_internal.h>
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <es_enum_internal.h>
#include <nifvar_internal.h>
#endif
#include <elements/nm_messages_child.h>
#include <elements/nm_messages_peer.h>
#include <comms-infras/ss_nodemessages_dataclient.h>
#include <comms-infras/ss_nodemessages_legacy.h>
#include <comms-infras/ss_nodemessages_tiermanager.h>
#include <comms-infras/ss_nodemessages_serviceprovider.h>
#include <comms-infras/ss_nodemessages_internal_esock.h>
#include <comms-infras/ss_nodemessages_selector.h>
#include <comms-infras/ss_nodemessages_factory.h>
#include <comms-infras/ss_nodemessages_tiermanagerfactory.h>
#define SYMBIAN_NETWORKING_UPS
#ifdef SYMBIAN_NETWORKING_UPS
#include <comms-infras/ss_upsaccesspointconfigext.h>
#include <comms-infras/upsmessages.h>
#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<ECNStart>(&iContext.iMessage))
|| (subsessmessage_cast<ECNAttach>(&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<ECNStart>(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage));
__ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity));
ConnActivities::CStartAttachActivity& ac = static_cast<ConnActivities::CStartAttachActivity&>(*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; i<prefsList->Count(); i++)
{
TConnAPPref* pref = smetadata_cast<TConnAPPref>((*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<ConnActivities::CStartAttachActivity&>(*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<ConnActivities::CStartAttachActivity&>(*iContext.iNodeActivity);
__ASSERT_DEBUG(ac.CSR().IsNull(), User::Panic(KSpecAssert_ESockSSockscnsts, 1));
ac.SetCSR(message_cast<TCFInternalEsock::TCSRCreated>(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<ConnActivities::CStartAttachActivity&>(*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<TCFDataClient::TBindTo>(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<ConnActivities::CStartAttachActivity&>(*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<TCFServiceProvider::TCommsBinderResponse>(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<ConnActivities::CStartAttachActivity&>(*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<TCFSelector::TSelectComplete>(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<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(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<TCFServiceProvider::TCommsBinderResponse>(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<ConnActivities::CStartAttachActivity&>(*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<ECNAttach>(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage));
__ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity));
ConnActivities::CStartAttachActivity& ac = static_cast<ConnActivities::CStartAttachActivity&>(*iContext.iNodeActivity);
//Read preferences
const TUint KMaxConnectionInfoLength = 32;
TBuf8<KMaxConnectionInfoLength> 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<TConnectionInfo&>(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<TConnProviderInfo&>(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<ConnActivities::CStartAttachActivity&>(*iContext.iNodeActivity).SelectionPrefs());
}
//
//WaitForIncoming
DEFINE_SMELEMENT(ConnStates::TRequestIncomingConnection, NetStateMachine::MStateTransition, ConnStates::TContext)
void ConnStates::TRequestIncomingConnection::DoL()
{
__ASSERT_DEBUG((subsessmessage_cast<ECNWaitForIncoming>(&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<CESockClientActivityBase&>(*iContext.iNodeActivity).Int0());
User::LeaveIfError(waitingSubConn != NULL ? KErrNone : KErrCancel);
TCFServiceProvider::TCommsBinderResponse& binderResp = message_cast<TCFServiceProvider::TCommsBinderResponse>(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<ECNStop>(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage));
__ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity));
CESockClientActivityBase& ac = static_cast<CESockClientActivityBase&>(*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<CESockClientActivityBase*>(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<CConnection&>(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<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(TClientType(TCFClientType::EData));
RNodeInterface* client = iter[0];
if (client)
{
#if defined(__GCCXML__)
CSubConnection& subconn = *reinterpret_cast<CSubConnection*>(&client->RecipientId().Node());
#else
CSubConnection& subconn = *mcfnode_cast<CSubConnection>(&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<TCFControlClient::TGoneDown>())
{
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<TCFServiceProvider::TStopped>())
{
error = message_cast<TCFServiceProvider::TStopped>(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<TCFMessage::TStateChange>(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<CESockClientActivityBase&>(*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<TCFMessage::TStateChange>(&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<ECNProgressNotification>(&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<TStateChange> 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<TCFInternalEsock::TLegacyConnectionEnumResponse>();
}
DEFINE_SMELEMENT(ConnStates::TProcessEnumResponse, NetStateMachine::MStateTransition, ConnStates::TContext)
void ConnStates::TProcessEnumResponse::DoL()
{
TCFInternalEsock::TLegacyConnectionEnumResponse& msg = message_cast<TCFInternalEsock::TLegacyConnectionEnumResponse>(iContext.iMessage);
iContext.Node().iLegacyConnection.CompleteDataPlaneEnumeration(address_cast<TNodeId>(iContext.iSender), msg.iValue1, reinterpret_cast<HBufC8*>(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<TDefaultClientMatchPolicy>(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<TDefaultClientMatchPolicy>(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<TCFInternalEsock::TSubSess>(&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<CStartAttachActivity&>(*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<ConnActivities::CStartAttachActivity&>(*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<ConnActivities::CStartAttachActivity&>(*iContext.iNodeActivity);
TConnPrefList* prefsList = activity.ConnPrefList();
if (prefsList)
{
TBool startAuto = EFalse;
for (TInt i = 0; i < prefsList->Count(); i++)
{
TConnAutoStartPref* pref = smetadata_cast<TConnAutoStartPref>((*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<TEBase::TError>(&iContext.iMessage)), ConnPanic(KPanicIncorrectMessage));
__ASSERT_DEBUG(iContext.iNodeActivity, ConnPanic(KPanicNoActivity));
ConnActivities::CStartAttachActivity& activity = static_cast<ConnActivities::CStartAttachActivity&>(*iContext.iNodeActivity);
if (!activity.AutoStartPresent())
{
return KErrorTag;
}
TEBase::TError& msg = message_cast<TEBase::TError>(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>())
{
TCFAvailabilityControlClient::TAvailabilityNotification& msg = message_cast<TCFAvailabilityControlClient::TAvailabilityNotification>(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>())
{
TEBase::TError* msg = message_cast<TEBase::TError>(&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<ConnActivities::CStartAttachActivity&>(*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<TConnAutoStartPref>((*connPrefList)[i]);
if(pref)
{
startAuto = ETrue;
break;
}
}
if (startAuto)
{
TAvailabilitySubscriptionOptions subscriptionOptions;
TClientIter<TDefaultClientMatchPolicy> iter = iContext.Node().GetClientIter<TDefaultClientMatchPolicy>(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<TCFSelector::TSelectComplete>())
{
return ETrue;
}
else if(iContext.iMessage.IsMessage<TEBase::TError>())
{
TEBase::TError& errorMsg = message_cast<TEBase::TError>(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<UpsMessage::TPolicyCheckResponse>(&iContext.iMessage);
if (policyCheckResponseMsg && policyCheckResponseMsg->iValue != KErrNone)
{
iContext.Activity()->SetError(policyCheckResponseMsg->iValue);
return KUpsErrorTag;
}
else
{
TEBase::TError* errorMsg = message_cast<TEBase::TError>(&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>())
{
TCFFactory::TPeerFoundOrCreated& msg = message_cast<TCFFactory::TPeerFoundOrCreated>(iContext.iMessage);
iContext.Activity()->iTierManager = msg.iNodeId;
iContext.Activity()->ClearPostedTo();
return ETrue;
}
else if(iContext.iMessage.IsMessage<TEBase::TCancel>())
{
iContext.Activity()->SetError(KErrCancel);
return ETrue;
}
else if(iContext.iMessage.IsMessage<TEBase::TError>())
{
// Register the error
TEBase::TError& errorMsg = message_cast<TEBase::TError>(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<TCFPeer::TJoinComplete>())
{
return ETrue;
}
else if(iContext.iMessage.IsMessage<TEBase::TCancel>())
{
iContext.Activity()->SetError(KErrCancel);
return ETrue;
}
else if(iContext.iMessage.IsMessage<TEBase::TError>())
{
// Register the error
TEBase::TError& errorMsg = message_cast<TEBase::TError>(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<TDefaultClientMatchPolicy>(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<TCFServiceProvider::TStart>();
}
DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TAwaitingTierManager, NetStateMachine::MState, TContext)
TInt AllInterfaceNotificationActivity::TAwaitingTierManager::Accept()
{
if(iContext.iMessage.IsMessage<TCFFactory::TPeerFoundOrCreated>())
{
TCFFactory::TPeerFoundOrCreated& msg = message_cast<TCFFactory::TPeerFoundOrCreated>(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<TCFPeer::TJoinComplete>();
}
DEFINE_SMELEMENT(AllInterfaceNotificationActivity::TAwaitingLinkNotification, NetStateMachine::MState, TContext)
TInt AllInterfaceNotificationActivity::TAwaitingLinkNotification::Accept()
{
return (iContext.iMessage.IsMessage<TCFTierStatusProvider::TTierNotification>() ||
iContext.iMessage.IsMessage<TEBase::TCancel>() ||
iContext.iMessage.IsMessage<TEBase::TError>() );
}
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<TCFTierStatusProvider::TTierNotification>())
{
// 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<TCFTierStatusProvider::TTierNotification>(iContext.iMessage);
msg.iBundle->Close();
iContext.iMessage.ClearMessageId();
}
else if(iContext.iMessage.IsMessage<TEBase::TCancel>())
{
LOG( ESockLog::Printf(KESockConnectionTag, _L("AllInterfaceNotification received TCancel when already shutting down so discarding it")));
iContext.iMessage.ClearMessageId();
}
return iContext.iMessage.IsMessage<TEBase::TError>();
}
// Transitions
DEFINE_SMELEMENT(ConnectionGoingDownActivity::TStoreGoneDownError, NetStateMachine::MStateTransition, TContext)
void ConnectionGoingDownActivity::TStoreGoneDownError::DoL()
{
__ASSERT_DEBUG(iContext.Activity(), ConnPanic(KPanicNoActivity));
TCFControlClient::TGoneDown& goneDownMessage = message_cast<TCFControlClient::TGoneDown>(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<TNodeId>(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<TCFTierStatusProvider::TTierNotification>(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<const CConnectionServParameterSetContainer*>(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<TCFTierStatusProvider::TTierStatus>();
TBool isError = iContext.iMessage.IsMessage<TEBase::TError>();
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<TUint> 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<TCFTierStatusProvider::TTierStatus>(iContext.iMessage);
const CConnectionServParameterSetContainer* container;
const XIpProtoAccessPointParameterSet* ipApParams;
for (TInt i=0; i<msg.iBundle->PtrL()->CountParamSetContainers(); i++)
{
container = static_cast<const CConnectionServParameterSetContainer*>(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<TEPeer::TLeaveComplete>() )
{
// __ASSERT_DEBUG(iContext.Node().GetClientIter(RNodeInterface::ECtrl|RNodeInterface::EData)[0] == NULL,
// User::Panic(KCorePRPanic, KPanicClientsStillPresent));
if (iContext.Node().GetFirstClient<TDefaultClientMatchPolicy>(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<TCFInternalEsock::TSubConnectionOpenedEvent>() ||
iContext.iMessage.IsMessage<TCFInternalEsock::TSubConnectionClosedEvent>())
{
return ETrue;
}
return EFalse;
}
DEFINE_SMELEMENT(ConnSubConnEventsActivity::TProcessSubConnEvent, NetStateMachine::MStateTransition, TContext)
void ConnSubConnEventsActivity::TProcessSubConnEvent::DoL()
{
CConnection& conn = static_cast<CConnection&>(iContext.Node());
if(iContext.iMessage.IsMessage<TCFInternalEsock::TSubConnectionOpenedEvent>())
{
const TCFInternalEsock::TSubConnectionOpenedEvent& msg = message_cast<TCFInternalEsock::TSubConnectionOpenedEvent>(iContext.iMessage);
conn.iLegacyConnection.SubConnectionEvent(msg.iSubConnectionOpenedEvent);
}
else
{
const TCFInternalEsock::TSubConnectionClosedEvent& msg = message_cast<TCFInternalEsock::TSubConnectionClosedEvent>(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<CConnLegacyRMessage2Activity*>(iContext.Activity());
TCFSigLegacyRMessage2Ext& msg = static_cast<TCFSigLegacyRMessage2Ext&>(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<TCFLegacyMessage::TLegacyRMessage2Processed>(iContext.iMessage);
CConnLegacyRMessage2Activity* act = static_cast<CConnLegacyRMessage2Activity*>(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<TCFSigLegacyRMessage2Ext&>(act->Message()).CheckError(iContext, msg.iResponse.iCode);
act->Complete(error);
}
}
DEFINE_SMELEMENT(THandleRMessage2Error, NetStateMachine::MStateTransition, ConnStates::TContext)
void THandleRMessage2Error::DoL()
{
CConnLegacyRMessage2Activity* act = static_cast<CConnLegacyRMessage2Activity*>(iContext.Activity());
ASSERT(act->Message().IsTypeOf(Meta::STypeId::CreateSTypeId(TCFSigLegacyRMessage2Ext::EUid, TCFSigLegacyRMessage2Ext::ETypeId)));
TInt error = static_cast<TCFSigLegacyRMessage2Ext&>(act->Message()).CheckError(iContext, act->Error());
act->SetError(error);
act->Complete(error);
}
DEFINE_SMELEMENT(TCancelAllLegacyRMessage2Activities, NetStateMachine::MStateTransition, TContext)
void TCancelAllLegacyRMessage2Activities::DoL()
{
const RPointerArray<CNodeActivityBase>& activities = iContext.Node().Activities();
for (TInt i = 0; i < activities.Count(); i++)
{
if (activities[i]->ActivitySigId() == ESock::ECFActivityConnectionLegacyRMessage2Handler)
{
activities[i]->Cancel(iContext);
}
}
}