diff --git a/examples/all-clusters-app/esp32/main/main.cpp b/examples/all-clusters-app/esp32/main/main.cpp index 94bf4afcc2e5e2..6d9c4e2c488af4 100644 --- a/examples/all-clusters-app/esp32/main/main.cpp +++ b/examples/all-clusters-app/esp32/main/main.cpp @@ -111,8 +111,10 @@ static void InitServer(intptr_t context) { Esp32AppServer::Init(&sCallbacks); // Init ZCL Data Model and CHIP App Server AND Initialize device attestation config +#if !(CHIP_DEVICE_CONFIG_ENABLE_WIFI && CHIP_DEVICE_CONFIG_ENABLE_THREAD) // We only have network commissioning on endpoint 0. emberAfEndpointEnableDisable(kNetworkCommissioningEndpointSecondary, false); +#endif CHIP_ERROR err = GetAppTask().LockInit(); if (err != CHIP_NO_ERROR) diff --git a/examples/all-clusters-app/esp32/partitions.csv b/examples/all-clusters-app/esp32/partitions.csv index efe7f6e9caf0e4..2211b30fa01a74 100644 --- a/examples/all-clusters-app/esp32/partitions.csv +++ b/examples/all-clusters-app/esp32/partitions.csv @@ -3,6 +3,6 @@ nvs, data, nvs, , 0x6000, otadata, data, ota, , 0x2000, phy_init, data, phy, , 0x1000, -ota_0, app, ota_0, , 1700K, -ota_1, app, ota_1, , 1700K, +ota_0, app, ota_0, , 1900K, +ota_1, app, ota_1, , 1900K, ot_storage, data, 0x3a, , 0x2000, diff --git a/examples/platform/esp32/common/Esp32AppServer.cpp b/examples/platform/esp32/common/Esp32AppServer.cpp index 91120707b9504c..06bb0d9a6c6c0b 100644 --- a/examples/platform/esp32/common/Esp32AppServer.cpp +++ b/examples/platform/esp32/common/Esp32AppServer.cpp @@ -33,8 +33,13 @@ static constexpr char TAG[] = "ESP32Appserver"; namespace { #if CHIP_DEVICE_CONFIG_ENABLE_WIFI +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +constexpr chip::EndpointId kNetworkCommissioningEndpointWiFi = 0xFFFE; +#else +constexpr chip::EndpointId kNetworkCommissioningEndpointWiFi = 0; +#endif app::Clusters::NetworkCommissioning::Instance - sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::ESPWiFiDriver::GetInstance())); + sWiFiNetworkCommissioningInstance(kNetworkCommissioningEndpointWiFi, &(NetworkCommissioning::ESPWiFiDriver::GetInstance())); #elif CHIP_DEVICE_CONFIG_ENABLE_ETHERNET static app::Clusters::NetworkCommissioning::Instance sEthernetNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::ESPEthernetDriver::GetInstance())); diff --git a/src/platform/ESP32/BUILD.gn b/src/platform/ESP32/BUILD.gn index 66cf6279dfc6f8..367c445c3ace71 100644 --- a/src/platform/ESP32/BUILD.gn +++ b/src/platform/ESP32/BUILD.gn @@ -125,15 +125,18 @@ static_library("ESP32") { ] if (chip_mdns == "platform") { sources += [ - "DnssdImpl.cpp", - "DnssdImpl.h", + "WiFiDnssdImpl.cpp", + "WiFiDnssdImpl.h", ] } } + if (chip_mdns == "platform") { + sources += [ "DnssdImpl.cpp" ] + } + if (chip_enable_openthread) { sources += [ - "../OpenThread/DnssdImpl.cpp", "../OpenThread/GenericNetworkCommissioningThreadDriver.cpp", "../OpenThread/GenericNetworkCommissioningThreadDriver.h", "../OpenThread/OpenThreadUtils.cpp", @@ -143,6 +146,12 @@ static_library("ESP32") { "ThreadStackManagerImpl.cpp", "ThreadStackManagerImpl.h", ] + if (chip_mdns == "platform") { + sources += [ + "../OpenThread/OpenThreadDnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.h", + ] + } configs -= [ "${chip_root}/build/config/compiler:warnings_default" ] } diff --git a/src/platform/ESP32/DnssdImpl.cpp b/src/platform/ESP32/DnssdImpl.cpp index a16659a642141d..37d33f9d13903a 100644 --- a/src/platform/ESP32/DnssdImpl.cpp +++ b/src/platform/ESP32/DnssdImpl.cpp @@ -15,568 +15,99 @@ * limitations under the License. */ -#include "DnssdImpl.h" #include "lib/dnssd/platform/Dnssd.h" - -#include -#include -#include - #include "platform/CHIPDeviceLayer.h" + #include #include #include +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD +#include +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI +#include +#endif -namespace { - -static constexpr uint32_t kTimeoutMilli = 3000; -static constexpr size_t kMaxResults = 20; - -} // namespace +using namespace ::chip::DeviceLayer; namespace chip { namespace Dnssd { -struct MdnsQuery -{ - GenericContext * ctx; - MdnsQuery * next; -}; - -static MdnsQuery * sQueryList = nullptr; -static void MdnsQueryNotifier(mdns_search_once_t * queryHandle); - -static CHIP_ERROR AddQueryList(GenericContext * ctx) -{ - MdnsQuery * ret = static_cast(chip::Platform::MemoryAlloc(sizeof(MdnsQuery))); - if (ret == nullptr) - { - ChipLogError(DeviceLayer, "Failed to alloc memory for MdnsQuery"); - return CHIP_ERROR_NO_MEMORY; - } - ret->ctx = ctx; - ret->next = sQueryList; - sQueryList = ret; - return CHIP_NO_ERROR; -} - -static GenericContext * FindMdnsQuery(mdns_search_once_t * queryHandle) -{ - MdnsQuery * current = sQueryList; - while (current) - { - if (current->ctx) - { - if (current->ctx->mContextType == ContextType::Browse) - { - BrowseContext * browseCtx = reinterpret_cast(current->ctx); - if (browseCtx->mPtrQueryHandle == queryHandle) - { - return current->ctx; - } - } - else if (current->ctx->mContextType == ContextType::Resolve) - { - ResolveContext * resolveCtx = reinterpret_cast(current->ctx); - if (resolveCtx->mSrvQueryHandle == queryHandle || resolveCtx->mTxtQueryHandle == queryHandle) - { - return current->ctx; - } - } - } - current = current->next; - } - return nullptr; -} - -static CHIP_ERROR RemoveMdnsQuery(GenericContext * ctx) -{ - MdnsQuery * current = sQueryList; - MdnsQuery * front = nullptr; - - VerifyOrReturnError(ctx != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - while (current) - { - if (current->ctx == ctx) - { - break; - } - front = current; - current = current->next; - } - if (!current) - { - return CHIP_ERROR_NOT_FOUND; - } - if (front) - { - front->next = current->next; - } - else - { - sQueryList = current->next; - } - if (current->ctx->mContextType == ContextType::Browse) - { - chip::Platform::Delete(reinterpret_cast(current->ctx)); - } - else if (ctx->mContextType == ContextType::Resolve) - { - chip::Platform::Delete(reinterpret_cast(current->ctx)); - } - chip::Platform::MemoryFree(current); - return CHIP_NO_ERROR; -} - CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context) { - CHIP_ERROR error = CHIP_NO_ERROR; - esp_err_t espError; - - espError = mdns_init(); - VerifyOrExit(espError == ESP_OK, error = CHIP_ERROR_INTERNAL); - -exit: - if (espError != ESP_OK) - { - ChipLogError(DeviceLayer, "esp mdns internal error: %s", esp_err_to_name(espError)); - } - initCallback(context, error); - - return error; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + ReturnErrorOnFailure(WiFiDnssdInit(initCallback, errorCallback, context)); +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + ReturnErrorOnFailure(OpenThreadDnssdInit(initCallback, errorCallback, context)); +#endif + return CHIP_NO_ERROR; } void ChipDnssdShutdown() {} -static const char * GetProtocolString(DnssdServiceProtocol protocol) -{ - return protocol == DnssdServiceProtocol::kDnssdProtocolTcp ? "_tcp" : "_udp"; -} - CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context) { - CHIP_ERROR error = CHIP_NO_ERROR; - mdns_txt_item_t * items = nullptr; - esp_err_t espError; - - if (strcmp(service->mHostName, "") != 0) +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + if (ConnectivityMgr().IsWiFiStationProvisioned()) { - VerifyOrExit(mdns_hostname_set(service->mHostName) == ESP_OK, error = CHIP_ERROR_INTERNAL); - } - - VerifyOrExit(service->mTextEntrySize <= UINT8_MAX, error = CHIP_ERROR_INVALID_ARGUMENT); - if (service->mTextEntries) - { - items = static_cast(chip::Platform::MemoryCalloc(service->mTextEntrySize, sizeof(mdns_txt_item_t))); - VerifyOrExit(items != nullptr, error = CHIP_ERROR_NO_MEMORY); - for (size_t i = 0; i < service->mTextEntrySize; i++) - { - items[i].key = service->mTextEntries[i].mKey; - // Unfortunately ESP mdns stack doesn't support arbitrary binary data - items[i].value = reinterpret_cast(service->mTextEntries[i].mData); - } - } - - espError = mdns_service_add(service->mName, service->mType, GetProtocolString(service->mProtocol), service->mPort, items, - service->mTextEntrySize); - // The mdns_service_add will return error if we try to add an existing service - if (espError != ESP_OK && espError != ESP_ERR_NO_MEM) - { - espError = mdns_service_txt_set(service->mType, GetProtocolString(service->mProtocol), items, - static_cast(service->mTextEntrySize)); - } -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) - for (size_t i = 0; i < service->mSubTypeSize; i++) - { - mdns_service_subtype_add_for_host(service->mName, service->mType, GetProtocolString(service->mProtocol), service->mHostName, - service->mSubTypes[i]); + ReturnErrorOnFailure(WiFiDnssdPublishService(service, callback, context)); } #endif - VerifyOrExit(espError == ESP_OK, error = CHIP_ERROR_INTERNAL); - -exit: - if (items != nullptr) +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + if (ConnectivityMgr().IsThreadProvisioned()) { - chip::Platform::MemoryFree(items); + ReturnErrorOnFailure(OpenThreadDnssdPublishService(service, callback, context)); } - - return error; -} - -CHIP_ERROR ChipDnssdRemoveServices() -{ - mdns_service_remove("_matter", "_tcp"); - mdns_service_remove("_matterc", "_udp"); - return CHIP_NO_ERROR; -} - -CHIP_ERROR ChipDnssdFinalizeServiceUpdate() -{ - return CHIP_NO_ERROR; -} - -static Inet::IPAddressType MapAddressType(mdns_ip_protocol_t ip_protocol) -{ - switch (ip_protocol) - { -#if INET_CONFIG_ENABLE_IPV4 - case MDNS_IP_PROTOCOL_V4: - return Inet::IPAddressType::kIPv4; #endif - case MDNS_IP_PROTOCOL_V6: - return Inet::IPAddressType::kIPv6; - default: - return Inet::IPAddressType::kAny; - } -} - -static TextEntry * GetTextEntry(mdns_txt_item_t * txt_array, uint8_t * txt_value_len, size_t txt_count) -{ - if (txt_count == 0 || txt_array == NULL) - { - return NULL; - } - TextEntry * ret = static_cast(chip::Platform::MemoryCalloc(txt_count, sizeof(TextEntry))); - if (ret) - { - for (size_t TextEntryIndex = 0; TextEntryIndex < txt_count; ++TextEntryIndex) - { - ret[TextEntryIndex].mKey = txt_array[TextEntryIndex].key; - ret[TextEntryIndex].mData = reinterpret_cast(txt_array[TextEntryIndex].value); - ret[TextEntryIndex].mDataSize = txt_value_len[TextEntryIndex]; - } - } - return ret; -} - -static CHIP_ERROR GetIPAddress(Inet::IPAddress & outIPAddress, mdns_ip_addr_t * mdnsIPAddr) -{ - if (!mdnsIPAddr) - { - return CHIP_ERROR_INVALID_ARGUMENT; - } - if (mdnsIPAddr->addr.type == ESP_IPADDR_TYPE_V6) - { - memcpy(outIPAddress.Addr, mdnsIPAddr->addr.u_addr.ip6.addr, sizeof(mdnsIPAddr->addr.u_addr.ip6.addr)); - } - else if (mdnsIPAddr->addr.type == ESP_IPADDR_TYPE_V4) - { - outIPAddress.Addr[0] = 0; - outIPAddress.Addr[1] = 0; - outIPAddress.Addr[2] = htonl(0xFFFF); - outIPAddress.Addr[3] = mdnsIPAddr->addr.u_addr.ip4.addr; - } - else - { - outIPAddress = Inet::IPAddress::Any; - } return CHIP_NO_ERROR; } -size_t GetResultSize(mdns_result_t * result) -{ - size_t ret = 0; - while (result) - { - ret++; - result = result->next; - } - return ret; -} - -static CHIP_ERROR OnBrowseDone(BrowseContext * ctx) -{ - CHIP_ERROR error = CHIP_NO_ERROR; - mdns_result_t * currentResult = nullptr; - size_t servicesIndex = 0; - VerifyOrExit(ctx && ctx->mBrowseCb, error = CHIP_ERROR_INVALID_ARGUMENT); - if (ctx->mPtrQueryResult) - { - ctx->mServiceSize = GetResultSize(ctx->mPtrQueryResult); - if (ctx->mServiceSize > 0) - { - ctx->mService = static_cast(chip::Platform::MemoryCalloc(ctx->mServiceSize, sizeof(DnssdService))); - if (!ctx->mService) - { - ChipLogError(DeviceLayer, "Failed to alloc memory for Dnssd services"); - ctx->mServiceSize = 0; - error = CHIP_ERROR_NO_MEMORY; - ExitNow(); - } - currentResult = ctx->mPtrQueryResult; - servicesIndex = 0; - while (currentResult) - { - Platform::CopyString(ctx->mService[servicesIndex].mName, currentResult->instance_name); - Platform::CopyString(ctx->mService[servicesIndex].mHostName, currentResult->hostname); - Platform::CopyString(ctx->mService[servicesIndex].mType, currentResult->service_type); - ctx->mService[servicesIndex].mProtocol = ctx->mProtocol; - ctx->mService[servicesIndex].mAddressType = MapAddressType(currentResult->ip_protocol); - ctx->mService[servicesIndex].mTransportType = ctx->mAddressType; - ctx->mService[servicesIndex].mPort = currentResult->port; - ctx->mService[servicesIndex].mInterface = ctx->mInterfaceId; - ctx->mService[servicesIndex].mTextEntries = - GetTextEntry(currentResult->txt, currentResult->txt_value_len, currentResult->txt_count); - ctx->mService[servicesIndex].mTextEntrySize = currentResult->txt_count; - ctx->mService[servicesIndex].mSubTypes = NULL; - ctx->mService[servicesIndex].mSubTypeSize = 0; - if (currentResult->addr) - { - Inet::IPAddress IPAddr; - error = GetIPAddress(IPAddr, currentResult->addr); - SuccessOrExit(error); - ctx->mService[servicesIndex].mAddress.SetValue(IPAddr); - } - currentResult = currentResult->next; - servicesIndex++; - } - } - } -exit: - ctx->mBrowseCb(ctx->mCbContext, ctx->mService, ctx->mServiceSize, true, error); - return RemoveMdnsQuery(reinterpret_cast(ctx)); -} - -size_t GetAddressCount(mdns_ip_addr_t * addr) -{ - size_t ret = 0; - while (addr) - { - ret++; - addr = addr->next; - } - return ret; -} - -static CHIP_ERROR ParseIPAddresses(ResolveContext * ctx) -{ - size_t addressIndex = 0; - if (ctx->mAddrQueryResult && ctx->mAddrQueryResult->addr) - { - ctx->mAddressCount = GetAddressCount(ctx->mAddrQueryResult->addr); - if (ctx->mAddressCount > 0) - { - ctx->mAddresses = - static_cast(chip::Platform::MemoryCalloc(ctx->mAddressCount, sizeof(Inet::IPAddress))); - if (ctx->mAddresses == nullptr) - { - ChipLogError(DeviceLayer, "Failed to alloc memory for addresses"); - ctx->mAddressCount = 0; - return CHIP_ERROR_NO_MEMORY; - } - auto * addr = ctx->mAddrQueryResult->addr; - while (addr) - { - GetIPAddress(ctx->mAddresses[addressIndex], addr); - addressIndex++; - addr = addr->next; - } - return CHIP_NO_ERROR; - } - } - return CHIP_ERROR_INVALID_ARGUMENT; -} - -static CHIP_ERROR ParseSrvResult(ResolveContext * ctx) -{ - if (ctx->mSrvQueryResult) - { - if (!ctx->mService) - { - ctx->mService = static_cast(chip::Platform::MemoryAlloc(sizeof(DnssdService))); - } - VerifyOrReturnError(ctx->mService, CHIP_ERROR_NO_MEMORY); - ctx->mServiceSize = 1; - Platform::CopyString(ctx->mService->mName, ctx->mSrvQueryResult->instance_name); - Platform::CopyString(ctx->mService->mHostName, ctx->mSrvQueryResult->hostname); - Platform::CopyString(ctx->mService->mType, ctx->mSrvQueryResult->service_type); - ctx->mService->mProtocol = ctx->mProtocol; - ctx->mService->mAddressType = MapAddressType(ctx->mSrvQueryResult->ip_protocol); - ctx->mService->mTransportType = ctx->mService->mAddressType; - ctx->mService->mPort = ctx->mSrvQueryResult->port; - ctx->mService->mInterface = ctx->mInterfaceId; - ctx->mService->mSubTypes = nullptr; - ctx->mService->mSubTypeSize = 0; - return CHIP_NO_ERROR; - } - else - { - ctx->mService = nullptr; - ctx->mServiceSize = 0; - } - return CHIP_ERROR_INVALID_ARGUMENT; -} - -// ParseTxtResult should be called after ParseSrvResult -static CHIP_ERROR ParseTxtResult(ResolveContext * ctx) +CHIP_ERROR ChipDnssdRemoveServices() { - VerifyOrReturnError(ctx->mService, CHIP_ERROR_INCORRECT_STATE); - if (ctx->mTxtQueryResult) +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + if (ConnectivityMgr().IsWiFiStationProvisioned()) { - ctx->mService->mTextEntries = - GetTextEntry(ctx->mTxtQueryResult->txt, ctx->mTxtQueryResult->txt_value_len, ctx->mTxtQueryResult->txt_count); - ctx->mService->mTextEntrySize = ctx->mTxtQueryResult->txt_count; + ReturnErrorOnFailure(WiFiDnssdRemoveServices()); } - else +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + if (ConnectivityMgr().IsThreadProvisioned()) { - ctx->mService->mTextEntries = nullptr; - ctx->mService->mTextEntrySize = 0; + ReturnErrorOnFailure(OpenThreadDnssdRemoveServices()); } +#endif return CHIP_NO_ERROR; } -static CHIP_ERROR OnResolveDone(ResolveContext * ctx) +CHIP_ERROR ChipDnssdFinalizeServiceUpdate() { - CHIP_ERROR error = CHIP_NO_ERROR; - - VerifyOrExit(ctx && ctx->mResolveCb, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(!ctx->mService && ctx->mSrvAddrQueryFinished && ctx->mTxtQueryFinished, error = CHIP_ERROR_INCORRECT_STATE); - error = ParseSrvResult(ctx); - SuccessOrExit(error); - error = ParseIPAddresses(ctx); - SuccessOrExit(error); - error = ParseTxtResult(ctx); - SuccessOrExit(error); -exit: - if (error != CHIP_NO_ERROR) - { - ctx->mResolveCb(ctx->mCbContext, nullptr, Span(nullptr, 0), error); - } - else +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + if (ConnectivityMgr().IsThreadProvisioned()) { - ctx->mResolveCb(ctx->mCbContext, ctx->mService, Span(ctx->mAddresses, ctx->mAddressCount), error); + ReturnErrorOnFailure(OpenThreadDnssdFinalizeServiceUpdate()); } - RemoveMdnsQuery(reinterpret_cast(ctx)); - return error; -} - -static mdns_result_t * MdnsQueryGetResults(mdns_search_once_t * queryHandle) -{ - mdns_result_t * ret = nullptr; -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) - if (mdns_query_async_get_results(queryHandle, kTimeoutMilli, &ret, NULL)) -#else - if (mdns_query_async_get_results(queryHandle, kTimeoutMilli, &ret)) #endif - { - return ret; - } - return nullptr; -} - -static void MdnsQueryDone(intptr_t context) -{ - if (!context) - { - return; - } - mdns_search_once_t * queryHandle = reinterpret_cast(context); - mdns_result_t * result = MdnsQueryGetResults(queryHandle); - GenericContext * ctx = FindMdnsQuery(queryHandle); - if (!ctx) - { - mdns_query_results_free(result); - mdns_query_async_delete(queryHandle); - return; - } - if (ctx->mContextType == ContextType::Browse) - { - BrowseContext * browseCtx = reinterpret_cast(ctx); - browseCtx->mPtrQueryResult = result; - OnBrowseDone(browseCtx); - } - else if (ctx->mContextType == ContextType::Resolve) - { - - ResolveContext * resolveCtx = reinterpret_cast(ctx); - if (resolveCtx->mSrvQueryHandle == queryHandle) - { - // No result found. - if (!result) - { - resolveCtx->mResolveCb(ctx->mCbContext, nullptr, Span(nullptr, 0), CHIP_ERROR_INVALID_ARGUMENT); - RemoveMdnsQuery(ctx); - return; - } - // If SRV Query Result is empty, the result is for SRV Query. - if (!resolveCtx->mSrvQueryResult) - { - resolveCtx->mSrvQueryResult = result; - if (result->addr) - { - resolveCtx->mAddrQueryResult = result; - resolveCtx->mSrvAddrQueryFinished = true; - } - else - { - // If there is no A/AAAA records in SRV query response, we will send an AAAA query for the IP addresses. - mdns_query_async_delete(resolveCtx->mSrvQueryHandle); - resolveCtx->mAddrQueryResult = nullptr; - resolveCtx->mSrvQueryHandle = mdns_query_async_new(result->hostname, NULL, NULL, MDNS_TYPE_AAAA, kTimeoutMilli, - kMaxResults, MdnsQueryNotifier); - if (!resolveCtx->mSrvQueryHandle) - { - resolveCtx->mResolveCb(ctx->mCbContext, nullptr, Span(nullptr, 0), CHIP_ERROR_NO_MEMORY); - RemoveMdnsQuery(ctx); - return; - } - } - } - else if (!resolveCtx->mAddrQueryResult) - { - resolveCtx->mAddrQueryResult = result; - resolveCtx->mSrvAddrQueryFinished = true; - } - else - { - resolveCtx->mResolveCb(ctx->mCbContext, nullptr, Span(nullptr, 0), CHIP_ERROR_INCORRECT_STATE); - RemoveMdnsQuery(ctx); - return; - } - } - else if (resolveCtx->mTxtQueryHandle == queryHandle) - { - resolveCtx->mTxtQueryResult = result; - resolveCtx->mTxtQueryFinished = true; - } - if (resolveCtx->mTxtQueryFinished && resolveCtx->mSrvAddrQueryFinished) - { - OnResolveDone(resolveCtx); - } - } -} - -static void MdnsQueryNotifier(mdns_search_once_t * searchHandle) -{ - chip::DeviceLayer::PlatformMgr().ScheduleWork(MdnsQueryDone, reinterpret_cast(searchHandle)); + return CHIP_NO_ERROR; } CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType, chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, intptr_t * browseIdentifier) { - CHIP_ERROR error = CHIP_NO_ERROR; - mdns_search_once_t * queryHandle = - mdns_query_async_new(NULL, type, GetProtocolString(protocol), MDNS_TYPE_PTR, kTimeoutMilli, kMaxResults, MdnsQueryNotifier); - VerifyOrReturnError(queryHandle, CHIP_ERROR_NO_MEMORY); - BrowseContext * ctx = - chip::Platform::New(type, protocol, interface, queryHandle, addressType, callback, context); - if (!ctx) +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + if (ConnectivityMgr().IsWiFiStationProvisioned()) { - ChipLogError(DeviceLayer, "Failed to alloc memory for browse context"); - mdns_query_async_delete(queryHandle); - return CHIP_ERROR_NO_MEMORY; + ReturnErrorOnFailure(WiFiDnssdBrowse(type, protocol, addressType, interface, callback, context, browseIdentifier)); } - error = AddQueryList(reinterpret_cast(ctx)); - if (error != CHIP_NO_ERROR) - { - chip::Platform::Delete(ctx); - } - else +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + if (ConnectivityMgr().IsThreadProvisioned()) { - *browseIdentifier = reinterpret_cast(nullptr); + ReturnErrorOnFailure(OpenThreadDnssdBrowse(type, protocol, addressType, interface, callback, context, browseIdentifier)); } - return error; +#endif + return CHIP_NO_ERROR; } CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier) @@ -587,31 +118,19 @@ CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier) CHIP_ERROR ChipDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interface, DnssdResolveCallback callback, void * context) { - CHIP_ERROR error = CHIP_NO_ERROR; - mdns_search_once_t * querySrv = mdns_query_async_new(service->mName, service->mType, GetProtocolString(service->mProtocol), - MDNS_TYPE_SRV, kTimeoutMilli, kMaxResults, MdnsQueryNotifier); - VerifyOrReturnError(querySrv, CHIP_ERROR_NO_MEMORY); - mdns_search_once_t * queryTxt = mdns_query_async_new(service->mName, service->mType, GetProtocolString(service->mProtocol), - MDNS_TYPE_TXT, kTimeoutMilli, kMaxResults, MdnsQueryNotifier); - if (!queryTxt) +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI + if (ConnectivityMgr().IsWiFiStationProvisioned()) { - mdns_query_async_delete(querySrv); - return CHIP_ERROR_NO_MEMORY; + ReturnErrorOnFailure(WiFiDnssdResolve(service, interface, callback, context)); } - ResolveContext * ctx = chip::Platform::New(service, interface, querySrv, queryTxt, callback, context); - if (!ctx) - { - ChipLogError(DeviceLayer, "Failed to alloc memory for resolve context"); - mdns_query_async_delete(querySrv); - mdns_query_async_delete(queryTxt); - return CHIP_ERROR_NO_MEMORY; - } - error = AddQueryList(reinterpret_cast(ctx)); - if (error != CHIP_NO_ERROR) +#endif +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + if (ConnectivityMgr().IsThreadProvisioned()) { - chip::Platform::Delete(ctx); + ReturnErrorOnFailure(OpenThreadDnssdResolve(service, interface, callback, context)); } - return error; +#endif + return CHIP_NO_ERROR; } void ChipDnssdResolveNoLongerNeeded(const char * instanceName) {} diff --git a/src/platform/ESP32/WiFiDnssdImpl.cpp b/src/platform/ESP32/WiFiDnssdImpl.cpp new file mode 100644 index 00000000000000..4900bf08b37002 --- /dev/null +++ b/src/platform/ESP32/WiFiDnssdImpl.cpp @@ -0,0 +1,606 @@ +/* + * + * Copyright (c) 2020-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. + */ + +#include "WiFiDnssdImpl.h" +#include "lib/dnssd/platform/Dnssd.h" + +#include +#include +#include + +#include "platform/CHIPDeviceLayer.h" +#include +#include +#include + +namespace { + +static constexpr uint32_t kTimeoutMilli = 3000; +static constexpr size_t kMaxResults = 20; + +} // namespace + +namespace chip { +namespace Dnssd { + +struct MdnsQuery +{ + GenericContext * ctx; + MdnsQuery * next; +}; + +static MdnsQuery * sQueryList = nullptr; +static void MdnsQueryNotifier(mdns_search_once_t * queryHandle); + +static CHIP_ERROR AddQueryList(GenericContext * ctx) +{ + MdnsQuery * ret = static_cast(chip::Platform::MemoryAlloc(sizeof(MdnsQuery))); + if (ret == nullptr) + { + ChipLogError(DeviceLayer, "Failed to alloc memory for MdnsQuery"); + return CHIP_ERROR_NO_MEMORY; + } + ret->ctx = ctx; + ret->next = sQueryList; + sQueryList = ret; + return CHIP_NO_ERROR; +} + +static GenericContext * FindMdnsQuery(mdns_search_once_t * queryHandle) +{ + MdnsQuery * current = sQueryList; + while (current) + { + if (current->ctx) + { + if (current->ctx->mContextType == ContextType::Browse) + { + BrowseContext * browseCtx = reinterpret_cast(current->ctx); + if (browseCtx->mPtrQueryHandle == queryHandle) + { + return current->ctx; + } + } + else if (current->ctx->mContextType == ContextType::Resolve) + { + ResolveContext * resolveCtx = reinterpret_cast(current->ctx); + if (resolveCtx->mSrvQueryHandle == queryHandle || resolveCtx->mTxtQueryHandle == queryHandle) + { + return current->ctx; + } + } + } + current = current->next; + } + return nullptr; +} + +static CHIP_ERROR RemoveMdnsQuery(GenericContext * ctx) +{ + MdnsQuery * current = sQueryList; + MdnsQuery * front = nullptr; + + VerifyOrReturnError(ctx != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + while (current) + { + if (current->ctx == ctx) + { + break; + } + front = current; + current = current->next; + } + if (!current) + { + return CHIP_ERROR_NOT_FOUND; + } + if (front) + { + front->next = current->next; + } + else + { + sQueryList = current->next; + } + if (current->ctx->mContextType == ContextType::Browse) + { + chip::Platform::Delete(reinterpret_cast(current->ctx)); + } + else if (ctx->mContextType == ContextType::Resolve) + { + chip::Platform::Delete(reinterpret_cast(current->ctx)); + } + chip::Platform::MemoryFree(current); + return CHIP_NO_ERROR; +} + +CHIP_ERROR WiFiDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + esp_err_t espError; + + espError = mdns_init(); + VerifyOrExit(espError == ESP_OK, error = CHIP_ERROR_INTERNAL); + +exit: + if (espError != ESP_OK) + { + ChipLogError(DeviceLayer, "esp mdns internal error: %s", esp_err_to_name(espError)); + } + initCallback(context, error); + + return error; +} + +static const char * GetProtocolString(DnssdServiceProtocol protocol) +{ + return protocol == DnssdServiceProtocol::kDnssdProtocolTcp ? "_tcp" : "_udp"; +} + +CHIP_ERROR WiFiDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + mdns_txt_item_t * items = nullptr; + esp_err_t espError; + + if (strcmp(service->mHostName, "") != 0) + { + VerifyOrExit(mdns_hostname_set(service->mHostName) == ESP_OK, error = CHIP_ERROR_INTERNAL); + } + + VerifyOrExit(service->mTextEntrySize <= UINT8_MAX, error = CHIP_ERROR_INVALID_ARGUMENT); + if (service->mTextEntries) + { + items = static_cast(chip::Platform::MemoryCalloc(service->mTextEntrySize, sizeof(mdns_txt_item_t))); + VerifyOrExit(items != nullptr, error = CHIP_ERROR_NO_MEMORY); + for (size_t i = 0; i < service->mTextEntrySize; i++) + { + items[i].key = service->mTextEntries[i].mKey; + // Unfortunately ESP mdns stack doesn't support arbitrary binary data + items[i].value = reinterpret_cast(service->mTextEntries[i].mData); + } + } + + espError = mdns_service_add(service->mName, service->mType, GetProtocolString(service->mProtocol), service->mPort, items, + service->mTextEntrySize); + // The mdns_service_add will return error if we try to add an existing service + if (espError != ESP_OK && espError != ESP_ERR_NO_MEM) + { + espError = mdns_service_txt_set(service->mType, GetProtocolString(service->mProtocol), items, + static_cast(service->mTextEntrySize)); + } +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + for (size_t i = 0; i < service->mSubTypeSize; i++) + { + mdns_service_subtype_add_for_host(service->mName, service->mType, GetProtocolString(service->mProtocol), service->mHostName, + service->mSubTypes[i]); + } +#endif + VerifyOrExit(espError == ESP_OK, error = CHIP_ERROR_INTERNAL); + +exit: + if (items != nullptr) + { + chip::Platform::MemoryFree(items); + } + + return error; +} + +CHIP_ERROR WiFiDnssdRemoveServices() +{ + mdns_service_remove("_matter", "_tcp"); + mdns_service_remove("_matterc", "_udp"); + return CHIP_NO_ERROR; +} + +static Inet::IPAddressType MapAddressType(mdns_ip_protocol_t ip_protocol) +{ + switch (ip_protocol) + { +#if INET_CONFIG_ENABLE_IPV4 + case MDNS_IP_PROTOCOL_V4: + return Inet::IPAddressType::kIPv4; +#endif + case MDNS_IP_PROTOCOL_V6: + return Inet::IPAddressType::kIPv6; + default: + return Inet::IPAddressType::kAny; + } +} + +static TextEntry * GetTextEntry(mdns_txt_item_t * txt_array, uint8_t * txt_value_len, size_t txt_count) +{ + if (txt_count == 0 || txt_array == NULL) + { + return NULL; + } + TextEntry * ret = static_cast(chip::Platform::MemoryCalloc(txt_count, sizeof(TextEntry))); + if (ret) + { + for (size_t TextEntryIndex = 0; TextEntryIndex < txt_count; ++TextEntryIndex) + { + ret[TextEntryIndex].mKey = txt_array[TextEntryIndex].key; + ret[TextEntryIndex].mData = reinterpret_cast(txt_array[TextEntryIndex].value); + ret[TextEntryIndex].mDataSize = txt_value_len[TextEntryIndex]; + } + } + return ret; +} + +static CHIP_ERROR GetIPAddress(Inet::IPAddress & outIPAddress, mdns_ip_addr_t * mdnsIPAddr) +{ + if (!mdnsIPAddr) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + if (mdnsIPAddr->addr.type == ESP_IPADDR_TYPE_V6) + { + memcpy(outIPAddress.Addr, mdnsIPAddr->addr.u_addr.ip6.addr, sizeof(mdnsIPAddr->addr.u_addr.ip6.addr)); + } + else if (mdnsIPAddr->addr.type == ESP_IPADDR_TYPE_V4) + { + outIPAddress.Addr[0] = 0; + outIPAddress.Addr[1] = 0; + outIPAddress.Addr[2] = htonl(0xFFFF); + outIPAddress.Addr[3] = mdnsIPAddr->addr.u_addr.ip4.addr; + } + else + { + outIPAddress = Inet::IPAddress::Any; + } + return CHIP_NO_ERROR; +} + +size_t GetResultSize(mdns_result_t * result) +{ + size_t ret = 0; + while (result) + { + ret++; + result = result->next; + } + return ret; +} + +static CHIP_ERROR OnBrowseDone(BrowseContext * ctx) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + mdns_result_t * currentResult = nullptr; + size_t servicesIndex = 0; + VerifyOrExit(ctx && ctx->mBrowseCb, error = CHIP_ERROR_INVALID_ARGUMENT); + if (ctx->mPtrQueryResult) + { + ctx->mServiceSize = GetResultSize(ctx->mPtrQueryResult); + if (ctx->mServiceSize > 0) + { + ctx->mService = static_cast(chip::Platform::MemoryCalloc(ctx->mServiceSize, sizeof(DnssdService))); + if (!ctx->mService) + { + ChipLogError(DeviceLayer, "Failed to alloc memory for Dnssd services"); + ctx->mServiceSize = 0; + error = CHIP_ERROR_NO_MEMORY; + ExitNow(); + } + currentResult = ctx->mPtrQueryResult; + servicesIndex = 0; + while (currentResult) + { + Platform::CopyString(ctx->mService[servicesIndex].mName, currentResult->instance_name); + Platform::CopyString(ctx->mService[servicesIndex].mHostName, currentResult->hostname); + Platform::CopyString(ctx->mService[servicesIndex].mType, currentResult->service_type); + ctx->mService[servicesIndex].mProtocol = ctx->mProtocol; + ctx->mService[servicesIndex].mAddressType = MapAddressType(currentResult->ip_protocol); + ctx->mService[servicesIndex].mTransportType = ctx->mAddressType; + ctx->mService[servicesIndex].mPort = currentResult->port; + ctx->mService[servicesIndex].mInterface = ctx->mInterfaceId; + ctx->mService[servicesIndex].mTextEntries = + GetTextEntry(currentResult->txt, currentResult->txt_value_len, currentResult->txt_count); + ctx->mService[servicesIndex].mTextEntrySize = currentResult->txt_count; + ctx->mService[servicesIndex].mSubTypes = NULL; + ctx->mService[servicesIndex].mSubTypeSize = 0; + if (currentResult->addr) + { + Inet::IPAddress IPAddr; + error = GetIPAddress(IPAddr, currentResult->addr); + SuccessOrExit(error); + ctx->mService[servicesIndex].mAddress.SetValue(IPAddr); + } + currentResult = currentResult->next; + servicesIndex++; + } + } + } +exit: + ctx->mBrowseCb(ctx->mCbContext, ctx->mService, ctx->mServiceSize, true, error); + return RemoveMdnsQuery(reinterpret_cast(ctx)); +} + +size_t GetAddressCount(mdns_ip_addr_t * addr) +{ + size_t ret = 0; + while (addr) + { + ret++; + addr = addr->next; + } + return ret; +} + +static CHIP_ERROR ParseIPAddresses(ResolveContext * ctx) +{ + size_t addressIndex = 0; + if (ctx->mAddrQueryResult && ctx->mAddrQueryResult->addr) + { + ctx->mAddressCount = GetAddressCount(ctx->mAddrQueryResult->addr); + if (ctx->mAddressCount > 0) + { + ctx->mAddresses = + static_cast(chip::Platform::MemoryCalloc(ctx->mAddressCount, sizeof(Inet::IPAddress))); + if (ctx->mAddresses == nullptr) + { + ChipLogError(DeviceLayer, "Failed to alloc memory for addresses"); + ctx->mAddressCount = 0; + return CHIP_ERROR_NO_MEMORY; + } + auto * addr = ctx->mAddrQueryResult->addr; + while (addr) + { + GetIPAddress(ctx->mAddresses[addressIndex], addr); + addressIndex++; + addr = addr->next; + } + return CHIP_NO_ERROR; + } + } + return CHIP_ERROR_INVALID_ARGUMENT; +} + +static CHIP_ERROR ParseSrvResult(ResolveContext * ctx) +{ + if (ctx->mSrvQueryResult) + { + if (!ctx->mService) + { + ctx->mService = static_cast(chip::Platform::MemoryAlloc(sizeof(DnssdService))); + } + VerifyOrReturnError(ctx->mService, CHIP_ERROR_NO_MEMORY); + ctx->mServiceSize = 1; + Platform::CopyString(ctx->mService->mName, ctx->mSrvQueryResult->instance_name); + Platform::CopyString(ctx->mService->mHostName, ctx->mSrvQueryResult->hostname); + Platform::CopyString(ctx->mService->mType, ctx->mSrvQueryResult->service_type); + ctx->mService->mProtocol = ctx->mProtocol; + ctx->mService->mAddressType = MapAddressType(ctx->mSrvQueryResult->ip_protocol); + ctx->mService->mTransportType = ctx->mService->mAddressType; + ctx->mService->mPort = ctx->mSrvQueryResult->port; + ctx->mService->mInterface = ctx->mInterfaceId; + ctx->mService->mSubTypes = nullptr; + ctx->mService->mSubTypeSize = 0; + return CHIP_NO_ERROR; + } + else + { + ctx->mService = nullptr; + ctx->mServiceSize = 0; + } + return CHIP_ERROR_INVALID_ARGUMENT; +} + +// ParseTxtResult should be called after ParseSrvResult +static CHIP_ERROR ParseTxtResult(ResolveContext * ctx) +{ + VerifyOrReturnError(ctx->mService, CHIP_ERROR_INCORRECT_STATE); + if (ctx->mTxtQueryResult) + { + ctx->mService->mTextEntries = + GetTextEntry(ctx->mTxtQueryResult->txt, ctx->mTxtQueryResult->txt_value_len, ctx->mTxtQueryResult->txt_count); + ctx->mService->mTextEntrySize = ctx->mTxtQueryResult->txt_count; + } + else + { + ctx->mService->mTextEntries = nullptr; + ctx->mService->mTextEntrySize = 0; + } + return CHIP_NO_ERROR; +} + +static CHIP_ERROR OnResolveDone(ResolveContext * ctx) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + + VerifyOrExit(ctx && ctx->mResolveCb, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(!ctx->mService && ctx->mSrvAddrQueryFinished && ctx->mTxtQueryFinished, error = CHIP_ERROR_INCORRECT_STATE); + error = ParseSrvResult(ctx); + SuccessOrExit(error); + error = ParseIPAddresses(ctx); + SuccessOrExit(error); + error = ParseTxtResult(ctx); + SuccessOrExit(error); +exit: + if (error != CHIP_NO_ERROR) + { + ctx->mResolveCb(ctx->mCbContext, nullptr, Span(nullptr, 0), error); + } + else + { + ctx->mResolveCb(ctx->mCbContext, ctx->mService, Span(ctx->mAddresses, ctx->mAddressCount), error); + } + RemoveMdnsQuery(reinterpret_cast(ctx)); + return error; +} + +static mdns_result_t * MdnsQueryGetResults(mdns_search_once_t * queryHandle) +{ + mdns_result_t * ret = nullptr; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + if (mdns_query_async_get_results(queryHandle, kTimeoutMilli, &ret, NULL)) +#else + if (mdns_query_async_get_results(queryHandle, kTimeoutMilli, &ret)) +#endif + { + return ret; + } + return nullptr; +} + +static void MdnsQueryDone(intptr_t context) +{ + if (!context) + { + return; + } + mdns_search_once_t * queryHandle = reinterpret_cast(context); + mdns_result_t * result = MdnsQueryGetResults(queryHandle); + GenericContext * ctx = FindMdnsQuery(queryHandle); + if (!ctx) + { + mdns_query_results_free(result); + mdns_query_async_delete(queryHandle); + return; + } + if (ctx->mContextType == ContextType::Browse) + { + BrowseContext * browseCtx = reinterpret_cast(ctx); + browseCtx->mPtrQueryResult = result; + OnBrowseDone(browseCtx); + } + else if (ctx->mContextType == ContextType::Resolve) + { + + ResolveContext * resolveCtx = reinterpret_cast(ctx); + if (resolveCtx->mSrvQueryHandle == queryHandle) + { + // No result found. + if (!result) + { + resolveCtx->mResolveCb(ctx->mCbContext, nullptr, Span(nullptr, 0), CHIP_ERROR_INVALID_ARGUMENT); + RemoveMdnsQuery(ctx); + return; + } + // If SRV Query Result is empty, the result is for SRV Query. + if (!resolveCtx->mSrvQueryResult) + { + resolveCtx->mSrvQueryResult = result; + if (result->addr) + { + resolveCtx->mAddrQueryResult = result; + resolveCtx->mSrvAddrQueryFinished = true; + } + else + { + // If there is no A/AAAA records in SRV query response, we will send an AAAA query for the IP addresses. + mdns_query_async_delete(resolveCtx->mSrvQueryHandle); + resolveCtx->mAddrQueryResult = nullptr; + resolveCtx->mSrvQueryHandle = mdns_query_async_new(result->hostname, NULL, NULL, MDNS_TYPE_AAAA, kTimeoutMilli, + kMaxResults, MdnsQueryNotifier); + if (!resolveCtx->mSrvQueryHandle) + { + resolveCtx->mResolveCb(ctx->mCbContext, nullptr, Span(nullptr, 0), CHIP_ERROR_NO_MEMORY); + RemoveMdnsQuery(ctx); + return; + } + } + } + else if (!resolveCtx->mAddrQueryResult) + { + resolveCtx->mAddrQueryResult = result; + resolveCtx->mSrvAddrQueryFinished = true; + } + else + { + resolveCtx->mResolveCb(ctx->mCbContext, nullptr, Span(nullptr, 0), CHIP_ERROR_INCORRECT_STATE); + RemoveMdnsQuery(ctx); + return; + } + } + else if (resolveCtx->mTxtQueryHandle == queryHandle) + { + resolveCtx->mTxtQueryResult = result; + resolveCtx->mTxtQueryFinished = true; + } + if (resolveCtx->mTxtQueryFinished && resolveCtx->mSrvAddrQueryFinished) + { + OnResolveDone(resolveCtx); + } + } +} + +static void MdnsQueryNotifier(mdns_search_once_t * searchHandle) +{ + chip::DeviceLayer::PlatformMgr().ScheduleWork(MdnsQueryDone, reinterpret_cast(searchHandle)); +} + +CHIP_ERROR WiFiDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType, + chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, + intptr_t * browseIdentifier) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + mdns_search_once_t * queryHandle = + mdns_query_async_new(NULL, type, GetProtocolString(protocol), MDNS_TYPE_PTR, kTimeoutMilli, kMaxResults, MdnsQueryNotifier); + VerifyOrReturnError(queryHandle, CHIP_ERROR_NO_MEMORY); + BrowseContext * ctx = + chip::Platform::New(type, protocol, interface, queryHandle, addressType, callback, context); + if (!ctx) + { + ChipLogError(DeviceLayer, "Failed to alloc memory for browse context"); + mdns_query_async_delete(queryHandle); + return CHIP_ERROR_NO_MEMORY; + } + error = AddQueryList(reinterpret_cast(ctx)); + if (error != CHIP_NO_ERROR) + { + chip::Platform::Delete(ctx); + } + else + { + *browseIdentifier = reinterpret_cast(nullptr); + } + return error; +} + +CHIP_ERROR WiFiDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interface, DnssdResolveCallback callback, + void * context) +{ + CHIP_ERROR error = CHIP_NO_ERROR; + mdns_search_once_t * querySrv = mdns_query_async_new(service->mName, service->mType, GetProtocolString(service->mProtocol), + MDNS_TYPE_SRV, kTimeoutMilli, kMaxResults, MdnsQueryNotifier); + VerifyOrReturnError(querySrv, CHIP_ERROR_NO_MEMORY); + mdns_search_once_t * queryTxt = mdns_query_async_new(service->mName, service->mType, GetProtocolString(service->mProtocol), + MDNS_TYPE_TXT, kTimeoutMilli, kMaxResults, MdnsQueryNotifier); + if (!queryTxt) + { + mdns_query_async_delete(querySrv); + return CHIP_ERROR_NO_MEMORY; + } + ResolveContext * ctx = chip::Platform::New(service, interface, querySrv, queryTxt, callback, context); + if (!ctx) + { + ChipLogError(DeviceLayer, "Failed to alloc memory for resolve context"); + mdns_query_async_delete(querySrv); + mdns_query_async_delete(queryTxt); + return CHIP_ERROR_NO_MEMORY; + } + error = AddQueryList(reinterpret_cast(ctx)); + if (error != CHIP_NO_ERROR) + { + chip::Platform::Delete(ctx); + } + return error; +} + +} // namespace Dnssd +} // namespace chip diff --git a/src/platform/ESP32/DnssdImpl.h b/src/platform/ESP32/WiFiDnssdImpl.h similarity index 85% rename from src/platform/ESP32/DnssdImpl.h rename to src/platform/ESP32/WiFiDnssdImpl.h index 658ec8fe67c7f6..1f1c378a414cb2 100644 --- a/src/platform/ESP32/DnssdImpl.h +++ b/src/platform/ESP32/WiFiDnssdImpl.h @@ -139,5 +139,18 @@ struct ResolveContext : public GenericContext } }; +CHIP_ERROR WiFiDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context); + +CHIP_ERROR WiFiDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context); + +CHIP_ERROR WiFiDnssdRemoveServices(); + +CHIP_ERROR WiFiDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType, + chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, + intptr_t * browseIdentifier); + +CHIP_ERROR WiFiDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interface, DnssdResolveCallback callback, + void * context); + } // namespace Dnssd } // namespace chip diff --git a/src/platform/Infineon/CYW30739/BUILD.gn b/src/platform/Infineon/CYW30739/BUILD.gn index 61f03102cc75b3..2af62c34d6accc 100644 --- a/src/platform/Infineon/CYW30739/BUILD.gn +++ b/src/platform/Infineon/CYW30739/BUILD.gn @@ -93,7 +93,11 @@ static_library("CYW30739") { } if (chip_mdns == "platform") { - sources += [ "../../OpenThread/DnssdImpl.cpp" ] + sources += [ + "../../OpenThread/DnssdImpl.cpp", + "../../OpenThread/OpenThreadDnssdImpl.cpp", + "../../OpenThread/OpenThreadDnssdImpl.h", + ] deps += [ "${chip_root}/src/lib/dnssd:platform_header" ] } diff --git a/src/platform/OpenThread/DnssdImpl.cpp b/src/platform/OpenThread/DnssdImpl.cpp index 5fbe3acba11537..7f6b200651c5cf 100644 --- a/src/platform/OpenThread/DnssdImpl.cpp +++ b/src/platform/OpenThread/DnssdImpl.cpp @@ -15,91 +15,37 @@ * limitations under the License. */ -#include "lib/dnssd/platform/Dnssd.h" - -#include -#include -#include - -using namespace ::chip::DeviceLayer; +#include namespace chip { namespace Dnssd { CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context) { - ReturnErrorOnFailure(ThreadStackMgr().SetSrpDnsCallbacks(initCallback, errorCallback, context)); - - uint8_t macBuffer[ConfigurationManager::kPrimaryMACAddressLength]; - MutableByteSpan mac(macBuffer); - char hostname[kHostNameMaxLength + 1] = ""; - ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetPrimaryMACAddress(mac)); - MakeHostName(hostname, sizeof(hostname), mac); - - return ThreadStackMgr().ClearSrpHost(hostname); + return OpenThreadDnssdInit(initCallback, errorCallback, context); } void ChipDnssdShutdown() {} -const char * GetProtocolString(DnssdServiceProtocol protocol) -{ - return protocol == DnssdServiceProtocol::kDnssdProtocolUdp ? "_udp" : "_tcp"; -} - CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context) { -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - ReturnErrorCodeIf(service == nullptr, CHIP_ERROR_INVALID_ARGUMENT); - if (strcmp(service->mHostName, "") != 0) - { - ReturnErrorOnFailure(ThreadStackMgr().SetupSrpHost(service->mHostName)); - } - - char serviceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + 1]; - snprintf(serviceType, sizeof(serviceType), "%s.%s", service->mType, GetProtocolString(service->mProtocol)); - - Span subTypes(service->mSubTypes, service->mSubTypeSize); - Span textEntries(service->mTextEntries, service->mTextEntrySize); - return ThreadStackMgr().AddSrpService(service->mName, serviceType, service->mPort, subTypes, textEntries); -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + return OpenThreadDnssdPublishService(service, callback, context); } CHIP_ERROR ChipDnssdRemoveServices() { -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - ThreadStackMgr().InvalidateAllSrpServices(); - return CHIP_NO_ERROR; -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + return OpenThreadDnssdRemoveServices(); } CHIP_ERROR ChipDnssdFinalizeServiceUpdate() { -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT - return ThreadStackMgr().RemoveInvalidSrpServices(); -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + return OpenThreadDnssdFinalizeServiceUpdate(); } CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, Inet::IPAddressType addressType, Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, intptr_t * browseIdentifier) { -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT - if (type == nullptr || callback == nullptr) - return CHIP_ERROR_INVALID_ARGUMENT; - - char serviceType[Dnssd::kDnssdFullTypeAndProtocolMaxSize + 1]; // +1 for null-terminator - snprintf(serviceType, sizeof(serviceType), "%s.%s", StringOrNullMarker(type), GetProtocolString(protocol)); - - *browseIdentifier = reinterpret_cast(nullptr); - return ThreadStackMgr().DnsBrowse(serviceType, callback, context); -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT + return OpenThreadDnssdBrowse(type, protocol, addressType, interface, callback, context, browseIdentifier); } CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier) @@ -109,17 +55,7 @@ CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier) CHIP_ERROR ChipDnssdResolve(DnssdService * browseResult, Inet::InterfaceId interface, DnssdResolveCallback callback, void * context) { -#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT - if (browseResult == nullptr || callback == nullptr) - return CHIP_ERROR_INVALID_ARGUMENT; - - char serviceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + 1]; - snprintf(serviceType, sizeof(serviceType), "%s.%s", browseResult->mType, GetProtocolString(browseResult->mProtocol)); - - return ThreadStackMgr().DnsResolve(serviceType, browseResult->mName, callback, context); -#else - return CHIP_ERROR_NOT_IMPLEMENTED; -#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT + return OpenThreadDnssdResolve(browseResult, interface, callback, context); } void ChipDnssdResolveNoLongerNeeded(const char * instanceName) {} diff --git a/src/platform/OpenThread/OpenThreadDnssdImpl.cpp b/src/platform/OpenThread/OpenThreadDnssdImpl.cpp new file mode 100644 index 00000000000000..cb205df95eb72b --- /dev/null +++ b/src/platform/OpenThread/OpenThreadDnssdImpl.cpp @@ -0,0 +1,117 @@ +/* + * + * Copyright (c) 2021-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. + */ + +#include + +using namespace ::chip::DeviceLayer; + +namespace chip { +namespace Dnssd { + +CHIP_ERROR OpenThreadDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context) +{ + ReturnErrorOnFailure(ThreadStackMgr().SetSrpDnsCallbacks(initCallback, errorCallback, context)); + + uint8_t macBuffer[ConfigurationManager::kPrimaryMACAddressLength]; + MutableByteSpan mac(macBuffer); + char hostname[kHostNameMaxLength + 1] = ""; + ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetPrimaryMACAddress(mac)); + MakeHostName(hostname, sizeof(hostname), mac); + + return ThreadStackMgr().ClearSrpHost(hostname); +} + +const char * GetProtocolString(DnssdServiceProtocol protocol) +{ + return protocol == DnssdServiceProtocol::kDnssdProtocolUdp ? "_udp" : "_tcp"; +} + +CHIP_ERROR OpenThreadDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + ReturnErrorCodeIf(service == nullptr, CHIP_ERROR_INVALID_ARGUMENT); + if (strcmp(service->mHostName, "") != 0) + { + ReturnErrorOnFailure(ThreadStackMgr().SetupSrpHost(service->mHostName)); + } + + char serviceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + 1]; + snprintf(serviceType, sizeof(serviceType), "%s.%s", service->mType, GetProtocolString(service->mProtocol)); + + Span subTypes(service->mSubTypes, service->mSubTypeSize); + Span textEntries(service->mTextEntries, service->mTextEntrySize); + return ThreadStackMgr().AddSrpService(service->mName, serviceType, service->mPort, subTypes, textEntries); +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +} + +CHIP_ERROR OpenThreadDnssdRemoveServices() +{ +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + ThreadStackMgr().InvalidateAllSrpServices(); + return CHIP_NO_ERROR; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +} + +CHIP_ERROR OpenThreadDnssdFinalizeServiceUpdate() +{ +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT + return ThreadStackMgr().RemoveInvalidSrpServices(); +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +} + +CHIP_ERROR OpenThreadDnssdBrowse(const char * type, DnssdServiceProtocol protocol, Inet::IPAddressType addressType, + Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, + intptr_t * browseIdentifier) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT + if (type == nullptr || callback == nullptr) + return CHIP_ERROR_INVALID_ARGUMENT; + + char serviceType[Dnssd::kDnssdFullTypeAndProtocolMaxSize + 1]; // +1 for null-terminator + snprintf(serviceType, sizeof(serviceType), "%s.%s", StringOrNullMarker(type), GetProtocolString(protocol)); + + *browseIdentifier = reinterpret_cast(nullptr); + return ThreadStackMgr().DnsBrowse(serviceType, callback, context); +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT +} + +CHIP_ERROR OpenThreadDnssdResolve(DnssdService * browseResult, Inet::InterfaceId interface, DnssdResolveCallback callback, + void * context) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT + if (browseResult == nullptr || callback == nullptr) + return CHIP_ERROR_INVALID_ARGUMENT; + + char serviceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + 1]; + snprintf(serviceType, sizeof(serviceType), "%s.%s", browseResult->mType, GetProtocolString(browseResult->mProtocol)); + + return ThreadStackMgr().DnsResolve(serviceType, browseResult->mName, callback, context); +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT +} + +} // namespace Dnssd +} // namespace chip diff --git a/src/platform/OpenThread/OpenThreadDnssdImpl.h b/src/platform/OpenThread/OpenThreadDnssdImpl.h new file mode 100644 index 00000000000000..7dc47c027ff313 --- /dev/null +++ b/src/platform/OpenThread/OpenThreadDnssdImpl.h @@ -0,0 +1,43 @@ +/* + * + * Copyright (c) 2021-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. + */ + +#include "lib/dnssd/platform/Dnssd.h" + +#include +#include +#include + +namespace chip { +namespace Dnssd { + +CHIP_ERROR OpenThreadDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context); + +CHIP_ERROR OpenThreadDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context); + +CHIP_ERROR OpenThreadDnssdRemoveServices(); + +CHIP_ERROR OpenThreadDnssdFinalizeServiceUpdate(); + +CHIP_ERROR OpenThreadDnssdBrowse(const char * type, DnssdServiceProtocol protocol, Inet::IPAddressType addressType, + Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, + intptr_t * browseIdentifier); + +CHIP_ERROR OpenThreadDnssdResolve(DnssdService * browseResult, Inet::InterfaceId interface, DnssdResolveCallback callback, + void * context); + +} // namespace Dnssd +} // namespace chip diff --git a/src/platform/Zephyr/BUILD.gn b/src/platform/Zephyr/BUILD.gn index 748bc6e2419994..951c6f1f5cc90b 100644 --- a/src/platform/Zephyr/BUILD.gn +++ b/src/platform/Zephyr/BUILD.gn @@ -61,7 +61,11 @@ static_library("Zephyr") { ] if (chip_mdns == "platform") { - sources += [ "../OpenThread/DnssdImpl.cpp" ] + sources += [ + "../OpenThread/DnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.h", + ] deps = [ "${chip_root}/src/lib/dnssd:platform_header" ] } } diff --git a/src/platform/bouffalolab/BL702/BUILD.gn b/src/platform/bouffalolab/BL702/BUILD.gn index e10cf6a45d7d78..ae941605978012 100644 --- a/src/platform/bouffalolab/BL702/BUILD.gn +++ b/src/platform/bouffalolab/BL702/BUILD.gn @@ -82,7 +82,11 @@ static_library("BL702") { ] if (chip_mdns == "platform") { - sources += [ "../../OpenThread/DnssdImpl.cpp" ] + sources += [ + "../../OpenThread/DnssdImpl.cpp", + "../../OpenThread/OpenThreadDnssdImpl.cpp", + "../../OpenThread/OpenThreadDnssdImpl.h", + ] deps += [ "${chip_root}/src/lib/dnssd:platform_header" ] } } diff --git a/src/platform/cc13xx_26xx/cc13x2_26x2/BUILD.gn b/src/platform/cc13xx_26xx/cc13x2_26x2/BUILD.gn index 133580e80169dc..d46bd18544af15 100644 --- a/src/platform/cc13xx_26xx/cc13x2_26x2/BUILD.gn +++ b/src/platform/cc13xx_26xx/cc13x2_26x2/BUILD.gn @@ -98,7 +98,11 @@ static_library("cc13x2_26x2") { ] if (chip_mdns == "platform") { - sources += [ "../../OpenThread/DnssdImpl.cpp" ] + sources += [ + "../OpenThread/DnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.h", + ] deps += [ "${chip_root}/src/lib/dnssd:platform_header" ] } } diff --git a/src/platform/nrfconnect/BUILD.gn b/src/platform/nrfconnect/BUILD.gn index 1efcadfa9fe82e..7b1a8872aa2d39 100644 --- a/src/platform/nrfconnect/BUILD.gn +++ b/src/platform/nrfconnect/BUILD.gn @@ -84,7 +84,11 @@ static_library("nrfconnect") { ] if (chip_mdns == "platform") { - sources += [ "../OpenThread/DnssdImpl.cpp" ] + sources += [ + "../OpenThread/DnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.h", + ] deps = [ "${chip_root}/src/lib/dnssd:platform_header" ] } } diff --git a/src/platform/nxp/k32w/k32w0/BUILD.gn b/src/platform/nxp/k32w/k32w0/BUILD.gn index 98118b4f902c37..f8f33dd6798c46 100644 --- a/src/platform/nxp/k32w/k32w0/BUILD.gn +++ b/src/platform/nxp/k32w/k32w0/BUILD.gn @@ -135,7 +135,11 @@ static_library("k32w0") { ] if (chip_mdns == "platform") { - sources += [ "../../../OpenThread/DnssdImpl.cpp" ] + sources += [ + "../../../OpenThread/DnssdImpl.cpp", + "../../../OpenThread/OpenThreadDnssdImpl.cpp", + "../../../OpenThread/OpenThreadDnssdImpl.h", + ] deps += [ "${chip_root}/src/lib/dnssd:platform_header" ] } } diff --git a/src/platform/qpg/BUILD.gn b/src/platform/qpg/BUILD.gn index c6ec711e70f4b3..ad96b2aa3d42e1 100644 --- a/src/platform/qpg/BUILD.gn +++ b/src/platform/qpg/BUILD.gn @@ -82,7 +82,11 @@ static_library("qpg") { ] if (chip_mdns == "platform") { - sources += [ "../OpenThread/DnssdImpl.cpp" ] + sources += [ + "../OpenThread/DnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.h", + ] deps += [ "${chip_root}/src/lib/dnssd:platform_header" ] } } diff --git a/src/platform/silabs/efr32/BUILD.gn b/src/platform/silabs/efr32/BUILD.gn index d6efa34ad7388f..262621e40f86ac 100644 --- a/src/platform/silabs/efr32/BUILD.gn +++ b/src/platform/silabs/efr32/BUILD.gn @@ -115,7 +115,11 @@ static_library("efr32") { ] if (chip_mdns == "platform") { - sources += [ "../../OpenThread/DnssdImpl.cpp" ] + sources += [ + "../../OpenThread/DnssdImpl.cpp", + "../../OpenThread/OpenThreadDnssdImpl.cpp", + "../../OpenThread/OpenThreadDnssdImpl.h", + ] deps += [ "${chip_root}/src/lib/dnssd:platform_header" ] } diff --git a/src/platform/telink/BUILD.gn b/src/platform/telink/BUILD.gn index 4a4cbb9bd66338..0970bb68fee624 100644 --- a/src/platform/telink/BUILD.gn +++ b/src/platform/telink/BUILD.gn @@ -74,7 +74,11 @@ static_library("telink") { ] if (chip_mdns == "platform") { - sources += [ "../OpenThread/DnssdImpl.cpp" ] + sources += [ + "../OpenThread/DnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.cpp", + "../OpenThread/OpenThreadDnssdImpl.h", + ] deps = [ "${chip_root}/src/lib/dnssd:platform_header" ] } }