--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/natfw/natfwicecandidatehandler/src/cicechecklist.cpp Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,1525 @@
+/*
+* Copyright (c) 2007 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 "natfwcandidate.h"
+#include "natfwcandidatepair.h"
+#include "cicechecklist.h"
+#include "cicecheckprioritizer.h"
+#include "cicecandidateprioritizer.h"
+#include "ciceconnectivitycheck.h"
+#include "cicesessiondata.h"
+#include "micechecklistobserver.h"
+#include "cicevalidlist.h"
+#include "icecandidatehandlerdefs.h"
+#include "icecandidatehandlerlogs.h"
+
+const TUint KComponentIdRtp = 1;
+
+// ======== MEMBER FUNCTIONS ========
+
+CIceCheckList::CIceCheckList(
+ MIceChecklistObserver& aClient,
+ TUint aStreamCollectionId,
+ CIceSessionData& aSessionData,
+ CIceConnectionHandler& aConnHandler )
+ :
+ iStreamCollectionId( aStreamCollectionId ),
+ iClient( aClient ),
+ iSessionData( aSessionData ),
+ iConnHandler( aConnHandler )
+ {
+ }
+
+
+void CIceCheckList::ConstructL()
+ {
+ iCheckPrioritizer = CIceCheckPrioritizer::NewL();
+ iCandPrioritizer = CIceCandidatePrioritizer::NewL(
+ iSessionData.Domain() );
+ iTimer = CPeriodic::NewL( CActive::EPriorityStandard );
+ iValidList = CIceValidList::NewL( iStreamCollectionId );
+ GenerateCheckListL( iChecks );
+ }
+
+
+CIceCheckList* CIceCheckList::NewL(
+ MIceChecklistObserver& aClient,
+ TUint aStreamCollectionId,
+ CIceSessionData& aSessionData,
+ CIceConnectionHandler& aConnHandler )
+ {
+ CIceCheckList* self
+ = CIceCheckList::NewLC( aClient, aStreamCollectionId,
+ aSessionData, aConnHandler );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+CIceCheckList* CIceCheckList::NewLC(
+ MIceChecklistObserver& aClient,
+ TUint aStreamCollectionId,
+ CIceSessionData& aSessionData,
+ CIceConnectionHandler& aConnHandler )
+ {
+ CIceCheckList* self
+ = new( ELeave ) CIceCheckList(
+ aClient, aStreamCollectionId, aSessionData, aConnHandler );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+
+CIceCheckList::~CIceCheckList()
+ {
+ __ICEDP( "CIceCheckList::~CIceCheckList" )
+
+ iChecks.ResetAndDestroy();
+ iCheckQue.Close();
+ delete iCheckPrioritizer;
+ delete iCandPrioritizer;
+ delete iTimer;
+ delete iValidList;
+ iComponentIds.Close();
+ iSelectedPairs.ResetAndDestroy();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::TimerFired
+// ---------------------------------------------------------------------------
+//
+TInt CIceCheckList::TimerFired( TAny* aObject )
+ {
+ if ( aObject )
+ {
+ CIceCheckList* list = reinterpret_cast<CIceCheckList*>( aObject );
+ TRAPD( error, list->OnTimerFiredL() )
+ if ( error )
+ {
+ __ICEDP_INT1( "CIceCheckList::TimerFired, ERR:", error )
+ if ( KErrNoMemory == error )
+ {
+ TRAP_IGNORE( list->SetStateL( EIceCheckListFailed ) )
+ }
+ else
+ {
+ ASSERT( EFalse );
+ }
+ }
+
+ return 1;
+ }
+ else
+ {
+ __ICEDP( "CIceCheckList::TimerFired, ELSE" )
+ ASSERT( EFalse );
+ return 0; // lint #527
+ }
+ }
+
+
+// Non-derived function
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::State
+// ---------------------------------------------------------------------------
+//
+CIceCheckList::TIceCheckListState CIceCheckList::State() const
+ {
+ return iState;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::StreamCollectionId()
+// ---------------------------------------------------------------------------
+//
+TUint CIceCheckList::StreamCollectionId() const
+ {
+ return iStreamCollectionId;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::InitializeCheckListL()
+// Used to initialize check list corresponding first SDP mediastream.
+// ICE-17, section 5.7.4.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::InitializeCheckListL()
+ {
+ __ICEDP( "CIceCheckList::InitializeCheckListL" )
+ __ASSERT_DEBUG( iChecks.Count(), User::Leave( KErrNotReady ) );
+
+ TUint lowestComponentId = LowestComponentId( iComponentIds );
+
+ CDesC8ArrayFlat* foundations
+ = FoundationsForCollectionL( iStreamCollectionId );
+
+ TInt foundationCount( foundations->Count() );
+ for ( TInt i(0); i < foundationCount; ++i )
+ {
+ // inside foundation group set lowest component id waiting
+ TInt checkIndex( iChecks.Count() );
+ TBool checkInitialized( EFalse );
+
+ while ( ( checkIndex-- ) && ( !checkInitialized ) )
+ {
+ CIceConnectivityCheck& check( *iChecks[checkIndex] );
+ if ( check.CandidatePair().Foundation()
+ == foundations->MdcaPoint(i)
+ && check.ComponentId() == lowestComponentId )
+ {
+ check.Initialize();
+ checkInitialized = ETrue;
+ }
+ }
+ }
+
+ delete foundations;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::InitializeCheckListL
+// ICE-17, 7.1.2.2.3, Updating Pair States.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::InitializeCheckListL( const TDesC8& aFoundation )
+ {
+ __ICEDP( "CIceCheckList::InitializeCheckListL" )
+ __ASSERT_DEBUG( iChecks.Count(), User::Leave( KErrNotReady ) );
+
+ TBool initComplete( EFalse );
+ TInt count( iChecks.Count() );
+ for ( TInt i = 0; i < count; ++i )
+ {
+ if ( CIceConnectivityCheck::EIceCheckFrozen == iChecks[i]->State()
+ && iChecks[i]->CandidatePair().Foundation() == aFoundation )
+ {
+ iChecks[i]->Initialize();
+ initComplete = ETrue;
+ }
+ }
+
+ if ( !initComplete && CheckListFrozen() )
+ {
+ InitializeCheckListL();
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::StartPerformChecksL()
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::StartPerformChecksL(
+ const TTimeIntervalMicroSeconds32& anInterval )
+ {
+ __ICEDP( "CIceCheckList::StartPerformChecksL" )
+
+ iInterval = anInterval;
+ SetStateL( EIceCheckListRunning );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::RestartCheckListL()
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::RestartCheckListL(
+ const TTimeIntervalMicroSeconds32& anInterval )
+ {
+ __ICEDP( "CIceCheckList::RestartCheckListL" )
+ __ASSERT_ALWAYS( EIceCheckListCompleted == State(),
+ User::Leave( KErrNotReady ) );
+
+ iValidList->FlushValidList();
+ iChecks.ResetAndDestroy();
+ GenerateCheckListL( iChecks );
+
+ iInterval = anInterval;
+ SetStateL( EIceCheckListRunning );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::UpdateCheckListL()
+// Controlling peer has selected candidate pairs to be used.
+// ICE-17, 9.2.2.3. Existing Media Streams and remote-candidates.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::UpdateCheckListL(
+ RPointerArray<CNATFWCandidatePair>& aPeerSelectedPairs )
+ {
+ __ICEDP( "CIceCheckList::UpdateIceProcessingL" )
+ __ASSERT_DEBUG( EIceCheckListRunning == State(),
+ User::Leave( KErrNotReady ) );
+ __ASSERT_ALWAYS( !iSelectedPairs.Count(),
+ User::Leave( KErrAlreadyExists ) );
+
+ TInt numOfSelectedComps( aPeerSelectedPairs.Count() );
+ for ( TInt i( 0 ); i < numOfSelectedComps; ++i )
+ {
+ CNATFWCandidatePair* pair
+ = CNATFWCandidatePair::NewLC( *aPeerSelectedPairs[i] );
+ iSelectedPairs.AppendL( pair );
+ CleanupStack::Pop( pair );
+ }
+
+ DoLosingPairProcessingL( iSelectedPairs );
+ UpdateCheckListStateL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::UpdateCheckListL()
+// Peer has added new remote candidates to the session negotiation.
+// ICE-17, 9.3.1.4. ICE Continuing for Existing Media Stream.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::UpdateCheckListL(
+ RPointerArray<CNATFWCandidate>& /*aRemoteCands*/ )
+ {
+ __ICEDP( "CIceCheckList::UpdateIceProcessingL" )
+ __ASSERT_DEBUG( EIceCheckListRunning == State(),
+ User::Leave( KErrNotReady ) );
+
+ RPointerArray<CIceConnectivityCheck> newCheckList;
+ CleanupResetAndDestroyPushL( newCheckList );
+ GenerateCheckListL( newCheckList );
+
+ // Add new checks to the checklist
+ for ( TInt i( newCheckList.Count() - 1 ); i >= 0; --i )
+ {
+ CIceConnectivityCheck* newCheck( newCheckList[i] );
+
+ TInt ind = iChecks.Find(
+ newCheck, CIceConnectivityCheck::MatchAddresses );
+
+ // All new checks are in frozen state initially
+ if ( KErrNotFound == ind )
+ {
+ iChecks.InsertInOrderL( newCheck,
+ CIceConnectivityCheck::ComparePriorities );
+ newCheckList.Remove( i );
+ }
+ }
+
+ TBool rtpComponentFound( EFalse );
+ TInt ind( iChecks.Count() - 1 );
+ while( ( !rtpComponentFound ) && ( 0 <= ind ) )
+ {
+ if ( KComponentIdRtp == iChecks[ind]->ComponentId()
+ && CIceConnectivityCheck::EIceCheckSucceed
+ == iChecks[ind]->State() )
+ {
+ rtpComponentFound = ETrue;
+ InitializeCheckList(
+ iChecks[ind]->CandidatePair().Foundation(),
+ KComponentIdRtp );
+
+ if ( iValidList->HasPairForComponents( iComponentIds ) )
+ {
+ // Start checks in other check lists for checks of same type
+ iClient.ComponentsHaveValidPairsL(
+ *this, iChecks[ind]->CandidatePair().Foundation() );
+ }
+ }
+
+ ind--;
+ }
+
+ CleanupStack::PopAndDestroy( &newCheckList );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::GenerateCheckListL()
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::GenerateCheckListL(
+ RPointerArray<CIceConnectivityCheck>& aCheckList )
+ {
+ __ICEDP( "CIceCheckList::GenerateCheckListL" )
+
+ RPointerArray<CNATFWCandidate> localCandidates;
+ RPointerArray<CNATFWCandidate> remoteCandidates;
+ CleanupClosePushL( localCandidates );
+ CleanupClosePushL( remoteCandidates );
+
+ iSessionData.GetLocalCandidates(
+ iStreamCollectionId,
+ localCandidates );
+
+ iSessionData.GetRemoteCandidatesL(
+ iStreamCollectionId,
+ remoteCandidates );
+
+ __ASSERT_ALWAYS( localCandidates.Count() && remoteCandidates.Count(),
+ User::Leave( KErrNotReady ) );
+
+ PairCandidatesL( aCheckList, localCandidates, remoteCandidates );
+ CleanupStack::PopAndDestroy( &remoteCandidates );
+ CleanupStack::PopAndDestroy( &localCandidates );
+
+ iCheckPrioritizer->PrioritizeChecks( aCheckList, iSessionData.Role() );
+ aCheckList.Sort( CIceConnectivityCheck::ComparePriorities );
+ PruneChecksL( aCheckList );
+
+#ifdef _DEBUG
+ __ICEDP( "CIceCheckList::GenerateCheckListL, LIST AFTER PRUNING" )
+ TInt count( aCheckList.Count() );
+ for ( TInt i(0); i < count; ++i )
+ {
+ __ICEDP_ADDRLOG( "LOCAL_ADDR",
+ aCheckList[i]->CandidatePair().LocalCandidate().TransportAddr() )
+
+ __ICEDP_ADDRLOG( "PEER_ADDR",
+ aCheckList[i]->CandidatePair().RemoteCandidate().TransportAddr() )
+ }
+#endif
+
+ GetComponentIdsL( iComponentIds );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::PairCandidatesL
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::PairCandidatesL(
+ RPointerArray<CIceConnectivityCheck>& aCheckList,
+ RPointerArray<CNATFWCandidate>& aLocalCands,
+ RPointerArray<CNATFWCandidate>& aRemoteCands )
+ {
+ __ICEDP( "CIceCheckList::PairCandidatesL" )
+
+ CNATFWCandidate* lCand( NULL );
+ CNATFWCandidate* rCand( NULL );
+
+ TInt lInd = aLocalCands.Count();
+ while ( lInd-- )
+ {
+ lCand = aLocalCands[lInd];
+
+ TInt rInd = aRemoteCands.Count();
+ while ( rInd-- )
+ {
+ rCand = aRemoteCands[rInd];
+
+ if ( CompatibleCandidates( *lCand, *rCand ) )
+ {
+ CIceConnectivityCheck* check
+ = CIceConnectivityCheck::NewLC( *this, *lCand, *rCand,
+ iConnHandler, iSessionData );
+
+ aCheckList.AppendL( check );
+ CleanupStack::Pop( check );
+ }
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::CompatibleCandidates
+// According to ICE-17, 5.7.1. and ICE-TCP-03, 4.1.
+// ---------------------------------------------------------------------------
+//
+TBool CIceCheckList::CompatibleCandidates(
+ const CNATFWCandidate& aCand1, const CNATFWCandidate& aCand2 ) const
+ {
+ __ICEDP( "CIceCheckList::CompatibleCandidates" )
+
+ TUint protocol( aCand1.TransportProtocol() );
+ if ( protocol != aCand2.TransportProtocol()
+ || aCand1.TransportAddr().Family() != aCand2.TransportAddr().Family()
+ || aCand1.ComponentId() != aCand2.ComponentId() )
+ {
+ return EFalse;
+ }
+
+ if ( KProtocolInetUdp == protocol )
+ {
+ return ETrue;
+ }
+ else
+ {
+ // we have not TCP support yet
+ return EFalse;
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::PruneChecksL
+// ICE-17, 5.7.3 Pruning the pairs.
+// Procedures of ICE-TCP-03, 4.1. to be added.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::PruneChecksL(
+ RPointerArray<CIceConnectivityCheck>& aChecks )
+ {
+ __ICEDP_INT1( "CIceCheckList::PruneChecksL start, COUNT:", aChecks.Count() )
+
+ // Replace server reflexive local candidate of the check by corresponding
+ // base candidate.
+ ReplaceReflexiveCandidatesWithBaseL( aChecks );
+
+ // Remove redundant checks.
+ for ( TInt i( aChecks.Count() - 1 ); 0 <= i; --i )
+ {
+ TInt matchInd = aChecks.Find( aChecks[i],
+ CIceConnectivityCheck::MatchAddresses );
+
+ if ( KErrNotFound != matchInd && matchInd != i )
+ {
+ delete aChecks[i];
+ aChecks.Remove( i );
+ }
+ }
+
+ __ICEDP_INT1( "CIceCheckList::PruneChecksL end, COUNT:", aChecks.Count() )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::ReplaceReflexiveCandidatesWithBaseL
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::ReplaceReflexiveCandidatesWithBaseL(
+ RPointerArray<CIceConnectivityCheck>& aChecks )
+ {
+ for ( TInt i( aChecks.Count() - 1 ); i >= 0; --i )
+ {
+ CNATFWCandidate& localCand = const_cast<CNATFWCandidate&>
+ ( aChecks[ i ]->CandidatePair().LocalCandidate() );
+
+ if ( CNATFWCandidate::EServerReflexive == localCand.Type() )
+ {
+ TInt numOfChecks( aChecks.Count() );
+ for ( TInt j( 0 ); j < numOfChecks; ++j )
+ {
+ const CNATFWCandidate& baseCand
+ = aChecks[ j ]->CandidatePair().LocalCandidate();
+ if ( CNATFWCandidate::EHost == baseCand.Type()
+ && TIceUtils::MatchAddresses(
+ localCand.Base(), baseCand.Base() ) )
+ {
+ localCand.SetTransportAddrL( baseCand.Base() );
+ localCand.SetType( CNATFWCandidate::EHost );
+ localCand.SetFoundationL( baseCand.Foundation() );
+ localCand.SetPriority( baseCand.Priority() );
+ }
+ }
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::OnTimerFiredL
+// If triggered check queue contains items, top-most triggered check is sent.
+// Otherwise an ordinary check is sent. ICE-17, 5.8. Scheduling checks.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::OnTimerFiredL()
+ {
+ __ICEDP( "CIceCheckList::OnTimerFiredL" )
+
+ TBool found = DequeueCheckL();
+ if ( found )
+ {
+ return;
+ }
+
+ // Find highest priority check in waiting state
+ TInt ind = FindCheckInState( CIceConnectivityCheck::EIceCheckWaiting );
+ if ( KErrNotFound != ind )
+ {
+ TUint priority = PriorityForPeerReflCandL(
+ iChecks[ind]->CandidatePair().LocalCandidate() );
+ iChecks[ind]->PerformConnCheckL(
+ CIceConnectivityCheck::EIceCheckTypePeriodic, priority,
+ RetransmissionTimeOut() );
+
+ return;
+ }
+
+ ind = FindCheckInState( CIceConnectivityCheck::EIceCheckFrozen );
+ if ( KErrNotFound != ind )
+ {
+ iChecks[ind]->Initialize();
+ TUint priority = PriorityForPeerReflCandL(
+ iChecks[ind]->CandidatePair().LocalCandidate() );
+ iChecks[ind]->PerformConnCheckL(
+ CIceConnectivityCheck::EIceCheckTypePeriodic, priority,
+ RetransmissionTimeOut() );
+
+ return;
+ }
+
+ iTimer->Cancel();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::PriorityForPeerReflCandL
+// ---------------------------------------------------------------------------
+//
+TUint CIceCheckList::PriorityForPeerReflCandL(
+ const CNATFWCandidate& aLocalCandidate ) const
+ {
+ __ICEDP( "CIceCheckList::PriorityForTentativePeerReflCandL" )
+
+ CNATFWCandidate* candidate = CNATFWCandidate::NewLC( aLocalCandidate );
+ candidate->SetType( CNATFWCandidate::EPeerReflexive );
+ iCandPrioritizer->PrioritizeL( *candidate );
+ TUint priority( candidate->Priority() );
+ CleanupStack::PopAndDestroy( candidate );
+
+ return priority;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::STUNRequestReceivedL
+// Resolve local and remote candidates and set up them for actual handler.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::STUNRequestReceivedL( const TInetAddr& aLocalAddr,
+ const TInetAddr& aFromAddr, const TInetAddr& aPeerAddr,
+ TUint aPriority, TBool aRemoteFavored )
+ {
+ __ICEDP( "CIceCheckList::STUNRequestReceivedL" )
+ if ( ( State() != EIceCheckListRunning )
+ && ( State() != EIceCheckListCompleted ) )
+ {
+ SetStateL( EIceCheckListRunning );
+ }
+
+ // Find real local candidate where request was sent to
+ const CNATFWCandidate* localCand = NULL;
+ TBool relayUsed = !TIceUtils::MatchAddresses( aFromAddr, aPeerAddr );
+ if ( relayUsed )
+ {
+ __ICEDP( "CIceCheckList::STUNRequestReceivedL, RELAY USED" )
+
+ // Find out media component type (RTP/RTCP)
+ localCand = iSessionData.FindLocalCandidate( aLocalAddr );
+ TUint componentId = localCand->ComponentId();
+ localCand = iSessionData.FindLocalCandidate(
+ iStreamCollectionId, componentId, CNATFWCandidate::ERelay );
+ }
+ else
+ {
+ localCand = iSessionData.FindLocalCandidate( aLocalAddr );
+ }
+
+ __ASSERT_ALWAYS( NULL != localCand, User::Leave( KErrNotFound ) );
+
+ const CNATFWCandidate* remoteCand
+ = iSessionData.FindRemoteCandidate( aPeerAddr );
+ CNATFWCandidate* newRemoteCand = NULL;
+ if ( remoteCand )
+ {
+ newRemoteCand = CNATFWCandidate::NewLC( *remoteCand );
+ }
+ else
+ {
+ // ICE-17, 7.2.1.3. Learning Peer Reflexive (remote) Candidates
+ newRemoteCand = CNATFWCandidate::NewLC();
+ newRemoteCand->SetTransportAddrL( aPeerAddr );
+ newRemoteCand->SetType( CNATFWCandidate::EPeerReflexive );
+ newRemoteCand->SetStreamCollectionId( localCand->StreamCollectionId() );
+ newRemoteCand->SetStreamId( localCand->StreamId() );
+ newRemoteCand->SetComponentId( localCand->ComponentId() );
+ newRemoteCand->SetPriority( aPriority );
+
+ CNATFWCandidate* peerReflCand
+ = CNATFWCandidate::NewLC( *newRemoteCand );
+ // Session data generates arbitrary foundation
+ iSessionData.AddPeerReflexiveCandidateL( peerReflCand, ETrue );
+ CleanupStack::Pop( peerReflCand );
+ }
+
+ CNATFWCandidatePair* pair = CNATFWCandidatePair::NewLC(
+ *localCand, *newRemoteCand );
+ pair->SetSelected( aRemoteFavored );
+ HandleTriggeredCheckL( *pair );
+
+ CleanupStack::PopAndDestroy( pair );
+ CleanupStack::PopAndDestroy( newRemoteCand );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::RelayUsedForSelectedPairL
+// ---------------------------------------------------------------------------
+//
+TBool CIceCheckList::RelayUsedForSelectedPairL() const
+ {
+ __ICEDP( "CIceCheckList::RelayUsedForSelectedPairL" )
+
+ TInt numOfComponents( iComponentIds.Count() );
+ __ASSERT_ALWAYS( numOfComponents, User::Leave( KErrNotReady ) );
+
+ TBool relayUseDetected( EFalse );
+ for ( TInt i( 0 ); i < numOfComponents; ++i )
+ {
+ const CNATFWCandidatePair* pair
+ = iValidList->SelectedPair( iComponentIds[i] );
+
+ if ( !relayUseDetected && pair
+ && CNATFWCandidate::ERelay == pair->LocalCandidate().Type() )
+ {
+ relayUseDetected = ETrue;
+ }
+ }
+
+ return relayUseDetected;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::RecomputePairPriorities
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::RecomputePairPriorities()
+ {
+ __ICEDP( "CIceCheckList::RecomputePairPriorities" )
+
+ iCheckPrioritizer->PrioritizeChecks( iChecks, iSessionData.Role() );
+
+ iChecks.Sort( CIceConnectivityCheck::ComparePriorities );
+ }
+
+
+// Derived function
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::CheckCompletedL
+// From class MIceConnCheckListener.
+// Once a successful check has completed for the first component, the other
+// components of the same type and local preference will get performed.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::CheckCompletedL(
+ TInt aCompletionCode,
+ const CIceConnectivityCheck& aCheck,
+ CNATFWCandidatePair* aValidatedPair )
+ {
+ __ICEDP_INT1( "CIceCheckList::CheckCompletedL, COMPLETION_CODE:",
+ aCompletionCode )
+
+ CleanupStack::PushL( aValidatedPair );
+
+ if ( KErrNone == aCompletionCode )
+ {
+ __ASSERT_DEBUG( aValidatedPair, User::Leave( KErrArgument ) );
+
+ // Priorities of local and remote candidates of validated pair must
+ // be calculated before coming here.
+ iCheckPrioritizer->PrioritizePair(
+ *aValidatedPair, iSessionData.Role() );
+ iValidList->AddValidPairL( *aValidatedPair );
+
+ if ( CNATFWCandidate::EPeerReflexive
+ == aValidatedPair->LocalCandidate().Type() )
+ {
+ iSessionData.AddPeerReflexiveCandidateL(
+ CNATFWCandidate::NewL( aValidatedPair->LocalCandidate() ),
+ EFalse );
+ }
+
+ // Unfreeze other checks having same foundation ICE-17, 7.1.2.2.3
+ InitializeCheckListL( aCheck.CandidatePair().Foundation() );
+
+ TBool validPairsExistForComponents(
+ iValidList->HasPairForComponents( iComponentIds ) );
+ if ( validPairsExistForComponents )
+ {
+ // Start checks in other check lists for candidates of same type
+ iClient.ComponentsHaveValidPairsL( *this,
+ aCheck.CandidatePair().Foundation() );
+ }
+
+ if ( ( validPairsExistForComponents ) &&
+ ( EIceRoleControlling == iSessionData.Role() ) &&
+ ( !NominationExecuted() ) )
+ {
+ // stopping criteria is minimal latency; nominate pairs when we
+ // have some valid pair for each component
+ NominateCandidatePairsL();
+ }
+ }
+ else if ( KErrRoleConflict == aCompletionCode )
+ {
+ // ICE-17, section 7.1.2.1. Failure cases.
+ // Candidate pair whose check has generated 487 role conflict is
+ // enqueued to the triggered check queue.
+ TUint priority = PriorityForPeerReflCandL(
+ aCheck.CandidatePair().LocalCandidate() );
+
+ EnqueueCheckL( const_cast<CIceConnectivityCheck&>( aCheck ),
+ CIceConnectivityCheck::EIceCheckTypeTriggered,
+ priority );
+
+ TNATFWIceRole currentRole = iSessionData.Role();
+ TNATFWIceRole desiredRole = ( EIceRoleControlling == currentRole )
+ ? EIceRoleControlled : EIceRoleControlling;
+ iClient.RoleChangeNeeded( desiredRole );
+ }
+ else
+ {
+ // unrecoverable failure
+ }
+
+ CleanupStack::PopAndDestroy( aValidatedPair );
+
+ DoLosingPairProcessingL( iSelectedPairs );
+
+ // ICE-17, 7.1.2.3. Check List and Timer State Updates
+ UpdateCheckListStateL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::NominationCompletedL
+// From class MIceConnCheckListener.
+// ICE-15, 7.1.2.2.4. Updating the Nominated Flag
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::NominationCompletedL(
+ TInt aCompletionCode,
+ const CIceConnectivityCheck& /*aCheck*/,
+ const CNATFWCandidatePair& aValidatedPair )
+ {
+ __ICEDP( "CIceCheckList::NominationCompletedL" )
+
+ if ( KErrNone == aCompletionCode )
+ {
+ iValidList->SetPairNominatedL( aValidatedPair );
+ }
+
+ // ICE-17, 7.1.2.3. Check List and Timer State Updates
+ UpdateCheckListStateL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::HandleTriggeredCheckL
+// ICE-17 7.2.1.4. Triggered Checks
+// STUN server has set PRIORITY & USE-CANDIDATE -attributes to the remote
+// candidate.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::HandleTriggeredCheckL(
+ const CNATFWCandidatePair& aPair )
+ {
+ __ICEDP( "CIceCheckList::HandleTriggeredCheckL" )
+
+ TUint trCheckPriority
+ = PriorityForPeerReflCandL( aPair.LocalCandidate() );
+
+ TInt ind = FindCheck( aPair );
+
+ if ( KErrNotFound != ind )
+ {
+ // We have corresponding check already in checklist
+ CIceConnectivityCheck& check = *iChecks[ind];
+ check.SetRemoteCheckInfo(
+ aPair.RemoteCandidate().Priority(),
+ aPair.Selected() );
+
+ CIceConnectivityCheck::TIceCheckState state = check.State();
+ if ( CIceConnectivityCheck::EIceCheckWaiting & state
+ || CIceConnectivityCheck::EIceCheckFrozen & state )
+ {
+ EnqueueCheckL( check,
+ CIceConnectivityCheck::EIceCheckTypeTriggered,
+ trCheckPriority );
+ }
+ else if ( CIceConnectivityCheck::EIceCheckInProgress & state )
+ {
+ __ICEDP( "CIceCheckList::HandleTriggeredCheckL, INPROGRESS" )
+ // Nomination check should always succeed, so do not cancel it.
+ // With ordinary checks ICE specification is followed.
+ if ( !check.Nominated() )
+ {
+ check.Cancel();
+ EnqueueCheckL( check,
+ CIceConnectivityCheck::EIceCheckTypeTriggered,
+ trCheckPriority );
+ }
+ }
+ else if ( CIceConnectivityCheck::EIceCheckFailed & state )
+ {
+ EnqueueCheckL( check,
+ CIceConnectivityCheck::EIceCheckTypeTriggered,
+ trCheckPriority );
+ }
+ else if ( CIceConnectivityCheck::EIceCheckSucceed & state )
+ {
+ if ( aPair.Selected() )
+ {
+ // ICE-17, 7.2.1.5, Updating the Nominated Flag
+ const_cast<CNATFWCandidatePair&>
+ ( check.CandidatePair() ).SetSelected( ETrue );
+ // Set validated pair learned from this check as selected
+ const CNATFWCandidatePair* validatedPair
+ = check.ValidatedPair();
+ __ASSERT_DEBUG( NULL != validatedPair,
+ User::Leave( KErrNotReady ) );
+
+ iValidList->SetPairNominatedL( *validatedPair );
+
+ UpdateCheckListStateL();
+ }
+ }
+ else
+ {
+ __ICEDP( "CIceCheckList::HandleTriggeredCheckL, ASSERT" )
+ ASSERT( EFalse );
+ }
+ }
+ else
+ {
+ // We have learned peer reflexive remote candidate
+ CIceConnectivityCheck* trCheck = CIceConnectivityCheck::NewLC(
+ *this, aPair.LocalCandidate(), aPair.RemoteCandidate(),
+ iConnHandler, iSessionData );
+ iCheckPrioritizer->PrioritizeCheck( *trCheck,
+ iSessionData.Role() );
+ iChecks.InsertInOrderL( trCheck,
+ CIceConnectivityCheck::ComparePriorities );
+ CleanupStack::Pop( trCheck );
+
+ // remote priority used due to ICE-17, 7.1.2.2.2
+ trCheck->SetRemoteCheckInfo(
+ aPair.RemoteCandidate().Priority(), aPair.Selected() );
+
+ EnqueueCheckL( *trCheck,
+ CIceConnectivityCheck::EIceCheckTypeTriggered,
+ trCheckPriority );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::UpdateCheckListStateL
+// Check list state is updated due to check completion or pair nomination.
+// Refer to ICE-17 7.1.2.3. Check List and Timer State Updates and
+// ICE-15 8.2. Updating States.
+// Change state to completed if controlling client has selected candidate
+// pair for every component of the media stream. If all checks for any
+// media component has failed, ICE processing is stopped for a media stream.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::UpdateCheckListStateL()
+ {
+ __ICEDP( "CIceCheckList::UpdateCheckListStateL" )
+
+ if ( EIceCheckListRunning == State() )
+ {
+ TInt numOfComponents( iComponentIds.Count() );
+ __ASSERT_DEBUG( numOfComponents, User::Leave( KErrNotReady ) );
+
+ for ( TInt i( 0 ); i < numOfComponents; ++i )
+ {
+ // ICE-15, 8.2. If some component has completed, remove pending
+ // checks for that component.
+ RemovePendingChecks( iComponentIds[i] );
+ }
+
+ if ( iValidList->NominatedPairsExist( iComponentIds ) )
+ {
+ // when check list completes, frozen check lists are unfreezed
+ SetStateL( EIceCheckListCompleted );
+ }
+ else
+ {
+ // If all checks are completed and there is not valid pair for
+ // each media component, check list has failed. ICE-17, 7.1.2.3.
+ TInt activeStates = (
+ CIceConnectivityCheck::EIceCheckWaiting |
+ CIceConnectivityCheck::EIceCheckInProgress |
+ CIceConnectivityCheck::EIceCheckFrozen );
+
+ if ( KErrNotFound == FindCheckInState( activeStates )
+ && !iValidList->HasPairForComponents( iComponentIds ) )
+ {
+ // when check list completes, frozen check lists are unfreezed
+ SetStateL( EIceCheckListFailed );
+ }
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::RemovePendingChecks
+// ICE-17, 8.1.2 Updating States
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::RemovePendingChecks( TUint aComponentId )
+ {
+ const CNATFWCandidatePair* nominatedPair
+ = iValidList->SelectedPair( aComponentId );
+ if ( nominatedPair )
+ {
+ TInt stateMask = (
+ CIceConnectivityCheck::EIceCheckWaiting |
+ CIceConnectivityCheck::EIceCheckFrozen );
+
+ TInt ind = FindCheckInState( stateMask, aComponentId );
+ while ( KErrNotFound != ind )
+ {
+ iChecks.Remove( ind );
+ ind = FindCheckInState( stateMask, aComponentId );
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::GetComponentIdsL
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::GetComponentIdsL( RArray<TUint>& aComponentIds ) const
+ {
+ __ICEDP( "CIceCheckList::GetComponentIdsL" )
+
+ aComponentIds.Reset();
+ TInt count( iChecks.Count() );
+ for ( TInt i( 0 ); i < count; ++i )
+ {
+ TUint curCompId
+ = iChecks[i]->CandidatePair().LocalCandidate().ComponentId();
+ if ( KErrNotFound == aComponentIds.Find( curCompId ) )
+ {
+ aComponentIds.AppendL( curCompId );
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::FindCheckInState
+// ---------------------------------------------------------------------------
+//
+TInt CIceCheckList::FindCheckInState( TInt aStateMask )
+ {
+ TInt count( iChecks.Count() );
+ __ICEDP_INT1( "CIceCheckList::FindCheckInState1:", count )
+
+ for ( TInt i( 0 ); i < count; ++i )
+ {
+ CIceConnectivityCheck& check( *iChecks[i] );
+ if ( aStateMask & check.State() )
+ {
+ return i;
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::FindCheckInState
+// ---------------------------------------------------------------------------
+//
+TInt CIceCheckList::FindCheckInState( TInt aStateMask, TUint aComponentId )
+ {
+ TInt count( iChecks.Count() );
+ for ( TInt i( 0 ); i < count; ++i )
+ {
+ CIceConnectivityCheck& check( *iChecks[i] );
+ if ( ( aStateMask & check.State() )
+ && check.ComponentId() == aComponentId )
+ {
+ return i;
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::FindCheckInState
+// ---------------------------------------------------------------------------
+//
+TInt CIceCheckList::FindCheckInState( TInt aStateMask,
+ const TInetAddr& aRemoteAddr )
+ {
+ TInt count( iChecks.Count() );
+ for ( TInt i( 0 ); i < count; ++i )
+ {
+ CIceConnectivityCheck& check( *iChecks[i] );
+ const TInetAddr& remoteAddr
+ = check.CandidatePair().RemoteCandidate().TransportAddr();
+ if ( ( aStateMask & check.State() )
+ && TIceUtils::MatchAddresses( remoteAddr, aRemoteAddr ) )
+ {
+ return i;
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::FindCheck
+// ---------------------------------------------------------------------------
+//
+TInt CIceCheckList::FindCheck( const CNATFWCandidatePair& aPair )
+ {
+ for ( TInt i( iChecks.Count() - 1 ); 0 <= i; --i )
+ {
+ TBool match = CNATFWCandidatePair::MatchAddresses(
+ iChecks[i]->CandidatePair(), aPair );
+ if ( match )
+ {
+ return i;
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::SetStateL
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::SetStateL( TIceCheckListState aNewState )
+ {
+ __ICEDP( "CIceCheckList::SetStateL" )
+
+ __ASSERT_ALWAYS( iState != aNewState, User::Leave( KErrArgument ) );
+ iState = aNewState;
+ iCheckQue.Reset();
+
+ if ( EIceCheckListCompleted == aNewState )
+ {
+ iTimer->Cancel();
+ iSelectedPairs.ResetAndDestroy();
+
+ TInt numOfComponents( iComponentIds.Count() );
+ RPointerArray<CNATFWCandidatePair> selectedPairs;
+ CleanupResetAndDestroyPushL( selectedPairs );
+ for ( TInt i( 0 ); i < numOfComponents; ++i )
+ {
+ CNATFWCandidatePair* newPair = CNATFWCandidatePair::NewLC(
+ *iValidList->SelectedPair( iComponentIds[i] ) );
+ selectedPairs.AppendL( newPair );
+ CleanupStack::Pop( newPair );
+ }
+
+ iClient.ChecklistCompletedL( *this, selectedPairs );
+
+ selectedPairs.Close();
+ CleanupStack::Pop( &selectedPairs );
+ }
+ else if ( EIceCheckListRunning == aNewState )
+ {
+ if ( !iTimer->IsActive() )
+ {
+ TCallBack callBack( CIceCheckList::TimerFired, this );
+ iTimer->Start( 0, iInterval, callBack );
+ }
+ }
+ else if ( EIceCheckListFailed == aNewState )
+ {
+ iTimer->Cancel();
+ iSelectedPairs.ResetAndDestroy();
+
+ RArray<TUint> failedStreams;
+ CleanupClosePushL( failedStreams );
+ TInt stateMask = (
+ CIceConnectivityCheck::EIceCheckWaiting |
+ CIceConnectivityCheck::EIceCheckInProgress |
+ CIceConnectivityCheck::EIceCheckSucceed |
+ CIceConnectivityCheck::EIceCheckFailed |
+ CIceConnectivityCheck::EIceCheckFrozen );
+
+ TInt numOfComponents( iComponentIds.Count() );
+ for ( TInt i( 0 ); i < numOfComponents; ++i )
+ {
+ if ( KErrNotFound != FindCheckInState(
+ stateMask, iComponentIds[i] ) )
+ {
+ failedStreams.AppendL( iChecks[i]->StreamId() );
+ }
+ }
+
+ iClient.ChecklistCompletedL(
+ *this, failedStreams, KErrCouldNotConnect );
+ CleanupStack::PopAndDestroy( &failedStreams );
+ }
+ else
+ {
+ __ICEDP( "CIceCheckList::SetStateL, ELSE" )
+ User::Leave( KErrArgument );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::DoLosingPairProcessingL
+// ICE-17, 9.2.2.3.
+// ICE SHOULD be restarted if some peer selected pair has failed.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::DoLosingPairProcessingL(
+ const RPointerArray<CNATFWCandidatePair>& aSelectedPairs )
+ {
+ __ICEDP( "CIceCheckList::DoLosingPairProcessingL" )
+
+ // find out losing pairs
+ RPointerArray<CNATFWCandidatePair> losingPairs;
+ CleanupResetAndDestroyPushL( losingPairs );
+ for ( TInt i( aSelectedPairs.Count() - 1 ); 0 <= i ; --i )
+ {
+ const CNATFWCandidatePair& pair( *aSelectedPairs[i] );
+ if ( iValidList->HasPair( pair ) )
+ {
+ iValidList->SetPairNominatedL( pair );
+ }
+ else
+ {
+ CNATFWCandidatePair* losingPair
+ = CNATFWCandidatePair::NewLC( pair );
+ losingPairs.AppendL( losingPair );
+ CleanupStack::Pop( losingPair );
+ }
+ }
+
+ /* If none of peer selected pairs is in-progress and at least one
+ is failed, check list is completed unsuccessfully. If some selected
+ pair is in-progress, we wait for check completion and do this
+ processing again. */
+ TBool inProgressCheckFound( EFalse );
+ TBool failedCheckFound( EFalse );
+ TInt losingPairInd( losingPairs.Count() - 1 );
+ while ( ( 0 <= losingPairInd ) && ( !inProgressCheckFound ) )
+ {
+ TInetAddr remoteAddr(
+ losingPairs[losingPairInd]->RemoteCandidate().TransportAddr() );
+
+ TInt inProgressCheckInd = FindCheckInState(
+ CIceConnectivityCheck::EIceCheckInProgress, remoteAddr );
+ if ( KErrNotFound == inProgressCheckInd )
+ {
+ TInt failedCheckInd = FindCheckInState(
+ CIceConnectivityCheck::EIceCheckFailed, remoteAddr );
+ if ( KErrNotFound != failedCheckInd )
+ {
+ failedCheckFound = ETrue;
+ }
+ }
+ else
+ {
+ inProgressCheckFound = ETrue;
+ }
+
+ losingPairInd--;
+ }
+
+ if ( failedCheckFound )
+ {
+ SetStateL( EIceCheckListFailed );
+ }
+
+ CleanupStack::PopAndDestroy( &losingPairs );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::NominateCandidatePairsL
+// Resends connectivity checks to select pair for each media component.
+// ICE-17, section 8.1.1.1, regular nomination is used.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::NominateCandidatePairsL()
+ {
+ __ICEDP( "CIceCheckList::NominateCandidatePairsL" )
+
+ TInt numOfComponents( iComponentIds.Count() );
+ for ( TInt i( 0 ); i < numOfComponents; ++i )
+ {
+ const CNATFWCandidatePair* pair
+ = iValidList->HighestPriorityPair( iComponentIds[i] );
+ ASSERT( NULL != pair );
+ const TInetAddr& lAddr( pair->LocalCandidate().TransportAddr() );
+ const TInetAddr& rAddr( pair->RemoteCandidate().TransportAddr() );
+
+ TInt index( iChecks.Count() );
+ TBool checkFound( EFalse );
+ while ( !checkFound && --index >= 0 )
+ {
+ const CNATFWCandidatePair* validatedPair
+ = iChecks[index]->ValidatedPair();
+ if ( validatedPair )
+ {
+ const TInetAddr& lAddrOfCheck
+ = validatedPair->LocalCandidate().TransportAddr();
+ const TInetAddr& rAddrOfCheck
+ = validatedPair->RemoteCandidate().TransportAddr();
+
+ checkFound =
+ ( TIceUtils::MatchAddresses( lAddrOfCheck, lAddr ) &&
+ TIceUtils::MatchAddresses( rAddrOfCheck, rAddr ) );
+ }
+ }
+
+ User::LeaveIfError( index );
+ EnqueueCheckL( *iChecks[index],
+ CIceConnectivityCheck::EIceCheckTypeNomination, 0 );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::CheckListFrozen
+// ---------------------------------------------------------------------------
+//
+TBool CIceCheckList::CheckListFrozen()
+ {
+ __ICEDP( "CIceCheckList::CheckListFrozen" )
+
+ TInt ind( iChecks.Count() );
+ while ( ind-- )
+ {
+ if ( CIceConnectivityCheck::EIceCheckFrozen != iChecks[ind]->State() )
+ {
+ return EFalse;
+ }
+ }
+
+ return ETrue;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::EnqueueCheckL
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::EnqueueCheckL( CIceConnectivityCheck& aCheck,
+ CIceConnectivityCheck::TIceCheckType aType,
+ TUint aLocalPriority )
+ {
+ TIceCheckQueItem item( aCheck, aType, aLocalPriority );
+
+ TInt index = iCheckQue.Find( item, TIceCheckQueItem::MatchCheck );
+ if ( CIceConnectivityCheck::EIceCheckTypeNomination == aType
+ && KErrNotFound != index )
+ {
+ // nomination check is privileged over triggered one
+ __ICEDP( "CIceCheckList::EnqueueCheckL, REMOVE TRIGGERED CHECK" )
+ iCheckQue.Remove( index );
+ }
+
+ // do not allow duplicate entries
+ if ( KErrNotFound == iCheckQue.Find(
+ item, TIceCheckQueItem::MatchCheck ) )
+ {
+ __ICEDP( "CIceCheckList::EnqueueCheckL, APPENDING" )
+ iCheckQue.AppendL( item );
+
+ if ( !iTimer->IsActive() )
+ {
+ TCallBack callBack( CIceCheckList::TimerFired, this );
+ iTimer->Start( 0, iInterval, callBack );
+ }
+ }
+ else
+ {
+ __ICEDP( "CIceCheckList::EnqueueCheckL, DUPLICATE ENTRY" )
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::DequeueCheckL
+// ---------------------------------------------------------------------------
+//
+TBool CIceCheckList::DequeueCheckL()
+ {
+ __ICEDP_INT1( "CIceCheckList::DequeueCheckL, COUNT:", iCheckQue.Count() )
+
+ if ( 0 != iCheckQue.Count() )
+ {
+ TIceCheckQueItem item = iCheckQue[0];
+ iCheckQue.Remove( 0 );
+
+ CIceConnectivityCheck& check = item.Check();
+ if ( CIceConnectivityCheck::EIceCheckTypeNomination == item.Type() )
+ {
+ check.PerformNominationL( RetransmissionTimeOut() );
+ }
+ else
+ {
+ CIceConnectivityCheck::TIceCheckState state = check.State();
+ // save bandwidth if previous transaction already succeeded
+ if ( CIceConnectivityCheck::EIceCheckSucceed != state )
+ {
+ check.Initialize();
+ check.PerformConnCheckL(
+ CIceConnectivityCheck::EIceCheckTypeTriggered,
+ item.Priority(), RetransmissionTimeOut() );
+ }
+ }
+
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::RetransmissionTimeOut
+// ICE-17, section 16. RTO = MAX (100ms, Ta*N * (Num-Waiting))
+// ---------------------------------------------------------------------------
+//
+TUint CIceCheckList::RetransmissionTimeOut() const
+ {
+ TInt numOfWaitingPairs( 0 );
+
+ TInt numOfChecks( iChecks.Count() );
+ for ( TInt i( 0 ); i < numOfChecks; ++i )
+ {
+ CIceConnectivityCheck& check( *iChecks[i] );
+ if ( CIceConnectivityCheck::EIceCheckWaiting == check.State() )
+ {
+ numOfWaitingPairs++;
+ }
+ }
+
+ const TInt KMinimumRto( 100 );
+ return TUint( Max( KMinimumRto, iInterval.Int() * numOfWaitingPairs ) );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::FoundationsForCollectionL
+// ---------------------------------------------------------------------------
+//
+CDesC8ArrayFlat* CIceCheckList::FoundationsForCollectionL(
+ TUint aStreamCollectionId ) const
+ {
+ const TInt KGranularity(4);
+ CDesC8ArrayFlat* descArray = new (ELeave) CDesC8ArrayFlat( KGranularity );
+ CleanupStack::PushL( descArray );
+
+ TInt numOfChecks( iChecks.Count() );
+ for ( TInt i(0); i < numOfChecks; ++i )
+ {
+ CIceConnectivityCheck& check( *iChecks[i] );
+ if ( check.StreamCollectionId() == aStreamCollectionId )
+ {
+ TInt matchItemInd(0);
+ const TDesC8& foundation(
+ iChecks[i]->CandidatePair().Foundation() );
+ if ( 0 != descArray->Find( foundation, matchItemInd ) )
+ {
+ descArray->AppendL( foundation );
+ }
+ }
+ }
+
+ CleanupStack::Pop( descArray );
+ return descArray;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::LowestComponentId
+// ---------------------------------------------------------------------------
+//
+TUint CIceCheckList::LowestComponentId( RArray<TUint>& aComponentIds ) const
+ {
+ TInt componentIdCount( aComponentIds.Count() );
+ ASSERT( 0 != componentIdCount );
+
+ TUint lowestComponentId( aComponentIds[0] );
+ for ( TInt i(1); i < componentIdCount; ++i )
+ {
+ if ( aComponentIds[i] < lowestComponentId )
+ {
+ lowestComponentId = aComponentIds[i];
+ }
+ }
+
+ return lowestComponentId;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::NominationExecuted
+// ---------------------------------------------------------------------------
+//
+TBool CIceCheckList::NominationExecuted() const
+ {
+ TInt numOfChecks( iChecks.Count() );
+ for ( TInt i(0); i < numOfChecks; ++i )
+ {
+ CIceConnectivityCheck& check( *iChecks[i] );
+ if ( check.Nominated() )
+ {
+ return ETrue;
+ }
+ }
+
+ return EFalse;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CIceCheckList::InitializeCheckList
+// Special initialization due to ICE-17, 9.3.1.4 ICE Continuing for Existing
+// Media Stream.
+// ---------------------------------------------------------------------------
+//
+void CIceCheckList::InitializeCheckList( const TDesC8& aFoundation,
+ TInt aExcludedComponentId )
+ {
+ __ICEDP( "CIceCheckList::InitializeCheckList" )
+ ASSERT( 0 != iChecks.Count() );
+
+ for ( TInt i( iChecks.Count() - 1 ); i >= 0; --i )
+ {
+ if ( CIceConnectivityCheck::EIceCheckFrozen == iChecks[i]->State()
+ && iChecks[i]->CandidatePair().Foundation() == aFoundation
+ && iChecks[i]->ComponentId() != aExcludedComponentId )
+ {
+ iChecks[i]->Initialize();
+ }
+ }
+ }