|
1 // Copyright (c) 1998-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 <treng.h> |
|
17 #include <e32hal.h> |
|
18 #include <icmp6_hdr.h> |
|
19 #include <in_chk.h> |
|
20 #include <commdbconnpref.h> |
|
21 |
|
22 const TUint KDefaultMaxTtl = 30; |
|
23 const TInt KDefaultWait = 5000000; |
|
24 const TInt KDefaultNrProbes = 3; |
|
25 |
|
26 const TInt KMinIpHeaderSize = 20; |
|
27 const TInt KMaxSendTime=60000000; |
|
28 const TInt KRecvDataSize=512; |
|
29 const TInt KResolvTime=10000000; |
|
30 |
|
31 const TInt KIcmpHeaderSize = 8; |
|
32 |
|
33 class CTraceRtTimer : public CTimer |
|
34 { |
|
35 friend class CTraceRtEng; |
|
36 protected: |
|
37 CTraceRtTimer(CTraceRtEng& aParent); |
|
38 void RunL(); |
|
39 private: |
|
40 CTraceRtEng* iParent; |
|
41 }; |
|
42 |
|
43 class CTraceRtSender : public CActive |
|
44 { |
|
45 friend class CTraceRtEng; |
|
46 protected: |
|
47 CTraceRtSender(CTraceRtEng& aParent); |
|
48 ~CTraceRtSender(); |
|
49 void RunL(); |
|
50 void DoCancel(); |
|
51 private: |
|
52 CTraceRtEng* iParent; |
|
53 }; |
|
54 |
|
55 class CTraceRtReceiver : public CActive |
|
56 { |
|
57 friend class CTraceRtEng; |
|
58 protected: |
|
59 CTraceRtReceiver(CTraceRtEng& aParent); |
|
60 ~CTraceRtReceiver(); |
|
61 void RunL(); |
|
62 void DoCancel(); |
|
63 private: |
|
64 CTraceRtEng* iParent; |
|
65 }; |
|
66 |
|
67 |
|
68 // Class to manage ICMP headers information |
|
69 class HTraceRtHeader : public TInet6HeaderICMP_Echo |
|
70 { |
|
71 public: |
|
72 static HTraceRtHeader* NewL(TInt aSize = KIcmpHeaderSize); |
|
73 ~HTraceRtHeader(); |
|
74 |
|
75 TBool VerifyRecv(TInt aIdent, TInt aSeq); |
|
76 void FormatSend(TUint aId, TUint aSeq); |
|
77 TInt MaxLength(); |
|
78 TInt DataLength(); |
|
79 TPtr8* Grab(); |
|
80 |
|
81 private: |
|
82 void ConstructL(TInt aSize); |
|
83 TBool SetHeader(TUint aOffset = 0); |
|
84 |
|
85 HBufC8* iData; |
|
86 TPtr8* iDataPtr; // Packet data |
|
87 }; |
|
88 |
|
89 enum TTraceRtEngPanic |
|
90 { |
|
91 |
|
92 ETimerPriorityGreaterThanSender, // 0 |
|
93 ESenderPrirityGreaterThanReceiver // 1 |
|
94 }; |
|
95 |
|
96 LOCAL_C void Panic(TTraceRtEngPanic aPanic) |
|
97 // |
|
98 // Panic the user |
|
99 // |
|
100 { |
|
101 |
|
102 User::Panic(_L("TraceRtEng"), aPanic); |
|
103 } |
|
104 |
|
105 EXPORT_C TTraceRtOptions::TTraceRtOptions() |
|
106 // |
|
107 // Default TraceRt options |
|
108 // |
|
109 { |
|
110 |
|
111 iMaxTtl=KDefaultMaxTtl; |
|
112 iResolveAddress=ETrue; |
|
113 iWait=KDefaultWait; |
|
114 iTos=0; |
|
115 iDestname.SetLength(0); |
|
116 iNrProbes=KDefaultNrProbes; |
|
117 iPrompt = EFalse; |
|
118 } |
|
119 |
|
120 EXPORT_C CTraceRtEng* CTraceRtEng::NewL(MTraceRtNotificationHandler& aUi) |
|
121 // |
|
122 // Create a new TraceRt engine |
|
123 // |
|
124 { |
|
125 |
|
126 CTraceRtEng* p= new(ELeave) CTraceRtEng; |
|
127 CleanupStack::PushL(p); |
|
128 p->ConstructL(aUi); |
|
129 CleanupStack::Pop(); |
|
130 return p; |
|
131 } |
|
132 |
|
133 EXPORT_C CTraceRtEng::CTraceRtEng() |
|
134 // |
|
135 // Declare a name |
|
136 // |
|
137 { |
|
138 |
|
139 __DECLARE_NAME(_S("CTraceRtEng")); |
|
140 } |
|
141 |
|
142 EXPORT_C CTraceRtEng::~CTraceRtEng() |
|
143 // |
|
144 // Destroy wot TraceRt created |
|
145 { |
|
146 |
|
147 iIcmpSocket.Close(); |
|
148 iResolver.Close(); |
|
149 iConnect.Close(); |
|
150 iSocketServ.Close(); |
|
151 delete iReceiver; |
|
152 delete iSender; |
|
153 delete iTimer; |
|
154 delete iRecvData; |
|
155 delete iSendData; |
|
156 } |
|
157 |
|
158 EXPORT_C void CTraceRtEng::ConstructL(MTraceRtNotificationHandler& aUi) |
|
159 // |
|
160 // Construct and heap objects |
|
161 // |
|
162 { |
|
163 |
|
164 iUi = &aUi; |
|
165 iTimer = new (ELeave) CTraceRtTimer(*this); |
|
166 iTimer->ConstructL(); |
|
167 iSender = new (ELeave) CTraceRtSender(*this); |
|
168 iReceiver = new (ELeave) CTraceRtReceiver(*this); |
|
169 User::LeaveIfError(iSocketServ.Connect()); |
|
170 iSendData = NULL; |
|
171 iRecvData = NULL; |
|
172 iResolv = EFalse; |
|
173 } |
|
174 |
|
175 EXPORT_C void CTraceRtEng::SetPriorities(TInt aTimerPriority, TInt aSenderPriority, TInt aReceiverPriority) |
|
176 // |
|
177 // Set various active object priorities |
|
178 // |
|
179 { |
|
180 |
|
181 __ASSERT_ALWAYS(aTimerPriority < aSenderPriority, Panic(ETimerPriorityGreaterThanSender)); |
|
182 __ASSERT_ALWAYS(aSenderPriority < aReceiverPriority, Panic(ESenderPrirityGreaterThanReceiver)); |
|
183 |
|
184 iTimer->SetPriority(aTimerPriority); |
|
185 iSender->SetPriority(aSenderPriority); |
|
186 iReceiver->SetPriority(aReceiverPriority); |
|
187 } |
|
188 |
|
189 EXPORT_C void CTraceRtEng::Start(const TTraceRtOptions& aOptions) |
|
190 // |
|
191 // Start a TraceRt |
|
192 // |
|
193 { |
|
194 |
|
195 // Reset All Variables |
|
196 iProbeNr=0; |
|
197 iTtl=1; |
|
198 iSeq=0; |
|
199 iNameEntry().iName.SetLength(0); |
|
200 iNameEntry().iFlags=0; |
|
201 TInetAddr::Cast(iNameEntry().iAddr).SetAddress(0); |
|
202 iGotThere=EFalse; |
|
203 iUnreachCount=0; |
|
204 iIdent=User::TickCount()&KMaxTUint16; |
|
205 iLastCode=KTraceRtCodeTimeout; |
|
206 |
|
207 iOptions=aOptions; |
|
208 |
|
209 |
|
210 if(iOptions.iMaxTtl>255 || iOptions.iTos>255 |
|
211 || iOptions.iNrProbes>100 || iOptions.iNrProbes<1) |
|
212 { |
|
213 DoError(KErrNotSupported); |
|
214 return; |
|
215 } |
|
216 |
|
217 if(iSendData) |
|
218 { |
|
219 delete iSendData; |
|
220 } |
|
221 iSendData = HTraceRtHeader::NewL(KIcmpHeaderSize); |
|
222 |
|
223 if(iRecvData) |
|
224 { |
|
225 delete iRecvData; |
|
226 } |
|
227 iRecvData = HTraceRtHeader::NewL(KRecvDataSize); |
|
228 |
|
229 if(!iRecvData || !iSendData) |
|
230 { |
|
231 DoError(KErrNoMemory); |
|
232 } |
|
233 else if(iOptions.iDestname.Length()>0) |
|
234 { |
|
235 iConnect.Close(); |
|
236 User::LeaveIfError(iConnect.Open(iSocketServ, KConnectionTypeDefault)); |
|
237 |
|
238 TCommDbConnPref commDbPref; |
|
239 if(!iOptions.iPrompt) |
|
240 { |
|
241 commDbPref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); |
|
242 } |
|
243 else |
|
244 { |
|
245 commDbPref.SetDialogPreference(ECommDbDialogPrefPrompt); |
|
246 } |
|
247 User::LeaveIfError(iConnect.Start(commDbPref)); |
|
248 |
|
249 TInt err=iResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp, iConnect); |
|
250 if(err==KErrNone) |
|
251 { |
|
252 |
|
253 TInetAddr& addr = (TInetAddr&)iNameEntry().iAddr; |
|
254 if ((err=addr.Input(iOptions.iDestname))==KErrNone) |
|
255 { |
|
256 |
|
257 if(iOptions.iResolveAddress) |
|
258 { |
|
259 iState=ELookingUpHost; |
|
260 iResolver.GetByAddress(addr, iNameEntry, iSender->iStatus); |
|
261 iSender->SetActive(); |
|
262 iTimer->After(KResolvTime); |
|
263 } |
|
264 else |
|
265 { |
|
266 iSender->iStatus=KErrNone; |
|
267 iState=ELookingUpHost; |
|
268 SendComplete(); |
|
269 } |
|
270 } |
|
271 else |
|
272 { |
|
273 iState=ELookingUpHost; |
|
274 iResolver.GetByName(iOptions.iDestname, iNameEntry, iSender->iStatus); |
|
275 |
|
276 iSender->SetActive(); |
|
277 iTimer->After(KResolvTime); |
|
278 } |
|
279 } |
|
280 else |
|
281 { |
|
282 DoError(err); |
|
283 } |
|
284 } |
|
285 else |
|
286 { |
|
287 DoError(KErrBadName); |
|
288 } |
|
289 } |
|
290 |
|
291 EXPORT_C void CTraceRtEng::CancelAndFinished() |
|
292 // |
|
293 // Cancel from the UI |
|
294 // |
|
295 { |
|
296 |
|
297 if(iState!=EStopped || iTimer->IsActive()) |
|
298 { |
|
299 Cancel(); |
|
300 iUi->Finished(KErrCancel); |
|
301 } |
|
302 } |
|
303 |
|
304 EXPORT_C void CTraceRtEng::Cancel() |
|
305 // |
|
306 // Cancel a TraceRt in progress |
|
307 // |
|
308 { |
|
309 |
|
310 iSender->Cancel(); |
|
311 iReceiver->Cancel(); |
|
312 iTimer->Cancel(); |
|
313 |
|
314 iIcmpSocket.Close(); |
|
315 iResolver.Close(); |
|
316 |
|
317 iState=EStopped; |
|
318 } |
|
319 |
|
320 void CTraceRtEng::DoError(TInt aError) |
|
321 // |
|
322 // Generate an error from somewhere |
|
323 // |
|
324 { |
|
325 |
|
326 Cancel(); |
|
327 iTimer->SetActive(); |
|
328 TRequestStatus* p = &iTimer->iStatus; |
|
329 User::RequestComplete(p, aError); |
|
330 } |
|
331 |
|
332 void CTraceRtEng::TimerComplete() |
|
333 // |
|
334 // Timer event completed |
|
335 // |
|
336 { |
|
337 |
|
338 if(iTimer->iStatus==KErrNone) |
|
339 { |
|
340 |
|
341 if(iSender->IsActive()) |
|
342 { |
|
343 if(iResolv) |
|
344 { |
|
345 // We didn't manage to get the name |
|
346 // from the address, so we pass on |
|
347 iResolv = EFalse; |
|
348 // Reset sender |
|
349 iSender->Cancel(); |
|
350 // Clear previous name |
|
351 iNameEntry().iName.SetLength(0); |
|
352 // Continue |
|
353 NextSend(); |
|
354 } |
|
355 else |
|
356 { |
|
357 Cancel(); |
|
358 iUi->Finished(KErrTimedOut); |
|
359 } |
|
360 } |
|
361 else |
|
362 { |
|
363 iUi->Reply(iProbeNr, 0, KTraceRtCodeTimeout); |
|
364 switch(iLastCode) |
|
365 { |
|
366 case KTraceRtCodeUnreachNet: |
|
367 case KTraceRtCodeUnreachHost: |
|
368 ++iUnreachCount; |
|
369 break; |
|
370 default: |
|
371 break; |
|
372 } |
|
373 NextSend(); |
|
374 } |
|
375 } |
|
376 else |
|
377 { |
|
378 Cancel(); |
|
379 iUi->Finished(iTimer->iStatus.Int()); |
|
380 } |
|
381 } |
|
382 |
|
383 void CTraceRtEng::SendComplete() |
|
384 // |
|
385 // A send operation has completed |
|
386 // |
|
387 { |
|
388 |
|
389 TInt err=iSender->iStatus.Int(); |
|
390 iTimer->Cancel(); |
|
391 iResolv = EFalse; |
|
392 |
|
393 switch(iState) |
|
394 { |
|
395 |
|
396 case ELookingUpHost: |
|
397 iDstAddr = iNameEntry().iAddr; |
|
398 if(iDstAddr.Address()!=0) |
|
399 { |
|
400 TInt res=iIcmpSocket.Open(iSocketServ, KAfInet, KSockDatagram, KProtocolInetIcmp, iConnect); |
|
401 |
|
402 if(res==KErrNone) |
|
403 { |
|
404 res=iIcmpSocket.SetOpt(KSORecvBuf, KSOLSocket, iRecvData->MaxLength()); |
|
405 } |
|
406 if(res==KErrNone) |
|
407 { |
|
408 res=iIcmpSocket.SetOpt(KSOSendBuf, KSOLSocket, iSendData->MaxLength()); |
|
409 } |
|
410 if(res==KErrNone) |
|
411 { |
|
412 res=iIcmpSocket.SetOpt(KSoIpTOS, KSolInetIp, (TInt)iOptions.iTos); |
|
413 } |
|
414 |
|
415 if(res!=KErrNone) |
|
416 { |
|
417 DoError(res); |
|
418 return; |
|
419 } |
|
420 |
|
421 // Tell the UI |
|
422 iUi->Starting(iNameEntry(), iOptions.iMaxTtl, iSendData->MaxLength()); |
|
423 iState=ESending; |
|
424 NextSend(); |
|
425 } |
|
426 else |
|
427 { |
|
428 DoError(err!=KErrNone ? err : KErrNotFound); |
|
429 } |
|
430 break; |
|
431 |
|
432 case ELookingUpReply: |
|
433 if(err!=KErrNone) |
|
434 { |
|
435 iNameEntry().iName.SetLength(0); |
|
436 } |
|
437 NextSend(); |
|
438 break; |
|
439 |
|
440 default: |
|
441 if(err==KErrNone) |
|
442 { |
|
443 iTimer->After(iOptions.iWait); |
|
444 iIcmpSocket.RecvFrom(*(iRecvData->Grab()), iSrcAddr, 0, iReceiver->iStatus); |
|
445 iReceiver->SetActive(); |
|
446 } |
|
447 else |
|
448 { |
|
449 DoError(err); |
|
450 } |
|
451 } |
|
452 } |
|
453 |
|
454 void CTraceRtEng::NextSend() |
|
455 // |
|
456 // Initiate the next send |
|
457 // |
|
458 { |
|
459 |
|
460 iReceiver->Cancel(); |
|
461 |
|
462 if(iProbeNr>=iOptions.iNrProbes) |
|
463 { |
|
464 |
|
465 if(iState==ELookingUpReply || !iOptions.iResolveAddress || TInetAddr::Cast(iNameEntry().iAddr).Address()==0) |
|
466 { |
|
467 |
|
468 if(!iOptions.iResolveAddress) |
|
469 { |
|
470 iNameEntry().iName.SetLength(0); |
|
471 } |
|
472 |
|
473 iUi->FromHost(iNameEntry()); |
|
474 if(iGotThere || iUnreachCount>=iOptions.iNrProbes ) |
|
475 { |
|
476 Cancel(); |
|
477 iUi->Finished(KErrNone); |
|
478 return; |
|
479 } |
|
480 |
|
481 TInetAddr::Cast(iNameEntry().iAddr).SetAddress(0); |
|
482 ++iTtl; |
|
483 iProbeNr=0; |
|
484 iLastCode=KTraceRtCodeTimeout; |
|
485 iUnreachCount=0; |
|
486 iState=ESending; |
|
487 } |
|
488 else |
|
489 { |
|
490 iState=ELookingUpReply; |
|
491 |
|
492 // Work around for bug in pre-61 versions of TCPIP |
|
493 TProtocolDesc info; |
|
494 if(iIcmpSocket.Info(info)==KErrNone) |
|
495 { |
|
496 TVersion &v=info.iVersion; |
|
497 if(v.iMajor==1 && v.iMinor==0 && v.iBuild<61) |
|
498 { |
|
499 iResolver.Close(); |
|
500 TInt res=iResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp, iConnect); |
|
501 if(res!=KErrNone) |
|
502 { |
|
503 DoError(res); |
|
504 return; |
|
505 } |
|
506 } |
|
507 } |
|
508 // Work around ends |
|
509 |
|
510 iResolver.GetByAddress(iNameEntry().iAddr, iNameEntry, iSender->iStatus); |
|
511 iSender->SetActive(); |
|
512 iResolv = ETrue; |
|
513 iTimer->After(KResolvTime); |
|
514 return; |
|
515 } |
|
516 } |
|
517 |
|
518 if(iTtl>iOptions.iMaxTtl) |
|
519 { |
|
520 Cancel(); |
|
521 iUi->Finished(KErrNone); |
|
522 return; |
|
523 } |
|
524 |
|
525 if(iProbeNr==0) |
|
526 { |
|
527 iUi->Probe(iTtl); |
|
528 } |
|
529 |
|
530 iSendData->FormatSend(++iSeq, iIdent); |
|
531 TInt res=iIcmpSocket.SetOpt(KSoIpTTL, KSolInetIp, (TInt)iTtl); |
|
532 if(res!=KErrNone) |
|
533 { |
|
534 DoError(res); |
|
535 return; |
|
536 } |
|
537 iIcmpSocket.SendTo(*(iSendData->Grab()), iDstAddr, 0, iSender->iStatus); |
|
538 iSendTime.UniversalTime(); |
|
539 iSender->SetActive(); |
|
540 iTimer->After(KMaxSendTime); |
|
541 // pg 13/03/2000 - Base removing this api |
|
542 // UserHal::ResetAutoSwitchOffTimer(); |
|
543 |
|
544 ++iProbeNr; |
|
545 return; |
|
546 } |
|
547 |
|
548 void CTraceRtEng::SendDoCancel() |
|
549 // |
|
550 // A send operation requires cancelling |
|
551 // |
|
552 { |
|
553 |
|
554 if(iState==ELookingUpHost || iState==ELookingUpReply) |
|
555 { |
|
556 iResolver.Cancel(); |
|
557 } |
|
558 else if(iState==ESending) |
|
559 { |
|
560 iIcmpSocket.CancelSend(); |
|
561 } |
|
562 } |
|
563 |
|
564 void CTraceRtEng::RecvComplete() |
|
565 // |
|
566 // A recv operation has completed |
|
567 // |
|
568 { |
|
569 |
|
570 if(iReceiver->iStatus==KErrNone) |
|
571 { |
|
572 |
|
573 if(iState!=ESending) |
|
574 { |
|
575 return; |
|
576 } |
|
577 |
|
578 if(iRecvData->VerifyRecv(iSeq, iIdent)) |
|
579 { |
|
580 |
|
581 iNameEntry().iAddr = iSrcAddr; |
|
582 TTime now; |
|
583 now.UniversalTime(); |
|
584 TTimeIntervalMicroSeconds delta = now.MicroSecondsFrom(iSendTime); |
|
585 TUint code; |
|
586 |
|
587 switch(iRecvData->Type()) |
|
588 { |
|
589 case KTraceRtTypeTimeExceeded: |
|
590 code = KTraceRtCodeTimedOutInTransit; |
|
591 break; |
|
592 case KTraceRtTypeEchoReply: |
|
593 code = KTraceRtCodeEchoReply; |
|
594 iGotThere=ETrue; |
|
595 break; |
|
596 default: |
|
597 code=iRecvData->Code(); |
|
598 ++iUnreachCount; |
|
599 } |
|
600 |
|
601 iLastCode=code; |
|
602 |
|
603 delta = delta.Int64()/TInt64(1000); |
|
604 iUi->Reply(iProbeNr, I64LOW(delta.Int64()), code); |
|
605 |
|
606 iTimer->Cancel(); |
|
607 NextSend(); |
|
608 return; |
|
609 } |
|
610 if(!iSender->IsActive()) |
|
611 { |
|
612 iLastCode = iRecvData->Code(); |
|
613 iIcmpSocket.RecvFrom(*(iRecvData->Grab()), iSrcAddr, 0, iReceiver->iStatus); |
|
614 iReceiver->SetActive(); |
|
615 } |
|
616 } |
|
617 else |
|
618 { |
|
619 DoError(iReceiver->iStatus.Int()); |
|
620 } |
|
621 } |
|
622 |
|
623 void CTraceRtEng::RecvDoCancel() |
|
624 // |
|
625 // A send operation requires cancelling |
|
626 // |
|
627 { |
|
628 |
|
629 iIcmpSocket.CancelRecv(); |
|
630 } |
|
631 |
|
632 CTraceRtTimer::CTraceRtTimer(CTraceRtEng& aParent) |
|
633 // |
|
634 // To time events |
|
635 // |
|
636 : CTimer(ETraceRtTimerPriority) |
|
637 { |
|
638 |
|
639 iParent = &aParent; |
|
640 CActiveScheduler::Add(this); |
|
641 __DECLARE_NAME(_S("CTraceRtTimer")); |
|
642 } |
|
643 |
|
644 void CTraceRtTimer::RunL() |
|
645 // |
|
646 // Timer is complete |
|
647 // |
|
648 { |
|
649 |
|
650 iParent->TimerComplete(); |
|
651 } |
|
652 |
|
653 CTraceRtSender::CTraceRtSender(CTraceRtEng& aParent) |
|
654 // |
|
655 // C'tor |
|
656 // |
|
657 : CActive(ETraceRtSenderPriority) |
|
658 { |
|
659 |
|
660 iParent = &aParent; |
|
661 CActiveScheduler::Add(this); |
|
662 __DECLARE_NAME(_S("CTraceRtSender")); |
|
663 } |
|
664 |
|
665 CTraceRtSender::~CTraceRtSender() |
|
666 // |
|
667 // D'tor cancels |
|
668 // |
|
669 { |
|
670 |
|
671 Cancel(); |
|
672 } |
|
673 |
|
674 void CTraceRtSender::RunL() |
|
675 // |
|
676 // Upcall to parent |
|
677 // |
|
678 { |
|
679 |
|
680 iParent->SendComplete(); |
|
681 } |
|
682 |
|
683 void CTraceRtSender::DoCancel() |
|
684 // |
|
685 // Get parent to cancel send |
|
686 // |
|
687 { |
|
688 |
|
689 iParent->SendDoCancel(); |
|
690 } |
|
691 |
|
692 CTraceRtReceiver::CTraceRtReceiver(CTraceRtEng& aParent) |
|
693 // |
|
694 // C'tor |
|
695 // |
|
696 : CActive(ETraceRtReceiverPriority) |
|
697 { |
|
698 |
|
699 iParent = &aParent; |
|
700 CActiveScheduler::Add(this); |
|
701 __DECLARE_NAME(_S("CTraceRtReceiver")); |
|
702 } |
|
703 |
|
704 CTraceRtReceiver::~CTraceRtReceiver() |
|
705 // |
|
706 // D'tor cancels |
|
707 // |
|
708 { |
|
709 |
|
710 Cancel(); |
|
711 } |
|
712 |
|
713 void CTraceRtReceiver::RunL() |
|
714 // |
|
715 // Upcall to parent |
|
716 // |
|
717 { |
|
718 |
|
719 iParent->RecvComplete(); |
|
720 } |
|
721 |
|
722 void CTraceRtReceiver::DoCancel() |
|
723 // |
|
724 // Get parent to cancel send |
|
725 // |
|
726 { |
|
727 |
|
728 iParent->RecvDoCancel(); |
|
729 } |
|
730 |
|
731 |
|
732 HTraceRtHeader::~HTraceRtHeader() |
|
733 // |
|
734 // D'tor deletes |
|
735 // |
|
736 { |
|
737 |
|
738 delete iData; |
|
739 delete iDataPtr; |
|
740 } |
|
741 |
|
742 HTraceRtHeader* HTraceRtHeader::NewL(TInt aSize) |
|
743 // |
|
744 // Create a new trace route header |
|
745 // |
|
746 { |
|
747 |
|
748 HTraceRtHeader* h = new(ELeave) HTraceRtHeader(); |
|
749 |
|
750 CleanupStack::PushL(h); |
|
751 h->ConstructL(aSize); |
|
752 CleanupStack::Pop(h); |
|
753 |
|
754 return h; |
|
755 } |
|
756 |
|
757 void HTraceRtHeader::ConstructL(TInt aSize) |
|
758 { |
|
759 |
|
760 iData = HBufC8::NewL(aSize); |
|
761 iDataPtr = new(ELeave) TPtr8(iData->Des()); |
|
762 |
|
763 iData->Des().FillZ(); |
|
764 } |
|
765 |
|
766 TInt HTraceRtHeader::MaxLength() |
|
767 { |
|
768 |
|
769 return iData->Des().MaxLength(); |
|
770 } |
|
771 |
|
772 TInt HTraceRtHeader::DataLength() |
|
773 { |
|
774 |
|
775 return iData->Des().Length(); |
|
776 } |
|
777 |
|
778 TPtr8* HTraceRtHeader::Grab() |
|
779 { |
|
780 |
|
781 iDataPtr->Copy(iData->Des()); |
|
782 return iDataPtr; |
|
783 } |
|
784 |
|
785 TBool HTraceRtHeader::SetHeader(TUint aOffset) |
|
786 // |
|
787 // Set the header from an Icmp reply |
|
788 // |
|
789 { |
|
790 |
|
791 const TUint8* buffData; |
|
792 |
|
793 // Check size |
|
794 if(DataLength() < KIcmpHeaderSize) |
|
795 { |
|
796 return EFalse; |
|
797 } |
|
798 |
|
799 buffData = iData->Des().Ptr(); |
|
800 |
|
801 if(!buffData) |
|
802 { |
|
803 return EFalse; |
|
804 } |
|
805 |
|
806 // Fill TInet6HeaderICMP_Echo from the buffer |
|
807 for(int k=0;k<KIcmpHeaderSize;k++) |
|
808 { |
|
809 i[k] = *(buffData + k + aOffset); |
|
810 } |
|
811 |
|
812 return ETrue; |
|
813 } |
|
814 |
|
815 TBool HTraceRtHeader::VerifyRecv(TInt aSeq, TInt aIdent) |
|
816 // |
|
817 // Verify header is valid |
|
818 // |
|
819 { |
|
820 |
|
821 TBool ret = SetHeader(); |
|
822 |
|
823 if(ret) |
|
824 { |
|
825 ret = EFalse; |
|
826 |
|
827 if(Type() == KTraceRtTypeEchoReply && Identifier() == aIdent && Sequence() == aSeq) |
|
828 { |
|
829 ret = ETrue; |
|
830 } |
|
831 |
|
832 if(!ret && ((Type() == KTraceRtTypeTimeExceeded && Code() == KTraceRtCodeExceedInTransit) || Type() == KTraceRtTypeUnreachable)) |
|
833 { |
|
834 TUint code = Code(); |
|
835 TUint type = Type(); |
|
836 ret = SetHeader(KMinIpHeaderSize + KIcmpHeaderSize); |
|
837 |
|
838 if(ret) |
|
839 { |
|
840 ret = EFalse; |
|
841 |
|
842 if(Type() != KTraceRtTypeEchoRequest || Identifier() != aIdent || Sequence() != aSeq) |
|
843 { |
|
844 ret = EFalse; |
|
845 } |
|
846 else |
|
847 { |
|
848 ret = ETrue; |
|
849 } |
|
850 } |
|
851 SetCode(static_cast<TUint8>(code)); |
|
852 SetType(static_cast<TUint8>(type)); |
|
853 } |
|
854 } |
|
855 |
|
856 return ret; |
|
857 } |
|
858 |
|
859 |
|
860 void HTraceRtHeader::FormatSend(TUint aSeq, TUint aIdent) |
|
861 // |
|
862 // Format an ICMP Header |
|
863 // |
|
864 { |
|
865 |
|
866 TChecksum sum; |
|
867 |
|
868 // Fill header |
|
869 SetType(KTraceRtTypeEchoRequest); |
|
870 SetCode(KTraceRtCodeEcho); |
|
871 SetIdentifier(static_cast<TUint16>(aIdent)); |
|
872 SetSequence(static_cast<TUint16>(aSeq)); |
|
873 |
|
874 // Compute cheksum |
|
875 SetChecksum(0); |
|
876 sum.Add(reinterpret_cast<TUint16*>(this), HeaderLength()); |
|
877 SetChecksum(sum.Sum()); |
|
878 |
|
879 // Copy the ICMP Header in the buffer |
|
880 iData->Des().Copy((TUint8*)this, HeaderLength()); |
|
881 } |
|
882 |