Skip to content

Commit 1089696

Browse files
bzbarsky-applepull[bot]
authored andcommitted
Improve logic for deciding whether to re-establish CASE in ReadClient. (#23627)
* Improve logic for deciding whether to re-establish CASE in ReadClient. We could end up in a situation where we had a defunct session but did not have the "try to re-establish CASE" flag set. In that case we would keep trying resubscribe attempts, which would keep failing because we could not actually create an exchange on our session, and we would never recover from that. The fix is that we try to re-establish CASE (assuming the IM engine has a CASE Session manager) if we don't have an active session. Also fixes an incorrect error ("no memory") being reported if we in fact try to subscribe when our session is not active. * Address review comments.
1 parent d22a23c commit 1089696

File tree

2 files changed

+41
-21
lines changed

2 files changed

+41
-21
lines changed

src/app/ReadClient.cpp

+40-20
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,14 @@ CHIP_ERROR ReadClient::ScheduleResubscription(uint32_t aTimeTillNextResubscripti
143143
mReadPrepareParams.mSessionHolder.Grab(aNewSessionHandle.Value());
144144
}
145145

146-
mDoCaseOnNextResub = aReestablishCASE;
146+
mForceCaseOnNextResub = aReestablishCASE;
147+
if (mForceCaseOnNextResub && mReadPrepareParams.mSessionHolder)
148+
{
149+
// Mark our existing session defunct, so that we will try to
150+
// re-establish it when the timer fires (unless something re-establishes
151+
// before then).
152+
mReadPrepareParams.mSessionHolder->AsSecureSession()->MarkAsDefunct();
153+
}
147154

148155
ReturnErrorOnFailure(
149156
InteractionModelEngine::GetInstance()->GetExchangeManager()->GetSessionManager()->SystemLayer()->StartTimer(
@@ -1013,7 +1020,16 @@ CHIP_ERROR ReadClient::SendSubscribeRequestImpl(const ReadPrepareParams & aReadP
10131020
VerifyOrReturnError(aReadPrepareParams.mSessionHolder, CHIP_ERROR_MISSING_SECURE_SESSION);
10141021

10151022
auto exchange = mpExchangeMgr->NewContext(aReadPrepareParams.mSessionHolder.Get().Value(), this);
1016-
VerifyOrReturnError(exchange != nullptr, CHIP_ERROR_NO_MEMORY);
1023+
if (exchange == nullptr)
1024+
{
1025+
if (aReadPrepareParams.mSessionHolder->AsSecureSession()->IsActiveSession())
1026+
{
1027+
return CHIP_ERROR_NO_MEMORY;
1028+
}
1029+
1030+
// Trying to subscribe with a defunct session somehow.
1031+
return CHIP_ERROR_INCORRECT_STATE;
1032+
}
10171033

10181034
mExchange.Grab(exchange);
10191035

@@ -1081,30 +1097,34 @@ void ReadClient::OnResubscribeTimerCallback(System::Layer * apSystemLayer, void
10811097

10821098
CHIP_ERROR err;
10831099

1084-
ChipLogProgress(DataManagement, "OnResubscribeTimerCallback: DoCASE = %d", _this->mDoCaseOnNextResub);
1100+
ChipLogProgress(DataManagement, "OnResubscribeTimerCallback: ForceCASE = %d", _this->mForceCaseOnNextResub);
10851101
_this->mNumRetries++;
10861102

1087-
if (_this->mDoCaseOnNextResub)
1103+
bool allowResubscribeOnError = true;
1104+
if (!_this->mReadPrepareParams.mSessionHolder ||
1105+
!_this->mReadPrepareParams.mSessionHolder->AsSecureSession()->IsActiveSession())
10881106
{
1107+
// We don't have an active CASE session. We need to go ahead and set
1108+
// one up, if we can.
1109+
ChipLogProgress(DataManagement, "Trying to establish a CASE session");
10891110
auto * caseSessionManager = InteractionModelEngine::GetInstance()->GetCASESessionManager();
1090-
VerifyOrExit(caseSessionManager != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
1111+
if (caseSessionManager)
1112+
{
1113+
caseSessionManager->FindOrEstablishSession(_this->mPeer, &_this->mOnConnectedCallback,
1114+
&_this->mOnConnectionFailureCallback);
1115+
return;
1116+
}
10911117

1092-
//
1093-
// We need to mark our session as defunct explicitly since the assessment of a liveness failure
1094-
// is usually triggered by the absence of any exchange activity that would have otherwise
1095-
// automatically marked the session as defunct on a response timeout.
1096-
//
1097-
// Doing so will ensure that the subsequent call to FindOrEstablishSession will not bind to
1098-
// an existing established session but rather trigger establishing a new one.
1099-
//
1100-
if (_this->mReadPrepareParams.mSessionHolder)
1118+
if (_this->mForceCaseOnNextResub)
11011119
{
1102-
_this->mReadPrepareParams.mSessionHolder->AsSecureSession()->MarkAsDefunct();
1120+
// Caller asked us to force CASE but we have no way to do CASE.
1121+
// Just stop trying.
1122+
allowResubscribeOnError = false;
11031123
}
11041124

1105-
caseSessionManager->FindOrEstablishSession(_this->mPeer, &_this->mOnConnectedCallback,
1106-
&_this->mOnConnectionFailureCallback);
1107-
return;
1125+
// No way to send our subscribe request.
1126+
err = CHIP_ERROR_INCORRECT_STATE;
1127+
ExitNow();
11081128
}
11091129

11101130
err = _this->SendSubscribeRequest(_this->mReadPrepareParams);
@@ -1114,11 +1134,11 @@ void ReadClient::OnResubscribeTimerCallback(System::Layer * apSystemLayer, void
11141134
{
11151135
//
11161136
// Call Close (which should trigger re-subscription again) EXCEPT if we got here because we didn't have a valid
1117-
// CASESessionManager pointer when mDoCaseOnNextResub was true.
1137+
// CASESessionManager pointer when mForceCaseOnNextResub was true.
11181138
//
11191139
// In that case, don't permit re-subscription to occur.
11201140
//
1121-
_this->Close(err, err != CHIP_ERROR_INCORRECT_STATE);
1141+
_this->Close(err, allowResubscribeOnError);
11221142
}
11231143
}
11241144

src/app/ReadClient.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ class ReadClient : public Messaging::ExchangeDelegate
501501
InteractionType mInteractionType = InteractionType::Read;
502502
Timestamp mEventTimestamp;
503503

504-
bool mDoCaseOnNextResub = true;
504+
bool mForceCaseOnNextResub = true;
505505

506506
chip::Callback::Callback<OnDeviceConnected> mOnConnectedCallback;
507507
chip::Callback::Callback<OnDeviceConnectionFailure> mOnConnectionFailureCallback;

0 commit comments

Comments
 (0)