/*
 *  Copyright (c) 2017-2021, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

#include "dns_client.hpp"

#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE

#include "common/array.hpp"
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "net/udp6.hpp"
#include "thread/network_data_types.hpp"
#include "thread/thread_netif.hpp"

/**
 * @file
 *   This file implements the DNS client.
 */

namespace ot {
namespace Dns {

#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
using ot::Encoding::BigEndian::ReadUint16;
using ot::Encoding::BigEndian::WriteUint16;
#endif

RegisterLogModule("DnsClient");

//---------------------------------------------------------------------------------------------------------------------
// Client::QueryConfig

const char Client::QueryConfig::kDefaultServerAddressString[] = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_IP6_ADDRESS;

Client::QueryConfig::QueryConfig(InitMode aMode)
{
    OT_UNUSED_VARIABLE(aMode);

    IgnoreError(GetServerSockAddr().GetAddress().FromString(kDefaultServerAddressString));
    GetServerSockAddr().SetPort(kDefaultServerPort);
    SetResponseTimeout(kDefaultResponseTimeout);
    SetMaxTxAttempts(kDefaultMaxTxAttempts);
    SetRecursionFlag(kDefaultRecursionDesired ? kFlagRecursionDesired : kFlagNoRecursion);
    SetServiceMode(kDefaultServiceMode);
#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
    SetNat64Mode(kDefaultNat64Allowed ? kNat64Allow : kNat64Disallow);
#endif
    SetTransportProto(kDnsTransportUdp);
}

void Client::QueryConfig::SetFrom(const QueryConfig *aConfig, const QueryConfig &aDefaultConfig)
{
    // This method sets the config from `aConfig` replacing any
    // unspecified fields (value zero) with the fields from
    // `aDefaultConfig`. If `aConfig` is `nullptr` then
    // `aDefaultConfig` is used.

    if (aConfig == nullptr)
    {
        *this = aDefaultConfig;
        ExitNow();
    }

    *this = *aConfig;

    if (GetServerSockAddr().GetAddress().IsUnspecified())
    {
        GetServerSockAddr().GetAddress() = aDefaultConfig.GetServerSockAddr().GetAddress();
    }

    if (GetServerSockAddr().GetPort() == 0)
    {
        GetServerSockAddr().SetPort(aDefaultConfig.GetServerSockAddr().GetPort());
    }

    if (GetResponseTimeout() == 0)
    {
        SetResponseTimeout(aDefaultConfig.GetResponseTimeout());
    }

    if (GetMaxTxAttempts() == 0)
    {
        SetMaxTxAttempts(aDefaultConfig.GetMaxTxAttempts());
    }

    if (GetRecursionFlag() == kFlagUnspecified)
    {
        SetRecursionFlag(aDefaultConfig.GetRecursionFlag());
    }

#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
    if (GetNat64Mode() == kNat64Unspecified)
    {
        SetNat64Mode(aDefaultConfig.GetNat64Mode());
    }
#endif

    if (GetServiceMode() == kServiceModeUnspecified)
    {
        SetServiceMode(aDefaultConfig.GetServiceMode());
    }

    if (GetTransportProto() == kDnsTransportUnspecified)
    {
        SetTransportProto(aDefaultConfig.GetTransportProto());
    }

exit:
    return;
}

//---------------------------------------------------------------------------------------------------------------------
// Client::Response

void Client::Response::SelectSection(Section aSection, uint16_t &aOffset, uint16_t &aNumRecord) const
{
    switch (aSection)
    {
    case kAnswerSection:
        aOffset    = mAnswerOffset;
        aNumRecord = mAnswerRecordCount;
        break;
    case kAdditionalDataSection:
    default:
        aOffset    = mAdditionalOffset;
        aNumRecord = mAdditionalRecordCount;
        break;
    }
}

Error Client::Response::GetName(char *aNameBuffer, uint16_t aNameBufferSize) const
{
    uint16_t offset = kNameOffsetInQuery;

    return Name::ReadName(*mQuery, offset, aNameBuffer, aNameBufferSize);
}

Error Client::Response::CheckForHostNameAlias(Section aSection, Name &aHostName) const
{
    // If the response includes a CNAME record mapping the query host
    // name to a canonical name, we update `aHostName` to the new alias
    // name. Otherwise `aHostName` remains as before. This method handles
    // when there are multiple CNAME records mapping the host name multiple
    // times. We limit number of changes to `kMaxCnameAliasNameChanges`
    // to detect and handle if the response contains CNAME record loops.

    Error       error;
    uint16_t    offset;
    uint16_t    numRecords;
    CnameRecord cnameRecord;

    VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);

    for (uint16_t counter = 0; counter < kMaxCnameAliasNameChanges; counter++)
    {
        SelectSection(aSection, offset, numRecords);
        error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, /* aIndex */ 0, aHostName, cnameRecord);

        if (error == kErrorNotFound)
        {
            error = kErrorNone;
            ExitNow();
        }

        SuccessOrExit(error);

        // A CNAME record was found. `offset` now points to after the
        // last read byte within the `mMessage` into the `cnameRecord`
        // (which is the start of the new canonical name).

        aHostName.SetFromMessage(*mMessage, offset);
        SuccessOrExit(error = Name::ParseName(*mMessage, offset));

        // Loop back to check if there may be a CNAME record for the
        // new `aHostName`.
    }

    error = kErrorParse;

exit:
    return error;
}

Error Client::Response::FindHostAddress(Section       aSection,
                                        const Name   &aHostName,
                                        uint16_t      aIndex,
                                        Ip6::Address &aAddress,
                                        uint32_t     &aTtl) const
{
    Error      error;
    uint16_t   offset;
    uint16_t   numRecords;
    Name       name = aHostName;
    AaaaRecord aaaaRecord;

    SuccessOrExit(error = CheckForHostNameAlias(aSection, name));

    SelectSection(aSection, offset, numRecords);
    SuccessOrExit(error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, aIndex, name, aaaaRecord));
    aAddress = aaaaRecord.GetAddress();
    aTtl     = aaaaRecord.GetTtl();

exit:
    return error;
}

#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE

Error Client::Response::FindARecord(Section aSection, const Name &aHostName, uint16_t aIndex, ARecord &aARecord) const
{
    Error    error;
    uint16_t offset;
    uint16_t numRecords;
    Name     name = aHostName;

    SuccessOrExit(error = CheckForHostNameAlias(aSection, name));

    SelectSection(aSection, offset, numRecords);
    error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, aIndex, name, aARecord);

exit:
    return error;
}

#endif // OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE

#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE

void Client::Response::InitServiceInfo(ServiceInfo &aServiceInfo) const
{
    // This method initializes `aServiceInfo` setting all
    // TTLs to zero and host name to empty string.

    aServiceInfo.mTtl              = 0;
    aServiceInfo.mHostAddressTtl   = 0;
    aServiceInfo.mTxtDataTtl       = 0;
    aServiceInfo.mTxtDataTruncated = false;

    AsCoreType(&aServiceInfo.mHostAddress).Clear();

    if ((aServiceInfo.mHostNameBuffer != nullptr) && (aServiceInfo.mHostNameBufferSize > 0))
    {
        aServiceInfo.mHostNameBuffer[0] = '\0';
    }
}

