networkingtestandutils/networkingunittest/DummyNifProtos/src/Dummynifbinder.cpp
changeset 0 af10295192d8
child 5 1422c6cd3f0c
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 // Implementation file for the NIF Protocol2
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file DummyNifBinder.cpp
       
    20 */
       
    21 
       
    22 #include <e32std.h>
       
    23 #include <eui_addr.h>
       
    24 #include <ip4_hdr.h>
       
    25 #include <udp_hdr.h>
       
    26 #include <in_chk.h>
       
    27 #include <in_iface.h>
       
    28 #include <comms-infras/nifif.h>
       
    29 #include <in_sock.h>
       
    30 #include "dummynifvar.h"
       
    31 #include "Dummynifbinder.h"
       
    32 #include "DummyProvision.h"
       
    33 
       
    34 using namespace ESock;
       
    35 
       
    36 _LIT8(KNif,"DummyNif");
       
    37 _LIT8(KBinder4,"Binder4");
       
    38 _LIT8(KBinder6,"Binder6");
       
    39 
       
    40 //
       
    41 // CDummyNifBinder4 //
       
    42 //
       
    43 
       
    44 CDummyNifBinder4::CDummyNifBinder4(CDummyNifSubConnectionFlow& aDummyNifSubConnectionFlow) : iDummyNifSubConnectionFlow(aDummyNifSubConnectionFlow)
       
    45 	{
       
    46     __FLOG_OPEN(KNif, KBinder4);
       
    47    	// generate my local ip address (ip4) - vals potentially will be overwritten by any derived classes
       
    48 	iLocalAddressBase = KDummyNifLocalAddressBase; // also used later in control method
       
    49 	
       
    50 	TUint32 id = ((TUint32)this) % 255;
       
    51 	// Avoid the reserved address (least significant byte KDummyHungryNifReservedHostId) that
       
    52 	// is never to be allocated as a local address.
       
    53 	if (id == KDummyHungryNifReservedHostId)
       
    54 		{
       
    55 		++id;
       
    56 		}
       
    57 	iLocalAddress = iLocalAddressBase + id;
       
    58     __FLOG_3(_L8("CDummyNifBinder4 %08x:\tCDummyNifBinder4(CDummyNifSubConnectionFlow& %08x): iLocalAddress %08x"), this, &aDummyNifSubConnectionFlow, iLocalAddress);
       
    59 }
       
    60 
       
    61 CDummyNifBinder4::~CDummyNifBinder4()
       
    62 /** 
       
    63 Destroys 'this'
       
    64 */
       
    65     {
       
    66     if (iTestSubscriber)
       
    67     	{
       
    68     	iTestSubscriber->Cancel();
       
    69     	}
       
    70     delete iTestSubscriber;
       
    71     
       
    72     __FLOG_1(_L8("CDummyNifBinder4 %08x:\t~CDummyNifBinder4()"), this);
       
    73     ASSERT(iUpperControl == NULL);
       
    74     ASSERT(iUpperReceiver == NULL);
       
    75 	ASSERT(!iErrorOneShot.IsActive());
       
    76     __FLOG_CLOSE;
       
    77     }
       
    78 
       
    79 CDummyNifBinder4* CDummyNifBinder4::NewL(CDummyNifSubConnectionFlow& aDummyNifSubConnectionFlow)
       
    80 	{
       
    81 	CDummyNifBinder4* self = new (ELeave) CDummyNifBinder4(aDummyNifSubConnectionFlow);
       
    82 	CleanupStack::PushL(self);
       
    83 	
       
    84 	const TProviderInfo& providerInfo = static_cast<const TProviderInfoExt&>(
       
    85 		aDummyNifSubConnectionFlow.AccessPointConfig().FindExtensionL(
       
    86 			STypeId::CreateSTypeId(TProviderInfoExt::EUid, TProviderInfoExt::ETypeId))).iProviderInfo;
       
    87 	TInt ap = providerInfo.APId();
       
    88 	if (CDummyNifFlowTestingSubscriber::ShouldRun(ap))
       
    89 		{
       
    90 		ASSERT(self->iTestSubscriber==NULL);
       
    91 		self->iTestSubscriber = CDummyNifFlowTestingSubscriber::NewL(aDummyNifSubConnectionFlow, ap);
       
    92 		}
       
    93 
       
    94 	CleanupStack::Pop(self);
       
    95 	return self;
       
    96 	}
       
    97 
       
    98 void CDummyNifBinder4::UpdateHeaders(TInet6HeaderIP4* aIp4, TInet6HeaderUDP* aUdp)
       
    99 /**
       
   100 Update the IPv4 and UDP headers to allow the packet to be looped back.
       
   101 */
       
   102 {
       
   103 	// swap over the destination and source addresses
       
   104 	TUint32 temp;
       
   105 	temp = aIp4->SrcAddr();
       
   106 	aIp4->SetSrcAddr(aIp4->DstAddr());
       
   107 	aIp4->SetDstAddr(temp);
       
   108 
       
   109    	// swap over the destination and source ports
       
   110 	if (aUdp)
       
   111 		{
       
   112 		TUint tempPort;
       
   113 		tempPort = aUdp->DstPort();
       
   114 		aUdp->SetDstPort(aUdp->SrcPort());
       
   115 		aUdp->SetSrcPort(tempPort);
       
   116 		}
       
   117 
       
   118 	// we've changed the ip hdr so need to recalculate the ip hdr checksum
       
   119 	aIp4->SetChecksum(0); 
       
   120 	aIp4->SetChecksum(TChecksum::ComplementedFold(TChecksum::Calculate((TUint16*)aIp4, aIp4->HeaderLength())));
       
   121 
       
   122 	// also want to set the udp checksum to zero cos it will be wrong now that we have 
       
   123 	// changed the ip hdr - just set to zero and it is ignored
       
   124 	if (aUdp)
       
   125 		{
       
   126 		aUdp->SetChecksum(0);
       
   127 		}
       
   128 }
       
   129     
       
   130 MLowerDataSender::TSendResult CDummyNifBinder4::Send(RMBufChain& aData)
       
   131 /**
       
   132 Entry point for receiving IPv4 outgoing data
       
   133 
       
   134 @param aData MBuf chain containing data to send
       
   135 @return an indication of whether the upper layer should block.
       
   136 */
       
   137 	{
       
   138     __FLOG_1(_L8("CDummyNifBinder4 %08x:\tSend()"), this);
       
   139 
       
   140 	// Loop the data straight back into the TCP/IP stack
       
   141 	ProcessPacket(aData);
       
   142 	return ESendAccepted;
       
   143 	}
       
   144 	
       
   145 MLowerDataSender* CDummyNifBinder4::Bind(MUpperDataReceiver& aUpperReceiver, MUpperControl& aUpperControl)
       
   146 /**
       
   147 Return the MLowerDataSender instance (CDummyNifBinder4) that we
       
   148 previously allocated.
       
   149 */
       
   150 	{
       
   151     __FLOG_3(_L8("CDummyNifBinder4 %08x:\tBind(aUpperReceiver %08x, aUpperControl %08x)"), this, &aUpperReceiver, &aUpperControl);
       
   152 	iUpperReceiver = &aUpperReceiver;
       
   153 	iUpperControl = &aUpperControl;
       
   154 
       
   155 	// Signal upper layer that we are ready
       
   156 	BinderReady();
       
   157 
       
   158 	return this;
       
   159 	}
       
   160 	
       
   161 void CDummyNifBinder4::Unbind(MUpperDataReceiver& aUpperReceiver, MUpperControl& aUpperControl)
       
   162 /**
       
   163 Forget our association with upper layer.
       
   164 */
       
   165 	{
       
   166     static_cast<void>(aUpperReceiver);
       
   167     static_cast<void>(aUpperControl);
       
   168     __FLOG_1(_L8("CDummyNifBinder4 %08x:\tUnbind()"), this);
       
   169     ASSERT(&aUpperReceiver == iUpperReceiver);
       
   170     ASSERT(&aUpperControl == iUpperControl);
       
   171     iUpperReceiver = NULL;
       
   172     iUpperControl = NULL;
       
   173 	}
       
   174 	
       
   175 void CDummyNifBinder4::BinderReady()
       
   176 /**
       
   177 Signal upper layer that we are ready
       
   178 */
       
   179 	{
       
   180     __FLOG_1(_L8("CDummyNifBinder4 %08x:\tBinderReady()"), this);
       
   181 
       
   182 	iUpperControl->StartSending();
       
   183 	}
       
   184 
       
   185 void CDummyNifBinder4::ProcessPacket(RMBufChain& aPdu)
       
   186 /**
       
   187 Process incoming data
       
   188 */
       
   189     {
       
   190 	// this received data has already been looped back...
       
   191 	// get the ip header from the RMBufChain
       
   192 	TInet6HeaderIP4* ip4 = (TInet6HeaderIP4*) aPdu.First()->Next()->Ptr();
       
   193 
       
   194 	if (ip4->Protocol() != KProtocolInetUdp)
       
   195 		{
       
   196 		//Non UDP traffic goes here!
       
   197 		__FLOG_3(_L("CDummyNifBinder4 %08x:\tProcessPacket(): IPv4 length %d, protocol %d"), this, ip4->TotalLength(), ip4->Protocol());
       
   198 
       
   199 		UpdateHeaders(ip4, NULL);
       
   200 		// now process it (pass up the stack)
       
   201 		iUpperReceiver->Process(aPdu);
       
   202 		return;
       
   203 		}
       
   204 
       
   205 	// get the udp header as well - assume only udp traffic here
       
   206 	TInet6HeaderUDP* udp = (TInet6HeaderUDP*) ip4->EndPtr();
       
   207 	__FLOG_4(_L("CDummyNifBinder4 %08x:\tProcessPacket(): UDP length %d, src port %d, dst port %d"), this, udp->Length(), udp->SrcPort(), udp->DstPort());
       
   208 
       
   209 	// depending on the contents, pass it on up thru the stack 
       
   210 	// or maybe do something else
       
   211 
       
   212 	// use the destination port number to decide whether or not the payload is a command
       
   213 	TUint dstPort = udp->DstPort();
       
   214 	if (KDummyNifCmdPort == dstPort)
       
   215     	{
       
   216 		// let's use the first payload byte as the command byte
       
   217 		switch (*(udp->EndPtr()))
       
   218     		{
       
   219 		    case KForceDisconnect:
       
   220 			    __FLOG(_L("KForceDisconnect command"));
       
   221 			    // do some action
       
   222 	            Flow()->Progress(KLinkLayerClosed, KErrCommsLineFail);
       
   223 
       
   224 	            Flow()->FlowDown(KErrCommsLineFail, MNifIfNotify::EDisconnect);
       
   225 
       
   226 			    // no return code so all we can do is respond with what we got
       
   227 			    UpdateHeaders(ip4, udp);
       
   228 			    iUpperReceiver->Process(aPdu);
       
   229 			    break;
       
   230 
       
   231 		    case KForceReconnect:
       
   232 			    __FLOG(_L("KForceReconnect command"));
       
   233 			    // do some action
       
   234 	            Flow()->Progress(KLinkLayerClosed, KErrCommsLineFail);
       
   235 	            
       
   236 	            Flow()->FlowDown(KErrCommsLineFail, MNifIfNotify::EReconnect);
       
   237 
       
   238 			    // no return code so all we can do is respond with what we got
       
   239 			    UpdateHeaders(ip4, udp);
       
   240 			    iUpperReceiver->Process(aPdu);
       
   241 			    break;
       
   242 
       
   243 		    case KSendNotification:
       
   244 			    __FLOG(_L("KSendNotification command"));
       
   245 			    //let's write the result in the next byte of the reply
       
   246 			    if (Flow()->AgentProvision()->IsDialIn() == KErrNotSupported)
       
   247 				    udp->EndPtr()[1] = (unsigned char) KErrNone;
       
   248 			    else
       
   249 				    udp->EndPtr()[1] = (unsigned char) KErrGeneral; // this will lose it's sign :-(
       
   250 			
       
   251 			    UpdateHeaders(ip4, udp);
       
   252                 iUpperReceiver->Process(aPdu);
       
   253 			    break;
       
   254 			    
       
   255 			case KForceFinishedSelection:
       
   256 				__FLOG(_L("KForceFinishedSelection command"));
       
   257 				// force subConn into KFinishedSelection State
       
   258 	            Flow()->Progress(KFinishedSelection, KErrNone);
       
   259 				UpdateHeaders(ip4, udp);
       
   260 				aPdu.Free();
       
   261 				break;
       
   262 
       
   263     		case KForceBinderError:
       
   264 			    __FLOG(_L("KForceBinderError command"));
       
   265 				// We cannot signal an error whilst in the middle of a send in the TCP/IP stack,
       
   266 				// as the act of signalling the error will eventually result in the CNifIfBase binder
       
   267 				// being destructed by the TCP/IP stack whilst we're in the middle of using it.
       
   268 				// Consequently, we would panic on exit from this routine.  So make the call
       
   269 				// via an asynchronous callback.
       
   270 				if (!iErrorOneShot.IsActive())
       
   271 					{
       
   272 					iErrorOneShot.Schedule(iUpperControl);
       
   273 					}
       
   274     			aPdu.Free();
       
   275     			break;
       
   276 
       
   277     		case KColourDataByLinkTierAccessPointId:
       
   278 				{
       
   279 				const TProviderInfoExt* providerInfo = static_cast<const TProviderInfoExt*>(
       
   280 					iDummyNifSubConnectionFlow.AccessPointConfig().FindExtension(
       
   281 						STypeId::CreateSTypeId(TProviderInfoExt::EUid, TProviderInfoExt::ETypeId)));
       
   282 				ASSERT(providerInfo); // Should always be present
       
   283 
       
   284 				// We are going to simply add the access point id to the command byte
       
   285 				// A test client can then validate that the socket is connected on the expected access point
       
   286 			    __FLOG(_L("KColourDataByAccessPointId command"));
       
   287 				*(udp->EndPtr()) += static_cast<TUint8>(providerInfo->iProviderInfo.APId());
       
   288 
       
   289 				// Update the udp headers and forward on
       
   290 				UpdateHeaders(ip4, udp);
       
   291 				iUpperReceiver->Process(aPdu);
       
   292 				}
       
   293 				break;
       
   294 
       
   295 		    default:
       
   296 			    __FLOG(_L("Unknown command - ignoring it"));
       
   297 			    aPdu.Free();
       
   298 			    // unknown command, just ignore this packet???
       
   299 		    }
       
   300 	    }
       
   301 	else
       
   302 	    {
       
   303         __FLOG(_L("Standard echo packet"));
       
   304         if (iTestSubscriber && !iTestSubscriber->IsEnabled())
       
   305         	{
       
   306         	__FLOG(_L("Bearer not available. Packet dropped."));
       
   307         	aPdu.Free();
       
   308         	return;
       
   309         	}
       
   310 
       
   311         // just echo the packet back to the original sender
       
   312 		// update the headers (addresses, checksums etc)
       
   313 		UpdateHeaders(ip4, udp);
       
   314 		// now process it (pass up the stack)
       
   315 		iUpperReceiver->Process(aPdu);
       
   316 		}
       
   317     }
       
   318 
       
   319 TInt CDummyNifBinder4::GetConfig(TBinderConfig& aConfig)
       
   320 /**
       
   321 Return IPv4 configuration information.
       
   322 
       
   323 Called from upper layer.
       
   324 
       
   325 @param aConfig structure to populate with IPv4 configuration
       
   326 */
       
   327 	{
       
   328     TBinderConfig4* config = TBinderConfig::Cast<TBinderConfig4>(aConfig);
       
   329     
       
   330 	if(config == NULL)
       
   331 		{
       
   332 		return KErrNotSupported;
       
   333 		}
       
   334 
       
   335 	// Setup config
       
   336 	config->iInfo.iFeatures = KIfCanBroadcast | KIfCanMulticast;
       
   337 	config->iInfo.iMtu = 1500;
       
   338 	config->iInfo.iRMtu = 1500;
       
   339 	config->iInfo.iSpeedMetric = 0;
       
   340 
       
   341 	config->iFamily = KAfInet6;
       
   342 
       
   343     TUint32 address;
       
   344 	const TInt KPort = 65;
       
   345 
       
   346     config->iFamily = KAfInet;
       
   347 
       
   348 	__FLOG_2(_L8("CDummyNifBinder4 %08x:\tGetConfig(): iLocalAddress %08x"), this, iLocalAddress);        
       
   349 	
       
   350 	config->iAddress.SetAddress(iLocalAddress);
       
   351 	config->iAddress.SetPort(KPort);
       
   352 
       
   353 	// network mask
       
   354 	config->iNetMask.SetAddress(KInetAddrNetMaskC);	// 255.255.255.0
       
   355 	config->iNetMask.SetPort(KPort);
       
   356 
       
   357 	// broadcast address
       
   358 	address = iLocalAddressBase + KBroadcastAddressSuffix;
       
   359 	config->iBrdAddr.SetAddress(address);
       
   360 	config->iBrdAddr.SetPort(KPort);
       
   361 
       
   362 	// default gateway
       
   363 	address = iLocalAddressBase + KDefaultGatewayAddressSuffix;
       
   364 	config->iDefGate.SetAddress(address);
       
   365 	config->iDefGate.SetPort(KPort);
       
   366 
       
   367 	// primary DNS, just make same as default gateway
       
   368 	config->iNameSer1.SetAddress(address);
       
   369 	config->iNameSer1.SetPort(KPort);
       
   370 
       
   371 	// secondary DNS
       
   372 	address = iLocalAddressBase + KSecondaryDnsAddressSuffix;
       
   373 	config->iNameSer2.SetAddress(address);
       
   374 	config->iNameSer2.SetPort(KPort);
       
   375 	
       
   376 	return KErrNone;
       
   377 	}
       
   378 
       
   379 TInt CDummyNifBinder4::Control(TUint aLevel, TUint aName, TDes8& aOption)
       
   380 /**
       
   381 Called from upper layer for special control functionality.
       
   382 */
       
   383 	{
       
   384     static_cast<void> (aOption);
       
   385 	__FLOG_3(_L("CDummyNifBinder4 %08x:\tControl(aLevel %x, aName %x)"), this, aLevel, aName);
       
   386 	return KErrNotSupported;
       
   387 	}
       
   388 
       
   389 TInt CDummyNifBinder4::GetName(TDes& aName)
       
   390 /**
       
   391 Called from upper layer to retrieve the binder name.
       
   392 
       
   393 @param aName populated with name
       
   394 @return KErrNone on success, else a system wide error code.
       
   395 */
       
   396 	{
       
   397 	// This name matches the NIF-based DummyNif to match any potential
       
   398 	// test code expectations on the name.
       
   399 	aName.Format(_L("dummynif[0x%08x]"), this);
       
   400 
       
   401 	__FLOG_2(_L("CDummyNifBinder4 %08x:\tGetName(): %S"), this, &aName);
       
   402 
       
   403 	return KErrNone;
       
   404 	}
       
   405 
       
   406 TInt CDummyNifBinder4::BlockFlow(MLowerControl::TBlockOption /*aOption*/)
       
   407 	{
       
   408     __FLOG_1(_L8("CDummyNifBinder4 %08x:\tBlockFlow()"), this);
       
   409 
       
   410 	return KErrNotSupported;
       
   411 	}
       
   412 
       
   413 TBool CDummyNifBinder4::MatchesUpperControl(ESock::MUpperControl* aUpperControl) const
       
   414 /**
       
   415 Utility function that returns whether this binder is associated with the
       
   416 MUpperControl object passed as argument.
       
   417 
       
   418 @param aUpperControl upper layer to match against
       
   419 @return ETrue on a match else EFalse.
       
   420 */
       
   421 	{
       
   422 	return aUpperControl == iUpperControl;
       
   423 	}
       
   424 
       
   425 // =================================================================================
       
   426 //
       
   427 // CDummyNifBinder6
       
   428 
       
   429 CDummyNifBinder6::CDummyNifBinder6(CDummyNifSubConnectionFlow& aDummyNifSubConnectionFlow) : iDummyNifSubConnectionFlow(aDummyNifSubConnectionFlow)
       
   430 	{
       
   431     __FLOG_OPEN(KNif, KBinder6);
       
   432     __FLOG_2(_L8("CDummyNifBinder6 %08x:\tCDummyNifBinder6(CDummyNifSubConnectionFlow& %08x)"), this, &aDummyNifSubConnectionFlow);
       
   433 	}
       
   434 
       
   435 CDummyNifBinder6::~CDummyNifBinder6()
       
   436 /** 
       
   437 Destroys 'this'
       
   438 */
       
   439     {
       
   440     __FLOG(_L8("CDummyNifBinder6:\t~CDummyNifBinder6()"));
       
   441     __FLOG_CLOSE;
       
   442     }
       
   443 
       
   444 CDummyNifBinder6* CDummyNifBinder6::NewL(CDummyNifSubConnectionFlow& aDummyNifSubConnectionFlow)
       
   445 	{
       
   446 	return new (ELeave) CDummyNifBinder6(aDummyNifSubConnectionFlow);
       
   447 	}
       
   448 
       
   449 void CDummyNifBinder6::UpdateHeaders(TInet6HeaderIP* aIp6, TInet6HeaderUDP* /*aUdp*/)
       
   450     {
       
   451 	// swap over the destination and source addresses
       
   452 	TIp6Addr temp;
       
   453 	temp = aIp6->SrcAddr();
       
   454 	aIp6->SetSrcAddr(aIp6->DstAddr());
       
   455 	aIp6->SetDstAddr(temp);
       
   456     }
       
   457     
       
   458 MLowerDataSender::TSendResult CDummyNifBinder6::Send(RMBufChain& aData)
       
   459 /**
       
   460 Send IPv6 data
       
   461 
       
   462 Note: not clear that this is properly supported or used.
       
   463 
       
   464 @param aData data to send
       
   465 */
       
   466 	{
       
   467     __FLOG(_L8("CDummyNifBinder6:\tSend()"));
       
   468 
       
   469    	// Loop the data straight back into the TCP/IP stack
       
   470 	ProcessPacket(aData);
       
   471 	return ESendAccepted;
       
   472 	}
       
   473 	
       
   474 MLowerDataSender* CDummyNifBinder6::Bind(MUpperDataReceiver& aUpperReceiver, MUpperControl& aUpperControl)
       
   475 	{
       
   476     __FLOG_2(_L8("CDummyNifBinder6:\tBind(MUpperDataReceiver %08x, MUpperControl %08x)"), &aUpperReceiver, &aUpperControl);
       
   477 
       
   478 	iUpperReceiver = &aUpperReceiver;
       
   479 	iUpperControl = &aUpperControl;
       
   480 	
       
   481 	// Signal upper layer that we are ready
       
   482 	BinderReady();
       
   483 	
       
   484 	return this;
       
   485 	}
       
   486 
       
   487 void CDummyNifBinder6::BinderReady()
       
   488 /**
       
   489 Signal to upper layer that we are ready
       
   490 */
       
   491     {
       
   492     __FLOG(_L8("CDummyNifBinder6:\tBinderReady()"));
       
   493 
       
   494 	iUpperControl->StartSending();
       
   495     }
       
   496 
       
   497 void CDummyNifBinder6::ProcessPacket(RMBufChain& aPdu)
       
   498 /**
       
   499 Process incoming IPv6 packets.
       
   500 
       
   501 Note: not clear that this is properly supported or used.
       
   502 
       
   503 @param aPdu incoming data packet
       
   504 */
       
   505     {
       
   506     __FLOG(_L8("CDummyNifBinder6:\tProcessPacket()"));
       
   507 
       
   508 	// this received data has already been looped back...
       
   509 	// get the ip header from the RMBufChain
       
   510 	TInet6HeaderIP* ip6 = (TInet6HeaderIP*) aPdu.First()->Next()->Ptr();
       
   511 	TInet6HeaderUDP* udp = NULL;
       
   512 
       
   513 	if ((TUint)ip6->NextHeader() == KProtocolInetUdp)
       
   514 		{
       
   515 		// get the udp header as well - assume only udp traffic here
       
   516 		udp = (TInet6HeaderUDP*) ip6->EndPtr();
       
   517 
       
   518 		__FLOG_3(_L("CDummyNifBinder6:\tProcessPacket(...): UDP length %d, src port %d, dst port %d"),
       
   519 			udp->Length(), udp->SrcPort(), udp->DstPort());
       
   520 
       
   521 		// depending on the contents, pass it on up thru the stack 
       
   522 		// or maybe do something else
       
   523 
       
   524 		// use the destination port number to decide whether or not the payload is a command
       
   525 		TUint dstPort = udp->DstPort();
       
   526 		if (KDummyNifCmdPort == dstPort)
       
   527             {
       
   528  			// let's use the first payload byte as the command byte
       
   529 			switch (*(udp->EndPtr()))
       
   530 				{
       
   531 			case KForceDisconnect:
       
   532 				__FLOG(_L("KForceDisconnect command"));
       
   533 				// do some action
       
   534 	            Flow()->Progress(KLinkLayerClosed, KErrCommsLineFail);
       
   535 
       
   536 	            Flow()->FlowDown(KErrCommsLineFail, MNifIfNotify::EDisconnect);
       
   537 
       
   538 				// no return code so all we can do is respond with what we got
       
   539 				UpdateHeaders(ip6, udp);
       
   540 				iUpperReceiver->Process(aPdu);
       
   541 				break;
       
   542 
       
   543 			case KForceReconnect:
       
   544 				__FLOG(_L("KForceReconnect command"));
       
   545 				// do some action
       
   546 	            Flow()->Progress(KLinkLayerClosed, KErrCommsLineFail);
       
   547 
       
   548                 //cause.iReserved=MNifIfNotify::EReconnect;
       
   549 	            Flow()->FlowDown(KErrCommsLineFail);
       
   550 
       
   551 				// no return code so all we can do is respond with what we got
       
   552 				UpdateHeaders(ip6, udp);
       
   553 				iUpperReceiver->Process(aPdu);
       
   554 				break;
       
   555 
       
   556 			case KSendNotification:
       
   557 				__FLOG(_L("KSendNotification command"));
       
   558 			    //let's write the result in the next byte of the reply
       
   559 			    if (Flow()->AgentProvision()->IsDialIn() == KErrNotSupported)
       
   560 				    udp->EndPtr()[1] = (unsigned char) KErrNone;
       
   561 			    else
       
   562 				    udp->EndPtr()[1] = (unsigned char) KErrGeneral; // this will lose it's sign :-(
       
   563 			
       
   564 				UpdateHeaders(ip6, udp);
       
   565                 iUpperReceiver->Process(aPdu);
       
   566 			    break;
       
   567 
       
   568 
       
   569 			default:
       
   570 				__FLOG(_L("Unknown command - ignoring it"));
       
   571 				break;
       
   572 				// unknown command, just ignore this packet???
       
   573 				}
       
   574 			return;
       
   575 			}
       
   576 
       
   577 		}
       
   578 	else
       
   579 		{
       
   580 		__FLOG_2(_L("CDummyNifBinder6:\tProcessPacket(...): IPv6 length %d, next header %d"),
       
   581 			ip6->PayloadLength(), ip6->NextHeader());
       
   582 		}
       
   583 
       
   584 	// just echo the packet back to the original sender
       
   585 
       
   586 	// update the headers (addresses, checksums etc).  If "udp" is non-NULL, then
       
   587 	// the UDP ports will be updated as well.
       
   588 	UpdateHeaders(ip6, udp);
       
   589 	// now process it (pass up the stack)
       
   590 	iUpperReceiver->Process(aPdu);		
       
   591     }
       
   592 
       
   593 void CDummyNifBinder6::Unbind(MUpperDataReceiver& aUpperReceiver, MUpperControl& aUpperControl)
       
   594 	{
       
   595     static_cast<void>(aUpperReceiver);
       
   596     static_cast<void>(aUpperControl);
       
   597     __FLOG(_L8("CDummyNifBinder6:\tUnbind()"));
       
   598 
       
   599     ASSERT(&aUpperReceiver == iUpperReceiver);
       
   600     ASSERT(&aUpperControl == iUpperControl);
       
   601     iUpperReceiver = NULL;
       
   602     iUpperControl = NULL;
       
   603 	}
       
   604 	
       
   605 TInt CDummyNifBinder6::GetName(TDes& aName)
       
   606 /**
       
   607 Called from upper layer to retrieve the binder name.
       
   608 
       
   609 @param aName populated with name
       
   610 @return KErrNone on success, else a system wide error code.
       
   611 */
       
   612 	{
       
   613     __FLOG(_L8("CDummyNifBinder6:\tGetName()"));
       
   614 
       
   615 	// This name matches the NIF-based DummyNif to match any potential
       
   616 	// test code expectations on the name.
       
   617 	aName.Format(_L("dummynif6[0x%08x]"), this);
       
   618 	
       
   619 	return KErrNone;
       
   620 	}
       
   621 
       
   622 TInt CDummyNifBinder6::BlockFlow(MLowerControl::TBlockOption /*aOption*/)
       
   623 	{
       
   624     __FLOG(_L8("CDummyNifBinder6:\tBlockFlow()"));
       
   625 
       
   626 	return KErrNotSupported;
       
   627 	}
       
   628 
       
   629 void CDummyNifBinder6::StaticDnsConfiguration(TBinderConfig6& aConfig)
       
   630 	{
       
   631     __FLOG(_L8("CDummyNifBinder6:\tStaticDnsConfiguration()"));
       
   632 
       
   633 	const TDummyIp6Provision* ip6Provision = Flow()->Ip6Provision();
       
   634 
       
   635 	if (!ip6Provision->Ip6DNSAddrFromServer()) 
       
   636 		{
       
   637         aConfig.iNameSer1.SetAddress(ip6Provision->Ip6NameServer1());
       
   638         aConfig.iNameSer2.SetAddress(ip6Provision->Ip6NameServer2());
       
   639 		}
       
   640 	else
       
   641 		{
       
   642 		// Ensure that static DNS addresses are set as unspecified,
       
   643 		// so they are not used in Control(KSoIfConfig).
       
   644         aConfig.iNameSer1.SetAddress(KInet6AddrNone);
       
   645         aConfig.iNameSer2.SetAddress(KInet6AddrNone);
       
   646 		}
       
   647 	}
       
   648 
       
   649 TInt CDummyNifBinder6::GetConfig(TBinderConfig& aConfig)
       
   650 /**
       
   651 Return IPv6 configuration information.
       
   652 
       
   653 Called from upper layer.
       
   654 
       
   655 @param aConfig structure to populate with IPv6 configuration
       
   656 */
       
   657 	{
       
   658     TBinderConfig6* config = TBinderConfig::Cast<TBinderConfig6>(aConfig);
       
   659     
       
   660 	if(config == NULL)
       
   661 		{
       
   662 		return KErrNotSupported;
       
   663 		}
       
   664 		
       
   665 	// Setup config
       
   666 	config->iInfo.iFeatures = KIfCanBroadcast | KIfCanMulticast;;
       
   667 	config->iInfo.iMtu = 1500;
       
   668 	config->iInfo.iRMtu = 1500;
       
   669 	config->iInfo.iSpeedMetric = 0;
       
   670 	
       
   671 	// Setup addresses 
       
   672 	
       
   673 	config->iFamily = KAfInet6;
       
   674 	
       
   675 	// Local ID
       
   676 	
       
   677 	TInt addr64 = 0x80;
       
   678 	TE64Addr localAddr(addr64);
       
   679 	TEui64Addr* id = (TEui64Addr*) &config->iLocalId;
       
   680 	
       
   681 	id->Init();
       
   682 	id->SetAddress(localAddr);
       
   683 	
       
   684 	// Remote ID
       
   685 	addr64 = 0x81;
       
   686 	TE64Addr remoteAddr(addr64);
       
   687 	id = (TEui64Addr*) &config->iRemoteId;
       
   688 	
       
   689 	id->Init();
       
   690 	id->SetAddress(remoteAddr);
       
   691 	
       
   692 	// Setup static DNS address if required
       
   693 	StaticDnsConfiguration(*config);
       
   694 	    
       
   695     return KErrNone;
       
   696     }
       
   697 
       
   698 TInt CDummyNifBinder6::Control(TUint aLevel, TUint aName, TDes8& aOption)
       
   699 	{
       
   700     static_cast<void> (aOption);
       
   701 	__FLOG_2(_L("CDummyNifBinder6:\tControl(aLevel %x, aName %x, ...)"), aLevel, aName);
       
   702 	return KErrNotSupported;
       
   703 	}
       
   704 
       
   705 //
       
   706 // Utilities
       
   707 //
       
   708 
       
   709 TBool CDummyNifBinder6::MatchesUpperControl(ESock::MUpperControl* aUpperControl) const
       
   710 /**
       
   711 Utility function that returns whether this binder is associated with the
       
   712 MUpperControl object passed as argument.
       
   713 
       
   714 @param aUpperControl upper layer to match against
       
   715 @return ETrue on a match else EFalse.
       
   716 */
       
   717 	{
       
   718 	return aUpperControl == iUpperControl;
       
   719 	}
       
   720 
       
   721 //
       
   722 // Async error callback
       
   723 //
       
   724 // Used to schedule asynchronous signalling of a binder error to upper flow in circumstances
       
   725 // where a direct call is not possible (e.g. in the middle of a TCP/IP send as the binder
       
   726 // may disappear underneath the TCP/IP stack).
       
   727 
       
   728 CDummyErrorOneShot::CDummyErrorOneShot()
       
   729   : CAsyncOneShot(EPriorityStandard)
       
   730 	{
       
   731 	}
       
   732 
       
   733 void CDummyErrorOneShot::Schedule(MUpperControl* aUpperControl)
       
   734 	{
       
   735 	iUpperControl = aUpperControl;
       
   736 	Call();
       
   737 	}
       
   738 
       
   739 void CDummyErrorOneShot::RunL()
       
   740 	{
       
   741 	iUpperControl->Error(KErrCommsLineFail);
       
   742 	}
       
   743 
       
   744 
       
   745 CDummyNifFlowTestingSubscriber::CDummyNifFlowTestingSubscriber(CDummyNifSubConnectionFlow& aFlow, TUint aApId)
       
   746 	: CActive(0),
       
   747 	iFlow(aFlow),
       
   748 	iApId(aApId)
       
   749 	{
       
   750 	}
       
   751 
       
   752 /*static*/ TBool CDummyNifFlowTestingSubscriber::ShouldRun(TUint aApId)
       
   753 	{
       
   754 	RProperty property;
       
   755 	TInt result = property.Attach(KDummyNifTestingPubSubUid, aApId);
       
   756 	if(result == KErrNone)
       
   757 		{
       
   758 		TInt propertyValue;
       
   759 		result = property.Get(propertyValue);
       
   760 		if(result == KErrNone)
       
   761 			{
       
   762 			return ETrue;
       
   763 			}
       
   764 		}
       
   765 	return EFalse;
       
   766 	}
       
   767 
       
   768 void CDummyNifFlowTestingSubscriber::ConstructL()
       
   769 	{
       
   770 	CActiveScheduler::Add(this);
       
   771 //	__DECLARE_NAME(_S("CAvailabilityTestingSubscriber"));
       
   772 
       
   773 	TInt result = iProperty.Attach(KDummyNifTestingPubSubUid, iApId);
       
   774 	ASSERT(result == KErrNone);
       
   775 
       
   776 	RunL();
       
   777 	}
       
   778 
       
   779 void CDummyNifFlowTestingSubscriber::RunL()
       
   780 	{
       
   781 	// .. and repeat..
       
   782 	iProperty.Subscribe(iStatus);
       
   783 	
       
   784 	TInt publishedValue;
       
   785 	TInt result = iProperty.Get(publishedValue);
       
   786 	ASSERT(result == KErrNone);
       
   787 
       
   788 	TAvailabilityStatus av(publishedValue);
       
   789 	if (av.Score())
       
   790 		{
       
   791 		iIsEnabled = ETrue;
       
   792 		iFlow.iDisableStart = EFalse;
       
   793 		}
       
   794 	else
       
   795 		{
       
   796 		iIsEnabled = EFalse;
       
   797 		iFlow.iDisableStart = ETrue;
       
   798 		}
       
   799 
       
   800 	SetActive();
       
   801 	}
       
   802 
       
   803 void CDummyNifFlowTestingSubscriber::DoCancel()
       
   804 	{
       
   805 	iProperty.Cancel();
       
   806 	}
       
   807 
       
   808 /*virtual*/ CDummyNifFlowTestingSubscriber::~CDummyNifFlowTestingSubscriber()
       
   809 	{
       
   810 	this->Cancel(); // object must be stoppable by descruction due to cleanup restrictions
       
   811 	iProperty.Close();
       
   812 	}
       
   813