/*
 *
 *    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 "DnssdImpl.h"

#include <algorithm>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <string>
#include <utility>

// Note: Include dns-sd-internal.h is needed, this source file uses some undocumented functions.
#include <dns-sd-internal.h>
#include <dns-sd.h>
#include <glib.h>
#include <lib/dnssd/platform/Dnssd.h>
#include <net/if.h>

#include <inet/InetBuildConfig.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <lib/support/Span.h>
#include <platform/CHIPDeviceConfig.h>
#include <platform/PlatformManager.h>

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
#include <platform/ThreadStackManager.h>
#endif

namespace {

constexpr uint8_t kDnssdKeyMaxSize       = 32;
constexpr const char * kEmptyAddressIpv6 = "0000:0000:0000:0000:0000:0000:0000:0000";

// The number of miliseconds which must elapse without a new "found" event before
// mDNS browsing is considered finished. We need this timeout because Tizen Native
// API does not deliver all-for-now signal (such signal is delivered by e.g. Avahi)
// and the browsing callback is called multiple times (once for each service found).
constexpr unsigned int kDnssdBrowseTimeoutMs = 250;

bool IsSupportedProtocol(chip::Dnssd::DnssdServiceProtocol protocol)
{
    return (protocol == chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUdp) ||
        (protocol == chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolTcp);
}

const char * GetProtocolString(chip::Dnssd::DnssdServiceProtocol protocol)
{
    return protocol == chip::Dnssd::DnssdServiceProtocol::kDnssdProtocolUdp ? chip::Dnssd::kCommissionProtocol
                                                                            : chip::Dnssd::kOperationalProtocol;
}

std::string GetFullType(const char * type, chip::Dnssd::DnssdServiceProtocol protocol)
{
    std::ostringstream typeBuilder;
    typeBuilder << type << "." << GetProtocolString(protocol);
    return typeBuilder.str();
}

CHIP_ERROR GetChipError(int dnssdError)
{
    switch (dnssdError)
    {
    case DNSSD_ERROR_NONE:
        return CHIP_NO_ERROR;
    case DNSSD_ERROR_NAME_CONFLICT:
        return CHIP_ERROR_MDNS_COLLISION;
    case DNSSD_ERROR_OUT_OF_MEMORY:
        return CHIP_ERROR_NO_MEMORY;
    default:
        return CHIP_ERROR_INTERNAL;
    }
}

void OnRegister(dnssd_error_e result, dnssd_service_h service, void * data)
{
    auto rCtx = reinterpret_cast<chip::Dnssd::RegisterContext *>(data);

    ChipLogDetail(DeviceLayer, "DNSsd %s: name: %s, type: %s, port: %u, interfaceId: %u", __func__, rCtx->mName, rCtx->mType,
                  rCtx->mPort, rCtx->mInterfaceId);

    if (result != DNSSD_ERROR_NONE)
    {
        ChipLogError(DeviceLayer, "DNSsd %s: Error: %d", __func__, result);
        rCtx->mCallback(rCtx->mCbContext, nullptr, nullptr, GetChipError(result));
        // After this point, the context might be no longer valid
        rCtx->mInstance->RemoveContext(rCtx);
        return;
    }

    rCtx->mCallback(rCtx->mCbContext, rCtx->mType, rCtx->mName, CHIP_NO_ERROR);
}

CHIP_ERROR RegisterAsync(chip::Dnssd::RegisterContext * rCtx)
{
    ChipLogDetail(DeviceLayer, "DNSsd %s", __func__);

    int ret = dnssd_register_local_service(rCtx->mServiceHandle, OnRegister, rCtx);
    VerifyOrReturnValue(ret == DNSSD_ERROR_NONE, GetChipError(ret),
                        ChipLogError(DeviceLayer, "dnssd_register_local_service() failed. ret: %d", ret));

    rCtx->mIsRegistered = true;
    return CHIP_NO_ERROR;
}

gboolean OnBrowseTimeout(void * userData)
{
    ChipLogDetail(DeviceLayer, "DNSsd %s: all for now", __func__);

    auto * bCtx = reinterpret_cast<chip::Dnssd::BrowseContext *>(userData);

    bCtx->mCallback(bCtx->mCbContext, bCtx->mServices.data(), bCtx->mServices.size(), true, CHIP_NO_ERROR);

    // After this point the context might be no longer valid
    bCtx->mInstance->RemoveContext(bCtx);

    // This is a one-shot timer
    return G_SOURCE_REMOVE;
}

void OnBrowseAdd(chip::Dnssd::BrowseContext * context, const char * type, const char * name, uint32_t interfaceId)
{
    ChipLogDetail(DeviceLayer, "DNSsd %s: name: %s, type: %s, interfaceId: %u", __func__, StringOrNullMarker(name),
                  StringOrNullMarker(type), interfaceId);

    char * tokens  = strdup(type);
    char * regtype = strtok(tokens, ".");

    chip::Dnssd::DnssdService dnssdService = {};
    chip::Platform::CopyString(dnssdService.mName, name);
    chip::Platform::CopyString(dnssdService.mType, regtype);
    dnssdService.mProtocol  = context->mProtocol;
    dnssdService.mInterface = chip::Inet::InterfaceId(interfaceId);

    context->mServices.push_back(dnssdService);

    free(tokens);
}

void OnBrowseRemove(chip::Dnssd::BrowseContext * context, const char * type, const char * name, uint32_t interfaceId)
{
    ChipLogDetail(DeviceLayer, "DNSsd %s: name: %s, type: %s, interfaceId: %u", __func__, StringOrNullMarker(name),
                  StringOrNullMarker(type), interfaceId);
    context->mServices.erase(std::remove_if(
        context->mServices.begin(), context->mServices.end(), [name, type, interfaceId](const chip::Dnssd::DnssdService & service) {
            return strcmp(name, service.mName) == 0 && type == GetFullType(service.mType, service.mProtocol) &&
                interfaceId == service.mInterface.GetPlatformInterface();
        }));
}

void OnBrowse(dnssd_service_state_e state, dnssd_service_h service, void * data)
{
    ChipLogDetail(DeviceLayer, "DNSsd %s", __func__);
    auto bCtx = reinterpret_cast<chip::Dnssd::BrowseContext *>(data);
    int ret;

    // If there is already a timeout source, so we need to cancel it.
    if (bCtx->mTimeoutSource != nullptr)
    {
        g_source_destroy(bCtx->mTimeoutSource);
        g_source_unref(bCtx->mTimeoutSource);
    }

    // Start a timer, so we could detect when there is no more on-browse events.
    // The timeout callback function will be called in the same event loop as the
    // browse callback (this one), so locking is not required.
    auto * source = g_timeout_source_new(kDnssdBrowseTimeoutMs);
    g_source_set_callback(source, OnBrowseTimeout, bCtx, nullptr);
    g_source_attach(source, g_main_context_get_thread_default());
    bCtx->mTimeoutSource = source;

    char * type          = nullptr;
    char * name          = nullptr;
    char * ifaceName     = nullptr;
    uint32_t interfaceId = 0;

    ret = dnssd_service_get_type(service, &type);
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_type() failed. ret: %d", ret));

    ret = dnssd_service_get_name(service, &name);
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_name() failed. ret: %d", ret));

    ret = dnssd_service_get_interface(service, &ifaceName);
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_interface() failed. ret: %d", ret));

    interfaceId = if_nametoindex(ifaceName);
    VerifyOrExit(interfaceId > 0, ChipLogError(DeviceLayer, "if_nametoindex() failed. errno: %d", errno);
                 ret = DNSSD_ERROR_OPERATION_FAILED);

    if (state == DNSSD_SERVICE_STATE_AVAILABLE)
    {
        OnBrowseAdd(bCtx, type, name, interfaceId);
    }
    else
    {
        OnBrowseRemove(bCtx, type, name, interfaceId);
    }

exit:

    dnssd_destroy_remote_service(service);

    if (ret != DNSSD_ERROR_NONE)
    {
        bCtx->mCallback(bCtx->mCbContext, nullptr, 0, true, GetChipError(ret));
        // After this point the context might be no longer valid
        bCtx->mInstance->RemoveContext(bCtx);
    }

    g_free(type);
    g_free(name);
    g_free(ifaceName);
}

CHIP_ERROR BrowseAsync(chip::Dnssd::BrowseContext * bCtx)
{
    ChipLogDetail(DeviceLayer, "DNSsd %s", __func__);

    auto interfaceId = bCtx->mInterfaceId;
    int ret;

    if (interfaceId == 0)
    {
        ret = dnssd_browse_service(bCtx->mType, nullptr, &bCtx->mBrowserHandle, OnBrowse, bCtx);
    }
    else
    {
        char iface[IF_NAMESIZE + 1] = "";
        VerifyOrReturnValue(if_indextoname(interfaceId, iface) != nullptr, CHIP_ERROR_INTERNAL,
                            ChipLogError(DeviceLayer, "if_indextoname() failed. errno: %d", errno));
        ret = dnssd_browse_service(bCtx->mType, iface, &bCtx->mBrowserHandle, OnBrowse, bCtx);
    }

    VerifyOrReturnValue(ret == DNSSD_ERROR_NONE, GetChipError(ret),
                        ChipLogError(DeviceLayer, "dnssd_browse_service() failed. ret: %d", ret));

    bCtx->mIsBrowsing = true;
    return CHIP_NO_ERROR;
}

void GetTextEntries(unsigned short txtLen, uint8_t * txtRecord, std::vector<chip::Dnssd::TextEntry> & textEntries)
{
    VerifyOrReturn(txtLen > 1, ChipLogDetail(DeviceLayer, "DNSsd %s: No TXT records", __func__));
    const uint8_t * txtRecordEnd = txtRecord + txtLen;

    while (txtRecord < txtRecordEnd)
    {
        uint8_t txtRecordSize = txtRecord[0];
        txtRecord++;

        VerifyOrReturn(txtRecord + txtRecordSize <= txtRecordEnd,
                       ChipLogError(DeviceLayer, "DNSsd %s: Invalid TXT data", __func__));

        for (size_t i = 0; i < txtRecordSize; i++)
        {
            if (txtRecord[i] == '=')
            {
                // NULL-terminate the key string
                txtRecord[i] = '\0';

                char * key      = reinterpret_cast<char *>(txtRecord);
                uint8_t * data  = txtRecord + i + 1;
                size_t dataSize = txtRecordSize - i - 1;
                textEntries.push_back({ key, data, dataSize });

                break;
            }
        }

        // Move to the next text entry
        txtRecord += txtRecordSize;
    }
}

gboolean OnResolveFinalize(gpointer userData)
{
    ChipLogDetail(DeviceLayer, "DNSsd %s", __func__);
    auto rCtx = reinterpret_cast<chip::Dnssd::ResolveContext *>(userData);

    {
        // Lock the stack mutex when calling the callback function, so that the callback
        // function could safely perform message exchange (e.g. PASE session pairing).
        chip::DeviceLayer::StackLock lock;
        rCtx->Finalize(CHIP_NO_ERROR);
    }

    rCtx->mInstance->RemoveContext(rCtx);
    return G_SOURCE_REMOVE;
}

void OnResolve(dnssd_error_e result, dnssd_service_h service, void * userData)
{
    ChipLogDetail(DeviceLayer, "DNSsd %s", __func__);
    auto rCtx = reinterpret_cast<chip::Dnssd::ResolveContext *>(userData);

    char * name      = nullptr;
    char * ipv4      = nullptr;
    char * ipv6      = nullptr;
    int port         = 0;
    char * interface = nullptr;
    chip::Inet::IPAddress ipAddr;
    CHIP_ERROR err = CHIP_NO_ERROR;

    int ret = dnssd_service_get_name(service, &name);
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_name() failed. ret: %d", ret));

    chip::Platform::CopyString(rCtx->mResult.mName, name);
    g_free(name);

    ret = dnssd_service_get_ip(service, &ipv4, &ipv6);
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_ip() failed. ret: %d", ret));

    // If both IPv4 and IPv6 are set, IPv6 address has higher priority.
    if (ipv6 != nullptr && strcmp(ipv6, kEmptyAddressIpv6) != 0)
    {
        if (!chip::Inet::IPAddress::FromString(ipv6, ipAddr) || ipAddr.Type() != chip::Inet::IPAddressType::kIPv6)
        {
            ret = DNSSD_ERROR_OPERATION_FAILED;
        }
    }
#if INET_CONFIG_ENABLE_IPV4
    else if (ipv4 != nullptr)
    {
        if (!chip::Inet::IPAddress::FromString(ipv4, ipAddr) || ipAddr.Type() != chip::Inet::IPAddressType::kIPv4)
        {
            ret = DNSSD_ERROR_OPERATION_FAILED;
        }
    }
#endif

    ChipLogDetail(DeviceLayer, "DNSsd %s: IPv4: %s, IPv6: %s, ret: %d", __func__, StringOrNullMarker(ipv4),
                  StringOrNullMarker(ipv6), ret);

    g_free(ipv4);
    g_free(ipv6);

    VerifyOrExit(ret == DNSSD_ERROR_NONE, );

    ret = dnssd_service_get_port(service, &port);
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_port() failed. ret: %d", ret));

    rCtx->mResult.mPort = static_cast<uint16_t>(port);

    ret = dnssd_service_get_interface(service, &interface);
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_interface() failed. ret: %d", ret));

    err = chip::Inet::InterfaceId::InterfaceNameToId(interface, rCtx->mResult.mInterface);
    VerifyOrExit(
        err == CHIP_NO_ERROR,
        ChipLogError(DeviceLayer, "chip::Inet::InterfaceId::InterfaceNameToId() failed. ret: %" CHIP_ERROR_FORMAT, err.Format()));

    ret = dnssd_service_get_all_txt_record(service, &rCtx->mResultTxtRecordLen, reinterpret_cast<void **>(&rCtx->mResultTxtRecord));
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_get_all_txt_record() failed. ret: %d", ret));

    rCtx->mResult.mAddress.SetValue(ipAddr);

    {
        // Before calling the Resolve() callback, we need to lock stack mutex.
        // However, we cannot lock the stack mutex from here, because we might
        // face lock inversion problem. This callback (OnResolve()) is called
        // with the NSD internal mutex locked, which is also locked by the
        // dnssd_create_remote_service() function called in the Resolve(), and
        // the Resolve() itself is called with the stack mutex locked.
        auto * sourceIdle = g_idle_source_new();
        g_source_set_callback(sourceIdle, OnResolveFinalize, rCtx, NULL);
        g_source_attach(sourceIdle, g_main_context_get_thread_default());
        g_source_unref(sourceIdle);
    }

    return;

exit:
    rCtx->Finalize(ret != DNSSD_ERROR_NONE ? GetChipError(ret) : err);
    rCtx->mInstance->RemoveContext(rCtx);
}

CHIP_ERROR ResolveAsync(chip::Dnssd::ResolveContext * rCtx)
{
    ChipLogDetail(DeviceLayer, "DNSsd %s", __func__);

    int ret = dnssd_resolve_service(rCtx->mServiceHandle, OnResolve, rCtx);
    VerifyOrReturnValue(ret == DNSSD_ERROR_NONE, GetChipError(ret),
                        ChipLogError(DeviceLayer, "dnssd_resolve_service() failed. ret: %d", ret));

    rCtx->mIsResolving = true;
    return CHIP_NO_ERROR;
}

} // namespace

namespace chip {
namespace Dnssd {

DnssdTizen DnssdTizen::sInstance;

RegisterContext::RegisterContext(DnssdTizen * instance, const char * type, const DnssdService & service,
                                 DnssdPublishCallback callback, void * context) :
    GenericContext(ContextType::Register, instance)
{
    Platform::CopyString(mName, service.mName);
    Platform::CopyString(mType, type);
    mInterfaceId = service.mInterface.GetPlatformInterface();
    mPort        = service.mPort;

    mCallback  = callback;
    mCbContext = context;
}

RegisterContext::~RegisterContext()
{
    if (mIsRegistered)
    {
        dnssd_deregister_local_service(mServiceHandle);
    }
    if (mServiceHandle != 0)
    {
        dnssd_destroy_local_service(mServiceHandle);
    }
}

BrowseContext::BrowseContext(DnssdTizen * instance, const char * type, Dnssd::DnssdServiceProtocol protocol, uint32_t interfaceId,
                             DnssdBrowseCallback callback, void * context) :
    GenericContext(ContextType::Browse, instance)
{
    Platform::CopyString(mType, type);
    mProtocol    = protocol;
    mInterfaceId = interfaceId;

    mCallback  = callback;
    mCbContext = context;
}

BrowseContext::~BrowseContext()
{
    if (mTimeoutSource != nullptr)
    {
        g_source_destroy(mTimeoutSource);
        g_source_unref(mTimeoutSource);
    }
}

ResolveContext::ResolveContext(DnssdTizen * instance, const char * name, const char * type, uint32_t interfaceId,
                               DnssdResolveCallback callback, void * context) :
    GenericContext(ContextType::Resolve, instance)
{
    Platform::CopyString(mName, name);
    Platform::CopyString(mType, type);
    mInterfaceId = interfaceId;

    mCallback  = callback;
    mCbContext = context;
}

ResolveContext::~ResolveContext()
{
    g_free(mResultTxtRecord);
}

void ResolveContext::Finalize(CHIP_ERROR error)
{
    // In case of error, run the callback function with nullptr as the result.
    VerifyOrReturn(error == CHIP_NO_ERROR, mCallback(mCbContext, nullptr, chip::Span<chip::Inet::IPAddress>(), error));

    std::vector<chip::Dnssd::TextEntry> textEntries;
    GetTextEntries(mResultTxtRecordLen, mResultTxtRecord, textEntries);
    mResult.mTextEntries   = textEntries.empty() ? nullptr : textEntries.data();
    mResult.mTextEntrySize = textEntries.size();

    chip::Inet::IPAddress ipAddr = mResult.mAddress.Value();

    mCallback(mCbContext, &mResult, chip::Span<chip::Inet::IPAddress>(&ipAddr, 1), CHIP_NO_ERROR);
}

CHIP_ERROR DnssdTizen::Init(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context)
{
    int ret = dnssd_initialize();
    VerifyOrExit(ret == DNSSD_ERROR_NONE || ret == DNSSD_ERROR_INVALID_OPERATION /* Already initialized */, );

    initCallback(context, CHIP_NO_ERROR);
    return CHIP_NO_ERROR;