Error Client::Response::ReadServiceInfo(Section aSection, const Name &aName, ServiceInfo &aServiceInfo) const
{
    // This method searches for SRV record in the given `aSection`
    // matching the record name against `aName`, and updates the
    // `aServiceInfo` accordingly. It also searches for AAAA record
    // for host name associated with the service (from SRV record).
    // The search for AAAA record is always performed in Additional
    // Data section (independent of the value given in `aSection`).

    Error     error = kErrorNone;
    uint16_t  offset;
    uint16_t  numRecords;
    Name      hostName;
    SrvRecord srvRecord;

    // A non-zero `mTtl` indicates that SRV record is already found
    // and parsed from a previous response.
    VerifyOrExit(aServiceInfo.mTtl == 0);

    VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);

    // Search for a matching SRV record
    SelectSection(aSection, offset, numRecords);
    SuccessOrExit(error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, /* aIndex */ 0, aName, srvRecord));

    aServiceInfo.mTtl      = srvRecord.GetTtl();
    aServiceInfo.mPort     = srvRecord.GetPort();
    aServiceInfo.mPriority = srvRecord.GetPriority();
    aServiceInfo.mWeight   = srvRecord.GetWeight();

    hostName.SetFromMessage(*mMessage, offset);

    if (aServiceInfo.mHostNameBuffer != nullptr)
    {
        SuccessOrExit(error = srvRecord.ReadTargetHostName(*mMessage, offset, aServiceInfo.mHostNameBuffer,
                                                           aServiceInfo.mHostNameBufferSize));
    }
    else
    {
        SuccessOrExit(error = Name::ParseName(*mMessage, offset));
    }

    // Search in additional section for AAAA record for the host name.

    VerifyOrExit(AsCoreType(&aServiceInfo.mHostAddress).IsUnspecified());

    error = FindHostAddress(kAdditionalDataSection, hostName, /* aIndex */ 0, AsCoreType(&aServiceInfo.mHostAddress),
                            aServiceInfo.mHostAddressTtl);

    if (error == kErrorNotFound)
    {
        error = kErrorNone;
    }

exit:
    return error;
}

Error Client::Response::ReadTxtRecord(Section aSection, const Name &aName, ServiceInfo &aServiceInfo) const
{
    // This method searches a TXT record in the given `aSection`
    // matching the record name against `aName` and updates the TXT
    // related properties in `aServicesInfo`.
    //
    // If no match is found `mTxtDataTtl` (which is initialized to zero)
    // remains unchanged to indicate this. In this case this method still
    // returns `kErrorNone`.

    Error     error = kErrorNone;
    uint16_t  offset;
    uint16_t  numRecords;
    TxtRecord txtRecord;

    // A non-zero `mTxtDataTtl` indicates that TXT record is already
    // found and parsed from a previous response.
    VerifyOrExit(aServiceInfo.mTxtDataTtl == 0);

    // A null `mTxtData` indicates that caller does not want to retrieve
    // TXT data.
    VerifyOrExit(aServiceInfo.mTxtData != nullptr);

    VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);

    SelectSection(aSection, offset, numRecords);

    aServiceInfo.mTxtDataTruncated = false;

    SuccessOrExit(error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, /* aIndex */ 0, aName, txtRecord));

    error = txtRecord.ReadTxtData(*mMessage, offset, aServiceInfo.mTxtData, aServiceInfo.mTxtDataSize);

    if (error == kErrorNoBufs)
    {
        error = kErrorNone;

        // Mark `mTxtDataTruncated` to indicate that we could not read
        // the full TXT record into the given `mTxtData` buffer.
        aServiceInfo.mTxtDataTruncated = true;
    }

    SuccessOrExit(error);
    aServiceInfo.mTxtDataTtl = txtRecord.GetTtl();

exit:
    if (error == kErrorNotFound)
    {
        error = kErrorNone;
    }

    return error;
}

#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE

void Client::Response::PopulateFrom(const Message &aMessage)
{
    // Populate `Response` with info from `aMessage`.

    uint16_t offset = aMessage.GetOffset();
    Header   header;

    mMessage = &aMessage;

    IgnoreError(aMessage.Read(offset, header));
    offset += sizeof(Header);

    for (uint16_t num = 0; num < header.GetQuestionCount(); num++)
    {
        IgnoreError(Name::ParseName(aMessage, offset));
        offset += sizeof(Question);
    }

    mAnswerOffset = offset;
    IgnoreError(ResourceRecord::ParseRecords(aMessage, offset, header.GetAnswerCount()));
    IgnoreError(ResourceRecord::ParseRecords(aMessage, offset, header.GetAuthorityRecordCount()));
    mAdditionalOffset = offset;
    IgnoreError(ResourceRecord::ParseRecords(aMessage, offset, header.GetAdditionalRecordCount()));

    mAnswerRecordCount     = header.GetAnswerCount();
    mAdditionalRecordCount = header.GetAdditionalRecordCount();
}

//---------------------------------------------------------------------------------------------------------------------
// Client::AddressResponse

Error Client::AddressResponse::GetAddress(uint16_t aIndex, Ip6::Address &aAddress, uint32_t &aTtl) const
{
    Error error = kErrorNone;
    Name  name(*mQuery, kNameOffsetInQuery);

#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE

    // If the response is for an IPv4 address query or if it is an
    // IPv6 address query response with no IPv6 address but with
    // an IPv4 in its additional section, we read the IPv4 address
    // and translate it to an IPv6 address.

    QueryInfo info;

    info.ReadFrom(*mQuery);

    if ((info.mQueryType == kIp4AddressQuery) || mIp6QueryResponseRequiresNat64)
    {
        Section                          section;
        ARecord                          aRecord;
        NetworkData::ExternalRouteConfig nat64Prefix;

        VerifyOrExit(mInstance->Get<NetworkData::Leader>().GetPreferredNat64Prefix(nat64Prefix) == kErrorNone,
                     error = kErrorInvalidState);

        section = (info.mQueryType == kIp4AddressQuery) ? kAnswerSection : kAdditionalDataSection;
        SuccessOrExit(error = FindARecord(section, name, aIndex, aRecord));

        aAddress.SynthesizeFromIp4Address(nat64Prefix.GetPrefix(), aRecord.GetAddress());
        aTtl = aRecord.GetTtl();

        ExitNow();
    }

#endif // OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE

    ExitNow(error = FindHostAddress(kAnswerSection, name, aIndex, aAddress, aTtl));

exit:
    return error;
}

#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE

//---------------------------------------------------------------------------------------------------------------------
// Client::BrowseResponse

Error Client::BrowseResponse::GetServiceInstance(uint16_t aIndex, char *aLabelBuffer, uint8_t aLabelBufferSize) const
{
    Error     error;
    uint16_t  offset;
    uint16_t  numRecords;
    Name      serviceName(*mQuery, kNameOffsetInQuery);
    PtrRecord ptrRecord;

    VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);

    SelectSection(kAnswerSection, offset, numRecords);
    SuccessOrExit(error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, aIndex, serviceName, ptrRecord));
    error = ptrRecord.ReadPtrName(*mMessage, offset, aLabelBuffer, aLabelBufferSize, nullptr, 0);

exit:
    return error;
}

