diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index 9e778041994626..95f884253404b4 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -1,14 +1,13 @@ + 14 15 16 17 -ContentApp's 18 19 20 21 22 - AAAA aabbccddeeff aarch @@ -25,9 +24,9 @@ ACL AdapterAddress AdapterName adb -addr AddOrUpdateThreadNetwork AddOrUpdateWiFiNetwork +addr adk adoc AdvAutonomous @@ -216,11 +215,13 @@ ConnectionData ConnectIP ConnectivityManager ConnectivityManagerImpl +ConnectNetwork connstring conntype const ContentApp ContentAppPlatform +ContentApp's ContentLaunch ContentLauncher contrib @@ -353,7 +354,6 @@ elftools elock emberAfExternalAttributeReadCallback emberAfExternalAttributeWriteCallback -ConnectNetwork EnableWiFiNetwork EndpointId endpointName @@ -382,6 +382,7 @@ ExtendedPAN extern extpanid FabricId +fabricIdx factoryreset fb fbb @@ -748,6 +749,8 @@ pcaps PDFs PDK peerAddrStr +peerNodeId +peerSessionId pem percentageLiftValue pexpect @@ -1003,8 +1006,9 @@ ttyUSB TXD txt UART -UDC udc +UDC +udcport udhcpc UDP UDPEndPoint diff --git a/examples/shell/README.md b/examples/shell/README.md index f94f60215b310b..4b76af87e5d89c 100644 --- a/examples/shell/README.md +++ b/examples/shell/README.md @@ -36,6 +36,7 @@ Done - [otcli](README_OTCLI.md) - [ping](#ping) - [rand](#rand) +- [server](README_SERVER.md) - [version](#version) ## Matter Shell Command Details diff --git a/examples/shell/README_SERVER.md b/examples/shell/README_SERVER.md new file mode 100644 index 00000000000000..4b1133ea1cf6af --- /dev/null +++ b/examples/shell/README_SERVER.md @@ -0,0 +1,206 @@ +# Matter Shell - App Server module + +The all-clusters-app server may be invoked and managed via the Matter Shell CLI. + +## Command List + +- [help](#help) +- [clusters](#clusters) +- [endpoints](#endpoints) +- [exchanges](#exchanges) +- [port](#port) +- [sessions](#sessions) +- [start](#start) +- [stop](#stop) +- [udcport](#udcport) + +## Command Details + +### help + +List the Server CLI commands. + +```bash +> server help + help Usage: server + start Start the ZCL application server. + stop Stop the ZCL application server. + port Get/Set operational port of server. + udcport Get/Set commissioning port of server. + sessions Manage active sessions on the server. + exchanges Manage active exchanges on the server. + endpoints Display endpoints on the server. + clusters Display clusters on the server. +Done +``` + +### clusters + +Displays all clusters in endpoint hierarchy. + +```bash +> server clusters +Endpoint 0: + - Cluster 0x0003 + - Cluster 0x0004 + - Cluster 0x001D + - Cluster 0x001E + - Cluster 0x001F + - Cluster 0x0028 + - Cluster 0x0029 + - Cluster 0x002A + - Cluster 0x002E + - Cluster 0x0030 + - Cluster 0x0031 + - Cluster 0x0032 + - Cluster 0x0033 + - Cluster 0x0034 + - Cluster 0x0035 + - Cluster 0x0036 + - Cluster 0x0037 + - Cluster 0x003C + - Cluster 0x003E + - Cluster 0x003F + - Cluster 0x0040 + - Cluster 0x0041 + - Cluster 0x0405 +Endpoint 1: + - Cluster 0x0003 + - Cluster 0x0004 + - Cluster 0x0005 + - Cluster 0x0006 + - Cluster 0x0007 + - Cluster 0x0008 + - Cluster 0x000F + - Cluster 0x001D + - Cluster 0x001E + - Cluster 0x0025 + - Cluster 0x002F + - Cluster 0x0039 + - Cluster 0x003B + - Cluster 0x0040 + - Cluster 0x0041 + - Cluster 0x0045 + - Cluster 0x0050 + - Cluster 0x0101 + - Cluster 0x0102 + - Cluster 0x0103 + - Cluster 0x0200 + - Cluster 0x0201 + - Cluster 0x0204 + - Cluster 0x0300 + - Cluster 0x0400 + - Cluster 0x0402 + - Cluster 0x0403 + - Cluster 0x0404 + - Cluster 0x0405 + - Cluster 0x0406 + - Cluster 0x0500 + - Cluster 0x0503 + - Cluster 0x0504 + - Cluster 0x0505 + - Cluster 0x0506 + - Cluster 0x0507 + - Cluster 0x0508 + - Cluster 0x0509 + - Cluster 0x050A + - Cluster 0x050B + - Cluster 0x050C + - Cluster 0x050D + - Cluster 0x050E + - Cluster 0x050F + - Cluster 0x0B04 +Endpoint 2: + - Cluster 0x0004 + - Cluster 0x0006 + - Cluster 0x001D + - Cluster 0x0406 +Done +``` + +### endpoints + +Displays all endpoints in device hierarchy. + +```bash +> server endpoints +Endpoint 0 +Endpoint 1 +Endpoint 2 +Done +``` + +### port + +Display the current operational port for the server node. + +```bash +> server port +5540 +Done +``` + +### port \ + +Sets the operational port to the given value. NOTE: server must be restarted to +take effect. + +- udp_port: new value to set operational port to + +```bash +> server port 5541 +Done +``` + +### sessions + +Displays active session handles. + +```bash +> server sessions +session id=0x0002 peerSessionId=0x0012 peerNodeId=0x000000000001b669 fabricIdx=1 +Done +``` + +### start + +Start the App Server on the Node. This also starts the commissioning window as +is done with the all-clusters-app. + +```bash +> server start +... +[1639549415.105682][1468836:1468841] CHIP:SVR: Server Listening... +Done +``` + +### stop + +Stops the App Server, closes all related sockets, and frees resources. + +```bash +> server stop +Done +``` + +### udcport + +Display the current commissioning port for the server node. + +```bash +> server udcport +5550 +Done +``` + +### udcport \ + +Sets the commissioning port to the given value. NOTE: server must be restarted +to take effect. + +- udp_port: new value to set commissioning port to + +```bash +> server udcport 5551 +Done +``` diff --git a/examples/shell/shell_common/BUILD.gn b/examples/shell/shell_common/BUILD.gn index c0b372eb87d1cb..484c3dbbbde058 100644 --- a/examples/shell/shell_common/BUILD.gn +++ b/examples/shell/shell_common/BUILD.gn @@ -17,6 +17,11 @@ import("//build_overrides/openthread.gni") import("${chip_root}/src/platform/device.gni") +declare_args() { + # Enable server command only on linux for now. + chip_shell_cmd_server = current_os == "linux" || current_os == "mac" +} + config("shell_common_config") { include_dirs = [ ".", @@ -27,6 +32,7 @@ config("shell_common_config") { defines = [ "ENABLE_CHIP_SHELL", "OPENTHREAD_CONFIG_CLI_TRANSPORT=OT_CLI_TRANSPORT_CONSOLE", + "CHIP_SHELL_ENABLE_CMD_SERVER=${chip_shell_cmd_server}", ] } @@ -61,5 +67,22 @@ static_library("shell_common") { } } + if (chip_shell_cmd_server) { + sources += [ "cmd_server.cpp" ] + + import("${chip_root}/src/app/chip_data_model.gni") + + sources += [ + "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", + "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", + ] + + include_dirs = + [ "${chip_root}/examples/all-clusters-app/all-clusters-common/include" ] + + public_deps += + [ "${chip_root}/examples/all-clusters-app/all-clusters-common" ] + } + public_configs = [ ":shell_common_config" ] } diff --git a/examples/shell/shell_common/cmd_server.cpp b/examples/shell/shell_common/cmd_server.cpp new file mode 100644 index 00000000000000..8f37bc9a385c7e --- /dev/null +++ b/examples/shell/shell_common/cmd_server.cpp @@ -0,0 +1,200 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace chip; +using namespace chip::Shell; +using namespace chip::Credentials; +using namespace chip::ArgParser; + +bool lowPowerClusterSleep() +{ + return true; +} + +static chip::Shell::Engine sShellServerSubcommands; +static uint16_t sServerPortOperational = CHIP_PORT; +static uint16_t sServerPortCommissioning = CHIP_UDC_PORT; + +static CHIP_ERROR CmdAppServerHelp(int argc, char ** argv) +{ + sShellServerSubcommands.ForEachCommand(PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +static CHIP_ERROR CmdAppServerStart(int argc, char ** argv) +{ + // Init ZCL Data Model and CHIP App Server + chip::Server::GetInstance().Init(nullptr, sServerPortOperational, sServerPortCommissioning); + + // Initialize device attestation config + SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider()); + + return CHIP_NO_ERROR; +} + +static CHIP_ERROR CmdAppServerStop(int argc, char ** argv) +{ + chip::Server::GetInstance().Shutdown(); + return CHIP_NO_ERROR; +} + +static CHIP_ERROR CmdAppServerPort(int argc, char ** argv) +{ + if (argc == 0) + { + streamer_printf(streamer_get(), "%d\r\n", sServerPortOperational); + } + else + { + bool success = ParseInt(argv[0], sServerPortOperational); + if (!success) + return CHIP_ERROR_INVALID_ARGUMENT; + } + + return CHIP_NO_ERROR; +} + +static CHIP_ERROR CmdAppServerUdcPort(int argc, char ** argv) +{ + if (argc == 0) + { + streamer_printf(streamer_get(), "%d\r\n", sServerPortCommissioning); + } + else + { + bool success = ParseInt(argv[0], sServerPortCommissioning); + if (!success) + return CHIP_ERROR_INVALID_ARGUMENT; + } + + return CHIP_NO_ERROR; +} + +static bool PrintServerSession(void * context, SessionHandle & session) +{ + streamer_printf(streamer_get(), "session id=0x%04x peerSessionId=0x%04x peerNodeId=0x%016" PRIx64 " fabricIdx=%d\r\n", + session.GetLocalSessionId().Value(), session.GetPeerSessionId().Value(), session.GetPeerNodeId(), + session.GetFabricIndex()); + return true; +} + +static CHIP_ERROR CmdAppServerSessions(int argc, char ** argv) +{ + Server::GetInstance().GetSecureSessionManager().ForEachSessionHandle(nullptr, PrintServerSession); + + return CHIP_NO_ERROR; +} + +static CHIP_ERROR CmdAppServerExchanges(int argc, char ** argv) +{ + // Messaging::ExchangeManager * exchangeMgr = &Server::GetInstance().GetExchangeManager(); + + return CHIP_NO_ERROR; +} + +static CHIP_ERROR CmdAppServerClusters(int argc, char ** argv) +{ + bool server = true; + + for (int i = 0; i < emberAfEndpointCount(); i++) + { + EndpointId endpoint = emberAfEndpointFromIndex(i); + uint16_t clusterCount = emberAfClusterCount(endpoint, server); + + streamer_printf(streamer_get(), "Endpoint %d:\r\n", endpoint); + + for (uint8_t clusterIndex = 0; clusterIndex < clusterCount; clusterIndex++) + { + EmberAfCluster * cluster = emberAfGetNthCluster(endpoint, clusterIndex, server); + streamer_printf(streamer_get(), " - Cluster 0x%04X\r\n", cluster->clusterId); + } + } + + return CHIP_NO_ERROR; +} + +static CHIP_ERROR CmdAppServerEndpoints(int argc, char ** argv) +{ + for (int i = 0; i < emberAfEndpointCount(); i++) + { + EndpointId endpoint = emberAfEndpointFromIndex(i); + + streamer_printf(streamer_get(), "Endpoint %d\r\n", endpoint); + } + + return CHIP_NO_ERROR; +} + +static CHIP_ERROR CmdAppServer(int argc, char ** argv) +{ + switch (argc) + { + case 0: + return CmdAppServerHelp(argc, argv); + case 1: + if ((strcmp(argv[0], "help") == 0) || (strcmp(argv[0], "-h") == 0)) + { + return CmdAppServerHelp(argc, argv); + } + } + return sShellServerSubcommands.ExecCommand(argc, argv); +} + +static void CmdAppServerAtExit() +{ + CmdAppServerStop(0, nullptr); +} + +void cmd_app_server_init() +{ + static const shell_command_t sServerComand = { &CmdAppServer, "server", + "Manage the ZCL application server. Usage: server [help|start|stop]" }; + + static const shell_command_t sServerSubCommands[] = { + { &CmdAppServerHelp, "help", "Usage: server " }, + { &CmdAppServerStart, "start", "Start the ZCL application server." }, + { &CmdAppServerStop, "stop", "Stop the ZCL application server." }, + { &CmdAppServerPort, "port", "Get/Set operational port of server." }, + { &CmdAppServerUdcPort, "udcport", "Get/Set commissioning port of server." }, + { &CmdAppServerSessions, "sessions", "Manage active sessions on the server." }, + { &CmdAppServerExchanges, "exchanges", "Manage active exchanges on the server." }, + { &CmdAppServerClusters, "clusters", "Display clusters on the server." }, + { &CmdAppServerEndpoints, "endpoints", "Display endpoints on the server." }, + }; + + std::atexit(CmdAppServerAtExit); + + // Register `config` subcommands with the local shell dispatcher. + sShellServerSubcommands.RegisterCommands(sServerSubCommands, ArraySize(sServerSubCommands)); + + // Register the root `config` command with the top-level shell. + Engine::Root().RegisterCommands(&sServerComand, 1); +} diff --git a/examples/shell/shell_common/include/ChipShellCollection.h b/examples/shell/shell_common/include/ChipShellCollection.h index ba54bad94391af..60161cbafd9c1b 100644 --- a/examples/shell/shell_common/include/ChipShellCollection.h +++ b/examples/shell/shell_common/include/ChipShellCollection.h @@ -17,10 +17,9 @@ #pragma once -extern "C" { // A list of shell commands provided by ChipShell void cmd_misc_init(void); void cmd_otcli_init(void); void cmd_ping_init(void); void cmd_send_init(void); -} +void cmd_app_server_init(void); diff --git a/examples/shell/standalone/main.cpp b/examples/shell/standalone/main.cpp index 77d880471d7600..363f18caa8aaec 100644 --- a/examples/shell/standalone/main.cpp +++ b/examples/shell/standalone/main.cpp @@ -51,6 +51,9 @@ int main() cmd_otcli_init(); cmd_ping_init(); cmd_send_init(); +#if CHIP_SHELL_ENABLE_CMD_SERVER + cmd_app_server_init(); +#endif Engine::Root().RunMainLoop(); return 0; diff --git a/src/app/clusters/basic/basic.cpp b/src/app/clusters/basic/basic.cpp index 88dcadf7de97a1..900b358287c8c3 100644 --- a/src/app/clusters/basic/basic.cpp +++ b/src/app/clusters/basic/basic.cpp @@ -180,7 +180,7 @@ void emberAfBasicClusterServerInitCallback(chip::EndpointId endpoint) uint8_t manufacturingDayOfMonth; if (ConfigurationMgr().GetManufacturingDate(manufacturingYear, manufacturingMonth, manufacturingDayOfMonth) == CHIP_NO_ERROR) { - snprintf(manufacturingDateString, sizeof(manufacturingDateString), "%04" PRIu16 "-%02" PRIu16 "-%02" PRIu16, + snprintf(manufacturingDateString, sizeof(manufacturingDateString), "%04" PRIu16 "-%02" PRIu8 "-%02" PRIu8, manufacturingYear, manufacturingMonth, manufacturingDayOfMonth); status = Attributes::ManufacturingDate::Set(endpoint, CharSpan(manufacturingDateString, strlen(manufacturingDateString))); VerifyOrdo(EMBER_ZCL_STATUS_SUCCESS == status, diff --git a/src/app/clusters/ota-provider/ota-provider.cpp b/src/app/clusters/ota-provider/ota-provider.cpp index bff08e61551145..e01cd9edebfd7c 100644 --- a/src/app/clusters/ota-provider/ota-provider.cpp +++ b/src/app/clusters/ota-provider/ota-provider.cpp @@ -174,6 +174,10 @@ bool emberAfOtaSoftwareUpdateProviderClusterQueryImageCallback(app::CommandHandl auto & requestorCanConsent = commandData.requestorCanConsent; auto & metadataForProvider = commandData.metadataForProvider; + (void) vendorId; + (void) productId; + (void) softwareVersion; + EndpointId endpoint = commandPath.mEndpointId; EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 48067d02b4d85d..ffd15910992f68 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -226,7 +226,8 @@ CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint &mSessions, &mFabrics, &mSessionIDAllocator); SuccessOrExit(err); - err = mCASESessionManager.Init(); + err = mCASESessionManager.Init(); + mState = ServerState::Enabled; exit: if (err != CHIP_NO_ERROR) @@ -242,6 +243,9 @@ CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint void Server::Shutdown() { + if (mState == ServerState::Disabled) + return; + chip::Dnssd::ServiceAdvertiser::Instance().Shutdown(); chip::app::InteractionModelEngine::GetInstance()->Shutdown(); mExchangeMgr.Shutdown(); @@ -249,6 +253,8 @@ void Server::Shutdown() mTransports.Close(); mCommissioningWindowManager.Shutdown(); chip::Platform::MemoryShutdown(); + + mState = ServerState::Disabled; } #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT diff --git a/src/app/server/Server.h b/src/app/server/Server.h index 06590b73b116f7..ed54e148babb9b 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -130,6 +130,14 @@ class Server CHIP_ERROR SyncDelete(FabricIndex fabricIndex, const char * key) override { return SyncDeleteKeyValue(key); }; }; + enum class ServerState + { + Disabled, ///< The Server is inactive and disabled. + Enabled, ///< The Server is active and enabled. + }; + + ServerState mState = ServerState::Disabled; + #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * mBleLayer = nullptr; #endif diff --git a/src/lib/shell/commands/Meta.cpp b/src/lib/shell/commands/Meta.cpp index dfe49415ac263d..67490cd22be64c 100644 --- a/src/lib/shell/commands/Meta.cpp +++ b/src/lib/shell/commands/Meta.cpp @@ -32,6 +32,7 @@ #include #include #include +#include namespace chip { namespace Shell { @@ -39,6 +40,7 @@ namespace Shell { static CHIP_ERROR ExitHandler(int argc, char ** argv) { streamer_printf(streamer_get(), "Goodbye\r\n"); + chip::DeviceLayer::PlatformMgr().Shutdown(); exit(0); return CHIP_NO_ERROR; } diff --git a/src/transport/SessionManager.cpp b/src/transport/SessionManager.cpp index cee779e8c09860..21b627c325d921 100644 --- a/src/transport/SessionManager.cpp +++ b/src/transport/SessionManager.cpp @@ -662,4 +662,18 @@ SessionHandle SessionManager::FindSecureSessionForNode(NodeId peerNodeId) return SessionHandle(found->GetPeerNodeId(), found->GetLocalSessionId(), found->GetPeerSessionId(), found->GetFabricIndex()); } +/** + * Provides a means to get diagnostic information such as number of sessions. + */ +[[maybe_unused]] CHIP_ERROR SessionManager::ForEachSessionHandle(void * context, SessionHandleCallback lambda) +{ + mSecureSessions.ForEachSession([&](auto session) { + SessionHandle handle(session->GetPeerNodeId(), session->GetLocalSessionId(), session->GetPeerSessionId(), + session->GetFabricIndex()); + lambda(context, handle); + return Loop::Continue; + }); + return CHIP_NO_ERROR; +} + } // namespace chip diff --git a/src/transport/SessionManager.h b/src/transport/SessionManager.h index 2d5b48dd57ec79..dbdf0a187b3ed0 100644 --- a/src/transport/SessionManager.h +++ b/src/transport/SessionManager.h @@ -246,6 +246,9 @@ class DLL_EXPORT SessionManager : public TransportMgrDelegate // TODO: this is a temporary solution for legacy tests which use nodeId to send packets SessionHandle FindSecureSessionForNode(NodeId peerNodeId); + using SessionHandleCallback = bool (*)(void * context, SessionHandle & sessionHandle); + CHIP_ERROR ForEachSessionHandle(void * context, SessionHandleCallback callback); + private: /** * The State of a secure transport object.