--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkcontrol/ipnetworklayer/src/nif.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,473 @@
+// Copyright (c) 2005-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:
+// CNifIfBase and CProtocolBase shim layer functionality
+//
+//
+
+/**
+ @file nif.cpp
+*/
+
+#include <e32base.h>
+#include <networking/qos_if.h>
+#include <nifmbuf.h>
+#include <es_prot_internal.h>
+#include <comms-infras/ss_subconnflow.h>
+#include <comms-infras/ss_protflow.h>
+
+#include "in_sock.h"
+#include "in_iface.h"
+#include "in6_if.h"
+
+#include "flow.h"
+#include "nif.h"
+#include "notify.h"
+#include "panic.h"
+#include "ItfInfoConfigExt.h"
+
+#include "nif4.h" // for CIPShimIfBase::NewL()
+#include "nif6.h" // for CIPShimIfBase::NewL()
+
+#include "IPProtoDeMux.h"
+
+#include "../addressinfohook/inc/hookaddrinfo.h"
+
+
+using namespace ESock;
+
+//
+// CIPShimIfBase methods
+//
+
+CIPShimIfBase* CIPShimIfBase::NewL(const TDesC8& aProtocol, CIPShimProtocolIntf *aIntf)
+ {
+ CIPShimIfBase* intf = NULL;
+
+ if (aProtocol.CompareF(KProtocolIp()) == 0)
+ {
+ intf = CIPShimIfBase4::NewL(aProtocol);
+ }
+ else
+ if (aProtocol.CompareF(KProtocolIp6()) == 0)
+ {
+ intf = CIPShimIfBase6::NewL(aProtocol);
+ }
+ else
+ {
+ // only support "ip" and "ip6" protocol names
+ User::Leave(KErrArgument);
+ }
+ intf->SetProtocolIntf(aIntf);
+
+ return intf;
+ }
+
+
+CIPShimIfBase::CIPShimIfBase(const TDesC8& aProtocolName)
+ : CNifIfBase(), iBinderReady(EFalse), iProtIntf(NULL)
+/**
+CIPShimIfBase constructor
+*/
+ {
+ __CFLOG_2(KIPProtoTag1, KIPProtoTag2, _L8("CIPShimIfBase %08x:\tCIPShimIfBase(aProtocolName '%S')"), this, &aProtocolName);
+ iProtocolName.Copy(aProtocolName);
+ }
+
+CIPShimIfBase::~CIPShimIfBase()
+ {
+ __CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\t~CIPShimIfBase()"), this);
+ delete iShimNotify;
+
+ for (TInt i = 0; i < iProtoBinders.Count(); i++)
+ {
+ iProtoBinders[i]->Unbind();
+ }
+
+ iProtoBinders.Close();
+
+/* ASSERT(iProtIntf);
+ iProtIntf->NifDisappearing(this);*/
+
+ /*
+ * it's not legal to assume that this pointer isn't NULL. There can be
+ * OOM conditions in the constructor (which doesn't follow the official
+ * 2 way constructions [in nif4 or nif6]) which can cause not to initialize
+ * this pointer.
+ */
+ if (iProtIntf)
+ {
+ iProtIntf->NifDisappearing(this);
+ }
+ }
+
+void CIPShimIfBase::ConstructL()
+ {
+ iShimNotify = CIPShimNotify::NewL(this);
+ // Setup the CNifIfBase::iNotify for the benefit of the TCP/IP stack to call us
+ iNotify = static_cast<MNifIfNotify*>(iShimNotify);
+ }
+
+void CIPShimIfBase::StartL()
+ {
+ if (iUpperProtocol)
+ {
+ return;
+ }
+
+ TBuf<KMaxProtocolNameSize> protocolName;
+ protocolName.Copy(iProtocolName);
+ __CFLOG_2(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tStartL(): FindAndLoadProtocolL('%S')"), this, &protocolName);
+ iUpperProtocol = SocketServExt::FindAndLoadProtocolL(protocolName);
+ iUpperProtocol->Open();
+
+
+ // Retrieve the MNifIfUser derived object from the upper protocol
+
+ TNifIfUser ifuser;
+ TInt err = iUpperProtocol->GetOption(KNifOptLevel, KNifOptGetNifIfUser, ifuser, 0);
+
+ if (err == KErrNone)
+ {
+ iNifUser = ifuser();
+
+ // Inform the upper protocol of our CNifIfBase derived interface.
+ // (the second argument does not appear to be used in current SymbianOS, so pass 0).
+ __CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tStartL(): IfUserNewInterfaceL()"), this);
+
+ CleanupClosePushL(*iUpperProtocol);
+ iNifUser->IfUserNewInterfaceL(this, 0); // Note: increments CNifIfBase reference
+ CleanupStack::Pop();
+
+ // Cleanup Note: if you ever add a leaving function after IfUserNewInterfaceL() above,
+ // then you'll need to arrange for CleanupSignalNewInterface() to be called here (it is pushed
+ // onto the cleanup stack later as there are no subsequent leaving functions in this routine.
+
+ iNifUser->IfUserOpenNetworkLayer(); // Note: increments protocol reference count
+ }
+ else
+ {
+ __CFLOG_VAR((KIPProtoTag1, KIPProtoTag2, _L8("CIPShimIfBase %08x:\tStartL(): Error %d issuing KNifOptGetNifIfUser to protocol"), this, err));
+ User::Leave(err);
+ }
+ }
+
+void CIPShimIfBase::BindToL(CIPProtoBinder* aIPProtoBinder)
+ {
+ aIPProtoBinder->BindL(this);
+ iProtoBinders.AppendL(aIPProtoBinder);
+ }
+
+void CIPShimIfBase::UnbindFrom(CIPProtoBinder* aIPProtoBinder)
+ {
+ TInt index = iProtoBinders.Find(aIPProtoBinder);
+
+ // shouldn't try to unbind from a binder we're not bound to
+ ASSERT(index >= 0);
+ iProtoBinders.Remove(index);
+ aIPProtoBinder->Unbind();
+ }
+
+//-=========================================
+// MUpperDataReceiver methods
+//-=========================================
+void CIPShimIfBase::Process(RMBufChain& aData)
+ {
+ iUpperProtocol->Process(aData, reinterpret_cast<CProtocolBase*>(this));
+ }
+
+//-=========================================
+// MUpperControl methods
+//-=========================================
+void CIPShimIfBase::StartSending()
+ {
+ if (!iBinderReady)
+ {
+ // Get config info (for first time)
+ __CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tStartSending() (first time)"), this);
+ GetConfigFirstTime();
+ iBinderReady = ETrue;
+ }
+
+ if (iUpperProtocol)
+ {
+ // Call StartSending(...) in the context of "downstream path ready for first time"
+ __CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tStartSending()"), this);
+ iUpperProtocol->StartSending(reinterpret_cast<CProtocolBase*>(this));
+ }
+ }
+
+void CIPShimIfBase::Error(TInt anError)
+ {
+ iProtoBinders[0]->Error(anError);
+ }
+
+#ifdef _DEBUG
+void CIPShimIfBase::BindL(TAny* aId)
+#else
+void CIPShimIfBase::BindL(TAny* /*aId*/)
+#endif
+/**
+Called from upper protocol to pass its CProtocolBase pointer
+*/
+ {
+ //[401TODO] RZ: Is this assumption safe?
+ ASSERT(iUpperProtocol == aId);
+
+ if (iBinderReady && iUpperProtocol)
+ {
+ __CFLOG_2(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tBindL(%08x)"), this, aId);
+ iUpperProtocol->StartSending(reinterpret_cast<CProtocolBase*>(this));
+ }
+ }
+
+void CIPShimIfBase::CleanupInterface(TInt aError)
+ {
+ __CFLOG_2(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %x:\tCleanupInterface(%d)"), this, aError);
+ iUpperProtocol->Close();
+ iUpperProtocol = NULL;
+
+ if(iInterfaceNameRecorded && iProtoBinders.Count())
+ {
+ XInterfaceNames* itfNames = static_cast<XInterfaceNames*>(
+ const_cast<Meta::SMetaData*>(iProtoBinders[0]->Flow().AccessPointConfig().FindExtension(XInterfaceNames::TypeId())));
+ itfNames->RemoveInterfaceName(this);
+ }
+
+ // IfUserInterfaceDown may delete this object, so create a stack variable for the NifIfUser
+ // so CloseNetworkLayer can be called on it.
+ MNifIfUser* nifUser = iNifUser;
+ nifUser->IfUserInterfaceDown(aError, this); // Note: decrements CNifIfBase reference
+ nifUser->IfUserCloseNetworkLayer(); // Note: decrements protocol reference count
+ }
+
+void CIPShimIfBase::RemoveInterfaceName(CIPProtoBinder* aBinder)
+ {
+ ASSERT(aBinder);
+
+ if(iInterfaceNameRecorded)
+ {
+ XInterfaceNames* itfNames = static_cast<XInterfaceNames*>(
+ const_cast<Meta::SMetaData*>(aBinder->Flow().AccessPointConfig().FindExtension(XInterfaceNames::TypeId())));
+ itfNames->RemoveInterfaceName(this);
+ }
+ }
+
+
+void CIPShimIfBase::Release(TInt aError)
+ {
+ /* CleanupInterface will delete the interface when it is done if refcount is 0 (it will decrement it itself).
+ If iRefCount 0 when release is called, Start must never have been
+ called on this nif. */
+ if (iProtoBinders.Count())
+ {
+ return; //can't go away if we still have binders
+ }
+
+ if (iRefCount == 0)
+ {
+ delete this;
+ }
+ else
+ {
+ CleanupInterface(aError);
+ }
+ }
+
+TInt CIPShimIfBase::State()
+ {
+ return EIfDown;
+ }
+
+TInt CIPShimIfBase::ServiceHwAddrControl(TDes8& aOption)
+/**
+Service KSoIfHardwareAddr calls from upper protocol
+*/
+ {
+ ASSERT(aOption.Length() == sizeof(TSoIfHardwareAddr));
+ if (iProtoBinders.Count())
+ {
+ //[401TODO] RZ: we're probably need fixed array to avoid index changing
+ return iProtoBinders[0]->Control(KSOLInterface, KSoIfHardwareAddr, aOption);
+ }
+ else
+ {
+ __CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tServiceHwAddrControl(): no binders"), this);
+ return KErrNotReady;
+ }
+ }
+
+TInt CIPShimIfBase::ServiceConnInfo(TDes8& aOption)
+/**
+Service KSoIfGetConnectionInfo calls from upper protocol
+*/
+ {
+ ASSERT(aOption.Length() == sizeof(TSoIfConnectionInfo));
+ TUint8* ptr = const_cast<TUint8*>(aOption.Ptr());
+ TSoIfConnectionInfo& returnedInfo = reinterpret_cast<TSoIfConnectionInfo&>(*ptr);
+
+ returnedInfo.iIAPId = iConnectionInfo.iIapId;
+ returnedInfo.iNetworkId = iConnectionInfo.iNetId;
+
+ return KErrNone;
+ }
+
+TInt CIPShimIfBase::Control(TUint aLevel, TUint aName, TDes8& aOption, TAny* aSource)
+ {
+ __CFLOG_3(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tControl(aLevel 0x%x, aName 0x%x)"), this, aLevel, aName);
+ if (aLevel == KSOLInterface)
+ {
+ switch (aName)
+ {
+ case KSoIfInfo:
+ /* FALLTHROUGH */
+ case KSoIfInfo6:
+ return ServiceInfoControl(aOption, aName);
+
+ case KSoIfConfig:
+ return ServiceConfigControl(aOption);
+
+ case KSoIfHardwareAddr:
+ return ServiceHwAddrControl(aOption);
+
+ case KSoIfGetConnectionInfo:
+ return ServiceConnInfo(aOption);
+ case 0x734:
+ iHookAddressInfo = (CHookAddressInfo*)aSource;
+ return KErrNone;
+ default:
+ break;
+ }
+ }
+
+ if (iProtoBinders.Count())
+ {
+ //[401TODO] RZ: we're probably need fixed array to avoid index changing
+ return iProtoBinders[0]->Control(aLevel, aName, aOption);
+ }
+ return KErrNotReady;
+ }
+
+void CIPShimIfBase::Info(TNifIfInfo& aInfo) const
+ {
+ // Fill in the TNifIfInfo::iName field, which is used by TCP/IP
+ if (iProtoBinders.Count())
+ {
+ //[401TODO] RZ: we're probably need fixed array to avoid index changing
+ iProtoBinders[0]->GetName(aInfo.iName);
+
+ if(!iInterfaceNameRecorded)
+ {
+ XInterfaceNames* itfNames = static_cast<XInterfaceNames*>(
+ const_cast<Meta::SMetaData*>(iProtoBinders[0]->Flow().AccessPointConfig().FindExtension(XInterfaceNames::TypeId())));
+ itfNames->AddInterfaceNameL(this, aInfo.iName);
+ iInterfaceNameRecorded = ETrue;
+ }
+ }
+
+ //[401TODO] DL: get rid of magic number
+ aInfo.iVersion = TVersion(78,96,12453);
+
+ }
+
+TInt CIPShimIfBase::Send(RMBufChain& aPdu, TAny* /*aSource*/)
+/**
+Called from upper protocol to send a data packet.
+
+@param aPdu packet to send
+@param aSource unused
+@return 0 if upper protocol should block until receipt of StartSending(), else 1.
+*/
+ {
+ // demultiplex packets into the approriate senders
+ const RMBufPktInfo* info = RMBufPacket::PeekInfoInChain(aPdu);
+ CIPProtoBinder *binder = reinterpret_cast<CIPProtoBinder*>(info->iDstAddr.Port());
+
+ //[401TODO] This check is there purely because of GuQoS interoperability
+ //i.e.: GuQoS colloring packets for the Flow below IPShim. Get rid of
+ //this if statement along with GuQoS.
+ if (iProtoBinders.Count() == 1 || binder == NULL)
+ {
+ return iProtoBinders[0]->Send(aPdu);
+ }
+ else
+ {
+ return binder->Send(aPdu);
+ }
+ }
+
+TInt CIPShimIfBase::Notification(TAgentToNifEventType /*aEvent*/, void * /*aInfo*/)
+/**
+*/
+ {
+ return KErrNotSupported;
+ }
+
+void CIPShimIfBase::SetConnectionInfo(const TConnectionInfo& aConnectionInfo)
+/**
+Called from the Flow to provision the connection info to us.
+*/
+ {
+ iConnectionInfo = aConnectionInfo;
+ }
+
+const TConnectionInfo& CIPShimIfBase::ConnectionInfo()
+/**
+Called from the Flow to provision the connection info to us.
+*/
+ {
+ return iConnectionInfo;
+ }
+
+const TDesC8& CIPShimIfBase::ProtocolName()
+/**
+Return the associated protocol name.
+*/
+ {
+ ASSERT(iProtocolName.Length());
+ return iProtocolName;
+ }
+
+
+void CIPShimIfBase::AddIpAddrInfoL(CIPProtoBinder* aBinder, CSubConIPAddressInfoParamSet::TSubConIPAddressInfo& aAddrInfo)
+ {
+ ASSERT(iHookAddressInfo);
+ iHookAddressInfo->AddL(aBinder, aAddrInfo);
+ }
+
+void CIPShimIfBase::RemoveIpAddrInfo(CIPProtoBinder* aBinder, CSubConIPAddressInfoParamSet::TSubConIPAddressInfo& aAddrInfo)
+ {
+ ASSERT(iHookAddressInfo);
+ iHookAddressInfo->Remove(aBinder, aAddrInfo);
+ }
+
+void CIPShimIfBase::RemoveIpAddrInfo(CIPProtoBinder* aBinder)
+ {
+ if (iHookAddressInfo)
+ {
+ iHookAddressInfo->Remove(aBinder);
+ }
+ }
+
+
+CIPShimSubConnectionFlow& CIPShimIfBase::Flow()
+ {
+ ASSERT(iProtoBinders.Count() > 0);
+ return iProtoBinders[0]->Flow();
+ }
+
+CIPShimProtocolIntf* CIPShimIfBase::ProtcolIntf()
+ {
+ ASSERT(iProtIntf);
+ return iProtIntf;
+ }