Error Client::BrowseResponse::GetServiceInfo(const char *aInstanceLabel, ServiceInfo &aServiceInfo) const
{
    Error error;
    Name  instanceName;

    // Find a matching PTR record for the service instance label. Then
    // search and read SRV, TXT and AAAA records in Additional Data
    // section matching the same name to populate `aServiceInfo`.

    SuccessOrExit(error = FindPtrRecord(aInstanceLabel, instanceName));

    InitServiceInfo(aServiceInfo);
    SuccessOrExit(error = ReadServiceInfo(kAdditionalDataSection, instanceName, aServiceInfo));
    SuccessOrExit(error = ReadTxtRecord(kAdditionalDataSection, instanceName, aServiceInfo));

    if (aServiceInfo.mTxtDataTtl == 0)
    {
        aServiceInfo.mTxtDataSize = 0;
    }

exit:
    return error;
}

Error Client::BrowseResponse::GetHostAddress(const char   *aHostName,
                                             uint16_t      aIndex,
                                             Ip6::Address &aAddress,
                                             uint32_t     &aTtl) const
{
    return FindHostAddress(kAdditionalDataSection, Name(aHostName), aIndex, aAddress, aTtl);
}

Error Client::BrowseResponse::FindPtrRecord(const char *aInstanceLabel, Name &aInstanceName) const
{
    // This method searches within the Answer Section for a PTR record
    // matching a given instance label @aInstanceLabel. If found, the
    // `aName` is updated to return the name in the message.

    Error     error;
    uint16_t  offset;
    Name      serviceName(*mQuery, kNameOffsetInQuery);
    uint16_t  numRecords;
    uint16_t  labelOffset;
    PtrRecord ptrRecord;

    VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);

    SelectSection(kAnswerSection, offset, numRecords);

    for (; numRecords > 0; numRecords--)
    {
        SuccessOrExit(error = Name::CompareName(*mMessage, offset, serviceName));

        error = ResourceRecord::ReadRecord(*mMessage, offset, ptrRecord);

        if (error == kErrorNotFound)
        {
            // `ReadRecord()` updates `offset` to skip over a
            // non-matching record.
            continue;
        }

        SuccessOrExit(error);

        // It is a PTR record. Check the first label to match the
        // instance label.

        labelOffset = offset;
        error       = Name::CompareLabel(*mMessage, labelOffset, aInstanceLabel);

        if (error == kErrorNone)
        {
            aInstanceName.SetFromMessage(*mMessage, offset);
            ExitNow();
        }

        VerifyOrExit(error == kErrorNotFound);

        // Update offset to skip over the PTR record.
        offset += static_cast<uint16_t>(ptrRecord.GetSize()) - sizeof(ptrRecord);
    }

    error = kErrorNotFound;

exit:
    return error;
}

//---------------------------------------------------------------------------------------------------------------------
// Client::ServiceResponse

Error Client::ServiceResponse::GetServiceName(char    *aLabelBuffer,
                                              uint8_t  aLabelBufferSize,
                                              char    *aNameBuffer,
                                              uint16_t aNameBufferSize) const
{
    Error    error;
    uint16_t offset = kNameOffsetInQuery;

    SuccessOrExit(error = Name::ReadLabel(*mQuery, offset, aLabelBuffer, aLabelBufferSize));

    VerifyOrExit(aNameBuffer != nullptr);
    SuccessOrExit(error = Name::ReadName(*mQuery, offset, aNameBuffer, aNameBufferSize));

exit:
    return error;
}

Error Client::ServiceResponse::GetServiceInfo(ServiceInfo &aServiceInfo) const
{
    // Search and read SRV, TXT records matching name from query.

    Error error = kErrorNotFound;

    InitServiceInfo(aServiceInfo);

    for (const Response *response = this; response != nullptr; response = response->mNext)
    {
        Name      name(*response->mQuery, kNameOffsetInQuery);
        QueryInfo info;
        Section   srvSection;
        Section   txtSection;

        info.ReadFrom(*response->mQuery);

        switch (info.mQueryType)
        {
        case kIp6AddressQuery:
#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
        case kIp4AddressQuery:
#endif
            IgnoreError(response->FindHostAddress(kAnswerSection, name, /* aIndex */ 0,
                                                  AsCoreType(&aServiceInfo.mHostAddress),
                                                  aServiceInfo.mHostAddressTtl));

            continue; // to `for()` loop

        case kServiceQuerySrvTxt:
        case kServiceQuerySrv:
        case kServiceQueryTxt:
            break;

        default:
            continue;
        }

        // Determine from which section we should try to read the SRV and
        // TXT records based on the query type.
        //
        // In `kServiceQuerySrv` or `kServiceQueryTxt` we expect to see
        // only one record (SRV or TXT) in the answer section, but we
        // still try to read the other records from additional data
        // section in case server provided them.

        srvSection = (info.mQueryType != kServiceQueryTxt) ? kAnswerSection : kAdditionalDataSection;
        txtSection = (info.mQueryType != kServiceQuerySrv) ? kAnswerSection : kAdditionalDataSection;

        error = response->ReadServiceInfo(srvSection, name, aServiceInfo);

        if ((srvSection == kAdditionalDataSection) && (error == kErrorNotFound))
        {
            error = kErrorNone;
        }

        SuccessOrExit(error);

        SuccessOrExit(error = response->ReadTxtRecord(txtSection, name, aServiceInfo));
    }

    if (aServiceInfo.mTxtDataTtl == 0)
    {
        aServiceInfo.mTxtDataSize = 0;
    }

exit:
    return error;
}

Error Client::ServiceResponse::GetHostAddress(const char   *aHostName,
                                              uint16_t      aIndex,
                                              Ip6::Address &aAddress,
                                              uint32_t     &aTtl) const
{
    Error error = kErrorNotFound;

    for (const Response *response = this; response != nullptr; response = response->mNext)
    {
        Section   section = kAdditionalDataSection;
        QueryInfo info;

        info.ReadFrom(*response->mQuery);

        switch (info.mQueryType)
        {
        case kIp6AddressQuery:
#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
        case kIp4AddressQuery:
#endif
            section = kAnswerSection;
            break;

        default:
            break;
        }

        error = response->FindHostAddress(section, Name(aHostName), aIndex, aAddress, aTtl);

        if (error == kErrorNone)
        {
            break;
        }
    }

    return error;
}

#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE

//---------------------------------------------------------------------------------------------------------------------
// Client

const uint16_t Client::kIp6AddressQueryRecordTypes[] = {ResourceRecord::kTypeAaaa};
#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
const uint16_t Client::kIp4AddressQueryRecordTypes[] = {ResourceRecord::kTypeA};
#endif
#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
const uint16_t Client::kBrowseQueryRecordTypes[]  = {ResourceRecord::kTypePtr};
const uint16_t Client::kServiceQueryRecordTypes[] = {ResourceRecord::kTypeSrv, ResourceRecord::kTypeTxt};
#endif

const uint8_t Client::kQuestionCount[] = {
    /* kIp6AddressQuery -> */ GetArrayLength(kIp6AddressQueryRecordTypes), // AAAA record
#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
    /* kIp4AddressQuery -> */ GetArrayLength(kIp4AddressQueryRecordTypes), // A record
#endif
#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
    /* kBrowseQuery        -> */ GetArrayLength(kBrowseQueryRecordTypes),  // PTR record
    /* kServiceQuerySrvTxt -> */ GetArrayLength(kServiceQueryRecordTypes), // SRV and TXT records
    /* kServiceQuerySrv    -> */ 1,                                        // SRV record only
    /* kServiceQueryTxt    -> */ 1,                                        // TXT record only
#endif
};

