Enable pairing for multiple devices (#3630)
diff --git a/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp b/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp
index 5060b57..683a577 100644
--- a/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp
+++ b/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp
@@ -70,12 +70,23 @@
bluetoothLED.Set(true);
break;
+ case RendezvousSessionDelegate::SecurePairingFailed:
+ ESP_LOGI(TAG, "Failed in SPAKE2+ handshake\n");
+ bluetoothLED.Set(false);
+ break;
+
case RendezvousSessionDelegate::NetworkProvisioningSuccess:
ESP_LOGI(TAG, "Device was assigned an ip address\n");
bluetoothLED.Set(false);
break;
+ case RendezvousSessionDelegate::NetworkProvisioningFailed:
+
+ ESP_LOGI(TAG, "Failed in network provisioning\n");
+ bluetoothLED.Set(false);
+ break;
+
default:
break;
};
diff --git a/examples/chip-tool/commands/common/Command.h b/examples/chip-tool/commands/common/Command.h
index 8c81731..7ef5727 100644
--- a/examples/chip-tool/commands/common/Command.h
+++ b/examples/chip-tool/commands/common/Command.h
@@ -18,7 +18,7 @@
#pragma once
-#include <controller/CHIPDeviceController.h>
+#include <controller/CHIPDeviceController_deprecated.h>
#include <inet/InetInterface.h>
#include <support/logging/CHIPLogging.h>
diff --git a/examples/chip-tool/commands/common/Commands.h b/examples/chip-tool/commands/common/Commands.h
index 531b557..c331831 100644
--- a/examples/chip-tool/commands/common/Commands.h
+++ b/examples/chip-tool/commands/common/Commands.h
@@ -21,7 +21,7 @@
#include "Command.h"
#include <map>
-#include <controller/CHIPDeviceController.h>
+#include <controller/CHIPDeviceController_deprecated.h>
class Commands
{
diff --git a/src/controller/BUILD.gn b/src/controller/BUILD.gn
index 7d843de..aaab1fe 100644
--- a/src/controller/BUILD.gn
+++ b/src/controller/BUILD.gn
@@ -18,8 +18,12 @@
output_name = "libChipController"
sources = [
+ "CHIPDevice.cpp",
+ "CHIPDevice.h",
"CHIPDeviceController.cpp",
"CHIPDeviceController.h",
+ "CHIPDeviceController_deprecated.cpp",
+ "CHIPDeviceController_deprecated.h",
]
cflags = [ "-Wconversion" ]
diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp
new file mode 100644
index 0000000..68048e7
--- /dev/null
+++ b/src/controller/CHIPDevice.cpp
@@ -0,0 +1,216 @@
+/*
+ *
+ * Copyright (c) 2020 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.
+ */
+
+/**
+ * @file
+ * This file contains implementation of Device class. The objects of this
+ * class will be used by Controller applications to interact with CHIP
+ * devices. The class provides mechanism to construct, send and receive
+ * messages to and from the corresponding CHIP devices.
+ */
+
+#include <controller/CHIPDevice.h>
+
+#if CONFIG_DEVICE_LAYER
+#include <platform/CHIPDeviceLayer.h>
+#endif
+
+#include <core/CHIPCore.h>
+#include <core/CHIPEncoding.h>
+#include <core/CHIPSafeCasts.h>
+#include <support/Base64.h>
+#include <support/CHIPMem.h>
+#include <support/CodeUtils.h>
+#include <support/ErrorStr.h>
+#include <support/SafeInt.h>
+#include <support/logging/CHIPLogging.h>
+
+using namespace chip::Inet;
+using namespace chip::System;
+
+namespace chip {
+namespace Controller {
+
+CHIP_ERROR Device::SendMessage(System::PacketBuffer * buffer)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ System::PacketBuffer * resend = nullptr;
+
+ VerifyOrExit(mSessionManager != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrExit(buffer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+ // If there is no secure connection to the device, try establishing it
+ if (mState != ConnectionState::SecureConnected)
+ {
+ err = LoadSecureSessionParameters();
+ SuccessOrExit(err);
+ }
+ else
+ {
+ // Secure connection already exists
+ // Hold on to the buffer, in case session resumption and resend is needed
+ buffer->AddRef();
+ resend = buffer;
+ }
+
+ err = mSessionManager->SendMessage(mDeviceId, buffer);
+ buffer = nullptr;
+ ChipLogDetail(Controller, "SendMessage returned %d", err);
+
+ // The send could fail due to network timeouts (e.g. broken pipe)
+ // Try sesion resumption if needed
+ if (err != CHIP_NO_ERROR && resend != nullptr && mState == ConnectionState::SecureConnected)
+ {
+ mState = ConnectionState::NotConnected;
+
+ err = LoadSecureSessionParameters();
+ SuccessOrExit(err);
+
+ err = mSessionManager->SendMessage(mDeviceId, resend);
+ resend = nullptr;
+ ChipLogDetail(Controller, "Re-SendMessage returned %d", err);
+ SuccessOrExit(err);
+ }
+
+exit:
+
+ if (buffer != nullptr)
+ {
+ PacketBuffer::Free(buffer);
+ }
+
+ if (resend != nullptr)
+ {
+ PacketBuffer::Free(resend);
+ }
+
+ return err;
+}
+
+CHIP_ERROR Device::Serialize(SerializedDevice & output)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ uint16_t serializedLen = 0;
+ SerializableDevice serializable;
+
+ nlSTATIC_ASSERT_PRINT(BASE64_ENCODED_LEN(sizeof(serializable)) <= sizeof(output.inner),
+ "Size of serializable should be <= size of output");
+
+ CHIP_ZERO_AT(serializable);
+
+ memmove(&serializable.mOpsCreds, &mPairing, sizeof(mPairing));
+ serializable.mDeviceId = Encoding::LittleEndian::HostSwap64(mDeviceId);
+ serializable.mDevicePort = Encoding::LittleEndian::HostSwap16(mDevicePort);
+ nlSTATIC_ASSERT_PRINT(sizeof(serializable.mDeviceAddr) <= INET6_ADDRSTRLEN,
+ "Size of device address must fit within INET6_ADDRSTRLEN");
+ mDeviceAddr.ToString(Uint8::to_char(serializable.mDeviceAddr), sizeof(serializable.mDeviceAddr));
+
+ serializedLen = chip::Base64Encode(Uint8::to_const_uchar(reinterpret_cast<uint8_t *>(&serializable)),
+ static_cast<uint16_t>(sizeof(serializable)), Uint8::to_char(output.inner));
+ VerifyOrExit(serializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(serializedLen < sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT);
+ output.inner[serializedLen] = '\0';
+
+exit:
+ return error;
+}
+
+CHIP_ERROR Device::Deserialize(const SerializedDevice & input)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ SerializableDevice serializable;
+ size_t maxlen = BASE64_ENCODED_LEN(sizeof(serializable));
+ size_t len = strnlen(Uint8::to_const_char(&input.inner[0]), maxlen);
+ uint16_t deserializedLen = 0;
+
+ VerifyOrExit(len < sizeof(SerializedDevice), error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(CanCastTo<uint16_t>(len), error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ CHIP_ZERO_AT(serializable);
+ deserializedLen = Base64Decode(Uint8::to_const_char(input.inner), static_cast<uint16_t>(len),
+ Uint8::to_uchar(reinterpret_cast<uint8_t *>(&serializable)));
+
+ VerifyOrExit(deserializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(deserializedLen <= sizeof(serializable), error = CHIP_ERROR_INVALID_ARGUMENT);
+
+ // The second parameter to FromString takes the strlen value. We are subtracting 1
+ // from the sizeof(serializable.mDeviceAddr) to account for null termination, since
+ // strlen doesn't include null character in the size.
+ VerifyOrExit(
+ IPAddress::FromString(Uint8::to_const_char(serializable.mDeviceAddr), sizeof(serializable.mDeviceAddr) - 1, mDeviceAddr),
+ error = CHIP_ERROR_INVALID_ADDRESS);
+
+ memmove(&mPairing, &serializable.mOpsCreds, sizeof(mPairing));
+ mDeviceId = Encoding::LittleEndian::HostSwap64(serializable.mDeviceId);
+ mDevicePort = Encoding::LittleEndian::HostSwap16(serializable.mDevicePort);
+
+exit:
+ return error;
+}
+
+void Device::OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader,
+ Transport::PeerConnectionState * state, System::PacketBuffer * msgBuf, SecureSessionMgrBase * mgr)
+{
+ if (mState == ConnectionState::SecureConnected && mStatusDelegate != nullptr)
+ {
+ mStatusDelegate->OnMessage(msgBuf);
+ }
+}
+
+CHIP_ERROR Device::LoadSecureSessionParameters()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ SecurePairingSession pairingSession;
+
+ if (mSessionManager == nullptr || mState == ConnectionState::SecureConnected)
+ {
+ ExitNow(err = CHIP_ERROR_INCORRECT_STATE);
+ }
+
+ err = pairingSession.FromSerializable(mPairing);
+ SuccessOrExit(err);
+
+ err = mSessionManager->ResetTransport(Transport::UdpListenParameters(mInetLayer).SetAddressType(mDeviceAddr.Type()));
+ SuccessOrExit(err);
+
+ err = mSessionManager->NewPairing(
+ Optional<Transport::PeerAddress>::Value(Transport::PeerAddress::UDP(mDeviceAddr, mDevicePort, mInterface)),
+ &pairingSession);
+ SuccessOrExit(err);
+
+ mState = ConnectionState::SecureConnected;
+
+exit:
+
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(Controller, "LoadSecureSessionParameters returning error %d\n", err);
+ }
+ return err;
+}
+
+bool Device::GetIpAddress(Inet::IPAddress & addr) const
+{
+ if (mState == ConnectionState::SecureConnected)
+ addr = mDeviceAddr;
+ return mState == ConnectionState::SecureConnected;
+}
+
+} // namespace Controller
+} // namespace chip
diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h
new file mode 100644
index 0000000..69d7491
--- /dev/null
+++ b/src/controller/CHIPDevice.h
@@ -0,0 +1,260 @@
+/*
+ *
+ * Copyright (c) 2020 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.
+ */
+
+/**
+ * @file
+ * This file contains definitions for Device class. The objects of this
+ * class will be used by Controller applications to interact with CHIP
+ * devices. The class provides mechanism to construct, send and receive
+ * messages to and from the corresponding CHIP devices.
+ */
+
+#pragma once
+
+#include <core/CHIPCore.h>
+#include <support/Base64.h>
+#include <support/DLLUtil.h>
+#include <transport/SecurePairingSession.h>
+#include <transport/SecureSessionMgr.h>
+#include <transport/raw/MessageHeader.h>
+#include <transport/raw/UDP.h>
+
+namespace chip {
+namespace Controller {
+
+class DeviceController;
+class DeviceStatusDelegate;
+struct SerializedDevice;
+
+class DLL_EXPORT Device
+{
+public:
+ Device() : mActive(false), mState(ConnectionState::NotConnected) {}
+ ~Device() {}
+
+ /**
+ * @brief
+ * Set the delegate object which will be called when a message is received.
+ * The user of this Device object must reset the delegate (by calling
+ * SetDelegate(nullptr)) before releasing their delegate object.
+ *
+ * @param[in] delegate The pointer to the delegate object.
+ */
+ void SetDelegate(DeviceStatusDelegate * delegate) { mStatusDelegate = delegate; }
+
+ // ----- Messaging -----
+ /**
+ * @brief
+ * Send the provided message to the device
+ *
+ * @param[in] message The message to be sent. The ownership of the message buffer
+ * is handed over to Device object. SendMessage() will
+ * decrement the reference count of the message buffer before
+ * returning.
+ *
+ * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error
+ */
+ CHIP_ERROR SendMessage(System::PacketBuffer * message);
+
+ /**
+ * @brief
+ * Get the IP address assigned to the device.
+ *
+ * @param[out] addr The reference to the IP address.
+ *
+ * @return true, if the IP address was filled in the out parameter, false otherwise
+ */
+ bool GetIpAddress(Inet::IPAddress & addr) const;
+
+ /**
+ * @brief
+ * Initialize the device object with secure session manager and inet layer object
+ * references. This variant of function is typically used when the device object
+ * is created from a serialized device information. The other parameters (address, port,
+ * interface etc) are part of the serialized device, so those are not required to be
+ * initialized.
+ *
+ * Note: The lifetime of session manager and inet layer objects must be longer than
+ * that of this device object. If these objects are freed, while the device object is
+ * still using them, it can lead to unknown behavior and crashes.
+ *
+ * @param[in] sessionMgr Secure session manager object pointer
+ * @param[in] inetLayer InetLayer object pointer
+ */
+ void Init(SecureSessionMgr<Transport::UDP> * sessionMgr, Inet::InetLayer * inetLayer)
+ {
+ mSessionManager = sessionMgr;
+ mInetLayer = inetLayer;
+ }
+
+ /**
+ * @brief
+ * Initialize a new device object with secure session manager, inet layer object,
+ * and other device specific parameters. This variant of function is typically used when
+ * a new device is paired, and the corresponding device object needs to updated with
+ * all device specifc parameters (address, port, interface etc).
+ *
+ * This is not done as part of constructor so that the controller can have a list of
+ * uninitialzed/unpaired device objects. The object is initialized only when the device
+ * is actually paired.
+ *
+ * @param[in] sessionMgr Secure session manager object pointer
+ * @param[in] inetLayer InetLayer object pointer
+ * @param[in] deviceId Node ID of the device
+ * @param[in] devicePort Port on which device is listening (typically CHIP_PORT)
+ * @param[in] interfaceId Local Interface ID that should be used to talk to the device
+ */
+ void Init(SecureSessionMgr<Transport::UDP> * sessionMgr, Inet::InetLayer * inetLayer, NodeId deviceId, uint16_t devicePort,
+ Inet::InterfaceId interfaceId)
+ {
+ Init(sessionMgr, inetLayer);
+ mDeviceId = deviceId;
+ mDevicePort = devicePort;
+ mInterface = interfaceId;
+ mState = ConnectionState::Connecting;
+ }
+
+ /** @brief Serialize the Pairing Session to a string. It's guaranteed that the string
+ * will be null terminated, and there won't be any embedded null characters.
+ *
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR Serialize(SerializedDevice & output);
+
+ /** @brief Deserialize the Pairing Session from the string. It's expected that the string
+ * will be null terminated, and there won't be any embedded null characters.
+ *
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR Deserialize(const SerializedDevice & input);
+
+ /**
+ * @brief
+ * This function is called when a message is received from the corresponding CHIP
+ * device. The message ownership is transferred to the function, and it is expected
+ * to release the message buffer before returning.
+ *
+ * @param[in] header Reference to common packet header of the received message
+ * @param[in] payloadHeader Reference to payload header in the message
+ * @param[in] state Pointer to the peer connection state on which message is received
+ * @param[in] msgBuf The message buffer
+ * @param[in] mgr Pointer to secure session manager which received the message
+ */
+ void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, Transport::PeerConnectionState * state,
+ System::PacketBuffer * msgBuf, SecureSessionMgrBase * mgr);
+
+ /**
+ * @brief
+ * Return whether the current device object is actively associated with a paired CHIP
+ * device. An active object can be used to communicate with the corresponding device.
+ */
+ bool IsActive() const { return mActive; }
+
+ void SetActive(bool active) { mActive = active; }
+
+ NodeId GetDeviceId() const { return mDeviceId; }
+
+ void SetAddress(const Inet::IPAddress & deviceAddr) { mDeviceAddr = deviceAddr; }
+
+ SecurePairingSessionSerializable & GetPairing() { return mPairing; }
+
+private:
+ enum class ConnectionState
+ {
+ NotConnected,
+ Connecting,
+ SecureConnected,
+ };
+
+ /* Node ID assigned to the CHIP device */
+ NodeId mDeviceId;
+
+ /* IP Address of the CHIP device */
+ Inet::IPAddress mDeviceAddr;
+
+ /* Port on which the CHIP device is receiving messages. Typically it is CHIP_PORT */
+ uint16_t mDevicePort;
+
+ /* Local network interface that should be used to communicate with the device */
+ Inet::InterfaceId mInterface;
+
+ Inet::InetLayer * mInetLayer;
+
+ bool mActive;
+ ConnectionState mState;
+
+ SecurePairingSessionSerializable mPairing;
+
+ DeviceStatusDelegate * mStatusDelegate;
+
+ SecureSessionMgr<Transport::UDP> * mSessionManager;
+
+ /**
+ * @brief
+ * This function loads the secure session object from the serialized operational
+ * credentials corresponding to the device. This is typically done when the device
+ * does not have an active secure channel.
+ */
+ CHIP_ERROR LoadSecureSessionParameters();
+};
+
+/**
+ * This class defines an interface for an object that the user of Device
+ * can register as a delegate. The delegate object will be called by the
+ * Device when a new message or status update is received from the corresponding
+ * CHIP device.
+ */
+class DLL_EXPORT DeviceStatusDelegate
+{
+public:
+ virtual ~DeviceStatusDelegate() {}
+
+ /**
+ * @brief
+ * Called when a message is received from the device.
+ *
+ * @param[in] msg Received message buffer.
+ */
+ virtual void OnMessage(System::PacketBuffer * msg) = 0;
+
+ /**
+ * @brief
+ * Called when device status is updated.
+ *
+ */
+ virtual void OnStatusChange(void){};
+};
+
+typedef struct SerializableDevice
+{
+ SecurePairingSessionSerializable mOpsCreds;
+ uint64_t mDeviceId; /* This field is serialized in LittleEndian byte order */
+ uint8_t mDeviceAddr[INET6_ADDRSTRLEN];
+ uint16_t mDevicePort; /* This field is serealized in LittelEndian byte order */
+} SerializableDevice;
+
+typedef struct SerializedDevice
+{
+ // Extra uint64_t to account for padding bytes (NULL termination, and some decoding overheads)
+ // The encoder may not include a NULL character, and there are maximum 2 bytes of padding.
+ // So extra 8 bytes should be sufficient to absorb this overhead.
+ uint8_t inner[BASE64_ENCODED_LEN(sizeof(SerializableDevice) + sizeof(uint64_t))];
+} SerializedDevice;
+
+} // namespace Controller
+} // namespace chip
diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp
index ab1471b..7ce20bd 100644
--- a/src/controller/CHIPDeviceController.cpp
+++ b/src/controller/CHIPDeviceController.cpp
@@ -46,6 +46,7 @@
#include <support/CHIPMem.h>
#include <support/CodeUtils.h>
#include <support/ErrorStr.h>
+#include <support/SafeInt.h>
#include <support/TimeUtils.h>
#include <support/logging/CHIPLogging.h>
@@ -59,12 +60,12 @@
using namespace chip::System;
namespace chip {
-namespace DeviceController {
+namespace Controller {
using namespace chip::Encoding;
-constexpr const char kDeviceCredentialsKeyPrefix[] = "DeviceCredentials";
-constexpr const char kDeviceAddressKeyPrefix[] = "DeviceAddress";
+constexpr const char kPairedDeviceListKeyPrefix[] = "ListPairedDevices";
+constexpr const char kPairedDeviceKeyPrefix[] = "PairedDevice";
// This macro generates a key using node ID an key prefix, and performs the given action
// on that key.
@@ -80,66 +81,41 @@
action; \
} while (0)
-ChipDeviceController::ChipDeviceController()
+DeviceController::DeviceController()
{
- mState = kState_NotInitialized;
- AppState = nullptr;
- mConState = kConnectionState_NotConnected;
- mRendezvousSession = nullptr;
- mSessionManager = nullptr;
- mCurReqMsg = nullptr;
- mOnError = nullptr;
- mOnNewConnection = nullptr;
- mPairingDelegate = nullptr;
- mStorageDelegate = nullptr;
- mListenPort = CHIP_PORT;
- mDeviceAddr = IPAddress::Any;
- mDevicePort = CHIP_PORT;
- mInterface = INET_NULL_INTERFACEID;
- mLocalDeviceId = 0;
- mNumCachedPackets = 0;
- CHIP_ZERO_AT(mOnComplete);
- CHIP_ZERO_AT(mCachedPackets);
+ mState = State::NotInitialized;
+ mSessionManager = nullptr;
+ mLocalDeviceId = 0;
+ mStorageDelegate = nullptr;
+ mPairedDevicesInitialized = false;
}
-ChipDeviceController::~ChipDeviceController()
+CHIP_ERROR DeviceController::Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate, System::Layer * systemLayer,
+ Inet::InetLayer * inetLayer)
{
- if (mTestSecurePairingSecret != nullptr)
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ VerifyOrExit(mState == State::NotInitialized, err = CHIP_ERROR_INCORRECT_STATE);
+
+ if (systemLayer != nullptr && inetLayer != nullptr)
{
- chip::Platform::Delete(mTestSecurePairingSecret);
+ mSystemLayer = systemLayer;
+ mInetLayer = inetLayer;
}
-}
-
-CHIP_ERROR ChipDeviceController::Init(NodeId localNodeId, DevicePairingDelegate * pairingDelegate,
- PersistentStorageDelegate * storageDelegate)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- VerifyOrExit(mState == kState_NotInitialized, err = CHIP_ERROR_INCORRECT_STATE);
-
+ else
+ {
#if CONFIG_DEVICE_LAYER
- err = DeviceLayer::PlatformMgr().InitChipStack();
- SuccessOrExit(err);
+ err = DeviceLayer::PlatformMgr().InitChipStack();
+ SuccessOrExit(err);
- err = Init(localNodeId, &DeviceLayer::SystemLayer, &DeviceLayer::InetLayer, pairingDelegate, storageDelegate);
+ mSystemLayer = &DeviceLayer::SystemLayer;
+ mInetLayer = &DeviceLayer::InetLayer;
#endif // CONFIG_DEVICE_LAYER
+ }
-exit:
- return err;
-}
+ VerifyOrExit(mSystemLayer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(mInetLayer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
-CHIP_ERROR ChipDeviceController::Init(NodeId localNodeId, System::Layer * systemLayer, InetLayer * inetLayer,
- DevicePairingDelegate * pairingDelegate, PersistentStorageDelegate * storageDelegate)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- VerifyOrExit(mState == kState_NotInitialized, err = CHIP_ERROR_INCORRECT_STATE);
-
- mState = kState_Initialized;
- mLocalDeviceId = localNodeId;
- mSystemLayer = systemLayer;
- mInetLayer = inetLayer;
- mPairingDelegate = pairingDelegate;
mStorageDelegate = storageDelegate;
if (mStorageDelegate != nullptr)
@@ -147,19 +123,30 @@
mStorageDelegate->SetDelegate(this);
}
+ mSessionManager = chip::Platform::New<SecureSessionMgr<Transport::UDP>>();
+
+ err = mSessionManager->Init(localDeviceId, mSystemLayer,
+ Transport::UdpListenParameters(mInetLayer).SetAddressType(Inet::kIPAddressType_IPv6));
+ SuccessOrExit(err);
+
+ mSessionManager->SetDelegate(this);
+
+ mState = State::Initialized;
+ mLocalDeviceId = localDeviceId;
+
exit:
return err;
}
-CHIP_ERROR ChipDeviceController::Shutdown()
+CHIP_ERROR DeviceController::Shutdown()
{
CHIP_ERROR err = CHIP_NO_ERROR;
+ VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+
ChipLogDetail(Controller, "Shutting down the controller");
- VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE);
-
- mState = kState_NotInitialized;
+ mState = State::NotInitialized;
#if CONFIG_DEVICE_LAYER
err = DeviceLayer::PlatformMgr().Shutdown();
@@ -174,408 +161,128 @@
mSystemLayer = nullptr;
mInetLayer = nullptr;
- if (mSessionManager != nullptr)
- {
- chip::Platform::Delete(mSessionManager);
- mSessionManager = nullptr;
- }
-
- if (mRendezvousSession != nullptr)
- {
- chip::Platform::Delete(mRendezvousSession);
- mRendezvousSession = nullptr;
- }
-
- mConState = kConnectionState_NotConnected;
- CHIP_ZERO_AT(mOnComplete);
- mOnError = nullptr;
- mOnNewConnection = nullptr;
- mRemoteDeviceId.ClearValue();
-
-exit:
- return err;
-}
-
-CHIP_ERROR ChipDeviceController::ConnectDevice(NodeId remoteDeviceId, RendezvousParameters & params, void * appReqState,
- NewConnectionHandler onConnected, MessageReceiveHandler onMessageReceived,
- ErrorHandler onError, uint16_t devicePort, Inet::InterfaceId interfaceId)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE);
- VerifyOrExit(mConState == kConnectionState_NotConnected, err = CHIP_ERROR_INCORRECT_STATE);
-
-#if CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE
- if (!params.HasBleLayer())
- {
- params.SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer());
- }
-#endif // CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE
-
- mRendezvousSession = chip::Platform::New<RendezvousSession>(this);
- err = mRendezvousSession->Init(params.SetLocalNodeId(mLocalDeviceId));
- SuccessOrExit(err);
-
- mRemoteDeviceId = Optional<NodeId>::Value(remoteDeviceId);
- mDevicePort = devicePort;
- mInterface = interfaceId;
- mAppReqState = appReqState;
- mOnNewConnection = onConnected;
-
- // connected state before 'OnConnect'
- mConState = kConnectionState_Connected;
-
- mOnComplete.Response = onMessageReceived;
- mOnError = onError;
-
-exit:
- if (err != CHIP_NO_ERROR && mRendezvousSession != nullptr)
- {
- chip::Platform::Delete(mRendezvousSession);
- mRendezvousSession = nullptr;
- }
-
- return err;
-}
-
-CHIP_ERROR ChipDeviceController::ConnectDeviceWithoutSecurePairing(NodeId remoteDeviceId, const IPAddress & deviceAddr,
- void * appReqState, NewConnectionHandler onConnected,
- MessageReceiveHandler onMessageReceived, ErrorHandler onError,
- uint16_t devicePort, Inet::InterfaceId interfaceId)
-{
- if (mTestSecurePairingSecret != nullptr)
- {
- chip::Platform::Delete(mTestSecurePairingSecret);
- }
-
- mTestSecurePairingSecret = chip::Platform::New<SecurePairingUsingTestSecret>(
- Optional<NodeId>::Value(remoteDeviceId), static_cast<uint16_t>(0), static_cast<uint16_t>(0));
-
- mSecurePairingSession = mTestSecurePairingSecret;
-
- mDeviceAddr = deviceAddr;
- mRemoteDeviceId = Optional<NodeId>::Value(remoteDeviceId);
- mDevicePort = devicePort;
- mInterface = interfaceId;
- mAppReqState = appReqState;
- mOnNewConnection = onConnected;
-
- mConState = kConnectionState_Connected;
-
- mOnComplete.Response = onMessageReceived;
- mOnError = onError;
-
- if (mOnNewConnection)
- {
- mOnNewConnection(this, nullptr, mAppReqState);
- }
-
- return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR ChipDeviceController::SetUdpListenPort(uint16_t listenPort)
-{
- if (mState != kState_Initialized || mConState != kConnectionState_NotConnected)
- return CHIP_ERROR_INCORRECT_STATE;
- mListenPort = listenPort;
- return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR ChipDeviceController::EstablishSecureSession()
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- VerifyOrExit(mSecurePairingSession != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
-
- mSessionManager = chip::Platform::New<SecureSessionMgr<Transport::UDP>>();
-
- err = mSessionManager->Init(
- mLocalDeviceId, mSystemLayer,
- Transport::UdpListenParameters(mInetLayer).SetAddressType(mDeviceAddr.Type()).SetListenPort(mListenPort));
- SuccessOrExit(err);
-
- mSessionManager->SetDelegate(this);
-
- err = mSessionManager->NewPairing(
- Optional<Transport::PeerAddress>::Value(Transport::PeerAddress::UDP(mDeviceAddr, mDevicePort, mInterface)),
- mSecurePairingSession);
- SuccessOrExit(err);
-
- mConState = kConnectionState_SecureConnected;
-
- if (mDeviceAddr != IPAddress::Any)
- {
- SendCachedPackets();
- } // else wait for mdns discovery
-
-exit:
-
- if (err != CHIP_NO_ERROR)
- {
- if (mSessionManager != nullptr)
- {
- chip::Platform::Delete(mSessionManager);
- mSessionManager = nullptr;
- }
- mConState = kConnectionState_NotConnected;
- }
-
- return err;
-}
-
-void ChipDeviceController::OnValue(const char * key, const char * value)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
- NodeId peer = mRemoteDeviceId.Value();
-
- VerifyOrExit(key != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
-
- PERSISTENT_KEY_OP(
- peer, kDeviceCredentialsKeyPrefix, expectedKey, if (strcmp(key, expectedKey) == 0) {
- SecurePairingSessionSerialized serialized;
- size_t length = 0;
-
- VerifyOrExit(value != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
- length = strlen(value) + 1; // account for the null termination
- VerifyOrExit(length <= sizeof(serialized.inner), err = CHIP_ERROR_INVALID_ARGUMENT);
- memmove(serialized.inner, value, length);
- SuccessOrExit(mPairingSession.Deserialize(serialized));
-
- mSecurePairingSession = &mPairingSession;
- });
-
- PERSISTENT_KEY_OP(
- peer, kDeviceAddressKeyPrefix, expectedKey, if (strcmp(key, expectedKey) == 0) {
- VerifyOrExit(value != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
- VerifyOrExit(IPAddress::FromString(value, mDeviceAddr), err = CHIP_ERROR_INVALID_ADDRESS);
- });
-
- if (mSecurePairingSession != nullptr && mDeviceAddr != IPAddress::Any)
- {
- SuccessOrExit(EstablishSecureSession());
- }
-
-exit:
- if (err != CHIP_NO_ERROR)
- {
- mConState = kConnectionState_NotConnected;
- DiscardCachedPackets();
- }
-}
-
-void ChipDeviceController::OnStatus(const char * key, Operation op, CHIP_ERROR err) {}
-
-CHIP_ERROR ChipDeviceController::TryEstablishingSecureSession(NodeId peer)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- if (mState != kState_Initialized || mSessionManager != nullptr || mConState == kConnectionState_SecureConnected)
- {
- ExitNow(err = CHIP_ERROR_INCORRECT_STATE);
- }
-
if (mStorageDelegate != nullptr)
{
- mSecurePairingSession = nullptr;
- mDeviceAddr = IPAddress::Any;
- PERSISTENT_KEY_OP(peer, kDeviceCredentialsKeyPrefix, key, mStorageDelegate->GetKeyValue(key));
- PERSISTENT_KEY_OP(peer, kDeviceAddressKeyPrefix, key, mStorageDelegate->GetKeyValue(key));
- mConState = kConnectionState_SecureConnecting;
- }
- else
- {
- ExitNow(err = EstablishSecureSession());
- }
-
-exit:
-
- if (err != CHIP_NO_ERROR)
- {
- DiscardCachedPackets();
- }
- return err;
-}
-
-CHIP_ERROR ChipDeviceController::ResumeSecureSession(NodeId peer)
-{
- if (mConState == kConnectionState_SecureConnected)
- {
- mConState = kConnectionState_Connected;
+ mStorageDelegate->SetDelegate(nullptr);
+ mStorageDelegate = nullptr;
}
if (mSessionManager != nullptr)
{
+ mSessionManager->SetDelegate(nullptr);
chip::Platform::Delete(mSessionManager);
mSessionManager = nullptr;
}
- CHIP_ERROR err = TryEstablishingSecureSession(peer);
- SuccessOrExit(err);
-
-exit:
-
- if (err != CHIP_NO_ERROR)
- {
- ChipLogError(Controller, "ResumeSecureSession returning error %d\n", err);
- }
- return err;
-}
-
-bool ChipDeviceController::IsConnected() const
-{
- return mState == kState_Initialized &&
- (mConState == kConnectionState_Connected || mConState == kConnectionState_SecureConnected);
-}
-
-bool ChipDeviceController::IsSecurelyConnected() const
-{
- return mState == kState_Initialized && mConState == kConnectionState_SecureConnected;
-}
-
-bool ChipDeviceController::GetIpAddress(Inet::IPAddress & addr) const
-{
- if (IsConnected())
- addr = mDeviceAddr;
- return IsConnected();
-}
-
-CHIP_ERROR ChipDeviceController::DisconnectDevice()
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- if (!IsConnected())
- {
- return CHIP_ERROR_INCORRECT_STATE;
- }
-
- if (mSessionManager != nullptr)
- {
- chip::Platform::Delete(mSessionManager);
- mSessionManager = nullptr;
- }
-
- if (mRendezvousSession != nullptr)
- {
- chip::Platform::Delete(mRendezvousSession);
- mRendezvousSession = nullptr;
- }
-
- mConState = kConnectionState_NotConnected;
- return err;
-}
-
-CHIP_ERROR ChipDeviceController::CachePacket(System::PacketBuffer * buffer)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
-
- VerifyOrExit(mNumCachedPackets < kPacketCacheMaxSize, err = CHIP_ERROR_INTERNAL);
- mCachedPackets[mNumCachedPackets++] = buffer;
-
exit:
return err;
}
-CHIP_ERROR ChipDeviceController::SendCachedPackets()
+CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, const SerializedDevice & deviceInfo, Device ** out_device)
{
- CHIP_ERROR err = CHIP_NO_ERROR;
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ Device * device = nullptr;
+ uint16_t index = 0;
- VerifyOrExit(IsSecurelyConnected(), err = CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrExit(out_device != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
+ index = FindDeviceIndex(deviceId);
- for (uint16_t i = 0; i < mNumCachedPackets; i++)
+ if (index < kNumMaxActiveDevices)
{
- err = mSessionManager->SendMessage(mRemoteDeviceId.Value(), mCachedPackets[i]);
- ChipLogDetail(Controller, "SendMessage returned %d", err);
- }
-
- mNumCachedPackets = 0;
- CHIP_ZERO_AT(mCachedPackets);
-
-exit:
- return err;
-}
-
-void ChipDeviceController::DiscardCachedPackets()
-{
- for (uint16_t i = 0; i < mNumCachedPackets; i++)
- {
- PacketBuffer::Free(mCachedPackets[i]);
- }
-
- mNumCachedPackets = 0;
- CHIP_ZERO_AT(mCachedPackets);
-}
-
-CHIP_ERROR ChipDeviceController::SendMessage(void * appReqState, PacketBuffer * buffer, NodeId peerDevice)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
- bool trySessionResumption = true;
-
- VerifyOrExit(buffer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
- VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE);
-
- mAppReqState = appReqState;
-
- if (peerDevice != kUndefinedNodeId)
- {
- mRemoteDeviceId = Optional<NodeId>::Value(peerDevice);
- }
- VerifyOrExit(mRemoteDeviceId.HasValue(), err = CHIP_ERROR_INCORRECT_STATE);
-
- // If there is no secure connection to the device, try establishing it
- if (!IsSecurelyConnected())
- {
- err = TryEstablishingSecureSession(mRemoteDeviceId.Value());
- SuccessOrExit(err);
-
- trySessionResumption = false;
-
- if (mDeviceAddr == IPAddress::Any || mConState == kConnectionState_SecureConnecting)
- {
- // Cache the packet while connection is being established
- ExitNow(err = CachePacket(buffer));
- }
- }
-
- // Hold on to the buffer, in case of session resumption and resend is needed
- buffer->AddRef();
-
- err = mSessionManager->SendMessage(mRemoteDeviceId.Value(), buffer);
- ChipLogDetail(Controller, "SendMessage returned %d", err);
-
- // The send could fail due to network timeouts (e.g. broken pipe)
- // Try sesion resumption if needed
- if (err != CHIP_NO_ERROR && trySessionResumption)
- {
- err = ResumeSecureSession(mRemoteDeviceId.Value());
- // If session resumption failed, let's free the extra reference to
- // the buffer. If not, SendMessage would free it.
- VerifyOrExit(err == CHIP_NO_ERROR, PacketBuffer::Free(buffer));
-
- if (mConState == kConnectionState_SecureConnecting)
- {
- // Cache the packet while connection is being established
- ExitNow(err = CachePacket(buffer));
- }
-
- err = mSessionManager->SendMessage(mRemoteDeviceId.Value(), buffer);
- SuccessOrExit(err);
+ device = &mActiveDevices[index];
}
else
{
- // Free the extra reference to the buffer
- PacketBuffer::Free(buffer);
+ VerifyOrExit(mPairedDevices.Contains(deviceId), err = CHIP_ERROR_NOT_CONNECTED);
+
+ index = GetInactiveDeviceIndex();
+ VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY);
+ device = &mActiveDevices[index];
+
+ err = device->Deserialize(deviceInfo);
+ VerifyOrExit(err == CHIP_NO_ERROR, ReleaseDevice(device));
+
+ device->Init(mSessionManager, mInetLayer);
}
-exit:
+ *out_device = device;
+exit:
return err;
}
-CHIP_ERROR ChipDeviceController::ServiceEvents()
+CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ Device * device = nullptr;
+ uint16_t index = 0;
+ char * buffer = nullptr;
+
+ VerifyOrExit(out_device != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
+ index = FindDeviceIndex(deviceId);
+
+ if (index < kNumMaxActiveDevices)
+ {
+ device = &mActiveDevices[index];
+ }
+ else
+ {
+ VerifyOrExit(mStorageDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
+
+ if (!mPairedDevicesInitialized)
+ {
+ constexpr uint16_t max_size = CHIP_MAX_SERIALIZED_SIZE_U64(kNumMaxPairedDevices);
+ buffer = static_cast<char *>(chip::Platform::MemoryAlloc(max_size));
+ uint16_t size = max_size;
+
+ VerifyOrExit(buffer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+ PERSISTENT_KEY_OP(static_cast<uint64_t>(0), kPairedDeviceListKeyPrefix, key,
+ err = mStorageDelegate->GetKeyValue(key, buffer, size));
+ SuccessOrExit(err);
+ VerifyOrExit(size <= max_size, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR);
+
+ err = SetPairedDeviceList(buffer);
+ SuccessOrExit(err);
+ }
+
+ VerifyOrExit(mPairedDevices.Contains(deviceId), err = CHIP_ERROR_NOT_CONNECTED);
+
+ index = GetInactiveDeviceIndex();
+ VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY);
+ device = &mActiveDevices[index];
+
+ {
+ SerializedDevice deviceInfo;
+ uint16_t size = sizeof(deviceInfo.inner);
+
+ PERSISTENT_KEY_OP(deviceId, kPairedDeviceKeyPrefix, key,
+ err = mStorageDelegate->GetKeyValue(key, Uint8::to_char(deviceInfo.inner), size));
+ SuccessOrExit(err);
+ VerifyOrExit(size <= sizeof(deviceInfo.inner), err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR);
+
+ err = device->Deserialize(deviceInfo);
+ VerifyOrExit(err == CHIP_NO_ERROR, ReleaseDevice(device));
+
+ device->Init(mSessionManager, mInetLayer);
+ }
+ }
+
+ *out_device = device;
+
+exit:
+ if (buffer != nullptr)
+ {
+ chip::Platform::MemoryFree(buffer);
+ }
+ return err;
+}
+
+CHIP_ERROR DeviceController::ServiceEvents()
{
CHIP_ERROR err = CHIP_NO_ERROR;
- VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
#if CONFIG_DEVICE_LAYER
err = DeviceLayer::PlatformMgr().StartEventLoopTask();
@@ -586,11 +293,11 @@
return err;
}
-CHIP_ERROR ChipDeviceController::ServiceEventSignal()
+CHIP_ERROR DeviceController::ServiceEventSignal()
{
CHIP_ERROR err = CHIP_NO_ERROR;
- VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
#if CONFIG_DEVICE_LAYER && (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK)
DeviceLayer::SystemLayer.WakeSelect();
@@ -602,54 +309,274 @@
return err;
}
-CHIP_ERROR ChipDeviceController::SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate)
+void DeviceController::OnNewConnection(Transport::PeerConnectionState * peerConnection, SecureSessionMgrBase * mgr) {}
+
+void DeviceController::OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader,
+ Transport::PeerConnectionState * state, System::PacketBuffer * msgBuf,
+ SecureSessionMgrBase * mgr)
{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ uint16_t index = 0;
+ NodeId peer;
+
+ VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrExit(header.GetSourceNodeId().HasValue(), err = CHIP_ERROR_INVALID_ARGUMENT);
+
+ peer = header.GetSourceNodeId().Value();
+ index = FindDeviceIndex(peer);
+ VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR);
+
+ mActiveDevices[index].OnMessageReceived(header, payloadHeader, state, msgBuf, mgr);
+
+exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(Controller, "Failed to process received message: err %d", err);
+ }
+ return;
+}
+
+uint16_t DeviceController::GetInactiveDeviceIndex()
+{
+ uint16_t i = 0;
+ while (i < kNumMaxActiveDevices && mActiveDevices[i].IsActive())
+ i++;
+ if (i < kNumMaxActiveDevices)
+ {
+ mActiveDevices[i].SetActive(true);
+ }
+
+ return i;
+}
+
+void DeviceController::ReleaseDevice(Device * device)
+{
+ device->SetActive(false);
+}
+
+void DeviceController::ReleaseDevice(uint16_t index)
+{
+ if (index < kNumMaxActiveDevices)
+ {
+ ReleaseDevice(&mActiveDevices[index]);
+ }
+}
+
+uint16_t DeviceController::FindDeviceIndex(NodeId id)
+{
+ uint16_t i = 0;
+ while (i < kNumMaxActiveDevices)
+ {
+ if (mActiveDevices[i].IsActive() && mActiveDevices[i].GetDeviceId() == id)
+ {
+ return i;
+ }
+ i++;
+ }
+ return i;
+}
+
+CHIP_ERROR DeviceController::SetPairedDeviceList(const char * serialized)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ size_t len = strlen(serialized) + 1;
+ uint16_t lenU16 = static_cast<uint16_t>(len);
+ VerifyOrExit(CanCastTo<uint16_t>(len), err = CHIP_ERROR_INVALID_ARGUMENT);
+ err = mPairedDevices.DeserializeBase64(serialized, lenU16);
+
+exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(Controller, "Failed to recreate the device list\n");
+ }
+ else
+ {
+ mPairedDevicesInitialized = true;
+ }
+
+ return err;
+}
+
+void DeviceController::OnValue(const char * key, const char * value) {}
+
+void DeviceController::OnStatus(const char * key, Operation op, CHIP_ERROR err) {}
+
+DeviceCommissioner::DeviceCommissioner()
+{
+ mPairingDelegate = nullptr;
+ mRendezvousSession = nullptr;
+ mDeviceBeingPaired = kNumMaxActiveDevices;
+ mPairedDevicesUpdated = false;
+}
+
+CHIP_ERROR DeviceCommissioner::Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate,
+ DevicePairingDelegate * pairingDelegate, System::Layer * systemLayer,
+ Inet::InetLayer * inetLayer)
+{
+ CHIP_ERROR err = DeviceController::Init(localDeviceId, storageDelegate, systemLayer, inetLayer);
+ SuccessOrExit(err);
+
mPairingDelegate = pairingDelegate;
+
+exit:
+ return err;
+}
+
+CHIP_ERROR DeviceCommissioner::Shutdown()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+
+ ChipLogDetail(Controller, "Shutting down the commissioner");
+
+ PersistDeviceList();
+
+ if (mRendezvousSession != nullptr)
+ {
+ chip::Platform::Delete(mRendezvousSession);
+ mRendezvousSession = nullptr;
+ }
+
+ DeviceController::Shutdown();
+
+exit:
+ return err;
+}
+
+CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & params, uint16_t remotePort,
+ Inet::InterfaceId interfaceId)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ Device * device = nullptr;
+
+ VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrExit(mDeviceBeingPaired == kNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrExit(mStorageDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
+
+#if CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE
+ if (!params.HasBleLayer())
+ {
+ params.SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer());
+ }
+#endif // CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE
+
+ mDeviceBeingPaired = GetInactiveDeviceIndex();
+ VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY);
+ device = &mActiveDevices[mDeviceBeingPaired];
+
+ mRendezvousSession = chip::Platform::New<RendezvousSession>(this);
+ VerifyOrExit(mRendezvousSession != nullptr, err = CHIP_ERROR_NO_MEMORY);
+ err = mRendezvousSession->Init(params.SetLocalNodeId(mLocalDeviceId));
+ SuccessOrExit(err);
+
+ device->Init(mSessionManager, mInetLayer, remoteDeviceId, remotePort, interfaceId);
+
+exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ if (mRendezvousSession != nullptr)
+ {
+ chip::Platform::Delete(mRendezvousSession);
+ mRendezvousSession = nullptr;
+ }
+
+ if (device != nullptr)
+ {
+ ReleaseDevice(device);
+ mDeviceBeingPaired = kNumMaxActiveDevices;
+ }
+ }
+
+ return err;
+}
+
+CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDeviceId, const Inet::IPAddress & deviceAddr,
+ SerializedDevice & serialized, uint16_t remotePort,
+ Inet::InterfaceId interfaceId)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ Device * device = nullptr;
+
+ SecurePairingUsingTestSecret * testSecurePairingSecret = nullptr;
+
+ VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrExit(mDeviceBeingPaired == kNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE);
+
+ testSecurePairingSecret = chip::Platform::New<SecurePairingUsingTestSecret>(Optional<NodeId>::Value(remoteDeviceId),
+ static_cast<uint16_t>(0), static_cast<uint16_t>(0));
+ VerifyOrExit(testSecurePairingSecret != nullptr, err = CHIP_ERROR_NO_MEMORY);
+
+ mDeviceBeingPaired = GetInactiveDeviceIndex();
+ VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY);
+ device = &mActiveDevices[mDeviceBeingPaired];
+
+ testSecurePairingSecret->ToSerializable(device->GetPairing());
+
+ device->Init(mSessionManager, mInetLayer, remoteDeviceId, remotePort, interfaceId);
+
+ device->SetAddress(deviceAddr);
+
+ device->Serialize(serialized);
+
+ OnRendezvousComplete();
+
+exit:
+ if (testSecurePairingSecret != nullptr)
+ {
+ chip::Platform::Delete(testSecurePairingSecret);
+ }
+
+ if (err != CHIP_NO_ERROR)
+ {
+ if (device != nullptr)
+ {
+ ReleaseDevice(device);
+ mDeviceBeingPaired = kNumMaxActiveDevices;
+ }
+ }
+
+ return err;
+}
+CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ Device * device = nullptr;
+
+ VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+ VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE);
+
+ device = &mActiveDevices[mDeviceBeingPaired];
+ VerifyOrExit(device->GetDeviceId() == remoteDeviceId, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR);
+
+ if (mRendezvousSession != nullptr)
+ {
+ chip::Platform::Delete(mRendezvousSession);
+ mRendezvousSession = nullptr;
+ }
+
+ ReleaseDevice(device);
+ mDeviceBeingPaired = kNumMaxActiveDevices;
+
+exit:
+ return err;
+}
+
+CHIP_ERROR DeviceCommissioner::UnpairDevice(NodeId remoteDeviceId)
+{
+ // TODO: Send unpairing message to the remote device.
+
+ if (mStorageDelegate != nullptr)
+ {
+ PERSISTENT_KEY_OP(remoteDeviceId, kPairedDeviceKeyPrefix, key, mStorageDelegate->DeleteKeyValue(key));
+ mPairedDevices.Remove(remoteDeviceId);
+ mPairedDevicesUpdated = true;
+ }
+
return CHIP_NO_ERROR;
}
-void ChipDeviceController::ClearRequestState()
-{
- if (mCurReqMsg != nullptr)
- {
- PacketBuffer::Free(mCurReqMsg);
- mCurReqMsg = nullptr;
- }
-}
-
-void ChipDeviceController::OnNewConnection(Transport::PeerConnectionState * state, SecureSessionMgrBase * mgr) {}
-
-void ChipDeviceController::OnAddressResolved(CHIP_ERROR error, NodeId nodeId, SecureSessionMgrBase * mgr)
-{
- if (error == CHIP_NO_ERROR && nodeId == mSecurePairingSession->GetPeerNodeId() && mDeviceAddr == IPAddress::Any)
- {
- SendCachedPackets();
- }
-}
-
-void ChipDeviceController::OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader,
- Transport::PeerConnectionState * state, System::PacketBuffer * msgBuf,
- SecureSessionMgrBase * mgr)
-{
- if (header.GetSourceNodeId().HasValue())
- {
- if (!mRemoteDeviceId.HasValue())
- {
- ChipLogDetail(Controller, "Learned remote device id");
- mRemoteDeviceId = header.GetSourceNodeId();
- }
- else if (mRemoteDeviceId != header.GetSourceNodeId())
- {
- ChipLogError(Controller, "Received message from an unexpected source node id.");
- }
- }
- if (IsSecurelyConnected() && mOnComplete.Response != nullptr)
- {
- mOnComplete.Response(this, mAppReqState, msgBuf);
- }
-}
-
-void ChipDeviceController::OnRendezvousError(CHIP_ERROR err)
+void DeviceCommissioner::RendezvousCleanup(CHIP_ERROR status)
{
if (mRendezvousSession != nullptr)
{
@@ -659,74 +586,130 @@
if (mPairingDelegate != nullptr)
{
- mPairingDelegate->OnPairingComplete(err);
+ mPairingDelegate->OnPairingComplete(status);
}
-}
-void ChipDeviceController::OnRendezvousComplete()
-{
- OnRendezvousError(CHIP_NO_ERROR);
-}
-
-void ChipDeviceController::OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err)
-{
- if (mOnError != nullptr && err != CHIP_NO_ERROR)
+ if (mDeviceBeingPaired != kNumMaxActiveDevices)
{
- mOnError(this, mAppReqState, err, nullptr);
+ // Let's release the device that's being paired.
+ // If pairing was successful, its information is
+ // already persisted. The application will use GetDevice()
+ // method to get access to the device, which will fetch
+ // the device information from the persistent storage.
+ DeviceController::ReleaseDevice(mDeviceBeingPaired);
+ mDeviceBeingPaired = kNumMaxActiveDevices;
+ }
+}
+
+void DeviceCommissioner::OnRendezvousError(CHIP_ERROR err)
+{
+ RendezvousCleanup(err);
+}
+
+void DeviceCommissioner::OnRendezvousComplete()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ Device * device = nullptr;
+
+ VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR);
+ device = &mActiveDevices[mDeviceBeingPaired];
+ mPairedDevices.Insert(device->GetDeviceId());
+ mPairedDevicesUpdated = true;
+
+ // mStorageDelegate would not be null for a typical pairing scenario, as Pair()
+ // requires a valid storage delegate. However, test pairing usecase, that's used
+ // mainly by test applications, do not require a storage delegate. This is to
+ // reduce overheads on these tests.
+ // Let's make sure the delegate object is available before calling into it.
+ if (mStorageDelegate != nullptr)
+ {
+ SerializedDevice serialized;
+ device->Serialize(serialized);
+ PERSISTENT_KEY_OP(device->GetDeviceId(), kPairedDeviceKeyPrefix, key,
+ mStorageDelegate->SetKeyValue(key, Uint8::to_const_char(serialized.inner)));
}
+exit:
+ if (err == CHIP_NO_ERROR)
+ {
+ RendezvousCleanup(CHIP_NO_ERROR);
+ }
+ else
+ {
+ OnRendezvousError(err);
+ }
+}
+
+void DeviceCommissioner::OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err)
+{
+ Device * device = nullptr;
+ if (mDeviceBeingPaired >= kNumMaxActiveDevices)
+ {
+ ExitNow();
+ }
+
+ device = &mActiveDevices[mDeviceBeingPaired];
switch (status)
{
case RendezvousSessionDelegate::SecurePairingSuccess:
- ChipLogProgress(Controller, "Remote device completed SPAKE2+ handshake\n");
- mPairingSession = mRendezvousSession->GetPairingSession();
- mSecurePairingSession = &mPairingSession;
-
- if (mOnNewConnection)
- {
- ChipLogProgress(Controller, "Will Call on mOnNewConnection(%p)\n", mOnNewConnection);
- mOnNewConnection(this, nullptr, mAppReqState);
- }
+ ChipLogDetail(Controller, "Remote device completed SPAKE2+ handshake\n");
+ mRendezvousSession->GetPairingSession().ToSerializable(device->GetPairing());
if (mPairingDelegate != nullptr)
{
mPairingDelegate->OnNetworkCredentialsRequested(mRendezvousSession);
}
+ break;
- if (mStorageDelegate != nullptr)
- {
- SecurePairingSessionSerialized serialized;
- CHIP_ERROR err = mSecurePairingSession->Serialize(serialized);
- if (err == CHIP_NO_ERROR)
- {
- PERSISTENT_KEY_OP(mSecurePairingSession->GetPeerNodeId(), kDeviceCredentialsKeyPrefix, key,
- mStorageDelegate->SetKeyValue(key, Uint8::to_const_char(serialized.inner)));
- }
- }
+ case RendezvousSessionDelegate::SecurePairingFailed:
+ ChipLogDetail(Controller, "Remote device failed in SPAKE2+ handshake\n");
break;
case RendezvousSessionDelegate::NetworkProvisioningSuccess:
-
ChipLogDetail(Controller, "Remote device was assigned an ip address\n");
- mDeviceAddr = mRendezvousSession->GetIPAddress();
- if (mStorageDelegate != nullptr)
- {
- char addrStr[INET6_ADDRSTRLEN];
- mDeviceAddr.ToString(addrStr, INET6_ADDRSTRLEN);
- PERSISTENT_KEY_OP(mRendezvousSession->GetPairingSession().GetPeerNodeId(), kDeviceAddressKeyPrefix, key,
- mStorageDelegate->SetKeyValue(key, addrStr));
- }
+ device->SetAddress(mRendezvousSession->GetIPAddress());
+ break;
+
+ case RendezvousSessionDelegate::NetworkProvisioningFailed:
+ ChipLogDetail(Controller, "Remote device failed in network provisioning\n");
break;
default:
break;
};
-
+exit:
if (mPairingDelegate != nullptr)
{
mPairingDelegate->OnStatusUpdate(status);
}
}
-} // namespace DeviceController
+void DeviceCommissioner::PersistDeviceList()
+{
+ if (mStorageDelegate != nullptr && mPairedDevicesUpdated)
+ {
+ constexpr uint16_t size = CHIP_MAX_SERIALIZED_SIZE_U64(kNumMaxPairedDevices);
+ char * serialized = static_cast<char *>(chip::Platform::MemoryAlloc(size));
+ uint16_t requiredSize = size;
+ if (serialized != nullptr)
+ {
+ const char * value = mPairedDevices.SerializeBase64(serialized, requiredSize);
+ if (value != nullptr && requiredSize <= size)
+ {
+ PERSISTENT_KEY_OP(static_cast<uint64_t>(0), kPairedDeviceListKeyPrefix, key,
+ mStorageDelegate->SetKeyValue(key, value));
+ mPairedDevicesUpdated = false;
+ }
+ chip::Platform::MemoryFree(serialized);
+ }
+ }
+}
+
+void DeviceCommissioner::ReleaseDevice(Device * device)
+{
+ PersistDeviceList();
+ DeviceController::ReleaseDevice(device);
+}
+
+} // namespace Controller
} // namespace chip
diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h
index a115288..1e7ec69 100644
--- a/src/controller/CHIPDeviceController.h
+++ b/src/controller/CHIPDeviceController.h
@@ -28,28 +28,23 @@
#pragma once
+#include <controller/CHIPDevice.h>
#include <controller/CHIPPersistentStorageDelegate.h>
#include <core/CHIPCore.h>
#include <core/CHIPTLV.h>
#include <support/DLLUtil.h>
+#include <support/SerializableIntegerSet.h>
#include <transport/RendezvousSession.h>
#include <transport/RendezvousSessionDelegate.h>
#include <transport/SecureSessionMgr.h>
#include <transport/raw/UDP.h>
namespace chip {
-namespace DeviceController {
-constexpr uint16_t kPacketCacheMaxSize = 16;
+namespace Controller {
-class ChipDeviceController;
-
-typedef void (*NewConnectionHandler)(ChipDeviceController * deviceController, Transport::PeerConnectionState * state,
- void * appReqState);
-typedef void (*CompleteHandler)(ChipDeviceController * deviceController, void * appReqState);
-typedef void (*ErrorHandler)(ChipDeviceController * deviceController, void * appReqState, CHIP_ERROR err,
- const Inet::IPPacketInfo * pktInfo);
-typedef void (*MessageReceiveHandler)(ChipDeviceController * deviceController, void * appReqState, System::PacketBuffer * payload);
+constexpr uint16_t kNumMaxActiveDevices = 64;
+constexpr uint16_t kNumMaxPairedDevices = 128;
class DLL_EXPORT DevicePairingDelegate
{
@@ -100,117 +95,57 @@
virtual void OnPairingDeleted(CHIP_ERROR error) {}
};
-class DLL_EXPORT ChipDeviceController : public SecureSessionMgrDelegate,
- public RendezvousSessionDelegate,
- public PersistentStorageResultDelegate
+/**
+ * @brief
+ * Controller applications can use this class to communicate with already paired CHIP devices. The
+ * application is required to provide access to the persistent storage, where the paired device information
+ * is stored. This object of this class can be initialized with the data from the storage (List of devices,
+ * and device pairing information for individual devices). Alternatively, this class can retrieve the
+ * relevant information when the application tries to communicate with the device
+ */
+class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public PersistentStorageResultDelegate
{
- friend class ChipDeviceControllerCallback;
-
public:
- ChipDeviceController();
- ~ChipDeviceController();
-
- void * AppState;
+ DeviceController();
+ virtual ~DeviceController() {}
/**
* Init function to be used when there exists a device layer that takes care of initializing
* System::Layer and InetLayer.
*/
- CHIP_ERROR Init(NodeId localDeviceId, DevicePairingDelegate * pairingDelegate = nullptr,
- PersistentStorageDelegate * storageDelegate = nullptr);
- /**
- * Init function to be used when already-initialized System::Layer and InetLayer are available.
- */
- CHIP_ERROR Init(NodeId localDeviceId, System::Layer * systemLayer, Inet::InetLayer * inetLayer,
- DevicePairingDelegate * pairingDelegate = nullptr, PersistentStorageDelegate * storageDelegate = nullptr);
- CHIP_ERROR Shutdown();
+ CHIP_ERROR Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate = nullptr,
+ System::Layer * systemLayer = nullptr, Inet::InetLayer * inetLayer = nullptr);
- CHIP_ERROR SetUdpListenPort(uint16_t listenPort);
-
- // ----- Connection Management -----
- /**
- * @brief
- * Connect to a CHIP device with the provided Rendezvous connection parameters
- *
- * @param[in] remoteDeviceId The remote device Id.
- * @param[in] params The Rendezvous connection parameters
- * @param[in] appReqState Application specific context to be passed back when a message is received or on error
- * @param[in] onConnected Callback for when the connection is established
- * @param[in] onMessageReceived Callback for when a message is received
- * @param[in] onError Callback for when an error occurs
- * @param[in] devicePort [Optional] The CHIP Device's port, defaults to CHIP_PORT
- * @param[in] interfaceId [Optional] The interface indicator to use
- *
- * @return CHIP_ERROR The connection status
- */
- CHIP_ERROR ConnectDevice(NodeId remoteDeviceId, RendezvousParameters & params, void * appReqState,
- NewConnectionHandler onConnected, MessageReceiveHandler onMessageReceived, ErrorHandler onError,
- uint16_t devicePort = CHIP_PORT, Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID);
+ virtual CHIP_ERROR Shutdown();
/**
* @brief
- * Connect to a CHIP device at a given address and an optional port. This is a test only API
- * that bypasses Rendezvous and Secure Pairing process.
+ * This function deserializes the provided deviceInfo object, and initializes and outputs the
+ * corresponding Device object. The lifetime of the output object is tied to that of the DeviceController
+ * object. The caller must not use the Device object If they free the DeviceController object, or
+ * after they call ReleaseDevice() on the returned device object.
*
- * @param[in] remoteDeviceId The remote device Id.
- * @param[in] deviceAddr The IPAddress of the requested Device
- * @param[in] appReqState Application specific context to be passed back when a message is received or on error
- * @param[in] onConnected Callback for when the connection is established
- * @param[in] onMessageReceived Callback for when a message is received
- * @param[in] onError Callback for when an error occurs
- * @param[in] devicePort [Optional] The CHIP Device's port, defaults to CHIP_PORT
- * @param[in] interfaceId [Optional] The interface indicator to use
- * @return CHIP_ERROR The connection status
+ * @param[in] deviceId Node ID for the CHIP device
+ * @param[in] deviceInfo Serialized device info for the device
+ * @param[out] device The output device object
+ *
+ * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code.
*/
- [[deprecated("Available until Rendezvous is implemented")]] CHIP_ERROR
- ConnectDeviceWithoutSecurePairing(NodeId remoteDeviceId, const Inet::IPAddress & deviceAddr, void * appReqState,
- NewConnectionHandler onConnected, MessageReceiveHandler onMessageReceived,
- ErrorHandler onError, uint16_t devicePort = CHIP_PORT,
- Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID);
+ CHIP_ERROR GetDevice(NodeId deviceId, const SerializedDevice & deviceInfo, Device ** device);
/**
* @brief
- * Disconnect from a connected device
+ * This function is similar to the other GetDevice object, except it reads the serialized object from
+ * the persistent storage.
*
- * @return CHIP_ERROR If the device was disconnected successfully
+ * @param[in] deviceId Node ID for the CHIP device
+ * @param[out] device The output device object
+ *
+ * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code.
*/
- CHIP_ERROR DisconnectDevice();
+ CHIP_ERROR GetDevice(NodeId deviceId, Device ** device);
- /**
- * @brief
- * Check if there's an active connection
- *
- * @return bool If there is an active connection
- */
- bool IsConnected() const;
-
- /**
- * @brief
- * Check if the connection is active and security context is established
- *
- * @return bool If the connection is active and security context is established
- */
- bool IsSecurelyConnected() const;
-
- /**
- * @brief
- * Get IP Address of the peer if the connection is active
- *
- * @return bool If IP Address was returned
- */
- bool GetIpAddress(Inet::IPAddress & addr) const;
-
- // ----- Messaging -----
- /**
- * @brief
- * Send a message to a connected CHIP device
- *
- * @param[in] appReqState Application specific context to be passed back when a message is received or on error
- * @param[in] buffer The Data Buffer to trasmit to the device
- * @param[in] peerDevice Device ID of the peer device
- * @return CHIP_ERROR The return status
- */
- CHIP_ERROR SendMessage(void * appReqState, System::PacketBuffer * buffer, NodeId peerDevice = kUndefinedNodeId);
+ virtual void ReleaseDevice(Device * device);
// ----- IO -----
/**
@@ -220,14 +155,6 @@
*/
CHIP_ERROR ServiceEvents();
- // ----- Pairing -----
- /**
- * @brief
- * Set device pairing delegate after init, pass nullptr remove device delegate.
- * @return CHIP_ERROR The return status
- */
- CHIP_ERROR SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate);
-
/**
* @brief
* Allow the CHIP Stack to process any pending events
@@ -236,86 +163,142 @@
*/
CHIP_ERROR ServiceEventSignal();
+protected:
+ enum class State
+ {
+ NotInitialized,
+ Initialized
+ };
+
+ State mState;
+
+ /* A list of device objects that can be used for communicating with corresponding
+ CHIP devices. The list does not contain all the paired devices, but only the ones
+ which the controller application is currently accessing.
+ */
+ Device mActiveDevices[kNumMaxActiveDevices];
+
+ SerializableU64Set<kNumMaxPairedDevices> mPairedDevices;
+ bool mPairedDevicesInitialized;
+
+ NodeId mLocalDeviceId;
+ SecureSessionMgr<Transport::UDP> * mSessionManager;
+ PersistentStorageDelegate * mStorageDelegate;
+ Inet::InetLayer * mInetLayer;
+
+ uint16_t GetInactiveDeviceIndex();
+ uint16_t FindDeviceIndex(NodeId id);
+ void ReleaseDevice(uint16_t index);
+ CHIP_ERROR SetPairedDeviceList(const char * pairedDeviceSerializedSet);
+
+private:
+ //////////// SecureSessionMgrDelegate Implementation ///////////////
void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, Transport::PeerConnectionState * state,
System::PacketBuffer * msgBuf, SecureSessionMgrBase * mgr) override;
void OnNewConnection(Transport::PeerConnectionState * state, SecureSessionMgrBase * mgr) override;
- void OnAddressResolved(CHIP_ERROR error, NodeId nodeId, SecureSessionMgrBase * mgr) override;
+ //////////// PersistentStorageResultDelegate Implementation ///////////////
+ void OnValue(const char * key, const char * value) override;
+ void OnStatus(const char * key, Operation op, CHIP_ERROR err) override;
+
+ System::Layer * mSystemLayer;
+};
+
+/**
+ * @brief
+ * The commissioner applications can use this class to pair new/unpaired CHIP devices. The application is
+ * required to provide write access to the persistent storage, where the paired device information
+ * will be stored.
+ */
+class DLL_EXPORT DeviceCommissioner : public DeviceController, public RendezvousSessionDelegate
+{
+public:
+ DeviceCommissioner();
+ ~DeviceCommissioner() {}
+
+ /**
+ * Init function to be used when there exists a device layer that takes care of initializing
+ * System::Layer and InetLayer.
+ */
+ CHIP_ERROR Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate = nullptr,
+ DevicePairingDelegate * pairingDelegate = nullptr, System::Layer * systemLayer = nullptr,
+ Inet::InetLayer * inetLayer = nullptr);
+
+ void SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate) { mPairingDelegate = pairingDelegate; }
+
+ CHIP_ERROR Shutdown() override;
+
+ // ----- Connection Management -----
+ /**
+ * @brief
+ * Pair a CHIP device with the provided Rendezvous connection parameters.
+ * Use registered DevicePairingDelegate object to receive notifications on
+ * pairing status updates.
+ *
+ * Note: Pairing process requires that the caller has registered PersistentStorageDelegate
+ * in the Init() call.
+ *
+ * @param[in] remoteDeviceId The remote device Id.
+ * @param[in] params The Rendezvous connection parameters
+ * @param[in] devicePort [Optional] The CHIP Device's port, defaults to CHIP_PORT
+ * @param[in] interfaceId [Optional] The local inet interface to use to communicate with the device.
+ *
+ * @return CHIP_ERROR The connection status
+ */
+ CHIP_ERROR PairDevice(NodeId remoteDeviceId, RendezvousParameters & params, uint16_t devicePort = CHIP_PORT,
+ Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID);
+
+ [[deprecated("Available until Rendezvous is implemented")]] CHIP_ERROR
+ PairTestDeviceWithoutSecurity(NodeId remoteDeviceId, const Inet::IPAddress & deviceAddr, SerializedDevice & serialized,
+ uint16_t devicePort = CHIP_PORT, Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID);
+
+ /**
+ * @brief
+ * This function stops a pairing process that's in progress. It does not delete the pairing of a previously
+ * paired device.
+ *
+ * @param[in] remoteDeviceId The remote device Id.
+ *
+ * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error
+ */
+ CHIP_ERROR StopPairing(NodeId remoteDeviceId);
+
+ /**
+ * @brief
+ * Remove pairing for a paired device. If the device is currently being paired, it'll stop the pairing process.
+ *
+ * @param[in] remoteDeviceId The remote device Id.
+ *
+ * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error
+ */
+ CHIP_ERROR UnpairDevice(NodeId remoteDeviceId);
//////////// RendezvousSessionDelegate Implementation ///////////////
void OnRendezvousError(CHIP_ERROR err) override;
void OnRendezvousComplete() override;
void OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) override;
- //////////// PersistentStorageResultDelegate Implementation ///////////////
- void OnValue(const char * key, const char * value) override;
- void OnStatus(const char * key, Operation op, CHIP_ERROR err) override;
+ void RendezvousCleanup(CHIP_ERROR status);
+
+ void ReleaseDevice(Device * device) override;
private:
- enum
- {
- kState_NotInitialized = 0,
- kState_Initialized = 1
- } mState;
-
- enum ConnectionState
- {
- kConnectionState_NotConnected = 0,
- kConnectionState_Connected = 1,
- kConnectionState_SecureConnecting = 2,
- kConnectionState_SecureConnected = 3,
- };
-
- System::Layer * mSystemLayer;
- Inet::InetLayer * mInetLayer;
-
- SecureSessionMgr<Transport::UDP> * mSessionManager;
+ DevicePairingDelegate * mPairingDelegate;
RendezvousSession * mRendezvousSession;
- ConnectionState mConState;
- void * mAppReqState;
+ /* This field is an index in mActiveDevices list. The object at this index in the list
+ contains the device object that's tracking the state of the device that's being paired.
+ If no device is currently being paired, this value will be kNumMaxPairedDevices. */
+ uint16_t mDeviceBeingPaired;
- union
- {
- CompleteHandler General;
- MessageReceiveHandler Response;
- } mOnComplete;
+ /* This field is true when device pairing information changes, e.g. a new device is paired, or
+ the pairing for a device is removed. The DeviceCommissioner uses this to decide when to
+ persist the device list */
+ bool mPairedDevicesUpdated;
- ErrorHandler mOnError;
- NewConnectionHandler mOnNewConnection;
- System::PacketBuffer * mCurReqMsg;
-
- NodeId mLocalDeviceId;
- uint16_t mListenPort;
- Inet::IPAddress mDeviceAddr;
- uint16_t mDevicePort;
- Inet::InterfaceId mInterface;
- Optional<NodeId> mRemoteDeviceId;
-
- SecurePairingSession mPairingSession;
- SecurePairingUsingTestSecret * mTestSecurePairingSecret = nullptr;
-
- SecurePairingSession * mSecurePairingSession = nullptr;
-
- DevicePairingDelegate * mPairingDelegate = nullptr;
-
- PersistentStorageDelegate * mStorageDelegate;
-
- System::PacketBuffer * mCachedPackets[kPacketCacheMaxSize];
- uint16_t mNumCachedPackets;
-
- void ClearRequestState();
- void ClearOpState();
-
- CHIP_ERROR EstablishSecureSession();
- CHIP_ERROR TryEstablishingSecureSession(NodeId peer);
- CHIP_ERROR ResumeSecureSession(NodeId peer);
-
- CHIP_ERROR CachePacket(System::PacketBuffer * buffer);
- CHIP_ERROR SendCachedPackets();
- void DiscardCachedPackets();
+ void PersistDeviceList();
};
-} // namespace DeviceController
+} // namespace Controller
} // namespace chip
diff --git a/src/controller/CHIPDeviceController_deprecated.cpp b/src/controller/CHIPDeviceController_deprecated.cpp
new file mode 100644
index 0000000..eaaa237
--- /dev/null
+++ b/src/controller/CHIPDeviceController_deprecated.cpp
@@ -0,0 +1,239 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2013-2017 Nest Labs, Inc.
+ * 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.
+ */
+
+/**
+ * @file
+ * Implementation of CHIP Device Controller, a common class
+ * that implements discovery, pairing and provisioning of CHIP
+ * devices.
+ *
+ */
+
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+// module header, comes first
+#include <controller/CHIPDeviceController_deprecated.h>
+
+#if CONFIG_DEVICE_LAYER
+#include <platform/CHIPDeviceLayer.h>
+#endif
+
+#include <core/CHIPCore.h>
+#include <core/CHIPEncoding.h>
+#include <core/CHIPSafeCasts.h>
+#include <support/Base64.h>
+#include <support/CHIPMem.h>
+#include <support/CodeUtils.h>
+#include <support/ErrorStr.h>
+#include <support/TimeUtils.h>
+#include <support/logging/CHIPLogging.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <time.h>
+
+using namespace chip::Inet;
+using namespace chip::System;
+using namespace chip::Controller;
+
+namespace chip {
+namespace DeviceController {
+
+using namespace chip::Encoding;
+
+ChipDeviceController::ChipDeviceController()
+{
+ mState = kState_NotInitialized;
+ AppState = nullptr;
+ mCurReqMsg = nullptr;
+ mOnError = nullptr;
+ mOnNewConnection = nullptr;
+ mListenPort = CHIP_PORT;
+ mLocalDeviceId = kUndefinedNodeId;
+ mRemoteDeviceId = kUndefinedNodeId;
+ mDevice = nullptr;
+ mPairingWithoutSecurity = false;
+ CHIP_ZERO_AT(mOnComplete);
+}
+
+ChipDeviceController::~ChipDeviceController() {}
+
+CHIP_ERROR ChipDeviceController::Init(NodeId localNodeId, DevicePairingDelegate * pairingDelegate,
+ PersistentStorageDelegate * storageDelegate)
+{
+ return mCommissioner.Init(localNodeId, storageDelegate, pairingDelegate);
+}
+
+CHIP_ERROR ChipDeviceController::Init(NodeId localNodeId, System::Layer * systemLayer, InetLayer * inetLayer,
+ DevicePairingDelegate * pairingDelegate, PersistentStorageDelegate * storageDelegate)
+{
+ return mCommissioner.Init(localNodeId, storageDelegate, pairingDelegate, systemLayer, inetLayer);
+}
+
+CHIP_ERROR ChipDeviceController::Shutdown()
+{
+ return mCommissioner.Shutdown();
+}
+
+CHIP_ERROR ChipDeviceController::ConnectDevice(NodeId remoteDeviceId, RendezvousParameters & params, void * appReqState,
+ NewConnectionHandler onConnected, MessageReceiveHandler onMessageReceived,
+ ErrorHandler onError, uint16_t devicePort, Inet::InterfaceId interfaceId)
+{
+ CHIP_ERROR err = mCommissioner.PairDevice(remoteDeviceId, params, devicePort, interfaceId);
+ SuccessOrExit(err);
+
+ mRemoteDeviceId = remoteDeviceId;
+ mAppReqState = appReqState;
+ mOnNewConnection = onConnected;
+
+ mOnComplete.Response = onMessageReceived;
+ mOnError = onError;
+
+exit:
+ return err;
+}
+
+CHIP_ERROR ChipDeviceController::ConnectDeviceWithoutSecurePairing(NodeId remoteDeviceId, const IPAddress & deviceAddr,
+ void * appReqState, NewConnectionHandler onConnected,
+ MessageReceiveHandler onMessageReceived, ErrorHandler onError,
+ uint16_t devicePort, Inet::InterfaceId interfaceId)
+{
+ CHIP_ERROR err =
+ mCommissioner.PairTestDeviceWithoutSecurity(remoteDeviceId, deviceAddr, mSerializedTestDevice, devicePort, interfaceId);
+ SuccessOrExit(err);
+
+ mPairingWithoutSecurity = true;
+
+ mRemoteDeviceId = remoteDeviceId;
+ mAppReqState = appReqState;
+ mOnNewConnection = onConnected;
+
+ mOnComplete.Response = onMessageReceived;
+ mOnError = onError;
+
+ if (mOnNewConnection)
+ {
+ mOnNewConnection(this, nullptr, mAppReqState);
+ }
+
+exit:
+ return err;
+}
+
+CHIP_ERROR ChipDeviceController::SetUdpListenPort(uint16_t listenPort)
+{
+ if (mState != kState_Initialized)
+ return CHIP_ERROR_INCORRECT_STATE;
+ mListenPort = listenPort;
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ChipDeviceController::ServiceEvents()
+{
+ return mCommissioner.ServiceEvents();
+}
+
+CHIP_ERROR ChipDeviceController::ServiceEventSignal()
+{
+ return mCommissioner.ServiceEventSignal();
+}
+
+bool ChipDeviceController::IsConnected() const
+{
+ return mState == kState_Initialized;
+}
+
+bool ChipDeviceController::GetIpAddress(Inet::IPAddress & addr) const
+{
+ if (IsConnected() && mDevice != nullptr)
+ return mDevice->GetIpAddress(addr);
+
+ return false;
+}
+
+CHIP_ERROR ChipDeviceController::DisconnectDevice()
+{
+ if (mDevice != nullptr)
+ {
+ mCommissioner.ReleaseDevice(mDevice);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ChipDeviceController::SendMessage(void * appReqState, PacketBuffer * buffer, NodeId peerDevice)
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ VerifyOrExit(buffer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+ mAppReqState = appReqState;
+
+ if (peerDevice != kUndefinedNodeId)
+ {
+ mRemoteDeviceId = peerDevice;
+ }
+ VerifyOrExit(mRemoteDeviceId != kUndefinedNodeId, err = CHIP_ERROR_INCORRECT_STATE);
+
+ if (mDevice == nullptr)
+ {
+ if (mPairingWithoutSecurity)
+ {
+ err = mCommissioner.GetDevice(mRemoteDeviceId, mSerializedTestDevice, &mDevice);
+ }
+ else
+ {
+ err = mCommissioner.GetDevice(mRemoteDeviceId, &mDevice);
+ }
+ SuccessOrExit(err);
+ }
+
+ VerifyOrExit(mDevice != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
+ mDevice->SetDelegate(this);
+
+ err = mDevice->SendMessage(buffer);
+
+exit:
+
+ return err;
+}
+
+CHIP_ERROR ChipDeviceController::SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate)
+{
+ mCommissioner.SetDevicePairingDelegate(pairingDelegate);
+ return CHIP_NO_ERROR;
+}
+
+void ChipDeviceController::OnMessage(System::PacketBuffer * msgBuf)
+{
+ if (mOnComplete.Response != nullptr)
+ {
+ mOnComplete.Response(this, mAppReqState, msgBuf);
+ }
+}
+
+} // namespace DeviceController
+} // namespace chip
diff --git a/src/controller/CHIPDeviceController_deprecated.h b/src/controller/CHIPDeviceController_deprecated.h
new file mode 100644
index 0000000..d1bf836
--- /dev/null
+++ b/src/controller/CHIPDeviceController_deprecated.h
@@ -0,0 +1,220 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2013-2017 Nest Labs, Inc.
+ * 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.
+ */
+
+/**
+ * @file
+ * Declaration of CHIP Device Controller, a common class
+ * that implements connecting and messaging and will later
+ * be expanded to support discovery, pairing and
+ * provisioning of CHIP devices.
+ *
+ */
+
+#pragma once
+
+#include <controller/CHIPDeviceController.h>
+#include <controller/CHIPPersistentStorageDelegate.h>
+#include <core/CHIPCore.h>
+#include <core/CHIPTLV.h>
+#include <support/DLLUtil.h>
+#include <transport/RendezvousSession.h>
+#include <transport/RendezvousSessionDelegate.h>
+#include <transport/SecureSessionMgr.h>
+#include <transport/raw/UDP.h>
+
+namespace chip {
+namespace DeviceController {
+
+constexpr uint16_t kPacketCacheMaxSize = 16;
+
+class ChipDeviceController;
+
+typedef void (*NewConnectionHandler)(ChipDeviceController * deviceController, Transport::PeerConnectionState * state,
+ void * appReqState);
+typedef void (*CompleteHandler)(ChipDeviceController * deviceController, void * appReqState);
+typedef void (*ErrorHandler)(ChipDeviceController * deviceController, void * appReqState, CHIP_ERROR err,
+ const Inet::IPPacketInfo * pktInfo);
+typedef void (*MessageReceiveHandler)(ChipDeviceController * deviceController, void * appReqState, System::PacketBuffer * payload);
+
+class DLL_EXPORT ChipDeviceController : public Controller::DeviceStatusDelegate
+{
+ friend class ChipDeviceControllerCallback;
+
+public:
+ ChipDeviceController();
+ ~ChipDeviceController();
+
+ void * AppState;
+
+ /**
+ * Init function to be used when there exists a device layer that takes care of initializing
+ * System::Layer and InetLayer.
+ */
+ CHIP_ERROR Init(NodeId localDeviceId, Controller::DevicePairingDelegate * pairingDelegate = nullptr,
+ Controller::PersistentStorageDelegate * storageDelegate = nullptr);
+ /**
+ * Init function to be used when already-initialized System::Layer and InetLayer are available.
+ */
+ CHIP_ERROR Init(NodeId localDeviceId, System::Layer * systemLayer, Inet::InetLayer * inetLayer,
+ Controller::DevicePairingDelegate * pairingDelegate = nullptr,
+ Controller::PersistentStorageDelegate * storageDelegate = nullptr);
+ CHIP_ERROR Shutdown();
+
+ CHIP_ERROR SetUdpListenPort(uint16_t listenPort);
+
+ // ----- Connection Management -----
+ /**
+ * @brief
+ * Connect to a CHIP device with the provided Rendezvous connection parameters
+ *
+ * @param[in] remoteDeviceId The remote device Id.
+ * @param[in] params The Rendezvous connection parameters
+ * @param[in] appReqState Application specific context to be passed back when a message is received or on error
+ * @param[in] onConnected Callback for when the connection is established
+ * @param[in] onMessageReceived Callback for when a message is received
+ * @param[in] onError Callback for when an error occurs
+ * @param[in] devicePort [Optional] The CHIP Device's port, defaults to CHIP_PORT
+ * @param[in] interfaceId [Optional] The interface indicator to use
+ *
+ * @return CHIP_ERROR The connection status
+ */
+ [[deprecated("Available until controller apps move to DeviceController/DeviceCommissioner API")]] CHIP_ERROR
+ ConnectDevice(NodeId remoteDeviceId, RendezvousParameters & params, void * appReqState, NewConnectionHandler onConnected,
+ MessageReceiveHandler onMessageReceived, ErrorHandler onError, uint16_t devicePort = CHIP_PORT,
+ Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID);
+
+ /**
+ * @brief
+ * Connect to a CHIP device at a given address and an optional port. This is a test only API
+ * that bypasses Rendezvous and Secure Pairing process.
+ *
+ * @param[in] remoteDeviceId The remote device Id.
+ * @param[in] deviceAddr The IPAddress of the requested Device
+ * @param[in] appReqState Application specific context to be passed back when a message is received or on error
+ * @param[in] onConnected Callback for when the connection is established
+ * @param[in] onMessageReceived Callback for when a message is received
+ * @param[in] onError Callback for when an error occurs
+ * @param[in] devicePort [Optional] The CHIP Device's port, defaults to CHIP_PORT
+ * @param[in] interfaceId [Optional] The interface indicator to use
+ * @return CHIP_ERROR The connection status
+ */
+ [[deprecated("Available until Rendezvous is implemented")]] CHIP_ERROR
+ ConnectDeviceWithoutSecurePairing(NodeId remoteDeviceId, const Inet::IPAddress & deviceAddr, void * appReqState,
+ NewConnectionHandler onConnected, MessageReceiveHandler onMessageReceived,
+ ErrorHandler onError, uint16_t devicePort = CHIP_PORT,
+ Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID);
+
+ /**
+ * @brief
+ * Disconnect from a connected device
+ *
+ * @return CHIP_ERROR If the device was disconnected successfully
+ */
+ CHIP_ERROR DisconnectDevice();
+
+ /**
+ * @brief
+ * Check if there's an active connection
+ *
+ * @return bool If there is an active connection
+ */
+ bool IsConnected() const;
+
+ /**
+ * @brief
+ * Get IP Address of the peer if the connection is active
+ *
+ * @return bool If IP Address was returned
+ */
+ bool GetIpAddress(Inet::IPAddress & addr) const;
+
+ // ----- Messaging -----
+ /**
+ * @brief
+ * Send a message to a connected CHIP device
+ *
+ * @param[in] appReqState Application specific context to be passed back when a message is received or on error
+ * @param[in] buffer The Data Buffer to trasmit to the device
+ * @param[in] peerDevice Device ID of the peer device
+ * @return CHIP_ERROR The return status
+ */
+ CHIP_ERROR SendMessage(void * appReqState, System::PacketBuffer * buffer, NodeId peerDevice = kUndefinedNodeId);
+
+ // ----- IO -----
+ /**
+ * @brief
+ * Start the event loop task within the CHIP stack
+ * @return CHIP_ERROR The return status
+ */
+ CHIP_ERROR ServiceEvents();
+
+ /**
+ * @brief
+ * Allow the CHIP Stack to process any pending events
+ * This can be called in an event handler loop to tigger callbacks within the CHIP stack
+ * @return CHIP_ERROR The return status
+ */
+ CHIP_ERROR ServiceEventSignal();
+
+ // ----- Pairing -----
+ /**
+ * @brief
+ * Set device pairing delegate after init, pass nullptr remove device delegate.
+ * @return CHIP_ERROR The return status
+ */
+ CHIP_ERROR SetDevicePairingDelegate(Controller::DevicePairingDelegate * pairingDelegate);
+
+ //////////// DeviceStatusDelegate Implementation ///////////////
+ void OnMessage(System::PacketBuffer * msg) override;
+
+private:
+ enum
+ {
+ kState_NotInitialized = 0,
+ kState_Initialized = 1
+ } mState;
+
+ Controller::DeviceCommissioner mCommissioner;
+ Controller::Device * mDevice;
+
+ void * mAppReqState;
+
+ union
+ {
+ CompleteHandler General;
+ MessageReceiveHandler Response;
+ } mOnComplete;
+
+ ErrorHandler mOnError;
+ NewConnectionHandler mOnNewConnection;
+ System::PacketBuffer * mCurReqMsg;
+
+ NodeId mLocalDeviceId;
+ NodeId mRemoteDeviceId;
+ uint16_t mListenPort;
+
+ Controller::SerializedDevice mSerializedTestDevice;
+ bool mPairingWithoutSecurity;
+
+ void ClearRequestState();
+ void ClearOpState();
+};
+
+} // namespace DeviceController
+} // namespace chip
diff --git a/src/controller/CHIPPersistentStorageDelegate.h b/src/controller/CHIPPersistentStorageDelegate.h
index 1414477..a2176f2 100644
--- a/src/controller/CHIPPersistentStorageDelegate.h
+++ b/src/controller/CHIPPersistentStorageDelegate.h
@@ -22,7 +22,7 @@
#include <support/DLLUtil.h>
namespace chip {
-namespace DeviceController {
+namespace Controller {
class DLL_EXPORT PersistentStorageResultDelegate
{
@@ -81,6 +81,21 @@
/**
* @brief
+ * This is a synchronous Get API, where the value is returned via the output
+ * buffer. This API should be used sparingly, since it may block for
+ * some duration.
+ *
+ * @param[in] key Key to lookup
+ * @param[out] value Value for the key
+ * @param[in, out] size Input value buffer size, output length of value.
+ * The output length could be larger than input value. In
+ * such cases, the user should allocate the buffer large
+ * enough (>= output length), and call the API again.
+ */
+ virtual CHIP_ERROR GetKeyValue(const char * key, char * value, uint16_t & size) { return CHIP_ERROR_NOT_IMPLEMENTED; }
+
+ /**
+ * @brief
* Set the value for the key
*
* @param[in] key Key to be set
@@ -97,5 +112,5 @@
virtual void DeleteKeyValue(const char * key) = 0;
};
-} // namespace DeviceController
+} // namespace Controller
} // namespace chip
diff --git a/src/controller/java/AndroidDeviceControllerWrapper.h b/src/controller/java/AndroidDeviceControllerWrapper.h
index a2715f8..59eb1fe 100644
--- a/src/controller/java/AndroidDeviceControllerWrapper.h
+++ b/src/controller/java/AndroidDeviceControllerWrapper.h
@@ -21,7 +21,7 @@
#include <jni.h>
-#include <controller/CHIPDeviceController.h>
+#include <controller/CHIPDeviceController_deprecated.h>
/**
* This class contains all relevant information for the JNI view of CHIPDeviceController
@@ -29,7 +29,7 @@
*
* Generally it contains the DeviceController class itself, plus any related delegates/callbacks.
*/
-class AndroidDeviceControllerWrapper : public chip::DeviceController::DevicePairingDelegate
+class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDelegate
{
public:
~AndroidDeviceControllerWrapper();
diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp
index 007e53e..721d8a7 100644
--- a/src/controller/java/CHIPDeviceController-JNI.cpp
+++ b/src/controller/java/CHIPDeviceController-JNI.cpp
@@ -28,7 +28,7 @@
#include "AndroidDeviceControllerWrapper.h"
#include <ble/BleUUID.h>
-#include <controller/CHIPDeviceController.h>
+#include <controller/CHIPDeviceController_deprecated.h>
#include <jni.h>
#include <pthread.h>
#include <support/CHIPMem.h>
diff --git a/src/controller/python/BUILD.gn b/src/controller/python/BUILD.gn
index dd9407a..84b22a1 100644
--- a/src/controller/python/BUILD.gn
+++ b/src/controller/python/BUILD.gn
@@ -23,7 +23,8 @@
}
config("includes") {
- include_dirs = [ "${chip_root}/src/controller/CHIPDeviceController.h" ]
+ include_dirs =
+ [ "${chip_root}/src/controller/CHIPDeviceController_deprecated.h" ]
}
shared_library("ChipDeviceCtrl") {
diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp
index 18f6c02..8e9e927 100644
--- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp
+++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp
@@ -45,7 +45,7 @@
#include "ChipDeviceController-ScriptDevicePairingDelegate.h"
-#include <controller/CHIPDeviceController.h>
+#include <controller/CHIPDeviceController_deprecated.h>
#include <support/CHIPMem.h>
#include <support/CodeUtils.h>
#include <support/DLLUtil.h>
@@ -178,7 +178,7 @@
nl_Chip_ScriptDevicePairingDelegate_SetWifiCredential(chip::DeviceController::ScriptDevicePairingDelegate * pairingDelegate,
const char * ssid, const char * password);
CHIP_ERROR nl_Chip_DeviceController_SetDevicePairingDelegate(chip::DeviceController::ChipDeviceController * devCtrl,
- chip::DeviceController::DevicePairingDelegate * pairingDelegate);
+ chip::Controller::DevicePairingDelegate * pairingDelegate);
#if CONFIG_NETWORK_LAYER_BLE
CHIP_ERROR nl_Chip_DeviceController_ValidateBTP(chip::DeviceController::ChipDeviceController * devCtrl,
@@ -583,7 +583,7 @@
return err;
}
CHIP_ERROR nl_Chip_DeviceController_SetDevicePairingDelegate(chip::DeviceController::ChipDeviceController * devCtrl,
- chip::DeviceController::DevicePairingDelegate * pairingDelegate)
+ chip::Controller::DevicePairingDelegate * pairingDelegate)
{
CHIP_ERROR err = CHIP_NO_ERROR;
diff --git a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h
index 17b51a6..3a821bf 100644
--- a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h
+++ b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h
@@ -25,7 +25,7 @@
#pragma once
-#include <controller/CHIPDeviceController.h>
+#include <controller/CHIPDeviceController_deprecated.h>
#include <platform/internal/DeviceNetworkInfo.h>
#include <transport/RendezvousSessionDelegate.h>
@@ -33,7 +33,7 @@
namespace chip {
namespace DeviceController {
-class ScriptDevicePairingDelegate final : public DevicePairingDelegate
+class ScriptDevicePairingDelegate final : public Controller::DevicePairingDelegate
{
public:
~ScriptDevicePairingDelegate() = default;
diff --git a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m
index be0c0fc..fcc9d05 100644
--- a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m
+++ b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m
@@ -48,9 +48,17 @@
- (void)GetKeyValue:(NSString *)key handler:(SendKeyValue)completionHandler
{
NSString * value = CHIPGetDomainValueForKey(kCHIPToolDefaultsDomain, key);
+ NSLog(@"CHIPPersistentStorageDelegate Get Value for Key: %@, value %@", key, value);
completionHandler(key, value);
}
+- (NSString *)GetKeyValue:(NSString *)key
+{
+ NSString * value = CHIPGetDomainValueForKey(kCHIPToolDefaultsDomain, key);
+ NSLog(@"CHIPPersistentStorageDelegate Get Value for Key: %@, value %@", key, value);
+ return value;
+}
+
- (void)SetKeyValue:(NSString *)key value:(NSString *)value handler:(SendStatus)completionHandler
{
CHIPSetDomainValueForKey(kCHIPToolDefaultsDomain, key, value);
diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm
index 3d57db3..faa2d56 100644
--- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm
+++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm
@@ -25,7 +25,7 @@
#import "CHIPLogging.h"
#import "CHIPPersistentStorageDelegateBridge.h"
-#include <controller/CHIPDeviceController.h>
+#include <controller/CHIPDeviceController_deprecated.h>
#include <inet/IPAddress.h>
#include <support/CHIPMem.h>
#include <system/SystemPacketBuffer.h>
@@ -95,6 +95,11 @@
return nil;
}
+ if (CHIP_NO_ERROR != chip::Platform::MemoryInit()) {
+ CHIP_LOG_ERROR("Error: Failed in memory init");
+ return nil;
+ }
+
_cppController = new chip::DeviceController::ChipDeviceController();
if (!_cppController) {
CHIP_LOG_ERROR("Error: couldn't create c++ controller");
@@ -129,17 +134,6 @@
_persistentStorageDelegateBridge = NULL;
return nil;
}
-
- if (CHIP_NO_ERROR != chip::Platform::MemoryInit()) {
- CHIP_LOG_ERROR("Error: couldn't initialize c++ controller");
- delete _cppController;
- _cppController = NULL;
- delete _pairingDelegateBridge;
- _pairingDelegateBridge = NULL;
- delete _persistentStorageDelegateBridge;
- _persistentStorageDelegateBridge = NULL;
- return nil;
- }
}
return self;
}
diff --git a/src/darwin/Framework/CHIP/CHIPDevicePairingDelegateBridge.h b/src/darwin/Framework/CHIP/CHIPDevicePairingDelegateBridge.h
index b448c06..884c17b 100644
--- a/src/darwin/Framework/CHIP/CHIPDevicePairingDelegateBridge.h
+++ b/src/darwin/Framework/CHIP/CHIPDevicePairingDelegateBridge.h
@@ -22,7 +22,7 @@
NS_ASSUME_NONNULL_BEGIN
-class CHIPDevicePairingDelegateBridge : public chip::DeviceController::DevicePairingDelegate
+class CHIPDevicePairingDelegateBridge : public chip::Controller::DevicePairingDelegate
{
public:
CHIPDevicePairingDelegateBridge();
diff --git a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegate.h b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegate.h
index 916b1f4..b59cce2 100644
--- a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegate.h
+++ b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegate.h
@@ -44,6 +44,12 @@
- (void)GetKeyValue:(NSString *)key handler:(SendKeyValue)completionHandler;
/**
+ * Get the value for the given key
+ *
+ */
+- (NSString *)GetKeyValue:(NSString *)key;
+
+/**
* Set the value of the key to the given value
*
*/
diff --git a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h
index fe9645b..bb689a0 100644
--- a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h
+++ b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h
@@ -22,7 +22,7 @@
NS_ASSUME_NONNULL_BEGIN
-class CHIPPersistentStorageDelegateBridge : public chip::DeviceController::PersistentStorageDelegate
+class CHIPPersistentStorageDelegateBridge : public chip::Controller::PersistentStorageDelegate
{
public:
CHIPPersistentStorageDelegateBridge();
@@ -30,10 +30,12 @@
void setFrameworkDelegate(id<CHIPPersistentStorageDelegate> delegate, dispatch_queue_t queue);
- void SetDelegate(chip::DeviceController::PersistentStorageResultDelegate * delegate);
+ void SetDelegate(chip::Controller::PersistentStorageResultDelegate * delegate);
void GetKeyValue(const char * key) override;
+ CHIP_ERROR GetKeyValue(const char * key, char * value, uint16_t & size) override;
+
void SetKeyValue(const char * key, const char * value) override;
void DeleteKeyValue(const char * key) override;
@@ -42,7 +44,7 @@
id<CHIPPersistentStorageDelegate> mDelegate;
dispatch_queue_t mQueue;
- chip::DeviceController::PersistentStorageResultDelegate * mCallback;
+ chip::Controller::PersistentStorageResultDelegate * mCallback;
SendKeyValue mCompletionHandler;
SendStatus mStatusHandler;
NSUserDefaults * mDefaultPersistentStorage;
diff --git a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm
index 51a7444..92f3862 100644
--- a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm
+++ b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm
@@ -39,7 +39,7 @@
}
}
-void CHIPPersistentStorageDelegateBridge::SetDelegate(chip::DeviceController::PersistentStorageResultDelegate * delegate)
+void CHIPPersistentStorageDelegateBridge::SetDelegate(chip::Controller::PersistentStorageResultDelegate * delegate)
{
if (delegate) {
mCallback = delegate;
@@ -49,17 +49,17 @@
};
mStatusHandler = ^(NSString * key, Operation operation, NSError * status) {
- chip::DeviceController::PersistentStorageResultDelegate::Operation op
- = chip::DeviceController::PersistentStorageResultDelegate::Operation::kGET;
+ chip::Controller::PersistentStorageResultDelegate::Operation op
+ = chip::Controller::PersistentStorageResultDelegate::Operation::kGET;
switch (operation) {
case kGet:
- op = chip::DeviceController::PersistentStorageResultDelegate::Operation::kGET;
+ op = chip::Controller::PersistentStorageResultDelegate::Operation::kGET;
break;
case kSet:
- op = chip::DeviceController::PersistentStorageResultDelegate::Operation::kSET;
+ op = chip::Controller::PersistentStorageResultDelegate::Operation::kSET;
break;
case kDelete:
- op = chip::DeviceController::PersistentStorageResultDelegate::Operation::kDELETE;
+ op = chip::Controller::PersistentStorageResultDelegate::Operation::kDELETE;
break;
}
mCallback->OnStatus([key UTF8String], op, [CHIPError errorToCHIPErrorCode:status]);
@@ -84,16 +84,41 @@
} else {
dispatch_async(mDefaultCallbackQueue, ^{
NSString * value = [mDefaultPersistentStorage objectForKey:keyString];
+ NSLog(@"PersistentStorageDelegate Get Value for Key: %@, value %@", keyString, value);
mCompletionHandler(keyString, value);
});
}
}
+CHIP_ERROR CHIPPersistentStorageDelegateBridge::GetKeyValue(const char * key, char * value, uint16_t & size)
+{
+ NSString * keyString = [NSString stringWithUTF8String:key];
+ NSLog(@"PersistentStorageDelegate Sync Get Value for Key: %@", keyString);
+
+ NSString * valueString = nil;
+
+ id<CHIPPersistentStorageDelegate> strongDelegate = mDelegate;
+ if (strongDelegate) {
+ valueString = [strongDelegate GetKeyValue:keyString];
+ } else {
+ valueString = [mDefaultPersistentStorage objectForKey:keyString];
+ }
+
+ if (value != nullptr) {
+ size = strlcpy(value, [valueString UTF8String], size);
+ } else {
+ size = [valueString length];
+ }
+ // Increment size to account for null termination
+ size += 1;
+ return CHIP_NO_ERROR;
+}
+
void CHIPPersistentStorageDelegateBridge::SetKeyValue(const char * key, const char * value)
{
NSString * keyString = [NSString stringWithUTF8String:key];
NSString * valueString = [NSString stringWithUTF8String:value];
- NSLog(@"PersistentStorageDelegate Set Key %@", keyString);
+ NSLog(@"PersistentStorageDelegate Set Key %@, Value %@", keyString, valueString);
id<CHIPPersistentStorageDelegate> strongDelegate = mDelegate;
if (strongDelegate && mQueue) {
diff --git a/src/lib/support/SerializableIntegerSet.h b/src/lib/support/SerializableIntegerSet.h
index 0fe6e0d..6e59f77 100644
--- a/src/lib/support/SerializableIntegerSet.h
+++ b/src/lib/support/SerializableIntegerSet.h
@@ -34,6 +34,8 @@
#include <support/Base64.h>
#include <support/CodeUtils.h>
+#define CHIP_MAX_SERIALIZED_SIZE_U64(count) static_cast<uint16_t>(BASE64_ENCODED_LEN(sizeof(uint64_t) * (count)))
+
namespace chip {
class SerializableU64SetBase
@@ -78,13 +80,13 @@
* @brief
* Get the length of string if the array is serialized.
*/
- uint16_t SerializedSize() { return static_cast<uint16_t>(BASE64_ENCODED_LEN(sizeof(uint64_t) * mNextAvailable)); }
+ uint16_t SerializedSize() { return CHIP_MAX_SERIALIZED_SIZE_U64(mNextAvailable); }
/**
* @brief
* Get the maximum length of string if the array were full and serialized.
*/
- uint16_t MaxSerializedSize() { return static_cast<uint16_t>(BASE64_ENCODED_LEN(sizeof(uint64_t) * mCapacity)); }
+ uint16_t MaxSerializedSize() { return CHIP_MAX_SERIALIZED_SIZE_U64(mCapacity); }
/**
* @brief
diff --git a/src/transport/RendezvousSession.cpp b/src/transport/RendezvousSession.cpp
index 838d4d0..8e66d74 100644
--- a/src/transport/RendezvousSession.cpp
+++ b/src/transport/RendezvousSession.cpp
@@ -213,19 +213,33 @@
break;
};
mDelegate->OnRendezvousError(err);
- UpdateState(State::kInit);
+ UpdateState(State::kInit, err);
}
-void RendezvousSession::UpdateState(RendezvousSession::State newState)
+void RendezvousSession::UpdateState(RendezvousSession::State newState, CHIP_ERROR err)
{
switch (mCurrentState)
{
case State::kSecurePairing:
- mDelegate->OnRendezvousStatusUpdate(RendezvousSessionDelegate::SecurePairingSuccess, CHIP_NO_ERROR);
+ if (newState != State::kInit)
+ {
+ mDelegate->OnRendezvousStatusUpdate(RendezvousSessionDelegate::SecurePairingSuccess, err);
+ }
+ else
+ {
+ mDelegate->OnRendezvousStatusUpdate(RendezvousSessionDelegate::SecurePairingFailed, err);
+ }
break;
case State::kNetworkProvisioning:
- mDelegate->OnRendezvousStatusUpdate(RendezvousSessionDelegate::NetworkProvisioningSuccess, CHIP_NO_ERROR);
+ if (newState != State::kInit)
+ {
+ mDelegate->OnRendezvousStatusUpdate(RendezvousSessionDelegate::NetworkProvisioningSuccess, err);
+ }
+ else
+ {
+ mDelegate->OnRendezvousStatusUpdate(RendezvousSessionDelegate::NetworkProvisioningFailed, err);
+ }
break;
default:
diff --git a/src/transport/RendezvousSession.h b/src/transport/RendezvousSession.h
index 3a0b718..ed0415f 100644
--- a/src/transport/RendezvousSession.h
+++ b/src/transport/RendezvousSession.h
@@ -138,7 +138,7 @@
uint16_t mNextKeyId = 0;
RendezvousSession::State mCurrentState = State::kInit;
- void UpdateState(RendezvousSession::State newState);
+ void UpdateState(RendezvousSession::State newState, CHIP_ERROR err = CHIP_NO_ERROR);
};
} // namespace chip
diff --git a/src/transport/SecurePairingSession.cpp b/src/transport/SecurePairingSession.cpp
index 61335c1..780654b 100644
--- a/src/transport/SecurePairingSession.cpp
+++ b/src/transport/SecurePairingSession.cpp
@@ -57,37 +57,20 @@
CHIP_ERROR SecurePairingSession::Serialize(SecurePairingSessionSerialized & output)
{
- CHIP_ERROR error = CHIP_NO_ERROR;
+ CHIP_ERROR error = CHIP_NO_ERROR;
+ uint16_t serializedLen = 0;
+ SecurePairingSessionSerializable serializable;
- const NodeId localNodeId = (mLocalNodeId.HasValue()) ? mLocalNodeId.Value() : kUndefinedNodeId;
- const NodeId peerNodeId = (mPeerNodeId.HasValue()) ? mPeerNodeId.Value() : kUndefinedNodeId;
- VerifyOrExit(CanCastTo<uint16_t>(mKeLen), error = CHIP_ERROR_INTERNAL);
- VerifyOrExit(CanCastTo<uint64_t>(localNodeId), error = CHIP_ERROR_INTERNAL);
- VerifyOrExit(CanCastTo<uint64_t>(peerNodeId), error = CHIP_ERROR_INTERNAL);
- VerifyOrExit(CanCastTo<uint16_t>(sizeof(SecurePairingSessionSerializable)), error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(BASE64_ENCODED_LEN(sizeof(serializable)) <= sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT);
- {
- SecurePairingSessionSerializable serializable;
- memset(&serializable, 0, sizeof(serializable));
- serializable.mKeLen = static_cast<uint16_t>(mKeLen);
- serializable.mPairingComplete = (mPairingComplete) ? 1 : 0;
- serializable.mLocalNodeId = localNodeId;
- serializable.mPeerNodeId = peerNodeId;
- serializable.mLocalKeyId = mLocalKeyId;
- serializable.mPeerKeyId = mPeerKeyId;
+ error = ToSerializable(serializable);
+ SuccessOrExit(error);
- memcpy(serializable.mKe, mKe, mKeLen);
-
- uint16_t serializedLen = 0;
-
- VerifyOrExit(BASE64_ENCODED_LEN(sizeof(serializable)) <= sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT);
-
- serializedLen = chip::Base64Encode(Uint8::to_const_uchar(reinterpret_cast<uint8_t *>(&serializable)),
- static_cast<uint16_t>(sizeof(serializable)), Uint8::to_char(output.inner));
- VerifyOrExit(serializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
- VerifyOrExit(serializedLen < sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT);
- output.inner[serializedLen] = '\0';
- }
+ serializedLen = chip::Base64Encode(Uint8::to_const_uchar(reinterpret_cast<uint8_t *>(&serializable)),
+ static_cast<uint16_t>(sizeof(serializable)), Uint8::to_char(output.inner));
+ VerifyOrExit(serializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(serializedLen < sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT);
+ output.inner[serializedLen] = '\0';
exit:
return error;
@@ -107,9 +90,44 @@
memset(&serializable, 0, sizeof(serializable));
deserializedLen =
Base64Decode(Uint8::to_const_char(input.inner), static_cast<uint16_t>(len), Uint8::to_uchar((uint8_t *) &serializable));
+
VerifyOrExit(deserializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(deserializedLen <= sizeof(serializable), error = CHIP_ERROR_INVALID_ARGUMENT);
+ error = FromSerializable(serializable);
+
+exit:
+ return error;
+}
+
+CHIP_ERROR SecurePairingSession::ToSerializable(SecurePairingSessionSerializable & serializable)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+
+ const NodeId localNodeId = (mLocalNodeId.HasValue()) ? mLocalNodeId.Value() : kUndefinedNodeId;
+ const NodeId peerNodeId = (mPeerNodeId.HasValue()) ? mPeerNodeId.Value() : kUndefinedNodeId;
+ VerifyOrExit(CanCastTo<uint16_t>(mKeLen), error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(CanCastTo<uint64_t>(localNodeId), error = CHIP_ERROR_INTERNAL);
+ VerifyOrExit(CanCastTo<uint64_t>(peerNodeId), error = CHIP_ERROR_INTERNAL);
+
+ memset(&serializable, 0, sizeof(serializable));
+ serializable.mKeLen = static_cast<uint16_t>(mKeLen);
+ serializable.mPairingComplete = (mPairingComplete) ? 1 : 0;
+ serializable.mLocalNodeId = localNodeId;
+ serializable.mPeerNodeId = peerNodeId;
+ serializable.mLocalKeyId = mLocalKeyId;
+ serializable.mPeerKeyId = mPeerKeyId;
+
+ memcpy(serializable.mKe, mKe, mKeLen);
+
+exit:
+ return error;
+}
+
+CHIP_ERROR SecurePairingSession::FromSerializable(const SecurePairingSessionSerializable & serializable)
+{
+ CHIP_ERROR error = CHIP_NO_ERROR;
+
mPairingComplete = (serializable.mPairingComplete == 1);
mKeLen = static_cast<size_t>(serializable.mKeLen);
diff --git a/src/transport/SecurePairingSession.h b/src/transport/SecurePairingSession.h
index dfe3857..d811c2e 100644
--- a/src/transport/SecurePairingSession.h
+++ b/src/transport/SecurePairingSession.h
@@ -74,6 +74,17 @@
struct SecurePairingSessionSerialized;
+struct SecurePairingSessionSerializable
+{
+ uint16_t mKeLen;
+ uint8_t mKe[kMAX_Hash_Length];
+ uint8_t mPairingComplete;
+ uint64_t mLocalNodeId;
+ uint64_t mPeerNodeId;
+ uint16_t mLocalKeyId;
+ uint16_t mPeerKeyId;
+};
+
class DLL_EXPORT SecurePairingSession
{
public:
@@ -178,6 +189,18 @@
**/
CHIP_ERROR Deserialize(SecurePairingSessionSerialized & input);
+ /** @brief Serialize the SecurePairingSession to the given serializable data structure for secure pairing
+ *
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR ToSerializable(SecurePairingSessionSerializable & output);
+
+ /** @brief Reconstruct secure pairing class from the serializable data structure.
+ *
+ * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+ **/
+ CHIP_ERROR FromSerializable(const SecurePairingSessionSerializable & output);
+
private:
CHIP_ERROR Init(uint32_t setupCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, Optional<NodeId> myNodeId,
uint16_t myKeyId, SecurePairingSessionDelegate * delegate);
@@ -209,12 +232,6 @@
/* w0s and w1s */
uint8_t mWS[2][kSpake2p_WS_Length];
- uint8_t mKe[kMAX_Hash_Length];
-
- size_t mKeLen = sizeof(mKe);
-
- bool mPairingComplete = false;
-
protected:
Optional<NodeId> mLocalNodeId = Optional<NodeId>::Value(kUndefinedNodeId);
@@ -223,6 +240,12 @@
uint16_t mLocalKeyId;
uint16_t mPeerKeyId;
+
+ uint8_t mKe[kMAX_Hash_Length];
+
+ size_t mKeLen = sizeof(mKe);
+
+ bool mPairingComplete = false;
};
/*
@@ -234,12 +257,25 @@
class SecurePairingUsingTestSecret : public SecurePairingSession
{
public:
- SecurePairingUsingTestSecret() {}
+ SecurePairingUsingTestSecret()
+ {
+ const char * secret = "Test secret for key derivation";
+ size_t secretLen = strlen(secret);
+ mKeLen = secretLen;
+ memmove(mKe, secret, mKeLen);
+ mPairingComplete = true;
+ }
+
SecurePairingUsingTestSecret(Optional<NodeId> peerNodeId, uint16_t peerKeyId, uint16_t localKeyId)
{
- mPeerNodeId = peerNodeId;
- mPeerKeyId = peerKeyId;
- mLocalKeyId = localKeyId;
+ const char * secret = "Test secret for key derivation";
+ size_t secretLen = strlen(secret);
+ mPeerNodeId = peerNodeId;
+ mPeerKeyId = peerKeyId;
+ mLocalKeyId = localKeyId;
+ mKeLen = secretLen;
+ memmove(mKe, secret, mKeLen);
+ mPairingComplete = true;
}
~SecurePairingUsingTestSecret() override {}
@@ -256,28 +292,9 @@
return CHIP_NO_ERROR;
}
- CHIP_ERROR DeriveSecureSession(const uint8_t * info, size_t info_len, SecureSession & session) override
- {
- const char * secret = "Test secret for key derivation";
- size_t secretLen = strlen(secret);
- return session.InitFromSecret(reinterpret_cast<const uint8_t *>(secret), secretLen, reinterpret_cast<const uint8_t *>(""),
- 0, reinterpret_cast<const uint8_t *>(secret), secretLen);
- }
-
CHIP_ERROR HandlePeerMessage(const PacketHeader & packetHeader, System::PacketBuffer * msg) override { return CHIP_NO_ERROR; }
};
-typedef struct SecurePairingSessionSerializable
-{
- uint16_t mKeLen;
- uint8_t mKe[kMAX_Hash_Length];
- uint8_t mPairingComplete;
- uint64_t mLocalNodeId;
- uint64_t mPeerNodeId;
- uint16_t mLocalKeyId;
- uint16_t mPeerKeyId;
-} SecurePairingSessionSerializable;
-
typedef struct SecurePairingSessionSerialized
{
// Extra uint64_t to account for padding bytes (NULL termination, and some decoding overheads)
diff --git a/src/transport/SecureSessionMgr.cpp b/src/transport/SecureSessionMgr.cpp
index 4e41dc4..a8dea8e 100644
--- a/src/transport/SecureSessionMgr.cpp
+++ b/src/transport/SecureSessionMgr.cpp
@@ -65,6 +65,8 @@
mSystemLayer = systemLayer;
mTransport = transport;
+ ChipLogProgress(Inet, "local node id is %llu\n", mLocalNodeId);
+
mTransport->SetMessageReceiveHandler(HandleDataReceived, this);
mPeerConnections.SetConnectionExpiredHandler(HandleConnectionExpired, this);
@@ -124,6 +126,8 @@
.SetEncryptionKeyID(state->GetLocalKeyID()) //
.SetPayloadLength(static_cast<uint16_t>(payloadLength));
+ ChipLogProgress(Inet, "Sending msg from %llu to %llu\n", mLocalNodeId, peerNodeId);
+
VerifyOrExit(msgBuf->EnsureReservedSize(headerSize), err = CHIP_ERROR_NO_MEMORY);
msgBuf->SetStart(msgBuf->Start() - headerSize);
diff --git a/src/transport/SecureSessionMgr.h b/src/transport/SecureSessionMgr.h
index ac66baf..5536715 100644
--- a/src/transport/SecureSessionMgr.h
+++ b/src/transport/SecureSessionMgr.h
@@ -224,6 +224,12 @@
return err;
}
+ template <typename... Args>
+ CHIP_ERROR ResetTransport(Args &&... transportInitArgs)
+ {
+ return mTransport.Init(std::forward<Args>(transportInitArgs)...);
+ }
+
private:
Transport::Tuple<TransportTypes...> mTransport;
};
diff --git a/src/transport/raw/Base.h b/src/transport/raw/Base.h
index fe1dc4f..f374bff 100644
--- a/src/transport/raw/Base.h
+++ b/src/transport/raw/Base.h
@@ -82,6 +82,11 @@
*/
virtual void Disconnect(const PeerAddress & address) {}
+ /**
+ * Close the open endpoint without destroying the object
+ */
+ virtual void Close(){};
+
protected:
/**
* Method used by subclasses to notify that a packet has been received after
diff --git a/src/transport/raw/UDP.cpp b/src/transport/raw/UDP.cpp
index ce065b6..aa5621a 100644
--- a/src/transport/raw/UDP.cpp
+++ b/src/transport/raw/UDP.cpp
@@ -34,20 +34,17 @@
UDP::~UDP()
{
- if (mUDPEndPoint)
- {
- // Udp endpoint is only non null if udp endpoint is initialized and listening
- mUDPEndPoint->Close();
- mUDPEndPoint->Free();
- mUDPEndPoint = nullptr;
- }
+ Close();
}
CHIP_ERROR UDP::Init(UdpListenParameters & params)
{
CHIP_ERROR err = CHIP_NO_ERROR;
- VerifyOrExit(mState == State::kNotReady, err = CHIP_ERROR_INCORRECT_STATE);
+ if (mState != State::kNotReady)
+ {
+ Close();
+ }
err = params.GetInetLayer()->NewUDPEndPoint(&mUDPEndPoint);
SuccessOrExit(err);
@@ -78,6 +75,18 @@
return err;
}
+void UDP::Close()
+{
+ if (mUDPEndPoint)
+ {
+ // Udp endpoint is only non null if udp endpoint is initialized and listening
+ mUDPEndPoint->Close();
+ mUDPEndPoint->Free();
+ mUDPEndPoint = nullptr;
+ }
+ mState = State::kNotReady;
+}
+
CHIP_ERROR UDP::SendMessage(const PacketHeader & header, Header::Flags payloadFlags, const Transport::PeerAddress & address,
System::PacketBuffer * msgBuf)
{
diff --git a/src/transport/raw/UDP.h b/src/transport/raw/UDP.h
index d2dfcc3..2cfbf76 100644
--- a/src/transport/raw/UDP.h
+++ b/src/transport/raw/UDP.h
@@ -105,6 +105,11 @@
*/
CHIP_ERROR Init(UdpListenParameters & params);
+ /**
+ * Close the open endpoint without destroying the object
+ */
+ void Close() override;
+
CHIP_ERROR SendMessage(const PacketHeader & header, Header::Flags payloadFlags, const Transport::PeerAddress & address,
System::PacketBuffer * msgBuf) override;