servicediscoveryandcontrol/pnp/test/upnp/Server/Flow/src/httpserverhandler.cpp
changeset 0 f5a58ecadc66
equal deleted inserted replaced
-1:000000000000 0:f5a58ecadc66
       
     1 // Copyright (c) 2008-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 <httpstringconstants.h>
       
    17 #include <httperr.h>
       
    18 #include <http/thttptable.h>
       
    19 #include <upnp/tupnptable.h>
       
    20 
       
    21 #include "httpserverhandler.h"
       
    22 #include "httpserver.h"
       
    23 #include "httpevent.h"
       
    24 
       
    25 #include "upnpserverconstants.h"
       
    26 #include "upnplog.h"
       
    27 #include "upnpmemoryutils.h"
       
    28 
       
    29 const TUint KRecvTimeOutVal = 30000000; // 30secs
       
    30 
       
    31 
       
    32 __FLOG_STMT(_LIT8(KComponent,"Flow");)
       
    33 
       
    34 
       
    35 CHttpServerHandler* CHttpServerHandler::NewL ( RInternalSocket& aSocket, RMemChunk& aData, CServiceInfoArray& aServiceInfos, CServerHandlerArray& aServerHandlers, CHeaderCodec& aCodec, RStringPool& aStringPool, CChunkManager* aChunkMgr )
       
    36 	{
       
    37 	CHttpServerHandler* self = new ( ELeave ) CHttpServerHandler ( aSocket, aData, aServiceInfos, aServerHandlers, aCodec, aStringPool, aChunkMgr );
       
    38 	CleanupStack::PushL ( self );
       
    39 	self->ConstructL ();
       
    40 	CleanupStack::Pop (); // self
       
    41 	return self;
       
    42 	}
       
    43 
       
    44 void CHttpServerHandler::ConstructL ()
       
    45 	{
       
    46 	CProtocolHandler::ConstructL ();
       
    47 	iRequestParser = CUpnpRequestParser::NewL ( *this );
       
    48 	iResponseComposer = CUpnpResponseComposer::NewL ( *this );
       
    49 	StartNewTransactionL ();
       
    50 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("Created CHttpServerHandler")));
       
    51 	}
       
    52 
       
    53 CHttpServerHandler::~CHttpServerHandler ()
       
    54 	{
       
    55 	if ( !iReceivedData.IsEmpty() )
       
    56 		iReceivedData.Free ();
       
    57 	delete	iRequestParser;
       
    58 	delete	iResponseComposer;	
       
    59 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("Destroyed CHttpServerHandler")));
       
    60 	}
       
    61 
       
    62 CHttpServerHandler::CHttpServerHandler ( RInternalSocket& aSocket, RMemChunk& aData, CServiceInfoArray& aServiceInfos, CServerHandlerArray& aServerHandlers, CHeaderCodec& aCodec, RStringPool& aStringPool, CChunkManager* aChunkMgr )
       
    63 : CProtocolHandler (aSocket ),
       
    64 iServiceInfos ( aServiceInfos ),
       
    65 iServerHandlers ( aServerHandlers ),
       
    66 iServerCodec ( aCodec ),
       
    67 iStringPool ( aStringPool )
       
    68 	{
       
    69 	iSocketHandler.Attach ( iSocket );
       
    70 	iAllocator.SetChunkManager(aChunkMgr);
       
    71 	iReceivedData.Assign( aData );
       
    72 	}
       
    73 
       
    74 // MParserObserver
       
    75 void CHttpServerHandler::GotHeaders ()
       
    76 	{
       
    77 	CServerTransaction& trans = LastTransaction ();
       
    78 	RRequest request = trans.Request ()->Handle ();
       
    79 	RStringF hostStr = trans.Request ()->StringPool().StringF(HTTP::EHost, THTTPTable::Table());
       
    80 
       
    81 	if(!HttpRequestUtils::IsConnectionRequired( *( trans.Request () ) ))
       
    82 		trans.SetClosing();
       
    83 
       
    84 	TRAPD ( err, HttpRequestUtils::ValidateL ( *( trans.Request () ) ) );
       
    85 
       
    86 	if ( err == KErrNone )
       
    87 		{
       
    88 		// Notify the flow that the headers are received
       
    89 		THTTPEvent evt (THTTPEvent::EGotRequestHeaders);
       
    90 		NotifyEvent ( evt );
       
    91 		}
       
    92 	else
       
    93 		{
       
    94 		TInt statusCode = KErrNone;;
       
    95 		switch ( err )
       
    96 			{
       
    97 			case KErrNotSupported:
       
    98 			statusCode = HTTPStatus::ENotImplemented;
       
    99 			break;
       
   100 
       
   101 			case KErrCorrupt:
       
   102 			statusCode = HTTPStatus::EBadRequest;
       
   103 			break;
       
   104 
       
   105 			default:
       
   106 			// Internal server error
       
   107 			statusCode = HTTPStatus::EInternalServerError;
       
   108 			break;
       
   109 			}
       
   110 		CHttpServerHandler::CreateResponse ( *(trans.Response()), statusCode, this );
       
   111 		trans.SetReadyToSend ();
       
   112 		trans.SetClosing ();
       
   113 		// We have an error and we no longer parse
       
   114 		iRequestParser->ResetParser ();
       
   115 		// If this is the only transaction we can compose the response.
       
   116 		if ( &LastTransaction () == &CurrentTransaction () )
       
   117 			{
       
   118 			CurrentTransaction ().SetComposing ( ETrue );
       
   119 			iResponseComposer->ComposeResponse ( trans.Response () );
       
   120 			}
       
   121 		}
       
   122 	}
       
   123 
       
   124 
       
   125 void CHttpServerHandler::GotBodyData ()
       
   126 	{
       
   127 	THTTPEvent evt( THTTPEvent::EGotRequestBodyData );
       
   128 	NotifyEvent ( evt );
       
   129 	}
       
   130 
       
   131 void CHttpServerHandler::DataParsed ()
       
   132 	{	
       
   133 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::DataParsed")));
       
   134 	
       
   135 	// Reset parser on completion one parsing successfully.
       
   136 	if ( !LastTransaction ().Parsing () )
       
   137 		{
       
   138 		iRequestParser->ResetParser ();
       
   139 		}
       
   140 
       
   141 	// Handle excess data & start new transaction
       
   142 	if ( !iReceivedData.IsEmpty() )
       
   143 		{
       
   144 		// Start a new transaction with the pending data. We are getting pipelined request
       
   145 		StartNewTransaction ();
       
   146 		// Free up the data that we received
       
   147 		iReceivedData.Free ();
       
   148 		}
       
   149 	else
       
   150 		{
       
   151 		iSocketHandler.Recv ();
       
   152 		iTimer->StartTimer ( KRecvTimeOutVal );
       
   153 		}
       
   154 	}
       
   155 
       
   156 void CHttpServerHandler::ParsingComplete ( RMemChunk& aExcessData )
       
   157 	{
       
   158 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::ParsingComplete")));
       
   159 	
       
   160 	// Notify the flow that our request is complete
       
   161 	THTTPEvent evt( THTTPEvent::ERequestComplete );
       
   162 	NotifyEvent ( evt );
       
   163 
       
   164 	LastTransaction ().SetParsing ( EFalse );
       
   165 	
       
   166 	if ( !aExcessData.IsEmpty () )
       
   167 		iReceivedData.Append ( aExcessData );
       
   168 	
       
   169 	if ( Error () == KErrNone )
       
   170 		{
       
   171 		// Check do we have to send the response for our first transaction. This typically happens
       
   172 		// in the case of URI not found
       
   173 		CServerTransaction& currentTrans = CurrentTransaction ();
       
   174 		if ( currentTrans.ReadyToSend ()
       
   175 				&& !currentTrans.Composing () )
       
   176 			{
       
   177 			CurrentTransaction ().SetComposing ( ETrue );
       
   178 			iResponseComposer->ComposeResponse ( currentTrans.Response () );
       
   179 			}
       
   180 		}
       
   181 	else if ( Error () != KErrNone && iTransactions.Count () == 0 )
       
   182 		{
       
   183 		// We give a chance to send any pending responses
       
   184 		DestroySelf ();
       
   185 		}
       
   186 
       
   187 	}
       
   188 
       
   189 void CHttpServerHandler::ParserError ( TInt aError )
       
   190 	{
       
   191 	// If we got a parser error we should see whether we had more than one transaction.
       
   192 	// Yes? Then we should wait for the previous transactions completion then
       
   193 	// close the connection.
       
   194 	// No? we just cleanup ourself. We will not send any response as we got an invalid request
       
   195 	// and we have no previous transactions.
       
   196 
       
   197 	// Note: The above is what we have to do... But for now Cleanup ourself by doing nothing
       
   198 	SetError ( aError );
       
   199 	DestroySelf ();	 // ... more
       
   200 	}
       
   201 
       
   202 // MComposerObserver
       
   203 void CHttpServerHandler::MessageDataReadyL ( RBuf8& aData )
       
   204 	{
       
   205 	RMBufChain sendData;
       
   206 	sendData.CreateL(aData);
       
   207 	iSocketHandler.Send ( sendData );
       
   208 	}
       
   209 
       
   210 void CHttpServerHandler::ComposingConcluded ()
       
   211 	{
       
   212 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::ComposingConcluded")));
       
   213 	iResponseComposer->ResetComposer ();
       
   214 
       
   215 	TBool needToClose = CurrentTransaction ().IsClosing ();
       
   216 
       
   217 	// Delete the first transaction
       
   218 	DeleteTransaction ( iTransactions[0] );
       
   219 
       
   220 	// Check we should close the connection once we sent response to this transaction
       
   221 	if ( needToClose )
       
   222 		{
       
   223 		DestroySelf ();
       
   224 		return;
       
   225 		}
       
   226 
       
   227 	if ( iTransactions.Count () > 0 )
       
   228 		{
       
   229 		// Check the next transaction is ready to send
       
   230 		CServerTransaction& trans = CurrentTransaction ();
       
   231 		if ( trans.ReadyToSend () )
       
   232 			{
       
   233 			CurrentTransaction ().SetComposing ( ETrue );
       
   234 			iResponseComposer->ComposeResponse ( trans.Response () );
       
   235 			}
       
   236 		}
       
   237 	}
       
   238 
       
   239 void CHttpServerHandler::ComposerError ( TInt aError )
       
   240 	{
       
   241 	// Now we have an error. We just cleanup ourself
       
   242 	SetError ( aError );
       
   243 	DestroySelf ();
       
   244 	}
       
   245 
       
   246 void CHttpServerHandler::SendComplete ( TInt /* aLength */ )
       
   247 	{
       
   248 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::SendComplete")));
       
   249 	CurrentTransaction ().SetComposing ( EFalse );
       
   250 	iResponseComposer->ResponseDataSent	();
       
   251 	}
       
   252 
       
   253 void CHttpServerHandler::RecvComplete ( RMBufChain& aData )
       
   254 	{
       
   255 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::RecvComplete")));
       
   256 	
       
   257 	iTimer->StopTimer ();
       
   258 	
       
   259 	RMemChunk memChunk;
       
   260 	TUPnPMemoryUtils::CreateMemChunk(memChunk, aData, iAllocator);
       
   261 	iReceivedData.Append ( memChunk );	
       
   262 	// Check we have some transactions to give the received data or should we create a new one
       
   263 	if ( iTransactions.Count () > 0 && LastTransaction ().Parsing () )
       
   264 		{
       
   265 		iRequestParser->ParseRequest ( iReceivedData, LastTransaction ().Request () );
       
   266 		// parser takes ownership of aData, so it can be cleaned-up
       
   267 		iReceivedData.Free ();
       
   268 		return;
       
   269 		}
       
   270 	StartNewTransaction ();
       
   271 
       
   272 	if ( Error () != KErrNone && iTransactions.Count () == 0 )
       
   273 		{
       
   274 		// We give a chance to send any pending responses
       
   275 		DestroySelf ();
       
   276 		}
       
   277 	aData.Free();
       
   278 	}
       
   279 
       
   280 void CHttpServerHandler::TimeOut ()
       
   281 	{
       
   282 	if ( iTransactions.Count () > 0 )		
       
   283 		{
       
   284 		CServerTransaction& trans = CurrentTransaction ();
       
   285 		if ( trans.Parsing () )
       
   286 			{
       
   287 			// reset the request parser that is waiting for more data
       
   288 			iRequestParser->ResetParser ();
       
   289 			trans.SetParsing ( EFalse );
       
   290 			//create reponse with 408 status code
       
   291 			CHttpServerHandler::CreateResponse ( *( trans.Response () ), KRequestTimeoutStatusCode, this );
       
   292 			trans.SetReadyToSend ();
       
   293 			trans.SetComplete ();
       
   294 			// trigger compose self start event for the timed-out transaction
       
   295 			THTTPEvent evt ( THTTPEvent::ECompleteResponse );
       
   296 			OnHttpEvent ( iTransactions[0], evt );
       
   297 			}
       
   298 		}
       
   299 	else
       
   300 		{
       
   301 		// no transactions are pending,simply make self destroy.
       
   302 		DestroySelf ();
       
   303 		}
       
   304 	}
       
   305 
       
   306 void CHttpServerHandler::Error ( TOperation /*aOperation*/, TInt aError  )
       
   307 	{
       
   308 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::Error - %D"), aError));
       
   309 	// This is a socket error. We cannot do anything here.
       
   310 	// We just cleanup ourself
       
   311 	SetError ( aError );
       
   312 	
       
   313 	iResponseComposer->DataSentFailed ();		
       
   314 	iResponseComposer->ResetComposer ();
       
   315 	iRequestParser->ResetParser ();
       
   316 	iSocketHandler.CancelAll ();	
       
   317 	
       
   318 	TInt i = iTransactions.Count () - 1;
       
   319 	while ( i >= 0 )
       
   320 		{
       
   321 		CTransaction* trans = iTransactions[i];
       
   322 		if ( trans->Complete () )
       
   323 			{
       
   324 			iTransactions.Remove ( i );
       
   325 			delete trans;
       
   326 			}
       
   327 		--i;
       
   328 		}
       
   329 		
       
   330 	DestroySelf ();
       
   331 	}
       
   332 
       
   333 CServerTransaction& CHttpServerHandler::CurrentTransaction () const
       
   334 	{
       
   335 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::CurrentTransaction")));
       
   336 	__ASSERT_DEBUG ( iTransactions.Count () > 0, User::Invariant () );
       
   337 	return static_cast < CServerTransaction& > ( *( iTransactions[0] ) );
       
   338 	}
       
   339 
       
   340 CServerTransaction& CHttpServerHandler::LastTransaction () const
       
   341 	{
       
   342 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::LastTransaction")));
       
   343 	TInt count = iTransactions.Count ();
       
   344 	__ASSERT_DEBUG ( count > 0, User::Invariant () );
       
   345 	return static_cast < CServerTransaction& > ( *( iTransactions[ count - 1 ]  ) );
       
   346 	}
       
   347 
       
   348 void CHttpServerHandler::NotifyEvent ( THTTPEvent& aEvent )
       
   349 	{
       
   350 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::NotifyEvent")));
       
   351 	CServerTransaction& trans = LastTransaction ();
       
   352 	// Ensure that the flow still exists
       
   353 	CRequest* request = trans.Request ();
       
   354 	TInt pos = iServiceInfos.MatchServiceUri ( request->Handle ().URI (), HttpRequestUtils::HostStr ( *request ) );
       
   355 	if ( pos == KErrNotFound )
       
   356 		{
       
   357 		if ( !trans.Composing () )
       
   358 			{
       
   359 			CHttpServerHandler::CreateResponse ( *( trans.Response () ), HTTPStatus::ENotFound, this );
       
   360 			trans.SetReadyToSend ();
       
   361 			}
       
   362 		}
       
   363 	else if ( !trans.Complete () ) // Server flow on validation failure, 
       
   364 								   // completes the transaction after creating error response
       
   365 								   // so no need to push ERequestComplete Event to ServerFlow.
       
   366 								   // start composing error response
       
   367 		{
       
   368 		CServiceInfo& info = iServiceInfos [ pos ];
       
   369 		info.Observer ().OnHttpEvent ( &trans, aEvent );
       
   370 		}
       
   371 	}
       
   372 
       
   373 void CHttpServerHandler::CreateResponse ( CResponse& aResponse, TInt aStatusCode, MHttpEventObserver* aServerHandler )
       
   374 	{
       
   375 	TRAPD ( err, CHttpServerHandler::CreateResponseL ( aResponse, aStatusCode ) );
       
   376 
       
   377 	if ( err != KErrNone )
       
   378 		{
       
   379 		RResponse response = aResponse.Handle ();
       
   380 		response.SetStatusCode ( HTTPStatus::EInternalServerError );
       
   381 
       
   382 		// Should be changed once the status text us moved to te string table
       
   383 		RStringF responseTextString;
       
   384 		responseTextString = aResponse.StringPool().StringF ( UPnP::EInternalServerError, TUPnPTable::Table() );
       
   385 		response.SetStatusText ( responseTextString );
       
   386 		
       
   387 		if ( aServerHandler != NULL )
       
   388 			{
       
   389 			CHttpServerHandler& handler = static_cast < CHttpServerHandler& > ( *aServerHandler );
       
   390 			handler.SetError ( err );
       
   391 			}
       
   392 		}
       
   393 	}
       
   394 
       
   395 void CHttpServerHandler::CreateResponseL ( CResponse& aResponse, TInt aStatusCode )
       
   396 	{
       
   397 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::CreateResponse")));
       
   398 	TVersion version ( KMajorVersion, KMinorVersion, 0 );
       
   399 	RResponse response = aResponse.Handle ();
       
   400 	RStringPool sp = aResponse.StringPool ();
       
   401 
       
   402 	response.SetStatusCode ( aStatusCode );
       
   403 	response.SetVersion ( version );
       
   404 
       
   405 	// Add current date header
       
   406 	RHTTPHeaders hdrs = response.GetHeaderCollection ();
       
   407 	TTime time;
       
   408 	time.UniversalTime();
       
   409 	THTTPHdrVal timeHdrVal ( time.DateTime() );
       
   410 	hdrs.SetFieldL ( aResponse.StringPool().StringF(HTTP::EDate, THTTPTable::Table() ), timeHdrVal );
       
   411 
       
   412 	_LIT8 ( KServerName, "Symbian UPnP/1.0 server" );
       
   413 	RStringF serverStr = sp.OpenFStringL ( KServerName () );
       
   414 	THTTPHdrVal serverHdrVal ( serverStr );
       
   415 	hdrs.SetFieldL ( sp.StringF ( HTTP::EServer, THTTPTable::Table() ), serverHdrVal );
       
   416 	serverStr.Close ();
       
   417 
       
   418 	if ( aStatusCode != HTTPStatus::EOk )
       
   419 		{// Content Length
       
   420 		hdrs.SetFieldL ( sp.StringF( HTTP::EContentLength, THTTPTable::Table() ), THTTPHdrVal ( 0 ) );
       
   421 		}
       
   422 
       
   423 	RStringF responseTextString;
       
   424 	response.SetStatusText ( responseTextString );
       
   425 
       
   426 	switch ( aStatusCode )
       
   427 		{
       
   428 		case HTTPStatus::EOk:
       
   429 		responseTextString = sp.StringF ( UPnP::EOk, TUPnPTable::Table() );
       
   430 		break;
       
   431 
       
   432 		case HTTPStatus::ENotFound:
       
   433 		responseTextString = sp.StringF ( UPnP::ENotFound, TUPnPTable::Table() );
       
   434 		break;
       
   435 
       
   436 		case HTTPStatus::EBadRequest:
       
   437 		responseTextString = sp.StringF ( UPnP::EBadRequest, TUPnPTable::Table() );
       
   438 		break;
       
   439 
       
   440 		case HTTPStatus::EInternalServerError:
       
   441 		responseTextString = sp.StringF ( UPnP::EInternalServerError, TUPnPTable::Table() );
       
   442 		break;
       
   443 
       
   444 		case HTTPStatus::ENotImplemented:
       
   445 		responseTextString = sp.StringF ( UPnP::ENotImplemented, TUPnPTable::Table() );
       
   446 		break;
       
   447 
       
   448 		case HTTPStatus::EPreconditionFailed:
       
   449 		responseTextString = sp.StringF ( UPnP::EPreconditionFailed, TUPnPTable::Table() );
       
   450 		break;
       
   451 
       
   452 		case HTTPStatus::EMethodNotAllowed:
       
   453 		responseTextString = sp.StringF ( UPnP::EMethodNotAllowed, TUPnPTable::Table() );
       
   454 		break;
       
   455 	
       
   456 		case HTTPStatus::EUnsupportedMediaType:
       
   457 		responseTextString = sp.StringF ( UPnP::EUnsupportedMediaType, TUPnPTable::Table() );
       
   458 		break;
       
   459 
       
   460 		case KRequestTimeoutStatusCode:
       
   461 		responseTextString = sp.StringF ( UPnP::ERequestTimeout, TUPnPTable::Table() );
       
   462 		break;
       
   463 		
       
   464 		case KInvalidSeqStatusCode:
       
   465 		responseTextString = sp.StringF ( UPnP::EMethodNotAllowed, TUPnPTable::Table() );
       
   466 		break;
       
   467 
       
   468 		default:
       
   469 		ASSERT ( 0 );
       
   470 		break;
       
   471 		}
       
   472 	response.SetStatusText ( responseTextString );
       
   473 	}
       
   474 
       
   475 void CHttpServerHandler::StartNewTransactionL ( )
       
   476 	{
       
   477 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::StartNewTransaction")));
       
   478 	CServerTransaction* trans = CServerTransaction::NewL ( iServerCodec, iStringPool, *this );
       
   479 	CleanupStack::PushL ( trans );
       
   480 	User::LeaveIfError ( iTransactions.Append ( trans ) );
       
   481 	CleanupStack::Pop (); // trans
       
   482 	iRequestParser->ParseRequest ( iReceivedData, trans->Request () ); // Needs change
       
   483 	iReceivedData.Free (); // Free up the data that we received, parser takes ownership
       
   484 	trans->SetParsing ( ETrue );
       
   485 	trans->Response()->Handle().SetBody ( *this ); // Set self as the response body supplier
       
   486 	}
       
   487 
       
   488 void CHttpServerHandler::StartNewTransaction ()
       
   489 	{
       
   490 	TRAPD ( err, StartNewTransactionL () );
       
   491 	if ( err != KErrNone )
       
   492 		{
       
   493 		SetError ( err );
       
   494 		}
       
   495 	}
       
   496 
       
   497 void CHttpServerHandler::DeleteTransaction ( CTransaction* aTrans )
       
   498 	{
       
   499 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::DeleteTransaction")));
       
   500 	for ( TInt i = 0; i < iTransactions.Count (); ++i )
       
   501 		{
       
   502 		CTransaction* trans = iTransactions[i];
       
   503 		if ( trans == aTrans )
       
   504 			{
       
   505 			iTransactions.Remove ( i );
       
   506 			delete trans;
       
   507 			return;
       
   508 			}
       
   509 		}
       
   510 	}
       
   511 
       
   512 TInt CHttpServerHandler::OnHttpEvent ( CTransaction* aTransaction, THTTPEvent& aEvent )
       
   513 	{
       
   514 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::OnHttpEvent")));
       
   515 	CServerTransaction& trans = static_cast< CServerTransaction& > (*aTransaction);
       
   516 	
       
   517 	if ( Error ()
       
   518 		|| aEvent == THTTPEvent::EFailed ) // ControlChannel transaction response is half send, so close it
       
   519 		{
       
   520 		if ( &trans == &CurrentTransaction () )
       
   521 			{
       
   522 			iResponseComposer->ResetComposer ();
       
   523 			}
       
   524 		DeleteTransaction ( aTransaction );
       
   525 		TInt err = iError;
       
   526 		DestroySelf ();
       
   527 		return err;
       
   528 		}
       
   529 		
       
   530 	// Check if this is the first transaction that we have to respond. Otherwise just move
       
   531 	// this into a ready to send state.	
       
   532 	if ( &trans != &CurrentTransaction() )
       
   533 		{
       
   534 		// THTTPEvent::EFailed is used for control channel pending transactions
       
   535 		if ( aEvent == THTTPEvent::EFailed )
       
   536 			{
       
   537 			DeleteTransaction ( aTransaction );
       
   538 			return KErrNone;
       
   539 			}
       
   540 		else
       
   541 			{
       
   542 			trans.SetReadyToSend ();
       
   543 			return KErrNone;
       
   544 			}
       
   545 		}	
       
   546 
       
   547 	// The flow can Notify us in 2 ways.
       
   548 	// 1. Complete response information is available including any body data. This happens when
       
   549 	// the flow receives the response from the control plane
       
   550 	// In this case we will receives a THTTPEvent::ECompleteResponse event from the flow
       
   551 	// in which case we start composing the response
       
   552 	// 2. The flow receives the data via RControlChannel send from the application
       
   553 	// Here, we have to start composing when we receive the THTTPEvent::EGotResponseHeaders &
       
   554 	// THTTPEvent::EGotResponseBodyData in which case we notify the composer about the body data.
       
   555 	// 1. We have to start composing when we get THTTPEvent::EGotResponseHeaders
       
   556 	// 2. We have to inform the composer that we have new response body data available
       
   557 	// 3. Response completion --- we don't do anything here, just an indication that we are concluded the response.
       
   558 	//  keep going ComposingConcluded will reset the composer
       
   559 	switch ( aEvent.iStatus )
       
   560 		{
       
   561 		case THTTPEvent::EGotResponseHeaders: // for control channel
       
   562 		case THTTPEvent::ECompleteResponse:	  // for control plane
       
   563 			{
       
   564 			LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::OnHttpEvent - THTTPEvent::EGotResponseHeaders")));
       
   565 			CurrentTransaction ().SetComposing ( ETrue );
       
   566 			iResponseComposer->ComposeResponse ( CurrentTransaction ().Response() );
       
   567 			}
       
   568 		break;
       
   569 
       
   570 		case THTTPEvent::EGotResponseBodyData:
       
   571 			{
       
   572 			LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::OnHttpEvent - THTTPEvent::EGotResponseBodyData")));
       
   573 
       
   574 			if ( !CurrentTransaction ().Composing () )
       
   575 				iResponseComposer->NotifyNewBodyData ();
       
   576 			}
       
   577 		break;
       
   578 
       
   579 		case THTTPEvent::EResponseComplete:
       
   580 			{
       
   581 			LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::OnHttpEvent - THTTPEvent::EResponseComplete")));
       
   582 			// We don't do anything here. We completed the whole response.
       
   583 			iResponseComposer->NotifyNewBodyData (); // This is the last chunk. This happens when we send via chunked encoding
       
   584 			}
       
   585 		break;
       
   586 
       
   587 		default:
       
   588 			ASSERT(0);
       
   589 			break;
       
   590 		}
       
   591 	return KErrNone;
       
   592 	}
       
   593 
       
   594 TBool CHttpServerHandler::CanDestroy () const
       
   595 	{
       
   596 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::CanDestroy")));
       
   597 	return ( iTransactions.Count () == 0 );
       
   598 	}
       
   599 
       
   600 // We will destroy ourself if we are not waiting for any response.
       
   601 void CHttpServerHandler::DestroySelf ( )
       
   602 	{
       
   603 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::DestroySelf")));
       
   604 	if ( CanDestroy () )
       
   605 		{
       
   606 		// Remove from the server handler array	 ...
       
   607 		for ( TInt i = 0; i < iServerHandlers.Count (); ++i )
       
   608 			{
       
   609 			if ( iServerHandlers[i] == this )
       
   610 				{
       
   611 				iServerHandlers.Remove ( i );
       
   612 				break;
       
   613 				}
       
   614 			}
       
   615 
       
   616 		// We don't have any more transactions. We can delete ourself
       
   617 		delete this;
       
   618 		}
       
   619 
       
   620 	}
       
   621 
       
   622 void CHttpServerHandler::SetError ( TInt aError )
       
   623 	{
       
   624 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::SetError - %d"), aError));
       
   625 	iError = aError;
       
   626 	}
       
   627 
       
   628 TBool CHttpServerHandler::Error () const
       
   629 	{
       
   630 	return ( iError != KErrNone );
       
   631 	}
       
   632 
       
   633 // -------------------------------------
       
   634 
       
   635 TBool CHttpServerHandler::GetNextDataPart ( TPtrC8& aDataPart )
       
   636 	{
       
   637 	CServerTransaction& trans = CurrentTransaction ();
       
   638 	trans.GetBodyPart ( aDataPart );
       
   639 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::GetNextDataPart - %d, %d"), trans.IsLastBodyPart (), aDataPart.Length () ));
       
   640 	return trans.IsLastBodyPart ();
       
   641 	}
       
   642 
       
   643 void CHttpServerHandler::ReleaseData ()
       
   644 	{
       
   645 	LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::ReleaseData" )));
       
   646 	CServerTransaction& trans = CurrentTransaction ();
       
   647 	trans.RemoveBodyPart ();
       
   648 	if ( !trans.BodyParts ().IsEmpty () )
       
   649 		{
       
   650 		LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler::ReleaseData body part present" )));
       
   651 		TInt count = trans.BodyParts().NumBufs();
       
   652 		// We will call NotifyNewBodyData only when we are sending it as a chunked-encoding &
       
   653 		// the number of MBuf available is > 1. Last MBuf we will notify via a EResponseComplete from OnHttpEvent
       
   654 		if ( ( trans.DataLeft() == KErrUnknown && count > 1 )
       
   655 				|| ( count > 0 ) ) // Normal send by knowing the length. we will notify if we have > 0 MBufs
       
   656 			{
       
   657 			LOG(ESockLogExternal::Printf(KSubsysHttpSrvrHndlr, KComponent, _L8("CHttpServerHandler - Calling NotifyNewBodyData on composer" )));
       
   658 			trans.SetComposing ( ETrue );
       
   659 			iResponseComposer->NotifyNewBodyData ();
       
   660 			}
       
   661 		}
       
   662 	}
       
   663 
       
   664 TInt CHttpServerHandler::OverallDataSize ()
       
   665 	{
       
   666 	CServerTransaction& trans = CurrentTransaction ();
       
   667 	// For now we calculate the total data size based on the Content-Length field
       
   668 	// Note: In the futre, ( for full HTTP server ) this should be based on the chunked encoding
       
   669 	// field or Content-Length
       
   670 	TInt dataSize = MHttpMessageParserObserver::ENoBody;
       
   671 	// Check is there a Content-Length field?
       
   672 	CResponse* response = trans.Response ();
       
   673 	RStringF contentLength = response->StringPool().StringF( HTTP::EContentLength, THTTPTable::Table() );
       
   674 	THTTPHdrVal value;
       
   675 	TInt err = response->Handle().GetHeaderCollection().GetField( contentLength, 0, value );
       
   676 	if ( err == KErrNone )
       
   677 		{
       
   678 		dataSize = value.Int ();
       
   679 		}
       
   680 	return dataSize;
       
   681 	}