--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocols/tcpipv4v6prt/src/loop6.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,204 @@
+// Copyright (c) 2004-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:
+// loop6.cpp - loopback interface for IPv6
+//
+
+#include "in_fmly.h"
+#include "loop6.h"
+#include <in6_if.h> // KSoIf*
+#include "networkinfo.h"
+
+CIfLoop6::CIfLoop6()
+{
+ __DECLARE_NAME(_S("CIfLoop6"));
+}
+
+void CIfLoop6::ConstructL(const TDesC& aTag)
+{
+ iIfaceName = aTag.AllocL();
+ iIfaceMTU = 4096;
+
+ TCallBack scb(SendCallBack, this);
+ iSendCallBack = new(ELeave) CAsyncCallBack(scb, KInet6DefaultPriority);
+
+ TCallBack rcb(RecvCallBack, this);
+ iRecvCallBack = new(ELeave) CAsyncCallBack(rcb, KInet6DefaultPriority);
+}
+
+CIfLoop6::~CIfLoop6()
+{
+ iRecvQ.Free();
+ iSendQ.Free();
+
+ delete iRecvCallBack;
+ delete iSendCallBack;
+ delete iIfaceName;
+}
+
+CIfLoop6* CIfLoop6::NewL(const TDesC& aTag)
+{
+ CIfLoop6* p = new(ELeave) CIfLoop6;
+
+ CleanupStack::PushL(p);
+ p->ConstructL(aTag);
+ CleanupStack::Pop();
+
+ return p;
+}
+
+void CIfLoop6::BindL(TAny* aId)
+{
+ iNetwork = (CProtocolBase*)aId;
+ iNetwork->StartSending((CProtocolBase *)this);
+}
+
+TInt CIfLoop6::State()
+{
+ return EIfUp;
+}
+
+TInt CIfLoop6::Control(TUint aLevel, TUint aName, TDes8& aOption, TAny*)
+ {
+ if (aLevel == KSOLInterface)
+ {
+ switch (aName)
+ {
+ case KSoIfInfo6:
+ {
+ __ASSERT_DEBUG(STATIC_CAST(TUint, aOption.MaxLength()) >= sizeof (TSoIfInfo6), User::Panic(_L("LOOP6"), 0));
+
+ if (STATIC_CAST(TUint, aOption.MaxLength()) < sizeof (TSoIfInfo6))
+ return KErrArgument;
+
+ TSoIfInfo6& opt = *(TSoIfInfo6*)aOption.Ptr();
+ opt.iRMtu = iIfaceMTU;
+ }
+ // FALL THROUGH AS TSoIfInfo6 IS AN EXTENSION OF TSoIfInfo
+
+ case KSoIfInfo:
+ {
+ __ASSERT_DEBUG(STATIC_CAST(TUint, aOption.MaxLength()) >= sizeof (TSoIfInfo), User::Panic(_L("LOOP6"), 0));
+
+ if (STATIC_CAST(TUint, aOption.MaxLength()) < sizeof (TSoIfInfo))
+ return KErrArgument;
+
+ TSoIfInfo& opt = *(TSoIfInfo*)aOption.Ptr();
+
+ opt.iFeatures = KIfIsLoopback | KIfCanMulticast;
+ opt.iMtu = iIfaceMTU;
+ opt.iSpeedMetric = 30000;
+ opt.iName = *iIfaceName;
+
+ return KErrNone;
+ }
+
+
+ case KSoIfConfig:
+ // PS: If KSoIfConfig returns KErrNotSupported, Update6 does not proceed
+ // with setting routes, etc.
+ {
+ TSoInet6IfConfig& cfg = *(TSoInet6IfConfig*)aOption.Ptr();
+ if (!iIfaceName->Compare(_L("loop6")) && cfg.iFamily == KAfInet6)
+ {
+
+ TSockAddr unspec(KAFUnspec);
+ cfg.iLocalId = unspec;
+ cfg.iRemoteId = unspec;
+ return KErrNone;
+ }
+ }
+ break;
+ case KSoIfGetConnectionInfo:
+ {
+ if (STATIC_CAST(TUint, aOption.MaxLength()) < sizeof(TSoIfConnectionInfo))
+ return KErrArgument;
+ TSoIfConnectionInfo &opt = *(TSoIfConnectionInfo *)aOption.Ptr();
+ opt.iIAPId = 0;
+ opt.iNetworkId = 0;
+ return KErrNone;
+ }
+
+ default:
+ break;
+ }
+ }
+ return KErrNotSupported;
+}
+
+void CIfLoop6::Info(TNifIfInfo& aInfo) const
+{
+ aInfo.iVersion = TVersion(KInet6MajorVersionNumber, KInet6MinorVersionNumber, KInet6BuildVersionNumber);
+ aInfo.iFlags = KNifIfIsBase | KNifIfCreatedAlone;
+ aInfo.iName = *iIfaceName;
+ aInfo.iProtocolSupported = KProtocolInet6Ip;
+}
+
+TInt CIfLoop6::Send(RMBufChain &aPacket, TAny*)
+{
+ iSendQ.Append(aPacket);
+ iSendCallBack->CallBack();
+
+ return 1;
+}
+
+TInt CIfLoop6::RecvCallBack(TAny* aCProtocol)
+{
+ ((CIfLoop6*)aCProtocol)->DoProcess();
+
+ return 0;
+}
+
+TInt CIfLoop6::SendCallBack(TAny* aCProtocol)
+{
+ ((CIfLoop6*)aCProtocol)->DoSend();
+
+ return 0;
+}
+
+void CIfLoop6::DoSend()
+{
+ RMBufPacket send;
+ RMBufPacket recv;
+
+ while (iSendQ.Remove(send))
+ {
+ send.Unpack();
+ Loop(send, recv);
+ iRecvQ.Append(recv);
+ iRecvCallBack->CallBack();
+ send.Free();
+ }
+}
+
+void CIfLoop6::DoProcess()
+{
+ RMBufPacket packet;
+
+ while (iRecvQ.Remove(packet))
+ {
+ iNetwork->Process(packet, (CProtocolBase*)this);
+ }
+}
+
+void CIfLoop6::Loop(RMBufPacket& aSend, RMBufPacket& aRecv)
+{
+ RMBufPktInfo* info = aSend.Info();
+
+ info->iProtocol = KProtocolInet6Loop;
+
+ aSend.SetInfo(NULL);
+ aRecv.Assign(aSend);
+ aRecv.SetInfo(info);
+ aRecv.Pack();
+}