applayerpluginsandutils/httptransportplugins/httptransporthandler/csocket.cpp
changeset 0 b16258d2340f
child 7 337070b4fa18
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "csocket.h"
       
    17 #include "chttpsecuresocket.h"
       
    18 #include "mcommsinfoprovider.h"
       
    19 #include "thttptrlayerpanic.h"
       
    20 
       
    21 #include  <http/rhttpconnectioninfo.h>
       
    22 #include <httpsocketconstants.h>
       
    23 #include <in6_opt.h> 
       
    24 
       
    25 const TInt KDefaultFlags		= 0;
       
    26 const TInt KTcpTriggeredKeepAlive	= 2;
       
    27 const TInt KSocketRecvBufSize = 16 * 1024;
       
    28 const TInt KSocketSendBufSize = 16 * 1024;
       
    29 const TInt KSocketDefaultSendBufSize = 4 * 1024;
       
    30 
       
    31 CSocket* CSocket::NewL(MCommsInfoProvider& aCommsInfoProvider, TSocketType aSocketType)
       
    32 /**	
       
    33 	The factory constructor.
       
    34 	@param		aCommsInfoProvider	The comms info provider object.
       
    35 	@param		aSocketType			The type of the socket.
       
    36 	@return		A pointer to a fully constructed object.
       
    37 */
       
    38 	{
       
    39 	CSocket* self = new (ELeave) CSocket(aCommsInfoProvider);
       
    40 	CleanupStack::PushL(self);
       
    41 	self->ConstructL(aSocketType);
       
    42 	CleanupStack::Pop(self);
       
    43 	return self;
       
    44 	}
       
    45 
       
    46 CSocket::~CSocket()
       
    47 /**
       
    48 	Destructor.
       
    49 */
       
    50 	{
       
    51 	// Close socket and notify the socket status observer
       
    52 	if( iSecureSocketController )
       
    53 		delete iSecureSocketController;
       
    54 	else
       
    55 		iSocket.Close();
       
    56 	}
       
    57 
       
    58 CSocket::CSocket(MCommsInfoProvider& aCommsInfoProvider)
       
    59 : CBase(), iCommsInfoProvider(aCommsInfoProvider)
       
    60 /**	
       
    61 	Constructor.
       
    62 	@param		aCommsInfoProvider	The comms info provider object.
       
    63 */
       
    64 	{
       
    65 	}
       
    66 
       
    67 void CSocket::ConstructL(TSocketType aSocketType)
       
    68 /**	
       
    69 	Second phase constructor.
       
    70 	@param		aSocketType	The type of the socket.
       
    71 */
       
    72 	{
       
    73 	switch( aSocketType )
       
    74 		{
       
    75 	case EProtocolSocket:
       
    76 		{
       
    77 		if ( iCommsInfoProvider.HasConnection() )
       
    78 			{
       
    79 			// Open a protocol socket with a RConnection
       
    80 			User::LeaveIfError(iSocket.Open(
       
    81 										   iCommsInfoProvider.SocketServer(),
       
    82 										   iCommsInfoProvider.ProtocolDescription().iAddrFamily, 
       
    83 										   iCommsInfoProvider.ProtocolDescription().iSockType, 
       
    84 										   iCommsInfoProvider.ProtocolDescription().iProtocol,
       
    85 										   iCommsInfoProvider.Connection()
       
    86 										   ));				
       
    87 			}
       
    88 		else
       
    89 			{
       
    90 			// Open a protocol socket without a RConnection, we don't need one ( Loopback address )
       
    91 			User::LeaveIfError(iSocket.Open(
       
    92 										   iCommsInfoProvider.SocketServer(),
       
    93 										   iCommsInfoProvider.ProtocolDescription().iAddrFamily, 
       
    94 										   iCommsInfoProvider.ProtocolDescription().iSockType, 
       
    95 										   iCommsInfoProvider.ProtocolDescription().iProtocol
       
    96 										   ));											
       
    97 			}
       
    98 		} break;
       
    99 	case EBlankSocket:
       
   100 		{
       
   101 		// Open a blank socket
       
   102 		User::LeaveIfError(iSocket.Open(iCommsInfoProvider.SocketServer()));
       
   103 		} break;
       
   104 	default:
       
   105 		User::Invariant();
       
   106 		}
       
   107 	TInt id = iCommsInfoProvider.SessionId();
       
   108 	if(id>=0) 
       
   109 		{
       
   110 		// set socket option
       
   111 		iSocket.SetOpt(KSOHttpSessionId, KSOLHttpSessionInfo, id);
       
   112 		iSocket.SetOpt(KSoTcpKeepAlive, KSolInetTcp, KTcpTriggeredKeepAlive);
       
   113 		}
       
   114 	if(aSocketType != EBlankSocket)
       
   115 	    {
       
   116 	    iSocket.SetOpt(KSoTcpNoDelay,KSolInetTcp,1);  // Disable the nagle.
       
   117         iSocket.SetOpt(KSORecvBuf, KSOLSocket, KSocketRecvBufSize); // Set the socket recv buf to be 16K
       
   118 	    }
       
   119 	}
       
   120 
       
   121 TInt CSocket::Listen(TUint aQSize, TUint16 aPort)
       
   122 /**	
       
   123 	Start the listen service. The socket is bound to the local port specified by
       
   124 	aPort. The listen service is then started. The aQSize argument specifies the
       
   125 	number of connections that can be received simultaneously, awaiting to be 
       
   126 	accepted.
       
   127 	@param		aQSize		The length of the listening queue.
       
   128 	@param		aPort		The local port number on which to listen.
       
   129 	@return		A value of KErrNone if the listen service was successfully 
       
   130 				started.
       
   131 */
       
   132 	{
       
   133 	// Bind the socket to the port
       
   134 	TSockAddr addr;
       
   135 	addr.SetPort(aPort);
       
   136 
       
   137 	TInt error = iSocket.Bind(addr);
       
   138 
       
   139 	if( error == KErrNone )
       
   140 		{
       
   141 		// Start the listening service
       
   142 		error = iSocket.Listen(aQSize);
       
   143 		}
       
   144 	return error;
       
   145 	}
       
   146 
       
   147 void CSocket::Accept(CSocket& aBlankSocket, TRequestStatus& aStatus)
       
   148 /**	
       
   149 	Start asynchronous accept service. The socket should have had the listening
       
   150 	service started. When a connection has been received, the blank socket will
       
   151 	be given the connection. The request status is completed either when a 
       
   152 	connection is received or an error has occured - this is reflected in the 
       
   153 	value of the request status.
       
   154 	@param		aBlankSocket	The blank socket which will be given the 
       
   155 								connection if one is received.
       
   156 	@param		aStatus			The request status that is completed when the
       
   157 								accept service completes.
       
   158 */
       
   159 	{
       
   160 	if( iSecureSocketController )
       
   161 		{
       
   162 		// Secure socket do not support secure listening
       
   163 		aStatus=KRequestPending;
       
   164 		TRequestStatus* pStat = &aStatus;
       
   165 		User::RequestComplete(pStat, KErrNotSupported);
       
   166 		}
       
   167 	else
       
   168 		iSocket.Accept(aBlankSocket.iSocket, aStatus);
       
   169 	}
       
   170 
       
   171 void CSocket::CancelAccept()
       
   172 /**	
       
   173 	Cancel the accept service.
       
   174 */
       
   175 	{
       
   176 	iSocket.CancelAccept();
       
   177 	}
       
   178 
       
   179 void CSocket::Connect(TInetAddr& aAddr, TRequestStatus& aStatus)
       
   180 /**	
       
   181 	Start asynchronous connect service. The address contains the IP address and
       
   182 	port with which a tcp connection should be established with. The request 
       
   183 	status is completed either when a connection has been established or an error
       
   184 	has occurred - this is reflected in the value of the request status.
       
   185 	@param		aAddr	The IP address and port of the remote host.
       
   186 	@param		aStatus	The request status that is completed when the connect 
       
   187 						service completes.
       
   188 */
       
   189 	{
       
   190 	iSocket.Connect(aAddr, aStatus);
       
   191 	}
       
   192 
       
   193 void CSocket::CancelConnect()
       
   194 /**	
       
   195 	Cancel the connect service.
       
   196 */
       
   197 	{
       
   198 	iSocket.CancelConnect();
       
   199 	}
       
   200 
       
   201 void CSocket::RecvOneOrMore(TDes8& aBuffer, TRequestStatus& aStatus)
       
   202 /**	
       
   203 	Receive data from socket asynchronously. Any data received by the socket is 
       
   204 	placed in the buffer supplied by aBuffer. The request status is completed 
       
   205 	either when data has been received or an error has occurred - this is 
       
   206 	reflected in the value of the request status.
       
   207 	@param		aBuffer	The buffer where any received data is placed.	
       
   208 	@param		aStatus	The request status that is completed when the receive 
       
   209 						service completes.
       
   210 */
       
   211 	{
       
   212 	if( iSecureSocketController )
       
   213 		// aFlags not used for secure sockets
       
   214 		iSecureSocketController->RecvOneOrMore(aBuffer, aStatus, iBytesReceived);
       
   215 	else
       
   216 		iSocket.RecvOneOrMore(aBuffer, KDefaultFlags, aStatus, iBytesReceived);
       
   217 	}
       
   218 
       
   219 void CSocket::CancelRecv()
       
   220 /**	
       
   221 	Cancel the receive service.
       
   222 */
       
   223 	{
       
   224 	if( iSecureSocketController )
       
   225 		iSecureSocketController->CancelRecv();
       
   226 	else
       
   227 		iSocket.CancelRecv();
       
   228 	}
       
   229 
       
   230 void CSocket::Send(const TDesC8& aBuffer, TRequestStatus& aStatus)
       
   231 /**	
       
   232 	Send data to the socket asynchronously. The data in the supplied buffer is 
       
   233 	sent to the socket. The request status is completed either when data has 
       
   234 	been sent or an error has occurred - this is reflected in the value of the
       
   235 	request status.
       
   236 	@param		aBuffer	The buffer containing the data to be sent.
       
   237 	@param		aStatus	The request status that is completed when the send 
       
   238 						service completes.
       
   239 */
       
   240 	{
       
   241 	if( iSecureSocketController )
       
   242 		iSecureSocketController->Send(aBuffer, aStatus);
       
   243 	else
       
   244 		iSocket.Write(aBuffer, aStatus);
       
   245 	}
       
   246 
       
   247 void CSocket::CancelSend()
       
   248 /**	
       
   249 	Cancel the send service.
       
   250 */
       
   251 	{
       
   252 	if( iSecureSocketController )
       
   253 		iSecureSocketController->CancelSend();
       
   254 	else
       
   255 		iSocket.CancelWrite();
       
   256 	}
       
   257 
       
   258 void CSocket::Shutdown(TRequestStatus& aStatus)
       
   259 /**	
       
   260 	Shutdown the connection asynchronously. Any pending receive or send requests
       
   261 	are allowed to complete before the connection is shutdown. The request 
       
   262 	status is completed when either the connection has shutdown or an error has
       
   263 	occurred - this is reflected in the value of the request status. This request
       
   264 	cannot be cancelled. This method does not apply to secure connections. The
       
   265 	request will complete with KErrNotSupported if used with a secure connection.
       
   266 	@param		aStatus	The request status that is completed when the shutdown 
       
   267 						service completes.
       
   268 */
       
   269 	{
       
   270 	if( iSecureSocketController )
       
   271 		{
       
   272 		// Not supported with secure connections
       
   273 		aStatus=KRequestPending;
       
   274 		TRequestStatus* pStat = &aStatus;
       
   275 		User::RequestComplete(pStat, KErrNotSupported);
       
   276 		}
       
   277 	else
       
   278 		iSocket.Shutdown(RSocket::ENormal, aStatus);
       
   279 	}
       
   280 	
       
   281 void CSocket::ShutdownImmediate()
       
   282 /**	
       
   283 	Shutdown the connection synchronously. This method will shutdown the socket
       
   284 	connection immediately using the abortive closing functionality. This method
       
   285 	has no effect with secure connections.
       
   286 */
       
   287 	{
       
   288 	if( iSecureSocketController==NULL )
       
   289 		{
       
   290 		TRequestStatus shutdownStatus = KRequestPending;
       
   291 		iSocket.Shutdown(RSocket::EImmediate, shutdownStatus);
       
   292 		User::WaitForRequest(shutdownStatus);
       
   293 		}
       
   294 	}
       
   295 
       
   296 void CSocket::RemoteName(TInetAddr& aAddr)
       
   297 /**	
       
   298 	Get the remote host name. The IP address and port of the remote host is set
       
   299 	in the output argument.
       
   300 	@param		aAddr	The output argument where the IP address and port of the
       
   301 						remote host is placed.
       
   302 */
       
   303 	{
       
   304 	iSocket.RemoteName(aAddr);
       
   305 	}
       
   306 
       
   307 void CSocket::LocalName(TInetAddr& aAddr)
       
   308 /**	
       
   309 	Get the local socket name. The IP address and port of the local socket is 
       
   310 	set in the output argument.
       
   311 	@param		aAddr	The output argument where the IP address and port of the
       
   312 						local socket is placed.
       
   313 */
       
   314 	{
       
   315 	iSocket.LocalName(aAddr);
       
   316 	}
       
   317 
       
   318 const CX509Certificate* CSocket::ServerCert()
       
   319  /**
       
   320  	Get the Server Certificate for this socket session.
       
   321 	@return		A Certificate with the certificate information. This may be 
       
   322 				NULL if the information is not available.
       
   323  */
       
   324  	{
       
   325  	if( iSecureSocketController )
       
   326 		{
       
   327 		return iSecureSocketController->ServerCert();
       
   328 		}
       
   329 	return NULL;
       
   330  	}
       
   331  	
       
   332 	
       
   333 TInt CSocket::CipherSuite(TDes8& aCipherSuite)
       
   334 /**
       
   335 	Get the current Cipher Suite for this socket session.
       
   336 	@param		aCiptherSuite	A descriptor which will be filled with the cipher suite. 
       
   337 								This is a 2 digit code as defined by RFC 2246. 
       
   338 	@return		An error code. KErrNone on sucess. KErrNotSupported if this socket session is not secure.
       
   339 */
       
   340 	{
       
   341 	if (iSecureSocketController)
       
   342 		return iSecureSocketController->CipherSuite(aCipherSuite);
       
   343 	//else
       
   344 	return KErrNotSupported;
       
   345 	}
       
   346 
       
   347 void CSocket::UpgradeToSecureL(TRequestStatus& aStatus, const TDesC8& aHostName)
       
   348 /**
       
   349 	Asynchronous request to upgrade the socket to a secure socket.
       
   350 	@param	aStatus The request status, this will complete with KErrNone on the successful
       
   351 					upgrade to a secure connection.
       
   352 	@param	aHostName The host name of the server used for domain name checking
       
   353 */
       
   354 	{
       
   355 	// Check that the socket is already a secure one.
       
   356 	if( iSecureSocketController )
       
   357 		{
       
   358 		// The socket connection is already secure, simply complete the request
       
   359 		aStatus=KRequestPending;
       
   360 		TRequestStatus* pStat = &aStatus;
       
   361 		User::RequestComplete(pStat, KErrNone);
       
   362 		}
       
   363 	else
       
   364 		{
       
   365 		// Create the secure socket controller and start the secure handshake
       
   366 		TRAPD(error, iSecureSocketController = CHttpSecureSocket::NewL(iSocket, iCommsInfoProvider));
       
   367 		if (error == KErrNotFound || error == KEComErrNoInterfaceIdentified)
       
   368 			User::Leave(KErrNotSupported);
       
   369 		else if (error != KErrNone)
       
   370 			User::Leave(error);
       
   371 		iSecureSocketController->StartSecureHandshakeL(aStatus, aHostName);
       
   372 		}
       
   373 	}
       
   374 
       
   375 void CSocket::CancelUpgradeToSecure()
       
   376 /**
       
   377 	Cancel the upgrade to a secure connection.
       
   378 */
       
   379 	{
       
   380 	if( iSecureSocketController )
       
   381 		iSecureSocketController->CancelHandshake();
       
   382 	}
       
   383 
       
   384 TInt CSocket::PendingBytesToRead ()
       
   385 	{
       
   386     if ( iSecureSocketController )
       
   387 		    return iSecureSocketController->PendingBytesToRead ();
       
   388 	TInt bytesToRead;
       
   389 	TInt err = iSocket.GetOpt ( KSOReadBytesPending, KSOLSocket, bytesToRead );
       
   390 	if ( err == KErrNone )
       
   391 		return bytesToRead;
       
   392 	return err;
       
   393 	}
       
   394 	
       
   395 void CSocket::SetTCPCorking(TBool aValue)
       
   396     {
       
   397     if(aValue)
       
   398     	{
       
   399     	iSocket.SetOpt(KSoTcpNoDelay,KSolInetTcp,0);  // Disable the nagle.
       
   400       iSocket.SetOpt(KSOSendBuf, KSOLSocket, KSocketSendBufSize);
       
   401       }
       
   402     else
       
   403     	{
       
   404     	iSocket.SetOpt(KSoTcpNoDelay,KSolInetTcp,1);  // Disable the nagle.
       
   405       iSocket.SetOpt(KSOSendBuf, KSOLSocket, KSocketDefaultSendBufSize);        
       
   406       }
       
   407     
       
   408     iSocket.SetOpt(KSoTcpCork, KSolInetTcp, aValue);       
       
   409     
       
   410     }