diff -r 000000000000 -r af10295192d8 networkcontrol/ipnetworklayer/src/IPProtoCprStates.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkcontrol/ipnetworklayer/src/IPProtoCprStates.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,317 @@ +// Copyright (c) 2006-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: +// IPProto Connection Provider implementation +// +// + +/** + @file + @internalComponent +*/ + +#include +#include + +#include +#include // for ioctl ipc + +#include "IPProtoCprStates.h" +#include "IPProtoMessages.h" +#include "linkcprextensionapi.h" +#include +#include +#include // KLinkLayerOpen +#include +#include +#include +#include +#include + +using namespace Messages; +using namespace MeshMachine; +using namespace IpProtoCpr; +using namespace ESock; + +DEFINE_SMELEMENT(TStoreProvision, NetStateMachine::MStateTransition, IpProtoCpr::TContext) +void TStoreProvision::DoL() + { + PRStates::TStoreProvision storeProvision(iContext); + storeProvision.DoL(); + + CIPProtoConnectionProvider& node = iContext.Node(); + + // Retrieve the idle timer values from the provisioning information bucket + const Meta::SMetaData* extension = + node.AccessPointConfig().FindExtension(STypeId::CreateSTypeId(TIdleTimerValues::iUid, TIdleTimerValues::iId)); + + if (extension) + { + const TIdleTimerValues* vals = static_cast(extension); + node.SetTimers(vals->iShortTimer, vals->iMediumTimer, vals->iLongTimer); + } + + if (!node.iNodeLocalExtensionsCreated) + { + node.iNodeLocalExtensions.Open(); + + TPacketActivity* packetActivity = new(ELeave)TPacketActivity(&iContext.Node().iPeriodActivity); + CleanupStack::PushL(packetActivity); + node.iNodeLocalExtensions.AppendExtensionL(packetActivity); + CleanupStack::Pop(packetActivity); + + // Allocate and add the data monitoring shared memory pointers to the provisioning info + TDataMonitoringConnProvisioningInfo* connProvisioningInfo = new (ELeave) TDataMonitoringConnProvisioningInfo(&node.iDataVolumes, &node.iThresholds); + CleanupStack::PushL(connProvisioningInfo); + node.iNodeLocalExtensions.AppendExtensionL(connProvisioningInfo); + CleanupStack::Pop(connProvisioningInfo); + + // Allocate the data monitoring subconnection data structure. + // + // This used to be allocated in the SCPR, but it has been moved here to the CPR. This is because there can be + // temporary circumstances where there is more than one SCPR present - one or more of these in a leaving + // state and one in an active state. The access point config cannot presently hold provisioning information + // specific to an SCPR instance, so it is allocated and managed here in the CPR as a shared entity. Only + // one SCPR instance should be using this at a time, however. + TDataMonitoringSubConnProvisioningInfo* subConnProvisioningInfo = new (ELeave) TDataMonitoringSubConnProvisioningInfo(NULL, NULL); + CleanupStack::PushL(subConnProvisioningInfo); + node.iNodeLocalExtensions.AppendExtensionL(subConnProvisioningInfo); + CleanupStack::Pop(subConnProvisioningInfo); + + // The CLinkCprExtensionApi may have been added previously if this is a reconnect scenario + // We add it again in this new override of the extensions, if the old container is fully superceded + // it will be closed and destroyed. + extension = CLinkCprExtensionApi::NewLC(iContext.Node()); + node.iNodeLocalExtensions.AppendExtensionL(extension); + CleanupStack::Pop(); // CLinkCprExtensionApi + + node.iNodeLocalExtensionsCreated = ETrue; + } + + RMetaExtensionContainer mec; + mec.Open(iContext.Node().AccessPointConfig()); + CleanupClosePushL(mec); + mec.AppendContainerL(node.iNodeLocalExtensions); + + iContext.Node().iAccessPointConfig.Close(); + iContext.Node().iAccessPointConfig.Open(mec); + CleanupStack::PopAndDestroy(&mec); + + // For the case that this is an update of the provisioned info we forward it to non-leaving data clients + TClientIter iter = iContext.Node().GetClientIter( + TClientType(TCFClientType::EData), + TClientType(0, TClientType::ELeaving) + ); + + for (TInt i = 0; iter[i]; i++) + { + iter[i]->PostMessage( + iContext.NodeId(), + TCFDataClient::TProvisionConfig(iContext.Node().iAccessPointConfig).CRef() + ); + } + } + +DEFINE_SMELEMENT(TAwaitingDataMonitoringNotification, NetStateMachine::MState, IpProtoCpr::TContext) +TBool TAwaitingDataMonitoringNotification::Accept() + { + return iContext.iMessage.IsMessage(); + } + + +DEFINE_SMELEMENT( TAwaitingGoneDown , NetStateMachine::MState, IpProtoCpr::TContext) +TBool TAwaitingGoneDown::Accept() + { + if (iContext.iMessage.IsMessage()) + { + iContext.Node().LinkDown(); + } + // return EFalse to allow further PRActivities processing + return EFalse; + } + + +DEFINE_SMELEMENT(TProcessDataMonitoringNotification, NetStateMachine::MStateTransition, IpProtoCpr::TContext) +void TProcessDataMonitoringNotification::DoL() + { + TCFDataMonitoringNotification::TDataMonitoringNotification& msg = + message_cast(iContext.iMessage); + + iContext.Node().DataNotificationL(msg); + } + +DEFINE_SMELEMENT(TAwaitingStart, NetStateMachine::MState, IpProtoCpr::TContext) +TBool TAwaitingStart::Accept() + { + CoreNetStates::TAwaitingStart state(iContext); + if (state.Accept()) + { + iContext.Node().DisableTimers(); + return ETrue; + } + return EFalse; + } + +DEFINE_SMELEMENT(TCleanupStart, NetStateMachine::MStateTransition, IpProtoCpr::TContext) +void TCleanupStart::DoL() + { + //Re-enable idle timers disabled by IpProtoCpr::TAwaitingStart + iContext.Node().EnableTimers(); + } + +DEFINE_SMELEMENT(TCheckIfLastControlClientLeaving, NetStateMachine::MStateTransition, IpProtoCpr::TContext) +void TCheckIfLastControlClientLeaving::DoL() + { + CIPProtoConnectionProvider& node = iContext.Node(); + node.ForceCheckShortTimerMode(); + } + +DEFINE_SMELEMENT(TAwaitingOpenCloseRoute, NetStateMachine::MState, IpProtoCpr::TContext) +TBool TAwaitingOpenCloseRoute::Accept() + { + return (iContext.iMessage.IsMessage()); + } + +DEFINE_SMELEMENT(TDoOpenCloseRoute, NetStateMachine::MStateTransition, IpProtoCpr::TContext) +void TDoOpenCloseRoute::DoL() + { + TCFIPProtoMessage::TOpenCloseRoute& msg = message_cast(iContext.iMessage); + if (msg.iValue) + iContext.Node().OpenRoute(); + else + iContext.Node().CloseRoute(); + } + + + + + +DEFINE_SMELEMENT(TLinkUp, NetStateMachine::MStateTransition, IpProtoCpr::TContext) +void TLinkUp::DoL() + { + iContext.Node().LinkUp(); + } + +DEFINE_SMELEMENT(TLinkDown, NetStateMachine::MStateTransition, IpProtoCpr::TContext) +void TLinkDown::DoL() + { + iContext.Node().LinkDown(); + } + +DEFINE_SMELEMENT(TStoreAndFilterDeprecatedAndForwardStateChange, NetStateMachine::MStateTransition, IpProtoCpr::TContext) +void TStoreAndFilterDeprecatedAndForwardStateChange::DoL() + { + TCFMessage::TStateChange& msg = message_cast(iContext.iMessage); + //Forward to control clients if there are any + + ESOCK_EXTLOG_VAR( (KESockConnectionTag, KIPProtoCprSubTag, _L8("CIPProtoConnectionProvider %x TStateChange\tProgress: %d, Error: %d"), &iContext.Node(), msg.iStateChange.iStage, msg.iStateChange.iError) ); + + //We are the only node accessing this CLinkCprExtensionApi interface so we can do it safely here. + //This is rather an exceptional situation, please keep the const_cast. + const CLinkCprExtensionApi* linkCPR = static_cast(iContext.Node().AccessPointConfig().FindExtension(CLinkCprExtensionApi::TypeId())); + const_cast(linkCPR)->SetLastProgress(msg.iStateChange); + + if ((KLinkLayerOpen != msg.iStateChange.iStage) && (KLinkLayerClosed != msg.iStateChange.iStage) ) + { + //KLinkLayerOpen is now redundant with TCFControlClient::TGoneUp & TCFServiceProvider::TStarted + //KLinkLayerClosed is now redundant with TCFControlClient::TGoneDown & TCFServiceProvider::TStopped + //They have therefore been deprecated. Stack nodes are requested not to send the deprecated + //signals anymore. If stack nodes do send the deprecated signals, the signals will be eaten here + //because they confuse convergence and mobility layers, which may live just above. + TInt ctrlClientCount = iContext.Node().PostToClients(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.iMessage, TClientType(TCFClientType::ECtrl)); + if (0==ctrlClientCount) + { //If there are no control clients any more, forward to the control provider + iContext.Node().PostToClients(TNodeCtxId(iContext.ActivityId(), iContext.NodeId()), iContext.iMessage, TClientType(TCFClientType::ECtrlProvider)); + } + } + } + +DEFINE_SMELEMENT(TSendStopToSelf, NetStateMachine::MStateTransition, TContext) +void TSendStopToSelf::DoL() + { + iContext.iNodeActivity->PostRequestTo(iContext.NodeId(), + TCFServiceProvider::TStop(iContext.iNodeActivity->Error()).CRef()); + } + + +DEFINE_SMELEMENT(TSendStarted, NetStateMachine::MStateTransition, TContext) +void TSendStarted::DoL() + { + //Set the idle timers + iContext.Node().EnableTimers(); + iContext.Node().SetUsageProfile(KConnProfileMedium); + iContext.Node().SetTimerMode(CIPProtoConnectionProvider::ETimerMedium); + + CoreNetStates::TSendStarted transition(iContext); + transition.DoL(); + } + +DEFINE_SMELEMENT(IpProtoCpr::TProcessDataClientStatusChange, NetStateMachine::MStateTransition, IpProtoCpr::TContext) +void IpProtoCpr::TProcessDataClientStatusChange::DoL() + { + TCFControlProvider::TDataClientStatusChange& msg = message_cast(iContext.iMessage); + + if(msg.iValue == TCFControlProvider::TDataClientStatusChange::EStarted) + { + iContext.iPeer->SetFlags(TCFClientType::EStarted); + } + else + { + iContext.iPeer->ClearFlags(TCFClientType::EStarted); + } + + if(!msg.iValue && !iContext.Node().iSubConnEventDataSent) + { // We're only interested in the provider being stopped. + ADataMonitoringProtocolReq* dmInterface = NULL; + iContext.Node().ReturnInterfacePtrL(dmInterface); + + ADataMonitoringProvider* dmProvider = static_cast(dmInterface); + + ASSERT(dmProvider); // Must always support this interface + + TCFMessage::TSubConnDataTransferred wholeConnMsg(KNifEMCompatibilityLayerEntireSubConnectionUid, dmProvider->DataVolumesPtr()->iSentBytes, dmProvider->DataVolumesPtr()->iReceivedBytes); + TCFMessage::TSubConnDataTransferred defaultSubConnMsg(KNifEMCompatibilityLayerFakeSubConnectionId, dmProvider->DataVolumesPtr()->iSentBytes, dmProvider->DataVolumesPtr()->iReceivedBytes); + + RNodeInterface* ctrlClient = iContext.Node().GetFirstClient(TClientType(TCFClientType::ECtrl)); + if(ctrlClient) + { // Can't send this if the client's gone + ctrlClient->PostMessage(iContext.NodeId(), wholeConnMsg); + ctrlClient->PostMessage(iContext.NodeId(), defaultSubConnMsg); + + iContext.Node().iSubConnEventDataSent = ETrue; + } + } + } + +DEFINE_SMELEMENT(TAwaitingIoctlMessage, NetStateMachine::MState, IpProtoCpr::TContext) +TBool TAwaitingIoctlMessage::Accept() + { + if (iContext.iMessage.IsTypeOf(Meta::STypeId::CreateSTypeId(TCFSigLegacyRMessage2Ext::EUid, TCFSigLegacyRMessage2Ext::ETypeId))) + { + TCFSigLegacyRMessage2Ext& msg = static_cast(iContext.iMessage); + if (msg.iMessage.Function() == ECNIoctl) + { + return ETrue; + } + } + return EFalse; + } + +DEFINE_SMELEMENT(TForwardToDefaultDataClient, NetStateMachine::MStateTransition, IpProtoCpr::TContext) +void TForwardToDefaultDataClient::DoL() + { + ASSERT(iContext.iMessage.IsTypeOf(Meta::STypeId::CreateSTypeId(TCFSigLegacyRMessage2Ext::EUid, TCFSigLegacyRMessage2Ext::ETypeId))); + + RNodeInterface* dc = iContext.Node().GetFirstClient(TClientType(TCFClientType::EData)); + iContext.Activity()->PostRequestTo(*dc, iContext.iMessage); + }