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

Add expiry to KeepActive as per spec into fabric-admin example #35099

Merged
Merged
48 changes: 36 additions & 12 deletions examples/fabric-admin/rpc/RpcServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,30 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate
public:
void OnCheckInCompleted(const chip::app::ICDClientInfo & clientInfo) override
{
chip::NodeId nodeId = clientInfo.peer_node.GetNodeId();
auto it = mPendingKeepActiveTimesMs.find(nodeId);
VerifyOrReturn(it != mPendingKeepActiveTimesMs.end());
// TODO(#33221): We also need a mechanism here to drop KeepActive
// request if they were recieved over 60 mins ago.
uint32_t stayActiveDurationMs = it->second;
NodeId nodeId = clientInfo.peer_node.GetNodeId();
auto it = mPendingCheckIn.find(nodeId);
VerifyOrReturn(it != mPendingCheckIn.end());

KeepActiveDataForCheckIn checkInData = it->second;
// Removed from pending map as check-in from this node has occured and we will handle the pending KeepActive
// request.
mPendingCheckIn.erase(nodeId);

auto timeNow = System::SystemClock().GetMonotonicTimestamp();
if (timeNow > checkInData.mRequestExpiryTimestamp)
{
ChipLogError(
NotSpecified,
"ICD check-in for device we have been waiting, came after KeepActive expiry. Reqeust dropped for Node ID: 0x%lx",
nodeId);
return;
}

// TODO(#33221): If there is a failure in sending the message this request just gets dropped.
// Work to see if there should be update to spec on whether some sort of failure later on
// Should be indicated in some manner, or identify a better recovery mechanism here.
mPendingKeepActiveTimesMs.erase(nodeId);

auto onDone = [=](uint32_t promisedActiveDuration) { ActiveChanged(nodeId, promisedActiveDuration); };
CHIP_ERROR err = StayActiveSender::SendStayActiveCommand(stayActiveDurationMs, clientInfo.peer_node,
CHIP_ERROR err = StayActiveSender::SendStayActiveCommand(checkInData.mStayActiveDurationMs, clientInfo.peer_node,
chip::app::InteractionModelEngine::GetInstance(), onDone);
if (err != CHIP_NO_ERROR)
{
Expand Down Expand Up @@ -145,10 +155,22 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate

void ScheduleSendingKeepActiveOnCheckIn(chip::NodeId nodeId, uint32_t stayActiveDurationMs)
{
mPendingKeepActiveTimesMs[nodeId] = stayActiveDurationMs;

auto timeNow = System::SystemClock().GetMonotonicTimestamp();
// Spec says we should expire the request 60 mins after we get it
System::Clock::Timestamp expiryTimestamp = timeNow + System::Clock::Seconds64(60 * 60);
KeepActiveDataForCheckIn checkInData = { .mStayActiveDurationMs = stayActiveDurationMs,
.mRequestExpiryTimestamp = expiryTimestamp };
mPendingCheckIn[nodeId] = checkInData;
}

private:
struct KeepActiveDataForCheckIn
{
uint32_t mStayActiveDurationMs = 0;
System::Clock::Timestamp mRequestExpiryTimestamp;
};

struct KeepActiveWorkData
{
KeepActiveWorkData(FabricAdmin * fabricAdmin, chip::NodeId nodeId, uint32_t stayActiveDurationMs) :
Expand All @@ -167,8 +189,10 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate
chip::Platform::Delete(data);
}

// Modifications to mPendingKeepActiveTimesMs should be done on the MatterEventLoop thread
std::map<chip::NodeId, uint32_t> mPendingKeepActiveTimesMs;
// Modifications to mPendingCheckIn should be done on the MatterEventLoop thread
// otherwise we would need a mutex protecting this data to prevent race as this
// data is accessible by both RPC thread and Matter eventloop.
std::unordered_map<NodeId, KeepActiveDataForCheckIn> mPendingCheckIn;
};

FabricAdmin fabric_admin_service;
Expand Down
Loading