From 79085001ca4bb528b8969d9ad87f26793a17ee4d Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 8 May 2023 18:16:43 -0400 Subject: [PATCH] Improve session-management commands in chip-tool. (#26404) * Improve session-management commands in chip-tool. * Move them into a separate "sessionmanagement" bit, to make them more discoverable. * Add a command to expire the local CASE sessions for a given node id. * Rename close-session to send-close-session. * Add an option to control whether send-close-session also expires the local session (defaulting to true). * use all-lowercase for CASE Co-authored-by: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> --------- Co-authored-by: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> --- examples/chip-tool/BUILD.gn | 4 +- .../chip-tool/commands/pairing/Commands.h | 2 - .../CloseSessionCommand.cpp | 33 +++++++++---- .../CloseSessionCommand.h | 48 ++++++++++++++++--- .../commands/session-management/Commands.h | 34 +++++++++++++ examples/chip-tool/main.cpp | 2 + 6 files changed, 104 insertions(+), 19 deletions(-) rename examples/chip-tool/commands/{pairing => session-management}/CloseSessionCommand.cpp (72%) rename examples/chip-tool/commands/{pairing => session-management}/CloseSessionCommand.h (53%) create mode 100644 examples/chip-tool/commands/session-management/Commands.h diff --git a/examples/chip-tool/BUILD.gn b/examples/chip-tool/BUILD.gn index 85f1c56e2d8266..e1e92d94b62ec3 100644 --- a/examples/chip-tool/BUILD.gn +++ b/examples/chip-tool/BUILD.gn @@ -70,8 +70,6 @@ static_library("chip-tool-utils") { "commands/discover/DiscoverCommand.cpp", "commands/discover/DiscoverCommissionablesCommand.cpp", "commands/discover/DiscoverCommissionersCommand.cpp", - "commands/pairing/CloseSessionCommand.cpp", - "commands/pairing/CloseSessionCommand.h", "commands/pairing/OpenCommissioningWindowCommand.cpp", "commands/pairing/OpenCommissioningWindowCommand.h", "commands/pairing/PairingCommand.cpp", @@ -80,6 +78,8 @@ static_library("chip-tool-utils") { "commands/payload/SetupPayloadGenerateCommand.cpp", "commands/payload/SetupPayloadParseCommand.cpp", "commands/payload/SetupPayloadVerhoeff.cpp", + "commands/session-management/CloseSessionCommand.cpp", + "commands/session-management/CloseSessionCommand.h", "commands/storage/StorageManagementCommand.cpp", ] diff --git a/examples/chip-tool/commands/pairing/Commands.h b/examples/chip-tool/commands/pairing/Commands.h index 4f4f445d929a8c..213c9e3ceb58f5 100644 --- a/examples/chip-tool/commands/pairing/Commands.h +++ b/examples/chip-tool/commands/pairing/Commands.h @@ -19,7 +19,6 @@ #pragma once #include "commands/common/Commands.h" -#include "commands/pairing/CloseSessionCommand.h" #include "commands/pairing/GetCommissionerNodeIdCommand.h" #include "commands/pairing/GetCommissionerRootCertificateCommand.h" #include "commands/pairing/IssueNOCChainCommand.h" @@ -241,7 +240,6 @@ void registerCommandsPairing(Commands & commands, CredentialIssuerCommands * cre // make_unique(), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), - make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), diff --git a/examples/chip-tool/commands/pairing/CloseSessionCommand.cpp b/examples/chip-tool/commands/session-management/CloseSessionCommand.cpp similarity index 72% rename from examples/chip-tool/commands/pairing/CloseSessionCommand.cpp rename to examples/chip-tool/commands/session-management/CloseSessionCommand.cpp index 7f0a8bfef4d34a..ba38bca90d5dbb 100644 --- a/examples/chip-tool/commands/pairing/CloseSessionCommand.cpp +++ b/examples/chip-tool/commands/session-management/CloseSessionCommand.cpp @@ -23,20 +23,20 @@ using namespace chip; using namespace chip::Protocols; -CHIP_ERROR CloseSessionCommand::RunCommand() +CHIP_ERROR SendCloseSessionCommand::RunCommand() { CommissioneeDeviceProxy * commissioneeDeviceProxy = nullptr; - if (CHIP_NO_ERROR == CurrentCommissioner().GetDeviceBeingCommissioned(mDestinationId, &commissioneeDeviceProxy)) + if (CHIP_NO_ERROR == CurrentCommissioner().GetDeviceBeingCommissioned(mDestinationNodeId, &commissioneeDeviceProxy)) { VerifyOrReturnError(commissioneeDeviceProxy->GetSecureSession().HasValue(), CHIP_ERROR_INCORRECT_STATE); return CloseSession(*commissioneeDeviceProxy->GetExchangeManager(), commissioneeDeviceProxy->GetSecureSession().Value()); } - return CurrentCommissioner().GetConnectedDevice(mDestinationId, &mOnDeviceConnectedCallback, + return CurrentCommissioner().GetConnectedDevice(mDestinationNodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); } -CHIP_ERROR CloseSessionCommand::CloseSession(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +CHIP_ERROR SendCloseSessionCommand::CloseSession(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) { // TODO perhaps factor out this code into something on StatusReport that // takes an exchange and maybe a SendMessageFlags? @@ -60,6 +60,10 @@ CHIP_ERROR CloseSessionCommand::CloseSession(Messaging::ExchangeManager & exchan exchange->SendMessage(SecureChannel::MsgType::StatusReport, std::move(msg), Messaging::SendMessageFlags::kNoAutoRequestAck); if (err == CHIP_NO_ERROR) { + if (mEvictLocalSession.ValueOr(true)) + { + sessionHandle->AsSecureSession()->MarkForEviction(); + } SetCommandExitStatus(CHIP_NO_ERROR); } else @@ -70,21 +74,32 @@ CHIP_ERROR CloseSessionCommand::CloseSession(Messaging::ExchangeManager & exchan return err; } -void CloseSessionCommand::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, - const SessionHandle & sessionHandle) +void SendCloseSessionCommand::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, + const SessionHandle & sessionHandle) { - auto * command = reinterpret_cast(context); + auto * command = reinterpret_cast(context); VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "OnDeviceConnectedFn: context is null")); CHIP_ERROR err = command->CloseSession(exchangeMgr, sessionHandle); VerifyOrReturn(CHIP_NO_ERROR == err, command->SetCommandExitStatus(err)); } -void CloseSessionCommand::OnDeviceConnectionFailureFn(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR err) +void SendCloseSessionCommand::OnDeviceConnectionFailureFn(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR err) { LogErrorOnFailure(err); - auto * command = reinterpret_cast(context); + auto * command = reinterpret_cast(context); VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "OnDeviceConnectionFailureFn: context is null")); command->SetCommandExitStatus(err); } + +CHIP_ERROR EvictLocalCASESessionsCommand::RunCommand() +{ + auto & controller = CurrentCommissioner(); + auto sessionManager = controller.SessionMgr(); + + sessionManager->ExpireAllSessions(ScopedNodeId(mDestinationNodeId, controller.GetFabricIndex())); + + SetCommandExitStatus(CHIP_NO_ERROR); + return CHIP_NO_ERROR; +} diff --git a/examples/chip-tool/commands/pairing/CloseSessionCommand.h b/examples/chip-tool/commands/session-management/CloseSessionCommand.h similarity index 53% rename from examples/chip-tool/commands/pairing/CloseSessionCommand.h rename to examples/chip-tool/commands/session-management/CloseSessionCommand.h index edbcb82b094d5d..b51934a9390a92 100644 --- a/examples/chip-tool/commands/pairing/CloseSessionCommand.h +++ b/examples/chip-tool/commands/session-management/CloseSessionCommand.h @@ -23,16 +23,35 @@ #include #include -class CloseSessionCommand : public CHIPCommand +namespace detail { + +class SessionManagementCommand : public CHIPCommand +{ +public: + SessionManagementCommand(const char * commandName, CredentialIssuerCommands * credIssuerCommands, const char * helpText) : + CHIPCommand(commandName, credIssuerCommands, helpText) + { + AddArgument("node-id", 0, UINT64_MAX, &mDestinationNodeId); + } + +protected: + chip::NodeId mDestinationNodeId; +}; + +} // namespace detail + +class SendCloseSessionCommand : public detail::SessionManagementCommand { public: - CloseSessionCommand(CredentialIssuerCommands * credIssuerCommands) : - CHIPCommand("close-session", credIssuerCommands, "Sends a CloseSession message to the given destination node id."), + SendCloseSessionCommand(CredentialIssuerCommands * credIssuerCommands) : + detail::SessionManagementCommand("send-close-session", credIssuerCommands, + "Sends a CloseSession message to the given node id."), mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this) { - AddArgument("destination-id", 0, UINT64_MAX, &mDestinationId); AddArgument("timeout", 0, UINT64_MAX, &mTimeoutSecs, "Time, in seconds, before this command is considered to have timed out."); + AddArgument("evict-local-session", 0, 1, &mEvictLocalSession, + "If true, evicts the local session after sending the message. If false, leaves it around. Defaults to true."); } /////////// CHIPCommand Interface ///////// @@ -43,16 +62,33 @@ class CloseSessionCommand : public CHIPCommand } private: - chip::NodeId mDestinationId; chip::Optional mTimeoutSecs; + chip::Optional mEvictLocalSession; static void OnDeviceConnectedFn(void * context, chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); static void OnDeviceConnectionFailureFn(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR error); - // Try to send the action CloseSession status report. + // Try to send the CloseSession status report. CHIP_ERROR CloseSession(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); chip::Callback::Callback mOnDeviceConnectedCallback; chip::Callback::Callback mOnDeviceConnectionFailureCallback; }; + +class EvictLocalCASESessionsCommand : public detail::SessionManagementCommand +{ +public: + EvictLocalCASESessionsCommand(CredentialIssuerCommands * credIssuerCommands) : + detail::SessionManagementCommand("expire-case-sessions", credIssuerCommands, + "Expires (evicts) all local CASE sessions to the given node id.") + {} + + /////////// CHIPCommand Interface ///////// + CHIP_ERROR RunCommand() override; + chip::System::Clock::Timeout GetWaitDuration() const override + { + // This command does all its work synchronously, so it really does not matter too much. + return chip::System::Clock::Seconds16(5); + } +}; diff --git a/examples/chip-tool/commands/session-management/Commands.h b/examples/chip-tool/commands/session-management/Commands.h new file mode 100644 index 00000000000000..7c75be2065f13d --- /dev/null +++ b/examples/chip-tool/commands/session-management/Commands.h @@ -0,0 +1,34 @@ +/* + * 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 "commands/common/Commands.h" +#include "commands/session-management/CloseSessionCommand.h" + +void registerCommandsSessionManagement(Commands & commands, CredentialIssuerCommands * credsIssuerConfig) +{ + const char * clusterName = "SessionManagement"; + + commands_list clusterCommands = { + make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), + }; + + commands.Register(clusterName, clusterCommands, "Commands for managing CASE and PASE session state"); +} diff --git a/examples/chip-tool/main.cpp b/examples/chip-tool/main.cpp index c45998a8c8e337..17bb7f13a57e80 100644 --- a/examples/chip-tool/main.cpp +++ b/examples/chip-tool/main.cpp @@ -26,6 +26,7 @@ #include "commands/interactive/Commands.h" #include "commands/pairing/Commands.h" #include "commands/payload/Commands.h" +#include "commands/session-management/Commands.h" #include "commands/storage/Commands.h" #include @@ -48,6 +49,7 @@ int main(int argc, char * argv[]) registerClusters(commands, &credIssuerCommands); registerCommandsSubscriptions(commands, &credIssuerCommands); registerCommandsStorage(commands); + registerCommandsSessionManagement(commands, &credIssuerCommands); return commands.Run(argc, argv); }