networkprotocols/tcpipv4v6prt/src/in_net.cpp
changeset 0 af10295192d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocols/tcpipv4v6prt/src/in_net.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,270 @@
+// 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:
+// in_net.cpp - network layer protocol
+//
+
+#include "in6_if.h"
+#include "inet.h"
+#include "in_net.h"
+#include "tcpip_ini.h"
+#include "inet6log.h"
+
+void CProtocolInet6Network::StartL()
+	{
+	CProtocolInet6Base::StartL();
+	//
+	// Get the default value for the provider receive queue limiter
+	// (use the protocol name as section name)
+	TServerProtocolDesc info;
+	Identify(&info);
+	TInt value;
+	if (iNetwork->Interfacer()->FindVar(info.iName, TCPIP_INI_RECV_BUF, value))
+		iQueueLimit = value;
+	else
+		iQueueLimit = KNetDefaultRecvBuf;
+	}
+
+
+CProtocolInet6Network::~CProtocolInet6Network()
+	{
+	}
+
+//
+//	CProtocolInet6Network::Deliver
+//	******************************
+//	Generate a copy of the packet to every bound provider
+//
+void CProtocolInet6Network::Deliver(/*const*/ RMBufPacketBase &aPacket)
+	// .. cannot use "const", because CopyInfoL is not const! -- msa */
+	{
+	CProviderInet6Network* provider;
+	TInet6SAPIter iter(this);
+
+	const RMBufPktInfo *const info = aPacket.Info();
+	while (provider = (CProviderInet6Network *)iter++, provider != NULL)
+		{
+		if (provider->IsReceiving(*info))
+			{
+			RMBufRecvPacket copy;
+			TRAPD(err, aPacket.CopyL(copy);aPacket.CopyInfoL(copy));
+			if (err == KErrNone)
+				{
+				copy.Pack();
+				provider->Process(copy);
+				}
+			else
+				copy.Free();
+			}
+		}
+	}
+
+//
+// Shared provider methods (defaults)
+//
+CProviderInet6Network::~CProviderInet6Network()
+	{
+	iProtocol->UnbindProvider(this);
+	iRecvQ.Free();
+	}
+
+
+void CProviderInet6Network::InitL()
+	{
+	//
+	// Set initial value for the iQueueLimit
+	//
+	iQueueLimit = ((CProtocolInet6Network*)iProtocol)->QueueLimit();
+	CProviderInet6Base::InitL();
+	iProtocol->UnbindProvider(this);
+	iProtocol->BindProvider(this);
+	}
+
+TInt CProviderInet6Network::SetLocalName(TSockAddr &aAddr)
+	{
+	iProtocol->UnbindProvider(this);
+	// Note: a non-zero port in aAddr is significant!
+	iFlow.SetLocalAddr(aAddr);
+	iProtocol->BindProvider(this);
+	return 0;
+	}
+
+void CProviderInet6Network::AutoBind()
+	{
+	// TInetAddr() is assumed to be KAFUnspec & port=0
+	iFlow.SetLocalAddr(TInetAddr());
+	}
+
+
+void CProviderInet6Network::Shutdown(TCloseType aOption)
+	{
+	
+	switch(aOption)
+		{
+		case EStopInput:
+			iInputStopped = 1;
+			iProtocol->UnbindProvider(this);	// We don't need any incoming data
+			iRecvQ.Free();
+			iSocket->Error(KErrNone,MSocketNotify::EErrorClose); // Complete KErrNone
+//			Nif::SetSocketState(ENifSocketConnected, this); // Reset CSocket state to ESStateConnected
+			break;
+
+		case EStopOutput:
+			iSocket->Error(KErrNone,MSocketNotify::EErrorClose); // Complete KErrNone
+//			Nif::SetSocketState(ENifSocketConnected, this); // Reset CSocket state to ESStateConnected
+			break;
+
+		default:
+	        iProtocol->UnbindProvider(this);
+	        if (aOption!=EImmediate)
+				iSocket->CanClose();
+		}
+	}
+
+//
+// CProviderInet6Network::Process()
+// ********************************
+//	Process incoming data from the protocol object.
+//
+void CProviderInet6Network::Process(RMBufChain& aPacket, CProtocolBase * /*aSourceProtocol*/)
+	{
+	// iInputStopped is set at ShutDown() and no packets should be coming
+	// from the protocol after that. However, without knowing the exact
+	// details of the process model/threads, it could be possible that
+	// a Process() call has been initiated by the protocol and interrupted
+	// before the shutdown, thus there may be a need for this iInputStopped
+	// flag, although I would prefer to do without... NEED TO VERIFY IF
+	// iInputStopped is really needed!!! -- msa
+	//
+	if(!(iInputStopped ||
+		(iErrorMask & (MSocketNotify::EErrorFatal|MSocketNotify::EErrorConnect|MSocketNotify::EErrorRecv))))
+		{
+		iQueueLimit -= RMBufPacketBase::PeekInfoInChain(aPacket)->iLength;
+		iRecvQ.Append(aPacket);
+		LOG(Log::Printf(_L("\t%S SAP[%u] Packet Queued, calling NewData(1), limit=%d"), &ProtocolName(), (TInt)this, iQueueLimit));
+		iSocket->NewData(1);
+		}
+	else
+		{
+		LOG(Log::Printf(_L("\t%S SAP[%u] Packet Dropped"), &ProtocolName(), (TInt)this));
+		aPacket.Free();
+		}
+	}
+
+// CProviderInet6Network::IsReceiving
+// **********************************
+//
+TBool CProviderInet6Network::IsReceiving(const RMBufPktInfo &aInfo)
+	{
+	if (!HasNetworkServices() && (aInfo.iFlags & KIpLoopbackPacket) == 0)
+		return FALSE;	// No network services and packet is external.
+	const TInt port = iFlow.FlowContext()->LocalPort();
+
+	if (iQueueLimit < 0)
+		{
+		// Receive Queue limit is full, cannot receive this packet
+		
+		LOG(Log::Printf(_L("\t%S SAP[%u] Not receiving packets, limit=%d"), &ProtocolName(), (TInt)this, iQueueLimit));
+		iPacketsDropped++;
+		return FALSE;
+		}
+	return port == 0 || port == aInfo.iProtocol;
+	}
+
+
+// CProviderInet6Network::GetData
+// ******************************
+
+TInt CProviderInet6Network::GetData(RMBufChain& aData, TUint aLength, TUint aOptions, TSockAddr* aAddr)
+	{
+	RMBufRecvPacket packet;
+	const RMBufRecvInfo *info;
+	if (!iRecvQ.Remove(packet))
+		{
+		LOG(Log::Printf(_L("GetData\t%S SAP[%u] No Data Available (0)"), &ProtocolName(), (TInt)this));
+		return 0;	// No Data Available
+		}
+
+	info = packet.Unpack();
+
+	if (aAddr != NULL)
+		*aAddr = info->iSrcAddr;
+
+#ifdef _LOG
+	TBuf<70> tmp(_L("NULL"));
+	if (aAddr)
+		TInetAddr::Cast(*aAddr).OutputWithScope(tmp);
+#endif
+	const TInt offset = ((aOptions & KIpHeaderIncluded) != 0 || iRawMode) ? 0 : info->iOffset;
+
+	if (aOptions & KSockReadPeek)
+		{
+		//
+		// Oops, peek needs to keep the original packet intact in the queue
+		//
+		TInt len = info->iLength - offset;
+		if (len > (TInt)aLength)
+			len = aLength;
+		TInt err = packet.Copy(aData, offset, len);
+		packet.Pack();
+		iRecvQ.Prepend(packet);
+		LOG(Log::Printf(_L("GetData\t%S SAP[%u] Peek len=%d err=%d from=%S, calling NewData(1)"), &ProtocolName(), (TInt)this, len, err, &tmp));
+		iSocket->NewData(1);
+		// Any failure to create the RMBufChain is signalled as KErrNoMBufs!
+		return err != KErrNone ? KErrNoMBufs : len;
+		}
+	iQueueLimit += info->iLength; // Allow more packets in..
+	packet.TrimStart(offset);
+	aData.Assign(packet);
+	if ((TUint)info->iLength > aLength)
+		aData.TrimEnd(aLength);
+	packet.Free();	// (Releases info block)
+	LOG(Log::Printf(_L("GetData\t%S SAP[%u] length=%d from=%S"), &ProtocolName(), (TInt)this, aLength, &tmp));
+	return aLength;
+	}
+
+void CProviderInet6Network::GetData(TDes8 &aDesc, TUint aOptions, TSockAddr *anAddr)
+	{
+	RMBufRecvPacket packet;
+	const RMBufRecvInfo *info;
+	if (!iRecvQ.Remove(packet))
+		Panic(EInet6Panic_NoData);
+
+	info = packet.Unpack();
+
+	const TInt offset = ((aOptions & KIpHeaderIncluded) != 0 || iRawMode) ? 0 : info->iOffset;
+	packet.CopyOut(aDesc, offset);
+
+	if (anAddr!=NULL)
+		*anAddr = info->iSrcAddr;
+
+#ifdef _LOG
+	TBuf<70> tmp(_L("NULL"));
+	if (anAddr)
+		TInetAddr::Cast(*anAddr).OutputWithScope(tmp);
+#endif
+
+	if (aOptions & KSockReadPeek)
+		{
+		packet.Pack();
+		iRecvQ.Prepend(packet);
+		LOG(Log::Printf(_L("GetData\t%S SAP[%u] peek aDesc = %d from %S, calling NewData(1)"), &ProtocolName(), (TInt)this, aDesc.Length(), &tmp));
+		iSocket->NewData(1);
+		}
+	else
+		{
+		iQueueLimit += info->iLength; // Allow more packets in..
+		packet.Free();
+		LOG(Log::Printf(_L("GetData\t%S SAP[%u] aDesc = %d from=%S"), &ProtocolName(), (TInt)this, aDesc.Length(), &tmp));
+		}
+	}