--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkingtestandutils/exampleinternetutilities/PINGENG/PINGENG.CPP Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,1053 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <pingeng.h>
+#include <e32hal.h>
+#include <icmp6_hdr.h>
+#include <in_chk.h>
+#include <commdbconnpref.h>
+#include <connpref.h>
+
+const TInt KDefaultPings = 4;
+const TInt KDefaultInterval = 1000000;
+const TInt KDefaultWait = 10000000;
+const TInt KDefaultPingSize = 32;
+const TInt KDefaultBacklog = 512;
+
+const TInt KMaxTimeOnQue=KDefaultBacklog*KDefaultInterval;
+const TInt KMaxSendTime=60000000;
+
+const TUint KIcmpHeaderSize = 8;
+const TUint KMinIpHeaderSize = 20;
+
+class CPingTimer : public CTimer
+ {
+friend class CPingEng;
+protected:
+ CPingTimer(CPingEng& aParent);
+ void RunL();
+private:
+ CPingEng& iParent;
+ };
+
+class CPingSender : public CActive
+ {
+friend class CPingEng;
+protected:
+ CPingSender(CPingEng& aParent);
+ ~CPingSender();
+ void RunL();
+ void DoCancel();
+private:
+ CPingEng& iParent;
+ };
+
+class CPingReceiver : public CActive
+ {
+friend class CPingEng;
+protected:
+ CPingReceiver(CPingEng& aParent);
+ ~CPingReceiver();
+ void RunL();
+ void DoCancel();
+private:
+ CPingEng& iParent;
+ };
+
+
+class HPingHeader : public TInet6HeaderICMP_Echo
+ {
+public:
+ static HPingHeader* NewL(TInt aSize = KIcmpHeaderSize, TUint aIPVersion = KAfInet);
+ ~HPingHeader();
+
+ TBool VerifyRecvEcho(TInt aId);
+ TBool VerifyNonEcho(TInt aId);
+ void SetVersion(TUint aIPVersion);
+ void FormatSend(TUint aId, TUint aSeqNum);
+ TInt MaxLength();
+ TInt DataLength();
+ TPtr8* Grab();
+ TPtrC8 IcmpContents();
+
+private:
+ void ConstructL(TInt aSize, TUint aIPVersion);
+ TBool SetHeader(TUint aOffset = 0);
+
+ HBufC8* iData;
+ TPtr8* iDataPtr;
+ TUint iIPVersion;
+ TInt iSize;
+ };
+
+enum TPingEngPanic
+ {
+
+ ETimerPriorityGreaterThanSender, // 0
+ ESenderPrirityGreaterThanReceiver // 1
+ };
+
+LOCAL_C void Panic(TPingEngPanic aPanic)
+//
+// Panic the user
+//
+ {
+
+ User::Panic(_L("PingEng"), aPanic);
+ }
+
+EXPORT_C TPingOptions::TPingOptions()
+//
+// Default ping options
+//
+ {
+
+ iNumberOfPings=KDefaultPings;
+ iInterval = KDefaultInterval;
+ iWait = KDefaultWait;
+ iPingSize=KDefaultPingSize;
+ iResolveAddress=EFalse;
+ iPrompt=EFalse;
+ iConnIap=0;
+ iConnSnap=0;
+ iPreload=0;
+ iBacklog=KDefaultBacklog;
+ }
+
+EXPORT_C CPingEng* CPingEng::NewL(MPingNotificationHandler& aUi)
+//
+// Create a new ping engine
+//
+ {
+
+ CPingEng* p= new(ELeave) CPingEng(aUi);
+ CleanupStack::PushL(p);
+ p->ConstructL();
+ CleanupStack::Pop(p);
+ return p;
+ }
+
+CPingEng::CPingEng(MPingNotificationHandler& aUi)
+: iUi(aUi)
+//
+// Declare a name
+//
+ {
+
+ __DECLARE_NAME(_S("CPingEng"));
+ }
+
+EXPORT_C CPingEng::~CPingEng()
+//
+// Destroy wot ping created
+ {
+
+ iSocket.Close();
+ iResolver.Close();
+ iConnect.Close();
+ iSocketServ.Close();
+ delete iReceiver;
+ delete iSender;
+ delete iTimer;
+ delete iRecvData;
+ delete iSendData;
+
+ EmptyPingRecordQue();
+ }
+
+void CPingEng::EmptyPingRecordQue()
+ {
+
+ while (!iQue.IsEmpty())
+ {
+ DeletePingRecord(iQue.First());
+ }
+ }
+
+void CPingEng::DeletePingRecord(TPingRecord* aRecord)
+ {
+
+ iQue.Remove(*aRecord);
+ delete aRecord;
+ iNoInQue--;
+ }
+
+void CPingEng::ConstructL()
+//
+// Construct and heap objects
+//
+ {
+
+ iQue.SetOffset(_FOFF(TPingRecord, iLink));
+ iTimer = new (ELeave) CPingTimer(*this);
+ iTimer->ConstructL();
+ iSender = new (ELeave) CPingSender(*this);
+ iReceiver = new (ELeave) CPingReceiver(*this);
+ User::LeaveIfError(iSocketServ.Connect());
+ }
+
+EXPORT_C void CPingEng::SetPriorities(TInt aTimerPriority, TInt aSenderPriority, TInt aReceiverPriority)
+//
+// Set various active object priorities
+//
+ {
+
+ __ASSERT_ALWAYS(aTimerPriority < aSenderPriority, Panic(ETimerPriorityGreaterThanSender));
+ __ASSERT_ALWAYS(aSenderPriority < aReceiverPriority, Panic(ESenderPrirityGreaterThanReceiver));
+
+ iTimer->SetPriority(aTimerPriority);
+ iSender->SetPriority(aSenderPriority);
+ iReceiver->SetPriority(aReceiverPriority);
+ }
+
+EXPORT_C void CPingEng::StartL(const TPingOptions& aOptions)
+//
+// Start a ping
+//
+ {
+
+ // Reset All Variables
+ iNrTransmitted=0;
+ iNrReceived=0;
+ iNrDuplicates=0;
+ iMinTime=KMaxTInt;
+ iMaxTime=0;
+ iSumTime=0;
+ iId=User::TickCount()&KMaxTUint16;
+ iNameEntry().iName.SetLength(0);
+ iNameEntry().iFlags=0;
+ iIsLoopback = EFalse;
+
+ iOptions=aOptions;
+
+ if(iOptions.iDestname.Length()>0)
+ {
+
+ TInetAddr& addr = (TInetAddr&)iNameEntry().iAddr;
+
+ const TBool addressInputValid = addr.Input(iOptions.iDestname) == KErrNone;
+
+ if (addressInputValid)
+ {
+ iIsLoopback = addr.IsLoopback();
+ }
+
+ iConnect.Close();
+
+ // Make a connection only if it is required.
+ //
+ if (!iIsLoopback)
+ {
+ // This branch will unfortunately be taken if the call to TInetAddr.Input() fails.
+
+
+ User::LeaveIfError(iConnect.Open(iSocketServ, KConnectionTypeDefault));
+
+ if(iOptions.iConnSnap)
+ {
+ TConnSnapPref connPref(iOptions.iConnSnap);
+ User::LeaveIfError(iConnect.Start(connPref));
+ }
+ else
+ {
+ TCommDbConnPref commDbPref;
+
+ if(iOptions.iConnIap)
+ {
+ commDbPref.SetIapId(iOptions.iConnIap);
+ }
+
+ if(!iOptions.iPrompt)
+ {
+ commDbPref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
+ }
+ else
+ {
+ commDbPref.SetDialogPreference(ECommDbDialogPrefPrompt);
+ }
+ User::LeaveIfError(iConnect.Start(commDbPref));
+ }
+ }
+
+
+ TInt err;
+
+ if (addressInputValid)
+ {
+ if(iOptions.iResolveAddress)
+ {
+ if((err=iResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp, iConnect))==KErrNone)
+ {
+ iState=ELookingUp;
+ iResolver.GetByAddress(addr, iNameEntry, iSender->iStatus);
+ iSender->SetActive();
+ iTimer->After(KMaxSendTime);
+ }
+ else
+ {
+ DoError(err);
+ }
+ }
+ else
+ {
+ iSender->iStatus=KErrNone;
+ iState=ELookingUp;
+ SendCompleteL();
+ }
+ }
+ else
+ {
+ if((err=iResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp, iConnect))==KErrNone)
+ {
+ iState=ELookingUp;
+ iResolver.GetByName(iOptions.iDestname, iNameEntry, iSender->iStatus);
+ iSender->SetActive();
+ iTimer->After(KMaxSendTime);
+ }
+ else
+ {
+ DoError(err);
+ }
+ }
+ }
+ else
+ {
+ DoError(KErrBadName);
+ }
+ }
+
+EXPORT_C void CPingEng::CancelAndFinished()
+//
+// Cancel from the UI
+//
+ {
+
+ if(iState!=EStopped || iTimer->IsActive())
+ {
+ Cancel();
+ iUi.Finished(iNameEntry(), iNrTransmitted, iNrReceived, iNrDuplicates, iMinTime, iMaxTime, iSumTime, KErrCancel);
+ }
+ }
+
+EXPORT_C void CPingEng::Cancel()
+//
+// Cancel a ping in progress
+//
+ {
+
+ iSender->Cancel();
+ iReceiver->Cancel();
+ iTimer->Cancel();
+ iSocket.Close();
+ iConnect.Close();
+ iResolver.Close();
+
+ EmptyPingRecordQue();
+
+ iState=EStopped;
+ }
+
+void CPingEng::DoError(TInt aError)
+//
+// Generate an error from somewhere
+//
+ {
+
+ Cancel();
+ iTimer->SetActive();
+ TRequestStatus* p = &iTimer->iStatus;
+ User::RequestComplete(p, aError);
+ }
+
+void CPingEng::TimerComplete()
+//
+// Timer event completed
+//
+ {
+
+ if(iTimer->iStatus==KErrNone)
+ {
+
+ if((iOptions.iNumberOfPings && iNrTransmitted>=iOptions.iNumberOfPings)
+ || iSender->IsActive())
+ {
+
+ Cancel();
+ iUi.Finished(iNameEntry(), iNrTransmitted, iNrReceived, iNrDuplicates, iMinTime, iMaxTime, iSumTime, KErrTimedOut);
+ }
+ else
+ {
+ PurgeQue();
+ NextSend();
+ }
+ }
+ else
+ {
+ iUi.Finished(iNameEntry(), iNrTransmitted, iNrReceived, iNrDuplicates, iMinTime, iMaxTime, iSumTime, iTimer->iStatus.Int());
+ }
+ }
+
+void CPingEng::SendCompleteL()
+//
+// A send operation has completed
+//
+ {
+ if(iState==ELookingUp)
+ {
+ iResolver.Close();
+ }
+
+ if(iSender->iStatus!=KErrNone)
+ {
+ DoError(iSender->iStatus.Int());
+ return;
+ }
+
+ iTimer->Cancel();
+
+ if(iState==ELookingUp) // Intiate the ping process
+ {
+ delete iSendData;
+ iSendData = NULL;
+ delete iRecvData;
+ iRecvData = NULL;
+ TInt res=KErrNone;
+
+ // Set up socket and recieve/send packets depending on address type.
+ switch(iNameEntry().iAddr.Family())
+ {
+ case KAfInet:
+ {
+ iSendData = HPingHeader::NewL(iOptions.iPingSize);
+ iRecvData = HPingHeader::NewL(iOptions.iPingSize);
+ if(!iRecvData || !iSendData)
+ {
+ DoError(KErrNoMemory);
+ return;
+ }
+
+ if (iIsLoopback)
+ {
+ res=iSocket.Open(iSocketServ, KAfInet, KSockDatagram, KProtocolInetIcmp);
+ }
+ else
+ {
+ res=iSocket.Open(iSocketServ, KAfInet, KSockDatagram, KProtocolInetIcmp, iConnect);
+ }
+ break;
+ }
+ case KAfInet6:
+ {
+ iSendData = HPingHeader::NewL(iOptions.iPingSize, KAfInet6);
+ iRecvData = HPingHeader::NewL(iOptions.iPingSize, KAfInet6);
+ if(!iRecvData || !iSendData)
+ {
+ DoError(KErrNoMemory);
+ return;
+ }
+
+ if (iIsLoopback)
+ {
+ res=iSocket.Open(iSocketServ, KAfInet, KSockDatagram, KProtocolInet6Icmp);
+ }
+ else
+ {
+ res=iSocket.Open(iSocketServ, KAfInet, KSockDatagram, KProtocolInet6Icmp, iConnect);
+ }
+ break;
+ }
+ default:
+ DoError(KErrGeneral);
+ return;
+ }
+
+ if(res==KErrNone)
+ {
+ res=iSocket.SetOpt(KSORecvBuf, KSOLSocket, iRecvData->MaxLength());
+ }
+ if(res==KErrNone)
+ {
+ res=iSocket.SetOpt(KSOSendBuf, KSOLSocket, iSendData->MaxLength());
+ }
+
+ if(res!=KErrNone)
+ {
+ DoError(res);
+ return;
+ }
+
+ // Start the receiver
+ iSocket.RecvFrom(*(iRecvData->Grab()), iSrcAddr, 0, iReceiver->iStatus);
+ iReceiver->SetActive();
+
+ // Tell the UI
+ iUi.Pinging(iNameEntry(),iOptions.iPingSize);
+ iState=ESending;
+ NextSend();
+ }
+ else // Start appropriate timer
+ {
+
+ iUi.Sent();
+ if(!iOptions.iNumberOfPings || iNrTransmitted<iOptions.iNumberOfPings)
+ {
+ if(iOptions.iPreload || !iOptions.iInterval.Int())
+ {
+ if(iOptions.iPreload>0)
+ {
+ --iOptions.iPreload;
+ }
+ iTimer->iStatus=KErrNone;
+ TimerComplete();
+ }
+ else
+ {
+ iTimer->After(iOptions.iInterval);
+ }
+ }
+ else if(iNrReceived)
+ {
+ iTimer->After(iMaxTime>500000 ? (iMaxTime*5) : 1000000);
+ }
+ else
+ {
+ iTimer->After(iOptions.iWait);
+ }
+ }
+ }
+
+
+void CPingEng::NextSend()
+//
+// Initiate the next send
+//
+ {
+ TPingRecord* r = new TPingRecord(iNrTransmitted);
+ if(!r)
+ {
+ DoError(KErrNoMemory);
+ return;
+ }
+
+ iQue.AddLast(*r);
+ iNoInQue++;
+
+ if(iNoInQue > iOptions.iBacklog)
+ {
+ DeletePingRecord(iQue.First());
+ }
+
+ iSendData->FormatSend(iId, iNrTransmitted++);
+ iSocket.SendTo(*(iSendData->Grab()), iNameEntry().iAddr, iSendFlags, iSender->iStatus);
+ iSender->SetActive();
+ iTimer->After(KMaxSendTime);
+
+ }
+
+void CPingEng::SendDoCancel()
+//
+// A send operation requires cancelling
+//
+ {
+
+ if(iState==ELookingUp)
+ {
+ iResolver.Cancel();
+ }
+ else if(iState==ESending)
+ {
+ iSocket.CancelSend();
+ }
+ }
+
+void CPingEng::RecvComplete()
+//
+// A recv operation has completed
+//
+ {
+
+ if(iReceiver->iStatus==KErrNone)
+ {
+
+ if(iRecvData->VerifyRecvEcho(iId))
+ {
+ TSglQueIter<TPingRecord> iter(iQue);
+ TPingRecord* p=0;
+ while((p=iter++)!=0)
+ {
+ if(iRecvData->Sequence() == p->iSeqNr)
+ {
+ ++iNrReceived;
+
+ TTime now;
+ now.UniversalTime();
+ TTimeIntervalMicroSeconds32 word = I64LOW(now.MicroSecondsFrom(p->iSendTime).Int64());
+
+ iMaxTime = word.Int()>iMaxTime ? word.Int() : iMaxTime;
+ iMinTime = word.Int()<iMinTime ? word.Int() : iMinTime;
+ iSumTime += word.Int();
+
+ iUi.Reply(iSrcAddr, iRecvData->DataLength(), p->iSeqNr, word);
+
+ DeletePingRecord(p);
+
+ if(iQue.IsEmpty() && iOptions.iNumberOfPings && iNrReceived>=iOptions.iNumberOfPings
+ && iNrTransmitted>=iOptions.iNumberOfPings)
+ {
+ Cancel();
+ iUi.Finished(iNameEntry(), iNrTransmitted, iNrReceived, iNrDuplicates, iMinTime, iMaxTime, iSumTime, KErrNone);
+ return;
+ }
+ break;
+ }
+ }
+ if(p==0)
+ {
+ ++iNrDuplicates;
+ }
+ }
+ else if(iRecvData->VerifyNonEcho(iId))
+ {
+ if(iNameEntry().iAddr.Family()==KAfInet)
+ {
+ iUi.Icmp4Message(iSrcAddr, iRecvData->Type(), iRecvData->Code(), iRecvData->IcmpContents());
+ }
+ else
+ {
+ iUi.Icmp6Message(iSrcAddr, iRecvData->Type(), iRecvData->Code());
+ }
+ }
+
+ iSocket.RecvFrom(*(iRecvData->Grab()), iSrcAddr, 0, iReceiver->iStatus);
+ iReceiver->SetActive();
+ }
+ else
+ {
+ DoError(iReceiver->iStatus.Int());
+ }
+ }
+
+void CPingEng::PurgeQue()
+//
+// Purge the que of things that linger about for too long
+//
+ {
+
+ TTime shortTimeAgo;
+ shortTimeAgo.UniversalTime();
+ shortTimeAgo -= TTimeIntervalMicroSeconds32(Max(KMaxTimeOnQue, iOptions.iWait.Int()));
+
+ TSglQueIter<TPingRecord> iter(iQue);
+ TPingRecord* p;
+ while((p=iter++)!=0)
+ {
+ if(p->iSendTime < shortTimeAgo)
+
+ {
+ DeletePingRecord(p);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+void CPingEng::RecvDoCancel()
+//
+// A send operation requires cancelling
+//
+ {
+
+ iSocket.CancelRecv();
+ }
+
+CPingTimer::CPingTimer(CPingEng& aParent)
+//
+// To time events
+//
+ : CTimer(EPingTimerPriority), iParent(aParent)
+ {
+
+ CActiveScheduler::Add(this);
+ __DECLARE_NAME(_S("CPingTimer"));
+ }
+
+void CPingTimer::RunL()
+//
+// Timer is complete
+//
+ {
+
+ iParent.TimerComplete();
+ }
+
+CPingSender::CPingSender(CPingEng& aParent)
+//
+// C'tor
+//
+ : CActive(EPingSenderPriority), iParent(aParent)
+ {
+
+ CActiveScheduler::Add(this);
+ __DECLARE_NAME(_S("CPingSender"));
+ }
+
+CPingSender::~CPingSender()
+//
+// D'tor cancels
+//
+ {
+
+ Cancel();
+ }
+
+void CPingSender::RunL()
+//
+// Upcall to parent
+//
+ {
+
+ iParent.SendCompleteL();
+ }
+
+void CPingSender::DoCancel()
+//
+// Get parent to cancel send
+//
+ {
+
+ iParent.SendDoCancel();
+ }
+
+CPingReceiver::CPingReceiver(CPingEng& aParent)
+//
+// C'tor
+//
+ : CActive(EPingReceiverPriority), iParent(aParent)
+ {
+
+ CActiveScheduler::Add(this);
+ __DECLARE_NAME(_S("CPingReceiver"));
+ }
+
+CPingReceiver::~CPingReceiver()
+//
+// D'tor cancels
+//
+ {
+
+ Cancel();
+ }
+
+void CPingReceiver::RunL()
+//
+// Upcall to parent
+//
+ {
+
+ iParent.RecvComplete();
+ }
+
+void CPingReceiver::DoCancel()
+//
+// Get parent to cancel send
+//
+ {
+
+ iParent.RecvDoCancel();
+ }
+
+TPingRecord::TPingRecord(TUint aSeqNr)
+//
+// Create new ping record
+//
+ {
+
+ iSeqNr = aSeqNr&KMaxTUint16;
+ iSendTime.UniversalTime();
+ }
+
+HPingHeader::~HPingHeader()
+//
+// D'tor deletes
+//
+ {
+
+ delete iData;
+ delete iDataPtr;
+ }
+
+HPingHeader* HPingHeader::NewL(TInt aSize, TUint aIPVersion)
+//
+// Create a new ping header
+//
+ {
+
+ HPingHeader* h = new(ELeave) HPingHeader();
+
+ CleanupStack::PushL(h);
+ h->ConstructL(aSize, aIPVersion);
+ CleanupStack::Pop(h);
+
+ return h;
+ }
+
+void HPingHeader::ConstructL(TInt aSize, TUint aIPVersion)
+ {
+
+ iData = HBufC8::NewL(aSize);
+ iDataPtr = new(ELeave) TPtr8(iData->Des());
+ iSize = aSize < KIcmpHeaderSize ? KIcmpHeaderSize : aSize;
+
+ iData->Des().FillZ();
+ SetVersion(aIPVersion);
+ }
+
+void HPingHeader::SetVersion(TUint aIPVersion)
+//
+// To set IP version of packet
+//
+ {
+
+ iIPVersion = aIPVersion;
+ }
+
+TInt HPingHeader::MaxLength()
+//
+// To get packet data maximum length
+//
+ {
+
+ return iData->Des().MaxLength();
+ }
+
+TInt HPingHeader::DataLength()
+//
+// To get packet data length
+//
+ {
+
+ return iData->Des().Length();
+ }
+
+TPtrC8 HPingHeader::IcmpContents()
+//
+// To get the icmp contents from packet data
+//
+ {
+
+ return iData->Des().Mid(4, iData->Length()-4);
+ }
+
+TPtr8* HPingHeader::Grab()
+//
+// To get data far a send or receive operation
+//
+ {
+
+ iDataPtr->Copy(iData->Des());
+ return iDataPtr;
+ }
+
+void HPingHeader::FormatSend(TUint aId, TUint aSeqNum)
+//
+// Format an ICMP packet to send
+//
+ {
+
+ TUint type;
+ TUint code;
+ TChecksum sum;
+
+ // Configure version
+ if(iIPVersion == KAfInet)
+ {
+ type = KIPv4PingTypeEchoRequest;
+ code = KIPv4PingCodeEcho;
+ }
+ else
+ {
+ type = KIPv6PingTypeEchoRequest;
+ code = KIPv6PingCodeEcho;
+ }
+
+ // Fill header
+ SetType(static_cast<TUint8>(type));
+ SetCode(static_cast<TUint8>(code));
+ SetIdentifier(static_cast<TUint16>(aId));
+ SetSequence(static_cast<TUint16>(aSeqNum));
+
+ // Zero checksum
+ SetChecksum(0);
+
+ // Copy the header to the data descriptor
+ iData->Des().Copy(reinterpret_cast<TUint8*>(this), KIcmpHeaderSize);
+
+ // Adjust the length for the appropriate ping size
+ iData->Des().SetLength(iSize);
+
+ // Fill ping data
+ if (iSize > KIcmpHeaderSize)
+ {
+ TInt i = 0;
+ TUint8 dataChar = 'a';
+ TInt dataLen = iSize - KIcmpHeaderSize;
+ TPtr8 dataPtr = iData->Des().MidTPtr(KIcmpHeaderSize, dataLen);
+
+ for (i = 0; i < dataLen; i++ )
+ {
+ dataPtr[i] = dataChar;
+ if (dataChar == 'z')
+ {
+ dataChar = 'a';
+ }
+ else
+ {
+ dataChar++;
+ }
+ }
+ }
+
+ // Compute checksum
+ sum.Add(reinterpret_cast<const TUint16*>(iData->Ptr()), iSize);
+ SetChecksum(sum.Sum());
+ }
+
+TBool HPingHeader::SetHeader(TUint aOffset)
+//
+// Set the header from an Icmp reply
+//
+ {
+
+ const TUint8* buffData;
+
+ // Check size
+ if(DataLength() < (TInt)KIcmpHeaderSize)
+ {
+ return EFalse;
+ }
+
+ buffData = iData->Des().Ptr();
+
+ if(!buffData)
+ {
+ return EFalse;
+ }
+
+ // Fill TInet6HeaderICMP_Echo from the buffer
+ for(int k=0;k<(TInt)KIcmpHeaderSize;k++)
+ {
+ i[k] = *(buffData + k + aOffset);
+ }
+
+ return ETrue;
+ }
+
+TBool HPingHeader::VerifyRecvEcho(TInt aId)
+//
+// Verifiy header is valid echo reply
+//
+ {
+
+ TBool ret = ETrue;
+ TUint typeCheck;
+ TUint codeCheck;
+
+ // Fill TInet6HeaderICMP_Echo from packet data
+ ret = SetHeader();
+
+ // Look at IP version
+ if(iIPVersion == KAfInet)
+ {
+ typeCheck = KIPv4PingTypeEchoReply;
+ codeCheck = KIPv4PingCodeEcho;
+ }
+ else
+ {
+ typeCheck = KIPv6PingTypeEchoReply;
+ codeCheck = KIPv6PingCodeEcho;
+ }
+
+ // Wrong packet type or code
+ if(ret && (Type() != typeCheck || Code() != codeCheck))
+ {
+ ret = EFalse;
+ }
+
+ // Wrong packet identifier
+ if(ret && Identifier() != aId)
+ {
+ ret = EFalse;
+ }
+
+ return ret;
+ }
+
+TBool HPingHeader::VerifyNonEcho(TInt aId)
+//
+// Verify header which is not echo reply
+//
+ {
+
+ // Fill TInet6HeaderICMP_Echo from packet data
+ TBool ret = SetHeader();
+
+ // Look at IP version
+ if(ret && iIPVersion == KAfInet) // IP4
+ {
+ switch(Type())
+ {
+ case KIPv4PingTypeUnreachable:
+ case KIPv4PingTypeSourceQuench:
+ case KIPv4PingTypeRedirect:
+ case KIPv4PingTypeTimeExceeded:
+ case KIPv4PingTypeBadParameter:
+ break;
+ default:
+ ret = EFalse;
+ }
+
+ if(ret && (DataLength() < (TInt)KIcmpHeaderSize))
+ {
+ ret = EFalse;
+ }
+
+ if(ret)
+ {
+ ret = SetHeader(KIcmpHeaderSize + KMinIpHeaderSize);
+ if(ret && (Type() != KIPv4PingTypeEchoRequest || Identifier() != aId))
+ {
+ ret = EFalse;
+ }
+ }
+ }
+ else
+ { // IP6
+ switch(Type())
+ {
+ case KIPv6PingTypeUnreachable:
+ case KIPv6PingTypePacketTooBig:
+ case KIPv6PingTypeTimeExeeded:
+ case KIPv6PingTypeParamProblem:
+ break;
+ default:
+ ret = EFalse;
+ }
+ }
+
+ return ret;
+ }
+