diff -r 000000000000 -r f5a58ecadc66 servicediscoveryandcontrol/pnp/test/upnp/Client/upnpplugin/src/cupnpsearch.cpp --- /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(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 ( 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(&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;iUriExists(uri)) + { + reinterpret_cast(&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;iDelay()); + 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 (aPtr); + CUPnPSearch* thisObject= static_cast < CUPnPSearch*> (pointerData->GetThisPointer()); + RPointerArray& rArray=thisObject->GetTimerArray(); + RPointerArray& argArray = thisObject->GetArgumentArray(); + const TDesC8& uri = pointerData->GetUri(); + TInt index; + for(index=0;indexUriExists(uri)) + { + // Removes the uri entry from the array + CTimerMappedUri* timerUri = rArray[index]; + rArray.Remove(index); + delete timerUri; + break; + } + } + for( index=0;indexGetUri()) == 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(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 ( 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;iUriExists(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(&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(); + }