| /* |
| * |
| * Copyright (c) 2022 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. |
| */ |
| |
| /** |
| * @file |
| * Provides an implementation of the ThreadStackManager singleton object |
| * for Tizen platform. |
| */ |
| |
| /** |
| * Note: ThreadStackManager requires ConnectivityManager to be defined |
| * beforehand, otherwise we will face circular dependency between them. */ |
| #include <platform/ConnectivityManager.h> |
| |
| /** |
| * Note: Use public include for ThreadStackManager which includes our local |
| * platform/<PLATFORM>/ThreadStackManagerImpl.h after defining interface |
| * class. */ |
| #include <platform/ThreadStackManager.h> |
| |
| #include <endian.h> |
| |
| #include <cstring> |
| |
| #include <thread.h> |
| #include <tizen_error.h> |
| |
| #include <app/AttributeAccessInterface.h> |
| #include <inet/IPAddress.h> |
| #include <lib/core/CHIPError.h> |
| #include <lib/core/DataModelTypes.h> |
| #include <lib/dnssd/Constants.h> |
| #include <lib/dnssd/platform/Dnssd.h> |
| #include <lib/support/CHIPMemString.h> |
| #include <lib/support/CodeUtils.h> |
| #include <lib/support/SafeInt.h> |
| #include <lib/support/Span.h> |
| #include <lib/support/ThreadOperationalDataset.h> |
| #include <platform/CHIPDeviceConfig.h> |
| #include <platform/CHIPDeviceEvent.h> |
| #include <platform/NetworkCommissioning.h> |
| #include <platform/PlatformManager.h> |
| |
| #include <platform/Tizen/ThreadStackManagerImpl.h> |
| #include <platform/internal/CHIPDeviceLayerInternal.h> |
| |
| namespace chip { |
| namespace DeviceLayer { |
| |
| namespace { |
| // Return human readable error message for given Thread API error code. |
| // |
| // This is a temporary workaround for the fact that Tizen common API |
| // does not return messages for all Thread API errors. |
| // |
| // TODO (a.bokowy): To be removed once Tizen fixes this issue. |
| const char * get_error_message(int code) |
| { |
| switch (code) |
| { |
| case THREAD_ERROR_NOT_INITIALIZED: |
| return "Not initialized"; |
| case THREAD_ERROR_NOT_IN_PROGRESS: |
| return "Operation not in progress"; |
| case THREAD_ERROR_ALREADY_DONE: |
| return "Operation already done"; |
| case THREAD_ERROR_OPERATION_FAILED: |
| return "Operation failed"; |
| case THREAD_ERROR_NOT_READY: |
| return "Resource not ready"; |
| case THREAD_ERROR_NOT_ENABLED: |
| return "Not enabled"; |
| case THREAD_ERROR_NOT_FOUND: |
| return "Not found"; |
| case THREAD_ERROR_ALREADY_REGISTERED: |
| return "Already registered"; |
| case THREAD_ERROR_DB_FAILED: |
| return "DB operation failed"; |
| case THREAD_ERROR_NOT_REGISTERED: |
| return "Not registered"; |
| default: |
| return ::get_error_message(code); |
| } |
| } |
| }; // namespace |
| |
| ThreadStackManagerImpl ThreadStackManagerImpl::sInstance; |
| |
| constexpr char ThreadStackManagerImpl::kOpenthreadDeviceRoleDisabled[]; |
| constexpr char ThreadStackManagerImpl::kOpenthreadDeviceRoleDetached[]; |
| constexpr char ThreadStackManagerImpl::kOpenthreadDeviceRoleChild[]; |
| constexpr char ThreadStackManagerImpl::kOpenthreadDeviceRoleRouter[]; |
| constexpr char ThreadStackManagerImpl::kOpenthreadDeviceRoleLeader[]; |
| |
| constexpr char ThreadStackManagerImpl::kOpenthreadDeviceTypeNotSupported[]; |
| constexpr char ThreadStackManagerImpl::kOpenthreadDeviceTypeRouter[]; |
| constexpr char ThreadStackManagerImpl::kOpenthreadDeviceTypeFullEndDevice[]; |
| constexpr char ThreadStackManagerImpl::kOpenthreadDeviceTypeMinimalEndDevice[]; |
| constexpr char ThreadStackManagerImpl::kOpenthreadDeviceTypeSleepyEndDevice[]; |
| |
| ThreadStackManagerImpl::ThreadStackManagerImpl() : mIsAttached(false), mIsInitialized(false), mThreadInstance(nullptr) {} |
| |
| const char * ThreadStackManagerImpl::_ThreadRoleToStr(thread_device_role_e role) |
| { |
| switch (role) |
| { |
| case THREAD_DEVICE_ROLE_DISABLED: |
| return kOpenthreadDeviceRoleDisabled; |
| case THREAD_DEVICE_ROLE_DETACHED: |
| return kOpenthreadDeviceRoleDetached; |
| case THREAD_DEVICE_ROLE_CHILD: |
| return kOpenthreadDeviceRoleChild; |
| case THREAD_DEVICE_ROLE_ROUTER: |
| return kOpenthreadDeviceRoleRouter; |
| case THREAD_DEVICE_ROLE_LEADER: |
| return kOpenthreadDeviceRoleLeader; |
| default: |
| return nullptr; |
| } |
| } |
| |
| const char * ThreadStackManagerImpl::_ThreadTypeToStr(thread_device_type_e type) |
| { |
| switch (type) |
| { |
| case THREAD_DEVICE_TYPE_NOT_SUPPORTED: |
| return kOpenthreadDeviceTypeNotSupported; |
| case THREAD_DEVICE_TYPE_ROUTER: |
| return kOpenthreadDeviceTypeRouter; |
| case THREAD_DEVICE_TYPE_FULL_END_DEVICE: |
| return kOpenthreadDeviceTypeFullEndDevice; |
| case THREAD_DEVICE_TYPE_MINIMAL_END_DEVICE: |
| return kOpenthreadDeviceTypeMinimalEndDevice; |
| case THREAD_DEVICE_TYPE_SLEEPY_END_DEVICE: |
| return kOpenthreadDeviceTypeSleepyEndDevice; |
| default: |
| return nullptr; |
| } |
| } |
| |
| void ThreadStackManagerImpl::_ThreadDeviceRoleChangedCb(thread_device_role_e deviceRole, void * userData) |
| { |
| ChipLogProgress(DeviceLayer, "Thread device role [%s]", sInstance._ThreadRoleToStr(deviceRole)); |
| sInstance.ThreadDeviceRoleChangedHandler(deviceRole); |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack() |
| { |
| int threadErr = THREAD_ERROR_NONE; |
| thread_device_role_e deviceRole; |
| |
| if (mIsInitialized) |
| { |
| ChipLogProgress(DeviceLayer, "Thread stack manager already initialized"); |
| return CHIP_NO_ERROR; |
| } |
| |
| threadErr = thread_initialize(); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Initialize Thread: %s", get_error_message(threadErr))); |
| ChipLogProgress(DeviceLayer, "Thread initialized"); |
| |
| threadErr = thread_enable(&mThreadInstance); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Enable Thread: %s", get_error_message(threadErr))); |
| ChipLogProgress(DeviceLayer, "Thread enabled"); |
| |
| threadErr = thread_get_device_role(mThreadInstance, &deviceRole); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Get Thread device role: %s", get_error_message(threadErr))); |
| ThreadDeviceRoleChangedHandler(deviceRole); |
| |
| /* Set callback for change of device role */ |
| threadErr = thread_set_device_role_changed_cb(mThreadInstance, _ThreadDeviceRoleChangedCb, nullptr); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Set Thread device role changed cb: %s", get_error_message(threadErr))); |
| |
| mIsInitialized = true; |
| ChipLogProgress(DeviceLayer, "Thread stack manager initialized"); |
| return CHIP_NO_ERROR; |
| |
| exit: |
| thread_deinitialize(); |
| return CHIP_ERROR_INTERNAL; |
| } |
| |
| void ThreadStackManagerImpl::ThreadDeviceRoleChangedHandler(thread_device_role_e role) |
| { |
| ChipLogProgress(DeviceLayer, "Thread device role [%s]", _ThreadRoleToStr(role)); |
| |
| bool isAttached = (role != THREAD_DEVICE_ROLE_DISABLED) && (role != THREAD_DEVICE_ROLE_DETACHED); |
| |
| ChipDeviceEvent event = ChipDeviceEvent{}; |
| |
| if (isAttached != mIsAttached) |
| { |
| ChipLogProgress(DeviceLayer, "Thread connectivity state changed [%s]", isAttached ? "Established" : "Lost"); |
| event.Type = DeviceEventType::kThreadConnectivityChange; |
| event.ThreadConnectivityChange.Result = |
| isAttached ? ConnectivityChange::kConnectivity_Established : ConnectivityChange::kConnectivity_Lost; |
| PlatformMgr().PostEventOrDie(&event); |
| } |
| |
| mIsAttached = isAttached; |
| |
| #if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT |
| int threadErr = THREAD_ERROR_NONE; |
| if (role == THREAD_DEVICE_ROLE_DISABLED) |
| { |
| /* start srp client */ |
| threadErr = thread_srp_client_start(mThreadInstance); |
| if (threadErr != THREAD_ERROR_NONE && threadErr != THREAD_ERROR_ALREADY_DONE) |
| ChipLogError(DeviceLayer, "FAIL: Start Thread SRP client: %s", get_error_message(threadErr)); |
| } |
| else if (role == THREAD_DEVICE_ROLE_ROUTER || role == THREAD_DEVICE_ROLE_CHILD) |
| { |
| threadErr = thread_srp_server_stop(mThreadInstance); |
| if (threadErr != THREAD_ERROR_NONE && threadErr != THREAD_ERROR_ALREADY_DONE) |
| ChipLogError(DeviceLayer, "FAIL: Stop Thread SRP server: %s", get_error_message(threadErr)); |
| threadErr = thread_srp_client_start(mThreadInstance); |
| if (threadErr != THREAD_ERROR_NONE && threadErr != THREAD_ERROR_ALREADY_DONE) |
| ChipLogError(DeviceLayer, "FAIL: Start Thread SRP client: %s", get_error_message(threadErr)); |
| } |
| else if (role == THREAD_DEVICE_ROLE_LEADER) |
| { |
| threadErr = thread_srp_client_stop(mThreadInstance); |
| if (threadErr != THREAD_ERROR_NONE && threadErr != THREAD_ERROR_ALREADY_DONE) |
| ChipLogError(DeviceLayer, "FAIL: Stop Thread SRP client: %s", get_error_message(threadErr)); |
| threadErr = thread_srp_server_start(mThreadInstance); |
| if (threadErr != THREAD_ERROR_NONE && threadErr != THREAD_ERROR_ALREADY_DONE) |
| ChipLogError(DeviceLayer, "FAIL: Start Thread SRP server: %s", get_error_message(threadErr)); |
| } |
| #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT |
| |
| ChipLogProgress(DeviceLayer, "Thread role state changed [%s]", mIsAttached ? "Attached" : "Detached"); |
| event.Type = DeviceEventType::kThreadStateChange; |
| event.ThreadStateChange.RoleChanged = true; |
| PlatformMgr().PostEventOrDie(&event); |
| } |
| |
| void ThreadStackManagerImpl::_ProcessThreadActivity() {} |
| |
| bool ThreadStackManagerImpl::_HaveRouteToAddress(const Inet::IPAddress & destAddr) |
| { |
| return false; |
| } |
| |
| void ThreadStackManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) |
| { |
| ChipLogProgress(DeviceLayer, "Thread platform event type [%d]", event->Type); |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_SetThreadProvision(ByteSpan netInfo) |
| { |
| VerifyOrReturnError(mIsInitialized, CHIP_ERROR_UNINITIALIZED); |
| VerifyOrReturnError(Thread::OperationalDataset::IsValid(netInfo), CHIP_ERROR_INVALID_ARGUMENT); |
| |
| int threadErr = THREAD_ERROR_NONE; |
| |
| threadErr = thread_network_set_active_dataset_tlvs(mThreadInstance, netInfo.data(), netInfo.size()); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Thread set active dataset TLVs: %s", get_error_message(threadErr))); |
| |
| // post an event alerting other subsystems about change in provisioning state |
| ChipDeviceEvent event; |
| event.Type = DeviceEventType::kServiceProvisioningChange; |
| event.ServiceProvisioningChange.IsServiceProvisioned = true; |
| PlatformMgr().PostEventOrDie(&event); |
| |
| ChipLogProgress(DeviceLayer, "Thread set active dataset TLVs"); |
| |
| return CHIP_NO_ERROR; |
| |
| exit: |
| return CHIP_ERROR_INTERNAL; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_GetThreadProvision(Thread::OperationalDataset & dataset) |
| { |
| VerifyOrReturnError(mIsInitialized, CHIP_ERROR_UNINITIALIZED); |
| |
| int threadErr = THREAD_ERROR_NONE; |
| uint8_t * tlvsData = nullptr; |
| int tlvsLen; |
| |
| threadErr = thread_network_get_active_dataset_tlvs(mThreadInstance, &tlvsData, &tlvsLen); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Thread get active dataset TLVs: %s", get_error_message(threadErr))); |
| |
| ChipLogProgress(DeviceLayer, "Thread get active dataset TLVs size [%u]", tlvsLen); |
| mDataset.Init(ByteSpan(tlvsData, tlvsLen)); |
| dataset.Init(mDataset.AsByteSpan()); |
| |
| return CHIP_NO_ERROR; |
| |
| exit: |
| return CHIP_ERROR_INTERNAL; |
| } |
| |
| bool ThreadStackManagerImpl::_IsThreadProvisioned() |
| { |
| return mDataset.IsCommissioned(); |
| } |
| |
| void ThreadStackManagerImpl::_ErasePersistentInfo() |
| { |
| mDataset.Clear(); |
| } |
| |
| bool ThreadStackManagerImpl::_IsThreadEnabled() |
| { |
| VerifyOrReturnError(mIsInitialized, false); |
| |
| int threadErr = THREAD_ERROR_NONE; |
| thread_device_role_e deviceRole; |
| |
| threadErr = thread_get_device_role(mThreadInstance, &deviceRole); |
| VerifyOrReturnError(threadErr == THREAD_ERROR_NONE, false, |
| ChipLogError(DeviceLayer, "FAIL: Get Thread device role: %s", get_error_message(threadErr))); |
| |
| ChipLogProgress(DeviceLayer, "Thread device role [%s]", _ThreadRoleToStr(deviceRole)); |
| return deviceRole != THREAD_DEVICE_ROLE_DISABLED; |
| } |
| |
| bool ThreadStackManagerImpl::_IsThreadAttached() |
| { |
| return mIsAttached; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_SetThreadEnabled(bool val) |
| { |
| VerifyOrReturnError(mIsInitialized, CHIP_ERROR_UNINITIALIZED); |
| |
| int threadErr = THREAD_ERROR_NONE; |
| bool isEnabled = sInstance._IsThreadEnabled(); |
| |
| if (val && !isEnabled) |
| { |
| threadErr = thread_network_attach(mThreadInstance); |
| DeviceLayer::SystemLayer().ScheduleLambda([&, threadErr]() { |
| if (this->mpConnectCallback != nullptr && threadErr != THREAD_ERROR_NONE) |
| { |
| this->mpConnectCallback->OnResult(NetworkCommissioning::Status::kUnknownError, CharSpan(), 0); |
| this->mpConnectCallback = nullptr; |
| } |
| }); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Attach Thread network: %s", get_error_message(threadErr))); |
| |
| threadErr = thread_start(mThreadInstance); |
| DeviceLayer::SystemLayer().ScheduleLambda([&, threadErr]() { |
| if (this->mpConnectCallback != nullptr) |
| { |
| this->mpConnectCallback->OnResult(threadErr == THREAD_ERROR_NONE ? NetworkCommissioning::Status::kSuccess |
| : NetworkCommissioning::Status::kUnknownError, |
| CharSpan(), 0); |
| this->mpConnectCallback = nullptr; |
| } |
| }); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Start Thread network: %s", get_error_message(threadErr))); |
| } |
| else if (!val && isEnabled) |
| { |
| threadErr = thread_stop(mThreadInstance); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Stop Thread: %s", get_error_message(threadErr))); |
| } |
| |
| thread_device_role_e deviceRole; |
| threadErr = thread_get_device_role(mThreadInstance, &deviceRole); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Get Thread device role: %s", get_error_message(threadErr))); |
| ThreadDeviceRoleChangedHandler(deviceRole); |
| |
| ChipLogProgress(DeviceLayer, "Thread set enabled [%s]", val ? "attach" : "reset"); |
| return CHIP_NO_ERROR; |
| |
| exit: |
| ChipLogError(DeviceLayer, "FAIL: Set Thread enabled [%s]", val ? "attach" : "reset"); |
| return CHIP_ERROR_INTERNAL; |
| } |
| |
| ConnectivityManager::ThreadDeviceType ThreadStackManagerImpl::_GetThreadDeviceType() |
| { |
| VerifyOrReturnError(mIsInitialized, ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported, |
| ChipLogError(DeviceLayer, "Thread stack not initialized")); |
| |
| int threadErr = THREAD_ERROR_NONE; |
| thread_device_type_e devType; |
| |
| threadErr = thread_get_device_type(mThreadInstance, &devType); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Get Thread device type: %s", get_error_message(threadErr))); |
| |
| ChipLogProgress(DeviceLayer, "Thread device type [%s]", _ThreadTypeToStr(devType)); |
| |
| switch (devType) |
| { |
| case THREAD_DEVICE_TYPE_NOT_SUPPORTED: |
| return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported; |
| case THREAD_DEVICE_TYPE_ROUTER: |
| return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_Router; |
| case THREAD_DEVICE_TYPE_FULL_END_DEVICE: |
| return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_FullEndDevice; |
| case THREAD_DEVICE_TYPE_MINIMAL_END_DEVICE: |
| return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_MinimalEndDevice; |
| case THREAD_DEVICE_TYPE_SLEEPY_END_DEVICE: |
| return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_SleepyEndDevice; |
| default: |
| return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported; |
| } |
| |
| exit: |
| return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_SetThreadDeviceType(ConnectivityManager::ThreadDeviceType deviceType) |
| { |
| VerifyOrReturnError(mIsInitialized, CHIP_ERROR_UNINITIALIZED); |
| |
| int threadErr = THREAD_ERROR_NONE; |
| thread_device_type_e devType; |
| |
| switch (deviceType) |
| { |
| case ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported: |
| devType = THREAD_DEVICE_TYPE_NOT_SUPPORTED; |
| break; |
| case ConnectivityManager::ThreadDeviceType::kThreadDeviceType_Router: |
| devType = THREAD_DEVICE_TYPE_ROUTER; |
| break; |
| case ConnectivityManager::ThreadDeviceType::kThreadDeviceType_FullEndDevice: |
| devType = THREAD_DEVICE_TYPE_FULL_END_DEVICE; |
| break; |
| case ConnectivityManager::ThreadDeviceType::kThreadDeviceType_MinimalEndDevice: |
| devType = THREAD_DEVICE_TYPE_MINIMAL_END_DEVICE; |
| break; |
| case ConnectivityManager::ThreadDeviceType::kThreadDeviceType_SleepyEndDevice: |
| devType = THREAD_DEVICE_TYPE_SLEEPY_END_DEVICE; |
| break; |
| default: |
| devType = THREAD_DEVICE_TYPE_NOT_SUPPORTED; |
| break; |
| } |
| |
| threadErr = thread_set_device_type(mThreadInstance, devType); |
| VerifyOrExit(threadErr == THREAD_ERROR_NONE, |
| ChipLogError(DeviceLayer, "FAIL: Set Thread device type: %s", get_error_message(threadErr))); |
| |
| ChipLogProgress(DeviceLayer, "Thread set device type [%s]", _ThreadTypeToStr(devType)); |
| return CHIP_NO_ERROR; |
| |
| exit: |
| return CHIP_ERROR_INTERNAL; |
| } |
| |
| bool ThreadStackManagerImpl::_HaveMeshConnectivity() |
| { |
| return false; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_GetAndLogThreadStatsCounters() |
| { |
| ChipLogError(DeviceLayer, "Not implemented"); |
| return CHIP_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_GetAndLogThreadTopologyMinimal() |
| { |
| ChipLogError(DeviceLayer, "Not implemented"); |
| return CHIP_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_GetAndLogThreadTopologyFull() |
| { |
| ChipLogError(DeviceLayer, "Not implemented"); |
| return CHIP_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_GetPrimary802154MACAddress(uint8_t * buf) |
| { |
| VerifyOrReturnError(mIsInitialized, CHIP_ERROR_UNINITIALIZED); |
| |
| uint64_t extAddr; |
| int threadErr; |
| |
| threadErr = thread_get_extended_address(mThreadInstance, &extAddr); |
| VerifyOrReturnError(threadErr == THREAD_ERROR_NONE, CHIP_ERROR_INTERNAL, |
| ChipLogError(DeviceLayer, "FAIL: Get Thread extended address: %s", get_error_message(threadErr))); |
| |
| extAddr = htobe64(extAddr); |
| memcpy(buf, &extAddr, sizeof(extAddr)); |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_GetExternalIPv6Address(chip::Inet::IPAddress & addr) |
| { |
| ChipLogError(DeviceLayer, "Not implemented"); |
| return CHIP_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_GetPollPeriod(uint32_t & buf) |
| { |
| ChipLogError(DeviceLayer, "Not implemented"); |
| return CHIP_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_JoinerStart() |
| { |
| ChipLogError(DeviceLayer, "Not implemented"); |
| return CHIP_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_StartThreadScan(NetworkCommissioning::ThreadDriver::ScanCallback * callback) |
| { |
| ChipLogError(DeviceLayer, "Not implemented"); |
| return CHIP_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| void ThreadStackManagerImpl::_ResetThreadNetworkDiagnosticsCounts() {} |
| |
| CHIP_ERROR |
| ThreadStackManagerImpl::_AttachToThreadNetwork(const Thread::OperationalDataset & dataset, |
| NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * callback) |
| { |
| // Reset the previously set callback since it will never be called in case incorrect dataset was supplied. |
| mpConnectCallback = nullptr; |
| ReturnErrorOnFailure(DeviceLayer::ThreadStackMgr().SetThreadEnabled(false)); |
| ReturnErrorOnFailure(DeviceLayer::ThreadStackMgr().SetThreadProvision(dataset.AsByteSpan())); |
| |
| if (dataset.IsCommissioned()) |
| { |
| ReturnErrorOnFailure(DeviceLayer::ThreadStackMgr().SetThreadEnabled(true)); |
| mpConnectCallback = callback; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| ThreadStackManager & ThreadStackMgr() |
| { |
| return DeviceLayer::ThreadStackManagerImpl::sInstance; |
| } |
| |
| ThreadStackManagerImpl & ThreadStackMgrImpl() |
| { |
| return DeviceLayer::ThreadStackManagerImpl::sInstance; |
| } |
| |
| #if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT |
| CHIP_ERROR ThreadStackManagerImpl::_AddSrpService(const char * aInstanceName, const char * aName, uint16_t aPort, |
| const Span<const char * const> & aSubTypes, |
| const Span<const Dnssd::TextEntry> & aTxtEntries, uint32_t aLeaseInterval, |
| uint32_t aKeyLeaseInterval) |
| { |
| VerifyOrReturnError(mIsInitialized, CHIP_ERROR_UNINITIALIZED); |
| VerifyOrReturnError(aInstanceName != nullptr, CHIP_ERROR_INVALID_ARGUMENT); |
| VerifyOrReturnError(aName != nullptr, CHIP_ERROR_INVALID_ARGUMENT); |
| |
| int threadErr; |
| |
| std::vector<thread_dns_txt_entry_s> entries; |
| entries.reserve(aTxtEntries.size()); |
| |
| thread_dns_txt_entry_s * ee = entries.data(); |
| for (auto & entry : aTxtEntries) |
| { |
| ee->key = entry.mKey; |
| ee->value = entry.mData; |
| VerifyOrReturnError(chip::CanCastTo<uint8_t>(entry.mDataSize), CHIP_ERROR_INVALID_ARGUMENT); |
| ee->value_len = static_cast<uint8_t>(entry.mDataSize); |
| ee++; |
| } |
| |
| VerifyOrReturnError(chip::CanCastTo<uint8_t>(entries.size()), CHIP_ERROR_INVALID_ARGUMENT); |
| threadErr = thread_srp_client_register_service_full(mThreadInstance, aInstanceName, aName, aPort, 0, 0, entries.data(), |
| static_cast<uint8_t>(entries.size())); |
| VerifyOrReturnError(threadErr == THREAD_ERROR_NONE || threadErr == THREAD_ERROR_ALREADY_DONE, CHIP_ERROR_INTERNAL, |
| ChipLogError(DeviceLayer, "FAIL: Register Thread SRP client service: %s", get_error_message(threadErr))); |
| |
| SrpClientService service; |
| Platform::CopyString(service.mInstanceName, aInstanceName); |
| Platform::CopyString(service.mName, aName); |
| service.mPort = aPort; |
| mSrpClientServices.push_back(service); |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_RemoveSrpService(const char * aInstanceName, const char * aName) |
| { |
| VerifyOrReturnError(mIsInitialized, CHIP_ERROR_UNINITIALIZED); |
| VerifyOrReturnError(aInstanceName != nullptr, CHIP_ERROR_INVALID_ARGUMENT); |
| VerifyOrReturnError(aName != nullptr, CHIP_ERROR_INVALID_ARGUMENT); |
| |
| int threadErr; |
| |
| threadErr = thread_srp_client_remove_service(mThreadInstance, aInstanceName, aName); |
| VerifyOrReturnError(threadErr == THREAD_ERROR_NONE, CHIP_ERROR_INTERNAL, |
| ChipLogError(DeviceLayer, "FAIL: Remove Thread SRP client service: %s", get_error_message(threadErr))); |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_InvalidateAllSrpServices() |
| { |
| for (auto & service : mSrpClientServices) |
| { |
| service.mValid = false; |
| } |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_RemoveInvalidSrpServices() |
| { |
| for (auto it = mSrpClientServices.begin(); it != mSrpClientServices.end();) |
| { |
| if (!it->mValid) |
| { |
| auto err = _RemoveSrpService(it->mInstanceName, it->mName); |
| VerifyOrReturnError(err == CHIP_NO_ERROR, err); |
| it = mSrpClientServices.erase(it); |
| } |
| else |
| { |
| ++it; |
| } |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_ClearAllSrpHostAndServices() |
| { |
| for (auto it = mSrpClientServices.begin(); it != mSrpClientServices.end();) |
| { |
| ReturnErrorOnFailure(_RemoveSrpService(it->mInstanceName, it->mName)); |
| it = mSrpClientServices.erase(it); |
| } |
| return CHIP_NO_ERROR; |
| } |
| |
| void ThreadStackManagerImpl::_ThreadIpAddressCb(int index, char * ipAddr, thread_ipaddr_type_e ipAddrType, void * userData) |
| { |
| VerifyOrReturn(ipAddr != nullptr, ChipLogError(DeviceLayer, "FAIL: Invalid argument: Thread ipAddr not found")); |
| VerifyOrReturn(strlen(ipAddr) >= 6, ChipLogError(DeviceLayer, "FAIL: Invalid Thread ipAddr")); |
| |
| ChipLogProgress(DeviceLayer, "_ThreadIpAddressCb index:[%d] ipAddr:[%s] type:[%d]", index, ipAddr, ipAddrType); |
| |
| if (ipAddrType != THREAD_IPADDR_TYPE_MLEID) |
| return; |
| |
| auto threadErr = thread_srp_client_set_host_address(sInstance.mThreadInstance, ipAddr); |
| VerifyOrReturn(threadErr == THREAD_ERROR_NONE || threadErr == THREAD_ERROR_ALREADY_DONE, |
| ChipLogError(DeviceLayer, "FAIL: Set Thread SRP client host address: %s", get_error_message(threadErr))); |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_SetupSrpHost(const char * aHostName) |
| { |
| VerifyOrReturnError(mIsInitialized, CHIP_ERROR_UNINITIALIZED); |
| VerifyOrReturnError(aHostName != nullptr, CHIP_ERROR_INVALID_ARGUMENT); |
| VerifyOrReturnError(strlen(aHostName) <= Dnssd::kHostNameMaxLength, CHIP_ERROR_INVALID_STRING_LENGTH); |
| |
| int threadErr; |
| |
| threadErr = thread_srp_client_set_host_name(mThreadInstance, aHostName); |
| if (threadErr != THREAD_ERROR_NONE && threadErr != THREAD_ERROR_ALREADY_DONE) |
| ChipLogError(DeviceLayer, "FAIL: Set Thread SRP client host name: %s", get_error_message(threadErr)); |
| |
| /* Get external IP address */ |
| threadErr = thread_get_ipaddr(mThreadInstance, _ThreadIpAddressCb, THREAD_IPADDR_TYPE_MLEID, nullptr); |
| VerifyOrReturnError(threadErr == THREAD_ERROR_NONE, CHIP_ERROR_INTERNAL, |
| ChipLogError(DeviceLayer, "FAIL: Get Thread IP address: %s", get_error_message(threadErr))); |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_ClearSrpHost(const char * aHostName) |
| { |
| ChipLogError(DeviceLayer, "Not implemented"); |
| return CHIP_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_DnsBrowse(const char * aServiceName, DnsBrowseCallback aCallback, void * aContext) |
| { |
| return CHIP_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| CHIP_ERROR ThreadStackManagerImpl::_DnsResolve(const char * aServiceName, const char * aInstanceName, DnsResolveCallback aCallback, |
| void * aContext) |
| { |
| return CHIP_ERROR_NOT_IMPLEMENTED; |
| } |
| |
| #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT |
| } // namespace DeviceLayer |
| } // namespace chip |