exit:
    errorCallback(context, CHIP_ERROR_INTERNAL);
    return CHIP_ERROR_INTERNAL;
}

void DnssdTizen::Shutdown()
{
    int ret = dnssd_deinitialize();
    if (ret != DNSSD_ERROR_NONE)
        ChipLogError(DeviceLayer, "DNSsd %s: Error: %d", __func__, ret);
}

CHIP_ERROR DnssdTizen::RegisterService(const DnssdService & service, DnssdPublishCallback callback, void * context)
{
    std::string fullType = GetFullType(service.mType, service.mProtocol);
    auto interfaceId     = service.mInterface.GetPlatformInterface();
    CHIP_ERROR err       = CHIP_NO_ERROR;

    ChipLogProgress(DeviceLayer, "DNSsd %s: name: %s, type: %s, interfaceId: %u, port: %u", __func__, service.mName,
                    fullType.c_str(), interfaceId, service.mPort);

    { // If the service was already registered, update it
        std::lock_guard<std::mutex> lock(mMutex);

        auto iServiceCtx = std::find_if(mContexts.begin(), mContexts.end(), [fullType, service, interfaceId](const auto & ctx) {
            VerifyOrReturnValue(ctx->mContextType == ContextType::Register, false);
            auto * rCtx = static_cast<RegisterContext *>(ctx.get());
            return strcmp(rCtx->mName, service.mName) == 0 && strcmp(rCtx->mType, fullType.c_str()) == 0 &&
                rCtx->mPort == service.mPort && rCtx->mInterfaceId == interfaceId;
        });
        if (iServiceCtx != mContexts.end())
        {
            ChipLogDetail(DeviceLayer, "DNSsd %s: Updating TXT records", __func__);
            auto serviceHandle = static_cast<RegisterContext *>(iServiceCtx->get())->mServiceHandle;

            for (size_t i = 0; i < service.mTextEntrySize; ++i)
            {
                TextEntry entry = service.mTextEntries[i];
                VerifyOrReturnError(chip::CanCastTo<unsigned short>(entry.mDataSize), CHIP_ERROR_INVALID_ARGUMENT);
                auto dataSize = static_cast<unsigned short>(entry.mDataSize);
                int ret       = dnssd_service_add_txt_record(serviceHandle, entry.mKey, dataSize, entry.mData);
                if (ret != DNSSD_ERROR_NONE)
                {
                    ChipLogError(DeviceLayer, "dnssd_service_add_txt_record() failed. ret: %d", ret);
                    callback(context, nullptr, nullptr, err = GetChipError(ret));
                }
            }

            return err;
        }
    }

    auto serviceCtx = CreateRegisterContext(fullType.c_str(), service, callback, context);

    // Local service will be freed by the RegisterContext destructor
    int ret            = dnssd_create_local_service(fullType.c_str(), &serviceCtx->mServiceHandle);
    auto serviceHandle = serviceCtx->mServiceHandle;
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_create_local_service() failed. ret: %d", ret);
                 err = GetChipError(ret));

    ret = dnssd_service_set_name(serviceHandle, service.mName);
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_set_name() failed. ret: %d", ret);
                 err = GetChipError(ret));

    ret = dnssd_service_set_port(serviceHandle, service.mPort);
    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_set_port() failed. ret: %d", ret);
                 err = GetChipError(ret));

    if (interfaceId > 0)
    {
        char iface[IF_NAMESIZE + 1] = "";
        VerifyOrExit(if_indextoname(interfaceId, iface) != nullptr,
                     ChipLogError(DeviceLayer, "if_indextoname() failed. errno: %d", errno);
                     err = CHIP_ERROR_INTERNAL);
        ret = dnssd_service_set_interface(serviceHandle, iface);
        VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_set_interface() failed. ret: %d", ret);
                     err = GetChipError(ret));
    }

    for (size_t i = 0; i < service.mTextEntrySize; ++i)
    {
        TextEntry entry = service.mTextEntries[i];
        VerifyOrReturnError(chip::CanCastTo<unsigned short>(entry.mDataSize), CHIP_ERROR_INVALID_ARGUMENT);
        ret = dnssd_service_add_txt_record(serviceHandle, entry.mKey, static_cast<unsigned short>(entry.mDataSize), entry.mData);
        VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_service_add_txt_record() failed. ret: %d", ret);
                     err = GetChipError(ret));
    }

    err = DeviceLayer::PlatformMgrImpl().GLibMatterContextInvokeSync(RegisterAsync, serviceCtx);
    SuccessOrExit(err);

