linklayerprotocols/tunnelnif/src/tunnelFlow.cpp
changeset 0 af10295192d8
--- /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 <es_mbuf.h>
+//#include <flogger.h>
+
+#include <agenterrors.h>
+
+//#include "TunnelNifVar.h"
+#include "tunnelFlow.h"
+#include "tunnelBinders.h"
+#include "tunnelProvision.h"
+#include <comms-infras/linkmessages.h>
+#include <comms-infras/ss_metaconnprov.h>					// for SAccessPointConfig
+#include <comms-infras/commsdebugutility.h>
+#include <elements/nm_messages_base.h>
+#include <elements/nm_messages_child.h>
+
+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<TEBase::TError>())
+		{
+		}
+	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<TCFDataClient::TStop&>(aMessage).iValue);
+			break;
+		case TCFDataClient::TBindTo::EId:
+            {
+			TCFDataClient::TBindTo& bindToReq = message_cast<TCFDataClient::TBindTo>(aMessage);
+			if (!bindToReq.iNodeId.IsNull())
+				{
+				User::Leave(KErrNotSupported);
+				}
+			RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef());
+            }
+			break;
+		case TCFDataClient::TProvisionConfig::EId:
+			ProvisionConfig(static_cast<TCFDataClient::TProvisionConfig&>(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<TTunnelAgentMessage::TTunnelSetAddress&>(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<const TTunnelProvision*>(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);
+	}
+