From 9d0d0f1de932e3a8ae2e4a604ac13efeb8d3725c Mon Sep 17 00:00:00 2001 From: James Swan <122404367+swan-amazon@users.noreply.github.com> Date: Wed, 31 Jul 2024 21:23:29 +0000 Subject: [PATCH] Enable Terms and Conditions (TC) feature for AutoCommissioner This commit enables the Terms and Conditions (TC) feature in the all-clusters-app example application. The changes ensure that the app can handle TC acknowledgements and enforce required terms and conditions during the commissioning process. Changes include: - Added TC attributes and commands in the General Commissioning cluster. - Enabled the TC feature in the application configuration. This enables the TC feature logic in the example app, building on the initial implementation. --- .../all-clusters-common/all-clusters-app.zap | 82 ++++- examples/chip-tool/BUILD.gn | 3 +- .../commands/pairing/PairingCommand.cpp | 10 + .../commands/pairing/PairingCommand.h | 5 + .../general-commissioning-server.cpp | 330 ++++++++++-------- src/app/common_flags.gni | 4 + src/app/server/BUILD.gn | 46 ++- .../DefaultEnhancedSetupFlowProvider.cpp | 3 - .../server/DefaultEnhancedSetupFlowProvider.h | 36 +- .../DefaultTermsAndConditionsProvider.cpp | 39 ++- .../DefaultTermsAndConditionsProvider.h | 23 +- src/app/server/EnhancedSetupFlowProvider.h | 43 +-- src/app/server/Server.cpp | 113 +----- src/app/server/Server.h | 110 +++++- src/app/server/TermsAndConditionsProvider.h | 15 +- src/app/tests/BUILD.gn | 1 + .../TestDefaultEnhancedSetupFlowProvider.cpp | 94 +++-- .../TestDefaultTermsAndConditionsProvider.cpp | 94 +++-- src/controller/AutoCommissioner.cpp | 6 +- src/controller/CHIPDeviceController.cpp | 78 ++++- src/controller/CHIPDeviceController.h | 24 +- src/controller/CommissioningDelegate.cpp | 6 + src/controller/CommissioningDelegate.h | 16 +- src/lib/core/CHIPConfig.h | 54 +++ 24 files changed, 742 insertions(+), 493 deletions(-) diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 9a736eea56fa30..e8fe1662c95545 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -2172,6 +2172,22 @@ "source": "server", "isIncoming": 0, "isEnabled": 1 + }, + { + "name": "SetTCAcknowledgements", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "SetTCAcknowledgementsResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 } ], "attributes": [ @@ -2255,6 +2271,70 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "TCAcceptedVersion", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TCMinRequiredVersion", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TCAcknowledgements", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "bitmap16", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TCAcknowledgementsRequired", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "GeneratedCommandList", "code": 65528, @@ -2329,7 +2409,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "1", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/chip-tool/BUILD.gn b/examples/chip-tool/BUILD.gn index 94e1eebbde7508..ebc800cf719484 100644 --- a/examples/chip-tool/BUILD.gn +++ b/examples/chip-tool/BUILD.gn @@ -105,7 +105,8 @@ static_library("chip-tool-utils") { "${chip_root}/examples/common/tracing:commandline", "${chip_root}/src/app/icd/client:handler", "${chip_root}/src/app/icd/client:manager", - "${chip_root}/src/app/server", + + # "${chip_root}/src/app/server", "${chip_root}/src/app/tests/suites/commands/interaction_model", "${chip_root}/src/controller/data_model", "${chip_root}/src/credentials:file_attestation_trust_store", diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp index b583aa5f202bd4..8af21776e06e2b 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.cpp +++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp @@ -129,6 +129,16 @@ CommissioningParameters PairingCommand::GetCommissioningParameters() params.SetCountryCode(CharSpan::fromCharString(mCountryCode.Value())); } + if (mRequireTCAcknowledgements.HasValue()) + { + params.SetRequireTermsAndConditionsAcknowledgement(mRequireTCAcknowledgements.Value()); + } + else + { + // Default requiring TCs to false, to preserve release 1.3 chip-tool behavior + params.SetRequireTermsAndConditionsAcknowledgement(false); + } + // mTCAcknowledgements and mTCAcknowledgementVersion are optional, but related. When one is missing, default the value to 0, to // increase the test tools ability to test the applications. if (mTCAcknowledgements.HasValue() || mTCAcknowledgementVersion.HasValue()) diff --git a/examples/chip-tool/commands/pairing/PairingCommand.h b/examples/chip-tool/commands/pairing/PairingCommand.h index 1161c3b0950374..b21f13067da4ed 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.h +++ b/examples/chip-tool/commands/pairing/PairingCommand.h @@ -203,6 +203,10 @@ class PairingCommand : public CHIPCommand, "DSTOffset list to use when setting Time Synchronization cluster's DSTOffset attribute", Argument::kOptional); + AddArgument("require-tc-acknowledgements", 0, 1, &mRequireTCAcknowledgements, + "Terms and Conditions acknowledgements is known to be required or not, (when required, the commissioner " + "will wait until they are provided)"); + AddArgument("tc-acknowledgements", 0, UINT16_MAX, &mTCAcknowledgements, "Terms and Conditions acknowledgements to use to set the General Commissioning cluster's TC " "Acknowledgements bit-field"); @@ -267,6 +271,7 @@ class PairingCommand : public CHIPCommand, chip::Optional mICDMonitoredSubject; chip::Optional mICDClientType; chip::Optional mICDStayActiveDurationMsec; + chip::Optional mRequireTCAcknowledgements; chip::Optional mTCAcknowledgements; chip::Optional mTCAcknowledgementVersion; chip::app::DataModel::List mTimeZoneList; diff --git a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp index 9174b2ae7a6d6a..f69d93a5343b23 100644 --- a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp +++ b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp @@ -27,7 +27,9 @@ #include #include #include +#if CHIP_CONFIG_TC_REQUIRED #include +#endif #include #include #include @@ -46,146 +48,194 @@ using namespace chip::DeviceLayer; using Transport::SecureSession; using Transport::Session; -#define CheckSuccess(expr, code) \ +// Function that calls the given callable if it is a function pointer and not nullptr +template +void CallIfFunction(T callable) +{ + if constexpr (std::is_pointer::value && std::is_function::type>::value) + { + if (nullptr != callable) + { + callable(); + } + } +} + +#define CheckSuccess(expr, code, onSuccess, onFailure) \ do \ { \ if (!::chip::ChipError::IsSuccess(expr)) \ { \ commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::code, #expr); \ + CallIfFunction(onFailure); \ return true; \ } \ + CallIfFunction(onSuccess); \ } while (false) namespace { template -static CHIP_ERROR ReadInternal(Provider* const provider, CHIP_ERROR (Provider::*const getter)(T&), AttributeValueEncoder& aEncoder) +CHIP_ERROR ReadIfSupported(Provider * const provider, CHIP_ERROR (Provider::*const nonConstGetter)(T &), + AttributeValueEncoder & aEncoder) { - T data; - if (nullptr == provider) { return CHIP_ERROR_PERSISTED_STORAGE_FAILED; } - CHIP_ERROR err = (provider->*getter)(data); - if (err == CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE) - { - data = 0; - } - else if (err != CHIP_NO_ERROR) + T value; + CHIP_ERROR err = (provider->*nonConstGetter)(value); + if (err != CHIP_NO_ERROR) { return err; } - return aEncoder.Encode(data); + return aEncoder.Encode(value); } template -static CHIP_ERROR ReadInternal(Provider* const provider, CHIP_ERROR (Provider::*const getter)(T&) const, AttributeValueEncoder& aEncoder) +CHIP_ERROR ReadIfSupported(Provider * const provider, CHIP_ERROR (Provider::*const getter)(T &) const, + AttributeValueEncoder & aEncoder) { - // Removing the const qualifier from the getter function pointer because there are a handful of getter functions that are not correctly marked as const. - using NonConstGetter = CHIP_ERROR (Provider::*)(T&); + // Removing the const qualifier from the getter function pointer because there are a handful of getter functions that are not + // correctly marked as const. + using NonConstGetter = CHIP_ERROR (Provider::*)(T &); NonConstGetter nonConstGetter = reinterpret_cast(getter); - - return ReadInternal(provider, nonConstGetter, aEncoder); -} - -template -static CHIP_ERROR ReadIfSupported(Args &&... args) -{ - return ReadInternal(std::forward(args)...); + return ReadIfSupported(provider, nonConstGetter, aEncoder); } class GeneralCommissioningAttrAccess : public AttributeAccessInterface { public: - // Register for the GeneralCommissioning cluster on all endpoints. GeneralCommissioningAttrAccess() : AttributeAccessInterface(Optional::Missing(), GeneralCommissioning::Id) {} - CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; + CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) + { + if (aPath.mClusterId != GeneralCommissioning::Id) + { + // We shouldn't have been called at all. + return CHIP_ERROR_INVALID_ARGUMENT; + } + + switch (aPath.mAttributeId) + { + case RegulatoryConfig::Id: { + return ReadIfSupported(&DeviceLayer::ConfigurationMgr(), &ConfigurationManager::GetRegulatoryLocation, aEncoder); + } + case LocationCapability::Id: { + return ReadIfSupported(&DeviceLayer::ConfigurationMgr(), &ConfigurationManager::GetLocationCapability, aEncoder); + } + case BasicCommissioningInfo::Id: { + BasicCommissioningInfo::TypeInfo::Type basicCommissioningInfo; + + // TODO: The commissioner might use the critical parameters in BasicCommissioningInfo to initialize + // the CommissioningParameters at the beginning of commissioning flow. + basicCommissioningInfo.failSafeExpiryLengthSeconds = CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC; + basicCommissioningInfo.maxCumulativeFailsafeSeconds = CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC; + static_assert(CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC >= CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC, + "Max cumulative failsafe seconds must be larger than failsafe expiry length seconds"); + + return aEncoder.Encode(basicCommissioningInfo); + } + case SupportsConcurrentConnection::Id: { + SupportsConcurrentConnection::TypeInfo::Type supportsConcurrentConnection; + + // TODO: The commissioner might use the critical parameters in BasicCommissioningInfo to initialize + // the CommissioningParameters at the beginning of commissioning flow. + supportsConcurrentConnection = (CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION) != 0; -private: - CHIP_ERROR ReadBasicCommissioningInfo(AttributeValueEncoder & aEncoder); - CHIP_ERROR ReadSupportsConcurrentConnection(AttributeValueEncoder & aEncoder); + return aEncoder.Encode(supportsConcurrentConnection); + } +#if CHIP_CONFIG_TC_REQUIRED + case TCAcceptedVersion::Id: { + auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsAcceptedAcknowledgementsVersion; + return ReadIfSupported(provider, getter, aEncoder); + } + case TCMinRequiredVersion::Id: { + auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsRequiredAcknowledgementsVersion; + return ReadIfSupported(provider, getter, aEncoder); + } + case TCAcknowledgements::Id: { + auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsAcceptedAcknowledgements; + return ReadIfSupported(provider, getter, aEncoder); + } + case TCAcknowledgementsRequired::Id: { + auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsRequiredAcknowledgements; + return ReadIfSupported(provider, getter, aEncoder); + } +#endif + default: + break; + } + return CHIP_NO_ERROR; + } }; -GeneralCommissioningAttrAccess gAttrAccess; +GeneralCommissioningAttrAccess gAttributeAccessInstance; -CHIP_ERROR GeneralCommissioningAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +#if CHIP_CONFIG_TC_REQUIRED +CHIP_ERROR checkTermsAndConditionsAcknowledgementsState(CommissioningErrorEnum & errorCode) { - if (aPath.mClusterId != GeneralCommissioning::Id) + EnhancedSetupFlowProvider * enhancedSetupFlowProvider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + + CHIP_ERROR err; + + uint16_t termsAndConditionsAcceptedAcknowledgements; + bool hasRequiredTermAccepted; + bool hasRequiredTermVersionAccepted; + + err = enhancedSetupFlowProvider->GetTermsAndConditionsAcceptedAcknowledgements(termsAndConditionsAcceptedAcknowledgements); + if (!::chip::ChipError::IsSuccess(err)) { - // We shouldn't have been called at all. - return CHIP_ERROR_INVALID_ARGUMENT; + ChipLogError(AppServer, "Failed to GetTermsAndConditionsAcceptedAcknowledgements"); + return err; } - switch (aPath.mAttributeId) + err = enhancedSetupFlowProvider->HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasRequiredTermAccepted); + if (!::chip::ChipError::IsSuccess(err)) { - case RegulatoryConfig::Id: { - return ReadIfSupported(&DeviceLayer::ConfigurationMgr(), &ConfigurationManager::GetRegulatoryLocation, aEncoder); - } - case LocationCapability::Id: { - return ReadIfSupported(&DeviceLayer::ConfigurationMgr(), &ConfigurationManager::GetLocationCapability, aEncoder); - } - case BasicCommissioningInfo::Id: { - return ReadBasicCommissioningInfo(aEncoder); - } - case SupportsConcurrentConnection::Id: { - return ReadSupportsConcurrentConnection(aEncoder); - } -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) - case TCAcceptedVersion::Id: { - app::EnhancedSetupFlowProvider * provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); - auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsAcceptedAcknowledgementsVersion; - return ReadIfSupported(provider, getter, aEncoder); - } - case TCMinRequiredVersion::Id: { - auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); - auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsRequiredAcknowledgementsVersion; - return ReadIfSupported(provider, getter, aEncoder); - } - case TCAcknowledgements::Id: { - auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); - auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsAcceptedAcknowledgements; - return ReadIfSupported(provider, getter, aEncoder); - } - case TCAcknowledgementsRequired::Id: { - auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); - auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsRequiredAcknowledgements; - return ReadIfSupported(provider, getter, aEncoder); - } -#endif - default: - break; + ChipLogError(AppServer, "Failed to HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted"); + return err; } - return CHIP_NO_ERROR; -} - -CHIP_ERROR GeneralCommissioningAttrAccess::ReadBasicCommissioningInfo(AttributeValueEncoder & aEncoder) -{ - BasicCommissioningInfo::TypeInfo::Type basicCommissioningInfo; - // TODO: The commissioner might use the critical parameters in BasicCommissioningInfo to initialize - // the CommissioningParameters at the beginning of commissioning flow. - basicCommissioningInfo.failSafeExpiryLengthSeconds = CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC; - basicCommissioningInfo.maxCumulativeFailsafeSeconds = CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC; - static_assert(CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC >= CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC, - "Max cumulative failsafe seconds must be larger than failsafe expiry length seconds"); + err = + enhancedSetupFlowProvider->HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasRequiredTermVersionAccepted); + if (!::chip::ChipError::IsSuccess(err)) + { + ChipLogError(AppServer, "Failed to HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted"); + return err; + } - return aEncoder.Encode(basicCommissioningInfo); -} + if (!hasRequiredTermAccepted) + { + uint16_t requiredAcknowledgements = 0; + (void) enhancedSetupFlowProvider->GetTermsAndConditionsRequiredAcknowledgements(requiredAcknowledgements); -CHIP_ERROR GeneralCommissioningAttrAccess::ReadSupportsConcurrentConnection(AttributeValueEncoder & aEncoder) -{ - SupportsConcurrentConnection::TypeInfo::Type supportsConcurrentConnection; + ChipLogProgress(AppServer, "Required terms and conditions, 0x%04x,have not been accepted", requiredAcknowledgements); + errorCode = (0 == termsAndConditionsAcceptedAcknowledgements) ? CommissioningErrorEnum::kTCAcknowledgementsNotReceived + : CommissioningErrorEnum::kRequiredTCNotAccepted; + return CHIP_NO_ERROR; + } - // TODO: The commissioner might use the critical parameters in BasicCommissioningInfo to initialize - // the CommissioningParameters at the beginning of commissioning flow. - supportsConcurrentConnection = (CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION) != 0; + if (!hasRequiredTermVersionAccepted) + { + uint16_t requiredAcknowledgementsVersion = 0; + (void) enhancedSetupFlowProvider->GetTermsAndConditionsRequiredAcknowledgementsVersion(requiredAcknowledgementsVersion); + ChipLogProgress(AppServer, "Minimum terms and conditions version, 0x%04x, has not been accepted", + requiredAcknowledgementsVersion); + errorCode = CommissioningErrorEnum::kTCMinVersionNotMet; + return CHIP_NO_ERROR; + } - return aEncoder.Encode(supportsConcurrentConnection); + errorCode = CommissioningErrorEnum::kOk; + return CHIP_NO_ERROR; } +#endif } // anonymous namespace @@ -236,7 +286,7 @@ bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler * { CheckSuccess( failSafeContext.ArmFailSafe(accessingFabricIndex, System::Clock::Seconds16(commandData.expiryLengthSeconds)), - Failure); + Failure, nullptr, nullptr); Breadcrumb::Set(commandPath.mEndpointId, commandData.breadcrumb); response.errorCode = CommissioningErrorEnum::kOk; commandObj->AddResponse(commandPath, response); @@ -257,9 +307,6 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( { MATTER_TRACE_SCOPE("CommissioningComplete", "GeneralCommissioning"); -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) - EnhancedSetupFlowProvider * enhancedSetupFlowProvider = Server::GetInstance().GetEnhancedSetupFlowProvider(); -#endif DeviceControlServer * const devCtrl = &DeviceLayer::DeviceControlServer::DeviceControlSvr(); auto & failSafe = Server::GetInstance().GetFailSafeContext(); auto & fabricTable = Server::GetInstance().GetFabricTable(); @@ -287,62 +334,30 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( { CHIP_ERROR err; -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) - - uint16_t termsAndConditionsAcceptedAcknowledgements; - bool hasRequiredTermAccepted; - bool hasRequiredTermVersionAccepted; - - err = enhancedSetupFlowProvider->GetTermsAndConditionsAcceptedAcknowledgements( - termsAndConditionsAcceptedAcknowledgements); - CheckSuccess(err, Failure); - - err = enhancedSetupFlowProvider->HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted( - hasRequiredTermAccepted); - CheckSuccess(err, Failure); - - err = enhancedSetupFlowProvider->HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted( - hasRequiredTermVersionAccepted); - CheckSuccess(err, Failure); +#if CHIP_CONFIG_TC_REQUIRED + CheckSuccess(checkTermsAndConditionsAcknowledgementsState(response.errorCode), Failure, nullptr, nullptr); +#endif - if (!hasRequiredTermAccepted) + if (failSafe.NocCommandHasBeenInvoked()) { - ChipLogProgress(AppServer, "Required terms and conditions have not been accepted"); - Breadcrumb::Set(commandPath.mEndpointId, 0); - response.errorCode = (0 == termsAndConditionsAcceptedAcknowledgements) - ? CommissioningErrorEnum::kTCAcknowledgementsNotReceived - : CommissioningErrorEnum::kRequiredTCNotAccepted; + err = fabricTable.CommitPendingFabricData(); + CheckSuccess( + err, Failure, + []() { ChipLogProgress(FailSafe, "GeneralCommissioning: Successfully commited pending fabric data"); }, + []() { ChipLogError(FailSafe, "GeneralCommissioning: Failed to commit pending fabric data"); }); } - else if (!hasRequiredTermVersionAccepted) - { - ChipLogProgress(AppServer, "Minimum terms and conditions version has not been accepted"); - Breadcrumb::Set(commandPath.mEndpointId, 0); - response.errorCode = CommissioningErrorEnum::kTCMinVersionNotMet; - } + /* + * Pass fabric of commissioner to DeviceControlSvr. + * This allows device to send messages back to commissioner. + * Once bindings are implemented, this may no longer be needed. + */ + failSafe.DisarmFailSafe(); + err = devCtrl->PostCommissioningCompleteEvent(handle->AsSecureSession()->GetPeerNodeId(), handle->GetFabricIndex()); + CheckSuccess(err, Failure, nullptr, nullptr); - else -#endif - { - if (failSafe.NocCommandHasBeenInvoked()) - { - err = fabricTable.CommitPendingFabricData(); - CheckSuccess(err, Failure); - ChipLogProgress(FailSafe, "GeneralCommissioning: Successfully commited pending fabric data"); - } - - /* - * Pass fabric of commissioner to DeviceControlSvr. - * This allows device to send messages back to commissioner. - * Once bindings are implemented, this may no longer be needed. - */ - failSafe.DisarmFailSafe(); - err = devCtrl->PostCommissioningCompleteEvent(handle->AsSecureSession()->GetPeerNodeId(), handle->GetFabricIndex()); - CheckSuccess(err, Failure); - - Breadcrumb::Set(commandPath.mEndpointId, 0); - response.errorCode = CommissioningErrorEnum::kOk; - } + Breadcrumb::Set(commandPath.mEndpointId, 0); + response.errorCode = CommissioningErrorEnum::kOk; } } @@ -380,7 +395,7 @@ bool emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(app::CommandH uint8_t locationCapability; uint8_t location = to_underlying(commandData.newRegulatoryConfig); - CheckSuccess(ConfigurationMgr().GetLocationCapability(locationCapability), Failure); + CheckSuccess(ConfigurationMgr().GetLocationCapability(locationCapability), Failure, nullptr, nullptr); // If the LocationCapability attribute is not Indoor/Outdoor and the NewRegulatoryConfig value received does not match // either the Indoor or Outdoor fixed value in LocationCapability. @@ -393,7 +408,7 @@ bool emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(app::CommandH } else { - CheckSuccess(server->SetRegulatoryConfig(location, countryCode), Failure); + CheckSuccess(server->SetRegulatoryConfig(location, countryCode), Failure, nullptr, nullptr); Breadcrumb::Set(commandPath.mEndpointId, commandData.breadcrumb); response.errorCode = CommissioningErrorEnum::kOk; } @@ -408,18 +423,22 @@ bool emberAfGeneralCommissioningClusterSetTCAcknowledgementsCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::GeneralCommissioning::Commands::SetTCAcknowledgements::DecodableType & commandData) { -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) +#if !CHIP_CONFIG_TC_REQUIRED + return false; + +#else MATTER_TRACE_SCOPE("SetTCAcknowledgements", "GeneralCommissioning"); Commands::SetTCAcknowledgementsResponse::Type response; EnhancedSetupFlowProvider * const enhancedSetupFlowProvider = Server::GetInstance().GetEnhancedSetupFlowProvider(); uint16_t acknowledgements = commandData.TCUserResponse; uint16_t acknowledgementsVersion = commandData.TCVersion; - CheckSuccess(enhancedSetupFlowProvider->SetTermsAndConditionsAcceptance(acknowledgements, acknowledgementsVersion), Failure); - response.errorCode = CommissioningErrorEnum::kOk; - + CheckSuccess(enhancedSetupFlowProvider->SetTermsAndConditionsAcceptance(acknowledgements, acknowledgementsVersion), Failure, + nullptr, nullptr); + CheckSuccess(checkTermsAndConditionsAcknowledgementsState(response.errorCode), Failure, nullptr, nullptr); commandObj->AddResponse(commandPath, response); -#endif return true; + +#endif } namespace { @@ -429,6 +448,11 @@ void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t { // Spec says to reset Breadcrumb attribute to 0. Breadcrumb::Set(0, 0); + +#if CHIP_CONFIG_TC_REQUIRED + // Clear terms and conditions acceptance on failsafe timer expiration + Server::GetInstance().GetEnhancedSetupFlowProvider()->ClearTermsAndConditionsAcceptance(); +#endif } } @@ -437,7 +461,7 @@ void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t void MatterGeneralCommissioningPluginServerInitCallback() { Breadcrumb::Set(0, 0); - AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess); + registerAttributeAccessOverride(&gAttributeAccessInstance); DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler); } diff --git a/src/app/common_flags.gni b/src/app/common_flags.gni index be1149b2b67eb5..34e8549a35d1cd 100644 --- a/src/app/common_flags.gni +++ b/src/app/common_flags.gni @@ -18,6 +18,10 @@ declare_args() { chip_enable_read_client = true chip_build_controller_dynamic_server = false + chip_config_tc_required = false + chip_config_tc_required_acknowledgements = 0 + chip_config_tc_required_acknowledgements_version = 0 + # Flag that controls whether the time-to-wait from BUSY responses is # communicated to OperationalSessionSetup API consumers. chip_enable_busy_handling_for_operational_session_setup = true diff --git a/src/app/server/BUILD.gn b/src/app/server/BUILD.gn index 10627a8c2d2b36..e49513ad398d4f 100644 --- a/src/app/server/BUILD.gn +++ b/src/app/server/BUILD.gn @@ -24,6 +24,41 @@ config("server_config") { } } +config("enhanced_setup_flow_config") { + defines = [] + if (chip_config_tc_required) { + defines += [ + "CHIP_CONFIG_TC_REQUIRED=1", + "CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS=${chip_config_tc_required_acknowledgements}", + "CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION=${chip_config_tc_required_acknowledgements_version}", + ] + } else { + defines += [ "CHIP_CONFIG_TC_REQUIRED=0" ] + } +} + +source_set("enhanced_setup_flow_interface") { + sources = [ + "DefaultEnhancedSetupFlowProvider.h", + "DefaultTermsAndConditionsProvider.h", + "EnhancedSetupFlowProvider.h", + "TermsAndConditionsProvider.h", + ] + + public_configs = [ ":enhanced_setup_flow_config" ] + + public_deps = [ "${chip_root}/src/lib/core" ] +} + +source_set("enhanced_setup_flow") { + sources = [ + "DefaultEnhancedSetupFlowProvider.cpp", + "DefaultTermsAndConditionsProvider.cpp", + ] + + deps = [ ":enhanced_setup_flow_interface" ] +} + static_library("server") { output_name = "libCHIPAppServer" @@ -36,20 +71,14 @@ static_library("server") { "CommissioningWindowManager.h", "DefaultAclStorage.cpp", "DefaultAclStorage.h", - "DefaultEnhancedSetupFlowProvider.cpp", - "DefaultEnhancedSetupFlowProvider.h", - "DefaultTermsAndConditionsProvider.cpp", - "DefaultTermsAndConditionsProvider.h", "Dnssd.cpp", "Dnssd.h", "EchoHandler.cpp", "EchoHandler.h", - "EnhancedSetupFlowProvider.h", "OnboardingCodesUtil.cpp", "OnboardingCodesUtil.h", "Server.cpp", "Server.h", - "TermsAndConditionsProvider.h", ] public_configs = [ ":server_config" ] @@ -57,6 +86,7 @@ static_library("server") { cflags = [ "-Wconversion" ] public_deps = [ + ":enhanced_setup_flow_interface", "${chip_root}/src/app", "${chip_root}/src/app:test-event-trigger", "${chip_root}/src/app/icd/server:check-in-back-off", @@ -85,4 +115,8 @@ static_library("server") { [ "${chip_root}/src/app/icd/server:default-check-in-back-off" ] } } + + if (chip_config_tc_required) { + public_deps += [ ":enhanced_setup_flow" ] + } } diff --git a/src/app/server/DefaultEnhancedSetupFlowProvider.cpp b/src/app/server/DefaultEnhancedSetupFlowProvider.cpp index b57c0381610e3c..e82af06ad5b014 100644 --- a/src/app/server/DefaultEnhancedSetupFlowProvider.cpp +++ b/src/app/server/DefaultEnhancedSetupFlowProvider.cpp @@ -16,13 +16,10 @@ * limitations under the License. */ -#include - #include "DefaultEnhancedSetupFlowProvider.h" #include #include -#include CHIP_ERROR chip::app::DefaultEnhancedSetupFlowProvider::Init(TermsAndConditionsProvider * const inTermsAndConditionsProvider) { diff --git a/src/app/server/DefaultEnhancedSetupFlowProvider.h b/src/app/server/DefaultEnhancedSetupFlowProvider.h index fc209cb410c334..52bbd7ab68ac4d 100644 --- a/src/app/server/DefaultEnhancedSetupFlowProvider.h +++ b/src/app/server/DefaultEnhancedSetupFlowProvider.h @@ -18,12 +18,11 @@ #pragma once -#include - #include "EnhancedSetupFlowProvider.h" #include +#include #include #include "TermsAndConditionsProvider.h" @@ -37,53 +36,28 @@ class DefaultEnhancedSetupFlowProvider : public EnhancedSetupFlowProvider * @brief Initializes the EnhancedSetupFlowProvider. * * @param[in] inTermsAndConditionsProvider The terms and conditions provide dependency. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ CHIP_ERROR Init(TermsAndConditionsProvider * const inTermsAndConditionsProvider); - /** - * @copydoc EnhancedSetupFlowProvider::HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted - */ CHIP_ERROR HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(bool & outAccepted) const override; - /** - * @copydoc EnhancedSetupFlowProvider::HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted - */ CHIP_ERROR HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(bool & outAccepted) const override; - /** - * @copydoc EnhancedSetupFlowProvider::GetTermsAndConditionsRequiredAcknowledgements - */ CHIP_ERROR GetTermsAndConditionsRequiredAcknowledgements(uint16_t & outValue) const override; - /** - * @copydoc EnhancedSetupFlowProvider::GetTermsAndConditionsRequiredAcknowledgementsVersion - */ CHIP_ERROR GetTermsAndConditionsRequiredAcknowledgementsVersion(uint16_t & outValue) const override; - /** - * @copydoc EnhancedSetupFlowProvider::GetTermsAndConditionsAcceptedAcknowledgements - */ CHIP_ERROR GetTermsAndConditionsAcceptedAcknowledgements(uint16_t & outValue) const override; - /** - * @copydoc EnhancedSetupFlowProvider::GetTermsAndConditionsAcceptedAcknowledgementsVersion - */ CHIP_ERROR GetTermsAndConditionsAcceptedAcknowledgementsVersion(uint16_t & outValue) const override; - /** - * @copydoc EnhancedSetupFlowProvider::SetTermsAndConditionsAcceptance - */ - CHIP_ERROR SetTermsAndConditionsAcceptance(uint16_t aTCAcknowledgements, uint16_t aTCAcknowledgementsVersion) override; + CHIP_ERROR SetTermsAndConditionsAcceptance(uint16_t aTCAcknowledgements, uint16_t inTCAcknowledgementsVersionValue) override; - /** - * @copydoc EnhancedSetupFlowProvider::ClearTermsAndConditionsAcceptance - */ CHIP_ERROR ClearTermsAndConditionsAcceptance() override; private: - TermsAndConditionsProvider * mTermsAndConditionsProvider; /**< TermsAndConditionsProvider instance. */ + TermsAndConditionsProvider * mTermsAndConditionsProvider; }; -}; // namespace app -}; // namespace chip +} // namespace app +} // namespace chip diff --git a/src/app/server/DefaultTermsAndConditionsProvider.cpp b/src/app/server/DefaultTermsAndConditionsProvider.cpp index 564c80b16e783d..c38390823f04a2 100644 --- a/src/app/server/DefaultTermsAndConditionsProvider.cpp +++ b/src/app/server/DefaultTermsAndConditionsProvider.cpp @@ -23,13 +23,20 @@ #include #include #include -#include +#include namespace { -static constexpr chip::TLV::Tag kAcceptedAcknowledgementsTag = chip::TLV::ContextTag(1); -static constexpr chip::TLV::Tag kAcceptedAcknowledgementsVersionTag = chip::TLV::ContextTag(2); -static constexpr size_t kEstimatedTlvBufferSize = chip::TLV::EstimateStructOverhead(sizeof(uint16_t), sizeof(uint16_t)); -}; // namespace +constexpr chip::TLV::Tag kSerializationVersionTag = chip::TLV::ContextTag(1); +constexpr chip::TLV::Tag kAcceptedAcknowledgementsTag = chip::TLV::ContextTag(2); +constexpr chip::TLV::Tag kAcceptedAcknowledgementsVersionTag = chip::TLV::ContextTag(3); +constexpr uint8_t kSerializationVersion = 1; + +constexpr size_t kEstimatedTlvBufferSize = chip::TLV::EstimateStructOverhead(sizeof(uint8_t), // SerializationVersion + sizeof(uint16_t), // AcceptedAcknowledgements + sizeof(uint16_t) // AcceptedAcknowledgementsVersion + ) * + 2; // Extra space for rollback compatibility +} // namespace CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::Init(chip::PersistentStorageDelegate * const inPersistentStorageDelegate, uint16_t inRequiredAcknowledgementsValue, @@ -57,6 +64,7 @@ CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::ClearAcceptance() CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::GetAcceptance(uint16_t & outAcknowledgementsValue, uint16_t & outAcknowledgementsVersionValue) const { + uint8_t serializationVersion = 0; uint16_t acknowledgements = 0; uint16_t acknowledgementsVersion = 0; @@ -80,17 +88,22 @@ CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::GetAcceptance(uint16_t VerifyOrReturnError(CHIP_NO_ERROR == err, err); - tlvReader.Init(buffer); + tlvReader.Init(buffer, bufferSize); ReturnErrorOnFailure(tlvReader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag())); ReturnErrorOnFailure(tlvReader.EnterContainer(tlvContainer)); - ReturnErrorOnFailure(tlvReader.Next()); - ReturnErrorOnFailure(tlvReader.Expect(kAcceptedAcknowledgementsTag)); + ReturnErrorOnFailure(tlvReader.Next(kSerializationVersionTag)); + ReturnErrorOnFailure(tlvReader.Get(serializationVersion)); + ReturnErrorOnFailure(tlvReader.Next(kAcceptedAcknowledgementsTag)); ReturnErrorOnFailure(tlvReader.Get(acknowledgements)); - ReturnErrorOnFailure(tlvReader.Next()); - ReturnErrorOnFailure(tlvReader.Expect(kAcceptedAcknowledgementsVersionTag)); + ReturnErrorOnFailure(tlvReader.Next(kAcceptedAcknowledgementsVersionTag)); ReturnErrorOnFailure(tlvReader.Get(acknowledgementsVersion)); ReturnErrorOnFailure(tlvReader.ExitContainer(tlvContainer)); + if (kSerializationVersion != serializationVersion) + { + return CHIP_ERROR_VERSION_MISMATCH; + } + outAcknowledgementsValue = acknowledgements; outAcknowledgementsVersionValue = acknowledgementsVersion; @@ -117,13 +130,17 @@ CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::SetAcceptance(uint16_t tlvWriter.Init(buffer, sizeof(buffer)); ReturnErrorOnFailure(tlvWriter.StartContainer(chip::TLV::AnonymousTag(), chip::TLV::kTLVType_Structure, tlvContainer)); + ReturnErrorOnFailure(tlvWriter.Put(kSerializationVersionTag, kSerializationVersion)); ReturnErrorOnFailure(tlvWriter.Put(kAcceptedAcknowledgementsTag, inAcceptedAcknowledgementsValue)); ReturnErrorOnFailure(tlvWriter.Put(kAcceptedAcknowledgementsVersionTag, inAcceptedAcknowledgementsVersionValue)); ReturnErrorOnFailure(tlvWriter.EndContainer(tlvContainer)); ReturnErrorOnFailure(tlvWriter.Finalize()); + uint32_t lengthWritten = tlvWriter.GetLengthWritten(); + VerifyOrReturnError(CanCastTo(lengthWritten), CHIP_ERROR_BUFFER_TOO_SMALL); const chip::StorageKeyName storageKey = DefaultStorageKeyAllocator::TermsAndConditionsAcceptance(); - ReturnErrorOnFailure(mPersistentStorageDelegate->SyncSetKeyValue(storageKey.KeyName(), buffer, sizeof(buffer))); + ReturnErrorOnFailure( + mPersistentStorageDelegate->SyncSetKeyValue(storageKey.KeyName(), buffer, static_cast(lengthWritten))); return CHIP_NO_ERROR; } diff --git a/src/app/server/DefaultTermsAndConditionsProvider.h b/src/app/server/DefaultTermsAndConditionsProvider.h index 3205f98e57948a..4eec8a67ac04cf 100644 --- a/src/app/server/DefaultTermsAndConditionsProvider.h +++ b/src/app/server/DefaultTermsAndConditionsProvider.h @@ -18,8 +18,6 @@ #pragma once -#include - #include "TermsAndConditionsProvider.h" #include @@ -38,36 +36,23 @@ class DefaultTermsAndConditionsProvider : public TermsAndConditionsProvider * @param[in] inPersistentStorageDelegate Persistent storage delegate dependency. * @param[in] inRequiredAcknowledgementsValue The bitmask of required acknowledgements. * @param[in] inRequiredAcknowledgementsVersionValue The version of the required acknowledgements. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ - CHIP_ERROR Init(chip::PersistentStorageDelegate * const inPersistentStorageDelegate, uint16_t inRequiredAcknowledgementsValue, + CHIP_ERROR Init(PersistentStorageDelegate * const inPersistentStorageDelegate, uint16_t inRequiredAcknowledgementsValue, uint16_t inRequiredAcknowledgementsVersionValue); - /** - * @copydoc TermsAndConditionsProvider::ClearAcceptance - */ CHIP_ERROR ClearAcceptance() override; - /** - * @copydoc TermsAndConditionsProvider::GetAcceptance - */ CHIP_ERROR GetAcceptance(uint16_t & outAcknowledgementsValue, uint16_t & outAcknowledgementsVersionValue) const override; - /** - * @copydoc TermsAndConditionsProvider::GetRequirements - */ CHIP_ERROR GetRequirements(uint16_t & outAcknowledgementsValue, uint16_t & outAcknowledgementsVersionValue) const override; - /** - * @copydoc TermsAndConditionsProvider::SetAcceptance - */ CHIP_ERROR SetAcceptance(uint16_t inAcknowledgementsValue, uint16_t inAcknowledgementsVersionValue) override; private: - chip::PersistentStorageDelegate * mPersistentStorageDelegate; + PersistentStorageDelegate * mPersistentStorageDelegate; uint16_t mRequiredAcknowledgementsValue; uint16_t mRequiredAcknowledgementsVersionValue; }; -}; // namespace app -}; // namespace chip +} // namespace app +} // namespace chip diff --git a/src/app/server/EnhancedSetupFlowProvider.h b/src/app/server/EnhancedSetupFlowProvider.h index 063b9352d18013..2d62fb186ec597 100644 --- a/src/app/server/EnhancedSetupFlowProvider.h +++ b/src/app/server/EnhancedSetupFlowProvider.h @@ -18,8 +18,6 @@ #pragma once -#include - #include #include @@ -28,83 +26,56 @@ namespace chip { namespace app { /** - * @brief Feature state access layer for the EnhancedSetupFlowProvider. - * - * This class provides access to the state of the feature through the TermsAndConditionsProvider. + * This class provides access to the state of the Enhanced Setup Flow feature. */ class EnhancedSetupFlowProvider { public: - /** - * @brief Destructor. - */ virtual ~EnhancedSetupFlowProvider() = default; /** - * @brief Checks if the required terms and conditions acknowledgements have been accepted. - * * @param[out] outAccepted true if the required acknowledgements have been accepted, false otherwise. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ virtual CHIP_ERROR HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(bool & outAccepted) const = 0; /** - * @brief Checks if the required terms and conditions acknowledgements version has been accepted. - * * @param[out] outAccepted true if the required acknowledgements version has been accepted, false otherwise. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ virtual CHIP_ERROR HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(bool & outAccepted) const = 0; /** - * @brief Retrieves the required terms and conditions acknowledgements. - * * @param[out] outValue The version of the required acknowledgements. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ virtual CHIP_ERROR GetTermsAndConditionsRequiredAcknowledgements(uint16_t & outValue) const = 0; /** - * @brief Retrieves the required terms and conditions acknowledgements version. - * * @param[out] outValue The outValue of the required acknowledgements version. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ virtual CHIP_ERROR GetTermsAndConditionsRequiredAcknowledgementsVersion(uint16_t & outValue) const = 0; /** - * @brief Retrieves the accepted terms and conditions acknowledgements. - * * @param[out] outValue The outValue of the accepted acknowledgements. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ virtual CHIP_ERROR GetTermsAndConditionsAcceptedAcknowledgements(uint16_t & outValue) const = 0; /** - * @brief Retrieves the accepted terms and conditions acknowledgements version. - * * @param[out] outValue The outValue of the accepted acknowledgements version. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ virtual CHIP_ERROR GetTermsAndConditionsAcceptedAcknowledgementsVersion(uint16_t & outValue) const = 0; /** - * @brief Sets the acceptance status of the terms and conditions. - * * @param[in] inTCAcknowledgements The acknowledgements to accept. - * @param[in] inTCAcknowledgementsoutValue The version of the acknowledgements to accept. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. + * @param[in] inTCAcknowledgementsVersionValue The version of the acknowledgements to accept. */ virtual CHIP_ERROR SetTermsAndConditionsAcceptance(uint16_t inTCAcknowledgementsValue, - uint16_t inTCAcknowledgementsoutValue) = 0; + uint16_t inTCAcknowledgementsVersionValue) = 0; /** - * @brief Clears the acceptance status of the terms and conditions. - * - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. + * Reset the terms and conditions acceptance. The terms and conditions should be cleared on factory reset or if failure occurs + * during a failsafe context. */ virtual CHIP_ERROR ClearTermsAndConditionsAcceptance() = 0; }; -}; // namespace app -}; // namespace chip +} // namespace app +} // namespace chip diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 94915381275e23..85f507f4cf6c43 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -21,8 +21,6 @@ #include #include -#include -#include #include #include #include @@ -107,110 +105,6 @@ static ::chip::PersistedCounter sGlobalEventIdCounter; static ::chip::app::CircularEventBuffer sLoggingBuffer[CHIP_NUM_EVENT_LOGGING_BUFFERS]; #endif // CHIP_CONFIG_ENABLE_SERVER_IM_EVENT -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) -app::DefaultEnhancedSetupFlowProvider sDefaultEnhancedSetupFlowProviderInstance; -app::EnhancedSetupFlowProvider * CommonCaseDeviceServerInitParams::sDefaultEnhancedSetupFlowProvider = - &sDefaultEnhancedSetupFlowProviderInstance; - -app::DefaultTermsAndConditionsProvider sDefaultTermsAndConditionsProviderInstance; -app::TermsAndConditionsProvider * CommonCaseDeviceServerInitParams::sDefaultTermsAndConditionsProvider = - &sDefaultTermsAndConditionsProviderInstance; -#endif - -CHIP_ERROR CommonCaseDeviceServerInitParams::InitializeStaticResourcesBeforeServerInit() -{ - chip::DeviceLayer::PersistedStorage::KeyValueStoreManager & kvsManager = DeviceLayer::PersistedStorage::KeyValueStoreMgr(); - - // KVS-based persistent storage delegate injection - if (persistentStorageDelegate == nullptr) - { - ReturnErrorOnFailure(sKvsPersistenStorageDelegate.Init(&kvsManager)); - this->persistentStorageDelegate = &sKvsPersistenStorageDelegate; - } - - // PersistentStorageDelegate "software-based" operational key access injection - if (this->operationalKeystore == nullptr) - { - // WARNING: PersistentStorageOperationalKeystore::Finish() is never called. It's fine for - // for examples and for now. - ReturnErrorOnFailure(sPersistentStorageOperationalKeystore.Init(this->persistentStorageDelegate)); - this->operationalKeystore = &sPersistentStorageOperationalKeystore; - } - - // OpCertStore can be injected but default to persistent storage default - // for simplicity of the examples. - if (this->opCertStore == nullptr) - { - // WARNING: PersistentStorageOpCertStore::Finish() is never called. It's fine for - // for examples and for now, since all storage is immediate for that impl. - ReturnErrorOnFailure(sPersistentStorageOpCertStore.Init(this->persistentStorageDelegate)); - this->opCertStore = &sPersistentStorageOpCertStore; - } - - // Injection of report scheduler WILL lead to two schedulers being allocated. As recommended above, this should only be used - // for IN-TREE examples. If a default scheduler is desired, the basic ServerInitParams should be used by the application and - // CommonCaseDeviceServerInitParams should not be allocated. - if (this->reportScheduler == nullptr) - { - reportScheduler = &sReportScheduler; - } - -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) - if (this->termsAndConditionsProvider == nullptr) - { - ReturnErrorOnFailure(sDefaultTermsAndConditionsProviderInstance.Init(this->persistentStorageDelegate, - CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS, - CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION)); - this->termsAndConditionsProvider = sDefaultTermsAndConditionsProvider; - } - - if (this->enhancedSetupFlowProvider == nullptr) - { - ReturnErrorOnFailure(sDefaultEnhancedSetupFlowProviderInstance.Init(this->termsAndConditionsProvider)); - this->enhancedSetupFlowProvider = sDefaultEnhancedSetupFlowProvider; - } -#endif - - // Session Keystore injection - this->sessionKeystore = &sSessionKeystore; - - // Group Data provider injection - sGroupDataProvider.SetStorageDelegate(this->persistentStorageDelegate); - sGroupDataProvider.SetSessionKeystore(this->sessionKeystore); - ReturnErrorOnFailure(sGroupDataProvider.Init()); - this->groupDataProvider = &sGroupDataProvider; - -#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION - ReturnErrorOnFailure(sSessionResumptionStorage.Init(this->persistentStorageDelegate)); - this->sessionResumptionStorage = &sSessionResumptionStorage; -#else - this->sessionResumptionStorage = nullptr; -#endif - - // Inject access control delegate - this->accessDelegate = Access::Examples::GetAccessControlDelegate(); - - // Inject ACL storage. (Don't initialize it.) - this->aclStorage = &sAclStorage; - -#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS - ChipLogProgress(AppServer, "Initializing subscription resumption storage..."); - ReturnErrorOnFailure(sSubscriptionResumptionStorage.Init(this->persistentStorageDelegate)); - this->subscriptionResumptionStorage = &sSubscriptionResumptionStorage; -#else - ChipLogProgress(AppServer, "Subscription persistence not supported"); -#endif - -#if CHIP_CONFIG_ENABLE_ICD_CIP - if (this->icdCheckInBackOffStrategy == nullptr) - { - this->icdCheckInBackOffStrategy = &sDefaultICDCheckInBackOffStrategy; - } -#endif - - return CHIP_NO_ERROR; -} - CHIP_ERROR Server::Init(const ServerInitParams & initParams) { ChipLogProgress(AppServer, "Server initializing..."); @@ -235,10 +129,6 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) VerifyOrExit(initParams.operationalKeystore != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(initParams.opCertStore != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(initParams.reportScheduler != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) - VerifyOrExit(initParams.enhancedSetupFlowProvider != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(initParams.termsAndConditionsProvider != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); -#endif // TODO(16969): Remove chip::Platform::MemoryInit() call from Server class, it belongs to outer code chip::Platform::MemoryInit(); @@ -295,7 +185,7 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) mReportScheduler = initParams.reportScheduler; -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) +#if CHIP_CONFIG_TC_REQUIRED mTermsAndConditionsProvider = initParams.termsAndConditionsProvider; mEnhancedSetupFlowProvider = initParams.enhancedSetupFlowProvider; #endif @@ -701,6 +591,7 @@ void Server::ScheduleFactoryReset() GetInstance().GetFabricTable().DeleteAllFabrics(); PlatformMgr().HandleServerShuttingDown(); ConfigurationMgr().InitiateFactoryReset(); + // Clear accepted terms and conditions }); } diff --git a/src/app/server/Server.h b/src/app/server/Server.h index f9ef037df96c08..be9b592432bf59 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -33,6 +33,10 @@ #include #include #include +#if CHIP_CONFIG_TC_REQUIRED +#include +#include +#endif #include #include #include @@ -181,12 +185,10 @@ struct ServerInitParams // Optional. Support for the ICD Check-In BackOff strategy. Must be initialized before being provided. // If the ICD Check-In protocol use-case is supported and no strategy is provided, server will use the default strategy. app::ICDCheckInBackOffStrategy * icdCheckInBackOffStrategy = nullptr; -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) // Optional. Enhanced setup flow provider to support terms and conditions acceptance check. app::EnhancedSetupFlowProvider * enhancedSetupFlowProvider = nullptr; // Optional. Terms and conditions provider to support enhanced setup flow feature. app::TermsAndConditionsProvider * termsAndConditionsProvider = nullptr; -#endif }; /** @@ -233,7 +235,101 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams * @return CHIP_NO_ERROR on success or a CHIP_ERROR value from APIs called to initialize * resources on failure. */ - CHIP_ERROR InitializeStaticResourcesBeforeServerInit(); + CHIP_ERROR InitializeStaticResourcesBeforeServerInit() + { + // KVS-based persistent storage delegate injection + if (persistentStorageDelegate == nullptr) + { + chip::DeviceLayer::PersistedStorage::KeyValueStoreManager & kvsManager = + DeviceLayer::PersistedStorage::KeyValueStoreMgr(); + ReturnErrorOnFailure(sKvsPersistenStorageDelegate.Init(&kvsManager)); + this->persistentStorageDelegate = &sKvsPersistenStorageDelegate; + } + + // PersistentStorageDelegate "software-based" operational key access injection + if (this->operationalKeystore == nullptr) + { + // WARNING: PersistentStorageOperationalKeystore::Finish() is never called. It's fine for + // for examples and for now. + ReturnErrorOnFailure(sPersistentStorageOperationalKeystore.Init(this->persistentStorageDelegate)); + this->operationalKeystore = &sPersistentStorageOperationalKeystore; + } + + // OpCertStore can be injected but default to persistent storage default + // for simplicity of the examples. + if (this->opCertStore == nullptr) + { + // WARNING: PersistentStorageOpCertStore::Finish() is never called. It's fine for + // for examples and for now, since all storage is immediate for that impl. + ReturnErrorOnFailure(sPersistentStorageOpCertStore.Init(this->persistentStorageDelegate)); + this->opCertStore = &sPersistentStorageOpCertStore; + } + + // Injection of report scheduler WILL lead to two schedulers being allocated. As recommended above, this should only be used + // for IN-TREE examples. If a default scheduler is desired, the basic ServerInitParams should be used by the application and + // CommonCaseDeviceServerInitParams should not be allocated. + if (this->reportScheduler == nullptr) + { + reportScheduler = &sReportScheduler; + } + + // Session Keystore injection + this->sessionKeystore = &sSessionKeystore; + + // Group Data provider injection + sGroupDataProvider.SetStorageDelegate(this->persistentStorageDelegate); + sGroupDataProvider.SetSessionKeystore(this->sessionKeystore); + ReturnErrorOnFailure(sGroupDataProvider.Init()); + this->groupDataProvider = &sGroupDataProvider; + +#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION + ReturnErrorOnFailure(sSessionResumptionStorage.Init(this->persistentStorageDelegate)); + this->sessionResumptionStorage = &sSessionResumptionStorage; +#else + this->sessionResumptionStorage = nullptr; +#endif + + // Inject access control delegate + this->accessDelegate = Access::Examples::GetAccessControlDelegate(); + + // Inject ACL storage. (Don't initialize it.) + this->aclStorage = &sAclStorage; + +#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS + ChipLogProgress(AppServer, "Initializing subscription resumption storage..."); + ReturnErrorOnFailure(sSubscriptionResumptionStorage.Init(this->persistentStorageDelegate)); + this->subscriptionResumptionStorage = &sSubscriptionResumptionStorage; +#else + ChipLogProgress(AppServer, "Subscription persistence not supported"); +#endif + +#if CHIP_CONFIG_ENABLE_ICD_CIP + if (this->icdCheckInBackOffStrategy == nullptr) + { + this->icdCheckInBackOffStrategy = &sDefaultICDCheckInBackOffStrategy; + } +#endif + +#if CHIP_CONFIG_TC_REQUIRED + static app::DefaultEnhancedSetupFlowProvider sDefaultEnhancedSetupFlowProviderInstance; + static app::DefaultTermsAndConditionsProvider sDefaultTermsAndConditionsProviderInstance; + if (this->termsAndConditionsProvider == nullptr) + { + ReturnErrorOnFailure(sDefaultTermsAndConditionsProviderInstance.Init(this->persistentStorageDelegate, + CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS, + CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION)); + this->termsAndConditionsProvider = &sDefaultTermsAndConditionsProviderInstance; + } + + if (this->enhancedSetupFlowProvider == nullptr) + { + ReturnErrorOnFailure(sDefaultEnhancedSetupFlowProviderInstance.Init(this->termsAndConditionsProvider)); + this->enhancedSetupFlowProvider = &sDefaultEnhancedSetupFlowProviderInstance; + } +#endif + + return CHIP_NO_ERROR; + } private: static KvsPersistentStorageDelegate sKvsPersistenStorageDelegate; @@ -254,10 +350,6 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams #if CHIP_CONFIG_ENABLE_ICD_CIP static app::DefaultICDCheckInBackOffStrategy sDefaultICDCheckInBackOffStrategy; #endif -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) - static app::EnhancedSetupFlowProvider * sDefaultEnhancedSetupFlowProvider; - static app::TermsAndConditionsProvider * sDefaultTermsAndConditionsProvider; -#endif }; /** @@ -338,7 +430,7 @@ class Server app::reporting::ReportScheduler * GetReportScheduler() { return mReportScheduler; } -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) +#if CHIP_CONFIG_TC_REQUIRED app::EnhancedSetupFlowProvider * GetEnhancedSetupFlowProvider() { return mEnhancedSetupFlowProvider; } #endif @@ -615,7 +707,7 @@ class Server GroupDataProviderListener mListener; ServerFabricDelegate mFabricDelegate; app::reporting::ReportScheduler * mReportScheduler; -#if defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS) && defined (CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION) +#if CHIP_CONFIG_TC_REQUIRED app::EnhancedSetupFlowProvider * mEnhancedSetupFlowProvider; app::TermsAndConditionsProvider * mTermsAndConditionsProvider; #endif diff --git a/src/app/server/TermsAndConditionsProvider.h b/src/app/server/TermsAndConditionsProvider.h index 55e00d3c74e04d..201b3b983d466d 100644 --- a/src/app/server/TermsAndConditionsProvider.h +++ b/src/app/server/TermsAndConditionsProvider.h @@ -18,10 +18,9 @@ #pragma once -#include - #include +#include #include namespace chip { @@ -33,15 +32,10 @@ namespace app { class TermsAndConditionsProvider { public: - /** - * @brief Destructor. - */ virtual ~TermsAndConditionsProvider() = default; /** * @brief Sets the acceptance status of the required terms and conditions. - * - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ virtual CHIP_ERROR ClearAcceptance() = 0; @@ -50,7 +44,6 @@ class TermsAndConditionsProvider * * @param[out] outAcknowledgementsValue The bitmask of acknowledgements accepted. * @param[out] outAcknowledgementsVersionValue The version of the accepted acknowledgements. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ virtual CHIP_ERROR GetAcceptance(uint16_t & outAcknowledgementsValue, uint16_t & outAcknowledgementsVersionValue) const = 0; @@ -59,7 +52,6 @@ class TermsAndConditionsProvider * * @param[out] outAcknowledgementsValue The bitmask of required acknowledgements. * @param[out] outAcknowledgementsVersionValue The version of the required acknowledgements. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ virtual CHIP_ERROR GetRequirements(uint16_t & outAcknowledgementsValue, uint16_t & outAcknowledgementsVersionValue) const = 0; @@ -68,10 +60,9 @@ class TermsAndConditionsProvider * * @param[in] inAcknowledgementsValue The bitmask of acknowledgements that was accepted. * @param[in] inAcknowledgementsVersionValue The version of the acknowledgements that was accepted. - * @return CHIP_ERROR On success returns CHIP_NO_ERROR, otherwise returns an error code. */ virtual CHIP_ERROR SetAcceptance(uint16_t inAcknowledgementsValue, uint16_t inAcknowledgementsVersionValue) = 0; }; -}; // namespace app -}; // namespace chip +} // namespace app +} // namespace chip diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 12e8524c407e81..9da370d705d940 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -238,6 +238,7 @@ chip_test_suite("tests") { "${chip_root}/src/app/codegen-data-model-provider:instance-header", "${chip_root}/src/app/common:cluster-objects", "${chip_root}/src/app/icd/client:manager", + "${chip_root}/src/app/server:enhanced_setup_flow", "${chip_root}/src/app/server:server", "${chip_root}/src/app/tests:helpers", "${chip_root}/src/app/util/mock:mock_codegen_data_model", diff --git a/src/app/tests/TestDefaultEnhancedSetupFlowProvider.cpp b/src/app/tests/TestDefaultEnhancedSetupFlowProvider.cpp index a394177d403642..d29a18824e23f6 100644 --- a/src/app/tests/TestDefaultEnhancedSetupFlowProvider.cpp +++ b/src/app/tests/TestDefaultEnhancedSetupFlowProvider.cpp @@ -15,12 +15,10 @@ * limitations under the License. */ -#define CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS 1 -#define CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION 1 - #include "app/server/DefaultEnhancedSetupFlowProvider.h" #include +#include #include class FakeTermsAndConditionsProvider : public chip::app::TermsAndConditionsProvider @@ -77,10 +75,10 @@ TEST(DefaultEnhancedSetupFlowProvider, TestNoAcceptanceRequiredCheckAcknowledgem chip::app::DefaultEnhancedSetupFlowProvider esfProvider; err = esfProvider.Init(&tncProvider); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); EXPECT_TRUE(hasTermsBeenAccepted); } @@ -93,10 +91,10 @@ TEST(DefaultEnhancedSetupFlowProvider, TestNoAcceptanceRequiredCheckAcknowledgem chip::app::DefaultEnhancedSetupFlowProvider esfProvider; err = esfProvider.Init(&tncProvider); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); EXPECT_TRUE(hasTermsVersionBeenAccepted); } @@ -109,11 +107,11 @@ TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredNoTermsAcceptedChec chip::app::DefaultEnhancedSetupFlowProvider esfProvider; err = esfProvider.Init(&tncProvider); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(!hasTermsBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(hasTermsBeenAccepted); } TEST(DefaultEnhancedSetupFlowProvider, @@ -127,18 +125,18 @@ TEST(DefaultEnhancedSetupFlowProvider, chip::app::DefaultEnhancedSetupFlowProvider esfProvider; err = esfProvider.Init(&tncProvider); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.SetTermsAndConditionsAcceptance(1, 0); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); EXPECT_TRUE(hasTermsBeenAccepted); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(!hasTermsVersionBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(hasTermsVersionBeenAccepted); } TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredTermsAcceptedFutureVersionCheckAcknowledgementsAcceptedSuccess) @@ -156,14 +154,14 @@ TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredTermsAcceptedFuture chip::app::DefaultEnhancedSetupFlowProvider esfProvider; err = esfProvider.Init(&tncProvider); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); EXPECT_TRUE(hasTermsBeenAccepted); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); EXPECT_TRUE(hasTermsVersionBeenAccepted); } @@ -177,17 +175,17 @@ TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredTermsAcceptedSucces chip::app::DefaultEnhancedSetupFlowProvider esfProvider; err = esfProvider.Init(&tncProvider); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.SetTermsAndConditionsAcceptance(1, 1); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); EXPECT_TRUE(hasTermsBeenAccepted); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); EXPECT_TRUE(hasTermsVersionBeenAccepted); } @@ -206,14 +204,14 @@ TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredTermsMissingFailure chip::app::DefaultEnhancedSetupFlowProvider esfProvider; err = esfProvider.Init(&tncProvider); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(!hasTermsBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(hasTermsBeenAccepted); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); EXPECT_TRUE(hasTermsVersionBeenAccepted); } @@ -232,14 +230,14 @@ TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredAllTermsAcceptedChe chip::app::DefaultEnhancedSetupFlowProvider esfProvider; err = esfProvider.Init(&tncProvider); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); EXPECT_TRUE(hasTermsBeenAccepted); err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); EXPECT_TRUE(hasTermsVersionBeenAccepted); } @@ -266,43 +264,43 @@ TEST(DefaultEnhancedSetupFlowProvider, TestClearAcceptanceRetainsRequirements) chip::app::DefaultEnhancedSetupFlowProvider esfProvider; err = esfProvider.Init(&tncProvider); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.SetTermsAndConditionsAcceptance(updatedAcceptedTermsAndConditions, updatedAcceptedTermsAndConditionsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.GetTermsAndConditionsRequiredAcknowledgements(outRequiredTermsAndConditions); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(outRequiredTermsAndConditions == initialRequiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outRequiredTermsAndConditions, initialRequiredTermsAndConditions); err = esfProvider.GetTermsAndConditionsRequiredAcknowledgementsVersion(outRequiredTermsAndConditionsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(outRequiredTermsAndConditionsVersion == initialRequiredTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outRequiredTermsAndConditionsVersion, initialRequiredTermsAndConditionsVersion); err = esfProvider.GetTermsAndConditionsAcceptedAcknowledgements(outAcceptedTermsAndConditions); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(outAcceptedTermsAndConditions == updatedAcceptedTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outAcceptedTermsAndConditions, updatedAcceptedTermsAndConditions); err = esfProvider.GetTermsAndConditionsAcceptedAcknowledgementsVersion(outAcceptedTermsAndConditionsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(outAcceptedTermsAndConditionsVersion == updatedAcceptedTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outAcceptedTermsAndConditionsVersion, updatedAcceptedTermsAndConditionsVersion); err = esfProvider.ClearTermsAndConditionsAcceptance(); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = esfProvider.GetTermsAndConditionsRequiredAcknowledgements(outRequiredTermsAndConditions); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(outRequiredTermsAndConditions == initialRequiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outRequiredTermsAndConditions, initialRequiredTermsAndConditions); err = esfProvider.GetTermsAndConditionsRequiredAcknowledgementsVersion(outRequiredTermsAndConditionsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(outRequiredTermsAndConditionsVersion == initialRequiredTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outRequiredTermsAndConditionsVersion, initialRequiredTermsAndConditionsVersion); err = esfProvider.GetTermsAndConditionsAcceptedAcknowledgements(outAcceptedTermsAndConditions); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(outAcceptedTermsAndConditions == 0); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outAcceptedTermsAndConditions, 0); err = esfProvider.GetTermsAndConditionsAcceptedAcknowledgementsVersion(outAcceptedTermsAndConditionsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(outAcceptedTermsAndConditionsVersion == 0); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outAcceptedTermsAndConditionsVersion, 0); } diff --git a/src/app/tests/TestDefaultTermsAndConditionsProvider.cpp b/src/app/tests/TestDefaultTermsAndConditionsProvider.cpp index 714f01e72073b3..be09c703a64f10 100644 --- a/src/app/tests/TestDefaultTermsAndConditionsProvider.cpp +++ b/src/app/tests/TestDefaultTermsAndConditionsProvider.cpp @@ -16,12 +16,10 @@ * limitations under the License. */ -#define CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS 1 -#define CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION 1 - #include "app/server/DefaultTermsAndConditionsProvider.h" #include +#include #include #include @@ -35,7 +33,7 @@ TEST(DefaultTermsAndConditionsProvider, TestInitSuccess) uint16_t requiredAcknowledgements = 1; uint16_t requiredAcknowledgementsVersion = 1; err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); } TEST(DefaultTermsAndConditionsProvider, TestNoRequirementsGetRequirementsSuccess) @@ -48,14 +46,14 @@ TEST(DefaultTermsAndConditionsProvider, TestNoRequirementsGetRequirementsSuccess uint16_t requiredAcknowledgements = 0; uint16_t requiredAcknowledgementsVersion = 0; err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t outAcceptance; uint16_t outAcknowledgementsVersion; err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(0 == outAcceptance); - EXPECT_TRUE(0 == outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(0, outAcceptance); + EXPECT_EQ(0, outAcknowledgementsVersion); } TEST(DefaultTermsAndConditionsProvider, TestNeverAcceptanceGetAcceptanceSuccess) @@ -68,14 +66,14 @@ TEST(DefaultTermsAndConditionsProvider, TestNeverAcceptanceGetAcceptanceSuccess) uint16_t requiredAcknowledgements = 0b1111'1111'1111'1111; uint16_t requiredAcknowledgementsVersion = 1; err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t outAcceptance; uint16_t outAcknowledgementsVersion; err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(0 == outAcceptance); - EXPECT_TRUE(0 == outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(0, outAcceptance); + EXPECT_EQ(0, outAcknowledgementsVersion); } TEST(DefaultTermsAndConditionsProvider, TestTermsAcceptedPersistsSuccess) @@ -89,27 +87,27 @@ TEST(DefaultTermsAndConditionsProvider, TestTermsAcceptedPersistsSuccess) uint16_t requiredAcknowledgements = 1; uint16_t requiredAcknowledgementsVersion = 1; err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t acceptedTermsAndConditions = 1; uint16_t acceptedTermsAndConditionsVersion = 1; err = tncProvider.SetAcceptance(acceptedTermsAndConditions, acceptedTermsAndConditionsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t outAcceptance; uint16_t outAcknowledgementsVersion; err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(1 == outAcceptance); - EXPECT_TRUE(1 == outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcceptance); + EXPECT_EQ(1, outAcknowledgementsVersion); err = anotherTncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = anotherTncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(1 == outAcceptance); - EXPECT_TRUE(1 == outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcceptance); + EXPECT_EQ(1, outAcknowledgementsVersion); } TEST(DefaultTermsAndConditionsProvider, TestTermsRequiredGetRequirementsSuccess) @@ -122,14 +120,14 @@ TEST(DefaultTermsAndConditionsProvider, TestTermsRequiredGetRequirementsSuccess) uint16_t initialRequiredAcknowledgements = 1; uint16_t initialRequiredAcknowledgementsVersion = 1; err = tncProvider.Init(&storageDelegate, initialRequiredAcknowledgements, initialRequiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t outRequiredAcknowledgements; uint16_t outRequiredAcknowledgementsVersion; err = tncProvider.GetRequirements(outRequiredAcknowledgements, outRequiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(1 == outRequiredAcknowledgements); - EXPECT_TRUE(1 == outRequiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outRequiredAcknowledgements); + EXPECT_EQ(1, outRequiredAcknowledgementsVersion); } TEST(DefaultTermsAndConditionsProvider, TestSetAcceptanceGetAcceptanceSuccess) @@ -142,19 +140,19 @@ TEST(DefaultTermsAndConditionsProvider, TestSetAcceptanceGetAcceptanceSuccess) uint16_t requiredAcknowledgements = 1; uint16_t requiredAcknowledgementsVersion = 1; err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t acceptedTermsAndConditions = 1; uint16_t acceptedTermsAndConditionsVersion = 1; err = tncProvider.SetAcceptance(acceptedTermsAndConditions, acceptedTermsAndConditionsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t outAcceptance; uint16_t outAcknowledgementsVersion; err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(1 == outAcceptance); - EXPECT_TRUE(1 == outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcceptance); + EXPECT_EQ(1, outAcknowledgementsVersion); } TEST(DefaultTermsAndConditionsProvider, TestClearAcceptanceGetAcceptanceSuccess) @@ -167,29 +165,29 @@ TEST(DefaultTermsAndConditionsProvider, TestClearAcceptanceGetAcceptanceSuccess) uint16_t requiredAcknowledgements = 1; uint16_t requiredAcknowledgementsVersion = 1; err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t acceptedTermsAndConditions = 1; uint16_t acceptedTermsAndConditionsVersion = 1; err = tncProvider.SetAcceptance(acceptedTermsAndConditions, acceptedTermsAndConditionsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t outAcceptance; uint16_t outAcknowledgementsVersion; err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(1 == outAcceptance); - EXPECT_TRUE(1 == outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcceptance); + EXPECT_EQ(1, outAcknowledgementsVersion); err = tncProvider.ClearAcceptance(); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t outAcceptance2; uint16_t outAcknowledgementsVersion2; err = tncProvider.GetAcceptance(outAcceptance2, outAcknowledgementsVersion2); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(0 == outAcceptance2); - EXPECT_TRUE(0 == outAcknowledgementsVersion2); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(0, outAcceptance2); + EXPECT_EQ(0, outAcknowledgementsVersion2); } TEST(DefaultTermsAndConditionsProvider, TestAcceptanceRequiredTermsMissingFailure) @@ -202,27 +200,27 @@ TEST(DefaultTermsAndConditionsProvider, TestAcceptanceRequiredTermsMissingFailur uint16_t requiredAcknowledgements = 1; uint16_t requiredAcknowledgementsVersion = 1; err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t acceptedTermsAndConditions = 1; uint16_t acceptedTermsAndConditionsVersion = 1; err = tncProvider.SetAcceptance(acceptedTermsAndConditions, acceptedTermsAndConditionsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t outAcceptance; uint16_t outAcknowledgementsVersion; err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(1 == outAcceptance); - EXPECT_TRUE(1 == outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcceptance); + EXPECT_EQ(1, outAcknowledgementsVersion); err = tncProvider.ClearAcceptance(); - EXPECT_TRUE(CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); uint16_t outRequiredAcknowledgements; uint16_t outRequiredAcknowledgementsVersion; err = tncProvider.GetRequirements(outRequiredAcknowledgements, outRequiredAcknowledgementsVersion); - EXPECT_TRUE(CHIP_NO_ERROR == err); - EXPECT_TRUE(1 == outRequiredAcknowledgements); - EXPECT_TRUE(1 == outRequiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outRequiredAcknowledgements); + EXPECT_EQ(1, outRequiredAcknowledgementsVersion); } diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp index 0e83d7125cf175..cfdd5826919a8b 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2021-2024 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -365,6 +365,10 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStageInternal(Commissio case CommissioningStage::kArmFailsafe: return CommissioningStage::kConfigRegulatory; case CommissioningStage::kConfigRegulatory: + return CommissioningStage::kGetTCAcknowledgments; + case CommissioningStage::kGetTCAcknowledgments: + return CommissioningStage::kConfigureTCAcknowledgments; + case CommissioningStage::kConfigureTCAcknowledgments: if (mDeviceCommissioningInfo.requiresUTC) { return CommissioningStage::kConfigureUTCTime; diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 955e36bfb0d8a2..383c8c87224c12 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020-2022 Project CHIP Authors + * Copyright (c) 2020-2024 Project CHIP Authors * Copyright (c) 2013-2017 Nest Labs, Inc. * All rights reserved. * @@ -2691,6 +2691,22 @@ void DeviceCommissioner::OnSetRegulatoryConfigResponse( commissioner->CommissioningStageComplete(err, report); } +void DeviceCommissioner::OnSetTCAcknowledgementsResponse( + void * context, const GeneralCommissioning::Commands::SetTCAcknowledgementsResponse::DecodableType & data) +{ + CommissioningDelegate::CommissioningReport report; + CHIP_ERROR err = CHIP_NO_ERROR; + + ChipLogProgress(Controller, "Received SetTCAcknowledgements response errorCode=%u", to_underlying(data.errorCode)); + if (data.errorCode != GeneralCommissioning::CommissioningErrorEnum::kOk) + { + err = CHIP_ERROR_INTERNAL; + report.Set(data.errorCode); + } + DeviceCommissioner * commissioner = static_cast(context); + commissioner->CommissioningStageComplete(err, report); +} + void DeviceCommissioner::OnSetTimeZoneResponse(void * context, const TimeSynchronization::Commands::SetTimeZoneResponse::DecodableType & data) { @@ -2766,6 +2782,16 @@ CHIP_ERROR DeviceCommissioner::ICDRegistrationInfoReady() return CHIP_NO_ERROR; } +CHIP_ERROR DeviceCommissioner::TermsAndConditionsAcknowledgementsReady() +{ + ReturnErrorCodeIf(mCommissioningStage != CommissioningStage::kGetTCAcknowledgments, CHIP_ERROR_INCORRECT_STATE); + + // need to advance to next step + CommissioningStageComplete(CHIP_NO_ERROR); + + return CHIP_NO_ERROR; +} + void DeviceCommissioner::OnNetworkConfigResponse(void * context, const NetworkCommissioning::Commands::NetworkConfigResponse::DecodableType & data) { @@ -3163,6 +3189,56 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio } } break; + case CommissioningStage::kGetTCAcknowledgments: { + ChipLogProgress(Controller, "Get Terms and Conditions Acknowledgments"); + + bool acknowledgementReady = params.GetTermsAndConditionsAcknowledgement().HasValue(); + bool acknowledgementNotRequired = params.GetRequireTermsAndConditionsAcknowledgement().HasValue() && + !params.GetRequireTermsAndConditionsAcknowledgement().Value(); + + // If terms and conditions acknowledgements were provided, or not required, in the commissioning parameters, then skip ahead + if (acknowledgementReady || acknowledgementNotRequired) + { + TermsAndConditionsAcknowledgementsReady(); + return; + } + + ChipLogProgress(Controller, "Waiting for Terms and Conditions"); + break; + } + case CommissioningStage::kConfigureTCAcknowledgments: { + ChipLogProgress(Controller, "Setting Terms and Conditions"); + + bool acknowledgementNotRequired = params.GetRequireTermsAndConditionsAcknowledgement().HasValue() && + !params.GetRequireTermsAndConditionsAcknowledgement().Value(); + + if (acknowledgementNotRequired) + { + CommissioningStageComplete(CHIP_NO_ERROR); + return; + } + + if (!params.GetTermsAndConditionsAcknowledgement().HasValue()) + { + ChipLogError(Controller, "No acknowledgements provided"); + CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT); + return; + } + + GeneralCommissioning::Commands::SetTCAcknowledgements::Type request; + TermsAndConditionsAcknowledgement termsAndConditionsAcknowledgement = params.GetTermsAndConditionsAcknowledgement().Value(); + request.TCUserResponse = termsAndConditionsAcknowledgement.acceptedTermsAndConditions; + request.TCVersion = termsAndConditionsAcknowledgement.acceptedTermsAndConditionsVersion; + CHIP_ERROR err = + SendCommissioningCommand(proxy, request, OnSetTCAcknowledgementsResponse, OnBasicFailure, endpoint, timeout); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Failed to send SetTCAcknowledgements command: %" CHIP_ERROR_FORMAT, err.Format()); + CommissioningStageComplete(err); + return; + } + break; + } case CommissioningStage::kSendPAICertificateRequest: { ChipLogProgress(Controller, "Sending request for PAI certificate"); CHIP_ERROR err = SendCertificateChainRequestCommand(proxy, CertificateType::kPAI, timeout); diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 4b876156199735..1f1b381da96cbd 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020-2022 Project CHIP Authors + * Copyright (c) 2020-2024 Project CHIP Authors * Copyright (c) 2013-2017 Nest Labs, Inc. * All rights reserved. * @@ -696,6 +696,25 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, */ CHIP_ERROR ICDRegistrationInfoReady(); + /** + * @brief + * This function is called by the upper layer application to indicate that the required terms and conditions + * acknowledgements have been set. This function should be called after the terms and conditions bitmask and version + * have been defined using the appropriate configuration macros and the application has gathered the necessary + * acknowledgements from the user. + * + * The upper layer application should call this method once it has successfully presented and obtained acknowledgements + * for the required terms and conditions from the user. This indicates that the commissioning process can advance to the + * next stage. + * + * When the terms and conditions acknowledgements process is completed, this function will signal the readiness to proceed + * to the next step in the commissioning process. + * + * @return CHIP_ERROR The return status. Returns CHIP_ERROR_INCORRECT_STATE if the function is called when the device + * is not in the correct state to accept terms and conditions acknowledgements. + */ + CHIP_ERROR TermsAndConditionsAcknowledgementsReady(); + /** * @brief * This function returns the current CommissioningStage for this commissioner. @@ -947,6 +966,9 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, static void OnSetRegulatoryConfigResponse( void * context, const chip::app::Clusters::GeneralCommissioning::Commands::SetRegulatoryConfigResponse::DecodableType & data); + static void OnSetTCAcknowledgementsResponse( + void * context, + const chip::app::Clusters::GeneralCommissioning::Commands::SetTCAcknowledgementsResponse::DecodableType & data); static void OnSetUTCError(void * context, CHIP_ERROR error); static void OnSetTimeZoneResponse(void * context, diff --git a/src/controller/CommissioningDelegate.cpp b/src/controller/CommissioningDelegate.cpp index 85ea5e86c5e3a6..ed7e558828db1b 100644 --- a/src/controller/CommissioningDelegate.cpp +++ b/src/controller/CommissioningDelegate.cpp @@ -46,6 +46,12 @@ const char * StageToString(CommissioningStage stage) case kConfigRegulatory: return "ConfigRegulatory"; + case kGetTCAcknowledgments: + return "GetTCAcknowledgments"; + + case kConfigureTCAcknowledgments: + return "ConfigureTCAcknowledgments"; + case kConfigureUTCTime: return "ConfigureUTCTime"; diff --git a/src/controller/CommissioningDelegate.h b/src/controller/CommissioningDelegate.h index 73716e0d9ad0de..4936677786814c 100644 --- a/src/controller/CommissioningDelegate.h +++ b/src/controller/CommissioningDelegate.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2021-2024 Project CHIP Authors + * Copyright (c) 2021 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,6 +40,8 @@ enum CommissioningStage : uint8_t kReadCommissioningInfo2, ///< Query SupportsConcurrentConnection, ICD state, check for matching fabric kArmFailsafe, ///< Send ArmFailSafe (0x30:0) command to the device kConfigRegulatory, ///< Send SetRegulatoryConfig (0x30:2) command to the device + kGetTCAcknowledgments, ///< Waiting for the higher layer to provide terms and conditions acknowledgements. + kConfigureTCAcknowledgments, ///< Send SetTCAcknowledgements (0x30:6) command to the device kConfigureUTCTime, ///< SetUTCTime if the DUT has a time cluster kConfigureTimeZone, ///< Configure a time zone if one is required and available kConfigureDSTOffset, ///< Configure DST offset if one is required and available @@ -174,6 +176,9 @@ class CommissioningParameters // The country code to be used for the node, if set. Optional GetCountryCode() const { return mCountryCode; } + + Optional GetRequireTermsAndConditionsAcknowledgement() const { return mRequireTermsAndConditionsAcknowledgement; } + Optional GetTermsAndConditionsAcknowledgement() const { return mTermsAndConditionsAcknowledgement; @@ -351,6 +356,12 @@ class CommissioningParameters return *this; } + CommissioningParameters & SetRequireTermsAndConditionsAcknowledgement(bool requireTermsAndConditionsAcknowledgement) + { + mRequireTermsAndConditionsAcknowledgement.SetValue(requireTermsAndConditionsAcknowledgement); + return *this; + } + CommissioningParameters & SetTermsAndConditionsAcknowledgement(TermsAndConditionsAcknowledgement termsAndConditionsAcknowledgement) { @@ -599,6 +610,8 @@ class CommissioningParameters mAttestationNonce.ClearValue(); mWiFiCreds.ClearValue(); mCountryCode.ClearValue(); + mRequireTermsAndConditionsAcknowledgement.ClearValue(); + mTermsAndConditionsAcknowledgement.ClearValue(); mThreadOperationalDataset.ClearValue(); mNOCChainGenerationParameters.ClearValue(); mRootCert.ClearValue(); @@ -629,6 +642,7 @@ class CommissioningParameters Optional mAttestationNonce; Optional mWiFiCreds; Optional mCountryCode; + Optional mRequireTermsAndConditionsAcknowledgement; Optional mTermsAndConditionsAcknowledgement; Optional mThreadOperationalDataset; Optional mNOCChainGenerationParameters; diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index e9c317dfc79d5c..d739017e401179 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -1785,6 +1785,60 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #define CHIP_CONFIG_MAX_BDX_LOG_TRANSFERS 5 #endif // CHIP_CONFIG_MAX_BDX_LOG_TRANSFERS +/** + * @file + * Configuration settings for Terms and Conditions (TC) acknowledgements during device commissioning. + */ + +/** + * @def CHIP_CONFIG_TC_REQUIRED + * + * @brief Indicates whether terms and conditions are required during commissioning. + * + * This macro defines whether the device commissioning process requires the user to acknowledge terms and conditions. + * - 1: Terms and conditions are required. + * - 0: Terms and conditions are not required. + * + * If this is set to 1, both CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS and + * CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION must be defined. + */ +#ifndef CHIP_CONFIG_TC_REQUIRED +#define CHIP_CONFIG_TC_REQUIRED (0) +#endif + +#if CHIP_CONFIG_TC_REQUIRED + +/** + * @def CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS + * + * @brief Configures the required terms and conditions acknowledgements bitmask. + * + * This macro defines the required terms and conditions acknowledgements bitmask. The bit-field is 16 bits long, so the possible + * value range is [0, 65535). This setting can be used to require that terms and conditions are presented to the user during + * commissioning. + */ +#ifndef CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS +#error "CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS must be defined when CHIP_CONFIG_TC_REQUIRED is enabled." +#endif + +/** + * @def CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION + * + * @brief Configures the latest known version of the terms and conditions. + * + * This macro defines the version number of the latest terms and conditions. It allows the application to iterate on revisions of + * the terms and conditions. A value of 0 indicates that no specific version is required. This setting can be used to enforce + * version-specific terms and conditions acknowledgements in the application. When the set of terms and conditions needs to be + * changed, the version number should be monotonically increased. If the latest terms and conditions version is updated (most + * likely during an OTA), then this may signal to the Administrator that updated terms and conditions should be presented to the + * user. + */ +#ifndef CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION +#error "CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION must be defined when CHIP_CONFIG_TC_REQUIRED is enabled." +#endif + +#endif // CHIP_CONFIG_TC_REQUIRED + /** * @} */