nettools/conntest/Engine/SocketsRead.cpp
changeset 0 857a3e953887
equal deleted inserted replaced
-1:000000000000 0:857a3e953887
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: CSocketsRead is an active obejct that reads data from
       
    15 * an already open socket and calculates some metrics from the data read
       
    16 *
       
    17 */
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "SocketsRead.h"
       
    21 #include "SocketsEngine.h"
       
    22 #include "uinotify.h"
       
    23 #include "Utils.h"
       
    24 
       
    25 
       
    26 // ---------------------------------------------------------
       
    27 // CSocketsRead::NewL(MUINotify& aConsole, RSocket& aSocket)
       
    28 // EPOC two phased constructor
       
    29 // ---------------------------------------------------------
       
    30 //
       
    31 CSocketsRead* CSocketsRead::NewL(MUINotify& aConsole, RSocket& aSocket, CSocketsEngine& aEngine)
       
    32 {
       
    33     CSocketsRead* self = CSocketsRead::NewLC(aConsole, aSocket, aEngine);
       
    34     CleanupStack::Pop(self);
       
    35     return self;
       
    36 }
       
    37 
       
    38 // ---------------------------------------------------------
       
    39 // CSocketsRead::NewLC(MUINotify& aConsole, RSocket& aSocket)
       
    40 // EPOC two phased constructor
       
    41 // ---------------------------------------------------------
       
    42 //
       
    43 CSocketsRead* CSocketsRead::NewLC(MUINotify& aConsole, RSocket& aSocket, CSocketsEngine& aEngine)
       
    44 {
       
    45     CSocketsRead* self = new (ELeave) CSocketsRead(aConsole, aSocket, aEngine);
       
    46     CleanupStack::PushL(self);
       
    47     self->ConstructL();
       
    48     return self;
       
    49 }
       
    50 
       
    51 // ---------------------------------------------------------
       
    52 // CSocketsRead::CSocketsRead(MUINotify& aConsole, RSocket& aSocket)
       
    53 // Constructor
       
    54 // ---------------------------------------------------------
       
    55 //
       
    56 CSocketsRead::CSocketsRead(MUINotify& aConsole, RSocket& aSocket, CSocketsEngine& aEngine)
       
    57 : CActive(/*EPriorityStandard*/EPriorityHigh),
       
    58 iEngine(aEngine),
       
    59 iSocket(aSocket),
       
    60 iConsole(aConsole)
       
    61 {
       
    62 }
       
    63 
       
    64 // ---------------------------------------------------------
       
    65 // CSocketsRead::~CSocketsRead()
       
    66 // Destructor
       
    67 // ---------------------------------------------------------
       
    68 //
       
    69 CSocketsRead::~CSocketsRead()
       
    70 {
       
    71     Cancel();
       
    72 }
       
    73 
       
    74 // ---------------------------------------------------------
       
    75 // CSocketsRead::ConstructL()
       
    76 // EPOC two-phased constructor
       
    77 // ---------------------------------------------------------
       
    78 //
       
    79 void CSocketsRead::ConstructL()
       
    80 {
       
    81     CActiveScheduler::Add(this);
       
    82 }
       
    83 
       
    84 
       
    85 // ---------------------------------------------------------
       
    86 // CSocketsRead::Start(TInetAddr* aAddress, TUint aProtocol)
       
    87 // Initiate a read from socket.
       
    88 // ---------------------------------------------------------
       
    89 //
       
    90 void CSocketsRead::Start(TInetAddr* aAddress, TUint aProtocol)
       
    91 {
       
    92     iAddress = aAddress;
       
    93     iProtocol = aProtocol;
       
    94 
       
    95     // Initiate a new read from socket into iBuffer
       
    96     if (!IsActive())
       
    97     {
       
    98         IssueRead();
       
    99     }
       
   100 }
       
   101 
       
   102 // ---------------------------------------------------------
       
   103 // CSocketsRead::StartRAWRead()
       
   104 // Start RAW read
       
   105 // ---------------------------------------------------------
       
   106 //
       
   107 
       
   108 void CSocketsRead::StartRAWRead(TInetAddr* aAddress, TUint aProtocol)
       
   109 	{
       
   110     iAddress = aAddress;
       
   111     iProtocol = aProtocol;
       
   112     iBodySize = 0; // REMEMBER TO DO THIS, OR OTHERWISE WE THINK THIS IS HTTP TRAFFIC
       
   113     iDoPerformance = ETrue;
       
   114 	iUdpPacketCounter = 0;
       
   115 	
       
   116     // Initiate a new read from socket into iBuffer
       
   117     iConsole.PrintNotify(_L("Getting data...\n"));
       
   118     iDoCount = ETrue;
       
   119     iStartTime.UniversalTime();
       
   120     iReceivedBytes = 0;
       
   121     
       
   122     if (!IsActive())
       
   123     {
       
   124         IssueRead();
       
   125 	}
       
   126 }
       
   127 
       
   128 
       
   129 // ---------------------------------------------------------
       
   130 // CSocketsRead::IssueRead()
       
   131 // Receive data.
       
   132 // ---------------------------------------------------------
       
   133 //
       
   134 void CSocketsRead::IssueRead()
       
   135 {
       
   136     // Initiate a new read from socket into iBuffer
       
   137     ASSERT(!IsActive());
       
   138     
       
   139     switch(iProtocol)
       
   140     {
       
   141     case KProtocolInetTcp:
       
   142         iSocket.RecvOneOrMore(iBuffer, 0, iStatus, iDummyLength);
       
   143         break;
       
   144     case KProtocolInetUdp:
       
   145     	iBuffer.Zero();
       
   146         iSocket.RecvFrom(iBuffer, *iAddress, 0, iStatus/*, iDummyLength*/);
       
   147         break;
       
   148     }    
       
   149     SetActive();
       
   150 }
       
   151 
       
   152 
       
   153 // ---------------------------------------------------------
       
   154 // CSocketsRead::SetPerformance(const TBool aValue)
       
   155 // Set performance calculation on/off
       
   156 // ---------------------------------------------------------
       
   157 //
       
   158 void CSocketsRead::SetPerformance(const TBool aValue)
       
   159 {
       
   160     iDoPerformance = aValue;
       
   161     iReceivedBytes = 0;
       
   162     iDoCount = EFalse;
       
   163     
       
   164     //TInt recBuf;
       
   165     //iSocket.SetOpt(KSORecvBuf, KSOLSocket, 200000);
       
   166     //iSocket.GetOpt(KSORecvBuf, KSOLSocket, recBuf);
       
   167 }
       
   168 
       
   169 
       
   170 // ---------------------------------------------------------
       
   171 // CSocketsRead::RunL()
       
   172 // Called when request has completed.
       
   173 // ---------------------------------------------------------
       
   174 //
       
   175 void CSocketsRead::RunL()
       
   176     {
       
   177     // Active object request complete handler
       
   178     if (iStatus == KErrNone)
       
   179         {
       
   180         // Character has been read from socket
       
   181         if(iDoPerformance)
       
   182             {
       
   183             if(!iDoCount)
       
   184                 {
       
   185                 iHeaders.Append(iBuffer.Left(iHeaders.MaxLength() - iHeaders.Length()));
       
   186                 iHeaders.LowerCase();
       
   187 
       
   188                 TInt end = iHeaders.Find(_L8("\r\n\r\n"));
       
   189                 TInt emptyLine = iBuffer.Find(_L8("\r\n\r\n"));
       
   190 
       
   191                 if(!(end == KErrNotFound))
       
   192                     {
       
   193                     TInt cl = iHeaders.Find(_L8("content-length:"));
       
   194 
       
   195                     if(!(cl == KErrNotFound))
       
   196                         {
       
   197                         TBuf8<512> temp;
       
   198                         temp = iHeaders.Mid(cl, end - cl);
       
   199 
       
   200                         TInt st = temp.Locate(':');
       
   201                         TInt endcl = temp.Find(_L8("\r\n"));
       
   202 
       
   203                         if ( endcl != KErrNotFound )
       
   204                             {
       
   205                             // not the last line in headers.
       
   206                             temp = temp.Mid(st+1, endcl - st);                            
       
   207                             }
       
   208                         else
       
   209                             {
       
   210                             temp = temp.Mid(st+1);                            
       
   211                             }
       
   212                         
       
   213                         temp.Trim();
       
   214 
       
   215                         TLex8 lex(temp);
       
   216                         TInt err = lex.Val(iBodySize);
       
   217 
       
   218                         if(err == KErrNone)
       
   219                             {
       
   220                             iConsole.PrintNotify(_L("Getting body...\n"));
       
   221                             iDoCount = ETrue;
       
   222                             iStartTime.UniversalTime();
       
   223                             iReceivedBytes = iBuffer.Length() - emptyLine - 4; 
       
   224                             }
       
   225                         }
       
   226                     }
       
   227                 }
       
   228             else
       
   229                 {          
       
   230                 iReceivedBytes += iBuffer.Length();
       
   231                 if (iProtocol == KProtocolInetUdp)
       
   232                     {
       
   233                     if (iUdpPacketCounter == 0)
       
   234                         iStartTime.UniversalTime(); // Start time calculation from the first received packet.
       
   235                     iUdpPacketCounter++;
       
   236                     if (iUdpPacketCounter == KMaximumPacketCount)
       
   237                         {
       
   238                         TBuf8<128> b(_L8("Got data\n"));
       
   239                         TInt ploss = CalculatePacketLoss();
       
   240                         Utils::CalculateThroughput(b, iStartTime, iReceivedBytes);
       
   241                         iEngine.Disconnect();
       
   242                         b.AppendFormat(_L8("Ploss: %d %%\n"),ploss);
       
   243                         iConsole.PrintNotify(b);
       
   244                         return; // do not issue any request.
       
   245                         }
       
   246                     else if (iUdpPacketCounter > KMaximumPacketCount)
       
   247                         {
       
   248                         iConsole.PrintNotify(_L8("Unexpected state\n"));
       
   249                         iEngine.Disconnect();
       
   250                         iSocket.Close();
       
   251                         return;
       
   252                         }
       
   253 
       
   254                     }
       
   255                 }
       
   256 
       
   257             // Check if all the data has been received
       
   258             if(iReceivedBytes == iBodySize)
       
   259                 {
       
   260                 // Throughput calculation
       
   261                 TBuf8<128> b(_L8("Got body\n"));
       
   262                 Utils::CalculateThroughput(b, iStartTime, iReceivedBytes);
       
   263                 iConsole.PrintNotify(b);
       
   264                 iHeaders.Zero();
       
   265                 iDoCount = EFalse;
       
   266                 }
       
   267             }
       
   268         else
       
   269             {            
       
   270             iConsole.PrintNotify(iBuffer);
       
   271             }
       
   272 
       
   273         IssueRead(); // Immediately start another read
       
   274         }
       
   275     else
       
   276         {
       
   277         if( iStatus.Int() == KErrEof || 
       
   278                 iStatus.Int() == KErrDisconnected || 
       
   279                 iStatus.Int() == KErrCancel )
       
   280             {
       
   281             TBuf<64> text(_L("HTTP Get Completed"));
       
   282             iEngine.StopTickCount(text);
       
   283             // Remote server closed the socket
       
   284             if (iBodySize == 0) // We don't know how much we are expecting data so we calculate throughput here
       
   285                 {
       
   286                 iReceivedBytes += iBuffer.Length();
       
   287                 // Throughput calculation
       
   288                 TBuf8<128> b(_L8("Got body\n"));
       
   289                 Utils::CalculateThroughput(b, iStartTime, iReceivedBytes);
       
   290                 iConsole.PrintNotify(b);
       
   291                 }
       
   292             TBuf<64> note;
       
   293             note.Format(_L("\nSocket closed: (%d)\n"), iStatus.Int());
       
   294             iEngine.Disconnect();
       
   295             iConsole.PrintNotify(note);
       
   296             }
       
   297         else if(iStatus.Int() == KErrTimedOut)
       
   298             {
       
   299             // LastSocketActivityTimeout has been elapsed
       
   300             TBuf<64> note;
       
   301             note.Copy(_L("\nLastSocketActivityTimeOut elapsed\n\n"));
       
   302             iEngine.Disconnect();
       
   303             iConsole.PrintNotify(note);
       
   304             }
       
   305         else
       
   306             {
       
   307             // Error: pass it up to user interface
       
   308             TBuf<50> err;
       
   309             err.Format(_L("\nCSocketsRead error %d\n"), iStatus.Int());
       
   310             iConsole.PrintNotify(err);
       
   311             }
       
   312         iSocket.Close();  // error is always fatal.      
       
   313         }	
       
   314     }
       
   315 
       
   316 // ---------------------------------------------------------
       
   317 // CSocketsRead::DoCancel()
       
   318 // Cancel ongoing requests.
       
   319 // ---------------------------------------------------------
       
   320 //
       
   321 void CSocketsRead::DoCancel()
       
   322 {
       
   323     // Cancel asychronous read request
       
   324     iSocket.CancelRead();
       
   325     // If we were accepting raw UDP-traffic, we should stop and analyse.
       
   326     if (iBodySize == 0 && iProtocol == KProtocolInetUdp && iReceivedBytes != 0)
       
   327 	{
       
   328         TBuf8<128> b(_L8("Got body\n"));
       
   329         Utils::CalculateThroughput(b, iStartTime, iReceivedBytes);
       
   330         iConsole.PrintNotify(b);
       
   331 	}
       
   332 }
       
   333 
       
   334 // ---------------------------------------------------------
       
   335 // CSocketsRead::CalculatePacketLoss()
       
   336 // Calculates packet loss rate
       
   337 // @return ploss percentage
       
   338 // ---------------------------------------------------------
       
   339 //
       
   340 TInt32 CSocketsRead::CalculatePacketLoss()
       
   341 {
       
   342 	TUint32* seqNumberPointer = (TUint32*)(iBuffer.Ptr());
       
   343 	TUint32 sequenceNumberOfThisPacket = ByteOrder::Swap32( *seqNumberPointer );
       
   344 	if(sequenceNumberOfThisPacket != 0)
       
   345 	    return (100 - (100 * iUdpPacketCounter) / sequenceNumberOfThisPacket);
       
   346 	else return 100;
       
   347 }
       
   348 
       
   349 // EOF