Skip to content

Commit

Permalink
Merge a51e3ef into 3f0f242
Browse files Browse the repository at this point in the history
  • Loading branch information
swan-amazon authored Sep 9, 2024
2 parents 3f0f242 + a51e3ef commit 2462912
Show file tree
Hide file tree
Showing 16 changed files with 955 additions and 19 deletions.
21 changes: 20 additions & 1 deletion src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ declare_args() {
current_os != "android"
}

config("enhanced_setup_flow_config") {
defines = []
if (chip_config_tc_required) {
defines += [ "CHIP_CONFIG_TC_REQUIRED=1" ]
} else {
defines += [ "CHIP_CONFIG_TC_REQUIRED=0" ]
}
}

buildconfig_header("app_buildconfig") {
header = "AppBuildConfig.h"
header_dir = "app"
Expand All @@ -81,6 +90,13 @@ buildconfig_header("app_buildconfig") {
"CHIP_CONFIG_DATA_MODEL_CHECK_DIE_ON_FAILURE=${chip_data_model_check_die_on_failure}",
]

if (chip_config_tc_required) {
defines += [
"CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS=${chip_config_tc_required_acknowledgements}",
"CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION=${chip_config_tc_required_acknowledgements_version}",
]
}

if (chip_use_data_model_interface == "disabled") {
defines += [
"CHIP_CONFIG_USE_DATA_MODEL_INTERFACE=0",
Expand Down Expand Up @@ -520,5 +536,8 @@ static_library("app") {

cflags = [ "-Wconversion" ]

public_configs = [ "${chip_root}/src:includes" ]
public_configs = [
":enhanced_setup_flow_config",
"${chip_root}/src:includes",
]
}
11 changes: 8 additions & 3 deletions src/app/FailSafeContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,14 @@ void FailSafeContext::ScheduleFailSafeCleanup(FabricIndex fabricIndex, bool addN
SetFailSafeArmed(false);

ChipDeviceEvent event{ .Type = DeviceEventType::kFailSafeTimerExpired,
.FailSafeTimerExpired = { .fabricIndex = fabricIndex,
.addNocCommandHasBeenInvoked = addNocCommandInvoked,
.updateNocCommandHasBeenInvoked = updateNocCommandInvoked } };
.FailSafeTimerExpired = {
.fabricIndex = fabricIndex,
.addNocCommandHasBeenInvoked = addNocCommandInvoked,
.updateNocCommandHasBeenInvoked = updateNocCommandInvoked,
#if CHIP_CONFIG_TC_REQUIRED
.updateTermsAndConditionsHasBeenInvoked = mUpdateTermsAndConditionsHasBeenInvoked,
#endif
} };
CHIP_ERROR status = PlatformMgr().PostEvent(&event);

if (status != CHIP_NO_ERROR)
Expand Down
12 changes: 12 additions & 0 deletions src/app/FailSafeContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ class FailSafeContext
void SetAddTrustedRootCertInvoked() { mAddTrustedRootCertHasBeenInvoked = true; }
void SetCsrRequestForUpdateNoc(bool isForUpdateNoc) { mIsCsrRequestForUpdateNoc = isForUpdateNoc; }

#if CHIP_CONFIG_TC_REQUIRED
void SetUpdateTermsAndConditionsHasBeenInvoked() { mUpdateTermsAndConditionsHasBeenInvoked = true; }
#endif
/**
* @brief
* Schedules a work to cleanup the FailSafe Context asynchronously after various cleanup work
Expand Down Expand Up @@ -91,6 +94,9 @@ class FailSafeContext
bool UpdateNocCommandHasBeenInvoked() const { return mUpdateNocCommandHasBeenInvoked; }
bool AddTrustedRootCertHasBeenInvoked() const { return mAddTrustedRootCertHasBeenInvoked; }
bool IsCsrRequestForUpdateNoc() const { return mIsCsrRequestForUpdateNoc; }
#if CHIP_CONFIG_TC_REQUIRED
bool UpdateTermsAndConditionsHasBeenInvoked() { return mUpdateTermsAndConditionsHasBeenInvoked; }
#endif

FabricIndex GetFabricIndex() const
{
Expand All @@ -111,6 +117,9 @@ class FailSafeContext
// The fact of whether a CSR occurred at all is stored elsewhere.
bool mIsCsrRequestForUpdateNoc = false;
FabricIndex mFabricIndex = kUndefinedFabricIndex;
#if CHIP_CONFIG_TC_REQUIRED
bool mUpdateTermsAndConditionsHasBeenInvoked = false;
#endif

/**
* @brief
Expand Down Expand Up @@ -145,6 +154,9 @@ class FailSafeContext
mAddTrustedRootCertHasBeenInvoked = false;
mFailSafeBusy = false;
mIsCsrRequestForUpdateNoc = false;
#if CHIP_CONFIG_TC_REQUIRED
mUpdateTermsAndConditionsHasBeenInvoked = false;
#endif
}

void FailSafeTimerExpired();
Expand Down
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 All @@ -27,8 +27,12 @@
#include <app/CommandHandler.h>
#include <app/ConcreteCommandPath.h>
#include <app/server/CommissioningWindowManager.h>
#if CHIP_CONFIG_TC_REQUIRED
#include <app/server/TermsAndConditionsProvider.h>
#endif
#include <app/server/Server.h>
#include <app/util/attribute-storage.h>
#include <credentials/FabricTable.h>
#include <lib/support/Span.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceConfig.h>
Expand Down Expand Up @@ -95,6 +99,28 @@ CHIP_ERROR GeneralCommissioningAttrAccess::Read(const ConcreteReadAttributePath
case SupportsConcurrentConnection::Id: {
return ReadSupportsConcurrentConnection(aEncoder);
}
#if CHIP_CONFIG_TC_REQUIRED
case TCAcceptedVersion::Id: {
Optional<TermsAndConditions> outTermsAndConditions;
Server::GetInstance().GetTermsAndConditionsProvider()->GetAcceptance(outTermsAndConditions);
return !outTermsAndConditions.HasValue() ? aEncoder.Encode(0) : aEncoder.Encode(outTermsAndConditions.Value().version);
}
case TCMinRequiredVersion::Id: {
Optional<TermsAndConditions> outTermsAndConditions;
Server::GetInstance().GetTermsAndConditionsProvider()->GetRequirements(outTermsAndConditions);
return !outTermsAndConditions.HasValue() ? aEncoder.Encode(0) : aEncoder.Encode(outTermsAndConditions.Value().version);
}
case TCAcknowledgements::Id: {
Optional<TermsAndConditions> outTermsAndConditions;
Server::GetInstance().GetTermsAndConditionsProvider()->GetAcceptance(outTermsAndConditions);
return !outTermsAndConditions.HasValue() ? aEncoder.Encode(0) : aEncoder.Encode(outTermsAndConditions.Value().value);
}
case TCAcknowledgementsRequired::Id: {
Optional<TermsAndConditions> outTermsAndConditions;
Server::GetInstance().GetTermsAndConditionsProvider()->GetRequirements(outTermsAndConditions);
return aEncoder.Encode(outTermsAndConditions.HasValue());
}
#endif
default: {
break;
}
Expand Down Expand Up @@ -144,6 +170,33 @@ CHIP_ERROR GeneralCommissioningAttrAccess::ReadSupportsConcurrentConnection(Attr
return aEncoder.Encode(supportsConcurrentConnection);
}

#if CHIP_CONFIG_TC_REQUIRED
CommissioningErrorEnum CheckTermsAndConditionsAcknowledgementsState(TermsAndConditionsProvider * const termsAndConditionsProvider,
const Optional<TermsAndConditions> & acceptedTermsAndConditions)
{
TermsAndConditionsState termsAndConditionsState;

CHIP_ERROR err = termsAndConditionsProvider->CheckAcceptance(acceptedTermsAndConditions, termsAndConditionsState);
if (CHIP_NO_ERROR != err)
{
return chip::app::Clusters::GeneralCommissioning::CommissioningErrorEnum::kUnknownEnumValue;
}

switch (termsAndConditionsState)
{
case OK:
return chip::app::Clusters::GeneralCommissioning::CommissioningErrorEnum::kOk;
case TC_ACKNOWLEDGEMENTS_NOT_RECEIVED:
return chip::app::Clusters::GeneralCommissioning::CommissioningErrorEnum::kTCAcknowledgementsNotReceived;
case TC_MIN_VERSION_NOT_MET:
return chip::app::Clusters::GeneralCommissioning::CommissioningErrorEnum::kTCMinVersionNotMet;
case REQUIRED_TC_NOT_ACCEPTED:
return chip::app::Clusters::GeneralCommissioning::CommissioningErrorEnum::kRequiredTCNotAccepted;
}

return chip::app::Clusters::GeneralCommissioning::CommissioningErrorEnum::kOk;
}
#endif // CHIP_CONFIG_TC_REQUIRED
} // anonymous namespace

bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler * commandObj,
Expand Down Expand Up @@ -218,6 +271,8 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback(
auto & failSafe = Server::GetInstance().GetFailSafeContext();
auto & fabricTable = Server::GetInstance().GetFabricTable();

CHIP_ERROR err;

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

Commands::CommissioningCompleteResponse::Type response;
Expand All @@ -239,9 +294,45 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback(
}
else
{
#if CHIP_CONFIG_TC_REQUIRED
TermsAndConditionsProvider * const termsAndConditionsProvider = Server::GetInstance().GetTermsAndConditionsProvider();
Optional<TermsAndConditions> acceptedTermsAndConditions;

err = termsAndConditionsProvider->GetAcceptance(acceptedTermsAndConditions);
if (CHIP_NO_ERROR != err)
{
//
}

response.errorCode =
CheckTermsAndConditionsAcknowledgementsState(termsAndConditionsProvider, acceptedTermsAndConditions);
if (CommissioningErrorEnum::kOk != response.errorCode)
{
commandObj->AddResponse(commandPath, response);
return true;
}

if (failSafe.UpdateTermsAndConditionsHasBeenInvoked())
{
// Commit terms and conditions acceptance on commissioning complete
err = Server::GetInstance().GetTermsAndConditionsProvider()->CommitAcceptance();
if (err != CHIP_NO_ERROR)
{
ChipLogError(FailSafe, "GeneralCommissioning: Failed to commit terms and conditions: %" CHIP_ERROR_FORMAT,
err.Format());
fabricTable.RevertPendingFabricData();
}
else
{
ChipLogProgress(FailSafe, "GeneralCommissioning: Successfully commited terms and conditions");
}
CheckSuccess(err, Failure);
}
#endif

if (failSafe.NocCommandHasBeenInvoked())
{
CHIP_ERROR err = fabricTable.CommitPendingFabricData();
err = fabricTable.CommitPendingFabricData();
if (err != CHIP_NO_ERROR)
{
// No need to revert on error: CommitPendingFabricData always reverts if not fully successful.
Expand Down Expand Up @@ -328,25 +419,67 @@ 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)
{
#if !CHIP_CONFIG_TC_REQUIRED
return false;

#else
MATTER_TRACE_SCOPE("SetTCAcknowledgements", "GeneralCommissioning");

auto & failSafeContext = Server::GetInstance().GetFailSafeContext();
TermsAndConditionsProvider * const termsAndConditionsProvider = Server::GetInstance().GetTermsAndConditionsProvider();

Optional<TermsAndConditions> acceptedTermsAndConditions = Optional<TermsAndConditions>({
.value = commandData.TCUserResponse,
.version = commandData.TCVersion,
});

Commands::SetTCAcknowledgementsResponse::Type response;
response.errorCode = CheckTermsAndConditionsAcknowledgementsState(termsAndConditionsProvider, acceptedTermsAndConditions);

if (CommissioningErrorEnum::kOk == response.errorCode)
{
CheckSuccess(termsAndConditionsProvider->SetAcceptance(acceptedTermsAndConditions), Failure);

if (failSafeContext.IsFailSafeArmed())
{
failSafeContext.SetUpdateTermsAndConditionsHasBeenInvoked();
}
else
{
CheckSuccess(termsAndConditionsProvider->CommitAcceptance(), Failure);
}
}

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

#endif
}

namespace {
void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
{
if (event->Type == DeviceLayer::DeviceEventType::kFailSafeTimerExpired)
{
// Spec says to reset Breadcrumb attribute to 0.
Breadcrumb::Set(0, 0);

#if CHIP_CONFIG_TC_REQUIRED
if (event->FailSafeTimerExpired.updateTermsAndConditionsHasBeenInvoked)
{
// Clear terms and conditions acceptance on failsafe timer expiration
Server::GetInstance().GetTermsAndConditionsProvider()->RevertAcceptance();
}
#endif
}
}

} // anonymous namespace

void MatterGeneralCommissioningPluginServerInitCallback()
{
Breadcrumb::Set(0, 0);
AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess);
DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler);
}

namespace chip {
namespace app {
namespace Clusters {
Expand All @@ -359,3 +492,32 @@ void SetBreadcrumb(Attributes::Breadcrumb::TypeInfo::Type breadcrumb)
} // namespace Clusters
} // namespace app
} // namespace chip

class GeneralCommissioningFabricTableDelegate : public chip::FabricTable::Delegate
{
public:
// Gets called when a fabric is deleted
void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override
{
// If the FabricIndex matches the last remaining entry in the Fabrics list, then the device SHALL delete all Matter
// related data on the node which was created since it was commissioned.
if (Server::GetInstance().GetFabricTable().FabricCount() == 0)
{
ChipLogProgress(Zcl, "general-commissioning-server: Last Fabric index 0x%x was removed",
static_cast<unsigned>(fabricIndex));
#if CHIP_CONFIG_TC_REQUIRED
Server::GetInstance().GetTermsAndConditionsProvider()->ResetAcceptance();
#endif // CHIP_CONFIG_TC_REQUIRED
}
}
};

void MatterGeneralCommissioningPluginServerInitCallback()
{
Breadcrumb::Set(0, 0);
AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess);
DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler);

static GeneralCommissioningFabricTableDelegate generalCommissioningFabricTableDelegate;
Server::GetInstance().GetFabricTable().AddFabricDelegate(&generalCommissioningFabricTableDelegate);
}
23 changes: 23 additions & 0 deletions src/app/common_flags.gni
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,29 @@ declare_args() {
chip_enable_read_client = true
chip_build_controller_dynamic_server = false

# Configures whether terms and conditions acknowledgements are required.
#
# When set to true, the application will enforce the requirement of
# terms and conditions acknowledgements during commissioning.
chip_config_tc_required = false

# Configures the required terms and conditions acknowledgements bitmask.
#
# This setting 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.
chip_config_tc_required_acknowledgements = 0

# Configures the latest known version of the terms and conditions.
#
# This setting 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.
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
Expand Down
Loading

0 comments on commit 2462912

Please sign in to comment.