servicediscoveryandcontrol/pnp/test/upnp/Server/Flow/src/httpudpflow.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 // upnpflow.cpp
       
    15 // @internalComponent
       
    16 // 
       
    17 //
       
    18 
       
    19 //System Includes
       
    20 #include <comms-infras/ss_nodeinterfaces.h>
       
    21 
       
    22 
       
    23 #include <http/thttptable.h>
       
    24 #include <http/framework/cheadercodecplugin.h>
       
    25 #include <httpstringconstants.h>
       
    26 #include <inetprottextutils.h>
       
    27 #include <upnp/tupnptable.h>
       
    28 
       
    29 //Local Includes
       
    30 #include "httpudpflow.h"
       
    31 #include "upnppint.h"
       
    32 #include "upnp_cf_msgs.h"
       
    33 #include "upnpctrlscprstates.h"
       
    34 #include "upnpserverconstants.h"
       
    35 #include "upnplog.h"
       
    36 #include "upnpmemoryutils.h"
       
    37 
       
    38 const TUint KDeftMaxAgeVal = 1800;
       
    39 const TUint KDeftSendCount = 9;
       
    40 const TUint KDeftTimeOutVal = 200000;	//200ms,Requirements [7.2.4.2] & [7.2.4.7] of DLNA
       
    41 
       
    42 __FLOG_STMT(_LIT8(KComponent,"Flow");)
       
    43 
       
    44 CHttpUdpFlow* CHttpUdpFlow::NewL ( CSubConnectionFlowFactoryBase& aFactory,
       
    45 						  			CUPnPProtocolIntfBase* aProtocolIntf,
       
    46 					  			const TNodeId& aSubConnId )
       
    47 	{
       
    48 	CHttpUdpFlow* self = new ( ELeave )CHttpUdpFlow ( aFactory, aProtocolIntf, aSubConnId );
       
    49 	CleanupStack::PushL ( self );
       
    50 	self->ConstructL ();
       
    51 	CleanupStack::Pop (); // self
       
    52 	return self;
       
    53 	}
       
    54 
       
    55 CHttpUdpFlow::CHttpUdpFlow ( CSubConnectionFlowFactoryBase& aFactory,
       
    56 					CUPnPProtocolIntfBase* aProtocolIntf,
       
    57 					const TNodeId& aSubConnId )
       
    58 	: CUPnPFlowBase ( aFactory, aProtocolIntf, EHttpUdpFlow, aSubConnId ),
       
    59 	iSocketHandler ( *this ), iSocketCreated ( EFalse ),iSendCount ( 0 ),  
       
    60 	iIsLeaving ( EFalse ),iSendFlag ( EFalse ),iIsComposeCompleted ( EFalse )
       
    61 	{
       
    62 	LOG_NODE_CREATE(KESockFlowTag, CHttpUdpFlow);
       
    63 	}
       
    64 
       
    65 CHttpUdpFlow::~CHttpUdpFlow ()
       
    66 	{
       
    67 	delete iRequestComposer;
       
    68 	delete iResponseParser;
       
    69 	delete iResponseComposer;
       
    70 	delete iSendTimer;
       
    71 
       
    72 	delete iSocketOpener;
       
    73 	iSocketHandler.CancelAll ();
       
    74 
       
    75 	iSocket.Close ();
       
    76 	iSearchTargetArray.Close ();
       
    77 	delete iUPnPResponse;
       
    78 	//delete iCodec;
       
    79 	iSendElements.Close ();
       
    80 	iStringPool.Close();
       
    81 	iSubConnectionProvider.Close ();
       
    82 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("Destroyed CHttpUdpFlow")));
       
    83 	LOG_NODE_DESTROY(KESockFlowTag, CHttpUdpFlow);
       
    84 	}
       
    85 
       
    86 
       
    87 void CHttpUdpFlow::ConstructL ()
       
    88 	{
       
    89 	iStringPool.OpenL ( TUPnPTable::Table() );
       
    90 	iStringPool.OpenL(THTTPTable::Table());
       
    91 	iCodec = CHeaderCodecPlugin::NewL ( KUPnPCodecName, iStringPool );
       
    92 	iResponseParser = CUpnpResponseParser::NewL ( *this );
       
    93 	iRequestComposer = CUpnpRequestComposer::NewL ( *this );
       
    94 	iResponseComposer = CUpnpResponseComposer::NewL ( *this );
       
    95 	iUPnPResponse = CResponse::NewL ( *iCodec, iStringPool );
       
    96 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("Created CHttpUdpFlow")));
       
    97 	}
       
    98 
       
    99 void CHttpUdpFlow::ReceivedL ( const TRuntimeCtxId& aSender, const TNodeId& /*aRecipient*/, TSignatureBase& aMessage )
       
   100 	{
       
   101 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReceivedL")));
       
   102 	
       
   103 	if ( aMessage.IsMessage<TEChild::TDestroy> () )
       
   104 		{
       
   105 		LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReceivedL - TCFMessage::TDestroy")));
       
   106     	if ( RemoveControlClient ( FindControlClient ( address_cast<TNodeId> ( aSender ) ) ) == 0 )
       
   107     		{
       
   108     		LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReceivedL - TCFMessage::TDestroy - Deleting current flow")));
       
   109     		DeleteThisFlow ();
       
   110     		}
       
   111 		}
       
   112 	else if ( aMessage.IsMessage<TCFDataClient::TStart> () )
       
   113 		{
       
   114 		LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReceivedL - TCFMessage::TDataClientStart")));
       
   115         RClientInterface::OpenPostMessageClose ( NodeId (), address_cast<TNodeCtxId> ( aSender ), TCFDataClient::TStarted ().CRef () );
       
   116 		}
       
   117 	else if ( aMessage.IsMessage<TCFDataClient::TStop> () )
       
   118 		{
       
   119        	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReceivedL - TUpnpMessage::TUPnPStopSearch")));
       
   120 
       
   121     	SetClientLeaving ( address_cast<TNodeId> ( aSender ) ); // set the control client leaving
       
   122 
       
   123 		if ( CheckIfAllClientsLeaving ( ) && iSendElements.Count () != 0 )
       
   124 		   	{
       
   125 		   	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReceivedL - TUpnpMessage::TUPnPStopSearch -- Marked for Deletion")));
       
   126 
       
   127 		   	MarkMeForDeletion ();
       
   128 		   	iIsLeaving = ETrue;
       
   129 			iLastLeavingClient = address_cast<TNodeCtxId> ( aSender );
       
   130 		   	}
       
   131 		else
       
   132 			{
       
   133 		    PostDataClientStopped ( address_cast<TNodeCtxId> ( aSender ) );
       
   134 			}
       
   135 		}
       
   136 	else if ( TUpnpMessage::ERealmId == aMessage.MessageId( ).Realm( ) )		
       
   137     	{
       
   138 	   	switch ( aMessage.MessageId( ).MessageId( ) )
       
   139 			{
       
   140 			case TUpnpMessage::TUPnPSearchRequest::EId:
       
   141             	{
       
   142             	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReceivedL - TUpnpMessage::TUPnPSearchRequest")));
       
   143             	HandleSearchRequestL ( address_cast<TNodeCtxId> ( aSender ), static_cast < TUpnpMessage::TUPnPSearchRequest& > ( aMessage ) );
       
   144             	CreateSendTimerL();
       
   145 				SendIfOneElement ();
       
   146             	}
       
   147             break;
       
   148 
       
   149 			case TUpnpMessage::TCancelRequest::EId:
       
   150 				{
       
   151             	HandleStopSearch ( address_cast<TNodeCtxId> ( aSender ) );
       
   152             	}
       
   153 			break;
       
   154 
       
   155             case TUpnpMessage::TUPnPSearchResponse::EId:
       
   156             	{
       
   157             	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReceivedL - TUpnpMessage::TUPnPSearchResponse")));
       
   158             	HandleSearchResponseL ( static_cast < TUpnpMessage::TUPnPSearchResponse& > ( aMessage ) );
       
   159 				SendIfOneElement ();
       
   160             	}
       
   161             break;
       
   162 
       
   163             case TUpnpMessage::TUPnPPublishAliveRequest::EId:
       
   164             	{
       
   165             	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReceivedL - TUpnpMessage::TUPnPPublishAliveRequest")));
       
   166             	HandlePublishAliveRequestL ( static_cast < TUpnpMessage::TUPnPPublishAliveRequest& > ( aMessage ) );
       
   167             	CreateSendTimerL();
       
   168             	SendIfOneElement ();
       
   169             	}
       
   170             break;
       
   171 
       
   172             case TUpnpMessage::TUPnPPublishByeRequest::EId:
       
   173             	{
       
   174             	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReceivedL - TUpnpMessage::TUPnPPublishByeRequest")));
       
   175             	HandlePublishByeRequestL ( static_cast < TUpnpMessage::TUPnPPublishByeRequest& > ( aMessage ) );
       
   176             	SendIfOneElement ();
       
   177             	}
       
   178             break;
       
   179 	        }
       
   180 		}
       
   181 	}
       
   182 
       
   183 // From MSocketHandlerObserver
       
   184 void CHttpUdpFlow::OpenComplete ( RInternalSocket& aSocket )
       
   185 	{
       
   186 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::OpenComplete")));
       
   187 	iSocket = aSocket;
       
   188 	TInt err = KErrNone;
       
   189 	TUint port = KUpnpUdpPort;
       
   190 	do
       
   191 		{
       
   192 		// [REF] DLNA Requirement-7.2.3.4
       
   193 		if ( port == KUpnpMCPort )
       
   194 			++port;
       
   195 
       
   196 		TInetAddr addr ( port++ );
       
   197 		addr.SetAddress ( KInetAddrAny );
       
   198 
       
   199 		err = aSocket.Bind( addr );
       
   200 
       
   201 		}while ( err == KErrInUse && port != KMaxTUint );
       
   202 
       
   203 	if ( err == KErrInUse || port == KMaxTUint )
       
   204 		{
       
   205 		return; // bind error is ignored, needs to be handled
       
   206 		}
       
   207 
       
   208 	iSocketHandler.Attach ( aSocket );
       
   209 	iSocketCreated = ETrue;
       
   210 	HandleSendElement (); // This call will happen only once.
       
   211 	StartRecv(); //keep Socket in receive mode
       
   212 	}
       
   213 
       
   214 void CHttpUdpFlow::SendToComplete ( TInt /*aLength*/ )
       
   215 	{
       
   216 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::SendToComplete")));
       
   217 
       
   218 	if ( !iSendFlag && iSendElements[0]->iType != CSendElement::EMSearchResponse )
       
   219 		{
       
   220 		IncrementSendCount();
       
   221 		iSendFlag = ETrue;
       
   222 		iSocketHandler.SendTo ( iBackupData, iSendElements[0]->iSockAddr );
       
   223 		}
       
   224 	else
       
   225 		{
       
   226 		iBackupData.Init ();
       
   227 		iSendFlag = EFalse;
       
   228 
       
   229 		iIsComposeCompleted = ETrue;
       
   230 		CSendElement::TSendType currentSendType = RemoveFirstSendElement ();
       
   231 		if ( CSendElement::EMSearchResponse == currentSendType )
       
   232 			{
       
   233 			//M-Serach Response
       
   234 			iResponseComposer->ResponseDataSent ();
       
   235 			iResponseComposer->ResetComposer ();
       
   236 			}
       
   237 		else
       
   238 			{
       
   239 			//Publish
       
   240 			iRequestComposer->RequestDataSent();
       
   241 			iRequestComposer->ResetComposer ();
       
   242 			}
       
   243 
       
   244 		HandleSendElement ();
       
   245 		}
       
   246 	}
       
   247 
       
   248 void CHttpUdpFlow::RecvFromComplete ( RMBufChain& aData, const TSockAddr& /*aAddr*/ )
       
   249 	{
       
   250 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::RecvFromComplete")));
       
   251 
       
   252 	RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( ProtocolIntf () )->GetMemoryChunkManager());
       
   253 	RMemChunk memChunk;
       
   254 	TUPnPMemoryUtils::CreateMemChunk(memChunk, aData, allocator);
       
   255 
       
   256 	iResponseParser->ParseResponse ( memChunk, iUPnPResponse );
       
   257 	
       
   258 	aData.Free();
       
   259 	}
       
   260 
       
   261 // From MComposerObserver
       
   262 void CHttpUdpFlow::MessageDataReadyL ( RBuf8& aData )
       
   263 	{
       
   264 	ASSERT ( iSendElements.Count() > 0 );
       
   265 
       
   266 	if ( !iSendFlag && iSendElements[0]->iType != CSendElement::EMSearchResponse)
       
   267 		{
       
   268 		iBackupData.CreateL(aData);
       
   269 		}
       
   270 	RMBufChain sendData;
       
   271 	sendData.CreateL(aData);
       
   272 	iSocketHandler.SendTo ( sendData, iSendElements[0]->iSockAddr );
       
   273 	}
       
   274 
       
   275 void CHttpUdpFlow::ComposingConcluded ()
       
   276 	{
       
   277 	if ( iIsLeaving && iSendElements.Count () == 0 )
       
   278 		{
       
   279 		LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ComposingConcluded - Deleting current flow")));
       
   280 
       
   281 		PostDataClientStopped ( iLastLeavingClient );
       
   282 		}
       
   283 	}
       
   284 
       
   285 void CHttpUdpFlow::ComposerError ( TInt /*aError*/ )
       
   286 	{
       
   287 	RemoveFirstSendElement ();
       
   288 	HandleSendElement ();
       
   289 	}
       
   290 
       
   291 // From MParserObserver
       
   292 void CHttpUdpFlow::GotHeaders ()
       
   293 	{
       
   294 	if ( ValidateSearchResponse () != KErrNone )
       
   295 		{
       
   296 		// Corrupt message. Reset the parser and restart the receive
       
   297 		StartRecv ();
       
   298 		}
       
   299 	// Else we will notify the SCPR from ::ParsingComplete
       
   300 	}
       
   301 
       
   302 void CHttpUdpFlow::ParsingComplete ( RMemChunk& /*aExcessData*/ )
       
   303 	{
       
   304 	TRAP_IGNORE ( NotifyClientsL () );
       
   305 	StartRecv ();
       
   306 	iUPnPResponse->Reset();
       
   307 	}
       
   308 
       
   309 void CHttpUdpFlow::ParserError ( TInt /*aError*/ )
       
   310 	{
       
   311 	StartRecv ();
       
   312 	}
       
   313 
       
   314 TInt CHttpUdpFlow::GetHeaderValue ( const CResponse& aResponse, TInt aFieldIndex, THTTPHdrVal& aFieldVal, const TStringTable& aTable )
       
   315 	{
       
   316 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::GetHeaderValue")));
       
   317 	CResponse& response = const_cast < CResponse& > ( aResponse );
       
   318 	RResponse res = response.Handle ();
       
   319 	RHTTPHeaders headers = res.GetHeaderCollection ();
       
   320 	RStringF fieldStr = aResponse.StringPool ().StringF ( aFieldIndex, aTable );
       
   321 	return headers.GetField ( fieldStr, 0, aFieldVal );
       
   322 	}
       
   323 
       
   324 TInt CHttpUdpFlow::GetParamValue ( const CResponse& aResponse, TInt aFieldIndex, TInt aParamIndex, THTTPHdrVal& aParamVal,  const TStringTable& aTable )
       
   325 	{
       
   326 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::GetParamValue")));
       
   327 	CResponse& response = const_cast < CResponse& > ( aResponse );
       
   328 	RResponse res = response.Handle ();
       
   329 	RHTTPHeaders headers = res.GetHeaderCollection ();
       
   330 	RStringF fieldStr = aResponse.StringPool ().StringF ( aFieldIndex, aTable );
       
   331 	RStringF paramStr = aResponse.StringPool ().StringF ( aParamIndex, aTable );
       
   332 	TInt err = KErrNotFound;
       
   333 	TInt fieldCount =  0;
       
   334 	TRAP ( err, fieldCount = headers.FieldPartsL(fieldStr) );
       
   335 	while (fieldCount>0)
       
   336 		{
       
   337 		err = headers.GetParam ( fieldStr, paramStr, aParamVal, fieldCount-1 );
       
   338 		if(err == KErrNone )
       
   339 			break;
       
   340 		fieldCount--;
       
   341 		}
       
   342 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::GetParamValue - Returned with error code %d"), err));
       
   343 	return err;
       
   344 	}
       
   345 
       
   346 TInt CHttpUdpFlow::IsHeaderPresent ( const CResponse& aResponse, TInt aFieldIndex, const TStringTable& aTable )
       
   347 	{
       
   348 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::IsHeaderPresent")));
       
   349 	THTTPHdrVal value;
       
   350 	return GetHeaderValue ( aResponse, aFieldIndex, value, aTable );
       
   351 	}
       
   352 
       
   353 TInt CHttpUdpFlow::IsValidCacheControlHeader ( const CResponse& aResponse )
       
   354 	{
       
   355 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::IsValidCacheControlHeader")));
       
   356 	THTTPHdrVal value;
       
   357 	return GetParamValue ( aResponse, HTTP::ECacheControl, HTTP::EMaxAge, value, THTTPTable::Table() );
       
   358 	}
       
   359 
       
   360 
       
   361 void CHttpUdpFlow::SetHeaderValueL ( RHTTPHeaders& aHdr, TInt aFieldIndex, const TDesC8& aFieldVal, const TStringTable& aTable )
       
   362 	{
       
   363 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::SetHeaderValueL")));
       
   364 	RStringF hdrValStr = iStringPool.OpenFStringL ( aFieldVal );
       
   365 	THTTPHdrVal hdrVal ( hdrValStr );
       
   366 	aHdr.SetFieldL ( iStringPool.StringF ( aFieldIndex, aTable ), hdrVal );
       
   367 	hdrValStr.Close();
       
   368 	}
       
   369 
       
   370 TInt CHttpUdpFlow::ValidateSearchResponse ()
       
   371 	{
       
   372 	// 1. MUST be a HTTP/1.1 version
       
   373 	// 2. MUST contain cache-control header with max-age directive
       
   374 	// 3. EXT header MUST be present
       
   375 	// 4. Location header MUST be present
       
   376 	// 5. ST header MUST be present
       
   377 	// 6. USN header MUST be present
       
   378 	// 7. No body
       
   379 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ValidateSearchResponse")));
       
   380 
       
   381 	if ( !iUPnPResponse->IsHTTP10() && IsValidCacheControlHeader ( *iUPnPResponse ) == KErrNone &&
       
   382 		IsHeaderPresent ( *iUPnPResponse, UPnP::EExt, TUPnPTable::Table() ) == KErrNone &&
       
   383 		IsHeaderPresent ( *iUPnPResponse, HTTP::ELocation, THTTPTable::Table() ) == KErrNone &&
       
   384 		IsHeaderPresent ( *iUPnPResponse, UPnP::EST, TUPnPTable::Table() ) == KErrNone &&
       
   385 		IsHeaderPresent ( *iUPnPResponse, UPnP::EUSN, TUPnPTable::Table() ) == KErrNone &&
       
   386 		IsContentLengthZero ( *iUPnPResponse ) )
       
   387 		{
       
   388 		LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ValidateSearchResponse - Returned with KErrNone")));
       
   389 		return KErrNone;
       
   390 		}
       
   391 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ValidateSearchResponse - Returned with KErrCorrupt")));
       
   392 	return KErrCorrupt;
       
   393 	}
       
   394 
       
   395 void CHttpUdpFlow::ReadResponseValues ( TInt& aMaxAge, RStringF& aLocation, RStringF& aUsn, RStringF& aST )
       
   396 	{
       
   397 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::ReadResponseValues")));
       
   398 	// We already checked the presence of these headers. We can just read those here
       
   399 	// Read maxAge, Location & USN values from the response
       
   400 	THTTPHdrVal value(KDeftMaxAgeVal);
       
   401 	GetParamValue ( *iUPnPResponse, HTTP::ECacheControl, HTTP::EMaxAge, value, THTTPTable::Table() );
       
   402 	aMaxAge = value.Int ();
       
   403 
       
   404 	GetHeaderValue ( *iUPnPResponse, HTTP::ELocation, value, THTTPTable::Table() );
       
   405 	aLocation = value.StrF ();
       
   406 
       
   407 	GetHeaderValue ( *iUPnPResponse, UPnP::EUSN, value, TUPnPTable::Table() );
       
   408 	aUsn = value.StrF ();
       
   409 
       
   410 	GetHeaderValue ( *iUPnPResponse, UPnP::EST, value, TUPnPTable::Table() );
       
   411 	aST = value.StrF ();
       
   412 	}
       
   413 
       
   414 void CHttpUdpFlow::NotifyClientsL ()
       
   415 	{
       
   416 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::NotifyClients")));
       
   417 	TInt maxAge;
       
   418 	RStringF location;
       
   419 	RStringF usn;
       
   420 	RStringF st;
       
   421 	ReadResponseValues ( maxAge, location, usn, st );
       
   422 	for ( TInt i = 0; i < iSearchTargetArray.Count (); ++i )
       
   423 		{
       
   424 		const CSearchTarget& target = *(iSearchTargetArray[i]);
       
   425 		if ( target.Match ( st.DesC() ) != KErrNotFound
       
   426 							&& !IsClientLeaving ( target.Originator () ) )
       
   427 			{
       
   428 			// We have a match. Post the information to our control client
       
   429 			RMemoryAllocator allocator(static_cast<CUPnPProtocolIntfBase *>( ProtocolIntf () )->GetMemoryChunkManager());
       
   430 			
       
   431 			RMemChunk locBuf;
       
   432 			RMemChunk usnBuf;
       
   433 			RMemChunk stBuf;
       
   434 			locBuf.CreateL ( location.DesC (), allocator );
       
   435 			TCleanupItem item1 ( &UPnPStateMachine::CUPnPUtils::CleanupMBufChain, &locBuf );
       
   436 			CleanupStack::PushL ( item1 );
       
   437 			usnBuf.CreateL ( usn.DesC (), allocator );
       
   438 			TCleanupItem item2 ( &UPnPStateMachine::CUPnPUtils::CleanupMBufChain, &usnBuf );
       
   439 			CleanupStack::PushL ( item2 );
       
   440 			stBuf.CreateL ( st.DesC (), allocator );
       
   441 			TCleanupItem item3 ( &UPnPStateMachine::CUPnPUtils::CleanupMBufChain, &stBuf );
       
   442 			CleanupStack::PushL ( item3 );
       
   443 
       
   444 			TSsdpInfo info ( maxAge, locBuf, usnBuf, stBuf );
       
   445 			
       
   446 			LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::NotifyClients - Posting message TUpnpMessage::TUPnPSearchResponse")));
       
   447 			TUpnpMessage::TUPnPSearchResponse msg ( info );
       
   448 	        RClientInterface::OpenPostMessageClose ( NodeId (), target.Originator (), msg );
       
   449 
       
   450 			CleanupStack::Pop (); // item1
       
   451 			CleanupStack::Pop (); // item2
       
   452 			CleanupStack::Pop (); // item3
       
   453 			}
       
   454 		}
       
   455 	}
       
   456 
       
   457 void CHttpUdpFlow::StartRecv ()
       
   458 	{
       
   459 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::StartRecv")));
       
   460 	// Reset the parser and recv
       
   461 	iResponseParser->ResetParser ();
       
   462 	iSocketHandler.RecvFrom ();
       
   463 	}
       
   464 
       
   465 // -----------------------
       
   466 // The below functions to be genralised
       
   467 void CHttpUdpFlow::HandleSearchRequestL ( TNodeCtxId aChannelId, TUpnpMessage::TUPnPSearchRequest& aMessage )
       
   468 	{
       
   469 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::HandleSearchRequestL")));
       
   470 	_LIT8 ( KMultiCastAddr, "239.255.255.250:1900" );
       
   471 	_LIT8 ( KManHeaderValue, "ssdp:discover" );
       
   472 	_LIT8 ( KSearchUri, "*" );
       
   473 	CRequest* searchRequest = CRequest::NewL ( *iCodec, iStringPool );
       
   474 	CleanupStack::PushL ( searchRequest );
       
   475 
       
   476 	RStringF method = iStringPool.StringF ( UPnP::EMSearch, TUPnPTable::Table() );
       
   477 	// Set the method and URI
       
   478 	RRequest req = searchRequest->Handle ();
       
   479 	req.SetMethod ( method );
       
   480 	TUriParser8 parser;
       
   481 	parser.Parse ( KSearchUri () );
       
   482 	req.SetURIL ( parser );
       
   483 
       
   484 	RHTTPHeaders hdr = searchRequest->Handle ().GetHeaderCollection ();
       
   485 
       
   486 	// Set host header
       
   487 	SetHeaderValueL ( hdr, HTTP::EHost, KMultiCastAddr(), THTTPTable::Table() );
       
   488 
       
   489 	// Set MAN header
       
   490 	SetHeaderValueL ( hdr, UPnP::EMAN, KManHeaderValue(), TUPnPTable::Table() );
       
   491 
       
   492 
       
   493 	// Set MX header
       
   494 	THTTPHdrVal mxVal ( aMessage.iSsdpInfo.iMx );
       
   495 	hdr.SetFieldL ( iStringPool.StringF ( UPnP::EMX, TUPnPTable::Table() ), mxVal );
       
   496 
       
   497 	// Set ST header
       
   498 	TPtrC8 stPtr ( aMessage.iSsdpInfo.iSearchTarget.First ()->Ptr (), aMessage.iSsdpInfo.iSearchTarget.First ()->Length () );
       
   499 	SetHeaderValueL ( hdr, UPnP::EST, stPtr, TUPnPTable::Table() );
       
   500 
       
   501 	CSearchTarget* searchTarget = new ( ELeave ) CSearchTarget ( aChannelId );
       
   502 	CleanupStack::PushL ( searchTarget );
       
   503 	searchTarget->AddTargetL ( aMessage.iSsdpInfo.iSearchTarget );
       
   504 	iSearchTargetArray.AppendL ( searchTarget );
       
   505 	CleanupStack::Pop (); // searchTarget
       
   506 	TAppProtAddr addr ( KSsdpMulticastAddr, KUpnpMCPort );
       
   507 
       
   508 	CSendElement* sendElement = new ( ELeave ) CSendElement ( CSendElement::EMSearchRequest, *searchRequest, addr );
       
   509 	CleanupStack::PushL ( sendElement );
       
   510 	iSendElements.AppendL ( sendElement );
       
   511 	CleanupStack::Pop (); // sendElement
       
   512 
       
   513 	CleanupStack::Pop (); // searchRequest
       
   514 	}
       
   515 
       
   516 void CHttpUdpFlow::HandleStopSearch ( TNodeCtxId aChannelId )
       
   517 	{
       
   518 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::HandleStopSearch")));
       
   519 
       
   520 	TInt pos = FindSearchTarget ( aChannelId );
       
   521 
       
   522 	if ( pos != KErrNotFound )
       
   523 		{
       
   524 		CSearchTarget *target = iSearchTargetArray[pos];
       
   525 		iSearchTargetArray.Remove ( pos );
       
   526 		delete target;
       
   527 
       
   528 		RClientInterface::OpenPostMessageClose ( NodeId (), aChannelId, TUpnpMessage::TCancelled ().CRef () );
       
   529 		}
       
   530 	}
       
   531 
       
   532 void CHttpUdpFlow::HandleSearchResponseL ( TUpnpMessage::TUPnPSearchResponse& aMessage )
       
   533 	{
       
   534 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::HandleSearchResponseL")));
       
   535 	CResponse* searchResponse = CResponse::NewL ( *iCodec, iStringPool );
       
   536 
       
   537 	RResponse response = searchResponse->Handle ();
       
   538 	RHTTPHeaders hdr = response.GetHeaderCollection ();
       
   539 
       
   540 	const TInt KStatusCode = 200;
       
   541 	_LIT8 ( KStatusText, "OK" );
       
   542 	// Set status code & text
       
   543 	response.SetStatusCode ( KStatusCode );
       
   544 
       
   545 	RStringF statusTextStr = iStringPool.OpenFStringL ( KStatusText() );
       
   546 	CleanupClosePushL ( statusTextStr );
       
   547 	response.SetStatusText ( statusTextStr );
       
   548 	CleanupStack::PopAndDestroy (); // statusTextStr
       
   549 
       
   550 	// Set CACHE-CONTROL: max-age=""
       
   551 	SetMaxAgeHeaderValueL ( aMessage.iSsdpInfo.iMx, hdr );
       
   552 
       
   553 	// Set Date header
       
   554 	TTime time;
       
   555 	time.UniversalTime();
       
   556 	THTTPHdrVal timeHdrVal ( time.DateTime() );
       
   557 	hdr.SetFieldL ( iStringPool.StringF(HTTP::EDate, THTTPTable::Table() ), timeHdrVal );
       
   558 
       
   559 	// set EXT header
       
   560 	SetHeaderValueL ( hdr, UPnP::EExt, KNullDesC8 (), TUPnPTable::Table() );
       
   561 
       
   562 	// Set location str
       
   563 	TPtrC8 locationPtr ( aMessage.iSsdpInfo.iLocation.First ()->Ptr (), aMessage.iSsdpInfo.iLocation.First ()->Length () );
       
   564 	SetHeaderValueL ( hdr, HTTP::ELocation, locationPtr, THTTPTable::Table() );
       
   565 
       
   566 	// Set ST str
       
   567 	TPtrC8 stPtr ( aMessage.iSsdpInfo.iSearchTarget.First ()->Ptr (), aMessage.iSsdpInfo.iSearchTarget.First ()->Length () );
       
   568 	SetHeaderValueL ( hdr, UPnP::EST, stPtr, TUPnPTable::Table() );
       
   569 
       
   570 	// Set USN str
       
   571 	TPtrC8 usnPtr ( aMessage.iSsdpInfo.iUsn.First ()->Ptr (), aMessage.iSsdpInfo.iUsn.First ()->Length () );
       
   572 	SetHeaderValueL ( hdr, UPnP::EUSN, usnPtr, TUPnPTable::Table() );
       
   573 
       
   574 	//Set Content Length
       
   575 	hdr.SetFieldL ( iStringPool.StringF ( HTTP::EContentLength, THTTPTable::Table() ), THTTPHdrVal ( 0 ) );
       
   576 
       
   577 	CSendElement* sendElement = new ( ELeave ) CSendElement ( CSendElement::EMSearchResponse, *searchResponse, aMessage.iSsdpInfo.iAddr );
       
   578 	iSendElements.AppendL ( sendElement );
       
   579 	}
       
   580 
       
   581 
       
   582 
       
   583 void CHttpUdpFlow::HandlePublishAliveRequestL ( TUpnpMessage::TUPnPPublishAliveRequest& aMessage )
       
   584 	{
       
   585 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::HandlePublishAliveRequestL")));
       
   586 	CRequest& request = CreatePublishRequestLC ();
       
   587 
       
   588 	RHTTPHeaders hdr = request.Handle ().GetHeaderCollection ();
       
   589 	// Set CACHE-CONTROL: max-age=""
       
   590 	SetMaxAgeHeaderValueL ( aMessage.iSsdpInfo.iMx, hdr );
       
   591 
       
   592 	// Set location str
       
   593 	TPtrC8 locationPtr ( aMessage.iSsdpInfo.iLocation.First ()->Ptr (), aMessage.iSsdpInfo.iLocation.First ()->Length () );
       
   594 	SetHeaderValueL ( hdr, HTTP::ELocation, locationPtr, THTTPTable::Table() );
       
   595 
       
   596 	// Set NT str
       
   597 	TPtrC8 ntPtr ( aMessage.iSsdpInfo.iSearchTarget.First ()->Ptr (), aMessage.iSsdpInfo.iSearchTarget.First ()->Length () );
       
   598 	SetHeaderValueL ( hdr, UPnP::ENT, ntPtr, TUPnPTable::Table() );
       
   599 
       
   600 	SetHeaderValueL ( hdr, UPnP::ENTS, KSsdpAlive(), TUPnPTable::Table() );
       
   601 	TPtrC8 usnPtr ( aMessage.iSsdpInfo.iUsn.First ()->Ptr (), aMessage.iSsdpInfo.iUsn.First ()->Length () );
       
   602 	SetHeaderValueL ( hdr, UPnP::EUSN, usnPtr, TUPnPTable::Table() );
       
   603 
       
   604 	//Set Server
       
   605 	_LIT8 ( KServerName, "Symbian UPnP/1.0 server" );
       
   606 	RStringF serverStr = iStringPool.OpenFStringL ( KServerName () );
       
   607 	THTTPHdrVal serverHdrVal ( serverStr );
       
   608 	hdr.SetFieldL ( iStringPool.StringF ( HTTP::EServer, THTTPTable::Table () ), serverHdrVal );
       
   609 	serverStr.Close ();
       
   610 
       
   611 	//Set Content Length
       
   612 	hdr.SetFieldL ( iStringPool.StringF ( HTTP::EContentLength, THTTPTable::Table() ), THTTPHdrVal ( 0 ) );
       
   613 
       
   614 	TAppProtAddr addr ( KSsdpMulticastAddr, KUpnpMCPort  );
       
   615 	CSendElement* sendElement = new ( ELeave ) CSendElement ( CSendElement::ENotifyAliveRequest, request, addr );
       
   616 	iSendElements.AppendL ( sendElement );
       
   617 
       
   618 	CleanupStack::Pop (); //request
       
   619 	}
       
   620 
       
   621 void CHttpUdpFlow::SetMaxAgeHeaderValueL ( TInt aMaxAgeVal, RHTTPHeaders aHeaders )
       
   622 	{
       
   623 	_LIT8 ( KMaxAge, "max-age=" );
       
   624 
       
   625 	RStringF cacheControl = iStringPool.StringF( HTTP::ECacheControl, THTTPTable::Table() );
       
   626 	HBufC8* buf;
       
   627 	InetProtTextUtils::ConvertIntToDescriptorL ( aMaxAgeVal, buf );
       
   628 	CleanupStack::PushL ( buf );
       
   629 	RBuf8 rBuf;
       
   630 	rBuf.CreateMaxL ( KMaxAge ().Length () + buf->Length () );
       
   631 	rBuf.Copy ( KMaxAge );
       
   632 	rBuf.Append ( buf->Des () );
       
   633 
       
   634 	RStringF cacheControlValStrF = iStringPool.OpenFStringL( rBuf );
       
   635 	CleanupClosePushL ( cacheControlValStrF );
       
   636 	THTTPHdrVal cacheControlVal;
       
   637 	cacheControlVal.SetStrF ( cacheControlValStrF );
       
   638 
       
   639 	aHeaders.SetFieldL ( cacheControl, cacheControlVal );
       
   640 
       
   641 	CleanupStack::PopAndDestroy ( &cacheControlValStrF );
       
   642 	CleanupStack::PopAndDestroy ( );
       
   643 	}
       
   644 
       
   645 void CHttpUdpFlow::HandlePublishByeRequestL ( TUpnpMessage::TUPnPPublishByeRequest& aMessage )
       
   646 	{
       
   647 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::HandlePublishByeRequestL")));
       
   648 	CRequest& request = CreatePublishRequestLC ();
       
   649 
       
   650 	RHTTPHeaders hdr = request.Handle ().GetHeaderCollection ();
       
   651 
       
   652 	// Set NT str
       
   653 	TPtrC8 ntPtr ( aMessage.iSsdpInfo.iSearchTarget.First ()->Ptr (), aMessage.iSsdpInfo.iSearchTarget.First ()->Length () );
       
   654 	SetHeaderValueL ( hdr, UPnP::ENT, ntPtr, TUPnPTable::Table() );
       
   655 
       
   656 	SetHeaderValueL ( hdr, UPnP::ENTS, KSsdpBye(), TUPnPTable::Table() );
       
   657 	TPtrC8 usnPtr ( aMessage.iSsdpInfo.iUsn.First ()->Ptr (), aMessage.iSsdpInfo.iUsn.First ()->Length () );
       
   658 	SetHeaderValueL ( hdr, UPnP::EUSN, usnPtr, TUPnPTable::Table() );
       
   659 
       
   660 	//Set Content Length
       
   661 	hdr.SetFieldL ( iStringPool.StringF ( HTTP::EContentLength, THTTPTable::Table() ), THTTPHdrVal ( 0 ) );
       
   662 
       
   663 	TAppProtAddr addr ( KSsdpMulticastAddr, KUpnpMCPort  );
       
   664 	CSendElement* sendElement = new ( ELeave ) CSendElement ( CSendElement::ENotifyByeRequest, request, addr );
       
   665 	iSendElements.AppendL ( sendElement );
       
   666 
       
   667 	CleanupStack::Pop (); //request
       
   668 	}
       
   669 
       
   670 CRequest& CHttpUdpFlow::CreatePublishRequestLC ()
       
   671 	{
       
   672 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::CreatePublishRequestLC")));
       
   673 	CRequest* publishRequest = CRequest::NewL ( *iCodec, iStringPool );
       
   674 	CleanupStack::PushL ( publishRequest );
       
   675 
       
   676 	RStringF method = iStringPool.StringF ( UPnP::ENotify, TUPnPTable::Table() );
       
   677 	// Set the method and URI
       
   678 	RRequest req = publishRequest->Handle ();
       
   679 	req.SetMethod ( method );
       
   680 	TUriParser8 parser;
       
   681 	parser.Parse ( KSearchUri () );
       
   682 	req.SetURIL ( parser );
       
   683 
       
   684 	RHTTPHeaders hdr = publishRequest->Handle ().GetHeaderCollection ();
       
   685 
       
   686 	// Set host header
       
   687 	SetHeaderValueL ( hdr, HTTP::EHost, KMultiCastAddr(), THTTPTable::Table() );
       
   688 
       
   689 	return *publishRequest;
       
   690 	}
       
   691 
       
   692 // --------------------------------------------
       
   693 
       
   694 void CHttpUdpFlow::SendIfOneElement ()
       
   695 	{
       
   696 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::SendIfOneElement")));
       
   697 	if ( iSendElements.Count () == 1 )
       
   698 		{
       
   699 		HandleSendElement ();
       
   700 		}
       
   701 	}
       
   702 
       
   703 void CHttpUdpFlow::HandleSendElement ()
       
   704 	{
       
   705 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::HandleSendElement")));
       
   706 
       
   707 	if ( !IsSocketCreated () )
       
   708 		{
       
   709 		TRAP_IGNORE ( CreateSocketL () );
       
   710 		return;
       
   711 		}
       
   712 	// Sent the first element
       
   713 	if ( iSendElements.Count() > 0 )
       
   714 		{
       
   715 		CSendElement* element = iSendElements[0];
       
   716 		
       
   717 		if(iSendCount > KDeftSendCount)
       
   718 			{
       
   719 			if(iSendTimer && iSendTimer->IsActive())
       
   720 				return;
       
   721 			}
       
   722 		iIsComposeCompleted = EFalse; 
       
   723 		if ( element->Type() == CSendElement::EMSearchResponse )
       
   724 			{
       
   725 			iSendCount = 0;
       
   726 			iResponseComposer->ComposeResponse ( static_cast < CResponse* > ( element->Message () ) );
       
   727 			}
       
   728 		else
       
   729 			{
       
   730 			StartSendTimer();
       
   731 			IncrementSendCount();
       
   732 			iRequestComposer->ComposeRequest ( static_cast <CRequest*> ( (element->Message ()) ) );
       
   733 			}		
       
   734 		}
       
   735 	}
       
   736 
       
   737 void CHttpUdpFlow::CreateSocketL ()
       
   738 	{
       
   739 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::CreateSocketL")));
       
   740 	if ( !iSocketOpener )
       
   741 		{
       
   742 		iSocketOpener = CSocketOpener::NewL ( *this );
       
   743 		iSocketOpener->MakeSocket ( KAfInet, KSockDatagram, KProtocolInetUdp );
       
   744 		}
       
   745 	}
       
   746 
       
   747 CSendElement::TSendType CHttpUdpFlow::RemoveFirstSendElement ()
       
   748 	{
       
   749 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::RemoveFirstSendElement")));
       
   750 	ASSERT ( iSendElements.Count () > 0 );
       
   751 	CSendElement* element = iSendElements[0];
       
   752 	iSendElements.Remove (0);
       
   753 	CSendElement::TSendType sendType = element->Type ();
       
   754 	delete element;
       
   755 	return sendType;
       
   756 	}
       
   757 
       
   758 TInt CHttpUdpFlow::FindSearchTarget ( TNodeCtxId& aChannelId )
       
   759 	{
       
   760 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::FindSearchTarget")));
       
   761 	for ( TInt i = 0; i < iSearchTargetArray.Count (); ++i )
       
   762 	{
       
   763 	if ( iSearchTargetArray[i]->Originator () == aChannelId )
       
   764 		{
       
   765 		LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::FindSearchTarget - Search target found")));
       
   766 		return i;
       
   767 		}
       
   768 	}
       
   769 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::FindSearchTarget - Search target not found")));
       
   770 	return KErrNotFound;
       
   771 	}
       
   772 
       
   773 
       
   774 TBool CHttpUdpFlow::IsContentLengthZero ( const CResponse& aResponse )
       
   775 	{
       
   776 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::IsContentLengthZero")));
       
   777 	THTTPHdrVal contentLenVal;
       
   778 	if ( GetHeaderValue ( aResponse, HTTP::EContentLength, contentLenVal, THTTPTable::Table() ) == KErrNone )
       
   779 		{
       
   780 		if ( contentLenVal.Int( ) == 0 )
       
   781 			{
       
   782 			LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::IsContentLengthZero - Returned ETrue")));
       
   783 			return ETrue;
       
   784 			}
       
   785 		LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::IsContentLengthZero - Returned EFalse")));
       
   786 		return EFalse;
       
   787 		}
       
   788 	LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::IsContentLengthZero - Content-Length header was not found")));
       
   789 	return EFalse;
       
   790 	}
       
   791 
       
   792 void CHttpUdpFlow::CreateSendTimerL()
       
   793 	{
       
   794 	if(!iSendTimer)
       
   795 		{
       
   796 		iSendTimer = CUPnPTimer::NewL(*this);
       
   797 		}
       
   798 	}
       
   799 
       
   800 void CHttpUdpFlow::TimeOut()
       
   801 	{
       
   802 	iSendCount = 0;
       
   803 	if(iIsComposeCompleted)
       
   804 		{
       
   805 		LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::TimeOut[HandleSendElement]")));
       
   806 		HandleSendElement();
       
   807 		}
       
   808 	return;
       
   809 	}
       
   810 
       
   811 void CHttpUdpFlow::IncrementSendCount()
       
   812 	{
       
   813 	if(IsMSearchOrAliveRequest())
       
   814 		{
       
   815 		++iSendCount;
       
   816 		}
       
   817 	else
       
   818 		{
       
   819 		iSendCount = 0;
       
   820 		}
       
   821 	}
       
   822 
       
   823 void CHttpUdpFlow::StartSendTimer()
       
   824 	{
       
   825 	if( IsMSearchOrAliveRequest() )
       
   826 		{
       
   827 		LOG(ESockLogExternal::Printf(KSubsysHttpUDPFlow, KComponent, _L8("CHttpUdpFlow::StartSendTimer[Timer Started]")));
       
   828 		iSendTimer->StartTimer(KDeftTimeOutVal);
       
   829 		}
       
   830 	}
       
   831 
       
   832 
       
   833 
       
   834 
       
   835 
       
   836 
       
   837