const uint16_t *const Client::kQuestionRecordTypes[] = {
    /* kIp6AddressQuery -> */ kIp6AddressQueryRecordTypes,
#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
    /* kIp4AddressQuery -> */ kIp4AddressQueryRecordTypes,
#endif
#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
    /* kBrowseQuery  -> */ kBrowseQueryRecordTypes,
    /* kServiceQuerySrvTxt -> */ kServiceQueryRecordTypes,
    /* kServiceQuerySrv    -> */ &kServiceQueryRecordTypes[0],
    /* kServiceQueryTxt    -> */ &kServiceQueryRecordTypes[1],

#endif
};

Client::Client(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mSocket(aInstance)
#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
    , mTcpState(kTcpUninitialized)
#endif
    , mTimer(aInstance)
    , mDefaultConfig(QueryConfig::kInitFromDefaults)
#if OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE
    , mUserDidSetDefaultAddress(false)
#endif
{
    static_assert(kIp6AddressQuery == 0, "kIp6AddressQuery value is not correct");
#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
    static_assert(kIp4AddressQuery == 1, "kIp4AddressQuery value is not correct");
#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
    static_assert(kBrowseQuery == 2, "kBrowseQuery value is not correct");
    static_assert(kServiceQuerySrvTxt == 3, "kServiceQuerySrvTxt value is not correct");
    static_assert(kServiceQuerySrv == 4, "kServiceQuerySrv value is not correct");
    static_assert(kServiceQueryTxt == 5, "kServiceQueryTxt value is not correct");
#endif
#elif OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
    static_assert(kBrowseQuery == 1, "kBrowseQuery value is not correct");
    static_assert(kServiceQuerySrvTxt == 2, "kServiceQuerySrvTxt value is not correct");
    static_assert(kServiceQuerySrv == 3, "kServiceQuerySrv value is not correct");
    static_assert(kServiceQueryTxt == 4, "kServiceQuerySrv value is not correct");
#endif
}

Error Client::Start(void)
{
    Error error;

    SuccessOrExit(error = mSocket.Open(&Client::HandleUdpReceive, this));
    SuccessOrExit(error = mSocket.Bind(0, Ip6::kNetifUnspecified));

exit:
    return error;
}

void Client::Stop(void)
{
    Query *query;

    while ((query = mMainQueries.GetHead()) != nullptr)
    {
        FinalizeQuery(*query, kErrorAbort);
    }

    IgnoreError(mSocket.Close());
#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
    if (mTcpState != kTcpUninitialized)
    {
        IgnoreError(mEndpoint.Deinitialize());
    }
#endif
}

#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
Error Client::InitTcpSocket(void)
{
    Error                       error;
    otTcpEndpointInitializeArgs endpointArgs;

    memset(&endpointArgs, 0x00, sizeof(endpointArgs));
    endpointArgs.mSendDoneCallback         = HandleTcpSendDoneCallback;
    endpointArgs.mEstablishedCallback      = HandleTcpEstablishedCallback;
    endpointArgs.mReceiveAvailableCallback = HandleTcpReceiveAvailableCallback;
    endpointArgs.mDisconnectedCallback     = HandleTcpDisconnectedCallback;
    endpointArgs.mContext                  = this;
    endpointArgs.mReceiveBuffer            = mReceiveBufferBytes;
    endpointArgs.mReceiveBufferSize        = sizeof(mReceiveBufferBytes);

    mSendLink.mNext   = nullptr;
    mSendLink.mData   = mSendBufferBytes;
    mSendLink.mLength = 0;

    SuccessOrExit(error = mEndpoint.Initialize(Get<Instance>(), endpointArgs));
exit:
    return error;
}
#endif

void Client::SetDefaultConfig(const QueryConfig &aQueryConfig)
{
    QueryConfig startingDefault(QueryConfig::kInitFromDefaults);

    mDefaultConfig.SetFrom(&aQueryConfig, startingDefault);

#if OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE
    mUserDidSetDefaultAddress = !aQueryConfig.GetServerSockAddr().GetAddress().IsUnspecified();
    UpdateDefaultConfigAddress();
#endif
}

void Client::ResetDefaultConfig(void)
{
    mDefaultConfig = QueryConfig(QueryConfig::kInitFromDefaults);

#if OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE
    mUserDidSetDefaultAddress = false;
    UpdateDefaultConfigAddress();
#endif
}

#if OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE
void Client::UpdateDefaultConfigAddress(void)
{
    const Ip6::Address &srpServerAddr = Get<Srp::Client>().GetServerAddress().GetAddress();

    if (!mUserDidSetDefaultAddress && Get<Srp::Client>().IsServerSelectedByAutoStart() &&
        !srpServerAddr.IsUnspecified())
    {
        mDefaultConfig.GetServerSockAddr().SetAddress(srpServerAddr);
    }
}
#endif

Error Client::ResolveAddress(const char        *aHostName,
                             AddressCallback    aCallback,
                             void              *aContext,
                             const QueryConfig *aConfig)
{
    QueryInfo info;

    info.Clear();
    info.mQueryType = kIp6AddressQuery;
    info.mConfig.SetFrom(aConfig, mDefaultConfig);
    info.mCallback.mAddressCallback = aCallback;
    info.mCallbackContext           = aContext;

    return StartQuery(info, nullptr, aHostName);
}

#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
Error Client::ResolveIp4Address(const char        *aHostName,
                                AddressCallback    aCallback,
                                void              *aContext,
                                const QueryConfig *aConfig)
{
    QueryInfo info;

    info.Clear();
    info.mQueryType = kIp4AddressQuery;
    info.mConfig.SetFrom(aConfig, mDefaultConfig);
    info.mCallback.mAddressCallback = aCallback;
    info.mCallbackContext           = aContext;

    return StartQuery(info, nullptr, aHostName);
}
#endif

#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE

Error Client::Browse(const char *aServiceName, BrowseCallback aCallback, void *aContext, const QueryConfig *aConfig)
{
    QueryInfo info;

    info.Clear();
    info.mQueryType = kBrowseQuery;
    info.mConfig.SetFrom(aConfig, mDefaultConfig);
    info.mCallback.mBrowseCallback = aCallback;
    info.mCallbackContext          = aContext;

    return StartQuery(info, nullptr, aServiceName);
}

Error Client::ResolveService(const char        *aInstanceLabel,
                             const char        *aServiceName,
                             ServiceCallback    aCallback,
                             void              *aContext,
                             const QueryConfig *aConfig)
{
    return Resolve(aInstanceLabel, aServiceName, aCallback, aContext, aConfig, false);
}

Error Client::ResolveServiceAndHostAddress(const char        *aInstanceLabel,
                                           const char        *aServiceName,
                                           ServiceCallback    aCallback,
                                           void              *aContext,
                                           const QueryConfig *aConfig)
{
    return Resolve(aInstanceLabel, aServiceName, aCallback, aContext, aConfig, true);
}

Error Client::Resolve(const char        *aInstanceLabel,
                      const char        *aServiceName,
                      ServiceCallback    aCallback,
                      void              *aContext,
                      const QueryConfig *aConfig,
                      bool               aShouldResolveHostAddr)
{
    QueryInfo info;
    Error     error;
    QueryType secondQueryType = kNoQuery;

    VerifyOrExit(aInstanceLabel != nullptr, error = kErrorInvalidArgs);

    info.Clear();

    info.mConfig.SetFrom(aConfig, mDefaultConfig);
    info.mShouldResolveHostAddr = aShouldResolveHostAddr;

    switch (info.mConfig.GetServiceMode())
    {
    case QueryConfig::kServiceModeSrvTxtSeparate:
        secondQueryType = kServiceQueryTxt;

        OT_FALL_THROUGH;

    case QueryConfig::kServiceModeSrv:
        info.mQueryType = kServiceQuerySrv;
        break;

    case QueryConfig::kServiceModeTxt:
        info.mQueryType = kServiceQueryTxt;
        VerifyOrExit(!info.mShouldResolveHostAddr, error = kErrorInvalidArgs);
        break;

    case QueryConfig::kServiceModeSrvTxt:
    case QueryConfig::kServiceModeSrvTxtOptimize:
    default:
        info.mQueryType = kServiceQuerySrvTxt;
        break;
    }

    info.mCallback.mServiceCallback = aCallback;
    info.mCallbackContext           = aContext;

    error = StartQuery(info, aInstanceLabel, aServiceName, secondQueryType);

exit:
    return error;
}

#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE

Error Client::StartQuery(QueryInfo &aInfo, const char *aLabel, const char *aName, QueryType aSecondType)
{
    // The `aLabel` can be `nullptr` and then `aName` provides the
    // full name, otherwise the name is appended as `{aLabel}.
    // {aName}`.

    Error  error;
    Query *query;

    VerifyOrExit(mSocket.IsBound(), error = kErrorInvalidState);

#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
    if (aInfo.mQueryType == kIp4AddressQuery)
    {
        NetworkData::ExternalRouteConfig nat64Prefix;

        VerifyOrExit(aInfo.mConfig.GetNat64Mode() == QueryConfig::kNat64Allow, error = kErrorInvalidArgs);
        VerifyOrExit(Get<NetworkData::Leader>().GetPreferredNat64Prefix(nat64Prefix) == kErrorNone,
                     error = kErrorInvalidState);
    }
#endif

    SuccessOrExit(error = AllocateQuery(aInfo, aLabel, aName, query));

    mMainQueries.Enqueue(*query);

    error = SendQuery(*query, aInfo, /* aUpdateTimer */ true);
    VerifyOrExit(error == kErrorNone, FreeQuery(*query));

    if (aSecondType != kNoQuery)
    {
        Query *secondQuery;

        aInfo.mQueryType         = aSecondType;
        aInfo.mMessageId         = 0;
        aInfo.mTransmissionCount = 0;
        aInfo.mMainQuery         = query;

        // We intentionally do not use `error` here so in the unlikely
        // case where we cannot allocate the second query we can proceed
        // with the first one.
        SuccessOrExit(AllocateQuery(aInfo, aLabel, aName, secondQuery));

        IgnoreError(SendQuery(*secondQuery, aInfo, /* aUpdateTimer */ true));

        // Update first query to link to second one by updating
        // its `mNextQuery`.
        aInfo.ReadFrom(*query);
        aInfo.mNextQuery = secondQuery;
        UpdateQuery(*query, aInfo);
    }

exit:
    return error;
}

Error Client::AllocateQuery(const QueryInfo &aInfo, const char *aLabel, const char *aName, Query *&aQuery)
{
    Error error = kErrorNone;

    aQuery = nullptr;

    VerifyOrExit(aInfo.mConfig.GetResponseTimeout() <= TimerMilli::kMaxDelay, error = kErrorInvalidArgs);

    aQuery = Get<MessagePool>().Allocate(Message::kTypeOther);
    VerifyOrExit(aQuery != nullptr, error = kErrorNoBufs);

    SuccessOrExit(error = aQuery->Append(aInfo));

    if (aLabel != nullptr)
    {
        SuccessOrExit(error = Name::AppendLabel(aLabel, *aQuery));
    }

    SuccessOrExit(error = Name::AppendName(aName, *aQuery));

exit:
    FreeAndNullMessageOnError(aQuery, error);
    return error;
}

Client::Query &Client::FindMainQuery(Query &aQuery)
{
    QueryInfo info;

    info.ReadFrom(aQuery);

    return (info.mMainQuery == nullptr) ? aQuery : *info.mMainQuery;
}

void Client::FreeQuery(Query &aQuery)
{
    Query    &mainQuery = FindMainQuery(aQuery);
    QueryInfo info;

    mMainQueries.Dequeue(mainQuery);

    for (Query *query = &mainQuery; query != nullptr; query = info.mNextQuery)
    {
        info.ReadFrom(*query);
        FreeMessage(info.mSavedResponse);
        query->Free();
    }
}

Error Client::SendQuery(Query &aQuery, QueryInfo &aInfo, bool aUpdateTimer)
{
    // This method prepares and sends a query message represented by
    // `aQuery` and `aInfo`. This method updates `aInfo` (e.g., sets
    // the new `mRetransmissionTime`) and updates it in `aQuery` as
    // well. `aUpdateTimer` indicates whether the timer should be
    // updated when query is sent or not (used in the case where timer
    // is handled by caller).

    Error            error   = kErrorNone;
    Message         *message = nullptr;
    Header           header;
    Ip6::MessageInfo messageInfo;
    uint16_t         length = 0;

    aInfo.mTransmissionCount++;
    aInfo.mRetransmissionTime = TimerMilli::GetNow() + aInfo.mConfig.GetResponseTimeout();

    if (aInfo.mMessageId == 0)
    {
        do
        {
            SuccessOrExit(error = header.SetRandomMessageId());
        } while ((header.GetMessageId() == 0) || (FindQueryById(header.GetMessageId()) != nullptr));

        aInfo.mMessageId = header.GetMessageId();
    }
    else
    {
        header.SetMessageId(aInfo.mMessageId);
    }

    header.SetType(Header::kTypeQuery);
    header.SetQueryType(Header::kQueryTypeStandard);

    if (aInfo.mConfig.GetRecursionFlag() == QueryConfig::kFlagRecursionDesired)
    {
        header.SetRecursionDesiredFlag();
    }

    header.SetQuestionCount(kQuestionCount[aInfo.mQueryType]);

    message = mSocket.NewMessage();
    VerifyOrExit(message != nullptr, error = kErrorNoBufs);

    SuccessOrExit(error = message->Append(header));

    // Prepare the question section.

    for (uint8_t num = 0; num < kQuestionCount[aInfo.mQueryType]; num++)
    {
        SuccessOrExit(error = AppendNameFromQuery(aQuery, *message));
        SuccessOrExit(error = message->Append(Question(kQuestionRecordTypes[aInfo.mQueryType][num])));
    }

    length = message->GetLength() - message->GetOffset();

    if (aInfo.mConfig.GetTransportProto() == QueryConfig::kDnsTransportTcp)
#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
    {
        // Check if query will fit into tcp buffer if not return error.
        VerifyOrExit(length + sizeof(uint16_t) + mSendLink.mLength <=
                         OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_QUERY_MAX_SIZE,
                     error = kErrorNoBufs);

        // In case of initialized connection check if connected peer and new query have the same address.
        if (mTcpState != kTcpUninitialized)
        {
            VerifyOrExit(mEndpoint.GetPeerAddress() == AsCoreType(&aInfo.mConfig.mServerSockAddr),
                         error = kErrorFailed);
        }

        switch (mTcpState)
        {
        case kTcpUninitialized:
            SuccessOrExit(error = InitTcpSocket());
            SuccessOrExit(
                error = mEndpoint.Connect(AsCoreType(&aInfo.mConfig.mServerSockAddr), OT_TCP_CONNECT_NO_FAST_OPEN));
            mTcpState = kTcpConnecting;
            PrepareTcpMessage(*message);
            break;
        case kTcpConnectedIdle:
            PrepareTcpMessage(*message);
            SuccessOrExit(error = mEndpoint.SendByReference(mSendLink, /* aFlags */ 0));
            mTcpState = kTcpConnectedSending;
            break;
        case kTcpConnecting:
            PrepareTcpMessage(*message);
            break;
        case kTcpConnectedSending:
            WriteUint16(length, mSendBufferBytes + mSendLink.mLength);
            SuccessOrAssert(error = message->Read(message->GetOffset(),
                                                  (mSendBufferBytes + sizeof(uint16_t) + mSendLink.mLength), length));
            IgnoreError(mEndpoint.SendByExtension(length + sizeof(uint16_t), /* aFlags */ 0));
            break;
        }
        message->Free();
        message = nullptr;
    }
#else
    {
        error = kErrorInvalidArgs;
        LogWarn("DNS query over TCP not supported.");
        ExitNow();
    }
#endif
    else
    {
        VerifyOrExit(length <= kUdpQueryMaxSize, error = kErrorInvalidArgs);
        messageInfo.SetPeerAddr(aInfo.mConfig.GetServerSockAddr().GetAddress());
        messageInfo.SetPeerPort(aInfo.mConfig.GetServerSockAddr().GetPort());
        SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
    }

exit:

    FreeMessageOnError(message, error);
    if (aUpdateTimer)
    {
        mTimer.FireAtIfEarlier(aInfo.mRetransmissionTime);
    }

    UpdateQuery(aQuery, aInfo);

    return error;
}

Error Client::AppendNameFromQuery(const Query &aQuery, Message &aMessage)
{
    // The name is encoded and included after the `Info` in `aQuery`
    // starting at `kNameOffsetInQuery`.

    return aMessage.AppendBytesFromMessage(aQuery, kNameOffsetInQuery, aQuery.GetLength() - kNameOffsetInQuery);
}

void Client::FinalizeQuery(Query &aQuery, Error aError)
{
    Response response;
    Query   &mainQuery = FindMainQuery(aQuery);

    response.mInstance = &Get<Instance>();
    response.mQuery    = &mainQuery;

    FinalizeQuery(response, aError);
}

void Client::FinalizeQuery(Response &aResponse, Error aError)
{
    QueryType type;
    Callback  callback;
    void     *context;

    GetQueryTypeAndCallback(*aResponse.mQuery, type, callback, context);

    switch (type)
    {
    case kIp6AddressQuery:
#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
    case kIp4AddressQuery:
#endif
        if (callback.mAddressCallback != nullptr)
        {
            callback.mAddressCallback(aError, &aResponse, context);
        }
        break;

#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
    case kBrowseQuery:
        if (callback.mBrowseCallback != nullptr)
        {
            callback.mBrowseCallback(aError, &aResponse, context);
        }
        break;

    case kServiceQuerySrvTxt:
    case kServiceQuerySrv:
    case kServiceQueryTxt:
        if (callback.mServiceCallback != nullptr)
        {
            callback.mServiceCallback(aError, &aResponse, context);
        }
        break;
#endif
    case kNoQuery:
        break;
    }

    FreeQuery(*aResponse.mQuery);
}

void Client::GetQueryTypeAndCallback(const Query &aQuery, QueryType &aType, Callback &aCallback, void *&aContext)
{
    QueryInfo info;

    info.ReadFrom(aQuery);

    aType     = info.mQueryType;
    aCallback = info.mCallback;
    aContext  = info.mCallbackContext;
}

Client::Query *Client::FindQueryById(uint16_t aMessageId)
{
    Query    *matchedQuery = nullptr;
    QueryInfo info;

    for (Query &mainQuery : mMainQueries)
    {
        for (Query *query = &mainQuery; query != nullptr; query = info.mNextQuery)
        {
            info.ReadFrom(*query);

            if (info.mMessageId == aMessageId)
            {
                matchedQuery = query;
                ExitNow();
            }
        }
    }

exit:
    return matchedQuery;
}

void Client::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMsgInfo)
{
    OT_UNUSED_VARIABLE(aMsgInfo);

    static_cast<Client *>(aContext)->ProcessResponse(AsCoreType(aMessage));
}

