36
36
#include < lib/dnssd/Resolver.h>
37
37
#include < lib/support/CodeUtils.h>
38
38
#include < lib/support/logging/CHIPLogging.h>
39
+ #include < system/SystemClock.h>
39
40
#include < system/SystemLayer.h>
40
41
41
42
using namespace chip ::Callback;
@@ -49,7 +50,7 @@ void OperationalSessionSetup::MoveToState(State aTargetState)
49
50
{
50
51
if (mState != aTargetState)
51
52
{
52
- ChipLogDetail (Controller , " OperationalSessionSetup[%u:" ChipLogFormatX64 " ]: State change %d --> %d" ,
53
+ ChipLogDetail (Discovery , " OperationalSessionSetup[%u:" ChipLogFormatX64 " ]: State change %d --> %d" ,
53
54
mPeerId .GetFabricIndex (), ChipLogValueX64 (mPeerId .GetNodeId ()), to_underlying (mState ),
54
55
to_underlying (aTargetState));
55
56
mState = aTargetState;
@@ -70,7 +71,7 @@ bool OperationalSessionSetup::AttachToExistingSecureSession()
70
71
if (!sessionHandle.HasValue ())
71
72
return false ;
72
73
73
- ChipLogProgress (Controller , " Found an existing secure session to [%u:" ChipLogFormatX64 " ]!" , mPeerId .GetFabricIndex (),
74
+ ChipLogProgress (Discovery , " Found an existing secure session to [%u:" ChipLogFormatX64 " ]!" , mPeerId .GetFabricIndex (),
74
75
ChipLogValueX64 (mPeerId .GetNodeId ()));
75
76
76
77
mDeviceAddress = sessionHandle.Value ()->AsSecureSession ()->GetPeerAddress ();
@@ -214,7 +215,7 @@ void OperationalSessionSetup::UpdateDeviceData(const Transport::PeerAddress & ad
214
215
return ;
215
216
}
216
217
217
- ChipLogError (Controller , " Received UpdateDeviceData in incorrect state" );
218
+ ChipLogError (Discovery , " Received UpdateDeviceData in incorrect state" );
218
219
DequeueConnectionCallbacks (CHIP_ERROR_INCORRECT_STATE);
219
220
// Do not touch `this` instance anymore; it has been destroyed in DequeueConnectionCallbacks.
220
221
}
@@ -304,7 +305,7 @@ void OperationalSessionSetup::DequeueConnectionCallbacks(CHIP_ERROR error)
304
305
void OperationalSessionSetup::OnSessionEstablishmentError (CHIP_ERROR error)
305
306
{
306
307
VerifyOrReturn (mState != State::Uninitialized && mState != State::NeedsAddress,
307
- ChipLogError (Controller , " HandleCASEConnectionFailure was called while the device was not initialized" ));
308
+ ChipLogError (Discovery , " HandleCASEConnectionFailure was called while the device was not initialized" ));
308
309
309
310
if (CHIP_ERROR_TIMEOUT == error)
310
311
{
@@ -313,6 +314,17 @@ void OperationalSessionSetup::OnSessionEstablishmentError(CHIP_ERROR error)
313
314
MoveToState (State::ResolvingAddress);
314
315
return ;
315
316
}
317
+
318
+ #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
319
+ if (mRemainingAttempts > 0 )
320
+ {
321
+ CHIP_ERROR err = ScheduleSessionSetupReattempt ();
322
+ if (err == CHIP_NO_ERROR)
323
+ {
324
+ return ;
325
+ }
326
+ }
327
+ #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
316
328
}
317
329
318
330
DequeueConnectionCallbacks (error);
@@ -322,7 +334,7 @@ void OperationalSessionSetup::OnSessionEstablishmentError(CHIP_ERROR error)
322
334
void OperationalSessionSetup::OnSessionEstablished (const SessionHandle & session)
323
335
{
324
336
VerifyOrReturn (mState != State::Uninitialized,
325
- ChipLogError (Controller , " HandleCASEConnected was called while the device was not initialized" ));
337
+ ChipLogError (Discovery , " HandleCASEConnected was called while the device was not initialized" ));
326
338
327
339
if (!mSecureSession .Grab (session))
328
340
return ; // Got an invalid session, do not change any state
@@ -377,6 +389,17 @@ OperationalSessionSetup::~OperationalSessionSetup()
377
389
378
390
CHIP_ERROR OperationalSessionSetup::LookupPeerAddress ()
379
391
{
392
+ #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
393
+ if (mRemainingAttempts > 0 )
394
+ {
395
+ --mRemainingAttempts ;
396
+ }
397
+ if (mAttemptsDone < UINT8_MAX)
398
+ {
399
+ ++mAttemptsDone ;
400
+ }
401
+ #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
402
+
380
403
// NOTE: This is public API that can be used to update our stored peer
381
404
// address even when we are in State::Connected, so we do not make any
382
405
// MoveToState calls in this method.
@@ -418,7 +441,7 @@ void OperationalSessionSetup::PerformAddressUpdate()
418
441
CHIP_ERROR err = LookupPeerAddress ();
419
442
if (err != CHIP_NO_ERROR)
420
443
{
421
- ChipLogError (Controller , " Failed to look up peer address: %" CHIP_ERROR_FORMAT, err.Format ());
444
+ ChipLogError (Discovery , " Failed to look up peer address: %" CHIP_ERROR_FORMAT, err.Format ());
422
445
DequeueConnectionCallbacks (err);
423
446
// Do not touch `this` instance anymore; it has been destroyed in DequeueConnectionCallbacks.
424
447
return ;
@@ -435,9 +458,93 @@ void OperationalSessionSetup::OnNodeAddressResolutionFailed(const PeerId & peerI
435
458
ChipLogError (Discovery, " OperationalSessionSetup[%u:" ChipLogFormatX64 " ]: operational discovery failed: %" CHIP_ERROR_FORMAT,
436
459
mPeerId .GetFabricIndex (), ChipLogValueX64 (mPeerId .GetNodeId ()), reason.Format ());
437
460
461
+ // Does it make sense to ScheduleSessionSetupReattempt() here? DNS-SD
462
+ // resolution has its own retry/backoff mechanisms, so if it's failed we
463
+ // have already done a lot of that.
464
+
438
465
// No need to modify any variables in `this` since call below releases `this`.
439
466
DequeueConnectionCallbacks (reason);
440
467
// Do not touch `this` instance anymore; it has been destroyed in DequeueConnectionCallbacks.
441
468
}
442
469
470
+ #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
471
+ void OperationalSessionSetup::UpdateAttemptCount (uint8_t attemptCount)
472
+ {
473
+ if (attemptCount == 0 )
474
+ {
475
+ // Nothing to do.
476
+ return ;
477
+ }
478
+
479
+ if (mState != State::NeedsAddress)
480
+ {
481
+ // We're in the middle of an attempt already, so decrement attemptCount
482
+ // by 1 to account for that.
483
+ --attemptCount;
484
+ }
485
+
486
+ if (attemptCount > mRemainingAttempts )
487
+ {
488
+ mRemainingAttempts = attemptCount;
489
+ }
490
+ }
491
+
492
+ CHIP_ERROR OperationalSessionSetup::ScheduleSessionSetupReattempt ()
493
+ {
494
+ VerifyOrDie (mRemainingAttempts > 0 );
495
+ // Try again, but not if things are in shutdown such that we can't get
496
+ // to a system layer, and not if we've run out of attempts.
497
+ if (!mInitParams .exchangeMgr ->GetSessionManager () || !mInitParams .exchangeMgr ->GetSessionManager ()->SystemLayer ())
498
+ {
499
+ return CHIP_ERROR_INCORRECT_STATE;
500
+ }
501
+
502
+ MoveToState (State::NeedsAddress);
503
+ System::Clock::Seconds16 timerDelay;
504
+ // Stop exponential backoff before our delays get too large.
505
+ //
506
+ // Note that mAttemptsDone is always > 0 here, because we have
507
+ // just finished one attempt.
508
+ VerifyOrDie (mAttemptsDone > 0 );
509
+ static_assert (UINT16_MAX / CHIP_DEVICE_CONFIG_AUTOMATIC_CASE_RETRY_INITIAL_DELAY_SECONDS >=
510
+ (1 << CHIP_DEVICE_CONFIG_AUTOMATIC_CASE_RETRY_MAX_BACKOFF),
511
+ " Our backoff calculation will overflow." );
512
+ timerDelay = System::Clock::Seconds16 (
513
+ static_cast <uint16_t >(CHIP_DEVICE_CONFIG_AUTOMATIC_CASE_RETRY_INITIAL_DELAY_SECONDS
514
+ << min ((mAttemptsDone - 1 ), CHIP_DEVICE_CONFIG_AUTOMATIC_CASE_RETRY_MAX_BACKOFF)));
515
+ CHIP_ERROR err = mInitParams .exchangeMgr ->GetSessionManager ()->SystemLayer ()->StartTimer (timerDelay, TrySetupAgain, this );
516
+ // The cast on count() is needed because the type count() returns might not
517
+ // actually be uint16_t; on some platforms it's int.
518
+ ChipLogProgress (Discovery,
519
+ " OperationalSessionSetup:attempts done: %u, attempts left: %u, retry delay %us, status %" CHIP_ERROR_FORMAT,
520
+ mAttemptsDone , mRemainingAttempts , static_cast <unsigned >(timerDelay.count ()), err.Format ());
521
+ return err;
522
+ }
523
+
524
+ void OperationalSessionSetup::TrySetupAgain (System::Layer * systemLayer, void * state)
525
+ {
526
+ auto * self = static_cast <OperationalSessionSetup *>(state);
527
+
528
+ CHIP_ERROR err = CHIP_NO_ERROR;
529
+
530
+ if (self->mState != State::NeedsAddress)
531
+ {
532
+ err = CHIP_ERROR_INCORRECT_STATE;
533
+ }
534
+ else
535
+ {
536
+ self->MoveToState (State::ResolvingAddress);
537
+ err = self->LookupPeerAddress ();
538
+ if (err == CHIP_NO_ERROR)
539
+ {
540
+ return ;
541
+ }
542
+ }
543
+
544
+ // Give up; we're either in a bad state or could not start a lookup.
545
+ self->DequeueConnectionCallbacks (err);
546
+ // Do not touch `self` instance anymore; it has been destroyed in DequeueConnectionCallbacks.
547
+ }
548
+ #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
549
+
443
550
} // namespace chip
0 commit comments