exit:
    if (err != CHIP_NO_ERROR)
    { // Notify caller about error
        callback(context, nullptr, nullptr, err);
        RemoveContext(serviceCtx);
    }
    return err;
}

CHIP_ERROR DnssdTizen::UnregisterAllServices()
{
    std::lock_guard<std::mutex> lock(mMutex);

    unsigned int numServices = 0;
    for (auto it = mContexts.begin(); it != mContexts.end(); it++)
    {
        if ((*it)->mContextType == ContextType::Register)
        {
            mContexts.erase(it--);
            numServices++;
        }
    }

    ChipLogDetail(DeviceLayer, "DNSsd %s: %u", __func__, numServices);
    return CHIP_NO_ERROR;
}

CHIP_ERROR DnssdTizen::Browse(const char * type, Dnssd::DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType,
                              chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context)
{
    std::string fullType = GetFullType(type, protocol);
    auto interfaceId     = interface.GetPlatformInterface();
    CHIP_ERROR err       = CHIP_NO_ERROR;

    auto browseCtx = CreateBrowseContext(fullType.c_str(), protocol, interfaceId, callback, context);

    err = DeviceLayer::PlatformMgrImpl().GLibMatterContextInvokeSync(BrowseAsync, browseCtx);
    SuccessOrExit(err);

exit:
    if (err != CHIP_NO_ERROR)
    { // Notify caller about error
        callback(context, nullptr, 0, true, err);
        RemoveContext(browseCtx);
    }
    return err;
}

