diff --git a/examples/lighting-app/k32w/main/AppTask.cpp b/examples/lighting-app/k32w/main/AppTask.cpp index 6e8184ffa76228..57dd35b5806e1d 100644 --- a/examples/lighting-app/k32w/main/AppTask.cpp +++ b/examples/lighting-app/k32w/main/AppTask.cpp @@ -24,6 +24,7 @@ #include "OnboardingCodesUtil.h" #include #include +#include #include "attribute-storage.h" #include "gen/attribute-id.h" @@ -396,48 +397,23 @@ void AppTask::LightActionEventHandler(AppEvent * aEvent) void AppTask::ThreadStart() { - chip::DeviceLayer::Internal::DeviceNetworkInfo networkInfo; - - memset(networkInfo.ThreadNetworkName, 0, chip::DeviceLayer::Internal::kMaxThreadNetworkNameLength + 1); - memcpy(networkInfo.ThreadNetworkName, "OpenThread", 10); - - networkInfo.ThreadExtendedPANId[0] = 0xde; - networkInfo.ThreadExtendedPANId[1] = 0xad; - networkInfo.ThreadExtendedPANId[2] = 0x00; - networkInfo.ThreadExtendedPANId[3] = 0xbe; - networkInfo.ThreadExtendedPANId[4] = 0xef; - networkInfo.ThreadExtendedPANId[5] = 0x00; - networkInfo.ThreadExtendedPANId[6] = 0xca; - networkInfo.ThreadExtendedPANId[7] = 0xfe; - - networkInfo.ThreadMasterKey[0] = 0x00; - networkInfo.ThreadMasterKey[1] = 0x11; - networkInfo.ThreadMasterKey[2] = 0x22; - networkInfo.ThreadMasterKey[3] = 0x33; - networkInfo.ThreadMasterKey[4] = 0x44; - networkInfo.ThreadMasterKey[5] = 0x55; - networkInfo.ThreadMasterKey[6] = 0x66; - networkInfo.ThreadMasterKey[7] = 0x77; - networkInfo.ThreadMasterKey[8] = 0x88; - networkInfo.ThreadMasterKey[9] = 0x99; - networkInfo.ThreadMasterKey[10] = 0xAA; - networkInfo.ThreadMasterKey[11] = 0xBB; - networkInfo.ThreadMasterKey[12] = 0xCC; - networkInfo.ThreadMasterKey[13] = 0xDD; - networkInfo.ThreadMasterKey[14] = 0xEE; - networkInfo.ThreadMasterKey[15] = 0xFF; - - networkInfo.ThreadPANId = 0xabcd; - networkInfo.ThreadChannel = 15; - - networkInfo.FieldPresent.ThreadExtendedPANId = true; - networkInfo.FieldPresent.ThreadMeshPrefix = false; - networkInfo.FieldPresent.ThreadPSKc = false; - networkInfo.NetworkId = 0; - networkInfo.FieldPresent.NetworkId = true; + chip::Thread::OperationalDataset dataset{}; + + constexpr uint8_t xpanid[] = { 0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0xca, 0xfe }; + constexpr uint8_t masterkey[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + constexpr uint16_t panid = 0xabcd; + constexpr uint16_t channel = 15; + + dataset.SetNetworkName("OpenThread"); + dataset.SetExtendedPanId(xpanid); + dataset.SetMasterKey(masterkey); + dataset.SetPanId(panid); + dataset.SetChannel(channel); ThreadStackMgr().SetThreadEnabled(false); - ThreadStackMgr().SetThreadProvision(networkInfo); + ThreadStackMgr().SetThreadProvision(dataset.AsByteSpan()); ThreadStackMgr().SetThreadEnabled(true); } diff --git a/examples/lock-app/k32w/main/AppTask.cpp b/examples/lock-app/k32w/main/AppTask.cpp index 1f95a51738f331..8a110fecbd8eea 100644 --- a/examples/lock-app/k32w/main/AppTask.cpp +++ b/examples/lock-app/k32w/main/AppTask.cpp @@ -24,6 +24,7 @@ #include "OnboardingCodesUtil.h" #include #include +#include #include "attribute-storage.h" #include "gen/attribute-id.h" @@ -400,48 +401,23 @@ void AppTask::LockActionEventHandler(AppEvent * aEvent) void AppTask::ThreadStart() { - chip::DeviceLayer::Internal::DeviceNetworkInfo networkInfo; - - memset(networkInfo.ThreadNetworkName, 0, chip::DeviceLayer::Internal::kMaxThreadNetworkNameLength + 1); - memcpy(networkInfo.ThreadNetworkName, "OpenThread", 10); - - networkInfo.ThreadExtendedPANId[0] = 0xde; - networkInfo.ThreadExtendedPANId[1] = 0xad; - networkInfo.ThreadExtendedPANId[2] = 0x00; - networkInfo.ThreadExtendedPANId[3] = 0xbe; - networkInfo.ThreadExtendedPANId[4] = 0xef; - networkInfo.ThreadExtendedPANId[5] = 0x00; - networkInfo.ThreadExtendedPANId[6] = 0xca; - networkInfo.ThreadExtendedPANId[7] = 0xfe; - - networkInfo.ThreadMasterKey[0] = 0x00; - networkInfo.ThreadMasterKey[1] = 0x11; - networkInfo.ThreadMasterKey[2] = 0x22; - networkInfo.ThreadMasterKey[3] = 0x33; - networkInfo.ThreadMasterKey[4] = 0x44; - networkInfo.ThreadMasterKey[5] = 0x55; - networkInfo.ThreadMasterKey[6] = 0x66; - networkInfo.ThreadMasterKey[7] = 0x77; - networkInfo.ThreadMasterKey[8] = 0x88; - networkInfo.ThreadMasterKey[9] = 0x99; - networkInfo.ThreadMasterKey[10] = 0xAA; - networkInfo.ThreadMasterKey[11] = 0xBB; - networkInfo.ThreadMasterKey[12] = 0xCC; - networkInfo.ThreadMasterKey[13] = 0xDD; - networkInfo.ThreadMasterKey[14] = 0xEE; - networkInfo.ThreadMasterKey[15] = 0xFF; - - networkInfo.ThreadPANId = 0xabcd; - networkInfo.ThreadChannel = 15; - - networkInfo.FieldPresent.ThreadExtendedPANId = true; - networkInfo.FieldPresent.ThreadMeshPrefix = false; - networkInfo.FieldPresent.ThreadPSKc = false; - networkInfo.NetworkId = 0; - networkInfo.FieldPresent.NetworkId = true; + chip::Thread::OperationalDataset dataset{}; + + constexpr uint8_t xpanid[] = { 0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0xca, 0xfe }; + constexpr uint8_t masterkey[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + constexpr uint16_t panid = 0xabcd; + constexpr uint16_t channel = 15; + + dataset.SetNetworkName("OpenThread"); + dataset.SetExtendedPanId(xpanid); + dataset.SetMasterKey(masterkey); + dataset.SetPanId(panid); + dataset.SetChannel(channel); ThreadStackMgr().SetThreadEnabled(false); - ThreadStackMgr().SetThreadProvision(networkInfo); + ThreadStackMgr().SetThreadProvision(dataset.AsByteSpan()); ThreadStackMgr().SetThreadEnabled(true); } diff --git a/examples/platform/nrfconnect/util/ThreadUtil.cpp b/examples/platform/nrfconnect/util/ThreadUtil.cpp index b19ea6183d39a0..4b751f5c069d38 100644 --- a/examples/platform/nrfconnect/util/ThreadUtil.cpp +++ b/examples/platform/nrfconnect/util/ThreadUtil.cpp @@ -20,6 +20,7 @@ #include #include +#include #include @@ -27,25 +28,23 @@ void StartDefaultThreadNetwork(void) { - chip::DeviceLayer::Internal::DeviceNetworkInfo deviceNetworkInfo; - memset(&deviceNetworkInfo, 0, sizeof(deviceNetworkInfo)); - - const uint8_t masterKey[chip::DeviceLayer::Internal::kThreadMasterKeyLength] = { - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff + chip::Thread::OperationalDataset dataset{}; + uint8_t xpanid[8]; + constexpr uint8_t masterkey[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; - const uint8_t threadMeshPrefix[chip::DeviceLayer::Internal::kThreadMeshPrefixLength] = { 0xfd, 0x11, 0x11, 0x11, - 0x11, 0x22, 0x00, 0x00 }; - - memcpy(deviceNetworkInfo.ThreadNetworkName, CONFIG_OPENTHREAD_NETWORK_NAME, strlen(CONFIG_OPENTHREAD_NETWORK_NAME)); - net_bytes_from_str(deviceNetworkInfo.ThreadExtendedPANId, 8, CONFIG_OPENTHREAD_XPANID); - deviceNetworkInfo.FieldPresent.ThreadExtendedPANId = true; - memcpy(deviceNetworkInfo.ThreadMasterKey, masterKey, sizeof(masterKey)); - deviceNetworkInfo.FieldPresent.ThreadMeshPrefix = true; - memcpy(deviceNetworkInfo.ThreadMeshPrefix, threadMeshPrefix, sizeof(threadMeshPrefix)); - deviceNetworkInfo.ThreadPANId = CONFIG_OPENTHREAD_PANID; - deviceNetworkInfo.ThreadChannel = CONFIG_OPENTHREAD_CHANNEL; + constexpr uint8_t meshLocalPrefix[] = { 0xfd, 0x11, 0x11, 0x11, 0x11, 0x22, 0x00, 0x00 }; + + net_bytes_from_str(xpanid, sizeof(xpanid), CONFIG_OPENTHREAD_XPANID); + + dataset.SetChannel(CONFIG_OPENTHREAD_CHANNEL); + dataset.SetExtendedPanId(xpanid); + dataset.SetMasterKey(masterkey); + dataset.SetMeshLocalPrefix(meshLocalPrefix); + dataset.SetNetworkName(CONFIG_OPENTHREAD_NETWORK_NAME); + dataset.SetPanId(CONFIG_OPENTHREAD_PANID); chip::DeviceLayer::ThreadStackMgr().SetThreadEnabled(false); - chip::DeviceLayer::ThreadStackMgr().SetThreadProvision(deviceNetworkInfo); + chip::DeviceLayer::ThreadStackMgr().SetThreadProvision(dataset.AsByteSpan()); chip::DeviceLayer::ThreadStackMgr().SetThreadEnabled(true); } diff --git a/examples/platform/qpg6100/app/Service.cpp b/examples/platform/qpg6100/app/Service.cpp index 39b190dbc42b5e..b2f4e8891f143c 100644 --- a/examples/platform/qpg6100/app/Service.cpp +++ b/examples/platform/qpg6100/app/Service.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -114,29 +115,23 @@ void PublishService() void StartDefaultThreadNetwork(void) { - // Set default thread network Info and enable/start thread - - chip::DeviceLayer::Internal::DeviceNetworkInfo deviceNetworkInfo; - memset(&deviceNetworkInfo, 0, sizeof(deviceNetworkInfo)); - const char * networkName = "OpenThread"; - const uint8_t masterKey[chip::DeviceLayer::Internal::kThreadMasterKeyLength] = { + chip::Thread::OperationalDataset dataset{}; + constexpr uint8_t masterkey[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; - const uint8_t threadMeshPrefix[chip::DeviceLayer::Internal::kThreadMeshPrefixLength] = { 0xfd, 0xde, 0xad, 0x00, - 0xbe, 0xef, 0x00, 0x00 }; - - const uint8_t extendedPanId[chip::DeviceLayer::Internal::kThreadExtendedPANIdLength] = { 0xDE, 0xAD, 0x00, 0xBE, - 0xEF, 0x00, 0xCA, 0xFE }; - memcpy(deviceNetworkInfo.ThreadNetworkName, networkName, strlen(networkName)); - memcpy(deviceNetworkInfo.ThreadExtendedPANId, extendedPanId, sizeof(extendedPanId)); - deviceNetworkInfo.FieldPresent.ThreadExtendedPANId = true; - memcpy(deviceNetworkInfo.ThreadMasterKey, masterKey, sizeof(masterKey)); - deviceNetworkInfo.FieldPresent.ThreadMeshPrefix = true; - memcpy(deviceNetworkInfo.ThreadMeshPrefix, threadMeshPrefix, sizeof(threadMeshPrefix)); - deviceNetworkInfo.ThreadPANId = 0x1234; - deviceNetworkInfo.ThreadChannel = 11; + constexpr uint8_t meshLocalPrefix[] = { 0xfd, 0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0x00 }; + constexpr uint8_t xpanid[] = { 0xDE, 0xAD, 0x00, 0xBE, 0xEF, 0x00, 0xCA, 0xFE }; + constexpr uint16_t panid = 0x1234; + constexpr uint16_t channel = 11; + + dataset.SetChannel(channel); + dataset.SetExtendedPanId(xpanid); + dataset.SetMasterKey(masterkey); + dataset.SetMeshLocalPrefix(meshLocalPrefix); + dataset.SetNetworkName("OpenThread"); + dataset.SetPanId(panid); chip::DeviceLayer::ThreadStackMgr().SetThreadEnabled(false); - chip::DeviceLayer::ThreadStackMgr().SetThreadProvision(deviceNetworkInfo); + chip::DeviceLayer::ThreadStackMgr().SetThreadProvision(dataset.AsByteSpan()); chip::DeviceLayer::ThreadStackMgr().SetThreadEnabled(true); } diff --git a/src/app/clusters/network-commissioning/network-commissioning.cpp b/src/app/clusters/network-commissioning/network-commissioning.cpp index bb79ca1b47e8ee..d2d7406b88860f 100644 --- a/src/app/clusters/network-commissioning/network-commissioning.cpp +++ b/src/app/clusters/network-commissioning/network-commissioning.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -66,12 +67,6 @@ constexpr uint8_t kMaxWiFiSSIDLen = 32; constexpr uint8_t kMaxWiFiCredentialsLen = 64; constexpr uint8_t kMaxNetworks = 4; -// The temporary network id which will be used by thread networks in CHIP before we have the API for getting extpanid from dataset -// tlv. -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD -constexpr uint8_t kTemporaryThreadNetworkId[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; -#endif - enum class NetworkType : uint8_t { kUndefined = 0, @@ -102,7 +97,7 @@ struct NetworkInfo NetworkType mNetworkType; union NetworkData { - ThreadNetworkInfo mThread; + Thread::OperationalDataset mThread; WiFiNetworkInfo mWiFi; } mData; }; @@ -122,21 +117,23 @@ EmberAfNetworkCommissioningError OnAddThreadNetworkCommandCallbackInternal(app:: { if (sNetworks[i].mNetworkType == NetworkType::kUndefined) { - VerifyOrExit(operationalDataset.size() <= sizeof(ThreadNetworkInfo::mDataset), - err = EMBER_ZCL_NETWORK_COMMISSIONING_ERROR_OUT_OF_RANGE); - memcpy(sNetworks[i].mData.mThread.mDataset, operationalDataset.data(), operationalDataset.size()); + Thread::OperationalDataset & dataset = sNetworks[i].mData.mThread; + CHIP_ERROR error = dataset.Init(operationalDataset); - using ThreadDatasetLenType = decltype(sNetworks[i].mData.mThread.mDatasetLen); - VerifyOrExit(chip::CanCastTo(operationalDataset.size()), - err = EMBER_ZCL_NETWORK_COMMISSIONING_ERROR_OUT_OF_RANGE); - sNetworks[i].mData.mThread.mDatasetLen = static_cast(operationalDataset.size()); + if (error != CHIP_NO_ERROR) + { + ChipLogDetail(Zcl, "Failed to parse Thread operational dataset: %s", ErrorStr(error)); + err = EMBER_ZCL_NETWORK_COMMISSIONING_ERROR_UNKNOWN_ERROR; + break; + } + + uint8_t extendedPanId[Thread::kSizeExtendedPanId]; - // A 64bit id for thread networks, currently, we are missing some API for getting the thread network extpanid from the - // dataset tlv. - static_assert(sizeof(kTemporaryThreadNetworkId) <= sizeof(sNetworks[i].mNetworkID), - "TemporaryThreadNetworkId too long"); - memcpy(sNetworks[i].mNetworkID, kTemporaryThreadNetworkId, sizeof(kTemporaryThreadNetworkId)); - sNetworks[i].mNetworkIDLen = sizeof(kTemporaryThreadNetworkId); + static_assert(sizeof(sNetworks[i].mNetworkID) >= sizeof(extendedPanId), + "Network ID must be larger than Thread extended PAN ID!"); + SuccessOrExit(dataset.GetExtendedPanId(extendedPanId)); + memcpy(sNetworks[i].mNetworkID, extendedPanId, sizeof(extendedPanId)); + sNetworks[i].mNetworkIDLen = sizeof(extendedPanId); sNetworks[i].mNetworkType = NetworkType::kThread; sNetworks[i].mEnabled = false; @@ -218,8 +215,7 @@ CHIP_ERROR DoEnableNetwork(NetworkInfo * network) case NetworkType::kThread: #if CHIP_DEVICE_CONFIG_ENABLE_THREAD ReturnErrorOnFailure(DeviceLayer::ThreadStackMgr().SetThreadEnabled(false)); - ReturnErrorOnFailure( - DeviceLayer::ThreadStackMgr().SetThreadProvision(network->mData.mThread.mDataset, network->mData.mThread.mDatasetLen)); + ReturnErrorOnFailure(DeviceLayer::ThreadStackMgr().SetThreadProvision(network->mData.mThread.AsByteSpan())); ReturnErrorOnFailure(DeviceLayer::ThreadStackMgr().SetThreadEnabled(true)); #else return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp index 9dfd6db3201ca0..08904a90ed555d 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.cpp +++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp @@ -20,6 +20,8 @@ #include +#include + using chip::PersistentStorageResultDelegate; using chip::Controller::DeviceCommissioner; @@ -214,7 +216,7 @@ void AndroidDeviceControllerWrapper::SendNetworkCredentials(const char * ssid, c mCredentialsDelegate->SendNetworkCredentials(ssid, password); } -void AndroidDeviceControllerWrapper::SendThreadCredentials(const chip::DeviceLayer::Internal::DeviceNetworkInfo & threadData) +void AndroidDeviceControllerWrapper::SendThreadCredentials(chip::ByteSpan threadData) { if (mCredentialsDelegate == nullptr) { @@ -222,8 +224,21 @@ void AndroidDeviceControllerWrapper::SendThreadCredentials(const chip::DeviceLay return; } - ChipLogProgress(Controller, "Sending Thread credentials for channel %u, PAN ID %x...", threadData.ThreadChannel, - threadData.ThreadPANId); + chip::Thread::OperationalDataset dataset{}; + + if (!dataset.Init(threadData)) + { + ChipLogError(Controller, "Failed to parse Thread credentials."); + return; + } + + uint16_t channel = chip::Thread::kChannel_NotSpecified; + uint16_t panid = chip::Thread::kPANId_NotSpecified; + + dataset.GetChannel(channel); + dataset.GetPanId(panid); + + ChipLogProgress(Controller, "Sending Thread credentials for channel %u, PAN ID 0x%04x...", channel, panid); mCredentialsDelegate->SendThreadCredentials(threadData); } diff --git a/src/controller/java/AndroidDeviceControllerWrapper.h b/src/controller/java/AndroidDeviceControllerWrapper.h index 6a51fc690176bd..563239f238976b 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.h +++ b/src/controller/java/AndroidDeviceControllerWrapper.h @@ -41,7 +41,7 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel void SetJavaObjectRef(JavaVM * vm, jobject obj); void SendNetworkCredentials(const char * ssid, const char * password); - void SendThreadCredentials(const chip::DeviceLayer::Internal::DeviceNetworkInfo & threadData); + void SendThreadCredentials(chip::ByteSpan threadData); // DevicePairingDelegate implementation void OnNetworkCredentialsRequested(chip::RendezvousDeviceCredentialsDelegate * callback) override; diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 61332116066a78..df4e946a069828 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include // Choose an approximation of PTHREAD_NULL if pthread.h doesn't define one. @@ -334,20 +335,41 @@ JNI_METHOD(void, sendThreadCredentials) VerifyOrReturn(CanCastTo(channel), ChipLogError(Controller, "sendThreadCredentials() called with invalid Channel")); VerifyOrReturn(CanCastTo(panId), ChipLogError(Controller, "sendThreadCredentials() called with invalid PAN ID")); - VerifyOrReturn(xpanIdBytes.size() <= static_cast(kThreadExtendedPANIdLength), + VerifyOrReturn(xpanIdBytes.size() == static_cast(Thread::kSizeExtendedPanId), ChipLogError(Controller, "sendThreadCredentials() called with invalid XPAN ID")); - VerifyOrReturn(masterKeyBytes.size() <= static_cast(kThreadMasterKeyLength), + VerifyOrReturn(masterKeyBytes.size() == static_cast(Thread::kSizeMasterKey), ChipLogError(Controller, "sendThreadCredentials() called with invalid Master Key")); - DeviceNetworkInfo threadData = {}; - threadData.ThreadChannel = channel; - threadData.ThreadPANId = panId; - threadData.FieldPresent.ThreadExtendedPANId = 1; - memcpy(threadData.ThreadExtendedPANId, xpanIdBytes.data(), xpanIdBytes.size()); - memcpy(threadData.ThreadMasterKey, masterKeyBytes.data(), masterKeyBytes.size()); + Thread::OperationalDataset dataset{}; + + dataset.SetChannel(channel); + dataset.SetPanId(panId); + + // TODO network name is required, need to add UI + { + char networkName[Thread::kSizeNetworkName + 1]; + + snprintf(networkName, sizeof(networkName), "CHIP-%04X", panId); + dataset.SetNetworkName(networkName); + } + + { + uint8_t value[Thread::kSizeMasterKey]; + + memcpy(value, masterKeyBytes.data(), sizeof(value)); + + dataset.SetMasterKey(value); + } + { + uint8_t value[Thread::kSizeExtendedPanId]; + + memcpy(value, xpanIdBytes.data(), sizeof(value)); + + dataset.SetExtendedPanId(value); + } ScopedPthreadLock lock(&sStackLock); - AndroidDeviceControllerWrapper::FromJNIHandle(handle)->SendThreadCredentials(threadData); + AndroidDeviceControllerWrapper::FromJNIHandle(handle)->SendThreadCredentials(dataset.AsByteSpan()); } JNI_METHOD(void, pairTestDeviceWithoutSecurity)(JNIEnv * env, jobject self, jlong handle, jstring deviceAddr) diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp index 435b282a61a40b..44c34353cf7574 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -244,13 +244,12 @@ pychip_ScriptDevicePairingDelegate_SetThreadCredential(chip::Controller::DeviceC const char * masterKeyStr) { CHIP_ERROR err = CHIP_NO_ERROR; - uint8_t masterKey[chip::DeviceLayer::Internal::kThreadMasterKeyLength]; + uint8_t masterKey[chip::Thread::kSizeMasterKey]; (void) devCtrl; - VerifyOrExit(strlen(masterKeyStr) == 2 * chip::DeviceLayer::Internal::kThreadMasterKeyLength, - err = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(strlen(masterKeyStr) == 2 * chip::Thread::kSizeMasterKey, err = CHIP_ERROR_INVALID_ARGUMENT); - for (size_t i = 0; i < chip::DeviceLayer::Internal::kThreadMasterKeyLength; i++) + for (size_t i = 0; i < chip::Thread::kSizeMasterKey; i++) VerifyOrExit(sscanf(&masterKeyStr[2 * i], "%2hhx", &masterKey[i]) == 1, err = CHIP_ERROR_INVALID_ARGUMENT); sPairingDelegate.SetThreadCredential(channel, panId, masterKey); diff --git a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp index dd7a3f96d171f9..578248b3785e71 100644 --- a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp +++ b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.cpp @@ -32,12 +32,11 @@ void ScriptDevicePairingDelegate::SetWifiCredential(const char * ssid, const cha } void ScriptDevicePairingDelegate::SetThreadCredential(uint8_t channel, uint16_t panId, - uint8_t (&masterKey)[chip::DeviceLayer::Internal::kThreadMasterKeyLength]) + uint8_t (&masterKey)[chip::Thread::kSizeMasterKey]) { - mThreadInfo = {}; - mThreadInfo.ThreadChannel = channel; - mThreadInfo.ThreadPANId = panId; - memcpy(mThreadInfo.ThreadMasterKey, masterKey, sizeof(masterKey)); + mThreadInfo.SetChannel(channel); + mThreadInfo.SetPanId(panId); + mThreadInfo.SetMasterKey(masterKey); mMode = Mode::Thread; } @@ -46,7 +45,7 @@ void ScriptDevicePairingDelegate::OnNetworkCredentialsRequested(RendezvousDevice if (mMode == Mode::Wifi) callback->SendNetworkCredentials(mWifiSSID, mWifiPassword); else - callback->SendThreadCredentials(mThreadInfo); + callback->SendThreadCredentials(mThreadInfo.AsByteSpan()); } void ScriptDevicePairingDelegate::OnOperationalCredentialsRequested(const char * csr, size_t csr_length, diff --git a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h index 010d5a62f280b4..cca5365db99498 100644 --- a/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h +++ b/src/controller/python/ChipDeviceController-ScriptDevicePairingDelegate.h @@ -28,6 +28,7 @@ #include #include +#include #include namespace chip { @@ -42,8 +43,7 @@ class ScriptDevicePairingDelegate final : public Controller::DevicePairingDelega public: ~ScriptDevicePairingDelegate() = default; void SetWifiCredential(const char * ssid, const char * password); - void SetThreadCredential(uint8_t channel, uint16_t panId, - uint8_t (&masterKey)[chip::DeviceLayer::Internal::kThreadMasterKeyLength]); + void SetThreadCredential(uint8_t channel, uint16_t panId, uint8_t (&masterKey)[chip::Thread::kSizeMasterKey]); void SetKeyExchangeCallback(DevicePairingDelegate_OnPairingCompleteFunct callback); void OnNetworkCredentialsRequested(RendezvousDeviceCredentialsDelegate * callback) override; @@ -59,7 +59,7 @@ class ScriptDevicePairingDelegate final : public Controller::DevicePairingDelega char mWifiPassword[chip::DeviceLayer::Internal::kMaxWiFiKeyLength]; // Thread Provisioning Data - chip::DeviceLayer::Internal::DeviceNetworkInfo mThreadInfo = {}; + chip::Thread::OperationalDataset mThreadInfo = {}; enum class Mode { diff --git a/src/controller/python/chip-repl.py b/src/controller/python/chip-repl.py index 36d817416ee8bc..a9391e8d2ee7b2 100644 --- a/src/controller/python/chip-repl.py +++ b/src/controller/python/chip-repl.py @@ -69,22 +69,18 @@ def main(): # Thread data is an opaque blob, but it can be build with internal constructs # starting from a memset(0) equivalent -from chip.internal.thread import ThreadDeviceNetworkInfo +from chip.internal.thread import ThreadNetworkInfo -data = ThreadDeviceNetworkInfo.parse(b'\\x00'*ThreadDeviceNetworkInfo.sizeof()) -data.ThreadNetworkName = "OpenThread" -data.ThreadExtendedPANId = b"\\xde\\xad\\x00\\xbe\\xef\\x00\\xca\\xfe" -data.ThreadMasterKey = b"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xAA\\xBB\\xCC\\xDD\\xEE\\xFF" -data.ThreadPANId = 0xabcd -data.ThreadChannel = 15 -data.NetworkId = 0 - -data.FieldPresent.NetworkId = True -data.FieldPresent.ThreadExtendedPANId = True +data = ThreadNetworkInfo.parse(b'\\x00'*ThreadNetworkInfo.sizeof()) +data.NetworkName = "OpenThread" +data.ExtendedPANId = b"\\xde\\xad\\x00\\xbe\\xef\\x00\\xca\\xfe" +data.MasterKey = b"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xAA\\xBB\\xCC\\xDD\\xEE\\xFF" +data.PANId = 0xabcd +data.Channel = 15 if device.needsNetworkCredentials: - device.ConnectToThread(ThreadDeviceNetworkInfo.build(data)) + device.ConnectToThread(ThreadNetworkInfo.build(data)) '''.strip()) if __name__ == "__main__": diff --git a/src/controller/python/chip/internal/CommissionerImpl.cpp b/src/controller/python/chip/internal/CommissionerImpl.cpp index f789045f906455..6fa3e739fddf37 100644 --- a/src/controller/python/chip/internal/CommissionerImpl.cpp +++ b/src/controller/python/chip/internal/CommissionerImpl.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include "ChipThreadWork.h" @@ -125,7 +127,7 @@ class ScriptDevicePairingDelegate final : public chip::Controller::DevicePairing mCredentialsDelegate->SendNetworkCredentials(ssid, password); } - void SetThreadCredentials(const chip::DeviceLayer::Internal::DeviceNetworkInfo & threadData) + void SetThreadCredentials(chip::ByteSpan threadData) { if (mCredentialsDelegate == nullptr) { @@ -157,34 +159,47 @@ extern "C" void pychip_internal_PairingDelegate_SetWifiCredentials(const char * extern "C" CHIP_ERROR pychip_internal_PairingDelegate_SetThreadCredentials(const void * data, uint32_t length) { + chip::Thread::OperationalDataset dataset{}; + CHIP_ERROR err = CHIP_NO_ERROR; - // Openthread is OPAQUE by the spec, however current CHIP stack does not have any - // validation/support for opaque blobs. As a result, we try to do some - // pre-validation here + struct + { + uint64_t mActiveTimestamp; + uint8_t mMasterKey[chip::Thread::kSizeMasterKey]; + uint8_t mPSKc[chip::Thread::kSizePSKc]; + uint8_t mExtendedPanId[chip::Thread::kSizeExtendedPanId]; + uint8_t mMeshLocalPrefix[chip::Thread::kSizeMeshLocalPrefix]; + uint16_t mPanId; + char mNetworkName[chip::Thread::kSizeNetworkName + 1]; + uint8_t mChannel; + } netInfo; + + assert(length == sizeof(netInfo)); - // TODO: there should be uniform 'BLOBL' support within the thread stack - if (length != sizeof(chip::DeviceLayer::Internal::DeviceNetworkInfo)) + memcpy(&netInfo, data, length); + + if (netInfo.mNetworkName[0] != 0) { - ChipLogError(Controller, "Received invalid thread credential blob. Expected size %u and got %u bytes instead", - sizeof(chip::DeviceLayer::Internal::DeviceNetworkInfo), length); - return CHIP_ERROR_INVALID_ARGUMENT; + SuccessOrExit(err = dataset.SetNetworkName(netInfo.mNetworkName)); } - // unsure about alignment so copy into a properly aligned item - chip::DeviceLayer::Internal::DeviceNetworkInfo threadInfo; - memcpy(&threadInfo, data, sizeof(threadInfo)); + SuccessOrExit(err = dataset.SetExtendedPanId(netInfo.mExtendedPanId)); + SuccessOrExit(err = dataset.SetMeshLocalPrefix(netInfo.mMeshLocalPrefix)); + SuccessOrExit(err = dataset.SetMasterKey(netInfo.mMasterKey)); + SuccessOrExit(err = dataset.SetPSKc(netInfo.mPSKc)); + SuccessOrExit(err = dataset.SetPanId(netInfo.mPanId)); + SuccessOrExit(err = dataset.SetChannel(netInfo.mChannel)); + SuccessOrExit(err = dataset.SetActiveTimestamp(netInfo.mActiveTimestamp)); - // TODO: figure out a proper way to validate this or remove validation once - // thread credentials are assumed opaque throughout - if ((threadInfo.ThreadChannel != chip::DeviceLayer::Internal::kThreadChannel_NotSpecified) && - ((threadInfo.ThreadChannel < 11) || (threadInfo.ThreadChannel > 26))) + if (!dataset.IsCommissioned()) { - ChipLogError(Controller, "Failed to validate thread info: channel %d is not valid", threadInfo.ThreadChannel); + ChipLogError(Controller, "Invalid Thread operational dataset"); return CHIP_ERROR_INVALID_ARGUMENT; } - chip::python::ChipMainThreadScheduleAndWait([&]() { gPairingDelegate.SetThreadCredentials(threadInfo); }); + chip::python::ChipMainThreadScheduleAndWait([&]() { gPairingDelegate.SetThreadCredentials(dataset.AsByteSpan()); }); +exit: return CHIP_NO_ERROR; } diff --git a/src/controller/python/chip/internal/thread.py b/src/controller/python/chip/internal/thread.py index 968b6be8bac146..4e7d84657cf375 100644 --- a/src/controller/python/chip/internal/thread.py +++ b/src/controller/python/chip/internal/thread.py @@ -15,48 +15,19 @@ # # Contains type definition to help with thread credentials. -# Generally thread credentials are assumed to be binary objects, however for +# Generally thread credentials are assumed to be binary objects, however for # testing purposes, we expose the internal structure here. from construct import BitStruct, Byte, Bytes, Enum, Flag, Int16ul, Int32ul, Int64ul, PaddedString, Padding, Struct -ThreadDeviceNetworkInfo = Struct( - "NetworkId" / Int32ul, - "FieldPresent" / BitStruct ( - "NetworkId" / Flag, - "ThreadExtendedPANId" / Flag, - "ThreadMeshPrefix" / Flag, - "ThreadPSKc" / Flag, - "Padding" / Padding(4), - ), - "WiFiSSID" / PaddedString(33, 'utf8'), - "WiFikey" / Bytes(64), - "WiFiKeyLen" / Byte, - "WiFiAuthSecurityType" / Enum(Byte, - # NotAvailable is the same as None/NotSpecified in DeviceNetworkInfo.h - # Used this name because 'None' is reserved in python - NotAvailable = 1, - WEP = 2, - WPAPersonal = 3, - WPA2Personal = 4, - WPA2MixedPersonal = 5, - WPAEnterprise = 6, - WPA2Enterprise = 7, - WPA2MixedEnterprise = 8, - WPA3Personal = 9, - WPA3MixedPersonal = 10, - WPA3Enterprise = 11, - WPA3MixedEnterprise = 12, - ), - "ThreadNetworkName" / PaddedString(17, 'utf8'), - "ThreadExtendedPANId" / Bytes(8), - "ThreadMeshPrefix" / Bytes(8), - "ThreadMasterKey" / Bytes(16), - "ThreadPSKc" / Bytes(16), - "_ThreadPANIdPadding" / Padding(1), # Aligns ThreadPANId - "ThreadPANId" / Int16ul, - "ThreadChannel" / Byte, - "_ThreadDatasetTimestampPadding" / Padding(3), # Aligns ThreadDAtasetTimestamp - "ThreadDatasetTimestamp" / Int64ul, +ThreadNetworkInfo = Struct( + "ActiveTimestamp" / Int64ul, + "MasterKey" / Bytes(16), + "PSKc" / Bytes(16), + "ExtendedPanId" / Bytes(8), + "MeshPrefix" / Bytes(8), + "PanId" / Int16ul, + "NetworkName" / PaddedString(17, 'utf8'), + "Channel" / Byte, ) diff --git a/src/include/platform/ThreadStackManager.h b/src/include/platform/ThreadStackManager.h index 5453a38d0f0bbb..4508665da93d33 100644 --- a/src/include/platform/ThreadStackManager.h +++ b/src/include/platform/ThreadStackManager.h @@ -23,6 +23,8 @@ #pragma once +#include + namespace chip { namespace Mdns { @@ -36,7 +38,6 @@ class ThreadStackManagerImpl; class ConfigurationManagerImpl; namespace Internal { -class DeviceNetworkInfo; class DeviceControlServer; class BLEManagerImpl; template @@ -82,8 +83,7 @@ class ThreadStackManager CHIP_ERROR GetPollPeriod(uint32_t & buf); CHIP_ERROR JoinerStart(); - CHIP_ERROR SetThreadProvision(const Internal::DeviceNetworkInfo & netInfo); - CHIP_ERROR SetThreadProvision(const uint8_t * operationalDataset, size_t operationalDatasetLen); + CHIP_ERROR SetThreadProvision(ByteSpan aDataset); CHIP_ERROR SetThreadEnabled(bool val); #if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT @@ -122,7 +122,7 @@ class ThreadStackManager bool IsThreadEnabled(); bool IsThreadProvisioned(); bool IsThreadAttached(); - CHIP_ERROR GetThreadProvision(Internal::DeviceNetworkInfo & netInfo, bool includeCredentials); + CHIP_ERROR GetThreadProvision(ByteSpan & netInfo); void ErasePersistentInfo(); ConnectivityManager::ThreadDeviceType GetThreadDeviceType(); CHIP_ERROR SetThreadDeviceType(ConnectivityManager::ThreadDeviceType threadRole); @@ -264,21 +264,16 @@ inline bool ThreadStackManager::IsThreadAttached() return static_cast(this)->_IsThreadAttached(); } -inline CHIP_ERROR ThreadStackManager::GetThreadProvision(Internal::DeviceNetworkInfo & netInfo, bool includeCredentials) +inline CHIP_ERROR ThreadStackManager::GetThreadProvision(ByteSpan & netInfo) { - return static_cast(this)->_GetThreadProvision(netInfo, includeCredentials); + return static_cast(this)->_GetThreadProvision(netInfo); } -inline CHIP_ERROR ThreadStackManager::SetThreadProvision(const Internal::DeviceNetworkInfo & netInfo) +inline CHIP_ERROR ThreadStackManager::SetThreadProvision(ByteSpan netInfo) { return static_cast(this)->_SetThreadProvision(netInfo); } -inline CHIP_ERROR ThreadStackManager::SetThreadProvision(const uint8_t * operationalDataset, size_t operationalDatasetLen) -{ - return static_cast(this)->_SetThreadProvision(operationalDataset, operationalDatasetLen); -} - inline void ThreadStackManager::ErasePersistentInfo() { static_cast(this)->_ErasePersistentInfo(); diff --git a/src/include/platform/internal/DeviceNetworkInfo.h b/src/include/platform/internal/DeviceNetworkInfo.h index 2efaaa10a967c3..6f47c19d4d113f 100644 --- a/src/include/platform/internal/DeviceNetworkInfo.h +++ b/src/include/platform/internal/DeviceNetworkInfo.h @@ -33,15 +33,6 @@ namespace Internal { constexpr size_t kMaxWiFiSSIDLength = 32; constexpr size_t kMaxWiFiKeyLength = 64; -// ---- Thread-specific Limits ---- -constexpr size_t kMaxThreadNetworkNameLength = 16; -constexpr size_t kThreadExtendedPANIdLength = 8; -constexpr size_t kThreadMeshPrefixLength = 8; -constexpr size_t kThreadMasterKeyLength = 16; -constexpr size_t kThreadPSKcLength = 16; -constexpr size_t kThreadChannel_NotSpecified = UINT8_MAX; -constexpr size_t kThreadPANId_NotSpecified = UINT16_MAX; - /** * Ids for well-known network provision types. */ @@ -90,21 +81,6 @@ class DeviceNetworkInfo uint8_t WiFiKey[kMaxWiFiKeyLength]; /**< The WiFi key (NOT NULL-terminated). */ uint8_t WiFiKeyLen; /**< The length in bytes of the WiFi key. */ WiFiAuthSecurityType WiFiSecurityType; /**< The WiFi security type. */ - - // ---- Thread-specific Fields ---- - char ThreadNetworkName[kMaxThreadNetworkNameLength + 1]; - /**< The Thread network name as a NULL-terminated string. */ - uint8_t ThreadExtendedPANId[kThreadExtendedPANIdLength]; - /**< The Thread extended PAN ID. */ - uint8_t ThreadMeshPrefix[kThreadMeshPrefixLength]; - /**< The Thread mesh prefix. */ - uint8_t ThreadMasterKey[kThreadMasterKeyLength]; - /**< The Thread master key (NOT NULL-terminated). */ - uint8_t ThreadPSKc[kThreadPSKcLength]; - /**< The Thread pre-shared commissioner key (NOT NULL-terminated). */ - uint16_t ThreadPANId; /**< The 16-bit Thread PAN ID, or kThreadPANId_NotSpecified */ - uint8_t ThreadChannel; /**< The Thread channel (currently [11..26]), or kThreadChannel_NotSpecified */ - uint64_t ThreadDatasetTimestamp; /**< Thread active dataset timestamp */ }; } // namespace Internal diff --git a/src/include/platform/internal/DeviceNetworkProvisioning.h b/src/include/platform/internal/DeviceNetworkProvisioning.h index 57b2a3a6b12720..9c2039faae1f3d 100644 --- a/src/include/platform/internal/DeviceNetworkProvisioning.h +++ b/src/include/platform/internal/DeviceNetworkProvisioning.h @@ -47,7 +47,7 @@ class DLL_EXPORT DeviceNetworkProvisioningDelegate * Called to provision Thread credentials in a device * */ - virtual CHIP_ERROR ProvisionThread(DeviceLayer::Internal::DeviceNetworkInfo & threadData) = 0; + virtual CHIP_ERROR ProvisionThread(ByteSpan threadData) = 0; virtual ~DeviceNetworkProvisioningDelegate() {} }; diff --git a/src/include/platform/internal/GenericDeviceNetworkProvisioningDelegateImpl.h b/src/include/platform/internal/GenericDeviceNetworkProvisioningDelegateImpl.h index 22186e8503952f..66768752790653 100644 --- a/src/include/platform/internal/GenericDeviceNetworkProvisioningDelegateImpl.h +++ b/src/include/platform/internal/GenericDeviceNetworkProvisioningDelegateImpl.h @@ -32,7 +32,7 @@ class GenericDeviceNetworkProvisioningDelegateImpl : public DeviceNetworkProvisi { public: CHIP_ERROR ProvisionWiFi(const char * ssid, const char * passwd) override; - CHIP_ERROR ProvisionThread(DeviceLayer::Internal::DeviceNetworkInfo & threadData) override; + CHIP_ERROR ProvisionThread(ByteSpan threadData) override; private: ImplClass * Impl() { return static_cast(this); } @@ -45,8 +45,7 @@ inline CHIP_ERROR GenericDeviceNetworkProvisioningDelegateImpl::Provi } template -inline CHIP_ERROR -GenericDeviceNetworkProvisioningDelegateImpl::ProvisionThread(DeviceLayer::Internal::DeviceNetworkInfo & threadData) +inline CHIP_ERROR GenericDeviceNetworkProvisioningDelegateImpl::ProvisionThread(ByteSpan threadData) { return Impl()->_ProvisionThreadNetwork(threadData); } diff --git a/src/lib/support/BUILD.gn b/src/lib/support/BUILD.gn index d5d261200eddf4..987dccb2f78982 100644 --- a/src/lib/support/BUILD.gn +++ b/src/lib/support/BUILD.gn @@ -86,6 +86,8 @@ static_library("support") { "SafeInt.h", "SerializableIntegerSet.cpp", "SerializableIntegerSet.h", + "ThreadOperationalDataset.cpp", + "ThreadOperationalDataset.h", "TimeUtils.cpp", "TimeUtils.h", "UnitTestRegistration.cpp", diff --git a/src/lib/support/ThreadOperationalDataset.cpp b/src/lib/support/ThreadOperationalDataset.cpp new file mode 100644 index 00000000000000..2bc466407b2d8b --- /dev/null +++ b/src/lib/support/ThreadOperationalDataset.cpp @@ -0,0 +1,545 @@ +/* + * + * 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 + +namespace chip { +namespace Thread { + +/** + * Thread Operational Dataset TLV is defined in Thread Specification as the following format: + * + * +---------+---------+-------------------------+ + * | uint8_t | uint8_t | network byte order data | + * | 1 byte | 1 byte | n byte (0 <= n < 255) | + * +---------+---------+-------------------------+ + * | Type | Length | Value | + * +---------+---------+-------------------------+ + * + */ +class ThreadTLV final +{ + static constexpr uint8_t kLengthEscape = 0xff; ///< This length value indicates the actual length is of two-bytes length, which + ///< not allowed in Thread Operational Dataset TLVs. + +public: + enum : uint8_t + { + kChannel = 0, + kPanId = 1, + kExtendedPanId = 2, + kNetworkName = 3, + kPSKc = 4, + kMasterKey = 5, + kMeshLocalPrefix = 7, + kActiveTimestamp = 14, + }; + + uint8_t GetSize(void) const { return static_cast(sizeof(*this) + GetLength()); } + + uint8_t GetType(void) const { return mType; } + + void SetType(uint8_t aType) { mType = aType; } + + uint8_t GetLength(void) const + { + assert(mLength != kLengthEscape); + return mLength; + } + + void SetLength(uint8_t aLength) + { + assert(mLength != kLengthEscape); + mLength = aLength; + } + + const void * GetValue(void) const + { + assert(mLength != kLengthEscape); + + static_assert(sizeof(*this) == sizeof(ThreadTLV::mType) + sizeof(ThreadTLV::mLength), "Wrong size for ThreadTLV header"); + + return reinterpret_cast(this) + sizeof(*this); + } + + void * GetValue(void) { return const_cast(const_cast(this)->GetValue()); } + + void Get64(uint64_t & aValue) const + { + assert(GetLength() >= sizeof(aValue)); + + const uint8_t * p = reinterpret_cast(GetValue()); + aValue = // + (static_cast(p[0]) << 56) | // + (static_cast(p[1]) << 48) | // + (static_cast(p[2]) << 40) | // + (static_cast(p[3]) << 32) | // + (static_cast(p[4]) << 24) | // + (static_cast(p[5]) << 16) | // + (static_cast(p[6]) << 8) | // + (static_cast(p[7])); + } + + void Get16(uint16_t & aValue) const + { + assert(GetLength() >= sizeof(aValue)); + + const uint8_t * p = static_cast(GetValue()); + + aValue = static_cast(p[0] << 8 | p[1]); + } + + void Get8(uint8_t & aValue) const + { + assert(GetLength() >= sizeof(aValue)); + aValue = *static_cast(GetValue()); + } + + void Set64(uint64_t aValue) + { + uint8_t * value = static_cast(GetValue()); + + SetLength(sizeof(aValue)); + + value[0] = static_cast((aValue >> 56) & 0xff); + value[1] = static_cast((aValue >> 48) & 0xff); + value[2] = static_cast((aValue >> 40) & 0xff); + value[3] = static_cast((aValue >> 32) & 0xff); + value[4] = static_cast((aValue >> 24) & 0xff); + value[5] = static_cast((aValue >> 16) & 0xff); + value[6] = static_cast((aValue >> 8) & 0xff); + value[7] = static_cast(aValue & 0xff); + } + + void Set16(uint16_t aValue) + { + uint8_t * value = static_cast(GetValue()); + + SetLength(sizeof(aValue)); + + value[0] = static_cast(aValue >> 8); + value[1] = static_cast(aValue & 0xff); + } + + void Set8(uint8_t aValue) + { + SetLength(sizeof(aValue)); + *static_cast(GetValue()) = aValue; + } + + void Set8(int8_t aValue) + { + SetLength(sizeof(aValue)); + *static_cast(GetValue()) = aValue; + } + + void SetValue(const void * aValue, uint8_t aLength) + { + SetLength(aLength); + memcpy(GetValue(), aValue, aLength); + } + + const ThreadTLV * GetNext(void) const + { + static_assert(alignof(ThreadTLV) == 1, "Wrong alignment for ThreadTLV header"); + return reinterpret_cast(static_cast(GetValue()) + GetLength()); + } + + ThreadTLV * GetNext(void) { return reinterpret_cast(static_cast(GetValue()) + GetLength()); } + + static bool IsValid(ByteSpan aData) + { + const uint8_t * const end = aData.data() + aData.size(); + const uint8_t * curr = aData.data(); + + while (curr + sizeof(ThreadTLV) < end) + { + const ThreadTLV * tlv = reinterpret_cast(curr); + + if (tlv->GetLength() == kLengthEscape) + { + break; + } + + curr = reinterpret_cast(tlv->GetNext()); + } + + return curr == end; + } + +private: + uint8_t mType; + uint8_t mLength; +}; + +bool OperationalDataset::IsValid(ByteSpan aData) +{ + return ThreadTLV::IsValid(aData); +} + +CHIP_ERROR OperationalDataset::Init(ByteSpan aData) +{ + if (aData.size() > sizeof(mData)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + if (aData.size() > 0) + { + if (!ThreadTLV::IsValid(aData)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + memcpy(mData, aData.data(), aData.size()); + } + + mLength = static_cast(aData.size()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR OperationalDataset::GetActiveTimestamp(uint64_t & aActiveTimestamp) const +{ + const ThreadTLV * tlv = Locate(ThreadTLV::kActiveTimestamp); + + if (tlv != nullptr) + { + tlv->Get64(aActiveTimestamp); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_TLV_TAG_NOT_FOUND; +} + +CHIP_ERROR OperationalDataset::SetActiveTimestamp(uint64_t aActiveTimestamp) +{ + ThreadTLV * tlv = MakeRoom(ThreadTLV::kActiveTimestamp, sizeof(*tlv) + sizeof(aActiveTimestamp)); + + if (tlv == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + + tlv->Set64(aActiveTimestamp); + + mLength = static_cast(mLength + tlv->GetSize()); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OperationalDataset::GetChannel(uint16_t & aChannel) const +{ + const ThreadTLV * tlv = Locate(ThreadTLV::kChannel); + + if (tlv != nullptr) + { + const uint8_t * value = reinterpret_cast(tlv->GetValue()); + aChannel = static_cast((value[1] << 8) | value[2]); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_TLV_TAG_NOT_FOUND; +} + +CHIP_ERROR OperationalDataset::SetChannel(uint16_t aChannel) +{ + uint8_t value[] = { 0, static_cast(aChannel >> 8), static_cast(aChannel & 0xff) }; + ThreadTLV * tlv = MakeRoom(ThreadTLV::kChannel, sizeof(*tlv) + sizeof(value)); + + if (tlv == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + + tlv->SetValue(value, sizeof(value)); + + mLength = static_cast(mLength + tlv->GetSize()); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OperationalDataset::GetExtendedPanId(uint8_t (&aExtendedPanId)[kSizeExtendedPanId]) const +{ + const ThreadTLV * tlv = Locate(ThreadTLV::kExtendedPanId); + + if (tlv != nullptr) + { + memcpy(aExtendedPanId, tlv->GetValue(), sizeof(aExtendedPanId)); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_TLV_TAG_NOT_FOUND; +} + +CHIP_ERROR OperationalDataset::SetExtendedPanId(const uint8_t (&aExtendedPanId)[kSizeExtendedPanId]) +{ + ThreadTLV * tlv = MakeRoom(ThreadTLV::kExtendedPanId, sizeof(*tlv) + sizeof(aExtendedPanId)); + + if (tlv == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + + tlv->SetValue(aExtendedPanId, sizeof(aExtendedPanId)); + + assert(mLength + tlv->GetSize() < sizeof(mData)); + + mLength = static_cast(mLength + tlv->GetSize()); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OperationalDataset::GetMasterKey(uint8_t (&aMasterKey)[kSizeMasterKey]) const +{ + const ThreadTLV * tlv = Locate(ThreadTLV::kMasterKey); + + if (tlv != nullptr) + { + memcpy(aMasterKey, tlv->GetValue(), sizeof(aMasterKey)); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_TLV_TAG_NOT_FOUND; +} + +CHIP_ERROR OperationalDataset::SetMasterKey(const uint8_t (&aMasterKey)[kSizeMasterKey]) +{ + ThreadTLV * tlv = MakeRoom(ThreadTLV::kMasterKey, sizeof(*tlv) + sizeof(aMasterKey)); + + if (tlv == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + + tlv->SetValue(aMasterKey, sizeof(aMasterKey)); + + assert(mLength + tlv->GetSize() < sizeof(mData)); + + mLength = static_cast(mLength + tlv->GetSize()); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OperationalDataset::GetMeshLocalPrefix(uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]) const +{ + const ThreadTLV * tlv = Locate(ThreadTLV::kMeshLocalPrefix); + + if (tlv != nullptr) + { + memcpy(aMeshLocalPrefix, tlv->GetValue(), sizeof(aMeshLocalPrefix)); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_TLV_TAG_NOT_FOUND; +} + +CHIP_ERROR OperationalDataset::SetMeshLocalPrefix(const uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]) +{ + ThreadTLV * tlv = MakeRoom(ThreadTLV::kMeshLocalPrefix, sizeof(*tlv) + sizeof(aMeshLocalPrefix)); + + if (tlv == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + + tlv->SetValue(aMeshLocalPrefix, sizeof(aMeshLocalPrefix)); + + mLength = static_cast(mLength + tlv->GetSize()); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OperationalDataset::GetNetworkName(char (&aNetworkName)[kSizeNetworkName + 1]) const +{ + const ThreadTLV * tlv = Locate(ThreadTLV::kNetworkName); + + if (tlv != nullptr) + { + memcpy(aNetworkName, tlv->GetValue(), tlv->GetLength()); + aNetworkName[tlv->GetLength()] = '\0'; + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_TLV_TAG_NOT_FOUND; +} + +CHIP_ERROR OperationalDataset::SetNetworkName(const char * aNetworkName) +{ + size_t len = strlen(aNetworkName); + + if (len > kSizeNetworkName || len == 0) + { + return CHIP_ERROR_INVALID_STRING_LENGTH; + } + + ThreadTLV * tlv = MakeRoom(ThreadTLV::kNetworkName, static_cast(sizeof(*tlv) + static_cast(len))); + + if (tlv == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + + tlv->SetValue(aNetworkName, static_cast(len)); + + mLength = static_cast(mLength + tlv->GetSize()); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OperationalDataset::GetPanId(uint16_t & aPanId) const +{ + const ThreadTLV * tlv = Locate(ThreadTLV::kPanId); + + if (tlv != nullptr) + { + tlv->Get16(aPanId); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_TLV_TAG_NOT_FOUND; +} + +CHIP_ERROR OperationalDataset::SetPanId(uint16_t aPanId) +{ + ThreadTLV * tlv = MakeRoom(ThreadTLV::kPanId, sizeof(*tlv) + sizeof(aPanId)); + + if (tlv == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + + tlv->Set16(aPanId); + + mLength = static_cast(mLength + tlv->GetSize()); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OperationalDataset::GetPSKc(uint8_t (&aPSKc)[kSizePSKc]) const +{ + const ThreadTLV * tlv = Locate(ThreadTLV::kPSKc); + + if (tlv != nullptr) + { + memcpy(aPSKc, tlv->GetValue(), sizeof(aPSKc)); + return CHIP_NO_ERROR; + } + + return CHIP_ERROR_TLV_TAG_NOT_FOUND; +} + +CHIP_ERROR OperationalDataset::SetPSKc(const uint8_t (&aPSKc)[kSizePSKc]) +{ + ThreadTLV * tlv = MakeRoom(ThreadTLV::kPSKc, sizeof(*tlv) + sizeof(aPSKc)); + + if (tlv == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + + tlv->SetValue(aPSKc, sizeof(aPSKc)); + + mLength = static_cast(mLength + tlv->GetSize()); + + return CHIP_NO_ERROR; +} + +void OperationalDataset::UnsetMasterKey(void) +{ + Remove(ThreadTLV::kMasterKey); +} + +void OperationalDataset::UnsetPSKc(void) +{ + Remove(ThreadTLV::kPSKc); +} + +bool OperationalDataset::IsCommissioned(void) const +{ + return Has(ThreadTLV::kNetworkName) && Has(ThreadTLV::kPanId) && Has(ThreadTLV::kMasterKey) && Has(ThreadTLV::kExtendedPanId) && + Has(ThreadTLV::kChannel); +} + +const ThreadTLV * OperationalDataset::Locate(uint8_t aType) const +{ + const ThreadTLV * tlv = &Begin(); + const ThreadTLV * end = &End(); + + while (tlv < end) + { + if (tlv->GetType() == aType) + break; + else + tlv = tlv->GetNext(); + } + + assert(tlv < reinterpret_cast(&mData[sizeof(mData)])); + + return tlv != end ? tlv : nullptr; +} + +void OperationalDataset::Remove(ThreadTLV & aThreadTLV) +{ + uint8_t offset = static_cast(reinterpret_cast(&aThreadTLV) - mData); + + if (offset < mLength && mLength >= (offset + aThreadTLV.GetSize())) + { + mLength = static_cast(mLength - aThreadTLV.GetSize()); + memmove(&aThreadTLV, aThreadTLV.GetNext(), mLength - offset); + } +} + +void OperationalDataset::Remove(uint8_t aType) +{ + ThreadTLV * tlv = Locate(aType); + + if (tlv != nullptr) + { + Remove(*tlv); + } +} + +ThreadTLV * OperationalDataset::MakeRoom(uint8_t aType, uint8_t aSize) +{ + ThreadTLV * tlv = Locate(aType); + + size_t freeSpace = sizeof(mData) - mLength; + + if (tlv != nullptr) + { + if (freeSpace + tlv->GetSize() < aSize) + { + return nullptr; + } + + Remove(*tlv); + } + else if (freeSpace < aSize) + { + return nullptr; + } + + End().SetType(aType); + + return &End(); +} + +} // namespace Thread +} // namespace chip diff --git a/src/lib/support/ThreadOperationalDataset.h b/src/lib/support/ThreadOperationalDataset.h new file mode 100644 index 00000000000000..ab6944a9da379c --- /dev/null +++ b/src/lib/support/ThreadOperationalDataset.h @@ -0,0 +1,291 @@ +/* + * + * 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 + +#include +#include +#include + +namespace chip { +namespace Thread { + +class ThreadTLV; + +constexpr size_t kChannel_NotSpecified = UINT8_MAX; +constexpr size_t kPANId_NotSpecified = UINT16_MAX; + +constexpr size_t kSizeOperationalDataset = 254; + +constexpr size_t kSizeNetworkName = 16; +constexpr size_t kSizeExtendedPanId = 8; +constexpr size_t kSizeMasterKey = 16; +constexpr size_t kSizeMeshLocalPrefix = 8; +constexpr size_t kSizePSKc = 16; + +/** + * This class provides methods to manipulate Thread operational dataset. + * + */ +class OperationalDataset +{ +public: + /** + * This method initializes the dataset with the given dataset. + * + * @param[in] aData Thread Operational dataset in octects. + * + * @retval CHIP_NO_ERROR Successfully initialized the dataset. + * @retval CHIP_ERROR_INVALID_ARGUMENT The dataset length @p aLength is too long or @p data is corrupted. + * + */ + CHIP_ERROR Init(ByteSpan aData); + + /** + * This method retrieves Thread active timestamp from the dataset. + * + * @param[out] aActiveTimestamp A reference to receive the active timestamp. + * + * @retval CHIP_NO_ERROR Successfully retrieved the active timestamp. + * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread active timestamp is not present in the dataset. + * + */ + CHIP_ERROR GetActiveTimestamp(uint64_t & aActiveTimestamp) const; + + /** + * This method sets Thread active timestamp to the dataset. + * + * @param[in] aActiveTimestamp The Thread active timestamp. + * + * @retval CHIP_NO_ERROR Successfully set the active timestamp. + * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread active timestamp. + * + */ + CHIP_ERROR SetActiveTimestamp(uint64_t aActiveTimestamp); + + /** + * This method retrieves Thread channel from the dataset. + * + * @param[out] aChannel A reference to receive the channel. + * + * @retval CHIP_NO_ERROR Successfully retrieved the channel. + * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread channel is not present in the dataset. + * + */ + CHIP_ERROR GetChannel(uint16_t & aChannel) const; + + /** + * This method sets Thread channel to the dataset. + * + * @param[in] aChannel The Thread channel. + * + * @retval CHIP_NO_ERROR Successfully set the channel. + * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread channel. + * + */ + CHIP_ERROR SetChannel(uint16_t aChannel); + + /** + * This method retrieves Thread extended PAN ID from the dataset. + * + * @param[out] aExtendedPanId A reference to receive the extended PAN ID. + * + * @retval CHIP_NO_ERROR Successfully retrieved the extended PAN ID. + * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread extended PAN ID is not present in the dataset. + * + */ + CHIP_ERROR GetExtendedPanId(uint8_t (&aExtendedPanId)[kSizeExtendedPanId]) const; + + /** + * This method sets Thread extended PAN ID to the dataset. + * + * @param[in] aExtendedPanId The Thread extended PAN ID. + * + * @retval CHIP_NO_ERROR Successfully set the extended PAN ID. + * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread extended PAN ID. + * + */ + CHIP_ERROR SetExtendedPanId(const uint8_t (&aExtendedPanId)[kSizeExtendedPanId]); + + /** + * This method retrieves Thread master key from the dataset. + * + * @param[out] aMasterKey A reference to receive the master key. + * + * @retval CHIP_NO_ERROR Successfully retrieved the master key. + * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread master key is not present in the dataset. + * + */ + CHIP_ERROR GetMasterKey(uint8_t (&aMasterKey)[kSizeMasterKey]) const; + + /** + * This method sets Thread master key to the dataset. + * + * @param[in] aMasterKey The Thread master key. + * + * @retval CHIP_NO_ERROR Successfully set the master key. + * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread master key. + * + */ + CHIP_ERROR SetMasterKey(const uint8_t (&aMasterKey)[kSizeMasterKey]); + + /** + * This method unsets Thread master key to the dataset. + * + */ + void UnsetMasterKey(void); + + /** + * This method retrieves Thread mesh local prefix from the dataset. + * + * @param[out] aMeshLocalPrefix A reference to receive the mesh local prefix. + * + * @retval CHIP_NO_ERROR Successfully retrieved the mesh local prefix. + * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread mesh local prefix is not present in the dataset. + * + */ + CHIP_ERROR GetMeshLocalPrefix(uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]) const; + + /** + * This method sets Thread mesh local prefix to the dataset. + * + * @param[in] aMeshLocalPrefix The Thread mesh local prefix. + * + * @retval CHIP_NO_ERROR Successfully set the Thread mesh local prefix. + * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread mesh local prefix. + * + */ + CHIP_ERROR SetMeshLocalPrefix(const uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]); + + /** + * This method retrieves Thread network name from the dataset. + * + * @param[out] aNetworkName A reference to receive the Thread network name. + * + * @retval CHIP_NO_ERROR Successfully retrieved the network name. + * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread network name is not present in the dataset. + * + */ + CHIP_ERROR GetNetworkName(char (&aNetworkName)[kSizeNetworkName + 1]) const; + + /** + * This method sets Thread network name to the dataset. + * + * @param[in] aNetworkName The Thread network name. + * + * @retval CHIP_NO_ERROR Successfully set the network name. + * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread network name. + * + */ + CHIP_ERROR SetNetworkName(const char * aNetworkName); + + /** + * This method retrieves Thread PAN ID from the dataset. + * + * @param[out] aPanId A reference to receive the PAN ID. + * + * @retval CHIP_NO_ERROR Successfully retrieved the PAN ID. + * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread PAN ID is not present in the dataset. + * + */ + CHIP_ERROR GetPanId(uint16_t & aPanId) const; + + /** + * This method sets Thread PAN ID to the dataset. + * + * @param[in] aPanId The Thread PAN ID. + * + * @retval CHIP_NO_ERROR Successfully set the PAN ID. + * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread PAN ID. + * + */ + CHIP_ERROR SetPanId(uint16_t aPanId); + + /** + * This method retrieves Thread PSKc from the dataset. + * + * @param[out] aPSKc A reference to receive the PSKc. + * + * @retval CHIP_NO_ERROR Successfully retrieved the PSKc. + * @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread PSKc is not present in the dataset. + * + */ + CHIP_ERROR GetPSKc(uint8_t (&aPSKc)[kSizePSKc]) const; + + /** + * This method sets Thread PSKc to the dataset. + * + * @param[in] aPSKc The Thread PSKc. + * + * @retval CHIP_NO_ERROR Successfully set the PSKc. + * @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread PSKc. + * + */ + CHIP_ERROR SetPSKc(const uint8_t (&aPSKc)[kSizePSKc]); + + /** + * This method unsets Thread PSKc to the dataset. + * + */ + void UnsetPSKc(void); + + /** + * This method clears all data stored in the dataset. + */ + void Clear(void) { mLength = 0; } + + /** + * This method checks if the dataset is ready for creating Thread network. + * + */ + bool IsCommissioned(void) const; + + /** + * This method checks whether @p aData is formatted as ThreadTLVs. + * + * @note This method doesn't verify ThreadTLV values are valid. + * + */ + static bool IsValid(ByteSpan aData); + + ByteSpan AsByteSpan(void) const { return ByteSpan(mData, mLength); } + +private: + ThreadTLV * Locate(uint8_t aType) + { + return const_cast(const_cast(this)->Locate(aType)); + } + const ThreadTLV * Locate(uint8_t aType) const; + const ThreadTLV & Begin(void) const { return *reinterpret_cast(&mData[0]); }; + ThreadTLV & Begin(void) { return const_cast(const_cast(this)->Begin()); } + const ThreadTLV & End(void) const { return *reinterpret_cast(&mData[mLength]); }; + ThreadTLV & End(void) { return const_cast(const_cast(this)->End()); } + void Remove(uint8_t aType); + void Remove(ThreadTLV & aTlv); + ThreadTLV * MakeRoom(uint8_t aType, uint8_t aSize); + bool Has(uint8_t aType) const { return Locate(aType) != nullptr; } + + uint8_t mData[kSizeOperationalDataset]; + uint8_t mLength; +}; + +} // namespace Thread +}; // namespace chip diff --git a/src/lib/support/tests/BUILD.gn b/src/lib/support/tests/BUILD.gn index 1ffeeb0c1c8a13..5d1e4e4a9c37f7 100644 --- a/src/lib/support/tests/BUILD.gn +++ b/src/lib/support/tests/BUILD.gn @@ -38,6 +38,7 @@ chip_test_suite("tests") { "TestSerializableIntegerSet.cpp", "TestSpan.cpp", "TestStringBuilder.cpp", + "TestThreadOperationalDataset.cpp", "TestTimeUtils.cpp", ] sources = [] diff --git a/src/lib/support/tests/TestThreadOperationalDataset.cpp b/src/lib/support/tests/TestThreadOperationalDataset.cpp new file mode 100644 index 00000000000000..adf039b2e1c702 --- /dev/null +++ b/src/lib/support/tests/TestThreadOperationalDataset.cpp @@ -0,0 +1,294 @@ +/* + * + * 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 + +namespace { + +using namespace chip; + +void TestInit(nlTestSuite * inSuite, void * inContext) +{ + Thread::OperationalDataset & dataset = *static_cast(inContext); + + NL_TEST_ASSERT(inSuite, dataset.Init(ByteSpan(nullptr, 255)) == CHIP_ERROR_INVALID_ARGUMENT); + NL_TEST_ASSERT(inSuite, dataset.Init(ByteSpan(nullptr, 0)) == CHIP_NO_ERROR); + + { + uint8_t data[] = { 0x01, 0x02, 0x03 }; + + NL_TEST_ASSERT(inSuite, dataset.Init(ByteSpan(data)) == CHIP_ERROR_INVALID_ARGUMENT); + } + + { + uint8_t data[] = { 0x01 }; + + NL_TEST_ASSERT(inSuite, dataset.Init(ByteSpan(data)) == CHIP_ERROR_INVALID_ARGUMENT); + } +} + +void TestActiveTimestamp(nlTestSuite * inSuite, void * inContext) +{ + static constexpr uint64_t kActiveTimestampValue = 1; + + Thread::OperationalDataset & dataset = *static_cast(inContext); + + uint64_t activeTimestamp = 0; + + NL_TEST_ASSERT(inSuite, dataset.SetActiveTimestamp(kActiveTimestampValue) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, dataset.GetActiveTimestamp(activeTimestamp) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, activeTimestamp == kActiveTimestampValue); +} + +void TestChannel(nlTestSuite * inSuite, void * inContext) +{ + static constexpr uint16_t kChannelValue = 15; + + Thread::OperationalDataset & dataset = *static_cast(inContext); + + uint16_t channel = 0; + + NL_TEST_ASSERT(inSuite, dataset.SetChannel(kChannelValue) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, dataset.GetChannel(channel) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, channel == kChannelValue); +} + +void TestExtendedPanId(nlTestSuite * inSuite, void * inContext) +{ + static constexpr uint8_t kExtendedPanId[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + + Thread::OperationalDataset & dataset = *static_cast(inContext); + + uint8_t extendedPanId[Thread::kSizeExtendedPanId] = { 0 }; + + NL_TEST_ASSERT(inSuite, dataset.SetExtendedPanId(kExtendedPanId) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, dataset.GetExtendedPanId(extendedPanId) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, memcmp(extendedPanId, kExtendedPanId, sizeof(kExtendedPanId)) == 0); +} + +void TestMasterKey(nlTestSuite * inSuite, void * inContext) +{ + static constexpr uint8_t kMasterKey[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; + + Thread::OperationalDataset & dataset = *static_cast(inContext); + + uint8_t masterKey[Thread::kSizeMasterKey] = { 0 }; + + NL_TEST_ASSERT(inSuite, dataset.SetMasterKey(kMasterKey) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, dataset.GetMasterKey(masterKey) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, memcmp(masterKey, kMasterKey, sizeof(kMasterKey)) == 0); +} + +void TestMeshLocalPrefix(nlTestSuite * inSuite, void * inContext) +{ + static constexpr uint8_t kMeshLocalPrefix[] = { 0xfd, 0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0x00 }; + + Thread::OperationalDataset & dataset = *static_cast(inContext); + + uint8_t meshLocalPrefix[Thread::kSizeMeshLocalPrefix] = { 0 }; + + NL_TEST_ASSERT(inSuite, dataset.SetMeshLocalPrefix(kMeshLocalPrefix) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, dataset.GetMeshLocalPrefix(meshLocalPrefix) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, memcmp(meshLocalPrefix, kMeshLocalPrefix, sizeof(kMeshLocalPrefix)) == 0); +} + +void TestNetworkName(nlTestSuite * inSuite, void * inContext) +{ + static constexpr char kNetworkName[] = "ThreadNetwork"; + + Thread::OperationalDataset & dataset = *static_cast(inContext); + + char networkName[Thread::kSizeNetworkName + 1] = { 0 }; + + NL_TEST_ASSERT(inSuite, dataset.SetNetworkName(kNetworkName) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, dataset.GetNetworkName(networkName) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, strcmp(networkName, kNetworkName) == 0); + + NL_TEST_ASSERT(inSuite, dataset.SetNetworkName("0123456789abcdef") == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, dataset.SetNetworkName("0123456789abcdefg") == CHIP_ERROR_INVALID_STRING_LENGTH); + NL_TEST_ASSERT(inSuite, dataset.SetNetworkName("") == CHIP_ERROR_INVALID_STRING_LENGTH); +} + +void TestPanId(nlTestSuite * inSuite, void * inContext) +{ + static constexpr uint16_t kPanIdValue = 0x1234; + + Thread::OperationalDataset & dataset = *static_cast(inContext); + + uint16_t panid = 0; + + NL_TEST_ASSERT(inSuite, dataset.SetPanId(kPanIdValue) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, dataset.GetPanId(panid) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, panid == kPanIdValue); +} + +void TestPSKc(nlTestSuite * inSuite, void * inContext) +{ + static constexpr uint8_t kPSKc[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; + + Thread::OperationalDataset & dataset = *static_cast(inContext); + + uint8_t pskc[Thread::kSizePSKc] = { 0 }; + + NL_TEST_ASSERT(inSuite, dataset.SetPSKc(kPSKc) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, dataset.GetPSKc(pskc) == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, memcmp(pskc, kPSKc, sizeof(kPSKc)) == 0); +} + +void TestUnsetMasterKey(nlTestSuite * inSuite, void * inContext) +{ + Thread::OperationalDataset & dataset = *static_cast(inContext); + + uint8_t masterKey[Thread::kSizeMasterKey] = { 0 }; + + NL_TEST_ASSERT(inSuite, dataset.GetMasterKey(masterKey) == CHIP_NO_ERROR); + dataset.UnsetMasterKey(); + NL_TEST_ASSERT(inSuite, dataset.GetMasterKey(masterKey) == CHIP_ERROR_TLV_TAG_NOT_FOUND); + NL_TEST_ASSERT(inSuite, dataset.SetMasterKey(masterKey) == CHIP_NO_ERROR); +} + +void TestUnsetPSKc(nlTestSuite * inSuite, void * inContext) +{ + Thread::OperationalDataset & dataset = *static_cast(inContext); + + uint8_t pskc[Thread::kSizePSKc] = { 0 }; + + NL_TEST_ASSERT(inSuite, dataset.GetPSKc(pskc) == CHIP_NO_ERROR); + dataset.UnsetPSKc(); + NL_TEST_ASSERT(inSuite, dataset.GetPSKc(pskc) == CHIP_ERROR_TLV_TAG_NOT_FOUND); + NL_TEST_ASSERT(inSuite, dataset.SetPSKc(pskc) == CHIP_NO_ERROR); +} + +void TestClear(nlTestSuite * inSuite, void * inContext) +{ + Thread::OperationalDataset & dataset = *static_cast(inContext); + + { + uint64_t activeTimestamp; + NL_TEST_ASSERT(inSuite, dataset.GetActiveTimestamp(activeTimestamp) == CHIP_NO_ERROR); + } + + { + uint16_t channel; + NL_TEST_ASSERT(inSuite, dataset.GetChannel(channel) == CHIP_NO_ERROR); + } + + { + uint8_t extendedPanId[Thread::kSizeExtendedPanId] = { 0 }; + NL_TEST_ASSERT(inSuite, dataset.GetExtendedPanId(extendedPanId) == CHIP_NO_ERROR); + } + + { + uint8_t masterKey[Thread::kSizeMasterKey] = { 0 }; + NL_TEST_ASSERT(inSuite, dataset.GetMasterKey(masterKey) == CHIP_NO_ERROR); + } + + { + uint8_t meshLocalPrefix[Thread::kSizeMeshLocalPrefix] = { 0 }; + NL_TEST_ASSERT(inSuite, dataset.GetMeshLocalPrefix(meshLocalPrefix) == CHIP_NO_ERROR); + } + + { + char networkName[Thread::kSizeNetworkName + 1] = { 0 }; + NL_TEST_ASSERT(inSuite, dataset.GetNetworkName(networkName) == CHIP_NO_ERROR); + } + + { + uint16_t panid; + NL_TEST_ASSERT(inSuite, dataset.GetPanId(panid) == CHIP_NO_ERROR); + } + + { + uint8_t pskc[Thread::kSizePSKc] = { 0 }; + NL_TEST_ASSERT(inSuite, dataset.GetPSKc(pskc) == CHIP_NO_ERROR); + } + + dataset.Clear(); + + { + uint64_t activeTimestamp; + NL_TEST_ASSERT(inSuite, dataset.GetActiveTimestamp(activeTimestamp) == CHIP_ERROR_TLV_TAG_NOT_FOUND); + } + + { + uint16_t channel; + NL_TEST_ASSERT(inSuite, dataset.GetChannel(channel) == CHIP_ERROR_TLV_TAG_NOT_FOUND); + } + + { + uint8_t extendedPanId[Thread::kSizeExtendedPanId] = { 0 }; + NL_TEST_ASSERT(inSuite, dataset.GetExtendedPanId(extendedPanId) == CHIP_ERROR_TLV_TAG_NOT_FOUND); + } + + { + uint8_t masterKey[Thread::kSizeMasterKey] = { 0 }; + NL_TEST_ASSERT(inSuite, dataset.GetMasterKey(masterKey) == CHIP_ERROR_TLV_TAG_NOT_FOUND); + } + + { + uint8_t meshLocalPrefix[Thread::kSizeMeshLocalPrefix] = { 0 }; + NL_TEST_ASSERT(inSuite, dataset.GetMeshLocalPrefix(meshLocalPrefix) == CHIP_ERROR_TLV_TAG_NOT_FOUND); + } + + { + char networkName[Thread::kSizeNetworkName + 1] = { 0 }; + NL_TEST_ASSERT(inSuite, dataset.GetNetworkName(networkName) == CHIP_ERROR_TLV_TAG_NOT_FOUND); + } + + { + uint16_t panid; + NL_TEST_ASSERT(inSuite, dataset.GetPanId(panid) == CHIP_ERROR_TLV_TAG_NOT_FOUND); + } + + { + uint8_t pskc[Thread::kSizePSKc] = { 0 }; + NL_TEST_ASSERT(inSuite, dataset.GetPSKc(pskc) == CHIP_ERROR_TLV_TAG_NOT_FOUND); + } +} + +const nlTest sTests[] = { + NL_TEST_DEF("TestInit", TestInit), // + NL_TEST_DEF("TestActiveTimestamp", TestActiveTimestamp), // + NL_TEST_DEF("TestChannel", TestChannel), // + NL_TEST_DEF("TestExtendedPanId", TestExtendedPanId), // + NL_TEST_DEF("TestMasterKey", TestMasterKey), // + NL_TEST_DEF("TestMeshLocalPrefix", TestMeshLocalPrefix), // + NL_TEST_DEF("TestNetworkName", TestNetworkName), // + NL_TEST_DEF("TestPanId", TestPanId), // + NL_TEST_DEF("TestPSKc", TestPSKc), // + NL_TEST_DEF("TestUnsetMasterKey", TestUnsetMasterKey), // + NL_TEST_DEF("TestUnsetPSKc", TestUnsetPSKc), // + NL_TEST_DEF("TestClear", TestClear), // + NL_TEST_SENTINEL() // +}; + +} // namespace + +int TestThreadOperationalDatasetBuilder(void) +{ + nlTestSuite theSuite = { "ThreadOperationalDataset", sTests, nullptr, nullptr }; + Thread::OperationalDataset dataset{}; + + nlTestRunner(&theSuite, &dataset); + return nlTestRunnerStats(&theSuite); +} + +CHIP_REGISTER_TEST_SUITE(TestThreadOperationalDatasetBuilder) diff --git a/src/platform/Darwin/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/Darwin/DeviceNetworkProvisioningDelegateImpl.h index e3ba66ca9db3f4..872c3f9c59469d 100644 --- a/src/platform/Darwin/DeviceNetworkProvisioningDelegateImpl.h +++ b/src/platform/Darwin/DeviceNetworkProvisioningDelegateImpl.h @@ -36,7 +36,7 @@ class DeviceNetworkProvisioningDelegateImpl final private: CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd) { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) { return CHIP_ERROR_NOT_IMPLEMENTED; } + CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData) { return CHIP_ERROR_NOT_IMPLEMENTED; } }; } // namespace DeviceLayer diff --git a/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.cpp b/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.cpp index 4a756405871e6b..0f87641906c80b 100644 --- a/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.cpp +++ b/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.cpp @@ -24,7 +24,8 @@ namespace chip { namespace DeviceLayer { -CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) +CHIP_ERROR +DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(ByteSpan threadData) { #if CHIP_ENABLE_OPENTHREAD CHIP_ERROR error = CHIP_NO_ERROR; diff --git a/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.h index 05a642417934d4..e799358e4b7536 100644 --- a/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.h +++ b/src/platform/EFR32/DeviceNetworkProvisioningDelegateImpl.h @@ -36,7 +36,7 @@ class DeviceNetworkProvisioningDelegateImpl final private: CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd) { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData); + CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData); }; } // namespace DeviceLayer diff --git a/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.h index 618ddd47ccb8ea..6e89a78e2110b2 100644 --- a/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.h +++ b/src/platform/ESP32/DeviceNetworkProvisioningDelegateImpl.h @@ -36,7 +36,7 @@ class DeviceNetworkProvisioningDelegateImpl final friend class GenericDeviceNetworkProvisioningDelegateImpl; CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd); - CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) { return CHIP_ERROR_NOT_IMPLEMENTED; } + CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData) { return CHIP_ERROR_NOT_IMPLEMENTED; } }; } // namespace DeviceLayer diff --git a/src/platform/K32W/DeviceNetworkProvisioningDelegateImpl.cpp b/src/platform/K32W/DeviceNetworkProvisioningDelegateImpl.cpp index 060c09ef1a1da6..2915e85c40bbcb 100644 --- a/src/platform/K32W/DeviceNetworkProvisioningDelegateImpl.cpp +++ b/src/platform/K32W/DeviceNetworkProvisioningDelegateImpl.cpp @@ -24,7 +24,8 @@ namespace chip { namespace DeviceLayer { -CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) +CHIP_ERROR +DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(ByteSpan threadData) { #if CHIP_ENABLE_OPENTHREAD CHIP_ERROR error = CHIP_NO_ERROR; diff --git a/src/platform/K32W/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/K32W/DeviceNetworkProvisioningDelegateImpl.h index 05a642417934d4..e799358e4b7536 100644 --- a/src/platform/K32W/DeviceNetworkProvisioningDelegateImpl.h +++ b/src/platform/K32W/DeviceNetworkProvisioningDelegateImpl.h @@ -36,7 +36,7 @@ class DeviceNetworkProvisioningDelegateImpl final private: CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd) { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData); + CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData); }; } // namespace DeviceLayer diff --git a/src/platform/Linux/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/Linux/DeviceNetworkProvisioningDelegateImpl.h index 0db3663a2288b1..47c9f0f6e8262c 100644 --- a/src/platform/Linux/DeviceNetworkProvisioningDelegateImpl.h +++ b/src/platform/Linux/DeviceNetworkProvisioningDelegateImpl.h @@ -36,7 +36,7 @@ class DeviceNetworkProvisioningDelegateImpl final private: CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd); - CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) { return CHIP_ERROR_NOT_IMPLEMENTED; } + CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData) { return CHIP_ERROR_NOT_IMPLEMENTED; } }; } // namespace DeviceLayer diff --git a/src/platform/Linux/ThreadStackManagerImpl.cpp b/src/platform/Linux/ThreadStackManagerImpl.cpp index c28d0903c9bee7..353aec6635f87e 100644 --- a/src/platform/Linux/ThreadStackManagerImpl.cpp +++ b/src/platform/Linux/ThreadStackManagerImpl.cpp @@ -58,7 +58,7 @@ namespace DeviceLayer { ThreadStackManagerImpl ThreadStackManagerImpl::sInstance; -ThreadStackManagerImpl::ThreadStackManagerImpl() : mThreadApi(nullptr), mConnection(nullptr), mNetworkInfo(), mAttached(false) {} +ThreadStackManagerImpl::ThreadStackManagerImpl() : mThreadApi(nullptr), mConnection(nullptr), mAttached(false) {} CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack() { @@ -165,54 +165,50 @@ void ThreadStackManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) // isn't much to do in the Chip stack. } -CHIP_ERROR ThreadStackManagerImpl::_SetThreadProvision(const Internal::DeviceNetworkInfo & netInfo) +CHIP_ERROR ThreadStackManagerImpl::_SetThreadProvision(ByteSpan netInfo) { - mNetworkInfo = netInfo; + CHIP_ERROR err = CHIP_NO_ERROR; - // post an event alerting other subsystems about change in provisioning state - ChipDeviceEvent event; - event.Type = DeviceEventType::kServiceProvisioningChange; - event.ServiceProvisioningChange.IsServiceProvisioned = true; - PlatformMgr().PostEvent(&event); + VerifyOrExit(Thread::OperationalDataset::IsValid(netInfo), err = CHIP_ERROR_INVALID_ARGUMENT); - return CHIP_NO_ERROR; -} + { + std::vector data(netInfo.data(), netInfo.data() + netInfo.size()); -CHIP_ERROR ThreadStackManagerImpl::_SetThreadProvision(const uint8_t * operationalDataset, size_t operationalDatasetLen) -{ - mOperationalDatasetTlv = std::vector(operationalDataset, operationalDataset + operationalDatasetLen); + SuccessOrExit(err = OTBR_TO_CHIP_ERROR(mThreadApi->SetActiveDatasetTlvs(data))); - // post an event alerting other subsystems about change in provisioning state - ChipDeviceEvent event; - event.Type = DeviceEventType::kServiceProvisioningChange; - event.ServiceProvisioningChange.IsServiceProvisioned = true; - PlatformMgr().PostEvent(&event); + // post an event alerting other subsystems about change in provisioning state + ChipDeviceEvent event; + event.Type = DeviceEventType::kServiceProvisioningChange; + event.ServiceProvisioningChange.IsServiceProvisioned = true; + PlatformMgr().PostEvent(&event); + } - return CHIP_NO_ERROR; +exit: + return err; } -CHIP_ERROR ThreadStackManagerImpl::_GetThreadProvision(Internal::DeviceNetworkInfo & netInfo, bool includeCredentials) +CHIP_ERROR ThreadStackManagerImpl::_GetThreadProvision(ByteSpan & netInfo) { - netInfo = mNetworkInfo; + CHIP_ERROR err = CHIP_NO_ERROR; + std::vector data(Thread::kSizeOperationalDataset); - if (!includeCredentials) - { - memset(&netInfo.ThreadMasterKey, 0, sizeof(netInfo.ThreadMasterKey)); - memset(&netInfo.ThreadPSKc, 0, sizeof(netInfo.ThreadPSKc)); - netInfo.FieldPresent.ThreadPSKc = false; - } + SuccessOrExit(err = OTBR_TO_CHIP_ERROR(mThreadApi->GetActiveDatasetTlvs(data))); + SuccessOrExit(err = mDataset.Init(ByteSpan(data.data(), data.size()))); + + netInfo = mDataset.AsByteSpan(); - return CHIP_NO_ERROR; +exit: + return err; } bool ThreadStackManagerImpl::_IsThreadProvisioned() { - return mNetworkInfo.ThreadNetworkName[0] != '\0'; + return static_cast(mDataset).IsCommissioned(); } void ThreadStackManagerImpl::_ErasePersistentInfo() { - mNetworkInfo = Internal::DeviceNetworkInfo{}; + static_cast(mDataset).Clear(); } bool ThreadStackManagerImpl::_IsThreadEnabled() @@ -239,50 +235,10 @@ CHIP_ERROR ThreadStackManagerImpl::_SetThreadEnabled(bool val) if (val) { - if (mOperationalDatasetTlv.size() > 0) - { - SuccessOrExit(error = mThreadApi->SetActiveDatasetTlvs(mOperationalDatasetTlv)); - SuccessOrExit(error = mThreadApi->Attach([](ClientError result) { - // ThreadDevcieRoleChangedHandler should take care of this, so we don't emit another event. - ChipLogProgress(DeviceLayer, "Thread attach result %d", result); - })); - } - else - { - std::vector masterkey(std::begin(mNetworkInfo.ThreadMasterKey), std::end(mNetworkInfo.ThreadMasterKey)); - std::vector pskc; - uint64_t extPanId = UINT64_MAX; - uint32_t channelMask = UINT32_MAX; - - if (mNetworkInfo.FieldPresent.ThreadExtendedPANId) - { - extPanId = 0; - for (size_t i = 0; i < extPanId; i++) - { - extPanId <<= CHAR_BIT; - extPanId |= mNetworkInfo.ThreadExtendedPANId[i]; - } - } - if (mNetworkInfo.FieldPresent.ThreadPSKc) - { - pskc = std::vector(std::begin(mNetworkInfo.ThreadPSKc), std::end(mNetworkInfo.ThreadPSKc)); - } - if (mNetworkInfo.ThreadChannel != Internal::kThreadChannel_NotSpecified) - { - channelMask = 1 << mNetworkInfo.ThreadChannel; - } - - if (mNetworkInfo.FieldPresent.ThreadMeshPrefix) - { - std::array prefix; - - std::copy(std::begin(mNetworkInfo.ThreadMeshPrefix), std::end(mNetworkInfo.ThreadMeshPrefix), std::begin(prefix)); - SuccessOrExit(error = mThreadApi->SetMeshLocalPrefix(prefix)); - } - - mThreadApi->Attach(mNetworkInfo.ThreadNetworkName, mNetworkInfo.ThreadPANId, extPanId, masterkey, pskc, channelMask, - [](ClientError result) { ChipLogProgress(DeviceLayer, "Thread attach result %d", result); }); - } + SuccessOrExit(error = mThreadApi->Attach([](ClientError result) { + // ThreadDevcieRoleChangedHandler should take care of this, so we don't emit another event. + ChipLogProgress(DeviceLayer, "Thread attach result %d", result); + })); } else { diff --git a/src/platform/Linux/ThreadStackManagerImpl.h b/src/platform/Linux/ThreadStackManagerImpl.h index 742a1a4f74dd3f..de6803c2d5e667 100644 --- a/src/platform/Linux/ThreadStackManagerImpl.h +++ b/src/platform/Linux/ThreadStackManagerImpl.h @@ -26,6 +26,8 @@ #include "dbus/client/thread_api_dbus.hpp" #include "platform/internal/DeviceNetworkInfo.h" +#include + namespace chip { namespace DeviceLayer { @@ -46,11 +48,9 @@ class ThreadStackManagerImpl : public ThreadStackManager void _OnPlatformEvent(const ChipDeviceEvent * event); - CHIP_ERROR _GetThreadProvision(Internal::DeviceNetworkInfo & netInfo, bool includeCredentials); - - CHIP_ERROR _SetThreadProvision(const Internal::DeviceNetworkInfo & netInfo); + CHIP_ERROR _GetThreadProvision(ByteSpan & netInfo); - CHIP_ERROR _SetThreadProvision(const uint8_t * operationalDataset, size_t operationalDatasetLen); + CHIP_ERROR _SetThreadProvision(ByteSpan netInfo); void _ErasePersistentInfo(); @@ -112,10 +112,10 @@ class ThreadStackManagerImpl : public ThreadStackManager void _ThreadDevcieRoleChangedHandler(otbr::DBus::DeviceRole role); + Thread::OperationalDataset mDataset = {}; + std::unique_ptr mThreadApi; UniqueDBusConnection mConnection; - std::vector mOperationalDatasetTlv; - Internal::DeviceNetworkInfo mNetworkInfo; bool mAttached; std::thread mDBusEventLoop; }; diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp index 803d5c813da10d..681b406d10914a 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp @@ -48,8 +48,8 @@ #include #include #include -#include #include +#include #include extern "C" void otSysProcessDrivers(otInstance * aInstance); @@ -220,89 +220,18 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_SetThreadEnable } template -CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_SetThreadProvision(const DeviceNetworkInfo & netInfo) +CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_SetThreadProvision(ByteSpan netInfo) { otError otErr = OT_ERROR_FAILED; - otOperationalDataset newDataset; + otOperationalDatasetTlvs tlvs; - // Form a Thread operational dataset from the given network parameters. - memset(&newDataset, 0, sizeof(newDataset)); - - if (netInfo.ThreadNetworkName[0] != 0) - { - strncpy((char *) newDataset.mNetworkName.m8, netInfo.ThreadNetworkName, sizeof(newDataset.mNetworkName.m8)); - newDataset.mComponents.mIsNetworkNamePresent = true; - } - - if (netInfo.FieldPresent.ThreadExtendedPANId) - { - memcpy(newDataset.mExtendedPanId.m8, netInfo.ThreadExtendedPANId, sizeof(newDataset.mExtendedPanId.m8)); - newDataset.mComponents.mIsExtendedPanIdPresent = true; - } - - if (netInfo.FieldPresent.ThreadMeshPrefix) - { - memcpy(newDataset.mMeshLocalPrefix.m8, netInfo.ThreadMeshPrefix, sizeof(newDataset.mMeshLocalPrefix.m8)); - newDataset.mComponents.mIsMeshLocalPrefixPresent = true; - } - - memcpy(newDataset.mMasterKey.m8, netInfo.ThreadMasterKey, sizeof(newDataset.mMasterKey.m8)); - newDataset.mComponents.mIsMasterKeyPresent = true; - - if (netInfo.FieldPresent.ThreadPSKc) - { - memcpy(newDataset.mPskc.m8, netInfo.ThreadPSKc, sizeof(newDataset.mPskc.m8)); - newDataset.mComponents.mIsPskcPresent = true; - } - - if (netInfo.ThreadPANId != kThreadPANId_NotSpecified) - { - newDataset.mPanId = netInfo.ThreadPANId; - newDataset.mComponents.mIsPanIdPresent = true; - } - - if (netInfo.ThreadChannel != kThreadChannel_NotSpecified) - { - newDataset.mChannel = netInfo.ThreadChannel; - newDataset.mComponents.mIsChannelPresent = true; - } - - if (netInfo.ThreadDatasetTimestamp != 0) - { - newDataset.mActiveTimestamp = netInfo.ThreadDatasetTimestamp; - newDataset.mComponents.mIsActiveTimestampPresent = true; - } - - // Set the dataset as the active dataset for the node. - Impl()->LockThreadStack(); - otErr = otDatasetSetActive(mOTInst, &newDataset); - Impl()->UnlockThreadStack(); - - // post an event alerting other subsystems about change in provisioning state - ChipDeviceEvent event; - event.Type = DeviceEventType::kServiceProvisioningChange; - event.ServiceProvisioningChange.IsServiceProvisioned = true; - PlatformMgr().PostEvent(&event); - - return MapOpenThreadError(otErr); -} - -template -CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_SetThreadProvision(const uint8_t * operationalDataset, - size_t operationalDatasetLen) -{ - otError otErr = OT_ERROR_FAILED; - otOperationalDatasetTlvs datasetTlv; - - VerifyOrReturnError(operationalDatasetLen <= sizeof(datasetTlv.mTlvs), CHIP_ERROR_MESSAGE_TOO_LONG); - // A compile time check to avoid misbehavior if the openthread implementation changed over time. - static_assert(sizeof(datasetTlv.mTlvs) <= UINT8_MAX); - memcpy(datasetTlv.mTlvs, operationalDataset, operationalDatasetLen); - datasetTlv.mLength = static_cast(operationalDatasetLen); + assert(netInfo.size() <= Thread::kSizeOperationalDataset); + tlvs.mLength = static_cast(netInfo.size()); + memcpy(tlvs.mTlvs, netInfo.data(), netInfo.size()); // Set the dataset as the active dataset for the node. Impl()->LockThreadStack(); - otErr = otDatasetSetActiveTlvs(mOTInst, &datasetTlv); + otErr = otDatasetSetActiveTlvs(mOTInst, &tlvs); Impl()->UnlockThreadStack(); // post an event alerting other subsystems about change in provisioning state diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h index a70c1825bcb1fc..2e5bf8f605fb02 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h @@ -41,8 +41,6 @@ class ThreadStackManagerImpl; namespace Internal { -class DeviceNetworkInfo; - /** * Provides a generic implementation of ThreadStackManager features that works in conjunction * with OpenThread. @@ -75,9 +73,8 @@ class GenericThreadStackManagerImpl_OpenThread bool _IsThreadProvisioned(void); bool _IsThreadAttached(void); - CHIP_ERROR _GetThreadProvision(DeviceNetworkInfo & netInfo, bool includeCredentials); - CHIP_ERROR _SetThreadProvision(const DeviceNetworkInfo & netInfo); - CHIP_ERROR _SetThreadProvision(const uint8_t * operationalDataset, size_t operationalDatasetLen); + CHIP_ERROR _GetThreadProvision(ByteSpan & netInfo); + CHIP_ERROR _SetThreadProvision(ByteSpan netInfo); void _ErasePersistentInfo(void); ConnectivityManager::ThreadDeviceType _GetThreadDeviceType(void); CHIP_ERROR _SetThreadDeviceType(ConnectivityManager::ThreadDeviceType deviceType); diff --git a/src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.cpp b/src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.cpp index 4a756405871e6b..0f87641906c80b 100644 --- a/src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.cpp +++ b/src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.cpp @@ -24,7 +24,8 @@ namespace chip { namespace DeviceLayer { -CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) +CHIP_ERROR +DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(ByteSpan threadData) { #if CHIP_ENABLE_OPENTHREAD CHIP_ERROR error = CHIP_NO_ERROR; diff --git a/src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.h index 05a642417934d4..e799358e4b7536 100644 --- a/src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.h +++ b/src/platform/cc13x2_26x2/DeviceNetworkProvisioningDelegateImpl.h @@ -36,7 +36,7 @@ class DeviceNetworkProvisioningDelegateImpl final private: CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd) { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData); + CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData); }; } // namespace DeviceLayer diff --git a/src/platform/nrfconnect/DeviceNetworkProvisioningDelegateImpl.cpp b/src/platform/nrfconnect/DeviceNetworkProvisioningDelegateImpl.cpp index 4a756405871e6b..0f87641906c80b 100644 --- a/src/platform/nrfconnect/DeviceNetworkProvisioningDelegateImpl.cpp +++ b/src/platform/nrfconnect/DeviceNetworkProvisioningDelegateImpl.cpp @@ -24,7 +24,8 @@ namespace chip { namespace DeviceLayer { -CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) +CHIP_ERROR +DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(ByteSpan threadData) { #if CHIP_ENABLE_OPENTHREAD CHIP_ERROR error = CHIP_NO_ERROR; diff --git a/src/platform/nrfconnect/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/nrfconnect/DeviceNetworkProvisioningDelegateImpl.h index 05a642417934d4..e799358e4b7536 100644 --- a/src/platform/nrfconnect/DeviceNetworkProvisioningDelegateImpl.h +++ b/src/platform/nrfconnect/DeviceNetworkProvisioningDelegateImpl.h @@ -36,7 +36,7 @@ class DeviceNetworkProvisioningDelegateImpl final private: CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd) { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData); + CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData); }; } // namespace DeviceLayer diff --git a/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.cpp b/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.cpp index 4a756405871e6b..0f87641906c80b 100644 --- a/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.cpp +++ b/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.cpp @@ -24,7 +24,8 @@ namespace chip { namespace DeviceLayer { -CHIP_ERROR DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData) +CHIP_ERROR +DeviceNetworkProvisioningDelegateImpl::_ProvisionThreadNetwork(ByteSpan threadData) { #if CHIP_ENABLE_OPENTHREAD CHIP_ERROR error = CHIP_NO_ERROR; diff --git a/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.h b/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.h index 05a642417934d4..e799358e4b7536 100644 --- a/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.h +++ b/src/platform/qpg6100/DeviceNetworkProvisioningDelegateImpl.h @@ -36,7 +36,7 @@ class DeviceNetworkProvisioningDelegateImpl final private: CHIP_ERROR _ProvisionWiFiNetwork(const char * ssid, const char * passwd) { return CHIP_ERROR_NOT_IMPLEMENTED; } - CHIP_ERROR _ProvisionThreadNetwork(DeviceLayer::Internal::DeviceNetworkInfo & threadData); + CHIP_ERROR _ProvisionThreadNetwork(ByteSpan threadData); }; } // namespace DeviceLayer diff --git a/src/platform/tests/TestThreadStackMgr.cpp b/src/platform/tests/TestThreadStackMgr.cpp index eb66767c489ad2..74516e5e85761a 100644 --- a/src/platform/tests/TestThreadStackMgr.cpp +++ b/src/platform/tests/TestThreadStackMgr.cpp @@ -16,10 +16,10 @@ */ #include -#include #include #include +#include #include #include "platform/internal/CHIPDeviceLayerInternal.h" @@ -28,6 +28,7 @@ #include "platform/ThreadStackManager.h" #if CHIP_DEVICE_LAYER_TARGET == LINUX +#include #include struct DBusConnectionDeleter @@ -53,16 +54,15 @@ void EventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg int TestThreadStackManager() { chip::DeviceLayer::ThreadStackManagerImpl impl; - chip::DeviceLayer::Internal::DeviceNetworkInfo info; - uint16_t masterKey[16] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; + chip::Thread::OperationalDataset dataset{}; + constexpr uint8_t masterKey[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff + }; - strncpy(info.ThreadNetworkName, "CHIP-TEST", sizeof(info.ThreadNetworkName)); - info.ThreadChannel = UINT8_MAX; - info.ThreadPANId = 0x3455; - info.FieldPresent.ThreadExtendedPANId = false; - info.FieldPresent.ThreadMeshPrefix = false; - info.FieldPresent.ThreadPSKc = false; - memcpy(&info.ThreadMasterKey, &masterKey, sizeof(masterKey)); + dataset.SetNetworkName("CHIP-TEST"); + dataset.SetChannel(UINT8_MAX); + dataset.SetPanId(0x3455); + dataset.SetMasterKey(masterKey); chip::Platform::MemoryInit(); chip::DeviceLayer::PlatformMgrImpl().InitChipStack(); @@ -70,7 +70,7 @@ int TestThreadStackManager() impl.InitThreadStack(); impl.StartThreadTask(); - impl._SetThreadProvision(info); + impl._SetThreadProvision(dataset.AsByteSpan()); impl._SetThreadEnabled(true); printf("Start Thread task done\n"); diff --git a/src/protocols/secure_channel/NetworkProvisioning.cpp b/src/protocols/secure_channel/NetworkProvisioning.cpp index 5c8c38ac0d6214..a3a2777ac80edf 100644 --- a/src/protocols/secure_channel/NetworkProvisioning.cpp +++ b/src/protocols/secure_channel/NetworkProvisioning.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #if CONFIG_DEVICE_LAYER @@ -259,35 +260,16 @@ CHIP_ERROR NetworkProvisioning::SendNetworkCredentials(const char * ssid, const return err; } -CHIP_ERROR NetworkProvisioning::SendThreadCredentials(const DeviceLayer::Internal::DeviceNetworkInfo & threadData) +CHIP_ERROR NetworkProvisioning::SendThreadCredentials(ByteSpan threadData) { CHIP_ERROR err = CHIP_NO_ERROR; - /* clang-format off */ - constexpr uint16_t credentialSize = - sizeof(threadData.ThreadNetworkName) + - sizeof(threadData.ThreadExtendedPANId) + - sizeof(threadData.ThreadMeshPrefix) + - sizeof(threadData.ThreadMasterKey) + - sizeof(threadData.ThreadPSKc) + - sizeof (uint16_t) + // threadData.ThereadPANId - 4; // threadData.ThreadChannel, threadData.FieldPresent.ThreadExtendedPANId, - // threadData.FieldPresent.ThreadMeshPrefix, threadData.FieldPresent.ThreadPSKc - /* clang-format on */ - Encoding::LittleEndian::PacketBufferWriter bbuf(MessagePacketBuffer::New(credentialSize), credentialSize); + + Encoding::LittleEndian::PacketBufferWriter bbuf(MessagePacketBuffer::New(threadData.size()), threadData.size()); ChipLogProgress(NetworkProvisioning, "Sending Thread Credentials"); VerifyOrExit(!bbuf.IsNull(), err = CHIP_ERROR_NO_MEMORY); - bbuf.Put(threadData.ThreadNetworkName, sizeof(threadData.ThreadNetworkName)); - bbuf.Put(threadData.ThreadExtendedPANId, sizeof(threadData.ThreadExtendedPANId)); - bbuf.Put(threadData.ThreadMeshPrefix, sizeof(threadData.ThreadMeshPrefix)); - bbuf.Put(threadData.ThreadMasterKey, sizeof(threadData.ThreadMasterKey)); - bbuf.Put(threadData.ThreadPSKc, sizeof(threadData.ThreadPSKc)); - bbuf.Put16(threadData.ThreadPANId); - bbuf.Put(threadData.ThreadChannel); - bbuf.Put(static_cast(threadData.FieldPresent.ThreadExtendedPANId)); - bbuf.Put(static_cast(threadData.FieldPresent.ThreadMeshPrefix)); - bbuf.Put(static_cast(threadData.FieldPresent.ThreadPSKc)); + bbuf.Put(threadData.data(), threadData.size()); VerifyOrExit(bbuf.Fit(), err = CHIP_ERROR_BUFFER_TOO_SMALL); @@ -302,62 +284,7 @@ CHIP_ERROR NetworkProvisioning::SendThreadCredentials(const DeviceLayer::Interna #ifdef CHIP_ENABLE_OPENTHREAD CHIP_ERROR NetworkProvisioning::DecodeThreadAssociationRequest(const System::PacketBufferHandle & msgBuf) { - CHIP_ERROR err = CHIP_NO_ERROR; - DeviceLayer::Internal::DeviceNetworkInfo networkInfo = {}; - uint8_t * data = msgBuf->Start(); - size_t dataLen = msgBuf->DataLength(); - - VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadNetworkName), - ChipLogProgress(NetworkProvisioning, "Invalid network provision message")); - memcpy(networkInfo.ThreadNetworkName, data, sizeof(networkInfo.ThreadNetworkName)); - data += sizeof(networkInfo.ThreadNetworkName); - dataLen -= sizeof(networkInfo.ThreadNetworkName); - - VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadExtendedPANId), - ChipLogProgress(NetworkProvisioning, "Invalid network provision message")); - memcpy(networkInfo.ThreadExtendedPANId, data, sizeof(networkInfo.ThreadExtendedPANId)); - data += sizeof(networkInfo.ThreadExtendedPANId); - dataLen -= sizeof(networkInfo.ThreadExtendedPANId); - - VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadMeshPrefix), - ChipLogProgress(NetworkProvisioning, "Invalid network provision message")); - memcpy(networkInfo.ThreadMeshPrefix, data, sizeof(networkInfo.ThreadMeshPrefix)); - data += sizeof(networkInfo.ThreadMeshPrefix); - dataLen -= sizeof(networkInfo.ThreadMeshPrefix); - - VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadMasterKey), - ChipLogProgress(NetworkProvisioning, "Invalid network provision message")); - memcpy(networkInfo.ThreadMasterKey, data, sizeof(networkInfo.ThreadMasterKey)); - data += sizeof(networkInfo.ThreadMasterKey); - dataLen -= sizeof(networkInfo.ThreadMasterKey); - - VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadPSKc), - ChipLogProgress(NetworkProvisioning, "Invalid network provision message")); - memcpy(networkInfo.ThreadPSKc, data, sizeof(networkInfo.ThreadPSKc)); - data += sizeof(networkInfo.ThreadPSKc); - dataLen -= sizeof(networkInfo.ThreadPSKc); - - VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadPANId), - ChipLogProgress(NetworkProvisioning, "Invalid network provision message")); - networkInfo.ThreadPANId = Encoding::LittleEndian::Get16(data); - data += sizeof(networkInfo.ThreadPANId); - dataLen -= sizeof(networkInfo.ThreadPANId); - - VerifyOrExit(dataLen >= sizeof(networkInfo.ThreadChannel), - ChipLogProgress(NetworkProvisioning, "Invalid network provision message")); - networkInfo.ThreadChannel = data[0]; - data += sizeof(networkInfo.ThreadChannel); - dataLen -= sizeof(networkInfo.ThreadChannel); - - VerifyOrExit(dataLen >= 3, ChipLogProgress(NetworkProvisioning, "Invalid network provision message")); - networkInfo.FieldPresent.ThreadExtendedPANId = *data; - data++; - networkInfo.FieldPresent.ThreadMeshPrefix = *data; - data++; - networkInfo.FieldPresent.ThreadPSKc = *data; - data++; - networkInfo.NetworkId = 0; - networkInfo.FieldPresent.NetworkId = true; + CHIP_ERROR err = CHIP_NO_ERROR; #if CONFIG_DEVICE_LAYER // Start listening for OpenThread changes to be able to respond with SLAAC/On-Mesh IP Address @@ -365,12 +292,11 @@ CHIP_ERROR NetworkProvisioning::DecodeThreadAssociationRequest(const System::Pac #if defined(CHIP_DEVICE_LAYER_TARGET) { DeviceLayer::DeviceNetworkProvisioningDelegateImpl deviceDelegate; - err = deviceDelegate.ProvisionThread(networkInfo); + err = deviceDelegate.ProvisionThread(ByteSpan(msgBuf->Start(), msgBuf->DataLength())); } #endif #endif -exit: return err; } #else // CHIP_ENABLE_OPENTHREAD diff --git a/src/protocols/secure_channel/NetworkProvisioning.h b/src/protocols/secure_channel/NetworkProvisioning.h index 3efa8510f8b3ba..7f4f4f76bffe1b 100644 --- a/src/protocols/secure_channel/NetworkProvisioning.h +++ b/src/protocols/secure_channel/NetworkProvisioning.h @@ -88,7 +88,7 @@ class DLL_EXPORT NetworkProvisioning : public Messaging::ExchangeDelegate ~NetworkProvisioning(); CHIP_ERROR SendNetworkCredentials(const char * ssid, const char * passwd); - CHIP_ERROR SendThreadCredentials(const DeviceLayer::Internal::DeviceNetworkInfo & threadData); + CHIP_ERROR SendThreadCredentials(ByteSpan threadData); CHIP_ERROR HandleNetworkProvisioningMessage(uint8_t msgType, const System::PacketBufferHandle & msgBuf); diff --git a/src/protocols/secure_channel/RendezvousSession.cpp b/src/protocols/secure_channel/RendezvousSession.cpp index 330c0be5676ca6..99b01ce99d3768 100644 --- a/src/protocols/secure_channel/RendezvousSession.cpp +++ b/src/protocols/secure_channel/RendezvousSession.cpp @@ -340,7 +340,7 @@ void RendezvousSession::SendNetworkCredentials(const char * ssid, const char * p mNetworkProvision.SendNetworkCredentials(ssid, passwd); } -void RendezvousSession::SendThreadCredentials(const DeviceLayer::Internal::DeviceNetworkInfo & threadData) +void RendezvousSession::SendThreadCredentials(ByteSpan threadData) { mNetworkProvision.SendThreadCredentials(threadData); } diff --git a/src/protocols/secure_channel/RendezvousSession.h b/src/protocols/secure_channel/RendezvousSession.h index 5bb19ef465f152..60fd9042b2b3c7 100644 --- a/src/protocols/secure_channel/RendezvousSession.h +++ b/src/protocols/secure_channel/RendezvousSession.h @@ -119,7 +119,7 @@ class RendezvousSession : public SessionEstablishmentDelegate, //////////// RendezvousDeviceCredentialsDelegate Implementation /////////////// void SendNetworkCredentials(const char * ssid, const char * passwd) override; - void SendThreadCredentials(const DeviceLayer::Internal::DeviceNetworkInfo & threadData) override; + void SendThreadCredentials(ByteSpan threadData) override; void SendOperationalCredentials() override; //////////// NetworkProvisioningDelegate Implementation /////////////// diff --git a/src/transport/RendezvousSessionDelegate.h b/src/transport/RendezvousSessionDelegate.h index 28157df9ef3fb4..af2542dd806605 100644 --- a/src/transport/RendezvousSessionDelegate.h +++ b/src/transport/RendezvousSessionDelegate.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -51,9 +52,9 @@ class DLL_EXPORT RendezvousDeviceCredentialsDelegate public: virtual ~RendezvousDeviceCredentialsDelegate() {} - virtual void SendNetworkCredentials(const char * ssid, const char * passwd) = 0; - virtual void SendThreadCredentials(const DeviceLayer::Internal::DeviceNetworkInfo &) = 0; - virtual void SendOperationalCredentials() = 0; + virtual void SendNetworkCredentials(const char * ssid, const char * passwd) = 0; + virtual void SendThreadCredentials(ByteSpan threadDataset) = 0; + virtual void SendOperationalCredentials() = 0; }; } // namespace chip