diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index d08d4a0fdf1a82..5eb3d60065c868 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -377,6 +377,14 @@ CHIP_ERROR Device::OpenPairingWindow(uint32_t timeout, PairingWindowOption optio return CHIP_NO_ERROR; } +CHIP_ERROR Device::CloseSession() +{ + ReturnErrorCodeIf(mState != ConnectionState::SecureConnected, CHIP_ERROR_INCORRECT_STATE); + mSessionManager->ExpirePairing(mSecureSession); + mState = ConnectionState::NotConnected; + return CHIP_NO_ERROR; +} + CHIP_ERROR Device::UpdateAddress(const Transport::PeerAddress & addr) { bool didLoad; @@ -505,12 +513,7 @@ void Device::OperationalCertProvisioned() mDeviceOperationalCertProvisioned = true; Persist(); - - if (mState == ConnectionState::SecureConnected) - { - mSessionManager->ExpirePairing(mSecureSession); - mState = ConnectionState::NotConnected; - } + CloseSession(); } CHIP_ERROR Device::WarmupCASESession() diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index 86ca0228d972ec..e5c4834b6dfc14 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -297,6 +297,11 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta */ CHIP_ERROR OpenPairingWindow(uint32_t timeout, PairingWindowOption option, SetupPayload & setupPayload); + /** + * In case there exists an open session to the device, mark it as expired. + */ + CHIP_ERROR CloseSession(); + /** * @brief * Update address of the device. diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp index 2ef0ee1d7e319d..f69021e1a62795 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -96,6 +96,7 @@ CHIP_ERROR pychip_DeviceController_ConnectBLE(chip::Controller::DeviceCommission uint32_t setupPINCode, chip::NodeId nodeid); CHIP_ERROR pychip_DeviceController_ConnectIP(chip::Controller::DeviceCommissioner * devCtrl, const char * peerAddrStr, uint32_t setupPINCode, chip::NodeId nodeid); +CHIP_ERROR pychip_DeviceController_CloseSession(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeid); CHIP_ERROR pychip_DeviceController_DiscoverCommissionableNodesLongDiscriminator(chip::Controller::DeviceCommissioner * devCtrl, uint16_t long_discriminator); @@ -257,6 +258,14 @@ CHIP_ERROR pychip_DeviceController_ConnectIP(chip::Controller::DeviceCommissione return devCtrl->PairDevice(nodeid, params); } +CHIP_ERROR pychip_DeviceController_CloseSession(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeid) +{ + Device * device; + ReturnErrorOnFailure(devCtrl->GetDevice(nodeid, &device)); + + return device->CloseSession(); +} + CHIP_ERROR pychip_DeviceController_DiscoverAllCommissionableNodes(chip::Controller::DeviceCommissioner * devCtrl) { Mdns::DiscoveryFilter filter(Mdns::DiscoveryFilterType::kNone, (uint16_t) 0); diff --git a/src/controller/python/README.md b/src/controller/python/README.md index 1e64cf8168c8d4..eb99707a048ec2 100644 --- a/src/controller/python/README.md +++ b/src/controller/python/README.md @@ -366,6 +366,11 @@ persisted by controller / device. If no nodeid given, a random Node ID will be used. +### `close-session ` + +If case there eixsts an open session (PASE or CASE) to the device with a given +Node ID, mark it as expired. + ### `discover` Discover available Matter accessory devices: diff --git a/src/controller/python/chip-device-ctrl.py b/src/controller/python/chip-device-ctrl.py index deea0c43923d1c..a31c7a56017f8e 100755 --- a/src/controller/python/chip-device-ctrl.py +++ b/src/controller/python/chip-device-ctrl.py @@ -195,6 +195,7 @@ def __init__(self, rendezvousAddr=None, controllerNodeId=0, bluetoothAdapter=Non "connect", "close-ble", + "close-session", "resolve", "zcl", "zclread", @@ -527,6 +528,23 @@ def do_connect(self, line): print(str(ex)) return + def do_closesession(self, line): + """ + close-session + + Close any session associated with a given node ID. + """ + try: + parser = argparse.ArgumentParser() + parser.add_argument('nodeid', type=int, help='Peer node ID') + args = parser.parse_args(shlex.split(line)) + + self.devCtrl.CloseSession(args.nodeid) + except exceptions.ChipStackException as ex: + print(str(ex)) + except: + self.do_help("close-session") + def do_resolve(self, line): """ resolve diff --git a/src/controller/python/chip/ChipDeviceCtrl.py b/src/controller/python/chip/ChipDeviceCtrl.py index 93dd0e5dc652a5..56a40e25df2829 100644 --- a/src/controller/python/chip/ChipDeviceCtrl.py +++ b/src/controller/python/chip/ChipDeviceCtrl.py @@ -181,6 +181,11 @@ def CloseBLEConnection(self): lambda: self._dmLib.pychip_DeviceCommissioner_CloseBleConnection(self.devCtrl) ) + def CloseSession(self, nodeid): + return self._ChipStack.Call( + lambda: self._dmLib.pychip_DeviceController_CloseSession(self.devCtrl, nodeid) + ) + def ConnectIP(self, ipaddr, setupPinCode, nodeid): self.state = DCState.RENDEZVOUS_ONGOING return self._ChipStack.CallAsync( @@ -398,6 +403,9 @@ def _InitLib(self): self._dmLib.pychip_DeviceController_ConnectIP.argtypes = [c_void_p, c_char_p, c_uint32, c_uint64] self._dmLib.pychip_DeviceController_ConnectIP.restype = c_uint32 + self._dmLib.pychip_DeviceController_CloseSession.argtypes = [c_void_p, c_uint64] + self._dmLib.pychip_DeviceController_CloseSession.restype = c_uint32 + self._dmLib.pychip_DeviceController_GetAddressAndPort.argtypes = [ c_void_p, c_uint64, c_char_p, c_uint64, POINTER(c_uint16)] self._dmLib.pychip_DeviceController_GetAddressAndPort.restype = c_uint32 diff --git a/src/controller/python/test/test_scripts/base.py b/src/controller/python/test/test_scripts/base.py index 10143756e43be6..9e5fd8046dcf07 100644 --- a/src/controller/python/test/test_scripts/base.py +++ b/src/controller/python/test/test_scripts/base.py @@ -66,6 +66,15 @@ def TestKeyExchange(self, ip: str, setuppin: int, nodeid: int): self.logger.info("Device finished key exchange.") return True + def TestCloseSession(self, nodeid: int): + self.logger.info(f"Closing sessions with device {nodeid}") + try: + self.devCtrl.CloseSession(nodeid) + return True + except Exception as ex: + self.logger.exception(f"Failed to close sessions with device {nodeid}: {ex}") + return False + def TestNetworkCommissioning(self, nodeid: int, endpoint: int, group: int, dataset: str, network_id: str): self.logger.info("Commissioning network to device {}".format(nodeid)) try: 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 0e9d4037642a33..79f86d85a559bd 100755 --- a/src/controller/python/test/test_scripts/mobile-device-test.py +++ b/src/controller/python/test/test_scripts/mobile-device-test.py @@ -91,6 +91,9 @@ def main(): group=GROUP_ID), "Failed to test Write Basic Attributes") + logger.info("Testing closing sessions") + FailIfNot(test.TestCloseSession(nodeid=1), "Failed to close sessions") + timeoutTicker.stop() logger.info("Test finished")