void Client::ProcessResponse(const Message &aResponseMessage)
{
    Error  responseError;
    Query *query;

    SuccessOrExit(ParseResponse(aResponseMessage, query, responseError));

    if (responseError != kErrorNone)
    {
        // Received an error from server, check if we can replace
        // the query.

#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
        if (ReplaceWithIp4Query(*query) == kErrorNone)
        {
            ExitNow();
        }
#endif
#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
        if (ReplaceWithSeparateSrvTxtQueries(*query) == kErrorNone)
        {
            ExitNow();
        }
#endif

        FinalizeQuery(*query, responseError);
        ExitNow();
    }

    // Received successful response from server.

#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
    ResolveHostAddressIfNeeded(*query, aResponseMessage);
#endif

    if (!CanFinalizeQuery(*query))
    {
        SaveQueryResponse(*query, aResponseMessage);
        ExitNow();
    }

    PrepareResponseAndFinalize(FindMainQuery(*query), aResponseMessage, nullptr);

exit:
    return;
}

Error Client::ParseResponse(const Message &aResponseMessage, Query *&aQuery, Error &aResponseError)
{
    Error     error  = kErrorNone;
    uint16_t  offset = aResponseMessage.GetOffset();
    Header    header;
    QueryInfo info;
    Name      queryName;

    SuccessOrExit(error = aResponseMessage.Read(offset, header));
    offset += sizeof(Header);

    VerifyOrExit((header.GetType() == Header::kTypeResponse) && (header.GetQueryType() == Header::kQueryTypeStandard) &&
                     !header.IsTruncationFlagSet(),
                 error = kErrorDrop);

    aQuery = FindQueryById(header.GetMessageId());
    VerifyOrExit(aQuery != nullptr, error = kErrorNotFound);

    info.ReadFrom(*aQuery);

    queryName.SetFromMessage(*aQuery, kNameOffsetInQuery);

    // Check the Question Section

    if (header.GetQuestionCount() == kQuestionCount[info.mQueryType])
    {
        for (uint8_t num = 0; num < kQuestionCount[info.mQueryType]; num++)
        {
            SuccessOrExit(error = Name::CompareName(aResponseMessage, offset, queryName));
            offset += sizeof(Question);
        }
    }
    else
    {
        VerifyOrExit((header.GetResponseCode() != Header::kResponseSuccess) && (header.GetQuestionCount() == 0),
                     error = kErrorParse);
    }

    // Check the answer, authority and additional record sections

    SuccessOrExit(error = ResourceRecord::ParseRecords(aResponseMessage, offset, header.GetAnswerCount()));
    SuccessOrExit(error = ResourceRecord::ParseRecords(aResponseMessage, offset, header.GetAuthorityRecordCount()));
    SuccessOrExit(error = ResourceRecord::ParseRecords(aResponseMessage, offset, header.GetAdditionalRecordCount()));

    // Read the response code

    aResponseError = Header::ResponseCodeToError(header.GetResponseCode());

exit:
    return error;
}

