--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wlanapitest/wlanhaitest/wlan/src/T_RSocketData.cpp Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,1359 @@
+/*
+* Copyright (c) 2005-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 <wlanscaninfo.h>
+#include "t_rsocketdata.h"
+
+/*@{*/
+// LITs from the ini file
+_LIT( KSocketServ, "socketserv");
+_LIT( KConnection, "connection");
+_LIT( KScanInfo, "scaninfo");
+_LIT( KAddress, "Ip");
+_LIT( KPort, "Port");
+_LIT( KFile, "File");
+_LIT( KSave, "Save");
+_LIT( KARates, "rate");
+_LIT( KFileServer, "FileServer");
+/*@}*/
+
+/*@{*/
+// Upload
+_LIT(KNullFile, "KNullDesC");
+/*@}*/
+
+/*@{*/
+// LITs for the commands
+_LIT( KCmdOpen, "Open");
+_LIT( KCmdConnect, "Connect");
+_LIT( KCmdHttpGet, "HttpGet");
+_LIT( KCmdDownloadSendHTTPGet, "DownloadSendHTTPGet");
+_LIT( KCmdRecvOneOrMore, "RecvOneOrMore");
+_LIT( KCmdUploadSendHTTPPost, "UploadSendHTTPPost");
+_LIT( KCmdCheckSupportedRates, "CheckSupportedRates");
+_LIT( KCmdShutdown, "Shutdown");
+_LIT( KCmdClose, "Close");
+/*@}*/
+
+/*@{*/
+// Constants for creating a HTTP request in the command DoCmdDownloadSendHTTPGet
+_LIT8( KHTTPGET, "GET");
+_LIT8( KHTTPSeparator, " ");
+_LIT8( KHTTPSuffix, "HTTP/1.1");
+_LIT( KHostS, "Host");
+_LIT8( KLineFeed, "\r\n");
+_LIT8( KEmptyLine, "\r\n\r\n");
+_LIT8( KHeaderEndMark, "\r\n\r\n" );
+_LIT8( KContentLengthField, "Content-Length: ");
+_LIT8( KFieldEnd, "\r\n" );
+_LIT8( KGETHTTP, "GET / HTTP/1.0\r\n\r\n" );
+/*@}*/
+
+/*@{*/
+// Constants for CreateHTTPHeaderStart
+_LIT8(KHTTPPOST, "POST");
+_LIT8(KLineBreak, "\r\n");
+_LIT(KClientID, "clientID");
+_LIT(KServerScript, "serverScript");
+_LIT8(KFrom, "From:");
+_LIT8(KHosts, "Host:");
+_LIT8(KContentType, "Content-Type:");
+_LIT8(KContentLength, "Content-Length:");
+_LIT8(KContentDisposition, "Content-Disposition:");
+_LIT8(KMultipartType, "multipart/form-data;");
+_LIT8(KOctetType, "application/octet-stream");
+_LIT8(KBoundary, "boundary=---------------------------sg976436h73");
+_LIT8(KBoundaryStart, "-----------------------------sg976436h73");
+_LIT8(KDisposition, "form-data; name=\"userfile\"; filename=");
+_LIT8(KBackS, "\"");
+_LIT8(KBoundaryEnd, "-----------------------------sg976436h73--");
+/*@}*/
+
+
+const TInt KHttpHeaderBufferIncrement = 4096;
+// Const for supported rates
+// The first bit includes information about BSSBasicRateSet,
+// mask it out
+
+const TUint32 KBasicRateMask = 0x7F;
+// 802.11g supported speed rate
+const TUint8 K80211Rate1Mbit = 2;
+const TUint8 K80211Rate2Mbit = 4;
+const TUint8 K80211Rate5Mbit = 11;
+const TUint8 K80211Rate11Mbit = 22;
+const TUint8 K80211Rate12Mbit = 24;
+const TUint8 K80211Rate18Mbit = 36;
+const TUint8 K80211Rate22Mbit = 44;
+const TUint8 K80211Rate24Mbit = 48;
+const TUint8 K80211Rate33Mbit = 66;
+const TUint8 K80211Rate36Mbit = 72;
+const TUint8 K80211Rate48Mbit = 96;
+const TUint8 K80211Rate54Mbit = 108;
+
+
+
+
+
+
+
+/**
+ * Two phase constructor
+ *
+ * @leave system wide error
+ */
+CT_RSocketData* CT_RSocketData::NewL()
+ {
+ CT_RSocketData * ret = new (ELeave)CT_RSocketData();
+ CleanupStack::PushL(ret);
+ ret->ConstructL();
+ CleanupStack::Pop(ret);
+ return ret;
+ }
+
+/*
+ *RunL method for management Active callbacks
+ * @param aActive param to review which active call back is being fished
+ * @param aIndex
+ * @return void
+ */
+void CT_RSocketData::RunL(CActive* aActive, TInt /*aIndex*/)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::RunL"));
+ DecOutstanding(); // One of the async calls has completed
+ TInt err(KErrNone);
+ if(aActive == iActiveCallback)
+ {
+ INFO_PRINTF1(_L("active call back for Write Socket."));
+ err = iActiveCallback->iStatus.Int();
+ if(err != KErrNone)
+ {
+ ERR_PRINTF1(_L("iSocket->Write(...) Fail"));
+ SetError(err);
+ }
+ else
+ {
+ INFO_PRINTF2(_L("CT_RSocketData::SendHTTPGet [%d]"), iActiveCallback->iStatus.Int());
+ INFO_PRINTF1(_L("Asynchronous task has completed. RunL called"));
+ }
+ }
+ else if(aActive == iActCallConnectSocket)
+ {
+ INFO_PRINTF1(_L("active call back for Connect Socket."));
+ err = iActCallConnectSocket->iStatus.Int();
+ if(err != KErrNone)
+ {
+ ERR_PRINTF1(_L("iSocket->Connect(...) Fail"));
+ SetError(err);
+ }
+ else
+ {
+ INFO_PRINTF1(_L("CT_RSocketData::DoCmdConnect(...) success"));
+ iSocketOpened = ETrue;
+ }
+ }
+ else if(aActive == iActCallShutDownSocket)
+ {
+ INFO_PRINTF1(_L("active call back for Shutdown Socket."));
+ err = iActCallShutDownSocket->iStatus.Int();
+ if(err != KErrNone)
+ {
+ ERR_PRINTF2(_L("iSocket->Shutdown(...): [%d] Fail"),iActCallShutDownSocket->iStatus.Int());
+ SetError(err);
+ }
+ else
+ {
+ INFO_PRINTF1(_L("CT_RSocketData::Shutdown success"));
+ iSocketStarted = EFalse;
+ }
+ }
+ else
+ {
+ ERR_PRINTF1(_L("An unchecked active object completed"));
+ SetBlockResult(EFail);
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::RunL"));
+ }
+/*
+ * public destructor
+ */
+CT_RSocketData::~CT_RSocketData()
+ {
+ if (iSocketStarted)
+ {
+ INFO_PRINTF1(_L("CT_RSocketData: Shutting down socket"));
+ Shutdown();
+ }
+ if (iSocketOpened)
+ {
+ Close();
+ }
+ if (iDownloadBuffer)
+ {
+ delete iDownloadBuffer;
+ iDownloadBuffer = NULL;
+ }
+ if (iSocket)
+ {
+ delete iSocket;
+ iSocket = NULL;
+ }
+ if (iActiveCallback)
+ {
+ delete iActiveCallback;
+ iActiveCallback = NULL;
+ }
+ if (iActCallShutDownSocket)
+ {
+ delete iActCallShutDownSocket;
+ iActCallShutDownSocket = NULL;
+ }
+ if (iActCallConnectSocket)
+ {
+ delete iActCallConnectSocket;
+ iActCallConnectSocket = NULL;
+ }
+
+ iFs.Close();
+
+ if (iUploadBuffer)
+ {
+ delete iUploadBuffer;
+ iUploadBuffer = NULL;
+ }
+ }
+
+/**
+ * Private constructor. First phase construction
+ *
+ */
+CT_RSocketData::CT_RSocketData()
+: iSocket(NULL),
+ iActiveCallback(NULL),
+ iActCallConnectSocket(NULL),
+ iActCallShutDownSocket(NULL),
+ iSocketOpened(EFalse),
+ iSocketStarted(EFalse),
+ iAsyncErrorIndex(0),
+ iDownloadBuffer(NULL),
+ iUploadBuffer(NULL),
+ iHttpResponseHeader(),
+ iDownloadThroughput(0.0),
+ iFs(),
+ iUploadThroughput(0.0),
+ itotalReceived(0)
+ {
+
+ }
+
+/**
+ * Second phase construction
+ *
+ * @internalComponent
+ *
+ * @return N/A
+ *
+ * @pre None
+ * @post None
+ *
+ * @leave system wide error
+ */
+void CT_RSocketData::ConstructL()
+ {
+ const TInt KDefaultBufferSize = 4096;
+ TInt err(KErrNone);
+ iSocket = new (ELeave) RSocket();
+ iActiveCallback = CActiveCallback::NewL(*this);
+ iActCallConnectSocket = CActiveCallback::NewL(*this);
+ iActCallShutDownSocket = CActiveCallback::NewL(*this);
+ iDownloadBuffer = HBufC8::NewL( KDefaultBufferSize);
+ iUploadBuffer = HBufC8::NewL(KDefaultBufferSize);
+ err = iFs.Connect();
+ if(err != KErrNone)
+ {
+ SetError(err);
+ }
+ }
+
+
+/**
+ * Return a pointer to the object that the data wraps
+ *
+ * @return pointer to the object that the data wraps
+ */
+TAny* CT_RSocketData::GetObject()
+ {
+ return iSocket;
+ }
+
+
+
+/**
+ * Process a command read from the Ini file
+ * @param aCommand The command to process
+ * @param aSection The section get from the *.ini file of the project T_Wlan
+ * @param aAsyncErrorIndex Command index for async calls to returns errors to
+ * @return TBool ETrue if the command is process
+ * @leave system wide error
+ *
+ */
+TBool CT_RSocketData::DoCommandL(const TTEFFunction& aCommand, const TTEFSectionName& aSection, const TInt aAsyncErrorIndex)
+ {
+ TBool ret = ETrue;
+ if(aCommand == KCmdOpen )
+ {
+ DoCmdOpen(aSection);
+ }
+ else if(aCommand == KCmdConnect)
+ {
+ DoCmdConnect(aSection,aAsyncErrorIndex);
+ }
+ else if(aCommand == KCmdDownloadSendHTTPGet)
+ {
+ DoCmdDownloadSendHTTPGet(aSection,aAsyncErrorIndex);
+ }
+ else if(aCommand == KCmdRecvOneOrMore)
+ {
+ DoCmdRecvOneOrMore(aSection);
+ }
+ else if(aCommand == KCmdUploadSendHTTPPost)
+ {
+ DoCmdUploadSendHTTPPost(aSection);
+ }
+ else if(aCommand == KCmdShutdown)
+ {
+ DoCmdShutdown(aAsyncErrorIndex);
+ }
+ else if(aCommand == KCmdClose)
+ {
+ DoCmdClose();
+ }
+ else if(aCommand == KCmdHttpGet)
+ {
+ DoCmdHttpGet();
+ }
+ else if(aCommand == KCmdCheckSupportedRates)
+ {
+ DoCmdCheckSupportedRates(aSection);
+ }
+ else
+ {
+ ERR_PRINTF1(_L("Unknown command."));
+ ret = EFalse;
+ }
+ return ret;
+ }
+
+
+
+
+/**
+ * Open the Socket from RSocket. The errors are management with SetError() and SetBlockResult().
+ * @param aSection Section in the ini file for this command.
+ * @return
+ */
+void CT_RSocketData::DoCmdOpen(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdOpen"));
+ TBool dataOk = ETrue;
+
+ TPtrC connectionName;
+ if(! GetStringFromConfig(aSection, KConnection, connectionName))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KConnection);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TPtrC socketServName;
+ if(! GetStringFromConfig(aSection, KSocketServ, socketServName))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KSocketServ);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ INFO_PRINTF1(_L("Opening a TCP/IP socket"));
+
+ RConnection* rConnection = static_cast<RConnection*>(GetDataObjectL(connectionName));
+ RSocketServ* rSocketServ = static_cast<RSocketServ*>(GetDataObjectL(socketServName));
+
+ if(rConnection != NULL && rSocketServ != NULL)
+ {
+ TInt error = iSocket->Open( *rSocketServ, KAfInet, KSockStream, KProtocolInetTcp, *rConnection );
+
+ if(error == KErrNone)
+ {
+ iSocketOpened = ETrue;
+ }
+ else
+ {
+ ERR_PRINTF2(_L("Socket opening failed [%d]"), error);
+ SetError(error);
+ }
+ }
+ else
+ {
+ if(rConnection == NULL)
+ {
+ ERR_PRINTF2(_L("rConnection is NULL: %S"),rConnection);
+ SetBlockResult(EFail);
+ }
+
+ if(rSocketServ == NULL)
+ {
+ INFO_PRINTF2(_L("rSocketServ is NULL: %S"),rSocketServ);
+ SetBlockResult(EFail);
+ }
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdOpen"));
+ }
+
+/**
+ * Command to Connect a Socket of RSocket.
+ * @param aSection Section to read from the ini file
+ * @param aAsyncErrorIndex Command index for async calls to returns errors to
+ * @return
+ */
+void CT_RSocketData::DoCmdConnect(const TTEFSectionName& aSection, const TInt aAsyncErrorIndex)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdConnect"));
+ TBool dataOk = ETrue;
+
+ //Getting from the .ini the IP Address
+ TPtrC aIpAddr;
+ if(!GetStringFromConfig( aSection, KAddress, aIpAddr ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KAddress);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ //Getting the port from the file ini
+ TInt aPort;
+ if(!GetIntFromConfig( aSection, KPort,aPort ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KPort);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if(dataOk)
+ {
+ // Set the IP Address
+ TInetAddr inetAddr;
+ TInt err = inetAddr.Input( aIpAddr ) ;
+ if(err == KErrNone)
+ {
+ INFO_PRINTF2(_L("Remote IP: %S"), &aIpAddr );
+ INFO_PRINTF2( _L("Port: %d"), aPort );
+ // Set the port
+ inetAddr.SetPort( aPort );
+ // Connect an IP through the Port 80
+ iSocket->Connect( inetAddr, iActCallConnectSocket->iStatus );
+ iActCallConnectSocket->Activate(aAsyncErrorIndex);
+ IncOutstanding();
+ }
+ else
+ {
+ ERR_PRINTF2(_L("inetAddr.Input( aIpAddr ) Failed with error %d"), err);
+ SetError(err);
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdConnect"));
+ }
+
+/**
+ * Command to send the HTTP Get, using the socket Write.
+ * @param aSection Section to read from the ini file
+ * @param aAsyncErrorIndex Command index for async calls to returns errors to
+ * @return
+ */
+void CT_RSocketData::DoCmdDownloadSendHTTPGet(const TTEFSectionName& aSection, const TInt aAsyncErrorIndex )
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdDownloadSendHTTPGet"));
+ TBool dataOk = ETrue;
+
+ // Read params from the ini file
+ TPtrC aHost;
+ if(!GetStringFromConfig( aSection, KHostS, aHost))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KHostS);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TPtrC aFilename;
+ if(!GetStringFromConfig( aSection, KFile, aFilename ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KFile);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ const TInt KMaxHostNameLength(256);
+ if( aHost.Length() > KMaxHostNameLength )
+ {
+ ERR_PRINTF1(_L("Host is too long, cannot send HTTP request"));
+ SetBlockResult(EFail);
+ }
+ else if( aFilename.Length() > KMaxFileName )
+ {
+ ERR_PRINTF1(_L("Filename is too long, cannot send HTTP request"));
+ SetBlockResult(EFail);
+ }
+ else
+ {
+ INFO_PRINTF1(_L("Create HTTP GET request"));
+ // Buffer that will hold the request.
+ TBuf8< sizeof( KHTTPGET ) +
+ sizeof( KHTTPSeparator ) +
+ KMaxFileName +
+ sizeof( KHTTPSeparator ) +
+ sizeof( KHTTPSuffix ) +
+ sizeof( KLineFeed ) +
+ sizeof( KHosts ) +
+ KMaxHostNameLength +
+ sizeof( KEmptyLine ) > request;
+ // Construct the final request.
+ request.Copy( KHTTPGET );
+ request.Append( KHTTPSeparator );
+ request.Append( aFilename );
+ request.Append( KHTTPSeparator );
+ request.Append( KHTTPSuffix );
+ request.Append( KLineFeed );
+ request.Append( KHosts );
+ request.Append( aHost );
+ request.Append( KEmptyLine );
+
+ INFO_PRINTF1(_L("Write to socket"));
+ // Send the request through socket
+ iSocket->Write(request, iActiveCallback->iStatus);
+ iActiveCallback->Activate(aAsyncErrorIndex);
+ IncOutstanding();
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdDownloadSendHTTPGet"));
+ }
+
+/**
+ * Command to receive an HTTP Response for Upload and Download of files.
+ * @param aSection Section to read from the ini file
+ * @return
+ */
+void CT_RSocketData::DoCmdRecvOneOrMore(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdRecvOneOrMore"));
+ TBool dataOk = ETrue;
+
+ // Read from the ini file
+ TPtrC aFilename;
+ if(!GetStringFromConfig( aSection, KSave,aFilename ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KSave);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ RFile file;
+ TInt error = KErrNone;
+
+ //if KNullFile then Upload
+ TBool discardData = ( aFilename == KNullFile);
+ INFO_PRINTF2(_L("File and path to Download: %S"),&aFilename);
+ if( !discardData )
+ {
+ INFO_PRINTF1( _L("Data is not discarded, creating file") );
+ error = file.Replace( iFs, aFilename, EFileShareAny|EFileWrite );
+ }
+ else
+ {
+ INFO_PRINTF1( _L("Discarding downloaded data") );
+ }
+
+ if( error == KErrNone )
+ {
+ TSockXfrLength received;
+ TInt totalReceived = 0;
+ TInt contentReceived = 0;
+ TInt timedReceived = 0;
+ TInt contentLength = 0;
+ TRequestStatus status;
+ TPtr8 downloadBufferPtr( iDownloadBuffer->Des() );
+
+ downloadBufferPtr.SetMax();
+ INFO_PRINTF2( _L("Using buffer size [%d]"), downloadBufferPtr.MaxSize() );
+
+ INFO_PRINTF1(_L("Set time stamps for download"));
+ TTime endTime;
+ TTime startTime;
+
+ INFO_PRINTF1( _L("Receiving data"));
+
+ // Let's assume that we receive a HTTP header first
+ TBool header( ETrue );
+ TBool timerStarted( EFalse );
+ TBool failure = EFalse; // a flag to delete multiple returns
+
+ iHttpResponseHeader.Zero();
+ // receive until RecvOneOrMore fails or all content is received
+ do
+ {
+ if( !timerStarted && !header)
+ {
+ startTime.HomeTime();
+ endTime.HomeTime();
+ timerStarted = ETrue;
+ }
+
+ iSocket->RecvOneOrMore( downloadBufferPtr, 0, status, received );
+ User::WaitForRequest( status );
+ if( !header )
+ {
+ timedReceived += received();
+ }
+
+ if( KErrNone == status.Int() )
+ {
+ // Check if we are still receiving the HTTP header
+ if( header )
+ {
+ //Increase httpResponseheader size if needed
+ if(iHttpResponseHeader.Length() + downloadBufferPtr.Length() > iHttpResponseHeader.MaxLength())
+ {
+ error = iHttpResponseHeader.ReAlloc(iHttpResponseHeader.MaxLength() + KHttpHeaderBufferIncrement);
+ if(error != KErrNone)
+ {
+ ERR_PRINTF2( _L("iHttpResponseHeader.ReAlloc(...) Failed with error %d"), error);
+ SetError( error );
+ failure = ETrue;
+ break;
+ }
+ }
+
+ //Append the donwloaded content to headerbuffer
+ iHttpResponseHeader.Append(downloadBufferPtr);
+ TInt headerEndIndex = iHttpResponseHeader.Find( KHeaderEndMark );
+ if( headerEndIndex != KErrNotFound )
+ {
+ INFO_PRINTF1( _L("Header end mark found"));
+ //Parse Content-Length field and extract content length
+ TInt contentLengthStart = iHttpResponseHeader.Find( KContentLengthField );
+ //If Content-Length field is found
+ if( contentLengthStart != KErrNotFound )
+ {
+ INFO_PRINTF1(_L("Content-Length field found from HTTP response"));
+ contentLengthStart += KContentLengthField().Length();
+ TPtrC8 contentLengthDes;
+ contentLengthDes.Set(iHttpResponseHeader.Mid( contentLengthStart ));
+ TInt contentLengthEnd = contentLengthDes.Find( KFieldEnd );
+ contentLengthDes.Set(contentLengthDes.Mid(0, contentLengthEnd));
+ TLex8 lex;
+ lex.Assign( contentLengthDes );
+ lex.Val(contentLength);
+ INFO_PRINTF2( _L("Content-Length: [%d]"), contentLength );
+ }
+ else
+ {
+ INFO_PRINTF1( _L("No Content-Length field found from HTTP response"));
+ INFO_PRINTF1( _L("Assuming Content-Length: 0"));
+ contentLength = 0;
+ file.Close();
+ error = iFs.Delete(aFilename);
+ if(error != KErrNone)
+ {
+ INFO_PRINTF3(_L("Error [%d] for delete the file %S"), &aFilename,error);
+ SetError(error);
+ failure = ETrue;
+ break;
+ }
+ ERR_PRINTF2(_L("File %S was not found"), &aFilename);
+ SetBlockResult(EFail);
+ failure = ETrue;
+ break;
+ }
+ // Header was found
+ headerEndIndex += KHeaderEndMark().Length();
+ //Convert the headerEndIndex in httpResponseheader to index in downloadBuffer
+ headerEndIndex -= totalReceived;
+ //Delete remaining parts of the HTTP header from the download buffer
+ downloadBufferPtr.Delete( 0, headerEndIndex );
+ header = EFalse;
+ }
+ }
+
+ // Increase the total received amount as we receive more data.
+ // Note: received data count also counts headers, this is taken
+ // into account in timing (startTime)
+ totalReceived += received();
+ if(!header)
+ {
+ contentReceived += downloadBufferPtr.Length();
+ }
+
+ if( !discardData )
+ {
+ error = file.Write( *iDownloadBuffer );
+ if( KErrNone != error )
+ {
+ ERR_PRINTF2( _L("Failed to write local file [%d]"), error );
+ file.Close();
+ SetError(error);
+ failure = ETrue;
+ break;
+ }
+ }
+ }
+ else
+ {
+ INFO_PRINTF1(_L("Set end time"));
+ endTime.HomeTime();
+ INFO_PRINTF2( _L("Receiving err [%d]"), status.Int());
+ break;
+ }
+ }
+ while( KErrNone == status.Int() && contentReceived < contentLength );
+
+ if (!failure)
+ {
+ endTime.HomeTime();
+ INFO_PRINTF2( _L("Received total of [%d] bytes (inc headers)"), totalReceived );
+ INFO_PRINTF2( _L("Content received [%d] bytes"), contentReceived );
+
+ //Set this printing optional
+ //Print only if any amount of datatransfer was timed (skipped in the case of very short data transfers)
+ if( timerStarted )
+ {
+ INFO_PRINTF1(_L("Calculate duration of the transfer"));
+ TTimeIntervalMicroSeconds duration = endTime.MicroSecondsFrom( startTime );
+ INFO_PRINTF2( _L("Duration for the timed data transfer was [%Ld] microseconds"), duration.Int64() );
+ INFO_PRINTF2( _L("Received [%d] bytes during timed data transfer"), timedReceived);
+ iDownloadThroughput = ThroughputInMegaBits( duration, timedReceived );
+ }
+ else
+ {
+ INFO_PRINTF1( _L("Data transfer too short for throughput calculation"));
+ }
+
+ // We allow any response to our reply at the moment.
+ if( !discardData )
+ {
+ file.Close();
+ }
+ }
+ }
+ else
+ {
+ ERR_PRINTF2( _L("Failed to open local file [%d]"), error );
+ SetError(error);
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdRecvOneOrMore"));
+ }
+
+/**
+ * Create an HTTP Post for uploading files.
+ * @param aSection Section to read from the ini file
+ * @return
+ */
+void CT_RSocketData::DoCmdUploadSendHTTPPost(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdUploadSendHTTPPost"));
+ TBool dataOk = ETrue;
+
+ INFO_PRINTF1( _L("Write to socket"));
+
+ TPtrC aFilename;
+ if(!GetStringFromConfig(aSection,KFile,aFilename))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KFile);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TPtrC fileServer;
+ if(!GetStringFromConfig(aSection,KFileServer,fileServer))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KFileServer);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TPtrC clientID;
+ if(!GetStringFromConfig(aSection,KClientID,clientID))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KClientID);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TPtrC serverScript;
+ if(!GetStringFromConfig(aSection,KServerScript,serverScript))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KServerScript);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ const TInt KMaxTag = 256;
+ // KHeaderWithoutData will change if you alter the header in any way that changes the
+ // amount of characters in it! SO REMEMBER to calclulate header size again.
+ const TInt KHeaderWithoutData = 200;
+ TBuf8<KMaxTag + KHeaderWithoutData> request;
+ TRequestStatus status;
+
+ CreateHTTPHeaderStart(request, ReadFileSizeL(aFilename),fileServer, clientID, serverScript);
+
+ iSocket->Write( request,status);
+ User::WaitForRequest( status );
+ if(status.Int() == KErrNone)
+ {
+ INFO_PRINTF1( _L("HTTP POST request send, sending payload next"));
+ // Send file to iSocket
+ SendFileToSocketL(aFilename);
+ request.SetLength( 0 );
+ CreateHTTPHeaderEnd(request);
+
+ // Send the rest of the header
+ INFO_PRINTF1(_L("Sending boundary end"));
+ iSocket->Write( request, status );
+ User::WaitForRequest( status );
+ if(status.Int() != KErrNone)
+ {
+ ERR_PRINTF2(_L("CT_RSocketData::DoCmdUploadSendHTTPPost: iSocket->Write( request,status) Failed with error %d"), status.Int());
+ SetError(status.Int());
+ }
+ }
+ else
+ {
+ ERR_PRINTF2(_L("CT_RSocketData::DoCmdUploadSendHTTPPost: iSocket->Write( request,status) Failed with error %d"), status.Int());
+ SetError(status.Int());
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdUploadSendHTTPPost"));
+ }
+
+/**
+ * Create or build the header for POST.
+ * @param aRequest Descriptor with a lenght of 456 that contain the parameters for the POST
+ * @param aDataSize Size of the file
+ * @return
+ */
+void CT_RSocketData::CreateHTTPHeaderStart(TDes8& aRequest, TInt aDataSize,TDesC& aFileServer, TDesC& clientID,TDesC& serverScript)
+ {
+ // Manually created HTTP Post request is difficult to maintain.
+ // Request and server responce is logged into file during test run.
+
+ // KHeaderWithoutData will change if you alter the header in any way
+ // that changes the amount of characters in it! SO REMEMBER to calclulate
+ // header size again.
+ const TInt KHeaderWithoutData = 200;
+ INFO_PRINTF1( _L("Set socket remote name"));
+ TSockAddr address;
+ iSocket->RemoteName( address );
+
+ // Construct request
+ aRequest.Append(KHTTPPOST);
+ aRequest.Append(KHTTPSeparator);
+ aRequest.Append(serverScript);
+ aRequest.Append(KHTTPSeparator);
+ aRequest.Append(KHTTPSuffix);
+ aRequest.Append(KLineBreak);
+
+ aRequest.Append(KHosts);
+ aRequest.Append(KHTTPSeparator);
+ aRequest.Append(address);
+ aRequest.Append(KLineBreak);
+
+ aRequest.Append(KFrom);
+ aRequest.Append(KHTTPSeparator);
+ aRequest.Append(clientID);
+ aRequest.Append(KLineBreak);
+
+ aRequest.Append(KContentType);
+ aRequest.Append(KHTTPSeparator);
+ aRequest.Append(KMultipartType);
+ aRequest.Append(KHTTPSeparator);
+ aRequest.Append(KBoundary);
+ aRequest.Append(KLineBreak);
+
+ aRequest.Append(KContentLength);
+ aRequest.Append(KHTTPSeparator);
+ // aRequest size + size of the data to be sent. Server must know how much
+ // data is coming.
+ aRequest.AppendNum(KHeaderWithoutData+aDataSize);
+ aRequest.Append(KLineBreak);
+
+ // extra line break
+ aRequest.Append(KLineBreak);
+
+ aRequest.Append(KBoundaryStart);
+ aRequest.Append(KLineBreak);
+
+ aRequest.Append(KContentDisposition);
+ aRequest.Append(KHTTPSeparator);
+ aRequest.Append(KDisposition);
+ aRequest.Append(KBackS);
+ aRequest.Append(aFileServer);
+ aRequest.Append(KBackS);
+ aRequest.Append(KLineBreak);
+
+ aRequest.Append(KContentType);
+ aRequest.Append(KHTTPSeparator);
+ aRequest.Append(KOctetType);
+ aRequest.Append(KLineBreak);
+
+ aRequest.Append(KLineBreak);
+ }
+
+/**
+ * Send aFilename parameter to the Socket with RSocket::Write
+ * @param aFilename name of the file send to the Socket
+ * @return
+ */
+void CT_RSocketData::SendFileToSocketL(const TDesC& aFilename)
+ {
+ TInt err(KErrNone);
+ TPtr8 buffer( iUploadBuffer->Des() );
+ buffer.SetMax();
+ INFO_PRINTF2( _L("Using buffer size [%d]"), buffer.MaxSize() );
+ TInt bytesSent = 0;
+
+ INFO_PRINTF1( _L("Open file"));
+ RFile file;
+
+ err = file.Open(iFs, aFilename, EFileShareAny|EFileRead);
+
+ if(err == KErrNone)
+ {
+ CleanupClosePushL( file );
+ INFO_PRINTF1(_L("Read file size"));
+ TInt fileSize = ReadFileSizeL(aFilename);
+
+ INFO_PRINTF1( _L("Set time stamps for upload"));
+ TTime endTime;
+ endTime.HomeTime();
+ TTime startTime;
+ startTime.HomeTime();
+
+ INFO_PRINTF1( _L("Send file"));
+ // Loop while enough bytes are sent to socket
+ while( bytesSent < fileSize )
+ {
+ TInt err = file.Read( buffer );
+
+ if( err == KErrEof )
+ {
+ INFO_PRINTF1(_L("File sending finished"));
+ INFO_PRINTF2( _L("Upload buffer length is [%d]"), buffer.Length());
+ break;
+ }
+ else if( err != KErrNone )
+ {
+ ERR_PRINTF2( _L("Failed to read file [%d]"), err );
+ SetError( err );
+ break;
+ }
+
+ TRequestStatus status(KRequestPending);
+ iSocket->Write( buffer, status );
+ User::WaitForRequest( status );
+ err = status.Int();
+ if(err != KErrNone)
+ {
+ ERR_PRINTF2(_L("CT_RSocketData::SendFileToSocketL:iSocket->Write(...) Fail [%d] "),err);
+ SetError(err);
+ break;
+ }
+
+ bytesSent += ( buffer.Length() );
+ }
+
+ if (err == KErrNone || err == KErrEof)
+ {
+ INFO_PRINTF1( _L("Set end time"));
+ endTime.HomeTime();
+ INFO_PRINTF2( _L("Sent [%d] bytes to server"), bytesSent);
+
+ INFO_PRINTF1( _L("Calculate duration of the transfer"));
+ TTimeIntervalMicroSeconds duration = endTime.MicroSecondsFrom( startTime );
+ INFO_PRINTF2( _L("Duration for the data transfer was [%Ld] microseconds"), duration.Int64() );
+ iUploadThroughput = ThroughputInMegaBits( duration, bytesSent );
+ CleanupStack::PopAndDestroy( &file );
+ }
+ }
+ else
+ {
+ ERR_PRINTF2(_L("CT_RSocket::SendFileToSocketL::file.Open(...) Failed with error %d"), err);
+ SetError(err);
+ }
+ }
+
+/**
+ * Calculated the throughput based on duration of a data transfer and total transferred bytes.
+ * @param aDuration Duration of the transfer
+ * @param aBytes Total transferred in bytes
+ * @return Throughput in MBps
+ */
+TReal CT_RSocketData::ThroughputInMegaBits(TTimeIntervalMicroSeconds aDuration, TInt aBytes )
+ {
+ const TReal KBitsInByte(8.0);
+ TReal throughput = ( KBitsInByte * (TReal) aBytes ) / (TReal) aDuration.Int64();
+ return throughput;
+ }
+
+/**
+ * Read the lenght of the file (aFileName)
+ * @param aFileName file to read the lenght
+ * @return
+ */
+TInt CT_RSocketData::ReadFileSizeL(const TDesC& aFilename)
+ {
+ RFile file;
+ TInt error = file.Open(iFs, aFilename, EFileShareAny|EFileRead);
+ if ( error != KErrNone)
+ {
+ ERR_PRINTF2( _L("Failed to open local file [%d]"), error);
+ SetError(error);
+ return error;
+ }
+
+ TInt fileSize = 0;
+ error = file.Size(fileSize);
+
+ if (error!= KErrNone)
+ {
+ ERR_PRINTF2(_L("Failed to read file size [%d]"), error);
+ file.Close();
+ SetError(error);
+ return error;
+ }
+
+ file.Close();
+ return fileSize;
+ }
+
+/**
+ * Build the final header to POST for uploading files
+ * @param aRequest Descriptor with 456 of lenght that contain the final POST request
+ * @return
+ */
+void CT_RSocketData::CreateHTTPHeaderEnd(TDes8& aRequest)
+ {
+ //TRequestStatus status;
+ aRequest.SetLength( 0 );
+ //Create the rest of the header data
+ aRequest.Append( KLineBreak );
+ aRequest.Append( KBoundaryEnd );
+ aRequest.Append( KLineBreak );
+ }
+
+
+/**
+ * Make a HTTP request to the socket
+ * @param
+ * @return
+ */
+void CT_RSocketData::DoCmdHttpGet()
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdHttpGet"));
+
+ TInt err(KErrNone);
+ //Constant for creating a HTTP request.
+ const TInt KHTTPSize = 128;
+ // Buffer that will hold the request.
+ TBuf8 <KHTTPSize> request;
+ // Construct the final request.
+ request.Append( KGETHTTP );
+
+ INFO_PRINTF1( _L("Write to socket") );
+ TRequestStatus status( KRequestPending );
+ iSocket->Write( request, status);
+ User::WaitForRequest( status );
+ INFO_PRINTF2( _L("CT_RSocketData::DoCmdHttpGet: Write done: [%d]"), status.Int() );
+ err = status.Int();
+
+ if(err == KErrNone)
+ {
+ INFO_PRINTF1( _L("CT_RSocketData::DoCmdHttpGet: Receive from socket") );
+ // receive until RecvOneOrMore fails
+ do
+ {
+ RecvOneOrMore(status);
+ }
+ while( status.Int() == KErrNone );
+
+ INFO_PRINTF2( _L("CT_RSocketData::DoCmdHttpGet: Receiving finished. Received [%d] bytes in total"), itotalReceived );
+
+ // Currently all error codes returned by the server are accepted.
+ // Should only KErrEof be accepted?
+ INFO_PRINTF2( _L("Ignoring error code from RSocket::RecvOneOrMore [%d]"), status.Int());
+ }
+ else
+ {
+ ERR_PRINTF2(_L("CT_RSocketData::DoCmdHttpGet: iSocket.Write(...) Failed with error %d"), err);
+ SetError(err);
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdHttpGet"));
+ }
+
+/**
+ * Receive data from a remote host.
+ * @param status Indicates the complexion status of the request
+ * @return
+ */
+void CT_RSocketData::RecvOneOrMore(TRequestStatus &status)
+ {
+ TInt err(KErrNone);
+ // Create variables for receive buffer and received data counting variables.
+ const TInt KBufferSize(1024);
+ TBuf8<KBufferSize> buffer;
+ TSockXfrLength received;
+ iSocket->RecvOneOrMore( buffer, 0, status, received);
+ User::WaitForRequest( status );
+ err = status.Int();
+ if( err == KErrNone )
+ {
+ INFO_PRINTF2( _L("CWlanTestWrapper: Received [%d] bytes"), received() );
+ itotalReceived += received();
+ }
+ else if( err == KErrEof )
+ {
+ INFO_PRINTF1(_L("End of File reached"));
+ }
+ else
+ {
+ ERR_PRINTF2(_L("RecvOneOrMore async call failed with error %d"), err);
+ SetError(err);
+ }
+ }
+
+
+
+/**
+ * Check the supported rates for the IAP.
+ * @param aSection Section to read from the ini file
+ * @return
+ */
+void CT_RSocketData::DoCmdCheckSupportedRates(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdCheckSupportedRates"));
+ TBool dataOk = ETrue;
+
+ // Read from the ini file
+ TInt aRate;
+ if(!GetIntFromConfig(aSection,KARates,aRate))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KARates);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ // Check if a scan has been made
+ TPtrC iScanInfoName;
+ if(!GetStringFromConfig(aSection,KScanInfo,iScanInfoName ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KScanInfo);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ CWlanScanInfo* iScanInfo = static_cast<CWlanScanInfo*>(GetDataObjectL(iScanInfoName));
+
+ // Check if a scan has been made
+ if( iScanInfo != NULL )
+ {
+ const TUint8 KTemp80211SupRatesId = 1;
+ const TUint8 KTemp80211SupRatesMaxLen = 18;
+ // Scan info gives data as "information elements"
+ TUint8 ieLen(0);
+ const TUint8* ieData(0);
+
+ TInt err = iScanInfo->InformationElement( KTemp80211SupRatesId, ieLen, &ieData );
+
+ // Check supported rate if the information element was available
+ if(err == KErrNone)
+ {
+ TBuf8<KTemp80211SupRatesMaxLen> supRates8;
+ supRates8.Copy( ieData, ieLen );
+ TBool supported = CheckSupportedRates( supRates8, aRate );
+ if(!supported)
+ {
+ ERR_PRINTF2( _L("%d rate not supportedRates"), aRate );
+ SetError(KErrNotSupported);
+ }
+ }
+ else
+ {
+ ERR_PRINTF2( _L("err: [%d]"), err );
+ SetError(err);
+ }
+ }
+ else
+ {
+ ERR_PRINTF1(_L("Failed to get CWlanScanInfo object"));
+ SetBlockResult(EFail);
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdCheckSupportedRates"));
+ }
+
+/**
+ * Review if the rate its supported.
+ * @param aSupportedRates Rate to calculate and if match with the desired rate
+ * @param aRate rate to verify if is supporrted, The rate to be checked in 0.5Mb/s units.
+ * Ie. 2 = 2 * 0.5Mb/s = 1Mb/s.
+ * @return Etrue if the rate is supported
+ */
+TBool CT_RSocketData::CheckSupportedRates(const TDesC8& aSupportedRates, const TUint8 aRate)
+ {
+ // Supported rates information element format is the following:
+ // | element id (1 octet) | length (1 octet) | supported rates (1-8 octets) |
+ // where each octet of supported rates contains one supported rate in
+ // units of 500 kb/s. The first bit of supported rates field is always 1
+ // if the rate belongs to the BSSBasicRateSet, if the rate does not belong
+ // to the BSSBasicRateSet the first bit is 0.
+
+ // For example Supported rates information element with value
+ // 0x01,0x02,0x82,0x84
+ // would mean that BSSBasicRateSet rates 1Mb/s and 2Mb/s are supported
+
+ TBool supported( EFalse );
+
+ for ( TInt i( 0 ); i < aSupportedRates.Length(); i++ )
+ {
+ TUint8 rate = aSupportedRates[i] & KBasicRateMask;
+ if( rate == aRate ) supported = ETrue;
+ //INFO_PRINTF2( _L("speed rate [%d]"), rate);
+ switch( rate )
+ {
+ case K80211Rate1Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 1Mbit") );
+ break;
+ case K80211Rate2Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 2Mbit") );
+ break;
+ case K80211Rate5Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 5Mbit") );
+ break;
+ case K80211Rate11Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 11Mbit") );
+ break;
+ case K80211Rate12Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 12Mbit") );
+ break;
+ case K80211Rate18Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 18Mbit") );
+ break;
+ case K80211Rate22Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 22Mbit") );
+ break;
+ case K80211Rate24Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 24Mbit") );
+ break;
+ case K80211Rate36Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 36Mbit") );
+ break;
+ case K80211Rate48Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 48Mbit") );
+ break;
+ case K80211Rate54Mbit:
+ INFO_PRINTF1( _L("AP can support Speed Rate 54Mbit") );
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return supported;
+ }
+
+/**
+ * Shutdown the socket (RSocket::Shutdown).
+ * @param aAsyncErrorIndex Command index for async calls to returns errors to
+ * @return
+ */
+void CT_RSocketData::DoCmdShutdown( const TInt aAsyncErrorIndex)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdShutdown"));
+ INFO_PRINTF1(_L("Starting to shutdown Socket"));
+ iSocket->Shutdown( RSocket::ENormal, iActCallShutDownSocket->iStatus);
+ iActCallShutDownSocket->Activate(aAsyncErrorIndex);
+ IncOutstanding();
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdShutdown"));
+ }
+/**
+ * Helper function calling from the destroyer.
+ * @param
+ * @return
+ */
+void CT_RSocketData::Shutdown()
+ {
+ TInt err(KErrNone);
+ TRequestStatus status;
+ iSocket->Shutdown(RSocket::ENormal, status);
+ User::WaitForRequest( status );
+ err = status.Int();
+ if( err != KErrNone )
+ {
+ ERR_PRINTF2( _L("CT_RSocketData::Shutdown(): error[%d]"), err);
+ SetError(err);
+ }
+ }
+
+/**
+ * Close de socket.
+ * @param
+ * @return
+ */
+void CT_RSocketData::DoCmdClose()
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdClose"));
+ Close();
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdClose"));
+ }
+/**
+ * Helper function to close the socket.
+ * @param
+ * @return
+ */
+void CT_RSocketData::Close()
+ {
+ iSocket->Close();
+ iSocketOpened = EFalse;
+ }