diff -r 000000000000 -r af10295192d8 linklayerprotocols/tunnelnif/src/tunnelFlow.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linklayerprotocols/tunnelnif/src/tunnelFlow.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,370 @@ +// Copyright (c) 2002-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: +// tunnelnif.cpp +// +// + +#include +//#include + +#include + +//#include "TunnelNifVar.h" +#include "tunnelFlow.h" +#include "tunnelBinders.h" +#include "tunnelProvision.h" +#include +#include // for SAccessPointConfig +#include +#include +#include + +using namespace Messages; +using namespace MeshMachine; +using namespace ESock; + +/* + * This sections defines a whole load of constants etc... not very exciting + */ +#if defined (_DEBUG) + #define LOG(a) a +#else + #define LOG(a) +#endif + +_LIT8(KDescIp6, "ip6"); +_LIT8(KDescIp, "ip"); + +// Note: The "tunnel" logging string has been repeated here but should be unified throughout +// the Tunnel CFProtocol. The main logging relies on 16-bit RFileLogger calls whereas the +// CFNode logging requires an 8-bit string. An attempt to make everything 8-bit resulted +// in undefined RFileLogger symbols. +#ifdef SYMBIAN_TRACE_ENABLE +_LIT8(KTunnel, "tunnel"); +#endif + +/* + * The Link class + */ + +CTunnelFlow::CTunnelFlow(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf) + : CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf) +/** +Constructor. + +@param aFactory Reference to the factory which created this object. +@param aSubConnId Id of SubConnection Provider - for sending messages to it. +@param aProtocolIntf Protocol Interface corresponding to the Flow. +*/ + { + LOG_NODE_CREATE(KTunnel, CTunnelFlow); + } + +CTunnelFlow::~CTunnelFlow() + { + LOG_NODE_DESTROY(KTunnel, CTunnelFlow); + } + +TInt CTunnelFlow::Notification(TTunnelAgentMessage::TTunnelSetAddress& aMessage) + { + if (iNifIf4) + { + return iNifIf4->Notification(aMessage); + } + if (iNifIf6) + { + return iNifIf6->Notification(aMessage); + } + return KErrNotSupported; + } + + +// ===================================================================================== +// CSubConnectionFlowBase +// ===================================================================================== + +MFlowBinderControl* CTunnelFlow::DoGetBinderControlL() + { + return this; + } + +// ===================================================================================== +// MFlowBinderControl methods +// ===================================================================================== + +MLowerControl* CTunnelFlow::GetControlL(const TDesC8& aProtocol) + { + + if (aProtocol.CompareF(KDescIp6) == 0) + { + if ( iNifIf6 ) + { + CTunnelNcpLog::Printf(_L("CTunnelFlow:\tGetControlL already bound to %S"), &aProtocol); + User::Leave(KErrInUse); + return NULL; + } + iNifIf6 = CTunnelNcp6::ConstructL(*this); + return iNifIf6; + } + else if (aProtocol.CompareF(KDescIp) == 0) + { + if ( iNifIf4 ) + { + CTunnelNcpLog::Printf(_L("CTunnelFlow:\tGetControlL already bound to %S"), &aProtocol); + User::Leave(KErrInUse); + return NULL; + } + iNifIf4 = CTunnelNcp4::ConstructL(*this); + return iNifIf4; + } + Panic(ETunnelPanic_BadBind); + return NULL; + } + +MLowerDataSender* CTunnelFlow::BindL(const TDesC8& aProtocol, MUpperDataReceiver* aReceiver, MUpperControl* aControl) +/** + * Binds upper CFProtocol to this CFProtocol + * + * @param aUpperReceiver A pointer to Upper layer Receive class + * @param aUpperControl A pointer to Upper layer control class + */ + { + MLowerDataSender* lowerDataSender = NULL; + if (aProtocol.CompareF(KDescIp6) == 0) + { + ASSERT(iNifIf6); + lowerDataSender = iNifIf6->Bind(aReceiver, aControl); + } + else if (aProtocol.CompareF(KDescIp) == 0) + { + ASSERT(iNifIf4); + lowerDataSender = iNifIf4->Bind(aReceiver, aControl); + } + else + { + // GetControlL() should already have been called. + Panic(ETunnelPanic_BadBind); + } + + if (lowerDataSender) + { + iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TActive().CRef()); + } + + return lowerDataSender; + } + +void CTunnelFlow::Unbind(MUpperDataReceiver* aUpperReceiver, MUpperControl* aUpperControl) + { + if (iNifIf4 && iNifIf4->MatchesUpperControl(aUpperControl)) + { + iNifIf4->Unbind(aUpperReceiver, aUpperControl); + delete iNifIf4; + iNifIf4 = NULL; + } + else + if (iNifIf6 && iNifIf6->MatchesUpperControl(aUpperControl)) + { + iNifIf6->Unbind(aUpperReceiver, aUpperControl); + delete iNifIf6; + iNifIf6 = NULL; + } + else + { + Panic(ETunnelPanic_BadUnbind); + } + MaybePostDataClientIdle(); + } + +CSubConnectionFlowBase* CTunnelFlow::Flow() +/** +Return the Flow corresponding to the MFlowBinderControl +*/ + { + return this; + } + +// ===================================================================================== +// Messages::ANode +// ===================================================================================== + +void CTunnelFlow::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage) + { + CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage); + + if (aMessage.IsMessage()) + { + } + else if (TEChild::ERealmId == aMessage.MessageId().Realm()) + { + switch (aMessage.MessageId().MessageId()) + { + case TEChild::TDestroy::EId : + Destroy(); + break; + default: +//TODO - logging + ASSERT(EFalse); + } + } + else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm()) + { + switch (aMessage.MessageId().MessageId()) + { + case TCFDataClient::TStart::EId : + StartFlowL(); + break; + case TCFDataClient::TStop::EId : + StopFlow(static_cast(aMessage).iValue); + break; + case TCFDataClient::TBindTo::EId: + { + TCFDataClient::TBindTo& bindToReq = message_cast(aMessage); + if (!bindToReq.iNodeId.IsNull()) + { + User::Leave(KErrNotSupported); + } + RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef()); + } + break; + case TCFDataClient::TProvisionConfig::EId: + ProvisionConfig(static_cast(aMessage).iConfig); + break; + default: +//TODO - logging + ASSERT(EFalse); + } + } + else if (TTunnelAgentMessage::ERealmId == aMessage.MessageId().Realm()) + { + switch (aMessage.MessageId().MessageId()) + { + case TTunnelAgentMessage::TTunnelSetAddress::EId: + { + Notification(static_cast(aMessage)); + break; + } + default: + Panic(ETunnelPanic_UnexpectedMessage); + } + } + else // realm is not TCFMessage or TTunnelAgentMessage + { + Panic(ETunnelPanic_UnexpectedMessage); + } + } + +// ===================================================================================== +// +// Methods for handling incoming SCPR messages +// + +void CTunnelFlow::StartFlowL() + { + // NOTE: according to the NAF docs the sequence should really be StartSending(), then LinkLayerUp() then Progress() + // for DNS to work. However, this tunnel NIF doesn't support DNS. + // + CTunnelNcpLog::Write(_L("CTunnelFlow:\tStartFlow()")); + + // Process any errors that may have occurred during processing of the ProvisionConfig message earlier. + // ProvisionConfig has no response, so error the StartFlow here. + User::LeaveIfError(iSavedError); + + + PostDataClientStartedMessage(); + if (iNifIf4) + { + iNifIf4->StartSending(); + } + if (iNifIf6) + { + iNifIf6->StartSending(); + } + iMMState = EStarted; + } + +void CTunnelFlow::StopFlow(TInt aError) + { + CTunnelNcpLog::Printf(_L("CTunnelFlow:\tStop(aError %d)"), aError); + + PostFlowDownMessage(aError); + } + +void CTunnelFlow::MaybePostDataClientIdle() + { + if (iNifIf4 == NULL && iNifIf4 == NULL) + { + iSubConnectionProvider.RNodeInterface::PostMessage(Id(), TCFControlProvider::TIdle().CRef()); + } + } +/* +Provisioning description for Tunnel CFProtocol Flow: + +- on receipt of the TProvisionConfig message, the provisioning information contained within + the AccessPointConfig array is validated: + - TTunnelProvision must be present. It is added by the Tunnel MCPr and populated from CommsDat. A pointer to it + is stored in iProvisionInfo. If missing, TError(TCFDataClient::TStart, KErrCorrupt) message is signalled back + to the SCPr on the next StartFlow message (ProvisionConfig has no response message). +*/ + + +void CTunnelFlow::ProvisionConfig(const ESock::RMetaExtensionContainerC& aConfigData) +/** +Handle ProvisionConfig message from SCPR. +*/ + { + iSavedError = KErrNone; + CTunnelNcpLog::Printf(_L("CTunnelFlow:\tProvisionConfig message received")); + + AccessPointConfig().Close(); + AccessPointConfig().Open(aConfigData); + + const TTunnelProvision* provision = static_cast(AccessPointConfig().FindExtension( + STypeId::CreateSTypeId(TTunnelProvision::EUid, TTunnelProvision::ETypeId))); + if (provision == NULL) + { + CTunnelNcpLog::Printf(_L("CTunnelFlow:\tProcessProvisionConfigL() - no Tunnel configuration")); + iSavedError = KErrCorrupt; + } + + ASSERT(iProvisionInfo == NULL); + iProvisionInfo = &provision->iInfo; + ASSERT(iProvisionInfo); + } + +void CTunnelFlow::Destroy() +/** +Handle Destroy message from SCPR. +*/ + { + ASSERT(iNifIf4 == NULL); // must not still be bound from above before being destroyed + ASSERT(iNifIf6 == NULL); + DeleteThisFlow(); + } + +// +// Utility functions +// + +void CTunnelFlow::PostProgressMessage(TInt aStage, TInt aError) + { + iSubConnectionProvider.RNodeInterface::PostMessage(Id(), TCFMessage::TStateChange(Elements::TStateChange(aStage, aError)).CRef()); + } + +void Panic(TTunnelPanic aPanic) + { + _LIT(KTunnelPanicTag, "Tunnel"); + User::Panic(KTunnelPanicTag, aPanic); + } +