From 3c8183ba5e0b80c0ed11ee488e10666f14a1e6f0 Mon Sep 17 00:00:00 2001 From: Sagar Dhawan Date: Thu, 17 Mar 2022 09:00:32 -0700 Subject: [PATCH 01/15] Allow modifying the thermostat cluster attrs from the M5Stack (#16330) --- .../esp32/main/DeviceWithDisplay.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/examples/all-clusters-app/esp32/main/DeviceWithDisplay.cpp b/examples/all-clusters-app/esp32/main/DeviceWithDisplay.cpp index 9de9620fa17fad..b47ce31364f672 100644 --- a/examples/all-clusters-app/esp32/main/DeviceWithDisplay.cpp +++ b/examples/all-clusters-app/esp32/main/DeviceWithDisplay.cpp @@ -181,6 +181,21 @@ class EditAttributeListModel : public TouchesMatterStackModel ESP_LOGI(TAG, "Humidity changed to : %d", n); app::Clusters::RelativeHumidityMeasurement::Attributes::MeasuredValue::Set(1, static_cast(n * 100)); } + else if (name == "OccupiedCoolingSetpoint") + { + ESP_LOGI(TAG, "OccupiedCoolingSetpoint changed to : %d", n); + app::Clusters::Thermostat::Attributes::OccupiedCoolingSetpoint::Set(1, static_cast(n * 100)); + } + else if (name == "OccupiedHeatingSetpoint") + { + ESP_LOGI(TAG, "OccupiedHeatingSetpoint changed to : %d", n); + app::Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::Set(1, static_cast(n * 100)); + } + else if (name == "SystemMode") + { + ESP_LOGI(TAG, "SystemMode changed to : %d", n); + app::Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::Set(1, n); + } value = buffer; } else if (IsBooleanAttribute()) From e5c5a9ecf194ca3140931280265e2700cf0942ca Mon Sep 17 00:00:00 2001 From: Xuan Date: Fri, 18 Mar 2022 00:09:36 +0800 Subject: [PATCH 02/15] [python] fix failed import Mapping on python 3.10 (#16339) Signed-off-by: kXuan --- src/controller/python/chip/tlv/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controller/python/chip/tlv/__init__.py b/src/controller/python/chip/tlv/__init__.py index 962d208872e7a1..20f2bfebd2f2dd 100644 --- a/src/controller/python/chip/tlv/__init__.py +++ b/src/controller/python/chip/tlv/__init__.py @@ -29,7 +29,8 @@ from __future__ import print_function import struct -from collections import Mapping, Sequence, OrderedDict +from collections import OrderedDict +from collections.abc import Mapping, Sequence from enum import Enum TLV_TYPE_SIGNED_INTEGER = 0x00 From 4e1491d8da3a28f1d5caaa5e6411aad087f96c96 Mon Sep 17 00:00:00 2001 From: mkardous-silabs <84793247+mkardous-silabs@users.noreply.github.com> Date: Thu, 17 Mar 2022 13:29:36 -0400 Subject: [PATCH 03/15] [EFR32] Adding add binding commands to switch (#16030) * Adding binding commands to matter switch shell * restyle * update wordlist * remove debug define * PR comments - add save binding function * Restyled by whitespace * Restyled by clang-format * PR comments * add missing entry value * update comment Co-authored-by: Boris Zbarsky Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- .github/.wordlist.txt | 5 ++ examples/light-switch-app/efr32/README.md | 14 +++- .../efr32/include/binding-handler.h | 1 + .../efr32/src/binding-handler.cpp | 79 ++++++++++++++++++- src/app/clusters/bindings/bindings.cpp | 39 +++++---- src/app/clusters/bindings/bindings.h | 31 ++++++++ 6 files changed, 148 insertions(+), 21 deletions(-) create mode 100644 src/app/clusters/bindings/bindings.h diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index c9d72a3179beee..3245626bebaa79 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -1401,3 +1401,8 @@ kManage kOperate kView xFFFFFFFD +NAMESERVER +UTF +localedef +nameserver +nmcli diff --git a/examples/light-switch-app/efr32/README.md b/examples/light-switch-app/efr32/README.md index d73a2ab2fc9b63..641b6ddd55882b 100644 --- a/examples/light-switch-app/efr32/README.md +++ b/examples/light-switch-app/efr32/README.md @@ -271,6 +271,11 @@ combination with JLinkRTTClient as follows: - 'switch groups onoff off' : Sends On group command to bound group - 'switch groups onoff toggle' : Sends On group command to bound group + **_Binding Cluster_** + + - 'switch binding unicast ' : Creates a unicast binding + - 'switch binding group ' : Creates a group binding + * You can provision and control the Chip device using the python controller, [CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md) standalone, Android or iOS app @@ -280,7 +285,7 @@ combination with JLinkRTTClient as follows: ``` chip-tool pairing ble-thread 1 hex: 20202021 3840 - chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": [1], "targets": null }]' 0 + chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [], "targets": null }{"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": [1], "targets": null }]' 0 chip-tool binding write binding '[{"fabricIndex": 1, "node": , "endpoint": 1, "cluster":6}]' 1 1 ``` @@ -304,6 +309,13 @@ combination with JLinkRTTClient as follows: chip-tool binding write binding '[{"fabricIndex": 1, "group": 257},{"fabricIndex": 1, "node": , "endpoint": 1, "cluster":6} ]' 1 1 ``` + To acquire the chip-tool node id, read the acl table right after + commissioning + + ``` + ./connectedhomeip/out/chip-tool/chip-tool accesscontrol read acl 0 + ``` + ### Notes - Depending on your network settings your router might not provide native ipv6 diff --git a/examples/light-switch-app/efr32/include/binding-handler.h b/examples/light-switch-app/efr32/include/binding-handler.h index 367b8962771b46..aed08be25eb5bc 100644 --- a/examples/light-switch-app/efr32/include/binding-handler.h +++ b/examples/light-switch-app/efr32/include/binding-handler.h @@ -22,6 +22,7 @@ CHIP_ERROR InitBindingHandler(); void SwitchWorkerFunction(intptr_t context); +void BindingWorkerFunction(intptr_t context); struct BindingCommandData { diff --git a/examples/light-switch-app/efr32/src/binding-handler.cpp b/examples/light-switch-app/efr32/src/binding-handler.cpp index 24fc87e5b9a7fa..d58484e1b6dcc0 100644 --- a/examples/light-switch-app/efr32/src/binding-handler.cpp +++ b/examples/light-switch-app/efr32/src/binding-handler.cpp @@ -23,6 +23,7 @@ #include "app/server/Server.h" #include "controller/InvokeInteraction.h" #include "platform/CHIPDeviceLayer.h" +#include #include #if defined(ENABLE_CHIP_SHELL) @@ -41,9 +42,11 @@ using Shell::streamer_printf; Engine sShellSwitchSubCommands; Engine sShellSwitchOnOffSubCommands; -Engine sShellSwitchGroupsSubCommands; +Engine sShellSwitchGroupsSubCommands; Engine sShellSwitchGroupsOnOffSubCommands; + +Engine sShellSwitchBindingSubCommands; #endif // defined(ENABLE_CHIP_SHELL) namespace { @@ -202,6 +205,57 @@ CHIP_ERROR ToggleSwitchCommandHandler(int argc, char ** argv) return CHIP_NO_ERROR; } +/******************************************************** + * bind switch shell functions + *********************************************************/ + +CHIP_ERROR BindingHelpHandler(int argc, char ** argv) +{ + sShellSwitchBindingSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR BindingSwitchCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return BindingHelpHandler(argc, argv); + } + + return sShellSwitchBindingSubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR BindingGroupBindCommandHandler(int argc, char ** argv) +{ + VerifyOrReturnError(argc == 2, CHIP_ERROR_INVALID_ARGUMENT); + + EmberBindingTableEntry * entry = Platform::New(); + entry->type = EMBER_MULTICAST_BINDING; + entry->fabricIndex = atoi(argv[0]); + entry->groupId = atoi(argv[1]); + entry->local = 1; // Hardcoded to endpoint 1 for now + entry->clusterId.SetValue(6); // Hardcoded to OnOff cluster for now + + DeviceLayer::PlatformMgr().ScheduleWork(BindingWorkerFunction, reinterpret_cast(entry)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR BindingUnicastBindCommandHandler(int argc, char ** argv) +{ + VerifyOrReturnError(argc == 3, CHIP_ERROR_INVALID_ARGUMENT); + + EmberBindingTableEntry * entry = Platform::New(); + entry->type = EMBER_UNICAST_BINDING; + entry->fabricIndex = atoi(argv[0]); + entry->nodeId = atoi(argv[1]); + entry->local = 1; // Hardcoded to endpoint 1 for now + entry->remote = atoi(argv[2]); + entry->clusterId.SetValue(6)); // Hardcode to OnOff cluster for now + + DeviceLayer::PlatformMgr().ScheduleWork(BindingWorkerFunction, reinterpret_cast(entry)); + return CHIP_NO_ERROR; +} + /******************************************************** * Groups switch shell functions *********************************************************/ @@ -285,7 +339,7 @@ static void RegisterSwitchCommands() { &SwitchHelpHandler, "help", "Usage: switch " }, { &OnOffSwitchCommandHandler, "onoff", " Usage: switch onoff " }, { &GroupsSwitchCommandHandler, "groups", "Usage: switch groups " }, - + { &BindingSwitchCommandHandler, "binding", "Usage: switch binding " } }; static const shell_command_t sSwitchOnOffSubCommands[] = { @@ -299,19 +353,26 @@ static void RegisterSwitchCommands() { &GroupsOnOffSwitchCommandHandler, "onoff", "Usage: switch groups onoff " } }; - static const shell_command_t sSwichGroupsOnOffSubCommands[] = { + static const shell_command_t sSwitchGroupsOnOffSubCommands[] = { { &GroupsOnOffHelpHandler, "help", "Usage: switch groups onoff " }, { &GroupOnSwitchCommandHandler, "on", "Sends on command to bound group" }, { &GroupOffSwitchCommandHandler, "off", "Sends off command to bound group" }, { &GroupToggleSwitchCommandHandler, "toggle", "Sends toggle command to group" } }; + static const shell_command_t sSwitchBindingSubCommands[] = { + { &BindingHelpHandler, "help", "Usage: switch binding " }, + { &BindingGroupBindCommandHandler, "group", "Usage: switch binding group " }, + { &BindingUnicastBindCommandHandler, "unicast", "Usage: switch binding group " } + }; + static const shell_command_t sSwitchCommand = { &SwitchCommandHandler, "switch", "Light-switch commands. Usage: switch " }; - sShellSwitchGroupsOnOffSubCommands.RegisterCommands(sSwichGroupsOnOffSubCommands, ArraySize(sSwichGroupsOnOffSubCommands)); + sShellSwitchGroupsOnOffSubCommands.RegisterCommands(sSwitchGroupsOnOffSubCommands, ArraySize(sSwitchGroupsOnOffSubCommands)); sShellSwitchOnOffSubCommands.RegisterCommands(sSwitchOnOffSubCommands, ArraySize(sSwitchOnOffSubCommands)); sShellSwitchGroupsSubCommands.RegisterCommands(sSwitchGroupsSubCommands, ArraySize(sSwitchGroupsSubCommands)); + sShellSwitchBindingSubCommands.RegisterCommands(sSwitchBindingSubCommands, ArraySize(sSwitchBindingSubCommands)); sShellSwitchSubCommands.RegisterCommands(sSwitchSubCommands, ArraySize(sSwitchSubCommands)); Engine::Root().RegisterCommands(&sSwitchCommand, 1); @@ -342,6 +403,16 @@ void SwitchWorkerFunction(intptr_t context) Platform::Delete(data); } +void BindingWorkerFunction(intptr_t context) +{ + VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "BindingWorkerFunction - Invalid work data")); + + EmberBindingTableEntry * entry = reinterpret_cast(context); + AddBindingEntry(*entry); + + Platform::Delete(entry); +} + CHIP_ERROR InitBindingHandler() { // The initialization of binding manager will try establishing connection with unicast peers diff --git a/src/app/clusters/bindings/bindings.cpp b/src/app/clusters/bindings/bindings.cpp index c532c68cd65325..d13c1621416716 100644 --- a/src/app/clusters/bindings/bindings.cpp +++ b/src/app/clusters/bindings/bindings.cpp @@ -25,11 +25,9 @@ #include #include #include -#include +#include #include -#include #include - using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; @@ -86,7 +84,7 @@ CHIP_ERROR CheckValidBindingList(const DecodableBindingListType & bindingList, F return CHIP_NO_ERROR; } -void AddBindingEntry(const TargetStructType & entry, EndpointId localEndpoint) +void CreateBindingEntry(const TargetStructType & entry, EndpointId localEndpoint) { EmberBindingTableEntry bindingEntry; @@ -98,18 +96,9 @@ void AddBindingEntry(const TargetStructType & entry, EndpointId localEndpoint) { bindingEntry = EmberBindingTableEntry::ForNode(entry.fabricIndex, entry.node.Value(), localEndpoint, entry.endpoint.Value(), entry.cluster); - CHIP_ERROR err = BindingManager::GetInstance().UnicastBindingCreated(entry.fabricIndex, entry.node.Value()); - if (err != CHIP_NO_ERROR) - { - // Unicast connection failure can happen if peer is offline. We'll retry connection on-demand. - ChipLogProgress( - Zcl, "Binding: Failed to create session for unicast binding to device " ChipLogFormatX64 ": %" CHIP_ERROR_FORMAT, - ChipLogValueX64(entry.node.Value()), err.Format()); - } } - BindingTable::GetInstance().Add(bindingEntry); - BindingManager::GetInstance().NotifyBindingAdded(bindingEntry); + AddBindingEntry(bindingEntry); } CHIP_ERROR BindingTableAccess::Read(const ConcreteReadAttributePath & path, AttributeValueEncoder & encoder) @@ -200,7 +189,7 @@ CHIP_ERROR BindingTableAccess::WriteBindingTable(const ConcreteDataAttributePath auto iter = newBindingList.begin(); while (iter.Next()) { - AddBindingEntry(iter.GetValue(), path.mEndpointId); + CreateBindingEntry(iter.GetValue(), path.mEndpointId); } return CHIP_NO_ERROR; } @@ -212,7 +201,7 @@ CHIP_ERROR BindingTableAccess::WriteBindingTable(const ConcreteDataAttributePath { return CHIP_IM_GLOBAL_STATUS(ConstraintError); } - AddBindingEntry(target, path.mEndpointId); + CreateBindingEntry(target, path.mEndpointId); return CHIP_NO_ERROR; } return CHIP_IM_GLOBAL_STATUS(UnsupportedWrite); @@ -223,3 +212,21 @@ void MatterBindingPluginServerInitCallback() { registerAttributeAccessOverride(&gAttrAccess); } + +void AddBindingEntry(const EmberBindingTableEntry & entry) +{ + if (entry.type == EMBER_UNICAST_BINDING) + { + CHIP_ERROR err = BindingManager::GetInstance().UnicastBindingCreated(entry.fabricIndex, entry.nodeId); + if (err != CHIP_NO_ERROR) + { + // Unicast connection failure can happen if peer is offline. We'll retry connection on-demand. + ChipLogProgress( + Zcl, "Binding: Failed to create session for unicast binding to device " ChipLogFormatX64 ": %" CHIP_ERROR_FORMAT, + ChipLogValueX64(entry.nodeId), err.Format()); + } + } + + BindingTable::GetInstance().Add(entry); + BindingManager::GetInstance().NotifyBindingAdded(entry); +} diff --git a/src/app/clusters/bindings/bindings.h b/src/app/clusters/bindings/bindings.h new file mode 100644 index 00000000000000..3d6d773cdbcd8c --- /dev/null +++ b/src/app/clusters/bindings/bindings.h @@ -0,0 +1,31 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include + +/** + * @brief appends a binding to the list of bindings + * This function is to be used when a device wants to add a binding to its own table + * If entry is a unicast binding, BindingManager will be notified and will establish a case session with the peer device + * Entry will be added to the binding table and persisted into storage + * BindingManager will be notified and the binding added callback will be called if it has been set + * + * @param entry binding to add + */ +void AddBindingEntry(const EmberBindingTableEntry & entry); From 84c150a1b98746811b4931036d5ac3be0b2c592c Mon Sep 17 00:00:00 2001 From: Jean-Francois Penven <67962328+jepenven-silabs@users.noreply.github.com> Date: Thu, 17 Mar 2022 14:13:56 -0400 Subject: [PATCH 04/15] [Group] Configure Chip-tool's GroupDataProvider (#16232) * Configure Chip-tool's GroupDataProvider --- .github/.wordlist.txt | 8 + examples/chip-tool/README.md | 39 ++ .../chip-tool/commands/common/CHIPCommand.cpp | 2 +- examples/chip-tool/commands/group/Commands.h | 372 ++++++++++++++++++ examples/chip-tool/main.cpp | 2 + src/lib/support/TestGroupData.h | 8 + 6 files changed, 430 insertions(+), 1 deletion(-) create mode 100644 examples/chip-tool/commands/group/Commands.h diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 3245626bebaa79..4b3359cc8684a4 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -300,6 +300,7 @@ cxx CY CYW DAC +dadbdcdddedf DAP DAPLINK DataFrame @@ -358,6 +359,7 @@ DevKitC DevKitM devtype df +dfe dfu DgDxsfHx dhclient @@ -542,6 +544,7 @@ Gradle gradlew GroupId GroupKeyManagement +groupsettings gtk GUA Gv @@ -646,6 +649,7 @@ kBusy kCase Kconfig KeypadInput +keyset kGroup kInvalidCommandId KitProg @@ -1184,6 +1188,7 @@ TestEmptyString TestGenExample TestGroupDemoConfig TestMultiRead +TestName TESTPASSWD TestPICS TESTSSID @@ -1326,6 +1331,7 @@ WS WSL WSTK xa +xAAAA xab xaver xb @@ -1358,6 +1364,8 @@ xfffff xFFFFFFFD xffffffffe xfffffffff +xffffffffffff +xffffffffffffXXXX xtensa xwayland XXXX diff --git a/examples/chip-tool/README.md b/examples/chip-tool/README.md index e90072970abc15..c44e830e299595 100644 --- a/examples/chip-tool/README.md +++ b/examples/chip-tool/README.md @@ -120,6 +120,45 @@ The endpoint id must be between 1 and 240. The client will send a single command packet and then exit. +## Configuring the client for Group Commands + +Prior to sending a Group command, both the end device and the Client (Chip-tool) +must be configured appropriately. + +To configure the client please use the groupsettings option + + $ chip-tool groupsettings + +A group with a valid encryption key needs to be set. The groupid and the +encryption key must match the one configured on the end device. + +To add a group + + $ chip-tool groupsettings add-group TestName 0x1010 + +To add a keyset + + $ chip-tool groupsettings add-keyset 0xAAAA 0 0x000000000021dfe0 hex:d0d1d2d3d4d5d6d7d8d9dadbdcdddedf + +Take note that the epoch key must be in hex form with the 'hex:' prefix + +Finally to bind the keyset to the group + + $ chip-tool groupsettings bind-keyset 0x1010 0xAAAA + +## Using the Client to Send Group (Multicast) Matter Commands + +To use the Client to send Matter commands, run the built executable and pass it +the target cluster name, the target command name, the Group Id in Node Id form +(0xffffffffffffXXXX) and an unused endpoint Id. Take note that Only commands and +attributes write can be send with Group Id. + +E.G. sending to group Id 0x0025 + + $ chip-tool onoff on 0xffffffffffff0025 1 + +The client will send a single multicast command packet and then exit. + ### How to get the list of supported clusters To get the list of supported clusters, run the built executable without any diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index bb34584bf2ec72..856dbbeee6ed16 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -61,7 +61,7 @@ CHIP_ERROR CHIPCommand::Run() ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityGamma, kIdentityGammaFabricId, trustStore)); // Initialize Group Data - ReturnLogErrorOnFailure(chip::GroupTesting::InitProvider()); + ReturnLogErrorOnFailure(chip::GroupTesting::InitProvider(mDefaultStorage)); for (auto it = mCommissioners.begin(); it != mCommissioners.end(); it++) { chip::FabricInfo * fabric = it->second->GetFabricInfo(); diff --git a/examples/chip-tool/commands/group/Commands.h b/examples/chip-tool/commands/group/Commands.h new file mode 100644 index 00000000000000..7f5b838566c145 --- /dev/null +++ b/examples/chip-tool/commands/group/Commands.h @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include "../common/CHIPCommand.h" +#include "../common/Command.h" + +#include + +class ShowControllerGroups : public CHIPCommand +{ +public: + ShowControllerGroups(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("show-groups", credsIssuerConfig) {} + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); } + + bool FindKeySetId(chip::FabricIndex fabricIndex, chip::GroupId groupId, chip::KeysetId & keysetId) + { + chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider(); + auto iter = groupDataProvider->IterateGroupKeys(fabricIndex); + chip::Credentials::GroupDataProvider::GroupKey groupKey; + while (iter->Next(groupKey)) + { + if (groupKey.group_id == groupId) + { + keysetId = groupKey.keyset_id; + iter->Release(); + return true; + } + } + iter->Release(); + return false; + } + + CHIP_ERROR RunCommand() override + { + fprintf(stderr, "\n"); + fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); + fprintf(stderr, " | Available Groups : |\n"); + fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); + fprintf(stderr, " | Group Id | KeySet Id | Group Name |\n"); + chip::FabricIndex fabricIndex; + CurrentCommissioner().GetFabricIndex(&fabricIndex); + chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider(); + auto it = groupDataProvider->IterateGroupInfo(fabricIndex); + chip::Credentials::GroupDataProvider::GroupInfo group; + if (it) + { + while (it->Next(group)) + { + chip::KeysetId keysetId; + if (FindKeySetId(fabricIndex, group.group_id, keysetId)) + { + fprintf(stderr, " | 0x%-12x 0x%-13x %-50s |\n", group.group_id, keysetId, group.name); + } + else + { + fprintf(stderr, " | 0x%-12x %-15s %-50s |\n", group.group_id, "None", group.name); + } + } + it->Release(); + } + fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; + } +}; + +class AddGroup : public CHIPCommand +{ +public: + AddGroup(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("add-group", credsIssuerConfig) + { + AddArgument("groupName", &groupName); + AddArgument("groupId", chip::kUndefinedGroupId, UINT16_MAX, &groupId); + } + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(20); } + + CHIP_ERROR RunCommand() override + { + if (strlen(groupName) > CHIP_CONFIG_MAX_GROUP_NAME_LENGTH || groupId == chip::kUndefinedGroupId) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + chip::FabricIndex fabricIndex; + CurrentCommissioner().GetFabricIndex(&fabricIndex); + chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider(); + chip::Credentials::GroupDataProvider::GroupInfo group; + + group.SetName(groupName); + group.group_id = groupId; + ReturnErrorOnFailure(groupDataProvider->SetGroupInfo(fabricIndex, group)); + + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; + } + +private: + char * groupName; + chip::GroupId groupId; +}; + +class RemoveGroup : public CHIPCommand +{ +public: + RemoveGroup(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("remove-group", credsIssuerConfig) + { + AddArgument("groupId", chip::kUndefinedGroupId, UINT16_MAX, &groupId); + } + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); } + + CHIP_ERROR RunCommand() override + { + if (groupId == chip::kUndefinedGroupId) + { + ChipLogError(chipTool, "Invalid group Id : 0x%x", groupId); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + chip::FabricIndex fabricIndex; + CurrentCommissioner().GetFabricIndex(&fabricIndex); + chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider(); + ReturnErrorOnFailure(groupDataProvider->RemoveGroupInfo(fabricIndex, groupId)); + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; + } + +private: + chip::GroupId groupId; +}; + +class ShowKeySets : public CHIPCommand +{ +public: + ShowKeySets(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("show-keysets", credsIssuerConfig) {} + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); } + + CHIP_ERROR RunCommand() override + { + chip::FabricIndex fabricIndex; + CurrentCommissioner().GetFabricIndex(&fabricIndex); + chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider(); + chip::Credentials::GroupDataProvider::KeySet keySet; + + fprintf(stderr, "\n"); + fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); + fprintf(stderr, " | Available KeySets : |\n"); + fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); + fprintf(stderr, " | KeySet Id | Key Policy |\n"); + + auto it = groupDataProvider->IterateKeySets(fabricIndex); + if (it) + { + while (it->Next(keySet)) + { + fprintf(stderr, " | 0x%-12x %-66s |\n", keySet.keyset_id, + (keySet.policy == chip::Credentials::GroupDataProvider::SecurityPolicy::kCacheAndSync) ? "Cache and Sync" + : "Trust First"); + } + it->Release(); + } + fprintf(stderr, " +-------------------------------------------------------------------------------------+\n"); + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; + } +}; + +class BindKeySet : public CHIPCommand +{ +public: + BindKeySet(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("bind-keyset", credsIssuerConfig) + { + AddArgument("groupId", chip::kUndefinedGroupId, UINT16_MAX, &groupId); + AddArgument("keysetId", 0, UINT16_MAX, &keysetId); + } + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); } + + CHIP_ERROR RunCommand() override + { + size_t current_count = 0; + chip::FabricIndex fabricIndex; + CurrentCommissioner().GetFabricIndex(&fabricIndex); + chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider(); + + auto iter = groupDataProvider->IterateGroupKeys(fabricIndex); + current_count = iter->Count(); + iter->Release(); + + ReturnErrorOnFailure(groupDataProvider->SetGroupKeyAt(fabricIndex, current_count, + chip::Credentials::GroupDataProvider::GroupKey(groupId, keysetId))); + + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; + } + +private: + chip::GroupId groupId; + chip::KeysetId keysetId; +}; + +class UnbindKeySet : public CHIPCommand +{ +public: + UnbindKeySet(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("unbind-keyset", credsIssuerConfig) + { + AddArgument("groupId", chip::kUndefinedGroupId, UINT16_MAX, &groupId); + AddArgument("keysetId", 0, UINT16_MAX, &keysetId); + } + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); } + + CHIP_ERROR RunCommand() override + { + size_t index = 0; + chip::FabricIndex fabricIndex; + CurrentCommissioner().GetFabricIndex(&fabricIndex); + chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider(); + auto iter = groupDataProvider->IterateGroupKeys(fabricIndex); + size_t maxCount = iter->Count(); + chip::Credentials::GroupDataProvider::GroupKey groupKey; + while (iter->Next(groupKey)) + { + if (groupKey.group_id == groupId && groupKey.keyset_id == keysetId) + { + break; + } + index++; + } + iter->Release(); + if (index >= maxCount) + { + return CHIP_ERROR_INTERNAL; + } + + ReturnErrorOnFailure(groupDataProvider->RemoveGroupKeyAt(fabricIndex, index)); + + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; + } + +private: + chip::GroupId groupId; + chip::KeysetId keysetId; +}; + +class AddKeySet : public CHIPCommand +{ +public: + AddKeySet(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("add-keysets", credsIssuerConfig) + { + AddArgument("keysetId", 0, UINT16_MAX, &keysetId); + AddArgument("keyPolicy", 0, UINT16_MAX, &keyPolicy); + AddArgument("validityTime", 0, UINT64_MAX, &validityTime); + AddArgument("EpochKey", &epochKey); + } + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); } + + CHIP_ERROR RunCommand() override + { + chip::FabricIndex fabricIndex; + CurrentCommissioner().GetFabricIndex(&fabricIndex); + chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider(); + uint8_t compressed_fabric_id[sizeof(uint64_t)]; + chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id); + ReturnLogErrorOnFailure(CurrentCommissioner().GetFabricInfo()->GetCompressedId(compressed_fabric_id_span)); + + if ((keyPolicy != chip::Credentials::GroupDataProvider::SecurityPolicy::kCacheAndSync && + keyPolicy != chip::Credentials::GroupDataProvider::SecurityPolicy::kTrustFirst) || + (epochKey.size()) != chip::Credentials::GroupDataProvider::EpochKey::kLengthBytes) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + chip::Credentials::GroupDataProvider::KeySet keySet(keysetId, keyPolicy, 1); + chip::Credentials::GroupDataProvider::EpochKey epoch_key; + epoch_key.start_time = validityTime; + memcpy(epoch_key.key, epochKey.data(), chip::Credentials::GroupDataProvider::EpochKey::kLengthBytes); + + memcpy(keySet.epoch_keys, &epoch_key, sizeof(chip::Credentials::GroupDataProvider::EpochKey)); + ReturnErrorOnFailure(groupDataProvider->SetKeySet(fabricIndex, compressed_fabric_id_span, keySet)); + + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; + } + +private: + chip::KeysetId keysetId; + chip::Credentials::GroupDataProvider::SecurityPolicy keyPolicy; + uint64_t validityTime; + chip::ByteSpan epochKey; +}; + +class RemoveKeySet : public CHIPCommand +{ +public: + RemoveKeySet(CredentialIssuerCommands * credsIssuerConfig) : CHIPCommand("remove-keyset", credsIssuerConfig) + { + AddArgument("keysetId", 0, UINT16_MAX, &keysetId); + } + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(5); } + + CHIP_ERROR RunCommand() override + { + CHIP_ERROR err = CHIP_NO_ERROR; + chip::FabricIndex fabricIndex; + CurrentCommissioner().GetFabricIndex(&fabricIndex); + chip::Credentials::GroupDataProvider * groupDataProvider = chip::Credentials::GetGroupDataProvider(); + + // Unbind all group + size_t index = 0; + auto iter = groupDataProvider->IterateGroupKeys(fabricIndex); + chip::Credentials::GroupDataProvider::GroupKey groupKey; + while (iter->Next(groupKey)) + { + if (groupKey.keyset_id == keysetId) + { + err = groupDataProvider->RemoveGroupKeyAt(fabricIndex, index); + if (err != CHIP_NO_ERROR) + { + break; + } + } + index++; + } + iter->Release(); + + if (err == CHIP_NO_ERROR) + { + return err; + } + ReturnErrorOnFailure(groupDataProvider->RemoveKeySet(fabricIndex, keysetId)); + + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; + } + +private: + chip::KeysetId keysetId; +}; + +void registerCommandsGroup(Commands & commands, CredentialIssuerCommands * credsIssuerConfig) +{ + const char * clusterName = "GroupSettings"; + + commands_list clusterCommands = { + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + }; + + commands.Register(clusterName, clusterCommands); +} diff --git a/examples/chip-tool/main.cpp b/examples/chip-tool/main.cpp index 88d7adff4e800b..10e6b7440fb09c 100644 --- a/examples/chip-tool/main.cpp +++ b/examples/chip-tool/main.cpp @@ -20,6 +20,7 @@ #include "commands/example/ExampleCredentialIssuerCommands.h" #include "commands/discover/Commands.h" +#include "commands/group/Commands.h" #include "commands/pairing/Commands.h" #include "commands/payload/Commands.h" @@ -37,6 +38,7 @@ int main(int argc, char * argv[]) registerCommandsPayload(commands); registerCommandsPairing(commands, &credIssuerCommands); registerCommandsTests(commands, &credIssuerCommands); + registerCommandsGroup(commands, &credIssuerCommands); registerClusters(commands, &credIssuerCommands); return commands.Run(argc, argv); diff --git a/src/lib/support/TestGroupData.h b/src/lib/support/TestGroupData.h index bc80bac9ee84a8..dc611b4697609b 100644 --- a/src/lib/support/TestGroupData.h +++ b/src/lib/support/TestGroupData.h @@ -48,6 +48,14 @@ CHIP_ERROR InitProvider() return CHIP_NO_ERROR; } +CHIP_ERROR InitProvider(chip::PersistentStorageDelegate & storageDelegate) +{ + sGroupsProvider.SetStorageDelegate(&storageDelegate); + ReturnErrorOnFailure(sGroupsProvider.Init()); + chip::Credentials::SetGroupDataProvider(&sGroupsProvider); + return CHIP_NO_ERROR; +} + CHIP_ERROR InitData(chip::FabricIndex fabric_index, const ByteSpan & compressed_fabric_id) { // Groups From d43e6a791ac50c2c9cff1506f9106135a325753a Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Thu, 17 Mar 2022 17:39:24 -0400 Subject: [PATCH 05/15] use clang-tidy to readability-make-member-function-const (#16309) * use clang-tidy to readability-make-member-function-const * Code review comments - remove some of the consts that are not conceptually correct * Undo CHIPTLV changes - method seems to use class members * Update const compile for LWIP platforms * Restyle * Fix mbedos build * Fix one more const to make telink compile --- src/access/examples/ExampleAccessControlDelegate.cpp | 4 ++-- src/app/CASESessionManager.cpp | 6 +++--- src/app/CASESessionManager.h | 6 +++--- src/app/DataVersionFilter.h | 2 +- src/app/EventManagement.cpp | 2 +- src/app/EventManagement.h | 6 +++--- src/app/InteractionModelEngine.h | 2 +- src/app/ReadHandler.cpp | 2 +- src/app/ReadHandler.h | 12 ++++++------ src/app/reporting/Engine.h | 2 +- src/app/server/Dnssd.h | 6 +++--- src/app/util/binding-table.h | 8 ++++---- src/ble/BleLayer.cpp | 2 +- src/ble/BtpEngine.h | 8 ++++---- src/controller/AutoCommissioner.cpp | 4 ++-- src/controller/AutoCommissioner.h | 4 ++-- src/controller/SetUpCodePairer.cpp | 2 +- src/controller/SetUpCodePairer.h | 2 +- src/credentials/DeviceAttestationVendorReserved.h | 4 ++-- src/credentials/FabricTable.cpp | 2 +- src/credentials/FabricTable.h | 2 +- src/credentials/GroupDataProvider.h | 11 +++++++---- src/credentials/GroupDataProviderImpl.cpp | 4 ++-- src/include/platform/FailSafeContext.h | 8 ++++---- src/inet/InetInterface.cpp | 6 +++--- src/inet/InetInterface.h | 2 +- src/lib/core/CHIPTLV.h | 6 +++--- src/lib/core/CHIPTLVReader.cpp | 2 +- src/lib/support/CHIPArgParser.cpp | 6 +++--- src/lib/support/CHIPArgParser.hpp | 6 +++--- src/lib/support/SerializableIntegerSet.h | 4 ++-- src/messaging/ExchangeMgr.h | 2 +- src/platform/Linux/ThreadStackManagerImpl.cpp | 2 +- src/platform/Linux/ThreadStackManagerImpl.h | 2 +- src/platform/mbed/NetworkCommissioningWiFiDriver.cpp | 2 -- src/protocols/bdx/BdxTransferSession.cpp | 2 +- src/protocols/bdx/BdxTransferSession.h | 2 +- src/system/WakeEvent.cpp | 8 ++++---- src/system/WakeEvent.h | 4 ++-- src/transport/GroupSession.h | 4 ++-- src/transport/PeerMessageCounter.h | 2 +- 41 files changed, 87 insertions(+), 86 deletions(-) diff --git a/src/access/examples/ExampleAccessControlDelegate.cpp b/src/access/examples/ExampleAccessControlDelegate.cpp index 6d9b5595994ee4..f6b219b66a93e7 100644 --- a/src/access/examples/ExampleAccessControlDelegate.cpp +++ b/src/access/examples/ExampleAccessControlDelegate.cpp @@ -129,7 +129,7 @@ class SubjectStorage } public: - CHIP_ERROR Serialize(chip::TLV::TLVWriter & writer) { return writer.Put(chip::TLV::AnonymousTag(), mNode); } + CHIP_ERROR Serialize(chip::TLV::TLVWriter & writer) const { return writer.Put(chip::TLV::AnonymousTag(), mNode); } CHIP_ERROR Deserialize(chip::TLV::TLVReader & reader) { @@ -193,7 +193,7 @@ class TargetStorage } public: - CHIP_ERROR Serialize(chip::TLV::TLVWriter & writer) + CHIP_ERROR Serialize(chip::TLV::TLVWriter & writer) const { ReturnErrorOnFailure(writer.Put(chip::TLV::AnonymousTag(), mCluster)); return writer.Put(chip::TLV::AnonymousTag(), mDeviceType); diff --git a/src/app/CASESessionManager.cpp b/src/app/CASESessionManager.cpp index 58ec144a8f3fa6..af580d35148ee7 100644 --- a/src/app/CASESessionManager.cpp +++ b/src/app/CASESessionManager.cpp @@ -109,17 +109,17 @@ CHIP_ERROR CASESessionManager::GetPeerAddress(PeerId peerId, Transport::PeerAddr return CHIP_NO_ERROR; } -OperationalDeviceProxy * CASESessionManager::FindSession(const SessionHandle & session) +OperationalDeviceProxy * CASESessionManager::FindSession(const SessionHandle & session) const { return mConfig.devicePool->FindDevice(session); } -OperationalDeviceProxy * CASESessionManager::FindExistingSession(PeerId peerId) +OperationalDeviceProxy * CASESessionManager::FindExistingSession(PeerId peerId) const { return mConfig.devicePool->FindDevice(peerId); } -void CASESessionManager::ReleaseSession(OperationalDeviceProxy * session) +void CASESessionManager::ReleaseSession(OperationalDeviceProxy * session) const { if (session != nullptr) { diff --git a/src/app/CASESessionManager.h b/src/app/CASESessionManager.h index e2ab839b0df8a6..4f7c118c92a92f 100644 --- a/src/app/CASESessionManager.h +++ b/src/app/CASESessionManager.h @@ -75,7 +75,7 @@ class CASESessionManager CHIP_ERROR FindOrEstablishSession(PeerId peerId, Callback::Callback * onConnection, Callback::Callback * onFailure); - OperationalDeviceProxy * FindExistingSession(PeerId peerId); + OperationalDeviceProxy * FindExistingSession(PeerId peerId) const; void ReleaseSession(PeerId peerId); @@ -94,8 +94,8 @@ class CASESessionManager CHIP_ERROR GetPeerAddress(PeerId peerId, Transport::PeerAddress & addr); private: - OperationalDeviceProxy * FindSession(const SessionHandle & session); - void ReleaseSession(OperationalDeviceProxy * device); + OperationalDeviceProxy * FindSession(const SessionHandle & session) const; + void ReleaseSession(OperationalDeviceProxy * device) const; CASESessionManagerConfig mConfig; }; diff --git a/src/app/DataVersionFilter.h b/src/app/DataVersionFilter.h index ba93de61689693..1a6608e04a47eb 100644 --- a/src/app/DataVersionFilter.h +++ b/src/app/DataVersionFilter.h @@ -32,7 +32,7 @@ struct DataVersionFilter DataVersionFilter() {} - bool IsValidDataVersionFilter() + bool IsValidDataVersionFilter() const { return (mEndpointId != kInvalidEndpointId) && (mClusterId != kInvalidClusterId) && (mDataVersion.HasValue()); } diff --git a/src/app/EventManagement.cpp b/src/app/EventManagement.cpp index 1adb330321a2d9..88d4b7be7808f6 100644 --- a/src/app/EventManagement.cpp +++ b/src/app/EventManagement.cpp @@ -870,7 +870,7 @@ CHIP_ERROR EventManagement::EvictEvent(CHIPCircularTLVBuffer & apBuffer, void * return CHIP_END_OF_TLV; } -void EventManagement::SetScheduledEventInfo(EventNumber & aEventNumber, uint32_t & aInitialWrittenEventBytes) +void EventManagement::SetScheduledEventInfo(EventNumber & aEventNumber, uint32_t & aInitialWrittenEventBytes) const { #if !CHIP_SYSTEM_CONFIG_NO_LOCKING ScopedLock lock(sInstance); diff --git a/src/app/EventManagement.h b/src/app/EventManagement.h index 68d29cc66404df..9d6802105cc237 100644 --- a/src/app/EventManagement.h +++ b/src/app/EventManagement.h @@ -98,7 +98,7 @@ class CircularEventBuffer : public TLV::CHIPCircularTLVBuffer CircularEventBuffer * GetNextCircularEventBuffer() { return mpNext; } void SetRequiredSpaceforEvicted(size_t aRequiredSpace) { mRequiredSpaceForEvicted = aRequiredSpace; } - size_t GetRequiredSpaceforEvicted() { return mRequiredSpaceForEvicted; } + size_t GetRequiredSpaceforEvicted() const { return mRequiredSpaceForEvicted; } ~CircularEventBuffer() override = default; @@ -349,7 +349,7 @@ class EventManagement * * @return EventNumber most recently vended event Number for that event priority */ - EventNumber GetLastEventNumber() { return mLastEventNumber; } + EventNumber GetLastEventNumber() const { return mLastEventNumber; } /** * @brief @@ -360,7 +360,7 @@ class EventManagement /** * Logger would save last logged event number and initial written event bytes number into schedule event number array */ - void SetScheduledEventInfo(EventNumber & aEventNumber, uint32_t & aInitialWrittenEventBytes); + void SetScheduledEventInfo(EventNumber & aEventNumber, uint32_t & aInitialWrittenEventBytes) const; private: /** diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index f89ada218da0ec..572e9cbb35e833 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -129,7 +129,7 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate, public Comman /** * The Magic number of this InteractionModelEngine, the magic number is set during Init() */ - uint32_t GetMagicNumber() { return mMagic; } + uint32_t GetMagicNumber() const { return mMagic; } reporting::Engine & GetReportingEngine() { return mReportingEngine; } diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index 952d360046c11d..0ef94fd1f80706 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -273,7 +273,7 @@ CHIP_ERROR ReadHandler::OnMessageReceived(Messaging::ExchangeContext * apExchang return err; } -bool ReadHandler::IsFromSubscriber(Messaging::ExchangeContext & apExchangeContext) +bool ReadHandler::IsFromSubscriber(Messaging::ExchangeContext & apExchangeContext) const { return (IsType(InteractionType::Subscribe) && GetInitiatorNodeId() == apExchangeContext.GetSessionHandle()->AsSecureSession()->GetPeerNodeId() && diff --git a/src/app/ReadHandler.h b/src/app/ReadHandler.h index e5c4d7e83b2dff..f2c4bfc390ecb4 100644 --- a/src/app/ReadHandler.h +++ b/src/app/ReadHandler.h @@ -126,7 +126,7 @@ class ReadHandler : public Messaging::ExchangeDelegate /** * Returns whether this ReadHandler represents a subscription that was created by the other side of the provided exchange. */ - bool IsFromSubscriber(Messaging::ExchangeContext & apExchangeContext); + bool IsFromSubscriber(Messaging::ExchangeContext & apExchangeContext) const; bool IsReportable() const { return mState == HandlerState::GeneratingReports && !mHoldReport && (mDirty || !mHoldSync); } bool IsGeneratingReports() const { return mState == HandlerState::GeneratingReports; } @@ -145,12 +145,12 @@ class ReadHandler : public Messaging::ExchangeDelegate bool CheckEventClean(EventManagement & aEventManager); bool IsType(InteractionType type) const { return (mInteractionType == type); } - bool IsChunkedReport() { return mIsChunkedReport; } - bool IsPriming() { return mIsPrimingReports; } + bool IsChunkedReport() const { return mIsChunkedReport; } + bool IsPriming() const { return mIsPrimingReports; } bool IsActiveSubscription() const { return mActiveSubscription; } bool IsFabricFiltered() const { return mIsFabricFiltered; } CHIP_ERROR OnSubscribeRequest(Messaging::ExchangeContext * apExchangeContext, System::PacketBufferHandle && aPayload); - void GetSubscriptionId(uint64_t & aSubscriptionId) { aSubscriptionId = mSubscriptionId; } + void GetSubscriptionId(uint64_t & aSubscriptionId) const { aSubscriptionId = mSubscriptionId; } AttributePathExpandIterator * GetAttributePathExpandIterator() { return &mAttributePathExpandIterator; } void SetDirty() { @@ -161,7 +161,7 @@ class ReadHandler : public Messaging::ExchangeDelegate mAttributeEncoderState = AttributeValueEncoder::AttributeEncodeState(); } void ClearDirty() { mDirty = false; } - bool IsDirty() { return mDirty; } + bool IsDirty() const { return mDirty; } NodeId GetInitiatorNodeId() const { return mInitiatorNodeId; } FabricIndex GetAccessingFabricIndex() const { return mSubjectDescriptor.fabricIndex; } @@ -175,7 +175,7 @@ class ReadHandler : public Messaging::ExchangeDelegate const AttributeValueEncoder::AttributeEncodeState & GetAttributeEncodeState() const { return mAttributeEncoderState; } void SetAttributeEncodeState(const AttributeValueEncoder::AttributeEncodeState & aState) { mAttributeEncoderState = aState; } - uint32_t GetLastWrittenEventsBytes() { return mLastWrittenEventsBytes; } + uint32_t GetLastWrittenEventsBytes() const { return mLastWrittenEventsBytes; } CHIP_ERROR SendStatusReport(Protocols::InteractionModel::Status aStatus); private: diff --git a/src/app/reporting/Engine.h b/src/app/reporting/Engine.h index c29f100d0e5ac2..3ed8512dad8b47 100644 --- a/src/app/reporting/Engine.h +++ b/src/app/reporting/Engine.h @@ -118,7 +118,7 @@ class Engine } } - uint32_t GetNumReportsInFlight() { return mNumReportsInFlight; } + uint32_t GetNumReportsInFlight() const { return mNumReportsInFlight; } void ScheduleUrgentEventDeliverySync(); diff --git a/src/app/server/Dnssd.h b/src/app/server/Dnssd.h index c396fa5964b72d..efc7b86ea5ce08 100644 --- a/src/app/server/Dnssd.h +++ b/src/app/server/Dnssd.h @@ -45,13 +45,13 @@ class DLL_EXPORT DnssdServer void SetSecuredPort(uint16_t port) { mSecuredPort = port; } /// Gets the secure Matter port - uint16_t GetSecuredPort() { return mSecuredPort; } + uint16_t GetSecuredPort() const { return mSecuredPort; } /// Sets the unsecure Matter port void SetUnsecuredPort(uint16_t port) { mUnsecuredPort = port; } /// Gets the unsecure Matter port - uint16_t GetUnsecuredPort() { return mUnsecuredPort; } + uint16_t GetUnsecuredPort() const { return mUnsecuredPort; } /// Sets the interface id used for advertising void SetInterfaceId(Inet::InterfaceId interfaceId) { mInterfaceId = interfaceId; } @@ -63,7 +63,7 @@ class DLL_EXPORT DnssdServer void SetDiscoveryTimeoutSecs(int16_t secs) { mDiscoveryTimeoutSecs = secs; } /// Gets the factory-new state commissionable node discovery timeout - int16_t GetDiscoveryTimeoutSecs() { return mDiscoveryTimeoutSecs; } + int16_t GetDiscoveryTimeoutSecs() const { return mDiscoveryTimeoutSecs; } // // Override the referenced fabric table from the default that is present diff --git a/src/app/util/binding-table.h b/src/app/util/binding-table.h index 1ae270fd109035..792a796b737356 100644 --- a/src/app/util/binding-table.h +++ b/src/app/util/binding-table.h @@ -50,11 +50,11 @@ class BindingTable Iterator operator++(); - bool operator==(const Iterator & rhs) { return mIndex == rhs.mIndex; } + bool operator==(const Iterator & rhs) const { return mIndex == rhs.mIndex; } - bool operator!=(const Iterator & rhs) { return mIndex != rhs.mIndex; } + bool operator!=(const Iterator & rhs) const { return mIndex != rhs.mIndex; } - uint8_t GetIndex() { return mIndex; } + uint8_t GetIndex() const { return mIndex; } private: BindingTable * mTable; @@ -71,7 +71,7 @@ class BindingTable // Returns the number of active entries in the binding table. // *NOTE* The function does not return the capacity of the binding table. - uint8_t Size() { return mSize; } + uint8_t Size() const { return mSize; } Iterator begin(); diff --git a/src/ble/BleLayer.cpp b/src/ble/BleLayer.cpp index 50cf13ebe3e242..d634e1940e806e 100644 --- a/src/ble/BleLayer.cpp +++ b/src/ble/BleLayer.cpp @@ -94,7 +94,7 @@ class BleEndPointPool return nullptr; } - BLEEndPoint * Find(BLE_CONNECTION_OBJECT c) + BLEEndPoint * Find(BLE_CONNECTION_OBJECT c) const { if (c == BLE_CONNECTION_UNINITIALIZED) { diff --git a/src/ble/BtpEngine.h b/src/ble/BtpEngine.h index 1c3bed32206df9..d861c3df5e4c0c 100644 --- a/src/ble/BtpEngine.h +++ b/src/ble/BtpEngine.h @@ -108,14 +108,14 @@ class BtpEngine inline void SetTxFragmentSize(uint16_t size) { mTxFragmentSize = size; } inline void SetRxFragmentSize(uint16_t size) { mRxFragmentSize = size; } - uint16_t GetRxFragmentSize() { return mRxFragmentSize; } - uint16_t GetTxFragmentSize() { return mTxFragmentSize; } + uint16_t GetRxFragmentSize() const { return mRxFragmentSize; } + uint16_t GetTxFragmentSize() const { return mTxFragmentSize; } SequenceNumber_t GetAndIncrementNextTxSeqNum(); SequenceNumber_t GetAndRecordRxAckSeqNum(); - inline SequenceNumber_t GetLastReceivedSequenceNumber() { return mRxNewestUnackedSeqNum; } - inline SequenceNumber_t GetNewestUnackedSentSequenceNumber() { return mTxNewestUnackedSeqNum; } + inline SequenceNumber_t GetLastReceivedSequenceNumber() const { return mRxNewestUnackedSeqNum; } + inline SequenceNumber_t GetNewestUnackedSentSequenceNumber() const { return mTxNewestUnackedSeqNum; } inline bool ExpectingAck() const { return mExpectingAck; } diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp index d8c3b30e1a1206..4e176ac8bf4934 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -209,7 +209,7 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStag return CommissioningStage::kError; } -EndpointId AutoCommissioner::GetEndpoint(const CommissioningStage & stage) +EndpointId AutoCommissioner::GetEndpoint(const CommissioningStage & stage) const { switch (stage) { @@ -249,7 +249,7 @@ CHIP_ERROR AutoCommissioner::StartCommissioning(DeviceCommissioner * commissione return CHIP_NO_ERROR; } -Optional AutoCommissioner::GetCommandTimeout(CommissioningStage stage) +Optional AutoCommissioner::GetCommandTimeout(CommissioningStage stage) const { // Per spec, all commands that are sent with the arm failsafe held need at least a 30s timeout. // Network clusters can indicate the time required to connect, so if we are connecting, use that time as long as it is > 30s. diff --git a/src/controller/AutoCommissioner.h b/src/controller/AutoCommissioner.h index 5c2438fc28ee33..fa4693adf2152c 100644 --- a/src/controller/AutoCommissioner.h +++ b/src/controller/AutoCommissioner.h @@ -49,8 +49,8 @@ class AutoCommissioner : public CommissioningDelegate ByteSpan GetPAI() const { return ByteSpan(mPAI, mPAILen); } CHIP_ERROR NOCChainGenerated(ByteSpan noc, ByteSpan icac, ByteSpan rcac, AesCcm128KeySpan ipk, NodeId adminSubject); - Optional GetCommandTimeout(CommissioningStage stage); - EndpointId GetEndpoint(const CommissioningStage & stage); + Optional GetCommandTimeout(CommissioningStage stage) const; + EndpointId GetEndpoint(const CommissioningStage & stage) const; DeviceCommissioner * mCommissioner = nullptr; CommissioneeDeviceProxy * mCommissioneeDeviceProxy = nullptr; diff --git a/src/controller/SetUpCodePairer.cpp b/src/controller/SetUpCodePairer.cpp index 0cde726a50de15..cda0978655f74c 100644 --- a/src/controller/SetUpCodePairer.cpp +++ b/src/controller/SetUpCodePairer.cpp @@ -167,7 +167,7 @@ void SetUpCodePairer::OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR } #endif // CONFIG_NETWORK_LAYER_BLE -bool SetUpCodePairer::NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & nodeData) +bool SetUpCodePairer::NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & nodeData) const { if (nodeData.commissioningMode == 0) { diff --git a/src/controller/SetUpCodePairer.h b/src/controller/SetUpCodePairer.h index 51c3bbf46ca453..19b57999f0eeae 100644 --- a/src/controller/SetUpCodePairer.h +++ b/src/controller/SetUpCodePairer.h @@ -85,7 +85,7 @@ class DLL_EXPORT SetUpCodePairer static void OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err); #endif // CONFIG_NETWORK_LAYER_BLE - bool NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & nodeData); + bool NodeMatchesCurrentFilter(const Dnssd::DiscoveredNodeData & nodeData) const; Dnssd::DiscoveryFilter currentFilter; DeviceCommissioner * mCommissioner = nullptr; diff --git a/src/credentials/DeviceAttestationVendorReserved.h b/src/credentials/DeviceAttestationVendorReserved.h index f016d8799f8cc5..7042b2c946ca3b 100644 --- a/src/credentials/DeviceAttestationVendorReserved.h +++ b/src/credentials/DeviceAttestationVendorReserved.h @@ -72,7 +72,7 @@ class DeviceAttestationVendorReservedDeconstructor return CHIP_NO_ERROR; } - size_t GetNumberOfElements() { return mNumVendorReservedData; } + size_t GetNumberOfElements() const { return mNumVendorReservedData; } /** * @brief Return next VendorReserved element. PrepareToReadVendorReservedElements must be called first. @@ -169,7 +169,7 @@ class DeviceAttestationVendorReservedConstructor return CHIP_NO_ERROR; } - size_t GetNumberOfElements() { return mNumEntriesUsed; } + size_t GetNumberOfElements() const { return mNumEntriesUsed; } private: /* diff --git a/src/credentials/FabricTable.cpp b/src/credentials/FabricTable.cpp index 4f584437ba05d7..2642e82cb2dbda 100644 --- a/src/credentials/FabricTable.cpp +++ b/src/credentials/FabricTable.cpp @@ -434,7 +434,7 @@ CHIP_ERROR FabricInfo::VerifyCredentials(const ByteSpan & noc, const ByteSpan & } CHIP_ERROR FabricInfo::GenerateDestinationID(const ByteSpan & ipk, const ByteSpan & random, NodeId destNodeId, - MutableByteSpan & destinationId) + MutableByteSpan & destinationId) const { constexpr uint16_t kSigmaParamRandomNumberSize = 32; constexpr size_t kDestinationMessageLen = diff --git a/src/credentials/FabricTable.h b/src/credentials/FabricTable.h index 45d1163643e03f..adcfbd680b05a3 100644 --- a/src/credentials/FabricTable.h +++ b/src/credentials/FabricTable.h @@ -141,7 +141,7 @@ class DLL_EXPORT FabricInfo bool IsInitialized() const { return IsOperationalNodeId(mOperationalId.GetNodeId()); } CHIP_ERROR GenerateDestinationID(const ByteSpan & ipk, const ByteSpan & random, NodeId destNodeId, - MutableByteSpan & destinationId); + MutableByteSpan & destinationId) const; CHIP_ERROR MatchDestinationID(const ByteSpan & destinationId, const ByteSpan & initiatorRandom, const ByteSpan * ipkList, size_t ipkListEntries); diff --git a/src/credentials/GroupDataProvider.h b/src/credentials/GroupDataProvider.h index d6e25c7e3d0dcd..f5fa345213f1b2 100644 --- a/src/credentials/GroupDataProvider.h +++ b/src/credentials/GroupDataProvider.h @@ -87,7 +87,10 @@ class GroupDataProvider GroupId group_id = kUndefinedGroupId; // Set of group keys that generate operational group keys for use with this group KeysetId keyset_id = 0; - bool operator==(const GroupKey & other) { return this->group_id == other.group_id && this->keyset_id == other.keyset_id; } + bool operator==(const GroupKey & other) const + { + return this->group_id == other.group_id && this->keyset_id == other.keyset_id; + } }; struct GroupEndpoint @@ -99,7 +102,7 @@ class GroupDataProvider // Endpoint on the Node to which messages to this group may be forwarded EndpointId endpoint_id = kInvalidEndpointId; - bool operator==(const GroupEndpoint & other) + bool operator==(const GroupEndpoint & other) const { return this->group_id == other.group_id && this->endpoint_id == other.endpoint_id; } @@ -217,8 +220,8 @@ class GroupDataProvider GroupDataProvider(const GroupDataProvider &) = delete; GroupDataProvider & operator=(const GroupDataProvider &) = delete; - uint16_t GetMaxGroupsPerFabric() { return mMaxGroupsPerFabric; } - uint16_t GetMaxGroupKeysPerFabric() { return mMaxGroupKeysPerFabric; } + uint16_t GetMaxGroupsPerFabric() const { return mMaxGroupsPerFabric; } + uint16_t GetMaxGroupKeysPerFabric() const { return mMaxGroupKeysPerFabric; } /** * Initialize the GroupDataProvider, including possibly any persistent diff --git a/src/credentials/GroupDataProviderImpl.cpp b/src/credentials/GroupDataProviderImpl.cpp index 5dc549fb5b7e89..f9c03fd2e0dc8f 100644 --- a/src/credentials/GroupDataProviderImpl.cpp +++ b/src/credentials/GroupDataProviderImpl.cpp @@ -291,7 +291,7 @@ struct FabricData : public PersistentData } // Remove the fabric from the fabrics' linked list - CHIP_ERROR Unregister(PersistentStorageDelegate * storage) + CHIP_ERROR Unregister(PersistentStorageDelegate * storage) const { FabricList fabric_list; CHIP_ERROR err = fabric_list.Load(storage); @@ -334,7 +334,7 @@ struct FabricData : public PersistentData } // Check the fabric is registered in the fabrics' linked list - CHIP_ERROR Validate(PersistentStorageDelegate * storage) + CHIP_ERROR Validate(PersistentStorageDelegate * storage) const { FabricList fabric_list; ReturnErrorOnFailure(fabric_list.Load(storage)); diff --git a/src/include/platform/FailSafeContext.h b/src/include/platform/FailSafeContext.h index b575494574fe48..41eaac12023c07 100644 --- a/src/include/platform/FailSafeContext.h +++ b/src/include/platform/FailSafeContext.h @@ -47,15 +47,15 @@ class FailSafeContext return mFailSafeArmed && MatchesFabricIndex(accessingFabricIndex); } - inline bool IsFailSafeArmed() { return mFailSafeArmed; } + inline bool IsFailSafeArmed() const { return mFailSafeArmed; } - inline bool MatchesFabricIndex(FabricIndex accessingFabricIndex) + inline bool MatchesFabricIndex(FabricIndex accessingFabricIndex) const { VerifyOrDie(mFailSafeArmed); return (accessingFabricIndex == mFabricIndex); } - inline bool NocCommandHasBeenInvoked() { return mNocCommandHasBeenInvoked; } + inline bool NocCommandHasBeenInvoked() const { return mNocCommandHasBeenInvoked; } inline void SetNocCommandInvoked(FabricIndex nocFabricIndex) { @@ -63,7 +63,7 @@ class FailSafeContext mFabricIndex = nocFabricIndex; } - inline FabricIndex GetFabricIndex() + inline FabricIndex GetFabricIndex() const { VerifyOrDie(mFailSafeArmed); return mFabricIndex; diff --git a/src/inet/InetInterface.cpp b/src/inet/InetInterface.cpp index be344cbe43b983..9f5356eef52c23 100644 --- a/src/inet/InetInterface.cpp +++ b/src/inet/InetInterface.cpp @@ -283,7 +283,7 @@ bool InterfaceAddressIterator::HasBroadcastAddress() return HasCurrent() && mIntfIter.HasBroadcastAddress(); } -CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) +CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const { VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -754,7 +754,7 @@ bool InterfaceAddressIterator::HasBroadcastAddress() return HasCurrent() && (mCurAddr->ifa_flags & IFF_BROADCAST) != 0; } -CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) +CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const { VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -995,7 +995,7 @@ bool InterfaceAddressIterator::HasBroadcastAddress() return HasCurrent() && mIntfIter.HasBroadcastAddress(); } -CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) +CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const { VerifyOrReturnError(llAddr != nullptr, CHIP_ERROR_INVALID_ARGUMENT); diff --git a/src/inet/InetInterface.h b/src/inet/InetInterface.h index 1189b0a9024e45..aa303b57a2627f 100644 --- a/src/inet/InetInterface.h +++ b/src/inet/InetInterface.h @@ -180,7 +180,7 @@ class InterfaceId * any address configured. * @retval #CHIP_NO_ERROR On success. */ - CHIP_ERROR GetLinkLocalAddr(IPAddress * llAddr); + CHIP_ERROR GetLinkLocalAddr(IPAddress * llAddr) const; private: #if CHIP_SYSTEM_CONFIG_USE_LWIP diff --git a/src/lib/core/CHIPTLV.h b/src/lib/core/CHIPTLV.h index 9f3947c1df98bc..9dff35af5e476a 100644 --- a/src/lib/core/CHIPTLV.h +++ b/src/lib/core/CHIPTLV.h @@ -938,7 +938,7 @@ class DLL_EXPORT TLVReader CHIP_ERROR SkipData(); CHIP_ERROR SkipToEndOfContainer(); CHIP_ERROR VerifyElement(); - Tag ReadTag(TLVTagControl tagControl, const uint8_t *& p); + Tag ReadTag(TLVTagControl tagControl, const uint8_t *& p) const; CHIP_ERROR EnsureData(CHIP_ERROR noDataErr); CHIP_ERROR ReadData(uint8_t * buf, uint32_t len); CHIP_ERROR GetElementHeadLength(uint8_t & elemHeadBytes) const; @@ -2370,7 +2370,7 @@ class DLL_EXPORT TLVUpdater * implicit form. */ void SetImplicitProfileId(uint32_t profileId); - uint32_t GetImplicitProfileId() { return mUpdaterReader.ImplicitProfileId; } + uint32_t GetImplicitProfileId() const { return mUpdaterReader.ImplicitProfileId; } /** * Copies the current element from input TLV to output TLV. @@ -2610,7 +2610,7 @@ class DLL_EXPORT TLVUpdater } CHIP_ERROR EndContainer(TLVType outerContainerType) { return mUpdaterWriter.EndContainer(outerContainerType); } uint32_t GetLengthWritten() { return mUpdaterWriter.GetLengthWritten(); } - uint32_t GetRemainingFreeLength() { return mUpdaterWriter.mRemainingLen; } + uint32_t GetRemainingFreeLength() const { return mUpdaterWriter.mRemainingLen; } private: void AdjustInternalWriterFreeSpace(); diff --git a/src/lib/core/CHIPTLVReader.cpp b/src/lib/core/CHIPTLVReader.cpp index 18950d7111e863..9c5f23c5d60389 100644 --- a/src/lib/core/CHIPTLVReader.cpp +++ b/src/lib/core/CHIPTLVReader.cpp @@ -784,7 +784,7 @@ CHIP_ERROR TLVReader::VerifyElement() return CHIP_NO_ERROR; } -Tag TLVReader::ReadTag(TLVTagControl tagControl, const uint8_t *& p) +Tag TLVReader::ReadTag(TLVTagControl tagControl, const uint8_t *& p) const { uint16_t vendorId; uint16_t profileNum; diff --git a/src/lib/support/CHIPArgParser.cpp b/src/lib/support/CHIPArgParser.cpp index 6fd0858d855e25..e3102d4c09eee1 100644 --- a/src/lib/support/CHIPArgParser.cpp +++ b/src/lib/support/CHIPArgParser.cpp @@ -1141,7 +1141,7 @@ HelpOptions::HelpOptions(const char * appName, const char * appUsage, const char /** * Print a short description of the command's usage followed by instructions on how to get more help. */ -void HelpOptions::PrintBriefUsage(FILE * s) +void HelpOptions::PrintBriefUsage(FILE * s) const { PutStringWithNewLine(s, AppUsage); fprintf(s, "Try `%s --help' for more information.\n", AppName); @@ -1150,7 +1150,7 @@ void HelpOptions::PrintBriefUsage(FILE * s) /** * Print the full usage information, including information on all available options. */ -void HelpOptions::PrintLongUsage(OptionSet ** optSets, FILE * s) +void HelpOptions::PrintLongUsage(OptionSet ** optSets, FILE * s) const { PutStringWithBlankLine(s, AppUsage); if (AppDesc != nullptr) @@ -1160,7 +1160,7 @@ void HelpOptions::PrintLongUsage(OptionSet ** optSets, FILE * s) PrintOptionHelp(optSets, s); } -void HelpOptions::PrintVersion(FILE * s) +void HelpOptions::PrintVersion(FILE * s) const { fprintf(s, "%s ", AppName); PutStringWithNewLine(s, (AppVersion != nullptr) ? AppVersion : "(unknown version)"); diff --git a/src/lib/support/CHIPArgParser.hpp b/src/lib/support/CHIPArgParser.hpp index daeab0be9e6729..f22484fcf6089f 100644 --- a/src/lib/support/CHIPArgParser.hpp +++ b/src/lib/support/CHIPArgParser.hpp @@ -149,9 +149,9 @@ class HelpOptions : public OptionSetBase HelpOptions(const char * appName, const char * appUsage, const char * appVersion); HelpOptions(const char * appName, const char * appUsage, const char * appVersion, const char * appDesc); - void PrintBriefUsage(FILE * s); - void PrintLongUsage(OptionSet * optSets[], FILE * s); - void PrintVersion(FILE * s); + void PrintBriefUsage(FILE * s) const; + void PrintLongUsage(OptionSet * optSets[], FILE * s) const; + void PrintVersion(FILE * s) const; bool HandleOption(const char * progName, OptionSet * optSet, int id, const char * name, const char * arg) override; }; diff --git a/src/lib/support/SerializableIntegerSet.h b/src/lib/support/SerializableIntegerSet.h index b61b640ef39a61..45d7604d43ccbb 100644 --- a/src/lib/support/SerializableIntegerSet.h +++ b/src/lib/support/SerializableIntegerSet.h @@ -88,13 +88,13 @@ class SerializableU64SetBase * @brief * Get the length of the byte data if the array is serialized. */ - size_t SerializedSize() { return sizeof(uint64_t) * mNextAvailable; } + size_t SerializedSize() const { return sizeof(uint64_t) * mNextAvailable; } /** * @brief * Get the maximum length of the byte data if the array were full and serialized. */ - size_t MaxSerializedSize() { return sizeof(uint64_t) * mCapacity; } + size_t MaxSerializedSize() const { return sizeof(uint64_t) * mCapacity; } /** * @brief diff --git a/src/messaging/ExchangeMgr.h b/src/messaging/ExchangeMgr.h index e4e5d0f723f77a..673140f949d712 100644 --- a/src/messaging/ExchangeMgr.h +++ b/src/messaging/ExchangeMgr.h @@ -187,7 +187,7 @@ class DLL_EXPORT ExchangeManager : public SessionMessageDelegate ReliableMessageMgr * GetReliableMessageMgr() { return &mReliableMessageMgr; }; - FabricIndex GetFabricIndex() { return mFabricIndex; } + FabricIndex GetFabricIndex() const { return mFabricIndex; } uint16_t GetNextKeyId() { return ++mNextKeyId; } diff --git a/src/platform/Linux/ThreadStackManagerImpl.cpp b/src/platform/Linux/ThreadStackManagerImpl.cpp index 96ca50f464c0bd..104f90d805cb7a 100644 --- a/src/platform/Linux/ThreadStackManagerImpl.cpp +++ b/src/platform/Linux/ThreadStackManagerImpl.cpp @@ -343,7 +343,7 @@ bool ThreadStackManagerImpl::_IsThreadEnabled() return (strcmp(role, kOpenthreadDeviceRoleDisabled) != 0); } -bool ThreadStackManagerImpl::_IsThreadAttached() +bool ThreadStackManagerImpl::_IsThreadAttached() const { return mAttached; } diff --git a/src/platform/Linux/ThreadStackManagerImpl.h b/src/platform/Linux/ThreadStackManagerImpl.h index 4ae2fc71ed6d48..431812c8788238 100644 --- a/src/platform/Linux/ThreadStackManagerImpl.h +++ b/src/platform/Linux/ThreadStackManagerImpl.h @@ -69,7 +69,7 @@ class ThreadStackManagerImpl : public ThreadStackManager bool _IsThreadEnabled(); - bool _IsThreadAttached(); + bool _IsThreadAttached() const; CHIP_ERROR _AttachToThreadNetwork(ByteSpan netInfo, NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * callback); diff --git a/src/platform/mbed/NetworkCommissioningWiFiDriver.cpp b/src/platform/mbed/NetworkCommissioningWiFiDriver.cpp index d813b83da7cfb7..50d3548bfa58e8 100644 --- a/src/platform/mbed/NetworkCommissioningWiFiDriver.cpp +++ b/src/platform/mbed/NetworkCommissioningWiFiDriver.cpp @@ -265,8 +265,6 @@ void WiFiDriverImpl::ConnectNetwork(ByteSpan networkId, ConnectCallback * callba void WiFiDriverImpl::DisconnectNetwork(ByteSpan networkId) { - Status status = Status::kSuccess; - VerifyOrReturn(mWiFiInterface != nullptr, ChipLogError(DeviceLayer, "Wifi network not available")); VerifyOrReturn(NetworkMatch(mStagingNetwork, networkId), ChipLogError(DeviceLayer, "Network not found")); ChipLogProgress(NetworkProvisioning, "Mbed WiFi driver disconnect network: SSID: %.*s", static_cast(networkId.size()), diff --git a/src/protocols/bdx/BdxTransferSession.cpp b/src/protocols/bdx/BdxTransferSession.cpp index f92fb109284cd2..945381e2fefa2c 100644 --- a/src/protocols/bdx/BdxTransferSession.cpp +++ b/src/protocols/bdx/BdxTransferSession.cpp @@ -894,7 +894,7 @@ void TransferSession::PrepareStatusReport(StatusCode code) mAwaitingResponse = false; // Prevent triggering timeout } -bool TransferSession::IsTransferLengthDefinite() +bool TransferSession::IsTransferLengthDefinite() const { return (mTransferLength > 0); } diff --git a/src/protocols/bdx/BdxTransferSession.h b/src/protocols/bdx/BdxTransferSession.h index 7c37ed3019c3e3..7696d0473c9dc8 100644 --- a/src/protocols/bdx/BdxTransferSession.h +++ b/src/protocols/bdx/BdxTransferSession.h @@ -349,7 +349,7 @@ class DLL_EXPORT TransferSession CHIP_ERROR VerifyProposedMode(const BitFlags & proposed); void PrepareStatusReport(StatusCode code); - bool IsTransferLengthDefinite(); + bool IsTransferLengthDefinite() const; OutputEventType mPendingOutput = OutputEventType::kNone; TransferState mState = TransferState::kUnitialized; diff --git a/src/system/WakeEvent.cpp b/src/system/WakeEvent.cpp index 8c6cda1aa8fa87..a670cc687cff3c 100644 --- a/src/system/WakeEvent.cpp +++ b/src/system/WakeEvent.cpp @@ -91,7 +91,7 @@ void WakeEvent::Close(LayerSockets & systemLayer) mWriteFD = -1; } -void WakeEvent::Confirm() +void WakeEvent::Confirm() const { uint8_t buffer[128]; ssize_t res; @@ -107,7 +107,7 @@ void WakeEvent::Confirm() } while (res == sizeof(buffer)); } -CHIP_ERROR WakeEvent::Notify() +CHIP_ERROR WakeEvent::Notify() const { char byte = 1; @@ -143,7 +143,7 @@ void WakeEvent::Close(LayerSockets & systemLayer) mReadFD = -1; } -void WakeEvent::Confirm() +void WakeEvent::Confirm() const { uint64_t value; @@ -153,7 +153,7 @@ void WakeEvent::Confirm() } } -CHIP_ERROR WakeEvent::Notify() +CHIP_ERROR WakeEvent::Notify() const { uint64_t value = 1; diff --git a/src/system/WakeEvent.h b/src/system/WakeEvent.h index 1c5c3d843b9ef5..b979c67ab17752 100644 --- a/src/system/WakeEvent.h +++ b/src/system/WakeEvent.h @@ -48,8 +48,8 @@ class WakeEvent CHIP_ERROR Open(LayerSockets & systemLayer); /**< Initialize the pipeline */ void Close(LayerSockets & systemLayer); /**< Close both ends of the pipeline. */ - CHIP_ERROR Notify(); /**< Set the event. */ - void Confirm(); /**< Clear the event. */ + CHIP_ERROR Notify() const; /**< Set the event. */ + void Confirm() const; /**< Clear the event. */ private: friend class WakeEventTest; diff --git a/src/transport/GroupSession.h b/src/transport/GroupSession.h index 484d46ca4c27ff..88315d0527c97f 100644 --- a/src/transport/GroupSession.h +++ b/src/transport/GroupSession.h @@ -92,7 +92,7 @@ class IncomingGroupSession : public Session GroupId GetGroupId() const { return mGroupId; } - NodeId GetSourceNodeId() { return mSourceNodeId; } + NodeId GetSourceNodeId() const { return mSourceNodeId; } private: const GroupId mGroupId; @@ -153,7 +153,7 @@ class OutgoingGroupSession : public Session GroupId GetGroupId() const { return mGroupId; } - NodeId GetSourceNodeId() { return mSourceNodeId; } + NodeId GetSourceNodeId() const { return mSourceNodeId; } private: const GroupId mGroupId; diff --git a/src/transport/PeerMessageCounter.h b/src/transport/PeerMessageCounter.h index 2be1109b68b78e..edfac7bf8ddb5a 100644 --- a/src/transport/PeerMessageCounter.h +++ b/src/transport/PeerMessageCounter.h @@ -192,7 +192,7 @@ class PeerMessageCounter mSynced.mWindow.reset(); } - uint32_t GetCounter() { return mSynced.mMaxCounter; } + uint32_t GetCounter() const { return mSynced.mMaxCounter; } private: // Counter position indicator with respect to our current From c4d81c8c96ccc6fb6f021be1eb895a7959c123d3 Mon Sep 17 00:00:00 2001 From: Jerry Johns Date: Thu, 17 Mar 2022 15:25:51 -0700 Subject: [PATCH 06/15] Add more prints to AutoCommissioner/CASESessionManager (#14736) * Add more prints to AutoCommissioner/CASESessionManager This not only provides more insights into the mechanics of the commissioning state machinery but the state transitions with the controller-side CASE session machinery. This is needed to debug some hairy race conditions when commissioning onto multiple fabrics. * Update src/app/OperationalDeviceProxy.cpp Co-authored-by: Michael Sandstedt * Review feedback + some more prints. * Minor fixups. * Missed a file Co-authored-by: Justin Wood Co-authored-by: Michael Sandstedt --- src/app/CASESessionManager.cpp | 6 ++ src/app/OperationalDeviceProxy.cpp | 29 ++++-- src/app/OperationalDeviceProxy.h | 2 + src/controller/AutoCommissioner.cpp | 11 ++ src/controller/AutoCommissioner.h | 1 + src/controller/BUILD.gn | 1 + src/controller/CHIPDeviceController.cpp | 10 +- src/controller/CommissioningDelegate.cpp | 111 +++++++++++++++++++++ src/controller/CommissioningDelegate.h | 2 + src/lib/dnssd/Discovery_ImplPlatform.cpp | 4 + src/lib/dnssd/Resolver.h | 3 +- src/lib/dnssd/Resolver_ImplMinimalMdns.cpp | 3 + src/lib/support/logging/CHIPLogging.cpp | 1 + src/lib/support/logging/Constants.h | 1 + 14 files changed, 168 insertions(+), 17 deletions(-) create mode 100644 src/controller/CommissioningDelegate.cpp diff --git a/src/app/CASESessionManager.cpp b/src/app/CASESessionManager.cpp index af580d35148ee7..92c67a6b8f6f49 100644 --- a/src/app/CASESessionManager.cpp +++ b/src/app/CASESessionManager.cpp @@ -38,9 +38,15 @@ CHIP_ERROR CASESessionManager::FindOrEstablishSession(PeerId peerId, Callback::C false; #endif + ChipLogDetail(CASESessionManager, + "FindOrEstablishSession: PeerId = " ChipLogFormatX64 ":" ChipLogFormatX64 ", NodeIdWasResolved = %d", + ChipLogValueX64(peerId.GetCompressedFabricId()), ChipLogValueX64(peerId.GetNodeId()), nodeIDWasResolved); + OperationalDeviceProxy * session = FindExistingSession(peerId); if (session == nullptr) { + ChipLogDetail(CASESessionManager, "FindOrEstablishSession: No existing session found"); + // TODO - Implement LRU to evict least recently used session to handle mActiveSessions pool exhaustion if (nodeIDWasResolved) { diff --git a/src/app/OperationalDeviceProxy.cpp b/src/app/OperationalDeviceProxy.cpp index 95edcadc4ec0fe..4aad213124c966 100644 --- a/src/app/OperationalDeviceProxy.cpp +++ b/src/app/OperationalDeviceProxy.cpp @@ -46,6 +46,17 @@ using chip::AddressResolve::ResolveResult; namespace chip { +void OperationalDeviceProxy::MoveToState(State aTargetState) +{ + if (mState != aTargetState) + { + ChipLogDetail(Controller, "OperationalDeviceProxy[" ChipLogFormatX64 ":" ChipLogFormatX64 "]: State change %d --> %d", + ChipLogValueX64(mPeerId.GetCompressedFabricId()), ChipLogValueX64(mPeerId.GetNodeId()), to_underlying(mState), + to_underlying(aTargetState)); + mState = aTargetState; + } +} + CHIP_ERROR OperationalDeviceProxy::Connect(Callback::Callback * onConnection, Callback::Callback * onFailure) { @@ -118,8 +129,8 @@ CHIP_ERROR OperationalDeviceProxy::UpdateDeviceData(const Transport::PeerAddress if (mState == State::NeedsAddress) { - mState = State::Initialized; - err = EstablishConnection(); + MoveToState(State::Initialized); + err = EstablishConnection(); if (err != CHIP_NO_ERROR) { OnSessionEstablishmentError(err); @@ -163,7 +174,7 @@ CHIP_ERROR OperationalDeviceProxy::EstablishConnection() mCASEClient->EstablishSession(mPeerId, mDeviceAddress, mMRPConfig, HandleCASEConnected, HandleCASEConnectionFailure, this); ReturnErrorOnFailure(err); - mState = State::Connecting; + MoveToState(State::Connecting); return CHIP_NO_ERROR; } @@ -222,7 +233,7 @@ void OperationalDeviceProxy::HandleCASEConnectionFailure(void * context, CASECli ChipLogError(Controller, "HandleCASEConnectionFailure was called while the device was not initialized")); VerifyOrReturn(client == device->mCASEClient, ChipLogError(Controller, "HandleCASEConnectionFailure for unknown CASEClient")); - device->mState = State::Initialized; + device->MoveToState(State::Initialized); device->CloseCASESession(); device->DequeueConnectionSuccessCallbacks(/* executeCallback */ false); @@ -247,7 +258,7 @@ void OperationalDeviceProxy::HandleCASEConnected(void * context, CASEClient * cl } else { - device->mState = State::SecureConnected; + device->MoveToState(State::SecureConnected); device->CloseCASESession(); device->DequeueConnectionFailureCallbacks(CHIP_NO_ERROR, /* executeCallback */ false); @@ -264,7 +275,7 @@ CHIP_ERROR OperationalDeviceProxy::Disconnect() { mInitParams.sessionManager->ExpirePairing(mSecureSession.Get()); } - mState = State::Initialized; + MoveToState(State::Initialized); if (mCASEClient) { mInitParams.clientPool->Release(mCASEClient); @@ -276,7 +287,7 @@ CHIP_ERROR OperationalDeviceProxy::Disconnect() void OperationalDeviceProxy::SetConnectedSession(const SessionHandle & handle) { mSecureSession.Grab(handle); - mState = State::SecureConnected; + MoveToState(State::SecureConnected); } void OperationalDeviceProxy::Clear() @@ -287,7 +298,7 @@ void OperationalDeviceProxy::Clear() mCASEClient = nullptr; } - mState = State::Uninitialized; + MoveToState(State::Uninitialized); mInitParams = DeviceProxyInitParams(); } @@ -302,7 +313,7 @@ void OperationalDeviceProxy::CloseCASESession() void OperationalDeviceProxy::OnSessionReleased() { - mState = State::Initialized; + MoveToState(State::Initialized); } CHIP_ERROR OperationalDeviceProxy::ShutdownSubscriptions() diff --git a/src/app/OperationalDeviceProxy.h b/src/app/OperationalDeviceProxy.h index c976bde994b525..74806c4a57a4cc 100644 --- a/src/app/OperationalDeviceProxy.h +++ b/src/app/OperationalDeviceProxy.h @@ -246,6 +246,8 @@ class DLL_EXPORT OperationalDeviceProxy : public DeviceProxy, Transport::PeerAddress mDeviceAddress = Transport::PeerAddress::UDP(Inet::IPAddress::Any); + void MoveToState(State aTargetState); + State mState = State::Uninitialized; SessionHolderWithDelegate mSecureSession; diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp index 4e176ac8bf4934..763d92939a8ad8 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -102,6 +102,14 @@ CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParam } CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStage currentStage, CHIP_ERROR & lastErr) +{ + auto nextStage = GetNextCommissioningStageInternal(currentStage, lastErr); + ChipLogProgress(Controller, "Going from commissioning step '%s' with lastErr = '%s' --> '%s'", StageToString(currentStage), + lastErr.AsString(), StageToString(nextStage)); + return nextStage; +} + +CommissioningStage AutoCommissioner::GetNextCommissioningStageInternal(CommissioningStage currentStage, CHIP_ERROR & lastErr) { if (lastErr != CHIP_NO_ERROR) { @@ -320,6 +328,9 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio } else { + ChipLogProgress(Controller, "Finished commissioning step '%s' with error '%s'", StageToString(report.stageCompleted), + err.AsString()); + switch (report.stageCompleted) { case CommissioningStage::kReadCommissioningInfo: diff --git a/src/controller/AutoCommissioner.h b/src/controller/AutoCommissioner.h index fa4693adf2152c..82dd12fd4cbcc6 100644 --- a/src/controller/AutoCommissioner.h +++ b/src/controller/AutoCommissioner.h @@ -39,6 +39,7 @@ class AutoCommissioner : public CommissioningDelegate private: CommissioningStage GetNextCommissioningStage(CommissioningStage currentStage, CHIP_ERROR & lastErr); + CommissioningStage GetNextCommissioningStageInternal(CommissioningStage currentStage, CHIP_ERROR & lastErr); void ReleaseDAC(); void ReleasePAI(); diff --git a/src/controller/BUILD.gn b/src/controller/BUILD.gn index ece90d3921420d..f9e1a31eee6e32 100644 --- a/src/controller/BUILD.gn +++ b/src/controller/BUILD.gn @@ -46,6 +46,7 @@ static_library("controller") { "CommissioneeDeviceProxy.h", "CommissionerDiscoveryController.cpp", "CommissionerDiscoveryController.h", + "CommissioningDelegate.cpp", "DeviceDiscoveryDelegate.h", "EmptyDataModelHandler.cpp", "ExampleOperationalCredentialsIssuer.cpp", diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 0d66b3ec6f6e59..36890f85cca211 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -1753,6 +1753,9 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio CommissioningDelegate * delegate, EndpointId endpoint, Optional timeout) { + ChipLogProgress(Controller, "Performing next commissioning step '%s' with completion status = '%s'", StageToString(step), + params.GetCompletionStatus().AsString()); + // For now, we ignore errors coming in from the device since not all commissioning clusters are implemented on the device // side. mCommissioningStage = step; @@ -1997,7 +2000,6 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT); return; } - ChipLogProgress(Controller, "Sending operational certificate chain to the device"); SendOperationalCertificate(proxy, params.GetNoc().Value(), params.GetIcac().Value(), params.GetIpk().Value(), params.GetAdminSubject().Value()); break; @@ -2009,7 +2011,6 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio return; } - ChipLogProgress(Controller, "Adding wifi network"); NetworkCommissioning::Commands::AddOrUpdateWiFiNetwork::Type request; request.ssid = params.GetWiFiCredentials().Value().ssid; request.credentials = params.GetWiFiCredentials().Value().credentials; @@ -2024,7 +2025,6 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT); return; } - ChipLogProgress(Controller, "Adding thread network"); NetworkCommissioning::Commands::AddOrUpdateThreadNetwork::Type request; request.operationalDataset = params.GetThreadOperationalDataset().Value(); request.breadcrumb = breadcrumb; @@ -2038,7 +2038,6 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT); return; } - ChipLogProgress(Controller, "Enabling wifi network"); NetworkCommissioning::Commands::ConnectNetwork::Type request; request.networkID = params.GetWiFiCredentials().Value().ssid; request.breadcrumb = breadcrumb; @@ -2056,7 +2055,6 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT); return; } - ChipLogProgress(Controller, "Enabling thread network"); NetworkCommissioning::Commands::ConnectNetwork::Type request; request.networkID = extendedPanId; request.breadcrumb = breadcrumb; @@ -2074,14 +2072,12 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio } break; case CommissioningStage::kSendComplete: { - ChipLogProgress(Controller, "Calling commissioning complete"); GeneralCommissioning::Commands::CommissioningComplete::Type request; SendCommand(proxy, request, OnCommissioningCompleteResponse, OnBasicFailure, endpoint, timeout); } break; case CommissioningStage::kCleanup: - ChipLogProgress(Controller, "Rendezvous cleanup"); if (mPairingDelegate != nullptr) { mPairingDelegate->OnCommissioningComplete(proxy->GetDeviceId(), params.GetCompletionStatus()); diff --git a/src/controller/CommissioningDelegate.cpp b/src/controller/CommissioningDelegate.cpp new file mode 100644 index 00000000000000..9038af9402679f --- /dev/null +++ b/src/controller/CommissioningDelegate.cpp @@ -0,0 +1,111 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace chip { +namespace Controller { + +const char * StageToString(CommissioningStage stage) +{ + switch (stage) + { + case kError: + return "Error"; + break; + + case kSecurePairing: + return "SecurePairing"; + break; + + case kArmFailsafe: + return "ArmFailSafe"; + break; + + case kConfigRegulatory: + return "ConfigRegulatory"; + break; + + case kSendPAICertificateRequest: + return "SendPAICertificateRequest"; + break; + + case kSendDACCertificateRequest: + return "SendDACCertificateRequest"; + break; + + case kSendAttestationRequest: + return "SendAttestationRequest"; + break; + + case kAttestationVerification: + return "AttestationVerification"; + break; + + case kSendOpCertSigningRequest: + return "SendOpCertSigningRequest"; + break; + + case kGenerateNOCChain: + return "GenerateNOCChain"; + break; + + case kSendTrustedRootCert: + return "SendTrustedRootCert"; + break; + + case kSendNOC: + return "SendNOC"; + break; + + case kWiFiNetworkSetup: + return "WiFiNetworkSetup"; + break; + + case kThreadNetworkSetup: + return "ThreadNetworkSetup"; + break; + + case kWiFiNetworkEnable: + return "WiFiNetworkEnable"; + break; + + case kThreadNetworkEnable: + return "ThreadNetworkEnable"; + break; + + case kFindOperational: + return "FindOperational"; + break; + + case kSendComplete: + return "SendComplete"; + break; + + case kCleanup: + return "Cleanup"; + break; + + default: + return "???"; + break; + } +} + +} // namespace Controller +} // namespace chip diff --git a/src/controller/CommissioningDelegate.h b/src/controller/CommissioningDelegate.h index 4eb1825aeb36fb..c662ee7f22168d 100644 --- a/src/controller/CommissioningDelegate.h +++ b/src/controller/CommissioningDelegate.h @@ -51,6 +51,8 @@ enum CommissioningStage : uint8_t kCleanup, }; +const char * StageToString(CommissioningStage stage); + struct WiFiCredentials { ByteSpan ssid; diff --git a/src/lib/dnssd/Discovery_ImplPlatform.cpp b/src/lib/dnssd/Discovery_ImplPlatform.cpp index b1dd1fc32f2f37..d68b07ac436671 100644 --- a/src/lib/dnssd/Discovery_ImplPlatform.cpp +++ b/src/lib/dnssd/Discovery_ImplPlatform.cpp @@ -626,6 +626,10 @@ Resolver & chip::Dnssd::Resolver::Instance() CHIP_ERROR ResolverProxy::ResolveNodeId(const PeerId & peerId, Inet::IPAddressType type) { VerifyOrReturnError(mDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE); + + ChipLogProgress(Discovery, "Resolving " ChipLogFormatX64 ":" ChipLogFormatX64 " ...", + ChipLogValueX64(peerId.GetCompressedFabricId()), ChipLogValueX64(peerId.GetNodeId())); + mDelegate->Retain(); DnssdService service; diff --git a/src/lib/dnssd/Resolver.h b/src/lib/dnssd/Resolver.h index c09b0f36d1a70b..8984790d9f9326 100644 --- a/src/lib/dnssd/Resolver.h +++ b/src/lib/dnssd/Resolver.h @@ -47,7 +47,8 @@ struct ResolvedNodeData // Would be nice to log the interface id, but sorting out how to do so // across our differnet InterfaceId implementations is a pain. - ChipLogProgress(Discovery, "Node ID resolved for 0x" ChipLogFormatX64, ChipLogValueX64(mPeerId.GetNodeId())); + ChipLogProgress(Discovery, "Node ID resolved for " ChipLogFormatX64 ":" ChipLogFormatX64, + ChipLogValueX64(mPeerId.GetCompressedFabricId()), ChipLogValueX64(mPeerId.GetNodeId())); for (unsigned i = 0; i < mNumIPs; ++i) { mAddress[i].ToString(addrBuffer); diff --git a/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp b/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp index 78834aecc065ee..92130e2e21772a 100644 --- a/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp +++ b/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp @@ -683,6 +683,9 @@ Resolver & chip::Dnssd::Resolver::Instance() CHIP_ERROR ResolverProxy::ResolveNodeId(const PeerId & peerId, Inet::IPAddressType type) { VerifyOrReturnError(mDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE); + + ChipLogProgress(Discovery, "Resolving " ChipLogFormatX64 ":" ChipLogFormatX64 " ...", + ChipLogValueX64(peerId.GetCompressedFabricId()), ChipLogValueX64(peerId.GetNodeId())); chip::Dnssd::Resolver::Instance().SetOperationalDelegate(mDelegate); return chip::Dnssd::Resolver::Instance().ResolveNodeId(peerId, type); } diff --git a/src/lib/support/logging/CHIPLogging.cpp b/src/lib/support/logging/CHIPLogging.cpp index 19c24e81eb6f66..3cbd9e7acdf946 100644 --- a/src/lib/support/logging/CHIPLogging.cpp +++ b/src/lib/support/logging/CHIPLogging.cpp @@ -116,6 +116,7 @@ const char ModuleNames[] = "-\0\0" // None "TST" // Test "ODP" // OperationalDeviceProxy "ATM" // Automation + "CSM" // CASESessionManager ; #define ModuleNamesCount ((sizeof(ModuleNames) - 1) / chip::Logging::kMaxModuleNameLen) diff --git a/src/lib/support/logging/Constants.h b/src/lib/support/logging/Constants.h index 0214fcaa2dbab8..ec2c47aba9cff3 100644 --- a/src/lib/support/logging/Constants.h +++ b/src/lib/support/logging/Constants.h @@ -58,6 +58,7 @@ enum LogModule kLogModule_Test, kLogModule_OperationalDeviceProxy, kLogModule_Automation, + kLogModule_CASESessionManager, kLogModule_Max }; From 1b1dd0c263ec68708d86747743994cc8d11ca15b Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 17 Mar 2022 22:54:21 -0400 Subject: [PATCH 07/15] Move CASESessionManager to CHIPDeviceControllerSystemState. (#16233) We should have one CASESessionManager, not one per DeviceController. Fixes https://github.com/project-chip/connectedhomeip/issues/16174 --- src/controller/CHIPDeviceController.cpp | 58 +++++-------------- src/controller/CHIPDeviceController.h | 13 +---- .../CHIPDeviceControllerFactory.cpp | 58 +++++++++++++++++++ .../CHIPDeviceControllerSystemState.h | 31 +++++++++- 4 files changed, 105 insertions(+), 55 deletions(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 36890f85cca211..c7553ba8a668bd 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -148,28 +148,6 @@ CHIP_ERROR DeviceController::Init(ControllerInitParams params) } } - DeviceProxyInitParams deviceInitParams = { - .sessionManager = params.systemState->SessionMgr(), - .exchangeMgr = params.systemState->ExchangeMgr(), - .idAllocator = &mIDAllocator, - .fabricTable = params.systemState->Fabrics(), - .clientPool = &mCASEClientPool, - .mrpLocalConfig = Optional::Value(GetLocalMRPConfig()), - }; - - CASESessionManagerConfig sessionManagerConfig = { - .sessionInitParams = deviceInitParams, -#if CHIP_CONFIG_MDNS_CACHE_SIZE > 0 - .dnsCache = &mDNSCache, -#endif - .devicePool = &mDevicePool, - }; - - mCASESessionManager = chip::Platform::New(sessionManagerConfig); - VerifyOrReturnError(mCASESessionManager != nullptr, CHIP_ERROR_NO_MEMORY); - - ReturnErrorOnFailure(mCASESessionManager->Init(params.systemState->SystemLayer())); - mSystemState = params.systemState->Retain(); mState = State::Initialized; return CHIP_NO_ERROR; @@ -243,11 +221,9 @@ CHIP_ERROR DeviceController::Shutdown() if (mFabricInfo != nullptr) { - // Shut down any ongoing CASE session activity we have. Note that we - // own the mCASESessionManager, so shutting down everything on it is - // fine. If we ever end up sharing the CASE session manager with other - // DeviceController instances we may need to be more targeted here. - mCASESessionManager->ReleaseAllSessions(); + // Shut down any ongoing CASE session activity we have. We're going to + // assume that all sessions for our fabric belong to us here. + mSystemState->CASESessionMgr()->ReleaseSessionsForFabric(GetCompressedFabricId()); // TODO: The CASE session manager does not shut down existing CASE // sessions. It just shuts down any ongoing CASE session establishment @@ -268,9 +244,6 @@ CHIP_ERROR DeviceController::Shutdown() mDNSResolver.Shutdown(); mDeviceDiscoveryDelegate = nullptr; - chip::Platform::Delete(mCASESessionManager); - mCASESessionManager = nullptr; - return CHIP_NO_ERROR; } @@ -288,14 +261,14 @@ void DeviceController::ReleaseOperationalDevice(NodeId remoteDeviceId) { VerifyOrReturn(mState == State::Initialized && mFabricInfo != nullptr, ChipLogError(Controller, "ReleaseOperationalDevice was called in incorrect state")); - mCASESessionManager->ReleaseSession(mFabricInfo->GetPeerIdForNode(remoteDeviceId)); + mSystemState->CASESessionMgr()->ReleaseSession(mFabricInfo->GetPeerIdForNode(remoteDeviceId)); } CHIP_ERROR DeviceController::DisconnectDevice(NodeId nodeId) { ChipLogProgress(Controller, "Force close session for node 0x%" PRIx64, nodeId); - OperationalDeviceProxy * proxy = mCASESessionManager->FindExistingSession(mFabricInfo->GetPeerIdForNode(nodeId)); + OperationalDeviceProxy * proxy = mSystemState->CASESessionMgr()->FindExistingSession(mFabricInfo->GetPeerIdForNode(nodeId)); if (proxy == nullptr) { ChipLogProgress(Controller, "Attempted to close a session that does not exist."); @@ -419,7 +392,7 @@ CHIP_ERROR DeviceController::GetPeerAddressAndPort(PeerId peerId, Inet::IPAddres { VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE); Transport::PeerAddress peerAddr; - ReturnErrorOnFailure(mCASESessionManager->GetPeerAddress(peerId, peerAddr)); + ReturnErrorOnFailure(mSystemState->CASESessionMgr()->GetPeerAddress(peerId, peerAddr)); addr = peerAddr.GetIPAddress(); port = peerAddr.GetPort(); return CHIP_NO_ERROR; @@ -446,7 +419,7 @@ void DeviceController::OnVIDReadResponse(void * context, VendorId value) controller->mSetupPayload.vendorID = value; OperationalDeviceProxy * device = - controller->mCASESessionManager->FindExistingSession(controller->GetPeerIdWithCommissioningWindowOpen()); + controller->mSystemState->CASESessionMgr()->FindExistingSession(controller->GetPeerIdWithCommissioningWindowOpen()); if (device == nullptr) { ChipLogError(Controller, "Could not find device for opening commissioning window"); @@ -534,7 +507,8 @@ CHIP_ERROR DeviceController::OpenCommissioningWindowWithCallback(NodeId deviceId if (callback != nullptr && mCommissioningWindowOption != CommissioningWindowOption::kOriginalSetupCode && readVIDPIDAttributes) { - OperationalDeviceProxy * device = mCASESessionManager->FindExistingSession(GetPeerIdWithCommissioningWindowOpen()); + OperationalDeviceProxy * device = + mSystemState->CASESessionMgr()->FindExistingSession(GetPeerIdWithCommissioningWindowOpen()); VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); constexpr EndpointId kBasicClusterEndpoint = 0; @@ -552,7 +526,7 @@ CHIP_ERROR DeviceController::OpenCommissioningWindowInternal() ChipLogProgress(Controller, "OpenCommissioningWindow for device ID %" PRIu64, mDeviceWithCommissioningWindowOpen); VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE); - OperationalDeviceProxy * device = mCASESessionManager->FindExistingSession(GetPeerIdWithCommissioningWindowOpen()); + OperationalDeviceProxy * device = mSystemState->CASESessionMgr()->FindExistingSession(GetPeerIdWithCommissioningWindowOpen()); VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); constexpr EndpointId kAdministratorCommissioningClusterEndpoint = 0; @@ -619,7 +593,7 @@ ControllerDeviceInitParams DeviceController::GetControllerDeviceInitParams() .exchangeMgr = mSystemState->ExchangeMgr(), .udpEndPointManager = mSystemState->UDPEndPointManager(), .storageDelegate = mStorageDelegate, - .idAllocator = &mIDAllocator, + .idAllocator = mSystemState->SessionIDAlloc(), .fabricsTable = mSystemState->Fabrics(), }; } @@ -867,7 +841,7 @@ CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, Re session = mSystemState->SessionMgr()->CreateUnauthenticatedSession(params.GetPeerAddress(), device->GetMRPConfig()); VerifyOrExit(session.HasValue(), err = CHIP_ERROR_NO_MEMORY); - err = mIDAllocator.Allocate(keyID); + err = mSystemState->SessionIDAlloc()->Allocate(keyID); SuccessOrExit(err); // TODO - Remove use of SetActive/IsActive from CommissioneeDeviceProxy @@ -1522,7 +1496,7 @@ void DeviceCommissioner::OnDeviceConnectionFailureFn(void * context, PeerId peer error = CHIP_ERROR_INTERNAL; } - commissioner->mCASESessionManager->ReleaseSession(peerId); + commissioner->mSystemState->CASESessionMgr()->ReleaseSession(peerId); if (commissioner->mCommissioningStage == CommissioningStage::kFindOperational && commissioner->mCommissioningDelegate != nullptr) { @@ -2105,13 +2079,13 @@ CHIP_ERROR DeviceController::UpdateDevice(NodeId deviceId) OperationalDeviceProxy * DeviceController::GetDeviceSession(const PeerId & peerId) { - return mCASESessionManager->FindExistingSession(peerId); + return mSystemState->CASESessionMgr()->FindExistingSession(peerId); } OperationalDeviceProxy * DeviceCommissioner::GetDeviceSession(const PeerId & peerId) { - CHIP_ERROR err = - mCASESessionManager->FindOrEstablishSession(peerId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); + CHIP_ERROR err = mSystemState->CASESessionMgr()->FindOrEstablishSession(peerId, &mOnDeviceConnectedCallback, + &mOnDeviceConnectionFailureCallback); if (err != CHIP_NO_ERROR) { diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 72ed6f2416a432..b44010458184ba 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -211,7 +211,8 @@ class DLL_EXPORT DeviceController : public SessionRecoveryDelegate, public Abstr chip::Callback::Callback * onFailure) { VerifyOrReturnError(mState == State::Initialized && mFabricInfo != nullptr, CHIP_ERROR_INCORRECT_STATE); - return mCASESessionManager->FindOrEstablishSession(mFabricInfo->GetPeerIdForNode(deviceId), onConnection, onFailure); + return mSystemState->CASESessionMgr()->FindOrEstablishSession(mFabricInfo->GetPeerIdForNode(deviceId), onConnection, + onFailure); } /** @@ -350,14 +351,6 @@ class DLL_EXPORT DeviceController : public SessionRecoveryDelegate, public Abstr State mState; - CASESessionManager * mCASESessionManager = nullptr; - -#if CHIP_CONFIG_MDNS_CACHE_SIZE > 0 - Dnssd::DnssdCache mDNSCache; -#endif - CASEClientPool mCASEClientPool; - OperationalDeviceProxyPool mDevicePool; - SerializableU64Set mPairedDevices; bool mPairedDevicesInitialized; @@ -377,8 +370,6 @@ class DLL_EXPORT DeviceController : public SessionRecoveryDelegate, public Abstr OperationalCredentialsDelegate * mOperationalCredentialsDelegate; - SessionIDAllocator mIDAllocator; - uint16_t mVendorId; /// Fetches the session to use for the current device. Allows overriding diff --git a/src/controller/CHIPDeviceControllerFactory.cpp b/src/controller/CHIPDeviceControllerFactory.cpp index 4fc754997f3ee4..213ffddafb46e7 100644 --- a/src/controller/CHIPDeviceControllerFactory.cpp +++ b/src/controller/CHIPDeviceControllerFactory.cpp @@ -24,8 +24,10 @@ #include +#include #include #include +#include #if CONFIG_DEVICE_LAYER #include @@ -201,6 +203,31 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params) chip::app::DnssdServer::Instance().StartServer(); } + stateParams.sessionIDAllocator = Platform::New(); + stateParams.operationalDevicePool = Platform::New(); + stateParams.caseClientPool = Platform::New(); + + DeviceProxyInitParams deviceInitParams = { + .sessionManager = stateParams.sessionMgr, + .exchangeMgr = stateParams.exchangeMgr, + .idAllocator = stateParams.sessionIDAllocator, + .fabricTable = stateParams.fabricTable, + .clientPool = stateParams.caseClientPool, + .mrpLocalConfig = Optional::Value(GetLocalMRPConfig()), + }; + + CASESessionManagerConfig sessionManagerConfig = { + .sessionInitParams = deviceInitParams, +#if CHIP_CONFIG_MDNS_CACHE_SIZE > 0 + .dnsCache = NoSuchThingWeWouldNeedToAddIt, +#endif + .devicePool = stateParams.operationalDevicePool, + }; + + // TODO: Need to be able to create a CASESessionManagerConfig here! + stateParams.caseSessionManager = Platform::New(sessionManagerConfig); + ReturnErrorOnFailure(stateParams.caseSessionManager->Init(stateParams.systemLayer)); + // store the system state mSystemState = chip::Platform::New(stateParams); ChipLogDetail(Controller, "System State Initialized..."); @@ -287,6 +314,33 @@ CHIP_ERROR DeviceControllerSystemState::Shutdown() mCASEServer = nullptr; } + if (mCASESessionManager != nullptr) + { + mCASESessionManager->Shutdown(); + Platform::Delete(mCASESessionManager); + mCASESessionManager = nullptr; + } + + // mSessionIDAllocator, mCASEClientPool, and mDevicePool must be deallocated + // after mCASESessionManager, which uses them. + if (mSessionIDAllocator != nullptr) + { + Platform::Delete(mSessionIDAllocator); + mSessionIDAllocator = nullptr; + } + + if (mOperationalDevicePool != nullptr) + { + Platform::Delete(mOperationalDevicePool); + mOperationalDevicePool = nullptr; + } + + if (mCASEClientPool != nullptr) + { + Platform::Delete(mCASEClientPool); + mCASEClientPool = nullptr; + } + Dnssd::Resolver::Instance().Shutdown(); // Shut down the interaction model @@ -324,7 +378,11 @@ CHIP_ERROR DeviceControllerSystemState::Shutdown() } mSystemLayer = nullptr; + mTCPEndPointManager = nullptr; mUDPEndPointManager = nullptr; +#if CONFIG_NETWORK_LAYER_BLE + mBleLayer = nullptr; +#endif // CONFIG_NETWORK_LAYER_BLE if (mMessageCounterManager != nullptr) { diff --git a/src/controller/CHIPDeviceControllerSystemState.h b/src/controller/CHIPDeviceControllerSystemState.h index ebb0c87be3ef8a..869d77c1ca68a1 100644 --- a/src/controller/CHIPDeviceControllerSystemState.h +++ b/src/controller/CHIPDeviceControllerSystemState.h @@ -29,9 +29,13 @@ #pragma once +#include +#include #include +#include #include #include +#include #include #include @@ -63,18 +67,29 @@ namespace Controller { struct DeviceControllerSystemStateParams { + using OperationalDevicePool = OperationalDeviceProxyPool; + using CASEClientPool = chip::CASEClientPool; + + // Params that can outlive the DeviceControllerSystemState System::Layer * systemLayer = nullptr; Inet::EndPointManager * tcpEndPointManager = nullptr; Inet::EndPointManager * udpEndPointManager = nullptr; #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * bleLayer = nullptr; #endif + + // Params that will be deallocated via Platform::Delete in + // DeviceControllerSystemState::Shutdown. DeviceTransportMgr * transportMgr = nullptr; SessionManager * sessionMgr = nullptr; Messaging::ExchangeManager * exchangeMgr = nullptr; secure_channel::MessageCounterManager * messageCounterManager = nullptr; FabricTable * fabricTable = nullptr; CASEServer * caseServer = nullptr; + CASESessionManager * caseSessionManager = nullptr; + SessionIDAllocator * sessionIDAllocator = nullptr; + OperationalDevicePool * operationalDevicePool = nullptr; + CASEClientPool * caseClientPool = nullptr; }; // A representation of the internal state maintained by the DeviceControllerFactory @@ -82,13 +97,18 @@ struct DeviceControllerSystemStateParams // Expects that the creator of this object is the last one to release it. class DeviceControllerSystemState { + using OperationalDevicePool = DeviceControllerSystemStateParams::OperationalDevicePool; + using CASEClientPool = DeviceControllerSystemStateParams::CASEClientPool; + public: ~DeviceControllerSystemState(){}; DeviceControllerSystemState(DeviceControllerSystemStateParams params) : mSystemLayer(params.systemLayer), mTCPEndPointManager(params.tcpEndPointManager), mUDPEndPointManager(params.udpEndPointManager), mTransportMgr(params.transportMgr), mSessionMgr(params.sessionMgr), mExchangeMgr(params.exchangeMgr), mMessageCounterManager(params.messageCounterManager), mFabrics(params.fabricTable), - mCASEServer(params.caseServer) + mCASEServer(params.caseServer), mCASESessionManager(params.caseSessionManager), + mSessionIDAllocator(params.sessionIDAllocator), mOperationalDevicePool(params.operationalDevicePool), + mCASEClientPool(params.caseClientPool) { #if CONFIG_NETWORK_LAYER_BLE mBleLayer = params.bleLayer; @@ -120,7 +140,8 @@ class DeviceControllerSystemState bool IsInitialized() { return mSystemLayer != nullptr && mUDPEndPointManager != nullptr && mTransportMgr != nullptr && mSessionMgr != nullptr && - mExchangeMgr != nullptr && mMessageCounterManager != nullptr && mFabrics != nullptr; + mExchangeMgr != nullptr && mMessageCounterManager != nullptr && mFabrics != nullptr && mCASESessionManager != nullptr && + mSessionIDAllocator != nullptr && mOperationalDevicePool != nullptr && mCASEClientPool != nullptr; }; System::Layer * SystemLayer() { return mSystemLayer; }; @@ -134,6 +155,8 @@ class DeviceControllerSystemState #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * BleLayer() { return mBleLayer; }; #endif + CASESessionManager * CASESessionMgr() const { return mCASESessionManager; } + SessionIDAllocator * SessionIDAlloc() const { return mSessionIDAllocator; } private: DeviceControllerSystemState(){}; @@ -150,6 +173,10 @@ class DeviceControllerSystemState secure_channel::MessageCounterManager * mMessageCounterManager = nullptr; FabricTable * mFabrics = nullptr; CASEServer * mCASEServer = nullptr; + CASESessionManager * mCASESessionManager = nullptr; + SessionIDAllocator * mSessionIDAllocator = nullptr; + OperationalDevicePool * mOperationalDevicePool = nullptr; + CASEClientPool * mCASEClientPool = nullptr; std::atomic mRefCount{ 1 }; From 2fb3089963a32ff5886bfd698a8432d79148d112 Mon Sep 17 00:00:00 2001 From: Lisandre Taylor <7604725+Litome@users.noreply.github.com> Date: Fri, 18 Mar 2022 02:56:27 +0000 Subject: [PATCH 08/15] [Android] Fix CHIPTool cluster cmds fail or app crashes (Issue #15637). (#15919) * [Android] Fix CHIPTool cluster cmds fail or app crashes (Issue #15637). * [Android] Fix expression in verification instead of commenting out the verification. * Restyled by clang-format * [Android] Fix merge issue and revert un-necessary changes to verification expression Co-authored-by: Lisandre Taylor Co-authored-by: Restyled.io --- src/platform/android/DnssdImpl.cpp | 2 +- src/platform/android/KeyValueStoreManagerImpl.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/android/DnssdImpl.cpp b/src/platform/android/DnssdImpl.cpp index 52d20525e8ca04..fa5a9d30e589f2 100644 --- a/src/platform/android/DnssdImpl.cpp +++ b/src/platform/android/DnssdImpl.cpp @@ -44,7 +44,7 @@ jmethodID sPublishMethod = nullptr; jmethodID sRemoveServicesMethod = nullptr; } // namespace -// Implemention of functions declared in lib/dnssd/platform/Dnssd.h +// Implementation of functions declared in lib/dnssd/platform/Dnssd.h CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context) { diff --git a/src/platform/android/KeyValueStoreManagerImpl.cpp b/src/platform/android/KeyValueStoreManagerImpl.cpp index 46ba0354f915cb..3b15d888810e56 100644 --- a/src/platform/android/KeyValueStoreManagerImpl.cpp +++ b/src/platform/android/KeyValueStoreManagerImpl.cpp @@ -120,7 +120,7 @@ CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t ChipLogError(DeviceLayer, "KeyValueStoreManager base64 decoding failed"); return CHIP_ERROR_INTEGRITY_CHECK_FAILED; } - ReturnErrorCodeIf(offset_bytes >= decodedLength, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(offset_bytes != 0 && offset_bytes >= decodedLength, CHIP_ERROR_INVALID_ARGUMENT); size_t read_size = std::min(value_size, decodedLength - offset_bytes); if (value_size + offset_bytes < decodedLength) { From 6408518538c93f845c56e74d96dc8ddc5fd44001 Mon Sep 17 00:00:00 2001 From: "Josh V [Apple]" <12054330+krypton36@users.noreply.github.com> Date: Thu, 17 Mar 2022 20:23:24 -0700 Subject: [PATCH 09/15] Resolve optional attribute with response (#16321) * Handle optional attribute and response error write. * Generated Code. --- .../tests/partials/test_cluster.zapt | 9 ++ .../chip-tool/zap-generated/test/Commands.h | 88 +++++++++++++++---- 2 files changed, 81 insertions(+), 16 deletions(-) diff --git a/examples/chip-tool/templates/tests/partials/test_cluster.zapt b/examples/chip-tool/templates/tests/partials/test_cluster.zapt index 0a9dfe5b0c8fab..27616a54ed9c2e 100644 --- a/examples/chip-tool/templates/tests/partials/test_cluster.zapt +++ b/examples/chip-tool/templates/tests/partials/test_cluster.zapt @@ -318,8 +318,17 @@ class {{filename}}Suite: public TestCommand { chip::app::StatusIB status(error); {{#if response.error}} + {{#if optional}} + if (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute){ + {{#unless async}}NextTest();{{/unless}} + } else { + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), {{response.error}})); + {{#unless async}}NextTest();{{/unless}} + } + {{else}} VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), {{response.error}})); {{#unless async}}NextTest();{{/unless}} + {{/if}} {{else}} {{#if optional}}(status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) ? NextTest() : {{/if}}ThrowFailureResponse(); {{/if}} diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index 8ab256586aafee..507785446604c2 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -6865,8 +6865,15 @@ class Test_TC_CC_2_1Suite : public TestCommand void OnFailureResponse_47(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); - NextTest(); + if (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) + { + NextTest(); + } + else + { + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); + NextTest(); + } } void OnSuccessResponse_47() { ThrowSuccessResponse(); } @@ -7010,8 +7017,15 @@ class Test_TC_CC_2_1Suite : public TestCommand void OnFailureResponse_53(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); - NextTest(); + if (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) + { + NextTest(); + } + else + { + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); + NextTest(); + } } void OnSuccessResponse_53() { ThrowSuccessResponse(); } @@ -7082,8 +7096,15 @@ class Test_TC_CC_2_1Suite : public TestCommand void OnFailureResponse_56(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); - NextTest(); + if (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) + { + NextTest(); + } + else + { + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); + NextTest(); + } } void OnSuccessResponse_56() { ThrowSuccessResponse(); } @@ -7153,8 +7174,15 @@ class Test_TC_CC_2_1Suite : public TestCommand void OnFailureResponse_59(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); - NextTest(); + if (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) + { + NextTest(); + } + else + { + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); + NextTest(); + } } void OnSuccessResponse_59() { ThrowSuccessResponse(); } @@ -21690,8 +21718,15 @@ class Test_TC_FLW_2_1Suite : public TestCommand void OnFailureResponse_12(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); - NextTest(); + if (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) + { + NextTest(); + } + else + { + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); + NextTest(); + } } void OnSuccessResponse_12() { ThrowSuccessResponse(); } @@ -44311,8 +44346,15 @@ class Test_TC_TSTAT_2_1Suite : public TestCommand void OnFailureResponse_55(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); - NextTest(); + if (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) + { + NextTest(); + } + else + { + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); + NextTest(); + } } void OnSuccessResponse_55() { ThrowSuccessResponse(); } @@ -44383,8 +44425,15 @@ class Test_TC_TSTAT_2_1Suite : public TestCommand void OnFailureResponse_58(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); - NextTest(); + if (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) + { + NextTest(); + } + else + { + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); + NextTest(); + } } void OnSuccessResponse_58() { ThrowSuccessResponse(); } @@ -44430,8 +44479,15 @@ class Test_TC_TSTAT_2_1Suite : public TestCommand void OnFailureResponse_60(CHIP_ERROR error) { chip::app::StatusIB status(error); - VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); - NextTest(); + if (status.mStatus == chip::Protocols::InteractionModel::Status::UnsupportedAttribute) + { + NextTest(); + } + else + { + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_UNSUPPORTED_WRITE)); + NextTest(); + } } void OnSuccessResponse_60() { ThrowSuccessResponse(); } From 8dab08cab4484c47c6a46abf3c2543b5a8d2db42 Mon Sep 17 00:00:00 2001 From: Carol Yang Date: Thu, 17 Mar 2022 20:27:39 -0700 Subject: [PATCH 10/15] [OTA] Remove global resolver initialization from OTA Requestor (#16388) - This is already done in Server --- examples/ota-requestor-app/linux/main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/ota-requestor-app/linux/main.cpp b/examples/ota-requestor-app/linux/main.cpp index 454db06ddecb04..b02cae2c49ac3f 100644 --- a/examples/ota-requestor-app/linux/main.cpp +++ b/examples/ota-requestor-app/linux/main.cpp @@ -181,8 +181,6 @@ bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, void ApplicationInit() { - chip::Dnssd::Resolver::Instance().Init(chip::DeviceLayer::UDPEndPointManager()); - // Initialize all OTA download components InitOTARequestor(); } From 11b5fef46d47629f2059a9fbdd43df163811d39c Mon Sep 17 00:00:00 2001 From: Yuanyao Zhong <82843247+yyzhong-g@users.noreply.github.com> Date: Thu, 17 Mar 2022 23:36:00 -0400 Subject: [PATCH 11/15] Add trace events to commissioning flow (#16380) * Add trace events to commissioning flow Trace events are added to CHIPDeviceCommissioner and some clusters callbacks used for commissioning. * Restyled by gn Co-authored-by: Restyled.io --- .../esp32/main/CMakeLists.txt | 3 +- .../lighting-app/nrfconnect/CMakeLists.txt | 3 +- .../general-commissioning-server.cpp | 4 +++ .../network-commissioning.cpp | 8 ++++- .../operational-credentials-server.cpp | 10 ++++++ src/controller/BUILD.gn | 1 + src/controller/CHIPDeviceController.cpp | 31 +++++++++++++++++++ 7 files changed, 57 insertions(+), 3 deletions(-) diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index 11935f85c0ce31..8d54480789d9de 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -253,6 +253,7 @@ target_compile_options(${COMPONENT_LIB} PRIVATE "-DPW_RPC_LIGHTING_SERVICE=1" "-DPW_RPC_LOCKING_SERVICE=1" "-DPW_RPC_TRACING_SERVICE=1" - "-DPW_RPC_WIFI_SERVICE=1") + "-DPW_RPC_WIFI_SERVICE=1" + "-DPW_TRACE_BACKEND_SET=1") endif (CONFIG_ENABLE_PW_RPC) diff --git a/examples/lighting-app/nrfconnect/CMakeLists.txt b/examples/lighting-app/nrfconnect/CMakeLists.txt index 4755a2b9ec961b..1656937b0b050a 100644 --- a/examples/lighting-app/nrfconnect/CMakeLists.txt +++ b/examples/lighting-app/nrfconnect/CMakeLists.txt @@ -235,7 +235,8 @@ target_compile_options(app PRIVATE "-DPW_RPC_DEVICE_SERVICE=1" "-DPW_RPC_LIGHTING_SERVICE=1" "-DPW_RPC_THREAD_SERVICE=1" - "-DPW_RPC_TRACING_SERVICE=1") + "-DPW_RPC_TRACING_SERVICE=1" + "-DPW_TRACE_BACKEND_SET=1") target_link_libraries(app PRIVATE attributes_service.nanopb_rpc 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 6001f601142487..c46cfdd603fe21 100644 --- a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp +++ b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp @@ -32,6 +32,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app; @@ -131,6 +132,7 @@ bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler * const app::ConcreteCommandPath & commandPath, const Commands::ArmFailSafe::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("ArmFailSafe", "GeneralCommissioning"); FailSafeContext & failSafeContext = DeviceLayer::DeviceControlServer::DeviceControlSvr().GetFailSafeContext(); Commands::ArmFailSafeResponse::Type response; @@ -162,6 +164,7 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::CommissioningComplete::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("CommissioningComplete", "GeneralCommissioning"); DeviceControlServer * server = &DeviceLayer::DeviceControlServer::DeviceControlSvr(); /* @@ -184,6 +187,7 @@ bool emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(app::CommandH const app::ConcreteCommandPath & commandPath, const Commands::SetRegulatoryConfig::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("SetRegulatoryConfig", "GeneralCommissioning"); DeviceControlServer * server = &DeviceLayer::DeviceControlServer::DeviceControlSvr(); CheckSuccess(server->SetRegulatoryConfig(to_underlying(commandData.location), commandData.countryCode, commandData.breadcrumb), diff --git a/src/app/clusters/network-commissioning/network-commissioning.cpp b/src/app/clusters/network-commissioning/network-commissioning.cpp index 3ae06ed65a1aad..fb3ff2b8a63246 100644 --- a/src/app/clusters/network-commissioning/network-commissioning.cpp +++ b/src/app/clusters/network-commissioning/network-commissioning.cpp @@ -27,6 +27,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app; @@ -269,7 +270,7 @@ void Instance::OnNetworkingStatusChange(DeviceLayer::NetworkCommissioning::Statu void Instance::HandleScanNetworks(HandlerContext & ctx, const Commands::ScanNetworks::DecodableType & req) { - + MATTER_TRACE_EVENT_SCOPE("HandleScanNetwork", "NetworkCommissioning"); if (mFeatureFlags.Has(NetworkCommissioningFeature::kWiFiNetworkInterface)) { mAsyncCommandHandle = CommandHandler::Handle(&ctx.mCommandHandler); @@ -288,6 +289,7 @@ void Instance::HandleScanNetworks(HandlerContext & ctx, const Commands::ScanNetw void Instance::HandleAddOrUpdateWiFiNetwork(HandlerContext & ctx, const Commands::AddOrUpdateWiFiNetwork::DecodableType & req) { + MATTER_TRACE_EVENT_SCOPE("HandleAddOrUpdateWiFiNetwork", "NetworkCommissioning"); Commands::NetworkConfigResponse::Type response; response.networkingStatus = ToClusterObjectEnum(mpDriver.Get()->AddOrUpdateNetwork(req.ssid, req.credentials)); ctx.mCommandHandler.AddResponseData(ctx.mRequestPath, response); @@ -295,6 +297,7 @@ void Instance::HandleAddOrUpdateWiFiNetwork(HandlerContext & ctx, const Commands void Instance::HandleAddOrUpdateThreadNetwork(HandlerContext & ctx, const Commands::AddOrUpdateThreadNetwork::DecodableType & req) { + MATTER_TRACE_EVENT_SCOPE("HandleAddOrUpdateThreadNetwork", "NetworkCommissioning"); Commands::NetworkConfigResponse::Type response; response.networkingStatus = ToClusterObjectEnum(mpDriver.Get()->AddOrUpdateNetwork(req.operationalDataset)); ctx.mCommandHandler.AddResponseData(ctx.mRequestPath, response); @@ -302,6 +305,7 @@ void Instance::HandleAddOrUpdateThreadNetwork(HandlerContext & ctx, const Comman void Instance::HandleRemoveNetwork(HandlerContext & ctx, const Commands::RemoveNetwork::DecodableType & req) { + MATTER_TRACE_EVENT_SCOPE("HandleRemoveNetwork", "NetworkCommissioning"); Commands::NetworkConfigResponse::Type response; response.networkingStatus = ToClusterObjectEnum(mpWirelessDriver->RemoveNetwork(req.networkID)); ctx.mCommandHandler.AddResponseData(ctx.mRequestPath, response); @@ -309,6 +313,7 @@ void Instance::HandleRemoveNetwork(HandlerContext & ctx, const Commands::RemoveN void Instance::HandleConnectNetwork(HandlerContext & ctx, const Commands::ConnectNetwork::DecodableType & req) { + MATTER_TRACE_EVENT_SCOPE("HandleConnectNetwork", "NetworkCommissioning"); if (req.networkID.size() > DeviceLayer::NetworkCommissioning::kMaxNetworkIDLen) { ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::InvalidValue); @@ -324,6 +329,7 @@ void Instance::HandleConnectNetwork(HandlerContext & ctx, const Commands::Connec void Instance::HandleReorderNetwork(HandlerContext & ctx, const Commands::ReorderNetwork::DecodableType & req) { + MATTER_TRACE_EVENT_SCOPE("HandleReorderNetwork", "NetworkCommissioning"); Commands::NetworkConfigResponse::Type response; response.networkingStatus = ToClusterObjectEnum(mpWirelessDriver->ReorderNetwork(req.networkID, req.networkIndex)); ctx.mCommandHandler.AddResponseData(ctx.mRequestPath, response); diff --git a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp index 9ef192c645c184..ed0e2a878fc9c2 100644 --- a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp +++ b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp @@ -49,6 +49,7 @@ #include #include #include +#include using namespace chip; using namespace ::chip::DeviceLayer; @@ -368,6 +369,7 @@ bool emberAfOperationalCredentialsClusterRemoveFabricCallback(app::CommandHandle const app::ConcreteCommandPath & commandPath, const Commands::RemoveFabric::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("RemoveFabric", "OperationalCredentials"); auto & fabricBeingRemoved = commandData.fabricIndex; emberAfPrintln(EMBER_AF_PRINT_DEBUG, "OpCreds: RemoveFabric"); // TODO: Generate emberAfFabricClusterPrintln @@ -425,6 +427,7 @@ bool emberAfOperationalCredentialsClusterUpdateFabricLabelCallback(app::CommandH const app::ConcreteCommandPath & commandPath, const Commands::UpdateFabricLabel::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("UpdateFabricLabel", "OperationalCredentials"); auto & Label = commandData.label; auto ourFabricIndex = commandObj->GetAccessingFabricIndex(); @@ -521,6 +524,7 @@ bool emberAfOperationalCredentialsClusterAddNOCCallback(app::CommandHandler * co const app::ConcreteCommandPath & commandPath, const Commands::AddNOC::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("AddNOC", "OperationalCredentials"); auto & NOCValue = commandData.NOCValue; auto & ICACValue = commandData.ICACValue; auto & adminVendorId = commandData.adminVendorId; @@ -618,6 +622,7 @@ bool emberAfOperationalCredentialsClusterUpdateNOCCallback(app::CommandHandler * const app::ConcreteCommandPath & commandPath, const Commands::UpdateNOC::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("UpdateNOC", "OperationalCredentials"); auto & NOCValue = commandData.NOCValue; auto & ICACValue = commandData.ICACValue; @@ -683,6 +688,7 @@ bool emberAfOperationalCredentialsClusterCertificateChainRequestCallback( app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::CertificateChainRequest::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("CertificateChainRequest", "OperationalCredentials"); auto & certificateType = commandData.certificateType; CHIP_ERROR err = CHIP_NO_ERROR; @@ -730,6 +736,7 @@ bool emberAfOperationalCredentialsClusterAttestationRequestCallback(app::Command const app::ConcreteCommandPath & commandPath, const Commands::AttestationRequest::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("AttestationRequest", "OperationalCredentials"); auto & attestationNonce = commandData.attestationNonce; CHIP_ERROR err = CHIP_NO_ERROR; @@ -790,6 +797,7 @@ bool emberAfOperationalCredentialsClusterCSRRequestCallback(app::CommandHandler const app::ConcreteCommandPath & commandPath, const Commands::CSRRequest::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("CSRRequest", "OperationalCredentials"); emberAfPrintln(EMBER_AF_PRINT_DEBUG, "OpCreds: commissioner has requested a CSR"); CHIP_ERROR err = CHIP_NO_ERROR; @@ -879,6 +887,7 @@ bool emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback( app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::AddTrustedRootCertificate::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("AddTrustedRootCertificate", "OperationalCredentials"); auto & RootCertificate = commandData.rootCertificate; EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; @@ -917,6 +926,7 @@ bool emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback( app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::RemoveTrustedRootCertificate::DecodableType & commandData) { + MATTER_TRACE_EVENT_SCOPE("RemoveTrustedRootCertificate", "OperationalCredentials"); // TODO: Implement the logic for RemoveTrustedRootCertificate EmberAfStatus status = EMBER_ZCL_STATUS_FAILURE; emberAfSendImmediateDefaultResponse(status); diff --git a/src/controller/BUILD.gn b/src/controller/BUILD.gn index f9e1a31eee6e32..013f2101c457e1 100644 --- a/src/controller/BUILD.gn +++ b/src/controller/BUILD.gn @@ -68,6 +68,7 @@ static_library("controller") { "${chip_root}/src/platform", "${chip_root}/src/protocols", "${chip_root}/src/setup_payload", + "${chip_root}/src/trace", "${chip_root}/src/transport", ] diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index c7553ba8a668bd..2c4502f224e55d 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -73,6 +73,7 @@ #include #include #include +#include #if CONFIG_NETWORK_LAYER_BLE #include @@ -688,6 +689,7 @@ CHIP_ERROR DeviceCommissioner::Shutdown() CommissioneeDeviceProxy * DeviceCommissioner::FindCommissioneeDevice(const SessionHandle & session) { + MATTER_TRACE_EVENT_SCOPE("FindCommissioneeDevice", "DeviceCommissioner"); CommissioneeDeviceProxy * foundDevice = nullptr; mCommissioneeDevicePool.ForEachActiveObject([&](auto * deviceProxy) { if (deviceProxy->MatchesSession(session)) @@ -703,6 +705,7 @@ CommissioneeDeviceProxy * DeviceCommissioner::FindCommissioneeDevice(const Sessi CommissioneeDeviceProxy * DeviceCommissioner::FindCommissioneeDevice(NodeId id) { + MATTER_TRACE_EVENT_SCOPE("FindCommissioneeDevice", "DeviceCommissioner"); CommissioneeDeviceProxy * foundDevice = nullptr; mCommissioneeDevicePool.ForEachActiveObject([&](auto * deviceProxy) { if (deviceProxy->GetDeviceId() == id) @@ -740,17 +743,20 @@ CHIP_ERROR DeviceCommissioner::GetDeviceBeingCommissioned(NodeId deviceId, Commi CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, const char * setUpCode, const CommissioningParameters & params) { + MATTER_TRACE_EVENT_SCOPE("PairDevice", "DeviceCommissioner"); ReturnErrorOnFailure(mAutoCommissioner.SetCommissioningParameters(params)); return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kCommission); } CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, const char * setUpCode) { + MATTER_TRACE_EVENT_SCOPE("PairDevice", "DeviceCommissioner"); return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kCommission); } CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & params) { + MATTER_TRACE_EVENT_SCOPE("PairDevice", "DeviceCommissioner"); ReturnErrorOnFailure(EstablishPASEConnection(remoteDeviceId, params)); return Commission(remoteDeviceId); } @@ -758,17 +764,20 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & rendezvousParams, CommissioningParameters & commissioningParams) { + MATTER_TRACE_EVENT_SCOPE("PairDevice", "DeviceCommissioner"); ReturnErrorOnFailure(EstablishPASEConnection(remoteDeviceId, rendezvousParams)); return Commission(remoteDeviceId, commissioningParams); } CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, const char * setUpCode) { + MATTER_TRACE_EVENT_SCOPE("EstablishPASEConnection", "DeviceCommissioner"); return mSetUpCodePairer.PairDevice(remoteDeviceId, setUpCode, SetupCodePairerBehaviour::kPaseOnly); } CHIP_ERROR DeviceCommissioner::EstablishPASEConnection(NodeId remoteDeviceId, RendezvousParameters & params) { + MATTER_TRACE_EVENT_SCOPE("EstablishPASEConnection", "DeviceCommissioner"); CHIP_ERROR err = CHIP_NO_ERROR; CommissioneeDeviceProxy * device = nullptr; Transport::PeerAddress peerAddress = Transport::PeerAddress::UDP(Inet::IPAddress::Any); @@ -880,6 +889,7 @@ CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId, CommissioningPa CHIP_ERROR DeviceCommissioner::Commission(NodeId remoteDeviceId) { + MATTER_TRACE_EVENT_SCOPE("Commission", "DeviceCommissioner"); // TODO(cecille): Can we get rid of mDeviceBeingCommissioned and use the remote id instead? Would require storing the // commissioning stage in the device. CommissioneeDeviceProxy * device = mDeviceBeingCommissioned; @@ -1008,6 +1018,7 @@ void DeviceCommissioner::OnSessionEstablished() CHIP_ERROR DeviceCommissioner::SendCertificateChainRequestCommand(DeviceProxy * device, Credentials::CertificateType certificateType) { + MATTER_TRACE_EVENT_SCOPE("SendCertificateChainRequestCommand", "DeviceCommissioner"); ChipLogDetail(Controller, "Sending Certificate Chain request to %p device", device); VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -1021,6 +1032,7 @@ CHIP_ERROR DeviceCommissioner::SendCertificateChainRequestCommand(DeviceProxy * void DeviceCommissioner::OnCertificateChainFailureResponse(void * context, CHIP_ERROR error) { + MATTER_TRACE_EVENT_SCOPE("OnCertificateChainFailureResponse", "DeviceCommissioner"); ChipLogProgress(Controller, "Device failed to receive the Certificate Chain request Response: %s", chip::ErrorStr(error)); DeviceCommissioner * commissioner = reinterpret_cast(context); commissioner->CommissioningStageComplete(error); @@ -1029,6 +1041,7 @@ void DeviceCommissioner::OnCertificateChainFailureResponse(void * context, CHIP_ void DeviceCommissioner::OnCertificateChainResponse( void * context, const chip::app::Clusters::OperationalCredentials::Commands::CertificateChainResponse::DecodableType & response) { + MATTER_TRACE_EVENT_SCOPE("OnCertificateChainResponse", "DeviceCommissioner"); ChipLogProgress(Controller, "Received certificate chain from the device"); DeviceCommissioner * commissioner = reinterpret_cast(context); @@ -1040,6 +1053,7 @@ void DeviceCommissioner::OnCertificateChainResponse( CHIP_ERROR DeviceCommissioner::SendAttestationRequestCommand(DeviceProxy * device, const ByteSpan & attestationNonce) { + MATTER_TRACE_EVENT_SCOPE("SendAttestationRequestCommand", "DeviceCommissioner"); ChipLogDetail(Controller, "Sending Attestation request to %p device", device); VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -1054,6 +1068,7 @@ CHIP_ERROR DeviceCommissioner::SendAttestationRequestCommand(DeviceProxy * devic void DeviceCommissioner::OnAttestationFailureResponse(void * context, CHIP_ERROR error) { + MATTER_TRACE_EVENT_SCOPE("OnAttestationFailureResponse", "DeviceCommissioner"); ChipLogProgress(Controller, "Device failed to receive the Attestation Information Response: %s", chip::ErrorStr(error)); DeviceCommissioner * commissioner = reinterpret_cast(context); commissioner->CommissioningStageComplete(error); @@ -1062,6 +1077,7 @@ void DeviceCommissioner::OnAttestationFailureResponse(void * context, CHIP_ERROR void DeviceCommissioner::OnAttestationResponse(void * context, const OperationalCredentials::Commands::AttestationResponse::DecodableType & data) { + MATTER_TRACE_EVENT_SCOPE("OnAttestationResponse", "DeviceCommissioner"); ChipLogProgress(Controller, "Received Attestation Information from the device"); DeviceCommissioner * commissioner = reinterpret_cast(context); @@ -1072,6 +1088,7 @@ void DeviceCommissioner::OnAttestationResponse(void * context, void DeviceCommissioner::OnDeviceAttestationInformationVerification(void * context, AttestationVerificationResult result) { + MATTER_TRACE_EVENT_SCOPE("OnDeviceAttestationInformationVerification", "DeviceCommissioner"); DeviceCommissioner * commissioner = reinterpret_cast(context); if (result != AttestationVerificationResult::kSuccess) @@ -1103,6 +1120,7 @@ void DeviceCommissioner::OnDeviceAttestationInformationVerification(void * conte CHIP_ERROR DeviceCommissioner::ValidateAttestationInfo(const Credentials::DeviceAttestationVerifier::AttestationInfo & info) { + MATTER_TRACE_EVENT_SCOPE("ValidateAttestationInfo", "DeviceCommissioner"); VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE); DeviceAttestationVerifier * dac_verifier = GetDeviceAttestationVerifier(); @@ -1116,6 +1134,7 @@ CHIP_ERROR DeviceCommissioner::ValidateAttestationInfo(const Credentials::Device CHIP_ERROR DeviceCommissioner::SendOperationalCertificateSigningRequestCommand(DeviceProxy * device, const ByteSpan & csrNonce) { + MATTER_TRACE_EVENT_SCOPE("SendOperationalCertificateSigningRequestCommand", "DeviceCommissioner"); ChipLogDetail(Controller, "Sending CSR request to %p device", device); VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -1130,6 +1149,7 @@ CHIP_ERROR DeviceCommissioner::SendOperationalCertificateSigningRequestCommand(D void DeviceCommissioner::OnCSRFailureResponse(void * context, CHIP_ERROR error) { + MATTER_TRACE_EVENT_SCOPE("OnCSRFailureResponse", "DeviceCommissioner"); ChipLogProgress(Controller, "Device failed to receive the CSR request Response: %s", chip::ErrorStr(error)); DeviceCommissioner * commissioner = static_cast(context); commissioner->CommissioningStageComplete(error); @@ -1138,6 +1158,7 @@ void DeviceCommissioner::OnCSRFailureResponse(void * context, CHIP_ERROR error) void DeviceCommissioner::OnOperationalCertificateSigningRequest( void * context, const OperationalCredentials::Commands::CSRResponse::DecodableType & data) { + MATTER_TRACE_EVENT_SCOPE("OnOperationalCertificateSigningRequest", "DeviceCommissioner"); ChipLogProgress(Controller, "Received certificate signing request from the device"); DeviceCommissioner * commissioner = static_cast(context); @@ -1150,6 +1171,7 @@ void DeviceCommissioner::OnDeviceNOCChainGeneration(void * context, CHIP_ERROR s const ByteSpan & rcac, Optional ipk, Optional adminSubject) { + MATTER_TRACE_EVENT_SCOPE("OnDeviceNOCChainGeneration", "DeviceCommissioner"); DeviceCommissioner * commissioner = static_cast(context); // TODO(#13825): If not passed by the signer, the commissioner should @@ -1177,6 +1199,7 @@ void DeviceCommissioner::OnDeviceNOCChainGeneration(void * context, CHIP_ERROR s CHIP_ERROR DeviceCommissioner::ProcessCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements, const ByteSpan & AttestationSignature, ByteSpan dac, ByteSpan csrNonce) { + MATTER_TRACE_EVENT_SCOPE("ProcessOpCSR", "DeviceCommissioner"); VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE); ChipLogProgress(Controller, "Getting certificate chain for the device from the issuer"); @@ -1209,6 +1232,7 @@ CHIP_ERROR DeviceCommissioner::SendOperationalCertificate(DeviceProxy * device, const ByteSpan & icaCertBuf, const AesCcm128KeySpan ipk, const NodeId adminSubject) { + MATTER_TRACE_EVENT_SCOPE("SendOperationalCertificate", "DeviceCommissioner"); VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); OperationalCredentials::Commands::AddNOC::Type request; @@ -1256,6 +1280,7 @@ CHIP_ERROR DeviceCommissioner::ConvertFromOperationalCertStatus(OperationalCrede void DeviceCommissioner::OnAddNOCFailureResponse(void * context, CHIP_ERROR error) { + MATTER_TRACE_EVENT_SCOPE("OnAddNOCFailureResponse", "DeviceCommissioner"); ChipLogProgress(Controller, "Device failed to receive the operational certificate Response: %s", chip::ErrorStr(error)); DeviceCommissioner * commissioner = static_cast(context); commissioner->CommissioningStageComplete(error); @@ -1264,6 +1289,7 @@ void DeviceCommissioner::OnAddNOCFailureResponse(void * context, CHIP_ERROR erro void DeviceCommissioner::OnOperationalCertificateAddResponse( void * context, const OperationalCredentials::Commands::NOCResponse::DecodableType & data) { + MATTER_TRACE_EVENT_SCOPE("OnOperationalCertificateAddResponse", "DeviceCommissioner"); ChipLogProgress(Controller, "Device returned status %d on receiving the NOC", to_underlying(data.statusCode)); DeviceCommissioner * commissioner = static_cast(context); @@ -1291,6 +1317,7 @@ void DeviceCommissioner::OnOperationalCertificateAddResponse( CHIP_ERROR DeviceCommissioner::SendTrustedRootCertificate(DeviceProxy * device, const ByteSpan & rcac) { + MATTER_TRACE_EVENT_SCOPE("SendTrustedRootCertificate", "DeviceCommissioner"); VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); ChipLogProgress(Controller, "Sending root certificate to the device"); @@ -1307,6 +1334,7 @@ CHIP_ERROR DeviceCommissioner::SendTrustedRootCertificate(DeviceProxy * device, void DeviceCommissioner::OnRootCertSuccessResponse(void * context, const chip::app::DataModel::NullObjectType &) { + MATTER_TRACE_EVENT_SCOPE("OnRootCertSuccessResponse", "DeviceCommissioner"); ChipLogProgress(Controller, "Device confirmed that it has received the root certificate"); DeviceCommissioner * commissioner = static_cast(context); commissioner->CommissioningStageComplete(CHIP_NO_ERROR); @@ -1314,6 +1342,7 @@ void DeviceCommissioner::OnRootCertSuccessResponse(void * context, const chip::a void DeviceCommissioner::OnRootCertFailureResponse(void * context, CHIP_ERROR error) { + MATTER_TRACE_EVENT_SCOPE("OnRootCertFailureResponse", "DeviceCommissioner"); ChipLogProgress(Controller, "Device failed to receive the root certificate Response: %s", chip::ErrorStr(error)); DeviceCommissioner * commissioner = static_cast(context); commissioner->CommissioningStageComplete(error); @@ -1321,6 +1350,7 @@ void DeviceCommissioner::OnRootCertFailureResponse(void * context, CHIP_ERROR er CHIP_ERROR DeviceCommissioner::OnOperationalCredentialsProvisioningCompletion(CommissioneeDeviceProxy * device) { + MATTER_TRACE_EVENT_SCOPE("OnOperationalCredentialsProvisioningCompletion", "DeviceCommissioner"); ChipLogProgress(Controller, "Operational credentials provisioned on device %p", device); VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -1431,6 +1461,7 @@ void OnBasicFailure(void * context, CHIP_ERROR error) void DeviceCommissioner::CommissioningStageComplete(CHIP_ERROR err, CommissioningDelegate::CommissioningReport report) { + MATTER_TRACE_EVENT_SCOPE("CommissioningStageComplete", "DeviceCommissioner"); if (mCommissioningDelegate == nullptr) { return; From 378991846089c011b4a78afb0db738be05fa85cc Mon Sep 17 00:00:00 2001 From: Yuanyao Zhong <82843247+yyzhong-g@users.noreply.github.com> Date: Thu, 17 Mar 2022 23:36:49 -0400 Subject: [PATCH 12/15] Add instructions on how to add trace events (#16393) * Add instructions on how to add trace events * Restyled by prettier-markdown * Add words to wordlist Co-authored-by: Restyled.io --- .github/.wordlist.txt | 6 ++++++ src/trace/README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/trace/README.md diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 4b3359cc8684a4..6bc042eaf8c714 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -156,6 +156,7 @@ BTP btvirt buildwithmatter burndown +ButtonIsr BytesMain bz bzip @@ -604,6 +605,7 @@ Infineon ini init inlined +InputLoop installDebug instantiation integrations @@ -654,6 +656,7 @@ kGroup kInvalidCommandId KitProg kManage +kNewButton kNodeIdNotSpecified knownissues kOperate @@ -1080,6 +1083,8 @@ sdl SED SEGGER semver +SendButton +SendNewInputEvent sendto SERIALDEVICE SerialNumber @@ -1307,6 +1312,7 @@ vous VPN VSC VSCode +WaitNewInputEvent WakeOnLan WantedBy webpage diff --git a/src/trace/README.md b/src/trace/README.md new file mode 100644 index 00000000000000..64e699d4b08db0 --- /dev/null +++ b/src/trace/README.md @@ -0,0 +1,40 @@ +# Matter tracing + +Matter tracing provides a tool for applications to trace information about the +execution of the application. It depends on +[pw_trace module](https://pigweed.dev/pw_trace/). + +## How to add trace events + +1. Include "trace/trace.h" in the source file. +2. Add "\${chip_root}/src/trace" as deps in BUILD.gn. +3. Add MATTER*TRACE_EVENT*\* in functions to be traced. + +## Example + +``` +#include "pw_trace/trace.h" + + void SendButton() { + MATTER_TRACE_EVENT_FUNCTION(); + // do something + } + + void InputLoop() { + while(1) { + auto event = WaitNewInputEvent() + MATTER_TRACE_EVENT_SCOPE("Handle Event"); // measure until loop finished + if (event == kNewButton){ + SendButton(); + MATTER_TRACE_EVENT_END("button"); // Trace event was started in ButtonIsr + } else { + MATTER_TRACE_EVENT_INSTANT("Unknown event"); + } + } + } + + void ButtonIsr() { + MATTER_TRACE_EVENT_START("button"); + SendNewInputEvent(kNewButton); + } +``` From 2b959929976a96f3b9bf2759c84ab46a6b270d00 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Fri, 18 Mar 2022 04:39:35 +0100 Subject: [PATCH 13/15] Enable door lock and TV app tests on Darwin platform (#16347) Closes #15905 --- .github/workflows/tests.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 7181f7da0ba107..45577560359d05 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -176,6 +176,8 @@ jobs: "./scripts/build/build_examples.py \ --target darwin-x64-chip-tool-${BUILD_VARIANT}${CHIP_TOOL_VARIANT} \ --target darwin-x64-all-clusters-${BUILD_VARIANT} \ + --target darwin-x64-door-lock-${BUILD_VARIANT} \ + --target darwin-x64-tv-app-${BUILD_VARIANT} \ build \ --copy-artifacts-to objdir-clone \ " @@ -185,10 +187,12 @@ jobs: ./scripts/run_in_build_env.sh \ "./scripts/tests/run_test_suite.py \ --chip-tool ./out/darwin-x64-chip-tool-${BUILD_VARIANT}${CHIP_TOOL_VARIANT}/chip-tool \ - --target-skip-glob '{TestGroupMessaging,DL_*,TV_*}' \ + --target-skip-glob '{TestGroupMessaging}' \ run \ --iterations 1 \ --all-clusters-app ./out/darwin-x64-all-clusters-${BUILD_VARIANT}/chip-all-clusters-app \ + --door-lock-app ./out/darwin-x64-door-lock-${BUILD_VARIANT}/chip-door-lock-app \ + --tv-app ./out/darwin-x64-tv-app-${BUILD_VARIANT}/chip-tv-app \ " - name: Uploading core files uses: actions/upload-artifact@v2 From fe5ec84c965927d104e988c35d04cae16b9f753c Mon Sep 17 00:00:00 2001 From: Song GUO Date: Fri, 18 Mar 2022 12:32:16 +0800 Subject: [PATCH 14/15] [Python] Make it easier to run Python tests in CI (#15714) * Run Python Test script on CI * Redirect log for pretty output * Update output * Fix * Update doc * Update script * Fix * Disable re-CASE * Update test * Add no-wifi variant * Fix log * Remove test in build.yaml * Enrich functions for enable and disable tests * Remove wait time, update doc * Fix * These words should not by typo? --- .github/.wordlist.txt | 6 + .github/workflows/build.yaml | 1 + .github/workflows/tests.yaml | 166 ++++++++++++++++++ docs/guides/matter-repl.md | 82 +++++++++ scripts/build/build/targets.py | 1 + scripts/build/builders/host.py | 5 +- scripts/build_python.sh | 49 ++++-- scripts/tests/run_python_test.py | 157 +++++++++++++++++ .../python/test/test_scripts/base.py | 73 ++++++++ .../test/test_scripts/cluster_objects.py | 82 +++++---- .../test/test_scripts/mobile-device-test.py | 161 +++++++++++------ .../test_scripts/network_commissioning.py | 49 ++++-- .../linux-cirque/MobileDeviceTest.py | 3 +- 13 files changed, 708 insertions(+), 127 deletions(-) create mode 100755 scripts/tests/run_python_test.py diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 6bc042eaf8c714..2136de4b058c49 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -1415,6 +1415,12 @@ kManage kOperate kView xFFFFFFFD +ClusterObjectTests +TestTimedRequestTimeout +datamodel +appliable +commissionee +configs NAMESERVER UTF localedef diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 26d51133babca5..84b0c28d9873e5 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -265,6 +265,7 @@ jobs: run: | scripts/run_in_build_env.sh 'pip3 install ./out/controller/python/chip-0.0-cp37-abi3-linux_x86_64.whl' scripts/run_in_build_env.sh '(cd src/controller/python/test/unit_tests/ && python3 -m unittest -v)' + build_darwin: name: Build on Darwin (clang, python_lib, simulated) timeout-minutes: 200 diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 45577560359d05..58a781cedcfef8 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -216,3 +216,169 @@ jobs: path: objdir-clone/ # objdirs are big; don't hold on to them too long. retention-days: 5 + repl_tests_linux: + name: REPL Tests - Linux + timeout-minutes: 120 + + strategy: + matrix: + build_variant: [no-ble-no-wifi-tsan] + + env: + BUILD_VARIANT: ${{matrix.build_variant}} + TSAN_OPTIONS: "halt_on_error=1 suppressions=scripts/tests/chiptest/tsan-linux-suppressions.txt" + + if: github.actor != 'restyled-io[bot]' + runs-on: ubuntu-latest + + container: + image: connectedhomeip/chip-build:0.5.56 + options: + --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 + net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: true + - name: + Try to ensure the directories for core dumping exist and we + can write them. + run: | + mkdir /tmp/cores || true + sysctl -w kernel.core_pattern=/tmp/cores/core.%u.%p.%t || true + mkdir objdir-clone || true + - name: Bootstrap + timeout-minutes: 10 + run: scripts/build/gn_bootstrap.sh + - name: Uploading bootstrap logs + uses: actions/upload-artifact@v2 + if: ${{ always() }} && ${{ !env.ACT }} + with: + name: + bootstrap-logs-linux-${{ matrix.build_variant }}${{ matrix.chip_tool }} + path: | + .environment/gn_out/.ninja_log + .environment/pigweed-venv/*.log + - name: Build Python REPL and example apps + timeout-minutes: 50 + run: | + scripts/run_in_build_env.sh './scripts/build_python.sh --install_wheel build-env' + ./scripts/run_in_build_env.sh \ + "./scripts/build/build_examples.py \ + --target linux-x64-all-clusters-${BUILD_VARIANT} \ + build \ + --copy-artifacts-to objdir-clone \ + " + - name: Run Tests + timeout-minutes: 30 + run: | + scripts/run_in_build_env.sh './scripts/tests/run_python_test.py --app chip-all-clusters-app --factoryreset -- -t 3600 --disable-test ClusterObjectTests.TestTimedRequestTimeout' + - name: Uploading core files + uses: actions/upload-artifact@v2 + if: ${{ failure() }} && ${{ !env.ACT }} + with: + name: + crash-core-linux-python-repl + path: /tmp/cores/ + # Cores are big; don't hold on to them too long. + retention-days: 5 + - name: Uploading objdir for debugging + uses: actions/upload-artifact@v2 + if: ${{ failure() }} && ${{ !env.ACT }} + with: + name: + crash-objdir-linux-python-repl + path: objdir-clone/ + # objdirs are big; don't hold on to them too long. + retention-days: 5 + + repl_tests_darwin: + name: REPL Tests - Darwin + timeout-minutes: 120 + + strategy: + matrix: + build_variant: [no-ble-no-wifi-tsan] + env: + BUILD_VARIANT: ${{matrix.build_variant}} + TSAN_OPTIONS: "halt_on_error=1" + + if: github.actor != 'restyled-io[bot]' + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: true + - name: Setup Environment + # coreutils for stdbuf + run: brew install openssl pkg-config coreutils + - name: + Try to ensure the directories for core dumping and diagnostic + log collection exist and we can write them. + run: | + sudo chown ${USER} /cores || true + mkdir -p ~/Library/Logs/DiagnosticReports || true + mkdir objdir-clone || true + - name: Fix pkgconfig link + working-directory: /usr/local/lib/pkgconfig + run: | + pwd + ls -la /usr/local/Cellar/ + ls -la /usr/local/Cellar/openssl@1.1 + OPEN_SSL_VERSION=`ls -la /usr/local/Cellar/openssl@1.1 | cat | tail -n1 | awk '{print $NF}'` + ln -s /usr/local/Cellar/openssl@1.1/$OPEN_SSL_VERSION/lib/pkgconfig/* . + - name: Bootstrap + timeout-minutes: 25 + run: scripts/build/gn_bootstrap.sh + - name: Uploading bootstrap logs + uses: actions/upload-artifact@v2 + if: ${{ always() }} && ${{ !env.ACT }} + with: + name: + bootstrap-logs-darwin-${{ matrix.build_variant }}${{ matrix.chip_tool }} + path: | + .environment/gn_out/.ninja_log + .environment/pigweed-venv/*.log + - name: Build Python REPL and example apps + timeout-minutes: 50 + run: | + scripts/run_in_build_env.sh './scripts/build_python.sh --install_wheel build-env' + ./scripts/run_in_build_env.sh \ + "./scripts/build/build_examples.py \ + --target darwin-x64-all-clusters-${BUILD_VARIANT} \ + build \ + --copy-artifacts-to objdir-clone \ + " + - name: Run Tests + timeout-minutes: 30 + run: | + scripts/run_in_build_env.sh './scripts/tests/run_python_test.py --app chip-all-clusters-app --factoryreset --app-params "--discriminator 3840 --interface-id -1" -- -t 3600 --disable-test ClusterObjectTests.TestTimedRequestTimeout' + - name: Uploading core files + uses: actions/upload-artifact@v2 + if: ${{ failure() }} && ${{ !env.ACT }} + with: + name: + crash-core-darwin-python-repl + path: /cores/ + # Cores are big; don't hold on to them too long. + retention-days: 5 + - name: Uploading diagnostic logs + uses: actions/upload-artifact@v2 + if: ${{ failure() }} && ${{ !env.ACT }} + with: + name: + crash-log-darwin-python-repl + path: ~/Library/Logs/DiagnosticReports/ + - name: Uploading objdir for debugging + uses: actions/upload-artifact@v2 + if: ${{ failure() }} && ${{ !env.ACT }} + with: + name: + crash-objdir-darwin-python-repl + path: objdir-clone/ + # objdirs are big; don't hold on to them too long. + retention-days: 5 diff --git a/docs/guides/matter-repl.md b/docs/guides/matter-repl.md index c9a6aa86ce1684..52e0c31ba271c2 100644 --- a/docs/guides/matter-repl.md +++ b/docs/guides/matter-repl.md @@ -163,3 +163,85 @@ launched into the playground: [Multi Fabric Commissioning](https://deepnote.com/viewer/github/project-chip/connectedhomeip/blob/master/docs/guides/repl/Matter%20-%20Multi%20Fabric%20Commissioning.ipynb) [Access Control](https://deepnote.com/viewer/github/project-chip/connectedhomeip/blob/master/docs/guides/repl/Matter%20-%20Access%20Control.ipynb) + +## Testing + +We also provide `mobile-device-test.py` for testing your accessories, you can +run it manually or using a wrapper script. + +### Usage + +mobile-device-test.py provides the following options for running the tests: + +``` + --controller-nodeid INTEGER NodeId of the controller. + --device-nodeid INTEGER NodeId of the device. + -a, --address TEXT Skip commissionee discovery, commission the + device with the IP directly. + + -t, --timeout INTEGER The program will return with timeout after + specified seconds. + + --discriminator INTEGER Discriminator of the device. + --setup-pin INTEGER Setup pincode of the device. + --enable-test TEXT The tests to be executed. By default, all + tests will be executed, use this option to + run a specific set of tests. Use --print- + test-list for a list of appliable tests. + + --disable-test TEXT The tests to be excluded from the set of + enabled tests. Use --print-test-list for a + list of appliable tests. + + --log-level [ERROR|WARN|INFO|DEBUG] + The log level of the test. + --log-format TEXT Override logging format + --print-test-list Print a list of test cases and test sets + that can be toggled via --enable-test and + --disable-test, then exit + + --help Show this message and exit. +``` + +By default, all tests will be executed, however, you can exclude one or more +tests or only include a few tests if you want. + +For example, if you are working for commissioning, then you may want to exclude +the data model test cases by adding `--disable-test datamodel` to disable all +data model tests. + +Some tests provides the option to exclude them. For example, you can use +`--disable-test ClusterObjectTests.TestTimedRequestTimeout` to exclude the +"TestTimedRequestTimeout" test case. + +It is recommanded to use the test wrapper to run mobile-device-test.py, for +example, you can run: + +``` +./scripts/tests/run_python_test.py --app chip-all-clusters-app --factoryreset +``` + +It provides some extra options, for example: + +``` + --app TEXT Local application to use, omit to use external apps, use + a path for a specific binary or use a filename to search + under the current matter checkout. + + --factoryreset Remove app config and repl configs (/tmp/chip* and + /tmp/repl*) before running the tests. + + --app-params TEXT The extra parameters passed to the device. + --script PATH Test script to use. + --help Show this message and exit. +``` + +You can pass your own flags for mobile-device-test.py by appending them to the +command line with two dashes, for example: + +``` +./scripts/tests/run_python_test.py --app chip-all-clusters-app --factoryreset -- -t 90 --disable-test ClusterObjectTests.TestTimedRequestTimeout +``` + +will pass `-t 90 --disable-test ClusterObjectTests.TestTimedRequestTimeout` to +`mobile-device-test.py` diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index 3a3f38191b56f0..e591dfaee481f3 100644 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -229,6 +229,7 @@ def HostTargets(): # builds is exponential here builder.AppendVariant(name="ipv6only", enable_ipv4=False), builder.AppendVariant(name="no-ble", enable_ble=False), + builder.AppendVariant(name="no-wifi", enable_wifi=False), builder.AppendVariant(name="tsan", conflicts=['asan'], use_tsan=True), builder.AppendVariant(name="asan", conflicts=['tsan'], use_asan=True), builder.AppendVariant( diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index 4e787550b4cd56..a97b44c0df873c 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -154,7 +154,7 @@ def PlatformName(self): class HostBuilder(GnBuilder): def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE, enable_ipv4=True, - enable_ble=True, use_tsan=False, use_asan=False, separate_event_loop=True, + enable_ble=True, enable_wifi=True, use_tsan=False, use_asan=False, separate_event_loop=True, test_group=False, use_libfuzzer=False, use_clang=False, use_platform_mdns=False): super(HostBuilder, self).__init__( @@ -171,6 +171,9 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE, enable_ip if not enable_ble: self.extra_gn_options.append('chip_config_network_layer_ble=false') + if not enable_wifi: + self.extra_gn_options.append('chip_enable_wifi=false') + if use_tsan: self.extra_gn_options.append('is_tsan=true') diff --git a/scripts/build_python.sh b/scripts/build_python.sh index 7949f04644ca6f..c4504f1433907c 100755 --- a/scripts/build_python.sh +++ b/scripts/build_python.sh @@ -42,6 +42,7 @@ declare chip_detail_logging=false declare enable_pybindings=false declare chip_mdns declare case_retry_delta +declare install_wheel=no help() { @@ -58,6 +59,10 @@ Input Options: -t --time_between_case_retries MRPActiveRetryInterval Specify MRPActiveRetryInterval value Default is 300 ms + -i, --install_wheel no|build-env|separate Where to install the Python wheel + no: Do not install + build-env: install to virtual env for build matter + separate: install to another virtual env (out/python_env) " } @@ -85,6 +90,10 @@ while (($#)); do chip_case_retry_delta=$2 shift ;; + --install_wheel | -i) + install_wheel=$2 + shift + ;; -*) help echo "Unknown Option \"$1\"" @@ -114,24 +123,34 @@ else ninja -C "$OUTPUT_ROOT" python fi -# Create a virtual environment that has access to the built python tools -virtualenv --clear "$ENVIRONMENT_ROOT" - -# Activate the new environment to register the python WHL - if [ "$enable_pybindings" == true ]; then WHEEL=$(ls "$OUTPUT_ROOT"/pybindings/pycontroller/pychip-*.whl | head -n 1) else WHEEL=$(ls "$OUTPUT_ROOT"/controller/python/chip-*.whl | head -n 1) fi -source "$ENVIRONMENT_ROOT"/bin/activate -"$ENVIRONMENT_ROOT"/bin/python -m pip install --upgrade pip -"$ENVIRONMENT_ROOT"/bin/pip install --upgrade --force-reinstall --no-cache-dir "$WHEEL" - -echo "" -echo_green "Compilation completed and WHL package installed in: " -echo_blue " $ENVIRONMENT_ROOT" -echo "" -echo_green "To use please run:" -echo_bold_white " source $ENVIRONMENT_ROOT/bin/activate" +if [ "$install_wheel" = "no" ]; then + exit 0 +elif [ "$install_wheel" = "separate" ]; then + # Create a virtual environment that has access to the built python tools + virtualenv --clear "$ENVIRONMENT_ROOT" + + source "$ENVIRONMENT_ROOT"/bin/activate + "$ENVIRONMENT_ROOT"/bin/python -m pip install --upgrade pip + "$ENVIRONMENT_ROOT"/bin/pip install --upgrade --force-reinstall --no-cache-dir "$WHEEL" + + echo "" + echo_green "Compilation completed and WHL package installed in: " + echo_blue " $ENVIRONMENT_ROOT" + echo "" + echo_green "To use please run:" + echo_bold_white " source $ENVIRONMENT_ROOT/bin/activate" +elif [ "$install_wheel" = "build-env" ]; then + pip install --force-reinstall "$WHEEL" + + echo "" + echo_green "Compilation completed and WHL package installed in virtualenv for building sdk" + echo "" + echo_green "To use please run:" + echo_bold_white " source $CHIP_ROOT/scripts/activate.sh" +fi diff --git a/scripts/tests/run_python_test.py b/scripts/tests/run_python_test.py new file mode 100755 index 00000000000000..229e26594a4694 --- /dev/null +++ b/scripts/tests/run_python_test.py @@ -0,0 +1,157 @@ +#!/usr/bin/env -S python3 -B + +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pty +import subprocess +import click +import os +import pathlib +import typing +import queue +import threading +import sys +import time +import datetime +import shlex +import logging + +DEFAULT_CHIP_ROOT = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..')) + + +def FindBinaryPath(name: str): + for path in pathlib.Path(DEFAULT_CHIP_ROOT).rglob(name): + if not path.is_file(): + continue + if path.name != name: + continue + return str(path) + + return None + + +def EnqueueLogOutput(fp, tag, q): + for line in iter(fp.readline, b''): + timestamp = time.time() + if len(line) > len('[1646290606.901990]') and line[0:1] == b'[': + try: + timestamp = float(line[1:18].decode()) + line = line[19:] + except Exception as ex: + pass + q.put((tag, line, datetime.datetime.fromtimestamp( + timestamp).isoformat(sep=" "))) + fp.close() + + +def RedirectQueueThread(fp, tag, queue) -> threading.Thread: + log_queue_thread = threading.Thread(target=EnqueueLogOutput, args=( + fp, tag, queue)) + log_queue_thread.start() + return log_queue_thread + + +def DumpLogOutput(q: queue.Queue): + # TODO: Due to the nature of os pipes, the order of the timestamp is not guaranteed, need to figure out a better output format. + while True: + line = q.get_nowait() + sys.stdout.buffer.write( + (f"[{line[2]}]").encode() + line[0] + line[1]) + sys.stdout.flush() + + +def DumpProgramOutputToQueue(thread_list: typing.List[threading.Thread], tag: str, process: subprocess.Popen, queue: queue.Queue): + thread_list.append(RedirectQueueThread(process.stdout, + (f"[{tag}][\33[33mSTDOUT\33[0m]").encode(), queue)) + thread_list.append(RedirectQueueThread(process.stderr, + (f"[{tag}][\33[31mSTDERR\33[0m]").encode(), queue)) + + +@click.command() +@click.option("--app", type=str, default=None, help='Local application to use, omit to use external apps, use a path for a specific binary or use a filename to search under the current matter checkout.') +@click.option("--factoryreset", is_flag=True, help='Remove app config and repl configs (/tmp/chip* and /tmp/repl*) before running the tests.') +@click.option("--app-params", type=str, default='', help='The extra parameters passed to the device.') +@click.option("--script", type=click.Path(exists=True), default=FindBinaryPath("mobile-device-test.py"), help='Test script to use.') +@click.argument("script-args", nargs=-1, type=str) +def main(app: str, factoryreset: bool, app_params: str, script: str, script_args: typing.List[str]): + if factoryreset: + retcode = subprocess.call("rm -rf /tmp/chip* /tmp/repl*", shell=True) + if retcode != 0: + raise Exception("Failed to remove /tmp/chip* for factory reset.") + + log_queue = queue.Queue() + log_cooking_threads = [] + + app_process = None + if app: + if not os.path.exists(app): + app = FindBinaryPath(app) + if app is None: + raise FileNotFoundError(f"{app} not found") + app_args = [app] + shlex.split(app_params) + logging.info(f"Execute: {app_args}") + app_process = subprocess.Popen( + app_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0) + DumpProgramOutputToQueue( + log_cooking_threads, "\33[34mAPP \33[0m", app_process, log_queue) + + script_command = ["/usr/bin/env", "python3", script, + '--log-format', '%(message)s'] + [v for v in script_args] + logging.info(f"Execute: {script_command}") + test_script_process = subprocess.Popen( + script_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + DumpProgramOutputToQueue(log_cooking_threads, "\33[32mTEST\33[0m", + test_script_process, log_queue) + + test_script_exit_code = test_script_process.poll() + while test_script_exit_code is None: + try: + DumpLogOutput(log_queue) + except queue.Empty: + pass + test_script_exit_code = test_script_process.poll() + + test_app_exit_code = 0 + if app_process: + app_process.send_signal(2) + + test_app_exit_code = app_process.poll() + while test_app_exit_code is None: + try: + DumpLogOutput(log_queue) + except queue.Empty: + pass + test_app_exit_code = app_process.poll() + + # There are some logs not cooked, so we wait until we have processed all logs. + # This procedure should be very fast since the related processes are finished. + for thread in log_cooking_threads: + thread.join() + + try: + DumpLogOutput(log_queue) + except queue.Empty: + pass + + if test_script_exit_code != 0: + sys.exit(test_script_exit_code) + else: + # We expect both app and test script should exit with 0 + sys.exit(test_app_exit_code) + + +if __name__ == '__main__': + main() diff --git a/src/controller/python/test/test_scripts/base.py b/src/controller/python/test/test_scripts/base.py index 4094b2e65c13f9..2db688e9fd11d1 100644 --- a/src/controller/python/test/test_scripts/base.py +++ b/src/controller/python/test/test_scripts/base.py @@ -15,8 +15,10 @@ # limitations under the License. # +import asyncio from dataclasses import dataclass from inspect import Attribute +import inspect from typing import Any import typing from chip import ChipDeviceCtrl @@ -55,6 +57,67 @@ def FailIfNot(cond, message): TestFail(message) +_configurable_tests = set() +_configurable_test_sets = set() +_enabled_tests = [] +_disabled_tests = [] + + +def SetTestSet(enabled_tests, disabled_tests): + global _enabled_tests, _disabled_tests + _enabled_tests = enabled_tests[:] + _disabled_tests = disabled_tests[:] + + +def TestIsEnabled(test_name: str): + enabled_len = -1 + disabled_len = -1 + if 'all' in _enabled_tests: + enabled_len = 0 + if 'all' in _disabled_tests: + disabled_len = 0 + + for test_item in _enabled_tests: + if test_name.startswith(test_item) and (len(test_item) > enabled_len): + enabled_len = len(test_item) + + for test_item in _disabled_tests: + if test_name.startswith(test_item) and (len(test_item) > disabled_len): + disabled_len = len(test_item) + + return enabled_len > disabled_len + + +def test_set(cls): + _configurable_test_sets.add(cls.__qualname__) + return cls + + +def test_case(func): + test_name = func.__qualname__ + _configurable_tests.add(test_name) + + def CheckEnableBeforeRun(*args, **kwargs): + if TestIsEnabled(test_name=test_name): + return func(*args, **kwargs) + elif inspect.iscoroutinefunction(func): + # noop, so users can use await as usual + return asyncio.sleep(0) + return CheckEnableBeforeRun + + +def configurable_tests(): + res = [v for v in _configurable_test_sets] + res.sort() + return res + + +def configurable_test_cases(): + res = [v for v in _configurable_tests] + res.sort() + return res + + class TestTimeout(threading.Thread): def __init__(self, timeout: int): threading.Thread.__init__(self) @@ -136,6 +199,16 @@ def TestDiscovery(self, discriminator: int): self.logger.info(f"Found device at {res}") return res + def TestKeyExchangeBLE(self, discriminator: int, setuppin: int, nodeid: int): + self.logger.info( + "Conducting key exchange with device {}".format(discriminator)) + if not self.devCtrl.ConnectBLE(discriminator, setuppin, nodeid): + self.logger.info( + "Failed to finish key exchange with device {}".format(discriminator)) + return False + self.logger.info("Device finished key exchange.") + return True + def TestKeyExchange(self, ip: str, setuppin: int, nodeid: int): self.logger.info("Conducting key exchange with device {}".format(ip)) if not self.devCtrl.CommissionIP(ip.encode("utf-8"), setuppin, nodeid): diff --git a/src/controller/python/test/test_scripts/cluster_objects.py b/src/controller/python/test/test_scripts/cluster_objects.py index bc2b9f2dde6c0b..2586c1865a6f5f 100644 --- a/src/controller/python/test/test_scripts/cluster_objects.py +++ b/src/controller/python/test/test_scripts/cluster_objects.py @@ -15,7 +15,7 @@ # limitations under the License. # - +import pprint import chip.clusters as Clusters import chip.exceptions import logging @@ -24,6 +24,8 @@ import asyncio import time +import base + logger = logging.getLogger('PythonMatterControllerTEST') logger.setLevel(logging.INFO) @@ -44,19 +46,18 @@ def _IgnoreAttributeDecodeFailure(path): def VerifyDecodeSuccess(values): - print(f"{values}") + pprint.pprint(values) for endpoint in values: for cluster in values[endpoint]: for attribute in values[endpoint][cluster]: v = values[endpoint][cluster][attribute] - print(f"EP{endpoint}/{cluster}/{attribute} = {v}") if (isinstance(v, ValueDecodeFailure)): if _IgnoreAttributeDecodeFailure((endpoint, cluster, attribute)): print( - f"Ignoring attribute decode failure for path {endpoint}/{cluster}/{attribute}") + f"Ignoring attribute decode failure for path {endpoint}/{attribute}") else: raise AssertionError( - f"Cannot decode value for path {endpoint}/{cluster}/{attribute}, got error: '{str(v.Reason)}', raw TLV data: '{v.TLVValue}'") + f"Cannot decode value for path {endpoint}/{attribute}, got error: '{str(v.Reason)}', raw TLV data: '{v.TLVValue}'") for endpoint in values: for cluster in values[endpoint]: @@ -71,8 +72,10 @@ def _AssumeEventsDecodeSuccess(values): print(f"Dump the events: {values} ") +@base.test_set class ClusterObjectTests: @classmethod + @base.test_case def TestAPI(cls): if Clusters.OnOff.id != 6: raise ValueError() @@ -86,7 +89,8 @@ def TestAPI(cls): raise ValueError() @classmethod - async def RoundTripTest(cls, devCtrl): + @base.test_case + async def TestCommandRoundTrip(cls, devCtrl): req = Clusters.OnOff.Commands.On() res = await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=LIGHTING_ENDPOINT_ID, payload=req) if res is not None: @@ -95,7 +99,8 @@ async def RoundTripTest(cls, devCtrl): raise ValueError() @classmethod - async def RoundTripTestWithBadEndpoint(cls, devCtrl): + @base.test_case + async def TestCommandRoundTripWithBadEndpoint(cls, devCtrl): req = Clusters.OnOff.Commands.On() try: await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=233, payload=req) @@ -105,7 +110,8 @@ async def RoundTripTestWithBadEndpoint(cls, devCtrl): return @classmethod - async def SendCommandWithResponse(cls, devCtrl): + @base.test_case + async def TestCommandWithResponse(cls, devCtrl): req = Clusters.TestCluster.Commands.TestAddArguments(arg1=2, arg2=3) res = await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=LIGHTING_ENDPOINT_ID, payload=req) if not isinstance(res, Clusters.TestCluster.Commands.TestAddArgumentsResponse): @@ -116,7 +122,8 @@ async def SendCommandWithResponse(cls, devCtrl): raise ValueError() @classmethod - async def SendWriteRequest(cls, devCtrl): + @base.test_case + async def TestWriteRequest(cls, devCtrl): logger.info("1: Trivial writes (multiple attributes)") res = await devCtrl.WriteAttribute(nodeid=NODE_ID, attributes=[ @@ -154,6 +161,7 @@ async def SendWriteRequest(cls, devCtrl): raise AssertionError("Write returned unexpected result.") @classmethod + @base.test_case async def TestSubscribeAttribute(cls, devCtrl): logger.info("Test Subscription") sub = await devCtrl.ReadAttribute(nodeid=NODE_ID, attributes=[(1, Clusters.OnOff.Attributes.OnOff)], reportInterval=(3, 10)) @@ -179,6 +187,7 @@ def subUpdate(path: TypedAttributePath, transaction: SubscriptionTransaction): sub.Shutdown() @classmethod + @base.test_case async def TestReadAttributeRequests(cls, devCtrl): ''' Tests out various permutations of endpoint, cluster and attribute ID (with wildcards) to validate @@ -284,6 +293,7 @@ async def TriggerAndWaitForEvents(cls, devCtrl, req): raise AssertionError("Got no events back") @classmethod + @base.test_case async def TestReadEventRequests(cls, devCtrl, expectEventsNum): logger.info("1: Reading Ex Cx Ex") req = [ @@ -323,6 +333,7 @@ async def TestReadEventRequests(cls, devCtrl, expectEventsNum): # TODO: Add more wildcard test for IM events. @classmethod + @base.test_case async def TestTimedRequest(cls, devCtrl): logger.info("1: Send Timed Command Request") req = Clusters.TestCluster.Commands.TimedInvokeRequest() @@ -336,49 +347,53 @@ async def TestTimedRequest(cls, devCtrl): ], timedRequestTimeoutMs=1000) - logger.info("3: Send Timed Command Request -- Timeout") + logger.info( + "3: Sending TestCluster-TimedInvokeRequest without timedRequestTimeoutMs should be rejected") try: req = Clusters.TestCluster.Commands.TimedInvokeRequest() - # 10ms is a pretty short timeout, RTT is 400ms in simulated network on CI, so this test should fail. - await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=1, payload=req, timedRequestTimeoutMs=10) - raise AssertionError("Timeout expected!") - except chip.exceptions.ChipStackException: + await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=1, payload=req) + raise AssertionError("The command invoke should be rejected.") + except ValueError: pass - logger.info("4: Send Timed Write Request -- Timeout") + logger.info( + "4: Writing TestCluster-TimedWriteBoolean without timedRequestTimeoutMs should be rejected") try: await devCtrl.WriteAttribute(nodeid=NODE_ID, attributes=[ (1, Clusters.TestCluster.Attributes.TimedWriteBoolean( True)), - ], - timedRequestTimeoutMs=10) - raise AssertionError("Timeout expected!") - except chip.exceptions.ChipStackException: + ]) + raise AssertionError("The write request should be rejected.") + except ValueError: pass - logger.info( - "5: Sending TestCluster-TimedInvokeRequest without timedRequestTimeoutMs should be rejected") + @classmethod + @base.test_case + async def TestTimedRequestTimeout(cls, devCtrl): + logger.info("1: Send Timed Command Request -- Timeout") try: req = Clusters.TestCluster.Commands.TimedInvokeRequest() - await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=1, payload=req) - raise AssertionError("The command invoke should be rejected.") - except ValueError: + # 10ms is a pretty short timeout, RTT is 400ms in simulated network on CI, so this test should fail. + await devCtrl.SendCommand(nodeid=NODE_ID, endpoint=1, payload=req, timedRequestTimeoutMs=1) + raise AssertionError("Timeout expected!") + except chip.exceptions.ChipStackException: pass - logger.info( - "6: Writing TestCluster-TimedWriteBoolean without timedRequestTimeoutMs should be rejected") + logger.info("2: Send Timed Write Request -- Timeout") try: await devCtrl.WriteAttribute(nodeid=NODE_ID, attributes=[ (1, Clusters.TestCluster.Attributes.TimedWriteBoolean( True)), - ]) - raise AssertionError("The write request should be rejected.") - except ValueError: + ], + timedRequestTimeoutMs=1) + raise AssertionError("Timeout expected!") + except chip.exceptions.ChipStackException: pass @classmethod + @base.test_case async def TestReadWriteAttributeRequestsWithVersion(cls, devCtrl): logger.info("TestReadWriteAttributeRequestsWithVersion") req = [ @@ -457,16 +472,17 @@ async def TestReadWriteAttributeRequestsWithVersion(cls, devCtrl): async def RunTest(cls, devCtrl): try: cls.TestAPI() - await cls.RoundTripTest(devCtrl) - await cls.RoundTripTestWithBadEndpoint(devCtrl) - await cls.SendCommandWithResponse(devCtrl) + await cls.TestCommandRoundTrip(devCtrl) + await cls.TestCommandRoundTripWithBadEndpoint(devCtrl) + await cls.TestCommandWithResponse(devCtrl) await cls.TestReadEventRequests(devCtrl, 1) await cls.TestReadWriteAttributeRequestsWithVersion(devCtrl) await cls.TestReadAttributeRequests(devCtrl) await cls.TestSubscribeAttribute(devCtrl) # Note: Write will change some attribute values, always put it after read tests - await cls.SendWriteRequest(devCtrl) + await cls.TestWriteRequest(devCtrl) await cls.TestTimedRequest(devCtrl) + await cls.TestTimedRequestTimeout(devCtrl) except Exception as ex: logger.error( f"Unexpected error occurred when running tests: {ex}") diff --git a/src/controller/python/test/test_scripts/mobile-device-test.py b/src/controller/python/test/test_scripts/mobile-device-test.py index fdaaeca8b3caed..4c8a137dc7afe0 100755 --- a/src/controller/python/test/test_scripts/mobile-device-test.py +++ b/src/controller/python/test/test_scripts/mobile-device-test.py @@ -18,10 +18,15 @@ # # Commissioning test. +from logging import disable import os import sys -from optparse import OptionParser -from base import TestFail, TestTimeout, BaseTestHelper, FailIfNot, logger +import click +import coloredlogs +import chip.logging +import logging +from base import TestFail, TestTimeout, BaseTestHelper, FailIfNot, logger, TestIsEnabled, SetTestSet +import base from cluster_objects import NODE_ID, ClusterObjectTests from network_commissioning import NetworkCommissioningTests import asyncio @@ -40,53 +45,35 @@ # Network id, for the thread network, current a const value, will be changed to XPANID of the thread network. TEST_THREAD_NETWORK_ID = "fedcba9876543210" TEST_DISCRIMINATOR = 3840 +TEST_SETUPPIN = 20202021 ENDPOINT_ID = 0 LIGHTING_ENDPOINT_ID = 1 GROUP_ID = 0 +TEST_CONTROLLER_NODE_ID = 112233 +TEST_DEVICE_NODE_ID = 1 -def main(): - optParser = OptionParser() - optParser.add_option( - "-t", - "--timeout", - action="store", - dest="testTimeout", - default=75, - type='int', - help="The program will return with timeout after specified seconds.", - metavar="", - ) - optParser.add_option( - "-a", - "--address", - action="store", - dest="deviceAddress", - default='', - type='str', - help="Address of the device", - metavar="", - ) - - (options, remainingArgs) = optParser.parse_args(sys.argv[1:]) - - timeoutTicker = TestTimeout(options.testTimeout) - timeoutTicker.start() +ALL_TESTS = ['network_commissioning', 'datamodel'] - test = BaseTestHelper(nodeid=112233) +def ethernet_commissioning(test: BaseTestHelper, discriminator: int, setup_pin: int, address_override: str, device_nodeid: int): logger.info("Testing discovery") - FailIfNot(test.TestDiscovery(discriminator=TEST_DISCRIMINATOR), - "Failed to discover any devices.") + address = test.TestDiscovery(discriminator=discriminator) + FailIfNot(address, "Failed to discover any devices.") # FailIfNot(test.SetNetworkCommissioningParameters(dataset=TEST_THREAD_NETWORK_DATASET_TLV), # "Failed to finish network commissioning") + if address_override: + address = address_override + else: + address = address.decode("utf-8") + logger.info("Testing key exchange") - FailIfNot(test.TestKeyExchange(ip=options.deviceAddress, - setuppin=20202021, - nodeid=1), + FailIfNot(test.TestKeyExchange(ip=address, + setuppin=setup_pin, + nodeid=device_nodeid), "Failed to finish key exchange") # @@ -95,38 +82,34 @@ def main(): # # Issue: #15688 # - # asyncio.run(test.TestMultiFabric(ip=options.deviceAddress, + # asyncio.run(test.TestMultiFabric(ip=address.decode("utf-8"), # setuppin=20202021, # nodeid=1)) # - # logger.info("Testing writing/reading fabric sensitive data") - # asyncio.run(test.TestFabricSensitive(nodeid=1)) + # The server will crash if we are aborting / closing it too fast. + # Issue: #15987 + # logger.info("Testing closing sessions") + # FailIfNot(test.TestCloseSession(nodeid=device_nodeid), + # "Failed to close sessions") - logger.info("Testing closing sessions") - FailIfNot(test.TestCloseSession(nodeid=1), "Failed to close sessions") - logger.info("Testing resolve") - FailIfNot(test.TestResolve(nodeid=1), - "Failed to resolve nodeid") - - # Still test network commissioning - logger.info("Testing network commissioning") - FailIfNot(asyncio.run(NetworkCommissioningTests(devCtrl=test.devCtrl, nodeid=1).run()), - "Failed to finish network commissioning") +@base.test_case +def TestDatamodel(test: BaseTestHelper, device_nodeid: int): + logger.info("Testing datamodel functions") logger.info("Testing on off cluster") - FailIfNot(test.TestOnOffCluster(nodeid=1, + FailIfNot(test.TestOnOffCluster(nodeid=device_nodeid, endpoint=LIGHTING_ENDPOINT_ID, group=GROUP_ID), "Failed to test on off cluster") logger.info("Testing level control cluster") - FailIfNot(test.TestLevelControlCluster(nodeid=1, + FailIfNot(test.TestLevelControlCluster(nodeid=device_nodeid, endpoint=LIGHTING_ENDPOINT_ID, group=GROUP_ID), "Failed to test level control cluster") logger.info("Testing sending commands to non exist endpoint") - FailIfNot(not test.TestOnOffCluster(nodeid=1, + FailIfNot(not test.TestOnOffCluster(nodeid=device_nodeid, endpoint=233, group=GROUP_ID), "Failed to test on off cluster on non-exist endpoint") @@ -136,13 +119,13 @@ def main(): "Failed when testing Python Cluster Object APIs") logger.info("Testing attribute reading") - FailIfNot(test.TestReadBasicAttributes(nodeid=1, + FailIfNot(test.TestReadBasicAttributes(nodeid=device_nodeid, endpoint=ENDPOINT_ID, group=GROUP_ID), "Failed to test Read Basic Attributes") logger.info("Testing attribute writing") - FailIfNot(test.TestWriteBasicAttributes(nodeid=1, + FailIfNot(test.TestWriteBasicAttributes(nodeid=device_nodeid, endpoint=ENDPOINT_ID, group=GROUP_ID), "Failed to test Write Basic Attributes") @@ -154,18 +137,46 @@ def main(): "Failed to test Read Basic Attributes") logger.info("Testing subscription") - FailIfNot(test.TestSubscription(nodeid=1, endpoint=LIGHTING_ENDPOINT_ID), + FailIfNot(test.TestSubscription(nodeid=device_nodeid, endpoint=LIGHTING_ENDPOINT_ID), "Failed to subscribe attributes.") logger.info("Testing another subscription that kills previous subscriptions") - FailIfNot(test.TestSubscription(nodeid=1, endpoint=LIGHTING_ENDPOINT_ID), + FailIfNot(test.TestSubscription(nodeid=device_nodeid, endpoint=LIGHTING_ENDPOINT_ID), "Failed to subscribe attributes.") logger.info("Testing on off cluster over resolved connection") - FailIfNot(test.TestOnOffCluster(nodeid=1, + FailIfNot(test.TestOnOffCluster(nodeid=device_nodeid, endpoint=LIGHTING_ENDPOINT_ID, group=GROUP_ID), "Failed to test on off cluster") + # logger.info("Testing writing/reading fabric sensitive data") + # asyncio.run(test.TestFabricSensitive(nodeid=device_nodeid)) + + +def do_tests(controller_nodeid, device_nodeid, address, timeout, discriminator, setup_pin): + timeoutTicker = TestTimeout(timeout) + timeoutTicker.start() + + test = BaseTestHelper(nodeid=controller_nodeid) + + chip.logging.RedirectToPythonLogging() + + ethernet_commissioning(test, discriminator, setup_pin, address, + device_nodeid) + + logger.info("Testing resolve") + FailIfNot(test.TestResolve(nodeid=device_nodeid), + "Failed to resolve nodeid") + + # Still test network commissioning + FailIfNot(asyncio.run(NetworkCommissioningTests(devCtrl=test.devCtrl, nodeid=device_nodeid).run()), + "Failed to finish network commissioning") + + TestDatamodel(test, device_nodeid) + + logger.info("Testing non-controller APIs") + FailIfNot(test.TestNonControllerAPIs(), "Non controller API test failed") + timeoutTicker.stop() logger.info("Test finished") @@ -175,9 +186,45 @@ def main(): os._exit(0) +@click.command() +@click.option("--controller-nodeid", default=TEST_CONTROLLER_NODE_ID, type=int, help="NodeId of the controller.") +@click.option("--device-nodeid", default=TEST_DEVICE_NODE_ID, type=int, help="NodeId of the device.") +@click.option("--address", "-a", default='', type=str, help="Skip commissionee discovery, commission the device with the IP directly.") +@click.option("--timeout", "-t", default=240, type=int, help="The program will return with timeout after specified seconds.") +@click.option("--discriminator", default=TEST_DISCRIMINATOR, type=int, help="Discriminator of the device.") +@click.option("--setup-pin", default=TEST_SETUPPIN, type=int, help="Setup pincode of the device.") +@click.option('--enable-test', default=['all'], type=str, multiple=True, help='The tests to be executed. By default, all tests will be executed, use this option to run a specific set of tests. Use --print-test-list for a list of appliable tests.') +@click.option('--disable-test', default=[], type=str, multiple=True, help='The tests to be excluded from the set of enabled tests. Use --print-test-list for a list of appliable tests.') +@click.option('--log-level', default='WARN', type=click.Choice(['ERROR', 'WARN', 'INFO', 'DEBUG']), help="The log level of the test.") +@click.option('--log-format', default=None, type=str, help="Override logging format") +@click.option('--print-test-list', is_flag=True, help="Print a list of test cases and test sets that can be toggled via --enable-test and --disable-test, then exit") +def run(controller_nodeid, device_nodeid, address, timeout, discriminator, setup_pin, enable_test, disable_test, log_level, log_format, print_test_list): + coloredlogs.install(level=log_level, fmt=log_format, logger=logger) + + if print_test_list: + print("Test sets:") + for name in base.configurable_tests(): + print(f"\t{name}") + print("Test cases:") + for name in base.configurable_test_cases(): + print(f"\t{name}") + return + + logger.info("Test Parameters:") + logger.info(f"\tController NodeId: {controller_nodeid}") + logger.info(f"\tDevice NodeId: {device_nodeid}") + logger.info(f"\tTest Timeout: {timeout}s") + logger.info(f"\tDiscriminator: {discriminator}") + logger.info(f"\tEnabled Tests: {enable_test}") + logger.info(f"\tDisabled Tests: {disable_test}") + SetTestSet(enable_test, disable_test) + do_tests(controller_nodeid, device_nodeid, address, timeout, + discriminator, setup_pin) + + if __name__ == "__main__": try: - main() + run() except Exception as ex: logger.exception(ex) TestFail("Exception occurred when running tests.") diff --git a/src/controller/python/test/test_scripts/network_commissioning.py b/src/controller/python/test/test_scripts/network_commissioning.py index 13f64bd9588a6e..baf8a6da32a851 100644 --- a/src/controller/python/test/test_scripts/network_commissioning.py +++ b/src/controller/python/test/test_scripts/network_commissioning.py @@ -22,6 +22,8 @@ import chip.interaction_model import asyncio +import base + logger = logging.getLogger('NetworkCommissioning') logger.setLevel(logging.INFO) @@ -48,6 +50,7 @@ THREAD_NETWORK_FEATURE_MAP = 2 +@base.test_set class NetworkCommissioningTests: def __init__(self, devCtrl, nodeid): self._devCtrl = devCtrl @@ -279,26 +282,34 @@ async def test_thread(self, endpointId): raise AssertionError( f"Unexpected result: network is not marked as connected") + @base.test_case + async def Test(self): + clusters = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(Clusters.Descriptor.Attributes.ServerList)], returnClusterObject=True) + if Clusters.NetworkCommissioning.id not in clusters[0][Clusters.Descriptor].serverList: + logger.info( + f"Network commissioning cluster {endpoint} is not enabled on this device.") + return + endpoints = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(Clusters.NetworkCommissioning.Attributes.FeatureMap)], returnClusterObject=True) + logger.info(endpoints) + for endpoint, obj in endpoints.items(): + clus = obj[Clusters.NetworkCommissioning] + if clus.featureMap == WIFI_NETWORK_FEATURE_MAP: + logger.info( + f"Endpoint {endpoint} is configured as WiFi network, run WiFi commissioning test.") + await self.test_negative(endpoint) + await self.test_wifi(endpoint) + elif clus.featureMap == THREAD_NETWORK_FEATURE_MAP: + logger.info( + f"Endpoint {endpoint} is configured as Thread network, run Thread commissioning test.") + await self.test_negative(endpoint) + await self.test_thread(endpoint) + else: + logger.info( + f"Skip endpoint {endpoint} with featureMap {clus.featureMap}") + async def run(self): try: - endpoints = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(Clusters.NetworkCommissioning.Attributes.FeatureMap)], returnClusterObject=True) - logger.info(endpoints) - for endpoint, obj in endpoints.items(): - clus = obj[Clusters.NetworkCommissioning] - if clus.featureMap == WIFI_NETWORK_FEATURE_MAP: - logger.info( - f"Endpoint {endpoint} is configured as WiFi network, run WiFi commissioning test.") - await self.test_negative(endpoint) - await self.test_wifi(endpoint) - elif clus.featureMap == THREAD_NETWORK_FEATURE_MAP: - logger.info( - f"Endpoint {endpoint} is configured as Thread network, run Thread commissioning test.") - await self.test_negative(endpoint) - await self.test_thread(endpoint) - else: - logger.info( - f"Skip endpoint {endpoint} with featureMap {clus.featureMap}") + await self.Test() + return True except Exception as ex: - logger.exception(ex) return False - return True diff --git a/src/test_driver/linux-cirque/MobileDeviceTest.py b/src/test_driver/linux-cirque/MobileDeviceTest.py index 20fb5022a9cb98..9af296978b760d 100755 --- a/src/test_driver/linux-cirque/MobileDeviceTest.py +++ b/src/test_driver/linux-cirque/MobileDeviceTest.py @@ -93,8 +93,7 @@ def run_controller_test(self): command = "gdb -return-child-result -q -ex run -ex bt --args python3 {} -t 150 -a {}".format( os.path.join( - CHIP_REPO, "src/controller/python/test/test_scripts/mobile-device-test.py"), - ethernet_ip) + CHIP_REPO, "src/controller/python/test/test_scripts/mobile-device-test.py"), ethernet_ip) ret = self.execute_device_cmd(req_device_id, command) self.assertEqual(ret['return_code'], '0', From f68cca0b30a79ee55f24033b6a368dab74884642 Mon Sep 17 00:00:00 2001 From: Martin Turon Date: Thu, 17 Mar 2022 22:37:52 -0700 Subject: [PATCH 15/15] [msg] Fix #13669 - Skip over MX and SX extension blocks. (#16324) * [msg] Fix #13669 - Skip over MX and SX extension blocks. * [msg] Add MX flag parsing unit test. * [msg] Add SX flag parsing unit tests. * [restyle] * Remove redundant check. * [style] Use constexpr instead of #define. --- src/transport/raw/MessageHeader.cpp | 22 ++- src/transport/raw/MessageHeader.h | 3 + src/transport/raw/tests/TestMessageHeader.cpp | 141 +++++++++++++++++- 3 files changed, 160 insertions(+), 6 deletions(-) diff --git a/src/transport/raw/MessageHeader.cpp b/src/transport/raw/MessageHeader.cpp index 77474cf9941c01..1b8ef89680d75f 100644 --- a/src/transport/raw/MessageHeader.cpp +++ b/src/transport/raw/MessageHeader.cpp @@ -202,8 +202,17 @@ CHIP_ERROR PacketHeader::Decode(const uint8_t * const data, uint16_t size, uint1 mDestinationGroupId.ClearValue(); } + if (mSecFlags.Has(Header::SecFlagValues::kMsgExtensionFlag)) + { + // If present, skip over Message Extension block. + // Spec 4.4.1.8. Message Extensions (variable) + uint16_t mxLength; + SuccessOrExit(err = reader.Read16(&mxLength).StatusCode()); + VerifyOrExit(mxLength <= reader.Remaining(), err = CHIP_ERROR_INTERNAL); + reader.Skip(mxLength); + } + octets_read = static_cast(reader.OctetsRead()); - VerifyOrExit(octets_read == EncodeSizeBytes(), err = CHIP_ERROR_INTERNAL); *decode_len = octets_read; exit: @@ -258,8 +267,17 @@ CHIP_ERROR PayloadHeader::Decode(const uint8_t * const data, uint16_t size, uint mAckMessageCounter.ClearValue(); } + if (mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_SecuredExtension)) + { + // If present, skip over Secured Extension block. + // Spec 4.4.3.7. Secured Extensions (variable) + uint16_t sxLength; + SuccessOrExit(err = reader.Read16(&sxLength).StatusCode()); + VerifyOrExit(sxLength <= reader.Remaining(), err = CHIP_ERROR_INTERNAL); + reader.Skip(sxLength); + } + octets_read = static_cast(reader.OctetsRead()); - VerifyOrExit(octets_read == EncodeSizeBytes(), err = CHIP_ERROR_INTERNAL); *decode_len = octets_read; exit: diff --git a/src/transport/raw/MessageHeader.h b/src/transport/raw/MessageHeader.h index 60255f78d19629..f253aa4f928751 100644 --- a/src/transport/raw/MessageHeader.h +++ b/src/transport/raw/MessageHeader.h @@ -71,6 +71,9 @@ enum class ExFlagValues : uint8_t /// Set when current message is requesting an acknowledgment from the recipient. kExchangeFlag_NeedsAck = 0x04, + /// Secured Extension block is present. + kExchangeFlag_SecuredExtension = 0x08, + /// Set when a vendor id is prepended to the Message Protocol Id field. kExchangeFlag_VendorIdPresent = 0x10, }; diff --git a/src/transport/raw/tests/TestMessageHeader.cpp b/src/transport/raw/tests/TestMessageHeader.cpp index f335b61e45911b..ff50e104f7579f 100644 --- a/src/transport/raw/tests/TestMessageHeader.cpp +++ b/src/transport/raw/tests/TestMessageHeader.cpp @@ -22,6 +22,8 @@ * the Message Header class within the transport layer * */ + +#include #include #include #include @@ -304,9 +306,21 @@ void TestPayloadHeaderEncodeDecodeBounds(nlTestSuite * inSuite, void * inContext } } +constexpr size_t HDR_LEN = 8; ///< Message header length +constexpr size_t SRC_LEN = 8; ///< Source Node ID length +constexpr size_t DST_LEN = 8; ///< Destination Node ID length +constexpr size_t GID_LEN = 2; ///< Group ID length +constexpr size_t MX_LEN = 6; ///< Message Exchange block length +constexpr size_t SX_LEN = 6; ///< Security Exchange block length +constexpr size_t PRO_LEN = 6; ///< Protocol header length +constexpr size_t APP_LEN = 2; ///< App payload length + +/// Size of fixed portion of message header + max source node id + max destination node id. +constexpr size_t MAX_FIXED_HEADER_SIZE = (HDR_LEN + SRC_LEN + DST_LEN); + struct SpecComplianceTestVector { - uint8_t encoded[8 + 8 + 8]; // Fixed header + max source id + max dest id + uint8_t encoded[MAX_FIXED_HEADER_SIZE]; // Fixed header + max source id + max dest id uint8_t messageFlags; uint16_t sessionId; uint8_t sessionType; @@ -363,12 +377,10 @@ struct SpecComplianceTestVector theSpecComplianceTestVector[] = { const unsigned theSpecComplianceTestVectorLength = sizeof(theSpecComplianceTestVector) / sizeof(struct SpecComplianceTestVector); -#define MAX_HEADER_SIZE (8 + 8 + 8) - void TestSpecComplianceEncode(nlTestSuite * inSuite, void * inContext) { struct SpecComplianceTestVector * testEntry; - uint8_t buffer[MAX_HEADER_SIZE]; + uint8_t buffer[MAX_FIXED_HEADER_SIZE]; uint16_t encodeSize; for (unsigned i = 0; i < theSpecComplianceTestVectorLength; i++) @@ -412,6 +424,126 @@ void TestSpecComplianceDecode(nlTestSuite * inSuite, void * inContext) } } +struct TestVectorMsgExtensions +{ + uint8_t payloadOffset; + uint8_t appPayloadOffset; + uint16_t msgLength; + const char * msg; +}; + +struct TestVectorMsgExtensions theTestVectorMsgExtensions[] = { + { + // SRC=none, DST=none, MX=0, SX=0 + .payloadOffset = HDR_LEN, + .appPayloadOffset = PRO_LEN, + .msgLength = HDR_LEN + PRO_LEN + APP_LEN, + .msg = "\x00\x00\x00\x00\xCC\xCC\xCC\xCC" + "\x01\xCC\xEE\xEE\x66\x66\xBB\xBB", + }, + // ================== Test MX ================== + { + // SRC=none, DST=none, MX=1, SX=0 + .payloadOffset = HDR_LEN + MX_LEN, + .appPayloadOffset = PRO_LEN, + .msgLength = HDR_LEN + MX_LEN + PRO_LEN + APP_LEN, + .msg = "\x00\x00\x00\x20\xCC\xCC\xCC\xCC\x04\x00\xE4\xE3\xE2\xE1" + "\x01\xCC\xEE\xEE\x66\x66\xBB\xBB", + }, + { + // SRC=1, DST=none, MX=1, SX=0 + .payloadOffset = HDR_LEN + MX_LEN + SRC_LEN, + .appPayloadOffset = PRO_LEN, + .msgLength = HDR_LEN + MX_LEN + SRC_LEN + PRO_LEN + APP_LEN, + .msg = "\x04\x00\x00\x20\xCC\xCC\xCC\xCC\x11\x11\x11\x11\x11\x11\x11\x11\x04\x00\xE4\xE3\xE2\xE1" + "\x01\xCC\xEE\xEE\x66\x66\xBB\xBB", + }, + { + // SRC=none, DST=1, MX=1, SX=0 + .payloadOffset = HDR_LEN + MX_LEN + DST_LEN, + .appPayloadOffset = PRO_LEN, + .msgLength = HDR_LEN + MX_LEN + DST_LEN + PRO_LEN + APP_LEN, + .msg = "\x01\x00\x00\x20\xCC\xCC\xCC\xCC\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\x04\x00\xE4\xE3\xE2\xE1" + "\x01\xCC\xEE\xEE\x66\x66\xBB\xBB", + }, + { + // SRC=1, DST=1, MX=1, SX=0 + .payloadOffset = HDR_LEN + MX_LEN + SRC_LEN + DST_LEN, + .appPayloadOffset = PRO_LEN, + .msgLength = HDR_LEN + MX_LEN + SRC_LEN + DST_LEN + PRO_LEN + APP_LEN, + .msg = "\x05\x00\x00\x20\xCC\xCC\xCC\xCC\x11\x11\x11\x11\x11\x11\x11\x11\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\x04\x00\xE4\xE3" + "\xE2\xE1" + "\x01\xCC\xEE\xEE\x66\x66\xBB\xBB", + }, + { + // SRC=none, DST=group, MX=1, SX=0 + .payloadOffset = HDR_LEN + MX_LEN + GID_LEN, + .appPayloadOffset = PRO_LEN, + .msgLength = HDR_LEN + MX_LEN + GID_LEN + PRO_LEN + APP_LEN, + .msg = "\x02\x00\x00\x21\xCC\xCC\xCC\xCC\xDD\xDD\x04\x00\xE4\xE3\xE2\xE1" + "\x01\xCC\xEE\xEE\x66\x66\xBB\xBB", + }, + { + // SRC=1, DST=group, MX=1, SX=0 + .payloadOffset = HDR_LEN + MX_LEN + SRC_LEN + GID_LEN, + .appPayloadOffset = PRO_LEN, + .msgLength = HDR_LEN + MX_LEN + SRC_LEN + GID_LEN + PRO_LEN + APP_LEN, + .msg = "\x06\x00\x00\x21\xCC\xCC\xCC\xCC\x11\x11\x11\x11\x11\x11\x11\x11\xDD\xDD\x04\x00\xE4\xE3\xE2\xE1" + "\x01\xCC\xEE\xEE\x66\x66\xBB\xBB", + }, + // ================== Test SX ================== + { + // SRC=none, DST=none, MX=0, SX=1 + .payloadOffset = HDR_LEN, + .appPayloadOffset = PRO_LEN + SX_LEN, + .msgLength = HDR_LEN + PRO_LEN + SX_LEN + APP_LEN, + .msg = "\x00\x00\x00\x00\xCC\xCC\xCC\xCC" + "\x08\xCC\xEE\xEE\x66\x66\x04\x00\xE4\xE3\xE2\xE1\xBB\xBB", + }, + { + // SRC=none, DST=none, MX=1, SX=1 + .payloadOffset = HDR_LEN + MX_LEN, + .appPayloadOffset = PRO_LEN + SX_LEN, + .msgLength = HDR_LEN + MX_LEN + PRO_LEN + SX_LEN + APP_LEN, + .msg = "\x00\x00\x00\x20\xCC\xCC\xCC\xCC\x04\x00\xE4\xE3\xE2\xE1" + "\x08\xCC\xEE\xEE\x66\x66\x04\x00\xE4\xE3\xE2\xE1\xBB\xBB", + }, + { + // SRC=1, DST=1, MX=1, SX=1 + .payloadOffset = HDR_LEN + MX_LEN + SRC_LEN + DST_LEN, + .appPayloadOffset = PRO_LEN + SX_LEN, + .msgLength = HDR_LEN + MX_LEN + SRC_LEN + DST_LEN + PRO_LEN + SX_LEN + APP_LEN, + .msg = "\x05\x00\x00\x20\xCC\xCC\xCC\xCC\x11\x11\x11\x11\x11\x11\x11\x11\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\x04\x00\xE4\xE3" + "\xE2\xE1" + "\x09\xCC\xEE\xEE\x66\x66\x04\x00\xE4\xE3\xE2\xE1\xBB\xBB", + }, +}; + +const unsigned theTestVectorMsgExtensionsLength = sizeof(theTestVectorMsgExtensions) / sizeof(struct TestVectorMsgExtensions); + +void TestMsgExtensionsDecode(nlTestSuite * inSuite, void * inContext) +{ + struct TestVectorMsgExtensions * testEntry; + PacketHeader packetHeader; + PayloadHeader payloadHeader; + uint16_t decodeSize; + + NL_TEST_ASSERT(inSuite, chip::Platform::MemoryInit() == CHIP_NO_ERROR); + + for (unsigned i = 0; i < theTestVectorMsgExtensionsLength; i++) + { + testEntry = &theTestVectorMsgExtensions[i]; + + System::PacketBufferHandle msg = System::PacketBufferHandle::NewWithData(testEntry->msg, testEntry->msgLength); + + NL_TEST_ASSERT(inSuite, packetHeader.Decode(msg->Start(), msg->DataLength(), &decodeSize) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, decodeSize == testEntry->payloadOffset); + + NL_TEST_ASSERT(inSuite, payloadHeader.Decode(msg->Start() + decodeSize, msg->DataLength(), &decodeSize) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, decodeSize == testEntry->appPayloadOffset); + } +} + } // namespace // clang-format off @@ -425,6 +557,7 @@ static const nlTest sTests[] = NL_TEST_DEF("PayloadEncodeDecodeBounds", TestPayloadHeaderEncodeDecodeBounds), NL_TEST_DEF("SpecComplianceEncode", TestSpecComplianceEncode), NL_TEST_DEF("SpecComplianceDecode", TestSpecComplianceDecode), + NL_TEST_DEF("TestMsgExtensionsDecode", TestMsgExtensionsDecode), NL_TEST_SENTINEL() }; // clang-format on