servicediscoveryandcontrol/pnp/test/upnp/Client/upnpplugin/src/cupnpsubscribe.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 //
       
    15 
       
    16 #include "cupnpsubscribe.h"
       
    17 #include "upnpconstants.h"
       
    18 #include "pnputils.h"
       
    19 #include <e32const.h>
       
    20 
       
    21 CUPnPSubscribe::CUPnPSubscribe(RSubConnection& aSubConnection , RHostResolver& aResolver):iSubConnection(aSubConnection)
       
    22 	,iResolver ( aResolver )
       
    23 	{
       
    24 	}
       
    25 
       
    26 CUPnPSubscribe* CUPnPSubscribe::NewL(RSubConnection& aSubConnection , RHostResolver& aResolver)
       
    27 	{
       
    28 	CUPnPSubscribe* subscribe=new ( ELeave ) CUPnPSubscribe(aSubConnection , aResolver);
       
    29 	CleanupStack::PushL( subscribe );
       
    30 	subscribe->ConstructL();
       
    31 	CleanupStack::Pop();
       
    32 	return subscribe;
       
    33 	}
       
    34 
       
    35 void CUPnPSubscribe::ConstructL()
       
    36 	{
       
    37 	iDeltaTimer=CDeltaTimer::NewL(EPriorityLow);
       
    38 	}
       
    39 
       
    40 CUPnPSubscribe:: ~CUPnPSubscribe()
       
    41 	{
       
    42 	iDeltaTimer->Cancel();	
       
    43 	delete iDeltaTimer;
       
    44 	delete iElementArray;
       
    45 	iTimerMappedArray.ResetAndDestroy();
       
    46 	iCallbackArray.ResetAndDestroy();
       
    47 	iMappedUri=NULL;
       
    48 	}
       
    49 
       
    50 /* Sends a subscribe request to the service point.It resolves all the uris passed
       
    51    in the parameter bundle to ip addresses if they're passed as domain names and
       
    52    appends them to element array
       
    53 
       
    54    @param aServiceInfo The parameter bundle which contains the uris to be sent
       
    55    describe requests to
       
    56  */
       
    57 void CUPnPSubscribe::SubmitRequestL(const RPnPParameterBundle& aServiceInfo)
       
    58 	{
       
    59 	TInt paramIndex=0;
       
    60 	
       
    61 	RParameterFamily family = const_cast<RPnPParameterBundle&>(aServiceInfo).FindFamily( EUPnPSubscribeRequestParamSet );
       
    62 	
       
    63 	// Iteration 1 : Mainly used for resubscribing request. All the entries
       
    64 	// corresponding to the uri which've been subscribed for before and are
       
    65 	// present in this parameter set are removed
       
    66 	
       
    67 	CUPnPSubscribeRequestParamSet* paramSet  = NULL;
       
    68 	TUint count = family.CountParameterSets ( RParameterFamily::ERequested ) ;
       
    69 	
       
    70 	for ( paramIndex = count - 1; paramIndex >= 0; paramIndex-- )
       
    71 		{
       
    72 		paramSet = static_cast<CUPnPSubscribeRequestParamSet*> ( family.GetParameterSetAtIndex ( paramIndex, RParameterFamily::ERequested ) );
       
    73 		
       
    74 		const TDesC8& uri = paramSet->Uri();
       
    75 		__ASSERT_DEBUG( paramSet->Uri() != KNullDesC8, User::Panic( KUPnPInvalidUserInput, KUPnPErrInvalidInput ) );
       
    76 		__ASSERT_DEBUG( paramSet->Duration() > 0, User::Panic( KUPnPInvalidUserInput, KUPnPErrInvalidInput ) );
       
    77 
       
    78 		for(TInt i=0;i<iTimerMappedArray.Count();i++)
       
    79 			{
       
    80 			if(iTimerMappedArray[i]->UriExists(uri))
       
    81 				{
       
    82 				CTimerMappedUri* timerUri = iTimerMappedArray[i];
       
    83 				iDeltaTimer->Remove(timerUri->GetTimerEntry());
       
    84 				iTimerMappedArray.Remove(i);
       
    85 				delete timerUri;
       
    86 				break;
       
    87 				}
       
    88 			}
       
    89 		for( TInt i=0;i<iCallbackArray.Count();i++)
       
    90 			{
       
    91 			if(uri.CompareF(iCallbackArray[i]->GetUri()) == NULL)
       
    92 				{
       
    93 				CCallbackArgument* callArgument = iCallbackArray[i];
       
    94 				iCallbackArray.Remove(i);
       
    95 				delete callArgument;
       
    96 				break;
       
    97 				}
       
    98 			}
       
    99 		
       
   100 		if( iElementArray && iElementArray->MatchElement(uri))
       
   101 			iElementArray->RemoveElement(uri);
       
   102 		
       
   103 		}
       
   104 	// Initialize the iterator . The uris will be checked for duplication,resolved
       
   105 	// and appended
       
   106 	TInetAddr address;
       
   107 	
       
   108 	for ( paramIndex = count - 1; paramIndex >= 0; paramIndex-- )
       
   109 		{
       
   110 			paramSet = static_cast<CUPnPSubscribeRequestParamSet*> ( family.GetParameterSetAtIndex ( paramIndex, RParameterFamily::ERequested ) );
       
   111 			const TDesC8& uri = paramSet->Uri();
       
   112 			
       
   113 		// Creates a new Element array if one is not already present and
       
   114 		// appends the uri to it. If the uri is duplicate then the corresponding param
       
   115 		// set is removed
       
   116 		if(!iElementArray)
       
   117 			{
       
   118 			iElementArray = new CUPnPElementArray;
       
   119 			User::LeaveIfNull(iElementArray);
       
   120 			iElementArray->InsertElementL(aServiceInfo.PnPObserver(), uri);
       
   121 			}
       
   122 		else
       
   123 			{
       
   124 			if(!iElementArray->MatchElement(uri))
       
   125 				{
       
   126 				iElementArray->InsertElementL(aServiceInfo.PnPObserver(),uri);
       
   127 				}
       
   128 			else
       
   129 				{
       
   130 				reinterpret_cast<RUPnPParameterFamily*>(&family)->DeleteParamSetL(paramIndex);
       
   131 				continue;
       
   132 				}
       
   133 			}
       
   134 			
       
   135 		CUPnPUtils::ResolveHostAddressL ( iResolver, paramSet->Uri(), address );
       
   136 		paramSet->SetRemoteHost ( address );
       
   137 		
       
   138 		}
       
   139 	/* Finally if all other processing is done successfully do the
       
   140 	 * set params
       
   141 	 */
       
   142 			
       
   143 	if ( family.CountParameterSets(RParameterFamily::ERequested)>=1)
       
   144 		User::LeaveIfError(iSubConnection.SetParameters(aServiceInfo));
       
   145 	
       
   146 	
       
   147 	}
       
   148 
       
   149 /* On expiry of the CDeltaTimer associated with the requested uri
       
   150  * it removes the corresponding from the element array and notifies the client
       
   151  */
       
   152 TInt CUPnPSubscribe::OnTimerExpiry(TAny* aPtr)
       
   153 	{
       
   154 	TInt error = KErrNone;
       
   155 	CCallbackArgument* pointerData= static_cast<CCallbackArgument*> (aPtr);
       
   156 	CUPnPSubscribe* thisObject= static_cast<CUPnPSubscribe*> (pointerData->GetThisPointer());
       
   157 	CUPnPElementArray* thisElementArray=thisObject->ElementArrayHandle();
       
   158 	RPointerArray<CTimerMappedUri>& timerArray=thisObject->GetTimerArray();
       
   159 	RPointerArray<CCallbackArgument>& argArray = thisObject->GetArgumentArray();
       
   160 
       
   161 	const TDesC8& uri = pointerData->GetUri();
       
   162 
       
   163 	TInt index;
       
   164 	for( index=0; index<timerArray.Count(); index++ )
       
   165 		{
       
   166 		if(timerArray[index]->UriExists(uri))
       
   167 			{
       
   168 			CTimerMappedUri* timerUri = timerArray[index];
       
   169 			timerArray.Remove(index);
       
   170 			delete timerUri;
       
   171 			index = -1;
       
   172 			break;
       
   173 			}
       
   174 		}
       
   175 	__ASSERT_DEBUG( index == -1 ,User::Panic(KUPnPTimerUriNotFound,KUPnPErrTimerError) );
       
   176 	for( index=0; index<argArray.Count(); index++ )
       
   177 		{
       
   178 		const TDesC8& testUri = argArray[index]->GetUri();
       
   179 		if(uri.CompareF(argArray[index]->GetUri())==NULL)
       
   180 			{
       
   181 			argArray.Remove(index);
       
   182 			break;
       
   183 			}
       
   184 		}
       
   185 	MPnPObserver* observer = thisElementArray->MatchElement(uri);
       
   186 	__ASSERT_DEBUG( observer , User::Invariant());
       
   187 	// Removes the uri from the element Array 
       
   188 	HBufC8* notifyUri = pointerData->GetUri().Alloc();
       
   189 	__ASSERT_DEBUG( notifyUri , User::Invariant());
       
   190 	
       
   191 	// Deletes the CCallbackargument data
       
   192 	delete pointerData;
       
   193 	
       
   194 	// Notifies the client that timer has expired
       
   195 	TRAP(error,thisObject->MakeBundleAndNotifyL(observer, notifyUri));
       
   196 	return KErrNone;
       
   197 	}
       
   198 
       
   199 /* Passes back the response bundle to the client. A response bundle
       
   200  will contain only one parameter set consequently with a single observer
       
   201  */
       
   202 void CUPnPSubscribe::NotifyResultsL(TUint32 aFamilyId, RPnPParameterBundleBase& aBundle)
       
   203 	{
       
   204 	MPnPObserver* observer = NULL;
       
   205 	User::LeaveIfNull(iElementArray);
       
   206 	
       
   207 	CUPnPSubscribeResponseParamSet* subscribeParamSet  = NULL;
       
   208 	CUPnPNotifyEventParamSet* notifyParamSet  = NULL;	
       
   209 	RParameterFamily family ;
       
   210 	switch(aFamilyId)
       
   211 		{
       
   212 		case EUPnPSubscribeResponseParamSet:
       
   213 			{
       
   214 			// Response to subscription request
       
   215 			family = aBundle.FindFamily(EUPnPSubscribeResponseParamSet);			
       
   216 			__ASSERT_DEBUG(!family.IsNull (), User::Panic(KUPnPInvalidFamily,KUPnPErrInvalidFamily));	
       
   217 			__ASSERT_DEBUG(family.CountParameterSets(RParameterFamily::ERequested) > 0, User::Panic(KUPnPNoParamSet,KUPnPErrNoParamSet));				
       
   218 			TUint count = family.CountParameterSets ( RParameterFamily::ERequested ) ;
       
   219 			for ( TInt paramIndex = count - 1; paramIndex >= 0; paramIndex-- )
       
   220 				{
       
   221 				 subscribeParamSet = static_cast<CUPnPSubscribeResponseParamSet*> (family.GetParameterSetAtIndex(paramIndex,RParameterFamily::ERequested));
       
   222 				 switch(( subscribeParamSet->UPnPEvent() ).iStatus)
       
   223 					{
       
   224 					case TUPnPEvent::ESuccess:
       
   225 						{
       
   226 						/* Extract the uri and the expiry time which has been supplied by
       
   227 						 * the server and create a deltatimer entry using them
       
   228 						 */ 
       
   229 						TInt subscribeExpiryTime = subscribeParamSet->GetTimerExpiry();
       
   230 						const TDesC8& uri = subscribeParamSet->Uri();
       
   231 						observer = iElementArray->MatchElement(uri);
       
   232 						__ASSERT_DEBUG( observer != NULL, User::Panic(KUPnPResponseUriNotFound,KUPnPErrResponseUriNotFound));
       
   233 
       
   234 						CreateTimerEntryL(uri,subscribeExpiryTime);
       
   235 						}
       
   236 					break;
       
   237 
       
   238 					case TUPnPEvent::EFail:
       
   239 						{
       
   240 						const TDesC8& uri = subscribeParamSet->Uri();
       
   241 						observer=iElementArray->MatchElement(uri);
       
   242 						__ASSERT_DEBUG( observer != NULL, User::Panic(KUPnPResponseUriNotFound,KUPnPErrResponseUriNotFound));
       
   243 						iElementArray->RemoveElement(uri);
       
   244 						}
       
   245 					break;
       
   246 
       
   247 					default:
       
   248 						__ASSERT_DEBUG(0, User::Panic(KUPnPInvalidFamily,KUPnPErrInvalidFamily));	
       
   249 					}
       
   250 				}
       
   251 			}
       
   252 		break;
       
   253 
       
   254 		case EUPnPNotifyEventParamSet:
       
   255 			{
       
   256 			
       
   257 			// Eventing parameter set
       
   258 			family = aBundle.FindFamily( EUPnPNotifyEventParamSet );
       
   259 			TUint count = family.CountParameterSets ( RParameterFamily::ERequested ) ;			
       
   260 			notifyParamSet = static_cast<CUPnPNotifyEventParamSet*> ( family.GetParameterSetAtIndex ( count - 1, RParameterFamily::ERequested ) );	
       
   261 			observer = iElementArray->MatchElement(notifyParamSet->Uri());
       
   262 			__ASSERT_DEBUG( observer != NULL, User::Panic(KUPnPResponseUriNotFound,KUPnPErrResponseUriNotFound));
       
   263 			}
       
   264 			break;
       
   265 		default:
       
   266 			__ASSERT_DEBUG(0, User::Panic(KUPnPInvalidFamily,KUPnPErrInvalidFamily));	
       
   267 		}
       
   268 	
       
   269 	observer->OnPnPEventL(aBundle) ;
       
   270 	}
       
   271 
       
   272 /* Makes a bundle on expiry of the timer and sends it the client application
       
   273  * saying "Subscription has timed out"
       
   274  */
       
   275 void CUPnPSubscribe::MakeBundleAndNotifyL(MPnPObserver* aObserver, HBufC8* aUri)
       
   276 	{
       
   277 	RPnPParameterBundleBase pnpBundle ;
       
   278 	pnpBundle.Open();		
       
   279 	CleanupClosePushL( pnpBundle );
       
   280 
       
   281 	RParameterFamily family = pnpBundle.CreateFamilyL(EUPnPSubscribeResponseParamSet);
       
   282 	// Create a new Param set
       
   283     CUPnPSubscribeResponseParamSet* subscribeParamSet = CUPnPSubscribeResponseParamSet::NewL(family );
       
   284     
       
   285     // Set the values for the event
       
   286     TUPnPEvent event;
       
   287     event.iStatus=TUPnPEvent::ESubscriptionTimeout;
       
   288     event.iErrorCode = KErrTimedOut;
       
   289 
       
   290    // Set the values in the parameter set
       
   291     subscribeParamSet->SetUPnPEvent(event);
       
   292     subscribeParamSet->SetUriL ( *aUri );
       
   293     subscribeParamSet->SetTimerExpiry(NULL);
       
   294 
       
   295     CleanupStack::Pop( &pnpBundle);
       
   296     delete aUri;
       
   297     aObserver->OnPnPEventL( pnpBundle ) ;
       
   298 	}
       
   299 
       
   300 /* CancelDescribe is used to send cancel subscribe requests to the network
       
   301  @param aServiceInfo The bundle which contains the list of uris whose describe
       
   302  		request should be cancelled
       
   303  */
       
   304 void CUPnPSubscribe::CancelSubscribeL( const RPnPParameterBundle& aServiceInfo )
       
   305 	{
       
   306 	User::LeaveIfNull(iElementArray);	
       
   307 	RParameterFamily family = const_cast<RPnPParameterBundle&>(aServiceInfo).FindFamily( EUPnPCancelSubscribeParamSet );
       
   308 		
       
   309 	CUPnPCancelSubscribeParamSet* paramSet = NULL;
       
   310 	TUint count = family.CountParameterSets ( RParameterFamily::ERequested ) ;
       
   311 	
       
   312 	for ( TInt paramIndex = count - 1; paramIndex >= 0; paramIndex-- )
       
   313 	{
       
   314 		paramSet = static_cast<CUPnPCancelSubscribeParamSet*> ( family.GetParameterSetAtIndex ( paramIndex, RParameterFamily::ERequested) );
       
   315 		//Extract the uri
       
   316 		const TDesC8& uri = paramSet->Uri();
       
   317 		__ASSERT_DEBUG( paramSet->Uri() != KNullDesC8, User::Panic( KUPnPInvalidUserInput, KUPnPErrInvalidInput ) );
       
   318 
       
   319 		// Removes the uri entry from the array if exists
       
   320 		for(TInt i=0;i<iTimerMappedArray.Count();i++)
       
   321 			{
       
   322 			if(iTimerMappedArray[i]->UriExists(uri) )
       
   323 				{
       
   324 				CTimerMappedUri* timerUri = iTimerMappedArray[i];
       
   325 				iDeltaTimer->Remove(timerUri->GetTimerEntry());
       
   326 				iTimerMappedArray.Remove(i);
       
   327 				delete timerUri;
       
   328 				break;
       
   329 				}
       
   330 			}
       
   331 		for( TInt i=0;i<iCallbackArray.Count();i++)
       
   332 			{
       
   333 			if(uri.CompareF(iCallbackArray[i]->GetUri()) == NULL)
       
   334 				{
       
   335 				CCallbackArgument* callArgument = iCallbackArray[i];
       
   336 				iCallbackArray.Remove(i);
       
   337 				delete callArgument;
       
   338 				break;
       
   339 				}
       
   340 			}
       
   341 
       
   342 		// Remove the entry from element array
       
   343 		MPnPObserver* observer = iElementArray->MatchElement( uri );
       
   344 		if ( !observer )
       
   345 			{		
       
   346 			reinterpret_cast<RUPnPParameterFamily*>(&family)->DeleteParamSetL ( paramIndex );
       
   347 			continue;
       
   348 			}
       
   349 		iElementArray->RemoveElement( uri );
       
   350 		}
       
   351 	if ( family.CountParameterSets(RParameterFamily::ERequested) >= 1)
       
   352 		User::LeaveIfError(iSubConnection.SetParameters( aServiceInfo ));
       
   353 	
       
   354 	}
       
   355 
       
   356 /* The timer delay is adjusted to 90% of the subscription time.Also it is adjusted
       
   357    for microseconds and IPC lag
       
   358  */
       
   359 TInt CUPnPSubscribe::AdjustedDelay( TInt aTime )
       
   360 	{
       
   361 	TUint64 divisor = 10;
       
   362 	TUint64 temp; // just a placeholder
       
   363 	TUint64 q = Math::UDivMod64(aTime,divisor,temp);
       
   364 	temp = q*(divisor-1);
       
   365 	aTime = static_cast<TInt>(temp);
       
   366 
       
   367 	const TInt KIntTime = 1000000 ;
       
   368 	const TInt KInternalIPCLag = 1;
       
   369 	aTime = ( aTime + KInternalIPCLag ) * KIntTime ;
       
   370 	return aTime;
       
   371 	}
       
   372 
       
   373 /* CreateTimerEntry : creates the deltatimer entry and queues it up
       
   374  */
       
   375 void CUPnPSubscribe::CreateTimerEntryL(const TDesC8& aUri ,TInt aExpiryTime)
       
   376 
       
   377 	{
       
   378 	CCallbackArgument* callArgument = CCallbackArgument::NewL(this,aUri);
       
   379 	CleanupStack::PushL(callArgument);
       
   380 	iCallbackArray.AppendL(callArgument);
       
   381 	CleanupStack::Pop();
       
   382 	
       
   383 	TCallBack callBack(OnTimerExpiry,callArgument);
       
   384 	iTimerEntry = new(ELeave) TDeltaTimerEntry( callBack );
       
   385 	iMappedUri = CTimerMappedUri::NewL(aUri, iTimerEntry,aExpiryTime);
       
   386 	iTimerMappedArray.AppendL(iMappedUri);
       
   387 	
       
   388 	// The time is set to 90% of the given time to allow the user
       
   389 	// to resubscribe before the expiry time
       
   390 	TInt time = AdjustedDelay(aExpiryTime);
       
   391 	TTimeIntervalMicroSeconds32 delay(time);
       
   392 	iDeltaTimer->Queue(delay,*iTimerEntry);
       
   393 	}
       
   394 
       
   395