servicediscoveryandcontrol/pnp/test/upnp/Server/Flow/src/httpmudpflow.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 // @internalComponent
       
    15 // 
       
    16 //
       
    17 
       
    18 //System Includes
       
    19 #include <comms-infras/ss_nodeinterfaces.h>
       
    20 #include <comms-infras/ss_nodemessages_factory.h>
       
    21 #include <ss_glob.h>
       
    22 
       
    23 //Local Includes
       
    24 #include "httpmudpflow.h"
       
    25 #include "upnppint.h"
       
    26 #include "upnpctrlscprstates.h"
       
    27 #include "upnpstatemachine.h"
       
    28 #include "upnpserverconstants.h"
       
    29 #include "upnplog.h"
       
    30 #include "upnpmemoryutils.h"
       
    31 
       
    32 #include <http/thttptable.h>
       
    33 #include <http/framework/cheadercodecplugin.h>
       
    34 #include <httpstringconstants.h>
       
    35 #include <upnp/tupnptable.h>
       
    36 #include <e32math.h>
       
    37 
       
    38 const TUint KDeftMaxAgeVal = 1800;
       
    39 
       
    40 __FLOG_STMT(_LIT8(KComponent,"Flow");)
       
    41 CHttpMUdpFlow* CHttpMUdpFlow::NewL ( CSubConnectionFlowFactoryBase& aFactory,
       
    42 						  			CUPnPProtocolIntfBase* aProtocolIntf,
       
    43 					  				const TNodeId& aSubConnId )
       
    44 	{
       
    45 	CHttpMUdpFlow* self = new ( ELeave )CHttpMUdpFlow ( aFactory, aProtocolIntf, aSubConnId );
       
    46 	CleanupStack::PushL ( self );
       
    47 	self->ConstructL ();
       
    48 	CleanupStack::Pop (); // self
       
    49 	return self;
       
    50 	}
       
    51 
       
    52 CHttpMUdpFlow::CHttpMUdpFlow ( CSubConnectionFlowFactoryBase& aFactory,
       
    53 					CUPnPProtocolIntfBase* aProtocolIntf,
       
    54 					const TNodeId& aSubConnId )
       
    55 	: CUPnPFlowBase ( aFactory, aProtocolIntf, EHttpMUdpFlow, aSubConnId ), iIsStarted ( EFalse ), iIsLeaving ( EFalse )
       
    56 	{
       
    57 	LOG_NODE_CREATE(KESockFlowTag, CHttpMUdpFlow);
       
    58 	}
       
    59 
       
    60 CHttpMUdpFlow::~CHttpMUdpFlow ()
       
    61 	{
       
    62 	delete iRequestParser;
       
    63 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("Destroying iReceivedData")));
       
    64 	if ( !iReceivedData.IsEmpty () )
       
    65 		iReceivedData.Free ();
       
    66 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("Destroying iUPnPRequest")));
       
    67 	delete iUPnPRequest;
       
    68 	iRecvElements.Reset ();
       
    69 	//delete iCodec;
       
    70 
       
    71 	__ASSERT_DEBUG ( iSearchTargetArray.Count () == 0, User::Invariant () );
       
    72 	iSearchTargetArray.Close ();
       
    73 	__ASSERT_DEBUG ( iNotifyTargetArray.Count () == 0, User::Invariant () );
       
    74 	iNotifyTargetArray.Close ();
       
    75 	iListenRequestors.Reset ();
       
    76 
       
    77 	iStringPool.Close();
       
    78 	
       
    79 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("Destroying iSubConnectionProvider")));
       
    80 	iSubConnectionProvider.Close ();
       
    81 	__ASSERT_DEBUG ( iTimerMappedArray.Count () == 0, User::Invariant () );
       
    82 	iTimerMappedArray.ResetAndDestroy();
       
    83 	__ASSERT_DEBUG ( iCallbackArray.Count () == 0, User::Invariant () );
       
    84 	iCallbackArray.ResetAndDestroy();
       
    85 	if ( iDeltaTimer )
       
    86 		iDeltaTimer->Cancel();	
       
    87 	delete iDeltaTimer;
       
    88 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("Destroyed CHttpMUdpFlow")));
       
    89 	LOG_NODE_DESTROY(KESockFlowTag, CHttpMUdpFlow);
       
    90 	}
       
    91 
       
    92 
       
    93 void CHttpMUdpFlow::ConstructL ()
       
    94 	{
       
    95 	TAppProtIntfMessage::RegisterL (); // Register the message with COMMS transport
       
    96 	iStringPool.OpenL(TUPnPTable::Table());
       
    97 	iStringPool.OpenL(THTTPTable::Table());
       
    98 	iCodec = CHeaderCodecPlugin::NewL ( KUPnPCodecName, iStringPool );
       
    99 	iRequestParser = CUpnpRequestParser::NewL ( *this );
       
   100 	iUPnPRequest = CRequest::NewL ( *iCodec, iStringPool );
       
   101 	// Create a delta timer with the given priority
       
   102 	iDeltaTimer=CDeltaTimer::NewL(EPriorityLow);
       
   103 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("Created CHttpMUdpFlow")));
       
   104 	}
       
   105 
       
   106 void CHttpMUdpFlow::ReceivedL ( const TRuntimeCtxId& aSender, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage )
       
   107 	{
       
   108 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL")));
       
   109 
       
   110 	if ( aMessage.IsMessage<TEChild::TDestroy> () )
       
   111 		{
       
   112     	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TCFMessage::TDestroy")));
       
   113     	if ( RemoveControlClient ( FindControlClient ( address_cast<TNodeId> ( aSender ) ) ) == 0 )
       
   114     		{
       
   115     		LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TCFMessage::TDestroy - Deleting current flow")));
       
   116    			DeleteThisFlow ();
       
   117     		}
       
   118 		}
       
   119 	else if ( aMessage.IsMessage<TCFDataClient::TStart> () )
       
   120 		{
       
   121         LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TCFMessage::TDataClientStart")));
       
   122         StartFlow ( address_cast<TNodeCtxId> ( aSender ) );
       
   123     	}
       
   124     else if ( aMessage.IsMessage<TCFDataClient::TStop> () )
       
   125 		{
       
   126 		LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TUpnpMessage::TUPnPStopSearch")));
       
   127 
       
   128 		Unregister ( address_cast<TNodeCtxId> ( aSender ) );
       
   129         StopFlow ( address_cast<TNodeCtxId> ( aSender ) );
       
   130         }
       
   131 	else if ( aMessage.IsMessage<TCFFactory::TPeerFoundOrCreated> () )
       
   132 		{
       
   133 		LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TCFMessage::TFOCreated")));
       
   134 		const TCFFactory::TPeerFoundOrCreated& msg = message_cast < const TCFFactory::TPeerFoundOrCreated > ( aMessage );
       
   135 		iAppProtIntfId = msg.iNodeId;
       
   136 		
       
   137 		TAppProtAddr mCastAddr( KSsdpMulticastAddr, KUpnpMCPort );
       
   138 		RClientInterface::OpenPostMessageClose ( TNodeCtxId ( MeshMachine::KActivityNull, NodeId () ), iAppProtIntfId, TAppProtIntfMessage::TJoinWithMulticastAddress ( mCastAddr ).CRef () );
       
   139 		}
       
   140 	else if ( TAppProtIntfMessage::ERealmId == aMessage.MessageId ().Realm () )
       
   141 		{
       
   142         switch ( aMessage.MessageId ().MessageId () )
       
   143 	        {
       
   144 			case TAppProtIntfMessage::TJoinComplete::EId:
       
   145 				{
       
   146 				LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TAppProtIntfMessage::TJoinComplete")));
       
   147 				iIsStarted = ETrue;
       
   148 				for ( TInt i = 0; i < iListenRequestors.Count (); i++ )
       
   149 					{
       
   150 					RClientInterface::OpenPostMessageClose ( NodeId (), iListenRequestors[i], TCFDataClient::TStarted ().CRef () );
       
   151 					}
       
   152 
       
   153 				iListenRequestors.Reset ();
       
   154 				}
       
   155 			break;
       
   156 
       
   157 			case TAppProtIntfMessage::TLeaveComplete::EId:
       
   158 				{
       
   159 				LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TAppProtIntfMessage::TLeaveComplete")));
       
   160 				// post destroy to service provider
       
   161 				RClientInterface::OpenPostMessageClose ( NodeId (), iAppProtIntfId, TAppProtIntfMessage::TDestroy ().CRef () );
       
   162 				// post dataclient stopped to controlprovider
       
   163 				PostDataClientStopped ( iLastLeavingClient );
       
   164 				}
       
   165 			break;
       
   166 
       
   167 	        case TAppProtIntfMessage::TDataReceived::EId:
       
   168 	        	{
       
   169 	        	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TAppProtIntfMessage::TDataReceived")));
       
   170 	        	TAppProtIntfMessage::TDataReceived& msg = message_cast <TAppProtIntfMessage::TDataReceived> ( aMessage );
       
   171 	        	
       
   172 	        	if ( !iIsLeaving )
       
   173 		        	{
       
   174 		        	RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( ProtocolIntf () )->GetMemoryChunkManager());
       
   175 		        	RMemChunk memChunk;
       
   176 		        	TUPnPMemoryUtils::CreateMemChunk(memChunk, msg.iData, allocator);
       
   177 
       
   178 					CRecvElement* element = new ( ELeave ) CRecvElement ( memChunk, msg.iAddr );
       
   179 					CleanupStack::PushL ( element );
       
   180 					iRecvElements.AppendL ( element );
       
   181 					CleanupStack::Pop ( element );
       
   182 					ParseIfOneRecvElement ();
       
   183 		        	}
       
   184 	        	msg.iData.Free ();
       
   185 	        	}
       
   186 	        break;
       
   187 
       
   188 	        case TAppProtIntfMessage::TError::EId:
       
   189 	        	{
       
   190 	        	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TAppProtIntfMessage::TError")));
       
   191 	        	// Note! Nothing to do if already leaving state,
       
   192 				// else need to send error to control clients and do listener cleanup
       
   193 	        	}
       
   194 	        break;
       
   195 
       
   196 	        default:
       
   197 		    break;
       
   198 	        }
       
   199 		}
       
   200 	else if ( TUpnpMessage::ERealmId == aMessage.MessageId ().Realm () )
       
   201 		{
       
   202 		switch ( aMessage.MessageId ().MessageId () )
       
   203 			{
       
   204 			case TUpnpMessage::TUPnPNotifyRegistration::EId:
       
   205 				{
       
   206 				LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TUpnpMessage::TUPnPNotifyRegistration")));
       
   207 				RegisterL ( address_cast<TNodeCtxId> ( aSender ),
       
   208 							static_cast < TUpnpMessage::TUPnPNotifyRegistration& > ( aMessage ).iSsdpInfo.iSearchTarget,
       
   209 							iNotifyTargetArray );
       
   210 				}
       
   211 			break;
       
   212 
       
   213 			case TUpnpMessage::TUPnPPublishRegistration::EId:
       
   214 				{
       
   215 				LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReceivedL - TUpnpMessage::TUPnPPublishRegistration")));
       
   216 				RegisterL ( address_cast<TNodeCtxId> ( aSender ),
       
   217 							static_cast < TUpnpMessage::TUPnPPublishRegistration& > ( aMessage ).iSsdpInfo.iSearchTarget,
       
   218 							iSearchTargetArray );
       
   219 				}
       
   220 			break;
       
   221 
       
   222  			case TUpnpMessage::TCancelRequest::EId:
       
   223  				{
       
   224             	Unregister ( address_cast<TNodeCtxId> ( aSender ) );
       
   225 				RClientInterface::OpenPostMessageClose ( NodeId (), address_cast<TNodeCtxId> ( aSender ), TUpnpMessage::TCancelled ().CRef () );
       
   226  				}
       
   227             break;
       
   228 			}
       
   229 		}
       
   230 	}
       
   231 	
       
   232 
       
   233 void CHttpMUdpFlow::StartFlow ( TNodeCtxId aSender )
       
   234 	{
       
   235 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("HttpMUdpFlow::StartFlow")));
       
   236 	if ( iIsStarted )
       
   237 		{
       
   238 		RClientInterface::OpenPostMessageClose ( NodeId (), aSender, TCFDataClient::TStarted ().CRef () );
       
   239 		return;
       
   240 		}
       
   241 
       
   242 	if ( !iIsStarted && iListenRequestors.Count () == 0 )
       
   243 		{
       
   244 		iListenRequestors.Append ( aSender );
       
   245 		CreateMulticastListener  ();
       
   246 		iIsLeaving = EFalse;
       
   247 		}
       
   248 
       
   249 	}
       
   250 
       
   251 void CHttpMUdpFlow::StopFlow ( TNodeCtxId aSender )
       
   252 	{
       
   253 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::StopFlow")));
       
   254 
       
   255 	SetClientLeaving ( aSender ); // set the control client leaving
       
   256 
       
   257 	if ( iIsStarted && CheckIfAllClientsLeaving ( ) )
       
   258 		{
       
   259 		MarkMeForDeletion ();
       
   260 		iLastLeavingClient = aSender;
       
   261 		iIsLeaving = ETrue;
       
   262 		iIsStarted = EFalse;
       
   263 
       
   264 		LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::StopFlow - Posting message TAppProtIntfMessage::TLeave")));
       
   265 		// leaving service provider
       
   266 		RClientInterface::OpenPostMessageClose ( TNodeCtxId ( MeshMachine::KActivityNull, NodeId () ), iAppProtIntfId, TAppProtIntfMessage::TClientLeavingRequest ().CRef () );
       
   267 		}
       
   268 	else
       
   269 		{
       
   270 		PostDataClientStopped ( aSender );
       
   271 		}
       
   272 	}
       
   273 
       
   274 void CHttpMUdpFlow::ParseIfOneRecvElement ()
       
   275 	{
       
   276 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ParseIfOneRecvElement")));
       
   277 	if ( iRecvElements.Count () == 1 )
       
   278 		{
       
   279 		ParseElement ();
       
   280 		}
       
   281 	}
       
   282 
       
   283 void CHttpMUdpFlow::ParseElement ()
       
   284 	{
       
   285 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ParseElement")));
       
   286 	if ( iRecvElements.Count () > 0 )
       
   287 		{
       
   288 		LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ParseElement - Parsing request")));
       
   289 		iRequestParser->ParseRequest ( iRecvElements[0]->Data (), iUPnPRequest );
       
   290 		}
       
   291 	}
       
   292 
       
   293 void CHttpMUdpFlow::RemoveFirstRecvElement ()
       
   294 	{
       
   295 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::RemoveFirstRecvElement")));
       
   296 	ASSERT ( iRecvElements.Count () > 0 );
       
   297 	CRecvElement* element = iRecvElements[0];
       
   298 	iRecvElements.Remove (0);
       
   299 	delete element;
       
   300 	}
       
   301 
       
   302 // From MParserObserver
       
   303 void CHttpMUdpFlow::GotHeaders ()
       
   304 	{
       
   305 	if ( ValidateRequest () != KErrNone )
       
   306 		{
       
   307 		DataParsed ();
       
   308 		}
       
   309 
       
   310 	// Else we will notify to the SCPR(s) from ParsingComplete.
       
   311 	}
       
   312 
       
   313 void CHttpMUdpFlow::DataParsed()
       
   314 	{
       
   315 	// Bad data. This is UDP. we should get everything or none
       
   316 	iRequestParser->DataFailed ();
       
   317 	iRequestParser->ResetParser ();
       
   318 	RemoveFirstRecvElement ();
       
   319 	ParseElement ();
       
   320 	}
       
   321 
       
   322 void CHttpMUdpFlow::ParsingComplete ( RMemChunk& /*aExcessData*/ )
       
   323 	{
       
   324 	NotifyClients ();
       
   325 	DataParsed ();
       
   326 	iUPnPRequest->Reset();
       
   327 	}
       
   328 
       
   329 void CHttpMUdpFlow::ParserError ( TInt /*aError*/ )
       
   330 	{
       
   331 	DataParsed (); // Bad data.
       
   332 	}
       
   333 
       
   334 
       
   335 void CHttpMUdpFlow::NotifyClients ()
       
   336 	{
       
   337 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::NotifyClients")));
       
   338 	TInt method = iUPnPRequest->Handle ().Method ().Index ( TUPnPTable::Table() );
       
   339 	if ( method == UPnP::ENotify )	//control point end listening for notify packets
       
   340 		{
       
   341 		LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::NotifyClients - Handling NOTIFY request")));
       
   342 		TRAP_IGNORE ( HandleNotifyRequestL () );
       
   343 		}
       
   344 	else //if ( method == UPnP::EMSearch ) //service point end listening for m-search packets
       
   345 		{
       
   346 		LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::NotifyClients - Handling MSEARCH request")));
       
   347 		// CreateTimerEntry sets iEntry to the new timer entry and queues it in the deltatimer
       
   348 		TRAP_IGNORE ( CreateTimerEntryL() );
       
   349 		}
       
   350 	
       
   351 	return;
       
   352 	}
       
   353 
       
   354 void CHttpMUdpFlow::ReadRequestValues ( RStringF& aLocation, TInt& aMaxAge )
       
   355 	{
       
   356 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReadRequestValues - ST, USN, Location values")));
       
   357 	THTTPHdrVal value;
       
   358 	GetHeaderValue ( *iUPnPRequest, HTTP::ELocation, value , THTTPTable::Table());
       
   359 	aLocation = value.StrF ();
       
   360 
       
   361 	value.SetInt(KDeftMaxAgeVal);
       
   362 	GetParamValue ( *iUPnPRequest, HTTP::ECacheControl, HTTP::EMaxAge, value, THTTPTable::Table() );
       
   363 	aMaxAge = value.Int();
       
   364 	}
       
   365 
       
   366 void CHttpMUdpFlow::ReadRequestValues ( RStringF& aSt, RStringF& aUsn, RStringF& aNts)
       
   367 	{
       
   368 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReadRequestValues - ST, USN values")));
       
   369 	THTTPHdrVal value = RStringF();
       
   370 	GetHeaderValue ( *iUPnPRequest, UPnP::EUSN, value, TUPnPTable::Table() );
       
   371 	aUsn = value.StrF ();
       
   372 
       
   373 	GetHeaderValue ( *iUPnPRequest, UPnP::ENT, value, TUPnPTable::Table() );
       
   374 	aSt = value.StrF ();
       
   375 
       
   376 	GetHeaderValue ( *iUPnPRequest, UPnP::ENTS, value, TUPnPTable::Table() );
       
   377 	aNts = value.StrF ();
       
   378 	}
       
   379 
       
   380 void CHttpMUdpFlow::ReadRequestValues ( TInt& aMaxAge, RStringF& aSt )
       
   381 	{
       
   382 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ReadRequestValues - Max-Age, NT values")));
       
   383 	THTTPHdrVal value;
       
   384 	GetHeaderValue ( *iUPnPRequest, UPnP::EMX, value, TUPnPTable::Table() );
       
   385 	aMaxAge = value.Int();
       
   386 
       
   387 	GetHeaderValue ( *iUPnPRequest, UPnP::EST, value, TUPnPTable::Table() );
       
   388 	aSt = value.StrF ();
       
   389 	}
       
   390 
       
   391 
       
   392 void CHttpMUdpFlow::HandleNotifyRequestL ()
       
   393 	{
       
   394 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::HandleNotifyRequest")));
       
   395 	RStringF usn;
       
   396 	RStringF st;
       
   397 	RStringF nts;
       
   398 	RStringF location;
       
   399 	TInt maxAge = 0;
       
   400 	THTTPHdrVal value;
       
   401 	ReadRequestValues ( st, usn, nts );
       
   402 	for ( TInt i = 0; i < iNotifyTargetArray.Count (); ++i )
       
   403 		{
       
   404 		const CSearchTarget& target = *(iNotifyTargetArray[i]);
       
   405 
       
   406 		if ( target.Match ( st.DesC() ) != KErrNotFound &&
       
   407 		 							!IsClientLeaving ( target.Originator () ) )
       
   408 			{
       
   409 			// We have a match. Post the information to our control client
       
   410 			RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( ProtocolIntf () )->GetMemoryChunkManager());
       
   411 			
       
   412 			RMemChunk usnBuf;
       
   413 			RMemChunk stBuf;
       
   414 			usnBuf.CreateL ( usn.DesC (), allocator );
       
   415 			TCleanupItem item ( &UPnPStateMachine::CUPnPUtils::CleanupMBufChain, &usnBuf );
       
   416 			CleanupStack::PushL ( item );
       
   417 			stBuf.CreateL ( st.DesC (), allocator );
       
   418 			TCleanupItem item2 ( &UPnPStateMachine::CUPnPUtils::CleanupMBufChain, &stBuf );
       
   419 			CleanupStack::PushL ( item2 );
       
   420 			if ( nts.DesC().CompareF ( KSsdpAlive ) == 0 )
       
   421 				{
       
   422 				LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::HandleNotifyRequest - Posting message TUpnpMessage::TUPnPPublishAliveRequest")));
       
   423 				ReadRequestValues ( location, maxAge );
       
   424 				RMemChunk locationBuf;
       
   425 				locationBuf.CreateL ( location.DesC (), allocator );
       
   426 				TCleanupItem item3 ( &UPnPStateMachine::CUPnPUtils::CleanupMBufChain, &locationBuf );				
       
   427 				CleanupStack::PushL ( item3 );
       
   428 				
       
   429 				TSsdpInfo info ( maxAge, locationBuf, usnBuf, stBuf );
       
   430 				RClientInterface::OpenPostMessageClose ( NodeId (), target.Originator (), TUpnpMessage::TUPnPPublishAliveRequest ( info ).CRef () );
       
   431 				
       
   432 				CleanupStack::Pop (); // item3
       
   433 				}
       
   434 			else
       
   435 				{
       
   436 				LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::HandleNotifyRequest - Posting message TUpnpMessage::TUPnPPublishByeRequest")));
       
   437 				TSsdpInfo info ( usnBuf, stBuf );
       
   438 				RClientInterface::OpenPostMessageClose ( NodeId (), target.Originator (), TUpnpMessage::TUPnPPublishByeRequest ( info ).CRef () );
       
   439 				}
       
   440 			CleanupStack::Pop (); // item2
       
   441 			CleanupStack::Pop (); // item3
       
   442 			}
       
   443 
       
   444 		}
       
   445 	}
       
   446 
       
   447 TInt CHttpMUdpFlow::HandleMSearchRequestL ( TAny* aPtr )
       
   448 	{
       
   449 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::HandleMSearchRequest")));	
       
   450 	CCallbackArgument* pointerData= static_cast<CCallbackArgument*> (aPtr);
       
   451 	CHttpMUdpFlow* thisObject= static_cast < CHttpMUdpFlow* > (pointerData->GetThisPointer());
       
   452 	RPointerArray<CTimerMappedUri>& rArray=thisObject->GetTimerArray();
       
   453 	RPointerArray<CCallbackArgument>& argArray = thisObject->GetArgumentArray();
       
   454 	CTimerMappedUri* timerUri = NULL;
       
   455 	for(TInt index=0; index < rArray.Count();index++)
       
   456 		{
       
   457 		if(rArray[index]->MatchTimerEntry( pointerData->GetTimerEntry() ))
       
   458 			{
       
   459 			// Removes the uri entry from the array
       
   460 			timerUri = rArray[index];
       
   461 			rArray.Remove(index);
       
   462 			break;
       
   463 			}
       
   464 		}
       
   465 	TInt index = argArray.Find( pointerData );
       
   466 	__ASSERT_DEBUG(index >= 0 , User::Invariant());
       
   467 	argArray.Remove( index );
       
   468 	const CSearchTarget& target = *(pointerData->SearchTarget());
       
   469 	// We have a match. Post the information to our control client
       
   470 	if ( !(thisObject->IsClientLeaving ( target.Originator () ) ))
       
   471 		{
       
   472 		RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( thisObject->ProtocolIntf () )->GetMemoryChunkManager());
       
   473 		RMemChunk stBuf;
       
   474 		if ( timerUri->GetUri().CompareF(KSsdpAll) == 0 )
       
   475 			{
       
   476 			stBuf.CreateL ( target.SearchTarget(), allocator );
       
   477 			}
       
   478 		else
       
   479 			{
       
   480 			stBuf.CreateL ( timerUri->GetUri(), allocator );			
       
   481 			}
       
   482 
       
   483 		TSsdpInfo info ( stBuf, pointerData->GetAddress()  );
       
   484 		RClientInterface::OpenPostMessageClose ( thisObject->NodeId (), target.Originator (), TUpnpMessage::TUPnPSearchRequest ( info ).CRef () );	
       
   485 		}
       
   486 	
       
   487 	delete timerUri;
       
   488 	delete pointerData;
       
   489 	return KErrNone;
       
   490 	}
       
   491 
       
   492 void CHttpMUdpFlow::RegisterL ( TNodeCtxId aChannelId, RMemChunk& aST, CSearchTargetArray& aArray )
       
   493 	{
       
   494 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::RegisterL")));
       
   495 	CSearchTarget* searchTarget = new ( ELeave ) CSearchTarget ( aChannelId );
       
   496 	CleanupStack::PushL ( searchTarget );
       
   497 	searchTarget->AddTargetL ( aST );
       
   498 	aArray.AppendL ( searchTarget );
       
   499 	CleanupStack::Pop (); // searchTarget
       
   500 	}
       
   501 
       
   502 void CHttpMUdpFlow::Unregister ( TNodeCtxId aSender )
       
   503 	{
       
   504 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::Unregister")));
       
   505 	
       
   506 	TBool isPublisher = EFalse;
       
   507 	TInt i = iSearchTargetArray.Count () - 1;
       
   508 	while ( i >= 0)
       
   509 		{	
       
   510 		if ( aSender.Ptr () == iSearchTargetArray[i]->Originator ().Ptr () )
       
   511 					  			// for Published SCPR there is no activity running,
       
   512 								// For Embedded and Root Device SCPR, there will be
       
   513 								// multiple Entries in SearchTargetArray, which will be removed with
       
   514 								// one TDataClientStop Message
       
   515 			{
       
   516 			LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::Unregister - target found in search array")));
       
   517 			CSearchTarget *target = iSearchTargetArray[i];
       
   518 			iSearchTargetArray.Remove(i);
       
   519 			CCallbackArgument* callArgument;
       
   520 			TInt index = iCallbackArray.Count() - 1;
       
   521 			while ( index >= 0 )
       
   522 				{
       
   523 				if (target == iCallbackArray[index]->SearchTarget())
       
   524 					{
       
   525 					callArgument  = iCallbackArray[index];
       
   526 					iCallbackArray.Remove( index );
       
   527 					for ( TInt j = 0; j < iTimerMappedArray.Count (); j++ )
       
   528 						{
       
   529 						if ( iTimerMappedArray[j]->MatchTimerEntry( callArgument->GetTimerEntry() ) )
       
   530 							{
       
   531 							// Removes the uri entry from the array
       
   532 							CTimerMappedUri* timerUri = iTimerMappedArray[j];
       
   533 							iDeltaTimer->Remove(timerUri->GetTimerEntry());
       
   534 							iTimerMappedArray.Remove(j);
       
   535 							delete timerUri;
       
   536 							break;
       
   537 							}
       
   538 						}
       
   539 					delete callArgument;	
       
   540 					}
       
   541 				--index;
       
   542 				}
       
   543 				
       
   544 			delete target;
       
   545 			isPublisher = ETrue;
       
   546 			}
       
   547 		
       
   548 		--i;
       
   549 		}
       
   550 	if ( isPublisher )
       
   551 		{
       
   552 		return;
       
   553 		}
       
   554 		
       
   555 	for ( TInt i = 0; i < iNotifyTargetArray.Count (); ++i )
       
   556 		{
       
   557 		if ( aSender == iNotifyTargetArray[i]->Originator () )	// for Register Notify if the activity is not running,
       
   558 															// there will not be any Entry in NotifyTargetArray
       
   559 			{
       
   560 			LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::Unregister - target found in notify array")));
       
   561 			CSearchTarget *target = iNotifyTargetArray[i];
       
   562 			iNotifyTargetArray.Remove(i);
       
   563 			delete target;
       
   564 			return;
       
   565 			}
       
   566 		}	
       
   567 	}
       
   568 
       
   569 void CHttpMUdpFlow::CreateMulticastListener ()
       
   570 	{
       
   571 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::CreateMulticastListener")));
       
   572 	const TInt KAppProtIntfFactoryUid = 0x2000D05B; // Put in common place
       
   573 	//const TInt KGenericContainerIndex = 1;
       
   574 	TAppProtIntfQuery query ( KProtocolInetUdp, KUpnpMCPort );
       
   575 		
       
   576 	TCFFactory::TFindOrCreatePeer foMsg ( TCFPlayerRole::EDataPlane, TUid::Uid( KAppProtIntfFactoryUid ), &query );
       
   577    // foMsg.PostTo ( SockManGlobals::Get()->GetPlaneFC ( EDataPlane, KGenericContainerIndex ) );
       
   578     TNodeId containerId = static_cast<CUPnPProtocolIntfBase*>(ProtocolIntf())->GetAppProtIntfContainerId();
       
   579     if ( containerId != TNodeId::NullId ( ) )
       
   580     	{
       
   581 		RClientInterface::OpenPostMessageClose ( NodeId (), containerId, foMsg );
       
   582     	}
       
   583 	}
       
   584 
       
   585 TInt CHttpMUdpFlow::ValidateRequest ()
       
   586 	{
       
   587 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateRequest")));
       
   588 	TInt err = KErrNone;
       
   589 	TInt method = iUPnPRequest->Handle ().Method ().Index ( TUPnPTable::Table() );
       
   590 
       
   591 	switch ( method )
       
   592 		{
       
   593 		case UPnP::ENotify:
       
   594 			{
       
   595 			LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateRequest - Validating NOTIFY request")));
       
   596 			err = ValidateNotifyRequest ();
       
   597 			}
       
   598 		break;
       
   599 
       
   600 		case UPnP::EMSearch:
       
   601 			{
       
   602 			LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateRequest - Validating MSEARCH request")));
       
   603 			err = ValidateMSearchRequest ();
       
   604 			}
       
   605 		break;
       
   606 
       
   607 		default:
       
   608 		err = KErrCorrupt;
       
   609 		break;
       
   610 		}
       
   611 
       
   612 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateRequest - Validating returned with error code = %d"), err));
       
   613 	return err;
       
   614 	}
       
   615 
       
   616 TInt CHttpMUdpFlow::ValidateNotifyRequest ()
       
   617 	{
       
   618 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateNotifyRequest")));
       
   619 	
       
   620 	if ( IsHeaderPresent ( *iUPnPRequest, UPnP::ENTS, TUPnPTable::Table() ) != KErrNone )
       
   621 		return KErrCorrupt;
       
   622 	
       
   623 	THTTPHdrVal value;
       
   624 	GetHeaderValue ( *iUPnPRequest, UPnP::ENTS, value, TUPnPTable::Table() );
       
   625 	if(value.StrF ().DesC().CompareF ( KSsdpBye )!= 0)
       
   626 		{
       
   627 		if ( IsValidCacheControlHeader ( *iUPnPRequest ) != KErrNone )
       
   628 		return KErrCorrupt;
       
   629 
       
   630 		if ( IsHeaderPresent ( *iUPnPRequest, HTTP::ELocation, THTTPTable::Table() ) != KErrNone )
       
   631 		return KErrCorrupt;
       
   632 		}
       
   633 
       
   634 	if ( IsHeaderPresent ( *iUPnPRequest, UPnP::ENT, TUPnPTable::Table() ) != KErrNone )
       
   635 		return KErrCorrupt;
       
   636 
       
   637 	return KErrNone;
       
   638 	}
       
   639 
       
   640 TInt CHttpMUdpFlow::ValidateMSearchRequest ()
       
   641 	{
       
   642 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::ValidateMSearchRequest")));
       
   643 	if ( IsValidHostHeader ( *iUPnPRequest ) && IsValidManHeader ( *iUPnPRequest ) &&
       
   644 		IsHeaderPresent ( *iUPnPRequest, UPnP::EMX, TUPnPTable::Table() ) == KErrNone && IsHeaderPresent ( *iUPnPRequest, UPnP::EST, TUPnPTable::Table() )  == KErrNone )
       
   645 		return KErrNone;
       
   646 	return KErrCorrupt;
       
   647 	}
       
   648 
       
   649 TInt CHttpMUdpFlow::GetHeaderValue ( const CRequest& aRequest, TInt aFieldIndex, THTTPHdrVal& aFieldVal, const TStringTable& aTable ) const
       
   650 	{
       
   651 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::GetHeaderValue")));
       
   652 	CRequest& request = const_cast < CRequest& > ( aRequest  );
       
   653 	RRequest req = request.Handle ();
       
   654 	RHTTPHeaders headers = req.GetHeaderCollection ();
       
   655 	RStringF fieldStr = aRequest.StringPool ().StringF ( aFieldIndex, aTable );
       
   656 	return headers.GetField ( fieldStr, 0, aFieldVal );
       
   657 	}
       
   658 
       
   659 TInt CHttpMUdpFlow::GetParamValue ( const CRequest& aRequest , TInt aFieldIndex, TInt aParamIndex, THTTPHdrVal& aParamVal, const TStringTable& aTable ) const
       
   660 	{
       
   661 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::GetParamValue")));
       
   662 	CRequest& request = const_cast < CRequest& > ( aRequest  );
       
   663 	RRequest req = request.Handle ();
       
   664 	RHTTPHeaders headers = req.GetHeaderCollection ();
       
   665 	RStringF fieldStr = aRequest.StringPool ().StringF ( aFieldIndex, aTable );
       
   666 	RStringF paramStr = aRequest.StringPool ().StringF ( aParamIndex, aTable );
       
   667 	TInt err = KErrNone;
       
   668 	TInt fieldCount = 0;
       
   669 	TRAP ( err, fieldCount = headers.FieldPartsL(fieldStr) );
       
   670 	while (fieldCount>0)
       
   671 		{
       
   672 		err = headers.GetParam ( fieldStr, paramStr, aParamVal, fieldCount-1 );
       
   673 		if(err == KErrNone )
       
   674 			break;
       
   675 		fieldCount--;
       
   676 		}
       
   677 	return err;
       
   678 	}
       
   679 
       
   680 TBool CHttpMUdpFlow::IsHeaderPresent ( const CRequest& aRequest , TInt aFieldIndex, const TStringTable& aTable ) const
       
   681 	{
       
   682 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::IsHeaderPresent")));
       
   683 	THTTPHdrVal value;
       
   684 	return GetHeaderValue ( aRequest, aFieldIndex, value, aTable );
       
   685 	}
       
   686 
       
   687 TBool CHttpMUdpFlow::IsValidCacheControlHeader ( const CRequest& aRequest ) const
       
   688 	{
       
   689 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::IsValidCacheControlHeader")));
       
   690 	THTTPHdrVal value;
       
   691 	return GetParamValue ( aRequest, HTTP::ECacheControl, HTTP::EMaxAge, value, THTTPTable::Table());
       
   692 	}
       
   693 
       
   694 TBool CHttpMUdpFlow::IsValidManHeader ( const CRequest& aRequest ) const
       
   695 	{
       
   696 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::IsValidManHeader")));
       
   697 	THTTPHdrVal value;
       
   698 	TInt err = GetHeaderValue ( aRequest, UPnP::EMAN, value, TUPnPTable::Table() );
       
   699 	if ( ( err == KErrNone ) && ( value.StrF ().DesC ().Compare ( KSsdpDiscover ) == 0))
       
   700 		{
       
   701 		LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::IsValidManHeader - MAN header has a valid value")));
       
   702 		return ETrue;
       
   703 		}
       
   704 	LOG(ESockLogExternal::Printf(KSubsysMUDPFlow, KComponent, _L8("CHttpMUdpFlow::IsValidManHeader - MAN header does not have a valid value")));
       
   705 	return EFalse;
       
   706 	}
       
   707 
       
   708 TBool CHttpMUdpFlow::IsValidHostHeader ( CRequest& aRequest ) const
       
   709 	{
       
   710 	// From UPnP Device Architecture 1.0
       
   711 	// Must be 239.255.255.250:1900. If the port number(:1900) is omitted,the receiver
       
   712 	// should assume the default SSDP port number of 1900.
       
   713 	_LIT8 ( KSsdpHost, "239.255.255.250" );
       
   714 	
       
   715 	THTTPHdrVal value;
       
   716 	TInt err = GetHeaderValue ( aRequest, HTTP::EHost, value, THTTPTable::Table () );
       
   717 	if ( err != KErrNone )
       
   718 		{
       
   719 		return EFalse;
       
   720 		}
       
   721 	
       
   722 	const TDesC8& host = value.StrF ().DesC ();
       
   723 	TInt pos = host.Locate ( TChar (':') );
       
   724 	
       
   725 	if ( pos != KErrNotFound )
       
   726 		{
       
   727 		TPtrC8 ptrHost = host.Mid ( 0, pos );			
       
   728 		if ( ptrHost.Compare ( KSsdpHost ) != 0 )
       
   729 			{
       
   730 			return EFalse;
       
   731 			}
       
   732 		
       
   733 		TPtrC8 ptrPort = host.Mid ( pos + 1 );
       
   734 		_LIT8 ( KSsdpPort, "1900" );
       
   735 		
       
   736 		if ( ptrPort.Length () > 0 && ptrPort.Compare ( KSsdpPort ) != 0 )
       
   737 			{
       
   738 			return EFalse;
       
   739 			}
       
   740 		
       
   741 		return ETrue;
       
   742 		}
       
   743 	
       
   744 	if ( host.Compare ( KSsdpHost ) != 0 )
       
   745 		{
       
   746 		return EFalse;
       
   747 		}
       
   748 		
       
   749 	return ETrue;
       
   750 	}
       
   751 /* CreateTimerEntry : creates the deltatimer entry and sets it to iEntry
       
   752  @param aUri  The uri whose timer entry has to be created
       
   753  */
       
   754 void CHttpMUdpFlow::CreateTimerEntryL()
       
   755 	{
       
   756 	const TInt KMXValue = 120;
       
   757 	TInt maxAge = 0;
       
   758 	RStringF location;
       
   759 	ReadRequestValues ( maxAge, location );
       
   760 	if ( maxAge > KMXValue )
       
   761 		maxAge = KMXValue;
       
   762 	const TDesC8& uri = location.DesC();
       
   763 	for ( TInt i = 0; i < iSearchTargetArray.Count (); ++i )
       
   764 		{
       
   765 		const CSearchTarget& target = *(iSearchTargetArray[i]);
       
   766 		if ( target.Match ( uri ) != KErrNotFound )
       
   767 			{
       
   768 			CCallbackArgument* callArgument =CCallbackArgument::NewL(this, iRecvElements[0]->Address () , iSearchTargetArray[i]);
       
   769 			CleanupStack::PushL(callArgument);
       
   770 			TCallBack callBack(HandleMSearchRequestL,callArgument);
       
   771 			TDeltaTimerEntry* entry = new (ELeave) TDeltaTimerEntry ( callBack );
       
   772 			CTimerMappedUri* timerMappedUri = CTimerMappedUri::NewL(location.DesC(),entry,maxAge);
       
   773 			iTimerMappedArray.AppendL(timerMappedUri);
       
   774 			callArgument->SetTimerEntry( entry );
       
   775 			iCallbackArray.AppendL(callArgument);
       
   776 			CleanupStack::Pop();
       
   777 			// queue up in deltatimer
       
   778 			TInt time = AdjustedDelay(maxAge);
       
   779 			TTimeIntervalMicroSeconds32 delay(time);
       
   780 			iDeltaTimer->Queue(delay,*entry);
       
   781 			}	
       
   782 		}
       
   783 	}
       
   784 /* Used to calculate the time in microseconds to set the timer entry.Also a little
       
   785  of time is used extra to account for Intra process communication
       
   786  @param aTime	The time for which the timer has to be set in seconds
       
   787  @return The actual time in microseconds
       
   788  */
       
   789 TInt CHttpMUdpFlow::AdjustedDelay( TInt aTime )
       
   790 	{
       
   791 	TInt newNum;
       
   792  	TTime now;
       
   793 	now.UniversalTime();
       
   794 	TInt64 randSeed = now.Int64();
       
   795 	newNum = static_cast<TInt>(Math::Rand(randSeed)%aTime);
       
   796   	const TUint KIntTime = 1000000 ;
       
   797 	newNum =  newNum * KIntTime ;
       
   798 	return newNum;
       
   799 	}
       
   800 CCallbackArgument* CCallbackArgument::NewL(TAny* aThis ,const TAppProtAddr& aAddress , const CSearchTarget* aStTarget)
       
   801 	{
       
   802 	CCallbackArgument* callArgument = new (ELeave )CCallbackArgument(aThis, aAddress , aStTarget);
       
   803 	return callArgument;
       
   804 	}
       
   805