applayerpluginsandutils/httptransportplugins/httptransporthandler/csocketreader.cpp
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2001-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 "csocketreader.h"
       
    17 
       
    18 #include "csocket.h"
       
    19 #include "msocketcontroller.h"
       
    20 #include "minputstreamobserver.h"
       
    21 #include "httptransporthandlercommon.h"
       
    22 #include "thttptrlayerpanic.h"
       
    23 #include "chttpasyncwaiter.h"
       
    24 
       
    25 CSocketReader* CSocketReader::NewL(CSocket& aSocket, MSocketController& aController, TInt aRecvBufferSize, TBool aPriority)
       
    26 /**	
       
    27 	The factory constructor.
       
    28 	@param		aSocket		The connected socket. This owned by the observer.
       
    29 	@param		aController	The socket controller that owns the socket.
       
    30 	@return		A pointer to a fully constructed object.
       
    31 	@internalComponent
       
    32 */
       
    33 	{
       
    34 	CSocketReader* self = new (ELeave) CSocketReader(aSocket, aController, aPriority);
       
    35 	CleanupStack::PushL(self);
       
    36 	self->ConstructL( aRecvBufferSize );
       
    37 	CleanupStack::Pop(self); 
       
    38 	return self;
       
    39 	}
       
    40 
       
    41 void CSocketReader::ConstructL( TInt aRecvBufferSize )
       
    42 	{
       
    43 	iBuffer.CreateL ( aRecvBufferSize );
       
    44 	}
       
    45 
       
    46 CSocketReader::~CSocketReader()
       
    47 /**	
       
    48 	Destructor.
       
    49 	@internalComponent
       
    50 */
       
    51 	{
       
    52 	__ASSERT_DEBUG( iState == EIdle || iState == EClosed, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EBadInputStreamState) );
       
    53     
       
    54 	//Delete the Timer Object.
       
    55 	delete iReceiveTimer;
       
    56 
       
    57 	// Cancel any outstanding requests
       
    58 	Cancel();
       
    59 	iBuffer.Close ();
       
    60 //	__FLOG_CLOSE;
       
    61 	}
       
    62 
       
    63 CSocketReader::CSocketReader(CSocket& aSocket, MSocketController& aController, TBool aPriority)
       
    64 : CActive(CActive::EPriorityStandard), iSocket(aSocket), iController(aController)
       
    65 /**	
       
    66 	Constructor.
       
    67 	@param		aSocket		The connected socket. This owned by the observer.
       
    68 	@param		aController	The socket controller that owns the socket.
       
    69 	@internalComponent
       
    70 */
       
    71 	{
       
    72 	if(aPriority)
       
    73 		{
       
    74 		CActive::SetPriority(CActive::EPriorityHigh);	
       
    75 		}
       
    76 	CActiveScheduler::Add(this);
       
    77 
       
    78 //	__FLOG_OPEN("http", "httptransporthandler.txt");
       
    79 	}
       
    80 
       
    81 void CSocketReader::CompleteSelf()
       
    82 /**	
       
    83 	Requests that the input stream complete itself. This will caused the RunL()
       
    84 	to be called by the scheduler at the next opportunity.
       
    85 	@pre		The input stream is not active.
       
    86 	@post		The input stream object is active and the request has been
       
    87 				completed.
       
    88 	@internalComponent				
       
    89 */
       
    90 	{
       
    91 	TRequestStatus* pStat = &iStatus;
       
    92 	User::RequestComplete(pStat, KErrNone);
       
    93 	SetActive();
       
    94 	}
       
    95 
       
    96 void CSocketReader::SocketClosed(TInt aError)
       
    97 /**	
       
    98 	Notifies the input stream that the socket is closed. The input stream 
       
    99 	observer is notified that the stream is closed. No more data can be received
       
   100 	from the socket.
       
   101 	@param		aError	The error code explaining why the socket has closed. A
       
   102 						value of KErrNone indicates that the output stream 
       
   103 						observer requested that the socket be closed.
       
   104 	@pre		None.
       
   105 	@post		The input stream is in the Closed state.
       
   106 	@internalComponent
       
   107 */
       
   108 	{
       
   109 	// Cancel any outstanding requests
       
   110 	Cancel();
       
   111 
       
   112 	// The socket has shutdown. Inform the input stream observer that the input
       
   113 	// stream is closed.
       
   114 	if( iObserver )
       
   115 		iObserver->InputStreamCloseInd(aError);
       
   116 
       
   117 	// Move to the Closed state
       
   118 	iState = EClosed;
       
   119 	}
       
   120 
       
   121 void CSocketReader::Suspend()
       
   122 /**
       
   123 	Notifies the input stream that it should suspend its activity.
       
   124 	@pre		The input stream is not already suspended.
       
   125 	@post		Any pending read is cancelled and the stream is suspended.
       
   126 	@internalComponent
       
   127 */
       
   128 	{
       
   129 	__ASSERT_DEBUG( !iSuspended, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EInputStreamAlreadySuspended) );
       
   130 
       
   131 	// Cancel any outstanding requests
       
   132 	Cancel();
       
   133 
       
   134 #if defined (_DEBUG) && defined (_LOGGING)
       
   135 	TBuf8<KIpv6MaxAddrSize> ip;
       
   136 	TUint16	remotePort;
       
   137 	TUint16 localPort;
       
   138 	iController.ConnectionInfo(ip, remotePort, localPort);
       
   139 
       
   140 	__FLOG_0(_T8("!! Suspending input stream"));
       
   141 	__FLOG_3(_T8("-> on local port %d with %S, remote port %d"), localPort, &ip, remotePort);
       
   142 #endif
       
   143 
       
   144 	// Check to see a read requests had been issued.
       
   145 	if( iState == EReceivedData )
       
   146 		{
       
   147 		// Yep - change to the Read state so that read request is re-issued when
       
   148 		// the stream resumes.
       
   149 		iState = ERead;
       
   150 		}
       
   151 
       
   152 	// Stream is now suspended.
       
   153 	iSuspended = ETrue;
       
   154 	}
       
   155 
       
   156 void CSocketReader::Resume()
       
   157 /**
       
   158 	Notifies the input stream that it should resume its activity.
       
   159 	@pre		The input stream is suspended.
       
   160 	@post		The stream resumes. A read request is issued if required. 
       
   161 	@internalComponent
       
   162 */
       
   163 	{
       
   164 	__ASSERT_DEBUG( iSuspended, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EInputStreamNotSuspended) );
       
   165 
       
   166 #if defined (_DEBUG) && defined (_LOGGING)
       
   167 	TBuf8<KIpv6MaxAddrSize> ip;
       
   168 	TUint16	remotePort;
       
   169 	TUint16 localPort;
       
   170 	iController.ConnectionInfo(ip, remotePort, localPort);
       
   171 
       
   172 	__FLOG_0(_T8("!! Resumimng input stream"));
       
   173 	__FLOG_3(_T8("-> on local port %d with %S, remote port %d"), localPort, &ip, remotePort);
       
   174 #endif
       
   175 
       
   176 	// Check to see a read requests needs to be issued.
       
   177 	if( iState == ERead )
       
   178 		{
       
   179 		// Yep - self complete to get the read request issued.
       
   180 		CompleteSelf();
       
   181 		}
       
   182 
       
   183 	// Stream is no longer suspended.
       
   184 	iSuspended = EFalse;
       
   185 	}
       
   186 
       
   187 /*
       
   188  *	Methods from MInputStream
       
   189  */
       
   190 
       
   191 void CSocketReader::Bind(MInputStreamObserver& aObserver)
       
   192 /**	
       
   193 	@see		MInputStream
       
   194 	@internalComponent
       
   195 */
       
   196 	{
       
   197 	__ASSERT_DEBUG( iState == EIdle || iState == EPendingAck, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EBadInputStreamState) );
       
   198 
       
   199 	// Bind to the input stream observer
       
   200 	iObserver = &aObserver;
       
   201 	
       
   202 	if( iState == EIdle )
       
   203 		{
       
   204 		// Move to the Read state and self complete, only if not suspended.
       
   205 		iState = ERead;
       
   206 		if( !iSuspended )
       
   207 			CompleteSelf();
       
   208 		}
       
   209 	// Otherwise, stay in the PendingAck state and wait for input stream 
       
   210 	// observer to notify that it has finished with the buffer.
       
   211 	}
       
   212 
       
   213 void CSocketReader::ReceivedDataRes()
       
   214 /**	
       
   215 	@see		MInputStream
       
   216 	@internalComponent
       
   217 */
       
   218 	{
       
   219 	__ASSERT_DEBUG( iObserver != NULL, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EInputStreamNotBound) );
       
   220 	__ASSERT_DEBUG( iState == EPendingAck, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EBadInputStreamState) );
       
   221 
       
   222 	// The input stream observer has finished with the received data buffer. 
       
   223 	// Reset the buffer and prepare to read the input stream again.
       
   224 	iBuffer.Zero();
       
   225 
       
   226 	// Move to the Read state and self complete, only if not suspended.
       
   227 	iState = ERead;
       
   228 	if( !iSuspended )
       
   229 		CompleteSelf();
       
   230 	}
       
   231 
       
   232 void CSocketReader::ShutdownReq()
       
   233 /**	
       
   234 	@see		MInputStream
       
   235 	@internalComponent
       
   236 */
       
   237 	{
       
   238 	__ASSERT_DEBUG( iObserver != NULL, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EInputStreamNotBound) );
       
   239 	__ASSERT_DEBUG( iState != EClosing || iState != EClosed, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EBadInputStreamState) );
       
   240 
       
   241 	// Cancel any outstanding requests
       
   242 	Cancel();
       
   243 
       
   244 #if defined (_DEBUG) && defined (_LOGGING)
       
   245 	TBuf8<KIpv6MaxAddrSize> ip;
       
   246 	TUint16	remotePort;
       
   247 	TUint16 localPort;
       
   248 	iController.ConnectionInfo(ip, remotePort, localPort);
       
   249 
       
   250 	__FLOG_0(_T8("!! Shutting down input stream"));
       
   251 	__FLOG_3(_T8("-> on local port %d with %S, remote port %d"), localPort, &ip, remotePort);
       
   252 #endif
       
   253 
       
   254 	// Shutdown the socket.
       
   255 	iSocket.Shutdown(iStatus);
       
   256 
       
   257 	// Move to the Closing state and go active
       
   258 	iState = EClosing;
       
   259 	SetActive();
       
   260 	}
       
   261 
       
   262 void CSocketReader::Close()
       
   263 /**	
       
   264 	@see		MInputStream
       
   265 	@internalComponent
       
   266 */
       
   267 	{
       
   268 	__ASSERT_DEBUG( iObserver != NULL, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EInputStreamNotBound) );
       
   269 	__ASSERT_DEBUG( iState != EClosing || iState != EClosed, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EBadInputStreamState) );	
       
   270 
       
   271 	// Cancel any outstanding requests
       
   272 	Cancel();
       
   273 
       
   274 #if defined (_DEBUG) && defined (_LOGGING)
       
   275 	TBuf8<KIpv6MaxAddrSize> ip;
       
   276 	TUint16	remotePort;
       
   277 	TUint16 localPort;
       
   278 	iController.ConnectionInfo(ip, remotePort, localPort);
       
   279 
       
   280 	__FLOG_0(_T8("!! Closing input stream"));
       
   281 	__FLOG_3(_T8("-> on local port %d with %S, remote port %d"), localPort, &ip, remotePort);
       
   282 #endif
       
   283 
       
   284 	// There is no need to do anything here - by informing the socket controller
       
   285 	// that the input stream is closed it will notify the output stream and then
       
   286 	// close the socket.
       
   287 
       
   288 	// Move to the Closed state
       
   289 	iState = EClosed;
       
   290 
       
   291 	// Inform the socket controller that the input stream is closed
       
   292 	iController.StreamClosed(KErrCancel, MSocketController::EInputStream);
       
   293 	}
       
   294 
       
   295 const CX509Certificate* CSocketReader::ClientCert()
       
   296 /**	
       
   297 	@see		MInputStream
       
   298 	@internalComponent
       
   299 */
       
   300 	{
       
   301 	return NULL;
       
   302 	}
       
   303 
       
   304 void CSocketReader::StartReceieveTimer (TInt aTimeoutValue)
       
   305 	{
       
   306 	//Get the TimeOut Value.
       
   307 	if(aTimeoutValue > 0)
       
   308 		{
       
   309 		TInt timeoutValue = 0;
       
   310 		//Convert to Microseconds.
       
   311 		if(aTimeoutValue <= KMinTimeoutValue)
       
   312 			{
       
   313 			//Default Value is 60 Seconds
       
   314 			timeoutValue = KDefTimeoutValue;
       
   315 			}
       
   316 		else
       
   317 			{
       
   318 			timeoutValue = aTimeoutValue * KMicrovalue;
       
   319 			}
       
   320 		
       
   321 		//Create and Start the HTTP timer
       
   322 		if(!iReceiveTimer)
       
   323 			{
       
   324 			iReceiveTimer = CHttpTimer::NewL(*this);
       
   325 			}
       
   326 		iReceiveTimer->After(timeoutValue);
       
   327 		}
       
   328 	}
       
   329 
       
   330 /*
       
   331  *	Methods from CActive
       
   332  */
       
   333 
       
   334 void CSocketReader::RunL()
       
   335 /**	
       
   336 	The request servicing function. Behaviour depends on the state of the input
       
   337 	stream.
       
   338 	@internalComponent
       
   339 */
       
   340 	{
       
   341 	__ASSERT_DEBUG( iObserver != NULL, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EInputStreamNotBound) );
       
   342 
       
   343 	// Leave if the socket reported an error
       
   344 	User::LeaveIfError(iStatus.Int());
       
   345 
       
   346 	switch( iState )
       
   347 		{
       
   348 	case ERead:
       
   349 		{
       
   350 		iBuffer.Zero ();
       
   351 		// Request a read from the socket
       
   352 		iSocket.RecvOneOrMore(iBuffer, iStatus);
       
   353 
       
   354 		// Move to the Received state and go active - wait for read to complete
       
   355 		iState = EReceivedData;
       
   356 		SetActive();		
       
   357 		} break;
       
   358 	case EReceivedData:
       
   359 		{
       
   360 		__OOM_LEAVE_TEST
       
   361 
       
   362 		// Received data - move to the PendingAck state and wait for observer to 
       
   363 		// notify that it has finished with the buffer.
       
   364 		iState = EPendingAck;
       
   365         
       
   366 		if(iReceiveTimer)
       
   367 			{
       
   368 			iReceiveTimer->Cancel();
       
   369 			}
       
   370 
       
   371 		// Inform the observer of the received data. 
       
   372 		iObserver->ReceivedDataIndL(iBuffer);
       
   373 
       
   374 #if defined (_DEBUG) && defined (_LOGGING)
       
   375 		TBuf8<KIpv6MaxAddrSize> ip;
       
   376 		TUint16	remotePort;
       
   377 		TUint16 localPort;
       
   378 		iController.ConnectionInfo(ip, remotePort, localPort);
       
   379 	
       
   380 		__FLOG_4(_T8("Received %d bytes on local port %d from %S, remote port %d"), iBuffer.Length(), localPort, &ip, remotePort);
       
   381 		__FLOG_0(_T8("----------"));
       
   382 		__FLOG_HEXDUMP(iBuffer.Ptr(), iBuffer.Length());
       
   383 		__FLOG_0(_T8("----------"));
       
   384 #endif
       
   385 		} break;
       
   386 	case EClosing:
       
   387 		{
       
   388 		__OOM_LEAVE_TEST
       
   389 
       
   390 		// The socket has shutdown - move to the Closed state
       
   391 		iState = EClosed;
       
   392         
       
   393 		if(iReceiveTimer)
       
   394 			{
       
   395 			iReceiveTimer->Cancel();
       
   396 			}
       
   397 
       
   398 		// Inform the observer that the input stream is closed.
       
   399 		iObserver->InputStreamCloseInd(KErrNone);
       
   400 
       
   401 		// Inform the socket controller that the input stream is now shut
       
   402 		iController.StreamClosed(KErrNone, MSocketController::EInputStream);
       
   403 		} break;
       
   404 	case EPendingAck:
       
   405 	case EClosed:
       
   406 	case EIdle:
       
   407 	default:
       
   408 		THttpTrLayerPanic::Panic(THttpTrLayerPanic::EBadInputStreamError);
       
   409 		break;
       
   410 		}
       
   411 	}
       
   412 	
       
   413 void CSocketReader::DoCancel()
       
   414 /**	
       
   415 	The asynchronous request cancel function. If the input stream has requested a 
       
   416 	read from the socket (ie it is in the ReceivedData state) it cancels the read
       
   417 	request.
       
   418 	@internalComponent
       
   419 */
       
   420 	{
       
   421 	if( iState == EReceivedData )
       
   422 		{
       
   423 		// There is a pending read request - cancel it
       
   424 		iSocket.CancelRecv();
       
   425 		}
       
   426 	}
       
   427 	
       
   428 TInt CSocketReader::RunError(TInt aError)
       
   429 /**	
       
   430 	The asynchronous request error handler. If this has been called then the 
       
   431 	read request or the socket shutdown request has failed. The socket can no 
       
   432 	longer be used. The input stream observer is notified that the stream is 
       
   433 	closed. No more data can be received from the socket.
       
   434 	@return		A value of KErrNone.indicating that the the error has been 
       
   435 				handled.
       
   436 	@pre		The input stream has requested a service (a read or a shutdown)
       
   437 				from socket. The request has failed. It is either in the Read or
       
   438 				Closing state.
       
   439 	@post		The input stream is in the Closed state.
       
   440 	@internalComponent
       
   441 */
       
   442 	{
       
   443 	__ASSERT_DEBUG( iObserver != NULL, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EInputStreamNotBound) );
       
   444 
       
   445 #if defined (_DEBUG) && defined (_LOGGING)
       
   446 	TBuf8<KIpv6MaxAddrSize> ip;
       
   447 	TUint16	remotePort;
       
   448 	TUint16 localPort;
       
   449 	iController.ConnectionInfo(ip, remotePort, localPort);
       
   450 
       
   451 	__FLOG_1(_T8("!! Input stream error : %d"), aError);
       
   452 	__FLOG_3(_T8("-> Connection on local port %d with %S, remote port %d closed"), localPort, &ip, remotePort);
       
   453 #endif
       
   454 
       
   455 	// Move to the Closed state
       
   456 	iState = EClosed;
       
   457 
       
   458 	// The socket request has failed - the socket connection is broken. Need
       
   459 	// to inform the input stream observer that the input stream is closed.
       
   460 	iObserver->InputStreamCloseInd(aError);
       
   461 
       
   462 	// Inform the socket controller that the input stream is closed
       
   463 	iController.StreamClosed(aError, MSocketController::EInputStream);
       
   464 
       
   465 	return KErrNone;
       
   466 	}
       
   467 
       
   468 void CSocketReader::SecureServerReq()
       
   469 /**
       
   470 	Upgrades the socket reader to a secure socket. This is currently not supported and will result
       
   471 	in the stream being closed and KErrNotSupported sent to the observer.
       
   472 	@internalComponent
       
   473 */
       
   474 	{
       
   475 	TRequestStatus* pStat = &iStatus;
       
   476 	User::RequestComplete(pStat, KErrNotSupported);
       
   477 	SetActive();
       
   478 	}
       
   479 
       
   480 /**
       
   481 	Resets the state to EClosed
       
   482 	@internalComponent
       
   483 */
       
   484 void CSocketReader::Reset()
       
   485 	{
       
   486 	// Inform the connection manager that we are closing the output stream 
       
   487 	// due to no memory
       
   488 	iObserver->InputStreamCloseInd ( KErrNoMemory );
       
   489 	iState = EClosed;	
       
   490 	}
       
   491 
       
   492 TInt CSocketReader::ImmediateRead ( TPtrC8& aData )
       
   493  	{
       
   494 	TInt bytesToRead = iSocket.PendingBytesToRead ();
       
   495     __FLOG_1 (_T8("Bytes to read : %d"), bytesToRead);
       
   496 	if ( bytesToRead < KErrNone )
       
   497 		return bytesToRead;
       
   498 	if ( bytesToRead > iBuffer.Size() )
       
   499 		bytesToRead = iBuffer.Size(); 
       
   500 	
       
   501 	if ( bytesToRead > 0 )
       
   502  	     {
       
   503         // Now we know that there is some data to be read. 		
       
   504  		// Suspend the current AO to ensure that the AO does not trigger in between
       
   505  		// our operation.
       
   506 		Suspend(); 		
       
   507 		CHttpAsyncWaiter *waiter = CHttpAsyncWaiter::New();
       
   508 		if ( waiter == NULL)
       
   509 	    	{
       
   510 	    	return KErrNoMemory;
       
   511 	    	}
       
   512 
       
   513 		// Issue a read
       
   514 		iSocket.RecvOneOrMore ( iBuffer, waiter->iStatus );
       
   515 		// Wait for the socket read completion.
       
   516 		waiter->StartAndWait();
       
   517 		TInt result = waiter->Result();
       
   518 		if( result == KErrNone )
       
   519 		   {
       
   520 			aData.Set ( iBuffer );
       
   521 		// The socket reader sent the data for processing and we have to wait for the 
       
   522 		// acknowledgement for the process completion, so moving the state to EPendingAck.
       
   523 			iState = EPendingAck;
       
   524 			result = bytesToRead;
       
   525 		    }
       
   526 		delete waiter;
       
   527 		// Resume the current AO.
       
   528 		Resume();
       
   529 		__FLOG_1(_T8("Immediate read completes with the result = %d"), result);
       
   530 		return result;
       
   531  		}
       
   532 	return KErrNone;	
       
   533  	}
       
   534 
       
   535 void CSocketReader::Restart ()
       
   536 	{
       
   537 	if ( iState == EIdle )		
       
   538 		{
       
   539 		// Move to the Read state and self complete, only if not suspended.
       
   540 		iState = ERead;
       
   541 		if( !iSuspended )
       
   542 			CompleteSelf();
       
   543 		}
       
   544 	}
       
   545 
       
   546 void CSocketReader::TimeOut()
       
   547 	{	
       
   548 	// Cancel any outstanding requests
       
   549 	Cancel();
       
   550 
       
   551 	iObserver->OnReceiveTimeOut();
       
   552 	}
       
   553 
       
   554 void CSocketReader::Shutdown()
       
   555     {	
       
   556     Cancel(); // Cancel any outstanding requests
       
   557     iSocket.ShutdownImmediate();
       
   558 
       
   559     // The socket has shutdown - move to the Closed state
       
   560     iState = EClosed;
       
   561 
       
   562     if(iReceiveTimer)
       
   563         {
       
   564         iReceiveTimer->Cancel();
       
   565         }
       
   566 
       
   567     // Inform the observer that the input stream is closed.
       
   568     iObserver->InputStreamCloseInd(KErrCancel);
       
   569 
       
   570     // Inform the socket controller that the input stream is now shut
       
   571     iController.StreamClosed(KErrCancel, MSocketController::EInputStream);
       
   572     }