servicediscoveryandcontrol/pnp/test/upnp/Server/Flow/src/httpclientflow.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 // @file
       
    15 // @internalComponent
       
    16 // 
       
    17 //
       
    18 
       
    19 //System Includes
       
    20 #include <comms-infras/ss_nodeinterfaces.h>
       
    21 //#include <comms-infras/ss_nodemessages_controlprovider.h>
       
    22 #include <inetprottextutils.h>
       
    23 #include <uriutils.h>
       
    24 #include <http/thttptable.h>
       
    25 #include <httperr.h>
       
    26 #include <httpstringconstants.h>
       
    27 #include <stringpool.h>
       
    28 #include <http/framework/cheadercodecplugin.h>
       
    29 #include <upnp/tupnptable.h>
       
    30 #include <rmemchunk.h>
       
    31 
       
    32 //Local Includes
       
    33 #include "httpclientflow.h"
       
    34 #include "upnpserverconstants.h"
       
    35 #include "upnplog.h"
       
    36 #include "upnppint.h"
       
    37 #include "upnpmemoryutils.h"
       
    38 
       
    39 
       
    40 using namespace ESock;
       
    41 using namespace Messages;
       
    42 
       
    43 
       
    44 __FLOG_STMT(_LIT8(KComponent,"Flow");)
       
    45 const TUint KHttpDefaultPort = 80;
       
    46 _LIT8(KSlash, "/");
       
    47 
       
    48 CHttpClientFlow* CHttpClientFlow::NewL ( CSubConnectionFlowFactoryBase& aFactory,
       
    49 										CProtocolIntfBase* aProtocolIntf,
       
    50 										const TNodeId& aSubConnId,
       
    51 										const TAppProtAddr& aSockAddr )
       
    52 	{	
       
    53 	CHttpClientFlow* self = new ( ELeave ) CHttpClientFlow ( aFactory, aProtocolIntf, aSubConnId, aSockAddr );
       
    54 	CleanupStack::PushL ( self );
       
    55 	self->ConstructL( );
       
    56 	CleanupStack::Pop ( self );
       
    57 	return self;
       
    58 	}
       
    59 
       
    60 
       
    61 CHttpClientFlow::CHttpClientFlow ( CSubConnectionFlowFactoryBase& aFactory, CProtocolIntfBase* aProtocolIntf, const TNodeId& aSubConnId, const TAppProtAddr& aSockAddr )
       
    62 	: CUPnPFlowBase ( aFactory, aProtocolIntf, EHttpClientFlow, aSubConnId ),
       
    63 	iDCIdle ( EFalse ), iRemoteAddress ( aSockAddr.iAddr, aSockAddr.iPort ), iResponseCompleted ( EFalse ), iReadStreamStarted ( EFalse )
       
    64 	{
       
    65 	LOG_NODE_CREATE(KESockFlowTag, CHttpClientFlow);
       
    66 	}
       
    67 
       
    68 
       
    69 CHttpClientFlow::~CHttpClientFlow ( )
       
    70 	{	
       
    71 	iRemoteAddress.FillZ ( );
       
    72 	iRequestUri.Close ( );
       
    73 	iActionValue.Close ( );
       
    74 	for ( TInt idx = 0; idx < iTransactions->Count( ); idx++ )
       
    75 		{
       
    76 		delete iTransactions->Get( idx );
       
    77 		}
       
    78 	if ( !iBufChain.IsEmpty ( ) )
       
    79 		iBufChain.Free ( );
       
    80 
       
    81 	delete iCodec;
       
    82 	iStringPool.Close();
       
    83 	// Note! delete client handler after cleanp of transactions, or else it will panic
       
    84 	delete iClientHandler;
       
    85 	delete iActionParser;
       
    86 
       
    87 	iSubConnectionProvider.Close ( );
       
    88 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("Destroyed CHttpClientFlow")));
       
    89 	LOG_NODE_DESTROY(KESockFlowTag, CHttpClientFlow);
       
    90 	}
       
    91 
       
    92 void CHttpClientFlow::ConstructL ( )
       
    93 	{	
       
    94 	iClientHandler = CHTTPClientHandler::NewL ( *this, static_cast<CUPnPProtocolIntfBase *>( ProtocolIntf () )->GetMemoryChunkManager(), &iRemoteAddress );
       
    95 	iTransactions = iClientHandler->GetTransactionWrapperL( );
       
    96 
       
    97 	iStringPool.OpenL( TUPnPTable::Table() );
       
    98 	iStringPool.OpenL(THTTPTable::Table());
       
    99 	iCodec = CHeaderCodecPlugin::NewL ( KUPnPCodecName, iStringPool );
       
   100 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("Created CHttpClientFlow")));
       
   101 	}
       
   102 
       
   103 
       
   104 
       
   105 //From CSubConnectionFlowBase MNode
       
   106 void CHttpClientFlow::ReceivedL ( const TRuntimeCtxId& aSender, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage )
       
   107 	{	
       
   108  	if ( aMessage.IsMessage<TEChild::TDestroy> () )
       
   109 		{
       
   110 		LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReceivedL - Received message TCFMessage::TDestroy")));
       
   111   		if ( RemoveControlClient ( FindControlClient ( address_cast<TNodeId> ( aSender ) ) ) == 0 )
       
   112    			{
       
   113    			DeleteThisFlow ( );
       
   114    			}
       
   115 		}
       
   116 	else if ( aMessage.IsMessage<TCFDataClient::TStart> () )
       
   117 		{
       
   118         LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReceivedL - Received message TCFMessage::TDataClientStart")));
       
   119 		RClientInterface::OpenPostMessageClose ( NodeId (), address_cast<TNodeCtxId> ( aSender ), TCFDataClient::TStarted ().CRef () );
       
   120     	}
       
   121     else if ( aMessage.IsMessage<TCFDataClient::TStop> () )
       
   122 		{
       
   123 		LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReceivedL - Received message TCFMessage::TDataClientStop")));
       
   124 		CancelRequest ( address_cast<TNodeCtxId> ( aSender ) );
       
   125 		}
       
   126 	else if ( aMessage.IsMessage<TUpnpMessage::TUPnPClientRequestInfo> () )
       
   127 		{
       
   128 		LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReceivedL - Received message TUpnpMessage::TUPnPClientRequestInfo")));
       
   129 		TUpnpMessage::TUPnPClientRequestInfo& clntReqInfo = message_cast<TUpnpMessage::TUPnPClientRequestInfo> ( aMessage );
       
   130 		PrepareAndSubmitTransactionL ( clntReqInfo, address_cast<TNodeCtxId> ( aSender ) );
       
   131 		}
       
   132 	}
       
   133 
       
   134 void CHttpClientFlow::CancelRequest ( TNodeCtxId aChannelId )
       
   135 	{	
       
   136 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::CancelRequest")));
       
   137 	TInt pos = FindTransaction ( aChannelId );
       
   138 	if ( pos != KErrNotFound ) // transaction is not found
       
   139 		{
       
   140 		LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::CancelRequest - Cancelling transaction")));
       
   141 		CTransaction* ctrans = iTransactions->Get( pos );
       
   142 		iClientHandler->CancelTransaction ( ctrans );
       
   143 
       
   144 		THTTPEvent event ( THTTPEvent::ECancel );
       
   145 		OnHttpEvent ( ctrans, event );
       
   146 		}
       
   147 	else
       
   148 		{
       
   149 		if ( !iDCIdle ) // This will make sure when ASocket attached as upperflow
       
   150 						// and unbind is received from it, No more communication will 
       
   151 						// happen to SCPR.
       
   152 			{
       
   153 			RClientInterface::OpenPostMessageClose ( NodeId (), aChannelId, TCFDataClient::TStopped ( 0 ).CRef () );
       
   154 			}
       
   155 		}
       
   156 	}
       
   157 
       
   158 
       
   159 TInt CHttpClientFlow::FindTransaction ( TNodeCtxId aChannelId )
       
   160 	{	
       
   161 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::FindTransaction")));
       
   162 	TUint count = iTransactions->Count( );
       
   163 	for ( TInt idx = 0; idx < count; idx++ )
       
   164 		{
       
   165 		CHTTPClientTransaction* ctrans = iTransactions->Get( idx );
       
   166 
       
   167 		if ( ctrans->NodeCtxId ( ) == aChannelId )
       
   168 			{
       
   169 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::FindTransaction - Transaction found at index %d"), idx));
       
   170 			return idx;
       
   171 			}
       
   172 		}
       
   173 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::FindTransaction - Transaction not found")));
       
   174 	return KErrNotFound;
       
   175 	}
       
   176 
       
   177 void CHttpClientFlow::PrepareAndSubmitTransactionL ( RMBufChain& aData )
       
   178 	{	
       
   179 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL")));
       
   180 
       
   181 	TNodeCtxId channelId ( MeshMachine::KActivityNull, NodeId () );
       
   182 
       
   183 	CHTTPClientTransaction* ctrans = CHTTPClientTransaction::NewL ( *iCodec, iStringPool, channelId );
       
   184 	iTransactions->AppendL ( ctrans );
       
   185 
       
   186 	CRequest* crequest = ctrans->Request( );
       
   187 	RHTTPHeaders headers = crequest->Handle( ).GetHeaderCollection ( );
       
   188 	RRequest rrequest = crequest->Handle( );
       
   189 
       
   190 	// Set request method
       
   191 	RStringF stringF = iStringPool.StringF ( HTTP::EPOST, THTTPTable::Table() );
       
   192 	rrequest.SetMethod ( stringF );
       
   193 
       
   194 	// Set request Uri
       
   195 	SetRequestUriL ( ctrans, iRequestUri );
       
   196 	SetContentTypeHeaderL ( headers );
       
   197 
       
   198 	//Set Content Length
       
   199 	THTTPHdrVal hdrVal ( iOverallDataSize );
       
   200 	headers.SetFieldL ( iStringPool.StringF ( HTTP::EContentLength, THTTPTable::Table() ), hdrVal );
       
   201 
       
   202 	// Note! 100-continue, UPnP is not having any usecase to use this
       
   203 
       
   204     //Set Soap Action
       
   205 	if ( SetActionHeaderL ( aData ) )
       
   206 		{
       
   207 		// Complete headers are available, so Transaction is ready for submission
       
   208 		LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Submitting transaction")));
       
   209 		iClientHandler->SubmitTransaction( ctrans );
       
   210 		}
       
   211 
       
   212 	// Set Body Data
       
   213 	ctrans->AddBodyPart( aData );
       
   214 	SetTransactionComplete ( ctrans );
       
   215 	}
       
   216 
       
   217 TBool CHttpClientFlow::SetActionHeaderL ( RMBufChain& aData )
       
   218 	{	
       
   219 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetActionHeaderL")));
       
   220 
       
   221 	CTransaction* ctrans = iTransactions->Get( 0 );
       
   222 
       
   223 	CRequest* crequest = ctrans->Request( );
       
   224 	RHTTPHeaders headers = crequest->Handle( ).GetHeaderCollection ( );
       
   225 	RRequest rrequest = crequest->Handle( );
       
   226 
       
   227 	// get service name & action name
       
   228 	ConstructSoapActionHeaderValueL ( aData );
       
   229 
       
   230 	if ( iActionValue.Length ( ) != 0 )
       
   231 		{
       
   232 		RStringF stringF =  iStringPool.StringF ( UPnP::ESoapAction, TUPnPTable::Table() );
       
   233 		headers.SetRawFieldL ( stringF, iActionValue, KSoapFieldSeparator );
       
   234 		}
       
   235 
       
   236 	return iActionValue.Length ( ) > 0;
       
   237 	}
       
   238 
       
   239 void CHttpClientFlow::ConstructSoapActionHeaderValueL ( RMBufChain& aData )
       
   240 	{	
       
   241 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ConstructSoapActionHeaderValueL")));
       
   242 
       
   243 	if ( iActionParser == NULL )
       
   244 		{
       
   245 		iActionParser =  CSoapParser::NewL ( );
       
   246 		}
       
   247 
       
   248 	RBuf8 xmlData;
       
   249 	xmlData.CreateMaxL ( aData.Length ( ) );
       
   250 	aData.CopyOut ( xmlData );
       
   251 	CleanupClosePushL ( xmlData );
       
   252 
       
   253 	if ( iActionParser->ParseSoapL( xmlData ) )
       
   254 		{
       
   255 		TInt len = iActionParser->SoapAction( ).Length ( ) + KColon ( ).Length ( ) * 2;
       
   256 
       
   257 		iActionValue.CreateL ( len );
       
   258 
       
   259 		iActionValue.Copy ( KColon );
       
   260 		iActionValue.Append ( iActionParser->SoapAction( ) );
       
   261 		iActionValue.Append ( KColon );
       
   262 
       
   263 		delete iActionParser;
       
   264 		iActionParser = NULL;
       
   265 		}
       
   266 
       
   267 	CleanupStack::PopAndDestroy ( &xmlData );
       
   268 	}
       
   269 
       
   270 void CHttpClientFlow::SetContentTypeHeaderL ( RHTTPHeaders aHeaders )
       
   271 	{
       
   272 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetContentTypeHeaderL")));
       
   273 	// Set content-type
       
   274 	RStringF stringF = iStringPool.StringF ( HTTP::EContentType, THTTPTable::Table() );
       
   275 	THTTPHdrVal contentTypeHdrVal;
       
   276 	RStringF contentTypeHdr = iStringPool.StringF ( UPnP::ETextXml, TUPnPTable::Table() );
       
   277 	contentTypeHdrVal.SetStrF ( contentTypeHdr );
       
   278 
       
   279 	RStringF paramStringF = iStringPool.StringF ( HTTP::ECharset, THTTPTable::Table() );
       
   280 	THTTPHdrVal contentTypeParamVal;
       
   281 	RStringF contentTypeParam = iStringPool.StringF ( UPnP::EUtf8, TUPnPTable::Table() );
       
   282 	contentTypeParamVal.SetStrF ( contentTypeParam );
       
   283 	aHeaders.SetFieldL ( stringF, contentTypeHdrVal, paramStringF, contentTypeParamVal );
       
   284 	}
       
   285 
       
   286 void CHttpClientFlow::ReSubmitTransactionL ( CTransaction* aTransaction )
       
   287 	{
       
   288 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReSubmitTransactionL")));
       
   289 	CRequest* crequest = aTransaction->Request( );
       
   290 	RHTTPHeaders headers = crequest->Handle( ).GetHeaderCollection ( );
       
   291 	RRequest rrequest = crequest->Handle ( );
       
   292 
       
   293 	// Set request method
       
   294 	RStringF stringF = iStringPool.StringF ( UPnP::EMPost, TUPnPTable::Table() );
       
   295 	rrequest.SetMethod ( stringF );
       
   296 
       
   297 	// Set MAN Header
       
   298 	stringF = iStringPool.StringF ( UPnP::EMAN, TUPnPTable::Table() );
       
   299 	THTTPHdrVal manHdrVal;
       
   300 	RStringF manHdr = iStringPool.StringF ( UPnP::ESoapUrl, TUPnPTable::Table() );
       
   301 	manHdrVal.SetStrF ( manHdr );
       
   302 
       
   303 	RStringF paramStringF = iStringPool.StringF ( UPnP::ENS, TUPnPTable::Table() );
       
   304 	THTTPHdrVal nsParamVal;
       
   305 	RStringF nsParam = iStringPool.StringF ( UPnP::ENsParam, TUPnPTable::Table() );
       
   306 	headers.SetFieldL ( stringF, manHdrVal, paramStringF, nsParamVal );
       
   307 
       
   308 	// recompose by adding '01' for SOAPACTION
       
   309 	// remove existing soap header
       
   310 	headers.RemoveField ( iStringPool.StringF ( UPnP::ESoapAction, TUPnPTable::Table() ) );
       
   311 
       
   312 	RStringF soapHdr = iStringPool.StringF ( UPnP::ESoapHeader, TUPnPTable::Table() );
       
   313 	
       
   314 	// get service name & action name
       
   315 	headers.SetRawFieldL ( soapHdr, iActionValue, KSoapFieldSeparator );
       
   316 
       
   317 	// Transaction is ready for submission.
       
   318 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ReSubmitTransactionL - Submitting transaction")));
       
   319 	iClientHandler->SubmitTransaction( aTransaction );
       
   320 	}
       
   321 
       
   322 void CHttpClientFlow::PrepareAndSubmitTransactionL ( TUpnpMessage::TUPnPClientRequestInfo& aClntReqInfo, TNodeCtxId aChannelId )
       
   323 	{	
       
   324 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL")));
       
   325 	CHTTPClientTransaction* ctrans = CHTTPClientTransaction::NewL ( *iCodec, iStringPool, aChannelId );
       
   326 	CleanupStack::PushL ( ctrans );
       
   327 
       
   328 	RBuf8 uriBuf;
       
   329 	uriBuf.CreateMax( aClntReqInfo.iUri.Length( ) );
       
   330 	CleanupClosePushL( uriBuf );
       
   331 	uriBuf.FillZ( aClntReqInfo.iUri.Length( ) );
       
   332 	aClntReqInfo.iUri.CopyOut( uriBuf );
       
   333 	aClntReqInfo.iUri.Free( );
       
   334 	// Extract the uri path from the absolute uri and set the request uri
       
   335 	SetRequestUriL ( ctrans, uriBuf );
       
   336 	CleanupStack::PopAndDestroy( &uriBuf );
       
   337 
       
   338 	RRequest rrequest = ctrans->Request( )->Handle( );
       
   339 	RStringF method;
       
   340 	RStringF contentLenStrF = iStringPool.StringF ( HTTP::EContentLength, THTTPTable::Table() );
       
   341 	THTTPHdrVal contentLenVal;
       
   342 	TInt contentLength = 0;
       
   343 	contentLenVal.SetInt( contentLength );
       
   344 	switch ( aClntReqInfo.iRequestMethod )
       
   345 		{
       
   346 		case HTTP::EGET:
       
   347 			{
       
   348 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Handling describe(GET) request")));
       
   349 			method = iStringPool.StringF ( HTTP::EGET, THTTPTable::Table() );
       
   350 			rrequest.SetMethod ( method );
       
   351 			}
       
   352 		break;
       
   353 
       
   354 		case UPnP::ESubscribe:
       
   355 			{
       
   356 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Handling SUBSCRIBE request")));
       
   357 			method = iStringPool.StringF ( UPnP::ESubscribe, TUPnPTable::Table() );
       
   358 			rrequest.SetMethod ( method );
       
   359 			BuildSubscribeRequestL ( *(ctrans->Request()), aClntReqInfo );
       
   360 			}
       
   361 		break;
       
   362 
       
   363 		case UPnP::EUnsubscribe:
       
   364 			{
       
   365 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Handling UNSUBSCRIBE request")));
       
   366 			method = iStringPool.StringF ( UPnP::EUnsubscribe, TUPnPTable::Table() );
       
   367 			rrequest.SetMethod ( method );
       
   368 			SetSidHeaderL ( *(ctrans->Request()), aClntReqInfo );
       
   369 			}
       
   370 		break;
       
   371 
       
   372 		case UPnP::ENotify:
       
   373 			{
       
   374 			RMBufChain bufChain;
       
   375 			TUPnPMemoryUtils::CreateMBuf(bufChain, aClntReqInfo.iBody );
       
   376 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Handling NOTIFY request")));
       
   377 			method = iStringPool.StringF ( UPnP::ENotify, TUPnPTable::Table() );
       
   378 			rrequest.SetMethod ( method );
       
   379 			BuildNotifyRequestL ( *(ctrans->Request()), aClntReqInfo );
       
   380 			// set body
       
   381 			contentLength = aClntReqInfo.iBody.Length ( );
       
   382 			contentLenVal.SetInt( contentLength );
       
   383 			ctrans->AddBodyPart( bufChain );
       
   384 			aClntReqInfo.iBody.Free();
       
   385 			}
       
   386 		break;
       
   387 
       
   388 		default:
       
   389 		break;
       
   390 		}
       
   391 
       
   392 	CleanupStack::Pop ( );
       
   393 
       
   394 	rrequest.GetHeaderCollection ( ).SetFieldL ( contentLenStrF, contentLenVal );
       
   395 	// Transaction is ready for submission.
       
   396 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::PrepareAndSubmitTransactionL - Submitting transaction")));
       
   397 	ctrans->SetComplete ();
       
   398 	iClientHandler->SubmitTransaction( ctrans );
       
   399 	}
       
   400 
       
   401 void CHttpClientFlow::SetRequestUriL ( CTransaction* aTrans, const TDesC8& aUri )
       
   402 	{	
       
   403 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetRequestUriL")));
       
   404 	RRequest rrequest = aTrans->Request( )->Handle( );
       
   405 	TUriParser8 uri;
       
   406 	uri.Parse ( aUri );
       
   407 	TPtrC8 ptr;
       
   408 	ptr.Set(uri.UriDes());
       
   409 	ptr.Set(ptr.Mid(ptr.Find(_L8("//")) + 2));
       
   410 	TInt pos = ptr.Locate('/');
       
   411 	if(pos == KErrNotFound)
       
   412 		{
       
   413 		ptr.Set(KSlash());
       
   414 		}
       
   415 	else
       
   416 		{
       
   417 		ptr.Set(ptr.Mid(pos));
       
   418 		}
       
   419 	
       
   420 	TUriParser8 uriPath;
       
   421 	uriPath.Parse(ptr);
       
   422 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetRequestUriL - Setting the URI")));
       
   423 	rrequest.SetURIL ( uriPath );
       
   424 	
       
   425 	
       
   426 	// Set Host Header
       
   427 	TInt port;
       
   428 	if ( uri.IsPresent ( EUriPort ) )
       
   429 		{
       
   430 		const TDesC8& portStr = uri.Extract ( EUriPort );
       
   431 		InetProtTextUtils::ConvertDescriptorToInt ( portStr, port );
       
   432 		LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetRequestUriL - Got the port from URI %d"), port));
       
   433 		}
       
   434 	else
       
   435 		{
       
   436 		LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetRequestUriL - Using default HTTP port 80")));
       
   437 		port = KHttpDefaultPort;
       
   438 		}
       
   439 
       
   440 	SetHostHeaderL ( aTrans, uri.Extract ( EUriHost ), port );
       
   441 	}
       
   442 
       
   443 void CHttpClientFlow::SetHostHeaderL ( CTransaction* aTrans, const TDesC8& aHost, TInt aPort )
       
   444 	{	
       
   445 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetHostHeaderL")));
       
   446 	RStringF hostStr = iStringPool.StringF ( HTTP::EHost, THTTPTable::Table() );
       
   447 	RRequest request = aTrans->Request( )->Handle( );
       
   448     RHTTPHeaders headers = request.GetHeaderCollection();
       
   449 
       
   450 	//If the Host header does not already exist, add it!
       
   451 	THTTPHdrVal hostValue;
       
   452 	if ( headers.GetField ( hostStr, 0, hostValue ) == KErrNotFound )
       
   453 		{
       
   454 		// Set the Host header...
       
   455 		RStringF hostValStr;
       
   456 		// Check if its a literal IPV6 address
       
   457 		UriUtils::TUriHostType aHostsType = UriUtils::HostType ( aHost );
       
   458 		if ( ( aHostsType != UriUtils::ETextHost ) && ( aHostsType != UriUtils::EIPv4Host ) ) // is an IPv6 or other future protocol address
       
   459 			{
       
   460 			HBufC8* ipv6LiteralHost = HBufC8::NewLC ( aHost.Length() + 2 ); // add 2 for the braces
       
   461 
       
   462 			TPtr8 ipv6LiteralHostPtr = ipv6LiteralHost->Des();
       
   463 
       
   464 			ipv6LiteralHostPtr.Append ( KIPv6HostOpenBrace );
       
   465 			ipv6LiteralHostPtr.Append ( aHost );
       
   466 			ipv6LiteralHostPtr.Append ( KIPv6HostCloseBrace );
       
   467 
       
   468 			hostValStr = iStringPool.OpenFStringL( ipv6LiteralHostPtr );
       
   469 			CleanupStack::PopAndDestroy( ipv6LiteralHost );
       
   470 			}
       
   471 		else
       
   472 			{
       
   473 			hostValStr = iStringPool.OpenFStringL( aHost );
       
   474 			}
       
   475 
       
   476 		CleanupClosePushL ( hostValStr );
       
   477 
       
   478 		THTTPHdrVal hostVal ( hostValStr );
       
   479 		headers.SetFieldL ( hostStr, hostVal );
       
   480 		CleanupStack::PopAndDestroy ( &hostValStr );
       
   481 
       
   482 		// Also set the port number if Host header is not empty and a port
       
   483 		// number is not the default.
       
   484 		if ( aPort != KHttpDefaultPort )
       
   485 			{
       
   486 			THTTPHdrVal portVal ( aPort );
       
   487 			RStringF portStr = iStringPool.StringF ( HTTP::EPort,THTTPTable::Table() );
       
   488 			headers.SetParamL ( hostStr, portStr, portVal, 0 );
       
   489 			}
       
   490 		}
       
   491 	}
       
   492 
       
   493 void CHttpClientFlow::BuildSubscribeRequestL ( CRequest& aNewRequest, TUpnpMessage::TUPnPClientRequestInfo& aClntReqInfo )
       
   494 	{	
       
   495 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::BuildSubscribeRequestL")));
       
   496 	TSubscribeRequestInfo& info = *( reinterpret_cast < TSubscribeRequestInfo* > ( aClntReqInfo.iInfo ) );
       
   497 	RStringF strF = iStringPool.StringF ( UPnP::ETimeout, TUPnPTable::Table() );
       
   498 	if(info.iTimeOut != 0)
       
   499 		{
       
   500 		THTTPHdrVal hTimeOutVal(info.iTimeOut);
       
   501 		aNewRequest.Handle().GetHeaderCollection().SetFieldL ( strF, hTimeOutVal );
       
   502 		}
       
   503 
       
   504 	strF = iStringPool.StringF ( UPnP::ECallback, TUPnPTable::Table() );
       
   505 	THTTPHdrVal hCallbackVal;
       
   506 
       
   507 	if ( info.iCallback.Length() > 0 )
       
   508 		{
       
   509 		RBuf8 callbackBuf;
       
   510 		callbackBuf.CreateMax ( info.iCallback.Length( ) );
       
   511 		CleanupClosePushL ( callbackBuf );
       
   512 		callbackBuf.FillZ ( info.iCallback.Length( ) );
       
   513 		info.iCallback.CopyOut ( callbackBuf );
       
   514 		info.iCallback.Free ( );
       
   515 
       
   516 		RStringF callbackStrF = iStringPool.OpenFStringL ( callbackBuf );
       
   517 		CleanupClosePushL ( callbackStrF );
       
   518 		hCallbackVal.SetStrF (callbackStrF );
       
   519 		aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hCallbackVal );
       
   520 		CleanupStack::PopAndDestroy ( &callbackStrF );
       
   521 		CleanupStack::PopAndDestroy ( &callbackBuf );
       
   522 		SetNtHeaderL ( aNewRequest.Handle ( ).GetHeaderCollection ( ) );
       
   523 		}
       
   524 	else
       
   525 		{
       
   526 		SetSidHeaderL ( aNewRequest, aClntReqInfo );
       
   527 		}
       
   528 	}
       
   529 
       
   530 void CHttpClientFlow::SetSidHeaderL ( CRequest& aNewRequest, TUpnpMessage::TUPnPClientRequestInfo& aClntReqInfo )
       
   531 	{	
       
   532 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetSidHeaderL")));
       
   533 	if( aClntReqInfo.iRequestMethod == UPnP::ESubscribe || aClntReqInfo.iRequestMethod == UPnP::EUnsubscribe )
       
   534 		{
       
   535 		TSubscribeRequestInfo& info = *( reinterpret_cast < TSubscribeRequestInfo* > ( aClntReqInfo.iInfo ) );
       
   536 		RStringF strF = iStringPool.StringF ( UPnP::ESID, TUPnPTable::Table() );
       
   537 		THTTPHdrVal hSidVal;
       
   538 
       
   539 		RBuf8 sidBuf;
       
   540 		sidBuf.CreateMax ( info.iSid.Length( ) );
       
   541 		CleanupClosePushL ( sidBuf );
       
   542 		sidBuf.FillZ ( info.iSid.Length( ) );
       
   543 		info.iSid.CopyOut( sidBuf );
       
   544 		//info.iSid.Free ( );
       
   545 		info.iSid.Init();
       
   546 		TPtrC8 asdf(sidBuf);
       
   547 		RStringF sidValStrF = iStringPool.OpenFStringL( sidBuf );
       
   548 		CleanupClosePushL ( sidValStrF );
       
   549 		hSidVal.SetStrF ( sidValStrF );
       
   550 		aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hSidVal );
       
   551 		CleanupStack::PopAndDestroy ( &sidValStrF );
       
   552 		CleanupStack::PopAndDestroy ( &sidBuf );
       
   553 		}
       
   554 	else if ( aClntReqInfo.iRequestMethod == UPnP::ENotify )
       
   555 		{
       
   556 		TEventNotifyRequestInfo& info = *( reinterpret_cast < TEventNotifyRequestInfo* > ( aClntReqInfo.iInfo ) );
       
   557 		RStringF strF = iStringPool.StringF ( UPnP::ESID, TUPnPTable::Table() );
       
   558 		THTTPHdrVal hSidVal;
       
   559 
       
   560 		RBuf8 sidBuf;
       
   561 		sidBuf.CreateMax ( info.iSid.Length( ) );
       
   562 		CleanupClosePushL ( sidBuf );
       
   563 		sidBuf.FillZ ( info.iSid.Length( ) );
       
   564 		info.iSid.CopyOut( sidBuf );
       
   565 		//info.iSid.Free ( );
       
   566 		info.iSid.Init();
       
   567 		RStringF sidValStrF = iStringPool.OpenFStringL( sidBuf );
       
   568 		CleanupClosePushL ( sidValStrF );
       
   569 		hSidVal.SetStrF ( sidValStrF );
       
   570 		aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hSidVal );
       
   571 		CleanupStack::PopAndDestroy ( &sidValStrF );
       
   572 		CleanupStack::PopAndDestroy ( &sidBuf );
       
   573 		}
       
   574 	}
       
   575 
       
   576 void CHttpClientFlow::BuildNotifyRequestL ( CRequest& aNewRequest, TUpnpMessage::TUPnPClientRequestInfo& aClntReqInfo )
       
   577 	{	
       
   578 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::BuildNotifyRequestL")));
       
   579 	TEventNotifyRequestInfo& info = *( reinterpret_cast < TEventNotifyRequestInfo* > ( aClntReqInfo.iInfo ) );
       
   580 	SetSidHeaderL ( aNewRequest, aClntReqInfo );
       
   581 	SetNtHeaderL ( aNewRequest.Handle ( ).GetHeaderCollection ( ) );
       
   582 
       
   583 	RStringF strF = iStringPool.StringF ( UPnP::ESEQ, TUPnPTable::Table() );
       
   584 	THTTPHdrVal hSeqVal( info.iSeqKey );
       
   585 	aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hSeqVal );
       
   586 
       
   587 	strF = iStringPool.StringF ( UPnP::ENTS, TUPnPTable::Table() );
       
   588 	RStringF ntsValStrF = iStringPool.StringF ( UPnP::EUpnpPropChange, TUPnPTable::Table() );
       
   589 	THTTPHdrVal hNtsVal;
       
   590 	hNtsVal.SetStrF ( ntsValStrF );
       
   591 	aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hNtsVal );
       
   592 
       
   593 	// Set content-type
       
   594 	strF = iStringPool.StringF ( HTTP::EContentType, THTTPTable::Table() );
       
   595 	RStringF contentTypeStrF = iStringPool.StringF( UPnP::ETextXml, TUPnPTable::Table() );
       
   596 	THTTPHdrVal hContentTypeVal;
       
   597 	hContentTypeVal.SetStrF ( contentTypeStrF );
       
   598 	aNewRequest.Handle ( ).GetHeaderCollection ( ).SetFieldL ( strF, hContentTypeVal );
       
   599 	}
       
   600 
       
   601 void CHttpClientFlow::SetNtHeaderL ( RHTTPHeaders aHeaders )
       
   602 	{	
       
   603 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetNtHeaderL")));
       
   604 	RStringF strF = iStringPool.StringF ( UPnP::ENT, TUPnPTable::Table() );
       
   605 	RStringF ntValStrF = iStringPool.StringF ( UPnP::EUpnpEvent, TUPnPTable::Table() );
       
   606 	CleanupClosePushL ( ntValStrF );
       
   607 	THTTPHdrVal hNtVal;
       
   608 	hNtVal.SetStrF ( ntValStrF );
       
   609 	aHeaders.SetFieldL ( strF, hNtVal );
       
   610 	CleanupStack::PopAndDestroy ( &ntValStrF );
       
   611 	}
       
   612 
       
   613 
       
   614 MFlowBinderControl* CHttpClientFlow::DoGetBinderControlL ( )
       
   615 	{	
       
   616     return this;
       
   617 	}
       
   618 
       
   619 // MFlowBinderControl
       
   620 CSubConnectionFlowBase* CHttpClientFlow::Flow ( )
       
   621 	{	
       
   622 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Flow")));
       
   623 	return this;
       
   624 	}
       
   625 
       
   626 MSessionControl* CHttpClientFlow::GetControlL ( TInt /*aSessionType*/, MSessionControlNotify& aSessionControlNotify )
       
   627     {	
       
   628     LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::GetControlL")));
       
   629     ASSERT ( iSessionControlNotify == NULL );
       
   630 	iSessionControlNotify = &aSessionControlNotify;
       
   631 
       
   632 	return this;
       
   633     }
       
   634 
       
   635 MSessionData* CHttpClientFlow::BindL ( MSessionDataNotify& aNotify )
       
   636     {	
       
   637     LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::BindL")));
       
   638 	ASSERT ( iSessionDataNotify == NULL );
       
   639 	iSessionDataNotify = &aNotify;
       
   640 	iSubConnectionProvider.PostMessage ( Id (), TCFControlProvider::TActive ().CRef () );
       
   641 	return this;
       
   642     }
       
   643 
       
   644 void CHttpClientFlow::Unbind ( )
       
   645     {	
       
   646     LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Unbind")));
       
   647    	iSessionControlNotify = NULL;
       
   648 	iSessionDataNotify = NULL;
       
   649 	iDCIdle = ETrue;
       
   650 	if ( iSubConnectionProvider.IsOpen ( ) )
       
   651 		{
       
   652 	    iSubConnectionProvider.PostMessage ( Id (), TCFControlProvider::TIdle ().CRef () );
       
   653 		}
       
   654     }
       
   655 
       
   656 // MSessionControl
       
   657 void CHttpClientFlow::Shutdown ( MSessionControl::TCloseType aOption )
       
   658 	{	
       
   659 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Shutdown")));
       
   660 	if ( MSessionControl::ENormal == aOption)
       
   661 		iSessionControlNotify->CanClose( MSessionControlNotify::EDelete);
       
   662 	}
       
   663 
       
   664 void CHttpClientFlow::ActiveOpen ( )
       
   665 	{	
       
   666 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ActiveOpen")));
       
   667 	iSessionControlNotify->ConnectComplete ( );
       
   668 	}
       
   669 
       
   670 TInt CHttpClientFlow::SetRemName ( TSockAddr& anAddr )
       
   671 	{	
       
   672 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetRemName")));
       
   673 	iRemoteAddress = anAddr;
       
   674 	iClientHandler->SetConnectionInfo ( iRemoteAddress );
       
   675 	return KErrNone;
       
   676 	}
       
   677 
       
   678 TInt CHttpClientFlow::GetOption ( TUint aLevel, TUint aName, TDes8& anOption ) const
       
   679 	{	
       
   680 	if ( aLevel == KCHOptionLevel )
       
   681 		{
       
   682 		switch ( aName )
       
   683 			{
       
   684 			case KCHMaxLength:
       
   685 				{
       
   686 				*(TUint*) anOption.Ptr() = iOverallDataSize;
       
   687 				}
       
   688 			break;
       
   689 
       
   690 			case KCHLastMessage:
       
   691 				{
       
   692 				*(TUint*) anOption.Ptr() = ( iResponseCompleted && iBufChain.Length () == 0 );
       
   693 				}
       
   694 			break;
       
   695 
       
   696 			default:
       
   697 				{
       
   698 				ASSERT ( 0 );
       
   699 				}
       
   700 			break;
       
   701 			}
       
   702 		}
       
   703 
       
   704 	return KErrNone;
       
   705 	}
       
   706 
       
   707 TInt CHttpClientFlow::SetOption (TUint aLevel, TUint aName, const TDesC8& anOption)
       
   708 	{	
       
   709 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::SetOption")));
       
   710 
       
   711 	TInt err = KErrNone;
       
   712 	if ( aLevel == KCHOptionLevel )
       
   713 		{
       
   714 		switch ( aName )
       
   715 			{
       
   716 			case KCHAbsoluteUri:
       
   717 				{
       
   718 				err = iRequestUri.Create ( anOption );
       
   719 				}
       
   720 			break;
       
   721 
       
   722 			case KCHMaxLength:
       
   723 				{
       
   724 				TPckgBuf <TCHMessageOption> option;
       
   725 				option.Copy ( anOption );
       
   726 
       
   727 				iChannelIdentifier = option ( ).iId;
       
   728 				iOverallDataSize = option ( ).iValue;
       
   729 				}
       
   730 			break;
       
   731 
       
   732 			default:
       
   733 				{
       
   734 				ASSERT ( 0 );
       
   735 				}
       
   736 			break;
       
   737 			}
       
   738 		}
       
   739 
       
   740 	return err;
       
   741 	}
       
   742 
       
   743 TInt CHttpClientFlow::Write ( RMBufChain& aData, TUint /*aOptions*/, TSockAddr* /*anAddr*/ )
       
   744 	{	
       
   745 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Write")));
       
   746 
       
   747 	// Note!..http client flow of upnp stack doesn't
       
   748 	// supports HTTP chunked encoding for sending request body
       
   749 
       
   750 	__ASSERT_DEBUG ( iOverallDataSize != KErrUnknown, User::Invariant () );
       
   751 
       
   752 	TInt len = aData.Length ( );
       
   753 
       
   754 	if ( iTransactions->Count( ) == 0 )
       
   755 		{
       
   756 		TRAP ( iError, PrepareAndSubmitTransactionL ( aData ) );
       
   757 		if ( iError != KErrNone )
       
   758 			{
       
   759 			if ( !aData.IsEmpty() )
       
   760 				aData.Free ( );
       
   761 			DoReset ( );
       
   762 			return iError;
       
   763 			}
       
   764 		}
       
   765 	else
       
   766 		{
       
   767 		CTransaction* ctrans = iTransactions->Get( 0 );
       
   768 
       
   769 		if ( iActionValue.Length ( ) == 0 )
       
   770 			{			
       
   771 			TBool doSubmit = EFalse;
       
   772 			TRAP ( iError, doSubmit = SetActionHeaderL ( aData ) );
       
   773 			
       
   774 			// Append body parts
       
   775 			ctrans->AddBodyPart ( aData );
       
   776 
       
   777 			if ( iError == KErrNone )
       
   778 				{
       
   779 				// transaction is waiting for more data to build soap action header
       
   780 				if ( doSubmit )
       
   781 					{
       
   782 					// Complete headers are available, so Transaction is ready for submission
       
   783 					LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Write - Submitting transaction")));
       
   784 					iClientHandler->SubmitTransaction( ctrans );					
       
   785 					}
       
   786 				}
       
   787 			else
       
   788 				{
       
   789 				DoReset ( );
       
   790 				return iError;
       
   791 				}
       
   792 			}
       
   793 		else
       
   794 			{
       
   795 			// transaction is waiting for more request body data
       
   796 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::Write - Notfiy new request body parts")));
       
   797 			iClientHandler->NotifyNewRequestBodyData ( ctrans, aData );		
       
   798 			}
       
   799 		SetTransactionComplete ( ctrans );
       
   800 		}	
       
   801 	
       
   802 	aData.Init ( );
       
   803 	return len;
       
   804 	}
       
   805 
       
   806 TInt CHttpClientFlow::GetData ( RMBufChain& aData, TUint aLength, TUint /*aOptions*/, TSockAddr* /*anAddr*/ )
       
   807 	{	
       
   808 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::GetData")));
       
   809 	
       
   810 	if ( iError < 0 )
       
   811 		{
       
   812 		DoReset ();
       
   813 		return iError;
       
   814 		}
       
   815 		
       
   816 	if ( !iReadStreamStarted )
       
   817 		{
       
   818 		TBuf8<sizeof ( TInt )> identifiersBuf;
       
   819 		identifiersBuf.AppendNumFixedWidth ( iChannelIdentifier, EDecimal, sizeof ( TInt ) );
       
   820 		aData.Append ( identifiersBuf.Length () );
       
   821 		aData.CopyIn ( identifiersBuf );
       
   822 		iReadStreamStarted = ETrue;
       
   823 		}
       
   824 	else
       
   825 		{
       
   826 		RMBufChain newChain;
       
   827 		iError = iBufChain.Split ( aLength, newChain );
       
   828 		if ( iError != KErrNone )
       
   829 			{
       
   830 			DoReset ();
       
   831 			return iError;
       
   832 			}
       
   833 		
       
   834 		aData.Assign ( iBufChain );
       
   835 		iBufChain = newChain;
       
   836 		}
       
   837 
       
   838 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::GetData--Data Read by Upper flow--%d"), aData.Length ( )));
       
   839 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::GetData--Data left over--%d"), iBufChain.Length ( )));
       
   840 	
       
   841 	return aData.Length ( );
       
   842 	}
       
   843 
       
   844 void CHttpClientFlow::SetTransactionComplete ( CTransaction* aTransaction )
       
   845 	{
       
   846 	if ( iOverallDataSize == aTransaction->BodyParts ().Length () )
       
   847 		{
       
   848 		aTransaction->SetComplete ();
       
   849 		}
       
   850 	}
       
   851 
       
   852 // MInputStreamObserver
       
   853 TInt CHttpClientFlow::OnHttpEvent ( CTransaction* aTransaction, THTTPEvent& aEvent )
       
   854 	{	
       
   855 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent")));
       
   856 	CHTTPClientTransaction* clientTrans = static_cast<CHTTPClientTransaction*>( aTransaction );
       
   857 
       
   858 	// Process event for Control plane transaction
       
   859 	TNodeCtxId selfCtx ( MeshMachine::KActivityNull, NodeId () );
       
   860 	if ( clientTrans->NodeCtxId () != selfCtx )
       
   861 		{
       
   862 		ProcessControlPlaneResponseEvent ( clientTrans, aEvent );
       
   863 		return KErrNone;
       
   864 		}
       
   865 
       
   866 	// Process event for Socket Transaction
       
   867 	TBool cleanupNeeded = EFalse;
       
   868 	switch ( aEvent.iStatus )
       
   869 		{
       
   870 		case THTTPEvent::EGotResponseHeaders:
       
   871 			{
       
   872 			RResponse response = clientTrans->Response( )->Handle( );
       
   873 			RHTTPHeaders headers = response.GetHeaderCollection ( );
       
   874 
       
   875 			RStringF fieldStr = iStringPool.StringF ( HTTP::EContentLength, THTTPTable::Table ( ) );
       
   876 			THTTPHdrVal value;
       
   877 
       
   878 			if ( headers.GetField ( fieldStr, 0, value ) == KErrNotFound )
       
   879 				{
       
   880 				iOverallDataSize = KErrUnknown;
       
   881 				}
       
   882 			else
       
   883 				{
       
   884 				iOverallDataSize = value.Int ( );
       
   885 				}			
       
   886 			}
       
   887 			break;
       
   888 
       
   889 		case THTTPEvent::EGotResponseBodyData:
       
   890 			{
       
   891 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - THTTPEvent::EGotResponseBodyData")));
       
   892 			
       
   893 			TInt notifyLen = 0;
       
   894 			FillResponseChain ( aTransaction, notifyLen );			
       
   895 			iSessionDataNotify->NewData( notifyLen );
       
   896 			}
       
   897 			break;
       
   898 		
       
   899 		case THTTPEvent::EResponseComplete:
       
   900 			{
       
   901 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - THTTPEvent::EResponseComplete")));
       
   902 			if ( clientTrans->Response( )->Status( ) == HTTPStatus::EMethodNotAllowed )
       
   903 				{
       
   904 				LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - THTTPEvent::EResponseComplete - Response status = %d"), clientTrans->Response( )->Status( )));
       
   905 				
       
   906 				clientTrans->SetComposingStarted ( EFalse );
       
   907 				clientTrans->ResetRequestPart ();
       
   908 				TRAPD ( err, ReSubmitTransactionL ( clientTrans ) );
       
   909 
       
   910 				if ( err != KErrNone )
       
   911 					{
       
   912 					LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - THTTPEvent::EResponseComplete - Error %d while re-submitting trans"), err));
       
   913 					cleanupNeeded = ETrue;
       
   914 					NotifyError ( clientTrans, err );
       
   915 					}
       
   916 				}
       
   917 			else
       
   918 				{
       
   919 				LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - THTTPEvent::EResponseComplete - Response status = %d"), clientTrans->Response( )->Status( )));
       
   920 								
       
   921 				iResponseCompleted = ETrue;
       
   922 				cleanupNeeded = ETrue;
       
   923 				iSessionDataNotify->NewData( sizeof ( TInt ) );
       
   924 				}
       
   925 			}
       
   926 			break;
       
   927 
       
   928 		default:
       
   929 			{
       
   930 			if ( aEvent.iStatus < 0 )
       
   931 				{
       
   932 				LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::OnHttpEvent - Error status = %d"), aEvent.iStatus));
       
   933 				NotifyError ( clientTrans, aEvent.iStatus );
       
   934 				}
       
   935 			}
       
   936 			break;
       
   937 		}
       
   938 	
       
   939 	if ( cleanupNeeded )
       
   940 		{
       
   941 		// body is processed completely, and clienthandler removed it from its array
       
   942 		delete clientTrans;
       
   943 		}
       
   944 	return KErrNone;
       
   945 	}
       
   946 
       
   947 void CHttpClientFlow::ProcessControlPlaneResponseEvent ( CHTTPClientTransaction* aTransaction, THTTPEvent& aEvent )
       
   948 	{	
       
   949 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ProcessControlPlaneResponseEvent")));
       
   950 	TBool iCleanupNeeded = EFalse;
       
   951 
       
   952 	switch ( aEvent.iStatus )
       
   953 		{
       
   954 		case THTTPEvent::ECancel:
       
   955 			{
       
   956 			// post complete message with KErrCancel
       
   957 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ProcessControlPlaneResponseEvent - THTTPEvent::ECancel")));		
       
   958 			RClientInterface::OpenPostMessageClose ( NodeId (), aTransaction->NodeCtxId (), TCFDataClient::TStopped ( 0 ).CRef () );
       
   959 			iCleanupNeeded = ETrue;
       
   960 			}
       
   961 		break;
       
   962 
       
   963 		case THTTPEvent::EGotResponseBodyData:
       
   964 			{
       
   965 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ProcessControlPlaneResponseEvent - THTTPEvent::EGotResponseBodyData")));
       
   966 
       
   967 			TInt notifyLen = 0;
       
   968 			FillResponseChain ( aTransaction, notifyLen );
       
   969 			// Note! no need to process any body parts for control plane transaction
       
   970 			}
       
   971 		break;
       
   972 
       
   973 		case THTTPEvent::EResponseComplete:
       
   974 			{
       
   975 			LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ProcessControlPlaneResponseEvent - THTTPEvent::EResponseComplete")));
       
   976 			CResponse* cresponse = aTransaction->Response( );
       
   977 			RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( ProtocolIntf () )->GetMemoryChunkManager());
       
   978 
       
   979 			RMemChunk memChunk;
       
   980  			TUPnPMemoryUtils::CreateMemChunk(memChunk, iBufChain, allocator );
       
   981 
       
   982 			// request method is subscribe
       
   983 			if ( aTransaction->Request( )->Method( ).Index ( TUPnPTable::Table() )
       
   984 									== UPnP::ESubscribe )
       
   985 				{
       
   986 				if(cresponse->Status() == HTTPStatus::EOk)
       
   987 					{
       
   988 					RHTTPHeaders headers = cresponse->Handle( ).GetHeaderCollection ( );
       
   989 
       
   990 		  			// Timeout field value
       
   991 		  			RStringF fieldNameStr = iStringPool.StringF ( UPnP::ETimeout, TUPnPTable::Table() );
       
   992 		  			THTTPHdrVal timeOutVal;
       
   993 		 			headers.GetField ( fieldNameStr, 0, timeOutVal );
       
   994 					TInt timeOut;					
       
   995 					if ( timeOutVal.Type ( ) == THTTPHdrVal::KNoType )
       
   996 						{
       
   997 						RHTTPHeaders reqHds = aTransaction->Request( )->Handle( ).GetHeaderCollection ( );
       
   998 						reqHds.GetField ( fieldNameStr, 0, timeOutVal );
       
   999 						timeOut = timeOutVal.Int ( );
       
  1000 						}
       
  1001 					else
       
  1002 						{
       
  1003 						timeOut = timeOutVal.Int ( );
       
  1004 						}
       
  1005 						
       
  1006 		 			// SID field value
       
  1007 		 			fieldNameStr = iStringPool.StringF ( UPnP::ESID, TUPnPTable::Table() );
       
  1008 		 			TPtrC8 rawValue;
       
  1009 		 			headers.GetRawField ( fieldNameStr, rawValue );
       
  1010 		 			
       
  1011 		 			RMemChunk sid;
       
  1012 		 			sid.Create ( rawValue, allocator );
       
  1013 		 			
       
  1014 		 			
       
  1015 					TUpnpMessage::TSubscribeResponse msg ( cresponse->Status( ),
       
  1016 															cresponse->Version( ),
       
  1017 															memChunk,
       
  1018 															timeOut,
       
  1019 															sid );					
       
  1020 					RClientInterface::OpenPostMessageClose ( NodeId (), aTransaction->NodeCtxId (), msg );			
       
  1021 					}
       
  1022 				else
       
  1023 					{
       
  1024 					TEBase::TError msg ( TUpnpMessage::TUPnPClientRequestInfo::Id(), cresponse->Status() );
       
  1025 					RClientInterface::OpenPostMessageClose ( NodeId (), aTransaction->NodeCtxId (), msg );
       
  1026 					}
       
  1027 				}
       
  1028 			else
       
  1029 				{
       
  1030 				TUpnpMessage::TResponse msg ( cresponse->Status( ), cresponse->Version( ), memChunk );
       
  1031 				RClientInterface::OpenPostMessageClose ( NodeId (), aTransaction->NodeCtxId (), msg );					
       
  1032 				}
       
  1033 			iBufChain.Free ( );
       
  1034 			iCleanupNeeded = ETrue;
       
  1035 			}
       
  1036 		break;
       
  1037 
       
  1038 		default:
       
  1039 			{
       
  1040 			if ( aEvent.iStatus < 0 )
       
  1041 				{
       
  1042 				LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::ProcessControlPlaneResponseEvent - Error status = %d"), aEvent.iStatus));
       
  1043 				NotifyError ( aTransaction, aEvent.iStatus );
       
  1044 				iCleanupNeeded = ETrue;
       
  1045 				}
       
  1046 			}
       
  1047 		break;
       
  1048 		}
       
  1049 
       
  1050 	if ( iCleanupNeeded )
       
  1051 		{
       
  1052 		// Cleanup
       
  1053 		delete aTransaction;
       
  1054 		}
       
  1055 	}
       
  1056 
       
  1057 void CHttpClientFlow::FillResponseChain ( CTransaction* aTransaction, TInt& aNewLen )
       
  1058 	{	
       
  1059 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::FillResponseChain")));
       
  1060 	MHTTPDataSupplier* bodySupplier = aTransaction->Response( )->Body( );
       
  1061 	TPtrC8 bodyPtr;
       
  1062 	RMBufChain bodyChain;
       
  1063 
       
  1064 	bodySupplier->GetNextDataPart ( bodyPtr );
       
  1065 	bodyChain.Create ( bodyPtr );
       
  1066 	iBufChain.Append ( bodyChain );
       
  1067 
       
  1068 	bodySupplier->ReleaseData( );
       
  1069 
       
  1070 	aNewLen = bodyPtr.Length ( );
       
  1071 
       
  1072 	LOG(ESockLogExternal::Printf(KSubsysHttpClntFlow, KComponent, _L8("CHttpClientFlow::FillResponseChain--chunk length from parser = %d"), aNewLen));
       
  1073 	}
       
  1074 
       
  1075 void CHttpClientFlow::NotifyError ( CHTTPClientTransaction* aTransaction, TInt aError )
       
  1076 	{		
       
  1077 	TNodeCtxId selfCtx ( MeshMachine::KActivityNull, NodeId () );
       
  1078 	if ( aTransaction->NodeCtxId () != selfCtx )
       
  1079 		{
       
  1080 		// For SCPR Transactions post error response and cleanup
       
  1081 		TEBase::TError msg ( TUpnpMessage::TUPnPClientRequestInfo::Id ( ), aError );
       
  1082 		RClientInterface::OpenPostMessageClose ( NodeId (), aTransaction->NodeCtxId (), msg );		
       
  1083 		}
       
  1084 	else
       
  1085 		{
       
  1086 		// Handle error for socket transactions
       
  1087 		iError = aError;
       
  1088 		iResponseCompleted = ETrue;
       
  1089 		iOverallDataSize = sizeof ( TInt );
       
  1090 		iSessionDataNotify->NewData( iOverallDataSize );
       
  1091 		}		
       
  1092 	}
       
  1093 
       
  1094 void CHttpClientFlow::DoReset ( )
       
  1095 	{	
       
  1096 	iResponseCompleted = EFalse;
       
  1097 	iOverallDataSize = 0;
       
  1098 
       
  1099 	iRequestUri.Close ( );
       
  1100 	iActionValue.Close ( );
       
  1101 	iRemoteAddress.FillZ ( );
       
  1102 	iBufChain.Free ( );
       
  1103 
       
  1104 	if ( iTransactions->Count() )
       
  1105 		{
       
  1106 		CHTTPClientTransaction* ctrans = iTransactions->Get( 0 );
       
  1107 		delete ctrans;
       
  1108 		iTransactions->Remove( 0 );
       
  1109 		}
       
  1110 	}