diff -r 000000000000 -r af10295192d8 networkprotocols/tcpipv4v6prt/src/loop6.cpp --- /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 // 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(); +}