|
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 |