bool Client::CanFinalizeQuery(Query &aQuery)
{
    // Determines whether we can finalize a main query by checking if
    // we have received and saved responses for all other related
    // queries associated with `aQuery`. Note that this method is
    // called when we receive a response for `aQuery`, so no need to
    // check for a saved response for `aQuery` itself.

    bool      canFinalize = true;
    QueryInfo info;

    for (Query *query = &FindMainQuery(aQuery); query != nullptr; query = info.mNextQuery)
    {
        info.ReadFrom(*query);

        if (query == &aQuery)
        {
            continue;
        }

        if (info.mSavedResponse == nullptr)
        {
            canFinalize = false;
            ExitNow();
        }
    }

exit:
    return canFinalize;
}

void Client::SaveQueryResponse(Query &aQuery, const Message &aResponseMessage)
{
    QueryInfo info;

    info.ReadFrom(aQuery);
    VerifyOrExit(info.mSavedResponse == nullptr);

    // If `Clone()` fails we let retry or timeout handle the error.
    info.mSavedResponse = aResponseMessage.Clone();

    UpdateQuery(aQuery, info);

exit:
    return;
}

Client::Query *Client::PopulateResponse(Response &aResponse, Query &aQuery, const Message &aResponseMessage)
{
    // Populate `aResponse` for `aQuery`. If there is a saved response
    // message for `aQuery` we use it, otherwise, we use
    // `aResponseMessage`.

    QueryInfo info;

    info.ReadFrom(aQuery);

    aResponse.mInstance = &Get<Instance>();
    aResponse.mQuery    = &aQuery;
    aResponse.PopulateFrom((info.mSavedResponse == nullptr) ? aResponseMessage : *info.mSavedResponse);

    return info.mNextQuery;
}

