networkcontrol/ipnetworklayer/src/flow.cpp
changeset 0 af10295192d8
child 6 c64cefac6e99
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 // IP Shim Flow Base class.
       
    15 // This class is derived from by the separate IP4 and IP6 shim flow classes.
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file flow.cpp
       
    21 */
       
    22 
       
    23 #include <e32std.h>
       
    24 #include <e32test.h>
       
    25 #include <ecom/ecom.h>
       
    26 #include <ecom/implementationproxy.h>
       
    27 #include <comms-infras/ss_metaconnprov.h>
       
    28 #include <comms-infras/ss_subconnflow.h>
       
    29 #include "flow.h"
       
    30 #include "nif.h"
       
    31 #include "panic.h"
       
    32 #include "ItfInfoConfigExt.h"
       
    33 #include "IPProtoMessages.h"	// TCFIPProtoMessage
       
    34 #include "IPProtoCPR.h"
       
    35 #include "idletimer.h"
       
    36 #include <networking/ipaddrinfoparams.h>
       
    37 #include "IPProtoDeMux.h"
       
    38 #include <comms-infras/ss_log.h>
       
    39 #include <es_prot_internal.h>
       
    40 
       
    41 using namespace Messages;
       
    42 using namespace MeshMachine;
       
    43 using namespace ESock;
       
    44 using namespace IpProtoCpr;
       
    45 //
       
    46 // CIPShimSubConnectionFlow
       
    47 //
       
    48 
       
    49 CIPShimSubConnectionFlow::CIPShimSubConnectionFlow(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf)
       
    50 : CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf), iCleanupError(KErrUnknown),
       
    51   iAsyncBinderClose(*this)
       
    52 	{
       
    53 	LOG_NODE_CREATE(KIPProtoTag1, CIPShimSubConnectionFlow);
       
    54 	}
       
    55 
       
    56 CIPShimSubConnectionFlow::~CIPShimSubConnectionFlow()
       
    57 	{
       
    58 	ASSERT(iBinderList.Count() == 0);
       
    59     iConnectionInfo.Close();
       
    60 	// iIntf doesn't need to be deleted explicitly, as it will be deleted
       
    61 	// when the last Close() is issued on it (i.e. either by us or by the TCP/IP
       
    62 	// stack).  At the time of writing, our call to Close() is the last one and
       
    63 	// will delete it.
       
    64 	LOG_NODE_DESTROY(KIPProtoTag1, CIPShimSubConnectionFlow);
       
    65 	}
       
    66 
       
    67 MFlowBinderControl* CIPShimSubConnectionFlow::DoGetBinderControlL()
       
    68 	{
       
    69 	return this;
       
    70 	}
       
    71 
       
    72 
       
    73 void CIPShimSubConnectionFlow::InitialiseDataMonitoringL(CIPShimIfBase* intf)
       
    74 	{
       
    75 	const TPacketActivity* packetActivity =
       
    76 		static_cast<const TPacketActivity*>(AccessPointConfig().FindExtension(TPacketActivity::TypeId()));
       
    77 	if (packetActivity)
       
    78 		{
       
    79 		intf->ShimNotify()->SetPacketActivityFlag(packetActivity->iPacketActivity);
       
    80 		}
       
    81 	else
       
    82 		{
       
    83 		__CFLOG_VAR((KIPProtoTag1, KIPProtoTag2, _L8("Packet activity provisioning information missing")));
       
    84     	User::Leave(KErrNotReady);
       
    85 		}
       
    86 
       
    87 	const TDataMonitoringConnProvisioningInfo* connProvisioningInfo =
       
    88 		static_cast<const TDataMonitoringConnProvisioningInfo*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(TDataMonitoringConnProvisioningInfo::iUid, TDataMonitoringConnProvisioningInfo::iId)));
       
    89 
       
    90 	const TDataMonitoringSubConnProvisioningInfo* subConnProvisioningInfo =
       
    91 		static_cast<const TDataMonitoringSubConnProvisioningInfo*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(TDataMonitoringSubConnProvisioningInfo::iUid, TDataMonitoringSubConnProvisioningInfo::iId)));
       
    92 
       
    93     if(connProvisioningInfo && subConnProvisioningInfo)
       
    94     	{
       
    95 		intf->ShimNotify()->SetDataVolumePtrs(connProvisioningInfo->iDataVolumesPtr, subConnProvisioningInfo->iDataVolumesPtr);
       
    96 		intf->ShimNotify()->SetNotificationThresholdPtrs(connProvisioningInfo->iThresholdsPtr, subConnProvisioningInfo->iThresholdsPtr);
       
    97     	}
       
    98     else
       
    99     	{
       
   100 		__CFLOG_VAR((KIPProtoTag1, KIPProtoTag2, _L8("Data monitoring provisioning information missing")));
       
   101     	User::Leave(KErrNotReady);
       
   102     	}
       
   103 	}
       
   104 
       
   105 
       
   106 // ============================================================================
       
   107 //
       
   108 // from Messages::ANode
       
   109 
       
   110 void CIPShimSubConnectionFlow::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
       
   111 /**
       
   112 Receive function for incoming messages from SCPR.
       
   113 
       
   114 @param aCFMessage message from SCPR
       
   115 */
       
   116     {
       
   117 	CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage);
       
   118 	if(aMessage.IsMessage<TEBase::TCancel>())
       
   119 		{
       
   120 		if (iStarting )
       
   121 			{
       
   122 			StopFlow(KErrCancel);
       
   123 			}
       
   124 		}
       
   125 	else if(aMessage.IsMessage<TEChild::TDestroy>())
       
   126 		{
       
   127 		Destroy();
       
   128 		}
       
   129 	else if(aMessage.IsMessage<TCFDataClient::TBindTo>())
       
   130 		{
       
   131 		TCFDataClient::TBindTo& msg = message_cast<TCFDataClient::TBindTo>(aMessage);
       
   132 		BindToL(msg.iNodeId);
       
   133 		ASSERT(iSubConnectionProvider == aSender);
       
   134 		iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TBindToComplete().CRef());
       
   135 		}
       
   136 	else if(aMessage.IsMessage<TCFDataClient::TStart>())
       
   137 		{
       
   138 		StartFlowL();
       
   139 		}
       
   140 	else if(aMessage.IsMessage<TCFDataClient::TStop>())
       
   141 		{
       
   142 		StopFlow(static_cast<TCFDataClient::TStop&>(aMessage).iValue);
       
   143 		}
       
   144 	else if(aMessage.IsMessage<TCFDataClient::TProvisionConfig>())
       
   145 		{
       
   146 		iAccessPointConfig.Close();		
       
   147 		iAccessPointConfig.Open(static_cast<TCFDataClient::TProvisionConfig&>(aMessage).iConfig);
       
   148 		ProcessProvisionConfigL();
       
   149 		}
       
   150 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
   151 	else if(aMessage.IsMessage<TCFScpr::TSetParamsRequest>())
       
   152 		{
       
   153 		UpdateIpAddressInfoL(static_cast<TCFScpr::TSetParamsRequest&>(aMessage));
       
   154 		}
       
   155 #else
       
   156 	else if(aMessage.IsMessage<TCFScpr::TParamsRequest>())
       
   157 		{
       
   158 		UpdateIpAddressInfoL(static_cast<TCFScpr::TParamsRequest&>(aMessage));
       
   159 		}
       
   160 #endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
   161 	else
       
   162 		{
       
   163 		Panic(EUnexpectedSubConnectionMsg);
       
   164 		}
       
   165     }
       
   166 
       
   167 
       
   168 //
       
   169 // Dispatch functions for messages from SCPR
       
   170 //
       
   171 
       
   172 __CFLOG_STMT
       
   173 (
       
   174 void LOG_ADDRESS(TSockAddr addr)
       
   175 	{
       
   176 	TBuf<KMaxSockAddrSize> buff;
       
   177 	TInetAddr iaddr(addr);
       
   178 	iaddr.Output(buff);
       
   179 
       
   180 	__CFLOG_VAR((KIPProtoTag1, KIPProtoTag2, _L("CIPShimSubConnectionFlow::UpdateIpAddressInfoL %S %d"), &buff, addr.Port()));
       
   181 	}
       
   182 )
       
   183 
       
   184 //helper function
       
   185 CIPProtoBinder * FindBinderForProtocol(const TDesC8& proto, RPointerArray<CIPProtoBinder> &array)
       
   186 	{
       
   187 	TInt count= array.Count();
       
   188 	for (TInt i = 0; i < count; i++)
       
   189 		{
       
   190 		if (array[i]->ProtocolName().Compare(proto) == 0)
       
   191 			{
       
   192 			return array[i];
       
   193 			}
       
   194 		}
       
   195 	return 0;
       
   196 	}
       
   197 
       
   198 #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
   199 void CIPShimSubConnectionFlow::UpdateIpAddressInfoL(TCFScpr::TSetParamsRequest& aParamReq)
       
   200 #else
       
   201 void CIPShimSubConnectionFlow::UpdateIpAddressInfoL(TCFScpr::TParamsRequest& aParamReq)
       
   202 #endif // SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW
       
   203 	{
       
   204 
       
   205 	//[401TODO] DL: deal with the granted also.
       
   206 	const RCFParameterFamilyBundleC& newParamBundle = aParamReq.iFamilyBundle;
       
   207 
       
   208 	CSubConIPAddressInfoParamSet* IPAddressInfoSet;
       
   209 	RParameterFamily family = newParamBundle.FindFamily(KSubConIPAddressInfoFamily);
       
   210 	if ( family.IsNull() )
       
   211 		{
       
   212 		 IPAddressInfoSet = NULL;
       
   213 		}
       
   214     else
       
   215     	{
       
   216     	 IPAddressInfoSet = static_cast<CSubConIPAddressInfoParamSet*>
       
   217 		 	(family.FindParameterSet(
       
   218 		 			STypeId::CreateSTypeId(CSubConIPAddressInfoParamSet::EUid,
       
   219 				 		CSubConIPAddressInfoParamSet::ETypeId)
       
   220 						 ,RParameterFamily::ERequested));
       
   221 		}
       
   222 
       
   223 	if (IPAddressInfoSet)
       
   224         {
       
   225 		TUint aParamSetNum = IPAddressInfoSet->GetParamNum();
       
   226 		/** TODO: It should be only one in the queue, so remove the loop */
       
   227 		for (TUint i=0; i<aParamSetNum; ++i)
       
   228 			{
       
   229 
       
   230 			CSubConIPAddressInfoParamSet::TSubConIPAddressInfo paramInfo(IPAddressInfoSet->GetParamInfoL(i));
       
   231 
       
   232 			//The only protocol we are going to deal with is TCP/IP
       
   233 			//as the flow association gets lost in when it goes through the current stack.
       
   234 			if (paramInfo.iCliDstAddr.Family() == KAfInet6 ||
       
   235 				paramInfo.iCliDstAddr.Family() == KAfInet)
       
   236 				{
       
   237 				__CFLOG_STMT(LOG_ADDRESS(paramInfo.iCliDstAddr);)
       
   238 				__CFLOG_STMT(LOG_ADDRESS(paramInfo.iCliSrcAddr);)
       
   239 
       
   240 				TInetAddr addr(paramInfo.iCliDstAddr);
       
   241 				TUint32 ipv4Addr = addr.Address();
       
   242 
       
   243 				if (iBinderList.Count())
       
   244 					{
       
   245 					CIPShimIfBase* nif = iBinderList[0]->iNif;
       
   246 					ASSERT(nif);
       
   247 					CIPProtoBinder *binder = 0;
       
   248 					if(ipv4Addr)
       
   249 						{
       
   250 						//find ip4 binder
       
   251 						binder = FindBinderForProtocol(KProtocolIp, iBinderList);
       
   252 						}
       
   253 					else
       
   254 						{
       
   255 						//find ip6 binder
       
   256 						binder = FindBinderForProtocol(KProtocolIp6, iBinderList);
       
   257 						}
       
   258 
       
   259 					if (IPAddressInfoSet->GetOperationCode() == CSubConIPAddressInfoParamSet::EDelete)
       
   260 						{
       
   261 						nif->RemoveIpAddrInfo(binder, paramInfo);
       
   262 						}
       
   263 					else
       
   264 						{
       
   265 						nif->AddIpAddrInfoL(binder, paramInfo);
       
   266 						}
       
   267 					}
       
   268 				}
       
   269 			}
       
   270         }
       
   271 	}
       
   272 
       
   273 
       
   274 class TCleanupNifPair {
       
   275 public:
       
   276 	TCleanupNifPair(CIPShimIfBase* aNif) : iNif(aNif), iBinder(NULL) {}
       
   277 
       
   278 	void Cleanup();
       
   279 	static void CleanupReleaseNif(TAny* aThis);
       
   280 
       
   281 	CIPShimIfBase* iNif;
       
   282 	CIPProtoBinder* iBinder;
       
   283 	};
       
   284 
       
   285 void TCleanupNifPair::Cleanup()
       
   286 	{
       
   287 	ASSERT(iNif);
       
   288 
       
   289 	if (iBinder)
       
   290 		{
       
   291 		iNif->UnbindFrom(iBinder);
       
   292 		iBinder->UnbindFromLowerFlow();
       
   293 		}
       
   294 	iNif->Release(KErrAbort);
       
   295 	}
       
   296 
       
   297 void TCleanupNifPair::CleanupReleaseNif(TAny* aThis)
       
   298 	{
       
   299 	TCleanupNifPair* pair = static_cast<TCleanupNifPair*>(aThis);
       
   300 	pair->Cleanup();
       
   301 	}
       
   302 
       
   303 void CIPShimSubConnectionFlow::BindToL(const Messages::TNodeId& aCommsBinder)
       
   304 	{
       
   305 	// Assumption that TCommsBinder object contains pointer to Flow
       
   306     if (aCommsBinder.IsNull())
       
   307      	{
       
   308      	User::Leave(KErrNotSupported);
       
   309      	}
       
   310 
       
   311 	ANode& mcfNode = aCommsBinder.Node();
       
   312 #if !defined(__GCCXML__)
       
   313 	CSubConnectionFlowBase& flow = mcfnode_cast<CSubConnectionFlowBase>(mcfNode);
       
   314 #else
       
   315 	CSubConnectionFlowBase& flow = reinterpret_cast<CSubConnectionFlowBase&>(mcfNode);
       
   316 #endif
       
   317 
       
   318 	__CFLOG_VAR((KIPProtoTag1, KIPProtoTag2, _L8("CIPShimSubConnectionFlow %08x:\tBindToL(): flow 0x%08x, protocol list '%S'"),
       
   319  				this, &flow, &iProtocolList));
       
   320 
       
   321 	MFlowBinderControl* binderControl = flow.GetBinderControlL();
       
   322 	ASSERT(binderControl);
       
   323 
       
   324 	// Loop through all the protocols in the list and create binders for them
       
   325 	TPtrC8 protoList(iProtocolList);
       
   326 	TPtrC8 proto;
       
   327 	TInt pos = KErrNotFound;
       
   328 
       
   329 	do
       
   330 		{
       
   331 		pos = protoList.LocateF(',');
       
   332 		if (pos == KErrNotFound)
       
   333 			{
       
   334 			proto.Set(protoList);
       
   335 			}
       
   336 		else
       
   337 			{
       
   338 			proto.Set(protoList.Left(pos));
       
   339 			protoList.Set(protoList.Mid(pos + 1));
       
   340 			}
       
   341 
       
   342 		if (proto.Length() > 0)
       
   343 			{
       
   344 			CIPProtoBinder* protoBinder = CIPProtoBinder::NewL(*this, proto);
       
   345 			CleanupStack::PushL(protoBinder);
       
   346 
       
   347 			CIPShimIfBase* nif = ProtocolIntf()->FindOrCreateNifL(proto,
       
   348 				reinterpret_cast<const TConnectionInfo&>(*iConnectionInfo.Ptr()));
       
   349 			TCleanupNifPair cleanuppair(nif);
       
   350 			CleanupStack::PushL(TCleanupItem(TCleanupNifPair::CleanupReleaseNif, &cleanuppair));
       
   351 
       
   352 			__CFLOG_VAR((KIPProtoTag1, KIPProtoTag2, _L8("CIPShimSubConnectionFlow %08x:\tBindToL(): nif 0x%08x, binder 0x%08x"), this, nif, protoBinder));
       
   353 			nif->BindToL(protoBinder);
       
   354 			cleanuppair.iBinder = protoBinder;
       
   355 
       
   356 			protoBinder->BindToLowerFlowL(*binderControl);
       
   357 
       
   358 			iBinderList.AppendL(protoBinder);
       
   359 
       
   360 			CleanupStack::Pop(2);
       
   361 
       
   362 			InitialiseDataMonitoringL(nif);
       
   363 			}
       
   364 		}
       
   365 	while (pos != KErrNotFound);
       
   366 
       
   367 	NM_LOG((KIPProtoTag1, _L8("CIPShimSubConnectionFlow %08x:\tSynchronous call: From=%08x To=%08x Func=BindToL"), this, static_cast<Messages::ANode*>(this), &mcfNode));
       
   368 
       
   369 	TInt binderCount = iBinderList.Count();
       
   370 	for (TInt i = 0; i < binderCount; i++)
       
   371 		{
       
   372 		iBinderList[i]->StartL();
       
   373 		}
       
   374 	}
       
   375 
       
   376 
       
   377 
       
   378 void CIPShimSubConnectionFlow::StartFlowL()
       
   379 /**
       
   380 Message from SCPR to start.
       
   381 */
       
   382 	{
       
   383 	ASSERT(!iStarting);
       
   384 
       
   385 	iStarting = ETrue;
       
   386 
       
   387 	PostDataClientStartedIfReady();
       
   388 	}
       
   389 
       
   390 void CIPShimSubConnectionFlow::StopFlow(TInt aError)
       
   391 /**
       
   392 Message from SCPR to stop.
       
   393 
       
   394 The aError reason code is stored to be passed to the TCP/IP stack via IfUserInterfaceDown().
       
   395 
       
   396 @param aError Reason code.
       
   397 */
       
   398 	{
       
   399 	ASSERT(aError != KErrNone);
       
   400 	iStopCode = aError;
       
   401 
       
   402 	for(TInt i =0; i < iBinderList.Count(); i++)
       
   403 		{
       
   404 		MarkBinderForClosure(iBinderList[i]);
       
   405 		}
       
   406 	CloseMarkedBinders();
       
   407 
       
   408 	PostDataClientStoppedIfReady();
       
   409 	}
       
   410 
       
   411 
       
   412 
       
   413 void CIPShimSubConnectionFlow::ProcessProvisionConfigL()
       
   414 /**
       
   415 Message from SCPR providing configuration information.
       
   416 */
       
   417 	{
       
   418     const TItfInfoConfigExt* ext = static_cast<const TItfInfoConfigExt*>(AccessPointConfig().FindExtension(
       
   419     		STypeId::CreateSTypeId(KIpProtoConfigExtUid, EItfInfoConfigExt)));
       
   420     if (ext)
       
   421         {
       
   422         TInt err = SetConnectionInfo(ext->iConnectionInfo);
       
   423 		if (err == KErrNone)
       
   424 			{
       
   425 			err = SetProtocolList(ext->iProtocolList);
       
   426 			}
       
   427         if (err != KErrNone)
       
   428             {
       
   429     	    User::Leave(err);
       
   430             }
       
   431 	    }
       
   432 	}
       
   433 
       
   434 
       
   435 
       
   436 TInt CIPShimSubConnectionFlow::SetProtocolList(const TDesC8& aProtocolList)
       
   437 /**
       
   438 Save a pointer to the protocol list string in the provisioning information
       
   439 */
       
   440 	{
       
   441 	if (aProtocolList.Length() > 0)
       
   442 		{
       
   443 		iProtocolList.Set(aProtocolList);
       
   444 		return KErrNone;
       
   445 		}
       
   446 	else
       
   447 		{
       
   448 		return KErrArgument;
       
   449 		}
       
   450 	}
       
   451 
       
   452 void CIPShimSubConnectionFlow::Destroy()
       
   453 /**
       
   454 Message from SCPR to self destruct.
       
   455 */
       
   456 	{
       
   457 	// No-one should be bound to us from above if we are about to disappear.
       
   458 	ASSERT(iBindCallCount == 0);
       
   459 
       
   460 	MarkAllBindersForClosure();
       
   461 
       
   462 	if (iAsyncBinderClose.IsActive())
       
   463 		{
       
   464 		// Can't destroy ourselves whilst an asynchronous binder close is pending.
       
   465 		// Arrange for it to close all binders and initiate the destroy.
       
   466 		//
       
   467 		// Note that the async binder close may have been originally invoked with
       
   468 		// just a single binder marked for closure, and we are now marking them all
       
   469 		// for closure and requesting a destroy.  This is the main reason for using
       
   470 		// the "marked for closure" flag - to deal with events that require further
       
   471 		// binders to be closed whilst the async binder close is still pending.
       
   472 		iDestroyPending = ETrue;
       
   473 		}
       
   474 	else
       
   475 		{
       
   476 		// No async binder close pending - close binders and destroy ourselves here.
       
   477 		CloseMarkedBinders();
       
   478 		DeleteThisFlow();
       
   479 		}
       
   480 	}
       
   481 
       
   482 //
       
   483 // Utility functions for sending messages to SCPR
       
   484 //
       
   485 
       
   486 void CIPShimSubConnectionFlow::PostDataClientStartedIfReady()
       
   487 	{
       
   488 	if (iBinderReady && iStarting)
       
   489     	{
       
   490     	iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStarted().CRef());
       
   491     	iStarting = EFalse;
       
   492     	iStarted = ETrue;
       
   493     	}
       
   494 	}
       
   495 
       
   496 void CIPShimSubConnectionFlow::PostDataClientStoppedIfReady()
       
   497 	{
       
   498 	if (iStopCode != KErrNone)
       
   499     	{
       
   500     	iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStopped(iStopCode).CRef());
       
   501     	iStopCode = KErrNone;
       
   502     	iStarted = EFalse;
       
   503 
       
   504 		MarkAllBindersForClosure();
       
   505 
       
   506 		if (!iAsyncBinderClose.IsActive())
       
   507 			{
       
   508 			// No async binder close pending - close binders
       
   509 			CloseMarkedBinders();
       
   510 			}
       
   511        	}
       
   512 	}
       
   513 
       
   514 void CIPShimSubConnectionFlow::Error(TInt aError)
       
   515 	{
       
   516     ASSERT(iStarted || iStarting);
       
   517     ASSERT(iSubConnectionProvider.IsOpen());
       
   518     if (iStarting)
       
   519         {
       
   520         iSubConnectionProvider.PostMessage(Id(), TEBase::TError(TCFDataClient::TStart::Id(), aError).CRef());
       
   521         }
       
   522     else
       
   523         {
       
   524         iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TDataClientGoneDown(aError, MNifIfNotify::EDisconnect).CRef());
       
   525         }
       
   526 
       
   527     iStopCode = aError;
       
   528     iStarting = EFalse;
       
   529     }
       
   530 
       
   531 MLowerControl* CIPShimSubConnectionFlow::GetControlL(const TDesC8& aProtocol)
       
   532     {
       
   533     if (aProtocol.Length())
       
   534         {
       
   535         User::Leave(KErrNotSupported);
       
   536         }
       
   537     return this;
       
   538     }
       
   539 
       
   540 MLowerDataSender* CIPShimSubConnectionFlow::BindL(const TDesC8& /*aProtocol*/, MUpperDataReceiver* /*aReceiver*/, MUpperControl* /*aControl*/)
       
   541     {
       
   542     iBindCallCount++;
       
   543     if (iBindCallCount == 1)
       
   544     	{
       
   545 	    iSubConnectionProvider.RNodeInterface::PostMessage(Id(), TCFControlProvider::TActive().CRef());
       
   546     	}
       
   547     return NULL;
       
   548     }
       
   549 
       
   550 void CIPShimSubConnectionFlow::Unbind( MUpperDataReceiver* /*aReceiver*/, MUpperControl* /*aControl*/)
       
   551     {
       
   552     iBindCallCount--;
       
   553     if (iBindCallCount <= 0)
       
   554     	{
       
   555     	ASSERT(iBindCallCount == 0);
       
   556 	    PostClientIdleIfIdle();
       
   557     	}
       
   558     }
       
   559 
       
   560 CSubConnectionFlowBase* CIPShimSubConnectionFlow::Flow()
       
   561     {
       
   562     return this;
       
   563     }
       
   564 
       
   565 void CIPShimSubConnectionFlow::OpenRoute()
       
   566 	{
       
   567 	// Post directly to cpr bypassing the scpr purely for efficiency
       
   568 	__CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimSubConnectionFlow %08x:\tOpenRoute()"), this);
       
   569 
       
   570 	RClientInterface::OpenPostMessageClose(Id(), TNodeCtxId(ECFActivityOpenCloseRoute, iProtocolIntf->ControlProviderId()),
       
   571 		TCFIPProtoMessage::TOpenCloseRoute(ETrue).CRef());
       
   572 	}
       
   573 
       
   574 
       
   575 void CIPShimSubConnectionFlow::CloseRoute()
       
   576 	{
       
   577 	// Post directly to cpr bypassing the scpr purely for efficiency
       
   578 	__CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimSubConnectionFlow %08x:\tCloseRoute()"), this);
       
   579 
       
   580 	RClientInterface::OpenPostMessageClose(Id(), TNodeCtxId(ECFActivityOpenCloseRoute, iProtocolIntf->ControlProviderId()),
       
   581 		TCFIPProtoMessage::TOpenCloseRoute(EFalse).CRef());
       
   582 	}
       
   583 
       
   584 void CIPShimSubConnectionFlow::PostClientIdleIfIdle()
       
   585     {
       
   586     if (iBindCallCount == 0)
       
   587         {
       
   588         iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TIdle().CRef());
       
   589         }
       
   590     }
       
   591 
       
   592 
       
   593 TInt CIPShimSubConnectionFlow::Control(TUint aLevel, TUint aName, TDes8& aOption)
       
   594     {
       
   595     TInt err = KErrNotSupported;
       
   596     
       
   597     //It returns interface info alias TConnectionInfo in a form of an old fashioned descriptor
       
   598     //for SetOption
       
   599     if (aLevel == (TUint)KSOLProvider && aName == (TUint)KSoConnectionInfo)
       
   600         {
       
   601 	    // Get the connection info from the config if it has not been stored yet in case the
       
   602 	    // CTransportFlowShim locks the connection info for a host resolver and calls StartSending()
       
   603 	    // on the host resolver before CIPShimSubConnectionFlow::ProcessProvisionConfigL() is called.
       
   604 	    // Otherwise, if ProcessProvisionConfigL() is not called in time the CTransportFlowShim will
       
   605 	    // lock to empty connection info.  ProcessProvisionConfigL() is called when the
       
   606 	    // CIPShimSubConnectionFlow receives the request to bind to the bearer SCPR which is not
       
   607 	    // synchronised in any way with the request to bind the CIPShimSubConnectionFlow to the
       
   608 	    // CTransportFlowShim which triggers the call to StartSending().  We still return
       
   609 	    // KErrNotReady when we are not bound so that a socket does not try to flow on too early
       
   610 	    // (this was causing failures in te_spudnetworkside).  A host resolver does not check the
       
   611 	    // error code when calling KSoConnectionInfo and simply uses the info if it's there anyway.
       
   612 	    //
       
   613 	    // See DEF128574.
       
   614 	   	if(iConnectionInfo.Length() == 0)
       
   615 	   		{
       
   616 			const TItfInfoConfigExt* ext = static_cast<const TItfInfoConfigExt*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(KIpProtoConfigExtUid, EItfInfoConfigExt)));
       
   617 			if (ext)
       
   618 			    {
       
   619 				aOption.Copy((const TUint8*)&ext->iConnectionInfo, sizeof(TConnectionInfo));
       
   620 		   		err = KErrNotReady;
       
   621 			    }
       
   622 	   		}
       
   623 	   	else
       
   624 	   		{
       
   625 	        if(iConnectionInfo.Length() == 0)
       
   626 	        	{
       
   627 	        	err = KErrNotReady;
       
   628 	        	}
       
   629 	        else
       
   630 	        	{
       
   631 		        aOption.Copy(iConnectionInfo);
       
   632 		   		err = KErrNone;
       
   633 	        	}
       
   634 	   		}
       
   635         }
       
   636     
       
   637     return err;
       
   638     }
       
   639 
       
   640 TInt CIPShimSubConnectionFlow::SetConnectionInfo(const TConnectionInfo& aInfo)
       
   641 	{
       
   642 	iConnectionInfo.Close();
       
   643 	TInt ret = iConnectionInfo.Create(sizeof(TConnectionInfo));
       
   644 	if (ret == KErrNone)
       
   645 	    {
       
   646     	iConnectionInfo.Copy((TUint8*)&aInfo, sizeof(TConnectionInfo));
       
   647 	    }
       
   648 	return ret;
       
   649 	}
       
   650 
       
   651 void CIPShimSubConnectionFlow::BinderReady()
       
   652 /**
       
   653 Called from binder to indicate that it is ready.
       
   654 */
       
   655 	{
       
   656 	iBinderReady = ETrue;
       
   657 	PostDataClientStartedIfReady();
       
   658 	}
       
   659 
       
   660 /**
       
   661 Called from lower binder to indicate an error that renders the binder unusable
       
   662 
       
   663 Ensure that the TCP/IP stack is notified and the binder closed down.
       
   664 
       
   665 @param aError error code
       
   666 @param aIf CIPShimIfBase object associated with the binder
       
   667 */
       
   668 #ifdef _DEBUG
       
   669 void CIPShimSubConnectionFlow::BinderError(TInt aError, CIPProtoBinder* aBinder)
       
   670 #else
       
   671 void CIPShimSubConnectionFlow::BinderError(TInt /*aError*/, CIPProtoBinder* aBinder)
       
   672 #endif
       
   673 	{
       
   674 	__CFLOG_VAR((KIPProtoTag1, KIPProtoTag2, _L8("CIPShimSubConnectionFlow %08x:\tBinderError(%d)"), this, aError));
       
   675 
       
   676 	// NOTE:
       
   677 	// - We are currently in the stack frame of the lower binder as it makes the Error() upcall.
       
   678 	// - Calling CloseBinder() directly here will result in a recursive Unbind() and destructor
       
   679 	//   downcall back into the binder.  Consequently, schedule asynchronous closure of the binder
       
   680 	//   to ensure that the binder does not have the burden of dealing with this recursion.
       
   681 	// - Note that CloseBinder() will also Close() the CIPShimIfBase, which may cause it to be destructed
       
   682 	//   (if all other references on it are gone, in particular the TCP/IP stack)
       
   683 	MarkBinderForClosure(aBinder);
       
   684 	if (!iAsyncBinderClose.IsActive())
       
   685 		{
       
   686 		iAsyncBinderClose.Call();
       
   687 		}
       
   688 	}
       
   689 
       
   690 
       
   691 void CIPShimSubConnectionFlow::SendMessageToSubConnProvider(const Messages::TSignatureBase& aCFMessage)
       
   692     {
       
   693     iSubConnectionProvider.PostMessage(Id(), aCFMessage);
       
   694     }
       
   695 
       
   696 const Messages::TNodeId& CIPShimSubConnectionFlow::GetCommsId()
       
   697     {
       
   698     return NodeId();
       
   699     }
       
   700 
       
   701 
       
   702 // MIpDataMonitoringNotifications
       
   703 
       
   704 void CIPShimSubConnectionFlow::PostConnDataReceivedThresholdReached(TUint aVolume)
       
   705 	{
       
   706 	RClientInterface::OpenPostMessageClose(Id(), iProtocolIntf->ControlProviderId(),
       
   707 		TCFDataMonitoringNotification::TDataMonitoringNotification(EReceived, aVolume).CRef());
       
   708 	}
       
   709 
       
   710 void CIPShimSubConnectionFlow::PostConnDataSentThresholdReached(TUint aVolume)
       
   711 	{
       
   712 	RClientInterface::OpenPostMessageClose(Id(), iProtocolIntf->ControlProviderId(),
       
   713 		TCFDataMonitoringNotification::TDataMonitoringNotification(ESent, aVolume).CRef());
       
   714 	}
       
   715 
       
   716 void CIPShimSubConnectionFlow::PostSubConnDataReceivedThresholdReached(TUint aVolume)
       
   717 	{
       
   718 	iSubConnectionProvider.PostMessage(Id(),
       
   719 		TCFDataMonitoringNotification::TDataMonitoringNotification(EReceived, aVolume).CRef());
       
   720 	}
       
   721 
       
   722 void CIPShimSubConnectionFlow::PostSubConnDataSentThresholdReached(TUint aVolume)
       
   723 	{
       
   724 	iSubConnectionProvider.PostMessage(Id(),
       
   725 		TCFDataMonitoringNotification::TDataMonitoringNotification(ESent, aVolume).CRef());
       
   726 	}
       
   727 
       
   728 //
       
   729 // Asynchronous Binder Close routines
       
   730 //
       
   731 // Class used to asynchronously unbind/destroy a binder from outside of the binder's call stack.
       
   732 //
       
   733 
       
   734 CAsyncBinderClose::CAsyncBinderClose(CIPShimSubConnectionFlow& aFlow)
       
   735   : CAsyncOneShot(EPriorityStandard), iFlow(aFlow)
       
   736   	{
       
   737   	}
       
   738 
       
   739 void CAsyncBinderClose::RunL()
       
   740 	{
       
   741 	iFlow.AsyncBinderClose();
       
   742 	}
       
   743 
       
   744 void CIPShimSubConnectionFlow::AsyncBinderClose()
       
   745 /**
       
   746 Main method of asynchronous binder close callback.
       
   747 */
       
   748 	{
       
   749 	CloseMarkedBinders();
       
   750 	if (iDestroyPending)
       
   751 		{
       
   752 		// Deal with a pending Destroy() that happened whilst the asynchronous binder close was pending.
       
   753 		iDestroyPending = EFalse;
       
   754 		DeleteThisFlow();
       
   755 		}
       
   756 	}
       
   757 
       
   758 void CIPShimSubConnectionFlow::MarkAllBindersForClosure()
       
   759 /**
       
   760 Mark all binders for closure in the asynchronous binder close callback
       
   761 */
       
   762 	{
       
   763 	for (TInt index = 0 ; index < iBinderList.Count() ; ++index)
       
   764 		{
       
   765 		MarkBinderForClosure(iBinderList[index]);
       
   766 		}
       
   767 	}
       
   768 
       
   769 void CIPShimSubConnectionFlow::MarkBinderForClosure(CIPProtoBinder* aBinder)
       
   770 	{
       
   771 	__CFLOG_VAR((KIPProtoTag1, KIPProtoTag2, _L8("CIPShimSubConnectionFlow %08x:\tMarkBinderForClosure(%08x)"), this, aBinder));
       
   772 	aBinder->iMarkedForClosure = ETrue;
       
   773 	}
       
   774 
       
   775 void CIPShimSubConnectionFlow::CloseMarkedBinders()
       
   776 	{
       
   777 	TInt count = iBinderList.Count();
       
   778 	TBool reset = count > 0 ? ETrue : EFalse;
       
   779 	for (TInt index = count -1  ; index >= 0; --index)
       
   780 		{
       
   781 		CIPProtoBinder* binder = iBinderList[index];
       
   782 		if (binder->iMarkedForClosure)
       
   783 			{
       
   784 			CIPShimIfBase *nif = binder->iNif;
       
   785 			if (nif) // nif may have unbound itself
       
   786 				{
       
   787 				nif->RemoveIpAddrInfo(binder);
       
   788 				// The removal of interface name has to be extracted from Release() and
       
   789 				// performed before UnbindFrom() as otherwise Release() would have no CIPProtoBinders
       
   790 				// to navigate up to the Flow, which is required to remove the interface name.
       
   791 				nif->RemoveInterfaceName(binder);
       
   792 				nif->UnbindFrom(binder);
       
   793 				nif->Release(iStopCode);
       
   794 				}
       
   795 			binder->UnbindFromLowerFlow();
       
   796 
       
   797 			iBinderList.Remove(index);
       
   798 			delete binder;
       
   799 			}
       
   800 		else
       
   801 			{
       
   802 			reset = EFalse;
       
   803 			}
       
   804 		}
       
   805 
       
   806 	if (reset)
       
   807 		{
       
   808 		// If we've closed all binders in the list, and the list is non-empty, then reset it.
       
   809 		iBinderList.Reset();
       
   810 		}
       
   811 	}
       
   812 
       
   813 // Utility functions
       
   814 
       
   815 GLDEF_C void Panic(TIPShimPanic aReason)
       
   816 	{
       
   817 	_LIT(KPanicCategory, "IPShim");
       
   818 
       
   819 	User::Panic(KPanicCategory(), aReason);
       
   820 	}
       
   821 
       
   822 // =================================================================================
       
   823 //
       
   824 // Flow Factory methods
       
   825 //
       
   826 
       
   827 CIPShimFlowFactory* CIPShimFlowFactory::NewL(TAny* aConstructionParameters)
       
   828 /**
       
   829 Constructs a Default SubConnection Flow Factory
       
   830 
       
   831 @param aConstructionParameters construction data passed by ECOM
       
   832 
       
   833 @returns pointer to a constructed factory
       
   834 */
       
   835 	{
       
   836 	CIPShimFlowFactory* ptr = new (ELeave) CIPShimFlowFactory(TUid::Uid(KIPShimFlowImplUid), *(reinterpret_cast<CSubConnectionFlowFactoryContainer*>(aConstructionParameters)));
       
   837 	return ptr;
       
   838 	}
       
   839 
       
   840 CIPShimFlowFactory::~CIPShimFlowFactory()
       
   841 	{
       
   842 	}
       
   843 
       
   844 
       
   845 CIPShimFlowFactory::CIPShimFlowFactory(TUid aFactoryId, CSubConnectionFlowFactoryContainer& aParentContainer)
       
   846 	: CSubConnectionFlowFactoryBase(aFactoryId, aParentContainer)
       
   847 /**
       
   848 Default SubConnection Flow Factory Constructor
       
   849 
       
   850 @param aFactoryId ECOM Implementation Id
       
   851 @param aParentContainer Object Owner
       
   852 */
       
   853 	{
       
   854 	}
       
   855 
       
   856 
       
   857 CSubConnectionFlowBase* CIPShimFlowFactory::DoCreateFlowL(ESock::CProtocolIntfBase* aProtocolIntf, TFactoryQueryBase& aQuery)
       
   858 	{
       
   859 	const TDefaultFlowFactoryQuery& query = static_cast<const TDefaultFlowFactoryQuery&>(aQuery);
       
   860 	return new (ELeave) CIPShimSubConnectionFlow(*this, query.iSCprId, aProtocolIntf);
       
   861 	}
       
   862 
       
   863 CProtocolIntfFactoryBase* CIPShimFlowFactory::CreateProtocolIntfFactoryL(CProtocolIntfFactoryContainer& aParentContainer)
       
   864 	{
       
   865 	CProtocolIntfFactoryBase* factory = CIPShimProtocolIntfFactory::NewL(TUid::Uid(KIPShimFlowImplUid),
       
   866 																		 aParentContainer);
       
   867     return factory;
       
   868 	}
       
   869 
       
   870 CIPShimProtocolIntf::CIPShimProtocolIntf(CProtocolIntfFactoryBase& aFactory,const Messages::TNodeId& aCprId)
       
   871 	:CProtocolIntfBase(aFactory,aCprId)
       
   872 	{
       
   873 	}
       
   874 
       
   875 CIPShimProtocolIntf::~CIPShimProtocolIntf()
       
   876 	{
       
   877 	// if there is still a nif open, then one of the ipshimflows
       
   878 	// is not being cleaned up correctly
       
   879 	ASSERT(iNifs.Count() == 0);
       
   880 	iNifs.Close();
       
   881 	}
       
   882 
       
   883 void CIPShimProtocolIntf::DoFlowCreated(ESock::CSubConnectionFlowBase& /*aFlow*/)
       
   884 	{
       
   885 	// do nothing
       
   886 	}
       
   887 
       
   888 void CIPShimProtocolIntf::DoFlowBeingDeleted(ESock::CSubConnectionFlowBase& /*aFlow*/)
       
   889 	{
       
   890 	// do nothing
       
   891 	}
       
   892 
       
   893 CIPShimIfBase* CIPShimProtocolIntf::FindOrCreateNifL(const TDesC8& aProtocol, const TConnectionInfo& aConnectionInfo)
       
   894 	{
       
   895 	CIPShimIfBase* shim = NULL;
       
   896 
       
   897 	for (TInt i = 0; i < iNifs.Count(); i++)
       
   898 		{
       
   899 		if (iNifs[i]->ProtocolName().Compare(aProtocol) == 0)
       
   900 			{
       
   901 			shim = iNifs[i];
       
   902 			break;
       
   903 			}
       
   904 		}
       
   905 	if (shim == NULL)
       
   906 		{
       
   907 		shim = CIPShimIfBase::NewL(aProtocol, this);
       
   908 		
       
   909 		CleanupStack::PushL(shim);
       
   910 		iNifs.AppendL(shim);
       
   911 		CleanupStack::Pop(shim);
       
   912 		
       
   913 		shim->SetConnectionInfo(aConnectionInfo);
       
   914 		}
       
   915 
       
   916 	return shim;
       
   917 	}
       
   918 
       
   919 void CIPShimProtocolIntf::NifDisappearing(CIPShimIfBase* aNif)
       
   920 	{
       
   921 	TInt index = iNifs.Find(aNif);
       
   922 	// index can be KErrNotFound if there was an OOM whilst trying to append a CIPShimIfBase to iNifs.
       
   923 	ASSERT(index >= KErrNotFound);
       
   924 	if (index >= 0)
       
   925 		{
       
   926 		iNifs.Remove(index);
       
   927 		}
       
   928 	}
       
   929 
       
   930 //TNodeCtxId(ECFActivityOpenCloseRoute, ControlProviderId())
       
   931 void CIPShimProtocolIntf::OpenRoute()
       
   932 	{
       
   933 		// Post directly to cpr bypassing the scpr purely for efficiency
       
   934 	__CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimProtocolIntf %08x:\tOpenRoute()"), this);
       
   935 
       
   936 	RClientInterface::OpenPostMessageClose(ControlProviderId(), ControlProviderId(),
       
   937 		TCFIPProtoMessage::TOpenCloseRoute(ETrue).CRef());
       
   938 	}
       
   939 
       
   940 //TNodeCtxId(ECFActivityOpenCloseRoute, ControlProviderId())
       
   941 void CIPShimProtocolIntf::CloseRoute()
       
   942 	{
       
   943 	// Post directly to cpr bypassing the scpr purely for efficiency
       
   944 	__CFLOG_1(KIPProtoTag1, KIPProtoTag2, _L("CIPShimProtocolIntf %08x:\tCloseRoute()"), this);
       
   945 
       
   946 	RClientInterface::OpenPostMessageClose(ControlProviderId(), ControlProviderId(),
       
   947 		TCFIPProtoMessage::TOpenCloseRoute(EFalse).CRef());
       
   948 	}
       
   949 
       
   950 
       
   951 CIPShimProtocolIntfFactory* CIPShimProtocolIntfFactory::NewL(TUid aFactoryId,
       
   952 															 ESock::CProtocolIntfFactoryContainer& aParentContainer)
       
   953 	{
       
   954 	CIPShimProtocolIntfFactory *fact = new(ELeave) CIPShimProtocolIntfFactory(aFactoryId, aParentContainer);
       
   955 	CleanupStack::PushL(fact);
       
   956 	fact->ConstructL();
       
   957 	CleanupStack::Pop(fact);
       
   958 	return fact;
       
   959 	}
       
   960 
       
   961 CProtocolIntfBase* CIPShimProtocolIntfFactory::DoCreateProtocolIntfL(TFactoryQueryBase& aQuery)
       
   962 	{
       
   963 	const TDefaultProtocolIntfFactoryQuery& query = static_cast<const TDefaultProtocolIntfFactoryQuery&>(aQuery);
       
   964 	return new(ELeave) CIPShimProtocolIntf(*this, query.iCprId);
       
   965 	}
       
   966 
       
   967 CIPShimProtocolIntfFactory::CIPShimProtocolIntfFactory(TUid aFactoryId,
       
   968 													   ESock::CProtocolIntfFactoryContainer& aParentContainer)
       
   969 	:CProtocolIntfFactoryBase(aFactoryId, aParentContainer)
       
   970 	{
       
   971 	}