CHIP_ERROR DnssdTizen::Resolve(const DnssdService & browseResult, chip::Inet::InterfaceId interface, DnssdResolveCallback callback,
                               void * context)
{
    std::string fullType = GetFullType(browseResult.mType, browseResult.mProtocol);
    auto interfaceId     = interface.GetPlatformInterface();
    CHIP_ERROR err       = CHIP_NO_ERROR;
    int ret;

    ChipLogDetail(DeviceLayer, "DNSsd %s: name: %s, type: %s, interfaceId: %u", __func__, browseResult.mName, fullType.c_str(),
                  interfaceId);

    auto resolveCtx = CreateResolveContext(browseResult.mName, fullType.c_str(), interfaceId, callback, context);

    if (interfaceId == 0)
    {
        ret = dnssd_create_remote_service(fullType.c_str(), browseResult.mName, nullptr, &resolveCtx->mServiceHandle);
    }
    else
    {
        char iface[IF_NAMESIZE + 1] = "";
        VerifyOrExit(if_indextoname(interfaceId, iface) != nullptr,
                     ChipLogError(DeviceLayer, "if_indextoname() failed. errno: %d", errno);
                     err = CHIP_ERROR_INTERNAL);
        ret = dnssd_create_remote_service(fullType.c_str(), browseResult.mName, iface, &resolveCtx->mServiceHandle);
    }

    VerifyOrExit(ret == DNSSD_ERROR_NONE, ChipLogError(DeviceLayer, "dnssd_create_remote_service() failed. ret: %d", ret);
                 err = GetChipError(ret));

    err = DeviceLayer::PlatformMgrImpl().GLibMatterContextInvokeSync(ResolveAsync, resolveCtx);
    SuccessOrExit(err);

exit:
    if (err != CHIP_NO_ERROR)
        RemoveContext(resolveCtx);
    return err;
}