void Client::PrepareResponseAndFinalize(Query &aQuery, const Message &aResponseMessage, Response *aPrevResponse)
{
    // This method prepares a list of chained `Response` instances
    // corresponding to all related (chained) queries. It uses
    // recursion to go through the queries and construct the
    // `Response` chain.

    Response response;
    Query   *nextQuery;

    nextQuery      = PopulateResponse(response, aQuery, aResponseMessage);
    response.mNext = aPrevResponse;

    if (nextQuery != nullptr)
    {
        PrepareResponseAndFinalize(*nextQuery, aResponseMessage, &response);
    }
    else
    {
        FinalizeQuery(response, kErrorNone);
    }
}

void Client::HandleTimer(void)
{
    TimeMilli now      = TimerMilli::GetNow();
    TimeMilli nextTime = now.GetDistantFuture();
    QueryInfo info;
#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
    bool hasTcpQuery = false;
#endif

    for (Query &mainQuery : mMainQueries)
    {
        for (Query *query = &mainQuery; query != nullptr; query = info.mNextQuery)
        {
            info.ReadFrom(*query);

            if (info.mSavedResponse != nullptr)
            {
                continue;
            }

            if (now >= info.mRetransmissionTime)
            {
                if (info.mTransmissionCount >= info.mConfig.GetMaxTxAttempts())
                {
                    FinalizeQuery(*query, kErrorResponseTimeout);
                    break;
                }

                IgnoreError(SendQuery(*query, info, /* aUpdateTimer */ false));
            }

            if (nextTime > info.mRetransmissionTime)
            {
                nextTime = info.mRetransmissionTime;
            }

#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
            if (info.mConfig.GetTransportProto() == QueryConfig::kDnsTransportTcp)
            {
                hasTcpQuery = true;
            }
#endif
        }
    }

    if (nextTime < now.GetDistantFuture())
    {
        mTimer.FireAt(nextTime);
    }

#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
    if (!hasTcpQuery && mTcpState != kTcpUninitialized)
    {
        IgnoreError(mEndpoint.SendEndOfStream());
    }
#endif
}

#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE

Error Client::ReplaceWithIp4Query(Query &aQuery)
{
    Error     error = kErrorFailed;
    QueryInfo info;

    info.ReadFrom(aQuery);

    VerifyOrExit(info.mQueryType == kIp4AddressQuery);
    VerifyOrExit(info.mConfig.GetNat64Mode() == QueryConfig::kNat64Allow);

    // We send a new query for IPv4 address resolution
    // for the same host name. We reuse the existing `aQuery`
    // instance and keep all the info but clear `mTransmissionCount`
    // and `mMessageId` (so that a new random message ID is
    // selected). The new `info` will be saved in the query in
    // `SendQuery()`. Note that the current query is still in the
    // `mMainQueries` list when `SendQuery()` selects a new random
    // message ID, so the existing message ID for this query will
    // not be reused.

    info.mQueryType         = kIp4AddressQuery;
    info.mMessageId         = 0;
    info.mTransmissionCount = 0;

    IgnoreError(SendQuery(aQuery, info, /* aUpdateTimer */ true));
    error = kErrorNone;

exit:
    return error;
}

#endif // OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE

#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE

Error Client::ReplaceWithSeparateSrvTxtQueries(Query &aQuery)
{
    Error     error = kErrorFailed;
    QueryInfo info;
    Query    *secondQuery;

    info.ReadFrom(aQuery);

    VerifyOrExit(info.mQueryType == kServiceQuerySrvTxt);
    VerifyOrExit(info.mConfig.GetServiceMode() == QueryConfig::kServiceModeSrvTxtOptimize);

    secondQuery = aQuery.Clone();
    VerifyOrExit(secondQuery != nullptr);

    info.mQueryType         = kServiceQueryTxt;
    info.mMessageId         = 0;
    info.mTransmissionCount = 0;
    info.mMainQuery         = &aQuery;
    IgnoreError(SendQuery(*secondQuery, info, /* aUpdateTimer */ true));

    info.mQueryType         = kServiceQuerySrv;
    info.mMessageId         = 0;
    info.mTransmissionCount = 0;
    info.mNextQuery         = secondQuery;
    IgnoreError(SendQuery(aQuery, info, /* aUpdateTimer */ true));
    error = kErrorNone;

exit:
    return error;
}

