nettools/conntest/Engine/SocketsRead.cpp
changeset 0 857a3e953887
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nettools/conntest/Engine/SocketsRead.cpp	Thu Dec 17 08:39:25 2009 +0200
@@ -0,0 +1,349 @@
+/*
+* Copyright (c) 2006-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: CSocketsRead is an active obejct that reads data from
+* an already open socket and calculates some metrics from the data read
+*
+*/
+
+// INCLUDE FILES
+#include "SocketsRead.h"
+#include "SocketsEngine.h"
+#include "uinotify.h"
+#include "Utils.h"
+
+
+// ---------------------------------------------------------
+// CSocketsRead::NewL(MUINotify& aConsole, RSocket& aSocket)
+// EPOC two phased constructor
+// ---------------------------------------------------------
+//
+CSocketsRead* CSocketsRead::NewL(MUINotify& aConsole, RSocket& aSocket, CSocketsEngine& aEngine)
+{
+    CSocketsRead* self = CSocketsRead::NewLC(aConsole, aSocket, aEngine);
+    CleanupStack::Pop(self);
+    return self;
+}
+
+// ---------------------------------------------------------
+// CSocketsRead::NewLC(MUINotify& aConsole, RSocket& aSocket)
+// EPOC two phased constructor
+// ---------------------------------------------------------
+//
+CSocketsRead* CSocketsRead::NewLC(MUINotify& aConsole, RSocket& aSocket, CSocketsEngine& aEngine)
+{
+    CSocketsRead* self = new (ELeave) CSocketsRead(aConsole, aSocket, aEngine);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+}
+
+// ---------------------------------------------------------
+// CSocketsRead::CSocketsRead(MUINotify& aConsole, RSocket& aSocket)
+// Constructor
+// ---------------------------------------------------------
+//
+CSocketsRead::CSocketsRead(MUINotify& aConsole, RSocket& aSocket, CSocketsEngine& aEngine)
+: CActive(/*EPriorityStandard*/EPriorityHigh),
+iEngine(aEngine),
+iSocket(aSocket),
+iConsole(aConsole)
+{
+}
+
+// ---------------------------------------------------------
+// CSocketsRead::~CSocketsRead()
+// Destructor
+// ---------------------------------------------------------
+//
+CSocketsRead::~CSocketsRead()
+{
+    Cancel();
+}
+
+// ---------------------------------------------------------
+// CSocketsRead::ConstructL()
+// EPOC two-phased constructor
+// ---------------------------------------------------------
+//
+void CSocketsRead::ConstructL()
+{
+    CActiveScheduler::Add(this);
+}
+
+
+// ---------------------------------------------------------
+// CSocketsRead::Start(TInetAddr* aAddress, TUint aProtocol)
+// Initiate a read from socket.
+// ---------------------------------------------------------
+//
+void CSocketsRead::Start(TInetAddr* aAddress, TUint aProtocol)
+{
+    iAddress = aAddress;
+    iProtocol = aProtocol;
+
+    // Initiate a new read from socket into iBuffer
+    if (!IsActive())
+    {
+        IssueRead();
+    }
+}
+
+// ---------------------------------------------------------
+// CSocketsRead::StartRAWRead()
+// Start RAW read
+// ---------------------------------------------------------
+//
+
+void CSocketsRead::StartRAWRead(TInetAddr* aAddress, TUint aProtocol)
+	{
+    iAddress = aAddress;
+    iProtocol = aProtocol;
+    iBodySize = 0; // REMEMBER TO DO THIS, OR OTHERWISE WE THINK THIS IS HTTP TRAFFIC
+    iDoPerformance = ETrue;
+	iUdpPacketCounter = 0;
+	
+    // Initiate a new read from socket into iBuffer
+    iConsole.PrintNotify(_L("Getting data...\n"));
+    iDoCount = ETrue;
+    iStartTime.UniversalTime();
+    iReceivedBytes = 0;
+    
+    if (!IsActive())
+    {
+        IssueRead();
+	}
+}
+
+
+// ---------------------------------------------------------
+// CSocketsRead::IssueRead()
+// Receive data.
+// ---------------------------------------------------------
+//
+void CSocketsRead::IssueRead()
+{
+    // Initiate a new read from socket into iBuffer
+    ASSERT(!IsActive());
+    
+    switch(iProtocol)
+    {
+    case KProtocolInetTcp:
+        iSocket.RecvOneOrMore(iBuffer, 0, iStatus, iDummyLength);
+        break;
+    case KProtocolInetUdp:
+    	iBuffer.Zero();
+        iSocket.RecvFrom(iBuffer, *iAddress, 0, iStatus/*, iDummyLength*/);
+        break;
+    }    
+    SetActive();
+}
+
+
+// ---------------------------------------------------------
+// CSocketsRead::SetPerformance(const TBool aValue)
+// Set performance calculation on/off
+// ---------------------------------------------------------
+//
+void CSocketsRead::SetPerformance(const TBool aValue)
+{
+    iDoPerformance = aValue;
+    iReceivedBytes = 0;
+    iDoCount = EFalse;
+    
+    //TInt recBuf;
+    //iSocket.SetOpt(KSORecvBuf, KSOLSocket, 200000);
+    //iSocket.GetOpt(KSORecvBuf, KSOLSocket, recBuf);
+}
+
+
+// ---------------------------------------------------------
+// CSocketsRead::RunL()
+// Called when request has completed.
+// ---------------------------------------------------------
+//
+void CSocketsRead::RunL()
+    {
+    // Active object request complete handler
+    if (iStatus == KErrNone)
+        {
+        // Character has been read from socket
+        if(iDoPerformance)
+            {
+            if(!iDoCount)
+                {
+                iHeaders.Append(iBuffer.Left(iHeaders.MaxLength() - iHeaders.Length()));
+                iHeaders.LowerCase();
+
+                TInt end = iHeaders.Find(_L8("\r\n\r\n"));
+                TInt emptyLine = iBuffer.Find(_L8("\r\n\r\n"));
+
+                if(!(end == KErrNotFound))
+                    {
+                    TInt cl = iHeaders.Find(_L8("content-length:"));
+
+                    if(!(cl == KErrNotFound))
+                        {
+                        TBuf8<512> temp;
+                        temp = iHeaders.Mid(cl, end - cl);
+
+                        TInt st = temp.Locate(':');
+                        TInt endcl = temp.Find(_L8("\r\n"));
+
+                        if ( endcl != KErrNotFound )
+                            {
+                            // not the last line in headers.
+                            temp = temp.Mid(st+1, endcl - st);                            
+                            }
+                        else
+                            {
+                            temp = temp.Mid(st+1);                            
+                            }
+                        
+                        temp.Trim();
+
+                        TLex8 lex(temp);
+                        TInt err = lex.Val(iBodySize);
+
+                        if(err == KErrNone)
+                            {
+                            iConsole.PrintNotify(_L("Getting body...\n"));
+                            iDoCount = ETrue;
+                            iStartTime.UniversalTime();
+                            iReceivedBytes = iBuffer.Length() - emptyLine - 4; 
+                            }
+                        }
+                    }
+                }
+            else
+                {          
+                iReceivedBytes += iBuffer.Length();
+                if (iProtocol == KProtocolInetUdp)
+                    {
+                    if (iUdpPacketCounter == 0)
+                        iStartTime.UniversalTime(); // Start time calculation from the first received packet.
+                    iUdpPacketCounter++;
+                    if (iUdpPacketCounter == KMaximumPacketCount)
+                        {
+                        TBuf8<128> b(_L8("Got data\n"));
+                        TInt ploss = CalculatePacketLoss();
+                        Utils::CalculateThroughput(b, iStartTime, iReceivedBytes);
+                        iEngine.Disconnect();
+                        b.AppendFormat(_L8("Ploss: %d %%\n"),ploss);
+                        iConsole.PrintNotify(b);
+                        return; // do not issue any request.
+                        }
+                    else if (iUdpPacketCounter > KMaximumPacketCount)
+                        {
+                        iConsole.PrintNotify(_L8("Unexpected state\n"));
+                        iEngine.Disconnect();
+                        iSocket.Close();
+                        return;
+                        }
+
+                    }
+                }
+
+            // Check if all the data has been received
+            if(iReceivedBytes == iBodySize)
+                {
+                // Throughput calculation
+                TBuf8<128> b(_L8("Got body\n"));
+                Utils::CalculateThroughput(b, iStartTime, iReceivedBytes);
+                iConsole.PrintNotify(b);
+                iHeaders.Zero();
+                iDoCount = EFalse;
+                }
+            }
+        else
+            {            
+            iConsole.PrintNotify(iBuffer);
+            }
+
+        IssueRead(); // Immediately start another read
+        }
+    else
+        {
+        if( iStatus.Int() == KErrEof || 
+                iStatus.Int() == KErrDisconnected || 
+                iStatus.Int() == KErrCancel )
+            {
+            TBuf<64> text(_L("HTTP Get Completed"));
+            iEngine.StopTickCount(text);
+            // Remote server closed the socket
+            if (iBodySize == 0) // We don't know how much we are expecting data so we calculate throughput here
+                {
+                iReceivedBytes += iBuffer.Length();
+                // Throughput calculation
+                TBuf8<128> b(_L8("Got body\n"));
+                Utils::CalculateThroughput(b, iStartTime, iReceivedBytes);
+                iConsole.PrintNotify(b);
+                }
+            TBuf<64> note;
+            note.Format(_L("\nSocket closed: (%d)\n"), iStatus.Int());
+            iEngine.Disconnect();
+            iConsole.PrintNotify(note);
+            }
+        else if(iStatus.Int() == KErrTimedOut)
+            {
+            // LastSocketActivityTimeout has been elapsed
+            TBuf<64> note;
+            note.Copy(_L("\nLastSocketActivityTimeOut elapsed\n\n"));
+            iEngine.Disconnect();
+            iConsole.PrintNotify(note);
+            }
+        else
+            {
+            // Error: pass it up to user interface
+            TBuf<50> err;
+            err.Format(_L("\nCSocketsRead error %d\n"), iStatus.Int());
+            iConsole.PrintNotify(err);
+            }
+        iSocket.Close();  // error is always fatal.      
+        }	
+    }
+
+// ---------------------------------------------------------
+// CSocketsRead::DoCancel()
+// Cancel ongoing requests.
+// ---------------------------------------------------------
+//
+void CSocketsRead::DoCancel()
+{
+    // Cancel asychronous read request
+    iSocket.CancelRead();
+    // If we were accepting raw UDP-traffic, we should stop and analyse.
+    if (iBodySize == 0 && iProtocol == KProtocolInetUdp && iReceivedBytes != 0)
+	{
+        TBuf8<128> b(_L8("Got body\n"));
+        Utils::CalculateThroughput(b, iStartTime, iReceivedBytes);
+        iConsole.PrintNotify(b);
+	}
+}
+
+// ---------------------------------------------------------
+// CSocketsRead::CalculatePacketLoss()
+// Calculates packet loss rate
+// @return ploss percentage
+// ---------------------------------------------------------
+//
+TInt32 CSocketsRead::CalculatePacketLoss()
+{
+	TUint32* seqNumberPointer = (TUint32*)(iBuffer.Ptr());
+	TUint32 sequenceNumberOfThisPacket = ByteOrder::Swap32( *seqNumberPointer );
+	if(sequenceNumberOfThisPacket != 0)
+	    return (100 - (100 * iUdpPacketCounter) / sequenceNumberOfThisPacket);
+	else return 100;
+}
+
+// EOF