From f6af1c67a8b024b9ce74450d6f143614f3326365 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 3 Nov 2020 11:54:30 -0800 Subject: [PATCH 01/26] Enable pairing for multiple devices --- .../esp32/main/RendezvousDeviceDelegate.cpp | 11 + src/controller/BUILD.gn | 4 + src/controller/CHIPDevice.cpp | 221 +++++ src/controller/CHIPDevice.h | 141 ++++ src/controller/CHIPDeviceController.cpp | 770 +++++++++--------- src/controller/CHIPDeviceController.h | 274 +++---- .../CHIPDeviceController_deprecated.cpp | 231 ++++++ .../CHIPDeviceController_deprecated.h | 212 +++++ .../CHIPPersistentStorageDelegate.h | 17 +- src/controller/python/BUILD.gn | 3 +- .../ChipDeviceController-ScriptBinding.cpp | 6 +- ...ceController-ScriptDevicePairingDelegate.h | 4 +- .../Framework Helpers/DefaultsUtils.m | 8 + .../Framework/CHIP/CHIPDeviceController.mm | 2 +- .../CHIP/CHIPDevicePairingDelegateBridge.h | 2 +- .../CHIP/CHIPPersistentStorageDelegate.h | 6 + .../CHIPPersistentStorageDelegateBridge.h | 8 +- .../CHIPPersistentStorageDelegateBridge.mm | 38 +- src/transport/RendezvousSession.cpp | 22 +- src/transport/RendezvousSession.h | 2 +- src/transport/SecurePairingSession.cpp | 77 +- src/transport/SecurePairingSession.h | 34 +- src/transport/SecureSessionMgr.cpp | 4 + src/transport/SecureSessionMgr.h | 6 + src/transport/raw/Base.h | 5 + src/transport/raw/UDP.cpp | 25 +- src/transport/raw/UDP.h | 5 + 27 files changed, 1484 insertions(+), 654 deletions(-) create mode 100644 src/controller/CHIPDevice.cpp create mode 100644 src/controller/CHIPDevice.h create mode 100644 src/controller/CHIPDeviceController_deprecated.cpp create mode 100644 src/controller/CHIPDeviceController_deprecated.h diff --git a/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp b/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp index 5060b57595c12d..683a577c694fe3 100644 --- a/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp +++ b/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp @@ -70,12 +70,23 @@ void RendezvousDeviceDelegate::OnRendezvousStatusUpdate(RendezvousSessionDelegat 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/src/controller/BUILD.gn b/src/controller/BUILD.gn index 7d843de0f38dfc..aaab1fef51e675 100644 --- a/src/controller/BUILD.gn +++ b/src/controller/BUILD.gn @@ -18,8 +18,12 @@ static_library("controller") { 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 00000000000000..212d429d576a33 --- /dev/null +++ b/src/controller/CHIPDevice.cpp @@ -0,0 +1,221 @@ +/* + * + * 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. + */ + +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif + +// module header, comes first +#include + +#if CONFIG_DEVICE_LAYER +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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(buffer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + + // If there is no secure connection to the device, try establishing it + if (mState != kConnectionState_SecureConnected) + { + err = EstablishSecureSession(); + 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) + { + err = ResumeSecureSession(); + 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; + + VerifyOrExit(BASE64_ENCODED_LEN(sizeof(serializable)) <= sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT); + + CHIP_ZERO_AT(serializable); + + memmove(&serializable.mOpsCreds, &mPairing, sizeof(mPairing)); + serializable.mDeviceId = Encoding::LittleEndian::HostSwap64(mDeviceId); + serializable.mDevicePort = Encoding::LittleEndian::HostSwap16(mDevicePort); + mDeviceAddr.ToString(Uint8::to_char(serializable.mDeviceAddr), INET6_ADDRSTRLEN); + + serializedLen = chip::Base64Encode(Uint8::to_const_uchar(reinterpret_cast(&serializable)), + static_cast(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(len), error = CHIP_ERROR_INVALID_ARGUMENT); + + CHIP_ZERO_AT(serializable); + deserializedLen = + Base64Decode(Uint8::to_const_char(input.inner), static_cast(len), Uint8::to_uchar((uint8_t *) &serializable)); + + VerifyOrExit(deserializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(deserializedLen <= sizeof(serializable), error = CHIP_ERROR_INVALID_ARGUMENT); + + VerifyOrExit(IPAddress::FromString(Uint8::to_const_char(serializable.mDeviceAddr), 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 == kConnectionState_SecureConnected && mStatusDelegate != nullptr) + { + mStatusDelegate->OnMessage(msgBuf); + } +} + +CHIP_ERROR Device::EstablishSecureSession() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + SecurePairingSession pairingSession; + + if (mSessionManager == nullptr || mState == kConnectionState_SecureConnected) + { + ExitNow(err = CHIP_ERROR_INCORRECT_STATE); + } + + err = pairingSession.FromSerializable(mPairing); + SuccessOrExit(err); + + err = mSessionManager->NewPairing( + Optional::Value(Transport::PeerAddress::UDP(mDeviceAddr, mDevicePort, mInterface)), + &pairingSession); + SuccessOrExit(err); + + mState = kConnectionState_SecureConnected; + +exit: + + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "EstablishSecureSession returning error %d\n", err); + } + return err; +} + +CHIP_ERROR Device::ResumeSecureSession() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + if (mState == kConnectionState_SecureConnected) + { + mState = kConnectionState_NotConnected; + } + + VerifyOrExit(mSessionManager != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + err = mSessionManager->ResetTransport(Transport::UdpListenParameters(mInetLayer).SetAddressType(mDeviceAddr.Type())); + SuccessOrExit(err); + + err = EstablishSecureSession(); + SuccessOrExit(err); + +exit: + + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "ResumeSecureSession returning error %d\n", err); + } + return err; +} + +} // namespace Controller +} // namespace chip diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h new file mode 100644 index 00000000000000..966363d2ca262a --- /dev/null +++ b/src/controller/CHIPDevice.h @@ -0,0 +1,141 @@ +/* + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace Controller { + +class DeviceController; + +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){}; +}; + +struct SerializedDevice; + +class DLL_EXPORT Device +{ +public: + friend class DeviceController; + friend class DeviceCommissioner; + + void SetDelegate(DeviceStatusDelegate * delegate, void * state) + { + mStatusDelegate = delegate; + mAppReqState = state; + } + + // ----- Messaging ----- + /** + * @brief + * Send a message to a connected CHIP device + * + * @param[in] buffer The Data Buffer to trasmit to the device + * @return CHIP_ERROR The return status + */ + CHIP_ERROR SendMessage(System::PacketBuffer * buffer); + +private: + enum ConnectionState + { + kConnectionState_NotConnected = 0, + kConnectionState_Connecting = 1, + kConnectionState_SecureConnected = 2, + }; + + NodeId mDeviceId; + Inet::IPAddress mDeviceAddr; + uint16_t mDevicePort; + Inet::InterfaceId mInterface; + + Inet::InetLayer * mInetLayer; + + Device() {} + ~Device() {} + + bool mActive = false; + ConnectionState mState; + + SecurePairingSessionSerializable mPairing; + + DeviceStatusDelegate * mStatusDelegate; + void * mAppReqState; + + SecureSessionMgr * mSessionManager; + + /** @brief Serialize the Pairing Session to a string. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR Serialize(SerializedDevice & output); + + /** @brief Deserialize the Pairing Session from the string. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR Deserialize(const SerializedDevice & input); + + void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, Transport::PeerConnectionState * state, + System::PacketBuffer * msgBuf, SecureSessionMgrBase * mgr); + + CHIP_ERROR EstablishSecureSession(); + CHIP_ERROR ResumeSecureSession(); +}; + +typedef struct SerializableDevice +{ + SecurePairingSessionSerializable mOpsCreds; + uint64_t mDeviceId; + uint8_t mDeviceAddr[INET6_ADDRSTRLEN]; + uint16_t mDevicePort; +} SerializableDevice; + +typedef struct SerializedDevice +{ + // Extra uint64_t to account for padding bytes (NULL termination, and some decoding overheads) + 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 ab1471b3d1f651..b5ab7abfbf69ce 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -59,7 +60,7 @@ using namespace chip::Inet; using namespace chip::System; namespace chip { -namespace DeviceController { +namespace Controller { using namespace chip::Encoding; @@ -80,66 +81,51 @@ constexpr const char kDeviceAddressKeyPrefix[] = "DeviceAddress"; 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 = kState_NotInitialized; + mSessionManager = nullptr; + mLocalDeviceId = 0; + mStorageDelegate = nullptr; + mPairedDevicesInitialized = false; } -ChipDeviceController::~ChipDeviceController() -{ - if (mTestSecurePairingSecret != nullptr) - { - chip::Platform::Delete(mTestSecurePairingSecret); - } -} - -CHIP_ERROR ChipDeviceController::Init(NodeId localNodeId, DevicePairingDelegate * pairingDelegate, - PersistentStorageDelegate * storageDelegate) +CHIP_ERROR DeviceController::Init(NodeId localDeviceId, const char * pairedDeviceSerializedSet, + PersistentStorageDelegate * storageDelegate, System::Layer * systemLayer, + Inet::InetLayer * inetLayer) { CHIP_ERROR err = CHIP_NO_ERROR; VerifyOrExit(mState == kState_NotInitialized, err = CHIP_ERROR_INCORRECT_STATE); + if (systemLayer != nullptr && inetLayer != nullptr) + { + mSystemLayer = systemLayer; + mInetLayer = inetLayer; + } + else + { #if CONFIG_DEVICE_LAYER - err = DeviceLayer::PlatformMgr().InitChipStack(); - SuccessOrExit(err); + err = chip::Platform::MemoryInit(); + SuccessOrExit(err); - err = Init(localNodeId, &DeviceLayer::SystemLayer, &DeviceLayer::InetLayer, pairingDelegate, storageDelegate); -#endif // CONFIG_DEVICE_LAYER + err = DeviceLayer::PlatformMgr().InitChipStack(); + SuccessOrExit(err); -exit: - return err; -} + mSystemLayer = &DeviceLayer::SystemLayer; + mInetLayer = &DeviceLayer::InetLayer; +#endif // CONFIG_DEVICE_LAYER + } -CHIP_ERROR ChipDeviceController::Init(NodeId localNodeId, System::Layer * systemLayer, InetLayer * inetLayer, - DevicePairingDelegate * pairingDelegate, PersistentStorageDelegate * storageDelegate) -{ - CHIP_ERROR err = CHIP_NO_ERROR; + VerifyOrExit(mSystemLayer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(mInetLayer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(mState == kState_NotInitialized, err = CHIP_ERROR_INCORRECT_STATE); + if (pairedDeviceSerializedSet != nullptr) + { + err = SetPairedDeviceList(pairedDeviceSerializedSet); + SuccessOrExit(err); + } - mState = kState_Initialized; - mLocalDeviceId = localNodeId; - mSystemLayer = systemLayer; - mInetLayer = inetLayer; - mPairingDelegate = pairingDelegate; mStorageDelegate = storageDelegate; if (mStorageDelegate != nullptr) @@ -147,18 +133,29 @@ CHIP_ERROR ChipDeviceController::Init(NodeId localNodeId, System::Layer * system mStorageDelegate->SetDelegate(this); } + mSessionManager = chip::Platform::New>(); + + err = mSessionManager->Init(localDeviceId, mSystemLayer, + Transport::UdpListenParameters(mInetLayer).SetAddressType(kIPAddressType_IPv4)); + SuccessOrExit(err); + + mSessionManager->SetDelegate(this); + + mState = kState_Initialized; + mLocalDeviceId = localDeviceId; + exit: return err; } -CHIP_ERROR ChipDeviceController::Shutdown() +CHIP_ERROR DeviceController::Shutdown() { CHIP_ERROR err = CHIP_NO_ERROR; - ChipLogDetail(Controller, "Shutting down the controller"); - VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + ChipLogDetail(Controller, "Shutting down the controller"); + mState = kState_NotInitialized; #if CONFIG_DEVICE_LAYER @@ -180,279 +177,256 @@ CHIP_ERROR ChipDeviceController::Shutdown() 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 DeviceController::GetDevice(NodeId deviceId, const SerializedDevice & deviceInfo, Device ** out_device) { - CHIP_ERROR err = CHIP_NO_ERROR; - - VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); - VerifyOrExit(mConState == kConnectionState_NotConnected, err = CHIP_ERROR_INCORRECT_STATE); + CHIP_ERROR err = CHIP_NO_ERROR; + Device * device = nullptr; + uint16_t index = FindDevice(deviceId); -#if CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE - if (!params.HasBleLayer()) + if (index < mNumMaxActiveDevices) { - params.SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer()); + device = &mActiveDevices[index]; } -#endif // CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE + else + { + VerifyOrExit(mPairedDevices.Contains(deviceId), err = CHIP_ERROR_NOT_CONNECTED); - mRendezvousSession = chip::Platform::New(this); - err = mRendezvousSession->Init(params.SetLocalNodeId(mLocalDeviceId)); - SuccessOrExit(err); + index = GetAvailableDevice(); + VerifyOrExit(index < mNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); + device = &mActiveDevices[index]; - mRemoteDeviceId = Optional::Value(remoteDeviceId); - mDevicePort = devicePort; - mInterface = interfaceId; - mAppReqState = appReqState; - mOnNewConnection = onConnected; + err = device->Deserialize(deviceInfo); + VerifyOrExit(err == CHIP_NO_ERROR, ReleaseDevice(device)); - // connected state before 'OnConnect' - mConState = kConnectionState_Connected; + device->mSessionManager = mSessionManager; + device->mInetLayer = mInetLayer; + } - mOnComplete.Response = onMessageReceived; - mOnError = onError; + (*out_device) = device; 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) +CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) { - if (mTestSecurePairingSecret != nullptr) + CHIP_ERROR err = CHIP_NO_ERROR; + Device * device = nullptr; + uint16_t index = FindDevice(deviceId); + + if (index < mNumMaxActiveDevices) { - chip::Platform::Delete(mTestSecurePairingSecret); + device = &mActiveDevices[index]; } + else + { + if (!mPairedDevicesInitialized) + { + const uint16_t max_size = mPairedDevices.MaxSerializedSize(); + char buffer[max_size]; + uint16_t size = max_size; + + PERSISTENT_KEY_OP(0ull, kPairedDeviceListKeyPrefix, key, err = mStorageDelegate->GetKeyValue(key, buffer, size)); + SuccessOrExit(err); + VerifyOrExit(size <= max_size, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); - mTestSecurePairingSecret = chip::Platform::New( - Optional::Value(remoteDeviceId), static_cast(0), static_cast(0)); + err = SetPairedDeviceList(buffer); + SuccessOrExit(err); + } - mSecurePairingSession = mTestSecurePairingSecret; + VerifyOrExit(mPairedDevices.Contains(deviceId), err = CHIP_ERROR_NOT_CONNECTED); - mDeviceAddr = deviceAddr; - mRemoteDeviceId = Optional::Value(remoteDeviceId); - mDevicePort = devicePort; - mInterface = interfaceId; - mAppReqState = appReqState; - mOnNewConnection = onConnected; + index = GetAvailableDevice(); + VerifyOrExit(index < mNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); + device = &mActiveDevices[index]; - mConState = kConnectionState_Connected; + { + SerializedDevice deviceInfo; + uint16_t size = sizeof(deviceInfo.inner); - mOnComplete.Response = onMessageReceived; - mOnError = onError; + 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); - if (mOnNewConnection) - { - mOnNewConnection(this, nullptr, mAppReqState); + err = device->Deserialize(deviceInfo); + VerifyOrExit(err == CHIP_NO_ERROR, ReleaseDevice(device)); + + device->mSessionManager = mSessionManager; + device->mInetLayer = mInetLayer; + } } - return CHIP_NO_ERROR; -} + (*out_device) = device; -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; +exit: + return err; } -CHIP_ERROR ChipDeviceController::EstablishSecureSession() +CHIP_ERROR DeviceController::ServiceEvents() { CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrExit(mSecurePairingSession != nullptr, err = CHIP_ERROR_INCORRECT_STATE); - - mSessionManager = chip::Platform::New>(); + VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); - err = mSessionManager->Init( - mLocalDeviceId, mSystemLayer, - Transport::UdpListenParameters(mInetLayer).SetAddressType(mDeviceAddr.Type()).SetListenPort(mListenPort)); +#if CONFIG_DEVICE_LAYER + err = DeviceLayer::PlatformMgr().StartEventLoopTask(); SuccessOrExit(err); +#endif // CONFIG_DEVICE_LAYER - mSessionManager->SetDelegate(this); +exit: + return err; +} - err = mSessionManager->NewPairing( - Optional::Value(Transport::PeerAddress::UDP(mDeviceAddr, mDevicePort, mInterface)), - mSecurePairingSession); - SuccessOrExit(err); +CHIP_ERROR DeviceController::ServiceEventSignal() +{ + CHIP_ERROR err = CHIP_NO_ERROR; - mConState = kConnectionState_SecureConnected; + VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); - if (mDeviceAddr != IPAddress::Any) - { - SendCachedPackets(); - } // else wait for mdns discovery +#if CONFIG_DEVICE_LAYER && (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) + DeviceLayer::SystemLayer.WakeSelect(); +#else + err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +#endif // CONFIG_DEVICE_LAYER && (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) 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) +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; - NodeId peer = mRemoteDeviceId.Value(); - - VerifyOrExit(key != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + uint16_t index = 0; + NodeId peer; - PERSISTENT_KEY_OP( - peer, kDeviceCredentialsKeyPrefix, expectedKey, if (strcmp(key, expectedKey) == 0) { - SecurePairingSessionSerialized serialized; - size_t length = 0; + VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(header.GetSourceNodeId().HasValue(), err = CHIP_ERROR_INVALID_ARGUMENT); - 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)); + peer = header.GetSourceNodeId().Value(); + index = FindDevice(peer); + VerifyOrExit(index < mNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); - mSecurePairingSession = &mPairingSession; - }); + mActiveDevices[index].OnMessageReceived(header, payloadHeader, state, msgBuf, mgr); - 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); - }); +exit: + return; +} - if (mSecurePairingSession != nullptr && mDeviceAddr != IPAddress::Any) +uint16_t DeviceController::GetAvailableDevice() +{ + uint16_t i = 0; + while (i < mNumMaxActiveDevices && mActiveDevices[i].mActive) + i++; + if (i < mNumMaxActiveDevices) { - SuccessOrExit(EstablishSecureSession()); + mActiveDevices[i].mActive = true; } -exit: - if (err != CHIP_NO_ERROR) - { - mConState = kConnectionState_NotConnected; - DiscardCachedPackets(); - } + return i; } -void ChipDeviceController::OnStatus(const char * key, Operation op, CHIP_ERROR err) {} - -CHIP_ERROR ChipDeviceController::TryEstablishingSecureSession(NodeId peer) +void DeviceController::ReleaseDevice(Device * device) { - CHIP_ERROR err = CHIP_NO_ERROR; + device->mActive = false; +} - if (mState != kState_Initialized || mSessionManager != nullptr || mConState == kConnectionState_SecureConnected) +void DeviceController::ReleaseDevice(uint16_t index) +{ + if (index < mNumMaxActiveDevices) { - ExitNow(err = CHIP_ERROR_INCORRECT_STATE); + ReleaseDevice(&mActiveDevices[index]); } +} - 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 +uint16_t DeviceController::FindDevice(NodeId id) +{ + uint16_t i = 0; + while (i < mNumMaxActiveDevices) { - ExitNow(err = EstablishSecureSession()); + if (mActiveDevices[i].mActive && mActiveDevices[i].mDeviceId == id) + { + return i; + } + i++; } + return i; +} -exit: +CHIP_ERROR DeviceController::SetPairedDeviceList(const char * serialized) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + size_t len = strlen(serialized) + 1; + uint16_t lenU16 = static_cast(len); + VerifyOrExit(CanCastTo(len), err = CHIP_ERROR_INVALID_ARGUMENT); + err = mPairedDevices.DeserializeBase64(serialized, lenU16); +exit: if (err != CHIP_NO_ERROR) { - DiscardCachedPackets(); + ChipLogError(Controller, "Failed to recreate the device list\n"); } - return err; -} - -CHIP_ERROR ChipDeviceController::ResumeSecureSession(NodeId peer) -{ - if (mConState == kConnectionState_SecureConnected) + else { - mConState = kConnectionState_Connected; + mPairedDevicesInitialized = true; } - if (mSessionManager != nullptr) - { - chip::Platform::Delete(mSessionManager); - mSessionManager = nullptr; - } + return err; +} - CHIP_ERROR err = TryEstablishingSecureSession(peer); - SuccessOrExit(err); +void DeviceController::OnValue(const char * key, const char * value) {} -exit: +void DeviceController::OnStatus(const char * key, Operation op, CHIP_ERROR err) {} - if (err != CHIP_NO_ERROR) - { - ChipLogError(Controller, "ResumeSecureSession returning error %d\n", err); - } - return err; +DeviceCommissioner::DeviceCommissioner() : DeviceController() +{ + mPairingDelegate = nullptr; + mRendezvousSession = nullptr; + mDeviceBeingPaired = mNumMaxActiveDevices; + mPairedDevicesUpdated = false; } -bool ChipDeviceController::IsConnected() const +DeviceCommissioner::~DeviceCommissioner() { - return mState == kState_Initialized && - (mConState == kConnectionState_Connected || mConState == kConnectionState_SecureConnected); + PersistDeviceList(); } -bool ChipDeviceController::IsSecurelyConnected() const +CHIP_ERROR DeviceCommissioner::Init(NodeId localDeviceId, const char * pairedDeviceSerializedSet, + PersistentStorageDelegate * storageDelegate, DevicePairingDelegate * pairingDelegate, + System::Layer * systemLayer, Inet::InetLayer * inetLayer) { - return mState == kState_Initialized && mConState == kConnectionState_SecureConnected; + CHIP_ERROR err = DeviceController::Init(localDeviceId, pairedDeviceSerializedSet, storageDelegate, systemLayer, inetLayer); + SuccessOrExit(err); + + mPairingDelegate = pairingDelegate; + +exit: + return err; } -bool ChipDeviceController::GetIpAddress(Inet::IPAddress & addr) const +CHIP_ERROR DeviceCommissioner::SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate) { - if (IsConnected()) - addr = mDeviceAddr; - return IsConnected(); + mPairingDelegate = pairingDelegate; + return CHIP_NO_ERROR; } -CHIP_ERROR ChipDeviceController::DisconnectDevice() +CHIP_ERROR DeviceCommissioner::Shutdown() { CHIP_ERROR err = CHIP_NO_ERROR; - if (!IsConnected()) - { - return CHIP_ERROR_INCORRECT_STATE; - } + VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); - if (mSessionManager != nullptr) - { - chip::Platform::Delete(mSessionManager); - mSessionManager = nullptr; - } + ChipLogDetail(Controller, "Shutting down the commissioner"); + + PersistDeviceList(); if (mRendezvousSession != nullptr) { @@ -460,196 +434,155 @@ CHIP_ERROR ChipDeviceController::DisconnectDevice() 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; + DeviceController::Shutdown(); exit: return err; } -CHIP_ERROR ChipDeviceController::SendCachedPackets() +CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & params, void * appReqState, + uint16_t devicePort, Inet::InterfaceId interfaceId) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + Device * device = nullptr; - VerifyOrExit(IsSecurelyConnected(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mDeviceBeingPaired == mNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); - for (uint16_t i = 0; i < mNumCachedPackets; i++) +#if CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE + if (!params.HasBleLayer()) { - err = mSessionManager->SendMessage(mRemoteDeviceId.Value(), mCachedPackets[i]); - ChipLogDetail(Controller, "SendMessage returned %d", err); + params.SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer()); } +#endif // CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE - mNumCachedPackets = 0; - CHIP_ZERO_AT(mCachedPackets); + mDeviceBeingPaired = GetAvailableDevice(); + VerifyOrExit(mDeviceBeingPaired < mNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); + device = &mActiveDevices[mDeviceBeingPaired]; -exit: - return err; -} + if (mRendezvousSession != nullptr) + { + chip::Platform::Delete(mRendezvousSession); + } -void ChipDeviceController::DiscardCachedPackets() -{ - for (uint16_t i = 0; i < mNumCachedPackets; i++) + mRendezvousSession = chip::Platform::New(this); + err = mRendezvousSession->Init(params.SetLocalNodeId(mLocalDeviceId)); + SuccessOrExit(err); + + device->mDeviceId = remoteDeviceId; + device->mDevicePort = devicePort; + device->mInterface = interfaceId; + device->mState = Device::kConnectionState_Connecting; + device->mSessionManager = mSessionManager; + +exit: + if (err != CHIP_NO_ERROR) { - PacketBuffer::Free(mCachedPackets[i]); + if (mRendezvousSession != nullptr) + { + chip::Platform::Delete(mRendezvousSession); + mRendezvousSession = nullptr; + } + + if (device != nullptr) + { + ReleaseDevice(device); + mDeviceBeingPaired = mNumMaxActiveDevices; + } } - mNumCachedPackets = 0; - CHIP_ZERO_AT(mCachedPackets); + return err; } -CHIP_ERROR ChipDeviceController::SendMessage(void * appReqState, PacketBuffer * buffer, NodeId peerDevice) +CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDeviceId, const Inet::IPAddress & deviceAddr, + SerializedDevice & serialized, void * appReqState, uint16_t devicePort, + Inet::InterfaceId interfaceId) { - CHIP_ERROR err = CHIP_NO_ERROR; - bool trySessionResumption = true; + CHIP_ERROR err = CHIP_NO_ERROR; + Device * device = nullptr; + + SecurePairingUsingTestSecret * testSecurePairingSecret = nullptr; - VerifyOrExit(buffer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mDeviceBeingPaired == mNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); - mAppReqState = appReqState; + testSecurePairingSecret = chip::Platform::New(Optional::Value(remoteDeviceId), + static_cast(0), static_cast(0)); + VerifyOrExit(testSecurePairingSecret != nullptr, err = CHIP_ERROR_NO_MEMORY); - if (peerDevice != kUndefinedNodeId) - { - mRemoteDeviceId = Optional::Value(peerDevice); - } - VerifyOrExit(mRemoteDeviceId.HasValue(), err = CHIP_ERROR_INCORRECT_STATE); + mDeviceBeingPaired = GetAvailableDevice(); + VerifyOrExit(mDeviceBeingPaired < mNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); + device = &mActiveDevices[mDeviceBeingPaired]; - // If there is no secure connection to the device, try establishing it - if (!IsSecurelyConnected()) - { - err = TryEstablishingSecureSession(mRemoteDeviceId.Value()); - SuccessOrExit(err); + testSecurePairingSecret->Serializable(device->mPairing); - trySessionResumption = false; + device->mDeviceId = remoteDeviceId; + device->mDevicePort = devicePort; + device->mInterface = interfaceId; + device->mState = Device::kConnectionState_Connecting; + device->mDeviceAddr = deviceAddr; + device->mSessionManager = mSessionManager; - if (mDeviceAddr == IPAddress::Any || mConState == kConnectionState_SecureConnecting) - { - // Cache the packet while connection is being established - ExitNow(err = CachePacket(buffer)); - } - } + device->Serialize(serialized); - // Hold on to the buffer, in case of session resumption and resend is needed - buffer->AddRef(); + OnRendezvousComplete(); - 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) +exit: + if (testSecurePairingSecret != nullptr) { - 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)); + chip::Platform::Delete(testSecurePairingSecret); + } - if (mConState == kConnectionState_SecureConnecting) + if (err != CHIP_NO_ERROR) + { + if (device != nullptr) { - // Cache the packet while connection is being established - ExitNow(err = CachePacket(buffer)); + ReleaseDevice(device); + mDeviceBeingPaired = mNumMaxActiveDevices; } - - err = mSessionManager->SendMessage(mRemoteDeviceId.Value(), buffer); - SuccessOrExit(err); - } - else - { - // Free the extra reference to the buffer - PacketBuffer::Free(buffer); } -exit: - return err; } - -CHIP_ERROR ChipDeviceController::ServiceEvents() +CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + Device * device = nullptr; VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mDeviceBeingPaired < mNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); -#if CONFIG_DEVICE_LAYER - err = DeviceLayer::PlatformMgr().StartEventLoopTask(); - SuccessOrExit(err); -#endif // CONFIG_DEVICE_LAYER + device = &mActiveDevices[mDeviceBeingPaired]; + VerifyOrExit(device->mDeviceId == remoteDeviceId, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); -exit: - return err; -} - -CHIP_ERROR ChipDeviceController::ServiceEventSignal() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + if (mRendezvousSession != nullptr) + { + chip::Platform::Delete(mRendezvousSession); + mRendezvousSession = nullptr; + } -#if CONFIG_DEVICE_LAYER && (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) - DeviceLayer::SystemLayer.WakeSelect(); -#else - err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; -#endif // CONFIG_DEVICE_LAYER && (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) + ReleaseDevice(device); + mDeviceBeingPaired = mNumMaxActiveDevices; exit: return err; } -CHIP_ERROR ChipDeviceController::SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate) +CHIP_ERROR DeviceCommissioner::UnpairDevice(NodeId remoteDeviceId) { - mPairingDelegate = pairingDelegate; - return CHIP_NO_ERROR; -} + // TODO: Send unpairing message to the remote device. -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) + if (mStorageDelegate != nullptr) { - SendCachedPackets(); + PERSISTENT_KEY_OP(remoteDeviceId, kPairedDeviceKeyPrefix, key, mStorageDelegate->DeleteKeyValue(key)); + mPairedDevices.Remove(remoteDeviceId); + mPairedDevicesUpdated = true; } -} -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); - } + return CHIP_NO_ERROR; } -void ChipDeviceController::OnRendezvousError(CHIP_ERROR err) +void DeviceCommissioner::OnRendezvousError(CHIP_ERROR err) { if (mRendezvousSession != nullptr) { @@ -661,72 +594,97 @@ void ChipDeviceController::OnRendezvousError(CHIP_ERROR err) { mPairingDelegate->OnPairingComplete(err); } -} -void ChipDeviceController::OnRendezvousComplete() -{ - OnRendezvousError(CHIP_NO_ERROR); + if (mDeviceBeingPaired != mNumMaxActiveDevices) + { + DeviceController::ReleaseDevice(mDeviceBeingPaired); + mDeviceBeingPaired = mNumMaxActiveDevices; + } } -void ChipDeviceController::OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) +void DeviceCommissioner::OnRendezvousComplete() { - if (mOnError != nullptr && err != CHIP_NO_ERROR) + CHIP_ERROR err = CHIP_NO_ERROR; + Device * device = nullptr; + VerifyOrExit(mDeviceBeingPaired < mNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); + device = &mActiveDevices[mDeviceBeingPaired]; + mPairedDevices.Insert(device->mDeviceId); + mPairedDevicesUpdated = true; + SuccessOrExit(err); + + if (mStorageDelegate != nullptr) { - mOnError(this, mAppReqState, err, nullptr); + SerializedDevice serialized; + device->Serialize(serialized); + PERSISTENT_KEY_OP(device->mDeviceId, kPairedDeviceKeyPrefix, key, + mStorageDelegate->SetKeyValue(key, Uint8::to_const_char(serialized.inner))); } +exit: + OnRendezvousError(err); +} + +void DeviceCommissioner::OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) +{ + Device * device = nullptr; + VerifyOrExit(mDeviceBeingPaired < mNumMaxActiveDevices, /**/); + 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().Serializable(device->mPairing); 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->mDeviceAddr = 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) + { + uint16_t size = mPairedDevices.SerializedSize(); + char serialized[size]; + uint16_t requiredSize = size; + const char * value = mPairedDevices.SerializeBase64(serialized, requiredSize); + if (value != nullptr && requiredSize <= size) + { + PERSISTENT_KEY_OP(0ull, kPairedDeviceListKeyPrefix, key, mStorageDelegate->SetKeyValue(key, value)); + mPairedDevicesUpdated = false; + } + } +} + +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 a115288e37752c..615fabdfa58294 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -28,34 +28,27 @@ #pragma once +#include #include #include #include #include +#include #include #include #include #include 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 mNumMaxActiveDevices = 64; +constexpr uint16_t mNumMaxPairedDevices = 128; class DLL_EXPORT DevicePairingDelegate { public: - virtual ~DevicePairingDelegate() {} - /** * @brief * Called when the pairing reaches a certain stage. @@ -100,117 +93,29 @@ class DLL_EXPORT DevicePairingDelegate virtual void OnPairingDeleted(CHIP_ERROR error) {} }; -class DLL_EXPORT ChipDeviceController : public SecureSessionMgrDelegate, - public RendezvousSessionDelegate, - public PersistentStorageResultDelegate +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 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); - - /** - * @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); + CHIP_ERROR Init(NodeId localDeviceId, const char * pairedDeviceSerializedSet = nullptr, + PersistentStorageDelegate * storageDelegate = nullptr, System::Layer * systemLayer = nullptr, + Inet::InetLayer * inetLayer = nullptr); - /** - * @brief - * Disconnect from a connected device - * - * @return CHIP_ERROR If the device was disconnected successfully - */ - CHIP_ERROR DisconnectDevice(); + CHIP_ERROR SetPairedDeviceList(const char * pairedDeviceSerializedSet); - /** - * @brief - * Check if there's an active connection - * - * @return bool If there is an active connection - */ - bool IsConnected() const; + virtual CHIP_ERROR Shutdown(); - /** - * @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; + CHIP_ERROR GetDevice(NodeId deviceId, const SerializedDevice & deviceInfo, Device ** device); - /** - * @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; + CHIP_ERROR GetDevice(NodeId deviceId, Device ** device); - // ----- 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 +125,6 @@ class DLL_EXPORT ChipDeviceController : public SecureSessionMgrDelegate, */ 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 +133,113 @@ class DLL_EXPORT ChipDeviceController : public SecureSessionMgrDelegate, */ CHIP_ERROR ServiceEventSignal(); +protected: + enum + { + kState_NotInitialized = 0, + kState_Initialized = 1 + } mState; + + Device mActiveDevices[mNumMaxActiveDevices]; + + SerializableU64Set mPairedDevices; + bool mPairedDevicesInitialized; + + NodeId mLocalDeviceId; + SecureSessionMgr * mSessionManager; + PersistentStorageDelegate * mStorageDelegate; + + uint16_t GetAvailableDevice(); + uint16_t FindDevice(NodeId id); + void ReleaseDevice(uint16_t index); + +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; - - //////////// 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; -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 * mSessionManager; - RendezvousSession * mRendezvousSession; +class DLL_EXPORT DeviceCommissioner : public DeviceController, public RendezvousSessionDelegate +{ +public: + DeviceCommissioner(); + ~DeviceCommissioner(); - ConnectionState mConState; - void * mAppReqState; + /** + * 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, const char * pairedDeviceSerializedSet = nullptr, + PersistentStorageDelegate * storageDelegate = nullptr, DevicePairingDelegate * pairingDelegate = nullptr, + System::Layer * systemLayer = nullptr, Inet::InetLayer * inetLayer = nullptr); - union - { - CompleteHandler General; - MessageReceiveHandler Response; - } mOnComplete; + CHIP_ERROR SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate); - ErrorHandler mOnError; - NewConnectionHandler mOnNewConnection; - System::PacketBuffer * mCurReqMsg; + CHIP_ERROR Shutdown() override; - NodeId mLocalDeviceId; - uint16_t mListenPort; - Inet::IPAddress mDeviceAddr; - uint16_t mDevicePort; - Inet::InterfaceId mInterface; - Optional mRemoteDeviceId; + // ----- Connection Management ----- + /** + * @brief + * Pair a CHIP device with the provided Rendezvous connection parameters. + * Use registered DevicePairingDelegate object to receive notifications on + * pairing status updates. + * + * @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] 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 PairDevice(NodeId remoteDeviceId, RendezvousParameters & params, void * appReqState, uint16_t devicePort = CHIP_PORT, + Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID); - SecurePairingSession mPairingSession; - SecurePairingUsingTestSecret * mTestSecurePairingSecret = nullptr; + [[deprecated("Available until Rendezvous is implemented")]] CHIP_ERROR + PairTestDeviceWithoutSecurity(NodeId remoteDeviceId, const Inet::IPAddress & deviceAddr, SerializedDevice & serialized, + void * appReqState, uint16_t devicePort = CHIP_PORT, + Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID); - SecurePairingSession * mSecurePairingSession = nullptr; + CHIP_ERROR StopPairing(NodeId remoteDeviceId); - DevicePairingDelegate * mPairingDelegate = nullptr; + /** + * @brief + * Remove pairing for a paired device. + * + * @param[in] remoteDeviceId The remote device Id. + * + * @return CHIP_ERROR The connection status + */ + CHIP_ERROR UnpairDevice(NodeId remoteDeviceId); - PersistentStorageDelegate * mStorageDelegate; + //////////// RendezvousSessionDelegate Implementation /////////////// + void OnRendezvousError(CHIP_ERROR err) override; + void OnRendezvousComplete() override; + void OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) override; + + void ReleaseDevice(Device * device) override; - System::PacketBuffer * mCachedPackets[kPacketCacheMaxSize]; - uint16_t mNumCachedPackets; +private: + // SecurePairingUsingTestSecret * mTestSecurePairingSecret; + + DevicePairingDelegate * mPairingDelegate; + RendezvousSession * mRendezvousSession; - void ClearRequestState(); - void ClearOpState(); + uint16_t mDeviceBeingPaired; - CHIP_ERROR EstablishSecureSession(); - CHIP_ERROR TryEstablishingSecureSession(NodeId peer); - CHIP_ERROR ResumeSecureSession(NodeId peer); + bool mPairedDevicesUpdated; - 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 00000000000000..954a06de93dc20 --- /dev/null +++ b/src/controller/CHIPDeviceController_deprecated.cpp @@ -0,0 +1,231 @@ +/* + * + * 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 + +#if CONFIG_DEVICE_LAYER +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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, nullptr, storageDelegate, pairingDelegate); +} + +CHIP_ERROR ChipDeviceController::Init(NodeId localNodeId, System::Layer * systemLayer, InetLayer * inetLayer, + DevicePairingDelegate * pairingDelegate, PersistentStorageDelegate * storageDelegate) +{ + return mCommissioner.Init(localNodeId, nullptr, 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, nullptr, 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, nullptr, + 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; +} + +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, mAppReqState); + + 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 00000000000000..052a6960b85514 --- /dev/null +++ b/src/controller/CHIPDeviceController_deprecated.h @@ -0,0 +1,212 @@ +/* + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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; + + // ----- 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 141447795179f5..5a02a07af7dd5f 100644 --- a/src/controller/CHIPPersistentStorageDelegate.h +++ b/src/controller/CHIPPersistentStorageDelegate.h @@ -22,7 +22,7 @@ #include namespace chip { -namespace DeviceController { +namespace Controller { class DLL_EXPORT PersistentStorageResultDelegate { @@ -79,6 +79,19 @@ class DLL_EXPORT PersistentStorageDelegate */ virtual void GetKeyValue(const char * key) = 0; + /** + * @brief + * Lookup the key and call delegate object with it's stringified value. + * This is a synchronous 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 + */ + virtual CHIP_ERROR GetKeyValue(const char * key, char * value, uint16_t & size) { return CHIP_ERROR_NOT_IMPLEMENTED; } + /** * @brief * Set the value for the key @@ -97,5 +110,5 @@ class DLL_EXPORT PersistentStorageDelegate virtual void DeleteKeyValue(const char * key) = 0; }; -} // namespace DeviceController +} // namespace Controller } // namespace chip diff --git a/src/controller/python/BUILD.gn b/src/controller/python/BUILD.gn index dd9407ada2aec2..84b22a14e87614 100644 --- a/src/controller/python/BUILD.gn +++ b/src/controller/python/BUILD.gn @@ -23,7 +23,8 @@ config("controller_wno_deprecate") { } 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 18f6c0268510ae..8e9e927815036e 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -45,7 +45,7 @@ #include "ChipDeviceController-ScriptDevicePairingDelegate.h" -#include +#include #include #include #include @@ -178,7 +178,7 @@ CHIP_ERROR 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 @@ nl_Chip_ScriptDevicePairingDelegate_SetWifiCredential(chip::DeviceController::Sc 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 17b51a62c21ca2..3a821bf45bc065 100644 --- a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h +++ b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h @@ -25,7 +25,7 @@ #pragma once -#include +#include #include #include @@ -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 be0c0fc7d91ff9..fcc9d0545a7926 100644 --- a/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m +++ b/src/darwin/CHIPTool/CHIPTool/Framework Helpers/DefaultsUtils.m @@ -48,9 +48,17 @@ @implementation CHIPToolPersistentStorageDelegate - (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 3d57db3c9149fb..a695e72fcc61d0 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 +#include #include #include #include diff --git a/src/darwin/Framework/CHIP/CHIPDevicePairingDelegateBridge.h b/src/darwin/Framework/CHIP/CHIPDevicePairingDelegateBridge.h index b448c06b5e94dc..884c17bfd5f4db 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 916b1f40e2b850..b59cce262adab0 100644 --- a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegate.h +++ b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegate.h @@ -43,6 +43,12 @@ typedef void (^SendStatus)(NSString * key, Operation operation, NSError * status */ - (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 fe9645bfa18a31..bb689a0094d304 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 @@ class CHIPPersistentStorageDelegateBridge : public chip::DeviceController::Persi void setFrameworkDelegate(id 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 @@ class CHIPPersistentStorageDelegateBridge : public chip::DeviceController::Persi id 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 51a74449ac1e76..578a910bcb890c 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,40 @@ } 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 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]; + } + 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 strongDelegate = mDelegate; if (strongDelegate && mQueue) { diff --git a/src/transport/RendezvousSession.cpp b/src/transport/RendezvousSession.cpp index 838d4d0c5603a9..8e66d74919d771 100644 --- a/src/transport/RendezvousSession.cpp +++ b/src/transport/RendezvousSession.cpp @@ -213,19 +213,33 @@ void RendezvousSession::OnRendezvousError(CHIP_ERROR err) 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 3a0b71870cb570..ed0415f2bec021 100644 --- a/src/transport/RendezvousSession.h +++ b/src/transport/RendezvousSession.h @@ -138,7 +138,7 @@ class RendezvousSession : public SecurePairingSessionDelegate, 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 61335c1fb3a8f0..9750c30c40a00c 100644 --- a/src/transport/SecurePairingSession.cpp +++ b/src/transport/SecurePairingSession.cpp @@ -57,37 +57,20 @@ SecurePairingSession::~SecurePairingSession() 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(mKeLen), error = CHIP_ERROR_INTERNAL); - VerifyOrExit(CanCastTo(localNodeId), error = CHIP_ERROR_INTERNAL); - VerifyOrExit(CanCastTo(peerNodeId), error = CHIP_ERROR_INTERNAL); - VerifyOrExit(CanCastTo(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(mKeLen); - serializable.mPairingComplete = (mPairingComplete) ? 1 : 0; - serializable.mLocalNodeId = localNodeId; - serializable.mPeerNodeId = peerNodeId; - serializable.mLocalKeyId = mLocalKeyId; - serializable.mPeerKeyId = mPeerKeyId; - - 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(&serializable)), - static_cast(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'; - } + error = Serializable(serializable); + SuccessOrExit(error); + + serializedLen = chip::Base64Encode(Uint8::to_const_uchar(reinterpret_cast(&serializable)), + static_cast(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,45 @@ CHIP_ERROR SecurePairingSession::Deserialize(SecurePairingSessionSerialized & in memset(&serializable, 0, sizeof(serializable)); deserializedLen = Base64Decode(Uint8::to_const_char(input.inner), static_cast(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::Serializable(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(mKeLen), error = CHIP_ERROR_INTERNAL); + VerifyOrExit(CanCastTo(localNodeId), error = CHIP_ERROR_INTERNAL); + VerifyOrExit(CanCastTo(peerNodeId), error = CHIP_ERROR_INTERNAL); + VerifyOrExit(CanCastTo(sizeof(SecurePairingSessionSerializable)), error = CHIP_ERROR_INTERNAL); + + memset(&serializable, 0, sizeof(serializable)); + serializable.mKeLen = static_cast(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(serializable.mKeLen); diff --git a/src/transport/SecurePairingSession.h b/src/transport/SecurePairingSession.h index dfe3857c5d6863..f41c1dce5dd784 100644 --- a/src/transport/SecurePairingSession.h +++ b/src/transport/SecurePairingSession.h @@ -74,6 +74,17 @@ class DLL_EXPORT SecurePairingSessionDelegate struct SecurePairingSessionSerialized; +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; + class DLL_EXPORT SecurePairingSession { public: @@ -178,6 +189,18 @@ class DLL_EXPORT SecurePairingSession **/ CHIP_ERROR Deserialize(SecurePairingSessionSerialized & input); + /** @brief Return the serializable data structure for secure pairing. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR Serializable(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 myNodeId, uint16_t myKeyId, SecurePairingSessionDelegate * delegate); @@ -267,17 +290,6 @@ class SecurePairingUsingTestSecret : public SecurePairingSession 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 4e41dc49620e26..a8dea8e4b15bd7 100644 --- a/src/transport/SecureSessionMgr.cpp +++ b/src/transport/SecureSessionMgr.cpp @@ -65,6 +65,8 @@ CHIP_ERROR SecureSessionMgrBase::InitInternal(NodeId localNodeId, System::Layer 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 @@ CHIP_ERROR SecureSessionMgrBase::SendMessage(PayloadHeader & payloadHeader, Node .SetEncryptionKeyID(state->GetLocalKeyID()) // .SetPayloadLength(static_cast(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 ac66baf2e4c06c..553671537fd460 100644 --- a/src/transport/SecureSessionMgr.h +++ b/src/transport/SecureSessionMgr.h @@ -224,6 +224,12 @@ class SecureSessionMgr : public SecureSessionMgrBase return err; } + template + CHIP_ERROR ResetTransport(Args &&... transportInitArgs) + { + return mTransport.Init(std::forward(transportInitArgs)...); + } + private: Transport::Tuple mTransport; }; diff --git a/src/transport/raw/Base.h b/src/transport/raw/Base.h index fe1dc4fd30dccf..f374bffbaadd13 100644 --- a/src/transport/raw/Base.h +++ b/src/transport/raw/Base.h @@ -82,6 +82,11 @@ class Base */ 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 ce065b62be172a..aa5621a91856c5 100644 --- a/src/transport/raw/UDP.cpp +++ b/src/transport/raw/UDP.cpp @@ -34,20 +34,17 @@ namespace Transport { 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 @@ CHIP_ERROR UDP::Init(UdpListenParameters & params) 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 d2dfcc36ad5812..2cfbf7646a400f 100644 --- a/src/transport/raw/UDP.h +++ b/src/transport/raw/UDP.h @@ -105,6 +105,11 @@ class DLL_EXPORT UDP : public Base */ 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; From 01ff710895b62c8c4915d648d7b2f65b7956e491 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 3 Nov 2020 12:38:42 -0800 Subject: [PATCH 02/26] Fix build errors --- src/controller/CHIPDeviceController.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index b5ab7abfbf69ce..0c83709a5d6945 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -230,7 +230,8 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) char buffer[max_size]; uint16_t size = max_size; - PERSISTENT_KEY_OP(0ull, kPairedDeviceListKeyPrefix, key, err = mStorageDelegate->GetKeyValue(key, buffer, size)); + PERSISTENT_KEY_OP(static_cast(0), kPairedDeviceListKeyPrefix, key, + err = mStorageDelegate->GetKeyValue(key, buffer, size)); SuccessOrExit(err); VerifyOrExit(size <= max_size, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); @@ -674,7 +675,7 @@ void DeviceCommissioner::PersistDeviceList() const char * value = mPairedDevices.SerializeBase64(serialized, requiredSize); if (value != nullptr && requiredSize <= size) { - PERSISTENT_KEY_OP(0ull, kPairedDeviceListKeyPrefix, key, mStorageDelegate->SetKeyValue(key, value)); + PERSISTENT_KEY_OP(static_cast(0), kPairedDeviceListKeyPrefix, key, mStorageDelegate->SetKeyValue(key, value)); mPairedDevicesUpdated = false; } } From 5276eff09de578933621d34426fa5a8d8f559d08 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Wed, 4 Nov 2020 09:14:44 -0800 Subject: [PATCH 03/26] Fix build issues --- src/controller/CHIPDeviceController.cpp | 23 ++++++------------- src/controller/CHIPDeviceController.h | 11 ++++----- .../CHIPDeviceController_deprecated.cpp | 4 ++-- .../CHIPPersistentStorageDelegate.h | 6 ++--- .../Framework/CHIP/CHIPDeviceController.mm | 16 ++++--------- 5 files changed, 22 insertions(+), 38 deletions(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 0c83709a5d6945..a61b7cd052d753 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -90,8 +90,7 @@ DeviceController::DeviceController() mPairedDevicesInitialized = false; } -CHIP_ERROR DeviceController::Init(NodeId localDeviceId, const char * pairedDeviceSerializedSet, - PersistentStorageDelegate * storageDelegate, System::Layer * systemLayer, +CHIP_ERROR DeviceController::Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate, System::Layer * systemLayer, Inet::InetLayer * inetLayer) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -106,9 +105,6 @@ CHIP_ERROR DeviceController::Init(NodeId localDeviceId, const char * pairedDevic else { #if CONFIG_DEVICE_LAYER - err = chip::Platform::MemoryInit(); - SuccessOrExit(err); - err = DeviceLayer::PlatformMgr().InitChipStack(); SuccessOrExit(err); @@ -120,12 +116,6 @@ CHIP_ERROR DeviceController::Init(NodeId localDeviceId, const char * pairedDevic VerifyOrExit(mSystemLayer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(mInetLayer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); - if (pairedDeviceSerializedSet != nullptr) - { - err = SetPairedDeviceList(pairedDeviceSerializedSet); - SuccessOrExit(err); - } - mStorageDelegate = storageDelegate; if (mStorageDelegate != nullptr) @@ -135,8 +125,9 @@ CHIP_ERROR DeviceController::Init(NodeId localDeviceId, const char * pairedDevic mSessionManager = chip::Platform::New>(); + // ToDo: Fix hardcoded IPv4 address requirement: issue# 2984 err = mSessionManager->Init(localDeviceId, mSystemLayer, - Transport::UdpListenParameters(mInetLayer).SetAddressType(kIPAddressType_IPv4)); + Transport::UdpListenParameters(mInetLayer).SetAddressType(Inet::kIPAddressType_IPv4)); SuccessOrExit(err); mSessionManager->SetDelegate(this); @@ -400,11 +391,11 @@ DeviceCommissioner::~DeviceCommissioner() PersistDeviceList(); } -CHIP_ERROR DeviceCommissioner::Init(NodeId localDeviceId, const char * pairedDeviceSerializedSet, - PersistentStorageDelegate * storageDelegate, DevicePairingDelegate * pairingDelegate, - System::Layer * systemLayer, Inet::InetLayer * inetLayer) +CHIP_ERROR DeviceCommissioner::Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate, + DevicePairingDelegate * pairingDelegate, System::Layer * systemLayer, + Inet::InetLayer * inetLayer) { - CHIP_ERROR err = DeviceController::Init(localDeviceId, pairedDeviceSerializedSet, storageDelegate, systemLayer, inetLayer); + CHIP_ERROR err = DeviceController::Init(localDeviceId, storageDelegate, systemLayer, inetLayer); SuccessOrExit(err); mPairingDelegate = pairingDelegate; diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 615fabdfa58294..9206abd9f8c625 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -103,9 +103,8 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers * 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, const char * pairedDeviceSerializedSet = nullptr, - PersistentStorageDelegate * storageDelegate = nullptr, System::Layer * systemLayer = nullptr, - Inet::InetLayer * inetLayer = nullptr); + CHIP_ERROR Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate = nullptr, + System::Layer * systemLayer = nullptr, Inet::InetLayer * inetLayer = nullptr); CHIP_ERROR SetPairedDeviceList(const char * pairedDeviceSerializedSet); @@ -178,9 +177,9 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Rendezvous * 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, const char * pairedDeviceSerializedSet = nullptr, - PersistentStorageDelegate * storageDelegate = nullptr, DevicePairingDelegate * pairingDelegate = nullptr, - System::Layer * systemLayer = nullptr, Inet::InetLayer * inetLayer = nullptr); + CHIP_ERROR Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate = nullptr, + DevicePairingDelegate * pairingDelegate = nullptr, System::Layer * systemLayer = nullptr, + Inet::InetLayer * inetLayer = nullptr); CHIP_ERROR SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate); diff --git a/src/controller/CHIPDeviceController_deprecated.cpp b/src/controller/CHIPDeviceController_deprecated.cpp index 954a06de93dc20..8aea69681b3e8f 100644 --- a/src/controller/CHIPDeviceController_deprecated.cpp +++ b/src/controller/CHIPDeviceController_deprecated.cpp @@ -84,13 +84,13 @@ ChipDeviceController::~ChipDeviceController() {} CHIP_ERROR ChipDeviceController::Init(NodeId localNodeId, DevicePairingDelegate * pairingDelegate, PersistentStorageDelegate * storageDelegate) { - return mCommissioner.Init(localNodeId, nullptr, storageDelegate, pairingDelegate); + 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, nullptr, storageDelegate, pairingDelegate, systemLayer, inetLayer); + return mCommissioner.Init(localNodeId, storageDelegate, pairingDelegate, systemLayer, inetLayer); } CHIP_ERROR ChipDeviceController::Shutdown() diff --git a/src/controller/CHIPPersistentStorageDelegate.h b/src/controller/CHIPPersistentStorageDelegate.h index 5a02a07af7dd5f..252eb1a65195e1 100644 --- a/src/controller/CHIPPersistentStorageDelegate.h +++ b/src/controller/CHIPPersistentStorageDelegate.h @@ -86,9 +86,9 @@ class DLL_EXPORT PersistentStorageDelegate * 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 + * @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 */ virtual CHIP_ERROR GetKeyValue(const char * key, char * value, uint16_t & size) { return CHIP_ERROR_NOT_IMPLEMENTED; } diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm index a695e72fcc61d0..faa2d5687bffad 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm @@ -95,6 +95,11 @@ - (instancetype)init 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 @@ - (instancetype)init _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; } From b942ca24a4789170f99ec7c8b52454a794dbed93 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Wed, 4 Nov 2020 09:24:19 -0800 Subject: [PATCH 04/26] Fix chip tool --- examples/chip-tool/commands/common/Command.h | 2 +- examples/chip-tool/commands/common/Commands.h | 2 +- src/controller/java/AndroidDeviceControllerWrapper.h | 2 +- src/controller/java/CHIPDeviceController-JNI.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/chip-tool/commands/common/Command.h b/examples/chip-tool/commands/common/Command.h index 8c81731d486726..7ef5727c32b5fe 100644 --- a/examples/chip-tool/commands/common/Command.h +++ b/examples/chip-tool/commands/common/Command.h @@ -18,7 +18,7 @@ #pragma once -#include +#include #include #include diff --git a/examples/chip-tool/commands/common/Commands.h b/examples/chip-tool/commands/common/Commands.h index 531b557994ada7..c331831f86245f 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 -#include +#include class Commands { diff --git a/src/controller/java/AndroidDeviceControllerWrapper.h b/src/controller/java/AndroidDeviceControllerWrapper.h index a2715f85d52d4f..ce961ecf69763f 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.h +++ b/src/controller/java/AndroidDeviceControllerWrapper.h @@ -21,7 +21,7 @@ #include -#include +#include /** * This class contains all relevant information for the JNI view of CHIPDeviceController diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 007e53e95938d0..721d8a78300096 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -28,7 +28,7 @@ #include "AndroidDeviceControllerWrapper.h" #include -#include +#include #include #include #include From eef4af39bb3365389660dae1de2ec29cae6f0e55 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Wed, 4 Nov 2020 09:59:00 -0800 Subject: [PATCH 05/26] More build fixes --- src/controller/CHIPDevice.cpp | 5 +++-- src/controller/CHIPDeviceController.cpp | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 212d429d576a33..a9477c04e7aab8 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -176,6 +176,9 @@ CHIP_ERROR Device::EstablishSecureSession() err = pairingSession.FromSerializable(mPairing); SuccessOrExit(err); + err = mSessionManager->ResetTransport(Transport::UdpListenParameters(mInetLayer).SetAddressType(mDeviceAddr.Type())); + SuccessOrExit(err); + err = mSessionManager->NewPairing( Optional::Value(Transport::PeerAddress::UDP(mDeviceAddr, mDevicePort, mInterface)), &pairingSession); @@ -202,8 +205,6 @@ CHIP_ERROR Device::ResumeSecureSession() } VerifyOrExit(mSessionManager != nullptr, err = CHIP_ERROR_INCORRECT_STATE); - err = mSessionManager->ResetTransport(Transport::UdpListenParameters(mInetLayer).SetAddressType(mDeviceAddr.Type())); - SuccessOrExit(err); err = EstablishSecureSession(); SuccessOrExit(err); diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index a61b7cd052d753..e225bb9dafbf63 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -125,9 +125,8 @@ CHIP_ERROR DeviceController::Init(NodeId localDeviceId, PersistentStorageDelegat mSessionManager = chip::Platform::New>(); - // ToDo: Fix hardcoded IPv4 address requirement: issue# 2984 err = mSessionManager->Init(localDeviceId, mSystemLayer, - Transport::UdpListenParameters(mInetLayer).SetAddressType(Inet::kIPAddressType_IPv4)); + Transport::UdpListenParameters(mInetLayer).SetAddressType(Inet::kIPAddressType_IPv6)); SuccessOrExit(err); mSessionManager->SetDelegate(this); From 41094826f2a57be8ef694105dea08182035ad7ff Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Wed, 4 Nov 2020 12:48:59 -0800 Subject: [PATCH 06/26] fix unsecure pairing flow --- src/transport/SecurePairingSession.h | 35 ++++++++++++++++------------ 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/transport/SecurePairingSession.h b/src/transport/SecurePairingSession.h index f41c1dce5dd784..fbbe3e42ae3e46 100644 --- a/src/transport/SecurePairingSession.h +++ b/src/transport/SecurePairingSession.h @@ -232,12 +232,6 @@ class DLL_EXPORT SecurePairingSession /* 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 mLocalNodeId = Optional::Value(kUndefinedNodeId); @@ -246,6 +240,12 @@ class DLL_EXPORT SecurePairingSession uint16_t mLocalKeyId; uint16_t mPeerKeyId; + + uint8_t mKe[kMAX_Hash_Length]; + + size_t mKeLen = sizeof(mKe); + + bool mPairingComplete = false; }; /* @@ -257,12 +257,25 @@ class DLL_EXPORT SecurePairingSession 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 peerNodeId, uint16_t peerKeyId, uint16_t 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 {} @@ -279,14 +292,6 @@ class SecurePairingUsingTestSecret : public SecurePairingSession 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(secret), secretLen, reinterpret_cast(""), - 0, reinterpret_cast(secret), secretLen); - } - CHIP_ERROR HandlePeerMessage(const PacketHeader & packetHeader, System::PacketBuffer * msg) override { return CHIP_NO_ERROR; } }; From 4477c9a3607ef95c60eef2219066579e4d889600 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Wed, 4 Nov 2020 12:50:51 -0800 Subject: [PATCH 07/26] Fix style --- src/transport/SecurePairingSession.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/transport/SecurePairingSession.h b/src/transport/SecurePairingSession.h index fbbe3e42ae3e46..e50109f26626b6 100644 --- a/src/transport/SecurePairingSession.h +++ b/src/transport/SecurePairingSession.h @@ -261,7 +261,7 @@ class SecurePairingUsingTestSecret : public SecurePairingSession { const char * secret = "Test secret for key derivation"; size_t secretLen = strlen(secret); - mKeLen = secretLen; + mKeLen = secretLen; memmove(mKe, secret, mKeLen); mPairingComplete = true; } @@ -270,10 +270,10 @@ class SecurePairingUsingTestSecret : public SecurePairingSession { const char * secret = "Test secret for key derivation"; size_t secretLen = strlen(secret); - mPeerNodeId = peerNodeId; - mPeerKeyId = peerKeyId; - mLocalKeyId = localKeyId; - mKeLen = secretLen; + mPeerNodeId = peerNodeId; + mPeerKeyId = peerKeyId; + mLocalKeyId = localKeyId; + mKeLen = secretLen; memmove(mKe, secret, mKeLen); mPairingComplete = true; } From 77fe0a99ccc23c34cc20117f71229b4db46230c4 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Thu, 5 Nov 2020 09:28:10 -0800 Subject: [PATCH 08/26] Fix Android build --- src/controller/CHIPDevice.cpp | 7 +++++++ src/controller/CHIPDevice.h | 2 ++ src/controller/CHIPDeviceController_deprecated.cpp | 8 ++++++++ src/controller/CHIPDeviceController_deprecated.h | 8 ++++++++ 4 files changed, 25 insertions(+) diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index a9477c04e7aab8..9fd45e7ef3cc1e 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -218,5 +218,12 @@ CHIP_ERROR Device::ResumeSecureSession() return err; } +bool Device::GetIpAddress(Inet::IPAddress & addr) const +{ + if (mState == kConnectionState_SecureConnected) + addr = mDeviceAddr; + return mState == kConnectionState_SecureConnected; +} + } // namespace Controller } // namespace chip diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index 966363d2ca262a..4d044b776c7cbb 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -76,6 +76,8 @@ class DLL_EXPORT Device */ CHIP_ERROR SendMessage(System::PacketBuffer * buffer); + bool GetIpAddress(Inet::IPAddress & addr) const; + private: enum ConnectionState { diff --git a/src/controller/CHIPDeviceController_deprecated.cpp b/src/controller/CHIPDeviceController_deprecated.cpp index 8aea69681b3e8f..3996a8883b9f66 100644 --- a/src/controller/CHIPDeviceController_deprecated.cpp +++ b/src/controller/CHIPDeviceController_deprecated.cpp @@ -166,6 +166,14 @@ 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) diff --git a/src/controller/CHIPDeviceController_deprecated.h b/src/controller/CHIPDeviceController_deprecated.h index 052a6960b85514..d1bf8369893327 100644 --- a/src/controller/CHIPDeviceController_deprecated.h +++ b/src/controller/CHIPDeviceController_deprecated.h @@ -136,6 +136,14 @@ class DLL_EXPORT ChipDeviceController : public Controller::DeviceStatusDelegate */ 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 From 4c8e7607813f708c3b981e7b6a067c6337ee22f9 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Thu, 5 Nov 2020 11:22:22 -0800 Subject: [PATCH 09/26] Address review comments --- src/controller/CHIPDevice.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 9fd45e7ef3cc1e..5d39be14b2f988 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -16,15 +16,7 @@ * limitations under the License. */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif -#ifndef __STDC_FORMAT_MACROS -#define __STDC_FORMAT_MACROS -#endif - -// module header, comes first -#include +#include #if CONFIG_DEVICE_LAYER #include From bc28dddbc2eeebdfd7d4a57f1ea2fce6b2dbd9de Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Thu, 5 Nov 2020 11:55:57 -0800 Subject: [PATCH 10/26] add virtual destructor --- src/controller/CHIPDeviceController.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 9206abd9f8c625..de7ae66c727e20 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -49,6 +49,8 @@ constexpr uint16_t mNumMaxPairedDevices = 128; class DLL_EXPORT DevicePairingDelegate { public: + virtual ~DevicePairingDelegate() {} + /** * @brief * Called when the pairing reaches a certain stage. From 32dd372dcd15180b63650a17edc4b8aa81468740 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 9 Nov 2020 08:24:24 -0800 Subject: [PATCH 11/26] Fix build after rebase --- src/controller/CHIPDeviceController.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index e225bb9dafbf63..d3af353708abdc 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -64,8 +64,8 @@ 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. From 1f2122d915f577d145a80a5d5cfdad917d54fe95 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 9 Nov 2020 08:33:25 -0800 Subject: [PATCH 12/26] Fix unbounded stack usage --- src/controller/CHIPDeviceController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index d3af353708abdc..505066a738ca2f 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -659,7 +659,7 @@ void DeviceCommissioner::PersistDeviceList() { if (mStorageDelegate != nullptr && mPairedDevicesUpdated) { - uint16_t size = mPairedDevices.SerializedSize(); + const uint16_t size = mPairedDevices.SerializedSize(); char serialized[size]; uint16_t requiredSize = size; const char * value = mPairedDevices.SerializeBase64(serialized, requiredSize); From 9abf333d20695f63cfce05044179b744ae6f83d4 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 9 Nov 2020 08:40:14 -0800 Subject: [PATCH 13/26] Fix unbounded stack size --- src/controller/CHIPDeviceController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 505066a738ca2f..ba54a924c6ff69 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -659,7 +659,7 @@ void DeviceCommissioner::PersistDeviceList() { if (mStorageDelegate != nullptr && mPairedDevicesUpdated) { - const uint16_t size = mPairedDevices.SerializedSize(); + const uint16_t size = mPairedDevices.MaxSerializedSize(); char serialized[size]; uint16_t requiredSize = size; const char * value = mPairedDevices.SerializeBase64(serialized, requiredSize); From d194a2d14711acc1ab048493565cdc7f2f6c142b Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 9 Nov 2020 09:08:35 -0800 Subject: [PATCH 14/26] Fix stack usage --- src/controller/CHIPDeviceController.cpp | 48 ++++++++++++------------ src/controller/CHIPDeviceController.h | 8 ++-- src/lib/support/SerializableIntegerSet.h | 6 ++- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index ba54a924c6ff69..6adbd01e2593c5 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -177,7 +177,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, const SerializedDevice & Device * device = nullptr; uint16_t index = FindDevice(deviceId); - if (index < mNumMaxActiveDevices) + if (index < kNumMaxActiveDevices) { device = &mActiveDevices[index]; } @@ -186,7 +186,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, const SerializedDevice & VerifyOrExit(mPairedDevices.Contains(deviceId), err = CHIP_ERROR_NOT_CONNECTED); index = GetAvailableDevice(); - VerifyOrExit(index < mNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); + VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); device = &mActiveDevices[index]; err = device->Deserialize(deviceInfo); @@ -208,7 +208,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) Device * device = nullptr; uint16_t index = FindDevice(deviceId); - if (index < mNumMaxActiveDevices) + if (index < kNumMaxActiveDevices) { device = &mActiveDevices[index]; } @@ -216,7 +216,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) { if (!mPairedDevicesInitialized) { - const uint16_t max_size = mPairedDevices.MaxSerializedSize(); + const uint16_t max_size = CHIP_MAX_SERIALIZED_SIZE_U64(kNumMaxPairedDevices); char buffer[max_size]; uint16_t size = max_size; @@ -232,7 +232,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) VerifyOrExit(mPairedDevices.Contains(deviceId), err = CHIP_ERROR_NOT_CONNECTED); index = GetAvailableDevice(); - VerifyOrExit(index < mNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); + VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); device = &mActiveDevices[index]; { @@ -304,7 +304,7 @@ void DeviceController::OnMessageReceived(const PacketHeader & header, const Payl peer = header.GetSourceNodeId().Value(); index = FindDevice(peer); - VerifyOrExit(index < mNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); + VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); mActiveDevices[index].OnMessageReceived(header, payloadHeader, state, msgBuf, mgr); @@ -315,9 +315,9 @@ void DeviceController::OnMessageReceived(const PacketHeader & header, const Payl uint16_t DeviceController::GetAvailableDevice() { uint16_t i = 0; - while (i < mNumMaxActiveDevices && mActiveDevices[i].mActive) + while (i < kNumMaxActiveDevices && mActiveDevices[i].mActive) i++; - if (i < mNumMaxActiveDevices) + if (i < kNumMaxActiveDevices) { mActiveDevices[i].mActive = true; } @@ -332,7 +332,7 @@ void DeviceController::ReleaseDevice(Device * device) void DeviceController::ReleaseDevice(uint16_t index) { - if (index < mNumMaxActiveDevices) + if (index < kNumMaxActiveDevices) { ReleaseDevice(&mActiveDevices[index]); } @@ -341,7 +341,7 @@ void DeviceController::ReleaseDevice(uint16_t index) uint16_t DeviceController::FindDevice(NodeId id) { uint16_t i = 0; - while (i < mNumMaxActiveDevices) + while (i < kNumMaxActiveDevices) { if (mActiveDevices[i].mActive && mActiveDevices[i].mDeviceId == id) { @@ -381,7 +381,7 @@ DeviceCommissioner::DeviceCommissioner() : DeviceController() { mPairingDelegate = nullptr; mRendezvousSession = nullptr; - mDeviceBeingPaired = mNumMaxActiveDevices; + mDeviceBeingPaired = kNumMaxActiveDevices; mPairedDevicesUpdated = false; } @@ -438,7 +438,7 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam Device * device = nullptr; VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); - VerifyOrExit(mDeviceBeingPaired == mNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mDeviceBeingPaired == kNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); #if CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE if (!params.HasBleLayer()) @@ -448,7 +448,7 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam #endif // CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE mDeviceBeingPaired = GetAvailableDevice(); - VerifyOrExit(mDeviceBeingPaired < mNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); + VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); device = &mActiveDevices[mDeviceBeingPaired]; if (mRendezvousSession != nullptr) @@ -478,7 +478,7 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam if (device != nullptr) { ReleaseDevice(device); - mDeviceBeingPaired = mNumMaxActiveDevices; + mDeviceBeingPaired = kNumMaxActiveDevices; } } @@ -495,14 +495,14 @@ CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDevice SecurePairingUsingTestSecret * testSecurePairingSecret = nullptr; VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); - VerifyOrExit(mDeviceBeingPaired == mNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mDeviceBeingPaired == kNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); testSecurePairingSecret = chip::Platform::New(Optional::Value(remoteDeviceId), static_cast(0), static_cast(0)); VerifyOrExit(testSecurePairingSecret != nullptr, err = CHIP_ERROR_NO_MEMORY); mDeviceBeingPaired = GetAvailableDevice(); - VerifyOrExit(mDeviceBeingPaired < mNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); + VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); device = &mActiveDevices[mDeviceBeingPaired]; testSecurePairingSecret->Serializable(device->mPairing); @@ -529,7 +529,7 @@ CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDevice if (device != nullptr) { ReleaseDevice(device); - mDeviceBeingPaired = mNumMaxActiveDevices; + mDeviceBeingPaired = kNumMaxActiveDevices; } } @@ -541,7 +541,7 @@ CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId) Device * device = nullptr; VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); - VerifyOrExit(mDeviceBeingPaired < mNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); device = &mActiveDevices[mDeviceBeingPaired]; VerifyOrExit(device->mDeviceId == remoteDeviceId, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); @@ -553,7 +553,7 @@ CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId) } ReleaseDevice(device); - mDeviceBeingPaired = mNumMaxActiveDevices; + mDeviceBeingPaired = kNumMaxActiveDevices; exit: return err; @@ -586,10 +586,10 @@ void DeviceCommissioner::OnRendezvousError(CHIP_ERROR err) mPairingDelegate->OnPairingComplete(err); } - if (mDeviceBeingPaired != mNumMaxActiveDevices) + if (mDeviceBeingPaired != kNumMaxActiveDevices) { DeviceController::ReleaseDevice(mDeviceBeingPaired); - mDeviceBeingPaired = mNumMaxActiveDevices; + mDeviceBeingPaired = kNumMaxActiveDevices; } } @@ -597,7 +597,7 @@ void DeviceCommissioner::OnRendezvousComplete() { CHIP_ERROR err = CHIP_NO_ERROR; Device * device = nullptr; - VerifyOrExit(mDeviceBeingPaired < mNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); + VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); device = &mActiveDevices[mDeviceBeingPaired]; mPairedDevices.Insert(device->mDeviceId); mPairedDevicesUpdated = true; @@ -618,7 +618,7 @@ void DeviceCommissioner::OnRendezvousComplete() void DeviceCommissioner::OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) { Device * device = nullptr; - VerifyOrExit(mDeviceBeingPaired < mNumMaxActiveDevices, /**/); + VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, /**/); device = &mActiveDevices[mDeviceBeingPaired]; switch (status) { @@ -659,7 +659,7 @@ void DeviceCommissioner::PersistDeviceList() { if (mStorageDelegate != nullptr && mPairedDevicesUpdated) { - const uint16_t size = mPairedDevices.MaxSerializedSize(); + const uint16_t size = CHIP_MAX_SERIALIZED_SIZE_U64(kNumMaxPairedDevices); char serialized[size]; uint16_t requiredSize = size; const char * value = mPairedDevices.SerializeBase64(serialized, requiredSize); diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index de7ae66c727e20..e75ff504d4eef0 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -43,8 +43,8 @@ namespace chip { namespace Controller { -constexpr uint16_t mNumMaxActiveDevices = 64; -constexpr uint16_t mNumMaxPairedDevices = 128; +constexpr uint16_t kNumMaxActiveDevices = 64; +constexpr uint16_t kNumMaxPairedDevices = 128; class DLL_EXPORT DevicePairingDelegate { @@ -141,9 +141,9 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers kState_Initialized = 1 } mState; - Device mActiveDevices[mNumMaxActiveDevices]; + Device mActiveDevices[kNumMaxActiveDevices]; - SerializableU64Set mPairedDevices; + SerializableU64Set mPairedDevices; bool mPairedDevicesInitialized; NodeId mLocalDeviceId; diff --git a/src/lib/support/SerializableIntegerSet.h b/src/lib/support/SerializableIntegerSet.h index 0fe6e0d368a7de..6e59f7751c76bb 100644 --- a/src/lib/support/SerializableIntegerSet.h +++ b/src/lib/support/SerializableIntegerSet.h @@ -34,6 +34,8 @@ #include #include +#define CHIP_MAX_SERIALIZED_SIZE_U64(count) static_cast(BASE64_ENCODED_LEN(sizeof(uint64_t) * (count))) + namespace chip { class SerializableU64SetBase @@ -78,13 +80,13 @@ class SerializableU64SetBase * @brief * Get the length of string if the array is serialized. */ - uint16_t SerializedSize() { return static_cast(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(BASE64_ENCODED_LEN(sizeof(uint64_t) * mCapacity)); } + uint16_t MaxSerializedSize() { return CHIP_MAX_SERIALIZED_SIZE_U64(mCapacity); } /** * @brief From d7f176bdcbb8d8d5655a68cfeb5c78fad3725a4b Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 9 Nov 2020 09:49:24 -0800 Subject: [PATCH 15/26] Fix Android build --- src/controller/java/AndroidDeviceControllerWrapper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/java/AndroidDeviceControllerWrapper.h b/src/controller/java/AndroidDeviceControllerWrapper.h index ce961ecf69763f..59eb1febcfb058 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.h +++ b/src/controller/java/AndroidDeviceControllerWrapper.h @@ -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(); From 5d4854b6cffd60ddcff5bec2daec49886661b65a Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 9 Nov 2020 11:45:47 -0800 Subject: [PATCH 16/26] Address review comments --- src/controller/CHIPDevice.cpp | 16 ++-- src/controller/CHIPDevice.h | 85 +++++++++++-------- src/controller/CHIPDeviceController.cpp | 72 +++++++++------- src/controller/CHIPDeviceController.h | 10 +-- .../CHIPDeviceController_deprecated.cpp | 8 +- 5 files changed, 103 insertions(+), 88 deletions(-) diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 5d39be14b2f988..f0b8c2b6a20041 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -49,7 +49,7 @@ CHIP_ERROR Device::SendMessage(System::PacketBuffer * buffer) // If there is no secure connection to the device, try establishing it if (mState != kConnectionState_SecureConnected) { - err = EstablishSecureSession(); + err = LoadSecureSessionParameters(); SuccessOrExit(err); } else @@ -155,7 +155,7 @@ void Device::OnMessageReceived(const PacketHeader & header, const PayloadHeader } } -CHIP_ERROR Device::EstablishSecureSession() +CHIP_ERROR Device::LoadSecureSessionParameters() { CHIP_ERROR err = CHIP_NO_ERROR; SecurePairingSession pairingSession; @@ -182,7 +182,7 @@ CHIP_ERROR Device::EstablishSecureSession() if (err != CHIP_NO_ERROR) { - ChipLogError(Controller, "EstablishSecureSession returning error %d\n", err); + ChipLogError(Controller, "LoadSecureSessionParameters returning error %d\n", err); } return err; } @@ -191,14 +191,12 @@ CHIP_ERROR Device::ResumeSecureSession() { CHIP_ERROR err = CHIP_NO_ERROR; - if (mState == kConnectionState_SecureConnected) - { - mState = kConnectionState_NotConnected; - } - + VerifyOrExit(mState == kConnectionState_SecureConnected, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mSessionManager != nullptr, err = CHIP_ERROR_INCORRECT_STATE); - err = EstablishSecureSession(); + mState = kConnectionState_NotConnected; + + err = LoadSecureSessionParameters(); SuccessOrExit(err); exit: diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index 4d044b776c7cbb..3cc252312aec27 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -57,33 +57,63 @@ struct SerializedDevice; class DLL_EXPORT Device { public: - friend class DeviceController; - friend class DeviceCommissioner; + Device() {} + ~Device() {} + + void SetDelegate(DeviceStatusDelegate * delegate) { mStatusDelegate = delegate; } + + // ----- Messaging ----- + CHIP_ERROR SendMessage(System::PacketBuffer * message); + + bool GetIpAddress(Inet::IPAddress & addr) const; - void SetDelegate(DeviceStatusDelegate * delegate, void * state) + void Init(SecureSessionMgr * sessionMgr, Inet::InetLayer * inetLayer) { - mStatusDelegate = delegate; - mAppReqState = state; + mSessionManager = sessionMgr; + mInetLayer = inetLayer; } - // ----- Messaging ----- - /** - * @brief - * Send a message to a connected CHIP device + void Init(SecureSessionMgr * sessionMgr, Inet::InetLayer * inetLayer, NodeId deviceId, uint16_t devicePort, + Inet::InterfaceId interfaceId) + { + Init(sessionMgr, inetLayer); + mDeviceId = deviceId; + mDevicePort = devicePort; + mInterface = interfaceId; + mState = kConnectionState_Connecting; + } + + /** @brief Serialize the Pairing Session to a string. * - * @param[in] buffer The Data Buffer to trasmit to the device - * @return CHIP_ERROR The return status - */ - CHIP_ERROR SendMessage(System::PacketBuffer * buffer); + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR Serialize(SerializedDevice & output); - bool GetIpAddress(Inet::IPAddress & addr) const; + /** @brief Deserialize the Pairing Session from the string. + * + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ + CHIP_ERROR Deserialize(const SerializedDevice & input); + + void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, Transport::PeerConnectionState * state, + System::PacketBuffer * msgBuf, SecureSessionMgrBase * mgr); + + bool IsActive() { return mActive; } + + void SetActive(bool active) { mActive = active; } + + NodeId GetDeviceId() { return mDeviceId; } + + void SetAddress(Inet::IPAddress deviceAddr) { mDeviceAddr = deviceAddr; } + + SecurePairingSessionSerializable & GetPairing() { return mPairing; } private: enum ConnectionState { - kConnectionState_NotConnected = 0, - kConnectionState_Connecting = 1, - kConnectionState_SecureConnected = 2, + kConnectionState_NotConnected, + kConnectionState_Connecting, + kConnectionState_SecureConnected, }; NodeId mDeviceId; @@ -93,35 +123,16 @@ class DLL_EXPORT Device Inet::InetLayer * mInetLayer; - Device() {} - ~Device() {} - bool mActive = false; ConnectionState mState; SecurePairingSessionSerializable mPairing; DeviceStatusDelegate * mStatusDelegate; - void * mAppReqState; SecureSessionMgr * mSessionManager; - /** @brief Serialize the Pairing Session to a string. - * - * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise - **/ - CHIP_ERROR Serialize(SerializedDevice & output); - - /** @brief Deserialize the Pairing Session from the string. - * - * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise - **/ - CHIP_ERROR Deserialize(const SerializedDevice & input); - - void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, Transport::PeerConnectionState * state, - System::PacketBuffer * msgBuf, SecureSessionMgrBase * mgr); - - CHIP_ERROR EstablishSecureSession(); + CHIP_ERROR LoadSecureSessionParameters(); CHIP_ERROR ResumeSecureSession(); }; diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 6adbd01e2593c5..217aaa6cdaf369 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -192,8 +192,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, const SerializedDevice & err = device->Deserialize(deviceInfo); VerifyOrExit(err == CHIP_NO_ERROR, ReleaseDevice(device)); - device->mSessionManager = mSessionManager; - device->mInetLayer = mInetLayer; + device->Init(mSessionManager, mInetLayer); } (*out_device) = device; @@ -247,8 +246,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) err = device->Deserialize(deviceInfo); VerifyOrExit(err == CHIP_NO_ERROR, ReleaseDevice(device)); - device->mSessionManager = mSessionManager; - device->mInetLayer = mInetLayer; + device->Init(mSessionManager, mInetLayer); } } @@ -315,11 +313,11 @@ void DeviceController::OnMessageReceived(const PacketHeader & header, const Payl uint16_t DeviceController::GetAvailableDevice() { uint16_t i = 0; - while (i < kNumMaxActiveDevices && mActiveDevices[i].mActive) + while (i < kNumMaxActiveDevices && mActiveDevices[i].IsActive()) i++; if (i < kNumMaxActiveDevices) { - mActiveDevices[i].mActive = true; + mActiveDevices[i].SetActive(true); } return i; @@ -327,7 +325,7 @@ uint16_t DeviceController::GetAvailableDevice() void DeviceController::ReleaseDevice(Device * device) { - device->mActive = false; + device->SetActive(false); } void DeviceController::ReleaseDevice(uint16_t index) @@ -343,7 +341,7 @@ uint16_t DeviceController::FindDevice(NodeId id) uint16_t i = 0; while (i < kNumMaxActiveDevices) { - if (mActiveDevices[i].mActive && mActiveDevices[i].mDeviceId == id) + if (mActiveDevices[i].IsActive() && mActiveDevices[i].GetDeviceId() == id) { return i; } @@ -431,8 +429,8 @@ CHIP_ERROR DeviceCommissioner::Shutdown() return err; } -CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & params, void * appReqState, - uint16_t devicePort, Inet::InterfaceId interfaceId) +CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & params, uint16_t devicePort, + Inet::InterfaceId interfaceId) { CHIP_ERROR err = CHIP_NO_ERROR; Device * device = nullptr; @@ -460,11 +458,7 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam err = mRendezvousSession->Init(params.SetLocalNodeId(mLocalDeviceId)); SuccessOrExit(err); - device->mDeviceId = remoteDeviceId; - device->mDevicePort = devicePort; - device->mInterface = interfaceId; - device->mState = Device::kConnectionState_Connecting; - device->mSessionManager = mSessionManager; + device->Init(mSessionManager, mInetLayer, remoteDeviceId, devicePort, interfaceId); exit: if (err != CHIP_NO_ERROR) @@ -486,7 +480,7 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam } CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDeviceId, const Inet::IPAddress & deviceAddr, - SerializedDevice & serialized, void * appReqState, uint16_t devicePort, + SerializedDevice & serialized, uint16_t devicePort, Inet::InterfaceId interfaceId) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -505,14 +499,11 @@ CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDevice VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); device = &mActiveDevices[mDeviceBeingPaired]; - testSecurePairingSecret->Serializable(device->mPairing); + testSecurePairingSecret->Serializable(device->GetPairing()); - device->mDeviceId = remoteDeviceId; - device->mDevicePort = devicePort; - device->mInterface = interfaceId; - device->mState = Device::kConnectionState_Connecting; - device->mDeviceAddr = deviceAddr; - device->mSessionManager = mSessionManager; + device->Init(mSessionManager, mInetLayer, remoteDeviceId, devicePort, interfaceId); + + device->SetAddress(deviceAddr); device->Serialize(serialized); @@ -544,7 +535,7 @@ CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId) VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); device = &mActiveDevices[mDeviceBeingPaired]; - VerifyOrExit(device->mDeviceId == remoteDeviceId, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); + VerifyOrExit(device->GetDeviceId() == remoteDeviceId, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); if (mRendezvousSession != nullptr) { @@ -573,7 +564,7 @@ CHIP_ERROR DeviceCommissioner::UnpairDevice(NodeId remoteDeviceId) return CHIP_NO_ERROR; } -void DeviceCommissioner::OnRendezvousError(CHIP_ERROR err) +void DeviceCommissioner::RendezvousCleanup(CHIP_ERROR status) { if (mRendezvousSession != nullptr) { @@ -583,7 +574,7 @@ void DeviceCommissioner::OnRendezvousError(CHIP_ERROR err) if (mPairingDelegate != nullptr) { - mPairingDelegate->OnPairingComplete(err); + mPairingDelegate->OnPairingComplete(status); } if (mDeviceBeingPaired != kNumMaxActiveDevices) @@ -593,38 +584,53 @@ void DeviceCommissioner::OnRendezvousError(CHIP_ERROR err) } } +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->mDeviceId); + mPairedDevices.Insert(device->GetDeviceId()); mPairedDevicesUpdated = true; - SuccessOrExit(err); if (mStorageDelegate != nullptr) { SerializedDevice serialized; device->Serialize(serialized); - PERSISTENT_KEY_OP(device->mDeviceId, kPairedDeviceKeyPrefix, key, + PERSISTENT_KEY_OP(device->GetDeviceId(), kPairedDeviceKeyPrefix, key, mStorageDelegate->SetKeyValue(key, Uint8::to_const_char(serialized.inner))); } exit: - OnRendezvousError(err); + if (err == CHIP_NO_ERROR) + { + RendezvousCleanup(CHIP_NO_ERROR); + } + else + { + OnRendezvousError(err); + } } void DeviceCommissioner::OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) { Device * device = nullptr; - VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, /**/); + if (mDeviceBeingPaired >= kNumMaxActiveDevices) + { + ExitNow(); + } + device = &mActiveDevices[mDeviceBeingPaired]; switch (status) { case RendezvousSessionDelegate::SecurePairingSuccess: ChipLogDetail(Controller, "Remote device completed SPAKE2+ handshake\n"); - mRendezvousSession->GetPairingSession().Serializable(device->mPairing); + mRendezvousSession->GetPairingSession().Serializable(device->GetPairing()); if (mPairingDelegate != nullptr) { @@ -638,7 +644,7 @@ void DeviceCommissioner::OnRendezvousStatusUpdate(RendezvousSessionDelegate::Sta case RendezvousSessionDelegate::NetworkProvisioningSuccess: ChipLogDetail(Controller, "Remote device was assigned an ip address\n"); - device->mDeviceAddr = mRendezvousSession->GetIPAddress(); + device->SetAddress(mRendezvousSession->GetIPAddress()); break; case RendezvousSessionDelegate::NetworkProvisioningFailed: diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index e75ff504d4eef0..30e5966247e555 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -149,6 +149,7 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers NodeId mLocalDeviceId; SecureSessionMgr * mSessionManager; PersistentStorageDelegate * mStorageDelegate; + Inet::InetLayer * mInetLayer; uint16_t GetAvailableDevice(); uint16_t FindDevice(NodeId id); @@ -166,7 +167,6 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers void OnStatus(const char * key, Operation op, CHIP_ERROR err) override; System::Layer * mSystemLayer; - Inet::InetLayer * mInetLayer; }; class DLL_EXPORT DeviceCommissioner : public DeviceController, public RendezvousSessionDelegate @@ -196,19 +196,17 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Rendezvous * * @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] 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 PairDevice(NodeId remoteDeviceId, RendezvousParameters & params, void * appReqState, uint16_t devicePort = CHIP_PORT, + 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, - void * appReqState, uint16_t devicePort = CHIP_PORT, - Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID); + uint16_t devicePort = CHIP_PORT, Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID); CHIP_ERROR StopPairing(NodeId remoteDeviceId); @@ -227,6 +225,8 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Rendezvous void OnRendezvousComplete() override; void OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) override; + void RendezvousCleanup(CHIP_ERROR status); + void ReleaseDevice(Device * device) override; private: diff --git a/src/controller/CHIPDeviceController_deprecated.cpp b/src/controller/CHIPDeviceController_deprecated.cpp index 3996a8883b9f66..eaaa237488b251 100644 --- a/src/controller/CHIPDeviceController_deprecated.cpp +++ b/src/controller/CHIPDeviceController_deprecated.cpp @@ -102,7 +102,7 @@ CHIP_ERROR ChipDeviceController::ConnectDevice(NodeId remoteDeviceId, Rendezvous NewConnectionHandler onConnected, MessageReceiveHandler onMessageReceived, ErrorHandler onError, uint16_t devicePort, Inet::InterfaceId interfaceId) { - CHIP_ERROR err = mCommissioner.PairDevice(remoteDeviceId, params, nullptr, devicePort, interfaceId); + CHIP_ERROR err = mCommissioner.PairDevice(remoteDeviceId, params, devicePort, interfaceId); SuccessOrExit(err); mRemoteDeviceId = remoteDeviceId; @@ -121,8 +121,8 @@ CHIP_ERROR ChipDeviceController::ConnectDeviceWithoutSecurePairing(NodeId remote MessageReceiveHandler onMessageReceived, ErrorHandler onError, uint16_t devicePort, Inet::InterfaceId interfaceId) { - CHIP_ERROR err = mCommissioner.PairTestDeviceWithoutSecurity(remoteDeviceId, deviceAddr, mSerializedTestDevice, nullptr, - devicePort, interfaceId); + CHIP_ERROR err = + mCommissioner.PairTestDeviceWithoutSecurity(remoteDeviceId, deviceAddr, mSerializedTestDevice, devicePort, interfaceId); SuccessOrExit(err); mPairingWithoutSecurity = true; @@ -212,7 +212,7 @@ CHIP_ERROR ChipDeviceController::SendMessage(void * appReqState, PacketBuffer * } VerifyOrExit(mDevice != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); - mDevice->SetDelegate(this, mAppReqState); + mDevice->SetDelegate(this); err = mDevice->SendMessage(buffer); From 12d17148bc186f02ecc051af15c102f602df83ca Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 9 Nov 2020 17:20:21 -0800 Subject: [PATCH 17/26] Add documentation --- src/controller/CHIPDevice.cpp | 8 ++ src/controller/CHIPDevice.h | 77 +++++++++++++------ .../CHIPPersistentStorageDelegate.h | 5 +- src/transport/SecurePairingSession.h | 6 +- 4 files changed, 70 insertions(+), 26 deletions(-) diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index f0b8c2b6a20041..d500bb7481a1a0 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -16,6 +16,14 @@ * 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 #if CONFIG_DEVICE_LAYER diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index 3cc252312aec27..e474447dd45018 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -16,6 +16,14 @@ * 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 @@ -30,28 +38,7 @@ namespace chip { namespace Controller { class DeviceController; - -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){}; -}; - +class DeviceStatusDelegate; struct SerializedDevice; class DLL_EXPORT Device @@ -63,8 +50,27 @@ class DLL_EXPORT Device 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; void Init(SecureSessionMgr * sessionMgr, Inet::InetLayer * inetLayer) @@ -136,6 +142,33 @@ class DLL_EXPORT Device CHIP_ERROR ResumeSecureSession(); }; +/** + * 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; diff --git a/src/controller/CHIPPersistentStorageDelegate.h b/src/controller/CHIPPersistentStorageDelegate.h index 252eb1a65195e1..65ce9340b26e48 100644 --- a/src/controller/CHIPPersistentStorageDelegate.h +++ b/src/controller/CHIPPersistentStorageDelegate.h @@ -88,7 +88,10 @@ class DLL_EXPORT PersistentStorageDelegate * * @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 + * @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; } diff --git a/src/transport/SecurePairingSession.h b/src/transport/SecurePairingSession.h index e50109f26626b6..2b5029250f5f82 100644 --- a/src/transport/SecurePairingSession.h +++ b/src/transport/SecurePairingSession.h @@ -74,7 +74,7 @@ class DLL_EXPORT SecurePairingSessionDelegate struct SecurePairingSessionSerialized; -typedef struct SecurePairingSessionSerializable +struct SecurePairingSessionSerializable { uint16_t mKeLen; uint8_t mKe[kMAX_Hash_Length]; @@ -83,7 +83,7 @@ typedef struct SecurePairingSessionSerializable uint64_t mPeerNodeId; uint16_t mLocalKeyId; uint16_t mPeerKeyId; -} SecurePairingSessionSerializable; +}; class DLL_EXPORT SecurePairingSession { @@ -189,7 +189,7 @@ class DLL_EXPORT SecurePairingSession **/ CHIP_ERROR Deserialize(SecurePairingSessionSerialized & input); - /** @brief Return the serializable data structure for secure pairing. + /** @brief Serialize the SecurePairingSession to the given serializable data structure for secure pairing * * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise **/ From 1e38ed21d862ad8f1582f65b6b5b6f22a24f6f7f Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 9 Nov 2020 17:23:13 -0800 Subject: [PATCH 18/26] remove redundant check --- src/transport/SecurePairingSession.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/transport/SecurePairingSession.cpp b/src/transport/SecurePairingSession.cpp index 9750c30c40a00c..6458bcd8cc814d 100644 --- a/src/transport/SecurePairingSession.cpp +++ b/src/transport/SecurePairingSession.cpp @@ -109,7 +109,6 @@ CHIP_ERROR SecurePairingSession::Serializable(SecurePairingSessionSerializable & VerifyOrExit(CanCastTo(mKeLen), error = CHIP_ERROR_INTERNAL); VerifyOrExit(CanCastTo(localNodeId), error = CHIP_ERROR_INTERNAL); VerifyOrExit(CanCastTo(peerNodeId), error = CHIP_ERROR_INTERNAL); - VerifyOrExit(CanCastTo(sizeof(SecurePairingSessionSerializable)), error = CHIP_ERROR_INTERNAL); memset(&serializable, 0, sizeof(serializable)); serializable.mKeLen = static_cast(mKeLen); From aa4d51461365301c2f7f4ce0dd2a33ba07fba22a Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 10 Nov 2020 10:04:24 -0800 Subject: [PATCH 19/26] Address review comments --- src/controller/CHIPDevice.cpp | 56 ++++------ src/controller/CHIPDevice.h | 103 +++++++++++++++--- src/controller/CHIPDeviceController.cpp | 24 ++-- src/controller/CHIPDeviceController.h | 75 +++++++++++-- .../CHIPPersistentStorageDelegate.h | 3 +- .../CHIPPersistentStorageDelegateBridge.mm | 1 + 6 files changed, 187 insertions(+), 75 deletions(-) diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index d500bb7481a1a0..6c7096f5973ce5 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -52,10 +52,11 @@ CHIP_ERROR Device::SendMessage(System::PacketBuffer * buffer) 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 != kConnectionState_SecureConnected) + if (mState != ConnectionState::SecureConnected) { err = LoadSecureSessionParameters(); SuccessOrExit(err); @@ -74,9 +75,11 @@ CHIP_ERROR Device::SendMessage(System::PacketBuffer * buffer) // The send could fail due to network timeouts (e.g. broken pipe) // Try sesion resumption if needed - if (err != CHIP_NO_ERROR && resend != nullptr) + if (err != CHIP_NO_ERROR && resend != nullptr && mState == ConnectionState::SecureConnected) { - err = ResumeSecureSession(); + mState = ConnectionState::NotConnected; + + err = LoadSecureSessionParameters(); SuccessOrExit(err); err = mSessionManager->SendMessage(mDeviceId, resend); @@ -106,14 +109,17 @@ CHIP_ERROR Device::Serialize(SerializedDevice & output) uint16_t serializedLen = 0; SerializableDevice serializable; - VerifyOrExit(BASE64_ENCODED_LEN(sizeof(serializable)) <= sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT); + 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); - mDeviceAddr.ToString(Uint8::to_char(serializable.mDeviceAddr), INET6_ADDRSTRLEN); + 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(&serializable)), static_cast(sizeof(serializable)), Uint8::to_char(output.inner)); @@ -137,14 +143,15 @@ CHIP_ERROR Device::Deserialize(const SerializedDevice & input) VerifyOrExit(CanCastTo(len), error = CHIP_ERROR_INVALID_ARGUMENT); CHIP_ZERO_AT(serializable); - deserializedLen = - Base64Decode(Uint8::to_const_char(input.inner), static_cast(len), Uint8::to_uchar((uint8_t *) &serializable)); + deserializedLen = Base64Decode(Uint8::to_const_char(input.inner), static_cast(len), + Uint8::to_uchar(reinterpret_cast(&serializable))); VerifyOrExit(deserializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(deserializedLen <= sizeof(serializable), error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(IPAddress::FromString(Uint8::to_const_char(serializable.mDeviceAddr), mDeviceAddr), - error = CHIP_ERROR_INVALID_ADDRESS); + VerifyOrExit( + IPAddress::FromString(Uint8::to_const_char(serializable.mDeviceAddr), sizeof(serializable.mDeviceAddr), mDeviceAddr), + error = CHIP_ERROR_INVALID_ADDRESS); memmove(&mPairing, &serializable.mOpsCreds, sizeof(mPairing)); mDeviceId = Encoding::LittleEndian::HostSwap64(serializable.mDeviceId); @@ -157,7 +164,7 @@ CHIP_ERROR Device::Deserialize(const SerializedDevice & input) void Device::OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, Transport::PeerConnectionState * state, System::PacketBuffer * msgBuf, SecureSessionMgrBase * mgr) { - if (mState == kConnectionState_SecureConnected && mStatusDelegate != nullptr) + if (mState == ConnectionState::SecureConnected && mStatusDelegate != nullptr) { mStatusDelegate->OnMessage(msgBuf); } @@ -168,7 +175,7 @@ CHIP_ERROR Device::LoadSecureSessionParameters() CHIP_ERROR err = CHIP_NO_ERROR; SecurePairingSession pairingSession; - if (mSessionManager == nullptr || mState == kConnectionState_SecureConnected) + if (mSessionManager == nullptr || mState == ConnectionState::SecureConnected) { ExitNow(err = CHIP_ERROR_INCORRECT_STATE); } @@ -184,7 +191,7 @@ CHIP_ERROR Device::LoadSecureSessionParameters() &pairingSession); SuccessOrExit(err); - mState = kConnectionState_SecureConnected; + mState = ConnectionState::SecureConnected; exit: @@ -195,32 +202,11 @@ CHIP_ERROR Device::LoadSecureSessionParameters() return err; } -CHIP_ERROR Device::ResumeSecureSession() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - VerifyOrExit(mState == kConnectionState_SecureConnected, err = CHIP_ERROR_INCORRECT_STATE); - VerifyOrExit(mSessionManager != nullptr, err = CHIP_ERROR_INCORRECT_STATE); - - mState = kConnectionState_NotConnected; - - err = LoadSecureSessionParameters(); - SuccessOrExit(err); - -exit: - - if (err != CHIP_NO_ERROR) - { - ChipLogError(Controller, "ResumeSecureSession returning error %d\n", err); - } - return err; -} - bool Device::GetIpAddress(Inet::IPAddress & addr) const { - if (mState == kConnectionState_SecureConnected) + if (mState == ConnectionState::SecureConnected) addr = mDeviceAddr; - return mState == kConnectionState_SecureConnected; + return mState == ConnectionState::SecureConnected; } } // namespace Controller diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index e474447dd45018..b0df54106352b3 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -44,9 +44,17 @@ struct SerializedDevice; class DLL_EXPORT Device { public: - Device() {} + 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 ----- @@ -73,12 +81,44 @@ class DLL_EXPORT Device */ 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 * 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 * sessionMgr, Inet::InetLayer * inetLayer, NodeId deviceId, uint16_t devicePort, Inet::InterfaceId interfaceId) { @@ -86,50 +126,76 @@ class DLL_EXPORT Device mDeviceId = deviceId; mDevicePort = devicePort; mInterface = interfaceId; - mState = kConnectionState_Connecting; + mState = ConnectionState::Connecting; } - /** @brief Serialize the Pairing Session to a string. + /** @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. + /** @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); - bool IsActive() { return mActive; } + /** + * @brief + * Return if 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() { return mDeviceId; } + NodeId GetDeviceId() const { return mDeviceId; } - void SetAddress(Inet::IPAddress deviceAddr) { mDeviceAddr = deviceAddr; } + void SetAddress(const Inet::IPAddress & deviceAddr) { mDeviceAddr = deviceAddr; } SecurePairingSessionSerializable & GetPairing() { return mPairing; } private: - enum ConnectionState + enum class ConnectionState { - kConnectionState_NotConnected, - kConnectionState_Connecting, - kConnectionState_SecureConnected, + 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 message. 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 = false; + bool mActive; ConnectionState mState; SecurePairingSessionSerializable mPairing; @@ -138,8 +204,13 @@ class DLL_EXPORT Device SecureSessionMgr * 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(); - CHIP_ERROR ResumeSecureSession(); }; /** @@ -172,14 +243,16 @@ class DLL_EXPORT DeviceStatusDelegate typedef struct SerializableDevice { SecurePairingSessionSerializable mOpsCreds; - uint64_t mDeviceId; + uint64_t mDeviceId; /* This field is serialized in LittleEndian byte order */ uint8_t mDeviceAddr[INET6_ADDRSTRLEN]; - uint16_t mDevicePort; + 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; diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 217aaa6cdaf369..9b440222a5520a 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -83,7 +83,7 @@ constexpr const char kPairedDeviceKeyPrefix[] = "PairedDevice"; DeviceController::DeviceController() { - mState = kState_NotInitialized; + mState = State::NotInitialized; mSessionManager = nullptr; mLocalDeviceId = 0; mStorageDelegate = nullptr; @@ -95,7 +95,7 @@ CHIP_ERROR DeviceController::Init(NodeId localDeviceId, PersistentStorageDelegat { CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrExit(mState == kState_NotInitialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mState == State::NotInitialized, err = CHIP_ERROR_INCORRECT_STATE); if (systemLayer != nullptr && inetLayer != nullptr) { @@ -131,7 +131,7 @@ CHIP_ERROR DeviceController::Init(NodeId localDeviceId, PersistentStorageDelegat mSessionManager->SetDelegate(this); - mState = kState_Initialized; + mState = State::Initialized; mLocalDeviceId = localDeviceId; exit: @@ -142,11 +142,11 @@ CHIP_ERROR DeviceController::Shutdown() { CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE); ChipLogDetail(Controller, "Shutting down the controller"); - mState = kState_NotInitialized; + mState = State::NotInitialized; #if CONFIG_DEVICE_LAYER err = DeviceLayer::PlatformMgr().Shutdown(); @@ -260,7 +260,7 @@ 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(); @@ -275,7 +275,7 @@ 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(); @@ -297,7 +297,7 @@ void DeviceController::OnMessageReceived(const PacketHeader & header, const Payl uint16_t index = 0; NodeId peer; - VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(header.GetSourceNodeId().HasValue(), err = CHIP_ERROR_INVALID_ARGUMENT); peer = header.GetSourceNodeId().Value(); @@ -411,7 +411,7 @@ CHIP_ERROR DeviceCommissioner::Shutdown() { CHIP_ERROR err = CHIP_NO_ERROR; - VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE); ChipLogDetail(Controller, "Shutting down the commissioner"); @@ -435,7 +435,7 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam CHIP_ERROR err = CHIP_NO_ERROR; Device * device = nullptr; - VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mDeviceBeingPaired == kNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); #if CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE @@ -488,7 +488,7 @@ CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDevice SecurePairingUsingTestSecret * testSecurePairingSecret = nullptr; - VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mDeviceBeingPaired == kNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); testSecurePairingSecret = chip::Platform::New(Optional::Value(remoteDeviceId), @@ -531,7 +531,7 @@ CHIP_ERROR DeviceCommissioner::StopPairing(NodeId remoteDeviceId) CHIP_ERROR err = CHIP_NO_ERROR; Device * device = nullptr; - VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_INCORRECT_STATE); device = &mActiveDevices[mDeviceBeingPaired]; diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 30e5966247e555..938b49bd346c52 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -95,6 +95,14 @@ class DLL_EXPORT DevicePairingDelegate virtual void OnPairingDeleted(CHIP_ERROR error) {} }; +/** + * @brief + * The controller applications can use this class to commuicate 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 { public: @@ -108,12 +116,32 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers CHIP_ERROR Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate = nullptr, System::Layer * systemLayer = nullptr, Inet::InetLayer * inetLayer = nullptr); - CHIP_ERROR SetPairedDeviceList(const char * pairedDeviceSerializedSet); - virtual CHIP_ERROR Shutdown(); + /** + * @brief + * This function derserializes the provided deviceInfo object, and initialzes and output the + * corresponding Device object. The lifetime of the output object is tied to that of DeviceController + * object. The caller must not use the Device object If they free the DeviceController object. + * + * @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. + */ CHIP_ERROR GetDevice(NodeId deviceId, const SerializedDevice & deviceInfo, Device ** device); + /** + * @brief + * This function is similar to the other GetDevice object, except it reads the serialized object from + * the persistent storage. + * + * @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 GetDevice(NodeId deviceId, Device ** device); virtual void ReleaseDevice(Device * device); @@ -135,12 +163,18 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers CHIP_ERROR ServiceEventSignal(); protected: - enum + enum class State { - kState_NotInitialized = 0, - kState_Initialized = 1 - } mState; + NotInitialized, + Initialized + }; + + State mState; + /* A list of device objects that can be used for commincating with corresponding + CHIP device. The list does not contain all the paired devices, but only the ones + which the controller application is currently accessing. + */ Device mActiveDevices[kNumMaxActiveDevices]; SerializableU64Set mPairedDevices; @@ -154,6 +188,7 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers uint16_t GetAvailableDevice(); uint16_t FindDevice(NodeId id); void ReleaseDevice(uint16_t index); + CHIP_ERROR SetPairedDeviceList(const char * pairedDeviceSerializedSet); private: //////////// SecureSessionMgrDelegate Implementation /////////////// @@ -169,6 +204,12 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers 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: @@ -197,7 +238,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Rendezvous * @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 interface indicator to use + * @param[in] interfaceId [Optional] The local inet interface to use to communicate with the device. * * @return CHIP_ERROR The connection status */ @@ -208,15 +249,24 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Rendezvous 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. + * 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 The connection status + * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error */ CHIP_ERROR UnpairDevice(NodeId remoteDeviceId); @@ -230,13 +280,16 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Rendezvous void ReleaseDevice(Device * device) override; private: - // SecurePairingUsingTestSecret * mTestSecurePairingSecret; - DevicePairingDelegate * mPairingDelegate; RendezvousSession * mRendezvousSession; + /* 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 */ uint16_t mDeviceBeingPaired; + /* 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; void PersistDeviceList(); diff --git a/src/controller/CHIPPersistentStorageDelegate.h b/src/controller/CHIPPersistentStorageDelegate.h index 65ce9340b26e48..a2176f2bc63b80 100644 --- a/src/controller/CHIPPersistentStorageDelegate.h +++ b/src/controller/CHIPPersistentStorageDelegate.h @@ -81,8 +81,7 @@ class DLL_EXPORT PersistentStorageDelegate /** * @brief - * Lookup the key and call delegate object with it's stringified value. - * This is a synchronous API, where the value is returned via the output + * 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. * diff --git a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm index 578a910bcb890c..92f3862eedd37c 100644 --- a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm +++ b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm @@ -109,6 +109,7 @@ } else { size = [valueString length]; } + // Increment size to account for null termination size += 1; return CHIP_NO_ERROR; } From 92941efcedfbd0035103f39f68864db9323820f4 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 10 Nov 2020 12:27:43 -0800 Subject: [PATCH 20/26] Fix parameters to FromString --- src/controller/CHIPDevice.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 6c7096f5973ce5..0b479380851a45 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -149,8 +149,11 @@ CHIP_ERROR Device::Deserialize(const SerializedDevice & input) VerifyOrExit(deserializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(deserializedLen <= sizeof(serializable), error = CHIP_ERROR_INVALID_ARGUMENT); + // The second paramter 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), mDeviceAddr), + IPAddress::FromString(Uint8::to_const_char(serializable.mDeviceAddr), sizeof(serializable.mDeviceAddr) - 1, mDeviceAddr), error = CHIP_ERROR_INVALID_ADDRESS); memmove(&mPairing, &serializable.mOpsCreds, sizeof(mPairing)); From ea46ff7b642e235eb6444f6e0fa9d6bd920d5794 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 10 Nov 2020 16:23:28 -0800 Subject: [PATCH 21/26] Address comments --- src/controller/CHIPDevice.cpp | 2 +- src/controller/CHIPDevice.h | 6 +- src/controller/CHIPDeviceController.cpp | 111 +++++++++++++----------- src/controller/CHIPDeviceController.h | 11 ++- 4 files changed, 72 insertions(+), 58 deletions(-) diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 0b479380851a45..68048e7d97c1ba 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -149,7 +149,7 @@ CHIP_ERROR Device::Deserialize(const SerializedDevice & input) VerifyOrExit(deserializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(deserializedLen <= sizeof(serializable), error = CHIP_ERROR_INVALID_ARGUMENT); - // The second paramter to FromString takes the strlen value. We are subtracting 1 + // 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( diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index b0df54106352b3..69d7491717c08a 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -89,7 +89,7 @@ class DLL_EXPORT Device * 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 + * 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. * @@ -160,7 +160,7 @@ class DLL_EXPORT Device /** * @brief - * Return if the current device object is actively associated with a paired CHIP + * 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; } @@ -187,7 +187,7 @@ class DLL_EXPORT Device /* IP Address of the CHIP device */ Inet::IPAddress mDeviceAddr; - /* Port on which the CHIP device is receiving message. Typically it is CHIP_PORT */ + /* 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 */ diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 9b440222a5520a..1a721476800282 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -161,6 +161,8 @@ CHIP_ERROR DeviceController::Shutdown() mSystemLayer = nullptr; mInetLayer = nullptr; + mStorageDelegate = nullptr; + if (mSessionManager != nullptr) { chip::Platform::Delete(mSessionManager); @@ -175,7 +177,10 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, const SerializedDevice & { CHIP_ERROR err = CHIP_NO_ERROR; Device * device = nullptr; - uint16_t index = FindDevice(deviceId); + uint16_t index = 0; + + VerifyOrExit(out_device != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + index = FindDeviceIndex(deviceId); if (index < kNumMaxActiveDevices) { @@ -185,7 +190,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, const SerializedDevice & { VerifyOrExit(mPairedDevices.Contains(deviceId), err = CHIP_ERROR_NOT_CONNECTED); - index = GetAvailableDevice(); + index = GetInactiveDeviceIndex(); VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); device = &mActiveDevices[index]; @@ -195,7 +200,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, const SerializedDevice & device->Init(mSessionManager, mInetLayer); } - (*out_device) = device; + *out_device = device; exit: return err; @@ -205,7 +210,11 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) { CHIP_ERROR err = CHIP_NO_ERROR; Device * device = nullptr; - uint16_t index = FindDevice(deviceId); + uint16_t index = 0; + char * buffer = nullptr; + + VerifyOrExit(out_device != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + index = FindDeviceIndex(deviceId); if (index < kNumMaxActiveDevices) { @@ -213,11 +222,15 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) } else { + VerifyOrExit(mStorageDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + if (!mPairedDevicesInitialized) { - const uint16_t max_size = CHIP_MAX_SERIALIZED_SIZE_U64(kNumMaxPairedDevices); - char buffer[max_size]; - uint16_t size = max_size; + constexpr uint16_t max_size = CHIP_MAX_SERIALIZED_SIZE_U64(kNumMaxPairedDevices); + buffer = static_cast(chip::Platform::MemoryAlloc(max_size)); + uint16_t size = max_size; + + VerifyOrExit(buffer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); PERSISTENT_KEY_OP(static_cast(0), kPairedDeviceListKeyPrefix, key, err = mStorageDelegate->GetKeyValue(key, buffer, size)); @@ -230,7 +243,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) VerifyOrExit(mPairedDevices.Contains(deviceId), err = CHIP_ERROR_NOT_CONNECTED); - index = GetAvailableDevice(); + index = GetInactiveDeviceIndex(); VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); device = &mActiveDevices[index]; @@ -250,9 +263,13 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) } } - (*out_device) = device; + *out_device = device; exit: + if (buffer != nullptr) + { + chip::Platform::MemoryFree(buffer); + } return err; } @@ -301,7 +318,7 @@ void DeviceController::OnMessageReceived(const PacketHeader & header, const Payl VerifyOrExit(header.GetSourceNodeId().HasValue(), err = CHIP_ERROR_INVALID_ARGUMENT); peer = header.GetSourceNodeId().Value(); - index = FindDevice(peer); + index = FindDeviceIndex(peer); VerifyOrExit(index < kNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); mActiveDevices[index].OnMessageReceived(header, payloadHeader, state, msgBuf, mgr); @@ -310,7 +327,7 @@ void DeviceController::OnMessageReceived(const PacketHeader & header, const Payl return; } -uint16_t DeviceController::GetAvailableDevice() +uint16_t DeviceController::GetInactiveDeviceIndex() { uint16_t i = 0; while (i < kNumMaxActiveDevices && mActiveDevices[i].IsActive()) @@ -336,7 +353,7 @@ void DeviceController::ReleaseDevice(uint16_t index) } } -uint16_t DeviceController::FindDevice(NodeId id) +uint16_t DeviceController::FindDeviceIndex(NodeId id) { uint16_t i = 0; while (i < kNumMaxActiveDevices) @@ -375,7 +392,7 @@ void DeviceController::OnValue(const char * key, const char * value) {} void DeviceController::OnStatus(const char * key, Operation op, CHIP_ERROR err) {} -DeviceCommissioner::DeviceCommissioner() : DeviceController() +DeviceCommissioner::DeviceCommissioner() { mPairingDelegate = nullptr; mRendezvousSession = nullptr; @@ -383,11 +400,6 @@ DeviceCommissioner::DeviceCommissioner() : DeviceController() mPairedDevicesUpdated = false; } -DeviceCommissioner::~DeviceCommissioner() -{ - PersistDeviceList(); -} - CHIP_ERROR DeviceCommissioner::Init(NodeId localDeviceId, PersistentStorageDelegate * storageDelegate, DevicePairingDelegate * pairingDelegate, System::Layer * systemLayer, Inet::InetLayer * inetLayer) @@ -401,12 +413,6 @@ CHIP_ERROR DeviceCommissioner::Init(NodeId localDeviceId, PersistentStorageDeleg return err; } -CHIP_ERROR DeviceCommissioner::SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate) -{ - mPairingDelegate = pairingDelegate; - return CHIP_NO_ERROR; -} - CHIP_ERROR DeviceCommissioner::Shutdown() { CHIP_ERROR err = CHIP_NO_ERROR; @@ -429,7 +435,7 @@ CHIP_ERROR DeviceCommissioner::Shutdown() return err; } -CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & params, uint16_t devicePort, +CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParameters & params, uint16_t remotePort, Inet::InterfaceId interfaceId) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -437,6 +443,7 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam 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()) @@ -445,20 +452,16 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam } #endif // CONFIG_DEVICE_LAYER && CONFIG_NETWORK_LAYER_BLE - mDeviceBeingPaired = GetAvailableDevice(); + mDeviceBeingPaired = GetInactiveDeviceIndex(); VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); device = &mActiveDevices[mDeviceBeingPaired]; - if (mRendezvousSession != nullptr) - { - chip::Platform::Delete(mRendezvousSession); - } - mRendezvousSession = chip::Platform::New(this); - err = mRendezvousSession->Init(params.SetLocalNodeId(mLocalDeviceId)); + VerifyOrExit(mRendezvousSession != nullptr, err = CHIP_ERROR_NO_MEMORY); + err = mRendezvousSession->Init(params.SetLocalNodeId(mLocalDeviceId)); SuccessOrExit(err); - device->Init(mSessionManager, mInetLayer, remoteDeviceId, devicePort, interfaceId); + device->Init(mSessionManager, mInetLayer, remoteDeviceId, remotePort, interfaceId); exit: if (err != CHIP_NO_ERROR) @@ -480,7 +483,7 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam } CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDeviceId, const Inet::IPAddress & deviceAddr, - SerializedDevice & serialized, uint16_t devicePort, + SerializedDevice & serialized, uint16_t remotePort, Inet::InterfaceId interfaceId) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -495,13 +498,13 @@ CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDevice static_cast(0), static_cast(0)); VerifyOrExit(testSecurePairingSecret != nullptr, err = CHIP_ERROR_NO_MEMORY); - mDeviceBeingPaired = GetAvailableDevice(); + mDeviceBeingPaired = GetInactiveDeviceIndex(); VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); device = &mActiveDevices[mDeviceBeingPaired]; testSecurePairingSecret->Serializable(device->GetPairing()); - device->Init(mSessionManager, mInetLayer, remoteDeviceId, devicePort, interfaceId); + device->Init(mSessionManager, mInetLayer, remoteDeviceId, remotePort, interfaceId); device->SetAddress(deviceAddr); @@ -579,6 +582,11 @@ void DeviceCommissioner::RendezvousCleanup(CHIP_ERROR status) if (mDeviceBeingPaired != kNumMaxActiveDevices) { + // Let's release the device that's being paired. + // If pairing was successful, it's 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; } @@ -593,18 +601,16 @@ void DeviceCommissioner::OnRendezvousComplete() { CHIP_ERROR err = CHIP_NO_ERROR; Device * device = nullptr; + SerializedDevice serialized; + VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); device = &mActiveDevices[mDeviceBeingPaired]; mPairedDevices.Insert(device->GetDeviceId()); mPairedDevicesUpdated = true; - if (mStorageDelegate != nullptr) - { - SerializedDevice serialized; - device->Serialize(serialized); - PERSISTENT_KEY_OP(device->GetDeviceId(), kPairedDeviceKeyPrefix, key, - mStorageDelegate->SetKeyValue(key, Uint8::to_const_char(serialized.inner))); - } + 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) @@ -665,14 +671,19 @@ void DeviceCommissioner::PersistDeviceList() { if (mStorageDelegate != nullptr && mPairedDevicesUpdated) { - const uint16_t size = CHIP_MAX_SERIALIZED_SIZE_U64(kNumMaxPairedDevices); - char serialized[size]; - uint16_t requiredSize = size; - const char * value = mPairedDevices.SerializeBase64(serialized, requiredSize); - if (value != nullptr && requiredSize <= size) + constexpr uint16_t size = CHIP_MAX_SERIALIZED_SIZE_U64(kNumMaxPairedDevices); + char * serialized = static_cast(chip::Platform::MemoryAlloc(size)); + uint16_t requiredSize = size; + if (serialized != nullptr) { - PERSISTENT_KEY_OP(static_cast(0), kPairedDeviceListKeyPrefix, key, mStorageDelegate->SetKeyValue(key, value)); - mPairedDevicesUpdated = false; + const char * value = mPairedDevices.SerializeBase64(serialized, requiredSize); + if (value != nullptr && requiredSize <= size) + { + PERSISTENT_KEY_OP(static_cast(0), kPairedDeviceListKeyPrefix, key, + mStorageDelegate->SetKeyValue(key, value)); + mPairedDevicesUpdated = false; + } + chip::Platform::MemoryFree(serialized); } } } diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 938b49bd346c52..66c5ae42374ec4 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -185,8 +185,8 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers PersistentStorageDelegate * mStorageDelegate; Inet::InetLayer * mInetLayer; - uint16_t GetAvailableDevice(); - uint16_t FindDevice(NodeId id); + uint16_t GetInactiveDeviceIndex(); + uint16_t FindDeviceIndex(NodeId id); void ReleaseDevice(uint16_t index); CHIP_ERROR SetPairedDeviceList(const char * pairedDeviceSerializedSet); @@ -214,7 +214,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Rendezvous { public: DeviceCommissioner(); - ~DeviceCommissioner(); + ~DeviceCommissioner() {} /** * Init function to be used when there exists a device layer that takes care of initializing @@ -224,7 +224,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Rendezvous DevicePairingDelegate * pairingDelegate = nullptr, System::Layer * systemLayer = nullptr, Inet::InetLayer * inetLayer = nullptr); - CHIP_ERROR SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate); + void SetDevicePairingDelegate(DevicePairingDelegate * pairingDelegate) { mPairingDelegate = pairingDelegate; } CHIP_ERROR Shutdown() override; @@ -235,6 +235,9 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Rendezvous * 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 From a738bbc0bcbb424c7635fc099dfd5ed16879535d Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 10 Nov 2020 16:40:11 -0800 Subject: [PATCH 22/26] fix build --- src/controller/CHIPDeviceController.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 1a721476800282..1f2b6e4df8ebb6 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -324,6 +324,10 @@ void DeviceController::OnMessageReceived(const PacketHeader & header, const Payl 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; } From 446d183e71d0d731de54f93ae9ff65ff9531c70a Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 10 Nov 2020 17:01:40 -0800 Subject: [PATCH 23/26] Fix cirque test --- src/controller/CHIPDeviceController.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 1f2b6e4df8ebb6..d6897e38a452c6 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -605,16 +605,24 @@ void DeviceCommissioner::OnRendezvousComplete() { CHIP_ERROR err = CHIP_NO_ERROR; Device * device = nullptr; - SerializedDevice serialized; VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_INVALID_DEVICE_DESCRIPTOR); device = &mActiveDevices[mDeviceBeingPaired]; mPairedDevices.Insert(device->GetDeviceId()); mPairedDevicesUpdated = true; - device->Serialize(serialized); - PERSISTENT_KEY_OP(device->GetDeviceId(), kPairedDeviceKeyPrefix, key, - mStorageDelegate->SetKeyValue(key, Uint8::to_const_char(serialized.inner))); + // 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) From f1bbc69903ae9b08d206cfda7b771d30d0921cc6 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 10 Nov 2020 20:03:26 -0800 Subject: [PATCH 24/26] remove delegate on shutdown --- src/controller/CHIPDeviceController.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index d6897e38a452c6..2103b60bd43a77 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -161,10 +161,15 @@ CHIP_ERROR DeviceController::Shutdown() mSystemLayer = nullptr; mInetLayer = nullptr; - mStorageDelegate = nullptr; + if (mStorageDelegate != nullptr) + { + mStorageDelegate->SetDelegate(nullptr); + mStorageDelegate = nullptr; + } if (mSessionManager != nullptr) { + mSessionManager->SetDelegate(nullptr); chip::Platform::Delete(mSessionManager); mSessionManager = nullptr; } From 2e715e5e5e49db7f63ef9604ed1a3f72452571b2 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 10 Nov 2020 20:28:03 -0800 Subject: [PATCH 25/26] Address review comments --- src/controller/CHIPDeviceController.cpp | 6 +++--- src/controller/CHIPDeviceController.h | 14 ++++++++------ src/transport/SecurePairingSession.cpp | 4 ++-- src/transport/SecurePairingSession.h | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 2103b60bd43a77..7ce20bddb661e3 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -511,7 +511,7 @@ CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDevice VerifyOrExit(mDeviceBeingPaired < kNumMaxActiveDevices, err = CHIP_ERROR_NO_MEMORY); device = &mActiveDevices[mDeviceBeingPaired]; - testSecurePairingSecret->Serializable(device->GetPairing()); + testSecurePairingSecret->ToSerializable(device->GetPairing()); device->Init(mSessionManager, mInetLayer, remoteDeviceId, remotePort, interfaceId); @@ -592,7 +592,7 @@ void DeviceCommissioner::RendezvousCleanup(CHIP_ERROR status) if (mDeviceBeingPaired != kNumMaxActiveDevices) { // Let's release the device that's being paired. - // If pairing was successful, it's information is + // 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. @@ -653,7 +653,7 @@ void DeviceCommissioner::OnRendezvousStatusUpdate(RendezvousSessionDelegate::Sta { case RendezvousSessionDelegate::SecurePairingSuccess: ChipLogDetail(Controller, "Remote device completed SPAKE2+ handshake\n"); - mRendezvousSession->GetPairingSession().Serializable(device->GetPairing()); + mRendezvousSession->GetPairingSession().ToSerializable(device->GetPairing()); if (mPairingDelegate != nullptr) { diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 66c5ae42374ec4..43b10717c6f5ef 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -97,7 +97,7 @@ class DLL_EXPORT DevicePairingDelegate /** * @brief - * The controller applications can use this class to commuicate with already paired CHIP devices. The + * 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 @@ -120,9 +120,10 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers /** * @brief - * This function derserializes the provided deviceInfo object, and initialzes and output the + * 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 DeviceController - * object. The caller must not use the Device object If they free the DeviceController object. + * 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] deviceId Node ID for the CHIP device * @param[in] deviceInfo Serialized device info for the device @@ -171,8 +172,8 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers State mState; - /* A list of device objects that can be used for commincating with corresponding - CHIP device. The list does not contain all the paired devices, but only the ones + /* 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]; @@ -287,7 +288,8 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Rendezvous RendezvousSession * mRendezvousSession; /* 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 */ + 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; /* This field is true when device pairing information changes, e.g. a new device is paired, or diff --git a/src/transport/SecurePairingSession.cpp b/src/transport/SecurePairingSession.cpp index 6458bcd8cc814d..780654bd82676d 100644 --- a/src/transport/SecurePairingSession.cpp +++ b/src/transport/SecurePairingSession.cpp @@ -63,7 +63,7 @@ CHIP_ERROR SecurePairingSession::Serialize(SecurePairingSessionSerialized & outp VerifyOrExit(BASE64_ENCODED_LEN(sizeof(serializable)) <= sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT); - error = Serializable(serializable); + error = ToSerializable(serializable); SuccessOrExit(error); serializedLen = chip::Base64Encode(Uint8::to_const_uchar(reinterpret_cast(&serializable)), @@ -100,7 +100,7 @@ CHIP_ERROR SecurePairingSession::Deserialize(SecurePairingSessionSerialized & in return error; } -CHIP_ERROR SecurePairingSession::Serializable(SecurePairingSessionSerializable & serializable) +CHIP_ERROR SecurePairingSession::ToSerializable(SecurePairingSessionSerializable & serializable) { CHIP_ERROR error = CHIP_NO_ERROR; diff --git a/src/transport/SecurePairingSession.h b/src/transport/SecurePairingSession.h index 2b5029250f5f82..d811c2e22b3c94 100644 --- a/src/transport/SecurePairingSession.h +++ b/src/transport/SecurePairingSession.h @@ -193,7 +193,7 @@ class DLL_EXPORT SecurePairingSession * * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise **/ - CHIP_ERROR Serializable(SecurePairingSessionSerializable & output); + CHIP_ERROR ToSerializable(SecurePairingSessionSerializable & output); /** @brief Reconstruct secure pairing class from the serializable data structure. * From 305d924b815e615368102ed15bd803d73fae3e2d Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 10 Nov 2020 23:32:27 -0500 Subject: [PATCH 26/26] Update src/controller/CHIPDeviceController.h --- src/controller/CHIPDeviceController.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 43b10717c6f5ef..1e7ec69befa671 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -121,7 +121,7 @@ class DLL_EXPORT DeviceController : public SecureSessionMgrDelegate, public Pers /** * @brief * 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 DeviceController + * 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. *