--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cellularsrvapitest/datatransferhaitest/esock/src/T_RSocketData.cpp Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,1405 @@
+/*
+* 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 "T_RSocketData.h"
+#include "T_RHostResolverData.h"
+#include <e32property.h>
+#include <etelmm.h> // RMobilePhone
+#include <etelpckt.h> // RPacketService
+
+
+const TInt KBufferSize = 1024;
+_LIT( KNoFileSave, "NULL" );
+const TUint KNoDataDealer = 0;
+const TInt KNoDuration = -1;
+const TInt KNoSpeedCheck = -1;
+
+// Misc Types
+_LIT( KProtocolHTTP, "HTTP" );
+_LIT( KOff, "Off" ); // Can be used every2*where off is needed
+
+// HSDPA checks
+_LIT( KHsdpaIndicator, "Indicator" ); // Operator supports
+_LIT( KHsdpaSupported, "Supported" ); // Device supports
+_LIT( KHsdpaInUse, "Used" ); // In use during PSD
+
+// Constants for creating a HTTP request.
+_LIT8(KHTTPGET, "GET");
+_LIT8(KHTTPSeparator, " ");
+_LIT8(KHTTPSuffix, "HTTP/1.0");
+_LIT8(KEmptyLine, "\r\n\r\n");
+const TInt KEmptySize = 4;
+
+const TInt KHTTPSize = 17;
+const TInt KMaxTag = 256;
+const TInt KHeaderWithoutData=200;
+//
+// Manually created HTTP Post request is difficult to maintain.
+// Request and server responce is logged into file during test run.
+_LIT8(KHTTPPOST, "POST");
+_LIT8(KLineBreak, "\r\n");
+
+_LIT8(KAhti, "Ahti");
+
+_LIT8(KServerScript, "/dy/upload/upfile.php");
+_LIT8(KFrom, "From:");
+_LIT8(KHost, "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(KBoundaryEnd, "-----------------------------sg976436h73--");
+_LIT8(KDisposition, "form-data; name=\"userfile\"; filename=\"test.bin\"");
+
+_LIT( KPropertyCategory, "PropertyCategory");
+_LIT( KPropertyKey, "PropertyKey");
+_LIT( KMaxPropertyLength, "PropertyLength");
+
+//const TInt
+_LIT( KPort, "Port" );
+_LIT( KAddress, "Address" );
+_LIT( KProtocol, "Protocol" );
+_LIT( KFileName, "File" );
+_LIT( KSaveName, "Save" );
+_LIT( KDataDealerID, "DataDealer" ); // Data dealer ID is given may not be 0
+_LIT( KHsdpaCheck, "HSDPA" ); // HSDPA check can be done several ways
+_LIT( KDuration, "Duration" ); // How long should i.e. download last when it is stopped (THRO)
+_LIT( KMinimumSpeed, "MinSpeed" ); // Data transfer must be faster than MinSpeed
+_LIT( KBytes, "Bytes" ); // How many bytes are send
+_LIT( KResponseLogFile, "ResponseLogFile");
+_LIT( KRequestLogFile, "RequestLogFile");
+//LIT's to read from ini file
+_LIT( KDefaultSection, "Default");
+_LIT(KRConnection, "RConnection");
+_LIT(KRSocketServ, "RSocketServ");
+_LIT(KRHostResolver, "RHostResolver");
+_LIT(KRMobilePhone, "RMobilePhone");
+
+/*@}*/
+
+/*@{*/
+//LIT's for commands
+_LIT(KCmdRSocketOpen, "Open");
+_LIT(KCmdRSocketClose, "Close");
+_LIT(KCmdRSocketConnect, "Connect");
+_LIT(KCmdRSocketShutDown, "ShutDown");
+_LIT(KCmdRSocketWrite, "Write");
+_LIT(KCmdResponseFromServer, "ResponseFromServer");
+_LIT(KWriteRequest, "WriteRequest");
+_LIT(KCmdUtilityStartFile, "StartFile");
+_LIT(KCmdUtilityStartDealer, "StartDealer");
+_LIT(KCmdUtilityCheckHSDPA, "CheckHSDPA");
+_LIT(KCmdRecvOneOrMore, "RecvOneOrMore");
+_LIT(KCmdUtilityEndFile, "EndFile");
+_LIT(KCmdUtilityCalcDnloadStats, "CalcDnloadStats");
+_LIT(KCmdUtilityBuildRequest, "BuildRequest");
+_LIT(KCmdSendBytesToSocket, "SendBytesToSocket");
+_LIT(KCmdUtilityEndRequest, "EndRequest");
+_LIT(KCmdInfo, "Info");
+/*@}*/
+
+
+/**
+ * Two phase constructor
+ */
+CT_RSocketData* CT_RSocketData::NewL()
+ {
+ CT_RSocketData* ret=new (ELeave) CT_RSocketData();
+ CleanupStack::PushL(ret);
+ ret->ConstructL();
+ CleanupStack::Pop(ret);
+ return ret;
+ }
+
+/**
+* Protected constructor. First phase construction
+*/
+CT_RSocketData::CT_RSocketData():
+ iSocket(NULL),
+ iActiveCallback(NULL),
+ iBreathSaver(NULL)
+ {
+ }
+
+CT_RSocketData::~CT_RSocketData()
+ {
+ if(iBreathSaver)
+ {
+ delete iBreathSaver;
+ iBreathSaver = NULL;
+ }
+ if(iActiveCallback)
+ {
+ delete iActiveCallback;
+ iActiveCallback = NULL;
+ }
+ if(iSocket)
+ {
+ delete iSocket;
+ iSocket = NULL;
+ }
+ }
+
+void CT_RSocketData::ConstructL()
+ {
+ iActiveCallback = CActiveCallback::NewL(*this);
+ iBreathSaver = CBreathSaver::NewL();
+ iSocket = new (ELeave)RSocket();
+ }
+
+void CT_RSocketData::InitialiseL()
+ {
+ CDataWrapperBase::InitialiseL();
+
+ TInt propertyCategory;
+ GetHexFromConfig(KDefaultSection, KPropertyCategory, propertyCategory);
+ iPropertyCategory.iUid = propertyCategory;
+
+ TInt propertyKey;
+ GetIntFromConfig(KDefaultSection, KPropertyKey, propertyKey );
+ iPropertyKey =(TUint)propertyKey;
+
+ GetIntFromConfig(KDefaultSection, KMaxPropertyLength, iMaxPropertyLength );
+
+ }
+
+
+
+/**
+ * Process a command read from the ini file
+ *
+ * @param aCommand The command to process
+ * @param aSection The section in the ini containing data for the command
+ * @param aAsyncErrorIndex Command index for async calls to return errors to
+ *
+ * @return ETrue if the command is processed
+ *
+ * @leave System wide error
+ */
+TBool CT_RSocketData::DoCommandL(const TTEFFunction& aCommand, const TTEFSectionName& aSection, const TInt aAsyncErrorIndex)
+ {
+ TBool retVal=ETrue;
+
+ if (aCommand==KCmdRSocketOpen)
+ {
+ DoCmdOpenL(aSection);
+ }
+ else if (aCommand==KCmdRSocketConnect)
+ {
+ DoCmdConnectL(aSection, aAsyncErrorIndex);
+ }
+ else if (aCommand==KCmdRSocketShutDown)
+ {
+ DoCmdShutDown(aAsyncErrorIndex);
+ }
+ else if (aCommand==KCmdRSocketClose)
+ {
+ DoCmdClose();
+ }
+ else if ( aCommand == KWriteRequest )
+ {
+ DoCmdWriteRequest(aSection, aAsyncErrorIndex);
+ }
+ else if ( aCommand == KCmdUtilityStartFile )
+ {
+ DoCmdUtilityStartFile(aSection);
+ }
+ else if (aCommand == KCmdUtilityStartDealer )
+ {
+ DoCmdUtilityStartDealer(aSection);
+ }
+ else if (aCommand == KCmdUtilityCheckHSDPA )
+ {
+ DoCmdUtilityCheckHSDPAL(aSection);
+ }
+ else if (aCommand==KCmdRecvOneOrMore)
+ {
+ DoCmdRecvOneOrMore(aSection);
+ }
+ else if (aCommand == KCmdUtilityEndFile )
+ {
+ DoCmdUtilityEndFile(aSection);
+ }
+ else if (aCommand == KCmdUtilityCalcDnloadStats )
+ {
+ DoCmdUtilityCalculateDownloadStats(aSection);
+ }
+ else if (aCommand==KCmdUtilityBuildRequest)
+ {
+ DoCmdUtilityBuildRequest(aSection);
+ }
+ else if (aCommand==KCmdRSocketWrite)
+ {
+ DoCmdWrite(aAsyncErrorIndex);
+ }
+ else if (aCommand==KCmdSendBytesToSocket)
+ {
+ DoCmdSendBytesToSocket(aSection);
+ }
+ else if (aCommand==KCmdResponseFromServer)
+ {
+ DoCmdResponseFromServer(aSection);
+ }
+ else if (aCommand==KCmdUtilityEndRequest)
+ {
+ DoCmdUtilityEndRequest();
+ }
+ else if (aCommand==KCmdInfo)
+ {
+ DoCmdInfoL(aSection);
+ }
+ else
+ {
+ ERR_PRINTF1(_L("Unknown command"));
+ retVal=EFalse;
+ }
+
+ return retVal;
+ }
+
+/**
+ * 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;
+ }
+
+
+void CT_RSocketData::RunL(CActive* aActive, TInt aIndex)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::RunL"));
+ DecOutstanding(); // One of the async calls has completed
+
+ if(aActive == iActiveCallback)
+ {
+ INFO_PRINTF1(_L("Asynchronous task has completed. RunL called"));
+ }
+ else
+ {
+ ERR_PRINTF1(_L("Stray RunL signal"));
+ TInt err = aActive->iStatus.Int();
+ if( err != KErrNone )
+ {
+ ERR_PRINTF2(_L("RunL Error %d"), err);
+ SetAsyncError( aIndex, err );
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::RunL"));
+ }
+
+/**
+ * Opens a socket.
+ * @param aSection - Section in config file to get a RSocketServer and RConnection
+ * Sets TEF error if not successful.
+ */
+void CT_RSocketData::DoCmdOpenL(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdOpenL"));
+ TBool dataOk = ETrue;
+
+ TPtrC connectionName;
+ if ( !GetStringFromConfig(aSection, KRConnection(), connectionName) )
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KRConnection);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TPtrC socketServName;
+ if ( !GetStringFromConfig(aSection, KRSocketServ(), socketServName) )
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KRSocketServ);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ INFO_PRINTF1(_L("Create a RConnection for iSocket"));
+ RConnection* connection = static_cast<RConnection*>(GetDataObjectL(connectionName));
+ INFO_PRINTF1(_L("Create a RSocketServ for iSocket"));
+ RSocketServ* socketServ = static_cast<RSocketServ*>(GetDataObjectL(socketServName));
+
+ TInt error = iSocket->Open(*socketServ, KAfInet, KSockStream, KProtocolInetTcp, *connection);
+
+ if (error == KErrNone)
+ {
+ INFO_PRINTF1(_L("Socket opening succeeded"));
+ }
+ else
+ {
+ ERR_PRINTF2(_L("Socket opening failed [%d]"), error);
+ SetError(error);
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdOpenL"));
+ }
+
+/**
+ * Connects socket with a given address and port.
+ * @param aSection - The section in config file to look for the address, port and RHostResolver
+ * @param aAsyncErrorIndex - Command index for async calls to return errors to
+ */
+void CT_RSocketData::DoCmdConnectL(const TTEFSectionName& aSection, const TInt aAsyncErrorIndex)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdConnectL"));
+ TBool dataOk = ETrue;
+
+ TInt port;
+ if(!GetIntFromConfig( aSection, KPort, port ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KPort);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TPtrC address;
+ if(!GetStringFromConfig( aSection, KAddress, address ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KAddress);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ // Connect ready socket to given host and port number
+ TPtrC hostResolverName;
+ if( !GetStringFromConfig(aSection, KRHostResolver, hostResolverName) )
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KRHostResolver);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ INFO_PRINTF3(_L("Connecting socket to server \"%S\" at port [%d]"), &address, port);
+
+ CT_RHostResolverData* hostResolver = static_cast<CT_RHostResolverData*>(GetDataWrapperL(hostResolverName));
+ iNameEntry = hostResolver->GetNameEntry();
+ iNameEntry().iAddr.SetPort(port);
+ iSocket->Connect(iNameEntry().iAddr, iActiveCallback->iStatus);
+ iActiveCallback->Activate(aAsyncErrorIndex);
+ IncOutstanding();
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdConnectL"));
+ }
+
+/**
+ * Shuts down a connected socket - asynchronous.
+ * This method is asynchronous as non emergency shutdown may take a while.
+ * The shut down method allows input and output to be individually stopped for a protocol endpoint.
+ * @param aAsyncErrorIndex - Command index for async calls to return errors to
+ */
+void CT_RSocketData::DoCmdShutDown(const TInt aAsyncErrorIndex)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdShutDownSocket"));
+
+ // Shutdown the socket.
+ iSocket->Shutdown(RSocket::ENormal, iActiveCallback->iStatus);
+ iActiveCallback->Activate(aAsyncErrorIndex);
+ IncOutstanding();
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdShutDownSocket"));
+ }
+
+/**
+ * Closes a socket.
+ * If a socket has been opened using Open() then it should be closed using Close().
+ * This will ensure all associated resources are released.
+ * Closing serves two distinct purposes:
+ * - To release resources associated with the IPC channel to the socket server.
+ * - To disconnect a socket if it is connected.
+ */
+void CT_RSocketData::DoCmdClose()
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdCloseSocket"));
+ iSocket->Close(); // Close does not return error code
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdCloseSocket"));
+ }
+
+
+/**
+ * Builds an HTTP Get request
+ * @param aSection - The section in config file to look for address, port, protocol, filename and save path.
+ * @param aAsyncErrorIndex - Command index for async calls to return errors to
+ */
+void CT_RSocketData::DoCmdWriteRequest(const TTEFSectionName& aSection, const TInt aAsyncErrorIndex)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdWriteRequest"));
+ TBool dataOk = ETrue;
+
+ TPtrC filename;
+ if(!GetStringFromConfig(aSection, KFileName, filename ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KFileName);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TPtrC protocol;
+ if(!GetStringFromConfig(aSection, KProtocol, protocol ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KProtocol);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+
+ // Send http get request
+ if (dataOk && protocol != KProtocolHTTP)
+ {
+ ERR_PRINTF2(_L("Protocol \"%S\" is unknown"), &protocol);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk && filename.Length() > KMaxTag)
+ {
+ ERR_PRINTF1(_L("Filename is too long, cannot send HTTP request"));
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ INFO_PRINTF1(_L("Sending HTTP request"));
+
+ // Buffer that will hold the request.
+ TBuf8<KHTTPSize + KMaxTag> request;
+
+ // Construct the final request.
+ request.Append(KHTTPGET);
+ request.Append(KHTTPSeparator);
+ request.Append(filename);
+ request.Append(KHTTPSeparator);
+ request.Append(KHTTPSuffix);
+ request.Append(KEmptyLine);
+
+ // Send the request through socket
+ iSocket->Write(request, iActiveCallback->iStatus);
+ iActiveCallback->Activate(aAsyncErrorIndex);
+ IncOutstanding();
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdWriteRequest"));
+ }
+
+
+/**
+ * Uses helper class BreathSaver to generate a file and save downloaded data in a given path.
+ * @param aSection - The section in config file to look for address, port, protocol, filename and save path.
+ * Sets TEF error if not successful.
+ */
+void CT_RSocketData::DoCmdUtilityStartFile(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdUtilityStartFile"));
+ TBool dataOk = ETrue;
+
+ TPtrC savename( KNoFileSave );
+ if(!GetStringFromConfig(aSection, KSaveName, savename))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KSaveName);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if ( dataOk && savename == KNoFileSave)
+ {
+ ERR_PRINTF1(_L("Incorrect file name"));
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ INFO_PRINTF2(_L("Save incoming file to \"%S\""), &savename);
+ TInt error = iBreathSaver->StartFile(savename);
+
+ if (error != KErrNone)
+ {
+ ERR_PRINTF2(_L("Failed to save data file [%d]"), error);
+ SetError(error);
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdUtilityStartFile"));
+ }
+
+/**
+ * Uses helper class BreathSaver to start a Data dealer
+ * @param aSection - The section in config file to look for Data Dealer ID.
+ * Sets TEF error if not successful.
+ */
+void CT_RSocketData::DoCmdUtilityStartDealer(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdUtilityStartDealer"));
+ TBool dataOk = ETrue;
+
+ TUint datadealerid( KNoDataDealer );
+ if(!GetUintFromConfig(aSection, KDataDealerID, datadealerid ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KDataDealerID);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk && datadealerid != KNoDataDealer)
+ {
+ INFO_PRINTF2(_L("Use data dealer with id (%u) for incoming file"), datadealerid);
+ TInt error = iBreathSaver->StartDealer(datadealerid);
+
+ if (error == KErrNone)
+ {
+ INFO_PRINTF1(_L("iBreathSaver->StartDealer(datadealerid) was executed"));
+ }
+ else
+ {
+ ERR_PRINTF2(_L("Failed to use data dealer [%d]"), error);
+ SetError(error);
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdUtilityStartDealer"));
+ }
+
+
+
+/**
+ * Checks HSDPA options.
+ * @param aSection - The section in config file to look for HSDPA parameters.
+ * @return error - Error code. KErrNone if successful.
+ */
+void CT_RSocketData::DoCmdUtilityCheckHSDPAL(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdUtilityCheckHSDPAL"));
+ TBool dataOk = ETrue;
+
+ TPtrC hsdpacheck( KNullDesC );
+ if(!GetStringFromConfig(aSection, KHsdpaCheck, hsdpacheck))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KHsdpaCheck);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ TPtrC mobilePhoneName;
+ RMobilePhone* mobilePhone = NULL;
+ if(GetStringFromConfig(aSection, KRMobilePhone(), mobilePhoneName))
+ {
+ mobilePhone = static_cast<RMobilePhone*>(GetDataObjectL(mobilePhoneName));
+ }
+
+ INFO_PRINTF1(_L( "Checking HSDPA..." ));
+
+ if (hsdpacheck == KNullDesC)
+ {
+ INFO_PRINTF1(_L( "No HSDPA used. Nothing to check." ));
+ }
+ else if (hsdpacheck == KHsdpaIndicator)
+ {
+ if (CheckHSDPAIndicator())
+ {
+ INFO_PRINTF1(_L("HSDPA indicator available"));
+ }
+ else
+ {
+ ERR_PRINTF1(_L("HSDPA indicator not available"));
+ SetBlockResult(EFail);
+ }
+ }
+ else if (hsdpacheck == KHsdpaSupported && mobilePhone)
+ {
+ if (CheckHSDPASupportL(*mobilePhone))
+ {
+ INFO_PRINTF1(_L("HSDPA support available"));
+ }
+ else
+ {
+ ERR_PRINTF1(_L("HSDPA support not available"));
+ SetBlockResult(EFail);
+ }
+ }
+ else if (hsdpacheck == KHsdpaInUse && mobilePhone)
+ {
+ if (CheckHSDPAUsageL(*mobilePhone))
+ {
+ INFO_PRINTF1(_L("HSDPA in use"));
+ }
+ else
+ {
+ ERR_PRINTF1(_L("HSDPA not in use"));
+ SetBlockResult(EFail);
+ }
+ }
+ else if (hsdpacheck == KOff)
+ {
+ INFO_PRINTF1(_L("Can HSDPA be turned off?"));
+ }
+ else
+ {
+ ERR_PRINTF2(_L("Unknown HSDPA usage parameter \"%S\""), &hsdpacheck);
+ SetBlockResult(EFail);
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdUtilityCheckHSDPAL"));
+ }
+
+/**
+ * Downloads a file from a given address and saves it in specified path.
+ * @param aSection - The section in config file to look for address, port, protocol, filename and save path.
+ * @return error - Error code. KErrNone if successful.
+ */
+void CT_RSocketData::DoCmdRecvOneOrMore(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdDownloadToFile"));
+ TBool dataOk = ETrue;
+
+ TInt duration( KNoDuration );
+ if(!GetIntFromConfig(aSection, KDuration, duration ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KDuration);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TPtrC protocol;
+ if(!GetStringFromConfig(aSection, KProtocol, protocol ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KProtocol);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TUint datadealerid( KNoDataDealer );
+ if(!GetUintFromConfig(aSection, KDataDealerID, datadealerid ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KDataDealerID);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TPtrC savename( KNoFileSave );
+ if(!GetStringFromConfig(aSection, KSaveName, savename))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KSaveName);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TBuf8<KBufferSize> buffer;
+ if (protocol != KProtocolHTTP)
+ {
+ ERR_PRINTF3(_L("Error, %S protocol is not supported. %S protocol is expected"), &protocol, &KProtocolHTTP);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ INFO_PRINTF1(_L("Download starts"));
+
+ TInt error = KErrNone;
+ TBool header = ETrue;
+ TBool writeFail = EFalse;
+ TRequestStatus status;
+ TSockXfrLength received;
+
+ // Start and end time for calculating the transfer speed.
+ iStart.HomeTime();
+
+ // receive until RecvOneOrMore fails.
+ do
+ {
+ iSocket->RecvOneOrMore(buffer, 0, status, received);
+ User::WaitForRequest(status);
+
+ if (status == KErrNone)
+ {
+ iTotalReceived += received();
+
+ if (header)
+ {
+ // HTTP server first sends header and then data
+ TInt location = buffer.Find(KEmptyLine);
+ // If the separator (two line breaks) is found...
+ if (location != KErrNotFound)
+ {
+ TInt i = location + KEmptySize;
+ // Remove the header from the buffer
+ buffer.Delete(0, i);
+ if (savename != KNoFileSave ||
+ datadealerid != KNoDataDealer)
+ {
+ error = iBreathSaver->Append(buffer);
+ if (error != KErrNone)
+ {
+ WARN_PRINTF2(_L("Data append failed [%d]"), error);
+ iBreathSaver->End();
+ writeFail = ETrue;
+ }
+ }
+ header = EFalse;
+ }
+ }
+ // Header is already removed from the input data
+ else
+ {
+ // Write data into file
+ if (savename != KNoFileSave ||
+ datadealerid != KNoDataDealer)
+ {
+ error = iBreathSaver->Append(buffer);
+ if (error != KErrNone)
+ {
+ WARN_PRINTF2(_L("Data append failed [%d]"), error);
+ iBreathSaver->End();
+ writeFail = ETrue;
+ }
+ }
+ }
+ }
+ else
+ {
+ // KErrEof means that socket was closed or there is not any data to be read anymore
+ ERR_PRINTF2(_L("RecvOneOrMore returned error status [%d]"), status.Int());
+ }
+ // Check if duration parameter is given
+ if (duration != KNoDuration)
+ {
+ iEnd.HomeTime();
+ TTimeIntervalSeconds seconds (0);
+ error = iEnd.SecondsFrom(iStart, seconds);
+ if(error != KErrNone)
+ {
+ ERR_PRINTF2(_L("Failed to get time interval with error %d"), error);
+ SetError(error);
+ break;
+ }
+ if ( seconds.Int() >= duration )
+ {
+ WARN_PRINTF2(_L("Transfer is stopped because defined duration [%d] exceeded"), seconds.Int());
+ break;
+ }
+ }
+ }
+ while(status == KErrNone && writeFail == EFalse);
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdDownloadToFile"));
+ }
+
+/**
+ * Ends downloaded file.
+ * @param aSection - The section in config file to look for file's name.
+ * @return error - Error code. KErrNone if successful.
+ */
+void CT_RSocketData::DoCmdUtilityEndFile(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdUtilityEndFile"));
+ TBool dataOk = ETrue;
+
+ TPtrC savename( KNoFileSave );
+ if(!GetStringFromConfig(aSection, KSaveName, savename))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KSaveName);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ if (savename != KNoFileSave)
+ {
+ iBreathSaver->End();
+ }
+
+ iEnd.HomeTime();
+
+ INFO_PRINTF1(_L("Download ends"));
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdUtilityEndFile"));
+ }
+
+/**
+ * Calculates download time and compares with a given duration and speed
+ * @param aSection - The section in config file to look for speed and duration parameters.
+ */
+void CT_RSocketData::DoCmdUtilityCalculateDownloadStats(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdUtilityCalculateDownloadStats"));
+ TBool dataOk = ETrue;
+
+ TInt speed( KNoSpeedCheck );
+ if(!GetIntFromConfig(aSection, KMinimumSpeed, speed))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KMinimumSpeed);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TInt duration( KNoDuration );
+ if(!GetIntFromConfig(aSection, KDuration, duration ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KDuration);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ // Calculate the duration of the download.
+ TTimeIntervalMicroSeconds microseconds = iEnd.MicroSecondsFrom(iStart);
+ TInt error = KErrNone;
+ TReal throughput = 0;
+
+ if (iTotalReceived != 0)
+ {
+ throughput = ThroughputInKiloBits( microseconds, iTotalReceived );
+ }
+
+ error = SetThroughput(throughput);
+ if (error == KErrNone)
+ {
+ TBool speedEnough = ETrue;
+ if (speed != KNoSpeedCheck)
+ {
+ INFO_PRINTF2(_L("Check that the download speed was faster than (%d kpbs)"), speed);
+ if ( speed > throughput )
+ {
+ ERR_PRINTF1(_L("Speed was not fast enough"));
+ SetBlockResult(EFail);
+ speedEnough = EFalse;
+ }
+ else
+ {
+ INFO_PRINTF1(_L("Speed was fast enough"));
+ }
+ }
+
+ if (speedEnough && duration != KNoDuration)
+ {
+ TTimeIntervalSeconds seconds (0);
+ error = iEnd.SecondsFrom(iStart, seconds);
+ if(error != KErrNone)
+ {
+ ERR_PRINTF2(_L("Failed to get time interval with error %d"), error);
+ SetError(error);
+ }
+ else if ( seconds.Int() < duration )
+ {
+ ERR_PRINTF2(_L("Transfer failed, transfer did not last the defined duration [%d]"), duration);
+ SetBlockResult(EFail);
+ }
+ }
+ }
+ else
+ {
+ ERR_PRINTF2(_L("SetThroughput failed [%d]"), error);
+ SetError(error);
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdUtilityCalculateDownloadStats"));
+ }
+
+
+void CT_RSocketData::DoCmdInfoL(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdInfoL"));
+ TBool dataOk = ETrue;
+
+ TPtrC protocol;
+ if(!GetStringFromConfig(aSection, KProtocol, protocol))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KProtocol);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if(dataOk)
+ {
+ TProtocolDesc protocolDesc;
+ TInt err = iSocket->Info(protocolDesc);
+ if(err != KErrNone)
+ {
+ ERR_PRINTF2(_L("Getting Info failed with error %d"), err);
+ SetError(err);
+ }
+
+ TInt* protocolApi = static_cast<TInt*>(GetDataObjectL(protocolDesc.iName));
+ TInt* protocolIni = static_cast<TInt*>(GetDataObjectL(protocol));
+
+ if(protocolApi != protocolIni)
+ {
+ ERR_PRINTF3(_L("Mismatch between expected protocol [%S] and current protocol [%S]"),protocolIni, protocolApi);
+ SetBlockResult(EFail);
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdInfoL"));
+ }
+
+
+/**
+ * Build http post request
+ */
+void CT_RSocketData::DoCmdUtilityBuildRequest(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdUtilityBuildRequest"));
+ TBool dataOk = ETrue;
+
+ INFO_PRINTF1(_L("Sending HTTP request"));
+ TPtrC address( KNullDesC );
+ if(!GetStringFromConfig(aSection, KAddress, address ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KAddress);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ TInt bytes;
+ if(!GetIntFromConfig(aSection, KBytes, bytes ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KBytes);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+ TPtrC requestLogFile;
+ if(!GetStringFromConfig(aSection, KRequestLogFile, requestLogFile ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KRequestLogFile);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ // Construct request
+ iRequest.Append(KHTTPPOST);
+ iRequest.Append(KHTTPSeparator);
+ iRequest.Append(KServerScript);
+ iRequest.Append(KHTTPSeparator);
+ iRequest.Append(KHTTPSuffix);
+ iRequest.Append(KLineBreak);
+
+ iRequest.Append(KHost);
+ iRequest.Append(KHTTPSeparator);
+ iRequest.Append(address);
+ iRequest.Append(KLineBreak);
+
+ iRequest.Append(KFrom);
+ iRequest.Append(KHTTPSeparator);
+ iRequest.Append(KAhti);
+ iRequest.Append(KLineBreak);
+
+ iRequest.Append(KContentType);
+ iRequest.Append(KHTTPSeparator);
+ iRequest.Append(KMultipartType);
+ iRequest.Append(KHTTPSeparator);
+ iRequest.Append(KBoundary);
+ iRequest.Append(KLineBreak);
+
+ iRequest.Append(KContentLength);
+ iRequest.Append(KHTTPSeparator);
+ // Request size + size of the data to be sent. Server must know how much
+ // data is coming.
+ iRequest.AppendNum(KHeaderWithoutData+bytes);
+ iRequest.Append(KLineBreak);
+
+ // extra line break
+ iRequest.Append(KLineBreak);
+
+ iRequest.Append(KBoundaryStart);
+ iRequest.Append(KLineBreak);
+
+ iRequest.Append(KContentDisposition);
+ iRequest.Append(KHTTPSeparator);
+ iRequest.Append(KDisposition);
+ iRequest.Append(KLineBreak);
+
+ iRequest.Append(KContentType);
+ iRequest.Append(KHTTPSeparator);
+ iRequest.Append(KOctetType);
+ iRequest.Append(KLineBreak);
+
+ iRequest.Append(KLineBreak);
+
+ // Make a log file of the request
+ TFileName fileName;
+ TDriveUnit driveUnit(EDriveC);
+ fileName.Zero();
+ fileName.Append(driveUnit.Name()); // c:
+ fileName.Append(requestLogFile);
+ iBreathSaver->StartFile(fileName);
+
+ iBreathSaver->Append(iRequest);
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdUtilityBuildRequest"));
+ }
+
+void CT_RSocketData::DoCmdWrite(const TInt aAsyncErrorIndex)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdWrite"));
+
+ // Send the header before data
+ iSocket->Write(iRequest, iActiveCallback->iStatus);
+ iActiveCallback->Activate(aAsyncErrorIndex);
+ IncOutstanding();
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdWrite"));
+ }
+
+void CT_RSocketData::DoCmdSendBytesToSocket(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdSendBytesToSocket"));
+ TBool dataOk = ETrue;
+
+ TInt bytes;
+ if(!GetIntFromConfig(aSection, KBytes, bytes ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KBytes);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+ TInt duration ( KNoDuration );
+ if(!GetIntFromConfig(aSection, KDuration, duration ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KDuration);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+
+ if (dataOk)
+ {
+ TInt error = SendBytesToSocket(bytes, duration);
+ if (error != KErrNone)
+ {
+ ERR_PRINTF1(_L("Error in sending bytes to socket"));
+ SetError(error);
+ }
+ }
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdSendBytesToSocket"));
+ }
+
+void CT_RSocketData::DoCmdUtilityEndRequest()
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdUtilityEndRequest"));
+
+ iRequest.Delete(0, iRequest.Length());
+ // Now the rest of the header data
+ iRequest.Append(KLineBreak);
+
+ iRequest.Append(KBoundaryEnd);
+ iRequest.Append(KLineBreak);
+
+ // add the rest of the reaquest to log file
+ iBreathSaver->Append(iRequest);
+ iBreathSaver->End(); // Close the file
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdUtilityEndRequest"));
+ }
+
+void CT_RSocketData::DoCmdResponseFromServer(const TTEFSectionName& aSection)
+ {
+ INFO_PRINTF1(_L("*START* CT_RSocketData::DoCmdResponseFromServer"));
+ TBool dataOk = ETrue;
+ TPtrC responseLogFile;
+ if(!GetStringFromConfig(aSection, KResponseLogFile, responseLogFile ))
+ {
+ ERR_PRINTF2(_L("Error in getting parameter %S from INI file"), &KResponseLogFile);
+ SetBlockResult(EFail);
+ dataOk = EFalse;
+ }
+ if(dataOk)
+ {
+ // After file was succesfully sent to HTTP server we can receive the response
+ // from the server.
+ // Create variables for receive buffer and received data counting variables.
+
+ TBuf8<KBufferSize> buffer;
+ TSockXfrLength received;
+ TRequestStatus status;
+
+ TFileName fileName;
+ TDriveUnit driveUnit(EDriveC);
+ fileName.Zero();
+ fileName.Append(driveUnit.Name()); // c:
+ fileName.Append(responseLogFile);
+
+ iBreathSaver->StartFile(fileName);
+ // receive until RecvOneOrMore fails.
+ do
+ {
+ iSocket->RecvOneOrMore(buffer, 0, status, received);
+ User::WaitForRequest(status);
+
+ iBreathSaver->Append(buffer);
+ }
+ while(status.Int() == KErrNone);
+
+ iBreathSaver->End();
+ }
+
+
+ INFO_PRINTF1(_L("*END* CT_RSocketData::DoCmdResponseFromServer"));
+ }
+
+/**
+ * Send Bytes to the socket
+ * @param TInt How many bytes are sent
+ * @return Symbian error code
+ */
+TInt CT_RSocketData::SendBytesToSocket(TInt aBytes, TInt aDuration)
+ {
+ const TInt KDataBufferSize = 256;
+ TBuf8<KDataBufferSize> data;
+ data.SetMax();
+ data.FillZ();
+ TInt bytesSent = 0;
+
+ TRequestStatus status;
+
+ INFO_PRINTF1(_L("Uploading bytes to server"));
+ iStart.HomeTime();
+
+ // Loop while enough bytes are sent to socket
+ while (bytesSent < aBytes)
+ {
+ if ((aBytes - bytesSent) < KDataBufferSize)
+ {
+ // this is the last round where we don't send full buffer anymore
+ data.SetLength(aBytes - bytesSent);
+ iSocket->Write(data, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone)
+ {
+ ERR_PRINTF2(_L("Failed to send data to socket [%d]"), status.Int());
+ return status.Int();
+ }
+
+ bytesSent += (aBytes - bytesSent);
+ // We can break because there are no more data to be send
+ break;
+ }
+ iSocket->Write(data, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone)
+ {
+ ERR_PRINTF2(_L("Failed to send data to socket [%d]"), status.Int());
+ return status.Int();
+ }
+
+ bytesSent += KDataBufferSize;
+
+ if (aDuration != KNoDuration)
+ {
+ iEnd.HomeTime();
+ TTimeIntervalSeconds seconds (0);
+ TInt error = iEnd.SecondsFrom(iStart, seconds);
+ if (error != KErrNone)
+ {
+ ERR_PRINTF2(_L("Failed to get time interval with error %d"), error);
+ return error;
+ }
+ if ( seconds.Int() >= aDuration )
+ {
+ // Transfer has lasted long enough. Let's stop transfer
+ INFO_PRINTF2(_L("Transfer is stopped because defined duration [%d] exceeded"), seconds.Int());
+ break;
+ }
+ }
+ }
+
+ iEnd.HomeTime();
+
+ TTimeIntervalMicroSeconds microseconds = iEnd.MicroSecondsFrom(iStart);
+
+ // Calculate the upload speed
+ TInt error=0;
+ TReal throughput = 0;
+ if (bytesSent != 0)
+ {
+ throughput = ThroughputInKiloBits( microseconds, bytesSent );
+ }
+ error= SetThroughput(throughput);
+
+ if (error != KErrNone)
+ {
+ ERR_PRINTF2(_L("SetThroughput failed [%d]"), error);
+ return error;
+ }
+
+ if (aDuration != KNoDuration)
+ {
+ // Close the socket because next we try to read response from the server and it won't come
+ // because transfer is cut early (server waits until all bytes are sent or socket is closed)
+ iSocket->Shutdown(RSocket::ENormal, status);
+ User::WaitForRequest(status);
+
+ TTimeIntervalSeconds seconds (0);
+ TInt error = iEnd.SecondsFrom(iStart, seconds);
+ if (error != KErrNone)
+ {
+ ERR_PRINTF2(_L("Failed to get time interval with error %d"), error);
+ return error;
+ }
+ if ( seconds.Int() < aDuration )
+ {
+ // Transfer didn't last the defined duration!
+ ERR_PRINTF2(_L("Transfer failed, transfer did not last the defined duration [%d]"), aDuration);
+ return KErrEof;
+ }
+ else
+ {
+ // If duration was used and socket was closed early return KErrCancel (it won't cause the
+ // whole test case to fail
+ return KErrCancel;
+ }
+ }
+
+ return KErrNone;
+ }
+
+
+
+/**
+ * Calculates throughput based on duration of a data transfer and total transferred bytes.
+ * @param aDuration Duration of the transfer.
+ * @param aTotalTransferred Total transferred data length in bytes.
+ * @return Throughput in KBps.
+ */
+TReal CT_RSocketData::ThroughputInKiloBits( TTimeIntervalMicroSeconds aDuration, TInt aBytes )
+ {
+ const TReal KKiloConversion(1000.0);
+ TReal throughput = ThroughputInMegaBits( aDuration, aBytes ) * KKiloConversion;
+
+ return throughput;
+ }
+
+
+/**
+ * Calculates throughput based on duration of a data transfer and total transferred bytes.
+ * @param aDuration Duration of the transfer.
+ * @param aTotalTransferred Total transferred data length 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;
+ }
+
+/**
+ * Set throughput into RProperty
+ * @param aThroughput The calculated throughput
+ */
+TInt CT_RSocketData::SetThroughput( const TReal aThroughput )
+ {
+ TInt err = RProperty::Define( iPropertyCategory, iPropertyKey, RProperty::EByteArray );
+
+ if( err == KErrAlreadyExists )
+ {
+ INFO_PRINTF1(_L( "Property already exists. Contents will be overridden") );
+ err = KErrNone;
+ }
+
+ if (err == KErrNone)
+ {
+ // Convert throughput value (TReal) into descriptor
+ TBuf8<256> amount;
+ TRealFormat realFormat;
+ err = amount.AppendNum( aThroughput, realFormat );
+ // Set property value
+ err = RProperty::Set( iPropertyCategory, iPropertyKey, amount );
+ }
+ else
+ {
+ ERR_PRINTF2(_L( "Could not create pub&sub property: %d"), err );
+ }
+
+ return err;
+ }
+
+/**
+Check if RMobileCall has HSDPA indicator
+@return TBool value of the indicator
+*/
+TBool CT_RSocketData::CheckHSDPAIndicator()
+ {
+ RMobilePhone::TMobilePhoneNetworkInfoV5 networkInfo;
+ return networkInfo.iHsdpaAvailableIndicator;
+ }
+
+/**
+Check if RPacketService has HSDPA support
+@param RMobileCall aMobileCall
+@return TBool value of the indicator
+*/
+TBool CT_RSocketData::CheckHSDPASupportL(RMobilePhone &aMobilePhone)
+ {
+ RPacketService packetservice;
+
+ CleanupClosePushL(packetservice);
+ User::LeaveIfError(packetservice.Open(aMobilePhone));
+ TUint caps;
+ // Ask for static capabilities using CDMA context
+ TInt error = packetservice.GetStaticCaps(caps, RPacketContext::EPdpTypeCDPD);
+ CleanupStack::PopAndDestroy(&packetservice); // RPacketService.Close()
+
+ User::LeaveIfError(error);
+
+ return caps & RPacketService::KCapsHSDPASupported;
+ }
+
+/**
+Check if RPacketService is currently using HSDPA
+@param RMobileCall aMobileCall
+@return TBool value of the indicator
+*/
+TBool CT_RSocketData::CheckHSDPAUsageL(RMobilePhone &aMobilePhone)
+ {
+ RPacketService ps;
+
+ CleanupClosePushL(ps);
+ User::LeaveIfError(ps.Open(aMobilePhone));
+ RPacketService::TDynamicCapsFlags caps;
+ TInt error = ps.GetDynamicCaps(caps);
+ CleanupStack::PopAndDestroy(&ps); // RPacketService
+
+ User::LeaveIfError(error);
+
+ return caps & RPacketService::KCapsHSDPA;
+ }