datacommsserver/esockserver/test/protocols/pdummy/PDUMMY.CPP
changeset 0 dfb7c4ff071f
child 4 928ed51ddc43
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 1997-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 //
       
    15 
       
    16 #include <es_prot.h>
       
    17 #include <e32test.h>
       
    18 #include "ES_DUMMY.H"
       
    19 #include <comms-infras/nifif.h>
       
    20 #include <es_mbuf.h>
       
    21 #include <ss_std.h>
       
    22 #include <ss_pman.h>
       
    23 #include <ss_glob.h>
       
    24 #include <e32math.h>
       
    25 #include <dns_qry.h>
       
    26 #include <agenterrors.h>
       
    27 #include <e32property.h>
       
    28 #include <nifman_internal.h>
       
    29 #include "pdummy.h"
       
    30 
       
    31 
       
    32 #ifdef _DEBUG
       
    33 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    34 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    35 _LIT(KSpecAssert_ESockTestPDUMMY, "ESockTestPDUMMY.");
       
    36 #endif
       
    37 
       
    38 const TInt KPDummyDefaultGranularity=0xA; // Default number of incoming messages the protocol can queue up
       
    39 
       
    40 //---------------------------------------------------------------------------------------------------------
       
    41 
       
    42 
       
    43 CAsyncSocketErrorer* CAsyncSocketErrorer::NewL(MSocketNotify& aSocket,TInt aErrorCode,TUint aOpMask,
       
    44                                   CDummyProtocol * apProtocols, CDummyProvd* aOwner,const TDesC8* aListenData )
       
    45 	{
       
    46 	return new(ELeave) CAsyncSocketErrorer(aSocket, aErrorCode, aOpMask,apProtocols,aOwner,aListenData);
       
    47 	}
       
    48 
       
    49 CAsyncSocketErrorer::CAsyncSocketErrorer(MSocketNotify& aSocket, TInt aErrorCode, TUint aOpMask,
       
    50 		CDummyProtocol* apProtocols, CDummyProvd* aOwner, const TDesC8* aListenData):
       
    51     CActive(KMaxTInt),
       
    52 	iSocket(aSocket),
       
    53 	iErrorCode(aErrorCode),
       
    54 	iOpMask(aOpMask),
       
    55 	ipProtocols(apProtocols),
       
    56 	iOwner(aOwner),
       
    57 	iListenData(aListenData)
       
    58 	{
       
    59 	CActiveScheduler::Add(this);
       
    60 	SetActive();
       
    61 	TRequestStatus* p = &iStatus;
       
    62 	User::RequestComplete(p, KErrNone);
       
    63 	}
       
    64 
       
    65 void CAsyncSocketErrorer::RunL()
       
    66 	{
       
    67 	CDummyProvd* p = NULL;
       
    68     if ( iErrorCode == KErrNone )
       
    69         {
       
    70 	    TRAP(iErrorCode,p = CDummyProvd::NewL(*ipProtocols););
       
    71 	    if (iErrorCode)
       
    72 	    	{
       
    73 	    	iOpMask = MSocketNotify::EErrorFatal;
       
    74 	    	}
       
    75         }
       
    76     if ( iErrorCode == KErrNone )
       
    77         {
       
    78 	    if(iListenData)
       
    79 	    	{
       
    80 	    	iSocket.ConnectComplete(*p, *iListenData);
       
    81 	    	}
       
    82 	    else
       
    83 	    	{
       
    84 	    	iSocket.ConnectComplete(*p);
       
    85 	    	}
       
    86         }
       
    87     else
       
    88         {
       
    89 	    iSocket.Error(iErrorCode,iOpMask);
       
    90         }
       
    91 	iOwner->DestroyAsyncErrorer();	// ie "delete this"
       
    92 	}
       
    93 
       
    94 CAsyncSocketErrorer::~CAsyncSocketErrorer()
       
    95 	{
       
    96 	Cancel();
       
    97 	}
       
    98 
       
    99 void CAsyncSocketErrorer::DoCancel()
       
   100 	{
       
   101 	}
       
   102 
       
   103 //---------------------------------------------------------------------------------------------------------
       
   104 
       
   105 NONSHARABLE_CLASS(CDummyProvd::CFlowOnTimer): public CTimer
       
   106 	{
       
   107 public:
       
   108 	static CFlowOnTimer* NewL(CDummyProvd& aProvd, MSocketNotify& aSocketNotify);
       
   109 	virtual ~CFlowOnTimer();
       
   110 
       
   111 	virtual void RunL();
       
   112 
       
   113 private:
       
   114 	CFlowOnTimer(CDummyProvd& aProvd, MSocketNotify& aSocket);
       
   115 
       
   116 	CDummyProvd& iProvd;
       
   117 	MSocketNotify& iSocketNotify;
       
   118 	};
       
   119 
       
   120 
       
   121 CDummyProvd::CFlowOnTimer* CDummyProvd::CFlowOnTimer::NewL(CDummyProvd& aProvd, MSocketNotify& aSocketNotify)
       
   122 	{
       
   123 	CFlowOnTimer* self = new(ELeave) CFlowOnTimer(aProvd, aSocketNotify);
       
   124 	CleanupStack::PushL(self);
       
   125 	self->ConstructL();
       
   126 	CActiveScheduler::Add(self);
       
   127 	CleanupStack::Pop(self);
       
   128 	return self;
       
   129 	}
       
   130 
       
   131 CDummyProvd::CFlowOnTimer::CFlowOnTimer(CDummyProvd& aProvd, MSocketNotify& aSocketNotify)
       
   132 	: CTimer(CActive::EPriorityStandard), iProvd(aProvd), iSocketNotify(aSocketNotify)
       
   133 	{
       
   134 	}
       
   135 
       
   136 
       
   137 CDummyProvd::CFlowOnTimer::~CFlowOnTimer()
       
   138 	{
       
   139 	Cancel();
       
   140 	}
       
   141 
       
   142 void CDummyProvd::CFlowOnTimer::RunL()
       
   143 	{
       
   144 	iProvd.iFlowOffWriteTimeout = 0;
       
   145 	iSocketNotify.CanSend();
       
   146 	}
       
   147 
       
   148 enum TDPanic
       
   149 	{
       
   150 	EBadProtocol,
       
   151 	EBadCall,
       
   152 	ENotBound,
       
   153 	ENotStarted,
       
   154 	EInterfaceNotDeleted,
       
   155 	EIdAndNoHolder,
       
   156 	EIfAndHolder,
       
   157 	ETestPanic
       
   158 	};
       
   159 
       
   160 // RTest test(_L("Dummy protocol"));
       
   161 
       
   162 LOCAL_C void Panic(TDPanic aPanic)
       
   163 //
       
   164 // Panic the Protocol
       
   165 //
       
   166 	{
       
   167 
       
   168 	User::Panic(_L("Dummy Prot"),aPanic);
       
   169 	}
       
   170 
       
   171 extern "C"
       
   172 	{
       
   173 	IMPORT_C CProtocolFamilyBase* InstallDummy(void);	// Force export
       
   174 
       
   175 	EXPORT_C CProtocolFamilyBase * InstallDummy(void)
       
   176 	//
       
   177 	// Create a new protocol family
       
   178 	//
       
   179 		{
       
   180 		return CDProtocolFamily::NewL();
       
   181 		}
       
   182 	}
       
   183 
       
   184 CDProtocolFamily* CDProtocolFamily::NewL()
       
   185 //
       
   186 //
       
   187 //
       
   188 	{
       
   189 	CDProtocolFamily* pf = new (ELeave) CDProtocolFamily();
       
   190 	CleanupStack::PushL(pf);
       
   191 	pf->ConstructL();
       
   192 	CleanupStack::Pop();
       
   193 	return pf;
       
   194 	}
       
   195 
       
   196 void CDProtocolFamily::ConstructL()
       
   197 //
       
   198 //
       
   199 //
       
   200 	{
       
   201 	// Force a fail on Memory tests
       
   202 	char* ptr=new(ELeave) char;
       
   203 	delete ptr;
       
   204 
       
   205 	}
       
   206 
       
   207 CDProtocolFamily::CDProtocolFamily() : CProtocolFamilyBase()
       
   208 	{
       
   209 	iProtocolDescs[0].iAddrFamily=KDummyAddrFamily;
       
   210 	iProtocolDescs[0].iSockType=KSockDatagram;
       
   211 	iProtocolDescs[0].iProtocol=KDummyOne;
       
   212 	iProtocolDescs[0].iVersion=TVersion(KDummyMajor,KDummyMinor,KDummyBuild);
       
   213 	iProtocolDescs[0].iByteOrder=EBigEndian;
       
   214 	// KSIRequiresOwnerInfo is required to ensure that SetOption(KSoSetPlatSecApi) is issued to
       
   215 	// TransportFlowShim for NoBearer() testing.
       
   216 	iProtocolDescs[0].iServiceInfo=kDDatagramServiceInfo|KSIPeekData|KSIRequiresOwnerInfo;
       
   217 	iProtocolDescs[0].iSecurity=KSocketNoSecurity;
       
   218 	iProtocolDescs[0].iMessageSize=0x300;
       
   219 	iProtocolDescs[0].iName=KDummyOneName;
       
   220 	iProtocolDescs[0].iServiceTypeInfo=ESocketSupport|ECantProcessMBufChains;
       
   221 	iProtocolDescs[0].iNamingServices=KNSNameResolution|KNSServiceResolution|KNSInfoDatabase;
       
   222 	iProtocolDescs[0].iNumSockets=100;
       
   223 
       
   224 	iProtocolDescs[1].iAddrFamily=KDummyAddrFamily;
       
   225 	iProtocolDescs[1].iSockType=KSockStream;
       
   226 	iProtocolDescs[1].iProtocol=KDummyTwo;
       
   227 	iProtocolDescs[1].iVersion=TVersion(KDummyMajor,KDummyMinor,KDummyBuild);
       
   228 	iProtocolDescs[1].iByteOrder=EBigEndian;
       
   229 	iProtocolDescs[1].iServiceInfo=KDStreamServiceInfo;
       
   230 	iProtocolDescs[1].iSecurity=KSocketNoSecurity;
       
   231 	iProtocolDescs[1].iMessageSize=KSocketMessageSizeIsStream;
       
   232 	iProtocolDescs[1].iName=KDummyTwoName;
       
   233 	iProtocolDescs[1].iServiceTypeInfo=ESocketSupport|ECantProcessMBufChains;
       
   234 	iProtocolDescs[1].iNamingServices=0;
       
   235 	iProtocolDescs[1].iNumSockets=100;
       
   236 
       
   237 	iProtocolDescs[2].iAddrFamily=KDummyAddrFamily;
       
   238 	iProtocolDescs[2].iSockType=KSockSeqPacket;
       
   239 	iProtocolDescs[2].iProtocol=KDummyThree;
       
   240 	iProtocolDescs[2].iVersion=TVersion(KDummyMajor,KDummyMinor,KDummyBuild);
       
   241 	iProtocolDescs[2].iByteOrder=EBigEndian;
       
   242 	iProtocolDescs[2].iServiceInfo=KSIReliable|KSIInOrder|KSIDatagram|KSIGracefulClose|KSIBroadcast|KSIQOS|KSICanReconnect|KSIConnectData|KSIDisconnectData;
       
   243 	iProtocolDescs[2].iSecurity=KSocketNoSecurity;
       
   244 	iProtocolDescs[2].iMessageSize=KSocketMessageSizeNoLimit;
       
   245 	iProtocolDescs[2].iName=KDummyThreeName;
       
   246 	iProtocolDescs[2].iServiceTypeInfo=ESocketSupport|ECantProcessMBufChains|ETransport|EPreferDescriptors|EUseCanSend;
       
   247 	iProtocolDescs[2].iNamingServices=0;
       
   248 	iProtocolDescs[2].iNumSockets=100;
       
   249 
       
   250 	iProtocolDescs[3].iAddrFamily=KDummyAddrFamily;
       
   251 	iProtocolDescs[3].iSockType=KSockStream;
       
   252 	iProtocolDescs[3].iProtocol=KDummyFour;
       
   253 	iProtocolDescs[3].iVersion=TVersion(KDummyMajor,KDummyMinor,KDummyBuild);
       
   254 	iProtocolDescs[3].iByteOrder=EBigEndian;
       
   255 	iProtocolDescs[3].iServiceInfo=KDStreamServiceInfo;
       
   256 	iProtocolDescs[3].iSecurity=KSocketNoSecurity;
       
   257 	iProtocolDescs[3].iMessageSize=KSocketMessageSizeIsStream;
       
   258 	iProtocolDescs[3].iName=KDummyFourName;
       
   259 	iProtocolDescs[3].iServiceTypeInfo=ESocketSupport|ENeedMBufs;
       
   260 	iProtocolDescs[3].iNamingServices=0;
       
   261 	iProtocolDescs[3].iNumSockets=100;
       
   262 
       
   263 	iProtocolDescs[4].iAddrFamily=KDummyAddrFamily;
       
   264 	iProtocolDescs[4].iSockType=KSockDatagram;
       
   265 	iProtocolDescs[4].iProtocol=KDummyFive;
       
   266 	iProtocolDescs[4].iVersion=TVersion(KDummyMajor,KDummyMinor,KDummyBuild);
       
   267 	iProtocolDescs[4].iByteOrder=EBigEndian;
       
   268 	iProtocolDescs[4].iServiceInfo=kDDatagramServiceInfo|KSIPeekData;
       
   269 	iProtocolDescs[4].iSecurity=KSocketNoSecurity;
       
   270 	iProtocolDescs[4].iMessageSize=KSocketMessageSizeNoLimit;
       
   271 	iProtocolDescs[4].iName=KDummyFiveName;
       
   272 	iProtocolDescs[4].iServiceTypeInfo=ESocketSupport|ECantProcessMBufChains;
       
   273 	iProtocolDescs[4].iNamingServices=KNSNameResolution|KNSServiceResolution|KNSInfoDatabase;
       
   274 	iProtocolDescs[4].iNumSockets=100;
       
   275 
       
   276 	__DECLARE_NAME(_S("CDProtocolFamily"));
       
   277 	}
       
   278 
       
   279 #pragma warning( disable : 4100 )
       
   280 
       
   281 TInt CDProtocolFamily::Install()
       
   282 	{
       
   283 	// Force a fail on Memory tests
       
   284 	char* ptr=new char;
       
   285 	if (!ptr)
       
   286 		return KErrNoMemory;
       
   287 	delete ptr;
       
   288 	return KErrNone;
       
   289 	}
       
   290 
       
   291 TInt CDProtocolFamily::Remove()
       
   292 	{
       
   293 	return KErrNone;
       
   294 	}
       
   295 
       
   296 TUint CDProtocolFamily::ProtocolList(TServerProtocolDesc *& aProtocolDescPointer)
       
   297 	{
       
   298 
       
   299   	aProtocolDescPointer=new TServerProtocolDesc[KPDummyNumProtocols];
       
   300   	if (!aProtocolDescPointer)
       
   301   		return 0;
       
   302 
       
   303 	Mem::Copy(aProtocolDescPointer, iProtocolDescs, sizeof(TServerProtocolDesc)*KPDummyNumProtocols);
       
   304 
       
   305 	TRAP_IGNORE(Nif::CheckInstalledMBufManagerL();)
       
   306 
       
   307 	return KPDummyNumProtocols;
       
   308 	};
       
   309 
       
   310 CProtocolBase * CDProtocolFamily::NewProtocolL(TUint /* aSockType */,TUint aProtocol)
       
   311 	{
       
   312 
       
   313 	CDummyProtocol* p=CDummyProtocol::NewL(aProtocol, &iProtocolDescs[aProtocol-1]);
       
   314 	return p;
       
   315 	}
       
   316 
       
   317 
       
   318 //---------------------------------------------------------------------------------------------------------
       
   319 
       
   320 
       
   321 CServProviderBase * CDummyProtocol::NewSAPL(TUint /*aProtocol*/)
       
   322 	{
       
   323 	return CDummyProvd::NewL(*this);
       
   324 	}
       
   325 
       
   326 
       
   327 CHostResolvProvdBase* CDummyProtocol::NewHostResolverL()
       
   328 	{
       
   329 	return CDatagramHostResolver::NewL();
       
   330 	}
       
   331 
       
   332 CServiceResolvProvdBase* CDummyProtocol::NewServiceResolverL()
       
   333 	{
       
   334 	return CDatagramServResolver::NewL();
       
   335 	}
       
   336 
       
   337 CNetDBProvdBase* CDummyProtocol::NewNetDatabaseL()
       
   338 	{
       
   339 	return CDatagramNetDataBase::NewL();
       
   340 	}
       
   341 
       
   342 CDummyProtocol::~CDummyProtocol()
       
   343 	{
       
   344 	for (TInt i=0;i<iProtocols.Count();i++)
       
   345 		{
       
   346 		iProtocols[i]->Close();
       
   347 		}
       
   348 	}
       
   349 
       
   350 
       
   351 void CDummyProtocol::InitL(TDesC& /*aTag*/)
       
   352 	{
       
   353 	// Force a fail on Memory tests
       
   354 	char* ptr=new(ELeave) char;
       
   355 	delete ptr;
       
   356 	}
       
   357 
       
   358 void CDummyProtocol::BindL(CProtocolBase* /*aProtocol*/, TUint /*anId*/)
       
   359 	{
       
   360 	// Force a fail on Memory tests
       
   361 	char* ptr=new(ELeave) char;
       
   362 	delete ptr;
       
   363 	}
       
   364 
       
   365 void CDummyProtocol::BindToL(CProtocolBase* aProtocol)
       
   366 	{
       
   367 	// Force a fail on Memory tests
       
   368 	char* ptr=new(ELeave) char;
       
   369 	delete ptr;
       
   370 	iProtocols.AppendL(aProtocol);
       
   371 	aProtocol->Open();
       
   372 	}
       
   373 
       
   374 
       
   375 void CDummyProtocol::StartL(void)
       
   376 	{
       
   377 	// Force a fail on Memory tests
       
   378 	char* ptr=new(ELeave) char;
       
   379 	delete ptr;
       
   380 	iIsStarted=ETrue;
       
   381 	}
       
   382 
       
   383 TInt CDummyProtocol::Send(RMBufChain &,CProtocolBase* /*aSourceProtocol*/)
       
   384 	{
       
   385 	return 1;
       
   386 	}
       
   387 
       
   388 TInt CDummyProtocol::Send(TDes8 &, TSockAddr* /*to*/,TSockAddr* /*from*/,CProtocolBase* /*aSourceProtocol*/)
       
   389 	{
       
   390 	return 1;
       
   391 	}
       
   392 
       
   393 void CDummyProtocol::Process(RMBufChain &,CProtocolBase* /*aSourceProtocol*/)
       
   394 	{
       
   395 	}
       
   396 
       
   397 void CDummyProtocol::Process(TDes8 & ,TSockAddr* /*from*/,TSockAddr* /*to*/,CProtocolBase* /*aSourceProtocol*/)
       
   398 	{
       
   399 	}
       
   400 
       
   401 void CDummyProtocol::Identify(TServerProtocolDesc *aDesc) const
       
   402 	{
       
   403 	Mem::Copy(aDesc, iProtoDesc, sizeof(TServerProtocolDesc));
       
   404 	}
       
   405 
       
   406 TInt CDummyProtocol::GetOption(TUint level,TUint,TDes8&,CProtocolBase* /*aSourceProtocol*/)
       
   407 	{
       
   408 
       
   409 	if(level==KNifOptLevel)
       
   410 		{
       
   411 		return KErrNotSupported;
       
   412 		}
       
   413 	return KErrNone;
       
   414 	}
       
   415 
       
   416 TInt CDummyProtocol::SetOption(TUint /*level*/,TUint /*name*/,const TDesC8& /*option*/,CProtocolBase* /*aSourceProtocol*/)
       
   417 	{
       
   418 	return KErrNone;
       
   419 	}
       
   420 
       
   421 void CDummyProtocol::Error(TInt /*anerror*/,CProtocolBase* /*aSourceProtocol*/)
       
   422 	{
       
   423 	}
       
   424 
       
   425 
       
   426 EXPORT_C CDummyProtocol *CDummyProtocol::NewL(TInt aType, TServerProtocolDesc* aProtoDesc)
       
   427 	{
       
   428 
       
   429 	CDummyProtocol* p=0;
       
   430 	switch (aType)
       
   431 		{
       
   432 	case KDummyOne:
       
   433 	case KDummyTwo:
       
   434 	case KDummyFive:
       
   435 		p=new (ELeave) CDummyProtocol(aProtoDesc);
       
   436 		break;
       
   437 
       
   438 	case KDummyThree:
       
   439 	case KDummyFour:
       
   440 		p=new (ELeave) CInterfaceProtocol(aProtoDesc);
       
   441 		break;
       
   442 
       
   443 	default:
       
   444 		p=(CDummyProtocol*)0xABCD; // keep lint happy
       
   445 		Panic(EBadProtocol);
       
   446 		}
       
   447 	p->iType=aType;
       
   448 	return p;
       
   449 	}
       
   450 
       
   451 
       
   452 EXPORT_C CDummyProtocol::CDummyProtocol(TServerProtocolDesc* aProtoDesc)
       
   453 
       
   454 	:CProtocolBase(),iProtoDesc(aProtoDesc),iProtocols(0x16)
       
   455 	{
       
   456 	__DECLARE_NAME(_S("CDummyProtocol"));
       
   457 	iIsStarted=EFalse;
       
   458 	}
       
   459 
       
   460 
       
   461 /* exported functions that are used to exercise ProtocolBase functionality
       
   462 */
       
   463 EXPORT_C TInt CDummyProtocol::ProtocolBaseBind(CProtocolBase* aProt, TUint aId)
       
   464 	// expected to Panic(EDoesNotBindBelow);
       
   465 	{
       
   466 	TRAPD(ret, CProtocolBase::BindL(aProt, aId));
       
   467 	return ret;
       
   468 	}
       
   469 
       
   470 
       
   471 EXPORT_C TInt CDummyProtocol::ProtocolBaseBindTo(CProtocolBase* aProt)
       
   472 	// expected to Panic(EDoesNotBindAbove);
       
   473 	{
       
   474 	TRAPD(ret, CProtocolBase::BindToL(aProt));
       
   475 	return ret;
       
   476 	}
       
   477 
       
   478 EXPORT_C TInt CDummyProtocol::ProtocolBaseError(CProtocolBase* aProt)
       
   479 	// expected to Panic(EErrorCallNotHandled)
       
   480 	{
       
   481 	CProtocolBase::Error(KErrNone, aProt);
       
   482 	return KErrNone;
       
   483 	}
       
   484 
       
   485 EXPORT_C TInt CDummyProtocol::ProtocolBaseGetOption(TUint aLevel, TUint aName, TDes8& aBuf, CProtocolBase* aProt)
       
   486 	{
       
   487 	// expected to return KErrNotSupported
       
   488 	TInt ret = CProtocolBase::GetOption(aLevel,aName,aBuf,aProt);
       
   489 	__ASSERT_DEBUG(ret == KErrNotSupported, User::Panic(KSpecAssert_ESockTestPDUMMY, 1));
       
   490 	return ret;
       
   491 	}
       
   492 
       
   493 EXPORT_C TInt CDummyProtocol::ProtocolBaseNewHostResolver()
       
   494 	// expected to panic with Fault(EBadHostResolver);
       
   495 	{
       
   496 	TRAPD(ret, CProtocolBase::NewHostResolverL());
       
   497 	return ret;
       
   498 	}
       
   499 
       
   500 EXPORT_C TInt CDummyProtocol::ProtocolBaseNewNetDatabase()
       
   501 	// expected to panic with Fault(EBadNetDBRequest)
       
   502 	{
       
   503 	TRAPD(ret, CProtocolBase::NewNetDatabaseL());
       
   504 	return ret;
       
   505 	}
       
   506 
       
   507 EXPORT_C TInt CDummyProtocol::ProtocolBaseNewSAP(TUint aProt)
       
   508 	// expected to panic with Fault(EOddSock)
       
   509 	{
       
   510 	TRAPD(ret, CProtocolBase::NewSAPL(aProt));
       
   511 	return ret;
       
   512 	}
       
   513 
       
   514 EXPORT_C TInt CDummyProtocol::ProtocolBaseNewServiceResolver()
       
   515 	// expected to panic with Fault(EBadServiceResolver)
       
   516 	{
       
   517 	TRAPD(ret, CProtocolBase::NewServiceResolverL());
       
   518 	return ret;
       
   519 	}
       
   520 
       
   521 EXPORT_C TInt CDummyProtocol::ProtocolBaseProcess(RMBufChain &aChain, CProtocolBase* aProt)
       
   522 	// expected to panic with Panic(ECantProcessMbufs)
       
   523 	{
       
   524 	CProtocolBase::Process(aChain, aProt);
       
   525 	return KErrNone;
       
   526 	}
       
   527 
       
   528 EXPORT_C TInt CDummyProtocol::ProtocolBaseSend(RMBufChain &aChain, CProtocolBase* aProt)
       
   529 	// expected to panic with Panic(ECantSendMBufs);
       
   530 	{
       
   531 	TInt ret = CProtocolBase::Send(aChain, aProt);
       
   532 	return ret;
       
   533 	}
       
   534 
       
   535 EXPORT_C TInt CDummyProtocol::ProtocolBaseSetOption(TUint aLevel, TUint aName, TDes8& aBuf, CProtocolBase* aProt)
       
   536 	// expected to return KErrNotSupported
       
   537 	{
       
   538 	TInt ret = CProtocolBase::SetOption(aLevel, aName, aBuf, aProt);
       
   539 	__ASSERT_DEBUG(ret == KErrNotSupported, User::Panic(KSpecAssert_ESockTestPDUMMY, 2));
       
   540 	return ret;
       
   541 	}
       
   542 
       
   543 EXPORT_C TInt CDummyProtocol::ProtocolBaseSendWithAddress(TDes8& aBuf,TSockAddr* aTo ,TSockAddr* aFrom, CProtocolBase* aProt)
       
   544 	// expected to panic with Panic(ECantSendMBufs);
       
   545 	{
       
   546 	TInt ret = CProtocolBase::Send(aBuf, aTo, aFrom, aProt);
       
   547 	return ret;
       
   548 	}
       
   549 
       
   550 
       
   551 EXPORT_C TInt CDummyProtocol::ProtocolBaseProcessWithAddress(TDes8& aBuf, TSockAddr* aFrom, TSockAddr* aTo, CProtocolBase* aProt)
       
   552 	// expected to panic with Panic(ECantProcessMbufs)
       
   553 	{
       
   554 	CProtocolBase::Process(aBuf, aFrom, aTo, aProt);
       
   555 	return KErrNone;
       
   556 	}
       
   557 
       
   558 //---------------------------------------------------------------------------------------------------------
       
   559 
       
   560 CDummyProvd *CDummyProvd::NewL(CDummyProtocol &aProtocol)
       
   561 	{
       
   562 	CDummyProvd *sp=new(ELeave) CDummyProvd(aProtocol);
       
   563 	CleanupStack::PushL(sp);
       
   564 	sp->ConstructL();
       
   565 	CleanupStack::Pop(sp);
       
   566 	return sp;
       
   567 
       
   568 	}
       
   569 
       
   570 void CDummyProvd::ConstructL()
       
   571 	{
       
   572 	iDataArray = new (ELeave) CArrayFixFlat<RMBufChain>(KPDummyDefaultGranularity);
       
   573 	iChain.AllocL(128);
       
   574 	}
       
   575 
       
   576 TInt CDummyProvd::NoBearerCB(TAny* aArg)
       
   577 /**
       
   578 Issue a NoBearer() upcall to ESock.
       
   579  */
       
   580     {
       
   581     CDummyProvd* This = static_cast<CDummyProvd*>(aArg);
       
   582     // Scoped NoBearer() prevents a connection from being started by ESock - a side-effect we aren't interested in.
       
   583     _LIT8(KScoped, "scoped");
       
   584     This->iSocket->NoBearer(KScoped()); 
       
   585     return KErrNone;
       
   586     }
       
   587 
       
   588 CDummyProvd::CDummyProvd(CDummyProtocol &aProtocol) :
       
   589 	  iCancelIoctl(EFalse),
       
   590 	  iFlowOffWriteTimeout(0),
       
   591 	  iErrNoMBufs(EFalse),
       
   592 	  iNoBearerCB(TCallBack(NoBearerCB, this), EPriorityNormal)
       
   593 	{
       
   594 	__DECLARE_NAME(_S("CDummyProvd"));
       
   595 	iIsBound=EFalse;
       
   596 	iProtocol=&aProtocol;
       
   597 	iCompleteIoctl = FALSE;
       
   598 	iConnectCompleteState = ETrue;
       
   599 	iConnectPending = EFalse;
       
   600 	}
       
   601 
       
   602 CDummyProvd::~CDummyProvd()
       
   603 //
       
   604 
       
   605 	{
       
   606 	if (iDataArray)
       
   607 		{
       
   608 		TInt c = iDataArray->Count();
       
   609 		TInt i;
       
   610 		for (i=0; i < c; ++i)
       
   611 			{
       
   612 			iDataArray->At(i).Free();
       
   613 			}
       
   614 		delete iDataArray;
       
   615 		}
       
   616 
       
   617 	iListenData.Close();
       
   618 	iChain.Free();
       
   619 	delete iFlowOnTimer;
       
   620 	}
       
   621 
       
   622 void CDummyProvd::DestroyAsyncErrorer()
       
   623 	{
       
   624 	delete iAsyncErrorer;
       
   625 	iAsyncErrorer = NULL;
       
   626 	}
       
   627 
       
   628 
       
   629 void CDummyProvd::LocalName(TSockAddr& anAddr) const
       
   630 	{
       
   631 	anAddr=iAddr;
       
   632 	}
       
   633 
       
   634 TInt CDummyProvd::SetLocalName(TSockAddr& anAddr)
       
   635 	{
       
   636 	iAddr=anAddr;
       
   637 	iIsBound=ETrue;
       
   638 	return KErrNone;
       
   639 	}
       
   640 
       
   641 void CDummyProvd::RemName(TSockAddr& /*anAddr*/)const
       
   642 	{
       
   643 	}
       
   644 
       
   645 TInt CDummyProvd::SetRemName(TSockAddr& /*anAddr*/)
       
   646 	{
       
   647 	return KErrNone;
       
   648 	}
       
   649 
       
   650 TInt CDummyProvd::GetOption(TUint aLevel, TUint aName, TDes8& anOption) const
       
   651 	{
       
   652 	if(aLevel==KNifOptLevel)
       
   653 		{
       
   654 		return iProtocol->GetOption(aLevel, aName, anOption, 0);
       
   655 		}
       
   656 	else
       
   657 		{
       
   658 		switch(aName)
       
   659 			{
       
   660 			case KDummyOptionSetBlockConnect:
       
   661 				{
       
   662 				TBool blockedConnect = !iConnectCompleteState;
       
   663 				const TUint8* opt = reinterpret_cast<const TUint8*>(&blockedConnect);
       
   664 				anOption.Copy(opt,sizeof(blockedConnect));
       
   665 				return KErrNone;
       
   666 				}
       
   667 			case KDummyOptionSetErrorNextWrite:
       
   668 				{
       
   669 				anOption.Copy(reinterpret_cast<const TUint8*>(&iErrorForNextWrite), sizeof(iErrorForNextWrite));
       
   670 				return KErrNone;
       
   671 				}
       
   672 			case KDummyOptionSetErrorNextShutdown:
       
   673 				{
       
   674 				anOption.Copy(reinterpret_cast<const TUint8*>(&iErrorForNextShutdown), sizeof(iErrorForNextShutdown));
       
   675 				return KErrNone;
       
   676 				}
       
   677 			case KDummyOptionSetErrorNextConnect:
       
   678 				{
       
   679 				anOption.Copy(reinterpret_cast<const TUint8*>(&iErrorForNextConnect), sizeof(iErrorForNextConnect));
       
   680 				return KErrNone;
       
   681 				}
       
   682 			case KDummyOptionGetMBufFreeSpace:
       
   683 				{
       
   684 				RMBufAllocator mBufAllocator;
       
   685 				TInt availableBytes = mBufAllocator.BytesAvailable();
       
   686 				anOption.Copy(reinterpret_cast<const TUint8*>(&availableBytes), sizeof(availableBytes));
       
   687 				return KErrNone;
       
   688 				}
       
   689 			default:
       
   690 				return KErrNotSupported;
       
   691 			}
       
   692 		}
       
   693 	}
       
   694 
       
   695 TInt CDummyProvd::SetOption(TUint level,TUint name,const TDesC8& anOption)
       
   696 	{
       
   697 	switch(name)
       
   698 		{
       
   699 		case KDummyOptionSetErrorNextListen:
       
   700 			iListenErrorCode=*(TInt*)&anOption[0];
       
   701 			break;
       
   702 		case KDummyOptionSetConnectComplete:
       
   703 			__ASSERT_DEBUG(!iAsyncErrorer, User::Panic(KSpecAssert_ESockTestPDUMMY, 3));	// to support multiple outstanding would need a list
       
   704 				{
       
   705 				TInt ret = KErrNone;
       
   706 				if (iListenData.Length())
       
   707 					{
       
   708 					TRAP(ret,iAsyncErrorer = CAsyncSocketErrorer::NewL(*iSocket, KErrNone,0, iProtocol, this, &iListenData));
       
   709 					}
       
   710 			    else
       
   711 			    	{
       
   712 			    	TRAP(ret,iAsyncErrorer = CAsyncSocketErrorer::NewL(*iSocket,KErrNone,0,iProtocol,this,NULL));
       
   713 			    	}
       
   714 	            return ret;
       
   715 				}
       
   716 		case KDummyOptionSetBlockConnect:
       
   717 			return SetBlockedConnect(anOption);
       
   718 		case KDummyOptionSetBlockConnectData:
       
   719 			{
       
   720 			TBool opt = *reinterpret_cast<const TBool*>(anOption.Ptr());
       
   721 			if (!opt)	
       
   722 				{
       
   723 				iListenData.Create(KConnectCompleteData());
       
   724 				}
       
   725 			else
       
   726 				{
       
   727 				iConnectPending = ETrue;	
       
   728 				}
       
   729 			return SetBlockedConnect(anOption);
       
   730 			}			
       
   731 		case KDummyOptionSetIocltComplete:
       
   732 			if (iCompleteIoctl)
       
   733 				{
       
   734 				iSocket->IoctlComplete(NULL);
       
   735 				iCompleteIoctl = EFalse;
       
   736 				}
       
   737 			break;
       
   738 		case KDummyOptionSetErrorNextWrite:
       
   739 			return OptToErr(anOption,iErrorForNextWrite);
       
   740 		case KDummyOptionSetErrorNextShutdown:
       
   741 			return OptToErr(anOption,iErrorForNextShutdown);
       
   742 		case KDummyOptionSetErrorNextConnect:
       
   743 			return OptToErr(anOption,iErrorForNextConnect);
       
   744 
       
   745 	case KDummyOptionSetFlowOffWrite:
       
   746 		{
       
   747 		if (anOption.Length() != sizeof(TBool))
       
   748 			return KErrArgument;
       
   749 
       
   750 		iFlowOffWrite = *reinterpret_cast<const TBool*>(anOption.Ptr());
       
   751 		if (!iFlowOffWrite)
       
   752 			iSocket->CanSend();
       
   753 		}
       
   754 		break;
       
   755 
       
   756 
       
   757 	case KDummyOptionSetTimedFlowOffWrite:
       
   758 		{
       
   759 		if (anOption.Length() != sizeof(TInt))
       
   760 			return KErrArgument;
       
   761 
       
   762 		iFlowOffWriteTimeout = *reinterpret_cast<const TInt*>(anOption.Ptr());
       
   763 		if (iFlowOffWriteTimeout > 0)
       
   764 			{
       
   765 			if (!iFlowOnTimer)
       
   766 				{
       
   767 				TRAPD(ret, iFlowOnTimer = CFlowOnTimer::NewL(*this, *iSocket));
       
   768 				if (ret)
       
   769 					return ret;
       
   770 				}
       
   771 			}
       
   772 		else if (iFlowOffWriteTimeout == 0)
       
   773 			{
       
   774 			delete iFlowOnTimer;
       
   775 			iFlowOnTimer = NULL;
       
   776 			}
       
   777 		else
       
   778 			return KErrArgument;
       
   779 		}
       
   780 		break;
       
   781 
       
   782 	case KDummyOptionSetGobbleMBufs:
       
   783 		{
       
   784 		iErrNoMBufs = ETrue;
       
   785 		return GobbleMBufs();
       
   786 		}
       
   787 
       
   788 	case KDummyOptionSetFreeMBufs:
       
   789 		{
       
   790 		iErrNoMBufs = EFalse;
       
   791 		FreeMBufs();
       
   792 		break;
       
   793 		}
       
   794 
       
   795 	case KDummyOptionSetFreeSomeMBufs:
       
   796 		{
       
   797 		iErrNoMBufs = EFalse;
       
   798 		FreeMBufs(level);
       
   799 		break;
       
   800 		}
       
   801 
       
   802 
       
   803 	case KDummyOptionLeakMemory:
       
   804 		{
       
   805 		for(TUint i = 0; i < level; ++i)
       
   806 			{
       
   807 			(void) new TInt;	// deliberately leak the allocs
       
   808 			}
       
   809 		return KErrNone;
       
   810 		}
       
   811 		
       
   812 	case KDummyOptionIssueNoBearer:
       
   813 	    {
       
   814 	    // Issue a NoBearer() upcall.  We are testing the behaviour whereby NoBearer() is called
       
   815 	    // outside the context of any pending IPC.  We use an async callback to ensure that the current
       
   816 	    // SetOption() IPC is completed by ESock before the NoBearer() upcall.
       
   817 	    iNoBearerCB.Call();
       
   818 	    return KErrNone;
       
   819 	    }
       
   820 
       
   821 	default:
       
   822 		return KErrNotSupported;
       
   823 		}
       
   824 	return KErrNone;
       
   825 	}
       
   826 
       
   827 TInt CDummyProvd::GobbleMBufs()
       
   828 // Eat all the available mBufs in the mBuf pool
       
   829 	{
       
   830 	RMBufAllocator allocator;
       
   831 	RMBufChain aChain;
       
   832 	TInt size = allocator.NextMBufSize(0);
       
   833 	while (size != KErrNotFound)
       
   834 		{
       
   835 		TInt ret = KErrNone;
       
   836 		while (ret == KErrNone)
       
   837 			{
       
   838 			TRAP(ret, aChain.AllocL(size));
       
   839 			iChain.Append(aChain);
       
   840 			}
       
   841 		size = allocator.NextMBufSize(size);
       
   842 		}
       
   843 		
       
   844 	TInt length = iChain.Length();
       
   845 	RDebug::Print(_L("Out of MBuf Memory... Total MBuf memory in use %d"), length);
       
   846 	TInt numBufs = iChain.NumBufs();
       
   847 	RDebug::Print(_L("Out of MBuf Memory... Total MBufs in use %d"), numBufs);
       
   848 	return numBufs;
       
   849 	}
       
   850 
       
   851 void CDummyProvd::FreeMBufs()
       
   852 // Free All the MBufs that were allocated by GobbleMBufs
       
   853 	{
       
   854 	if(iChain.IsEmpty())
       
   855 		{
       
   856 		return;
       
   857 		}
       
   858 	iChain.Free();
       
   859 	TInt length = iChain.Length();
       
   860 	RDebug::Print(_L("MBufMemory De-Allocated... Total MBuf memory in use %d"), length);
       
   861 	}
       
   862 
       
   863 void CDummyProvd::FreeMBufs(TUint aNumber)
       
   864 // Free aNumber of mBufs that were allocated by GobbleMBufs
       
   865 	{
       
   866 	if(iChain.IsEmpty())
       
   867 		{
       
   868 		return;
       
   869 		}
       
   870 	TInt length = 0;
       
   871 	while (aNumber-- > 0)
       
   872 		{
       
   873 		TInt length = iChain.Length();
       
   874 		if (length == 0)
       
   875 			{
       
   876 			break;
       
   877 			}
       
   878 		TInt trimOffset = length - iChain.Last()->Size();
       
   879 		iChain.TrimEnd(trimOffset);
       
   880 		}
       
   881 	length = iChain.Length();
       
   882 	RDebug::Print(_L("MBufMemory De-Allocated... Total MBuf memory in use %d"), length);
       
   883 	}
       
   884 
       
   885 
       
   886 TInt CDummyProvd::OptToErr(const TDesC8 &aOption, TInt &aRes)
       
   887 	{
       
   888 	if (aOption.Length() != sizeof(TInt))
       
   889 		{
       
   890 		return KErrCorrupt;
       
   891 		}
       
   892 	const TInt &opt = *reinterpret_cast<const TInt*>(aOption.Ptr());
       
   893 	if (opt > KErrNone)
       
   894 		{
       
   895 		return KErrCorrupt;
       
   896 		}
       
   897 	aRes = opt;
       
   898 	return KErrNone;
       
   899 	}
       
   900 
       
   901 TInt CDummyProvd::SetBlockedConnect(const TDesC8 &anOption)
       
   902 	{
       
   903 	if (anOption.Length() != sizeof(TBool))
       
   904 		{
       
   905 		return KErrCorrupt;
       
   906 		}
       
   907 	TBool opt = *reinterpret_cast<const TBool*>(anOption.Ptr());
       
   908 	if (opt != TRUE && opt != FALSE)
       
   909 		{
       
   910 		return KErrCorrupt;
       
   911 		}
       
   912 	iConnectCompleteState = !opt;
       
   913 	if (iConnectCompleteState && iConnectPending)
       
   914 		{
       
   915 			if (iErrorForNextConnect != KErrNone)
       
   916 			{
       
   917 			iSocket->Error(iErrorForNextConnect, MSocketNotify::EErrorConnect);
       
   918 			iErrorForNextConnect = KErrNone;
       
   919 			return KErrNone;
       
   920 			}
       
   921 		if (iListenData.Length())
       
   922 			{
       
   923 			iSocket->ConnectComplete(iListenData);
       
   924 			}
       
   925 		else
       
   926 			{
       
   927 			iSocket->ConnectComplete();
       
   928 			}
       
   929 		iConnectPending = EFalse;
       
   930 		}
       
   931 	return KErrNone;
       
   932 	}
       
   933 
       
   934 void CDummyProvd::Ioctl(TUint /*level*/,TUint name,TDes8* anOption)
       
   935 	{
       
   936 	switch (name)
       
   937 		{
       
   938 		case KDummyIoctlCheckBound:
       
   939 			if (!iIsBound)
       
   940 				Panic(ENotBound);
       
   941 			iSocket->IoctlComplete(NULL);
       
   942 			break;
       
   943 		case KDummyIoctlCheckStarted:
       
   944 			if (!iProtocol->IsStarted())
       
   945 				Panic(ENotStarted);
       
   946 			iSocket->IoctlComplete(NULL);
       
   947 			break;
       
   948 		case KDummyIoctlIgnore:
       
   949 			iCancelIoctl=EFalse;
       
   950 			break;
       
   951 		case KDummyIoctlCancelled:
       
   952 			if(iCancelIoctl)
       
   953 				{
       
   954 				iSocket->IoctlComplete(NULL);
       
   955 				}
       
   956 			else
       
   957 				{
       
   958 				iSocket->Error(KErrNotFound,MSocketNotify::EErrorIoctl);
       
   959 				}
       
   960 			break;
       
   961 		case KDummyIoctlPanicProtocolModule:
       
   962 			Panic(ETestPanic);
       
   963 			iSocket->IoctlComplete(NULL); //Should never get here
       
   964 			break;
       
   965 		case KDummyIocltNonCompleting: //Ioclt never send back a complete message
       
   966 			iCompleteIoctl = TRUE;
       
   967 			break;
       
   968 		case KDummyIoctBlockHardOnClose:
       
   969 			iBlockOnClose = TRUE;
       
   970 			iSocket->IoctlComplete(NULL);
       
   971 			break;
       
   972 
       
   973 		case KDummyIoctlSlowIoctlReturn:
       
   974 			iSocket->IoctlComplete(NULL);
       
   975 			User::After(100000);
       
   976 			break;
       
   977 		case KDummyIoctlHangIoctlReturn:
       
   978 			iSocket->IoctlComplete(NULL);
       
   979 			HangModule();
       
   980 			break;
       
   981 		case KDummyIocltJustComplete:
       
   982 			iSocket->IoctlComplete(NULL);
       
   983 			break;
       
   984 		case KDummyIocltRemoteDisconnect:
       
   985 			if (anOption)
       
   986 				{
       
   987 				TBuf8<40> tmp(*anOption);
       
   988 				iSocket->Disconnect(tmp);
       
   989 				}
       
   990 			else
       
   991 				{
       
   992 				iSocket->Disconnect();
       
   993 				}
       
   994 			iSocket->IoctlComplete(NULL);
       
   995 			break;
       
   996 		
       
   997 		case KDummyIoctlCompleteWithData:
       
   998 			{
       
   999 			TBuf8<64> ioctlBuffer(KIoctlData());
       
  1000 			iSocket->IoctlComplete(	&ioctlBuffer );	
       
  1001 			}
       
  1002 			
       
  1003 			break;
       
  1004 		default:
       
  1005 			iSocket->Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
       
  1006 		}
       
  1007 	}
       
  1008 
       
  1009 void CDummyProvd::CancelIoctl(TUint /*aLevel*/,TUint /*aName*/)
       
  1010 	{
       
  1011 	iCancelIoctl=ETrue;
       
  1012 	}
       
  1013 
       
  1014 TInt CDummyProvd::Write(RMBufChain& aData,TUint aOptions, TSockAddr*)
       
  1015 	{
       
  1016 	if (iFlowOffWriteTimeout > 0)
       
  1017 		{
       
  1018 		__ASSERT_DEBUG(iFlowOffWriteTimeout, User::Panic(KSpecAssert_ESockTestPDUMMY, 4));
       
  1019 		iFlowOnTimer->After(iFlowOffWriteTimeout);
       
  1020 		return 0;
       
  1021 		}
       
  1022 
       
  1023 	if (iFlowOffWrite)
       
  1024 		return 0;
       
  1025 
       
  1026 	if (aOptions==KSockWriteUrgent)
       
  1027 		{
       
  1028 		iSocket->Error(KErrNotSupported);
       
  1029 		return 0;
       
  1030 		}
       
  1031 	if (iErrorForNextWrite != KErrNone)
       
  1032 		{
       
  1033 		iSocket->Error(iErrorForNextWrite, MSocketNotify::EErrorSend);
       
  1034 		iErrorForNextWrite = KErrNone;
       
  1035 		return 0;
       
  1036 		}
       
  1037 
       
  1038 	// From opposite angle, we dont need a new chain if it is a stream
       
  1039 	// we just append to the existing, unless there isn't an existing...
       
  1040 	if(iDataArray->Count()==0 || IsTransportType(KSockDatagram))
       
  1041 		{
       
  1042 		RMBufChain chain;
       
  1043 		TRAPD(ret, iDataArray->AppendL(chain));
       
  1044 		if(ret!=KErrNone)
       
  1045 			return ret;
       
  1046 		}
       
  1047 
       
  1048 	iDataArray->At(iDataArray->Count()-1).Append(aData);
       
  1049 
       
  1050 	// Gotta save the length of the chain before calling
       
  1051 	// NewData, as it could be changed after the call
       
  1052 	// (We need to be re-entrant).
       
  1053 	TInt consumed;
       
  1054 	if(IsTransportType(KSockStream))
       
  1055 		{
       
  1056 		consumed = iDataArray->At(iDataArray->Count()-1).Length();
       
  1057 		}
       
  1058 	else
       
  1059 		{
       
  1060 		consumed = 1;
       
  1061 		}
       
  1062 
       
  1063 	if(!iInputStopped)
       
  1064 		{
       
  1065 		if(IsTransportType(KSockDatagram))
       
  1066 			iSocket->NewData(1);
       
  1067 		else
       
  1068 			iSocket->NewData(consumed);
       
  1069 		}
       
  1070 
       
  1071 	return consumed;
       
  1072 	}
       
  1073 
       
  1074 TUint CDummyProvd::Write(const TDesC8& aDesc, TUint options, TSockAddr* anAddr)
       
  1075 	{
       
  1076 	if (iFlowOffWriteTimeout > 0)
       
  1077 		{
       
  1078 		__ASSERT_DEBUG(iFlowOffWriteTimeout, User::Panic(KSpecAssert_ESockTestPDUMMY, 5));
       
  1079 		iFlowOnTimer->After(iFlowOffWriteTimeout);
       
  1080 		return 0;
       
  1081 		}
       
  1082 
       
  1083 	if (iFlowOffWrite)
       
  1084 		return 0;
       
  1085 
       
  1086 	RMBufChain chain;
       
  1087 	TRAPD(r,chain.CreateL(aDesc));
       
  1088 	if (r != KErrNone)
       
  1089 		{
       
  1090 		return r;
       
  1091 		}
       
  1092 
       
  1093 	TInt ret = Write(chain, options, anAddr);
       
  1094 	if (ret<0)
       
  1095 		{
       
  1096 		return 0;
       
  1097 		}
       
  1098 	return ret;
       
  1099 	}
       
  1100 
       
  1101 TBool CDummyProvd::IsTransportType(TUint aType)
       
  1102 	{
       
  1103 	TServerProtocolDesc info;
       
  1104 	iProtocol->Identify(&info);
       
  1105 	return (info.iSockType==aType);
       
  1106 	}
       
  1107 
       
  1108 void CDummyProvd::GetData(TDes8& aDesc,TUint aOptions,TSockAddr* aAddr)
       
  1109 	{
       
  1110 	RMBufChain chain;
       
  1111 	GetData(chain,aDesc.MaxLength(),aOptions, aAddr);
       
  1112 	aDesc.SetMax();
       
  1113 	chain.CopyOut(aDesc);
       
  1114 	chain.Free();
       
  1115 	}
       
  1116 
       
  1117 TInt CDummyProvd::GetData(RMBufChain& aData,TUint aLength, TUint aOptions,TSockAddr* aAddr)
       
  1118 	{
       
  1119 	__ASSERT_DEBUG(iDataArray->Count()>0, User::Panic(KSpecAssert_ESockTestPDUMMY, 6));
       
  1120 	TInt res = KErrNone;
       
  1121 
       
  1122 	// If KSockReadPeek we copy the whole bally lot instead of moving it out.
       
  1123 	if((aOptions&KSockReadPeek)==KSockReadPeek)
       
  1124 		{
       
  1125 		TInt err;
       
  1126 		// For datagram, copy all datagram else copy just aLength
       
  1127 		if(!IsTransportType(KSockDatagram))
       
  1128 			{
       
  1129 			TRAP(err, iDataArray->At(0).CopyL(aData, 0, aLength));
       
  1130 //			iDataArray->At(0).TrimStart(aLength);
       
  1131 			}
       
  1132 		else
       
  1133 			{
       
  1134 			TRAP(err, iDataArray->At(0).CopyL(aData));
       
  1135 //			iDataArray->At(0).TrimStart(aData.Length());
       
  1136 			}
       
  1137 		if(res==KErrNone)
       
  1138 			{
       
  1139 			iSocket->NewData(1);
       
  1140 			}
       
  1141 		else
       
  1142 			{
       
  1143 			iDataArray->At(0).Free();
       
  1144 			}
       
  1145 		}
       
  1146 	else // Not KSockReadPeek
       
  1147 		{
       
  1148 		// Move datablock to receiving chain
       
  1149 		aData.Assign(iDataArray->At(0));
       
  1150 
       
  1151 		// For non-datagram types exact only amount of bytes
       
  1152 		// if they have more than asked for
       
  1153 		// so we move some of the data back to our array
       
  1154 		if( !IsTransportType(KSockDatagram) &&
       
  1155 			(((TUint)aData.Length())>aLength) )
       
  1156 			{
       
  1157 			// Put the tail back into our array for another good time
       
  1158 			TRAP(res, aData.SplitL(aLength, iDataArray->At(0)));
       
  1159 			// If it didnt work, save data internally again and return error
       
  1160 			if(res!=KErrNone)
       
  1161 				{
       
  1162 				iDataArray->At(0).Assign(aData);
       
  1163 				}
       
  1164 			}
       
  1165 		}
       
  1166 
       
  1167 	// No errors? Return number of bytes copied (stream) or 1 (dgram)
       
  1168 	if(res==KErrNone)
       
  1169 		{
       
  1170 		if(IsTransportType(KSockStream))
       
  1171 			{
       
  1172 			res = aData.Length();
       
  1173 			}
       
  1174 		else
       
  1175 			{
       
  1176 			res = 1;
       
  1177 			}
       
  1178 		}
       
  1179 	else // else report mbuf shortage
       
  1180 		{
       
  1181 		res=KErrNoMBufs;
       
  1182 		}
       
  1183 
       
  1184 	// Cleanup possibly unused chain
       
  1185 	if(iDataArray->At(0).Length()==0)
       
  1186 		iDataArray->Delete(0);
       
  1187 	
       
  1188 	// Copy the TSockAddr if requested
       
  1189 	if ( aAddr )
       
  1190 		{
       
  1191 		const TUint KProxyAddrFamily=0x20000;		
       
  1192 		TSockAddr addr(KProxyAddrFamily);
       
  1193 		aAddr->Copy(addr);
       
  1194 		}
       
  1195 	return res;
       
  1196 	}
       
  1197 
       
  1198 
       
  1199 void CDummyProvd::ActiveOpen(void)
       
  1200 	{
       
  1201 	if (iErrorForNextConnect != KErrNone)
       
  1202 		{
       
  1203 		iSocket->Error(iErrorForNextConnect, MSocketNotify::EErrorConnect);
       
  1204 		iErrorForNextConnect = KErrNone;
       
  1205 		return;
       
  1206 		}
       
  1207 	if (iConnectCompleteState)
       
  1208 		{
       
  1209 		iSocket->ConnectComplete();
       
  1210 		}
       
  1211 	else
       
  1212 		{
       
  1213 		if(iListenData.Length())
       
  1214 			{
       
  1215 			iListenData.Close();
       
  1216 			}
       
  1217 		iConnectPending = ETrue;
       
  1218 		}
       
  1219 	}
       
  1220 
       
  1221 void CDummyProvd::ActiveOpen(const TDesC8& aConnectionData)
       
  1222 	{
       
  1223 		if (iErrorForNextConnect != KErrNone)
       
  1224 		{
       
  1225 		iSocket->Error(iErrorForNextConnect, MSocketNotify::EErrorConnect);
       
  1226 		iErrorForNextConnect = KErrNone;
       
  1227 		return;
       
  1228 		}
       
  1229 	if (iConnectCompleteState)
       
  1230 		{
       
  1231 		iSocket->ConnectComplete(aConnectionData);
       
  1232 		}
       
  1233 	else
       
  1234 		{
       
  1235 		if(iListenData.Length())
       
  1236 			{
       
  1237 			iListenData.Close();
       
  1238 			}
       
  1239 		iListenData.Create(aConnectionData);
       
  1240 		iConnectPending = ETrue;
       
  1241 		}
       
  1242 	}
       
  1243 
       
  1244 TInt CDummyProvd::PassiveOpen(TUint /*aQue*/)
       
  1245 	{
       
  1246 //	test.Printf(_L("CDummyProvd::Open\n"));
       
  1247 	if(iListenErrorCode)
       
  1248 		{// We're going to error this call, but can't do it synchonously.
       
  1249 		// Do it with an AO of max prio, so we know it will happen next
       
  1250 //		iSocket->Error(iListenErrorCode);// Error all operations
       
  1251 		__ASSERT_DEBUG(!iAsyncErrorer, User::Panic(KSpecAssert_ESockTestPDUMMY, 7));	// to support multiple outstanding would need a list
       
  1252 		TRAPD(err, iAsyncErrorer = CAsyncSocketErrorer::NewL(*iSocket,iListenErrorCode,MSocketNotify::EErrorConnect,0,this,NULL));
       
  1253 		iListenErrorCode=KErrNone;
       
  1254 		return err;
       
  1255 		}
       
  1256 	return KErrNone;
       
  1257 	}
       
  1258 
       
  1259 TInt CDummyProvd::PassiveOpen(TUint /*aQue*/, const TDesC8& aConnectionData)
       
  1260 	{
       
  1261 	iListenData.Close();
       
  1262 	TInt ret = iListenData.Create(aConnectionData);
       
  1263 	if (ret != KErrNone)
       
  1264 		{
       
  1265 		return ret;
       
  1266 		}
       
  1267 		if(iListenErrorCode)
       
  1268 		{// We're going to error this call, but can't do it synchonously.
       
  1269 		// Do it with an AO of max prio, so we know it will happen next
       
  1270 //		iSocket->Error(iListenErrorCode);// Error all operations
       
  1271 		__ASSERT_DEBUG(!iAsyncErrorer, User::Panic(KSpecAssert_ESockTestPDUMMY, 8));	// to support multiple outstanding would need a list
       
  1272 		TRAPD(err, iAsyncErrorer = CAsyncSocketErrorer::NewL(*iSocket, iListenErrorCode, MSocketNotify::EErrorConnect, 0, this, &aConnectionData));
       
  1273 		iListenErrorCode=KErrNone;
       
  1274 		return err;
       
  1275 		}
       
  1276 	return KErrNone;
       
  1277 	}
       
  1278 
       
  1279 
       
  1280 void CDummyProvd::Shutdown(TCloseType anOption)
       
  1281 	{
       
  1282 	if (iErrorForNextShutdown != KErrNone)
       
  1283 		{
       
  1284 		iSocket->Error(iErrorForNextShutdown, MSocketNotify::EErrorClose);
       
  1285 		iErrorForNextShutdown = KErrNone;
       
  1286 		return;
       
  1287 		}
       
  1288 	if (iBlockOnClose)
       
  1289 		{
       
  1290 		HangModule();
       
  1291 		}
       
  1292 	DestroyAsyncErrorer();
       
  1293 
       
  1294 	if(anOption==EStopInput)
       
  1295 		iInputStopped=ETrue;
       
  1296 	if(anOption==EStopOutput)
       
  1297 		{
       
  1298 
       
  1299 		TInt c = iDataArray->Count();
       
  1300 		TInt i;
       
  1301 		for (i=0; i < c; ++i)
       
  1302 			{
       
  1303 			iDataArray->At(i).Free();
       
  1304 			}
       
  1305 		iDataArray->Reset();
       
  1306 
       
  1307 
       
  1308 		_LIT8(KEndOfData, "End of Data");
       
  1309 		RMBufChain datachain;
       
  1310 		TRAPD(res, iDataArray->AppendL(datachain));
       
  1311 
       
  1312 		if(res!=KErrNone)
       
  1313 			iSocket->Error(KErrNoMemory);
       
  1314 		else
       
  1315 			{
       
  1316 			TRAPD(res, iDataArray->At(0).CreateL(KEndOfData));
       
  1317 
       
  1318 			if(res!=KErrNone)
       
  1319 				iSocket->Error(KErrNoMemory);
       
  1320 			else
       
  1321 				{
       
  1322 				if(IsTransportType(KSockDatagram))
       
  1323 					{
       
  1324 					iSocket->NewData(1);
       
  1325 					}
       
  1326 				else
       
  1327 					{
       
  1328 					iSocket->NewData(iDataArray->At(0).Length());
       
  1329 					}
       
  1330 				iSocket->NewData(KNewDataEndofData);
       
  1331 				}
       
  1332 			}
       
  1333 		}
       
  1334 	if (anOption==ENormal)
       
  1335 		iSocket->CanClose();
       
  1336 	}
       
  1337 
       
  1338 void CDummyProvd::Start()
       
  1339 //
       
  1340 //
       
  1341 //
       
  1342 	{
       
  1343 	}
       
  1344 
       
  1345 void CDummyProvd::Shutdown(TCloseType /*anOption*/,const TDesC8 &/*aDisconnectData*/)
       
  1346 	{
       
  1347 	Panic(EBadCall);
       
  1348 	}
       
  1349 
       
  1350 void CDummyProvd::AutoBind( void )
       
  1351 	{
       
  1352 //	test.Printf(_L("CDummyProvd::AutoBind\n"));
       
  1353 	iIsBound=ETrue;
       
  1354 
       
  1355 	}
       
  1356 void CDummyProvd::HangModule(void)
       
  1357 	{
       
  1358 	TInt val;
       
  1359 	TInt shutdownVal;
       
  1360 	RProperty hangProp;
       
  1361 	TRequestStatus hangStat;
       
  1362 
       
  1363 	hangProp.Attach(KDummyUid,KDummyTerminationProperty);
       
  1364 	hangProp.Subscribe(hangStat);
       
  1365 	hangProp.Get(shutdownVal);
       
  1366 	val = shutdownVal + 1;
       
  1367 	hangProp.Set(val);
       
  1368 
       
  1369 	while (val > shutdownVal)
       
  1370 		{
       
  1371 		User::WaitForRequest(hangStat);
       
  1372 		hangProp.Subscribe(hangStat);
       
  1373 		hangProp.Get(val);
       
  1374 		}
       
  1375 	hangProp.Set(shutdownVal - 1);
       
  1376 	hangProp.Cancel();
       
  1377 	User::WaitForRequest(hangStat);
       
  1378 	hangProp.Close();
       
  1379 	}
       
  1380 
       
  1381 //
       
  1382 
       
  1383 TInt CDummyProvd::SecurityCheck(MProvdSecurityChecker* /*aChecker*/)
       
  1384 /**
       
  1385 Perform a security policy check on the client process (default implementation).
       
  1386 */
       
  1387 	{
       
  1388 	return KErrNone;
       
  1389 	}
       
  1390 
       
  1391 
       
  1392 //---------------------------------------------------------------------------------------------------------
       
  1393 
       
  1394 #pragma warning( default : 4100)
       
  1395 
       
  1396 CDatagramHostResolver::CDatagramHostResolver()
       
  1397 //
       
  1398 //
       
  1399 //
       
  1400 	{
       
  1401 	__DECLARE_NAME(_S("CDatagramHostResolver"));
       
  1402 	}
       
  1403 
       
  1404 CDatagramHostResolver::~CDatagramHostResolver()
       
  1405 {
       
  1406     delete ipDNSQueryProcessor;
       
  1407 }
       
  1408 
       
  1409 CDatagramHostResolver* CDatagramHostResolver::NewL()
       
  1410 //
       
  1411 // Make a new resolver
       
  1412 //
       
  1413 	{
       
  1414 
       
  1415       CDatagramHostResolver* self = new(ELeave) CDatagramHostResolver();
       
  1416 
       
  1417       CleanupStack::PushL(self);
       
  1418       self->ConstructL();
       
  1419       CleanupStack::Pop();
       
  1420 
       
  1421       return  self;
       
  1422 	}
       
  1423 
       
  1424 void CDatagramHostResolver::ConstructL()
       
  1425 {
       
  1426     //-- construct DNS Query processor
       
  1427     ipDNSQueryProcessor = CDNSQueryProcessor::NewL();
       
  1428 }
       
  1429 
       
  1430 void CDatagramHostResolver::CancelCurrentOperation()
       
  1431 //
       
  1432 //
       
  1433 //
       
  1434 	{
       
  1435 	    //-- cancel possible pending DNS Query processor request
       
  1436         if(ipDNSQueryProcessor)
       
  1437             ipDNSQueryProcessor->Cancel();
       
  1438 	}
       
  1439 
       
  1440 
       
  1441 void CDatagramHostResolver::GetByName(TNameRecord &aName)
       
  1442 //
       
  1443 //
       
  1444 //
       
  1445 	{
       
  1446 
       
  1447 	if(aName.iName==_L("DontComplete"))
       
  1448 		return;
       
  1449 
       
  1450 	aName.iAddr.SetFamily(KDummyAddrFamily);
       
  1451 	aName.iAddr.SetPort(0);
       
  1452 	if(aName.iFlags==0)
       
  1453 		{
       
  1454 		aName.iName=_L("Name One");
       
  1455 		aName.iFlags=0;
       
  1456 		iNotify->QueryComplete(KErrNone);
       
  1457 		}
       
  1458 	else if(aName.iFlags==1)
       
  1459 		{
       
  1460 		aName.iName=_L("Name Two");
       
  1461 		aName.iFlags=0;
       
  1462 		iNotify->QueryComplete(KErrNone);
       
  1463 		}
       
  1464 	else if(aName.iFlags==4)
       
  1465 		{
       
  1466 		aName.iName=_L("Name Five");
       
  1467 		aName.iFlags=0;
       
  1468 		iNotify->QueryComplete(KErrNone);
       
  1469 		}
       
  1470 	else
       
  1471 		iNotify->QueryComplete(KErrEof);
       
  1472 	}
       
  1473 
       
  1474 void CDatagramHostResolver::GetByAddress(TNameRecord &aName)
       
  1475 //
       
  1476 //
       
  1477 //
       
  1478 	{
       
  1479 
       
  1480 	aName.iName=_L("");
       
  1481 	if(aName.iFlags==0)
       
  1482 		{
       
  1483 		aName.iAddr.SetPort(10);
       
  1484 		aName.iFlags=0;
       
  1485 		iNotify->QueryComplete(KErrNone);
       
  1486 		}
       
  1487 	else if(aName.iFlags==1)
       
  1488 		{
       
  1489 		aName.iAddr.SetPort(11);
       
  1490 		aName.iFlags=0;
       
  1491 		iNotify->QueryComplete(KErrNone);
       
  1492 		}
       
  1493 	else
       
  1494 		iNotify->QueryComplete(KErrEof);
       
  1495 	}
       
  1496 
       
  1497 void CDatagramHostResolver::SetHostName(TDes & aNameBuf)
       
  1498 //
       
  1499 //
       
  1500 //
       
  1501 	{
       
  1502 	if(aNameBuf!=_L("Tara"))
       
  1503 		iNotify->QueryComplete(KErrNotSupported);
       
  1504 	else
       
  1505 		iNotify->QueryComplete(KErrNone);
       
  1506 	}
       
  1507 
       
  1508 void CDatagramHostResolver::GetHostName(TDes &aNameBuf)
       
  1509 //
       
  1510 //
       
  1511 //
       
  1512 	{
       
  1513 	aNameBuf=_S("PDummyHostName");
       
  1514 	iNotify->QueryComplete(KErrNone);
       
  1515 	}
       
  1516 
       
  1517 /**
       
  1518 *   Implementation "Query" function for CHostResolver. Simulates Query(...) behaviour, checks query data validity
       
  1519 *   and forges query response that shall be checked at client side.
       
  1520 *
       
  1521 * @param    aQryBuf  descriptor representing query data.
       
  1522 * @param    aResBuf  descriptor representing query response data.
       
  1523 * @param    aCounter query sequential number counter. From the client's point of view it will be 0 for "Query" call
       
  1524 *           and increased by 1 for each "QueryGetNext" call.
       
  1525 * @note     for aCounter > 0 data in aQryBuf may be invalid.
       
  1526 */
       
  1527 void CDatagramHostResolver::Query(const TDesC8& aQryBuf, TDes8& aResBuf, TInt aCounter)
       
  1528 {
       
  1529 
       
  1530     //-- convert 1st parameter to the reference to TDnsQuery.
       
  1531     //-- Actually, for pdummy.prt and tcpip6.prt aQryBuf is a reference to the TDnsQueryBuf indeed,
       
  1532     //-- but for the RHostresolver and CHostResolver protocol independency all the data passes like references to
       
  1533     //-- the raw buffers.
       
  1534     const TDnsQuery &dnsQry = * (reinterpret_cast<const TDnsQuery*> (aQryBuf.Ptr()));
       
  1535 
       
  1536     //-- set Query proccessor notifier.
       
  1537     //-- On request completion Query processor will call iNotify->QueryComplete();
       
  1538     ipDNSQueryProcessor->SetNotifier(iNotify);
       
  1539 
       
  1540     //-- process and complete query, calling iNotify->QueryComplete() later
       
  1541     ipDNSQueryProcessor->ProcessQuery(dnsQry, aResBuf, aCounter);
       
  1542 }
       
  1543 
       
  1544 
       
  1545 TInt CDatagramHostResolver::SetOption(TUint /*aLevel*/, TUint /*aName*/, const TDesC8 &/*anOption*/)
       
  1546 //
       
  1547 //
       
  1548 //
       
  1549 	{
       
  1550 	return (KErrNotSupported);
       
  1551 	}
       
  1552 
       
  1553 
       
  1554 
       
  1555 TInt CDatagramHostResolver::SecurityCheck(MProvdSecurityChecker* /*aChecker*/)
       
  1556 /**
       
  1557 Perform a security policy check on the client process (default implementation).
       
  1558 */
       
  1559 	{
       
  1560 	return KErrNone;
       
  1561 	}
       
  1562 
       
  1563 CDatagramServResolver::CDatagramServResolver()
       
  1564 //
       
  1565 //
       
  1566 //
       
  1567 	{
       
  1568 	__DECLARE_NAME(_S("CDatagramServResolver"));
       
  1569 	}
       
  1570 
       
  1571 CDatagramServResolver* CDatagramServResolver::NewL()
       
  1572 //
       
  1573 //
       
  1574 //
       
  1575 	{
       
  1576 	return new(ELeave) CDatagramServResolver;
       
  1577 	}
       
  1578 
       
  1579 void CDatagramServResolver::CancelCurrentOperation()
       
  1580 //
       
  1581 //
       
  1582 //
       
  1583 	{
       
  1584 	// were always synchronous so don't actually do anything
       
  1585 	}
       
  1586 
       
  1587 void CDatagramServResolver::GetByName(const TDesC & aNameBuf,TInt32 & aPortNum)
       
  1588 
       
  1589 //
       
  1590 //
       
  1591 //
       
  1592 	{
       
  1593 
       
  1594 	if(aNameBuf!=_L("DummyName"))
       
  1595 		{
       
  1596 		iNotify->QueryComplete(KErrNotFound);
       
  1597 		return;
       
  1598 		}
       
  1599 	aPortNum=64;
       
  1600 	iNotify->QueryComplete(KErrNone);
       
  1601 	}
       
  1602 
       
  1603 void CDatagramServResolver::GetByNumber(TDes & aNameBuf,TInt32 aPortNum)
       
  1604 //
       
  1605 //
       
  1606 //
       
  1607 	{
       
  1608 
       
  1609 	if(aPortNum==66) // for testing cancel
       
  1610 		{
       
  1611 		return;
       
  1612 		}
       
  1613 
       
  1614 	if(aPortNum!=21)
       
  1615 		{
       
  1616 		iNotify->QueryComplete(KErrNotFound);
       
  1617 		return;
       
  1618 		}
       
  1619 	aNameBuf=_S("DummyService");
       
  1620 	iNotify->QueryComplete(KErrNone);
       
  1621 	}
       
  1622 
       
  1623 void CDatagramServResolver::RegisterService(const TDesC & aNameBuf,TInt32 aPortNum)
       
  1624 //
       
  1625 // Register a new service with the net database
       
  1626 //
       
  1627 	{
       
  1628 
       
  1629 	if(aNameBuf!=_L("Simpson") || aPortNum!=500)
       
  1630 		{
       
  1631 		iNotify->QueryComplete(KErrNotFound);
       
  1632 		return;
       
  1633 		}
       
  1634 	iNotify->QueryComplete(KErrNone);
       
  1635 	}
       
  1636 
       
  1637 void CDatagramServResolver::RemoveService(const TDesC & aNameBuf,TInt32 aPortNum)
       
  1638 //
       
  1639 // remove a service registered with the database
       
  1640 //
       
  1641 	{
       
  1642 
       
  1643 	if(aNameBuf!=_L("Colt") || aPortNum!=45)
       
  1644 		{
       
  1645 		iNotify->QueryComplete(KErrNotFound);
       
  1646 		return;
       
  1647 		}
       
  1648 	iNotify->QueryComplete(KErrNone);
       
  1649 	}
       
  1650 
       
  1651 
       
  1652 TInt CDatagramServResolver::SecurityCheck(MProvdSecurityChecker* /*aChecker*/)
       
  1653 /**
       
  1654 Perform a security policy check on the client process (default implementation).
       
  1655 */
       
  1656 	{
       
  1657 	return KErrNone;
       
  1658 	}
       
  1659 //---------------------------------------------------------------------------------------------------------
       
  1660 
       
  1661 CDNSQueryProcessor::CDNSQueryProcessor()
       
  1662                    :CActive(0)
       
  1663 {
       
  1664     iDnsNotifier    = NULL;
       
  1665     iCompleteResult = KErrNotSupported;
       
  1666 
       
  1667     //-- initialize seed for random delay generator
       
  1668     TTime currTime;
       
  1669     currTime.UniversalTime();
       
  1670     iRndSeed = currTime.Int64();
       
  1671 }
       
  1672 
       
  1673 CDNSQueryProcessor::~CDNSQueryProcessor()
       
  1674 {
       
  1675     Cancel();
       
  1676     iDelayTimer.Close();
       
  1677 }
       
  1678 
       
  1679 CDNSQueryProcessor* CDNSQueryProcessor::NewL()
       
  1680 {
       
  1681     CDNSQueryProcessor* self = new(ELeave) CDNSQueryProcessor;
       
  1682     CleanupStack::PushL(self);
       
  1683     self->ConstructL();
       
  1684     CleanupStack::Pop();
       
  1685 
       
  1686     return self;
       
  1687 }
       
  1688 
       
  1689 void CDNSQueryProcessor::ConstructL(void)
       
  1690 {
       
  1691     User::LeaveIfError(iDelayTimer.CreateLocal());
       
  1692     CActiveScheduler::Add(this);
       
  1693 }
       
  1694 
       
  1695 void CDNSQueryProcessor::DoCancel()
       
  1696 {
       
  1697     iDelayTimer.Cancel();
       
  1698 }
       
  1699 
       
  1700 void CDNSQueryProcessor::RunL()
       
  1701 {
       
  1702   //-- complete esock's request
       
  1703   if(iDnsNotifier)
       
  1704     iDnsNotifier->QueryComplete(iCompleteResult);
       
  1705 }
       
  1706 
       
  1707 /**
       
  1708 * cancels pending request and completes with aResultCode
       
  1709 *
       
  1710 * @param    aResultCode completion code, which will be passed to the Esock
       
  1711 */
       
  1712 void  CDNSQueryProcessor::CompleteImmediately(TInt aResultCode)
       
  1713 {
       
  1714     iCompleteResult = aResultCode;
       
  1715     CompleteImmediately();
       
  1716 }
       
  1717 
       
  1718 /**
       
  1719 * cancels pending request and completes with code iCompleteResult
       
  1720 */
       
  1721 void  CDNSQueryProcessor::CompleteImmediately()
       
  1722 {
       
  1723     Cancel();
       
  1724 
       
  1725     SetActive();
       
  1726 
       
  1727     TRequestStatus* pStat = &iStatus;
       
  1728     User::RequestComplete(pStat, iCompleteResult);
       
  1729 }
       
  1730 
       
  1731 /**
       
  1732 * set up timer for a random delay between KMinDelay and KMaxDelay
       
  1733 * Used to similate queries processing
       
  1734 */
       
  1735 void CDNSQueryProcessor::SetQryProcessDelay()
       
  1736 {
       
  1737     const TInt KMinDelay = 200000; //-- minimal delay, 200 ms
       
  1738     const TInt KMaxDelay = 600000; //-- maximal delay, 600 ms
       
  1739 
       
  1740     iDelayTimer.Cancel();
       
  1741     iDelayTimer.After(iStatus, KMinDelay+(Math::Rand(iRndSeed) % (KMaxDelay-KMinDelay)));
       
  1742 }
       
  1743 
       
  1744 
       
  1745 /**
       
  1746 * process query. Checks query type and calls appropriate query processor function.
       
  1747 * @param    aQry       ref. to the query data
       
  1748 * @param    aResBuf    descriptor representing query response data. Will be initialized here.
       
  1749 * @param    aCounter   queries counter. It is 0 for "Query" call and increased each "QueryGetNext" call
       
  1750 */
       
  1751 void CDNSQueryProcessor::ProcessQuery(const TDnsQuery& aQry, TDes8& aResBuf, TInt aCounter)
       
  1752 {
       
  1753 
       
  1754     if(aCounter < 0)
       
  1755     {//-- invalid parameter
       
  1756      CompleteImmediately(KErrCorrupt);
       
  1757      return;
       
  1758     }
       
  1759 
       
  1760     if(aCounter == 0)
       
  1761     {//-- this is the "Query" call, not "QueryGetNext()", store query type for future use
       
  1762      iCurrQryType = aQry.Type();
       
  1763     }
       
  1764 
       
  1765     switch(iCurrQryType)
       
  1766     {
       
  1767 
       
  1768         case KDnsRRTypeA:
       
  1769             //-- process query of A type, treating aResBuf as a reference to TDnsRespABuf
       
  1770              if((TUint)aResBuf.MaxSize() < sizeof(TDnsRespABuf))
       
  1771              {  //-- there is no room in aResBuf to place there TDnsRespSRV structure
       
  1772                 CompleteImmediately(KErrNoMemory);
       
  1773              }
       
  1774              else
       
  1775              {
       
  1776                 aResBuf.SetLength(sizeof(TDnsRespA));
       
  1777                 //-- use placement new operator to construct object of our class in the chunk of memory
       
  1778                 //-- in aResBuf (which is already allocated by server)
       
  1779                 TDnsRespA *pRespA = new((TAny*)aResBuf.Ptr())TDnsRespA;
       
  1780                 QryProcessA(aQry, *pRespA, aCounter);   //-- process query and complete request.
       
  1781              }
       
  1782         break;
       
  1783 
       
  1784         case KDnsRRTypeSRV:
       
  1785              //-- process query of SRV type, treating aResBuf as a reference to TDnsRespSRVBuf
       
  1786              if((TUint)aResBuf.MaxSize() < sizeof(TDnsRespSRVBuf))
       
  1787              {  //-- there is no room in aResBuf to place there TDnsRespSRV structure
       
  1788                 CompleteImmediately(KErrNoMemory);
       
  1789              }
       
  1790              else
       
  1791              {
       
  1792                 aResBuf.SetLength(sizeof(TDnsRespSRV));
       
  1793                 //-- use placement new operator to construct object of our class in the chunk of memory
       
  1794                 //-- in aResBuf (which is already allocated by server)
       
  1795                 //-- aResBuf shall be considered as a TPckgBuf<TDnsRespSRV>, we will also need to set a length of the aResBuf descriptor
       
  1796 				TDnsRespSRV    *pRespSRV = new((TAny*)aResBuf.Ptr())TDnsRespSRV;
       
  1797                 QryProcessSRV(aQry, *pRespSRV, aCounter);//-- process query and complete request.
       
  1798 
       
  1799 
       
  1800              }
       
  1801 
       
  1802         break;
       
  1803 
       
  1804 
       
  1805         case KDnsRRTypePTR:
       
  1806             //-- process query of PTR type, treating aResBuf as a reference to TDnsRespPTRBuf
       
  1807              if((TUint)aResBuf.MaxSize() < sizeof(TDnsRespPTRBuf))
       
  1808              {  //-- there is no room in aResBuf to place there TDnsRespPTRBuf structure
       
  1809                 CompleteImmediately(KErrNoMemory);
       
  1810              }
       
  1811              else
       
  1812              {
       
  1813                 aResBuf.SetLength(sizeof(TDnsRespPTR));
       
  1814 
       
  1815                 TDnsRespPTR    *pRespPTR = new((TAny*)aResBuf.Ptr())TDnsRespPTR;
       
  1816                 QryProcessPTR(aQry, *pRespPTR, aCounter);//-- process query and complete request.
       
  1817 
       
  1818              }
       
  1819         break;
       
  1820 
       
  1821         case KDnsRRTypeNAPTR:
       
  1822             //-- process query of NAPTR type, treating aResBuf as a reference to TDnsRespNAPTRBuf
       
  1823              if((TUint)aResBuf.MaxSize() < sizeof(TDnsRespNAPTRBuf))
       
  1824              {  //-- there is no room in aResBuf to place there TDnsRespNAPTRBuf structure
       
  1825                 CompleteImmediately(KErrNoMemory);
       
  1826              }
       
  1827              else
       
  1828              {
       
  1829                 aResBuf.SetLength(sizeof(TDnsRespNAPTR));
       
  1830 
       
  1831                 TDnsRespNAPTR    *pRespNAPTR = new((TAny*)aResBuf.Ptr())TDnsRespNAPTR;
       
  1832                 QryProcessNAPTR(aQry, *pRespNAPTR, aCounter);//-- process query and complete request.
       
  1833              }
       
  1834         break;
       
  1835 
       
  1836         case KDnsRRTypeMX:
       
  1837             //-- process query of MX type, treating aResBuf as a reference to TDnsRespMXBuf
       
  1838              if((TUint)aResBuf.MaxSize() < sizeof(TDnsRespMXBuf))
       
  1839              {  //-- there is no room in aResBuf to place there TDnsRespMXBuf structure
       
  1840                 CompleteImmediately(KErrNoMemory);
       
  1841              }
       
  1842              else
       
  1843              {
       
  1844                 aResBuf.SetLength(sizeof(TDnsRespMX));
       
  1845 
       
  1846                 TDnsRespMX    *pRespMX  = new((TAny*)aResBuf.Ptr())TDnsRespMX;
       
  1847                 QryProcessMX(aQry, *pRespMX, aCounter);//-- process query and complete request.
       
  1848              }
       
  1849         break;
       
  1850 
       
  1851 
       
  1852         case KDnsRRTypeAAAA:
       
  1853             //-- process query of AAAA type, treating aResBuf as a reference to TDnsRespAAAABuf
       
  1854              if((TUint)aResBuf.MaxSize() < sizeof(TDnsRespAAAABuf))
       
  1855              {  //-- there is no room in aResBuf to place there TDnsRespMXBuf structure
       
  1856                 CompleteImmediately(KErrNoMemory);
       
  1857              }
       
  1858              else
       
  1859              {
       
  1860                 aResBuf.SetLength(sizeof(TDnsRespAAAA));
       
  1861 
       
  1862                 TDnsRespAAAA    *pRespAAAA = new((TAny*)aResBuf.Ptr())TDnsRespAAAA;
       
  1863                 QryProcessAAAA(aQry, *pRespAAAA, aCounter);//-- process query and complete request.
       
  1864              }
       
  1865         break;
       
  1866 
       
  1867 
       
  1868         default:
       
  1869             //-- Query of unknown type
       
  1870             CompleteImmediately(KErrNotSupported);
       
  1871         break;
       
  1872     } // switch
       
  1873 
       
  1874 }
       
  1875 
       
  1876 /**
       
  1877 * process A query. Checks query data and forges query result.
       
  1878 * @param aQry       ref. to the A query data
       
  1879 * @param aQryResult ref. to the destination query result buffer.
       
  1880 * @param aCounter   - queries counter. It is 0 for "Query" call and increased each "QueryGetNext" call
       
  1881 */
       
  1882 void CDNSQueryProcessor::QryProcessA(const TDnsQuery& aQry, TDnsRespA& aQryResult, TInt aCounter)
       
  1883 {
       
  1884     TInetAddr   addr;
       
  1885 
       
  1886     switch(aCounter)
       
  1887     {
       
  1888         //-- query counter is 0, so it is "Query" call
       
  1889         case 0:
       
  1890 
       
  1891             //-- check query data, it shall be set properly in the test case that calls RHostResolver::Query(...)
       
  1892             if( aQry.Class() != KDnsRRClassIN  ||  //-- Query class shall be IN
       
  1893                 aQry.Type()  != KDnsRRTypeA    ||  //-- Query type shall be KDnsRRTypeA
       
  1894                 aQry.Data().CompareF(_L8("http://www.sample.net/")) != 0
       
  1895               )
       
  1896             {
       
  1897                 CompleteImmediately(KErrCorrupt);
       
  1898                 return;
       
  1899             }
       
  1900 
       
  1901             //-- resolve domain name, forge "A" query result that will be checked on the client side.
       
  1902             addr.Input(_L("192.168.40.4"));
       
  1903 
       
  1904             aQryResult.SetHostAddress(addr);
       
  1905             aQryResult.SetRRTtl(0x121212);
       
  1906 
       
  1907             SetCompletionCode(KErrNone);
       
  1908 
       
  1909             //-- simulate processing random delay and complete the request later
       
  1910             SetQryProcessDelay();
       
  1911             SetActive();
       
  1912 
       
  1913         break;
       
  1914 
       
  1915         //-- query counter is 1, so it is the first "QueryGetNext" call.
       
  1916         case 1:
       
  1917 
       
  1918             //-- resolve domain name, forge "A" query result that will be checked on the client side.
       
  1919             addr.Input(_L("177.123.221.251"));
       
  1920 
       
  1921             aQryResult.SetHostAddress(addr);
       
  1922             aQryResult.SetRRTtl(0x112233);
       
  1923 
       
  1924             SetCompletionCode(KErrNone);
       
  1925 
       
  1926             //-- simulate processing random delay and complete the request later
       
  1927             SetQryProcessDelay();
       
  1928             SetActive();
       
  1929 
       
  1930         break;
       
  1931 
       
  1932 
       
  1933         default:
       
  1934             //-- query counter is greater than 0, let's not support more than one "QueryGetNext" call
       
  1935             CompleteImmediately(KErrNotFound);
       
  1936         break;
       
  1937 
       
  1938     }
       
  1939 
       
  1940 }
       
  1941 
       
  1942 /**
       
  1943 * process SRV query. Checks query data and forges query result.
       
  1944 * @param aQry       ref. to the SRV query data
       
  1945 * @param aQryResult ref. to the destination query result buffer.
       
  1946 * @param aCounter   - queries counter. It is 0 for "Query" call and increased each "QueryGetNext" call
       
  1947 */
       
  1948 void  CDNSQueryProcessor::QryProcessSRV   (const TDnsQuery& aQry, TDnsRespSRV& aQryResult, TInt aCounter)
       
  1949 {
       
  1950 
       
  1951     switch(aCounter)
       
  1952     {
       
  1953         case 0: //-- query counter is 0, so it is "Query" call
       
  1954 
       
  1955             //-- check query data, it shall be set properly in the test case that calls RHostResolver::Query(...)
       
  1956             //-- see also RFC 2782
       
  1957 
       
  1958             if(aQry.Class() != KDnsRRClassIN || //-- Query class shall be IN
       
  1959                aQry.Type() != KDnsRRTypeSRV  || //-- Query type shall be KDnsRRTypeSRV
       
  1960                aQry.Data().CompareF(_L8("_ldap._tcp.example.com")) != 0)
       
  1961             {
       
  1962                 CompleteImmediately(KErrCorrupt);
       
  1963                 return;
       
  1964             }
       
  1965 
       
  1966             //-- forge a SRV query result that will be checked on the client side.
       
  1967             aQryResult.SetRRTtl(0x123456);
       
  1968 
       
  1969             aQryResult.SetPriority(384);              //-- priority
       
  1970             aQryResult.SetWeight(784);                //-- weight
       
  1971             aQryResult.SetPort(123);                  //-- port
       
  1972             aQryResult.SetTarget(_L8("old-slow-box"));//-- target
       
  1973 
       
  1974             SetCompletionCode(KErrNone);
       
  1975 
       
  1976             //-- simulate processing random delay and complete the request later
       
  1977             SetQryProcessDelay();
       
  1978             SetActive();
       
  1979         break;
       
  1980 
       
  1981         case 1:
       
  1982             //-- query counter is 1, so it is the first "QueryGetNext" call.
       
  1983             //-- Forge a "SRV" query next result that will be checked on the client side.
       
  1984             aQryResult.SetRRTtl(0x123765);
       
  1985 
       
  1986             aQryResult.SetPriority(236);              //-- priority
       
  1987             aQryResult.SetWeight(962);                //-- weight
       
  1988             aQryResult.SetPort(125);                  //-- port
       
  1989             aQryResult.SetTarget(_L8("new-fast-box"));//-- target
       
  1990 
       
  1991             SetCompletionCode(KErrNone);
       
  1992 
       
  1993             //-- simulate processing random delay and complete the request later
       
  1994             SetQryProcessDelay();
       
  1995             SetActive();
       
  1996        break;
       
  1997 
       
  1998         default:
       
  1999             //-- query counter is greater than 0, let's not support more than one "QueryGetNext" call
       
  2000             CompleteImmediately(KErrNotFound);
       
  2001         break;
       
  2002     }// switch
       
  2003 }
       
  2004 
       
  2005 /**
       
  2006 * process PTR query. Checks query data and forges query result.
       
  2007 * @param aQry       ref. to the PTR query data
       
  2008 * @param aQryResult ref. to the destination query result buffer.
       
  2009 * @param aCounter   - queries counter. It is 0 for "Query" call and increased each "QueryGetNext" call
       
  2010 */
       
  2011 void  CDNSQueryProcessor::QryProcessPTR   (const TDnsQuery& aQry, TDnsRespPTR& aQryResult, TInt aCounter)
       
  2012 {
       
  2013     switch(aCounter)
       
  2014     {
       
  2015         case 0: //-- query counter is 0, so it is "Query" call
       
  2016            {
       
  2017 
       
  2018             //-- check query data, it shall be set properly in the test case that calls RHostResolver::Query(...)
       
  2019             if(aQry.Class() != KDnsRRClassIN || //-- Query class shall be IN
       
  2020                aQry.Type() != KDnsRRTypePTR)    //-- Query type shall be KDnsRRTypePTR
       
  2021             {
       
  2022                 CompleteImmediately(KErrCorrupt);
       
  2023                 return;
       
  2024             }
       
  2025 
       
  2026             //-- check  Inet Address passes by test from client side
       
  2027             const TInetAddr& inetAddr = (const TInetAddr&)aQry.Data();
       
  2028 
       
  2029             TInetAddr expInetAddr;
       
  2030             expInetAddr.Input(_L("192.111.22.77"));
       
  2031 
       
  2032             if(! inetAddr.CmpAddr(expInetAddr))
       
  2033             {
       
  2034                 CompleteImmediately(KErrCorrupt);
       
  2035                 return;
       
  2036             }
       
  2037 
       
  2038             //-- resolve address, forge "PTR" query result that will be checked on the client side.
       
  2039             aQryResult.SetHostName(_L8("http://www.CDatagramHostResolver_QryProcessPTR.response/"));
       
  2040             aQryResult.SetRRTtl(0x223441);
       
  2041 
       
  2042             SetCompletionCode(KErrNone);
       
  2043 
       
  2044             //-- simulate processing random delay and complete the request later
       
  2045             SetQryProcessDelay();
       
  2046             SetActive();
       
  2047            }
       
  2048         break;
       
  2049 
       
  2050         default:
       
  2051             //-- query counter is greater than 0, let's not support more than one "QueryGetNext" call
       
  2052             CompleteImmediately(KErrNotFound);
       
  2053         break;
       
  2054 
       
  2055     }
       
  2056 
       
  2057 }
       
  2058 
       
  2059 /**
       
  2060 * process NAPTR query. Checks query data and forges query result.
       
  2061 * @param aQry       ref. to the NAPTR query data
       
  2062 * @param aQryResult ref. to the destination query result buffer.
       
  2063 * @param aCounter   - queries counter. It is 0 for "Query" call and increased each "QueryGetNext" call
       
  2064 */
       
  2065 void  CDNSQueryProcessor::QryProcessNAPTR (const TDnsQuery& aQry, TDnsRespNAPTR& aQryResult, TInt aCounter)
       
  2066 {
       
  2067     switch(aCounter)
       
  2068     {
       
  2069         case 0: //-- query counter is 0, so it is "Query" call
       
  2070            {
       
  2071 
       
  2072             //-- check query data, it shall be set properly in the test case that calls RHostResolver::Query(...)
       
  2073             if(aQry.Class() != KDnsRRClassIN    ||  //-- Query class shall be IN
       
  2074                aQry.Type() != KDnsRRTypeNAPTR   ||  //-- Query type shall be KDnsRRTypeNAPTR
       
  2075                aQry.Data().CompareF(_L8("http://www.foo_bar.ru/")) != 0)
       
  2076             {
       
  2077                 CompleteImmediately(KErrCorrupt);
       
  2078                 return;
       
  2079             }
       
  2080 
       
  2081 
       
  2082             //-- forge "NAPTR" query result that will be checked on the client side.
       
  2083             aQryResult.SetRRTtl(0x2673411);
       
  2084             aQryResult.SetOrder(123);
       
  2085             aQryResult.SetPref(99);
       
  2086 
       
  2087             aQryResult.SetFlags(_L8("SAUP"));
       
  2088             aQryResult.SetService(_L8("http+I2R"));
       
  2089             aQryResult.SetRegexp(_L8("!£%^^&($%£$~~## !!!!!"));
       
  2090             aQryResult.SetReplacement(_L8("www.next-name.it"));
       
  2091 
       
  2092             SetCompletionCode(KErrNone);
       
  2093 
       
  2094             //-- simulate processing random delay and complete the request later
       
  2095             SetQryProcessDelay();
       
  2096             SetActive();
       
  2097            }
       
  2098         break;
       
  2099 
       
  2100         default:
       
  2101             //-- query counter is greater than 0, let's not support more than one "QueryGetNext" call
       
  2102             CompleteImmediately(KErrNotFound);
       
  2103         break;
       
  2104 
       
  2105     }
       
  2106 
       
  2107 }
       
  2108 
       
  2109 /**
       
  2110 * process MX query. Checks query data and forges query result.
       
  2111 * @param aQry       ref. to the MX query data
       
  2112 * @param aQryResult ref. to the destination query result buffer.
       
  2113 * @param aCounter   - queries counter. It is 0 for "Query" call and increased each "QueryGetNext" call
       
  2114 */
       
  2115 void  CDNSQueryProcessor::QryProcessMX    (const TDnsQuery& aQry, TDnsRespMX& aQryResult, TInt aCounter)
       
  2116 {
       
  2117     switch(aCounter)
       
  2118     {
       
  2119         case 0: //-- query counter is 0, so it is "Query" call
       
  2120            {
       
  2121             //-- check query data, it shall be set properly in the test case that calls RHostResolver::Query(...)
       
  2122 
       
  2123             if(aQry.Class() != KDnsRRClassIN || //-- Query class shall be IN
       
  2124                aQry.Type() != KDnsRRTypeMX   || //-- Query type shall be KDnsRRTypeMX
       
  2125                aQry.Data().CompareF(_L8("http://www.gooooooogle.ru/")) != 0)
       
  2126             {
       
  2127                 CompleteImmediately(KErrCorrupt);
       
  2128                 return;
       
  2129             }
       
  2130 
       
  2131 
       
  2132             //-- forge "MX" query result that will be checked on the client side.
       
  2133             aQryResult.SetRRTtl(0xdead);
       
  2134 
       
  2135             aQryResult.SetPref(345);
       
  2136             aQryResult.SetHostName(_L8("c.example.org"));
       
  2137 
       
  2138             SetCompletionCode(KErrNone);
       
  2139 
       
  2140             //-- simulate processing random delay and complete the request later
       
  2141             SetQryProcessDelay();
       
  2142             SetActive();
       
  2143            }
       
  2144         break;
       
  2145 
       
  2146         default:
       
  2147             //-- query counter is greater than 0, let's not support more than one "QueryGetNext" call
       
  2148             CompleteImmediately(KErrNotFound);
       
  2149         break;
       
  2150 
       
  2151     }
       
  2152 
       
  2153 }
       
  2154 
       
  2155 /**
       
  2156 * process AAAA query. Checks query data and forges query result.
       
  2157 * @param aQry       ref. to the AAAA query data
       
  2158 * @param aQryResult ref. to the destination query result buffer.
       
  2159 * @param aCounter   - queries counter. It is 0 for "Query" call and increased each "QueryGetNext" call
       
  2160 */
       
  2161 void  CDNSQueryProcessor::QryProcessAAAA(const TDnsQuery& aQry, TDnsRespAAAA& aQryResult, TInt aCounter)
       
  2162 {
       
  2163     TInetAddr   addr;
       
  2164 
       
  2165     switch(aCounter)
       
  2166     {
       
  2167         case 0: //-- query counter is 0, so it is "Query" call
       
  2168            {
       
  2169 
       
  2170             //-- check query data, it shall be set properly in the test case that calls RHostResolver::Query(...)
       
  2171             if(aQry.Class() != KDnsRRClassIN ||
       
  2172                aQry.Type() != KDnsRRTypeAAAA ||
       
  2173                aQry.Data().CompareF(_L8("http://www.sample_AAAA.net/")) != 0)
       
  2174             {
       
  2175                 CompleteImmediately(KErrCorrupt);
       
  2176                 return;
       
  2177             }
       
  2178 
       
  2179             //-- forge "AAAA" query result that will be checked on the client side.
       
  2180 
       
  2181             //-- resolve domain name, forge "A" query result that will be checked on the client side.
       
  2182             addr.Input(_L("2001:618:400:6a:0:0:0:abc"));
       
  2183             aQryResult.SetHostAddress(addr);
       
  2184             aQryResult.SetRRTtl(0xbeef);
       
  2185 
       
  2186             SetCompletionCode(KErrNone);
       
  2187 
       
  2188             //-- simulate processing random delay and complete the request later
       
  2189             SetQryProcessDelay();
       
  2190             SetActive();
       
  2191            }
       
  2192         break;
       
  2193 
       
  2194         default:
       
  2195             //-- query counter is greater than 0, let's not support more than one "QueryGetNext" call
       
  2196             CompleteImmediately(KErrNotFound);
       
  2197         break;
       
  2198 
       
  2199     }
       
  2200 
       
  2201 }
       
  2202 
       
  2203 
       
  2204 //---------------------------------------------------------------------------------------------------------
       
  2205 
       
  2206 void CDatagramNetDataBase::Query(TDes8& aBuffer)
       
  2207 //
       
  2208 // Ctor
       
  2209 //
       
  2210 	{
       
  2211 	aBuffer.Capitalize();
       
  2212 	iNotify->QueryComplete(KErrNone);
       
  2213 	}
       
  2214 
       
  2215 void CDatagramNetDataBase::Add(TDes8& aBuffer)
       
  2216 //
       
  2217 // Ctor
       
  2218 //
       
  2219 	{
       
  2220 
       
  2221 	// Query not completed because its cancelled by the test code
       
  2222 	if(aBuffer==_L8("Rabbit"))
       
  2223 		iCount=10;
       
  2224 	else
       
  2225 		iNotify->QueryComplete(KErrNotSupported);
       
  2226 	}
       
  2227 
       
  2228 void CDatagramNetDataBase::Remove(TDes8& aBuffer)
       
  2229 //
       
  2230 // Ctor
       
  2231 //
       
  2232 	{
       
  2233 
       
  2234 
       
  2235 	if(aBuffer==_L8("Rabbit") && iCount==20)
       
  2236 		iNotify->QueryComplete(KErrNone);
       
  2237 	else
       
  2238 		iNotify->QueryComplete(KErrNotFound);
       
  2239 	}
       
  2240 
       
  2241 void CDatagramNetDataBase::CancelCurrentOperation()
       
  2242 //
       
  2243 //
       
  2244 //
       
  2245 	{
       
  2246 
       
  2247 	if(iCount==10)
       
  2248 		iCount=20;
       
  2249 	}
       
  2250 
       
  2251 CDatagramNetDataBase* CDatagramNetDataBase::NewL()
       
  2252 //
       
  2253 // Ctor
       
  2254 //
       
  2255 	{
       
  2256 	return new(ELeave)CDatagramNetDataBase;
       
  2257 	}
       
  2258 
       
  2259 CDatagramNetDataBase::CDatagramNetDataBase()
       
  2260 //
       
  2261 // Ctor
       
  2262 //
       
  2263 	{
       
  2264 	__DECLARE_NAME(_S("CDatagramNetDataBase"));
       
  2265 	}
       
  2266 
       
  2267 
       
  2268 TInt CDatagramNetDataBase::SecurityCheck(MProvdSecurityChecker* /*aChecker*/)
       
  2269 /**
       
  2270 Perform a security policy check on the client process (default implementation).
       
  2271 */
       
  2272 	{
       
  2273 	return KErrNone;
       
  2274 	}
       
  2275 
       
  2276 //---------------------------------------------------------------------------------------------------------
       
  2277 
       
  2278 CInterfaceProtocol::CInterfaceProtocol(TServerProtocolDesc* aProtoDesc):CDummyProtocol(aProtoDesc)
       
  2279 	{
       
  2280 	iInterfaces.SetOffset(_FOFF(CIfHolder, iLink));
       
  2281 	}
       
  2282 
       
  2283 CInterfaceProtocol::~CInterfaceProtocol()
       
  2284 //
       
  2285 // Dtor
       
  2286 //
       
  2287 	{
       
  2288 
       
  2289 	__ASSERT_DEBUG(iInterfaces.IsEmpty(), Panic(EInterfaceNotDeleted));
       
  2290 	}
       
  2291 
       
  2292 TInt CInterfaceProtocol::GetOption(TUint level,TUint name,TDes8 &anOption,CProtocolBase* /*aSourceProtocol*/)
       
  2293 //
       
  2294 // Extra options
       
  2295 //
       
  2296 	{
       
  2297 
       
  2298 	if(level==KNifOptLevel)
       
  2299 		{
       
  2300 		TInt ret;
       
  2301 
       
  2302 		if(name==KNifOptGetNifIfUser)
       
  2303 			{
       
  2304 			TNifIfUser ifuser;
       
  2305 			ifuser() = this;
       
  2306 			anOption.Copy(ifuser);
       
  2307 			return KErrNone;
       
  2308 			}
       
  2309 		else if(name==1)
       
  2310 			{
       
  2311 			TRAP(ret, StartAutoInterfaceL();)
       
  2312 			return ret;
       
  2313 			}
       
  2314 		else if(name==2)
       
  2315 			{
       
  2316 			if(iInterfaceName.Length())
       
  2317 				Nif::Stop(iInterfaceName);
       
  2318 			return KErrNone;
       
  2319 			}
       
  2320 		else if(name==3)
       
  2321 			{
       
  2322 			TRAP(ret, Nif::StartL(iInterfaceName);)
       
  2323 			return ret;
       
  2324 			}
       
  2325 		else if(name==4)
       
  2326 			{
       
  2327 			TNifProgress* p = (TNifProgress*)anOption.Ptr();
       
  2328 			anOption.SetLength(sizeof(TNifProgress));
       
  2329 		    TRAP(ret, Nif::ProgressL(*p, iInterfaceName);)
       
  2330 			return ret;
       
  2331 			}
       
  2332 		else if(name==5)
       
  2333 			{
       
  2334 			if(iInterfaces.IsEmpty())
       
  2335 				return KErrNotFound;
       
  2336 		    Nif::Stop(iInterfaces.First(), iInterfaces.First()->iIf);
       
  2337 			return KErrNone;
       
  2338 			}
       
  2339 		else if(name==6)
       
  2340 			{
       
  2341 			if(iInterfaces.IsEmpty())
       
  2342 				return KErrNotFound;
       
  2343 			TNifProgress* p = (TNifProgress*)anOption.Ptr();
       
  2344 			anOption.SetLength(sizeof(TNifProgress));
       
  2345 		    TRAP(ret, Nif::ProgressL(*p, iInterfaces.First(), iInterfaces.First()->iIf);)
       
  2346 			return ret;
       
  2347 			}
       
  2348 		}
       
  2349 	return KErrNotSupported;
       
  2350 	}
       
  2351 
       
  2352 void CInterfaceProtocol::StartAutoInterfaceL()
       
  2353 	{
       
  2354 
       
  2355 	// Create holder
       
  2356 	CIfHolder* h;
       
  2357 	h = new (ELeave) CIfHolder(*this);
       
  2358 	CleanupStack::PushL(h);
       
  2359 	Nif::BindL(*this, h, iInterfaceName);
       
  2360 	CleanupStack::Pop();
       
  2361 	}
       
  2362 
       
  2363 void CInterfaceProtocol::IfUserBindFailure(TInt, TAny* aId)
       
  2364 	{
       
  2365 
       
  2366 	// Find the interface which went down
       
  2367 	TDblQueIter<CIfHolder> iter(iInterfaces);
       
  2368 	CIfHolder* h = 0;
       
  2369 	while((h=iter++)!=0)
       
  2370 		{
       
  2371 		if(aId==h)
       
  2372 			{
       
  2373 			delete h;
       
  2374 			break;
       
  2375 			}
       
  2376 		}
       
  2377 	__ASSERT_ALWAYS(h, Panic(EIdAndNoHolder));
       
  2378 	}
       
  2379 
       
  2380 void CInterfaceProtocol::IfUserNewInterfaceL(CNifIfBase* aIf, TAny* aId)
       
  2381 	{
       
  2382 
       
  2383 	// If Id try to find it
       
  2384 	CIfHolder* h;
       
  2385 	if(aId)
       
  2386 		{
       
  2387 		TDblQueIter<CIfHolder> iter(iInterfaces);
       
  2388 		while((h=iter++)!=0)
       
  2389 			{
       
  2390 			if(aId==h)
       
  2391 				break;
       
  2392 			}
       
  2393 		__ASSERT_ALWAYS(h, Panic(EIdAndNoHolder));
       
  2394 		if (h==0)
       
  2395 			{ // will never get in here as will have panic-ed above
       
  2396 			h = (CIfHolder*)0xABCD; // keep lint happy
       
  2397 			}
       
  2398 		}
       
  2399 	else // create a new holder
       
  2400 		h = new (ELeave) CIfHolder(*this);
       
  2401 
       
  2402     h->iIf=aIf;
       
  2403 	CleanupStack::PushL(h);
       
  2404 	aIf->BindL(this);
       
  2405 	CleanupStack::Pop();
       
  2406 	}
       
  2407 
       
  2408 void CInterfaceProtocol::IfUserInterfaceDown(TInt aError, CNifIfBase* aIf)
       
  2409 	{
       
  2410 
       
  2411 	if (aError == KErrLinkConfigChanged)
       
  2412 		{
       
  2413 		return;
       
  2414 		}
       
  2415 
       
  2416 	// Interface has gone down so delete it from our records
       
  2417 	TDblQueIter<CIfHolder> iter(iInterfaces);
       
  2418 	CIfHolder* h = 0;
       
  2419 	while((h=iter++)!=0)
       
  2420 		{
       
  2421 		if(aIf==h->iIf)
       
  2422 			{
       
  2423 			delete h;
       
  2424 			break;
       
  2425 			}
       
  2426 		}
       
  2427 	__ASSERT_ALWAYS(h, Panic(EIdAndNoHolder));
       
  2428 	}
       
  2429 
       
  2430 CProtocolBase* CInterfaceProtocol::IfUserProtocol()
       
  2431 	{
       
  2432 	return this;
       
  2433 	}
       
  2434 
       
  2435 void CInterfaceProtocol::IfUserOpenNetworkLayer()
       
  2436 	{
       
  2437 	iInterfaceCount++;
       
  2438 	Open();
       
  2439 	}
       
  2440 
       
  2441 void CInterfaceProtocol::IfUserCloseNetworkLayer()
       
  2442 	{
       
  2443 	iInterfaceCount--;
       
  2444 	Close();
       
  2445 	}
       
  2446 
       
  2447 TBool CInterfaceProtocol::IfUserIsNetworkLayerActive()
       
  2448 	{
       
  2449 	return (RefCount()-iInterfaceCount>0);
       
  2450 	}
       
  2451 
       
  2452 void CInterfaceProtocol::Close()
       
  2453 	{
       
  2454 	if(RefCount()-iInterfaceCount<=0)
       
  2455       {
       
  2456 		Nif::NetworkLayerClosed(*this);
       
  2457       }
       
  2458 	CProtocolBase::Close();
       
  2459 	}
       
  2460 
       
  2461 CIfHolder::CIfHolder(CInterfaceProtocol& aProt)
       
  2462 	{
       
  2463 	aProt.iInterfaces.AddLast(*this);
       
  2464 	}
       
  2465 
       
  2466 CIfHolder::~CIfHolder()
       
  2467 	{
       
  2468 	iLink.Deque();
       
  2469 	}
       
  2470 
       
  2471