servicediscoveryandcontrol/pnp/test/upnp/Client/upnpplugin/src/cupnpsearch.cpp
changeset 0 f5a58ecadc66
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servicediscoveryandcontrol/pnp/test/upnp/Client/upnpplugin/src/cupnpsearch.cpp	Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,293 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "cupnpsearch.h"
+
+CUPnPSearch::CUPnPSearch( RSubConnection& aSubConnection )
+	:iSubConnection( aSubConnection )
+	{
+	}
+
+CUPnPSearch* CUPnPSearch::NewL(RSubConnection& aSubConnection)
+	{
+	CUPnPSearch* search = new (ELeave) CUPnPSearch( aSubConnection );
+	CleanupStack::PushL( search );
+	search->ConstructL();
+	CleanupStack::Pop( search );
+	return search;
+	}
+
+void CUPnPSearch::ConstructL()
+	{
+	// Create a delta timer with the given priority
+	iDeltaTimer=CDeltaTimer::NewL(EPriorityLow);
+	}
+
+CUPnPSearch::~CUPnPSearch()
+	{
+	iDeltaTimer->Cancel();	
+	delete iDeltaTimer;
+	iTimerMappedArray.ResetAndDestroy();
+	iCallbackArray.ResetAndDestroy();
+	iMappedUri=NULL;
+	}
+
+/* Used to send a discover request to the network
+ @param aServiceInfo Bundle of uri's which have to be searched for
+ */
+void CUPnPSearch::SubmitRequestL(const RPnPParameterBundle& aServiceInfo)
+	{
+	const TInt KMaxMXValue = 120;
+	_LIT8(KSsdpAll,"ssdp:all");	
+	iObserver = aServiceInfo.PnPObserver();
+	
+	RParameterFamily family = const_cast<RPnPParameterBundle&>(aServiceInfo).FindFamily( EUPnPDiscoverRequestParamSet );
+	// Iterate through all the param sets in the passed bundle
+	
+	CUPnPDiscoverRequestParamSet* paramSet = NULL;
+	TUint count = family.CountParameterSets ( RParameterFamily::ERequested ) ;
+	
+	for ( TInt paramIndex = count - 1; paramIndex >= 0; paramIndex-- )
+		{
+		paramSet = static_cast<CUPnPDiscoverRequestParamSet*> ( family.GetParameterSetAtIndex ( paramIndex, RParameterFamily::ERequested ) );
+
+		//Extract the MX value and the uri
+		TInt delayResp=paramSet->ResponseTime();
+		const TDesC8& uri = paramSet->Uri();
+		__ASSERT_DEBUG( uri != KNullDesC8, User::Panic( KUPnPInvalidUserInput, KUPnPErrInvalidInput ) );
+		__ASSERT_DEBUG( delayResp>=0, User::Panic( KUPnPInvalidUserInput, KUPnPErrInvalidInput ) );
+		if ( delayResp > KMaxMXValue )
+			{
+			paramSet->SetResponseTime(KMaxMXValue);
+			delayResp = KMaxMXValue;
+			}
+		/* If one of the uris being discovered is ssdp:all then no other uri
+		 needs to be discovered and hence no more traversal through the param
+		 bundle is required */
+		if ( paramSet->Uri().CompareF(KSsdpAll) == NULL)
+			{
+			CreateTimerEntryL(uri);
+			iTimerMappedArray.ResetAndDestroy();
+			iMappedUri = CTimerMappedUri::NewL(uri,iEntry,delayResp);
+			iTimerMappedArray.AppendL(iMappedUri);
+			if ( family.CountParameterSets(RParameterFamily::ERequested) > 1 )
+				{
+				for ( TInt i = family.CountParameterSets(RParameterFamily::ERequested)-1; i >= 0; i-- )
+					{
+					if ( i != paramIndex )						
+					    reinterpret_cast<RUPnPParameterFamily*>(&family)->DeleteParamSetL ( i );
+
+					}
+				}
+
+			break;
+			}
+		// Check for validity of the uri
+		User::LeaveIfError(CUPnPUtils::GenericUriValidity( uri, CUPnPUtils::EAny ));
+		 
+
+		// If uri has already been indexed into iTimerMappedArray that means its a
+		// duplicate entry and the index of this param set is appended to
+		// tempDuplicateArray
+		TInt err = KErrNone;
+		for (TInt i=0;i<iTimerMappedArray.Count();i++)
+			{
+			if(iTimerMappedArray[i]->UriExists(uri))
+				{
+				reinterpret_cast<RUPnPParameterFamily*>(&family)->DeleteParamSetL(paramIndex);
+				err = KErrAlreadyExists;
+				break;
+				}
+			}
+		if (err == KErrAlreadyExists)
+			continue;
+
+		// CreateTimerEntry sets iEntry to the new timer entry
+		CreateTimerEntryL(uri);
+		iMappedUri = CTimerMappedUri::NewL(uri,iEntry,delayResp);
+		iTimerMappedArray.AppendL(iMappedUri);
+		
+		}
+
+	/* Transfer ownvership of all CTimerMappedUri objects from tempMappedArray to
+	  iTimerMappedArray
+	  */
+	for(TInt i=0;i<iTimerMappedArray.Count();i++)
+		{
+		// queue up in deltatimer
+		TInt time = AdjustedDelay(iTimerMappedArray[i]->Delay());
+		TTimeIntervalMicroSeconds32 delay(time);
+		iDeltaTimer->Queue(delay,iTimerMappedArray[i]->GetTimerEntry());
+		}
+	/* if SetParameters fails should it be communicated to client
+	* so that he may take corrective measures */
+	User::LeaveIfError(iSubConnection.SetParameters(aServiceInfo));
+	SetDiscoverProgress(ETrue);
+	}
+
+/* Static method which is called on timer expiry and which removes the uri entry
+ * from the array.
+ */
+TInt CUPnPSearch::StopSearch(TAny* aPtr)
+	{
+	CCallbackArgument* pointerData= static_cast<CCallbackArgument*> (aPtr);
+	CUPnPSearch* thisObject= static_cast < CUPnPSearch*> (pointerData->GetThisPointer());
+	RPointerArray<CTimerMappedUri>& rArray=thisObject->GetTimerArray();
+	RPointerArray<CCallbackArgument>& argArray = thisObject->GetArgumentArray();
+	const TDesC8& uri = pointerData->GetUri();
+	TInt index;
+	for(index=0;index<rArray.Count();index++)
+		{
+		if(rArray[index]->UriExists(uri))
+			{
+			// Removes the uri entry from the array
+			CTimerMappedUri* timerUri = rArray[index];
+			rArray.Remove(index);
+			delete timerUri;
+			break;
+			}
+		}
+	for( index=0;index<argArray.Count();index++)
+		{
+		if(uri.CompareF(argArray[index]->GetUri()) == NULL)
+			{
+			argArray.Remove(index);
+			break;
+			}
+		}
+	// Requests the subconnection to cancel ongoing search
+	TRAPD( error , thisObject->CancelSearchL( uri ));
+
+	// Reset Discover In progress
+	if(rArray.Count() <= 0)
+		thisObject->SetDiscoverProgress(EFalse);
+	
+	// Notifies the client that timer has expired
+	TRAP(error,thisObject->MakeBundleAndNotifyL(pointerData));
+	delete pointerData;
+	return error;
+	}
+
+/* Used to notify results back to the client application */
+void CUPnPSearch::NotifyResultsL(RPnPParameterBundleBase& aBundle)
+	{
+	RParameterFamily family = aBundle.FindFamily(EUPnPDiscoverResponseParamSet);	
+ 	__ASSERT_DEBUG(!family.IsNull (), User::Panic(KUPnPInvalidFamily,KUPnPErrInvalidFamily));	
+	__ASSERT_DEBUG(family.CountParameterSets(RParameterFamily::ERequested) > 0, User::Panic(KUPnPNoParamSet,KUPnPErrNoParamSet));
+	iObserver->OnPnPEventL(aBundle) ;
+	}
+
+/* Is used to notify the timeout expired result back to the control point */
+void CUPnPSearch::MakeBundleAndNotifyL(CCallbackArgument* aCallArgument)
+	{
+	RPnPParameterBundleBase pnpBundle ;
+	pnpBundle.Open();	
+	CleanupClosePushL( pnpBundle );
+
+	// Create the family on the bundle
+	RParameterFamily family = pnpBundle.CreateFamilyL(EUPnPDiscoverResponseParamSet);	
+	//Set the values in the parameter set
+	CUPnPDiscoverResponseParamSet* searchParamSet = CUPnPDiscoverResponseParamSet::NewL(family );
+
+	TUPnPEvent event;
+	const TDesC8& uri = aCallArgument->GetUri();
+	event.iStatus=TUPnPEvent::EDiscoveryTimeout;
+	event.iErrorCode = KErrTimedOut;
+	searchParamSet->SetUPnPEvent(event);
+	searchParamSet->SetUriL ( uri );	
+	CleanupStack::Pop(&pnpBundle);
+	iObserver->OnPnPEventL( pnpBundle );
+	}
+
+/* Used to send a Cancel discover request to the network in case of timer expiry
+ Sent automatically by CUPnPSearch::StopSearch */
+void CUPnPSearch::CancelSearchL(const TDesC8& aUri)
+	{	
+	RPnPParameterBundleBase rBundle;
+	rBundle.Open();
+	CleanupClosePushL( rBundle );
+	RParameterFamily family = rBundle.CreateFamilyL(EUPnPCancelDiscoverParamSet);	
+	
+	//Allocate the param set on the family
+	CUPnPCancelDiscoverParamSet* paramSet = CUPnPCancelDiscoverParamSet::NewL(family );
+
+	// Set the values in the parameter set
+	paramSet->SetUriL( aUri );
+	// Finally send cancel request to the subconnection
+	User::LeaveIfError( iSubConnection.SetParameters(rBundle ));
+	CleanupStack::PopAndDestroy( &rBundle );
+	}
+
+/* Used to send a Cancel discover request  to the network. This is called on client
+ invocation
+ @param aServiceInfo Bundle containing list of uri's whose discovery has to be cancelled
+ */
+void CUPnPSearch::CancelSearchL( const RPnPParameterBundle& aServiceInfo )
+	{	
+	RParameterFamily family = const_cast<RPnPParameterBundle&>(aServiceInfo).FindFamily(EUPnPCancelDiscoverParamSet);
+	
+	/* The uris passed in the bundle are looked up in iTimerMappedUri.If they
+	 exist, then its entry is removed from DeltaTimer and iTimerMappedUri as well
+	 */
+	TInt err = 0;
+	// Iterate through all the param sets in the passed bundle
+	
+	TUint count = family.CountParameterSets ( RParameterFamily::ERequested ) ;
+	CUPnPCancelDiscoverParamSet* paramSet = NULL;
+	for ( TInt paramIndex = count - 1; paramIndex >= 0; paramIndex-- )
+		{
+		paramSet = static_cast<CUPnPCancelDiscoverParamSet*> ( family.GetParameterSetAtIndex ( paramIndex, RParameterFamily::ERequested) );
+		
+		//Extract the uri
+		const TDesC8& uri = paramSet->Uri();
+		__ASSERT_DEBUG( paramSet->Uri() != KNullDesC8, User::Panic( KUPnPInvalidUserInput, KUPnPErrInvalidInput ) );
+		// Removes the uri entry from the array if exists
+		err=KErrNotFound;
+		for(TInt i=0;i<iTimerMappedArray.Count();i++)
+			{
+			if(iTimerMappedArray[i]->UriExists(uri))
+				{
+				err = KErrNone;
+				CTimerMappedUri* timerUri = iTimerMappedArray[i];
+				iDeltaTimer->Remove(timerUri->GetTimerEntry());
+				iTimerMappedArray.Remove(i);
+				if(iTimerMappedArray.Count()<= 0)
+					SetDiscoverProgress(EFalse);
+				delete timerUri;
+				break;
+				}
+			}
+		if ( err != KErrNone )
+			{			
+			reinterpret_cast<RUPnPParameterFamily*>(&family)->DeleteParamSetL ( paramIndex );
+			continue;
+			}
+		}
+	if ( family.CountParameterSets(RParameterFamily::ERequested)>= 1)
+			User::LeaveIfError(iSubConnection.SetParameters(aServiceInfo));
+	}
+
+/* CreateTimerEntry : creates the deltatimer entry and sets it to iEntry
+ @param aUri  The uri whose timer entry has to be created
+ */
+void CUPnPSearch::CreateTimerEntryL(const TDesC8& aUri )
+	{
+	CCallbackArgument* callArgument =CCallbackArgument::NewL(this,aUri);
+	CleanupStack::PushL(callArgument);
+	iCallbackArray.AppendL(callArgument);
+	TCallBack callBack(StopSearch,callArgument);
+	iEntry = new (ELeave) TDeltaTimerEntry ( callBack );
+	CleanupStack::Pop();
+	}