From 06ed4d00cec00a057c879b00ddbf0f6adf5bb457 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Fri, 19 Feb 2021 16:10:31 -0800 Subject: [PATCH 1/9] Integrate KVS with device session tables --- src/app/server/RendezvousServer.cpp | 7 ++ src/app/server/Server.cpp | 112 +++++++++++++++++- .../Darwin/KeyValueStoreManagerImpl.h | 80 +++++++++++++ src/transport/AdminPairingTable.h | 64 ++++++++++ src/transport/BUILD.gn | 1 + src/transport/RendezvousSession.cpp | 4 +- src/transport/RendezvousSession.h | 5 + src/transport/StorablePeerConnection.h | 95 +++++++++++++++ 8 files changed, 362 insertions(+), 6 deletions(-) create mode 100644 src/platform/Darwin/KeyValueStoreManagerImpl.h create mode 100644 src/transport/StorablePeerConnection.h diff --git a/src/app/server/RendezvousServer.cpp b/src/app/server/RendezvousServer.cpp index 1fed68bcb8446e..4e7a31dded3d9f 100644 --- a/src/app/server/RendezvousServer.cpp +++ b/src/app/server/RendezvousServer.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #if CHIP_ENABLE_OPENTHREAD #include @@ -63,6 +64,12 @@ void RendezvousServer::OnRendezvousMessageReceived(const PacketHeader & packetHe void RendezvousServer::OnRendezvousComplete() { ChipLogProgress(AppServer, "Device completed Rendezvous process"); + StorablePeerConnection connection(mRendezvousSession.GetPairingSession(), mRendezvousSession.GetAdminId()); + + VerifyOrReturn(connection.StoreUsingKVSMgr(PersistedStorage::KeyValueStoreMgr()) == CHIP_NO_ERROR); + + uint16_t nextKeyId = mRendezvousSession.GetNextKeyId(); + PersistedStorage::KeyValueStoreMgr().Put(kStorablePeerConnectionCountKey, nextKeyId); } void RendezvousServer::OnRendezvousStatusUpdate(Status status, CHIP_ERROR err) diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index a807fd0674359d..1de4327d46558a 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include using namespace ::chip; using namespace ::chip::Inet; @@ -70,6 +72,89 @@ constexpr bool useTestPairing() #endif } +CHIP_ERROR PersistAdminPairingToKVS(AdminPairingInfo * admin, AdminId nextAvailableId) +{ + ReturnErrorCodeIf(admin == nullptr, CHIP_ERROR_INVALID_ARGUMENT); + ChipLogProgress(AppServer, "Persisting admin ID %d, next available %d", admin->GetAdminId(), nextAvailableId); + + ReturnErrorOnFailure(admin->StoreUsingKVSMgr(PersistedStorage::KeyValueStoreMgr())); + ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kAdminTableCountKey, &nextAvailableId, sizeof(nextAvailableId))); + + ChipLogProgress(AppServer, "Persisting admin ID successfully"); + return CHIP_NO_ERROR; +} + +CHIP_ERROR RestoreAllAdminPairingsFromKVS(AdminPairingTable & adminPairings, AdminId & nextAvailableId) +{ + // It's not an error if the key doesn't exist. Just return right away. + VerifyOrReturnError(PersistedStorage::KeyValueStoreMgr().Get(kAdminTableCountKey, &nextAvailableId) == CHIP_NO_ERROR, + CHIP_NO_ERROR); + ChipLogProgress(AppServer, "Next available admin ID is %d", nextAvailableId); + + for (AdminId id = 0; id < nextAvailableId; id++) + { + AdminPairingInfo * admin = adminPairings.AssignAdminId(id); + // Recreate the binding if one exists in persistent storage. Else skip to the next ID + if (admin->FetchUsingKVSMgr(PersistedStorage::KeyValueStoreMgr()) != CHIP_NO_ERROR) + { + adminPairings.ReleaseAdminId(id); + } + else + { + ChipLogProgress(AppServer, "Found admin pairing for %d, node ID %llu", admin->GetAdminId(), admin->GetNodeId()); + } + } + + return CHIP_NO_ERROR; +} + +void DeleteAdminPairingsInKVS(AdminId nextAvailableId) +{ + PersistedStorage::KeyValueStoreMgr().Delete(kAdminTableCountKey); + for (AdminId id = 0; id < nextAvailableId; id++) + { + AdminPairingInfo::DeleteUsingKVSMgr(PersistedStorage::KeyValueStoreMgr(), id); + } +} + +CHIP_ERROR RestoreAllSessionsFromKVS(SecureSessionMgr & sessionMgr, RendezvousServer & server) +{ + uint16_t nextSessionKeyId = 0; + // It's not an error if the key doesn't exist. Just return right away. + VerifyOrReturnError(PersistedStorage::KeyValueStoreMgr().Get(kStorablePeerConnectionCountKey, &nextSessionKeyId) == + CHIP_NO_ERROR, + CHIP_NO_ERROR); + ChipLogProgress(AppServer, "Found %d stored connections", nextSessionKeyId); + + for (uint16_t keyId = 0; keyId < nextSessionKeyId; keyId++) + { + StorablePeerConnection connection; + if (CHIP_NO_ERROR == connection.FetchUsingKVSMgr(PersistedStorage::KeyValueStoreMgr(), keyId)) + { + // The following is static to save on stack space usage + static PASESession session; + connection.GetPASESession(session); + + ChipLogProgress(AppServer, "Fetched the session information: from %llu", session.PeerConnection().GetPeerNodeId()); + sessionMgr.NewPairing(Optional::Value(session.PeerConnection().GetPeerAddress()), + session.PeerConnection().GetPeerNodeId(), &session, + SecureSessionMgr::PairingDirection::kResponder, connection.GetAdminId(), nullptr); + } + } + + server.GetRendezvousSession()->SetNextKeyId(nextSessionKeyId); + return CHIP_NO_ERROR; +} + +void DeleteSessionsInKVS(uint16_t nextSessionKeyId) +{ + PersistedStorage::KeyValueStoreMgr().Delete(kStorablePeerConnectionCountKey); + for (uint16_t keyId = 0; keyId < nextSessionKeyId; keyId++) + { + StorablePeerConnection::DeleteUsingKVSMgr(PersistedStorage::KeyValueStoreMgr(), keyId); + } +} + // TODO: The following class is setting the discriminator in Persistent Storage. This is // is needed since BLE reads the discriminator using ConfigurationMgr APIs. The // better solution will be to pass the discriminator to BLE without changing it @@ -108,6 +193,8 @@ class DeviceDiscriminatorCache }; DeviceDiscriminatorCache gDeviceDiscriminatorCache; +AdminPairingTable gAdminPairings; +AdminId gNextAvailableAdminId = 0; class ServerRendezvousAdvertisementDelegate : public RendezvousAdvertisementDelegate { @@ -126,24 +213,31 @@ class ServerRendezvousAdvertisementDelegate : public RendezvousAdvertisementDele gDeviceDiscriminatorCache.RestoreDiscriminator(); ReturnErrorOnFailure(chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(false)); - if (mDelegate != nullptr) { - mDelegate->OnPairingWindowClosed(); + if (mDelegate != nullptr) + mDelegate->OnPairingWindowClosed(); + } + + AdminPairingInfo * admin = gAdminPairings.FindAdmin(mAdmin); + if (admin != nullptr) + { + ReturnErrorOnFailure(PersistAdminPairingToKVS(admin, gNextAvailableAdminId)); } return CHIP_NO_ERROR; } void SetDelegate(AppDelegate * delegate) { mDelegate = delegate; } + void SetAdminId(AdminId id) { mAdmin = id; } + private: AppDelegate * mDelegate = nullptr; + AdminId mAdmin; }; DemoTransportMgr gTransports; SecureSessionMgr gSessions; RendezvousServer gRendezvousServer; -AdminPairingTable gAdminPairings; -AdminId gNextAvailableAdminId = 0; ServerRendezvousAdvertisementDelegate gAdvDelegate; @@ -357,6 +451,9 @@ CHIP_ERROR OpenDefaultPairingWindow(ResetAdmins resetAdmins) if (resetAdmins == ResetAdmins::kYes) { + uint16_t nextKeyId = gRendezvousServer.GetRendezvousSession()->GetNextKeyId(); + DeleteAdminPairingsInKVS(gNextAvailableAdminId); + DeleteSessionsInKVS(nextKeyId); gNextAvailableAdminId = 0; gAdminPairings.Reset(); } @@ -423,6 +520,13 @@ void InitServer(AppDelegate * delegate) // If the network is already provisioned, proactively disable BLE advertisement. ChipLogProgress(AppServer, "Network already provisioned. Disabling BLE advertisement"); chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(false); + + // Restore any previous admin pairings + VerifyOrExit(CHIP_NO_ERROR == RestoreAllAdminPairingsFromKVS(gAdminPairings, gNextAvailableAdminId), + ChipLogError(AppServer, "Could not restore admin table")); + + VerifyOrExit(CHIP_NO_ERROR == RestoreAllSessionsFromKVS(gSessions, gRendezvousServer), + ChipLogError(AppServer, "Could not restore previous sessions")); } else { diff --git a/src/platform/Darwin/KeyValueStoreManagerImpl.h b/src/platform/Darwin/KeyValueStoreManagerImpl.h new file mode 100644 index 00000000000000..c72b9c8bf51d08 --- /dev/null +++ b/src/platform/Darwin/KeyValueStoreManagerImpl.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific key value storage implementation for Darwin. + */ + +#pragma once + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +class KeyValueStoreManagerImpl final : public KeyValueStoreManager +{ + // Allow the KeyValueStoreManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class KeyValueStoreManager; + +public: + // NOTE: Currently this platform does not support partial and offset reads + // these will return CHIP_ERROR_NOT_IMPLEMENTED. + CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + CHIP_ERROR _Delete(const char * key) { return CHIP_ERROR_NOT_IMPLEMENTED; } + + CHIP_ERROR _Put(const char * key, const void * value, size_t value_size) { return CHIP_ERROR_NOT_IMPLEMENTED; } + +private: + // ===== Members for internal use by the following friends. + friend KeyValueStoreManager & KeyValueStoreMgr(); + friend KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(); + + static KeyValueStoreManagerImpl sInstance; +}; + +/** + * Returns the public interface of the KeyValueStoreManager singleton object. + * + * Chip applications should use this to access features of the KeyValueStoreManager object + * that are common to all platforms. + */ +inline KeyValueStoreManager & KeyValueStoreMgr(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the KeyValueStoreManager singleton object. + * + * Chip applications can use this to gain access to features of the KeyValueStoreManager + * that are specific to the ESP32 platform. + */ +inline KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/transport/AdminPairingTable.h b/src/transport/AdminPairingTable.h index 19dd2189b72d18..6a65028299f432 100644 --- a/src/transport/AdminPairingTable.h +++ b/src/transport/AdminPairingTable.h @@ -21,7 +21,14 @@ #pragma once +#include +#include +#include +#include +#include #include +#include +#include #include namespace chip { @@ -30,6 +37,11 @@ namespace Transport { typedef uint16_t AdminId; static constexpr AdminId kUndefinedAdminId = UINT16_MAX; +// KVS store is sensitive to length of key strings, based on the underlying +// platform. Keeping them short. +constexpr char kAdminTableKeyPrefix[] = "CHIPAdmin"; +constexpr char kAdminTableCountKey[] = "CHIPAdminNextId"; + struct OperationalCredentials { uint32_t placeholder; @@ -81,12 +93,64 @@ class DLL_EXPORT AdminPairingInfo mAdmin = kUndefinedAdminId; } + CHIP_ERROR StoreUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr) + { + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(mAdmin, key, sizeof(key))); + + StorableAdminPairingInfo info; + info.mNodeId = Encoding::LittleEndian::HostSwap64(mNodeId); + info.mAdmin = Encoding::LittleEndian::HostSwap16(mAdmin); + + return mgr.Put(key, info); + } + + CHIP_ERROR FetchUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr) + { + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(mAdmin, key, sizeof(key))); + + StorableAdminPairingInfo info; + + ReturnErrorOnFailure(mgr.Get(key, &info, sizeof(info))); + mNodeId = Encoding::LittleEndian::HostSwap64(info.mNodeId); + AdminId id = Encoding::LittleEndian::HostSwap16(info.mAdmin); + ReturnErrorCodeIf(mAdmin != id, CHIP_ERROR_INCORRECT_STATE); + + return CHIP_NO_ERROR; + } + + static CHIP_ERROR DeleteUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr, AdminId id) + { + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(id, key, sizeof(key))); + + return mgr.Delete(key); + } + private: AdminId mAdmin = kUndefinedAdminId; NodeId mNodeId = kUndefinedNodeId; OperationalCredentials mOpCred; AccessControlList mACL; + + static constexpr size_t KeySize() { return sizeof(kAdminTableKeyPrefix) + 2 * sizeof(AdminId); } + + static CHIP_ERROR GenerateKey(AdminId id, char * key, size_t len) + { + VerifyOrReturnError(len >= KeySize(), CHIP_ERROR_INVALID_ARGUMENT); + int keySize = snprintf(key, len, "%s%x", kAdminTableKeyPrefix, id); + VerifyOrReturnError(keySize > 0, CHIP_ERROR_INTERNAL); + VerifyOrReturnError(len > (size_t) keySize, CHIP_ERROR_INTERNAL); + return CHIP_NO_ERROR; + } + + struct StorableAdminPairingInfo + { + uint16_t mAdmin; /* This field is serialized in LittleEndian byte order */ + uint64_t mNodeId; /* This field is serialized in LittleEndian byte order */ + }; }; class DLL_EXPORT AdminPairingTable diff --git a/src/transport/BUILD.gn b/src/transport/BUILD.gn index 3adaea5d0d8edc..06072b8dca62ac 100644 --- a/src/transport/BUILD.gn +++ b/src/transport/BUILD.gn @@ -39,6 +39,7 @@ static_library("transport") { "SecureSessionMgr.cpp", "SecureSessionMgr.h", "SessionEstablishmentDelegate.h", + "StorablePeerConnection.h", "TransportMgr.h", "TransportMgrBase.cpp", "TransportMgrBase.h", diff --git a/src/transport/RendezvousSession.cpp b/src/transport/RendezvousSession.cpp index abb1af1aaf064a..f5d25f4267614d 100644 --- a/src/transport/RendezvousSession.cpp +++ b/src/transport/RendezvousSession.cpp @@ -466,13 +466,13 @@ CHIP_ERROR RendezvousSession::WaitForPairing(uint32_t setupPINCode) UpdateState(State::kSecurePairing); return mPairingSession.WaitForPairing(setupPINCode, kSpake2p_Iteration_Count, reinterpret_cast(kSpake2pKeyExchangeSalt), - strlen(kSpake2pKeyExchangeSalt), 0, this); + strlen(kSpake2pKeyExchangeSalt), mNextKeyId++, this); } CHIP_ERROR RendezvousSession::WaitForPairing(const PASEVerifier & verifier) { UpdateState(State::kSecurePairing); - return mPairingSession.WaitForPairing(verifier, 0 /* keyId */, this); + return mPairingSession.WaitForPairing(verifier, mNextKeyId++, this); } CHIP_ERROR RendezvousSession::Pair(uint32_t setupPINCode) diff --git a/src/transport/RendezvousSession.h b/src/transport/RendezvousSession.h index 857bfe5fdc994f..91a312c6d0cd0e 100644 --- a/src/transport/RendezvousSession.h +++ b/src/transport/RendezvousSession.h @@ -142,6 +142,11 @@ class RendezvousSession : public SessionEstablishmentDelegate, */ const Inet::IPAddress & GetIPAddress() const { return mNetworkProvision.GetIPAddress(); } + Transport::AdminId GetAdminId() const { return (mAdmin != nullptr) ? mAdmin->GetAdminId() : Transport::kUndefinedAdminId; } + + uint16_t GetNextKeyId() const { return mNextKeyId; } + void SetNextKeyId(uint16_t id) { mNextKeyId = id; } + private: CHIP_ERROR HandlePairingMessage(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress, System::PacketBufferHandle msgBuf); diff --git a/src/transport/StorablePeerConnection.h b/src/transport/StorablePeerConnection.h new file mode 100644 index 00000000000000..44026cef4cfd96 --- /dev/null +++ b/src/transport/StorablePeerConnection.h @@ -0,0 +1,95 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +namespace chip { + +// KVS store is sensitive to length of key strings, based on the underlying +// platform. Keeping them short. +constexpr char kStorablePeerConnectionKeyPrefix[] = "CHIPCnxn"; +constexpr char kStorablePeerConnectionCountKey[] = "CHIPNxtCnxn"; + +class DLL_EXPORT StorablePeerConnection +{ +public: + StorablePeerConnection() {} + + StorablePeerConnection(PASESession & session, Transport::AdminId admin) + { + session.ToSerializable(mSession.mOpCreds); + mSession.mAdmin = Encoding::LittleEndian::HostSwap16(admin); + mKeyId = session.GetLocalKeyId(); + } + + virtual ~StorablePeerConnection() {} + + CHIP_ERROR StoreUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr) + { + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(mKeyId, key, sizeof(key))); + + return mgr.Put(key, &mSession, sizeof(mSession)); + } + + CHIP_ERROR FetchUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr, uint16_t keyId) + { + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(keyId, key, sizeof(key))); + + return mgr.Get(key, &mSession, sizeof(mSession)); + } + + static CHIP_ERROR DeleteUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr, uint16_t keyId) + { + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(keyId, key, sizeof(key))); + + return mgr.Delete(key); + } + + void GetPASESession(PASESession & session) { session.FromSerializable(mSession.mOpCreds); } + + Transport::AdminId GetAdminId() { return mSession.mAdmin; } + +private: + static constexpr size_t KeySize() { return sizeof(kStorablePeerConnectionKeyPrefix) + 2 * sizeof(uint16_t); } + + static CHIP_ERROR GenerateKey(uint16_t id, char * key, size_t len) + { + VerifyOrReturnError(len >= KeySize(), CHIP_ERROR_INVALID_ARGUMENT); + int keySize = snprintf(key, len, "%s%x", kStorablePeerConnectionKeyPrefix, id); + VerifyOrReturnError(keySize > 0, CHIP_ERROR_INTERNAL); + VerifyOrReturnError(len > (size_t) keySize, CHIP_ERROR_INTERNAL); + return CHIP_NO_ERROR; + } + + struct StorableSession + { + PASESessionSerializable mOpCreds; + Transport::AdminId mAdmin; /* This field is serialized in LittleEndian byte order */ + }; + + StorableSession mSession; + uint16_t mKeyId; +}; + +} // namespace chip From e528c490168be9b9bf526f3ede1713d889bf88d3 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Fri, 19 Feb 2021 16:28:11 -0800 Subject: [PATCH 2/9] Fix some build failures --- .../qpg6100/KeyValueStoreManagerImpl.h | 80 +++++++++++++++++++ src/transport/BUILD.gn | 2 + 2 files changed, 82 insertions(+) create mode 100644 src/platform/qpg6100/KeyValueStoreManagerImpl.h diff --git a/src/platform/qpg6100/KeyValueStoreManagerImpl.h b/src/platform/qpg6100/KeyValueStoreManagerImpl.h new file mode 100644 index 00000000000000..8d90fa3856dccd --- /dev/null +++ b/src/platform/qpg6100/KeyValueStoreManagerImpl.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific key value storage implementation for QPG6100. + */ + +#pragma once + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +class KeyValueStoreManagerImpl final : public KeyValueStoreManager +{ + // Allow the KeyValueStoreManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class KeyValueStoreManager; + +public: + // NOTE: Currently this platform does not support partial and offset reads + // these will return CHIP_ERROR_NOT_IMPLEMENTED. + CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + CHIP_ERROR _Delete(const char * key) { return CHIP_ERROR_NOT_IMPLEMENTED; } + + CHIP_ERROR _Put(const char * key, const void * value, size_t value_size) { return CHIP_ERROR_NOT_IMPLEMENTED; } + +private: + // ===== Members for internal use by the following friends. + friend KeyValueStoreManager & KeyValueStoreMgr(); + friend KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(); + + static KeyValueStoreManagerImpl sInstance; +}; + +/** + * Returns the public interface of the KeyValueStoreManager singleton object. + * + * Chip applications should use this to access features of the KeyValueStoreManager object + * that are common to all platforms. + */ +inline KeyValueStoreManager & KeyValueStoreMgr(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the KeyValueStoreManager singleton object. + * + * Chip applications can use this to gain access to features of the KeyValueStoreManager + * that are specific to the ESP32 platform. + */ +inline KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/transport/BUILD.gn b/src/transport/BUILD.gn index 06072b8dca62ac..38c96deda5a6a0 100644 --- a/src/transport/BUILD.gn +++ b/src/transport/BUILD.gn @@ -13,6 +13,7 @@ # limitations under the License. import("//build_overrides/chip.gni") +import("//build_overrides/nlio.gni") import("${chip_root}/src/ble/ble.gni") static_library("transport") { @@ -63,5 +64,6 @@ static_library("transport") { "${chip_root}/src/platform", "${chip_root}/src/setup_payload", "${chip_root}/src/transport/raw", + "${nlio_root}:nlio", ] } From d9ecabc2b0c225e493111e0cbd0458b26cacded1 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Sun, 21 Feb 2021 06:30:15 -0800 Subject: [PATCH 3/9] Decouple code from platform header --- examples/chip-tool/config/PersistentStorage.h | 4 +- src/app/server/RendezvousServer.cpp | 7 +++- src/app/server/RendezvousServer.h | 3 ++ src/app/server/Server.cpp | 40 ++++++++++++++++--- src/controller/CHIPDeviceController.h | 2 +- .../CHIPDeviceController_deprecated.h | 8 ++-- .../ChipDeviceController-StorageDelegate.cpp | 2 +- .../ChipDeviceController-StorageDelegate.h | 2 +- .../CHIPPersistentStorageDelegateBridge.h | 8 ++-- .../CHIPPersistentStorageDelegateBridge.mm | 12 +++--- .../core}/CHIPPersistentStorageDelegate.h | 31 ++++++++++++-- src/transport/AdminPairingTable.h | 20 ++++++---- src/transport/StorablePeerConnection.h | 19 +++++---- 13 files changed, 114 insertions(+), 44 deletions(-) rename src/{controller => lib/core}/CHIPPersistentStorageDelegate.h (73%) diff --git a/examples/chip-tool/config/PersistentStorage.h b/examples/chip-tool/config/PersistentStorage.h index 4f2a3b6297e554..edef1cdf94678c 100644 --- a/examples/chip-tool/config/PersistentStorage.h +++ b/examples/chip-tool/config/PersistentStorage.h @@ -22,13 +22,13 @@ #include #include -class PersistentStorage : public chip::Controller::PersistentStorageDelegate +class PersistentStorage : public chip::PersistentStorageDelegate { public: CHIP_ERROR Init(); /////////// PersistentStorageDelegate Interface ///////// - void SetDelegate(chip::Controller::PersistentStorageResultDelegate * delegate) override; + void SetDelegate(chip::PersistentStorageResultDelegate * delegate) override; 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; diff --git a/src/app/server/RendezvousServer.cpp b/src/app/server/RendezvousServer.cpp index 4e7a31dded3d9f..8da70684cac379 100644 --- a/src/app/server/RendezvousServer.cpp +++ b/src/app/server/RendezvousServer.cpp @@ -66,10 +66,13 @@ void RendezvousServer::OnRendezvousComplete() ChipLogProgress(AppServer, "Device completed Rendezvous process"); StorablePeerConnection connection(mRendezvousSession.GetPairingSession(), mRendezvousSession.GetAdminId()); - VerifyOrReturn(connection.StoreUsingKVSMgr(PersistedStorage::KeyValueStoreMgr()) == CHIP_NO_ERROR); + VerifyOrReturn(mStorage != nullptr); + VerifyOrReturn(connection.StoreIntoKVS(*mStorage) == CHIP_NO_ERROR); uint16_t nextKeyId = mRendezvousSession.GetNextKeyId(); - PersistedStorage::KeyValueStoreMgr().Put(kStorablePeerConnectionCountKey, nextKeyId); + VerifyOrReturn(CanCastTo(sizeof(nextKeyId))); + uint16_t size = static_cast(sizeof(nextKeyId)); + mStorage->SetKeyValue(kStorablePeerConnectionCountKey, &nextKeyId, size); } void RendezvousServer::OnRendezvousStatusUpdate(Status status, CHIP_ERROR err) diff --git a/src/app/server/RendezvousServer.h b/src/app/server/RendezvousServer.h index 147ef7a52a62f1..316deabdec78fd 100644 --- a/src/app/server/RendezvousServer.h +++ b/src/app/server/RendezvousServer.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include @@ -31,6 +32,7 @@ class RendezvousServer : public RendezvousSessionDelegate CHIP_ERROR Init(const RendezvousParameters & params, TransportMgrBase * transportMgr, SecureSessionMgr * sessionMgr, Transport::AdminPairingInfo * admin); void SetDelegate(AppDelegate * delegate) { mDelegate = delegate; }; + void SetStorage(PersistentStorageDelegate * delegate) { mStorage = delegate; }; //////////////// RendezvousSessionDelegate Implementation /////////////////// @@ -46,6 +48,7 @@ class RendezvousServer : public RendezvousSessionDelegate private: RendezvousSession mRendezvousSession; AppDelegate * mDelegate; + PersistentStorageDelegate * mStorage = nullptr; }; } // namespace chip diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 1de4327d46558a..7b12310c316e84 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -72,12 +73,33 @@ constexpr bool useTestPairing() #endif } +class ServerStorageDelegate : public PersistentStorageDelegate +{ + void SetDelegate(PersistentStorageResultDelegate * delegate) override {} + void GetKeyValue(const char * key) override {} + void SetKeyValue(const char * key, const char * value) override {} + + CHIP_ERROR GetKeyValue(const char * key, void * buffer, uint16_t & size) override + { + return PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size); + } + + CHIP_ERROR SetKeyValue(const char * key, const void * value, uint16_t size) override + { + return PersistedStorage::KeyValueStoreMgr().Put(key, value, size); + } + + void DeleteKeyValue(const char * key) override { PersistedStorage::KeyValueStoreMgr().Delete(key); } +}; + +ServerStorageDelegate gServerStorage; + CHIP_ERROR PersistAdminPairingToKVS(AdminPairingInfo * admin, AdminId nextAvailableId) { ReturnErrorCodeIf(admin == nullptr, CHIP_ERROR_INVALID_ARGUMENT); ChipLogProgress(AppServer, "Persisting admin ID %d, next available %d", admin->GetAdminId(), nextAvailableId); - ReturnErrorOnFailure(admin->StoreUsingKVSMgr(PersistedStorage::KeyValueStoreMgr())); + ReturnErrorOnFailure(admin->StoreIntoKVS(gServerStorage)); ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kAdminTableCountKey, &nextAvailableId, sizeof(nextAvailableId))); ChipLogProgress(AppServer, "Persisting admin ID successfully"); @@ -91,11 +113,14 @@ CHIP_ERROR RestoreAllAdminPairingsFromKVS(AdminPairingTable & adminPairings, Adm CHIP_NO_ERROR); ChipLogProgress(AppServer, "Next available admin ID is %d", nextAvailableId); + // TODO: The admin ID space allocation should be re-evaluated. With the current approach, the space could be + // exhausted while IDs are still available (e.g. if the admin IDs are allocated and freed over a period of time). + // Also, the current approach can make ID lookup slower as more IDs are allocated and freed. for (AdminId id = 0; id < nextAvailableId; id++) { AdminPairingInfo * admin = adminPairings.AssignAdminId(id); // Recreate the binding if one exists in persistent storage. Else skip to the next ID - if (admin->FetchUsingKVSMgr(PersistedStorage::KeyValueStoreMgr()) != CHIP_NO_ERROR) + if (admin->FetchFromKVS(gServerStorage) != CHIP_NO_ERROR) { adminPairings.ReleaseAdminId(id); } @@ -111,13 +136,14 @@ CHIP_ERROR RestoreAllAdminPairingsFromKVS(AdminPairingTable & adminPairings, Adm void DeleteAdminPairingsInKVS(AdminId nextAvailableId) { PersistedStorage::KeyValueStoreMgr().Delete(kAdminTableCountKey); + for (AdminId id = 0; id < nextAvailableId; id++) { - AdminPairingInfo::DeleteUsingKVSMgr(PersistedStorage::KeyValueStoreMgr(), id); + AdminPairingInfo::DeleteFromKVS(gServerStorage, id); } } -CHIP_ERROR RestoreAllSessionsFromKVS(SecureSessionMgr & sessionMgr, RendezvousServer & server) +static CHIP_ERROR RestoreAllSessionsFromKVS(SecureSessionMgr & sessionMgr, RendezvousServer & server) { uint16_t nextSessionKeyId = 0; // It's not an error if the key doesn't exist. Just return right away. @@ -129,7 +155,7 @@ CHIP_ERROR RestoreAllSessionsFromKVS(SecureSessionMgr & sessionMgr, RendezvousSe for (uint16_t keyId = 0; keyId < nextSessionKeyId; keyId++) { StorablePeerConnection connection; - if (CHIP_NO_ERROR == connection.FetchUsingKVSMgr(PersistedStorage::KeyValueStoreMgr(), keyId)) + if (CHIP_NO_ERROR == connection.FetchFromKVS(gServerStorage, keyId)) { // The following is static to save on stack space usage static PASESession session; @@ -149,9 +175,10 @@ CHIP_ERROR RestoreAllSessionsFromKVS(SecureSessionMgr & sessionMgr, RendezvousSe void DeleteSessionsInKVS(uint16_t nextSessionKeyId) { PersistedStorage::KeyValueStoreMgr().Delete(kStorablePeerConnectionCountKey); + for (uint16_t keyId = 0; keyId < nextSessionKeyId; keyId++) { - StorablePeerConnection::DeleteUsingKVSMgr(PersistedStorage::KeyValueStoreMgr(), keyId); + StorablePeerConnection::DeleteFromKVS(gServerStorage, keyId); } } @@ -476,6 +503,7 @@ void InitServer(AppDelegate * delegate) InitDataModelHandler(); gCallbacks.SetDelegate(delegate); gRendezvousServer.SetDelegate(delegate); + gRendezvousServer.SetStorage(&gServerStorage); gAdvDelegate.SetDelegate(delegate); // Init transport before operations with secure session mgr. diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index b7534f46b3f75e..426cc2847fb7f9 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -29,8 +29,8 @@ #pragma once #include -#include #include +#include #include #include #include diff --git a/src/controller/CHIPDeviceController_deprecated.h b/src/controller/CHIPDeviceController_deprecated.h index 246204a9d45211..d4572b8f548bab 100644 --- a/src/controller/CHIPDeviceController_deprecated.h +++ b/src/controller/CHIPDeviceController_deprecated.h @@ -29,8 +29,8 @@ #pragma once #include -#include #include +#include #include #include #include @@ -68,13 +68,13 @@ class DLL_EXPORT ChipDeviceController : public Controller::DeviceStatusDelegate * System::Layer and InetLayer. */ CHIP_ERROR Init(NodeId localDeviceId, Controller::DevicePairingDelegate * pairingDelegate = nullptr, - Controller::PersistentStorageDelegate * storageDelegate = 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, - Controller::DevicePairingDelegate * pairingDelegate = nullptr, - Controller::PersistentStorageDelegate * storageDelegate = nullptr); + Controller::DevicePairingDelegate * pairingDelegate = nullptr, + PersistentStorageDelegate * storageDelegate = nullptr); CHIP_ERROR Shutdown(); CHIP_ERROR SetUdpListenPort(uint16_t listenPort); diff --git a/src/controller/python/ChipDeviceController-StorageDelegate.cpp b/src/controller/python/ChipDeviceController-StorageDelegate.cpp index 31770e32fd1c68..96f7efcc6ae4ca 100644 --- a/src/controller/python/ChipDeviceController-StorageDelegate.cpp +++ b/src/controller/python/ChipDeviceController-StorageDelegate.cpp @@ -23,7 +23,7 @@ #include #include -#include +#include #include namespace chip { diff --git a/src/controller/python/ChipDeviceController-StorageDelegate.h b/src/controller/python/ChipDeviceController-StorageDelegate.h index e88dc6359fa533..ee4a5a0165f4f4 100644 --- a/src/controller/python/ChipDeviceController-StorageDelegate.h +++ b/src/controller/python/ChipDeviceController-StorageDelegate.h @@ -21,7 +21,7 @@ #include #include -#include +#include class PythonPersistentStorageDelegate; diff --git a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h index ff2fec0a3b4ad3..58941447e1487c 100644 --- a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h +++ b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.h @@ -18,11 +18,11 @@ #import "CHIPPersistentStorageDelegate.h" #import "CHIPError.h" -#include +#include NS_ASSUME_NONNULL_BEGIN -class CHIPPersistentStorageDelegateBridge : public chip::Controller::PersistentStorageDelegate +class CHIPPersistentStorageDelegateBridge : public chip::PersistentStorageDelegate { public: CHIPPersistentStorageDelegateBridge(); @@ -30,7 +30,7 @@ class CHIPPersistentStorageDelegateBridge : public chip::Controller::PersistentS void setFrameworkDelegate(id delegate, dispatch_queue_t queue); - void SetDelegate(chip::Controller::PersistentStorageResultDelegate * delegate) override; + void SetDelegate(chip::PersistentStorageResultDelegate * delegate) override; void GetKeyValue(const char * key) override; @@ -44,7 +44,7 @@ class CHIPPersistentStorageDelegateBridge : public chip::Controller::PersistentS id mDelegate; dispatch_queue_t mQueue; - chip::Controller::PersistentStorageResultDelegate * mCallback; + chip::PersistentStorageResultDelegate * mCallback; SendKeyValue mCompletionHandler; CHIPSendSetStatus mSetStatusHandler; CHIPSendDeleteStatus mDeleteStatusHandler; diff --git a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm index f841550517623d..1be4b605ce3d78 100644 --- a/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm +++ b/src/darwin/Framework/CHIP/CHIPPersistentStorageDelegateBridge.mm @@ -39,14 +39,14 @@ }); } -void CHIPPersistentStorageDelegateBridge::SetDelegate(chip::Controller::PersistentStorageResultDelegate * delegate) +void CHIPPersistentStorageDelegateBridge::SetDelegate(chip::PersistentStorageResultDelegate * delegate) { dispatch_async(mWorkQueue, ^{ if (delegate) { mCallback = delegate; mCompletionHandler = ^(NSString * key, NSString * value) { - chip::Controller::PersistentStorageResultDelegate * callback = mCallback; + chip::PersistentStorageResultDelegate * callback = mCallback; if (callback) { dispatch_async(mWorkQueue, ^{ callback->OnValue([key UTF8String], [value UTF8String]); @@ -55,20 +55,20 @@ }; mSetStatusHandler = ^(NSString * key, NSError * status) { - chip::Controller::PersistentStorageResultDelegate * callback = mCallback; + chip::PersistentStorageResultDelegate * callback = mCallback; if (callback) { dispatch_async(mWorkQueue, ^{ - callback->OnStatus([key UTF8String], chip::Controller::PersistentStorageResultDelegate::Operation::kSET, + callback->OnStatus([key UTF8String], chip::PersistentStorageResultDelegate::Operation::kSET, [CHIPError errorToCHIPErrorCode:status]); }); } }; mDeleteStatusHandler = ^(NSString * key, NSError * status) { - chip::Controller::PersistentStorageResultDelegate * callback = mCallback; + chip::PersistentStorageResultDelegate * callback = mCallback; if (callback) { dispatch_async(mWorkQueue, ^{ - callback->OnStatus([key UTF8String], chip::Controller::PersistentStorageResultDelegate::Operation::kDELETE, + callback->OnStatus([key UTF8String], chip::PersistentStorageResultDelegate::Operation::kDELETE, [CHIPError errorToCHIPErrorCode:status]); }); } diff --git a/src/controller/CHIPPersistentStorageDelegate.h b/src/lib/core/CHIPPersistentStorageDelegate.h similarity index 73% rename from src/controller/CHIPPersistentStorageDelegate.h rename to src/lib/core/CHIPPersistentStorageDelegate.h index a2176f2bc63b80..b502ff75d7a90c 100644 --- a/src/controller/CHIPPersistentStorageDelegate.h +++ b/src/lib/core/CHIPPersistentStorageDelegate.h @@ -22,7 +22,6 @@ #include namespace chip { -namespace Controller { class DLL_EXPORT PersistentStorageResultDelegate { @@ -96,13 +95,40 @@ class DLL_EXPORT PersistentStorageDelegate /** * @brief - * Set the value for the key + * 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. + * + * This API can be used to retrieve a byte buffer value from the storage. + * + * @param[in] key Key to lookup + * @param[out] buffer Value for the key + * @param[in, out] size Input value buffer size, output length of value. + * The output length could be larger than input value. In + * such cases, the user should allocate the buffer large + * enough (>= output length), and call the API again. + */ + virtual CHIP_ERROR GetKeyValue(const char * key, void * buffer, uint16_t & size) { return CHIP_ERROR_NOT_IMPLEMENTED; } + + /** + * @brief + * Set the value for the key to a null terminated string. * * @param[in] key Key to be set * @param[in] value Value to be set */ virtual void SetKeyValue(const char * key, const char * value) = 0; + /** + * @brief + * Set the value for the key to a byte buffer. + * + * @param[in] key Key to be set + * @param[in] value Value to be set + * @param[in] size Size of the Value + */ + virtual CHIP_ERROR SetKeyValue(const char * key, const void * value, uint16_t size) { return CHIP_ERROR_NOT_IMPLEMENTED; } + /** * @brief * Deletes the value for the key @@ -112,5 +138,4 @@ class DLL_EXPORT PersistentStorageDelegate virtual void DeleteKeyValue(const char * key) = 0; }; -} // namespace Controller } // namespace chip diff --git a/src/transport/AdminPairingTable.h b/src/transport/AdminPairingTable.h index 6a65028299f432..6aaba3b0da11fa 100644 --- a/src/transport/AdminPairingTable.h +++ b/src/transport/AdminPairingTable.h @@ -22,8 +22,8 @@ #pragma once #include +#include #include -#include #include #include #include @@ -93,7 +93,7 @@ class DLL_EXPORT AdminPairingInfo mAdmin = kUndefinedAdminId; } - CHIP_ERROR StoreUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr) + CHIP_ERROR StoreIntoKVS(PersistentStorageDelegate & kvs) { char key[KeySize()]; ReturnErrorOnFailure(GenerateKey(mAdmin, key, sizeof(key))); @@ -102,17 +102,22 @@ class DLL_EXPORT AdminPairingInfo info.mNodeId = Encoding::LittleEndian::HostSwap64(mNodeId); info.mAdmin = Encoding::LittleEndian::HostSwap16(mAdmin); - return mgr.Put(key, info); + VerifyOrReturnError(CanCastTo(sizeof(info)), CHIP_ERROR_INTERNAL); + uint16_t size = static_cast(sizeof(info)); + return kvs.SetKeyValue(key, &info, size); } - CHIP_ERROR FetchUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr) + CHIP_ERROR FetchFromKVS(PersistentStorageDelegate & kvs) { char key[KeySize()]; ReturnErrorOnFailure(GenerateKey(mAdmin, key, sizeof(key))); StorableAdminPairingInfo info; - ReturnErrorOnFailure(mgr.Get(key, &info, sizeof(info))); + VerifyOrReturnError(CanCastTo(sizeof(info)), CHIP_ERROR_INTERNAL); + uint16_t size = static_cast(sizeof(info)); + ReturnErrorOnFailure(kvs.GetKeyValue(key, &info, size)); + mNodeId = Encoding::LittleEndian::HostSwap64(info.mNodeId); AdminId id = Encoding::LittleEndian::HostSwap16(info.mAdmin); ReturnErrorCodeIf(mAdmin != id, CHIP_ERROR_INCORRECT_STATE); @@ -120,12 +125,13 @@ class DLL_EXPORT AdminPairingInfo return CHIP_NO_ERROR; } - static CHIP_ERROR DeleteUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr, AdminId id) + static CHIP_ERROR DeleteFromKVS(PersistentStorageDelegate & kvs, AdminId id) { char key[KeySize()]; ReturnErrorOnFailure(GenerateKey(id, key, sizeof(key))); - return mgr.Delete(key); + kvs.DeleteKeyValue(key); + return CHIP_NO_ERROR; } private: diff --git a/src/transport/StorablePeerConnection.h b/src/transport/StorablePeerConnection.h index 44026cef4cfd96..abe82ac6ec4f7a 100644 --- a/src/transport/StorablePeerConnection.h +++ b/src/transport/StorablePeerConnection.h @@ -18,7 +18,7 @@ #pragma once #include -#include +#include #include namespace chip { @@ -42,28 +42,33 @@ class DLL_EXPORT StorablePeerConnection virtual ~StorablePeerConnection() {} - CHIP_ERROR StoreUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr) + CHIP_ERROR StoreIntoKVS(PersistentStorageDelegate & kvs) { char key[KeySize()]; ReturnErrorOnFailure(GenerateKey(mKeyId, key, sizeof(key))); - return mgr.Put(key, &mSession, sizeof(mSession)); + VerifyOrReturnError(CanCastTo(sizeof(mSession)), CHIP_ERROR_INTERNAL); + uint16_t size = static_cast(sizeof(mSession)); + return kvs.SetKeyValue(key, &mSession, size); } - CHIP_ERROR FetchUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr, uint16_t keyId) + CHIP_ERROR FetchFromKVS(PersistentStorageDelegate & kvs, uint16_t keyId) { char key[KeySize()]; ReturnErrorOnFailure(GenerateKey(keyId, key, sizeof(key))); - return mgr.Get(key, &mSession, sizeof(mSession)); + VerifyOrReturnError(CanCastTo(sizeof(mSession)), CHIP_ERROR_INTERNAL); + uint16_t size = static_cast(sizeof(mSession)); + return kvs.GetKeyValue(key, &mSession, size); } - static CHIP_ERROR DeleteUsingKVSMgr(DeviceLayer::PersistedStorage::KeyValueStoreManager & mgr, uint16_t keyId) + static CHIP_ERROR DeleteFromKVS(PersistentStorageDelegate & kvs, uint16_t keyId) { char key[KeySize()]; ReturnErrorOnFailure(GenerateKey(keyId, key, sizeof(key))); - return mgr.Delete(key); + kvs.DeleteKeyValue(key); + return CHIP_NO_ERROR; } void GetPASESession(PASESession & session) { session.FromSerializable(mSession.mOpCreds); } From 276868746c0b8d1814666706d732a7b71fe6d2d0 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Sun, 21 Feb 2021 13:15:57 -0800 Subject: [PATCH 4/9] Split code from the header file to fix build issues --- src/app/server/RendezvousServer.cpp | 2 + src/platform/BUILD.gn | 5 +- src/transport/AdminPairingTable.cpp | 144 +++++++++++++++++++++++ src/transport/AdminPairingTable.h | 115 ++---------------- src/transport/BUILD.gn | 2 + src/transport/StorablePeerConnection.cpp | 75 ++++++++++++ src/transport/StorablePeerConnection.h | 48 +------- 7 files changed, 243 insertions(+), 148 deletions(-) create mode 100644 src/transport/AdminPairingTable.cpp create mode 100644 src/transport/StorablePeerConnection.cpp diff --git a/src/app/server/RendezvousServer.cpp b/src/app/server/RendezvousServer.cpp index 8da70684cac379..d7acccb37b96a8 100644 --- a/src/app/server/RendezvousServer.cpp +++ b/src/app/server/RendezvousServer.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index 7afbd9924c51f8..034b86163ac4b1 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -354,7 +354,10 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "$dir_pw_kvs:crc16", "$dir_pw_log", ] - public_deps += [ "$dir_pw_kvs" ] + public_deps += [ + "$dir_pw_checksum", + "$dir_pw_kvs", + ] sources += [ "EFR32/KeyValueStoreManagerImpl.cpp", "EFR32/KeyValueStoreManagerImpl.h", diff --git a/src/transport/AdminPairingTable.cpp b/src/transport/AdminPairingTable.cpp new file mode 100644 index 00000000000000..b8ee7c71680006 --- /dev/null +++ b/src/transport/AdminPairingTable.cpp @@ -0,0 +1,144 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @brief Defines a table of admins that have provisioned the device. + */ + +#include +#include +#include +#include +#include + +namespace chip { +namespace Transport { + +CHIP_ERROR AdminPairingInfo::StoreIntoKVS(PersistentStorageDelegate & kvs) +{ + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(mAdmin, key, sizeof(key))); + + StorableAdminPairingInfo info; + info.mNodeId = Encoding::LittleEndian::HostSwap64(mNodeId); + info.mAdmin = Encoding::LittleEndian::HostSwap16(mAdmin); + + VerifyOrReturnError(CanCastTo(sizeof(info)), CHIP_ERROR_INTERNAL); + uint16_t size = static_cast(sizeof(info)); + return kvs.SetKeyValue(key, &info, size); +} + +CHIP_ERROR AdminPairingInfo::FetchFromKVS(PersistentStorageDelegate & kvs) +{ + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(mAdmin, key, sizeof(key))); + + StorableAdminPairingInfo info; + + VerifyOrReturnError(CanCastTo(sizeof(info)), CHIP_ERROR_INTERNAL); + uint16_t size = static_cast(sizeof(info)); + ReturnErrorOnFailure(kvs.GetKeyValue(key, &info, size)); + + mNodeId = Encoding::LittleEndian::HostSwap64(info.mNodeId); + AdminId id = Encoding::LittleEndian::HostSwap16(info.mAdmin); + ReturnErrorCodeIf(mAdmin != id, CHIP_ERROR_INCORRECT_STATE); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR AdminPairingInfo::DeleteFromKVS(PersistentStorageDelegate & kvs, AdminId id) +{ + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(id, key, sizeof(key))); + + kvs.DeleteKeyValue(key); + return CHIP_NO_ERROR; +} + +constexpr size_t AdminPairingInfo::KeySize() +{ + return sizeof(kAdminTableKeyPrefix) + 2 * sizeof(AdminId); +} + +CHIP_ERROR AdminPairingInfo::GenerateKey(AdminId id, char * key, size_t len) +{ + VerifyOrReturnError(len >= KeySize(), CHIP_ERROR_INVALID_ARGUMENT); + int keySize = snprintf(key, len, "%s%x", kAdminTableKeyPrefix, id); + VerifyOrReturnError(keySize > 0, CHIP_ERROR_INTERNAL); + VerifyOrReturnError(len > (size_t) keySize, CHIP_ERROR_INTERNAL); + return CHIP_NO_ERROR; +} + +AdminPairingInfo * AdminPairingTable::AssignAdminId(AdminId adminId) +{ + for (size_t i = 0; i < CHIP_CONFIG_MAX_DEVICE_ADMINS; i++) + { + if (!mStates[i].IsInitialized()) + { + mStates[i].SetAdminId(adminId); + + return &mStates[i]; + } + } + + return nullptr; +} + +AdminPairingInfo * AdminPairingTable::AssignAdminId(AdminId adminId, NodeId nodeId) +{ + AdminPairingInfo * admin = AssignAdminId(adminId); + + if (admin != nullptr) + { + admin->SetNodeId(nodeId); + } + + return admin; +} + +void AdminPairingTable::ReleaseAdminId(AdminId adminId) +{ + AdminPairingInfo * admin = FindAdmin(adminId); + if (admin != nullptr) + { + admin->Reset(); + } +} + +AdminPairingInfo * AdminPairingTable::FindAdmin(AdminId adminId) +{ + for (size_t i = 0; i < CHIP_CONFIG_MAX_DEVICE_ADMINS; i++) + { + if (mStates[i].IsInitialized() && mStates[i].GetAdminId() == adminId) + { + return &mStates[i]; + } + } + + return nullptr; +} + +void AdminPairingTable::Reset() +{ + for (size_t i = 0; i < CHIP_CONFIG_MAX_DEVICE_ADMINS; i++) + { + return mStates[i].Reset(); + } +} + +} // namespace Transport +} // namespace chip diff --git a/src/transport/AdminPairingTable.h b/src/transport/AdminPairingTable.h index 6aaba3b0da11fa..b85c098b4be463 100644 --- a/src/transport/AdminPairingTable.h +++ b/src/transport/AdminPairingTable.h @@ -21,14 +21,8 @@ #pragma once -#include #include -#include -#include -#include #include -#include -#include #include namespace chip { @@ -93,46 +87,11 @@ class DLL_EXPORT AdminPairingInfo mAdmin = kUndefinedAdminId; } - CHIP_ERROR StoreIntoKVS(PersistentStorageDelegate & kvs) - { - char key[KeySize()]; - ReturnErrorOnFailure(GenerateKey(mAdmin, key, sizeof(key))); - - StorableAdminPairingInfo info; - info.mNodeId = Encoding::LittleEndian::HostSwap64(mNodeId); - info.mAdmin = Encoding::LittleEndian::HostSwap16(mAdmin); - - VerifyOrReturnError(CanCastTo(sizeof(info)), CHIP_ERROR_INTERNAL); - uint16_t size = static_cast(sizeof(info)); - return kvs.SetKeyValue(key, &info, size); - } + CHIP_ERROR StoreIntoKVS(PersistentStorageDelegate & kvs); - CHIP_ERROR FetchFromKVS(PersistentStorageDelegate & kvs) - { - char key[KeySize()]; - ReturnErrorOnFailure(GenerateKey(mAdmin, key, sizeof(key))); - - StorableAdminPairingInfo info; + CHIP_ERROR FetchFromKVS(PersistentStorageDelegate & kvs); - VerifyOrReturnError(CanCastTo(sizeof(info)), CHIP_ERROR_INTERNAL); - uint16_t size = static_cast(sizeof(info)); - ReturnErrorOnFailure(kvs.GetKeyValue(key, &info, size)); - - mNodeId = Encoding::LittleEndian::HostSwap64(info.mNodeId); - AdminId id = Encoding::LittleEndian::HostSwap16(info.mAdmin); - ReturnErrorCodeIf(mAdmin != id, CHIP_ERROR_INCORRECT_STATE); - - return CHIP_NO_ERROR; - } - - static CHIP_ERROR DeleteFromKVS(PersistentStorageDelegate & kvs, AdminId id) - { - char key[KeySize()]; - ReturnErrorOnFailure(GenerateKey(id, key, sizeof(key))); - - kvs.DeleteKeyValue(key); - return CHIP_NO_ERROR; - } + static CHIP_ERROR DeleteFromKVS(PersistentStorageDelegate & kvs, AdminId id); private: AdminId mAdmin = kUndefinedAdminId; @@ -141,16 +100,9 @@ class DLL_EXPORT AdminPairingInfo OperationalCredentials mOpCred; AccessControlList mACL; - static constexpr size_t KeySize() { return sizeof(kAdminTableKeyPrefix) + 2 * sizeof(AdminId); } + static constexpr size_t KeySize(); // { return sizeof(kAdminTableKeyPrefix) + 2 * sizeof(AdminId); } - static CHIP_ERROR GenerateKey(AdminId id, char * key, size_t len) - { - VerifyOrReturnError(len >= KeySize(), CHIP_ERROR_INVALID_ARGUMENT); - int keySize = snprintf(key, len, "%s%x", kAdminTableKeyPrefix, id); - VerifyOrReturnError(keySize > 0, CHIP_ERROR_INTERNAL); - VerifyOrReturnError(len > (size_t) keySize, CHIP_ERROR_INTERNAL); - return CHIP_NO_ERROR; - } + static CHIP_ERROR GenerateKey(AdminId id, char * key, size_t len); struct StorableAdminPairingInfo { @@ -162,62 +114,15 @@ class DLL_EXPORT AdminPairingInfo class DLL_EXPORT AdminPairingTable { public: - AdminPairingInfo * AssignAdminId(AdminId adminId) - { - for (size_t i = 0; i < CHIP_CONFIG_MAX_DEVICE_ADMINS; i++) - { - if (!mStates[i].IsInitialized()) - { - mStates[i].SetAdminId(adminId); - - return &mStates[i]; - } - } - - return nullptr; - } + AdminPairingInfo * AssignAdminId(AdminId adminId); - AdminPairingInfo * AssignAdminId(AdminId adminId, NodeId nodeId) - { - AdminPairingInfo * admin = AssignAdminId(adminId); + AdminPairingInfo * AssignAdminId(AdminId adminId, NodeId nodeId); - if (admin != nullptr) - { - admin->SetNodeId(nodeId); - } + void ReleaseAdminId(AdminId adminId); - return admin; - } + AdminPairingInfo * FindAdmin(AdminId adminId); - void ReleaseAdminId(AdminId adminId) - { - AdminPairingInfo * admin = FindAdmin(adminId); - if (admin != nullptr) - { - admin->Reset(); - } - } - - AdminPairingInfo * FindAdmin(AdminId adminId) - { - for (size_t i = 0; i < CHIP_CONFIG_MAX_DEVICE_ADMINS; i++) - { - if (mStates[i].IsInitialized() && mStates[i].GetAdminId() == adminId) - { - return &mStates[i]; - } - } - - return nullptr; - } - - void Reset() - { - for (size_t i = 0; i < CHIP_CONFIG_MAX_DEVICE_ADMINS; i++) - { - return mStates[i].Reset(); - } - } + void Reset(); private: AdminPairingInfo mStates[CHIP_CONFIG_MAX_DEVICE_ADMINS]; diff --git a/src/transport/BUILD.gn b/src/transport/BUILD.gn index 38c96deda5a6a0..ea57b63f16eb6c 100644 --- a/src/transport/BUILD.gn +++ b/src/transport/BUILD.gn @@ -20,6 +20,7 @@ static_library("transport") { output_name = "libTransportLayer" sources = [ + "AdminPairingTable.cpp", "AdminPairingTable.h", "CASESession.cpp", "CASESession.h", @@ -40,6 +41,7 @@ static_library("transport") { "SecureSessionMgr.cpp", "SecureSessionMgr.h", "SessionEstablishmentDelegate.h", + "StorablePeerConnection.cpp", "StorablePeerConnection.h", "TransportMgr.h", "TransportMgrBase.cpp", diff --git a/src/transport/StorablePeerConnection.cpp b/src/transport/StorablePeerConnection.cpp new file mode 100644 index 00000000000000..edb70b74f394b2 --- /dev/null +++ b/src/transport/StorablePeerConnection.cpp @@ -0,0 +1,75 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +namespace chip { + +StorablePeerConnection::StorablePeerConnection(PASESession & session, Transport::AdminId admin) +{ + session.ToSerializable(mSession.mOpCreds); + mSession.mAdmin = Encoding::LittleEndian::HostSwap16(admin); + mKeyId = session.GetLocalKeyId(); +} + +CHIP_ERROR StorablePeerConnection::StoreIntoKVS(PersistentStorageDelegate & kvs) +{ + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(mKeyId, key, sizeof(key))); + + VerifyOrReturnError(CanCastTo(sizeof(mSession)), CHIP_ERROR_INTERNAL); + uint16_t size = static_cast(sizeof(mSession)); + return kvs.SetKeyValue(key, &mSession, size); +} + +CHIP_ERROR StorablePeerConnection::FetchFromKVS(PersistentStorageDelegate & kvs, uint16_t keyId) +{ + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(keyId, key, sizeof(key))); + + VerifyOrReturnError(CanCastTo(sizeof(mSession)), CHIP_ERROR_INTERNAL); + uint16_t size = static_cast(sizeof(mSession)); + return kvs.GetKeyValue(key, &mSession, size); +} + +CHIP_ERROR StorablePeerConnection::DeleteFromKVS(PersistentStorageDelegate & kvs, uint16_t keyId) +{ + char key[KeySize()]; + ReturnErrorOnFailure(GenerateKey(keyId, key, sizeof(key))); + + kvs.DeleteKeyValue(key); + return CHIP_NO_ERROR; +} + +constexpr size_t StorablePeerConnection::KeySize() +{ + return sizeof(kStorablePeerConnectionKeyPrefix) + 2 * sizeof(uint16_t); +} + +CHIP_ERROR StorablePeerConnection::GenerateKey(uint16_t id, char * key, size_t len) +{ + VerifyOrReturnError(len >= KeySize(), CHIP_ERROR_INVALID_ARGUMENT); + int keySize = snprintf(key, len, "%s%x", kStorablePeerConnectionKeyPrefix, id); + VerifyOrReturnError(keySize > 0, CHIP_ERROR_INTERNAL); + VerifyOrReturnError(len > (size_t) keySize, CHIP_ERROR_INTERNAL); + return CHIP_NO_ERROR; +} + +} // namespace chip diff --git a/src/transport/StorablePeerConnection.h b/src/transport/StorablePeerConnection.h index abe82ac6ec4f7a..efe4c1092592cb 100644 --- a/src/transport/StorablePeerConnection.h +++ b/src/transport/StorablePeerConnection.h @@ -17,7 +17,6 @@ #pragma once -#include #include #include @@ -33,59 +32,24 @@ class DLL_EXPORT StorablePeerConnection public: StorablePeerConnection() {} - StorablePeerConnection(PASESession & session, Transport::AdminId admin) - { - session.ToSerializable(mSession.mOpCreds); - mSession.mAdmin = Encoding::LittleEndian::HostSwap16(admin); - mKeyId = session.GetLocalKeyId(); - } + StorablePeerConnection(PASESession & session, Transport::AdminId admin); virtual ~StorablePeerConnection() {} - CHIP_ERROR StoreIntoKVS(PersistentStorageDelegate & kvs) - { - char key[KeySize()]; - ReturnErrorOnFailure(GenerateKey(mKeyId, key, sizeof(key))); - - VerifyOrReturnError(CanCastTo(sizeof(mSession)), CHIP_ERROR_INTERNAL); - uint16_t size = static_cast(sizeof(mSession)); - return kvs.SetKeyValue(key, &mSession, size); - } - - CHIP_ERROR FetchFromKVS(PersistentStorageDelegate & kvs, uint16_t keyId) - { - char key[KeySize()]; - ReturnErrorOnFailure(GenerateKey(keyId, key, sizeof(key))); - - VerifyOrReturnError(CanCastTo(sizeof(mSession)), CHIP_ERROR_INTERNAL); - uint16_t size = static_cast(sizeof(mSession)); - return kvs.GetKeyValue(key, &mSession, size); - } + CHIP_ERROR StoreIntoKVS(PersistentStorageDelegate & kvs); - static CHIP_ERROR DeleteFromKVS(PersistentStorageDelegate & kvs, uint16_t keyId) - { - char key[KeySize()]; - ReturnErrorOnFailure(GenerateKey(keyId, key, sizeof(key))); + CHIP_ERROR FetchFromKVS(PersistentStorageDelegate & kvs, uint16_t keyId); - kvs.DeleteKeyValue(key); - return CHIP_NO_ERROR; - } + static CHIP_ERROR DeleteFromKVS(PersistentStorageDelegate & kvs, uint16_t keyId); void GetPASESession(PASESession & session) { session.FromSerializable(mSession.mOpCreds); } Transport::AdminId GetAdminId() { return mSession.mAdmin; } private: - static constexpr size_t KeySize() { return sizeof(kStorablePeerConnectionKeyPrefix) + 2 * sizeof(uint16_t); } + static constexpr size_t KeySize(); - static CHIP_ERROR GenerateKey(uint16_t id, char * key, size_t len) - { - VerifyOrReturnError(len >= KeySize(), CHIP_ERROR_INVALID_ARGUMENT); - int keySize = snprintf(key, len, "%s%x", kStorablePeerConnectionKeyPrefix, id); - VerifyOrReturnError(keySize > 0, CHIP_ERROR_INTERNAL); - VerifyOrReturnError(len > (size_t) keySize, CHIP_ERROR_INTERNAL); - return CHIP_NO_ERROR; - } + static CHIP_ERROR GenerateKey(uint16_t id, char * key, size_t len); struct StorableSession { From 4044b20995dbb38fe5d874ff7e98912a76446d60 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 22 Feb 2021 09:16:30 -0800 Subject: [PATCH 5/9] Address review comments --- src/app/server/RendezvousServer.cpp | 12 +++--- src/app/server/RendezvousServer.h | 11 ++++-- src/app/server/Server.cpp | 51 ++++++++++++++++++-------- src/transport/PASESession.h | 8 ++-- src/transport/StorablePeerConnection.h | 2 +- 5 files changed, 55 insertions(+), 29 deletions(-) diff --git a/src/app/server/RendezvousServer.cpp b/src/app/server/RendezvousServer.cpp index d7acccb37b96a8..3c3b32010e22f6 100644 --- a/src/app/server/RendezvousServer.cpp +++ b/src/app/server/RendezvousServer.cpp @@ -38,8 +38,8 @@ namespace chip { RendezvousServer::RendezvousServer() : mRendezvousSession(this) {} -CHIP_ERROR RendezvousServer::Init(const RendezvousParameters & params, TransportMgrBase * transportMgr, - SecureSessionMgr * sessionMgr, Transport::AdminPairingInfo * admin) +CHIP_ERROR RendezvousServer::WaitForPairing(const RendezvousParameters & params, TransportMgrBase * transportMgr, + SecureSessionMgr * sessionMgr, Transport::AdminPairingInfo * admin) { return mRendezvousSession.Init(params, transportMgr, sessionMgr, admin); } @@ -68,11 +68,13 @@ void RendezvousServer::OnRendezvousComplete() ChipLogProgress(AppServer, "Device completed Rendezvous process"); StorablePeerConnection connection(mRendezvousSession.GetPairingSession(), mRendezvousSession.GetAdminId()); - VerifyOrReturn(mStorage != nullptr); - VerifyOrReturn(connection.StoreIntoKVS(*mStorage) == CHIP_NO_ERROR); + VerifyOrReturn(mStorage != nullptr, + ChipLogError(AppServer, "Storage delegate is not available. Cannot store the connection state")); + VerifyOrReturn(connection.StoreIntoKVS(*mStorage) == CHIP_NO_ERROR, + ChipLogError(AppServer, "Failed to store the connection state")); uint16_t nextKeyId = mRendezvousSession.GetNextKeyId(); - VerifyOrReturn(CanCastTo(sizeof(nextKeyId))); + VerifyOrReturn(CanCastTo(sizeof(nextKeyId)), ChipLogError(AppServer, "Cannot cast the KeyID to uint16_t type")); uint16_t size = static_cast(sizeof(nextKeyId)); mStorage->SetKeyValue(kStorablePeerConnectionCountKey, &nextKeyId, size); } diff --git a/src/app/server/RendezvousServer.h b/src/app/server/RendezvousServer.h index 316deabdec78fd..a26a935f0154cb 100644 --- a/src/app/server/RendezvousServer.h +++ b/src/app/server/RendezvousServer.h @@ -29,10 +29,13 @@ class RendezvousServer : public RendezvousSessionDelegate public: RendezvousServer(); - CHIP_ERROR Init(const RendezvousParameters & params, TransportMgrBase * transportMgr, SecureSessionMgr * sessionMgr, - Transport::AdminPairingInfo * admin); - void SetDelegate(AppDelegate * delegate) { mDelegate = delegate; }; - void SetStorage(PersistentStorageDelegate * delegate) { mStorage = delegate; }; + CHIP_ERROR WaitForPairing(const RendezvousParameters & params, TransportMgrBase * transportMgr, SecureSessionMgr * sessionMgr, + Transport::AdminPairingInfo * admin); + void SetDelegates(AppDelegate * delegate, PersistentStorageDelegate * storage) + { + mDelegate = delegate; + mStorage = storage; + } //////////////// RendezvousSessionDelegate Implementation /////////////////// diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 7b12310c316e84..76a9938d4c1a8f 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -75,9 +75,23 @@ constexpr bool useTestPairing() class ServerStorageDelegate : public PersistentStorageDelegate { - void SetDelegate(PersistentStorageResultDelegate * delegate) override {} - void GetKeyValue(const char * key) override {} - void SetKeyValue(const char * key, const char * value) override {} + void SetDelegate(PersistentStorageResultDelegate * delegate) override + { + ChipLogError(AppServer, "ServerStorageDelegate does not support async operations"); + chipDie(); + } + + void GetKeyValue(const char * key) override + { + ChipLogError(AppServer, "ServerStorageDelegate does not support async operations"); + chipDie(); + } + + void SetKeyValue(const char * key, const char * value) override + { + ChipLogError(AppServer, "ServerStorageDelegate does not support async operations"); + chipDie(); + } CHIP_ERROR GetKeyValue(const char * key, void * buffer, uint16_t & size) override { @@ -133,7 +147,7 @@ CHIP_ERROR RestoreAllAdminPairingsFromKVS(AdminPairingTable & adminPairings, Adm return CHIP_NO_ERROR; } -void DeleteAdminPairingsInKVS(AdminId nextAvailableId) +void EraseAllAdminPairingsUpTo(AdminId nextAvailableId) { PersistedStorage::KeyValueStoreMgr().Delete(kAdminTableCountKey); @@ -152,27 +166,31 @@ static CHIP_ERROR RestoreAllSessionsFromKVS(SecureSessionMgr & sessionMgr, Rende CHIP_NO_ERROR); ChipLogProgress(AppServer, "Found %d stored connections", nextSessionKeyId); + PASESession * session = static_cast(chip::Platform::MemoryAlloc(sizeof(PASESession))); + VerifyOrReturnError(session != nullptr, CHIP_ERROR_NO_MEMORY); + for (uint16_t keyId = 0; keyId < nextSessionKeyId; keyId++) { StorablePeerConnection connection; if (CHIP_NO_ERROR == connection.FetchFromKVS(gServerStorage, keyId)) { - // The following is static to save on stack space usage - static PASESession session; connection.GetPASESession(session); - ChipLogProgress(AppServer, "Fetched the session information: from %llu", session.PeerConnection().GetPeerNodeId()); - sessionMgr.NewPairing(Optional::Value(session.PeerConnection().GetPeerAddress()), - session.PeerConnection().GetPeerNodeId(), &session, + ChipLogProgress(AppServer, "Fetched the session information: from %llu", session->PeerConnection().GetPeerNodeId()); + sessionMgr.NewPairing(Optional::Value(session->PeerConnection().GetPeerAddress()), + session->PeerConnection().GetPeerNodeId(), session, SecureSessionMgr::PairingDirection::kResponder, connection.GetAdminId(), nullptr); + session->Clear(); } } + chip::Platform::MemoryFree(session); + server.GetRendezvousSession()->SetNextKeyId(nextSessionKeyId); return CHIP_NO_ERROR; } -void DeleteSessionsInKVS(uint16_t nextSessionKeyId) +void EraseAllSessionsUpTo(uint16_t nextSessionKeyId) { PersistedStorage::KeyValueStoreMgr().Delete(kStorablePeerConnectionCountKey); @@ -288,7 +306,7 @@ static CHIP_ERROR OpenPairingWindowUsingVerifier(uint16_t discriminator, PASEVer VerifyOrReturnError(adminInfo != nullptr, CHIP_ERROR_NO_MEMORY); gNextAvailableAdminId++; - return gRendezvousServer.Init(std::move(params), &gTransports, &gSessions, adminInfo); + return gRendezvousServer.WaitForPairing(std::move(params), &gTransports, &gSessions, adminInfo); } class ServerCallback : public SecureSessionMgrDelegate @@ -479,8 +497,8 @@ CHIP_ERROR OpenDefaultPairingWindow(ResetAdmins resetAdmins) if (resetAdmins == ResetAdmins::kYes) { uint16_t nextKeyId = gRendezvousServer.GetRendezvousSession()->GetNextKeyId(); - DeleteAdminPairingsInKVS(gNextAvailableAdminId); - DeleteSessionsInKVS(nextKeyId); + EraseAllAdminPairingsUpTo(gNextAvailableAdminId); + EraseAllSessionsUpTo(nextKeyId); gNextAvailableAdminId = 0; gAdminPairings.Reset(); } @@ -490,7 +508,7 @@ CHIP_ERROR OpenDefaultPairingWindow(ResetAdmins resetAdmins) VerifyOrReturnError(adminInfo != nullptr, CHIP_ERROR_NO_MEMORY); gNextAvailableAdminId++; - return gRendezvousServer.Init(std::move(params), &gTransports, &gSessions, adminInfo); + return gRendezvousServer.WaitForPairing(std::move(params), &gTransports, &gSessions, adminInfo); } // The function will initialize datamodel handler and then start the server @@ -500,10 +518,11 @@ void InitServer(AppDelegate * delegate) CHIP_ERROR err = CHIP_NO_ERROR; Optional peer(Transport::Type::kUndefined); + chip::Platform::MemoryInit(); + InitDataModelHandler(); gCallbacks.SetDelegate(delegate); - gRendezvousServer.SetDelegate(delegate); - gRendezvousServer.SetStorage(&gServerStorage); + gRendezvousServer.SetDelegates(delegate, &gServerStorage); gAdvDelegate.SetDelegate(delegate); // Init transport before operations with secure session mgr. diff --git a/src/transport/PASESession.h b/src/transport/PASESession.h index 494c9369a9a4cf..1b12bdccb754e5 100644 --- a/src/transport/PASESession.h +++ b/src/transport/PASESession.h @@ -150,7 +150,7 @@ class DLL_EXPORT PASESession * initialized once pairing is complete * @return CHIP_ERROR The result of session derivation */ - virtual CHIP_ERROR DeriveSecureSession(const uint8_t * info, size_t info_len, SecureSession & session); + CHIP_ERROR DeriveSecureSession(const uint8_t * info, size_t info_len, SecureSession & session); /** * @brief @@ -206,6 +206,10 @@ class DLL_EXPORT PASESession **/ CHIP_ERROR FromSerializable(const PASESessionSerializable & output); + /** @brief This function zeroes out and resets the memory used by the object. + **/ + void Clear(); + private: enum Spake2pErrorType : uint8_t { @@ -237,8 +241,6 @@ class DLL_EXPORT PASESession CHIP_ERROR AttachHeaderAndSend(Protocols::SecureChannel::MsgType msgType, System::PacketBufferHandle msgBuf); - void Clear(); - SessionEstablishmentDelegate * mDelegate = nullptr; Protocols::SecureChannel::MsgType mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2pError; diff --git a/src/transport/StorablePeerConnection.h b/src/transport/StorablePeerConnection.h index efe4c1092592cb..9038e677c2acf0 100644 --- a/src/transport/StorablePeerConnection.h +++ b/src/transport/StorablePeerConnection.h @@ -42,7 +42,7 @@ class DLL_EXPORT StorablePeerConnection static CHIP_ERROR DeleteFromKVS(PersistentStorageDelegate & kvs, uint16_t keyId); - void GetPASESession(PASESession & session) { session.FromSerializable(mSession.mOpCreds); } + void GetPASESession(PASESession * session) { session->FromSerializable(mSession.mOpCreds); } Transport::AdminId GetAdminId() { return mSession.mAdmin; } From 75dcab70ec252e0995ce846ebc4d4625fe71be4e Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 22 Feb 2021 14:12:38 -0800 Subject: [PATCH 6/9] Rename SetDelegates to Init and check storage delegate --- src/app/server/RendezvousServer.h | 6 +++++- src/app/server/Server.cpp | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/app/server/RendezvousServer.h b/src/app/server/RendezvousServer.h index a26a935f0154cb..b3c493613de036 100644 --- a/src/app/server/RendezvousServer.h +++ b/src/app/server/RendezvousServer.h @@ -20,6 +20,7 @@ #include #include #include +#include #include namespace chip { @@ -31,10 +32,13 @@ class RendezvousServer : public RendezvousSessionDelegate CHIP_ERROR WaitForPairing(const RendezvousParameters & params, TransportMgrBase * transportMgr, SecureSessionMgr * sessionMgr, Transport::AdminPairingInfo * admin); - void SetDelegates(AppDelegate * delegate, PersistentStorageDelegate * storage) + + CHIP_ERROR Init(AppDelegate * delegate, PersistentStorageDelegate * storage) { + VerifyOrReturnError(storage != nullptr, CHIP_ERROR_INVALID_ARGUMENT); mDelegate = delegate; mStorage = storage; + return CHIP_NO_ERROR; } //////////////// RendezvousSessionDelegate Implementation /////////////////// diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 76a9938d4c1a8f..9f2e4cf1cd52d8 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -522,7 +522,10 @@ void InitServer(AppDelegate * delegate) InitDataModelHandler(); gCallbacks.SetDelegate(delegate); - gRendezvousServer.SetDelegates(delegate, &gServerStorage); + + err = gRendezvousServer.Init(delegate, &gServerStorage); + SuccessOrExit(err); + gAdvDelegate.SetDelegate(delegate); // Init transport before operations with secure session mgr. From 36cbd8072489c84e438bd9f0d1146aaada1d615c Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 23 Feb 2021 08:01:58 -0800 Subject: [PATCH 7/9] Use New<> and Delete, instead of MemoryAlloc and Free for session object --- src/app/server/Server.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 9f2e4cf1cd52d8..6128739871c53d 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -166,7 +166,7 @@ static CHIP_ERROR RestoreAllSessionsFromKVS(SecureSessionMgr & sessionMgr, Rende CHIP_NO_ERROR); ChipLogProgress(AppServer, "Found %d stored connections", nextSessionKeyId); - PASESession * session = static_cast(chip::Platform::MemoryAlloc(sizeof(PASESession))); + PASESession * session = chip::Platform::New(); VerifyOrReturnError(session != nullptr, CHIP_ERROR_NO_MEMORY); for (uint16_t keyId = 0; keyId < nextSessionKeyId; keyId++) @@ -184,7 +184,7 @@ static CHIP_ERROR RestoreAllSessionsFromKVS(SecureSessionMgr & sessionMgr, Rende } } - chip::Platform::MemoryFree(session); + chip::Platform::Delete(session); server.GetRendezvousSession()->SetNextKeyId(nextSessionKeyId); return CHIP_NO_ERROR; From 89a961461b2f5f83cbe6fa47cd63e15161306b89 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 23 Feb 2021 10:45:05 -0800 Subject: [PATCH 8/9] Fix link issues for Darwin and QPG6100 --- src/platform/BUILD.gn | 10 ++++++ .../Darwin/KeyValueStoreManagerImpl.cpp | 34 +++++++++++++++++++ .../qpg6100/KeyValueStoreManagerImpl.cpp | 34 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 src/platform/Darwin/KeyValueStoreManagerImpl.cpp create mode 100644 src/platform/qpg6100/KeyValueStoreManagerImpl.cpp diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index 034b86163ac4b1..192eec51d1f4af 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -309,6 +309,11 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "Darwin/SystemPlatformConfig.h", ] + sources += [ + "Darwin/KeyValueStoreManagerImpl.cpp", + "Darwin/KeyValueStoreManagerImpl.h", + ] + if (chip_enable_ble) { sources += [ "Darwin/BleApplicationDelegate.h", @@ -557,6 +562,11 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "qpg6100/qpg6100Config.h", ] + sources += [ + "qpg6100/KeyValueStoreManagerImpl.cpp", + "qpg6100/KeyValueStoreManagerImpl.h", + ] + if (chip_enable_openthread) { public_deps += [ "${openthread_root}:libopenthread-ftd" ] diff --git a/src/platform/Darwin/KeyValueStoreManagerImpl.cpp b/src/platform/Darwin/KeyValueStoreManagerImpl.cpp new file mode 100644 index 00000000000000..40c3fdeecb23f1 --- /dev/null +++ b/src/platform/Darwin/KeyValueStoreManagerImpl.cpp @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific key value storage implementation for Darwin + */ + +#include + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/qpg6100/KeyValueStoreManagerImpl.cpp b/src/platform/qpg6100/KeyValueStoreManagerImpl.cpp new file mode 100644 index 00000000000000..c213ee6820c549 --- /dev/null +++ b/src/platform/qpg6100/KeyValueStoreManagerImpl.cpp @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific key value storage implementation for QPG6100 + */ + +#include + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip From b33daa615a4d972040512c7a9b0dbc31fe5354c3 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Tue, 23 Feb 2021 17:23:24 -0500 Subject: [PATCH 9/9] Add stubs for K32W & cc13x2_26x2 --- src/platform/BUILD.gn | 4 + .../K32W/KeyValueStoreManagerImpl.cpp | 34 ++++++++ src/platform/K32W/KeyValueStoreManagerImpl.h | 80 +++++++++++++++++++ .../cc13x2_26x2/KeyValueStoreManagerImpl.cpp | 34 ++++++++ .../cc13x2_26x2/KeyValueStoreManagerImpl.h | 80 +++++++++++++++++++ 5 files changed, 232 insertions(+) create mode 100644 src/platform/K32W/KeyValueStoreManagerImpl.cpp create mode 100644 src/platform/K32W/KeyValueStoreManagerImpl.h create mode 100644 src/platform/cc13x2_26x2/KeyValueStoreManagerImpl.cpp create mode 100644 src/platform/cc13x2_26x2/KeyValueStoreManagerImpl.h diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index 192eec51d1f4af..8d9dd43340a876 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -253,6 +253,8 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.cpp", "cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.h", "cc13x2_26x2/InetPlatformConfig.h", + "cc13x2_26x2/KeyValueStoreManagerImpl.cpp", + "cc13x2_26x2/KeyValueStoreManagerImpl.h", "cc13x2_26x2/Logging.cpp", "cc13x2_26x2/PlatformManagerImpl.cpp", "cc13x2_26x2/PlatformManagerImpl.h", @@ -425,6 +427,8 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "K32W/DeviceNetworkProvisioningDelegateImpl.h", "K32W/K32WConfig.cpp", "K32W/K32WConfig.h", + "K32W/KeyValueStoreManagerImpl.cpp", + "K32W/KeyValueStoreManagerImpl.h", "K32W/Logging.cpp", "K32W/NetworkProvisioningServerImpl.h", "K32W/PlatformManagerImpl.cpp", diff --git a/src/platform/K32W/KeyValueStoreManagerImpl.cpp b/src/platform/K32W/KeyValueStoreManagerImpl.cpp new file mode 100644 index 00000000000000..84eff6796744f2 --- /dev/null +++ b/src/platform/K32W/KeyValueStoreManagerImpl.cpp @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific key value storage implementation for K32W + */ + +#include + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/K32W/KeyValueStoreManagerImpl.h b/src/platform/K32W/KeyValueStoreManagerImpl.h new file mode 100644 index 00000000000000..12ed71ef619b31 --- /dev/null +++ b/src/platform/K32W/KeyValueStoreManagerImpl.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific key value storage implementation for K32W + */ + +#pragma once + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +class KeyValueStoreManagerImpl final : public KeyValueStoreManager +{ + // Allow the KeyValueStoreManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class KeyValueStoreManager; + +public: + // NOTE: Currently this platform does not support partial and offset reads + // these will return CHIP_ERROR_NOT_IMPLEMENTED. + CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + CHIP_ERROR _Delete(const char * key) { return CHIP_ERROR_NOT_IMPLEMENTED; } + + CHIP_ERROR _Put(const char * key, const void * value, size_t value_size) { return CHIP_ERROR_NOT_IMPLEMENTED; } + +private: + // ===== Members for internal use by the following friends. + friend KeyValueStoreManager & KeyValueStoreMgr(); + friend KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(); + + static KeyValueStoreManagerImpl sInstance; +}; + +/** + * Returns the public interface of the KeyValueStoreManager singleton object. + * + * Chip applications should use this to access features of the KeyValueStoreManager object + * that are common to all platforms. + */ +inline KeyValueStoreManager & KeyValueStoreMgr(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the KeyValueStoreManager singleton object. + * + * Chip applications can use this to gain access to features of the KeyValueStoreManager + * that are specific to the ESP32 platform. + */ +inline KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13x2_26x2/KeyValueStoreManagerImpl.cpp b/src/platform/cc13x2_26x2/KeyValueStoreManagerImpl.cpp new file mode 100644 index 00000000000000..4d982b58126610 --- /dev/null +++ b/src/platform/cc13x2_26x2/KeyValueStoreManagerImpl.cpp @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific key value storage implementation for CC1352 + */ + +#include + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance; + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/cc13x2_26x2/KeyValueStoreManagerImpl.h b/src/platform/cc13x2_26x2/KeyValueStoreManagerImpl.h new file mode 100644 index 00000000000000..24f46ee57d1356 --- /dev/null +++ b/src/platform/cc13x2_26x2/KeyValueStoreManagerImpl.h @@ -0,0 +1,80 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Platform-specific key value storage implementation for CC1352. + */ + +#pragma once + +namespace chip { +namespace DeviceLayer { +namespace PersistedStorage { + +class KeyValueStoreManagerImpl final : public KeyValueStoreManager +{ + // Allow the KeyValueStoreManager interface class to delegate method calls to + // the implementation methods provided by this class. + friend class KeyValueStoreManager; + +public: + // NOTE: Currently this platform does not support partial and offset reads + // these will return CHIP_ERROR_NOT_IMPLEMENTED. + CHIP_ERROR _Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size = nullptr, size_t offset = 0) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + CHIP_ERROR _Delete(const char * key) { return CHIP_ERROR_NOT_IMPLEMENTED; } + + CHIP_ERROR _Put(const char * key, const void * value, size_t value_size) { return CHIP_ERROR_NOT_IMPLEMENTED; } + +private: + // ===== Members for internal use by the following friends. + friend KeyValueStoreManager & KeyValueStoreMgr(); + friend KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(); + + static KeyValueStoreManagerImpl sInstance; +}; + +/** + * Returns the public interface of the KeyValueStoreManager singleton object. + * + * Chip applications should use this to access features of the KeyValueStoreManager object + * that are common to all platforms. + */ +inline KeyValueStoreManager & KeyValueStoreMgr(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +/** + * Returns the platform-specific implementation of the KeyValueStoreManager singleton object. + * + * Chip applications can use this to gain access to features of the KeyValueStoreManager + * that are specific to the ESP32 platform. + */ +inline KeyValueStoreManagerImpl & KeyValueStoreMgrImpl(void) +{ + return KeyValueStoreManagerImpl::sInstance; +} + +} // namespace PersistedStorage +} // namespace DeviceLayer +} // namespace chip