RegisterContext * DnssdTizen::CreateRegisterContext(const char * type, const DnssdService & service, DnssdPublishCallback callback,
                                                    void * context)
{
    auto ctx    = std::make_unique<RegisterContext>(this, type, service, callback, context);
    auto ctxPtr = ctx.get();

    std::lock_guard<std::mutex> lock(mMutex);
    mContexts.emplace(std::move(ctx));

    return ctxPtr;
}

BrowseContext * DnssdTizen::CreateBrowseContext(const char * type, Dnssd::DnssdServiceProtocol protocol, uint32_t interfaceId,
                                                DnssdBrowseCallback callback, void * context)
{
    auto ctx    = std::make_unique<BrowseContext>(this, type, protocol, interfaceId, callback, context);
    auto ctxPtr = ctx.get();

    std::lock_guard<std::mutex> lock(mMutex);
    mContexts.emplace(std::move(ctx));

    return ctxPtr;
}

ResolveContext * DnssdTizen::CreateResolveContext(const char * name, const char * type, uint32_t interfaceId,
                                                  DnssdResolveCallback callback, void * context)
{
    auto ctx    = std::make_unique<ResolveContext>(this, name, type, interfaceId, callback, context);
    auto ctxPtr = ctx.get();

    std::lock_guard<std::mutex> lock(mMutex);
    mContexts.emplace(std::move(ctx));

    return ctxPtr;
}

