From 30951555cf42393960ffb025a97abce7ff603ba6 Mon Sep 17 00:00:00 2001 From: Mathieu Kardous Date: Wed, 22 Nov 2023 13:47:33 -0500 Subject: [PATCH] Create ICDData class with refactor --- src/app/InteractionModelEngine.cpp | 7 + src/app/InteractionModelEngine.h | 12 + src/app/ReadHandler.cpp | 11 +- src/app/ReadHandler.h | 12 + src/app/chip_data_model.gni | 12 +- .../icd-management-server.cpp | 255 ++++++++++++++---- .../icd-management-server.h | 43 +++ src/app/icd/BUILD.gn | 21 +- .../icd/{ICDManagementServer.h => ICDData.h} | 42 +-- src/app/icd/ICDManagementServer.cpp | 117 -------- src/app/icd/ICDManager.cpp | 22 +- src/app/icd/ICDManager.h | 5 +- src/app/server/Dnssd.cpp | 16 +- src/app/server/Dnssd.h | 10 + src/app/server/Server.cpp | 10 +- src/app/server/Server.h | 3 + src/app/tests/TestICDManager.cpp | 26 +- src/app/tests/TestReadInteraction.cpp | 10 + src/app/tests/TestReportScheduler.cpp | 8 + 19 files changed, 397 insertions(+), 245 deletions(-) rename src/app/icd/{ICDManagementServer.h => ICDData.h} (61%) delete mode 100644 src/app/icd/ICDManagementServer.cpp diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index d202dc7d07c062..98791d95d94b51 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -1935,5 +1935,12 @@ bool InteractionModelEngine::HasSubscriptionsToResume() } #endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION +#if CHIP_CONFIG_ENABLE_ICD_SERVER +void InteractionModelEngine::SetICDData(ICDData & data) +{ + ReadHandler::SetICDData(data); +} +#endif + } // namespace app } // namespace chip diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index ca1fa92f240c58..576c9f59a0b69c 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -64,6 +64,10 @@ #include +#if CHIP_CONFIG_ENABLE_ICD_SERVER +#include //nogncheck +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + namespace chip { namespace app { @@ -306,6 +310,10 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, CHIP_ERROR ResumeSubscriptions(); +#if CHIP_CONFIG_ENABLE_ICD_SERVER + void SetICDData(ICDData & data); +#endif + #if CONFIG_BUILD_FOR_HOST_UNIT_TEST // // Get direct access to the underlying read handler pool @@ -572,6 +580,10 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, CommandHandlerInterface * mCommandHandlerList = nullptr; +#if CHIP_CONFIG_ENABLE_ICD_SERVER + ICDData * mICDData = nullptr; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + ObjectPool mCommandHandlerObjs; ObjectPool mTimedHandlers; WriteHandler mWriteHandlers[CHIP_IM_MAX_NUM_WRITE_HANDLER]; diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index 0f79c1a1d0d5f4..b8efab97dfacf7 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -34,18 +34,19 @@ #include #include -#if CHIP_CONFIG_ENABLE_ICD_SERVER -#include // nogncheck -#endif - namespace chip { namespace app { using Status = Protocols::InteractionModel::Status; +#if CHIP_CONFIG_ENABLE_ICD_SERVER +ICDData * ReadHandler::mICDData; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + uint16_t ReadHandler::GetPublisherSelectedIntervalLimit() { #if CHIP_CONFIG_ENABLE_ICD_SERVER - return static_cast(ICDManagementServer::GetInstance().GetIdleModeDurationSec()); + VerifyOrDieWithMsg(mICDData != nullptr, DataManagement, "Requires ICDData when running as an ICD server"); + return static_cast(mICDData->GetIdleModeDurationSec()); #else return kSubscriptionMaxIntervalPublisherLimit; #endif diff --git a/src/app/ReadHandler.h b/src/app/ReadHandler.h index 4c9ad469c782eb..f6e29d8225bced 100644 --- a/src/app/ReadHandler.h +++ b/src/app/ReadHandler.h @@ -51,6 +51,10 @@ #include #include +#if CHIP_CONFIG_ENABLE_ICD_SERVER +#include //nogncheck +#endif + // https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/61a9d19e6af12fdfb0872bcff26d19de6c680a1a/src/Ch02_Architecture.adoc#1122-subscribe-interaction-limits inline constexpr uint16_t kSubscriptionMaxIntervalPublisherLimit = 3600; // seconds (60 minutes) @@ -253,6 +257,10 @@ class ReadHandler : public Messaging::ExchangeDelegate return CHIP_NO_ERROR; } +#if CHIP_CONFIG_ENABLE_ICD_SERVER + static void SetICDData(ICDData & icdData) { mICDData = &icdData; } +#endif + private: PriorityLevel GetCurrentPriority() const { return mCurrentPriority; } EventNumber & GetEventMin() { return mEventMin; } @@ -577,6 +585,10 @@ class ReadHandler : public Messaging::ExchangeDelegate chip::Callback::Callback mOnConnectedCallback; chip::Callback::Callback mOnConnectionFailureCallback; #endif + +#if CHIP_CONFIG_ENABLE_ICD_SERVER + static ICDData * mICDData; +#endif }; } // namespace app } // namespace chip diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 67baca6fdf3dff..c2f0c943fc7e9d 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -157,7 +157,6 @@ template("chip_data_model") { "${_app_root}/clusters/color-control-server/color-control-server.h", "${_app_root}/clusters/door-lock-server/door-lock-server.h", "${_app_root}/clusters/groups-server/groups-server.h", - "${_app_root}/clusters/icd-management-server/icd-management-server.h", "${_app_root}/clusters/identify-server/identify-server.h", "${_app_root}/clusters/level-control/level-control.h", "${_app_root}/clusters/on-off-server/on-off-server.h", @@ -294,8 +293,15 @@ template("chip_data_model") { "${_app_root}/clusters/${cluster}/dishwasher-alarm-delegate.h", ] } else if (cluster == "icd-management-server") { - sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ] - deps += [ "${chip_root}/src/app/icd:cluster" ] + sources += [ + "${_app_root}/clusters/${cluster}/${cluster}.cpp", + "${_app_root}/clusters/${cluster}/${cluster}.h", + ] + deps += [ + "${chip_root}/src/app/icd:data", + "${chip_root}/src/app/icd:notifier", + "${chip_root}/src/app/icd:table", + ] } else if (cluster == "resource-monitoring-server") { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp", diff --git a/src/app/clusters/icd-management-server/icd-management-server.cpp b/src/app/clusters/icd-management-server/icd-management-server.cpp index 5bec758330daa1..f30aae6a3d3eb9 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.cpp +++ b/src/app/clusters/icd-management-server/icd-management-server.cpp @@ -23,10 +23,8 @@ #include #include #include -#include -#include -#include #include +#include #include #include #include @@ -48,6 +46,15 @@ class IcdManagementAttributeAccess : public app::AttributeAccessInterface public: IcdManagementAttributeAccess() : AttributeAccessInterface(MakeOptional(kRootEndpointId), IcdManagement::Id) {} + void Init(PersistentStorageDelegate & storage, Crypto::SessionKeystore * sessionKeystore, FabricTable & fabricTable, + ICDData & icdData) + { + mStorage = &storage; + mSessionKeystore = sessionKeystore; + mFabricTable = &fabricTable; + mICDData = &icdData; + } + CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; private: @@ -57,6 +64,11 @@ class IcdManagementAttributeAccess : public app::AttributeAccessInterface CHIP_ERROR ReadRegisteredClients(EndpointId endpoint, AttributeValueEncoder & encoder); CHIP_ERROR ReadICDCounter(EndpointId endpoint, AttributeValueEncoder & encoder); CHIP_ERROR ReadClientsSupportedPerFabric(EndpointId endpoint, AttributeValueEncoder & encoder); + + PersistentStorageDelegate * mStorage = nullptr; + Crypto::SessionKeystore * mSessionKeystore = nullptr; + FabricTable * mFabricTable = nullptr; + ICDData * mICDData = nullptr; }; CHIP_ERROR IcdManagementAttributeAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) @@ -89,22 +101,22 @@ CHIP_ERROR IcdManagementAttributeAccess::Read(const ConcreteReadAttributePath & CHIP_ERROR IcdManagementAttributeAccess::ReadIdleModeDuration(EndpointId endpoint, AttributeValueEncoder & encoder) { - return encoder.Encode(ICDManagementServer::GetInstance().GetIdleModeDurationSec()); + return encoder.Encode(mICDData->GetIdleModeDurationSec()); } CHIP_ERROR IcdManagementAttributeAccess::ReadActiveModeDuration(EndpointId endpoint, AttributeValueEncoder & encoder) { - return encoder.Encode(ICDManagementServer::GetInstance().GetActiveModeDurationMs()); + return encoder.Encode(mICDData->GetActiveModeDurationMs()); } CHIP_ERROR IcdManagementAttributeAccess::ReadActiveModeThreshold(EndpointId endpoint, AttributeValueEncoder & encoder) { - return encoder.Encode(ICDManagementServer::GetInstance().GetActiveModeThresholdMs()); + return encoder.Encode(mICDData->GetActiveModeThresholdMs()); } CHIP_ERROR IcdManagementAttributeAccess::ReadRegisteredClients(EndpointId endpoint, AttributeValueEncoder & encoder) { - uint16_t supported_clients = ICDManagementServer::GetInstance().GetClientsSupportedPerFabric(); + uint16_t supported_clients = mICDData->GetClientsSupportedPerFabric(); return encoder.EncodeList([supported_clients](const auto & subEncoder) -> CHIP_ERROR { Crypto::SessionKeystore * keyStore = Server::GetInstance().GetSessionKeystore(); @@ -137,40 +149,39 @@ CHIP_ERROR IcdManagementAttributeAccess::ReadRegisteredClients(EndpointId endpoi CHIP_ERROR IcdManagementAttributeAccess::ReadICDCounter(EndpointId endpoint, AttributeValueEncoder & encoder) { - return encoder.Encode(ICDManagementServer::GetInstance().GetICDCounter()); + return encoder.Encode(mICDData->GetICDCounter()); } CHIP_ERROR IcdManagementAttributeAccess::ReadClientsSupportedPerFabric(EndpointId endpoint, AttributeValueEncoder & encoder) { - return encoder.Encode(ICDManagementServer::GetInstance().GetClientsSupportedPerFabric()); + return encoder.Encode(mICDData->GetClientsSupportedPerFabric()); } -CHIP_ERROR CheckAdmin(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, bool & is_admin) +/** + * @brief Implementation of Fabric Delegate for ICD Management cluster + */ +class IcdManagementFabricDelegate : public chip::FabricTable::Delegate { - RequestPath requestPath{ .cluster = commandPath.mClusterId, .endpoint = commandPath.mEndpointId }; - CHIP_ERROR err = GetAccessControl().Check(commandObj->GetSubjectDescriptor(), requestPath, Privilege::kAdminister); - if (CHIP_NO_ERROR == err) - { - is_admin = true; - } - else if (CHIP_ERROR_ACCESS_DENIED == err) +public: + void Init(PersistentStorageDelegate & storage, Crypto::SessionKeystore * sessionKeystore, ICDData icdData) { - is_admin = false; - err = CHIP_NO_ERROR; + mStorage = &storage; + mSessionKeystore = sessionKeystore; + mICDData = &icdData; } - return err; -} -class IcdManagementFabricDelegate : public chip::FabricTable::Delegate -{ void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override { - uint16_t supported_clients = ICDManagementServer::GetInstance().GetClientsSupportedPerFabric(); - ICDMonitoringTable table(Server::GetInstance().GetPersistentStorage(), fabricIndex, supported_clients, - Server::GetInstance().GetSessionKeystore()); + uint16_t supported_clients = mICDData->GetClientsSupportedPerFabric(); + ICDMonitoringTable table(*mStorage, fabricIndex, supported_clients, mSessionKeystore); table.RemoveAll(); - ICDManagementServer::GetInstance().TriggerICDMTableUpdatedEvent(); + app::ICDNotifier::GetInstance().BroadcastICDManagementEvent(app::ICDListener::ICDManagementEvents::kTableUpdated); } + +private: + PersistentStorageDelegate * mStorage = nullptr; + Crypto::SessionKeystore * mSessionKeystore = nullptr; + ICDData * mICDData = nullptr; }; IcdManagementFabricDelegate gFabricDelegate; @@ -178,11 +189,150 @@ IcdManagementAttributeAccess gAttribute; } // namespace -void emberAfIcdManagementClusterInitCallback() +/* + * ICD Management Implementation + */ + +PersistentStorageDelegate * ICDManagementServer::mStorage = nullptr; +Crypto::SymmetricKeystore * ICDManagementServer::mSymmetricKeystore = nullptr; +ICDData * ICDManagementServer::mICDData = nullptr; + +Status ICDManagementServer::RegisterClient(FabricIndex fabric_index, chip::NodeId node_id, uint64_t monitored_subject, + chip::ByteSpan key, Optional verification_key, bool isAdmin, + uint32_t & icdCounter) { - Server::GetInstance().GetFabricTable().AddFabricDelegate(&gFabricDelegate); + bool isFirstEntryForFabric = false; + ICDMonitoringTable table(*mStorage, fabric_index, mICDData->GetClientsSupportedPerFabric(), mSymmetricKeystore); + + // Get current entry, if exists + ICDMonitoringEntry entry(mSymmetricKeystore); + CHIP_ERROR err = table.Find(node_id, entry); + if (CHIP_NO_ERROR == err) + { + // Existing entry: Validate Key if, and only if, the ISD has NOT administrator permissions + if (!isAdmin) + { + VerifyOrReturnError(verification_key.HasValue(), InteractionModel::Status::Failure); + VerifyOrReturnError(entry.IsKeyEquivalent(verification_key.Value()), InteractionModel::Status::Failure); + } + } + else if (CHIP_ERROR_NOT_FOUND == err) + { + // New entry + VerifyOrReturnError(entry.index < table.Limit(), InteractionModel::Status::ResourceExhausted); + + // Check if it's going to be the first entry for fabric + isFirstEntryForFabric = table.IsEmpty(); + } + else + { + // Error + return InteractionModel::Status::Failure; + } + + // Save + entry.checkInNodeID = node_id; + entry.monitoredSubject = monitored_subject; + if (entry.keyHandleValid) + { + entry.DeleteKey(); + } + + err = entry.SetKey(key); + VerifyOrReturnError(CHIP_ERROR_INVALID_ARGUMENT != err, InteractionModel::Status::ConstraintError); + VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); + err = table.Set(entry.index, entry); + + // Delete key upon failure to prevent key storage leakage. + if (err != CHIP_NO_ERROR) + { + entry.DeleteKey(); + } + + VerifyOrReturnError(CHIP_ERROR_INVALID_ARGUMENT != err, InteractionModel::Status::ConstraintError); + VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); + + if (isFirstEntryForFabric) + { + // Notify subscribers that the first entry for the fabric was successfully added + TriggerICDMTableUpdatedEvent(); + } + + icdCounter = mICDData->GetICDCounter(); + return InteractionModel::Status::Success; +} + +Status ICDManagementServer::UnregisterClient(FabricIndex fabric_index, chip::NodeId node_id, + Optional verificationKey, bool isAdmin) +{ + ICDMonitoringTable table(*mStorage, fabric_index, mICDData->GetClientsSupportedPerFabric(), mSymmetricKeystore); + + // Get current entry, if exists + ICDMonitoringEntry entry(mSymmetricKeystore); + CHIP_ERROR err = table.Find(node_id, entry); + VerifyOrReturnError(CHIP_ERROR_NOT_FOUND != err, InteractionModel::Status::NotFound); + VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); + + // Existing entry: Validate Key if, and only if, the ISD has NOT administrator permissions + if (!isAdmin) + { + VerifyOrReturnError(verificationKey.HasValue(), InteractionModel::Status::Failure); + VerifyOrReturnError(entry.IsKeyEquivalent(verificationKey.Value()), InteractionModel::Status::Failure); + } + + err = table.Remove(entry.index); + VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); + + if (table.IsEmpty()) + { + TriggerICDMTableUpdatedEvent(); + } + + return InteractionModel::Status::Success; +} + +Status ICDManagementServer::StayActiveRequest(FabricIndex fabric_index) +{ + // TODO: Implementent stay awake logic for end device + // https://github.com/project-chip/connectedhomeip/issues/24259 + app::ICDNotifier::GetInstance().BroadcastICDManagementEvent(app::ICDListener::ICDManagementEvents::kStayActiveRequestReceived); + return InteractionModel::Status::UnsupportedCommand; +} + +void ICDManagementServer::TriggerICDMTableUpdatedEvent() +{ + app::ICDNotifier::GetInstance().BroadcastICDManagementEvent(app::ICDListener::ICDManagementEvents::kTableUpdated); } +CHIP_ERROR ICDManagementServer::CheckAdmin(chip::app::CommandHandler * commandObj, + const chip::app::ConcreteCommandPath & commandPath, bool & isAdmin) +{ + RequestPath requestPath{ .cluster = commandPath.mClusterId, .endpoint = commandPath.mEndpointId }; + CHIP_ERROR err = GetAccessControl().Check(commandObj->GetSubjectDescriptor(), requestPath, Privilege::kAdminister); + if (CHIP_NO_ERROR == err) + { + isAdmin = true; + } + else if (CHIP_ERROR_ACCESS_DENIED == err) + { + isAdmin = false; + err = CHIP_NO_ERROR; + } + return err; +} + +void ICDManagementServer::Init(PersistentStorageDelegate & storage, Crypto::SymmetricKeystore * symmetricKeystore, + ICDData & icdData) +{ + mStorage = &storage; + mSymmetricKeystore = symmetricKeystore; + mICDData = &icdData; +} + +/********************************************************** + * Callbacks Implementation + *********************************************************/ + /** * @brief ICD Management Cluster RegisterClient Command callback (from client) * @@ -192,21 +342,21 @@ bool emberAfIcdManagementClusterRegisterClientCallback(chip::app::CommandHandler const Commands::RegisterClient::DecodableType & commandData) { InteractionModel::Status status = InteractionModel::Status::Failure; - bool is_admin = false; - if (CHIP_NO_ERROR == CheckAdmin(commandObj, commandPath, is_admin)) + bool isAdmin = false; + uint32_t icdCounter = 0; + ICDManagementServer server; + + if (CHIP_NO_ERROR == server.CheckAdmin(commandObj, commandPath, isAdmin)) { - PersistentStorageDelegate & storage = chip::Server::GetInstance().GetPersistentStorage(); - FabricIndex fabric = commandObj->GetAccessingFabricIndex(); - status = ICDManagementServer::GetInstance().RegisterClient(storage, fabric, commandData.checkInNodeID, - commandData.monitoredSubject, commandData.key, - commandData.verificationKey, is_admin); + status = + server.RegisterClient(commandObj->GetAccessingFabricIndex(), commandData.checkInNodeID, commandData.monitoredSubject, + commandData.key, commandData.verificationKey, isAdmin, icdCounter); } if (InteractionModel::Status::Success == status) { // Response - IcdManagement::Commands::RegisterClientResponse::Type response{ .ICDCounter = - ICDManagementServer::GetInstance().GetICDCounter() }; + IcdManagement::Commands::RegisterClientResponse::Type response{ .ICDCounter = icdCounter }; commandObj->AddResponse(commandPath, response); return true; } @@ -225,13 +375,13 @@ bool emberAfIcdManagementClusterUnregisterClientCallback(chip::app::CommandHandl const Commands::UnregisterClient::DecodableType & commandData) { InteractionModel::Status status = InteractionModel::Status::Failure; - bool is_admin = false; - if (CHIP_NO_ERROR == CheckAdmin(commandObj, commandPath, is_admin)) + bool isAdmin = false; + ICDManagementServer server; + + if (CHIP_NO_ERROR == server.CheckAdmin(commandObj, commandPath, isAdmin)) { - PersistentStorageDelegate & storage = chip::Server::GetInstance().GetPersistentStorage(); - FabricIndex fabric = commandObj->GetAccessingFabricIndex(); - status = ICDManagementServer::GetInstance().UnregisterClient(storage, fabric, commandData.checkInNodeID, - commandData.verificationKey, is_admin); + status = server.UnregisterClient(commandObj->GetAccessingFabricIndex(), commandData.checkInNodeID, + commandData.verificationKey, isAdmin); } commandObj->AddStatus(commandPath, status); @@ -245,7 +395,8 @@ bool emberAfIcdManagementClusterStayActiveRequestCallback(chip::app::CommandHand const chip::app::ConcreteCommandPath & commandPath, const Commands::StayActiveRequest::DecodableType & commandData) { - InteractionModel::Status status = ICDManagementServer::GetInstance().StayActiveRequest(commandObj->GetAccessingFabricIndex()); + ICDManagementServer server; + InteractionModel::Status status = server.StayActiveRequest(commandObj->GetAccessingFabricIndex()); commandObj->AddStatus(commandPath, status); return true; @@ -253,5 +404,19 @@ bool emberAfIcdManagementClusterStayActiveRequestCallback(chip::app::CommandHand void MatterIcdManagementPluginServerInitCallback() { + PersistentStorageDelegate & storage = chip::Server::GetInstance().GetPersistentStorage(); + FabricTable & fabricTable = chip::Server::GetInstance().GetFabricTable(); + Crypto::SessionKeystore * sessionKeystore = chip::Server::GetInstance().GetSessionKeystore(); + ICDData & icdData = chip::Server::GetInstance().GetICDData(); + + // Configure and register Fabric delegate + gFabricDelegate.Init(storage, sessionKeystore, icdData); + fabricTable.AddFabricDelegate(&gFabricDelegate); + + // Configure and register Attribute Access Override + gAttribute.Init(storage, sessionKeystore, fabricTable, icdData); registerAttributeAccessOverride(&gAttribute); + + // Configure ICD Management + ICDManagementServer::Init(storage, sessionKeystore, icdData); } diff --git a/src/app/clusters/icd-management-server/icd-management-server.h b/src/app/clusters/icd-management-server/icd-management-server.h index 69c11082f14c02..568b1e90ab4804 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.h +++ b/src/app/clusters/icd-management-server/icd-management-server.h @@ -16,3 +16,46 @@ */ #pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using chip::Protocols::InteractionModel::Status; + +class ICDManagementServer +{ +public: + ICDManagementServer() = default; + + static void Init(chip::PersistentStorageDelegate & storage, chip::Crypto::SymmetricKeystore * symmetricKeystore, + chip::ICDData & icdData); + Status RegisterClient(chip::FabricIndex fabric_index, chip::NodeId node_id, uint64_t monitored_subject, chip::ByteSpan key, + chip::Optional verification_key, bool is_admin, uint32_t & icdCounter); + + Status UnregisterClient(chip::FabricIndex fabric_index, chip::NodeId node_id, chip::Optional verificationKey, + bool is_admin); + + Status StayActiveRequest(chip::FabricIndex fabric_index); + + CHIP_ERROR CheckAdmin(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + bool & is_admin); + +private: + /** + * @brief Triggers table update events to notify subscribers that an entry was added or removed + * from the ICDMonitoringTable. + */ + void TriggerICDMTableUpdatedEvent(); + + static chip::PersistentStorageDelegate * mStorage; + static chip::Crypto::SymmetricKeystore * mSymmetricKeystore; + static chip::ICDData * mICDData; +}; diff --git a/src/app/icd/BUILD.gn b/src/app/icd/BUILD.gn index 99e8a23b0b699f..777b689c6f78fa 100644 --- a/src/app/icd/BUILD.gn +++ b/src/app/icd/BUILD.gn @@ -39,10 +39,11 @@ source_set("manager") { ] public_deps = [ - ":cluster", + ":data", ":notifier", ":observer", ":sender", + ":table", "${chip_root}/src/credentials:credentials", ] } @@ -54,29 +55,29 @@ source_set("sender") { ] public_deps = [ - ":cluster", ":notifier", + ":table", "${chip_root}/src/credentials:credentials", "${chip_root}/src/lib/address_resolve:address_resolve", "${chip_root}/src/protocols/secure_channel", ] } -# ICD management cluster source-set is broken out of the main source-set to enable unit tests -# All sources and configurations used by the ICD management cluster need to go in this source-set -source_set("cluster") { +# ICDMonitoringTable source-set is broken out of the main source-set to enable unit tests +# All sources and configurations used by the ICDMonitoringTable need to go in this source-set +source_set("table") { sources = [ - "ICDManagementServer.cpp", - "ICDManagementServer.h", "ICDMonitoringTable.cpp", "ICDMonitoringTable.h", ] - deps = [ ":notifier" ] - public_deps = [ "${chip_root}/src/lib/core", "${chip_root}/src/platform:platform", - "${chip_root}/src/protocols:im_status", ] } + +source_set("data") { + sources = [ "ICDData.h" ] + deps = [ "${chip_root}/src/lib/core" ] +} diff --git a/src/app/icd/ICDManagementServer.h b/src/app/icd/ICDData.h similarity index 61% rename from src/app/icd/ICDManagementServer.h rename to src/app/icd/ICDData.h index cf4a1c9cef920b..400413bd7fb421 100644 --- a/src/app/icd/ICDManagementServer.h +++ b/src/app/icd/ICDData.h @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2023 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,28 +17,21 @@ #pragma once -#include -#include -#include -#include -#include -#include - -#include +#include +#include namespace chip { -using chip::Protocols::InteractionModel::Status; - -class ICDManagementServer +class ICDData { + public: + ICDData() = default; + uint32_t GetIdleModeDurationSec() { return mIdleInterval_s; } uint32_t GetActiveModeDurationMs() { return mActiveInterval_ms; } - void SetSymmetricKeystore(Crypto::SymmetricKeystore * keyStore) { mSymmetricKeystore = keyStore; } - uint16_t GetActiveModeThresholdMs() { return mActiveThreshold_ms; } uint32_t GetICDCounter() { return mICDCounter; } @@ -47,28 +40,7 @@ class ICDManagementServer uint16_t GetClientsSupportedPerFabric() { return mFabricClientsSupported; } - Status RegisterClient(PersistentStorageDelegate & storage, FabricIndex fabric_index, chip::NodeId node_id, - uint64_t monitored_subject, chip::ByteSpan key, Optional verification_key, bool is_admin); - - Status UnregisterClient(PersistentStorageDelegate & storage, FabricIndex fabric_index, chip::NodeId node_id, - Optional verificationKey, bool is_admin); - - /** - * @brief Triggers table update events to notify subscribers that an entry was added or removed - * from the ICDMonitoringTable. - */ - void TriggerICDMTableUpdatedEvent(); - - Status StayActiveRequest(FabricIndex fabric_index); - - static ICDManagementServer & GetInstance() { return mInstance; } - private: - ICDManagementServer() = default; - - static ICDManagementServer mInstance; - Crypto::SymmetricKeystore * mSymmetricKeystore = nullptr; - static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= 64800, "Spec requires the IdleModeDuration to be equal or inferior to 64800s."); static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) >= 1, diff --git a/src/app/icd/ICDManagementServer.cpp b/src/app/icd/ICDManagementServer.cpp deleted file mode 100644 index 3ededbcffe7cb4..00000000000000 --- a/src/app/icd/ICDManagementServer.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "ICDManagementServer.h" -#include - -using namespace chip; -using namespace chip::Protocols; - -namespace chip { - -ICDManagementServer ICDManagementServer::mInstance; - -Status ICDManagementServer::RegisterClient(PersistentStorageDelegate & storage, FabricIndex fabric_index, chip::NodeId node_id, - uint64_t monitored_subject, chip::ByteSpan key, - Optional verification_key, bool is_admin) -{ - bool isFirstEntryForFabric = false; - ICDMonitoringTable table(storage, fabric_index, GetClientsSupportedPerFabric(), mSymmetricKeystore); - - // Get current entry, if exists - ICDMonitoringEntry entry(mSymmetricKeystore); - CHIP_ERROR err = table.Find(node_id, entry); - if (CHIP_NO_ERROR == err) - { - // Existing entry: Validate Key if, and only if, the ISD has NOT administrator permissions - if (!is_admin) - { - VerifyOrReturnError(verification_key.HasValue(), InteractionModel::Status::Failure); - VerifyOrReturnError(entry.IsKeyEquivalent(verification_key.Value()), InteractionModel::Status::Failure); - } - } - else if (CHIP_ERROR_NOT_FOUND == err) - { - // New entry - VerifyOrReturnError(entry.index < table.Limit(), InteractionModel::Status::ResourceExhausted); - - // Check if it's going to be the first entry for fabric - isFirstEntryForFabric = table.IsEmpty(); - } - else - { - // Error - return InteractionModel::Status::Failure; - } - - // Save - entry.checkInNodeID = node_id; - entry.monitoredSubject = monitored_subject; - if (entry.keyHandleValid) - { - entry.DeleteKey(); - } - - err = entry.SetKey(key); - VerifyOrReturnError(CHIP_ERROR_INVALID_ARGUMENT != err, InteractionModel::Status::ConstraintError); - VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); - err = table.Set(entry.index, entry); - - // Delete key upon failure to prevent key storage leakage. - if (err != CHIP_NO_ERROR) - { - entry.DeleteKey(); - } - - VerifyOrReturnError(CHIP_ERROR_INVALID_ARGUMENT != err, InteractionModel::Status::ConstraintError); - VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); - - if (isFirstEntryForFabric) - { - // Notify subscribers that the first entry for the fabric was successfully added - TriggerICDMTableUpdatedEvent(); - } - - return InteractionModel::Status::Success; -} - -Status ICDManagementServer::UnregisterClient(PersistentStorageDelegate & storage, FabricIndex fabric_index, chip::NodeId node_id, - Optional verificationKey, bool is_admin) -{ - ICDMonitoringTable table(storage, fabric_index, GetClientsSupportedPerFabric(), mSymmetricKeystore); - - // Get current entry, if exists - ICDMonitoringEntry entry(mSymmetricKeystore); - CHIP_ERROR err = table.Find(node_id, entry); - VerifyOrReturnError(CHIP_ERROR_NOT_FOUND != err, InteractionModel::Status::NotFound); - VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); - - // Existing entry: Validate Key if, and only if, the ISD has NOT administrator permissions - if (!is_admin) - { - VerifyOrReturnError(verificationKey.HasValue(), InteractionModel::Status::Failure); - VerifyOrReturnError(entry.IsKeyEquivalent(verificationKey.Value()), InteractionModel::Status::Failure); - } - - err = table.Remove(entry.index); - VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); - - if (table.IsEmpty()) - { - TriggerICDMTableUpdatedEvent(); - } - - return InteractionModel::Status::Success; -} - -Status ICDManagementServer::StayActiveRequest(FabricIndex fabric_index) -{ - // TODO: Implementent stay awake logic for end device - // https://github.com/project-chip/connectedhomeip/issues/24259 - app::ICDNotifier::GetInstance().BroadcastICDManagementEvent(app::ICDListener::ICDManagementEvents::kStayActiveRequestReceived); - return InteractionModel::Status::UnsupportedCommand; -} - -void ICDManagementServer::TriggerICDMTableUpdatedEvent() -{ - app::ICDNotifier::GetInstance().BroadcastICDManagementEvent(app::ICDListener::ICDManagementEvents::kTableUpdated); -} - -} // namespace chip diff --git a/src/app/icd/ICDManager.cpp b/src/app/icd/ICDManager.cpp index fd744a25764402..f63ab30d7d3eef 100644 --- a/src/app/icd/ICDManager.cpp +++ b/src/app/icd/ICDManager.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -43,11 +43,13 @@ using namespace chip::app::Clusters::IcdManagement; static_assert(UINT8_MAX >= CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS, "ICDManager::mOpenExchangeContextCount cannot hold count for the max exchange count"); -void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeystore) +void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeystore, + ICDData * icdData) { VerifyOrDie(storage != nullptr); VerifyOrDie(fabricTable != nullptr); VerifyOrDie(symmetricKeystore != nullptr); + VerifyOrDie(icdData != nullptr); bool supportLIT = SupportsFeature(Feature::kLongIdleTimeSupport); VerifyOrDieWithMsg((supportLIT == false) || SupportsFeature(Feature::kCheckInProtocolSupport), AppServer, @@ -63,12 +65,11 @@ void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricT mFabricTable = fabricTable; VerifyOrDie(ICDNotifier::GetInstance().Subscribe(this) == CHIP_NO_ERROR); mSymmetricKeystore = symmetricKeystore; - - ICDManagementServer::GetInstance().SetSymmetricKeystore(mSymmetricKeystore); + mICDData = icdData; // Removing the check for now since it is possible for the Fast polling // to be larger than the ActiveModeDuration for now - // uint32_t activeModeDuration = ICDManagementServer::GetInstance().GetActiveModeDurationMs(); + // uint32_t activeModeDuration = mICDData->GetActiveModeDurationMs(); // VerifyOrDie(kFastPollingInterval.count() < activeModeDuration); UpdateICDMode(); @@ -86,6 +87,7 @@ void ICDManager::Shutdown() mOperationalState = OperationalState::ActiveMode; mStorage = nullptr; mFabricTable = nullptr; + mICDData = nullptr; mStateObserverPool.ReleaseAll(); } @@ -150,9 +152,9 @@ void ICDManager::UpdateOperationState(OperationalState state) mOperationalState = OperationalState::IdleMode; // When the active mode interval is 0, we stay in idleMode until a notification brings the icd into active mode - if (ICDManagementServer::GetInstance().GetActiveModeDurationMs() > 0) + if (mICDData->GetActiveModeDurationMs() > 0) { - uint32_t idleModeDuration = ICDManagementServer::GetInstance().GetIdleModeDurationSec(); + uint32_t idleModeDuration = mICDData->GetIdleModeDurationSec(); DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(idleModeDuration), OnIdleModeDone, this); } @@ -181,13 +183,13 @@ void ICDManager::UpdateOperationState(OperationalState state) DeviceLayer::SystemLayer().CancelTimer(OnIdleModeDone, this); mOperationalState = OperationalState::ActiveMode; - uint32_t activeModeDuration = ICDManagementServer::GetInstance().GetActiveModeDurationMs(); + uint32_t activeModeDuration = mICDData->GetActiveModeDurationMs(); if (activeModeDuration == 0 && !mKeepActiveFlags.HasAny()) { // A Network Activity triggered the active mode and activeModeDuration is 0. // Stay active for at least Active Mode Threshold. - activeModeDuration = ICDManagementServer::GetInstance().GetActiveModeThresholdMs(); + activeModeDuration = mICDData->GetActiveModeThresholdMs(); } DeviceLayer::SystemLayer().StartTimer(System::Clock::Timeout(activeModeDuration), OnActiveModeDone, this); @@ -206,7 +208,7 @@ void ICDManager::UpdateOperationState(OperationalState state) } else { - uint16_t activeModeThreshold = ICDManagementServer::GetInstance().GetActiveModeThresholdMs(); + uint16_t activeModeThreshold = mICDData->GetActiveModeThresholdMs(); DeviceLayer::SystemLayer().ExtendTimerTo(System::Clock::Timeout(activeModeThreshold), OnActiveModeDone, this); uint16_t activeModeJitterThreshold = (activeModeThreshold >= ICD_ACTIVE_TIME_JITTER_MS) ? activeModeThreshold - ICD_ACTIVE_TIME_JITTER_MS : 0; diff --git a/src/app/icd/ICDManager.h b/src/app/icd/ICDManager.h index 573a20011f7ffc..78f7874796e57e 100644 --- a/src/app/icd/ICDManager.h +++ b/src/app/icd/ICDManager.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include #include @@ -69,7 +70,8 @@ class ICDManager : public ICDListener }; ICDManager() {} - void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeyStore); + void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeyStore, + ICDData * icdData); void Shutdown(); void UpdateICDMode(); void UpdateOperationState(OperationalState state); @@ -151,6 +153,7 @@ class ICDManager : public ICDListener bool mTransitionToIdleCalled = false; Crypto::SymmetricKeystore * mSymmetricKeystore = nullptr; ObjectPool mStateObserverPool; + ICDData * mICDData = nullptr; #ifdef CONFIG_BUILD_FOR_HOST_UNIT_TEST // feature map that can be changed at runtime for testing purposes diff --git a/src/app/server/Dnssd.cpp b/src/app/server/Dnssd.cpp index cb627af4348dea..81237a25908d62 100644 --- a/src/app/server/Dnssd.cpp +++ b/src/app/server/Dnssd.cpp @@ -38,8 +38,6 @@ #include #include -#include - namespace chip { namespace app { namespace { @@ -149,11 +147,13 @@ CHIP_ERROR DnssdServer::SetEphemeralDiscriminator(Optional discriminat template void DnssdServer::AddICDKeyToAdvertisement(AdvertisingParams & advParams) { + VerifyOrDieWithMsg(mICDManager != nullptr, Discovery, + "Invalid pointer to the ICDManager which is required for the LIT operating mode"); + // Only advertise the ICD key if the device can operate as a LIT - if (Server::GetInstance().GetICDManager().SupportsFeature(Clusters::IcdManagement::Feature::kLongIdleTimeSupport)) + if (mICDManager->SupportsFeature(Clusters::IcdManagement::Feature::kLongIdleTimeSupport)) { - advParams.SetICDOperatingAsLIT( - Optional(Server::GetInstance().GetICDManager().GetICDMode() == ICDManager::ICDMode::LIT)); + advParams.SetICDOperatingAsLIT(Optional(mICDManager->GetICDMode() == ICDManager::ICDMode::LIT)); } } #endif @@ -371,9 +371,13 @@ void DnssdServer::StartServer() void DnssdServer::StopServer() { - // Make sure we don't hold on to a dangling fabric table pointer. + // Make sure we don't hold on to dangling pointers. mFabricTable = nullptr; +#if CHIP_CONFIG_ENABLE_ICD_SERVER + mICDManager = nullptr; +#endif + DeviceLayer::PlatformMgr().RemoveEventHandler(OnPlatformEventWrapper, 0); #if CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY diff --git a/src/app/server/Dnssd.h b/src/app/server/Dnssd.h index be1ec4fc09ccbb..a824de0d2f4d8e 100644 --- a/src/app/server/Dnssd.h +++ b/src/app/server/Dnssd.h @@ -17,6 +17,10 @@ #pragma once +#include +#if CHIP_CONFIG_ENABLE_ICD_SERVER +#include // nogncheck +#endif #include #include #include @@ -89,6 +93,8 @@ class DLL_EXPORT DnssdServer : public ICDStateObserver #if CHIP_CONFIG_ENABLE_ICD_SERVER template void AddICDKeyToAdvertisement(AdvertisingParams & advParams); + + void SetICDManager(ICDManager & manager) { mICDManager = &manager; }; #endif /// Start operational advertising CHIP_ERROR AdvertiseOperational(); @@ -149,6 +155,10 @@ class DLL_EXPORT DnssdServer : public ICDStateObserver FabricTable * mFabricTable = nullptr; CommissioningModeProvider * mCommissioningModeProvider = nullptr; +#if CHIP_CONFIG_ENABLE_ICD_SERVER + ICDManager * mICDManager = nullptr; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + uint16_t mSecuredPort = CHIP_PORT; uint16_t mUnsecuredPort = CHIP_UDC_PORT; Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null(); diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 65a45192728833..5f0bb2534915f2 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -257,7 +257,7 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) // ICD Init needs to be after data model init #if CHIP_CONFIG_ENABLE_ICD_SERVER - mICDManager.Init(mDeviceStorage, &GetFabricTable(), mSessionKeystore); + mICDManager.Init(mDeviceStorage, &GetFabricTable(), mSessionKeystore, &mICDData); // Register the ICDStateObservers. All observers are released at mICDManager.Shutdown() // They can be released individually with ReleaseObserver mICDManager.RegisterObserver(mReportScheduler); @@ -280,6 +280,10 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) app::DnssdServer::Instance().SetUnsecuredPort(mUserDirectedCommissioningPort); app::DnssdServer::Instance().SetInterfaceId(mInterfaceId); +#if CHIP_CONFIG_ENABLE_ICD_SERVER + app::DnssdServer::Instance().SetICDManager(mICDManager); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + if (GetFabricTable().FabricCount() != 0) { // The device is already commissioned, proactively disable BLE advertisement. @@ -328,6 +332,10 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) &mCASESessionManager, mSubscriptionResumptionStorage); SuccessOrExit(err); +#if CHIP_CONFIG_ENABLE_ICD_SERVER + chip::app::InteractionModelEngine::GetInstance()->SetICDData(mICDData); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + // This code is necessary to restart listening to existing groups after a reboot // Each manufacturer needs to validate that they can rejoin groups by placing this code at the appropriate location for them // diff --git a/src/app/server/Server.h b/src/app/server/Server.h index 018c6f2196eb49..701bc95c9982bb 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -68,6 +68,7 @@ #include #if CHIP_CONFIG_ENABLE_ICD_SERVER +#include // nogncheck #include // nogncheck #endif @@ -351,6 +352,7 @@ class Server #if CHIP_CONFIG_ENABLE_ICD_SERVER app::ICDManager & GetICDManager() { return mICDManager; } + ICDData & GetICDData() { return mICDData; }; #endif // CHIP_CONFIG_ENABLE_ICD_SERVER /** @@ -623,6 +625,7 @@ class Server System::Clock::Microseconds64 mInitTimestamp; #if CHIP_CONFIG_ENABLE_ICD_SERVER app::ICDManager mICDManager; + ICDData mICDData; #endif // CHIP_CONFIG_ENABLE_ICD_SERVER }; diff --git a/src/app/tests/TestICDManager.cpp b/src/app/tests/TestICDManager.cpp index ed6ecb7dc625b4..7602d30dd99f86 100644 --- a/src/app/tests/TestICDManager.cpp +++ b/src/app/tests/TestICDManager.cpp @@ -16,7 +16,7 @@ * limitations under the License. */ #include -#include +#include #include #include #include @@ -90,7 +90,7 @@ class TestContext : public Test::AppContext { return FAILURE; } - ctx->mICDManager.Init(&ctx->testStorage, &ctx->GetFabricTable(), &(ctx->mKeystore)); + ctx->mICDManager.Init(&ctx->testStorage, &ctx->GetFabricTable(), &(ctx->mKeystore), &(ctx->mICDData)); ctx->mICDManager.RegisterObserver(&mICDStateObserver); return SUCCESS; } @@ -111,6 +111,7 @@ class TestContext : public Test::AppContext TestSessionKeystoreImpl mKeystore; app::ICDManager mICDManager; + ICDData mICDData; TestPersistentStorageDelegate testStorage; private: @@ -143,22 +144,23 @@ class TestICDManager // After the init we should be in Idle mode NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); - AdvanceClockAndRunEventLoop(ctx, secondsToMilliseconds(ICDManagementServer::GetInstance().GetIdleModeDurationSec()) + 1); + AdvanceClockAndRunEventLoop(ctx, secondsToMilliseconds(ctx->mICDData.GetIdleModeDurationSec()) + 1); // Idle mode interval expired, ICDManager transitioned to the ActiveMode. NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); - AdvanceClockAndRunEventLoop(ctx, ICDManagementServer::GetInstance().GetActiveModeDurationMs() + 1); + AdvanceClockAndRunEventLoop(ctx, ctx->mICDData.GetActiveModeDurationMs() + 1); // Active mode interval expired, ICDManager transitioned to the IdleMode. NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); - AdvanceClockAndRunEventLoop(ctx, secondsToMilliseconds(ICDManagementServer::GetInstance().GetIdleModeDurationSec()) + 1); + AdvanceClockAndRunEventLoop(ctx, secondsToMilliseconds(ctx->mICDData.GetIdleModeDurationSec()) + 1); + // Idle mode interval expired, ICDManager transitioned to the ActiveMode. NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); // Events updating the Operation to Active mode can extend the current active mode time by 1 Active mode threshold. // Kick an active Threshold just before the end of the Active interval and validate that the active mode is extended. - AdvanceClockAndRunEventLoop(ctx, ICDManagementServer::GetInstance().GetActiveModeDurationMs() - 1); + AdvanceClockAndRunEventLoop(ctx, ctx->mICDData.GetActiveModeDurationMs() - 1); ICDNotifier::GetInstance().BroadcastNetworkActivityNotification(); - AdvanceClockAndRunEventLoop(ctx, ICDManagementServer::GetInstance().GetActiveModeThresholdMs() / 2); + AdvanceClockAndRunEventLoop(ctx, ctx->mICDData.GetActiveModeThresholdMs() / 2); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); - AdvanceClockAndRunEventLoop(ctx, ICDManagementServer::GetInstance().GetActiveModeThresholdMs()); + AdvanceClockAndRunEventLoop(ctx, ctx->mICDData.GetActiveModeThresholdMs()); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); } @@ -172,7 +174,7 @@ class TestICDManager notifier.BroadcastActiveRequestNotification(ActiveFlag::kCommissioningWindowOpen); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); // Advance time so active mode interval expires. - AdvanceClockAndRunEventLoop(ctx, ICDManagementServer::GetInstance().GetActiveModeDurationMs() + 1); + AdvanceClockAndRunEventLoop(ctx, ctx->mICDData.GetActiveModeDurationMs() + 1); // Requirement flag still set. We stay in active mode NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); @@ -186,12 +188,12 @@ class TestICDManager // Advance time, but by less than the active mode interval and remove the requirement. // We should stay in active mode. - AdvanceClockAndRunEventLoop(ctx, ICDManagementServer::GetInstance().GetActiveModeDurationMs() / 2); + AdvanceClockAndRunEventLoop(ctx, ctx->mICDData.GetActiveModeDurationMs() / 2); notifier.BroadcastActiveRequestWithdrawal(ActiveFlag::kFailSafeArmed); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); // Advance time again, The activemode interval is completed. - AdvanceClockAndRunEventLoop(ctx, ICDManagementServer::GetInstance().GetActiveModeDurationMs() + 1); + AdvanceClockAndRunEventLoop(ctx, ctx->mICDData.GetActiveModeDurationMs() + 1); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); // Set two requirements @@ -199,7 +201,7 @@ class TestICDManager notifier.BroadcastActiveRequestNotification(ActiveFlag::kExchangeContextOpen); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); // advance time so the active mode interval expires. - AdvanceClockAndRunEventLoop(ctx, ICDManagementServer::GetInstance().GetActiveModeDurationMs() + 1); + AdvanceClockAndRunEventLoop(ctx, ctx->mICDData.GetActiveModeDurationMs() + 1); // A requirement flag is still set. We stay in active mode. NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp index 2ddc7d78fc64c6..0e45c0d3c2139e 100644 --- a/src/app/tests/TestReadInteraction.cpp +++ b/src/app/tests/TestReadInteraction.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -113,6 +114,11 @@ class TestContext : public chip::Test::AppContext chip::app::EventManagement::CreateEventManagement(&ctx->GetExchangeManager(), ArraySize(logStorageResources), gCircularEventBuffer, logStorageResources, &ctx->mEventCounter); + +#if CHIP_CONFIG_ENABLE_ICD_SERVER + chip::app::ReadHandler::SetICDData(ctx->mICDData); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + return SUCCESS; } @@ -123,6 +129,10 @@ class TestContext : public chip::Test::AppContext return SUCCESS; } +#if CHIP_CONFIG_ENABLE_ICD_SERVER + chip::ICDData mICDData; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + private: chip::MonotonicallyIncreasingCounter mEventCounter; }; diff --git a/src/app/tests/TestReportScheduler.cpp b/src/app/tests/TestReportScheduler.cpp index c626202f82f629..07eefcc06eac09 100644 --- a/src/app/tests/TestReportScheduler.cpp +++ b/src/app/tests/TestReportScheduler.cpp @@ -42,6 +42,10 @@ class TestContext : public chip::Test::AppContext return FAILURE; } +#if CHIP_CONFIG_ENABLE_ICD_SERVER + chip::app::ReadHandler::SetICDData(ctx->mICDData); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + return SUCCESS; } @@ -55,6 +59,10 @@ class TestContext : public chip::Test::AppContext return SUCCESS; } +#if CHIP_CONFIG_ENABLE_ICD_SERVER + chip::ICDData mICDData; +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + private: chip::MonotonicallyIncreasingCounter mEventCounter; };