/*
 *
 *    Copyright (c) 2023 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 <lib/support/CodeUtils.h>
#include <lib/support/FixedBufferAllocator.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h>
#include <platform/OpenThread/OpenThreadUtils.h>

#include <platform/nxp/common/ConnectivityManagerImpl.h>

#include <openthread/mdns_server.h>

using namespace ::chip::DeviceLayer;
using namespace chip::DeviceLayer::Internal;

namespace chip {
namespace Dnssd {

#define LOCAL_DOMAIN_STRING_SIZE 7
#define ARPA_DOMAIN_STRING_SIZE 22
#define MATTER_DNS_TXT_SIZE 128

// Support both operational and commissionable discovery, so buffers sizes must be worst case.
static constexpr uint8_t kMaxMdnsServiceTxtEntriesNumber =
    std::max(Dnssd::CommissionAdvertisingParameters::kTxtMaxNumber, Dnssd::OperationalAdvertisingParameters::kTxtMaxNumber);
static constexpr size_t kTotalMdnsServiceTxtValueSize = std::max(Dnssd::CommissionAdvertisingParameters::kTxtTotalValueSize,
                                                                 Dnssd::OperationalAdvertisingParameters::kTxtTotalValueSize);
static constexpr size_t kTotalMdnsServiceTxtKeySize =
    std::max(Dnssd::CommissionAdvertisingParameters::kTxtTotalKeySize, Dnssd::OperationalAdvertisingParameters::kTxtTotalKeySize);

static constexpr size_t kTotalMdnsServiceTxtBufferSize =
    kTotalMdnsServiceTxtKeySize + kMaxMdnsServiceTxtEntriesNumber + kTotalMdnsServiceTxtValueSize;

static const char * GetProtocolString(DnssdServiceProtocol protocol)
{
    return protocol == DnssdServiceProtocol::kDnssdProtocolUdp ? "_udp" : "_tcp";
}

struct DnsServiceTxtEntries
{
    uint8_t mBuffer[kTotalMdnsServiceTxtBufferSize];
    Dnssd::TextEntry mTxtEntries[kMaxMdnsServiceTxtEntriesNumber];
};

struct mDnsQueryCtx
{
    void * matterCtx;
    chip::Dnssd::DnssdService mMdnsService;
    DnsServiceTxtEntries mServiceTxtEntry;
    char mServiceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + LOCAL_DOMAIN_STRING_SIZE + 1];
    CHIP_ERROR error;

    mDnsQueryCtx(void * context, CHIP_ERROR aError)
    {
        matterCtx = context;
        error     = aError;
    }
};

static const char * GetProtocolString(DnssdServiceProtocol protocol);

static void OtBrowseCallback(otError aError, const otDnsBrowseResponse * aResponse, void * aContext);
static void OtServiceCallback(otError aError, const otDnsServiceResponse * aResponse, void * aContext);

static void DispatchBrowseEmpty(intptr_t context);
static void DispatchBrowse(intptr_t context);
static void DispatchBrowseNoMemory(intptr_t context);

void DispatchAddressResolve(intptr_t context);
void DispatchResolve(intptr_t context);
void DispatchResolveNoMemory(intptr_t context);

static DnsBrowseCallback mDnsBrowseCallback;
static DnsResolveCallback mDnsResolveCallback;

CHIP_ERROR ResolveBySrp(DnssdService * mdnsReq, otInstance * thrInstancePtr, char * instanceName, void * context);
CHIP_ERROR BrowseBySrp(otInstance * thrInstancePtr, char * serviceName, void * context);

CHIP_ERROR FromSrpCacheToMdnsData(const otSrpServerService * service, const otSrpServerHost * host,
                                  const DnssdService * mdnsQueryReq, chip::Dnssd::DnssdService & mdnsService,
                                  DnsServiceTxtEntries & serviceTxtEntries);

static bool bBrowseInProgress = false;

CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context)
{
    CHIP_ERROR error            = CHIP_NO_ERROR;
    otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance();

    uint8_t macBuffer[ConfigurationManager::kPrimaryMACAddressLength];
    MutableByteSpan mac(macBuffer);
    char hostname[kHostNameMaxLength + LOCAL_DOMAIN_STRING_SIZE + 1] = "";
    ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetPrimaryMACAddress(mac));
    MakeHostName(hostname, sizeof(hostname), mac);
    snprintf(hostname + strlen(hostname), sizeof(hostname), ".local.");

    error = MapOpenThreadError(otMdnsServerSetHostName(thrInstancePtr, hostname));

    initCallback(context, error);
    return error;
}

void ChipDnssdShutdown()
{
    otMdnsServerStop(ThreadStackMgrImpl().OTInstance());
}

CHIP_ERROR ChipDnssdRemoveServices()
{
    otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance();

    otMdnsServerMarkServiceForRemoval(thrInstancePtr, nullptr, "_matter._tcp.local.");
    otMdnsServerMarkServiceForRemoval(thrInstancePtr, nullptr, "_matterc._udp.local.");

    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context)
{
    ReturnErrorCodeIf(service == nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance();
    otError otErr;
    otDnsTxtEntry aTxtEntry;
    uint32_t txtBufferOffset = 0;

    char fullInstName[Common::kInstanceNameMaxLength + chip::Dnssd::kDnssdTypeAndProtocolMaxSize + LOCAL_DOMAIN_STRING_SIZE + 1] =
        "";
    char serviceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + LOCAL_DOMAIN_STRING_SIZE + 1] = "";
    // secure space for the raw TXT data in the worst-case scenario relevant for Matter:
    // each entry consists of txt_entry_size (1B) + txt_entry_key + "=" + txt_entry_data
    uint8_t txtBuffer[kMaxMdnsServiceTxtEntriesNumber + kTotalMdnsServiceTxtBufferSize] = { 0 };

    if ((strcmp(service->mHostName, "") != 0) && (nullptr == otMdnsServerGetHostName(thrInstancePtr)))
    {
        char hostname[kHostNameMaxLength + LOCAL_DOMAIN_STRING_SIZE + 1] = "";
        snprintf(hostname, sizeof(hostname), "%s.local.", service->mHostName);
        otMdnsServerSetHostName(thrInstancePtr, hostname);
    }

    snprintf(serviceType, sizeof(serviceType), "%s.%s.local.", service->mType, GetProtocolString(service->mProtocol));
    snprintf(fullInstName, sizeof(fullInstName), "%s.%s", service->mName, serviceType);

    for (uint32_t i = 0; i < service->mTextEntrySize; i++)
    {
        uint32_t keySize = strlen(service->mTextEntries[i].mKey);
        // add TXT entry len, + 1 is for '='
        *(txtBuffer + txtBufferOffset++) = keySize + service->mTextEntries[i].mDataSize + 1;

        // add TXT entry key
        memcpy(txtBuffer + txtBufferOffset, service->mTextEntries[i].mKey, keySize);
        txtBufferOffset += keySize;

        // add TXT entry value if pointer is not null, if pointer is null it means we have bool value
        if (service->mTextEntries[i].mData)
        {
            *(txtBuffer + txtBufferOffset++) = '=';
            memcpy(txtBuffer + txtBufferOffset, service->mTextEntries[i].mData, service->mTextEntries[i].mDataSize);
            txtBufferOffset += service->mTextEntries[i].mDataSize;
        }
    }
    aTxtEntry.mKey         = nullptr;
    aTxtEntry.mValue       = txtBuffer;
    aTxtEntry.mValueLength = txtBufferOffset;

    otErr = otMdnsServerAddService(thrInstancePtr, fullInstName, serviceType, service->mSubTypes, service->mSubTypeSize,
                                   service->mPort, &aTxtEntry, 1);
    // Ignore duplicate error and threat it as error none
    if (otErr == OT_ERROR_DUPLICATED)
        otErr = OT_ERROR_NONE;

    return MapOpenThreadError(otErr);
}

CHIP_ERROR ChipDnssdFinalizeServiceUpdate()
{
    otMdnsServerRemoveMarkedServices(ThreadStackMgrImpl().OTInstance());
    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, Inet::IPAddressType addressType,
                           Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, intptr_t * browseIdentifier)
{
    *browseIdentifier                                                                         = reinterpret_cast<intptr_t>(nullptr);
    CHIP_ERROR error                                                                          = CHIP_NO_ERROR;
    CHIP_ERROR srpBrowseError                                                                 = CHIP_NO_ERROR;
    char serviceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + ARPA_DOMAIN_STRING_SIZE + 1] = ""; // +1 for null-terminator

    if (type == nullptr || callback == nullptr)
        return CHIP_ERROR_INVALID_ARGUMENT;

    otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance();
    mDnsBrowseCallback          = callback;

    mDnsQueryCtx * browseContext = Platform::New<mDnsQueryCtx>(context, CHIP_NO_ERROR);
    VerifyOrReturnError(browseContext != nullptr, CHIP_ERROR_NO_MEMORY);

    // First try to browse the service in the SRP cache, use default.service.arpa as domain name
    snprintf(serviceType, sizeof(serviceType), "%s.%s.default.service.arpa.", type, GetProtocolString(protocol));
    // After browsing in the SRP cache we will continue with regular mDNS browse
    srpBrowseError = BrowseBySrp(thrInstancePtr, serviceType, context);

    // Proceed to generate a mDNS query
    snprintf(browseContext->mServiceType, sizeof(browseContext->mServiceType), "%s.%s.local.", type, GetProtocolString(protocol));

    error = MapOpenThreadError(otMdnsServerBrowse(thrInstancePtr, browseContext->mServiceType, OtBrowseCallback, browseContext));

    if (CHIP_NO_ERROR == error)
    {
        bBrowseInProgress = true;
        *browseIdentifier = reinterpret_cast<intptr_t>(browseContext);
    }
    else
    {
        if (srpBrowseError == CHIP_NO_ERROR)
        {
            // In this case, we need to send a final browse indication to signal the Matter App that there are no more
            // browse results coming
            browseContext->error = error;
            DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowseEmpty, reinterpret_cast<intptr_t>(browseContext));
        }
        else
        {
            Platform::Delete<mDnsQueryCtx>(browseContext);
        }
    }
    return error;
}

CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier)
{
    mDnsQueryCtx * browseContext = reinterpret_cast<mDnsQueryCtx *>(browseIdentifier);
    otInstance * thrInstancePtr  = ThreadStackMgrImpl().OTInstance();
    otError error                = OT_ERROR_INVALID_ARGS;

    // browseContext is only valid when bBrowseInProgress is true. The Matter stack can call this function even with a browseContext
    // that has been freed in DispatchBrowseEmpty before.
    if ((true == bBrowseInProgress) && (browseContext))
    {
        browseContext->error = MapOpenThreadError(otMdnsServerStopQuery(thrInstancePtr, browseContext->mServiceType));

        // browse context will be freed in DispatchBrowseEmpty
        DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowseEmpty, reinterpret_cast<intptr_t>(browseContext));
    }
    return MapOpenThreadError(error);
}

CHIP_ERROR ChipDnssdResolve(DnssdService * browseResult, Inet::InterfaceId interface, DnssdResolveCallback callback, void * context)
{
    ChipError error;
    if (browseResult == nullptr || callback == nullptr)
        return CHIP_ERROR_INVALID_ARGUMENT;

    otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance();
    mDnsResolveCallback         = callback;

    char serviceType[chip::Dnssd::kDnssdTypeAndProtocolMaxSize + ARPA_DOMAIN_STRING_SIZE + 1] = ""; // +1 for null-terminator
    char fullInstName[Common::kInstanceNameMaxLength + chip::Dnssd::kDnssdTypeAndProtocolMaxSize + ARPA_DOMAIN_STRING_SIZE + 1] =
        "";

    // First try to find the service in the SRP cache, use default.service.arpa as domain name
    snprintf(serviceType, sizeof(serviceType), "%s.%s.default.service.arpa.", browseResult->mType,
             GetProtocolString(browseResult->mProtocol));
    snprintf(fullInstName, sizeof(fullInstName), "%s.%s", browseResult->mName, serviceType);

    error = ResolveBySrp(browseResult, thrInstancePtr, fullInstName, context);
    if (CHIP_ERROR_NOT_FOUND == error)
    {
        // If the SRP cache returns not found, proceed to generate a MDNS query
        memset(serviceType, 0, sizeof(serviceType));
        memset(fullInstName, 0, sizeof(fullInstName));

        snprintf(serviceType, sizeof(serviceType), "%s.%s.local.", browseResult->mType, GetProtocolString(browseResult->mProtocol));
        snprintf(fullInstName, sizeof(fullInstName), "%s.%s", browseResult->mName, serviceType);

        return MapOpenThreadError(otMdnsServerResolveService(thrInstancePtr, fullInstName, OtServiceCallback, context));
    }
    else
    {
        return error;
    }
}

CHIP_ERROR BrowseBySrp(otInstance * thrInstancePtr, char * serviceName, void * context)
{
    const otSrpServerHost * host       = nullptr;
    const otSrpServerService * service = nullptr;
    CHIP_ERROR error                   = CHIP_ERROR_NOT_FOUND;

    while ((host = otSrpServerGetNextHost(thrInstancePtr, host)) != nullptr)
    {
        service = otSrpServerHostFindNextService(host, service, OT_SRP_SERVER_FLAGS_ANY_TYPE_ACTIVE_SERVICE, serviceName, nullptr);
        if (service != nullptr)
        {
            mDnsQueryCtx * serviceContext;

            serviceContext = Platform::New<mDnsQueryCtx>(context, CHIP_NO_ERROR);
            if (serviceContext != nullptr)
            {
                if (CHIP_NO_ERROR ==
                    FromSrpCacheToMdnsData(service, host, nullptr, serviceContext->mMdnsService, serviceContext->mServiceTxtEntry))
                {
                    // Set error to CHIP_NO_ERROR to signal that there was at least one service found in the cache
                    error = CHIP_NO_ERROR;
                    DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowse, reinterpret_cast<intptr_t>(serviceContext));
                }
                else
                {
                    Platform::Delete<mDnsQueryCtx>(serviceContext);
                }
            }
        }
    }
    return error;
}

CHIP_ERROR ResolveBySrp(DnssdService * mdnsReq, otInstance * thrInstancePtr, char * instanceName, void * context)
{
    const otSrpServerHost * host       = nullptr;
    const otSrpServerService * service = nullptr;
    CHIP_ERROR error                   = CHIP_ERROR_NOT_FOUND;

    while ((host = otSrpServerGetNextHost(thrInstancePtr, host)) != nullptr)
    {
        service = otSrpServerHostFindNextService(
            host, service, (OT_SRP_SERVER_SERVICE_FLAG_BASE_TYPE | OT_SRP_SERVER_SERVICE_FLAG_ACTIVE), nullptr, instanceName);
        if (service != nullptr)
        {
            error = CHIP_NO_ERROR;
            mDnsQueryCtx * serviceContext;

            serviceContext = Platform::New<mDnsQueryCtx>(context, CHIP_NO_ERROR);
            if (serviceContext != nullptr)
            {
                error =
                    FromSrpCacheToMdnsData(service, host, mdnsReq, serviceContext->mMdnsService, serviceContext->mServiceTxtEntry);
                if (error == CHIP_NO_ERROR)
                {
                    DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast<intptr_t>(serviceContext));
                }
                else
                {
                    Platform::Delete<mDnsQueryCtx>(serviceContext);
                }
            }
            else
            {
                error = CHIP_ERROR_NO_MEMORY;
            }
            break;
        }
    }
    return error;
}

CHIP_ERROR FromSrpCacheToMdnsData(const otSrpServerService * service, const otSrpServerHost * host,
                                  const DnssdService * mdnsQueryReq, chip::Dnssd::DnssdService & mdnsService,
                                  DnsServiceTxtEntries & serviceTxtEntries)
{
    const char * tmpName;
    const uint8_t * txtStringPtr;
    size_t substringSize;
    uint8_t addrNum = 0;
    uint16_t txtDataLen;
    const otIp6Address * ip6AddrPtr = otSrpServerHostGetAddresses(host, &addrNum);

    if (mdnsQueryReq != nullptr)
    {
        Platform::CopyString(mdnsService.mName, sizeof(mdnsService.mName), mdnsQueryReq->mName);
        Platform::CopyString(mdnsService.mType, sizeof(mdnsService.mType), mdnsQueryReq->mType);
        mdnsService.mProtocol = mdnsQueryReq->mProtocol;
    }
    else
    {
        tmpName = otSrpServerServiceGetInstanceName(service);
        // Extract from the <instance>.<type>.<protocol>.<domain-name>. the <instance> part
        size_t substringSize = strchr(tmpName, '.') - tmpName;
        if (substringSize >= ArraySize(mdnsService.mName))
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        Platform::CopyString(mdnsService.mName, substringSize + 1, tmpName);

        // Extract from the <instance>.<type>.<protocol>.<domain-name>. the <type> part.
        tmpName       = tmpName + substringSize + 1;
        substringSize = strchr(tmpName, '.') - tmpName;
        if (substringSize >= ArraySize(mdnsService.mType))
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        Platform::CopyString(mdnsService.mType, substringSize + 1, tmpName);

        // Extract from the <instance>.<type>.<protocol>.<domain-name>. the <type> part.
        tmpName       = tmpName + substringSize + 1;
        substringSize = strchr(tmpName, '.') - tmpName;
        if (substringSize >= (chip::Dnssd::kDnssdProtocolTextMaxSize + 1))
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        if (strncmp(tmpName, "_udp", substringSize) == 0)
        {
            mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUdp;
        }
        else if (strncmp(tmpName, "_tcp", substringSize) == 0)
        {
            mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolTcp;
        }
        else
        {
            mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUnknown;
        }
    }

    // Extract from the <hostname>.<domain-name>. the <hostname> part.
    tmpName       = otSrpServerHostGetFullName(host);
    substringSize = strchr(tmpName, '.') - tmpName;
    if (substringSize >= ArraySize(mdnsService.mHostName))
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
    Platform::CopyString(mdnsService.mHostName, substringSize + 1, tmpName);
    mdnsService.mPort = otSrpServerServiceGetPort(service);

    // All SRP cache hits come from the Thread Netif
    mdnsService.mInterface = ConnectivityManagerImpl().GetThreadInterface();

    mdnsService.mAddressType = Inet::IPAddressType::kIPv6;
    mdnsService.mAddress     = MakeOptional(ToIPAddress(*ip6AddrPtr));

    // Extract TXT record SRP service
    txtStringPtr = otSrpServerServiceGetTxtData(service, &txtDataLen);
    if (txtDataLen != 0)
    {
        otDnsTxtEntryIterator iterator;
        otDnsInitTxtEntryIterator(&iterator, txtStringPtr, txtDataLen);

        otDnsTxtEntry txtEntry;
        chip::FixedBufferAllocator alloc(serviceTxtEntries.mBuffer);

        uint8_t entryIndex = 0;
        while ((otDnsGetNextTxtEntry(&iterator, &txtEntry) == OT_ERROR_NONE) && entryIndex < 64)
        {
            if (txtEntry.mKey == nullptr || txtEntry.mValue == nullptr)
                continue;

            serviceTxtEntries.mTxtEntries[entryIndex].mKey      = alloc.Clone(txtEntry.mKey);
            serviceTxtEntries.mTxtEntries[entryIndex].mData     = alloc.Clone(txtEntry.mValue, txtEntry.mValueLength);
            serviceTxtEntries.mTxtEntries[entryIndex].mDataSize = txtEntry.mValueLength;
            entryIndex++;
        }

        ReturnErrorCodeIf(alloc.AnyAllocFailed(), CHIP_ERROR_BUFFER_TOO_SMALL);

        mdnsService.mTextEntries   = serviceTxtEntries.mTxtEntries;
        mdnsService.mTextEntrySize = entryIndex;
    }
    else
    {
        mdnsService.mTextEntrySize = 0;
    }

    mdnsService.mSubTypes    = nullptr;
    mdnsService.mSubTypeSize = 0;

    return CHIP_NO_ERROR;
}

CHIP_ERROR FromOtDnsResponseToMdnsData(otDnsServiceInfo & serviceInfo, const char * serviceType,
                                       chip::Dnssd::DnssdService & mdnsService, DnsServiceTxtEntries & serviceTxtEntries,
                                       otError error)
{
    char protocol[chip::Dnssd::kDnssdProtocolTextMaxSize + 1];

    if (strchr(serviceType, '.') == nullptr)
        return CHIP_ERROR_INVALID_ARGUMENT;

    // Extract from the <type>.<protocol>.<domain-name>. the <type> part.
    size_t substringSize = strchr(serviceType, '.') - serviceType;
    if (substringSize >= ArraySize(mdnsService.mType))
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
    Platform::CopyString(mdnsService.mType, substringSize + 1, serviceType);

    // Extract from the <type>.<protocol>.<domain-name>. the <protocol> part.
    const char * protocolSubstringStart = serviceType + substringSize + 1;

    if (strchr(protocolSubstringStart, '.') == nullptr)
        return CHIP_ERROR_INVALID_ARGUMENT;

    substringSize = strchr(protocolSubstringStart, '.') - protocolSubstringStart;
    if (substringSize >= ArraySize(protocol))
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }
    Platform::CopyString(protocol, substringSize + 1, protocolSubstringStart);

    if (strncmp(protocol, "_udp", chip::Dnssd::kDnssdProtocolTextMaxSize) == 0)
    {
        mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUdp;
    }
    else if (strncmp(protocol, "_tcp", chip::Dnssd::kDnssdProtocolTextMaxSize) == 0)
    {
        mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolTcp;
    }
    else
    {
        mdnsService.mProtocol = chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUnknown;
    }

    // Check if SRV record was included in DNS response.
    if (error != OT_ERROR_NOT_FOUND)
    {
        if (strchr(serviceInfo.mHostNameBuffer, '.') == nullptr)
            return CHIP_ERROR_INVALID_ARGUMENT;

        // Extract from the <hostname>.<domain-name>. the <hostname> part.
        substringSize = strchr(serviceInfo.mHostNameBuffer, '.') - serviceInfo.mHostNameBuffer;
        if (substringSize >= ArraySize(mdnsService.mHostName))
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        Platform::CopyString(mdnsService.mHostName, substringSize + 1, serviceInfo.mHostNameBuffer);

        mdnsService.mPort = serviceInfo.mPort;
    }

    // All mDNS replies come from the External Netif
    mdnsService.mInterface = ConnectivityManagerImpl().GetExternalInterface();

    // Check if AAAA record was included in DNS response.
    if (!otIp6IsAddressUnspecified(&serviceInfo.mHostAddress))
    {
        mdnsService.mAddressType = Inet::IPAddressType::kIPv6;
        mdnsService.mAddress     = MakeOptional(ToIPAddress(serviceInfo.mHostAddress));
    }

    // Check if TXT record was included in DNS response.
    if (serviceInfo.mTxtDataSize != 0)
    {
        otDnsTxtEntryIterator iterator;
        otDnsInitTxtEntryIterator(&iterator, serviceInfo.mTxtData, serviceInfo.mTxtDataSize);

        otDnsTxtEntry txtEntry;
        chip::FixedBufferAllocator alloc(serviceTxtEntries.mBuffer);

        uint8_t entryIndex = 0;
        while ((otDnsGetNextTxtEntry(&iterator, &txtEntry) == OT_ERROR_NONE) && entryIndex < 64)
        {
            if (txtEntry.mKey == nullptr || txtEntry.mValue == nullptr)
                continue;

            serviceTxtEntries.mTxtEntries[entryIndex].mKey      = alloc.Clone(txtEntry.mKey);
            serviceTxtEntries.mTxtEntries[entryIndex].mData     = alloc.Clone(txtEntry.mValue, txtEntry.mValueLength);
            serviceTxtEntries.mTxtEntries[entryIndex].mDataSize = txtEntry.mValueLength;
            entryIndex++;
        }

        ReturnErrorCodeIf(alloc.AnyAllocFailed(), CHIP_ERROR_BUFFER_TOO_SMALL);

        mdnsService.mTextEntries   = serviceTxtEntries.mTxtEntries;
        mdnsService.mTextEntrySize = entryIndex;
    }
    else
    {
        mdnsService.mTextEntrySize = 0;
    }

    return CHIP_NO_ERROR;
}

void ChipDnssdResolveNoLongerNeeded(const char * instanceName) {}

CHIP_ERROR ChipDnssdReconfirmRecord(const char * hostname, chip::Inet::IPAddress address, chip::Inet::InterfaceId interface)
{
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

static void OtBrowseCallback(otError aError, const otDnsBrowseResponse * aResponse, void * aContext)
{
    CHIP_ERROR error;
    // type buffer size is kDnssdTypeAndProtocolMaxSize + . + kMaxDomainNameSize + . + termination character
    char type[Dnssd::kDnssdTypeAndProtocolMaxSize + LOCAL_DOMAIN_STRING_SIZE + 3];
    // hostname buffer size is kHostNameMaxLength + . + kMaxDomainNameSize + . + termination character
    char hostname[Dnssd::kHostNameMaxLength + LOCAL_DOMAIN_STRING_SIZE + 3];
    // secure space for the raw TXT data in the worst-case scenario relevant for Matter:
    // each entry consists of txt_entry_size (1B) + txt_entry_key + "=" + txt_entry_data
    uint8_t txtBuffer[kMaxMdnsServiceTxtEntriesNumber + kTotalMdnsServiceTxtBufferSize];

    mDnsQueryCtx * browseContext = reinterpret_cast<mDnsQueryCtx *>(aContext);
    otDnsServiceInfo serviceInfo;
    uint16_t index = 0;

    /// TODO: check this code, might be remvoed, or if not free browseContext
    if (mDnsBrowseCallback == nullptr)
    {
        ChipLogError(DeviceLayer, "Invalid dns browse callback");
        return;
    }

    VerifyOrExit(aError == OT_ERROR_NONE, error = MapOpenThreadError(aError));

    error = MapOpenThreadError(otDnsBrowseResponseGetServiceName(aResponse, type, sizeof(type)));

    VerifyOrExit(error == CHIP_NO_ERROR, );

    char serviceName[Dnssd::Common::kInstanceNameMaxLength + 1];
    while (otDnsBrowseResponseGetServiceInstance(aResponse, index, serviceName, sizeof(serviceName)) == OT_ERROR_NONE)
    {
        serviceInfo.mHostNameBuffer     = hostname;
        serviceInfo.mHostNameBufferSize = sizeof(hostname);
        serviceInfo.mTxtData            = txtBuffer;
        serviceInfo.mTxtDataSize        = sizeof(txtBuffer);

        otError err = otDnsBrowseResponseGetServiceInfo(aResponse, serviceName, &serviceInfo);
        error       = MapOpenThreadError(err);

        VerifyOrExit(err == OT_ERROR_NOT_FOUND || err == OT_ERROR_NONE, );

        mDnsQueryCtx * tmpContext = Platform::New<mDnsQueryCtx>(browseContext->matterCtx, CHIP_NO_ERROR);

        VerifyOrExit(tmpContext != nullptr, error = CHIP_ERROR_NO_MEMORY);

        error = FromOtDnsResponseToMdnsData(serviceInfo, type, tmpContext->mMdnsService, tmpContext->mServiceTxtEntry, err);
        if (CHIP_NO_ERROR == error)
        {
            // Invoke callback for every service one by one instead of for the whole
            // list due to large memory size needed to allocate on stack.
            static_assert(ArraySize(tmpContext->mMdnsService.mName) >= ArraySize(serviceName),
                          "The target buffer must be big enough");
            Platform::CopyString(tmpContext->mMdnsService.mName, serviceName);
            DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowse, reinterpret_cast<intptr_t>(tmpContext));
        }
        else
        {
            Platform::Delete<mDnsQueryCtx>(tmpContext);
        }
        index++;
    }

exit:
    // Invoke callback to notify about end-of-browse when OT_ERROR_RESPONSE_TIMEOUT is received, otherwise ignore errors
    if (aError == OT_ERROR_RESPONSE_TIMEOUT)
    {
        DeviceLayer::PlatformMgr().ScheduleWork(DispatchBrowseEmpty, reinterpret_cast<intptr_t>(browseContext));
    }
}
static void OtServiceCallback(otError aError, const otDnsServiceResponse * aResponse, void * aContext)
{
    CHIP_ERROR error;
    otError otErr;
    otDnsServiceInfo serviceInfo;
    mDnsQueryCtx * serviceContext;
    bool bStopQuery = false;

    // If error is timeout we don't need to inform the Matter app and we can just exit
    VerifyOrReturn(aError != OT_ERROR_RESPONSE_TIMEOUT, );

    bStopQuery     = true;
    serviceContext = Platform::New<mDnsQueryCtx>(aContext, MapOpenThreadError(aError));
    VerifyOrExit(serviceContext != nullptr, error = CHIP_ERROR_NO_MEMORY);

    // type buffer size is kDnssdTypeAndProtocolMaxSize + . + kMaxDomainNameSize + . + termination character
    char type[Dnssd::kDnssdTypeAndProtocolMaxSize + LOCAL_DOMAIN_STRING_SIZE + 3];
    // hostname buffer size is kHostNameMaxLength + . + kMaxDomainNameSize + . + termination character
    char hostname[Dnssd::kHostNameMaxLength + LOCAL_DOMAIN_STRING_SIZE + 3];
    // secure space for the raw TXT data in the worst-case scenario relevant for Matter:
    // each entry consists of txt_entry_size (1B) + txt_entry_key + "=" + txt_entry_data
    uint8_t txtBuffer[kMaxMdnsServiceTxtEntriesNumber + kTotalMdnsServiceTxtBufferSize];

    if (mDnsResolveCallback == nullptr)
    {
        ChipLogError(DeviceLayer, "Invalid dns resolve callback");
        return;
    }

    VerifyOrExit(aError == OT_ERROR_NONE, error = MapOpenThreadError(aError));

    error = MapOpenThreadError(otDnsServiceResponseGetServiceName(aResponse, serviceContext->mMdnsService.mName,
                                                                  sizeof(serviceContext->mMdnsService.mName), type, sizeof(type)));

    VerifyOrExit(error == CHIP_NO_ERROR, );

    serviceInfo.mHostNameBuffer     = hostname;
    serviceInfo.mHostNameBufferSize = sizeof(hostname);
    serviceInfo.mTxtData            = txtBuffer;
    serviceInfo.mTxtDataSize        = sizeof(txtBuffer);

    otErr = otDnsServiceResponseGetServiceInfo(aResponse, &serviceInfo);
    error = MapOpenThreadError(otErr);

    VerifyOrExit(error == CHIP_NO_ERROR, );

    error = FromOtDnsResponseToMdnsData(serviceInfo, type, serviceContext->mMdnsService, serviceContext->mServiceTxtEntry, otErr);

exit:
    if (serviceContext == nullptr)
    {
        DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolveNoMemory, reinterpret_cast<intptr_t>(aContext));
        return;
    }

    serviceContext->error = error;

    // If IPv6 address in unspecified (AAAA record not present), send additional DNS query to obtain IPv6 address.
    if (otIp6IsAddressUnspecified(&serviceInfo.mHostAddress))
    {
        DeviceLayer::PlatformMgr().ScheduleWork(DispatchAddressResolve, reinterpret_cast<intptr_t>(serviceContext));
    }
    else
    {
        DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast<intptr_t>(serviceContext));
    }

    if (bStopQuery)
    {
        char fullInstName[Common::kInstanceNameMaxLength + chip::Dnssd::kDnssdTypeAndProtocolMaxSize + LOCAL_DOMAIN_STRING_SIZE +
                          1] = "";
        snprintf(fullInstName, sizeof(fullInstName), "%s.%s", serviceContext->mMdnsService.mName, type);

        otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance();
        otMdnsServerStopQuery(thrInstancePtr, fullInstName);
    }
}

void DispatchBrowseEmpty(intptr_t context)
{
    auto * browseContext = reinterpret_cast<mDnsQueryCtx *>(context);
    mDnsBrowseCallback(browseContext->matterCtx, nullptr, 0, true, browseContext->error);
    Platform::Delete<mDnsQueryCtx>(browseContext);
    bBrowseInProgress = false;
}

void DispatchBrowse(intptr_t context)
{
    auto * browseContext = reinterpret_cast<mDnsQueryCtx *>(context);
    mDnsBrowseCallback(browseContext->matterCtx, &browseContext->mMdnsService, 1, false, browseContext->error);
    Platform::Delete<mDnsQueryCtx>(browseContext);
}

void DispatchBrowseNoMemory(intptr_t context)
{
    mDnsBrowseCallback(reinterpret_cast<void *>(context), nullptr, 0, true, CHIP_ERROR_NO_MEMORY);
}

void DispatchAddressResolve(intptr_t context)
{
    CHIP_ERROR error = CHIP_ERROR_NO_MEMORY; // ResolveAddress(context, OnDnsAddressResolveResult);

    // In case of address resolve failure, fill the error code field and dispatch method to end resolve process.
    if (error != CHIP_NO_ERROR)
    {
        mDnsQueryCtx * resolveContext = reinterpret_cast<mDnsQueryCtx *>(context);
        resolveContext->error         = error;

        DeviceLayer::PlatformMgr().ScheduleWork(DispatchResolve, reinterpret_cast<intptr_t>(resolveContext));
    }
}

void DispatchResolve(intptr_t context)
{
    mDnsQueryCtx * resolveContext = reinterpret_cast<mDnsQueryCtx *>(context);
    Dnssd::DnssdService & service = resolveContext->mMdnsService;
    Span<Inet::IPAddress> ipAddrs;

    if (service.mAddress.has_value())
    {
        ipAddrs = Span<Inet::IPAddress>(&*service.mAddress, 1);
    }

    mDnsResolveCallback(resolveContext->matterCtx, &service, ipAddrs, resolveContext->error);
    Platform::Delete<mDnsQueryCtx>(resolveContext);
}

void DispatchResolveNoMemory(intptr_t context)
{
    Span<Inet::IPAddress> ipAddrs;
    mDnsResolveCallback(reinterpret_cast<void *>(context), nullptr, ipAddrs, CHIP_ERROR_NO_MEMORY);
}

} // namespace Dnssd
} // namespace chip