void Client::ResolveHostAddressIfNeeded(Query &aQuery, const Message &aResponseMessage)
{
    QueryInfo   info;
    Response    response;
    ServiceInfo serviceInfo;
    char        hostName[Name::kMaxNameSize];

    info.ReadFrom(aQuery);

    VerifyOrExit(info.mQueryType == kServiceQuerySrvTxt || info.mQueryType == kServiceQuerySrv);
    VerifyOrExit(info.mShouldResolveHostAddr);

    PopulateResponse(response, aQuery, aResponseMessage);

    memset(&serviceInfo, 0, sizeof(serviceInfo));
    serviceInfo.mHostNameBuffer     = hostName;
    serviceInfo.mHostNameBufferSize = sizeof(hostName);
    SuccessOrExit(response.ReadServiceInfo(Response::kAnswerSection, Name(aQuery, kNameOffsetInQuery), serviceInfo));

    // Check whether AAAA record for host address is provided in the SRV query response

    if (AsCoreType(&serviceInfo.mHostAddress).IsUnspecified())
    {
        Query *newQuery;

        info.mQueryType         = kIp6AddressQuery;
        info.mMessageId         = 0;
        info.mTransmissionCount = 0;
        info.mMainQuery         = &FindMainQuery(aQuery);

        SuccessOrExit(AllocateQuery(info, nullptr, hostName, newQuery));
        IgnoreError(SendQuery(*newQuery, info, /* aUpdateTimer */ true));

        // Update `aQuery` to be linked with new query (inserting
        // the `newQuery` into the linked-list after `aQuery`).

        info.ReadFrom(aQuery);
        info.mNextQuery = newQuery;
        UpdateQuery(aQuery, info);
    }

exit:
    return;
}

#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE

#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
void Client::PrepareTcpMessage(Message &aMessage)
{
    uint16_t length = aMessage.GetLength() - aMessage.GetOffset();

    // Prepending the DNS query with length of the packet according to RFC1035.
    WriteUint16(length, mSendBufferBytes + mSendLink.mLength);
    SuccessOrAssert(
        aMessage.Read(aMessage.GetOffset(), (mSendBufferBytes + sizeof(uint16_t) + mSendLink.mLength), length));
    mSendLink.mLength += length + sizeof(uint16_t);
}

void Client::HandleTcpSendDone(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData)
{
    OT_UNUSED_VARIABLE(aEndpoint);
    OT_UNUSED_VARIABLE(aData);
    OT_ASSERT(mTcpState == kTcpConnectedSending);

    mSendLink.mLength = 0;
    mTcpState         = kTcpConnectedIdle;
}

void Client::HandleTcpSendDoneCallback(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData)
{
    static_cast<Client *>(otTcpEndpointGetContext(aEndpoint))->HandleTcpSendDone(aEndpoint, aData);
}

void Client::HandleTcpEstablished(otTcpEndpoint *aEndpoint)
{
    OT_UNUSED_VARIABLE(aEndpoint);
    IgnoreError(mEndpoint.SendByReference(mSendLink, /* aFlags */ 0));
    mTcpState = kTcpConnectedSending;
}

void Client::HandleTcpEstablishedCallback(otTcpEndpoint *aEndpoint)
{
    static_cast<Client *>(otTcpEndpointGetContext(aEndpoint))->HandleTcpEstablished(aEndpoint);
}

Error Client::ReadFromLinkBuffer(const otLinkedBuffer *&aLinkedBuffer,
                                 size_t                &aOffset,
                                 Message               &aMessage,
                                 uint16_t               aLength)
{
    // Read `aLength` bytes from `aLinkedBuffer` starting at `aOffset`
    // and copy the content into `aMessage`. As we read we can move
    // to the next `aLinkedBuffer` and update `aOffset`.
    // Returns:
    // - `kErrorNone` if `aLength` bytes are successfully read and
    //    `aOffset` and `aLinkedBuffer` are updated.
    // - `kErrorNotFound` is not enough bytes available to read
    //    from `aLinkedBuffer`.
    // - `kErrorNotBufs` if cannot grow `aMessage` to append bytes.

    Error error = kErrorNone;

    while (aLength > 0)
    {
        uint16_t bytesToRead = aLength;

        VerifyOrExit(aLinkedBuffer != nullptr, error = kErrorNotFound);

        if (bytesToRead > aLinkedBuffer->mLength - aOffset)
        {
            bytesToRead = static_cast<uint16_t>(aLinkedBuffer->mLength - aOffset);
        }

        SuccessOrExit(error = aMessage.AppendBytes(&aLinkedBuffer->mData[aOffset], bytesToRead));

        aLength -= bytesToRead;
        aOffset += bytesToRead;

        if (aOffset == aLinkedBuffer->mLength)
        {
            aLinkedBuffer = aLinkedBuffer->mNext;
            aOffset       = 0;
        }
    }

exit:
    return error;
}

void Client::HandleTcpReceiveAvailable(otTcpEndpoint *aEndpoint,
                                       size_t         aBytesAvailable,
                                       bool           aEndOfStream,
                                       size_t         aBytesRemaining)
{
    OT_UNUSED_VARIABLE(aEndpoint);
    OT_UNUSED_VARIABLE(aBytesRemaining);

    Message              *message   = nullptr;
    size_t                totalRead = 0;
    size_t                offset    = 0;
    const otLinkedBuffer *data;

    if (aEndOfStream)
    {
        // Cleanup is done in disconnected callback.
        IgnoreError(mEndpoint.SendEndOfStream());
    }

    SuccessOrExit(mEndpoint.ReceiveByReference(data));
    VerifyOrExit(data != nullptr);

    message = mSocket.NewMessage();
    VerifyOrExit(message != nullptr);

    while (aBytesAvailable > totalRead)
    {
        uint16_t length;

        // Read the `length` field.
        SuccessOrExit(ReadFromLinkBuffer(data, offset, *message, sizeof(uint16_t)));

        IgnoreError(message->Read(/* aOffset */ 0, length));
        length = HostSwap16(length);

        // Try to read `length` bytes.
        IgnoreError(message->SetLength(0));
        SuccessOrExit(ReadFromLinkBuffer(data, offset, *message, length));

        totalRead += length + sizeof(uint16_t);

        // Now process the read message as query response.
        ProcessResponse(*message);

        IgnoreError(message->SetLength(0));

        // Loop again to see if we can read another response.
    }

exit:
    // Inform `mEndPoint` about the total read and processed bytes
    IgnoreError(mEndpoint.CommitReceive(totalRead, /* aFlags */ 0));
    FreeMessage(message);
}

void Client::HandleTcpReceiveAvailableCallback(otTcpEndpoint *aEndpoint,
                                               size_t         aBytesAvailable,
                                               bool           aEndOfStream,
                                               size_t         aBytesRemaining)
{
    static_cast<Client *>(otTcpEndpointGetContext(aEndpoint))
        ->HandleTcpReceiveAvailable(aEndpoint, aBytesAvailable, aEndOfStream, aBytesRemaining);
}

void Client::HandleTcpDisconnected(otTcpEndpoint *aEndpoint, otTcpDisconnectedReason aReason)
{
    OT_UNUSED_VARIABLE(aEndpoint);
    OT_UNUSED_VARIABLE(aReason);
    QueryInfo info;

    IgnoreError(mEndpoint.Deinitialize());
    mTcpState = kTcpUninitialized;

    // Abort queries in case of connection failures
    for (Query &mainQuery : mMainQueries)
    {
        info.ReadFrom(mainQuery);

        if (info.mConfig.GetTransportProto() == QueryConfig::kDnsTransportTcp)
        {
            FinalizeQuery(mainQuery, kErrorAbort);
        }
    }
}

void Client::HandleTcpDisconnectedCallback(otTcpEndpoint *aEndpoint, otTcpDisconnectedReason aReason)
{
    static_cast<Client *>(otTcpEndpointGetContext(aEndpoint))->HandleTcpDisconnected(aEndpoint, aReason);
}

#endif // OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE

} // namespace Dns
} // namespace ot

#endif // OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