CHIP_ERROR DnssdTizen::RemoveContext(GenericContext * context)
{
    std::lock_guard<std::mutex> lock(mMutex);
    mContexts.erase(std::find_if(mContexts.begin(), mContexts.end(), [context](const auto & ctx) { return ctx.get() == context; }));
    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context)
{
    VerifyOrReturnError(initCallback != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(errorCallback != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    return DnssdTizen::GetInstance().Init(initCallback, errorCallback, context);
}

void ChipDnssdShutdown()
{
    DnssdTizen::GetInstance().Shutdown();
}

CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context)
{
    VerifyOrReturnError(service != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(IsSupportedProtocol(service->mProtocol), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(callback != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT
    if (DeviceLayer::ThreadStackMgr().IsThreadEnabled())
    {
        std::string regtype = GetFullType(service->mType, service->mProtocol);
        Span<const char * const> subTypes(service->mSubTypes, service->mSubTypeSize);
        Span<const TextEntry> textEntries(service->mTextEntries, service->mTextEntrySize);
        CHIP_ERROR err;

        if (strcmp(service->mHostName, "") != 0)
        {
            err = DeviceLayer::ThreadStackMgr().SetupSrpHost(service->mHostName);
            VerifyOrReturnError(err == CHIP_NO_ERROR, err);
        }

        err = DeviceLayer::ThreadStackMgr().AddSrpService(service->mName, regtype.c_str(), service->mPort, subTypes, textEntries);
        VerifyOrReturnError(err == CHIP_NO_ERROR, err);

        return CHIP_NO_ERROR;
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT

    return DnssdTizen::GetInstance().RegisterService(*service, callback, context);
}

CHIP_ERROR ChipDnssdRemoveServices()
{

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT
    if (DeviceLayer::ThreadStackMgr().IsThreadEnabled())
    {
        DeviceLayer::ThreadStackMgr().InvalidateAllSrpServices();
        return DeviceLayer::ThreadStackMgr().RemoveInvalidSrpServices();
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT

    return DnssdTizen::GetInstance().UnregisterAllServices();
}

CHIP_ERROR ChipDnssdFinalizeServiceUpdate()
{
    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDnssdBrowse(const char * type, Dnssd::DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType,
                           chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context,
                           intptr_t * browseIdentifier)
{
    VerifyOrReturnError(type != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(IsSupportedProtocol(protocol), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(callback != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    *browseIdentifier = reinterpret_cast<intptr_t>(nullptr);

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT
    if (DeviceLayer::ThreadStackMgr().IsThreadEnabled())
    {
        std::string fullType = GetFullType(type, protocol);
        return DeviceLayer::ThreadStackMgr().DnsBrowse(fullType.c_str(), callback, context);
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT

    return DnssdTizen::GetInstance().Browse(type, protocol, addressType, interface, callback, context);
}

CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier)
{
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR ChipDnssdResolve(DnssdService * browseResult, chip::Inet::InterfaceId interface, DnssdResolveCallback callback,
                            void * context)
{
    VerifyOrReturnError(browseResult != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(IsSupportedProtocol(browseResult->mProtocol), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(callback != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT
    if (DeviceLayer::ThreadStackMgr().IsThreadEnabled())
    {
        std::string fullType = GetFullType(browseResult->mType, browseResult->mProtocol);
        return DeviceLayer::ThreadStackMgr().DnsResolve(fullType.c_str(), browseResult->mName, callback, context);
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT && CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT

    return DnssdTizen::GetInstance().Resolve(*browseResult, interface, callback, context);
}

void ChipDnssdResolveNoLongerNeeded(const char * instanceName) {}

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

} // namespace Dnssd
} // namespace chip
