nettools/conntest/Engine/SocketsWrite.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: CSocketsWrite is an active object which implements data
       
    15  * sending through an already open socket using UDP or TCP
       
    16  *
       
    17  */
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <e32svr.h>
       
    21 
       
    22 #include "SocketsWrite.h"
       
    23 #include "TimeOutTimer.h"
       
    24 #include "ConnTest.pan"
       
    25 #include "uinotify.h"
       
    26 #include "Utils.h"
       
    27 #include "conntest.hrh"
       
    28 #include "datasendnotifyhandler.h"
       
    29 
       
    30 // CONSTANTS
       
    31 static const TInt KTimeOut = 30000000; // 30 seconds time-out
       
    32 
       
    33 
       
    34 // ---------------------------------------------------------
       
    35 // CSocketsWrite::NewL(MUINotify& aConsole, RSocket& aSocket, MDataSendNotifyHandler& aSendHandler)
       
    36 // EPOC two phased constructor
       
    37 // ---------------------------------------------------------
       
    38 //
       
    39 CSocketsWrite* CSocketsWrite::NewL( MUINotify& aConsole, 
       
    40         RSocket& aSocket, 
       
    41         MDataSendNotifyHandler& aSendHandler )
       
    42     {
       
    43     CSocketsWrite* self = CSocketsWrite::NewLC(aConsole, aSocket, aSendHandler);
       
    44     CleanupStack::Pop(self);
       
    45     return self;
       
    46     }
       
    47 
       
    48 
       
    49 // ---------------------------------------------------------
       
    50 // CSocketsWrite::NewLC(MUINotify& aConsole, RSocket& aSocket, MDataSendNotifyHandler& aSendHandler)
       
    51 // EPOC two phased constructor
       
    52 // ---------------------------------------------------------
       
    53 //
       
    54 CSocketsWrite* CSocketsWrite::NewLC( MUINotify& aConsole, 
       
    55         RSocket& aSocket, 
       
    56         MDataSendNotifyHandler& aSendHandler )
       
    57     {
       
    58     CSocketsWrite* self = new (ELeave) CSocketsWrite(aConsole, aSocket, aSendHandler);
       
    59     CleanupStack::PushL(self);
       
    60     self->ConstructL();
       
    61     return self;
       
    62     }
       
    63 
       
    64 
       
    65 // ---------------------------------------------------------
       
    66 // CSocketsWrite::CSocketsWrite(MUINotify& aConsole, RSocket& aSocket, MDataSendNotifyHandler& aSendHandler)
       
    67 // Constructor
       
    68 // ---------------------------------------------------------
       
    69 //
       
    70 CSocketsWrite::CSocketsWrite( MUINotify& aConsole, 
       
    71         RSocket& aSocket, 
       
    72         MDataSendNotifyHandler& aSendHandler ):
       
    73         CActive(EPriorityStandard),
       
    74         iSocket(aSocket),
       
    75         iConsole(aConsole),
       
    76         iPackets(0),
       
    77         iPacketSize(0),
       
    78         iReqBodySubmitBufferPtr(0,0),
       
    79         iSendHandler(aSendHandler)
       
    80     {
       
    81     }
       
    82 
       
    83 
       
    84 // ---------------------------------------------------------
       
    85 // CSocketsWrite::~CSocketsWrite()
       
    86 // Destructor
       
    87 // ---------------------------------------------------------
       
    88 //
       
    89 CSocketsWrite::~CSocketsWrite()
       
    90     {
       
    91     Cancel();
       
    92     delete iReqBodySubmitBuffer;
       
    93     delete iTimer;
       
    94     iTimer = NULL;
       
    95     if(iTransferBuffer)
       
    96         {
       
    97         delete iTransferBuffer;
       
    98         iTransferBuffer = NULL;
       
    99         }
       
   100     if(iWriteBuffer)
       
   101         {
       
   102         delete iWriteBuffer;
       
   103         iWriteBuffer = NULL;
       
   104         }
       
   105     }
       
   106 
       
   107 
       
   108 // ---------------------------------------------------------
       
   109 // CSocketsWrite::ConstructL()
       
   110 // EPOC two-phased constructor
       
   111 // ---------------------------------------------------------
       
   112 //
       
   113 void CSocketsWrite::ConstructL()
       
   114     {
       
   115     CActiveScheduler::Add(this);
       
   116 
       
   117     iTransferBuffer = HBufC8::NewL(KMaxSendBuffer);
       
   118     iWriteBuffer = HBufC8::NewL(KMaxSendBuffer);
       
   119 
       
   120     iTimeOut = KTimeOut; 
       
   121     iTimer = CTimeOutTimer::NewL(10, *this);
       
   122     iWriteStatus = EWaiting;
       
   123     }
       
   124 
       
   125 
       
   126 // ---------------------------------------------------------
       
   127 // CSocketsWrite::RunL()
       
   128 // Called when request has completed.
       
   129 // ---------------------------------------------------------
       
   130 //
       
   131 void CSocketsWrite::RunL()
       
   132     {
       
   133     if(!iFlood)
       
   134         {   
       
   135         RDebug::Print(_L("ConnTest: CSocketsWrite::RunL - iStatus = %d"), iStatus.Int());
       
   136         }
       
   137     // Active object request complete handler
       
   138     if (iStatus == KErrNone)
       
   139         {
       
   140         switch(iWriteStatus)
       
   141             {
       
   142             // Character has been written to socket
       
   143             case ESending:
       
   144                 if(!iFlood)
       
   145                     SendNextPacket();
       
   146                 else
       
   147                     DoFloodWrite();
       
   148                 break;
       
   149             default:
       
   150                 User::Panic(KPanicSocketsWrite, EConnTestBadStatus);
       
   151                 break;
       
   152             };
       
   153         }
       
   154     else 
       
   155         {
       
   156         // Error: pass it up to user interface
       
   157         iTimer->Cancel();
       
   158         TBuf<50> err;
       
   159         err.Format(_L("\nCSocketsWrite error %d\n"), iStatus.Int());
       
   160         //iConsole.ErrorNotify(_L("\nCSocketsWrite error"), iStatus.Int());
       
   161         iConsole.PrintNotify(err);
       
   162         iWriteStatus = ECommsFailed;
       
   163         }
       
   164     }
       
   165 
       
   166 
       
   167 // ---------------------------------------------------------
       
   168 // CSocketsWrite::DoCancel()
       
   169 // Cancel ongoing requests.
       
   170 // ---------------------------------------------------------
       
   171 //
       
   172 void CSocketsWrite::DoCancel()
       
   173     {	
       
   174     RDebug::Print(_L("CSocketsWrite::DoCancel"));
       
   175 
       
   176     // Cancel asychronous write request
       
   177     iSocket.CancelWrite();
       
   178 
       
   179     iTimer->Cancel();
       
   180     }
       
   181 
       
   182 
       
   183 // ---------------------------------------------------------
       
   184 // CSocketsWrite::IssueWriteL()
       
   185 // Add data into buffer for sending.
       
   186 // ---------------------------------------------------------
       
   187 //
       
   188 void CSocketsWrite::IssueWriteL(const TDesC8& aData, TInetAddr* aAddress, TUint aProtocol)
       
   189     {
       
   190     RDebug::Print(_L("ConnTest: CSocketsWrite::IssueWriteL - aData.Length = %d"), aData.Length());
       
   191 
       
   192     iFlood = EFalse;
       
   193     iAddress = aAddress;
       
   194     iProtocol = aProtocol;
       
   195 
       
   196     // Write data to a stream socket
       
   197     if ((aData.Length() + iTransferBuffer->Length()) > iTransferBuffer->Des().MaxLength())
       
   198         {
       
   199         RDebug::Print(_L("ConnTest: CSocketsWrite::IssueWriteL - data doesn't fit in the transferbuffer"));
       
   200         RDebug::Print( _L( 
       
   201                 "ConnTest: CSocketsWrite::IssueWriteL - data length = %d, buffer length = %d, buffer max length = %d"),
       
   202                 aData.Length(), iTransferBuffer->Length(), iTransferBuffer->Des().MaxLength() );
       
   203         // Not enough space in buffer
       
   204         User::Leave(KErrOverflow);
       
   205         }
       
   206 
       
   207     // Add new data to buffer
       
   208     iTransferBuffer->Des().Append(aData);
       
   209 
       
   210     if (!IsActive())
       
   211         {
       
   212         SendNextPacket();
       
   213         }
       
   214     }
       
   215 
       
   216 // ---------------------------------------------------------
       
   217 // CSocketsWrite::IssueWriteL()
       
   218 // Flood data over socket
       
   219 // ---------------------------------------------------------
       
   220 //
       
   221 void CSocketsWrite::IssueWriteL( const TDesC8& aData, 
       
   222         TInetAddr* aAddress, 
       
   223         TUint aProtocol, 
       
   224         TInt aCount )
       
   225     {
       
   226     RDebug::Print(_L("ConnTest: CSocketsWrite::IssueWriteL - flood, packet count=%d"), aCount);
       
   227     RDebug::Print(_L("ConnTest: CSocketsWrite::IssueWriteL - aData.Length = %d"), aData.Length());
       
   228     iFlood = ETrue;
       
   229     iCount = 0;
       
   230     iPackets = aCount;
       
   231     iPacketSize = aData.Length();
       
   232 
       
   233     iAddress = aAddress;
       
   234     iProtocol = aProtocol;
       
   235 
       
   236     // Write data to a stream socket
       
   237     if (aData.Length() > iTransferBuffer->Des().MaxLength())
       
   238         {
       
   239         // Not enough space in buffer
       
   240         User::Leave(KErrOverflow);
       
   241         }
       
   242 
       
   243     // Add new data to buffer
       
   244     iTransferBuffer->Des().Zero();
       
   245     iTransferBuffer->Des().Append(aData);
       
   246     iWriteBuffer->Des().Copy(*iTransferBuffer);
       
   247     if (!IsActive())
       
   248         {
       
   249         DoFloodWrite();
       
   250         }
       
   251     }
       
   252 
       
   253 // -------------------------------------------------------------------------
       
   254 // CSocketsWrite::IssueWriteL()
       
   255 // Add data into buffer for sending POST request, initializes body data.
       
   256 // -------------------------------------------------------------------------
       
   257 //
       
   258 void CSocketsWrite::IssueWriteL( const TDesC8& aData, 
       
   259         TInetAddr* aAddress, 
       
   260         TUint aProtocol, 
       
   261         TInt aPacketSize, 
       
   262         TInt aPackets )
       
   263     {
       
   264     RDebug::Print(_L("ConnTest: CSocketsWrite::IssueWriteL - aData.Length = %d"), aData.Length());
       
   265     iFlood = EFalse;
       
   266 
       
   267     iPackets = aPackets;
       
   268     iPacketSize = aPacketSize;
       
   269 
       
   270     delete iReqBodySubmitBuffer;
       
   271     iReqBodySubmitBuffer = NULL;
       
   272     iReqBodySubmitBuffer = HBufC8::NewMaxL(KSendDataSize);
       
   273     iReqBodySubmitBufferPtr.Set(iReqBodySubmitBuffer->Des());
       
   274 
       
   275     // Create body chunk
       
   276     Utils::CreateDataChunk(iReqBodySubmitBufferPtr, iPacketSize);
       
   277     iDataChunkCount = 0;
       
   278 
       
   279     IssueWriteL(aData, aAddress, aProtocol);
       
   280     }
       
   281 
       
   282 // ---------------------------------------------------------
       
   283 // CSocketsWrite::SendNextPacket()
       
   284 // Write data from buffer to socket.
       
   285 // ---------------------------------------------------------
       
   286 //
       
   287 void CSocketsWrite::SendNextPacket()
       
   288     {
       
   289     RDebug::Print(_L("ConnTest: CSocketsWrite::SendNextPacket - iTransferBuffer.Length = %d, iPackets = %d"), iTransferBuffer->Length(), iPackets);
       
   290 
       
   291     iTimer->Cancel(); // Cancel TimeOut timer
       
   292     iWriteStatus = EWaiting;
       
   293 
       
   294     if (iTransferBuffer->Length() > 0)
       
   295         {
       
   296         // Move data from transfer buffer to actual write buffer
       
   297         iWriteBuffer->Des().Copy(*iTransferBuffer);
       
   298         iTransferBuffer->Des().Zero();
       
   299 
       
   300         switch(iProtocol)
       
   301             {
       
   302             case KProtocolInetTcp:
       
   303                 iSocket.Write(*iWriteBuffer, iStatus); // Initiate actual write
       
   304                 break;
       
   305 
       
   306             case KProtocolInetUdp:
       
   307                 iSocket.SendTo(*iWriteBuffer, *iAddress, 0, iStatus);
       
   308                 break;
       
   309             }
       
   310         iSendHandler.NotifySend(iWriteBuffer->Length());
       
   311         // Request timeout
       
   312         iTimer->After(iTimeOut);
       
   313         SetActive();
       
   314         iWriteStatus = ESending;
       
   315         }
       
   316     else if(iPackets)
       
   317         {
       
   318         // We are sending body data, i.e. this is POST request
       
   319         if(iDataChunkCount == 0)
       
   320             {
       
   321             iConsole.PrintNotify(_L("Sending body...\n"));
       
   322             iSentBytes = 0;
       
   323             iStartTime.UniversalTime();
       
   324             }
       
   325 
       
   326         TBool noMoreData = iDataChunkCount < iPackets ? EFalse : ETrue;
       
   327         ++iDataChunkCount;
       
   328 
       
   329         if(noMoreData)
       
   330             {
       
   331             // Throughput calculation
       
   332             TBuf8<128> b(_L8("Body sent\n"));
       
   333             Utils::CalculateThroughput(b, iStartTime, iSentBytes);
       
   334 
       
   335             b.Append(_L("\n\n"));
       
   336             iConsole.PrintNotify(b);
       
   337 
       
   338             iPackets = 0;
       
   339             iPacketSize = 0;
       
   340             iSentBytes = 0;
       
   341 
       
   342             return;
       
   343             }
       
   344 
       
   345         iSentBytes += iReqBodySubmitBufferPtr.Length();
       
   346         iSocket.Write(iReqBodySubmitBufferPtr, iStatus); 
       
   347         SetActive();
       
   348         iWriteStatus = ESending;
       
   349 
       
   350         }
       
   351     }
       
   352 
       
   353 // ---------------------------------------------------------
       
   354 // CSocketsWrite::DoFloodWrite()
       
   355 // Floods the data to the socket
       
   356 // ---------------------------------------------------------
       
   357 //
       
   358 void CSocketsWrite::DoFloodWrite()
       
   359     {
       
   360     //RDebug::Print(_L("ConnTest: CSocketsWrite::DoFloodWrite: %d"),iCount); // eats CPU
       
   361     iTimer->Cancel(); // Cancel TimeOut timer
       
   362     iWriteStatus = EWaiting;
       
   363     if (iCount != iPackets)
       
   364         {
       
   365         if( iTransferBuffer->Length() > 0)
       
   366             {
       
   367             switch(iProtocol)
       
   368                 {
       
   369                 case KProtocolInetTcp:
       
   370                     iSocket.Write(*iWriteBuffer, iStatus); // Initiate actual write
       
   371                     break;
       
   372 
       
   373                 case KProtocolInetUdp:
       
   374                     {
       
   375                     TUint32* seqNumberPointer = (TUint32*)(iTransferBuffer->Des().Ptr());
       
   376                     *seqNumberPointer = ByteOrder::Swap32( iCount ); // put sequence number into to the packet
       
   377                     iSocket.SendTo(*iTransferBuffer, *iAddress, 0, iStatus);
       
   378                     break;
       
   379                     }
       
   380                 default:
       
   381                     iConsole.ErrorNotify(_L("Unsupproted protocol\n\n"),KErrNotSupported );
       
   382                     return;
       
   383                 }
       
   384 
       
   385             iCount++;
       
   386             iTimer->After(iTimeOut);
       
   387             SetActive();
       
   388             iWriteStatus = ESending;
       
   389             }
       
   390         }
       
   391     else
       
   392         {
       
   393         iTransferBuffer->Des().Zero();
       
   394         iWriteBuffer->Des().Zero();
       
   395         iSendHandler.NotifySend(iPacketSize*iPackets);   
       
   396         iFlood = EFalse;
       
   397         iCount = 0;
       
   398         iPackets = 0;
       
   399         iPacketSize = 0; 	    
       
   400         }
       
   401     }
       
   402 
       
   403 // ---------------------------------------------------------
       
   404 // CSocketsWrite::TimerExpired()
       
   405 // Timeout, show error notification.
       
   406 // ---------------------------------------------------------
       
   407 //
       
   408 void CSocketsWrite::TimerExpired()
       
   409     {
       
   410     Cancel();
       
   411     iWriteStatus = ECommsFailed;
       
   412     iConsole.ErrorNotify(_L("Write operation timed out\n"), KErrTimedOut);
       
   413     }
       
   414