From 17092046eaddcc596c2e94a98b4538f914324ed7 Mon Sep 17 00:00:00 2001 From: Martin Turon Date: Thu, 6 Jan 2022 13:41:41 -0800 Subject: [PATCH] [shell] Add 'server' command to shell app. (#13060) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [shell] Add command to start/stop zcl app server. - Add 'server port' and 'server udcport' commands. - Add 'server sessions' command. - Add 'server endpoints' and 'server clusters' commands. - Add docs for the new 'server' command subcommands (README_SERVER.md). - Add 'server' command to build of linux and mac platforms only initially. - Improve clean exit paths for 'server' command. - Update 'ForEachSessionHandle' to use new Loop construct. - Fix build failure in ota-provider (warning when logs disabled). * [shell] Correct order of atexit and shutdown handling. * [shell] Add OTA stubs. * Apply suggestions from code review Co-authored-by: Łukasz Duda * [session] Update ForEachSessionHandle to new API. Co-authored-by: Łukasz Duda --- .github/.wordlist.txt | 14 +- examples/platform/efr32/matter_shell.cpp | 2 +- examples/shell/README.md | 1 + examples/shell/README_SERVER.md | 206 ++++++++++++++++++ examples/shell/esp32/main/main.cpp | 4 + examples/shell/mbed/main/main.cpp | 2 +- examples/shell/shell_common/BUILD.gn | 24 ++ examples/shell/shell_common/cmd_server.cpp | 200 +++++++++++++++++ .../include/ChipShellCollection.h | 3 +- examples/shell/standalone/main.cpp | 7 +- src/app/clusters/basic/basic.cpp | 2 +- .../clusters/ota-provider/ota-provider.cpp | 4 + src/app/server/Server.cpp | 8 +- src/app/server/Server.h | 8 + src/lib/shell/Engine.cpp | 10 + src/lib/shell/Engine.h | 9 + src/lib/shell/MainLoopDefault.cpp | 1 - src/lib/shell/MainLoopEFR32.cpp | 1 - src/lib/shell/MainLoopESP32.cpp | 4 - src/lib/shell/commands/Meta.cpp | 8 + src/transport/SessionManager.cpp | 13 ++ src/transport/SessionManager.h | 3 + 22 files changed, 515 insertions(+), 19 deletions(-) create mode 100644 examples/shell/README_SERVER.md create mode 100644 examples/shell/shell_common/cmd_server.cpp diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index af8f1c262e655f..d7f33d37231f92 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 @@ -217,11 +216,13 @@ ConnectionData ConnectIP ConnectivityManager ConnectivityManagerImpl +ConnectNetwork connstring conntype const ContentApp ContentAppPlatform +ContentApp's ContentLaunch ContentLauncher contrib @@ -354,7 +355,6 @@ elftools elock emberAfExternalAttributeReadCallback emberAfExternalAttributeWriteCallback -ConnectNetwork EnableWiFiNetwork EndpointId endpointName @@ -383,6 +383,7 @@ ExtendedPAN extern extpanid FabricId +fabricIdx factoryreset fb fbb @@ -750,6 +751,8 @@ pcaps PDFs PDK peerAddrStr +peerNodeId +peerSessionId pem percentageLiftValue pexpect @@ -1006,8 +1009,9 @@ ttyUSB TXD txt UART -UDC udc +UDC +udcport udhcpc UDP UDPEndPoint diff --git a/examples/platform/efr32/matter_shell.cpp b/examples/platform/efr32/matter_shell.cpp index 50b5af84947a91..d398a41a0c7757 100644 --- a/examples/platform/efr32/matter_shell.cpp +++ b/examples/platform/efr32/matter_shell.cpp @@ -71,7 +71,7 @@ void WaitForShellActivity() void startShellTask() { - int status = chip::Shell::streamer_init(chip::Shell::streamer_get()); + int status = chip::Shell::Engine::Root().Init(); assert(status == 0); // For now also register commands from shell_common (shell app). 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/esp32/main/main.cpp b/examples/shell/esp32/main/main.cpp index 7f6879663c9080..1e990aad525e23 100644 --- a/examples/shell/esp32/main/main.cpp +++ b/examples/shell/esp32/main/main.cpp @@ -36,6 +36,10 @@ extern "C" void app_main(void) chip::Platform::MemoryInit(); chip::DeviceLayer::PlatformMgr().InitChipStack(); chip::DeviceLayer::PlatformMgr().StartEventLoopTask(); + + int ret = Engine::Root().Init(); + assert(ret == 0); + cmd_ping_init(); xTaskCreate(&chip_shell_task, "chip_shell", 2048, NULL, 5, NULL); } diff --git a/examples/shell/mbed/main/main.cpp b/examples/shell/mbed/main/main.cpp index 1ab85f2a196e7a..9d7d16c57184fb 100644 --- a/examples/shell/mbed/main/main.cpp +++ b/examples/shell/mbed/main/main.cpp @@ -84,7 +84,7 @@ int main() } // Initialize the default streamer that was linked. - ret = streamer_init(streamer_get()); + ret = Engine::Root().Init(); if (ret) { ChipLogError(Shell, "Streamer initialization failed [%d]", ret); diff --git a/examples/shell/shell_common/BUILD.gn b/examples/shell/shell_common/BUILD.gn index c0b372eb87d1cb..efd1a154fedabc 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,23 @@ 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/ota-requestor-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..c327aa5693d9ec --- /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 `server` subcommands with the local shell dispatcher. + sShellServerSubcommands.RegisterCommands(sServerSubCommands, ArraySize(sServerSubCommands)); + + // Register the root `server` 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..0335bbb6e497e0 100644 --- a/examples/shell/standalone/main.cpp +++ b/examples/shell/standalone/main.cpp @@ -38,8 +38,8 @@ int main() #if CHIP_DEVICE_CONFIG_ENABLE_WPA chip::DeviceLayer::ConnectivityManagerImpl().StartWiFiManagement(); #endif - // Initialize the default streamer that was linked. - const int rc = streamer_init(streamer_get()); + + const int rc = Engine::Root().Init(); if (rc != 0) { @@ -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 4ea8536fcb2589..b162bd5210fa8c 100644 --- a/src/app/clusters/basic/basic.cpp +++ b/src/app/clusters/basic/basic.cpp @@ -268,7 +268,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 b45b3cf4490110..bc5b364512fa7d 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 1364d11ecd956c..4852fe23f940b1 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -233,7 +233,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) @@ -249,6 +250,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(); @@ -256,6 +260,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 33c56610cded88..a0e694b2c9e73e 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -139,6 +139,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/Engine.cpp b/src/lib/shell/Engine.cpp index 5c7b10bf4364c0..10bb2dcfa6723a 100644 --- a/src/lib/shell/Engine.cpp +++ b/src/lib/shell/Engine.cpp @@ -44,6 +44,16 @@ namespace Shell { Engine Engine::theEngineRoot; +int Engine::Init() +{ + // Initialize the default streamer that was linked. + int error = streamer_init(streamer_get()); + + Engine::Root().RegisterDefaultCommands(); + + return error; +} + void Engine::ForEachCommand(shell_command_iterator_t * on_command, void * arg) { for (unsigned i = 0; i < _commandSetCount; i++) diff --git a/src/lib/shell/Engine.h b/src/lib/shell/Engine.h index 7c6238857f3f2a..be65ed45c94dc0 100644 --- a/src/lib/shell/Engine.h +++ b/src/lib/shell/Engine.h @@ -152,6 +152,15 @@ class Engine */ void RunMainLoop(); + /** + * Initialize the Shell::Engine. + * + * Activates the linked streamer, registers default commands, and sets up exit handlers. + * + * @return 0 for success, otherwise failed. + */ + int Init(); + private: static void ProcessShellLineTask(intptr_t context); }; diff --git a/src/lib/shell/MainLoopDefault.cpp b/src/lib/shell/MainLoopDefault.cpp index 34e393c1c741f0..f077a7cab3b8d6 100644 --- a/src/lib/shell/MainLoopDefault.cpp +++ b/src/lib/shell/MainLoopDefault.cpp @@ -181,7 +181,6 @@ namespace Shell { void Engine::RunMainLoop() { - Engine::Root().RegisterDefaultCommands(); streamer_printf(streamer_get(), CHIP_SHELL_PROMPT); while (true) diff --git a/src/lib/shell/MainLoopEFR32.cpp b/src/lib/shell/MainLoopEFR32.cpp index 32f4a1cc2012e4..3b1f298d5cfb55 100644 --- a/src/lib/shell/MainLoopEFR32.cpp +++ b/src/lib/shell/MainLoopEFR32.cpp @@ -185,7 +185,6 @@ namespace Shell { void Engine::RunMainLoop() { - Engine::Root().RegisterDefaultCommands(); streamer_printf(streamer_get(), kShellPrompt); while (true) diff --git a/src/lib/shell/MainLoopESP32.cpp b/src/lib/shell/MainLoopESP32.cpp index 8351c62721bc16..aecca35774a07e 100644 --- a/src/lib/shell/MainLoopESP32.cpp +++ b/src/lib/shell/MainLoopESP32.cpp @@ -70,10 +70,6 @@ namespace Shell { void Engine::RunMainLoop() { - int ret = chip::Shell::streamer_init(chip::Shell::streamer_get()); - assert(ret == 0); - - Engine::Root().RegisterDefaultCommands(); while (true) { const char * prompt = LOG_COLOR_I "> " LOG_RESET_COLOR; diff --git a/src/lib/shell/commands/Meta.cpp b/src/lib/shell/commands/Meta.cpp index dfe49415ac263d..7bf188de763e43 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 { @@ -43,6 +44,11 @@ static CHIP_ERROR ExitHandler(int argc, char ** argv) return CHIP_NO_ERROR; } +static void AtExitShell() +{ + chip::DeviceLayer::PlatformMgr().Shutdown(); +} + static CHIP_ERROR HelpHandler(int argc, char ** argv) { Engine::Root().ForEachCommand(PrintCommandHelp, nullptr); @@ -63,6 +69,8 @@ void RegisterMetaCommands() { &VersionHandler, "version", "Output the software version" }, }; + std::atexit(AtExitShell); + Engine::Root().RegisterCommands(sCmds, ArraySize(sCmds)); } diff --git a/src/transport/SessionManager.cpp b/src/transport/SessionManager.cpp index 0e6452efe755ff..872f9d0f3d5129 100644 --- a/src/transport/SessionManager.cpp +++ b/src/transport/SessionManager.cpp @@ -660,4 +660,17 @@ SessionHandle SessionManager::FindSecureSessionForNode(NodeId peerNodeId) return SessionHandle(*found); } +/** + * 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); + 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 70add956a8178f..c27b8e67b60f19 100644 --- a/src/transport/SessionManager.h +++ b/src/transport/SessionManager.h @@ -247,6 +247,9 @@ class DLL_EXPORT SessionManager : public TransportMgrDelegate // and tv-casting-app that uses the TV's node ID to find the associated secure session 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.