diff --git a/examples/lock-app/silabs/build_for_wifi_args.gni b/examples/lock-app/silabs/build_for_wifi_args.gni index 3769c90066ad7a..a9a7ee66170687 100644 --- a/examples/lock-app/silabs/build_for_wifi_args.gni +++ b/examples/lock-app/silabs/build_for_wifi_args.gni @@ -20,3 +20,13 @@ import("${chip_root}/src/platform/silabs/wifi_args.gni") chip_enable_ota_requestor = true app_data_model = "${chip_root}/examples/lock-app/lock-common" + +# ICD Default configurations +chip_enable_icd_server = true +chip_subscription_timeout_resumption = false +sl_use_subscription_synching = true + +# ICD Matter Configuration flags +sl_idle_mode_interval_s = 600 # 10min Idle Mode Interval +sl_active_mode_interval_ms = 10000 # 10s Active Mode Interval +sl_active_mode_threshold_ms = 1000 # 1s Active Mode Threshold diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index 5be0954b9bac34..411756ab22ff9c 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -36,7 +36,7 @@ #include #if CHIP_CONFIG_ENABLE_ICD_SERVER -#include // nogncheck +#include //nogncheck #endif namespace chip { @@ -46,7 +46,7 @@ using Status = Protocols::InteractionModel::Status; uint16_t ReadHandler::GetPublisherSelectedIntervalLimit() { #if CHIP_CONFIG_ENABLE_ICD_SERVER - return static_cast(ICDManagementServer::GetInstance().GetIdleModeDurationSec()); + return static_cast(ICDConfigurationData::GetInstance().GetIdleModeDurationSec()); #else return kSubscriptionMaxIntervalPublisherLimit; #endif diff --git a/src/app/chip_data_model.cmake b/src/app/chip_data_model.cmake index 29292bffc24d67..132a5836121f0f 100644 --- a/src/app/chip_data_model.cmake +++ b/src/app/chip_data_model.cmake @@ -139,8 +139,8 @@ function(chip_configure_data_model APP_TARGET) ${CHIP_APP_BASE_DIR}/util/attribute-table.cpp ${CHIP_APP_BASE_DIR}/util/binding-table.cpp ${CHIP_APP_BASE_DIR}/icd/ICDMonitoringTable.cpp - ${CHIP_APP_BASE_DIR}/icd/ICDManagementServer.cpp ${CHIP_APP_BASE_DIR}/icd/ICDNotifier.cpp + ${CHIP_APP_BASE_DIR}/icd/ICDConfigurationData.cpp ${CHIP_APP_BASE_DIR}/util/DataModelHandler.cpp ${CHIP_APP_BASE_DIR}/util/ember-compatibility-functions.cpp ${CHIP_APP_BASE_DIR}/util/generic-callback-stubs.cpp diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 11134e8c9c0b13..af048aa5917be4 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,10 +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" ] + sources += [ + "${_app_root}/clusters/${cluster}/${cluster}.cpp", + "${_app_root}/clusters/${cluster}/${cluster}.h", + ] deps += [ - "${chip_root}/src/app/icd:cluster", + "${chip_root}/src/app/icd:configuration-data", "${chip_root}/src/app/icd:icd_config", + "${chip_root}/src/app/icd:monitoring-table", + "${chip_root}/src/app/icd:notifier", ] } else if (cluster == "resource-monitoring-server") { sources += [ 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..941789d28144cc 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 @@ -43,11 +41,20 @@ namespace { /** * @brief Implementation of attribute access for IcdManagement cluster */ -class IcdManagementAttributeAccess : public app::AttributeAccessInterface +class IcdManagementAttributeAccess : public AttributeAccessInterface { public: IcdManagementAttributeAccess() : AttributeAccessInterface(MakeOptional(kRootEndpointId), IcdManagement::Id) {} + void Init(PersistentStorageDelegate & storage, Crypto::SymmetricKeystore * symmetricKeystore, FabricTable & fabricTable, + ICDConfigurationData & icdConfigurationData) + { + mStorage = &storage; + mSymmetricKeystore = symmetricKeystore; + mFabricTable = &fabricTable; + mICDConfigurationData = &icdConfigurationData; + } + 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::SymmetricKeystore * mSymmetricKeystore = nullptr; + FabricTable * mFabricTable = nullptr; + ICDConfigurationData * mICDConfigurationData = nullptr; }; CHIP_ERROR IcdManagementAttributeAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) @@ -89,32 +101,32 @@ CHIP_ERROR IcdManagementAttributeAccess::Read(const ConcreteReadAttributePath & CHIP_ERROR IcdManagementAttributeAccess::ReadIdleModeDuration(EndpointId endpoint, AttributeValueEncoder & encoder) { - return encoder.Encode(ICDManagementServer::GetInstance().GetIdleModeDurationSec()); + return encoder.Encode(mICDConfigurationData->GetIdleModeDurationSec()); } CHIP_ERROR IcdManagementAttributeAccess::ReadActiveModeDuration(EndpointId endpoint, AttributeValueEncoder & encoder) { - return encoder.Encode(ICDManagementServer::GetInstance().GetActiveModeDurationMs()); + return encoder.Encode(mICDConfigurationData->GetActiveModeDurationMs()); } CHIP_ERROR IcdManagementAttributeAccess::ReadActiveModeThreshold(EndpointId endpoint, AttributeValueEncoder & encoder) { - return encoder.Encode(ICDManagementServer::GetInstance().GetActiveModeThresholdMs()); + return encoder.Encode(mICDConfigurationData->GetActiveModeThresholdMs()); } CHIP_ERROR IcdManagementAttributeAccess::ReadRegisteredClients(EndpointId endpoint, AttributeValueEncoder & encoder) { - uint16_t supported_clients = ICDManagementServer::GetInstance().GetClientsSupportedPerFabric(); + uint16_t supported_clients = mICDConfigurationData->GetClientsSupportedPerFabric(); + PersistentStorageDelegate * storage = mStorage; + Crypto::SymmetricKeystore * symmetricKeystore = mSymmetricKeystore; + const FabricTable * fabricTable = mFabricTable; - return encoder.EncodeList([supported_clients](const auto & subEncoder) -> CHIP_ERROR { - Crypto::SessionKeystore * keyStore = Server::GetInstance().GetSessionKeystore(); - ICDMonitoringEntry e(keyStore); + return encoder.EncodeList([supported_clients, storage, symmetricKeystore, fabricTable](const auto & subEncoder) -> CHIP_ERROR { + ICDMonitoringEntry e(symmetricKeystore); - const auto & fabricTable = Server::GetInstance().GetFabricTable(); - PersistentStorageDelegate & storage = Server::GetInstance().GetPersistentStorage(); - for (const auto & fabricInfo : fabricTable) + for (const auto & fabricInfo : *fabricTable) { - ICDMonitoringTable table(storage, fabricInfo.GetFabricIndex(), supported_clients, keyStore); + ICDMonitoringTable table(*storage, fabricInfo.GetFabricIndex(), supported_clients, symmetricKeystore); for (uint16_t i = 0; i < table.Limit(); ++i) { CHIP_ERROR err = table.Get(i, e); @@ -137,40 +149,40 @@ CHIP_ERROR IcdManagementAttributeAccess::ReadRegisteredClients(EndpointId endpoi CHIP_ERROR IcdManagementAttributeAccess::ReadICDCounter(EndpointId endpoint, AttributeValueEncoder & encoder) { - return encoder.Encode(ICDManagementServer::GetInstance().GetICDCounter()); + return encoder.Encode(mICDConfigurationData->GetICDCounter()); } CHIP_ERROR IcdManagementAttributeAccess::ReadClientsSupportedPerFabric(EndpointId endpoint, AttributeValueEncoder & encoder) { - return encoder.Encode(ICDManagementServer::GetInstance().GetClientsSupportedPerFabric()); + return encoder.Encode(mICDConfigurationData->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 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::SymmetricKeystore * symmetricKeystore, + ICDConfigurationData & icdConfigurationData) { - is_admin = false; - err = CHIP_NO_ERROR; + mStorage = &storage; + mSymmetricKeystore = symmetricKeystore; + mICDConfigurationData = &icdConfigurationData; } - 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 = mICDConfigurationData->GetClientsSupportedPerFabric(); + ICDMonitoringTable table(*mStorage, fabricIndex, supported_clients, mSymmetricKeystore); table.RemoveAll(); - ICDManagementServer::GetInstance().TriggerICDMTableUpdatedEvent(); + ICDNotifier::GetInstance().BroadcastICDManagementEvent(ICDListener::ICDManagementEvents::kTableUpdated); } + +private: + PersistentStorageDelegate * mStorage = nullptr; + Crypto::SymmetricKeystore * mSymmetricKeystore = nullptr; + ICDConfigurationData * mICDConfigurationData = nullptr; }; IcdManagementFabricDelegate gFabricDelegate; @@ -178,35 +190,171 @@ IcdManagementAttributeAccess gAttribute; } // namespace -void emberAfIcdManagementClusterInitCallback() +/* + * ICD Management Implementation + */ + +PersistentStorageDelegate * ICDManagementServer::mStorage = nullptr; +Crypto::SymmetricKeystore * ICDManagementServer::mSymmetricKeystore = nullptr; +ICDConfigurationData * ICDManagementServer::mICDConfigurationData = nullptr; + +Status ICDManagementServer::RegisterClient(FabricIndex fabric_index, NodeId node_id, uint64_t monitored_subject, ByteSpan key, + Optional verification_key, bool isAdmin, uint32_t & icdCounter) { - Server::GetInstance().GetFabricTable().AddFabricDelegate(&gFabricDelegate); + bool isFirstEntryForFabric = false; + ICDMonitoringTable table(*mStorage, fabric_index, mICDConfigurationData->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 does NOT have 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 = mICDConfigurationData->GetICDCounter(); + return InteractionModel::Status::Success; } +Status ICDManagementServer::UnregisterClient(FabricIndex fabric_index, NodeId node_id, Optional verificationKey, + bool isAdmin) +{ + ICDMonitoringTable table(*mStorage, fabric_index, mICDConfigurationData->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 + ICDNotifier::GetInstance().BroadcastICDManagementEvent(ICDListener::ICDManagementEvents::kStayActiveRequestReceived); + return InteractionModel::Status::UnsupportedCommand; +} + +void ICDManagementServer::TriggerICDMTableUpdatedEvent() +{ + ICDNotifier::GetInstance().BroadcastICDManagementEvent(ICDListener::ICDManagementEvents::kTableUpdated); +} + +CHIP_ERROR ICDManagementServer::CheckAdmin(CommandHandler * commandObj, const 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, + ICDConfigurationData & icdConfigurationData) +{ + mStorage = &storage; + mSymmetricKeystore = symmetricKeystore; + mICDConfigurationData = &icdConfigurationData; +} + +/********************************************************** + * Callbacks Implementation + *********************************************************/ + /** * @brief ICD Management Cluster RegisterClient Command callback (from client) * */ -bool emberAfIcdManagementClusterRegisterClientCallback(chip::app::CommandHandler * commandObj, - const chip::app::ConcreteCommandPath & commandPath, +bool emberAfIcdManagementClusterRegisterClientCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, 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; } @@ -220,18 +368,17 @@ bool emberAfIcdManagementClusterRegisterClientCallback(chip::app::CommandHandler * @brief ICD Management Cluster UregisterClient Command callback (from client) * */ -bool emberAfIcdManagementClusterUnregisterClientCallback(chip::app::CommandHandler * commandObj, - const chip::app::ConcreteCommandPath & commandPath, +bool emberAfIcdManagementClusterUnregisterClientCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, 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); @@ -241,11 +388,11 @@ bool emberAfIcdManagementClusterUnregisterClientCallback(chip::app::CommandHandl /** * @brief ICD Management Cluster StayActiveRequest Command callback (from client) */ -bool emberAfIcdManagementClusterStayActiveRequestCallback(chip::app::CommandHandler * commandObj, - const chip::app::ConcreteCommandPath & commandPath, +bool emberAfIcdManagementClusterStayActiveRequestCallback(CommandHandler * commandObj, const 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 +400,19 @@ bool emberAfIcdManagementClusterStayActiveRequestCallback(chip::app::CommandHand void MatterIcdManagementPluginServerInitCallback() { + PersistentStorageDelegate & storage = Server::GetInstance().GetPersistentStorage(); + FabricTable & fabricTable = Server::GetInstance().GetFabricTable(); + Crypto::SymmetricKeystore * symmetricKeystore = Server::GetInstance().GetSessionKeystore(); + ICDConfigurationData & icdConfigurationData = ICDConfigurationData::GetInstance().GetInstance(); + + // Configure and register Fabric delegate + gFabricDelegate.Init(storage, symmetricKeystore, icdConfigurationData); + fabricTable.AddFabricDelegate(&gFabricDelegate); + + // Configure and register Attribute Access Override + gAttribute.Init(storage, symmetricKeystore, fabricTable, icdConfigurationData); registerAttributeAccessOverride(&gAttribute); + + // Configure ICD Management + ICDManagementServer::Init(storage, symmetricKeystore, icdConfigurationData); } 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..76fad5ca941475 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::ICDConfigurationData & ICDConfigurationData); + 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::ICDConfigurationData * mICDConfigurationData; +}; diff --git a/src/app/icd/BUILD.gn b/src/app/icd/BUILD.gn index 3be8fe48553301..7fdada476e989c 100644 --- a/src/app/icd/BUILD.gn +++ b/src/app/icd/BUILD.gn @@ -64,7 +64,8 @@ source_set("manager") { deps = [ ":icd_config" ] public_deps = [ - ":cluster", + ":configuration-data", + ":monitoring-table", ":notifier", ":observer", ":sender", @@ -79,7 +80,7 @@ source_set("sender") { ] public_deps = [ - ":cluster", + ":monitoring-table", ":notifier", "${chip_root}/src/credentials:credentials", "${chip_root}/src/lib/address_resolve:address_resolve", @@ -87,21 +88,25 @@ source_set("sender") { ] } -# 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("monitoring-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("configuration-data") { + sources = [ + "ICDConfigurationData.cpp", + "ICDConfigurationData.h", + ] + + deps = [ "${chip_root}/src/lib/core" ] +} diff --git a/src/app/icd/ICDConfigurationData.cpp b/src/app/icd/ICDConfigurationData.cpp new file mode 100644 index 00000000000000..d3f57eacced070 --- /dev/null +++ b/src/app/icd/ICDConfigurationData.cpp @@ -0,0 +1,38 @@ +/* + * + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ICDConfigurationData.h" + +namespace chip { + +ICDConfigurationData ICDConfigurationData::instance; + +System::Clock::Milliseconds32 ICDConfigurationData::GetSlowPollingInterval() +{ +#if ICD_ENFORCE_SIT_SLOW_POLL_LIMIT + // When in SIT mode, the slow poll interval SHOULDN'T be greater than the SIT mode polling threshold, per spec. + // This is important for ICD device configured for LIT operation but currently operating as a SIT + // due to a lack of client registration + if (mICDMode == ICDMode::SIT && GetSlowPollingInterval() > GetSITPollingThreshold()) + { + return GetSITPollingThreshold(); + } +#endif + return mSlowPollingInterval; +} + +} // namespace chip diff --git a/src/app/icd/ICDConfigurationData.h b/src/app/icd/ICDConfigurationData.h new file mode 100644 index 00000000000000..efb4e7e73867ca --- /dev/null +++ b/src/app/icd/ICDConfigurationData.h @@ -0,0 +1,127 @@ +/** + * + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#ifndef ICD_ENFORCE_SIT_SLOW_POLL_LIMIT +// Set to 1 to enforce SIT Slow Polling Max value to 15seconds (spec 9.16.1.5) +#define ICD_ENFORCE_SIT_SLOW_POLL_LIMIT 0 +#endif + +namespace chip { + +namespace app { +// Forward declaration of ICDManager to allow it to be friend with ICDConfigurationData +class ICDManager; +} // namespace app + +/** + * @brief ICDConfigurationData manages and stores ICD related configurations for the ICDManager. + * Goal of the class is to expose ICD information to all consummers without creating circular dependencies + * since the ICDManager is appart of the App layer + * + * Anyone can read the ICD configurations but only the ICDManager can changes those configurations. + */ +class ICDConfigurationData +{ +public: + enum class ICDMode : uint8_t + { + SIT, // Short Interval Time ICD + LIT, // Long Interval Time ICD + }; + + static ICDConfigurationData & GetInstance() { return instance; }; + + uint32_t GetIdleModeDurationSec() { return mIdleInterval_s; } + + uint32_t GetActiveModeDurationMs() { return mActiveInterval_ms; } + + uint16_t GetActiveModeThresholdMs() { return mActiveThreshold_ms; } + + uint32_t GetICDCounter() { return mICDCounter; } + + uint16_t GetClientsSupportedPerFabric() { return mFabricClientsSupported; } + + System::Clock::Milliseconds32 GetSITPollingThreshold() { return kSITPollingThreshold; } + + System::Clock::Milliseconds32 GetFastPollingInterval() { return mFastPollingInterval; } + + /** + * If ICD_ENFORCE_SIT_SLOW_POLL_LIMIT is set to 0, function will always return the configured Slow Polling interval + * (CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL). + * + * If ICD_ENFORCE_SIT_SLOW_POLL_LIMIT is set to 1, the returned value will depend on the devices operating mode. + * If ICDMode == SIT && the configured slow poll interval is superior to the maximum threshold (15s), the function will return + * the threshold (15s). If ICDMode == SIT but the configured slow poll interval is equal or inferior to the threshold, the + * function will the return the configured slow poll interval. If ICDMode == LIT, the function will return the configured slow + * poll interval. + * + * @return System::Clock::Milliseconds32 + */ + System::Clock::Milliseconds32 GetSlowPollingInterval(); + + ICDMode GetICDMode() { return mICDMode; } + +private: + // Singleton Object + ICDConfigurationData() = default; + static ICDConfigurationData instance; + + // ICD related information is managed by the ICDManager but stored in the ICDConfigurationData to enable consummers to access it + // without creating a circular dependency. To avoid allowing consummers changing the state of the ICD mode without going through + // the ICDManager, the ICDManager is a friend that can access the private setters. If a consummer needs to be notified when a + // value is changed, they can leverage the Observer events the ICDManager generates. See src/app/icd/ICDStateObserver.h + friend class chip::app::ICDManager; + + void SetICDMode(ICDMode mode) { mICDMode = mode; }; + void SetICDCounter(uint32_t count) { mICDCounter = count; } + void SetSlowPollingInterval(System::Clock::Milliseconds32 slowPollInterval) { mSlowPollingInterval = slowPollInterval; }; + void SetFastPollingInterval(System::Clock::Milliseconds32 fastPollInterval) { mFastPollingInterval = fastPollInterval; }; + + 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, + "Spec requires the IdleModeDuration to be equal or greater to 1s."); + uint32_t mIdleInterval_s = CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC; + + static_assert((CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS) <= (CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC * kMillisecondsPerSecond), + "Spec requires the IdleModeDuration be equal or greater to the ActiveModeDuration."); + uint32_t mActiveInterval_ms = CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS; + + uint16_t mActiveThreshold_ms = CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS; + + // TODO : Implement ICD counter + // https://github.com/project-chip/connectedhomeip/issues/29184 + uint32_t mICDCounter = 0; + + static_assert((CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC) >= 1, + "Spec requires the minimum of supported clients per fabric be equal or greater to 1."); + uint16_t mFabricClientsSupported = CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC; + + // SIT ICDs should have a SlowPollingThreshold shorter than or equal to 15s (spec 9.16.1.5) + static constexpr System::Clock::Milliseconds32 kSITPollingThreshold = System::Clock::Milliseconds32(15000); + System::Clock::Milliseconds32 mSlowPollingInterval = CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL; + System::Clock::Milliseconds32 mFastPollingInterval = CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL; + + ICDMode mICDMode = ICDMode::SIT; +}; + +} // namespace chip 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/ICDManagementServer.h b/src/app/icd/ICDManagementServer.h deleted file mode 100644 index cf4a1c9cef920b..00000000000000 --- a/src/app/icd/ICDManagementServer.h +++ /dev/null @@ -1,93 +0,0 @@ -/** - * - * Copyright (c) 2022 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include - -namespace chip { - -using chip::Protocols::InteractionModel::Status; - -class ICDManagementServer -{ -public: - 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; } - - void SetICDCounter(uint32_t count) { mICDCounter = count; } - - 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, - "Spec requires the IdleModeDuration to be equal or greater to 1s."); - uint32_t mIdleInterval_s = CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC; - - static_assert((CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS) <= (CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC * kMillisecondsPerSecond), - "Spec requires the IdleModeDuration be equal or greater to the ActiveModeDuration."); - uint32_t mActiveInterval_ms = CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS; - - uint16_t mActiveThreshold_ms = CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS; - - // TODO : Implement ICD counter - // https://github.com/project-chip/connectedhomeip/issues/29184 - uint32_t mICDCounter = 0; - - static_assert((CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC) >= 1, - "Spec requires the minimum of supported clients per fabric be equal or greater to 1."); - uint16_t mFabricClientsSupported = CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC; -}; - -} // namespace chip diff --git a/src/app/icd/ICDManager.cpp b/src/app/icd/ICDManager.cpp index ff95474b7d245d..eac574ca20ab2d 100644 --- a/src/app/icd/ICDManager.cpp +++ b/src/app/icd/ICDManager.cpp @@ -18,8 +18,9 @@ #include #include #include +#include #include -#include +#include #include #include #include @@ -29,13 +30,6 @@ #include #include -#include - -#ifndef ICD_ENFORCE_SIT_SLOW_POLL_LIMIT -// Set to 1 to enforce SIT Slow Polling Max value to 15seconds (spec 9.16.1.5) -#define ICD_ENFORCE_SIT_SLOW_POLL_LIMIT 0 -#endif - namespace chip { namespace app { @@ -70,11 +64,9 @@ void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricT mSymmetricKeystore = symmetricKeystore; mExchangeManager = exchangeManager; - ICDManagementServer::GetInstance().SetSymmetricKeystore(mSymmetricKeystore); - // 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 = ICDConfigurationData::GetInstance().GetActiveModeDurationMs(); // VerifyOrDie(kFastPollingInterval.count() < activeModeDuration); UpdateICDMode(); @@ -88,7 +80,7 @@ void ICDManager::Shutdown() DeviceLayer::SystemLayer().CancelTimer(OnIdleModeDone, this); DeviceLayer::SystemLayer().CancelTimer(OnActiveModeDone, this); DeviceLayer::SystemLayer().CancelTimer(OnTransitionToIdle, this); - mICDMode = ICDMode::SIT; + ICDConfigurationData::GetInstance().SetICDMode(ICDConfigurationData::ICDMode::SIT); mOperationalState = OperationalState::ActiveMode; mStorage = nullptr; mFabricTable = nullptr; @@ -115,7 +107,7 @@ void ICDManager::SendCheckInMsgs() VerifyOrDie(mFabricTable != nullptr); for (const auto & fabricInfo : *mFabricTable) { - uint16_t supported_clients = ICDManagementServer::GetInstance().GetClientsSupportedPerFabric(); + uint16_t supported_clients = ICDConfigurationData::GetInstance().GetClientsSupportedPerFabric(); ICDMonitoringTable table(*mStorage, fabricInfo.GetFabricIndex(), supported_clients /*Table entry limit*/, mSymmetricKeystore); @@ -165,7 +157,7 @@ void ICDManager::UpdateICDMode() { assertChipStackLockedByCurrentThread(); - ICDMode tempMode = ICDMode::SIT; + ICDConfigurationData::ICDMode tempMode = ICDConfigurationData::ICDMode::SIT; // Device can only switch to the LIT operating mode if LIT support is present if (SupportsFeature(Feature::kLongIdleTimeSupport)) @@ -179,23 +171,24 @@ void ICDManager::UpdateICDMode() ICDMonitoringTable table(*mStorage, fabricInfo.GetFabricIndex(), 1 /*Table entry limit*/, mSymmetricKeystore); if (!table.IsEmpty()) { - tempMode = ICDMode::LIT; + tempMode = ICDConfigurationData::ICDMode::LIT; break; } } } - if (mICDMode != tempMode) + if (ICDConfigurationData::GetInstance().GetICDMode() != tempMode) { - mICDMode = tempMode; + ICDConfigurationData::GetInstance().SetICDMode(tempMode); postObserverEvent(ObserverEventType::ICDModeChange); } // When in SIT mode, the slow poll interval SHOULDN'T be greater than the SIT mode polling threshold, per spec. - if (mICDMode == ICDMode::SIT && GetSlowPollingInterval() > GetSITPollingThreshold()) + if (ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::SIT && + ICDConfigurationData::GetInstance().GetSlowPollingInterval() > ICDConfigurationData::GetInstance().GetSITPollingThreshold()) { ChipLogDetail(AppServer, "The Slow Polling Interval of an ICD in SIT mode should be <= %" PRIu32 " seconds", - (GetSITPollingThreshold().count() / 1000)); + (ICDConfigurationData::GetInstance().GetSITPollingThreshold().count() / 1000)); } } @@ -210,17 +203,18 @@ 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 (ICDConfigurationData::GetInstance().GetActiveModeDurationMs() > 0) { - uint32_t idleModeDuration = ICDManagementServer::GetInstance().GetIdleModeDurationSec(); + uint32_t idleModeDuration = ICDConfigurationData::GetInstance().GetIdleModeDurationSec(); DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(idleModeDuration), OnIdleModeDone, this); } - System::Clock::Milliseconds32 slowPollInterval = GetSlowPollingInterval(); + System::Clock::Milliseconds32 slowPollInterval = ICDConfigurationData::GetInstance().GetSlowPollingInterval(); #if ICD_ENFORCE_SIT_SLOW_POLL_LIMIT // When in SIT mode, the slow poll interval SHOULDN'T be greater than the SIT mode polling threshold, per spec. - if (mICDMode == ICDMode::SIT && GetSlowPollingInterval() > GetSITPollingThreshold()) + if (ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::SIT && + GetSlowPollingInterval() > GetSITPollingThreshold()) { slowPollInterval = GetSITPollingThreshold(); } @@ -244,13 +238,13 @@ void ICDManager::UpdateOperationState(OperationalState state) DeviceLayer::SystemLayer().CancelTimer(OnIdleModeDone, this); mOperationalState = OperationalState::ActiveMode; - uint32_t activeModeDuration = ICDManagementServer::GetInstance().GetActiveModeDurationMs(); + uint32_t activeModeDuration = ICDConfigurationData::GetInstance().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 = ICDConfigurationData::GetInstance().GetActiveModeThresholdMs(); } DeviceLayer::SystemLayer().StartTimer(System::Clock::Timeout(activeModeDuration), OnActiveModeDone, this); @@ -259,7 +253,8 @@ void ICDManager::UpdateOperationState(OperationalState state) (activeModeDuration >= ICD_ACTIVE_TIME_JITTER_MS) ? activeModeDuration - ICD_ACTIVE_TIME_JITTER_MS : 0; DeviceLayer::SystemLayer().StartTimer(System::Clock::Timeout(activeModeJitterInterval), OnTransitionToIdle, this); - CHIP_ERROR err = DeviceLayer::ConnectivityMgr().SetPollingInterval(GetFastPollingInterval()); + CHIP_ERROR err = + DeviceLayer::ConnectivityMgr().SetPollingInterval(ICDConfigurationData::GetInstance().GetFastPollingInterval()); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "Failed to set Fast Polling Interval: err %" CHIP_ERROR_FORMAT, err.Format()); @@ -274,7 +269,7 @@ void ICDManager::UpdateOperationState(OperationalState state) } else { - uint16_t activeModeThreshold = ICDManagementServer::GetInstance().GetActiveModeThresholdMs(); + uint16_t activeModeThreshold = ICDConfigurationData::GetInstance().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; @@ -433,20 +428,6 @@ void ICDManager::OnICDManagementServerEvent(ICDManagementEvents event) } } -System::Clock::Milliseconds32 ICDManager::GetSlowPollingInterval() -{ -#if ICD_ENFORCE_SIT_SLOW_POLL_LIMIT - // When in SIT mode, the slow poll interval SHOULDN'T be greater than the SIT mode polling threshold, per spec. - // This is important for ICD device configured for LIT operation but currently operating as a SIT - // due to a lack of client registration - if (mICDMode == ICDMode::SIT && GetSlowPollingInterval() > GetSITPollingThreshold()) - { - return GetSITPollingThreshold(); - } -#endif - return kSlowPollingInterval; -} - ICDManager::ObserverPointer * ICDManager::RegisterObserver(ICDStateObserver * observer) { return mStateObserverPool.CreateObject(observer); diff --git a/src/app/icd/ICDManager.h b/src/app/icd/ICDManager.h index 662a15602cf455..7958adada0de63 100644 --- a/src/app/icd/ICDManager.h +++ b/src/app/icd/ICDManager.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -54,12 +55,6 @@ class ICDManager : public ICDListener ActiveMode, }; - enum class ICDMode : uint8_t - { - SIT, // Short Interval Time ICD - LIT, // Long Interval Time ICD - }; - // This enum class represents to all ICDStateObserver callbacks available from the // mStateObserverPool for the ICDManager. enum class ObserverEventType : uint8_t @@ -78,7 +73,7 @@ class ICDManager : public ICDListener void SetKeepActiveModeRequirements(KeepActiveFlags flag, bool state); bool IsKeepActive() { return mKeepActiveFlags.HasAny(); } bool SupportsFeature(Clusters::IcdManagement::Feature feature); - + ICDConfigurationData::ICDMode GetICDMode() { return ICDConfigurationData::GetInstance().GetICDMode(); }; /** * @brief Adds the referenced observer in parameters to the mStateObserverPool * A maximum of CHIP_CONFIG_ICD_OBSERVERS_POOL_SIZE observers can be concurrently registered @@ -97,14 +92,9 @@ class ICDManager : public ICDListener * ICDStateObservers function and calls it for all observers in the mStateObserverPool */ void postObserverEvent(ObserverEventType event); - ICDMode GetICDMode() { return mICDMode; } OperationalState GetOperationalState() { return mOperationalState; } void SendCheckInMsgs(); - static System::Clock::Milliseconds32 GetSITPollingThreshold() { return kSITPollingThreshold; } - static System::Clock::Milliseconds32 GetFastPollingInterval() { return kFastPollingInterval; } - static System::Clock::Milliseconds32 GetSlowPollingInterval(); - #ifdef CONFIG_BUILD_FOR_HOST_UNIT_TEST void SetTestFeatureMapValue(uint32_t featureMap) { mFeatureMap = featureMap; }; #endif @@ -134,21 +124,10 @@ class ICDManager : public ICDListener uint8_t mCheckInRequestCount = 0; private: - // SIT ICDs should have a SlowPollingThreshold shorter than or equal to 15s (spec 9.16.1.5) - static constexpr System::Clock::Milliseconds32 kSITPollingThreshold = System::Clock::Milliseconds32(15000); - static constexpr System::Clock::Milliseconds32 kSlowPollingInterval = CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL; - static constexpr System::Clock::Milliseconds32 kFastPollingInterval = CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL; - - // Minimal constraint value of the the ICD attributes. - static constexpr uint32_t kMinIdleModeDuration = 500; - static constexpr uint32_t kMinActiveModeDuration = 300; - static constexpr uint16_t kMinActiveModeThreshold = 300; - KeepActiveFlags mKeepActiveFlags{ 0 }; // Initialize mOperationalState to ActiveMode so the init sequence at bootup triggers the IdleMode behaviour first. OperationalState mOperationalState = OperationalState::ActiveMode; - ICDMode mICDMode = ICDMode::SIT; PersistentStorageDelegate * mStorage = nullptr; FabricTable * mFabricTable = nullptr; Messaging::ExchangeManager * mExchangeManager = nullptr; diff --git a/src/app/icd/ICDNotifier.h b/src/app/icd/ICDNotifier.h index 8c77811963d638..ef427f125ac32a 100644 --- a/src/app/icd/ICDNotifier.h +++ b/src/app/icd/ICDNotifier.h @@ -20,8 +20,6 @@ #include #include -class ICDListener; - namespace chip { namespace app { diff --git a/src/app/server/Dnssd.cpp b/src/app/server/Dnssd.cpp index cb627af4348dea..81c3754b891412 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() == ICDConfigurationData::ICDMode::LIT)); } } #endif diff --git a/src/app/server/Dnssd.h b/src/app/server/Dnssd.h index be1ec4fc09ccbb..6a9af18cda1dea 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 eab07e178b6e2f..daaf110acf26ed 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -271,6 +271,13 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) app::DnssdServer::Instance().SetUnsecuredPort(mUserDirectedCommissioningPort); app::DnssdServer::Instance().SetInterfaceId(mInterfaceId); +#if CHIP_CONFIG_ENABLE_ICD_SERVER + // We set the ICDManager reference betfore calling the ICDManager init due to the init ordering limitations. + // DnssdServer will use the default value initially and will update advertisement once ICDManager + // init is called. + app::DnssdServer::Instance().SetICDManager(&mICDManager); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER + if (GetFabricTable().FabricCount() != 0) { // The device is already commissioned, proactively disable BLE advertisement. @@ -321,11 +328,14 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) // ICD Init needs to be after data model init and InteractionModel Init #if CHIP_CONFIG_ENABLE_ICD_SERVER - mICDManager.Init(mDeviceStorage, &GetFabricTable(), mSessionKeystore, &mExchangeMgr); - // Register the ICDStateObservers. All observers are released at mICDManager.Shutdown() - // They can be released individually with ReleaseObserver + + // Register the ICDStateObservers. + // Call register before init so that observers are notified of any state change during the init. + // All observers are released at mICDManager.Shutdown(). They can be released individually with ReleaseObserver mICDManager.RegisterObserver(mReportScheduler); mICDManager.RegisterObserver(&app::DnssdServer::Instance()); + + mICDManager.Init(mDeviceStorage, &GetFabricTable(), mSessionKeystore, &mExchangeMgr); #endif // CHIP_CONFIG_ENABLE_ICD_SERVER // This code is necessary to restart listening to existing groups after a reboot @@ -495,9 +505,11 @@ void Server::Shutdown() PlatformMgr().RemoveEventHandler(OnPlatformEventWrapper, 0); mCASEServer.Shutdown(); mCASESessionManager.Shutdown(); +#if CHIP_CONFIG_ENABLE_ICD_SERVER + app::DnssdServer::Instance().SetICDManager(nullptr); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER app::DnssdServer::Instance().SetCommissioningModeProvider(nullptr); chip::Dnssd::ServiceAdvertiser::Instance().Shutdown(); - chip::Dnssd::Resolver::Instance().Shutdown(); chip::app::InteractionModelEngine::GetInstance()->Shutdown(); mCommissioningWindowManager.Shutdown(); diff --git a/src/app/tests/TestICDManager.cpp b/src/app/tests/TestICDManager.cpp index f503363ec63049..e3ca6eccbea768 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 @@ -143,22 +143,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(ICDConfigurationData::GetInstance().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, ICDConfigurationData::GetInstance().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(ICDConfigurationData::GetInstance().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, ICDConfigurationData::GetInstance().GetActiveModeDurationMs() - 1); ICDNotifier::GetInstance().BroadcastNetworkActivityNotification(); - AdvanceClockAndRunEventLoop(ctx, ICDManagementServer::GetInstance().GetActiveModeThresholdMs() / 2); + AdvanceClockAndRunEventLoop(ctx, ICDConfigurationData::GetInstance().GetActiveModeThresholdMs() / 2); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); - AdvanceClockAndRunEventLoop(ctx, ICDManagementServer::GetInstance().GetActiveModeThresholdMs()); + AdvanceClockAndRunEventLoop(ctx, ICDConfigurationData::GetInstance().GetActiveModeThresholdMs()); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); } @@ -172,7 +173,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, ICDConfigurationData::GetInstance().GetActiveModeDurationMs() + 1); // Requirement flag still set. We stay in active mode NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); @@ -186,12 +187,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, ICDConfigurationData::GetInstance().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, ICDConfigurationData::GetInstance().GetActiveModeDurationMs() + 1); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); // Set two requirements @@ -199,7 +200,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, ICDConfigurationData::GetInstance().GetActiveModeDurationMs() + 1); // A requirement flag is still set. We stay in active mode. NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); @@ -226,13 +227,13 @@ class TestICDManager ctx->mICDManager.SetTestFeatureMapValue(0x07); // Check ICDManager starts in SIT mode if no entries are present - NL_TEST_ASSERT(aSuite, ctx->mICDManager.GetICDMode() == ICDManager::ICDMode::SIT); + NL_TEST_ASSERT(aSuite, ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::SIT); // Trigger a "fake" register, ICDManager shoudl remain in SIT mode notifier.BroadcastICDManagementEvent(ICDMEvent::kTableUpdated); // Check ICDManager stayed in SIT mode - NL_TEST_ASSERT(aSuite, ctx->mICDManager.GetICDMode() == ICDManager::ICDMode::SIT); + NL_TEST_ASSERT(aSuite, ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::SIT); // Create tables with different fabrics ICDMonitoringTable table1(ctx->testStorage, kTestFabricIndex1, kMaxTestClients, &(ctx->mKeystore)); @@ -249,7 +250,7 @@ class TestICDManager notifier.BroadcastICDManagementEvent(ICDMEvent::kTableUpdated); // Check ICDManager is now in the LIT operating mode - NL_TEST_ASSERT(aSuite, ctx->mICDManager.GetICDMode() == ICDManager::ICDMode::LIT); + NL_TEST_ASSERT(aSuite, ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::LIT); // Add second entry to the first fabric ICDMonitoringEntry entry2(&(ctx->mKeystore)); @@ -262,7 +263,7 @@ class TestICDManager notifier.BroadcastICDManagementEvent(ICDMEvent::kTableUpdated); // Check ICDManager is now in the LIT operating mode - NL_TEST_ASSERT(aSuite, ctx->mICDManager.GetICDMode() == ICDManager::ICDMode::LIT); + NL_TEST_ASSERT(aSuite, ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::LIT); // Add first entry to the first fabric ICDMonitoringEntry entry3(&(ctx->mKeystore)); @@ -275,7 +276,7 @@ class TestICDManager notifier.BroadcastICDManagementEvent(ICDMEvent::kTableUpdated); // Check ICDManager is now in the LIT operating mode - NL_TEST_ASSERT(aSuite, ctx->mICDManager.GetICDMode() == ICDManager::ICDMode::LIT); + NL_TEST_ASSERT(aSuite, ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::LIT); // Add second entry to the first fabric ICDMonitoringEntry entry4(&(ctx->mKeystore)); @@ -291,7 +292,7 @@ class TestICDManager notifier.BroadcastICDManagementEvent(ICDMEvent::kTableUpdated); // Check ICDManager is still in the LIT operating mode - NL_TEST_ASSERT(aSuite, ctx->mICDManager.GetICDMode() == ICDManager::ICDMode::LIT); + NL_TEST_ASSERT(aSuite, ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::LIT); // Remove single entry from remaining fabric NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == table1.Remove(1)); @@ -300,7 +301,7 @@ class TestICDManager notifier.BroadcastICDManagementEvent(ICDMEvent::kTableUpdated); // Check ICDManager is still in the LIT operating mode - NL_TEST_ASSERT(aSuite, ctx->mICDManager.GetICDMode() == ICDManager::ICDMode::LIT); + NL_TEST_ASSERT(aSuite, ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::LIT); // Remove last entry from remaining fabric NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == table1.Remove(0)); @@ -311,7 +312,7 @@ class TestICDManager notifier.BroadcastICDManagementEvent(ICDMEvent::kTableUpdated); // Check ICDManager is still in the LIT operating mode - NL_TEST_ASSERT(aSuite, ctx->mICDManager.GetICDMode() == ICDManager::ICDMode::SIT); + NL_TEST_ASSERT(aSuite, ICDConfigurationData::GetInstance().GetICDMode() == ICDConfigurationData::ICDMode::SIT); } }; diff --git a/src/messaging/BUILD.gn b/src/messaging/BUILD.gn index b32099e8617b49..4c8ba1b9cb243c 100644 --- a/src/messaging/BUILD.gn +++ b/src/messaging/BUILD.gn @@ -79,6 +79,9 @@ static_library("messaging") { ] if (chip_enable_icd_server) { - public_deps += [ "${chip_root}/src/app/icd:notifier" ] + public_deps += [ + "${chip_root}/src/app/icd:configuration-data", + "${chip_root}/src/app/icd:notifier", + ] } } diff --git a/src/messaging/ReliableMessageMgr.cpp b/src/messaging/ReliableMessageMgr.cpp index 4ddf1801da0ade..f5731be868d7dd 100644 --- a/src/messaging/ReliableMessageMgr.cpp +++ b/src/messaging/ReliableMessageMgr.cpp @@ -24,8 +24,6 @@ #include #include -#include - #include #include #include @@ -35,10 +33,12 @@ #include #include #include +#include #include #if CHIP_CONFIG_ENABLE_ICD_SERVER -#include // nogncheck +#include // nogncheck +#include // nogncheck #endif using namespace chip::System::Clock::Literals; @@ -259,7 +259,7 @@ System::Clock::Timestamp ReliableMessageMgr::GetBackoff(System::Clock::Timestamp // Implement: // "An ICD sender SHOULD increase t to also account for its own sleepy interval // required to receive the acknowledgment" - mrpBackoffTime += CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL; + mrpBackoffTime += ICDConfigurationData::GetInstance().GetFastPollingInterval(); #endif mrpBackoffTime += CHIP_CONFIG_MRP_RETRY_INTERVAL_SENDER_BOOST; diff --git a/src/messaging/ReliableMessageProtocolConfig.cpp b/src/messaging/ReliableMessageProtocolConfig.cpp index c81325432cc51b..46d4b4b675b405 100644 --- a/src/messaging/ReliableMessageProtocolConfig.cpp +++ b/src/messaging/ReliableMessageProtocolConfig.cpp @@ -29,6 +29,10 @@ #include +#if CHIP_CONFIG_ENABLE_ICD_SERVER +#include // nogncheck +#endif + namespace chip { using namespace System::Clock::Literals; @@ -70,9 +74,9 @@ Optional GetLocalMRPConfig() // TODO ICD LIT shall not advertise the SII key // Increase local MRP retry intervals by ICD polling intervals. That is, intervals for // which the device can be at sleep and not be able to receive any messages). - config.mIdleRetransTimeout += CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL; - config.mActiveRetransTimeout += CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL; - config.mActiveThresholdTime = System::Clock::Milliseconds16(CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS); + config.mIdleRetransTimeout += ICDConfigurationData::GetInstance().GetSlowPollingInterval(); + config.mActiveRetransTimeout += ICDConfigurationData::GetInstance().GetFastPollingInterval(); + config.mActiveThresholdTime = System::Clock::Milliseconds16(ICDConfigurationData::GetInstance().GetActiveModeThresholdMs()); #endif #if CONFIG_BUILD_FOR_HOST_UNIT_TEST diff --git a/src/messaging/tests/BUILD.gn b/src/messaging/tests/BUILD.gn index 38ece653fe2f53..9b9e9f439a500a 100644 --- a/src/messaging/tests/BUILD.gn +++ b/src/messaging/tests/BUILD.gn @@ -18,6 +18,7 @@ import("//build_overrides/nlio.gni") import("//build_overrides/nlunit_test.gni") import("${chip_root}/build/chip/chip_test_suite.gni") +import("${chip_root}/src/app/icd/icd.gni") static_library("helpers") { output_name = "libMessagingTestHelpers" @@ -79,4 +80,8 @@ chip_test_suite_using_nltest("tests") { "${nlio_root}:nlio", "${nlunit_test_root}:nlunit-test", ] + + if (chip_enable_icd_server) { + public_deps += [ "${chip_root}/src/app/icd:configuration-data" ] + } } diff --git a/src/messaging/tests/TestAbortExchangesForFabric.cpp b/src/messaging/tests/TestAbortExchangesForFabric.cpp index 5bf92fb69b30d7..5354ee4cbde781 100644 --- a/src/messaging/tests/TestAbortExchangesForFabric.cpp +++ b/src/messaging/tests/TestAbortExchangesForFabric.cpp @@ -32,6 +32,10 @@ #include #include +#if CHIP_CONFIG_ENABLE_ICD_SERVER +#include // nogncheck +#endif + namespace { using namespace chip; @@ -209,7 +213,7 @@ void CommonCheckAbortAllButOneExchange(nlTestSuite * inSuite, TestContext & ctx, #if CHIP_CONFIG_ENABLE_ICD_SERVER == 1 // If running as an ICD, increase waitTimeout to account for the polling interval - waitTimeout += CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL; + waitTimeout += ICDConfigurationData::GetInstance().GetSlowPollingInterval(); #endif // Account for the retry delay booster, so that we do not timeout our IO processing before the diff --git a/src/messaging/tests/TestReliableMessageProtocol.cpp b/src/messaging/tests/TestReliableMessageProtocol.cpp index 6ef5f796abc25d..8c8443fd81d59e 100644 --- a/src/messaging/tests/TestReliableMessageProtocol.cpp +++ b/src/messaging/tests/TestReliableMessageProtocol.cpp @@ -45,6 +45,10 @@ #include #include +#if CHIP_CONFIG_ENABLE_ICD_SERVER +#include // nogncheck +#endif + namespace { using namespace chip; @@ -1832,7 +1836,7 @@ void TestReliableMessageProtocol::CheckGetBackoff(nlTestSuite * inSuite, void * auto maxBackoff = test.backoffMax + retryBoosterTimeout; #if CHIP_CONFIG_ENABLE_ICD_SERVER == 1 // If running as an ICD, increase maxBackoff to account for the polling interval - maxBackoff += CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL; + maxBackoff += ICDConfigurationData::GetInstance().GetSlowPollingInterval(); #endif NL_TEST_ASSERT(inSuite, backoff <= maxBackoff); } diff --git a/src/protocols/secure_channel/tests/BUILD.gn b/src/protocols/secure_channel/tests/BUILD.gn index ed6e0d8f527cac..26d0ec6b84a855 100644 --- a/src/protocols/secure_channel/tests/BUILD.gn +++ b/src/protocols/secure_channel/tests/BUILD.gn @@ -2,8 +2,8 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") import("//build_overrides/nlio.gni") import("//build_overrides/nlunit_test.gni") - import("${chip_root}/build/chip/chip_test_suite.gni") +import("${chip_root}/src/app/icd/icd.gni") chip_test_suite_using_nltest("tests") { output_name = "libSecureChannelTests" @@ -37,4 +37,8 @@ chip_test_suite_using_nltest("tests") { ] cflags = [ "-Wconversion" ] + + if (chip_enable_icd_server) { + public_deps += [ "${chip_root}/src/app/icd:configuration-data" ] + } } diff --git a/src/protocols/secure_channel/tests/TestPASESession.cpp b/src/protocols/secure_channel/tests/TestPASESession.cpp index b22a899f7225d0..c7c350fc3c80df 100644 --- a/src/protocols/secure_channel/tests/TestPASESession.cpp +++ b/src/protocols/secure_channel/tests/TestPASESession.cpp @@ -35,6 +35,10 @@ #include #include +#if CHIP_CONFIG_ENABLE_ICD_SERVER +#include // nogncheck +#endif + // This test suite pushes multiple PASESession objects onto the stack for the // purposes of testing device-to-device communication. However, in the real // world, these won't live in a single device's memory. Hence, disable stack @@ -294,7 +298,7 @@ void SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inContext, S #if CHIP_CONFIG_ENABLE_ICD_SERVER == 1 // If running as an ICD, increase waitTimeout to account for the polling interval - waitTimeout += CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL; + waitTimeout += ICDConfigurationData::GetInstance().GetSlowPollingInterval(); #endif // Wait some time so the dropped message will be retransmitted when we drain the IO.