networkcontrol/ipnetworklayer/src/nif.cpp
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // CNifIfBase and CProtocolBase shim layer functionality
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file nif.cpp
       
    20 */
       
    21 
       
    22 #include <e32base.h>
       
    23 #include <networking/qos_if.h>
       
    24 #include <nifmbuf.h>
       
    25 #include <es_prot_internal.h>
       
    26 #include <comms-infras/ss_subconnflow.h>
       
    27 #include <comms-infras/ss_protflow.h>
       
    28 
       
    29 #include "in_sock.h"
       
    30 #include "in_iface.h"
       
    31 #include "in6_if.h"
       
    32 
       
    33 #include "flow.h"
       
    34 #include "nif.h"
       
    35 #include "notify.h"
       
    36 #include "panic.h"
       
    37 #include "ItfInfoConfigExt.h"
       
    38 
       
    39 #include "nif4.h"		// for CIPShimIfBase::NewL()
       
    40 #include "nif6.h"		// for CIPShimIfBase::NewL()
       
    41 
       
    42 #include "IPProtoDeMux.h"
       
    43 
       
    44 #include "../addressinfohook/inc/hookaddrinfo.h"
       
    45 
       
    46 
       
    47 using namespace ESock;
       
    48 
       
    49 //
       
    50 // CIPShimIfBase methods
       
    51 //
       
    52 
       
    53 CIPShimIfBase* CIPShimIfBase::NewL(const TDesC8& aProtocol, CIPShimProtocolIntf *aIntf)
       
    54 	{
       
    55 	CIPShimIfBase* intf = NULL;
       
    56 
       
    57 	if (aProtocol.CompareF(KProtocolIp()) == 0)
       
    58 		{
       
    59 		intf = CIPShimIfBase4::NewL(aProtocol);
       
    60 		}
       
    61 	else
       
    62 	if (aProtocol.CompareF(KProtocolIp6()) == 0)
       
    63 		{
       
    64 		intf = CIPShimIfBase6::NewL(aProtocol);
       
    65 		}
       
    66 	else
       
    67 		{
       
    68 		// only support "ip" and "ip6" protocol names
       
    69 		User::Leave(KErrArgument);
       
    70 		}
       
    71 	intf->SetProtocolIntf(aIntf);
       
    72 	
       
    73 	return intf;
       
    74 	}
       
    75 
       
    76 
       
    77 CIPShimIfBase::CIPShimIfBase(const TDesC8& aProtocolName)
       
    78 	: CNifIfBase(), iBinderReady(EFalse), iProtIntf(NULL)
       
    79 /**
       
    80 CIPShimIfBase constructor
       
    81 */
       
    82 	{
       
    83 	__CFLOG_2(KIPProtoTag1, KIPProtoTag2, _L8("CIPShimIfBase %08x:\tCIPShimIfBase(aProtocolName '%S')"), this, &aProtocolName);
       
    84 	iProtocolName.Copy(aProtocolName);
       
    85 	}
       
    86 
       
    87 CIPShimIfBase::~CIPShimIfBase()
       
    88 	{
       
    89 	__CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\t~CIPShimIfBase()"), this);
       
    90 	delete iShimNotify;
       
    91 
       
    92 	for (TInt i = 0; i < iProtoBinders.Count(); i++)
       
    93 		{
       
    94 		iProtoBinders[i]->Unbind();
       
    95 		}
       
    96 		
       
    97 	iProtoBinders.Close();
       
    98 
       
    99 /*	ASSERT(iProtIntf);
       
   100 	iProtIntf->NifDisappearing(this);*/
       
   101 	
       
   102 	/*
       
   103 	 * it's not legal to assume that this pointer isn't NULL. There can be
       
   104 	 * OOM conditions in the constructor (which doesn't follow the official
       
   105 	 * 2 way constructions [in nif4 or nif6]) which can cause not to initialize
       
   106 	 * this pointer.
       
   107 	 */
       
   108 	if (iProtIntf)
       
   109 		{
       
   110 		iProtIntf->NifDisappearing(this);
       
   111 		}
       
   112 	}
       
   113 
       
   114 void CIPShimIfBase::ConstructL()
       
   115 	{
       
   116 	iShimNotify = CIPShimNotify::NewL(this);
       
   117 	// Setup the CNifIfBase::iNotify for the benefit of the TCP/IP stack to call us
       
   118 	iNotify = static_cast<MNifIfNotify*>(iShimNotify);	
       
   119 	}
       
   120 
       
   121 void CIPShimIfBase::StartL()
       
   122 	{
       
   123 	if (iUpperProtocol)
       
   124 		{
       
   125 		return;
       
   126 		}
       
   127 		
       
   128 	TBuf<KMaxProtocolNameSize> protocolName;
       
   129 	protocolName.Copy(iProtocolName);
       
   130 	__CFLOG_2(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tStartL(): FindAndLoadProtocolL('%S')"), this, &protocolName);    	
       
   131 	iUpperProtocol = SocketServExt::FindAndLoadProtocolL(protocolName);
       
   132 	iUpperProtocol->Open();
       
   133 	
       
   134 	
       
   135 	// Retrieve the MNifIfUser derived object from the upper protocol
       
   136 
       
   137 	TNifIfUser ifuser;
       
   138 	TInt err = iUpperProtocol->GetOption(KNifOptLevel, KNifOptGetNifIfUser, ifuser, 0);
       
   139 
       
   140 	if (err == KErrNone)
       
   141 		{
       
   142 		iNifUser = ifuser();
       
   143 
       
   144 		// Inform the upper protocol of our CNifIfBase derived interface.
       
   145 		// (the second argument does not appear to be used in current SymbianOS, so pass 0).
       
   146 		__CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tStartL(): IfUserNewInterfaceL()"), this);    	
       
   147 
       
   148 		CleanupClosePushL(*iUpperProtocol);
       
   149 		iNifUser->IfUserNewInterfaceL(this, 0);	// Note: increments CNifIfBase reference
       
   150 		CleanupStack::Pop();
       
   151 
       
   152 		// Cleanup Note: if you ever add a leaving function after IfUserNewInterfaceL() above,
       
   153 		// then you'll need to arrange for CleanupSignalNewInterface() to be called here (it is pushed
       
   154 		// onto the cleanup stack later as there are no subsequent leaving functions in this routine.
       
   155 
       
   156 		iNifUser->IfUserOpenNetworkLayer();				// Note: increments protocol reference count
       
   157 		}
       
   158 	else
       
   159 		{
       
   160 		__CFLOG_VAR((KIPProtoTag1, KIPProtoTag2, _L8("CIPShimIfBase %08x:\tStartL(): Error %d issuing KNifOptGetNifIfUser to protocol"), this, err));
       
   161 		User::Leave(err);
       
   162 		}
       
   163 	}
       
   164 
       
   165 void CIPShimIfBase::BindToL(CIPProtoBinder* aIPProtoBinder)
       
   166 	{
       
   167 	aIPProtoBinder->BindL(this);
       
   168 	iProtoBinders.AppendL(aIPProtoBinder);
       
   169 	}
       
   170 
       
   171 void CIPShimIfBase::UnbindFrom(CIPProtoBinder* aIPProtoBinder)
       
   172 	{
       
   173 	TInt index = iProtoBinders.Find(aIPProtoBinder);
       
   174 
       
   175 	// shouldn't try to unbind from a binder we're not bound to
       
   176 	ASSERT(index >= 0);
       
   177 	iProtoBinders.Remove(index);
       
   178 	aIPProtoBinder->Unbind();
       
   179 	}
       
   180 
       
   181 //-=========================================
       
   182 // MUpperDataReceiver methods
       
   183 //-=========================================        
       
   184 void CIPShimIfBase::Process(RMBufChain& aData)
       
   185 	{
       
   186 	iUpperProtocol->Process(aData, reinterpret_cast<CProtocolBase*>(this));
       
   187 	}
       
   188 
       
   189 //-=========================================
       
   190 // MUpperControl methods
       
   191 //-=========================================        
       
   192 void CIPShimIfBase::StartSending()
       
   193 	{
       
   194 	if (!iBinderReady)
       
   195 		{
       
   196 		// Get config info (for first time)
       
   197 		__CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tStartSending() (first time)"), this);
       
   198 		GetConfigFirstTime();
       
   199 		iBinderReady = ETrue;
       
   200 		}
       
   201 
       
   202 	if (iUpperProtocol)
       
   203 		{
       
   204 		// Call StartSending(...) in the context of "downstream path ready for first time"
       
   205 		__CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tStartSending()"), this);
       
   206 		iUpperProtocol->StartSending(reinterpret_cast<CProtocolBase*>(this));
       
   207 		}
       
   208 	}
       
   209 	
       
   210 void CIPShimIfBase::Error(TInt anError)
       
   211 	{
       
   212 	iProtoBinders[0]->Error(anError);
       
   213 	}
       
   214 
       
   215 #ifdef _DEBUG
       
   216 void CIPShimIfBase::BindL(TAny* aId)
       
   217 #else
       
   218 void CIPShimIfBase::BindL(TAny* /*aId*/)
       
   219 #endif
       
   220 /**
       
   221 Called from upper protocol to pass its CProtocolBase pointer
       
   222 */
       
   223 	{
       
   224 	//[401TODO] RZ: Is this assumption safe?
       
   225 	ASSERT(iUpperProtocol == aId);
       
   226 	
       
   227 	if (iBinderReady && iUpperProtocol)
       
   228 		{
       
   229 		__CFLOG_2(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tBindL(%08x)"), this, aId);
       
   230 		iUpperProtocol->StartSending(reinterpret_cast<CProtocolBase*>(this));
       
   231 		}
       
   232 	}
       
   233 
       
   234 void CIPShimIfBase::CleanupInterface(TInt aError)
       
   235 	{
       
   236 	__CFLOG_2(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %x:\tCleanupInterface(%d)"), this, aError);    	
       
   237 	iUpperProtocol->Close();
       
   238 	iUpperProtocol = NULL;
       
   239 	
       
   240 	if(iInterfaceNameRecorded && iProtoBinders.Count())
       
   241 		{
       
   242         XInterfaceNames* itfNames = static_cast<XInterfaceNames*>(
       
   243 			const_cast<Meta::SMetaData*>(iProtoBinders[0]->Flow().AccessPointConfig().FindExtension(XInterfaceNames::TypeId())));
       
   244 		itfNames->RemoveInterfaceName(this);
       
   245 		}
       
   246 
       
   247 	// IfUserInterfaceDown may delete this object, so create a stack variable for the NifIfUser
       
   248 	// so CloseNetworkLayer can be called on it.
       
   249 	MNifIfUser* nifUser = iNifUser; 
       
   250 	nifUser->IfUserInterfaceDown(aError, this);  	// Note: decrements CNifIfBase reference
       
   251 	nifUser->IfUserCloseNetworkLayer();				// Note: decrements protocol reference count
       
   252 	}
       
   253 
       
   254 void CIPShimIfBase::RemoveInterfaceName(CIPProtoBinder* aBinder)
       
   255 	{
       
   256 	ASSERT(aBinder);
       
   257 	
       
   258 	if(iInterfaceNameRecorded)
       
   259 		{
       
   260         XInterfaceNames* itfNames = static_cast<XInterfaceNames*>(
       
   261 			const_cast<Meta::SMetaData*>(aBinder->Flow().AccessPointConfig().FindExtension(XInterfaceNames::TypeId())));
       
   262 		itfNames->RemoveInterfaceName(this);
       
   263 		}
       
   264 	}
       
   265 
       
   266 
       
   267 void CIPShimIfBase::Release(TInt aError)
       
   268 	{
       
   269 	/* CleanupInterface will delete the interface when it is done if refcount is 0 (it will decrement it itself).
       
   270 	   If iRefCount 0 when release is called, Start must never have been
       
   271 	   called on this nif.  */
       
   272 	if (iProtoBinders.Count())
       
   273 		{
       
   274 		return;	//can't go away if we still have binders
       
   275 		}
       
   276 	   
       
   277 	if (iRefCount == 0)
       
   278 		{
       
   279 		delete this;
       
   280 		}
       
   281 	else
       
   282 		{
       
   283 		CleanupInterface(aError);
       
   284 		}
       
   285 	}
       
   286 
       
   287 TInt CIPShimIfBase::State()
       
   288 	{
       
   289 	return EIfDown;
       
   290 	}
       
   291 
       
   292 TInt CIPShimIfBase::ServiceHwAddrControl(TDes8& aOption)
       
   293 /**
       
   294 Service KSoIfHardwareAddr calls from upper protocol
       
   295 */
       
   296 	{
       
   297 	ASSERT(aOption.Length() == sizeof(TSoIfHardwareAddr));
       
   298 	if (iProtoBinders.Count())
       
   299 		{
       
   300 		//[401TODO] RZ: we're probably need fixed array to avoid index changing
       
   301 		return iProtoBinders[0]->Control(KSOLInterface, KSoIfHardwareAddr, aOption);		
       
   302 		}
       
   303 	else
       
   304 		{
       
   305 		__CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tServiceHwAddrControl(): no binders"), this);
       
   306 		return KErrNotReady;
       
   307 		}
       
   308 	}
       
   309 
       
   310 TInt CIPShimIfBase::ServiceConnInfo(TDes8& aOption)
       
   311 /**
       
   312 Service KSoIfGetConnectionInfo calls from upper protocol
       
   313 */
       
   314 	{
       
   315 	ASSERT(aOption.Length() == sizeof(TSoIfConnectionInfo));
       
   316 	TUint8* ptr = const_cast<TUint8*>(aOption.Ptr());
       
   317 	TSoIfConnectionInfo& returnedInfo = reinterpret_cast<TSoIfConnectionInfo&>(*ptr);
       
   318 
       
   319 	returnedInfo.iIAPId = iConnectionInfo.iIapId;
       
   320 	returnedInfo.iNetworkId = iConnectionInfo.iNetId;
       
   321 
       
   322 	return KErrNone;
       
   323 	}
       
   324 
       
   325 TInt CIPShimIfBase::Control(TUint aLevel, TUint aName, TDes8& aOption, TAny* aSource)
       
   326 	{
       
   327 	__CFLOG_3(KIPProtoTag1, KIPProtoTag2, _L("CIPShimIfBase %08x:\tControl(aLevel 0x%x, aName 0x%x)"), this, aLevel, aName);
       
   328 	if (aLevel == KSOLInterface)
       
   329 		{
       
   330 		switch (aName)
       
   331 			{
       
   332 		case KSoIfInfo:
       
   333 			/* FALLTHROUGH */
       
   334 		case KSoIfInfo6:
       
   335 			return ServiceInfoControl(aOption, aName);
       
   336 
       
   337 		case KSoIfConfig:
       
   338 			return ServiceConfigControl(aOption);
       
   339 
       
   340 		case KSoIfHardwareAddr:
       
   341 			return ServiceHwAddrControl(aOption);
       
   342 
       
   343 		case KSoIfGetConnectionInfo:
       
   344 			return ServiceConnInfo(aOption);			
       
   345 		case 0x734:
       
   346 			iHookAddressInfo = (CHookAddressInfo*)aSource;
       
   347 			return KErrNone;
       
   348 		default:
       
   349 			break;
       
   350 			}
       
   351 		}
       
   352 		
       
   353 	if (iProtoBinders.Count())
       
   354 		{
       
   355 		//[401TODO] RZ: we're probably need fixed array to avoid index changing
       
   356 		return iProtoBinders[0]->Control(aLevel, aName, aOption);
       
   357 		}
       
   358 	return KErrNotReady;	
       
   359 	}
       
   360 
       
   361 void CIPShimIfBase::Info(TNifIfInfo& aInfo) const
       
   362 	{
       
   363 	// Fill in the TNifIfInfo::iName field, which is used by TCP/IP
       
   364 	if (iProtoBinders.Count())
       
   365 		{
       
   366 		//[401TODO] RZ: we're probably need fixed array to avoid index changing
       
   367 		iProtoBinders[0]->GetName(aInfo.iName);
       
   368 
       
   369 		if(!iInterfaceNameRecorded)
       
   370 			{
       
   371 			XInterfaceNames* itfNames = static_cast<XInterfaceNames*>(
       
   372 				const_cast<Meta::SMetaData*>(iProtoBinders[0]->Flow().AccessPointConfig().FindExtension(XInterfaceNames::TypeId())));
       
   373 			itfNames->AddInterfaceNameL(this, aInfo.iName);
       
   374 			iInterfaceNameRecorded = ETrue;
       
   375 			}
       
   376 		}	
       
   377 
       
   378 	//[401TODO] DL: get rid of magic number
       
   379 	aInfo.iVersion = TVersion(78,96,12453);
       
   380 
       
   381 	}
       
   382 
       
   383 TInt CIPShimIfBase::Send(RMBufChain& aPdu, TAny* /*aSource*/)
       
   384 /**
       
   385 Called from upper protocol to send a data packet.
       
   386 
       
   387 @param aPdu packet to send
       
   388 @param aSource unused
       
   389 @return 0 if upper protocol should block until receipt of StartSending(), else 1.
       
   390 */
       
   391 	{
       
   392 	// demultiplex packets into the approriate senders
       
   393 	const RMBufPktInfo* info = RMBufPacket::PeekInfoInChain(aPdu);
       
   394 	CIPProtoBinder *binder = reinterpret_cast<CIPProtoBinder*>(info->iDstAddr.Port());
       
   395 	
       
   396     //[401TODO] This check is there purely because of GuQoS interoperability
       
   397     //i.e.: GuQoS colloring packets for the Flow below IPShim. Get rid of
       
   398     //this if statement along with GuQoS.
       
   399 	if (iProtoBinders.Count() == 1 || binder == NULL)
       
   400     	{
       
   401     	return iProtoBinders[0]->Send(aPdu);
       
   402     	}
       
   403     else
       
   404         {
       
   405         return binder->Send(aPdu);
       
   406         }
       
   407 	}
       
   408 
       
   409 TInt CIPShimIfBase::Notification(TAgentToNifEventType /*aEvent*/, void * /*aInfo*/)
       
   410 /**
       
   411 */
       
   412 	{
       
   413 	return KErrNotSupported;
       
   414 	}
       
   415 
       
   416 void CIPShimIfBase::SetConnectionInfo(const TConnectionInfo& aConnectionInfo)
       
   417 /**
       
   418 Called from the Flow to provision the connection info to us.
       
   419 */
       
   420 	{
       
   421 	iConnectionInfo = aConnectionInfo;
       
   422 	}
       
   423 
       
   424 const TConnectionInfo& CIPShimIfBase::ConnectionInfo()
       
   425 /**
       
   426 Called from the Flow to provision the connection info to us.
       
   427 */
       
   428 	{
       
   429 	return iConnectionInfo;
       
   430 	}
       
   431 
       
   432 const TDesC8& CIPShimIfBase::ProtocolName()
       
   433 /**
       
   434 Return the associated protocol name.
       
   435 */
       
   436 	{
       
   437 	ASSERT(iProtocolName.Length());
       
   438 	return iProtocolName;
       
   439 	}
       
   440 
       
   441 	
       
   442 void CIPShimIfBase::AddIpAddrInfoL(CIPProtoBinder* aBinder, CSubConIPAddressInfoParamSet::TSubConIPAddressInfo& aAddrInfo)
       
   443 	{
       
   444 	ASSERT(iHookAddressInfo);
       
   445 	iHookAddressInfo->AddL(aBinder, aAddrInfo);
       
   446 	}
       
   447 
       
   448 void CIPShimIfBase::RemoveIpAddrInfo(CIPProtoBinder* aBinder, CSubConIPAddressInfoParamSet::TSubConIPAddressInfo& aAddrInfo)
       
   449 	{
       
   450 	ASSERT(iHookAddressInfo);
       
   451     iHookAddressInfo->Remove(aBinder, aAddrInfo);	    
       
   452 	}
       
   453 
       
   454 void CIPShimIfBase::RemoveIpAddrInfo(CIPProtoBinder* aBinder)
       
   455 	{
       
   456 	if (iHookAddressInfo)
       
   457     	{
       
   458 	    iHookAddressInfo->Remove(aBinder);
       
   459     	}
       
   460 	}
       
   461 
       
   462 
       
   463 CIPShimSubConnectionFlow& CIPShimIfBase::Flow()
       
   464 	{
       
   465 	ASSERT(iProtoBinders.Count() > 0);
       
   466 	return iProtoBinders[0]->Flow();
       
   467 	}
       
   468 	
       
   469 CIPShimProtocolIntf* CIPShimIfBase::ProtcolIntf()
       
   470 	{
       
   471 	ASSERT(iProtIntf);
       
   472 	return iProtIntf;
       
   473 	}