Skip to content

Commit

Permalink
Add support for terms and conditions check and enhanced setup flow
Browse files Browse the repository at this point in the history
This commit adds support for terms and conditions (TC) check and
enhances the setup flow as part of the Connected Home over IP (CHIP)
Specification 1.4.

Changes include:

- Extended support for terms and conditions check and enhanced setup
  flow feature as part of the connectedhomeip spec 1.4.
- Added functionality to retrieve and store Terms and Conditions (TC)
  information, including accepted version, minimum required version,
  acknowledgements, and required acknowledgements.
- Implemented methods in `TermsAndConditionsManager` to handle TC
  versioning and acknowledgements.
- Updated `GeneralCommissioningAttrAccess` to include support for
  reading TC-related attributes.
- Added callback functions in `emberAfGeneralCommissioningCluster` to
  handle TC acknowledgements during commissioning.
- Integrated `TermsAndConditionsManager` into the server context for
  managing TC-related information.
- Enhanced error handling and logging for TC-related operations.
- Adjusted build configuration to include default values for TC
  versioning and acknowledgements.
- Expanded configuration management in `ConfigurationManagerImpl` to
  handle TC-related configuration keys.
- Updated `PosixConfig` to include configuration keys for TC-related
  information.
- Implemented default values for TC versioning and acknowledgements in
  `ConfigurationManagerImpl`.
  • Loading branch information
swan-amazon committed May 7, 2024
1 parent 5a7421f commit 4647629
Show file tree
Hide file tree
Showing 14 changed files with 326 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2021 Project CHIP Authors
* Copyright (c) 2021-2024 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.
Expand Down Expand Up @@ -66,7 +66,8 @@ class GeneralCommissioningAttrAccess : public AttributeAccessInterface
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;

private:
CHIP_ERROR ReadIfSupported(CHIP_ERROR (ConfigurationManager::*getter)(uint8_t &), AttributeValueEncoder & aEncoder);
template <typename T>
CHIP_ERROR ReadIfSupported(CHIP_ERROR (ConfigurationManager::*getter)(T &), AttributeValueEncoder & aEncoder);
CHIP_ERROR ReadBasicCommissioningInfo(AttributeValueEncoder & aEncoder);
CHIP_ERROR ReadSupportsConcurrentConnection(AttributeValueEncoder & aEncoder);
};
Expand Down Expand Up @@ -95,17 +96,29 @@ CHIP_ERROR GeneralCommissioningAttrAccess::Read(const ConcreteReadAttributePath
case SupportsConcurrentConnection::Id: {
return ReadSupportsConcurrentConnection(aEncoder);
}
default: {
break;
case TCAcceptedVersion::Id: {
return ReadIfSupported(&ConfigurationManager::GetTCAcceptedVersion, aEncoder);
}
case TCMinRequiredVersion::Id: {
return ReadIfSupported(&ConfigurationManager::GetTCMinRequiredVersion, aEncoder);
}
case TCAcknowledgements::Id: {
return ReadIfSupported(&ConfigurationManager::GetTCAcknowledgements, aEncoder);
}
case TCAcknowledgementsRequired::Id: {
return ReadIfSupported(&ConfigurationManager::GetTCAcknowledgementsRequired, aEncoder);
}
default:
break;
}
return CHIP_NO_ERROR;
}

