networkingtestandutils/exampleinternetutilities/TRENG/TRENG.CPP
changeset 0 af10295192d8
child 37 052078dda061
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     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