commsfwutils/commsbufs/reference/loopback_bearer/src/binder.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 #include <e32std.h>
       
    18 #include <eui_addr.h>
       
    19 #include <ip4_hdr.h>
       
    20 #include <udp_hdr.h>
       
    21 #include <tcp_hdr.h>
       
    22 #include <in_chk.h>
       
    23 #include <in_iface.h>
       
    24 #include <comms-infras/nifif.h>
       
    25 #include <in_sock.h>
       
    26 #include "var.h"
       
    27 #include "binder.h"
       
    28 #include "provision.h"
       
    29 
       
    30 #ifdef SYMBIAN_ZERO_COPY_NETWORKING
       
    31 #include <comms-infras/commsbuf.h>
       
    32 #include <comms-infras/commsbufpond.h>
       
    33 #include <comms-infras/commsbufpondop.h>
       
    34 #else
       
    35 #include <comms-infras/mbufmanager.h>
       
    36 #endif
       
    37 
       
    38 using namespace ESock;
       
    39 
       
    40 #ifdef _DEBUG
       
    41 _LIT8(KNif,"Legacy");
       
    42 _LIT8(KBinder4,"Binder4");
       
    43 _LIT8(KBinder6,"Binder6");
       
    44 #endif
       
    45 
       
    46 //
       
    47 // CLegacyLoopbackBinder4 //
       
    48 //
       
    49 
       
    50 CLegacyLoopbackBinder4::CLegacyLoopbackBinder4(CLegacyLoopbackSubConnectionFlow& aLegacyLoopbackSubConnectionFlow) : iLegacyLoopbackSubConnectionFlow(aLegacyLoopbackSubConnectionFlow)
       
    51 	{
       
    52     __FLOG_OPEN(KNif, KBinder4);
       
    53    	// generate my local ip address (ip4) - vals potentially will be overwritten by any derived classes
       
    54 	iLocalAddressBase = KLegacyLoopbackLocalAddressBase; // also used later in control method
       
    55 	
       
    56 	TUint32 id = ((TUint32)this) % 255;
       
    57 	// Avoid the reserved address (least significant byte KLegacyLoopbackReservedHostId) that
       
    58 	// is never to be allocated as a local address.
       
    59 	if (id == KLegacyLoopbackReservedHostId)
       
    60 		{
       
    61 		++id;
       
    62 		}
       
    63 	iLocalAddress = iLocalAddressBase + id;
       
    64     __FLOG_3(_L8("CLegacyLoopbackBinder4 %08x:\tCLegacyLoopbackBinder4(CLegacyLoopbackSubConnectionFlow& %08x): iLocalAddress %08x"), this, &aLegacyLoopbackSubConnectionFlow, iLocalAddress);
       
    65 }
       
    66 
       
    67 CLegacyLoopbackBinder4::~CLegacyLoopbackBinder4()
       
    68 /** 
       
    69 Destroys 'this'
       
    70 */
       
    71     {
       
    72     if (iTestSubscriber)
       
    73     	{
       
    74     	iTestSubscriber->Cancel();
       
    75     	}
       
    76     delete iTestSubscriber;
       
    77     delete iDrvReceiver;
       
    78     delete iDrvSender;
       
    79     __FLOG_1(_L8("CLegacyLoopbackBinder4 %08x:\t~CLegacyLoopbackBinder4()"), this);
       
    80     ASSERT(iUpperControl == NULL);
       
    81     ASSERT(iUpperReceiver == NULL);
       
    82 	ASSERT(!iErrorOneShot.IsActive());
       
    83     RDebug::Printf("closing driver\n");
       
    84     iDrv.Close();
       
    85     __FLOG_CLOSE;
       
    86     }
       
    87 
       
    88 CLegacyLoopbackBinder4* CLegacyLoopbackBinder4::NewL(CLegacyLoopbackSubConnectionFlow& aLegacyLoopbackSubConnectionFlow)
       
    89 	{
       
    90 	CLegacyLoopbackBinder4* self = new (ELeave) CLegacyLoopbackBinder4(aLegacyLoopbackSubConnectionFlow);
       
    91 	CleanupStack::PushL(self);
       
    92 	
       
    93 	const TProviderInfo& providerInfo = static_cast<const TProviderInfoExt&>(
       
    94 		aLegacyLoopbackSubConnectionFlow.AccessPointConfig().FindExtensionL(
       
    95 			STypeId::CreateSTypeId(TProviderInfoExt::EUid, TProviderInfoExt::ETypeId))).iProviderInfo;
       
    96 	TInt ap = providerInfo.APId();
       
    97 	if(CLegacyLoopbackFlowTestingSubscriber::ShouldRun(ap))
       
    98 		{
       
    99 		ASSERT(self->iTestSubscriber==NULL);
       
   100 		self->iTestSubscriber = CLegacyLoopbackFlowTestingSubscriber::NewL(aLegacyLoopbackSubConnectionFlow, ap);
       
   101 		}
       
   102 
       
   103 	// The send and receive paths each have an AO
       
   104 	self->iDrvReceiver = new(ELeave) CDrvReceiver(CActive::EPriorityHigh);
       
   105 	self->iDrvSender = new(ELeave) CDrvSender(CActive::EPriorityHigh);
       
   106 
       
   107 	CleanupStack::Pop(self);
       
   108 	return self;
       
   109 	}
       
   110 
       
   111 void CLegacyLoopbackBinder4::LogPacketDetails(TInet6HeaderIP4* aIp4, const TDesC8& aCaption)
       
   112     {
       
   113     static_cast<void>(aIp4);
       
   114     static_cast<void>(aCaption);
       
   115 
       
   116 #if defined __FLOG_ACTIVE
       
   117     TBuf8<KLogBufferSize> log;
       
   118     TInet6HeaderUDP* udp = NULL;
       
   119     TInet6HeaderTCP* tcp = NULL;
       
   120     TBuf8<10> prot;
       
   121     TBuf8<40> length;
       
   122     TInt srcPort = -1;
       
   123     TInt dstPort = -1;
       
   124     if(aIp4->Protocol() == KProtocolInetUdp)
       
   125         {
       
   126         udp = (TInet6HeaderUDP*) aIp4->EndPtr();
       
   127         prot = _L8("UDP");
       
   128         length.Format(_L8("payload %d"), udp->Length());
       
   129         srcPort = udp->SrcPort();
       
   130         dstPort = udp->DstPort();
       
   131         }
       
   132     else if(aIp4->Protocol() == KProtocolInetTcp)
       
   133         {
       
   134         tcp = (TInet6HeaderTCP*) aIp4->EndPtr();
       
   135         prot = _L8("TCP");
       
   136         length.Format(_L8("payload %d"), aIp4->TotalLength() - aIp4->HeaderLength() - tcp->HeaderLength());
       
   137         srcPort = tcp->SrcPort();
       
   138         dstPort = tcp->DstPort();
       
   139         }
       
   140     else
       
   141         {
       
   142         prot.Format(_L8("%d"), aIp4->Protocol());
       
   143         length.Format(_L8("tot_len %d"), aIp4->TotalLength());
       
   144         }	
       
   145     TDes8IgnoreOverflow overflow;
       
   146     log.AppendFormat(_L8("%S %S %S src %08x:%d, dst %08x:%d"), &overflow, &aCaption, &prot, &length,
       
   147             aIp4->SrcAddr(), srcPort, aIp4->DstAddr(), dstPort);
       
   148     __FLOG(log);
       
   149 #endif    
       
   150     }
       
   151     
       
   152 void CLegacyLoopbackBinder4::UpdateHeaders(TInet6HeaderIP4* aIp4, TInet6HeaderUDP* aUdp)
       
   153 /**
       
   154 Update the IPv4 and UDP headers to allow the packet to be looped back.
       
   155 */
       
   156 {
       
   157 	__FLOG_STMT( LogPacketDetails(aIp4, _L8("CLegacyLoopbackBinder4:\tUpdateHeaders(...): ")) );
       
   158 	
       
   159 	// swap over the destination and source addresses
       
   160 	TUint32 temp;
       
   161 	temp = aIp4->SrcAddr();
       
   162 	aIp4->SetSrcAddr(aIp4->DstAddr());
       
   163 	aIp4->SetDstAddr(temp);
       
   164 
       
   165    	// swap over the destination and source ports
       
   166 	if (aUdp)
       
   167 		{
       
   168 		TUint tempPort;
       
   169 		tempPort = aUdp->DstPort();
       
   170 		aUdp->SetDstPort(aUdp->SrcPort());
       
   171 		aUdp->SetSrcPort(tempPort);
       
   172 		}
       
   173 
       
   174 	// NB: don't need to recalculate any checksums since luckily IP sums don't detect transposition
       
   175 	__FLOG_4(_L("CLegacyLoopbackBinder4:\tUpdateHeaders(...): became src %08x:%d, dst %08x:%d"), 
       
   176 			aIp4->SrcAddr(), aUdp? (TInt)aUdp->SrcPort(): -1, (TInt)aIp4->DstAddr(), aUdp? (TInt)aUdp->DstPort(): -1);
       
   177 }
       
   178 
       
   179 MLowerDataSender::TSendResult CLegacyLoopbackBinder4::Send(RMBufChain& aData)
       
   180 /**
       
   181 Entry point for receiving IPv4 outgoing data
       
   182 
       
   183 @param aData MBuf chain containing data to send
       
   184 @return an indication of whether the upper layer should block.
       
   185 */
       
   186 	{
       
   187     RMBufPacket& pkt = static_cast<RMBufPacket&>(aData);
       
   188 
       
   189     pkt.Unpack();
       
   190 	TInet6HeaderIP4* ip4 = (TInet6HeaderIP4*) pkt.First()->Ptr();
       
   191     __FLOG_STMT( LogPacketDetails(ip4, _L8("CLegacyLoopbackBinder4:\tSend(...): ")) );
       
   192 
       
   193 	if (ip4->Protocol() == KProtocolInetUdp || ip4->Protocol() == KProtocolInetTcp)
       
   194 		{
       
   195 		// get the "udp" header as well - cheating & relying upon UDP & TCP being in same place
       
   196 		TInet6HeaderUDP* udp = (TInet6HeaderUDP*) ip4->EndPtr();
       
   197 	
       
   198 		// use the source or destination port number to decide whether or not to pass it through the loopback driver
       
   199 		// very weak this; dynamic ports could overlap. Really should do this for all packets and
       
   200 		// fix any impacted test code
       
   201 		TUint srcPort = udp->SrcPort();
       
   202 		TUint dstPort = udp->DstPort();
       
   203 
       
   204 		if(dstPort >= KDriverReflectionRangeStartPort && dstPort <= KDriverReflectionRangeEndPort ||
       
   205 			srcPort >= KDriverReflectionRangeStartPort && srcPort <= KDriverReflectionRangeEndPort)
       
   206 			{
       
   207 			if(!iLoopbackLoadAttempted)
       
   208 				{
       
   209 				iLoopbackLoadAttempted = ETrue;
       
   210 				TInt r = User::LoadPhysicalDevice(KLegacyLoopbackPddFileName);
       
   211 				RDebug::Printf("Loading PDD - %d\n", r);
       
   212 				if(r == KErrNone || r == KErrAlreadyExists)
       
   213 					{
       
   214 					r = User::LoadLogicalDevice(KLegacyLoopbackLddFileName);
       
   215 					RDebug::Printf("Loading LDD - %d\n", r);
       
   216 					if(r == KErrNone || r == KErrAlreadyExists)
       
   217 						{
       
   218 						r = iDrv.Open();
       
   219 						RDebug::Printf("Opening driver - %d\n", r);
       
   220 						if(r == KErrNone)
       
   221 							{
       
   222 							// Prime the pathways
       
   223 							iDrvReceiver->Start(this, iDrv);
       
   224 							iDrvSender->Start(this, iDrv);
       
   225 							}
       
   226 						}
       
   227 					}
       
   228 				}
       
   229 			if(iDrv.Handle())
       
   230 				{
       
   231 				// Swap the ports, because the receipt path also unconditionally swaps them (probably
       
   232 				// some test needs this 
       
   233 				// ugh! should use a queue here when the write is still busy
       
   234 				udp->SetDstPort(srcPort);
       
   235 				udp->SetSrcPort(dstPort);
       
   236 				
       
   237 				__FLOG_4(_L("CLegacyLoopbackBinder4:\tSend(...): passing packet to driver as src %08x:%d, dst %08x:%d"),  
       
   238 						ip4->SrcAddr(), dstPort, ip4->DstAddr(), srcPort);
       
   239 
       
   240 				iDrvSender->QueueForSend(pkt);
       
   241 				return ESendAccepted;
       
   242 				}
       
   243 			}
       
   244 		else if(dstPort >= KBearerReflectionRangeStartPort && dstPort <= KBearerReflectionRangeEndPort ||
       
   245 					srcPort >= KBearerReflectionRangeStartPort && srcPort <= KBearerReflectionRangeEndPort)
       
   246 			{
       
   247 			// Swap the ports, because the receipt path also unconditionally swaps them (probably
       
   248 			// some test needs this 
       
   249 			udp->SetDstPort(srcPort);
       
   250 			udp->SetSrcPort(dstPort);
       
   251 			}
       
   252 		}
       
   253 
       
   254 	// Loop the data straight back into the TCP/IP stack
       
   255 	pkt.Pack();
       
   256 	ProcessPacket(aData);
       
   257 	return ESendAccepted;
       
   258 	}
       
   259 	
       
   260 
       
   261 MLowerDataSender* CLegacyLoopbackBinder4::Bind(MUpperDataReceiver& aUpperReceiver, MUpperControl& aUpperControl)
       
   262 /**
       
   263 Return the MLowerDataSender instance (CLegacyLoopbackBinder4) that we
       
   264 previously allocated.
       
   265 */
       
   266 	{
       
   267     __FLOG_3(_L8("CLegacyLoopbackBinder4 %08x:\tBind(aUpperReceiver %08x, aUpperControl %08x)"), this, &aUpperReceiver, &aUpperControl);
       
   268 	iUpperReceiver = &aUpperReceiver;
       
   269 	iUpperControl = &aUpperControl;
       
   270 
       
   271 	// Signal upper layer that we are ready
       
   272 	BinderReady();
       
   273 
       
   274 	return this;
       
   275 	}
       
   276 	
       
   277 void CLegacyLoopbackBinder4::Unbind(MUpperDataReceiver& aUpperReceiver, MUpperControl& aUpperControl)
       
   278 /**
       
   279 Forget our association with upper layer.
       
   280 */
       
   281 	{
       
   282     static_cast<void>(aUpperReceiver);
       
   283     static_cast<void>(aUpperControl);
       
   284     __FLOG_1(_L8("CLegacyLoopbackBinder4 %08x:\tUnbind()"), this);
       
   285     ASSERT(&aUpperReceiver == iUpperReceiver);
       
   286     ASSERT(&aUpperControl == iUpperControl);
       
   287     iUpperReceiver = NULL;
       
   288     iUpperControl = NULL;
       
   289 	}
       
   290 	
       
   291 void CLegacyLoopbackBinder4::BinderReady()
       
   292 /**
       
   293 Signal upper layer that we are ready
       
   294 */
       
   295 	{
       
   296     __FLOG_1(_L8("CLegacyLoopbackBinder4 %08x:\tBinderReady()"), this);
       
   297 
       
   298 	iUpperControl->StartSending();
       
   299 	}
       
   300 
       
   301 void CLegacyLoopbackBinder4::ProcessPacket(RMBufChain& aPdu)
       
   302 /**
       
   303 Process incoming data
       
   304 */
       
   305     {
       
   306 	// this received data has already been looped back...
       
   307 	// get the ip header from the RMBufChain
       
   308 	TInet6HeaderIP4* ip4 = (TInet6HeaderIP4*) aPdu.First()->Next()->Ptr();
       
   309 
       
   310 	if (ip4->Protocol() != KProtocolInetUdp && ip4->Protocol() != KProtocolInetTcp)
       
   311 		{
       
   312 		//Non UDP traffic goes here!
       
   313 		__FLOG_3(_L("CLegacyLoopbackBinder4 %08x:\tProcessPacket(): IPv4 length %d, protocol %d"), this, ip4->TotalLength(), ip4->Protocol());
       
   314 
       
   315 		UpdateHeaders(ip4, NULL);
       
   316 		// now process it (pass up the stack)
       
   317 		iUpperReceiver->Process(aPdu);
       
   318 		return;
       
   319 		}
       
   320 
       
   321 	// get the udp header as well - assume only udp traffic here
       
   322     __FLOG_STMT( LogPacketDetails(ip4, _L8("CLegacyLoopbackBinder4:\tProcessPacket(...): ")) );
       
   323 
       
   324 	TInet6HeaderUDP* udp = (TInet6HeaderUDP*) ip4->EndPtr();
       
   325 
       
   326 	// depending on the contents, pass it on up thru the stack 
       
   327 	// or maybe do something else
       
   328 
       
   329 	// use the destination port number to decide whether or not the payload is a command
       
   330 	TUint dstPort = udp->DstPort();
       
   331 	if (KLegacyLoopbackCmdPort == dstPort)
       
   332     	{
       
   333 		// let's use the first payload byte as the command byte
       
   334 		switch (*(udp->EndPtr()))
       
   335     		{
       
   336 		    case KForceDisconnect:
       
   337 			    __FLOG(_L("KForceDisconnect command"));
       
   338 			    // do some action
       
   339 	            Flow()->Progress(KLinkLayerClosed, KErrCommsLineFail);
       
   340 
       
   341 	            Flow()->FlowDown(KErrCommsLineFail, MNifIfNotify::EDisconnect);
       
   342 
       
   343 			    // no return code so all we can do is respond with what we got
       
   344 			    UpdateHeaders(ip4, udp);
       
   345 			    iUpperReceiver->Process(aPdu);
       
   346 			    break;
       
   347 
       
   348 		    case KForceReconnect:
       
   349 			    __FLOG(_L("KForceReconnect command"));
       
   350 			    // do some action
       
   351 	            Flow()->Progress(KLinkLayerClosed, KErrCommsLineFail);
       
   352 	            
       
   353 	            Flow()->FlowDown(KErrCommsLineFail, MNifIfNotify::EReconnect);
       
   354 
       
   355 			    // no return code so all we can do is respond with what we got
       
   356 			    UpdateHeaders(ip4, udp);
       
   357 			    iUpperReceiver->Process(aPdu);
       
   358 			    break;
       
   359 
       
   360 		    case KSendNotification:
       
   361 			    __FLOG(_L("KSendNotification command"));
       
   362 			    //let's write the result in the next byte of the reply
       
   363 			    if (Flow()->AgentProvision()->IsDialIn() == KErrNotSupported)
       
   364 				    udp->EndPtr()[1] = (unsigned char) KErrNone;
       
   365 			    else
       
   366 				    udp->EndPtr()[1] = (unsigned char) KErrGeneral; // this will lose it's sign :-(
       
   367 			
       
   368 			    UpdateHeaders(ip4, udp);
       
   369                 iUpperReceiver->Process(aPdu);
       
   370 			    break;
       
   371 			    
       
   372 			case KForceFinishedSelection:
       
   373 				__FLOG(_L("KForceFinishedSelection command"));
       
   374 				// force subConn into KFinishedSelection State
       
   375 	            Flow()->Progress(KFinishedSelection, KErrNone);
       
   376 				UpdateHeaders(ip4, udp);
       
   377 				aPdu.Free();
       
   378 				break;
       
   379 
       
   380     		case KForceBinderError:
       
   381 			    __FLOG(_L("KForceBinderError command"));
       
   382 				// We cannot signal an error whilst in the middle of a send in the TCP/IP stack,
       
   383 				// as the act of signalling the error will eventually result in the CNifIfBase binder
       
   384 				// being destructed by the TCP/IP stack whilst we're in the middle of using it.
       
   385 				// Consequently, we would panic on exit from this routine.  So make the call
       
   386 				// via an asynchronous callback.
       
   387 				if (!iErrorOneShot.IsActive())
       
   388 					{
       
   389 					iErrorOneShot.Schedule(iUpperControl);
       
   390 					}
       
   391     			aPdu.Free();
       
   392     			break;
       
   393 
       
   394     		case KColourDataByLinkTierAccessPointId:
       
   395 				{
       
   396 				const TProviderInfoExt* providerInfo = static_cast<const TProviderInfoExt*>(
       
   397 					iLegacyLoopbackSubConnectionFlow.AccessPointConfig().FindExtension(
       
   398 						STypeId::CreateSTypeId(TProviderInfoExt::EUid, TProviderInfoExt::ETypeId)));
       
   399 				ASSERT(providerInfo); // Should always be present
       
   400 
       
   401 				// We are going to simply add the access point id to the command byte
       
   402 				// A test client can then validate that the socket is connected on the expected access point
       
   403 			    __FLOG(_L("KColourDataByAccessPointId command"));
       
   404 				*(udp->EndPtr()) += static_cast<TUint8>(providerInfo->iProviderInfo.APId());
       
   405 
       
   406 				// Update the udp headers and forward on
       
   407 				UpdateHeaders(ip4, udp);
       
   408 				iUpperReceiver->Process(aPdu);
       
   409 				}
       
   410 				break;
       
   411 
       
   412 		    default:
       
   413 			    __FLOG(_L("Unknown command - ignoring it"));
       
   414 			    aPdu.Free();
       
   415 			    // unknown command, just ignore this packet???
       
   416 		    }
       
   417 	    }
       
   418 	else
       
   419 	    {
       
   420         __FLOG(_L("Standard echo packet"));
       
   421         if (iTestSubscriber && !iTestSubscriber->IsEnabled())
       
   422         	{
       
   423         	__FLOG(_L("Bearer not available. Packet dropped."));
       
   424         	aPdu.Free();
       
   425         	return;
       
   426         	}
       
   427 
       
   428         // just echo the packet back to the original sender
       
   429 		// update the headers (addresses, checksums etc)
       
   430 		UpdateHeaders(ip4, udp);
       
   431 		// now process it (pass up the stack)
       
   432 		iUpperReceiver->Process(aPdu);
       
   433 		}
       
   434     }
       
   435 
       
   436 TInt CLegacyLoopbackBinder4::GetConfig(TBinderConfig& aConfig)
       
   437 /**
       
   438 Return IPv4 configuration information.
       
   439 
       
   440 Called from upper layer.
       
   441 
       
   442 @param aConfig structure to populate with IPv4 configuration
       
   443 */
       
   444 	{
       
   445     TBinderConfig4* config = TBinderConfig::Cast<TBinderConfig4>(aConfig);
       
   446     
       
   447 	if(config == NULL)
       
   448 		{
       
   449 		return KErrNotSupported;
       
   450 		}
       
   451 
       
   452 	// Setup config
       
   453 	config->iInfo.iFeatures = KIfCanBroadcast | KIfCanMulticast;
       
   454 	config->iInfo.iMtu = KLoopbackBearerMTU;
       
   455 	config->iInfo.iRMtu = KLoopbackBearerMTU;
       
   456 	config->iInfo.iSpeedMetric = 0;
       
   457 
       
   458 	config->iFamily = KAfInet6;
       
   459 
       
   460     TUint32 address;
       
   461 	const TInt KPort = 65;
       
   462 
       
   463     config->iFamily = KAfInet;
       
   464 
       
   465 	__FLOG_2(_L8("CLegacyLoopbackBinder4 %08x:\tGetConfig(): iLocalAddress %08x"), this, iLocalAddress);        
       
   466 	
       
   467 	config->iAddress.SetAddress(iLocalAddress);
       
   468 	config->iAddress.SetPort(KPort);
       
   469 
       
   470 	// network mask
       
   471 	config->iNetMask.SetAddress(KInetAddrNetMaskC);	// 255.255.255.0
       
   472 	config->iNetMask.SetPort(KPort);
       
   473 
       
   474 	// broadcast address
       
   475 	address = iLocalAddressBase + KBroadcastAddressSuffix;
       
   476 	config->iBrdAddr.SetAddress(address);
       
   477 	config->iBrdAddr.SetPort(KPort);
       
   478 
       
   479 	// default gateway
       
   480 	address = iLocalAddressBase + KDefaultGatewayAddressSuffix;
       
   481 	config->iDefGate.SetAddress(address);
       
   482 	config->iDefGate.SetPort(KPort);
       
   483 
       
   484 	// primary DNS, just make same as default gateway
       
   485 	config->iNameSer1.SetAddress(address);
       
   486 	config->iNameSer1.SetPort(KPort);
       
   487 
       
   488 	// secondary DNS
       
   489 	address = iLocalAddressBase + KSecondaryDnsAddressSuffix;
       
   490 	config->iNameSer2.SetAddress(address);
       
   491 	config->iNameSer2.SetPort(KPort);
       
   492 	
       
   493 	return KErrNone;
       
   494 	}
       
   495 
       
   496 TInt CLegacyLoopbackBinder4::Control(TUint aLevel, TUint aName, TDes8& aOption)
       
   497 /**
       
   498 Called from upper layer for special control functionality.
       
   499 */
       
   500 	{	
       
   501 	(void) aLevel;
       
   502 	(void) aName;
       
   503  	(void) aOption;
       
   504 	__FLOG_3(_L("CLegacyLoopbackBinder4 %08x:\tControl(aLevel %x, aName %x)"), this, aLevel, aName);
       
   505 	return KErrNotSupported;
       
   506 	}
       
   507 
       
   508 TInt CLegacyLoopbackBinder4::GetName(TDes& aName)
       
   509 /**
       
   510 Called from upper layer to retrieve the binder name.
       
   511 
       
   512 @param aName populated with name
       
   513 @return KErrNone on success, else a system wide error code.
       
   514 */
       
   515 	{
       
   516 	// This name matches the NIF-based DummyNif to match any potential
       
   517 	// test code expectations on the name.
       
   518 	aName.Format(_L("legacy_loopback[0x%08x]"), this);
       
   519 
       
   520 	__FLOG_2(_L("CLegacyLoopbackBinder4 %08x:\tGetName(): %S"), this, &aName);
       
   521 
       
   522 	return KErrNone;
       
   523 	}
       
   524 
       
   525 TInt CLegacyLoopbackBinder4::BlockFlow(MLowerControl::TBlockOption /*aOption*/)
       
   526 	{
       
   527     __FLOG_1(_L8("CLegacyLoopbackBinder4 %08x:\tBlockFlow()"), this);
       
   528 
       
   529 	return KErrNotSupported;
       
   530 	}
       
   531 
       
   532 TBool CLegacyLoopbackBinder4::MatchesUpperControl(ESock::MUpperControl* aUpperControl) const
       
   533 /**
       
   534 Utility function that returns whether this binder is associated with the
       
   535 MUpperControl object passed as argument.
       
   536 
       
   537 @param aUpperControl upper layer to match against
       
   538 @return ETrue on a match else EFalse.
       
   539 */
       
   540 	{
       
   541 	return aUpperControl == iUpperControl;
       
   542 	}
       
   543 
       
   544 
       
   545 CLegacyLoopbackBinder4::CDrvSender::CDrvSender(TInt aPriority)
       
   546 : CActive(aPriority)
       
   547 	{
       
   548 	CActiveScheduler::Add(this);
       
   549     __FLOG_OPEN(KNif, KBinder4);
       
   550 	}
       
   551 
       
   552 CLegacyLoopbackBinder4::CDrvSender::~CDrvSender()
       
   553 	{
       
   554 	Cancel();
       
   555 	do
       
   556 		{
       
   557 		iSendPkt.Free();
       
   558 		}
       
   559 	while(iSendQueue.Remove(iSendPkt));
       
   560     __FLOG_CLOSE;
       
   561 	}
       
   562 
       
   563 void CLegacyLoopbackBinder4::CDrvSender::Start(CLegacyLoopbackBinder4* aBinder, RLegacyLoopbackDriver aDrv)
       
   564 	{
       
   565 	iBinder = aBinder;
       
   566 	iDrv = aDrv;
       
   567 	}
       
   568 
       
   569 void CLegacyLoopbackBinder4::CDrvSender::RunL()
       
   570 	{
       
   571 	// Finished with the buffer just sent
       
   572 	iSendPkt.Free();
       
   573 
       
   574 	// Send the next packet waiting
       
   575 	SendPacket();
       
   576 	}
       
   577 
       
   578 void CLegacyLoopbackBinder4::CDrvSender::DoCancel()
       
   579 	{
       
   580 	iDrv.SendDataCancel();
       
   581 	}
       
   582 
       
   583 void CLegacyLoopbackBinder4::CDrvSender::SendPacket()
       
   584 	{
       
   585 	// Fetch packet to send
       
   586 	TBool havePktToSend = iSendQueue.Remove(iSendPkt);
       
   587 	
       
   588 	if(havePktToSend)
       
   589 		{
       
   590 		RMBuf* sendBuffer = NULL;
       
   591 
       
   592 		// If the packet is composed of more than one buffer then we log this and abandon the packet
       
   593 		if(iSendPkt.NumBufs() > 1)
       
   594 			{
       
   595 			__FLOG_VA((_L8("Warning: packet %d bytes %d buffers"), iSendPkt.Length(), iSendPkt.NumBufs() ));
       
   596 			iManyBufCount++;
       
   597 
       
   598 			// Copy out to a single buffer
       
   599 			sendBuffer = RMBuf::Alloc(KLoopbackBearerMTU, iBinder->iAllocator);
       
   600 			if(sendBuffer)
       
   601 				{
       
   602 				sendBuffer->SetLength(0);
       
   603 				RMBuf* currentBuf = iSendPkt.First();
       
   604 				while(currentBuf)
       
   605 					{
       
   606 					TPtr8 srcData(currentBuf->Ptr(), currentBuf->Length(), currentBuf->Length());
       
   607 					sendBuffer->Append(srcData);
       
   608 					currentBuf = currentBuf->Next();
       
   609 					}
       
   610 				}
       
   611 				iSendPkt.Free();
       
   612 				RMBufChain sendChain(sendBuffer);
       
   613 				iSendPkt.Assign(sendChain);
       
   614 			}
       
   615 		else
       
   616 			{
       
   617 			iOneBufCount++;
       
   618 			sendBuffer = iSendPkt.First();
       
   619 			}
       
   620 
       
   621 		// Send the buffer
       
   622 		if(sendBuffer)
       
   623 			{
       
   624 			TInt length(sendBuffer->Length());
       
   625 			TPtr8 txPtr(sendBuffer->Ptr(), length, length);
       
   626 			iDrv.SendData(iStatus, txPtr);
       
   627 			SetActive();
       
   628 			}
       
   629 		}
       
   630 	}
       
   631 
       
   632 void CLegacyLoopbackBinder4::CDrvSender::QueueForSend(RMBufPacket& aPkt)
       
   633 	{
       
   634 	aPkt.FreeInfo();
       
   635 	iSendQueue.Append(aPkt);
       
   636 	if(!IsActive())
       
   637 		{
       
   638 		SendPacket();
       
   639 		}
       
   640 	}
       
   641 	
       
   642 CLegacyLoopbackBinder4::CDrvReceiver::CDrvReceiver(TInt aPriority)
       
   643 : CActive(aPriority),
       
   644   iRxPtr(NULL, 0)
       
   645 	{
       
   646 	CActiveScheduler::Add(this);
       
   647 	iPond = TCommsBufPondTLSOp::Get();
       
   648 	}
       
   649 
       
   650 CLegacyLoopbackBinder4::CDrvReceiver::~CDrvReceiver()
       
   651 	{
       
   652 	Cancel();
       
   653 	}
       
   654 
       
   655 void CLegacyLoopbackBinder4::CDrvReceiver::Start(CLegacyLoopbackBinder4* aBinder, RLegacyLoopbackDriver aDrv)
       
   656 	{
       
   657 	iBinder = aBinder;
       
   658 	iDrv = aDrv;
       
   659 	RequestReceipt();
       
   660 	}
       
   661 
       
   662 void CLegacyLoopbackBinder4::CDrvReceiver::RequestReceipt()
       
   663 	{
       
   664 	ASSERT(iPkt.IsEmpty());
       
   665 	RMBuf* buf = RMBuf::Alloc(RLegacyLoopbackDriver::KLoopbackMTU);
       
   666 	if(buf)
       
   667 		{
       
   668 		RMBufQ q(buf);
       
   669 		TRAPD(ret, iPkt.CreateL(q));	// need non-leaving overload!
       
   670 		if(ret == KErrNone)
       
   671 			{
       
   672 			iPkt.Pack();
       
   673 			iRxPtr.Set(buf->Ptr(), 0, buf->Size());
       
   674 			}
       
   675 		else
       
   676 			{
       
   677 			// In a real version we could still strive to use the buf, even without the header
       
   678 			// But someday we'll be free of having the packet info as the magic extra buffer
       
   679 			// on the front & instead pass a concrete type in tandem: type safety & an end to
       
   680 			// all this pushing & popping
       
   681 			buf->Free();
       
   682 			buf = NULL;
       
   683 			}
       
   684 		}
       
   685 	if(!buf)
       
   686 		{
       
   687 		// No pre-built packet; copy through descriptor
       
   688 		iRxPtr.Set(iDesBuf.MidTPtr(0));
       
   689 		}
       
   690 
       
   691 	// Request the next received packet from the driver
       
   692 	iDrv.ReceiveData(iStatus, iRxPtr);
       
   693 	SetActive();
       
   694 	}
       
   695 
       
   696 void CLegacyLoopbackBinder4::CDrvReceiver::RunL()
       
   697 	{
       
   698 	TInt ret;
       
   699 	if(iPkt.IsEmpty())
       
   700 		{
       
   701 		TRAP(ret, iPkt.CreateL(iDesBuf));	// need non-leaving overload!
       
   702 		if(ret == KErrNone)
       
   703 			{
       
   704 			iPkt.Pack();
       
   705 			}
       
   706 		}
       
   707 	else
       
   708 		{
       
   709 		ret = KErrNone;
       
   710 		}
       
   711 	if(ret == KErrNone)
       
   712 		{
       
   713 		iBinder->ProcessPacket(iPkt);
       
   714 		ASSERT(iPkt.IsEmpty());
       
   715 		}
       
   716 	RequestReceipt();
       
   717 	}
       
   718 
       
   719 void CLegacyLoopbackBinder4::CDrvReceiver::DoCancel()
       
   720 	{
       
   721 	iDrv.ReceiveDataCancel();
       
   722 	}
       
   723 
       
   724 
       
   725 // =================================================================================
       
   726 //
       
   727 // CLegacyLoopbackBinder6
       
   728 
       
   729 CLegacyLoopbackBinder6::CLegacyLoopbackBinder6(CLegacyLoopbackSubConnectionFlow& aLegacyLoopbackSubConnectionFlow) : iLegacyLoopbackSubConnectionFlow(aLegacyLoopbackSubConnectionFlow)
       
   730 	{
       
   731     __FLOG_OPEN(KNif, KBinder6);
       
   732     __FLOG_2(_L8("CLegacyLoopbackBinder6 %08x:\tCLegacyLoopbackBinder6(CLegacyLoopbackSubConnectionFlow& %08x)"), this, &aLegacyLoopbackSubConnectionFlow);
       
   733 	}
       
   734 
       
   735 CLegacyLoopbackBinder6::~CLegacyLoopbackBinder6()
       
   736 /** 
       
   737 Destroys 'this'
       
   738 */
       
   739     {
       
   740     __FLOG(_L8("CLegacyLoopbackBinder6:\t~CLegacyLoopbackBinder6()"));
       
   741     __FLOG_CLOSE;
       
   742     }
       
   743 
       
   744 CLegacyLoopbackBinder6* CLegacyLoopbackBinder6::NewL(CLegacyLoopbackSubConnectionFlow& aLegacyLoopbackSubConnectionFlow)
       
   745 	{
       
   746 	return new (ELeave) CLegacyLoopbackBinder6(aLegacyLoopbackSubConnectionFlow);
       
   747 	}
       
   748 
       
   749 void CLegacyLoopbackBinder6::UpdateHeaders(TInet6HeaderIP* aIp6, TInet6HeaderUDP* /*aUdp*/)
       
   750     {
       
   751 	// swap over the destination and source addresses
       
   752 	TIp6Addr temp;
       
   753 	temp = aIp6->SrcAddr();
       
   754 	aIp6->SetSrcAddr(aIp6->DstAddr());
       
   755 	aIp6->SetDstAddr(temp);
       
   756     }
       
   757     
       
   758 MLowerDataSender::TSendResult CLegacyLoopbackBinder6::Send(RMBufChain& aData)
       
   759 /**
       
   760 Send IPv6 data
       
   761 
       
   762 Note: not clear that this is properly supported or used.
       
   763 
       
   764 @param aData data to send
       
   765 */
       
   766 	{
       
   767     __FLOG(_L8("CLegacyLoopbackBinder6:\tSend()"));
       
   768 
       
   769    	// Loop the data straight back into the TCP/IP stack
       
   770 	ProcessPacket(aData);
       
   771 	return ESendAccepted;
       
   772 	}
       
   773 	
       
   774 MLowerDataSender* CLegacyLoopbackBinder6::Bind(MUpperDataReceiver& aUpperReceiver, MUpperControl& aUpperControl)
       
   775 	{
       
   776     __FLOG_2(_L8("CLegacyLoopbackBinder6:\tBind(MUpperDataReceiver %08x, MUpperControl %08x)"), &aUpperReceiver, &aUpperControl);
       
   777 
       
   778 	iUpperReceiver = &aUpperReceiver;
       
   779 	iUpperControl = &aUpperControl;
       
   780 	
       
   781 	// Signal upper layer that we are ready
       
   782 	BinderReady();
       
   783 	
       
   784 	return this;
       
   785 	}
       
   786 
       
   787 void CLegacyLoopbackBinder6::BinderReady()
       
   788 /**
       
   789 Signal to upper layer that we are ready
       
   790 */
       
   791     {
       
   792     __FLOG(_L8("CLegacyLoopbackBinder6:\tBinderReady()"));
       
   793 
       
   794 	iUpperControl->StartSending();
       
   795     }
       
   796 
       
   797 void CLegacyLoopbackBinder6::ProcessPacket(RMBufChain& aPdu)
       
   798 /**
       
   799 Process incoming IPv6 packets.
       
   800 
       
   801 Note: not clear that this is properly supported or used.
       
   802 
       
   803 @param aPdu incoming data packet
       
   804 */
       
   805     {
       
   806     __FLOG(_L8("CLegacyLoopbackBinder6:\tProcessPacket()"));
       
   807 
       
   808 	// this received data has already been looped back...
       
   809 	// get the ip header from the RMBufChain
       
   810 	TInet6HeaderIP* ip6 = (TInet6HeaderIP*) aPdu.First()->Next()->Ptr();
       
   811 	TInet6HeaderUDP* udp = NULL;
       
   812 
       
   813 	if ((TUint)ip6->NextHeader() == KProtocolInetUdp)
       
   814 		{
       
   815 		// get the udp header as well - assume only udp traffic here
       
   816 		udp = (TInet6HeaderUDP*) ip6->EndPtr();
       
   817 
       
   818 		__FLOG_3(_L("CLegacyLoopbackBinder6:\tProcessPacket(...): UDP length %d, src port %d, dst port %d"),
       
   819 			udp->Length(), udp->SrcPort(), udp->DstPort());
       
   820 
       
   821 		// depending on the contents, pass it on up thru the stack 
       
   822 		// or maybe do something else
       
   823 
       
   824 		// use the destination port number to decide whether or not the payload is a command
       
   825 		TUint dstPort = udp->DstPort();
       
   826 		if (KLegacyLoopbackCmdPort == dstPort)
       
   827             {
       
   828  			// let's use the first payload byte as the command byte
       
   829 			switch (*(udp->EndPtr()))
       
   830 				{
       
   831 			case KForceDisconnect:
       
   832 				__FLOG(_L("KForceDisconnect command"));
       
   833 				// do some action
       
   834 	            Flow()->Progress(KLinkLayerClosed, KErrCommsLineFail);
       
   835 
       
   836 	            Flow()->FlowDown(KErrCommsLineFail, MNifIfNotify::EDisconnect);
       
   837 
       
   838 				// no return code so all we can do is respond with what we got
       
   839 				UpdateHeaders(ip6, udp);
       
   840 				iUpperReceiver->Process(aPdu);
       
   841 				break;
       
   842 
       
   843 			case KForceReconnect:
       
   844 				__FLOG(_L("KForceReconnect command"));
       
   845 				// do some action
       
   846 	            Flow()->Progress(KLinkLayerClosed, KErrCommsLineFail);
       
   847 
       
   848                 //cause.iReserved=MNifIfNotify::EReconnect;
       
   849 	            Flow()->FlowDown(KErrCommsLineFail);
       
   850 
       
   851 				// no return code so all we can do is respond with what we got
       
   852 				UpdateHeaders(ip6, udp);
       
   853 				iUpperReceiver->Process(aPdu);
       
   854 				break;
       
   855 
       
   856 			case KSendNotification:
       
   857 				__FLOG(_L("KSendNotification command"));
       
   858 			    //let's write the result in the next byte of the reply
       
   859 			    if (Flow()->AgentProvision()->IsDialIn() == KErrNotSupported)
       
   860 				    udp->EndPtr()[1] = (unsigned char) KErrNone;
       
   861 			    else
       
   862 				    udp->EndPtr()[1] = (unsigned char) KErrGeneral; // this will lose it's sign :-(
       
   863 			
       
   864 				UpdateHeaders(ip6, udp);
       
   865                 iUpperReceiver->Process(aPdu);
       
   866 			    break;
       
   867 
       
   868 
       
   869 			default:
       
   870 				__FLOG(_L("Unknown command - ignoring it"));
       
   871 				break;
       
   872 				// unknown command, just ignore this packet???
       
   873 				}
       
   874 			return;
       
   875 			}
       
   876 
       
   877 		}
       
   878 	else
       
   879 		{
       
   880 		__FLOG_2(_L("CLegacyLoopbackBinder6:\tProcessPacket(...): IPv6 length %d, next header %d"),
       
   881 			ip6->PayloadLength(), ip6->NextHeader());
       
   882 		}
       
   883 
       
   884 	// just echo the packet back to the original sender
       
   885 
       
   886 	// update the headers (addresses, checksums etc).  If "udp" is non-NULL, then
       
   887 	// the UDP ports will be updated as well.
       
   888 	UpdateHeaders(ip6, udp);
       
   889 	// now process it (pass up the stack)
       
   890 	iUpperReceiver->Process(aPdu);		
       
   891     }
       
   892 
       
   893 void CLegacyLoopbackBinder6::Unbind(MUpperDataReceiver& aUpperReceiver, MUpperControl& aUpperControl)
       
   894 	{
       
   895     static_cast<void>(aUpperReceiver);
       
   896     static_cast<void>(aUpperControl);
       
   897     __FLOG(_L8("CLegacyLoopbackBinder6:\tUnbind()"));
       
   898 
       
   899     ASSERT(&aUpperReceiver == iUpperReceiver);
       
   900     ASSERT(&aUpperControl == iUpperControl);
       
   901     iUpperReceiver = NULL;
       
   902     iUpperControl = NULL;
       
   903 	}
       
   904 	
       
   905 TInt CLegacyLoopbackBinder6::GetName(TDes& aName)
       
   906 /**
       
   907 Called from upper layer to retrieve the binder name.
       
   908 
       
   909 @param aName populated with name
       
   910 @return KErrNone on success, else a system wide error code.
       
   911 */
       
   912 	{
       
   913     __FLOG(_L8("CLegacyLoopbackBinder6:\tGetName()"));
       
   914 
       
   915 	// This name matches the NIF-based DummyNif to match any potential
       
   916 	// test code expectations on the name.
       
   917 	aName.Format(_L("legacy_loopback6[0x%08x]"), this);
       
   918 	
       
   919 	return KErrNone;
       
   920 	}
       
   921 
       
   922 TInt CLegacyLoopbackBinder6::BlockFlow(MLowerControl::TBlockOption /*aOption*/)
       
   923 	{
       
   924     __FLOG(_L8("CLegacyLoopbackBinder6:\tBlockFlow()"));
       
   925 
       
   926 	return KErrNotSupported;
       
   927 	}
       
   928 
       
   929 void CLegacyLoopbackBinder6::StaticDnsConfiguration(TBinderConfig6& aConfig)
       
   930 	{
       
   931     __FLOG(_L8("CLegacyLoopbackBinder6:\tStaticDnsConfiguration()"));
       
   932 
       
   933 	const TLegacyLoopbackIp6Provision* ip6Provision = Flow()->Ip6Provision();
       
   934 
       
   935 	if (!ip6Provision->Ip6DNSAddrFromServer()) 
       
   936 		{
       
   937         aConfig.iNameSer1.SetAddress(ip6Provision->Ip6NameServer1());
       
   938         aConfig.iNameSer2.SetAddress(ip6Provision->Ip6NameServer2());
       
   939 		}
       
   940 	else
       
   941 		{
       
   942 		// Ensure that static DNS addresses are set as unspecified,
       
   943 		// so they are not used in Control(KSoIfConfig).
       
   944         aConfig.iNameSer1.SetAddress(KInet6AddrNone);
       
   945         aConfig.iNameSer2.SetAddress(KInet6AddrNone);
       
   946 		}
       
   947 	}
       
   948 
       
   949 TInt CLegacyLoopbackBinder6::GetConfig(TBinderConfig& aConfig)
       
   950 /**
       
   951 Return IPv6 configuration information.
       
   952 
       
   953 Called from upper layer.
       
   954 
       
   955 @param aConfig structure to populate with IPv6 configuration
       
   956 */
       
   957 	{
       
   958     TBinderConfig6* config = TBinderConfig::Cast<TBinderConfig6>(aConfig);
       
   959     
       
   960 	if(config == NULL)
       
   961 		{
       
   962 		return KErrNotSupported;
       
   963 		}
       
   964 		
       
   965 	// Setup config
       
   966 	config->iInfo.iFeatures = KIfCanBroadcast | KIfCanMulticast;;
       
   967 	config->iInfo.iMtu = KLoopbackBearerMTU;
       
   968 	config->iInfo.iRMtu = KLoopbackBearerMTU;
       
   969 	config->iInfo.iSpeedMetric = 0;
       
   970 	
       
   971 	// Setup addresses 
       
   972 	
       
   973 	config->iFamily = KAfInet6;
       
   974 	
       
   975 	// Local ID
       
   976 	
       
   977 	TInt addr64 = 0x80;
       
   978 	TE64Addr localAddr(addr64);
       
   979 	TEui64Addr* id = (TEui64Addr*) &config->iLocalId;
       
   980 	
       
   981 	id->Init();
       
   982 	id->SetAddress(localAddr);
       
   983 	
       
   984 	// Remote ID
       
   985 	addr64 = 0x81;
       
   986 	TE64Addr remoteAddr(addr64);
       
   987 	id = (TEui64Addr*) &config->iRemoteId;
       
   988 	
       
   989 	id->Init();
       
   990 	id->SetAddress(remoteAddr);
       
   991 	
       
   992 	// Setup static DNS address if required
       
   993 	StaticDnsConfiguration(*config);
       
   994 	    
       
   995     return KErrNone;
       
   996     }
       
   997 
       
   998 TInt CLegacyLoopbackBinder6::Control(TUint aLevel, TUint aName, TDes8& aOption)
       
   999 	{
       
  1000 	(void) aLevel;
       
  1001 	(void) aName;
       
  1002 	(void) aOption;
       
  1003 	__FLOG_2(_L("CLegacyLoopbackBinder6:\tControl(aLevel %x, aName %x, ...)"), aLevel, aName);
       
  1004 	return KErrNotSupported;
       
  1005 	}
       
  1006 
       
  1007 //
       
  1008 // Utilities
       
  1009 //
       
  1010 
       
  1011 TBool CLegacyLoopbackBinder6::MatchesUpperControl(ESock::MUpperControl* aUpperControl) const
       
  1012 /**
       
  1013 Utility function that returns whether this binder is associated with the
       
  1014 MUpperControl object passed as argument.
       
  1015 
       
  1016 @param aUpperControl upper layer to match against
       
  1017 @return ETrue on a match else EFalse.
       
  1018 */
       
  1019 	{
       
  1020 	return aUpperControl == iUpperControl;
       
  1021 	}
       
  1022 
       
  1023 //
       
  1024 // Async error callback
       
  1025 //
       
  1026 // Used to schedule asynchronous signalling of a binder error to upper flow in circumstances
       
  1027 // where a direct call is not possible (e.g. in the middle of a TCP/IP send as the binder
       
  1028 // may disappear underneath the TCP/IP stack).
       
  1029 
       
  1030 CLegacyLoopbackErrorOneShot::CLegacyLoopbackErrorOneShot()
       
  1031   : CAsyncOneShot(EPriorityStandard)
       
  1032 	{
       
  1033 	}
       
  1034 
       
  1035 void CLegacyLoopbackErrorOneShot::Schedule(MUpperControl* aUpperControl)
       
  1036 	{
       
  1037 	iUpperControl = aUpperControl;
       
  1038 	Call();
       
  1039 	}
       
  1040 
       
  1041 void CLegacyLoopbackErrorOneShot::RunL()
       
  1042 	{
       
  1043 	iUpperControl->Error(KErrCommsLineFail);
       
  1044 	}
       
  1045 
       
  1046 
       
  1047 CLegacyLoopbackFlowTestingSubscriber::CLegacyLoopbackFlowTestingSubscriber(CLegacyLoopbackSubConnectionFlow& aFlow, TUint aApId)
       
  1048 	: CActive(0),
       
  1049 	iFlow(aFlow),
       
  1050 	iApId(aApId)
       
  1051 	{
       
  1052 	}
       
  1053 
       
  1054 /*static*/ TBool CLegacyLoopbackFlowTestingSubscriber::ShouldRun(TUint aApId)
       
  1055 	{
       
  1056 	RProperty property;
       
  1057 	TInt result = property.Attach(KLegacyLoopbackTestingPubSubUid, aApId);
       
  1058 	if(result == KErrNone)
       
  1059 		{
       
  1060 		TInt propertyValue;
       
  1061 		result = property.Get(propertyValue);
       
  1062 		if(result == KErrNone)
       
  1063 			{
       
  1064 			return ETrue;
       
  1065 			}
       
  1066 		}
       
  1067 	return EFalse;
       
  1068 	}
       
  1069 
       
  1070 void CLegacyLoopbackFlowTestingSubscriber::ConstructL()
       
  1071 	{
       
  1072 	CActiveScheduler::Add(this);
       
  1073 //	__DECLARE_NAME(_S("CAvailabilityTestingSubscriber"));
       
  1074 
       
  1075 	TInt result = iProperty.Attach(KLegacyLoopbackTestingPubSubUid, iApId);
       
  1076 	ASSERT(result == KErrNone);
       
  1077 
       
  1078 	RunL();
       
  1079 	}
       
  1080 
       
  1081 void CLegacyLoopbackFlowTestingSubscriber::RunL()
       
  1082 	{
       
  1083 	// .. and repeat..
       
  1084 	iProperty.Subscribe(iStatus);
       
  1085 	
       
  1086 	TInt publishedValue;
       
  1087 	TInt result = iProperty.Get(publishedValue);
       
  1088 	ASSERT(result == KErrNone);
       
  1089 
       
  1090 	TAvailabilityStatus av(publishedValue);
       
  1091 	if (av.Score())
       
  1092 		{
       
  1093 		iIsEnabled = ETrue;
       
  1094 		iFlow.iDisableStart = EFalse;
       
  1095 		}
       
  1096 	else
       
  1097 		{
       
  1098 		iIsEnabled = EFalse;
       
  1099 		iFlow.iDisableStart = ETrue;
       
  1100 		}
       
  1101 
       
  1102 	SetActive();
       
  1103 	}
       
  1104 
       
  1105 void CLegacyLoopbackFlowTestingSubscriber::DoCancel()
       
  1106 	{
       
  1107 	iProperty.Cancel();
       
  1108 	}
       
  1109 
       
  1110 /*virtual*/ CLegacyLoopbackFlowTestingSubscriber::~CLegacyLoopbackFlowTestingSubscriber()
       
  1111 	{
       
  1112 	this->Cancel(); // object must be stoppable by descruction due to cleanup restrictions
       
  1113 	iProperty.Close();
       
  1114 	}
       
  1115 
       
  1116 
       
  1117