|
1 /* |
|
2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 #include "natfwcandidate.h" |
|
22 #include "natfwcandidatepair.h" |
|
23 #include "cicechecklist.h" |
|
24 #include "cicecheckprioritizer.h" |
|
25 #include "cicecandidateprioritizer.h" |
|
26 #include "ciceconnectivitycheck.h" |
|
27 #include "cicesessiondata.h" |
|
28 #include "micechecklistobserver.h" |
|
29 #include "cicevalidlist.h" |
|
30 #include "icecandidatehandlerdefs.h" |
|
31 #include "icecandidatehandlerlogs.h" |
|
32 |
|
33 const TUint KComponentIdRtp = 1; |
|
34 |
|
35 // ======== MEMBER FUNCTIONS ======== |
|
36 |
|
37 CIceCheckList::CIceCheckList( |
|
38 MIceChecklistObserver& aClient, |
|
39 TUint aStreamCollectionId, |
|
40 CIceSessionData& aSessionData, |
|
41 CIceConnectionHandler& aConnHandler ) |
|
42 : |
|
43 iStreamCollectionId( aStreamCollectionId ), |
|
44 iClient( aClient ), |
|
45 iSessionData( aSessionData ), |
|
46 iConnHandler( aConnHandler ) |
|
47 { |
|
48 } |
|
49 |
|
50 |
|
51 void CIceCheckList::ConstructL() |
|
52 { |
|
53 iCheckPrioritizer = CIceCheckPrioritizer::NewL(); |
|
54 iCandPrioritizer = CIceCandidatePrioritizer::NewL( |
|
55 iSessionData.Domain() ); |
|
56 iTimer = CPeriodic::NewL( CActive::EPriorityStandard ); |
|
57 iValidList = CIceValidList::NewL( iStreamCollectionId ); |
|
58 GenerateCheckListL( iChecks ); |
|
59 } |
|
60 |
|
61 |
|
62 CIceCheckList* CIceCheckList::NewL( |
|
63 MIceChecklistObserver& aClient, |
|
64 TUint aStreamCollectionId, |
|
65 CIceSessionData& aSessionData, |
|
66 CIceConnectionHandler& aConnHandler ) |
|
67 { |
|
68 CIceCheckList* self |
|
69 = CIceCheckList::NewLC( aClient, aStreamCollectionId, |
|
70 aSessionData, aConnHandler ); |
|
71 CleanupStack::Pop( self ); |
|
72 return self; |
|
73 } |
|
74 |
|
75 |
|
76 CIceCheckList* CIceCheckList::NewLC( |
|
77 MIceChecklistObserver& aClient, |
|
78 TUint aStreamCollectionId, |
|
79 CIceSessionData& aSessionData, |
|
80 CIceConnectionHandler& aConnHandler ) |
|
81 { |
|
82 CIceCheckList* self |
|
83 = new( ELeave ) CIceCheckList( |
|
84 aClient, aStreamCollectionId, aSessionData, aConnHandler ); |
|
85 CleanupStack::PushL( self ); |
|
86 self->ConstructL(); |
|
87 return self; |
|
88 } |
|
89 |
|
90 |
|
91 CIceCheckList::~CIceCheckList() |
|
92 { |
|
93 __ICEDP( "CIceCheckList::~CIceCheckList" ) |
|
94 |
|
95 iChecks.ResetAndDestroy(); |
|
96 iCheckQue.Close(); |
|
97 delete iCheckPrioritizer; |
|
98 delete iCandPrioritizer; |
|
99 delete iTimer; |
|
100 delete iValidList; |
|
101 iComponentIds.Close(); |
|
102 iSelectedPairs.ResetAndDestroy(); |
|
103 } |
|
104 |
|
105 |
|
106 // --------------------------------------------------------------------------- |
|
107 // CIceCheckList::TimerFired |
|
108 // --------------------------------------------------------------------------- |
|
109 // |
|
110 TInt CIceCheckList::TimerFired( TAny* aObject ) |
|
111 { |
|
112 if ( aObject ) |
|
113 { |
|
114 CIceCheckList* list = reinterpret_cast<CIceCheckList*>( aObject ); |
|
115 TRAPD( error, list->OnTimerFiredL() ) |
|
116 if ( error ) |
|
117 { |
|
118 __ICEDP_INT1( "CIceCheckList::TimerFired, ERR:", error ) |
|
119 if ( KErrNoMemory == error ) |
|
120 { |
|
121 TRAP_IGNORE( list->SetStateL( EIceCheckListFailed ) ) |
|
122 } |
|
123 else |
|
124 { |
|
125 ASSERT( EFalse ); |
|
126 } |
|
127 } |
|
128 |
|
129 return 1; |
|
130 } |
|
131 else |
|
132 { |
|
133 __ICEDP( "CIceCheckList::TimerFired, ELSE" ) |
|
134 ASSERT( EFalse ); |
|
135 return 0; // lint #527 |
|
136 } |
|
137 } |
|
138 |
|
139 |
|
140 // Non-derived function |
|
141 |
|
142 // --------------------------------------------------------------------------- |
|
143 // CIceCheckList::State |
|
144 // --------------------------------------------------------------------------- |
|
145 // |
|
146 CIceCheckList::TIceCheckListState CIceCheckList::State() const |
|
147 { |
|
148 return iState; |
|
149 } |
|
150 |
|
151 |
|
152 // --------------------------------------------------------------------------- |
|
153 // CIceCheckList::StreamCollectionId() |
|
154 // --------------------------------------------------------------------------- |
|
155 // |
|
156 TUint CIceCheckList::StreamCollectionId() const |
|
157 { |
|
158 return iStreamCollectionId; |
|
159 } |
|
160 |
|
161 |
|
162 // --------------------------------------------------------------------------- |
|
163 // CIceCheckList::InitializeCheckListL() |
|
164 // Used to initialize check list corresponding first SDP mediastream. |
|
165 // ICE-17, section 5.7.4. |
|
166 // --------------------------------------------------------------------------- |
|
167 // |
|
168 void CIceCheckList::InitializeCheckListL() |
|
169 { |
|
170 __ICEDP( "CIceCheckList::InitializeCheckListL" ) |
|
171 __ASSERT_DEBUG( iChecks.Count(), User::Leave( KErrNotReady ) ); |
|
172 |
|
173 TUint lowestComponentId = LowestComponentId( iComponentIds ); |
|
174 |
|
175 CDesC8ArrayFlat* foundations |
|
176 = FoundationsForCollectionL( iStreamCollectionId ); |
|
177 |
|
178 TInt foundationCount( foundations->Count() ); |
|
179 for ( TInt i(0); i < foundationCount; ++i ) |
|
180 { |
|
181 // inside foundation group set lowest component id waiting |
|
182 TInt checkIndex( iChecks.Count() ); |
|
183 TBool checkInitialized( EFalse ); |
|
184 |
|
185 while ( ( checkIndex-- ) && ( !checkInitialized ) ) |
|
186 { |
|
187 CIceConnectivityCheck& check( *iChecks[checkIndex] ); |
|
188 if ( check.CandidatePair().Foundation() |
|
189 == foundations->MdcaPoint(i) |
|
190 && check.ComponentId() == lowestComponentId ) |
|
191 { |
|
192 check.Initialize(); |
|
193 checkInitialized = ETrue; |
|
194 } |
|
195 } |
|
196 } |
|
197 |
|
198 delete foundations; |
|
199 } |
|
200 |
|
201 |
|
202 // --------------------------------------------------------------------------- |
|
203 // CIceCheckList::InitializeCheckListL |
|
204 // ICE-17, 7.1.2.2.3, Updating Pair States. |
|
205 // --------------------------------------------------------------------------- |
|
206 // |
|
207 void CIceCheckList::InitializeCheckListL( const TDesC8& aFoundation ) |
|
208 { |
|
209 __ICEDP( "CIceCheckList::InitializeCheckListL" ) |
|
210 __ASSERT_DEBUG( iChecks.Count(), User::Leave( KErrNotReady ) ); |
|
211 |
|
212 TBool initComplete( EFalse ); |
|
213 TInt count( iChecks.Count() ); |
|
214 for ( TInt i = 0; i < count; ++i ) |
|
215 { |
|
216 if ( CIceConnectivityCheck::EIceCheckFrozen == iChecks[i]->State() |
|
217 && iChecks[i]->CandidatePair().Foundation() == aFoundation ) |
|
218 { |
|
219 iChecks[i]->Initialize(); |
|
220 initComplete = ETrue; |
|
221 } |
|
222 } |
|
223 |
|
224 if ( !initComplete && CheckListFrozen() ) |
|
225 { |
|
226 InitializeCheckListL(); |
|
227 } |
|
228 } |
|
229 |
|
230 |
|
231 // --------------------------------------------------------------------------- |
|
232 // CIceCheckList::StartPerformChecksL() |
|
233 // --------------------------------------------------------------------------- |
|
234 // |
|
235 void CIceCheckList::StartPerformChecksL( |
|
236 const TTimeIntervalMicroSeconds32& anInterval ) |
|
237 { |
|
238 __ICEDP( "CIceCheckList::StartPerformChecksL" ) |
|
239 |
|
240 iInterval = anInterval; |
|
241 SetStateL( EIceCheckListRunning ); |
|
242 } |
|
243 |
|
244 |
|
245 // --------------------------------------------------------------------------- |
|
246 // CIceCheckList::RestartCheckListL() |
|
247 // --------------------------------------------------------------------------- |
|
248 // |
|
249 void CIceCheckList::RestartCheckListL( |
|
250 const TTimeIntervalMicroSeconds32& anInterval ) |
|
251 { |
|
252 __ICEDP( "CIceCheckList::RestartCheckListL" ) |
|
253 __ASSERT_ALWAYS( EIceCheckListCompleted == State(), |
|
254 User::Leave( KErrNotReady ) ); |
|
255 |
|
256 iValidList->FlushValidList(); |
|
257 iChecks.ResetAndDestroy(); |
|
258 GenerateCheckListL( iChecks ); |
|
259 |
|
260 iInterval = anInterval; |
|
261 SetStateL( EIceCheckListRunning ); |
|
262 } |
|
263 |
|
264 |
|
265 // --------------------------------------------------------------------------- |
|
266 // CIceCheckList::UpdateCheckListL() |
|
267 // Controlling peer has selected candidate pairs to be used. |
|
268 // ICE-17, 9.2.2.3. Existing Media Streams and remote-candidates. |
|
269 // --------------------------------------------------------------------------- |
|
270 // |
|
271 void CIceCheckList::UpdateCheckListL( |
|
272 RPointerArray<CNATFWCandidatePair>& aPeerSelectedPairs ) |
|
273 { |
|
274 __ICEDP( "CIceCheckList::UpdateIceProcessingL" ) |
|
275 __ASSERT_DEBUG( EIceCheckListRunning == State(), |
|
276 User::Leave( KErrNotReady ) ); |
|
277 __ASSERT_ALWAYS( !iSelectedPairs.Count(), |
|
278 User::Leave( KErrAlreadyExists ) ); |
|
279 |
|
280 TInt numOfSelectedComps( aPeerSelectedPairs.Count() ); |
|
281 for ( TInt i( 0 ); i < numOfSelectedComps; ++i ) |
|
282 { |
|
283 CNATFWCandidatePair* pair |
|
284 = CNATFWCandidatePair::NewLC( *aPeerSelectedPairs[i] ); |
|
285 iSelectedPairs.AppendL( pair ); |
|
286 CleanupStack::Pop( pair ); |
|
287 } |
|
288 |
|
289 DoLosingPairProcessingL( iSelectedPairs ); |
|
290 UpdateCheckListStateL(); |
|
291 } |
|
292 |
|
293 |
|
294 // --------------------------------------------------------------------------- |
|
295 // CIceCheckList::UpdateCheckListL() |
|
296 // Peer has added new remote candidates to the session negotiation. |
|
297 // ICE-17, 9.3.1.4. ICE Continuing for Existing Media Stream. |
|
298 // --------------------------------------------------------------------------- |
|
299 // |
|
300 void CIceCheckList::UpdateCheckListL( |
|
301 RPointerArray<CNATFWCandidate>& /*aRemoteCands*/ ) |
|
302 { |
|
303 __ICEDP( "CIceCheckList::UpdateIceProcessingL" ) |
|
304 __ASSERT_DEBUG( EIceCheckListRunning == State(), |
|
305 User::Leave( KErrNotReady ) ); |
|
306 |
|
307 RPointerArray<CIceConnectivityCheck> newCheckList; |
|
308 CleanupResetAndDestroyPushL( newCheckList ); |
|
309 GenerateCheckListL( newCheckList ); |
|
310 |
|
311 // Add new checks to the checklist |
|
312 for ( TInt i( newCheckList.Count() - 1 ); i >= 0; --i ) |
|
313 { |
|
314 CIceConnectivityCheck* newCheck( newCheckList[i] ); |
|
315 |
|
316 TInt ind = iChecks.Find( |
|
317 newCheck, CIceConnectivityCheck::MatchAddresses ); |
|
318 |
|
319 // All new checks are in frozen state initially |
|
320 if ( KErrNotFound == ind ) |
|
321 { |
|
322 iChecks.InsertInOrderL( newCheck, |
|
323 CIceConnectivityCheck::ComparePriorities ); |
|
324 newCheckList.Remove( i ); |
|
325 } |
|
326 } |
|
327 |
|
328 TBool rtpComponentFound( EFalse ); |
|
329 TInt ind( iChecks.Count() - 1 ); |
|
330 while( ( !rtpComponentFound ) && ( 0 <= ind ) ) |
|
331 { |
|
332 if ( KComponentIdRtp == iChecks[ind]->ComponentId() |
|
333 && CIceConnectivityCheck::EIceCheckSucceed |
|
334 == iChecks[ind]->State() ) |
|
335 { |
|
336 rtpComponentFound = ETrue; |
|
337 InitializeCheckList( |
|
338 iChecks[ind]->CandidatePair().Foundation(), |
|
339 KComponentIdRtp ); |
|
340 |
|
341 if ( iValidList->HasPairForComponents( iComponentIds ) ) |
|
342 { |
|
343 // Start checks in other check lists for checks of same type |
|
344 iClient.ComponentsHaveValidPairsL( |
|
345 *this, iChecks[ind]->CandidatePair().Foundation() ); |
|
346 } |
|
347 } |
|
348 |
|
349 ind--; |
|
350 } |
|
351 |
|
352 CleanupStack::PopAndDestroy( &newCheckList ); |
|
353 } |
|
354 |
|
355 |
|
356 // --------------------------------------------------------------------------- |
|
357 // CIceCheckList::GenerateCheckListL() |
|
358 // --------------------------------------------------------------------------- |
|
359 // |
|
360 void CIceCheckList::GenerateCheckListL( |
|
361 RPointerArray<CIceConnectivityCheck>& aCheckList ) |
|
362 { |
|
363 __ICEDP( "CIceCheckList::GenerateCheckListL" ) |
|
364 |
|
365 RPointerArray<CNATFWCandidate> localCandidates; |
|
366 RPointerArray<CNATFWCandidate> remoteCandidates; |
|
367 CleanupClosePushL( localCandidates ); |
|
368 CleanupClosePushL( remoteCandidates ); |
|
369 |
|
370 iSessionData.GetLocalCandidates( |
|
371 iStreamCollectionId, |
|
372 localCandidates ); |
|
373 |
|
374 iSessionData.GetRemoteCandidatesL( |
|
375 iStreamCollectionId, |
|
376 remoteCandidates ); |
|
377 |
|
378 __ASSERT_ALWAYS( localCandidates.Count() && remoteCandidates.Count(), |
|
379 User::Leave( KErrNotReady ) ); |
|
380 |
|
381 PairCandidatesL( aCheckList, localCandidates, remoteCandidates ); |
|
382 CleanupStack::PopAndDestroy( &remoteCandidates ); |
|
383 CleanupStack::PopAndDestroy( &localCandidates ); |
|
384 |
|
385 iCheckPrioritizer->PrioritizeChecks( aCheckList, iSessionData.Role() ); |
|
386 aCheckList.Sort( CIceConnectivityCheck::ComparePriorities ); |
|
387 PruneChecksL( aCheckList ); |
|
388 |
|
389 #ifdef _DEBUG |
|
390 __ICEDP( "CIceCheckList::GenerateCheckListL, LIST AFTER PRUNING" ) |
|
391 TInt count( aCheckList.Count() ); |
|
392 for ( TInt i(0); i < count; ++i ) |
|
393 { |
|
394 __ICEDP_ADDRLOG( "LOCAL_ADDR", |
|
395 aCheckList[i]->CandidatePair().LocalCandidate().TransportAddr() ) |
|
396 |
|
397 __ICEDP_ADDRLOG( "PEER_ADDR", |
|
398 aCheckList[i]->CandidatePair().RemoteCandidate().TransportAddr() ) |
|
399 } |
|
400 #endif |
|
401 |
|
402 GetComponentIdsL( iComponentIds ); |
|
403 } |
|
404 |
|
405 |
|
406 // --------------------------------------------------------------------------- |
|
407 // CIceCheckList::PairCandidatesL |
|
408 // --------------------------------------------------------------------------- |
|
409 // |
|
410 void CIceCheckList::PairCandidatesL( |
|
411 RPointerArray<CIceConnectivityCheck>& aCheckList, |
|
412 RPointerArray<CNATFWCandidate>& aLocalCands, |
|
413 RPointerArray<CNATFWCandidate>& aRemoteCands ) |
|
414 { |
|
415 __ICEDP( "CIceCheckList::PairCandidatesL" ) |
|
416 |
|
417 CNATFWCandidate* lCand( NULL ); |
|
418 CNATFWCandidate* rCand( NULL ); |
|
419 |
|
420 TInt lInd = aLocalCands.Count(); |
|
421 while ( lInd-- ) |
|
422 { |
|
423 lCand = aLocalCands[lInd]; |
|
424 |
|
425 TInt rInd = aRemoteCands.Count(); |
|
426 while ( rInd-- ) |
|
427 { |
|
428 rCand = aRemoteCands[rInd]; |
|
429 |
|
430 if ( CompatibleCandidates( *lCand, *rCand ) ) |
|
431 { |
|
432 CIceConnectivityCheck* check |
|
433 = CIceConnectivityCheck::NewLC( *this, *lCand, *rCand, |
|
434 iConnHandler, iSessionData ); |
|
435 |
|
436 aCheckList.AppendL( check ); |
|
437 CleanupStack::Pop( check ); |
|
438 } |
|
439 } |
|
440 } |
|
441 } |
|
442 |
|
443 |
|
444 // --------------------------------------------------------------------------- |
|
445 // CIceCheckList::CompatibleCandidates |
|
446 // According to ICE-17, 5.7.1. and ICE-TCP-03, 4.1. |
|
447 // --------------------------------------------------------------------------- |
|
448 // |
|
449 TBool CIceCheckList::CompatibleCandidates( |
|
450 const CNATFWCandidate& aCand1, const CNATFWCandidate& aCand2 ) const |
|
451 { |
|
452 __ICEDP( "CIceCheckList::CompatibleCandidates" ) |
|
453 |
|
454 TUint protocol( aCand1.TransportProtocol() ); |
|
455 if ( protocol != aCand2.TransportProtocol() |
|
456 || aCand1.TransportAddr().Family() != aCand2.TransportAddr().Family() |
|
457 || aCand1.ComponentId() != aCand2.ComponentId() ) |
|
458 { |
|
459 return EFalse; |
|
460 } |
|
461 |
|
462 if ( KProtocolInetUdp == protocol ) |
|
463 { |
|
464 return ETrue; |
|
465 } |
|
466 else |
|
467 { |
|
468 // we have not TCP support yet |
|
469 return EFalse; |
|
470 } |
|
471 } |
|
472 |
|
473 |
|
474 // --------------------------------------------------------------------------- |
|
475 // CIceCheckList::PruneChecksL |
|
476 // ICE-17, 5.7.3 Pruning the pairs. |
|
477 // Procedures of ICE-TCP-03, 4.1. to be added. |
|
478 // --------------------------------------------------------------------------- |
|
479 // |
|
480 void CIceCheckList::PruneChecksL( |
|
481 RPointerArray<CIceConnectivityCheck>& aChecks ) |
|
482 { |
|
483 __ICEDP_INT1( "CIceCheckList::PruneChecksL start, COUNT:", aChecks.Count() ) |
|
484 |
|
485 // Replace server reflexive local candidate of the check by corresponding |
|
486 // base candidate. |
|
487 ReplaceReflexiveCandidatesWithBaseL( aChecks ); |
|
488 |
|
489 // Remove redundant checks. |
|
490 for ( TInt i( aChecks.Count() - 1 ); 0 <= i; --i ) |
|
491 { |
|
492 TInt matchInd = aChecks.Find( aChecks[i], |
|
493 CIceConnectivityCheck::MatchAddresses ); |
|
494 |
|
495 if ( KErrNotFound != matchInd && matchInd != i ) |
|
496 { |
|
497 delete aChecks[i]; |
|
498 aChecks.Remove( i ); |
|
499 } |
|
500 } |
|
501 |
|
502 __ICEDP_INT1( "CIceCheckList::PruneChecksL end, COUNT:", aChecks.Count() ) |
|
503 } |
|
504 |
|
505 |
|
506 // --------------------------------------------------------------------------- |
|
507 // CIceCheckList::ReplaceReflexiveCandidatesWithBaseL |
|
508 // --------------------------------------------------------------------------- |
|
509 // |
|
510 void CIceCheckList::ReplaceReflexiveCandidatesWithBaseL( |
|
511 RPointerArray<CIceConnectivityCheck>& aChecks ) |
|
512 { |
|
513 for ( TInt i( aChecks.Count() - 1 ); i >= 0; --i ) |
|
514 { |
|
515 CNATFWCandidate& localCand = const_cast<CNATFWCandidate&> |
|
516 ( aChecks[ i ]->CandidatePair().LocalCandidate() ); |
|
517 |
|
518 if ( CNATFWCandidate::EServerReflexive == localCand.Type() ) |
|
519 { |
|
520 TInt numOfChecks( aChecks.Count() ); |
|
521 for ( TInt j( 0 ); j < numOfChecks; ++j ) |
|
522 { |
|
523 const CNATFWCandidate& baseCand |
|
524 = aChecks[ j ]->CandidatePair().LocalCandidate(); |
|
525 if ( CNATFWCandidate::EHost == baseCand.Type() |
|
526 && TIceUtils::MatchAddresses( |
|
527 localCand.Base(), baseCand.Base() ) ) |
|
528 { |
|
529 localCand.SetTransportAddrL( baseCand.Base() ); |
|
530 localCand.SetType( CNATFWCandidate::EHost ); |
|
531 localCand.SetFoundationL( baseCand.Foundation() ); |
|
532 localCand.SetPriority( baseCand.Priority() ); |
|
533 } |
|
534 } |
|
535 } |
|
536 } |
|
537 } |
|
538 |
|
539 |
|
540 // --------------------------------------------------------------------------- |
|
541 // CIceCheckList::OnTimerFiredL |
|
542 // If triggered check queue contains items, top-most triggered check is sent. |
|
543 // Otherwise an ordinary check is sent. ICE-17, 5.8. Scheduling checks. |
|
544 // --------------------------------------------------------------------------- |
|
545 // |
|
546 void CIceCheckList::OnTimerFiredL() |
|
547 { |
|
548 __ICEDP( "CIceCheckList::OnTimerFiredL" ) |
|
549 |
|
550 TBool found = DequeueCheckL(); |
|
551 if ( found ) |
|
552 { |
|
553 return; |
|
554 } |
|
555 |
|
556 // Find highest priority check in waiting state |
|
557 TInt ind = FindCheckInState( CIceConnectivityCheck::EIceCheckWaiting ); |
|
558 if ( KErrNotFound != ind ) |
|
559 { |
|
560 TUint priority = PriorityForPeerReflCandL( |
|
561 iChecks[ind]->CandidatePair().LocalCandidate() ); |
|
562 iChecks[ind]->PerformConnCheckL( |
|
563 CIceConnectivityCheck::EIceCheckTypePeriodic, priority, |
|
564 RetransmissionTimeOut() ); |
|
565 |
|
566 return; |
|
567 } |
|
568 |
|
569 ind = FindCheckInState( CIceConnectivityCheck::EIceCheckFrozen ); |
|
570 if ( KErrNotFound != ind ) |
|
571 { |
|
572 iChecks[ind]->Initialize(); |
|
573 TUint priority = PriorityForPeerReflCandL( |
|
574 iChecks[ind]->CandidatePair().LocalCandidate() ); |
|
575 iChecks[ind]->PerformConnCheckL( |
|
576 CIceConnectivityCheck::EIceCheckTypePeriodic, priority, |
|
577 RetransmissionTimeOut() ); |
|
578 |
|
579 return; |
|
580 } |
|
581 |
|
582 iTimer->Cancel(); |
|
583 } |
|
584 |
|
585 |
|
586 // --------------------------------------------------------------------------- |
|
587 // CIceCheckList::PriorityForPeerReflCandL |
|
588 // --------------------------------------------------------------------------- |
|
589 // |
|
590 TUint CIceCheckList::PriorityForPeerReflCandL( |
|
591 const CNATFWCandidate& aLocalCandidate ) const |
|
592 { |
|
593 __ICEDP( "CIceCheckList::PriorityForTentativePeerReflCandL" ) |
|
594 |
|
595 CNATFWCandidate* candidate = CNATFWCandidate::NewLC( aLocalCandidate ); |
|
596 candidate->SetType( CNATFWCandidate::EPeerReflexive ); |
|
597 iCandPrioritizer->PrioritizeL( *candidate ); |
|
598 TUint priority( candidate->Priority() ); |
|
599 CleanupStack::PopAndDestroy( candidate ); |
|
600 |
|
601 return priority; |
|
602 } |
|
603 |
|
604 |
|
605 // --------------------------------------------------------------------------- |
|
606 // CIceCheckList::STUNRequestReceivedL |
|
607 // Resolve local and remote candidates and set up them for actual handler. |
|
608 // --------------------------------------------------------------------------- |
|
609 // |
|
610 void CIceCheckList::STUNRequestReceivedL( const TInetAddr& aLocalAddr, |
|
611 const TInetAddr& aFromAddr, const TInetAddr& aPeerAddr, |
|
612 TUint aPriority, TBool aRemoteFavored ) |
|
613 { |
|
614 __ICEDP( "CIceCheckList::STUNRequestReceivedL" ) |
|
615 if ( ( State() != EIceCheckListRunning ) |
|
616 && ( State() != EIceCheckListCompleted ) ) |
|
617 { |
|
618 SetStateL( EIceCheckListRunning ); |
|
619 } |
|
620 |
|
621 // Find real local candidate where request was sent to |
|
622 const CNATFWCandidate* localCand = NULL; |
|
623 TBool relayUsed = !TIceUtils::MatchAddresses( aFromAddr, aPeerAddr ); |
|
624 if ( relayUsed ) |
|
625 { |
|
626 __ICEDP( "CIceCheckList::STUNRequestReceivedL, RELAY USED" ) |
|
627 |
|
628 // Find out media component type (RTP/RTCP) |
|
629 localCand = iSessionData.FindLocalCandidate( aLocalAddr ); |
|
630 TUint componentId = localCand->ComponentId(); |
|
631 localCand = iSessionData.FindLocalCandidate( |
|
632 iStreamCollectionId, componentId, CNATFWCandidate::ERelay ); |
|
633 } |
|
634 else |
|
635 { |
|
636 localCand = iSessionData.FindLocalCandidate( aLocalAddr ); |
|
637 } |
|
638 |
|
639 __ASSERT_ALWAYS( NULL != localCand, User::Leave( KErrNotFound ) ); |
|
640 |
|
641 const CNATFWCandidate* remoteCand |
|
642 = iSessionData.FindRemoteCandidate( aPeerAddr ); |
|
643 CNATFWCandidate* newRemoteCand = NULL; |
|
644 if ( remoteCand ) |
|
645 { |
|
646 newRemoteCand = CNATFWCandidate::NewLC( *remoteCand ); |
|
647 } |
|
648 else |
|
649 { |
|
650 // ICE-17, 7.2.1.3. Learning Peer Reflexive (remote) Candidates |
|
651 newRemoteCand = CNATFWCandidate::NewLC(); |
|
652 newRemoteCand->SetTransportAddrL( aPeerAddr ); |
|
653 newRemoteCand->SetType( CNATFWCandidate::EPeerReflexive ); |
|
654 newRemoteCand->SetStreamCollectionId( localCand->StreamCollectionId() ); |
|
655 newRemoteCand->SetStreamId( localCand->StreamId() ); |
|
656 newRemoteCand->SetComponentId( localCand->ComponentId() ); |
|
657 newRemoteCand->SetPriority( aPriority ); |
|
658 |
|
659 CNATFWCandidate* peerReflCand |
|
660 = CNATFWCandidate::NewLC( *newRemoteCand ); |
|
661 // Session data generates arbitrary foundation |
|
662 iSessionData.AddPeerReflexiveCandidateL( peerReflCand, ETrue ); |
|
663 CleanupStack::Pop( peerReflCand ); |
|
664 } |
|
665 |
|
666 CNATFWCandidatePair* pair = CNATFWCandidatePair::NewLC( |
|
667 *localCand, *newRemoteCand ); |
|
668 pair->SetSelected( aRemoteFavored ); |
|
669 HandleTriggeredCheckL( *pair ); |
|
670 |
|
671 CleanupStack::PopAndDestroy( pair ); |
|
672 CleanupStack::PopAndDestroy( newRemoteCand ); |
|
673 } |
|
674 |
|
675 |
|
676 // --------------------------------------------------------------------------- |
|
677 // CIceCheckList::RelayUsedForSelectedPairL |
|
678 // --------------------------------------------------------------------------- |
|
679 // |
|
680 TBool CIceCheckList::RelayUsedForSelectedPairL() const |
|
681 { |
|
682 __ICEDP( "CIceCheckList::RelayUsedForSelectedPairL" ) |
|
683 |
|
684 TInt numOfComponents( iComponentIds.Count() ); |
|
685 __ASSERT_ALWAYS( numOfComponents, User::Leave( KErrNotReady ) ); |
|
686 |
|
687 TBool relayUseDetected( EFalse ); |
|
688 for ( TInt i( 0 ); i < numOfComponents; ++i ) |
|
689 { |
|
690 const CNATFWCandidatePair* pair |
|
691 = iValidList->SelectedPair( iComponentIds[i] ); |
|
692 |
|
693 if ( !relayUseDetected && pair |
|
694 && CNATFWCandidate::ERelay == pair->LocalCandidate().Type() ) |
|
695 { |
|
696 relayUseDetected = ETrue; |
|
697 } |
|
698 } |
|
699 |
|
700 return relayUseDetected; |
|
701 } |
|
702 |
|
703 |
|
704 // --------------------------------------------------------------------------- |
|
705 // CIceCheckList::RecomputePairPriorities |
|
706 // --------------------------------------------------------------------------- |
|
707 // |
|
708 void CIceCheckList::RecomputePairPriorities() |
|
709 { |
|
710 __ICEDP( "CIceCheckList::RecomputePairPriorities" ) |
|
711 |
|
712 iCheckPrioritizer->PrioritizeChecks( iChecks, iSessionData.Role() ); |
|
713 |
|
714 iChecks.Sort( CIceConnectivityCheck::ComparePriorities ); |
|
715 } |
|
716 |
|
717 |
|
718 // Derived function |
|
719 |
|
720 // --------------------------------------------------------------------------- |
|
721 // CIceCheckList::CheckCompletedL |
|
722 // From class MIceConnCheckListener. |
|
723 // Once a successful check has completed for the first component, the other |
|
724 // components of the same type and local preference will get performed. |
|
725 // --------------------------------------------------------------------------- |
|
726 // |
|
727 void CIceCheckList::CheckCompletedL( |
|
728 TInt aCompletionCode, |
|
729 const CIceConnectivityCheck& aCheck, |
|
730 CNATFWCandidatePair* aValidatedPair ) |
|
731 { |
|
732 __ICEDP_INT1( "CIceCheckList::CheckCompletedL, COMPLETION_CODE:", |
|
733 aCompletionCode ) |
|
734 |
|
735 CleanupStack::PushL( aValidatedPair ); |
|
736 |
|
737 if ( KErrNone == aCompletionCode ) |
|
738 { |
|
739 __ASSERT_DEBUG( aValidatedPair, User::Leave( KErrArgument ) ); |
|
740 |
|
741 // Priorities of local and remote candidates of validated pair must |
|
742 // be calculated before coming here. |
|
743 iCheckPrioritizer->PrioritizePair( |
|
744 *aValidatedPair, iSessionData.Role() ); |
|
745 iValidList->AddValidPairL( *aValidatedPair ); |
|
746 |
|
747 if ( CNATFWCandidate::EPeerReflexive |
|
748 == aValidatedPair->LocalCandidate().Type() ) |
|
749 { |
|
750 iSessionData.AddPeerReflexiveCandidateL( |
|
751 CNATFWCandidate::NewL( aValidatedPair->LocalCandidate() ), |
|
752 EFalse ); |
|
753 } |
|
754 |
|
755 // Unfreeze other checks having same foundation ICE-17, 7.1.2.2.3 |
|
756 InitializeCheckListL( aCheck.CandidatePair().Foundation() ); |
|
757 |
|
758 TBool validPairsExistForComponents( |
|
759 iValidList->HasPairForComponents( iComponentIds ) ); |
|
760 if ( validPairsExistForComponents ) |
|
761 { |
|
762 // Start checks in other check lists for candidates of same type |
|
763 iClient.ComponentsHaveValidPairsL( *this, |
|
764 aCheck.CandidatePair().Foundation() ); |
|
765 } |
|
766 |
|
767 if ( ( validPairsExistForComponents ) && |
|
768 ( EIceRoleControlling == iSessionData.Role() ) && |
|
769 ( !NominationExecuted() ) ) |
|
770 { |
|
771 // stopping criteria is minimal latency; nominate pairs when we |
|
772 // have some valid pair for each component |
|
773 NominateCandidatePairsL(); |
|
774 } |
|
775 } |
|
776 else if ( KErrRoleConflict == aCompletionCode ) |
|
777 { |
|
778 // ICE-17, section 7.1.2.1. Failure cases. |
|
779 // Candidate pair whose check has generated 487 role conflict is |
|
780 // enqueued to the triggered check queue. |
|
781 TUint priority = PriorityForPeerReflCandL( |
|
782 aCheck.CandidatePair().LocalCandidate() ); |
|
783 |
|
784 EnqueueCheckL( const_cast<CIceConnectivityCheck&>( aCheck ), |
|
785 CIceConnectivityCheck::EIceCheckTypeTriggered, |
|
786 priority ); |
|
787 |
|
788 TNATFWIceRole currentRole = iSessionData.Role(); |
|
789 TNATFWIceRole desiredRole = ( EIceRoleControlling == currentRole ) |
|
790 ? EIceRoleControlled : EIceRoleControlling; |
|
791 iClient.RoleChangeNeeded( desiredRole ); |
|
792 } |
|
793 else |
|
794 { |
|
795 // unrecoverable failure |
|
796 } |
|
797 |
|
798 CleanupStack::PopAndDestroy( aValidatedPair ); |
|
799 |
|
800 DoLosingPairProcessingL( iSelectedPairs ); |
|
801 |
|
802 // ICE-17, 7.1.2.3. Check List and Timer State Updates |
|
803 UpdateCheckListStateL(); |
|
804 } |
|
805 |
|
806 |
|
807 // --------------------------------------------------------------------------- |
|
808 // CIceCheckList::NominationCompletedL |
|
809 // From class MIceConnCheckListener. |
|
810 // ICE-15, 7.1.2.2.4. Updating the Nominated Flag |
|
811 // --------------------------------------------------------------------------- |
|
812 // |
|
813 void CIceCheckList::NominationCompletedL( |
|
814 TInt aCompletionCode, |
|
815 const CIceConnectivityCheck& /*aCheck*/, |
|
816 const CNATFWCandidatePair& aValidatedPair ) |
|
817 { |
|
818 __ICEDP( "CIceCheckList::NominationCompletedL" ) |
|
819 |
|
820 if ( KErrNone == aCompletionCode ) |
|
821 { |
|
822 iValidList->SetPairNominatedL( aValidatedPair ); |
|
823 } |
|
824 |
|
825 // ICE-17, 7.1.2.3. Check List and Timer State Updates |
|
826 UpdateCheckListStateL(); |
|
827 } |
|
828 |
|
829 |
|
830 // --------------------------------------------------------------------------- |
|
831 // CIceCheckList::HandleTriggeredCheckL |
|
832 // ICE-17 7.2.1.4. Triggered Checks |
|
833 // STUN server has set PRIORITY & USE-CANDIDATE -attributes to the remote |
|
834 // candidate. |
|
835 // --------------------------------------------------------------------------- |
|
836 // |
|
837 void CIceCheckList::HandleTriggeredCheckL( |
|
838 const CNATFWCandidatePair& aPair ) |
|
839 { |
|
840 __ICEDP( "CIceCheckList::HandleTriggeredCheckL" ) |
|
841 |
|
842 TUint trCheckPriority |
|
843 = PriorityForPeerReflCandL( aPair.LocalCandidate() ); |
|
844 |
|
845 TInt ind = FindCheck( aPair ); |
|
846 |
|
847 if ( KErrNotFound != ind ) |
|
848 { |
|
849 // We have corresponding check already in checklist |
|
850 CIceConnectivityCheck& check = *iChecks[ind]; |
|
851 check.SetRemoteCheckInfo( |
|
852 aPair.RemoteCandidate().Priority(), |
|
853 aPair.Selected() ); |
|
854 |
|
855 CIceConnectivityCheck::TIceCheckState state = check.State(); |
|
856 if ( CIceConnectivityCheck::EIceCheckWaiting & state |
|
857 || CIceConnectivityCheck::EIceCheckFrozen & state ) |
|
858 { |
|
859 EnqueueCheckL( check, |
|
860 CIceConnectivityCheck::EIceCheckTypeTriggered, |
|
861 trCheckPriority ); |
|
862 } |
|
863 else if ( CIceConnectivityCheck::EIceCheckInProgress & state ) |
|
864 { |
|
865 __ICEDP( "CIceCheckList::HandleTriggeredCheckL, INPROGRESS" ) |
|
866 // Nomination check should always succeed, so do not cancel it. |
|
867 // With ordinary checks ICE specification is followed. |
|
868 if ( !check.Nominated() ) |
|
869 { |
|
870 check.Cancel(); |
|
871 EnqueueCheckL( check, |
|
872 CIceConnectivityCheck::EIceCheckTypeTriggered, |
|
873 trCheckPriority ); |
|
874 } |
|
875 } |
|
876 else if ( CIceConnectivityCheck::EIceCheckFailed & state ) |
|
877 { |
|
878 EnqueueCheckL( check, |
|
879 CIceConnectivityCheck::EIceCheckTypeTriggered, |
|
880 trCheckPriority ); |
|
881 } |
|
882 else if ( CIceConnectivityCheck::EIceCheckSucceed & state ) |
|
883 { |
|
884 if ( aPair.Selected() ) |
|
885 { |
|
886 // ICE-17, 7.2.1.5, Updating the Nominated Flag |
|
887 const_cast<CNATFWCandidatePair&> |
|
888 ( check.CandidatePair() ).SetSelected( ETrue ); |
|
889 // Set validated pair learned from this check as selected |
|
890 const CNATFWCandidatePair* validatedPair |
|
891 = check.ValidatedPair(); |
|
892 __ASSERT_DEBUG( NULL != validatedPair, |
|
893 User::Leave( KErrNotReady ) ); |
|
894 |
|
895 iValidList->SetPairNominatedL( *validatedPair ); |
|
896 |
|
897 UpdateCheckListStateL(); |
|
898 } |
|
899 } |
|
900 else |
|
901 { |
|
902 __ICEDP( "CIceCheckList::HandleTriggeredCheckL, ASSERT" ) |
|
903 ASSERT( EFalse ); |
|
904 } |
|
905 } |
|
906 else |
|
907 { |
|
908 // We have learned peer reflexive remote candidate |
|
909 CIceConnectivityCheck* trCheck = CIceConnectivityCheck::NewLC( |
|
910 *this, aPair.LocalCandidate(), aPair.RemoteCandidate(), |
|
911 iConnHandler, iSessionData ); |
|
912 iCheckPrioritizer->PrioritizeCheck( *trCheck, |
|
913 iSessionData.Role() ); |
|
914 iChecks.InsertInOrderL( trCheck, |
|
915 CIceConnectivityCheck::ComparePriorities ); |
|
916 CleanupStack::Pop( trCheck ); |
|
917 |
|
918 // remote priority used due to ICE-17, 7.1.2.2.2 |
|
919 trCheck->SetRemoteCheckInfo( |
|
920 aPair.RemoteCandidate().Priority(), aPair.Selected() ); |
|
921 |
|
922 EnqueueCheckL( *trCheck, |
|
923 CIceConnectivityCheck::EIceCheckTypeTriggered, |
|
924 trCheckPriority ); |
|
925 } |
|
926 } |
|
927 |
|
928 |
|
929 // --------------------------------------------------------------------------- |
|
930 // CIceCheckList::UpdateCheckListStateL |
|
931 // Check list state is updated due to check completion or pair nomination. |
|
932 // Refer to ICE-17 7.1.2.3. Check List and Timer State Updates and |
|
933 // ICE-15 8.2. Updating States. |
|
934 // Change state to completed if controlling client has selected candidate |
|
935 // pair for every component of the media stream. If all checks for any |
|
936 // media component has failed, ICE processing is stopped for a media stream. |
|
937 // --------------------------------------------------------------------------- |
|
938 // |
|
939 void CIceCheckList::UpdateCheckListStateL() |
|
940 { |
|
941 __ICEDP( "CIceCheckList::UpdateCheckListStateL" ) |
|
942 |
|
943 if ( EIceCheckListRunning == State() ) |
|
944 { |
|
945 TInt numOfComponents( iComponentIds.Count() ); |
|
946 __ASSERT_DEBUG( numOfComponents, User::Leave( KErrNotReady ) ); |
|
947 |
|
948 for ( TInt i( 0 ); i < numOfComponents; ++i ) |
|
949 { |
|
950 // ICE-15, 8.2. If some component has completed, remove pending |
|
951 // checks for that component. |
|
952 RemovePendingChecks( iComponentIds[i] ); |
|
953 } |
|
954 |
|
955 if ( iValidList->NominatedPairsExist( iComponentIds ) ) |
|
956 { |
|
957 // when check list completes, frozen check lists are unfreezed |
|
958 SetStateL( EIceCheckListCompleted ); |
|
959 } |
|
960 else |
|
961 { |
|
962 // If all checks are completed and there is not valid pair for |
|
963 // each media component, check list has failed. ICE-17, 7.1.2.3. |
|
964 TInt activeStates = ( |
|
965 CIceConnectivityCheck::EIceCheckWaiting | |
|
966 CIceConnectivityCheck::EIceCheckInProgress | |
|
967 CIceConnectivityCheck::EIceCheckFrozen ); |
|
968 |
|
969 if ( KErrNotFound == FindCheckInState( activeStates ) |
|
970 && !iValidList->HasPairForComponents( iComponentIds ) ) |
|
971 { |
|
972 // when check list completes, frozen check lists are unfreezed |
|
973 SetStateL( EIceCheckListFailed ); |
|
974 } |
|
975 } |
|
976 } |
|
977 } |
|
978 |
|
979 |
|
980 // --------------------------------------------------------------------------- |
|
981 // CIceCheckList::RemovePendingChecks |
|
982 // ICE-17, 8.1.2 Updating States |
|
983 // --------------------------------------------------------------------------- |
|
984 // |
|
985 void CIceCheckList::RemovePendingChecks( TUint aComponentId ) |
|
986 { |
|
987 const CNATFWCandidatePair* nominatedPair |
|
988 = iValidList->SelectedPair( aComponentId ); |
|
989 if ( nominatedPair ) |
|
990 { |
|
991 TInt stateMask = ( |
|
992 CIceConnectivityCheck::EIceCheckWaiting | |
|
993 CIceConnectivityCheck::EIceCheckFrozen ); |
|
994 |
|
995 TInt ind = FindCheckInState( stateMask, aComponentId ); |
|
996 while ( KErrNotFound != ind ) |
|
997 { |
|
998 iChecks.Remove( ind ); |
|
999 ind = FindCheckInState( stateMask, aComponentId ); |
|
1000 } |
|
1001 } |
|
1002 } |
|
1003 |
|
1004 |
|
1005 // --------------------------------------------------------------------------- |
|
1006 // CIceCheckList::GetComponentIdsL |
|
1007 // --------------------------------------------------------------------------- |
|
1008 // |
|
1009 void CIceCheckList::GetComponentIdsL( RArray<TUint>& aComponentIds ) const |
|
1010 { |
|
1011 __ICEDP( "CIceCheckList::GetComponentIdsL" ) |
|
1012 |
|
1013 aComponentIds.Reset(); |
|
1014 TInt count( iChecks.Count() ); |
|
1015 for ( TInt i( 0 ); i < count; ++i ) |
|
1016 { |
|
1017 TUint curCompId |
|
1018 = iChecks[i]->CandidatePair().LocalCandidate().ComponentId(); |
|
1019 if ( KErrNotFound == aComponentIds.Find( curCompId ) ) |
|
1020 { |
|
1021 aComponentIds.AppendL( curCompId ); |
|
1022 } |
|
1023 } |
|
1024 } |
|
1025 |
|
1026 |
|
1027 // --------------------------------------------------------------------------- |
|
1028 // CIceCheckList::FindCheckInState |
|
1029 // --------------------------------------------------------------------------- |
|
1030 // |
|
1031 TInt CIceCheckList::FindCheckInState( TInt aStateMask ) |
|
1032 { |
|
1033 TInt count( iChecks.Count() ); |
|
1034 __ICEDP_INT1( "CIceCheckList::FindCheckInState1:", count ) |
|
1035 |
|
1036 for ( TInt i( 0 ); i < count; ++i ) |
|
1037 { |
|
1038 CIceConnectivityCheck& check( *iChecks[i] ); |
|
1039 if ( aStateMask & check.State() ) |
|
1040 { |
|
1041 return i; |
|
1042 } |
|
1043 } |
|
1044 |
|
1045 return KErrNotFound; |
|
1046 } |
|
1047 |
|
1048 |
|
1049 // --------------------------------------------------------------------------- |
|
1050 // CIceCheckList::FindCheckInState |
|
1051 // --------------------------------------------------------------------------- |
|
1052 // |
|
1053 TInt CIceCheckList::FindCheckInState( TInt aStateMask, TUint aComponentId ) |
|
1054 { |
|
1055 TInt count( iChecks.Count() ); |
|
1056 for ( TInt i( 0 ); i < count; ++i ) |
|
1057 { |
|
1058 CIceConnectivityCheck& check( *iChecks[i] ); |
|
1059 if ( ( aStateMask & check.State() ) |
|
1060 && check.ComponentId() == aComponentId ) |
|
1061 { |
|
1062 return i; |
|
1063 } |
|
1064 } |
|
1065 |
|
1066 return KErrNotFound; |
|
1067 } |
|
1068 |
|
1069 |
|
1070 // --------------------------------------------------------------------------- |
|
1071 // CIceCheckList::FindCheckInState |
|
1072 // --------------------------------------------------------------------------- |
|
1073 // |
|
1074 TInt CIceCheckList::FindCheckInState( TInt aStateMask, |
|
1075 const TInetAddr& aRemoteAddr ) |
|
1076 { |
|
1077 TInt count( iChecks.Count() ); |
|
1078 for ( TInt i( 0 ); i < count; ++i ) |
|
1079 { |
|
1080 CIceConnectivityCheck& check( *iChecks[i] ); |
|
1081 const TInetAddr& remoteAddr |
|
1082 = check.CandidatePair().RemoteCandidate().TransportAddr(); |
|
1083 if ( ( aStateMask & check.State() ) |
|
1084 && TIceUtils::MatchAddresses( remoteAddr, aRemoteAddr ) ) |
|
1085 { |
|
1086 return i; |
|
1087 } |
|
1088 } |
|
1089 |
|
1090 return KErrNotFound; |
|
1091 } |
|
1092 |
|
1093 |
|
1094 // --------------------------------------------------------------------------- |
|
1095 // CIceCheckList::FindCheck |
|
1096 // --------------------------------------------------------------------------- |
|
1097 // |
|
1098 TInt CIceCheckList::FindCheck( const CNATFWCandidatePair& aPair ) |
|
1099 { |
|
1100 for ( TInt i( iChecks.Count() - 1 ); 0 <= i; --i ) |
|
1101 { |
|
1102 TBool match = CNATFWCandidatePair::MatchAddresses( |
|
1103 iChecks[i]->CandidatePair(), aPair ); |
|
1104 if ( match ) |
|
1105 { |
|
1106 return i; |
|
1107 } |
|
1108 } |
|
1109 |
|
1110 return KErrNotFound; |
|
1111 } |
|
1112 |
|
1113 |
|
1114 // --------------------------------------------------------------------------- |
|
1115 // CIceCheckList::SetStateL |
|
1116 // --------------------------------------------------------------------------- |
|
1117 // |
|
1118 void CIceCheckList::SetStateL( TIceCheckListState aNewState ) |
|
1119 { |
|
1120 __ICEDP( "CIceCheckList::SetStateL" ) |
|
1121 |
|
1122 __ASSERT_ALWAYS( iState != aNewState, User::Leave( KErrArgument ) ); |
|
1123 iState = aNewState; |
|
1124 iCheckQue.Reset(); |
|
1125 |
|
1126 if ( EIceCheckListCompleted == aNewState ) |
|
1127 { |
|
1128 iTimer->Cancel(); |
|
1129 iSelectedPairs.ResetAndDestroy(); |
|
1130 |
|
1131 TInt numOfComponents( iComponentIds.Count() ); |
|
1132 RPointerArray<CNATFWCandidatePair> selectedPairs; |
|
1133 CleanupResetAndDestroyPushL( selectedPairs ); |
|
1134 for ( TInt i( 0 ); i < numOfComponents; ++i ) |
|
1135 { |
|
1136 CNATFWCandidatePair* newPair = CNATFWCandidatePair::NewLC( |
|
1137 *iValidList->SelectedPair( iComponentIds[i] ) ); |
|
1138 selectedPairs.AppendL( newPair ); |
|
1139 CleanupStack::Pop( newPair ); |
|
1140 } |
|
1141 |
|
1142 iClient.ChecklistCompletedL( *this, selectedPairs ); |
|
1143 |
|
1144 selectedPairs.Close(); |
|
1145 CleanupStack::Pop( &selectedPairs ); |
|
1146 } |
|
1147 else if ( EIceCheckListRunning == aNewState ) |
|
1148 { |
|
1149 if ( !iTimer->IsActive() ) |
|
1150 { |
|
1151 TCallBack callBack( CIceCheckList::TimerFired, this ); |
|
1152 iTimer->Start( 0, iInterval, callBack ); |
|
1153 } |
|
1154 } |
|
1155 else if ( EIceCheckListFailed == aNewState ) |
|
1156 { |
|
1157 iTimer->Cancel(); |
|
1158 iSelectedPairs.ResetAndDestroy(); |
|
1159 |
|
1160 RArray<TUint> failedStreams; |
|
1161 CleanupClosePushL( failedStreams ); |
|
1162 TInt stateMask = ( |
|
1163 CIceConnectivityCheck::EIceCheckWaiting | |
|
1164 CIceConnectivityCheck::EIceCheckInProgress | |
|
1165 CIceConnectivityCheck::EIceCheckSucceed | |
|
1166 CIceConnectivityCheck::EIceCheckFailed | |
|
1167 CIceConnectivityCheck::EIceCheckFrozen ); |
|
1168 |
|
1169 TInt numOfComponents( iComponentIds.Count() ); |
|
1170 for ( TInt i( 0 ); i < numOfComponents; ++i ) |
|
1171 { |
|
1172 if ( KErrNotFound != FindCheckInState( |
|
1173 stateMask, iComponentIds[i] ) ) |
|
1174 { |
|
1175 failedStreams.AppendL( iChecks[i]->StreamId() ); |
|
1176 } |
|
1177 } |
|
1178 |
|
1179 iClient.ChecklistCompletedL( |
|
1180 *this, failedStreams, KErrCouldNotConnect ); |
|
1181 CleanupStack::PopAndDestroy( &failedStreams ); |
|
1182 } |
|
1183 else |
|
1184 { |
|
1185 __ICEDP( "CIceCheckList::SetStateL, ELSE" ) |
|
1186 User::Leave( KErrArgument ); |
|
1187 } |
|
1188 } |
|
1189 |
|
1190 |
|
1191 // --------------------------------------------------------------------------- |
|
1192 // CIceCheckList::DoLosingPairProcessingL |
|
1193 // ICE-17, 9.2.2.3. |
|
1194 // ICE SHOULD be restarted if some peer selected pair has failed. |
|
1195 // --------------------------------------------------------------------------- |
|
1196 // |
|
1197 void CIceCheckList::DoLosingPairProcessingL( |
|
1198 const RPointerArray<CNATFWCandidatePair>& aSelectedPairs ) |
|
1199 { |
|
1200 __ICEDP( "CIceCheckList::DoLosingPairProcessingL" ) |
|
1201 |
|
1202 // find out losing pairs |
|
1203 RPointerArray<CNATFWCandidatePair> losingPairs; |
|
1204 CleanupResetAndDestroyPushL( losingPairs ); |
|
1205 for ( TInt i( aSelectedPairs.Count() - 1 ); 0 <= i ; --i ) |
|
1206 { |
|
1207 const CNATFWCandidatePair& pair( *aSelectedPairs[i] ); |
|
1208 if ( iValidList->HasPair( pair ) ) |
|
1209 { |
|
1210 iValidList->SetPairNominatedL( pair ); |
|
1211 } |
|
1212 else |
|
1213 { |
|
1214 CNATFWCandidatePair* losingPair |
|
1215 = CNATFWCandidatePair::NewLC( pair ); |
|
1216 losingPairs.AppendL( losingPair ); |
|
1217 CleanupStack::Pop( losingPair ); |
|
1218 } |
|
1219 } |
|
1220 |
|
1221 /* If none of peer selected pairs is in-progress and at least one |
|
1222 is failed, check list is completed unsuccessfully. If some selected |
|
1223 pair is in-progress, we wait for check completion and do this |
|
1224 processing again. */ |
|
1225 TBool inProgressCheckFound( EFalse ); |
|
1226 TBool failedCheckFound( EFalse ); |
|
1227 TInt losingPairInd( losingPairs.Count() - 1 ); |
|
1228 while ( ( 0 <= losingPairInd ) && ( !inProgressCheckFound ) ) |
|
1229 { |
|
1230 TInetAddr remoteAddr( |
|
1231 losingPairs[losingPairInd]->RemoteCandidate().TransportAddr() ); |
|
1232 |
|
1233 TInt inProgressCheckInd = FindCheckInState( |
|
1234 CIceConnectivityCheck::EIceCheckInProgress, remoteAddr ); |
|
1235 if ( KErrNotFound == inProgressCheckInd ) |
|
1236 { |
|
1237 TInt failedCheckInd = FindCheckInState( |
|
1238 CIceConnectivityCheck::EIceCheckFailed, remoteAddr ); |
|
1239 if ( KErrNotFound != failedCheckInd ) |
|
1240 { |
|
1241 failedCheckFound = ETrue; |
|
1242 } |
|
1243 } |
|
1244 else |
|
1245 { |
|
1246 inProgressCheckFound = ETrue; |
|
1247 } |
|
1248 |
|
1249 losingPairInd--; |
|
1250 } |
|
1251 |
|
1252 if ( failedCheckFound ) |
|
1253 { |
|
1254 SetStateL( EIceCheckListFailed ); |
|
1255 } |
|
1256 |
|
1257 CleanupStack::PopAndDestroy( &losingPairs ); |
|
1258 } |
|
1259 |
|
1260 |
|
1261 // --------------------------------------------------------------------------- |
|
1262 // CIceCheckList::NominateCandidatePairsL |
|
1263 // Resends connectivity checks to select pair for each media component. |
|
1264 // ICE-17, section 8.1.1.1, regular nomination is used. |
|
1265 // --------------------------------------------------------------------------- |
|
1266 // |
|
1267 void CIceCheckList::NominateCandidatePairsL() |
|
1268 { |
|
1269 __ICEDP( "CIceCheckList::NominateCandidatePairsL" ) |
|
1270 |
|
1271 TInt numOfComponents( iComponentIds.Count() ); |
|
1272 for ( TInt i( 0 ); i < numOfComponents; ++i ) |
|
1273 { |
|
1274 const CNATFWCandidatePair* pair |
|
1275 = iValidList->HighestPriorityPair( iComponentIds[i] ); |
|
1276 ASSERT( NULL != pair ); |
|
1277 const TInetAddr& lAddr( pair->LocalCandidate().TransportAddr() ); |
|
1278 const TInetAddr& rAddr( pair->RemoteCandidate().TransportAddr() ); |
|
1279 |
|
1280 TInt index( iChecks.Count() ); |
|
1281 TBool checkFound( EFalse ); |
|
1282 while ( !checkFound && --index >= 0 ) |
|
1283 { |
|
1284 const CNATFWCandidatePair* validatedPair |
|
1285 = iChecks[index]->ValidatedPair(); |
|
1286 if ( validatedPair ) |
|
1287 { |
|
1288 const TInetAddr& lAddrOfCheck |
|
1289 = validatedPair->LocalCandidate().TransportAddr(); |
|
1290 const TInetAddr& rAddrOfCheck |
|
1291 = validatedPair->RemoteCandidate().TransportAddr(); |
|
1292 |
|
1293 checkFound = |
|
1294 ( TIceUtils::MatchAddresses( lAddrOfCheck, lAddr ) && |
|
1295 TIceUtils::MatchAddresses( rAddrOfCheck, rAddr ) ); |
|
1296 } |
|
1297 } |
|
1298 |
|
1299 User::LeaveIfError( index ); |
|
1300 EnqueueCheckL( *iChecks[index], |
|
1301 CIceConnectivityCheck::EIceCheckTypeNomination, 0 ); |
|
1302 } |
|
1303 } |
|
1304 |
|
1305 |
|
1306 // --------------------------------------------------------------------------- |
|
1307 // CIceCheckList::CheckListFrozen |
|
1308 // --------------------------------------------------------------------------- |
|
1309 // |
|
1310 TBool CIceCheckList::CheckListFrozen() |
|
1311 { |
|
1312 __ICEDP( "CIceCheckList::CheckListFrozen" ) |
|
1313 |
|
1314 TInt ind( iChecks.Count() ); |
|
1315 while ( ind-- ) |
|
1316 { |
|
1317 if ( CIceConnectivityCheck::EIceCheckFrozen != iChecks[ind]->State() ) |
|
1318 { |
|
1319 return EFalse; |
|
1320 } |
|
1321 } |
|
1322 |
|
1323 return ETrue; |
|
1324 } |
|
1325 |
|
1326 |
|
1327 // --------------------------------------------------------------------------- |
|
1328 // CIceCheckList::EnqueueCheckL |
|
1329 // --------------------------------------------------------------------------- |
|
1330 // |
|
1331 void CIceCheckList::EnqueueCheckL( CIceConnectivityCheck& aCheck, |
|
1332 CIceConnectivityCheck::TIceCheckType aType, |
|
1333 TUint aLocalPriority ) |
|
1334 { |
|
1335 TIceCheckQueItem item( aCheck, aType, aLocalPriority ); |
|
1336 |
|
1337 TInt index = iCheckQue.Find( item, TIceCheckQueItem::MatchCheck ); |
|
1338 if ( CIceConnectivityCheck::EIceCheckTypeNomination == aType |
|
1339 && KErrNotFound != index ) |
|
1340 { |
|
1341 // nomination check is privileged over triggered one |
|
1342 __ICEDP( "CIceCheckList::EnqueueCheckL, REMOVE TRIGGERED CHECK" ) |
|
1343 iCheckQue.Remove( index ); |
|
1344 } |
|
1345 |
|
1346 // do not allow duplicate entries |
|
1347 if ( KErrNotFound == iCheckQue.Find( |
|
1348 item, TIceCheckQueItem::MatchCheck ) ) |
|
1349 { |
|
1350 __ICEDP( "CIceCheckList::EnqueueCheckL, APPENDING" ) |
|
1351 iCheckQue.AppendL( item ); |
|
1352 |
|
1353 if ( !iTimer->IsActive() ) |
|
1354 { |
|
1355 TCallBack callBack( CIceCheckList::TimerFired, this ); |
|
1356 iTimer->Start( 0, iInterval, callBack ); |
|
1357 } |
|
1358 } |
|
1359 else |
|
1360 { |
|
1361 __ICEDP( "CIceCheckList::EnqueueCheckL, DUPLICATE ENTRY" ) |
|
1362 } |
|
1363 } |
|
1364 |
|
1365 |
|
1366 // --------------------------------------------------------------------------- |
|
1367 // CIceCheckList::DequeueCheckL |
|
1368 // --------------------------------------------------------------------------- |
|
1369 // |
|
1370 TBool CIceCheckList::DequeueCheckL() |
|
1371 { |
|
1372 __ICEDP_INT1( "CIceCheckList::DequeueCheckL, COUNT:", iCheckQue.Count() ) |
|
1373 |
|
1374 if ( 0 != iCheckQue.Count() ) |
|
1375 { |
|
1376 TIceCheckQueItem item = iCheckQue[0]; |
|
1377 iCheckQue.Remove( 0 ); |
|
1378 |
|
1379 CIceConnectivityCheck& check = item.Check(); |
|
1380 if ( CIceConnectivityCheck::EIceCheckTypeNomination == item.Type() ) |
|
1381 { |
|
1382 check.PerformNominationL( RetransmissionTimeOut() ); |
|
1383 } |
|
1384 else |
|
1385 { |
|
1386 CIceConnectivityCheck::TIceCheckState state = check.State(); |
|
1387 // save bandwidth if previous transaction already succeeded |
|
1388 if ( CIceConnectivityCheck::EIceCheckSucceed != state ) |
|
1389 { |
|
1390 check.Initialize(); |
|
1391 check.PerformConnCheckL( |
|
1392 CIceConnectivityCheck::EIceCheckTypeTriggered, |
|
1393 item.Priority(), RetransmissionTimeOut() ); |
|
1394 } |
|
1395 } |
|
1396 |
|
1397 return ETrue; |
|
1398 } |
|
1399 else |
|
1400 { |
|
1401 return EFalse; |
|
1402 } |
|
1403 } |
|
1404 |
|
1405 |
|
1406 // --------------------------------------------------------------------------- |
|
1407 // CIceCheckList::RetransmissionTimeOut |
|
1408 // ICE-17, section 16. RTO = MAX (100ms, Ta*N * (Num-Waiting)) |
|
1409 // --------------------------------------------------------------------------- |
|
1410 // |
|
1411 TUint CIceCheckList::RetransmissionTimeOut() const |
|
1412 { |
|
1413 TInt numOfWaitingPairs( 0 ); |
|
1414 |
|
1415 TInt numOfChecks( iChecks.Count() ); |
|
1416 for ( TInt i( 0 ); i < numOfChecks; ++i ) |
|
1417 { |
|
1418 CIceConnectivityCheck& check( *iChecks[i] ); |
|
1419 if ( CIceConnectivityCheck::EIceCheckWaiting == check.State() ) |
|
1420 { |
|
1421 numOfWaitingPairs++; |
|
1422 } |
|
1423 } |
|
1424 |
|
1425 const TInt KMinimumRto( 100 ); |
|
1426 return TUint( Max( KMinimumRto, iInterval.Int() * numOfWaitingPairs ) ); |
|
1427 } |
|
1428 |
|
1429 |
|
1430 // --------------------------------------------------------------------------- |
|
1431 // CIceCheckList::FoundationsForCollectionL |
|
1432 // --------------------------------------------------------------------------- |
|
1433 // |
|
1434 CDesC8ArrayFlat* CIceCheckList::FoundationsForCollectionL( |
|
1435 TUint aStreamCollectionId ) const |
|
1436 { |
|
1437 const TInt KGranularity(4); |
|
1438 CDesC8ArrayFlat* descArray = new (ELeave) CDesC8ArrayFlat( KGranularity ); |
|
1439 CleanupStack::PushL( descArray ); |
|
1440 |
|
1441 TInt numOfChecks( iChecks.Count() ); |
|
1442 for ( TInt i(0); i < numOfChecks; ++i ) |
|
1443 { |
|
1444 CIceConnectivityCheck& check( *iChecks[i] ); |
|
1445 if ( check.StreamCollectionId() == aStreamCollectionId ) |
|
1446 { |
|
1447 TInt matchItemInd(0); |
|
1448 const TDesC8& foundation( |
|
1449 iChecks[i]->CandidatePair().Foundation() ); |
|
1450 if ( 0 != descArray->Find( foundation, matchItemInd ) ) |
|
1451 { |
|
1452 descArray->AppendL( foundation ); |
|
1453 } |
|
1454 } |
|
1455 } |
|
1456 |
|
1457 CleanupStack::Pop( descArray ); |
|
1458 return descArray; |
|
1459 } |
|
1460 |
|
1461 |
|
1462 // --------------------------------------------------------------------------- |
|
1463 // CIceCheckList::LowestComponentId |
|
1464 // --------------------------------------------------------------------------- |
|
1465 // |
|
1466 TUint CIceCheckList::LowestComponentId( RArray<TUint>& aComponentIds ) const |
|
1467 { |
|
1468 TInt componentIdCount( aComponentIds.Count() ); |
|
1469 ASSERT( 0 != componentIdCount ); |
|
1470 |
|
1471 TUint lowestComponentId( aComponentIds[0] ); |
|
1472 for ( TInt i(1); i < componentIdCount; ++i ) |
|
1473 { |
|
1474 if ( aComponentIds[i] < lowestComponentId ) |
|
1475 { |
|
1476 lowestComponentId = aComponentIds[i]; |
|
1477 } |
|
1478 } |
|
1479 |
|
1480 return lowestComponentId; |
|
1481 } |
|
1482 |
|
1483 |
|
1484 // --------------------------------------------------------------------------- |
|
1485 // CIceCheckList::NominationExecuted |
|
1486 // --------------------------------------------------------------------------- |
|
1487 // |
|
1488 TBool CIceCheckList::NominationExecuted() const |
|
1489 { |
|
1490 TInt numOfChecks( iChecks.Count() ); |
|
1491 for ( TInt i(0); i < numOfChecks; ++i ) |
|
1492 { |
|
1493 CIceConnectivityCheck& check( *iChecks[i] ); |
|
1494 if ( check.Nominated() ) |
|
1495 { |
|
1496 return ETrue; |
|
1497 } |
|
1498 } |
|
1499 |
|
1500 return EFalse; |
|
1501 } |
|
1502 |
|
1503 |
|
1504 // --------------------------------------------------------------------------- |
|
1505 // CIceCheckList::InitializeCheckList |
|
1506 // Special initialization due to ICE-17, 9.3.1.4 ICE Continuing for Existing |
|
1507 // Media Stream. |
|
1508 // --------------------------------------------------------------------------- |
|
1509 // |
|
1510 void CIceCheckList::InitializeCheckList( const TDesC8& aFoundation, |
|
1511 TInt aExcludedComponentId ) |
|
1512 { |
|
1513 __ICEDP( "CIceCheckList::InitializeCheckList" ) |
|
1514 ASSERT( 0 != iChecks.Count() ); |
|
1515 |
|
1516 for ( TInt i( iChecks.Count() - 1 ); i >= 0; --i ) |
|
1517 { |
|
1518 if ( CIceConnectivityCheck::EIceCheckFrozen == iChecks[i]->State() |
|
1519 && iChecks[i]->CandidatePair().Foundation() == aFoundation |
|
1520 && iChecks[i]->ComponentId() != aExcludedComponentId ) |
|
1521 { |
|
1522 iChecks[i]->Initialize(); |
|
1523 } |
|
1524 } |
|
1525 } |