Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ICD] Re-activate subscription when receiving check-in message if subscription fails and resub is scheduled #37481

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,14 +484,16 @@ CHIP_ERROR ReadClient::GenerateDataVersionFilterList(DataVersionFilterIBs::Build

void ReadClient::OnActiveModeNotification()
{
// This function just tries to complete the deferred resubscription logic in `OnLivenessTimeoutCallback`.
VerifyOrDie(mpImEngine->InActiveReadClientList(this));
// If we are not in InactiveICDSubscription state, that means the liveness timeout has not been reached. Simply do nothing.
VerifyOrReturn(IsInactiveICDSubscription());

// When we reach here, the subscription definitely exceeded the liveness timeout. Just continue the unfinished resubscription
// logic in `OnLivenessTimeoutCallback`.
TriggerResubscriptionForLivenessTimeout(CHIP_ERROR_TIMEOUT);
if (IsInactiveICDSubscription())
{
TriggerResubscriptionForLivenessTimeout(CHIP_ERROR_TIMEOUT);
return;
}

TriggerResubscribeIfScheduled("check-in message");
}

void ReadClient::OnPeerTypeChange(PeerType aType)
Expand Down
63 changes: 63 additions & 0 deletions src/controller/tests/data_model/TestRead.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2354,6 +2354,69 @@ TEST_F(TestRead, TestSubscribe_OnActiveModeNotification)
EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
}

TEST_F(TestRead, TestSubscribeFailed_OnActiveModeNotification)
{
auto sessionHandle = GetSessionBobToAlice();

SetMRPMode(MessagingContext::MRPMode::kResponsive);

{
TestResubscriptionCallback callback;
ReadClient readClient(InteractionModelEngine::GetInstance(), &GetExchangeManager(), callback,
ReadClient::InteractionType::Subscribe);

callback.mScheduleLITResubscribeImmediately = false;
callback.SetReadClient(&readClient);

ReadPrepareParams readPrepareParams(GetSessionBobToAlice());

AttributePathParams attributePathParams[1];
readPrepareParams.mpAttributePathParamsList = attributePathParams;
readPrepareParams.mAttributePathParamsListSize = MATTER_ARRAY_SIZE(attributePathParams);
attributePathParams[0].mEndpointId = kTestEndpointId;
attributePathParams[0].mClusterId = Clusters::UnitTesting::Id;
attributePathParams[0].mAttributeId = Clusters::UnitTesting::Attributes::Boolean::Id;

constexpr uint16_t maxIntervalCeilingSeconds = 1;

readPrepareParams.mMaxIntervalCeilingSeconds = maxIntervalCeilingSeconds;
readPrepareParams.mIsPeerLIT = true;

auto err = readClient.SendAutoResubscribeRequest(std::move(readPrepareParams));
EXPECT_EQ(err, CHIP_NO_ERROR);

GetLoopback().mNumMessagesToDrop = LoopbackTransport::kUnlimitedMessageCount;
GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(6000),
[&]() { return callback.mOnResubscriptionsAttempted == 1; });
EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 0);

GetLoopback().mNumMessagesToDrop = 0;
callback.ClearCounters();
InteractionModelEngine::GetInstance()->OnActiveModeNotification(
ScopedNodeId(readClient.GetPeerNodeId(), readClient.GetFabricIndex()));
//
// Drive servicing IO till we have established a subscription.
//
GetIOContext().DriveIOUntil(System::Clock::Milliseconds32(2000),
[&]() { return callback.mOnSubscriptionEstablishedCount == 1; });
EXPECT_EQ(callback.mOnSubscriptionEstablishedCount, 1);

//
// With re-sub enabled, we shouldn't have encountered any errors
//
EXPECT_EQ(callback.mOnError, 0);
EXPECT_EQ(callback.mOnDone, 0);

GetLoopback().mNumMessagesToDrop = 0;
callback.ClearCounters();
}

SetMRPMode(MessagingContext::MRPMode::kDefault);

InteractionModelEngine::GetInstance()->ShutdownActiveReads();
EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u);
}

/**
* When the liveness timeout of a subscription to ICD is reached, the subscription will enter "InactiveICDSubscription" state, the
* client should call "OnActiveModeNotification" to re-activate it again when the check-in message is received from the ICD.
Expand Down
Loading