diff -r 000000000000 -r b16258d2340f applayerpluginsandutils/httptransportplugins/httptransporthandler/csocket.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/applayerpluginsandutils/httptransportplugins/httptransporthandler/csocket.cpp Tue Feb 02 01:09:52 2010 +0200 @@ -0,0 +1,410 @@ +// Copyright (c) 2003-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 "csocket.h" +#include "chttpsecuresocket.h" +#include "mcommsinfoprovider.h" +#include "thttptrlayerpanic.h" + +#include +#include +#include + +const TInt KDefaultFlags = 0; +const TInt KTcpTriggeredKeepAlive = 2; +const TInt KSocketRecvBufSize = 16 * 1024; +const TInt KSocketSendBufSize = 16 * 1024; +const TInt KSocketDefaultSendBufSize = 4 * 1024; + +CSocket* CSocket::NewL(MCommsInfoProvider& aCommsInfoProvider, TSocketType aSocketType) +/** + The factory constructor. + @param aCommsInfoProvider The comms info provider object. + @param aSocketType The type of the socket. + @return A pointer to a fully constructed object. +*/ + { + CSocket* self = new (ELeave) CSocket(aCommsInfoProvider); + CleanupStack::PushL(self); + self->ConstructL(aSocketType); + CleanupStack::Pop(self); + return self; + } + +CSocket::~CSocket() +/** + Destructor. +*/ + { + // Close socket and notify the socket status observer + if( iSecureSocketController ) + delete iSecureSocketController; + else + iSocket.Close(); + } + +CSocket::CSocket(MCommsInfoProvider& aCommsInfoProvider) +: CBase(), iCommsInfoProvider(aCommsInfoProvider) +/** + Constructor. + @param aCommsInfoProvider The comms info provider object. +*/ + { + } + +void CSocket::ConstructL(TSocketType aSocketType) +/** + Second phase constructor. + @param aSocketType The type of the socket. +*/ + { + switch( aSocketType ) + { + case EProtocolSocket: + { + if ( iCommsInfoProvider.HasConnection() ) + { + // Open a protocol socket with a RConnection + User::LeaveIfError(iSocket.Open( + iCommsInfoProvider.SocketServer(), + iCommsInfoProvider.ProtocolDescription().iAddrFamily, + iCommsInfoProvider.ProtocolDescription().iSockType, + iCommsInfoProvider.ProtocolDescription().iProtocol, + iCommsInfoProvider.Connection() + )); + } + else + { + // Open a protocol socket without a RConnection, we don't need one ( Loopback address ) + User::LeaveIfError(iSocket.Open( + iCommsInfoProvider.SocketServer(), + iCommsInfoProvider.ProtocolDescription().iAddrFamily, + iCommsInfoProvider.ProtocolDescription().iSockType, + iCommsInfoProvider.ProtocolDescription().iProtocol + )); + } + } break; + case EBlankSocket: + { + // Open a blank socket + User::LeaveIfError(iSocket.Open(iCommsInfoProvider.SocketServer())); + } break; + default: + User::Invariant(); + } + TInt id = iCommsInfoProvider.SessionId(); + if(id>=0) + { + // set socket option + iSocket.SetOpt(KSOHttpSessionId, KSOLHttpSessionInfo, id); + iSocket.SetOpt(KSoTcpKeepAlive, KSolInetTcp, KTcpTriggeredKeepAlive); + } + if(aSocketType != EBlankSocket) + { + iSocket.SetOpt(KSoTcpNoDelay,KSolInetTcp,1); // Disable the nagle. + iSocket.SetOpt(KSORecvBuf, KSOLSocket, KSocketRecvBufSize); // Set the socket recv buf to be 16K + } + } + +TInt CSocket::Listen(TUint aQSize, TUint16 aPort) +/** + Start the listen service. The socket is bound to the local port specified by + aPort. The listen service is then started. The aQSize argument specifies the + number of connections that can be received simultaneously, awaiting to be + accepted. + @param aQSize The length of the listening queue. + @param aPort The local port number on which to listen. + @return A value of KErrNone if the listen service was successfully + started. +*/ + { + // Bind the socket to the port + TSockAddr addr; + addr.SetPort(aPort); + + TInt error = iSocket.Bind(addr); + + if( error == KErrNone ) + { + // Start the listening service + error = iSocket.Listen(aQSize); + } + return error; + } + +void CSocket::Accept(CSocket& aBlankSocket, TRequestStatus& aStatus) +/** + Start asynchronous accept service. The socket should have had the listening + service started. When a connection has been received, the blank socket will + be given the connection. The request status is completed either when a + connection is received or an error has occured - this is reflected in the + value of the request status. + @param aBlankSocket The blank socket which will be given the + connection if one is received. + @param aStatus The request status that is completed when the + accept service completes. +*/ + { + if( iSecureSocketController ) + { + // Secure socket do not support secure listening + aStatus=KRequestPending; + TRequestStatus* pStat = &aStatus; + User::RequestComplete(pStat, KErrNotSupported); + } + else + iSocket.Accept(aBlankSocket.iSocket, aStatus); + } + +void CSocket::CancelAccept() +/** + Cancel the accept service. +*/ + { + iSocket.CancelAccept(); + } + +void CSocket::Connect(TInetAddr& aAddr, TRequestStatus& aStatus) +/** + Start asynchronous connect service. The address contains the IP address and + port with which a tcp connection should be established with. The request + status is completed either when a connection has been established or an error + has occurred - this is reflected in the value of the request status. + @param aAddr The IP address and port of the remote host. + @param aStatus The request status that is completed when the connect + service completes. +*/ + { + iSocket.Connect(aAddr, aStatus); + } + +void CSocket::CancelConnect() +/** + Cancel the connect service. +*/ + { + iSocket.CancelConnect(); + } + +void CSocket::RecvOneOrMore(TDes8& aBuffer, TRequestStatus& aStatus) +/** + Receive data from socket asynchronously. Any data received by the socket is + placed in the buffer supplied by aBuffer. The request status is completed + either when data has been received or an error has occurred - this is + reflected in the value of the request status. + @param aBuffer The buffer where any received data is placed. + @param aStatus The request status that is completed when the receive + service completes. +*/ + { + if( iSecureSocketController ) + // aFlags not used for secure sockets + iSecureSocketController->RecvOneOrMore(aBuffer, aStatus, iBytesReceived); + else + iSocket.RecvOneOrMore(aBuffer, KDefaultFlags, aStatus, iBytesReceived); + } + +void CSocket::CancelRecv() +/** + Cancel the receive service. +*/ + { + if( iSecureSocketController ) + iSecureSocketController->CancelRecv(); + else + iSocket.CancelRecv(); + } + +void CSocket::Send(const TDesC8& aBuffer, TRequestStatus& aStatus) +/** + Send data to the socket asynchronously. The data in the supplied buffer is + sent to the socket. The request status is completed either when data has + been sent or an error has occurred - this is reflected in the value of the + request status. + @param aBuffer The buffer containing the data to be sent. + @param aStatus The request status that is completed when the send + service completes. +*/ + { + if( iSecureSocketController ) + iSecureSocketController->Send(aBuffer, aStatus); + else + iSocket.Write(aBuffer, aStatus); + } + +void CSocket::CancelSend() +/** + Cancel the send service. +*/ + { + if( iSecureSocketController ) + iSecureSocketController->CancelSend(); + else + iSocket.CancelWrite(); + } + +void CSocket::Shutdown(TRequestStatus& aStatus) +/** + Shutdown the connection asynchronously. Any pending receive or send requests + are allowed to complete before the connection is shutdown. The request + status is completed when either the connection has shutdown or an error has + occurred - this is reflected in the value of the request status. This request + cannot be cancelled. This method does not apply to secure connections. The + request will complete with KErrNotSupported if used with a secure connection. + @param aStatus The request status that is completed when the shutdown + service completes. +*/ + { + if( iSecureSocketController ) + { + // Not supported with secure connections + aStatus=KRequestPending; + TRequestStatus* pStat = &aStatus; + User::RequestComplete(pStat, KErrNotSupported); + } + else + iSocket.Shutdown(RSocket::ENormal, aStatus); + } + +void CSocket::ShutdownImmediate() +/** + Shutdown the connection synchronously. This method will shutdown the socket + connection immediately using the abortive closing functionality. This method + has no effect with secure connections. +*/ + { + if( iSecureSocketController==NULL ) + { + TRequestStatus shutdownStatus = KRequestPending; + iSocket.Shutdown(RSocket::EImmediate, shutdownStatus); + User::WaitForRequest(shutdownStatus); + } + } + +void CSocket::RemoteName(TInetAddr& aAddr) +/** + Get the remote host name. The IP address and port of the remote host is set + in the output argument. + @param aAddr The output argument where the IP address and port of the + remote host is placed. +*/ + { + iSocket.RemoteName(aAddr); + } + +void CSocket::LocalName(TInetAddr& aAddr) +/** + Get the local socket name. The IP address and port of the local socket is + set in the output argument. + @param aAddr The output argument where the IP address and port of the + local socket is placed. +*/ + { + iSocket.LocalName(aAddr); + } + +const CX509Certificate* CSocket::ServerCert() + /** + Get the Server Certificate for this socket session. + @return A Certificate with the certificate information. This may be + NULL if the information is not available. + */ + { + if( iSecureSocketController ) + { + return iSecureSocketController->ServerCert(); + } + return NULL; + } + + +TInt CSocket::CipherSuite(TDes8& aCipherSuite) +/** + Get the current Cipher Suite for this socket session. + @param aCiptherSuite A descriptor which will be filled with the cipher suite. + This is a 2 digit code as defined by RFC 2246. + @return An error code. KErrNone on sucess. KErrNotSupported if this socket session is not secure. +*/ + { + if (iSecureSocketController) + return iSecureSocketController->CipherSuite(aCipherSuite); + //else + return KErrNotSupported; + } + +void CSocket::UpgradeToSecureL(TRequestStatus& aStatus, const TDesC8& aHostName) +/** + Asynchronous request to upgrade the socket to a secure socket. + @param aStatus The request status, this will complete with KErrNone on the successful + upgrade to a secure connection. + @param aHostName The host name of the server used for domain name checking +*/ + { + // Check that the socket is already a secure one. + if( iSecureSocketController ) + { + // The socket connection is already secure, simply complete the request + aStatus=KRequestPending; + TRequestStatus* pStat = &aStatus; + User::RequestComplete(pStat, KErrNone); + } + else + { + // Create the secure socket controller and start the secure handshake + TRAPD(error, iSecureSocketController = CHttpSecureSocket::NewL(iSocket, iCommsInfoProvider)); + if (error == KErrNotFound || error == KEComErrNoInterfaceIdentified) + User::Leave(KErrNotSupported); + else if (error != KErrNone) + User::Leave(error); + iSecureSocketController->StartSecureHandshakeL(aStatus, aHostName); + } + } + +void CSocket::CancelUpgradeToSecure() +/** + Cancel the upgrade to a secure connection. +*/ + { + if( iSecureSocketController ) + iSecureSocketController->CancelHandshake(); + } + +TInt CSocket::PendingBytesToRead () + { + if ( iSecureSocketController ) + return iSecureSocketController->PendingBytesToRead (); + TInt bytesToRead; + TInt err = iSocket.GetOpt ( KSOReadBytesPending, KSOLSocket, bytesToRead ); + if ( err == KErrNone ) + return bytesToRead; + return err; + } + +void CSocket::SetTCPCorking(TBool aValue) + { + if(aValue) + { + iSocket.SetOpt(KSoTcpNoDelay,KSolInetTcp,0); // Disable the nagle. + iSocket.SetOpt(KSOSendBuf, KSOLSocket, KSocketSendBufSize); + } + else + { + iSocket.SetOpt(KSoTcpNoDelay,KSolInetTcp,1); // Disable the nagle. + iSocket.SetOpt(KSOSendBuf, KSOLSocket, KSocketDefaultSendBufSize); + } + + iSocket.SetOpt(KSoTcpCork, KSolInetTcp, aValue); + + }