CHIP_ERROR GeneralCommissioningAttrAccess::ReadIfSupported(CHIP_ERROR (ConfigurationManager::*getter)(uint8_t &),
template <typename T>
CHIP_ERROR GeneralCommissioningAttrAccess::ReadIfSupported(CHIP_ERROR (ConfigurationManager::*getter)(T &),
AttributeValueEncoder & aEncoder)
{
uint8_t data;
T data;
CHIP_ERROR err = (DeviceLayer::ConfigurationMgr().*getter)(data);
if (err == CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE)
{
Expand Down Expand Up @@ -208,15 +221,20 @@ bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler *
return true;
}

#ifndef CHIP_CONFIG_TNC_ACCEPTED_ACKNOWLEDGEMENTS
#error "Failed to set CHIP_CONFIG_TNC_ACCEPTED_ACKNOWLEDGEMENTS"
#endif

bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback(
app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
const Commands::CommissioningComplete::DecodableType & commandData)
{
MATTER_TRACE_SCOPE("CommissioningComplete", "GeneralCommissioning");

DeviceControlServer * devCtrl = &DeviceLayer::DeviceControlServer::DeviceControlSvr();
auto & failSafe = Server::GetInstance().GetFailSafeContext();
auto & fabricTable = Server::GetInstance().GetFabricTable();
DeviceControlServer * devCtrl = &DeviceLayer::DeviceControlServer::DeviceControlSvr();
auto & failSafe = Server::GetInstance().GetFailSafeContext();
auto & fabricTable = Server::GetInstance().GetFabricTable();
auto & termsAndConditionsManager = Server::GetInstance().GetTermsAndConditionsManager();

ChipLogProgress(FailSafe, "GeneralCommissioning: Received CommissioningComplete");

Expand All @@ -239,34 +257,58 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback(
}
else
{
if (failSafe.NocCommandHasBeenInvoked())
CHIP_ERROR err;

// Fetch the terms and conditions acknowledgements for verification
uint16_t tcAcceptedVersion = 0U, tcMinRequiredVersion = 0U, tcAcknowledgements = 0U, tcAcknowledgementsRequired = 0U;

err = termsAndConditionsManager.GetTCAcceptedVersion(tcAcceptedVersion);
CheckSuccess(err, Failure);

err = termsAndConditionsManager.GetTCMinRequiredVersion(tcMinRequiredVersion);
CheckSuccess(err, Failure);

err = termsAndConditionsManager.GetTCAcknowledgements(tcAcknowledgements);
CheckSuccess(err, Failure);

err = termsAndConditionsManager.GetTCAcknowledgementsRequired(tcAcknowledgementsRequired);
CheckSuccess(err, Failure);

if (tcAcknowledgementsRequired != (tcAcknowledgementsRequired & tcAcknowledgements))
{
CHIP_ERROR err = fabricTable.CommitPendingFabricData();
if (err != CHIP_NO_ERROR)
{
// No need to revert on error: CommitPendingFabricData always reverts if not fully successful.
ChipLogError(FailSafe, "GeneralCommissioning: Failed to commit pending fabric data: %" CHIP_ERROR_FORMAT,
err.Format());
}
else
ChipLogError(AppServer, "Required terms and conditions have not been accepted");
Breadcrumb::Set(commandPath.mEndpointId, 0);
response.errorCode = CommissioningErrorEnum::kRequiredTCNotAccepted;
}

else if (tcAcceptedVersion < tcMinRequiredVersion)
{
ChipLogError(AppServer, "Minimium terms and conditions version has not been accepted");
Breadcrumb::Set(commandPath.mEndpointId, 0);
response.errorCode = CommissioningErrorEnum::kTCMinVersionNotMet;
}

else
{
if (failSafe.NocCommandHasBeenInvoked())
{
err = fabricTable.CommitPendingFabricData();
CheckSuccess(err, Failure);
ChipLogProgress(FailSafe, "GeneralCommissioning: Successfully commited pending fabric data");
}
CheckSuccess(err, Failure);
}

/*
* 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();
CheckSuccess(
devCtrl->PostCommissioningCompleteEvent(handle->AsSecureSession()->GetPeerNodeId(), handle->GetFabricIndex()),
Failure);
/*
* 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;
}
}
}

Expand Down Expand Up @@ -328,6 +370,22 @@ bool emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(app::CommandH
return true;
}

bool emberAfGeneralCommissioningClusterSetTCAcknowledgementsCallback(
chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
const chip::app::Clusters::GeneralCommissioning::Commands::SetTCAcknowledgements::DecodableType & commandData)
{
MATTER_TRACE_SCOPE("SetTCAcknowledgements", "GeneralCommissioning");
auto & termsAndConditionsManager = Server::GetInstance().GetTermsAndConditionsManager();

Commands::SetTCAcknowledgementsResponse::Type response;

CheckSuccess(termsAndConditionsManager.SetTCAcknowledgements(commandData.TCVersion, commandData.TCUserResponse), Failure);
response.errorCode = CommissioningErrorEnum::kOk;

commandObj->AddResponse(commandPath, response);
return true;
}

namespace {
void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
{
Expand Down
4 changes: 3 additions & 1 deletion src/app/server/BUILD.gn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2020 Project CHIP Authors
# Copyright (c) 2020-2024 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.
Expand Down Expand Up @@ -44,6 +44,8 @@ static_library("server") {
"OnboardingCodesUtil.h",
"Server.cpp",
"Server.h",
"TermsAndConditionsManager.cpp",
"TermsAndConditionsManager.h",
]

public_configs = [ ":server_config" ]
Expand Down
4 changes: 4 additions & 0 deletions src/app/server/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <app/server/AppDelegate.h>
#include <app/server/CommissioningWindowManager.h>
#include <app/server/DefaultAclStorage.h>
#include <app/server/TermsAndConditionsManager.h>
#include <credentials/CertificateValidityPolicy.h>
#include <credentials/FabricTable.h>
#include <credentials/GroupDataProvider.h>
Expand Down Expand Up @@ -357,6 +358,8 @@ class Server

app::FailSafeContext & GetFailSafeContext() { return mFailSafeContext; }

app::TermsAndConditionsManager & GetTermsAndConditionsManager() { return mTermsAndConditionsManager; }

TestEventTriggerDelegate * GetTestEventTriggerDelegate() { return mTestEventTriggerDelegate; }

Crypto::OperationalKeystore * GetOperationalKeystore() { return mOperationalKeystore; }
Expand Down Expand Up @@ -636,6 +639,7 @@ class Server
Crypto::OperationalKeystore * mOperationalKeystore;
Credentials::OperationalCertificateStore * mOpCertStore;
app::FailSafeContext mFailSafeContext;
app::TermsAndConditionsManager mTermsAndConditionsManager;

bool mIsDnssdReady = false;
uint16_t mOperationalServicePort;
Expand Down
78 changes: 78 additions & 0 deletions src/app/server/TermsAndConditionsManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "TermsAndConditionsManager.h"

#include <platform/ConfigurationManager.h>

CHIP_ERROR chip::app::TermsAndConditionsManager::GetTCAcceptedVersion(uint16_t & value)
{
CHIP_ERROR err = CHIP_NO_ERROR;

err = DeviceLayer::ConfigurationMgr().GetTCAcceptedVersion(value);
SuccessOrExit(err);

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "GetTCAcceptedVersion failed with error: %s", ErrorStr(err));
}
return err;
}

CHIP_ERROR chip::app::TermsAndConditionsManager::GetTCMinRequiredVersion(uint16_t & value)
{
CHIP_ERROR err = CHIP_NO_ERROR;

err = DeviceLayer::ConfigurationMgr().GetTCMinRequiredVersion(value);
SuccessOrExit(err);

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "GetTCMinRequiredVersion failed with error: %s", ErrorStr(err));
}
return err;
}

CHIP_ERROR chip::app::TermsAndConditionsManager::GetTCAcknowledgements(uint16_t & value)
{
CHIP_ERROR err = CHIP_NO_ERROR;

err = DeviceLayer::ConfigurationMgr().GetTCAcknowledgements(value);
SuccessOrExit(err);

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "GetTCAcknowledgements failed with error: %s", ErrorStr(err));
}
return err;
}

CHIP_ERROR chip::app::TermsAndConditionsManager::GetTCAcknowledgementsRequired(uint16_t & value)
{
CHIP_ERROR err = CHIP_NO_ERROR;

err = DeviceLayer::ConfigurationMgr().GetTCAcknowledgementsRequired(value);
SuccessOrExit(err);

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "GetTCAcknowledgementsRequired failed with error: %s", ErrorStr(err));
}
return err;
}

CHIP_ERROR chip::app::TermsAndConditionsManager::SetTCAcknowledgements(uint16_t tcVersion, uint16_t tcUserResponse)
{
CHIP_ERROR err = CHIP_NO_ERROR;

err = DeviceLayer::ConfigurationMgr().StoreTCAcknowledgements(tcVersion, tcUserResponse);
SuccessOrExit(err);

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "SetTCAcknowledgements failed with error: %s", ErrorStr(err));
}
return err;
}
20 changes: 20 additions & 0 deletions src/app/server/TermsAndConditionsManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <stdint.h>

#include <lib/core/CHIPError.h>

namespace chip {
namespace app {

class TermsAndConditionsManager {
public:
CHIP_ERROR GetTCAcceptedVersion(uint16_t &value);
CHIP_ERROR GetTCMinRequiredVersion(uint16_t &value);
CHIP_ERROR GetTCAcknowledgements(uint16_t &value);
CHIP_ERROR GetTCAcknowledgementsRequired(uint16_t &value);
CHIP_ERROR SetTCAcknowledgements(uint16_t tcVersion, uint16_t tcUserResponse);
};

}; // namespace app
}; // namespace chip
18 changes: 18 additions & 0 deletions src/include/platform/CHIPDeviceConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -1507,6 +1507,24 @@ static_assert(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN <= CHIP_DEVICE

// -------------------- Miscellaneous --------------------

// ----------------------- Terms and Conditions -----------------------

#ifndef CHIP_CONFIG_TNC_ACCEPTED_ACKNOWLEDGEMENTS
#define CHIP_CONFIG_TNC_ACCEPTED_ACKNOWLEDGEMENTS 0
#endif

#ifndef CHIP_CONFIG_TNC_ACCEPTED_VERSION
#define CHIP_CONFIG_TNC_ACCEPTED_VERSION 0
#endif

#ifndef CHIP_CONFIG_TNC_REQUIRED_ACKNOWLEDGEMENTS
#define CHIP_CONFIG_TNC_REQUIRED_ACKNOWLEDGEMENTS 0
#endif

#ifndef CHIP_CONFIG_TNC_REQUIRED_VERSION
#define CHIP_CONFIG_TNC_REQUIRED_VERSION 0
#endif

/**
* CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES
*
Expand Down
6 changes: 6 additions & 0 deletions src/include/platform/ConfigurationManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ class ConfigurationManager
virtual CHIP_ERROR GetFailSafeArmed(bool & val) = 0;
virtual CHIP_ERROR SetFailSafeArmed(bool val) = 0;

virtual CHIP_ERROR GetTCAcceptedVersion(uint16_t &value) = 0;
virtual CHIP_ERROR GetTCMinRequiredVersion(uint16_t &value) = 0;
virtual CHIP_ERROR GetTCAcknowledgements(uint16_t &value) = 0;
virtual CHIP_ERROR GetTCAcknowledgementsRequired(uint16_t &value) = 0;
virtual CHIP_ERROR StoreTCAcknowledgements(uint16_t tcVersion, uint16_t tcUserResponse) = 0;

virtual CHIP_ERROR GetBLEDeviceIdentificationInfo(Ble::ChipBLEDeviceIdentificationInfo & deviceIdInfo) = 0;

#if CHIP_CONFIG_TEST
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class GenericConfigurationManagerImpl : public ConfigurationManager
#endif
CHIP_ERROR GetFailSafeArmed(bool & val) override;
CHIP_ERROR SetFailSafeArmed(bool val) override;

CHIP_ERROR GetBLEDeviceIdentificationInfo(Ble::ChipBLEDeviceIdentificationInfo & deviceIdInfo) override;
bool IsCommissionableDeviceTypeEnabled() override;
CHIP_ERROR GetDeviceTypeId(uint32_t & deviceType) override;
Expand All @@ -94,6 +95,11 @@ class GenericConfigurationManagerImpl : public ConfigurationManager
CHIP_ERROR StoreRegulatoryLocation(uint8_t location) override;
CHIP_ERROR GetCountryCode(char * buf, size_t bufSize, size_t & codeLen) override;
CHIP_ERROR StoreCountryCode(const char * code, size_t codeLen) override;
CHIP_ERROR GetTCAcceptedVersion(uint16_t &value) override;
CHIP_ERROR GetTCMinRequiredVersion(uint16_t &value) override;
CHIP_ERROR GetTCAcknowledgements(uint16_t &value) override;
CHIP_ERROR GetTCAcknowledgementsRequired(uint16_t &value) override;
CHIP_ERROR StoreTCAcknowledgements(uint16_t tcVersion, uint16_t tcUserResponse) override;
CHIP_ERROR GetRebootCount(uint32_t & rebootCount) override;
CHIP_ERROR StoreRebootCount(uint32_t rebootCount) override;
CHIP_ERROR GetTotalOperationalHours(uint32_t & totalOperationalHours) override;
Expand Down Expand Up @@ -136,11 +142,13 @@ class GenericConfigurationManagerImpl : public ConfigurationManager
// Methods to read and write configuration values, as well as run the configuration unit test.
typedef typename ConfigClass::Key Key;
virtual CHIP_ERROR ReadConfigValue(Key key, bool & val) = 0;
virtual CHIP_ERROR ReadConfigValue(Key key, uint16_t & val) = 0;
virtual CHIP_ERROR ReadConfigValue(Key key, uint32_t & val) = 0;
virtual CHIP_ERROR ReadConfigValue(Key key, uint64_t & val) = 0;
virtual CHIP_ERROR ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) = 0;
virtual CHIP_ERROR ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) = 0;
virtual CHIP_ERROR WriteConfigValue(Key key, bool val) = 0;
virtual CHIP_ERROR WriteConfigValue(Key key, uint16_t val) = 0;
virtual CHIP_ERROR WriteConfigValue(Key key, uint32_t val) = 0;
virtual CHIP_ERROR WriteConfigValue(Key key, uint64_t val) = 0;
virtual CHIP_ERROR WriteConfigValueStr(Key key, const char * str) = 0;
Expand Down
Loading

0 comments on commit 4647629

Please sign in to comment.