/*
 *
 *    Copyright (c) 2021 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 "Resolver.h"

#include <lib/core/CHIPConfig.h>
#include <lib/dnssd/ActiveResolveAttempts.h>
#include <lib/dnssd/IncrementalResolve.h>
#include <lib/dnssd/MinimalMdnsServer.h>
#include <lib/dnssd/ServiceNaming.h>
#include <lib/dnssd/minimal_mdns/Logging.h>
#include <lib/dnssd/minimal_mdns/Parser.h>
#include <lib/dnssd/minimal_mdns/QueryBuilder.h>
#include <lib/dnssd/minimal_mdns/RecordData.h>
#include <lib/dnssd/minimal_mdns/core/FlatAllocatedQName.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/logging/CHIPLogging.h>
#include <tracing/macros.h>

// MDNS servers will receive all broadcast packets over the network.
// Disable 'invalid packet' messages because the are expected and common
// These logs are useful for debug only
#undef MINMDNS_RESOLVER_OVERLY_VERBOSE

namespace chip {
namespace Dnssd {
namespace {

constexpr size_t kMdnsMaxPacketSize = 1024;
constexpr uint16_t kMdnsPort        = 5353;

using namespace mdns::Minimal;

/// Handles processing of minmdns packet data.
///
/// Can process multiple incremental resolves based on SRV data and allows
/// retrieval of pending (e.g. to ask for AAAA) and complete data items.
///
class PacketParser : private ParserDelegate
{
public:
    PacketParser(ActiveResolveAttempts & activeResolves) : mActiveResolves(activeResolves) {}

    /// Goes through the given SRV records within a response packet
    /// and sets up data resolution
    void ParseSrvRecords(const BytesRange & packet);

    /// Goes through non-SRV records and feeds them through the initialized
    /// SRV record parsing.
    ///
    /// Must be called AFTER ParseSrvRecords has been called.
    void ParseNonSrvRecords(Inet::InterfaceId interface, const BytesRange & packet);

    IncrementalResolver * ResolverBegin() { return mResolvers; }
    IncrementalResolver * ResolverEnd() { return mResolvers + kMinMdnsNumParallelResolvers; }

private:
    // ParserDelegate implementation
    void OnHeader(ConstHeaderRef & header) override;
    void OnQuery(const QueryData & data) override;
    void OnResource(ResourceType type, const ResourceData & data) override;

    /// Called IFF data is of SRV type and we are in SRV initialization state
    ///
    /// Initializes a resolver with the given SRV content as long as
    /// inactive resolvers exist.
    void ParseSRVResource(const ResourceData & data);

    /// Called IFF parsing state is in RecordParsing
    ///
    /// Forwards the resource to all active resolvers.
    void ParseResource(const ResourceData & data);

    enum class RecordParsingState
    {
        kIdle,
        kSrvInitialization,
        kRecordParsing,
    };

    static constexpr size_t kMinMdnsNumParallelResolvers = CHIP_CONFIG_MINMDNS_MAX_PARALLEL_RESOLVES;

    // Individual parse set
    bool mIsResponse               = false;
    Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null();
    BytesRange mPacketRange;
    RecordParsingState mParsingState = RecordParsingState::kIdle;

    // resolvers kept between parse steps
    ActiveResolveAttempts & mActiveResolves;
    IncrementalResolver mResolvers[kMinMdnsNumParallelResolvers];
};

void PacketParser::OnHeader(ConstHeaderRef & header)
{
    mIsResponse = header.GetFlags().IsResponse();

#ifdef MINMDNS_RESOLVER_OVERLY_VERBOSE
    if (header.GetFlags().IsTruncated())
    {
        // MinMdns does not cache data, so receiving piecewise data does not work
        ChipLogError(Discovery, "Truncated responses not supported for address resolution");
    }
#endif
}

void PacketParser::OnQuery(const QueryData & data)
{
    // Ignore queries:
    //   - unicast answers will include the corresponding query in the answer
    //     packet, however that is not interesting for the resolver.
}

void PacketParser::OnResource(ResourceType type, const ResourceData & data)
{
    if (!mIsResponse)
    {
        return;
    }

    switch (mParsingState)
    {
    case RecordParsingState::kSrvInitialization: {
        if (data.GetType() != QType::SRV)
        {
            return;
        }
        mdns::Minimal::Logging::LogReceivedResource(data);
        ParseSRVResource(data);
        break;
    }
    case RecordParsingState::kRecordParsing:
        if (data.GetType() != QType::SRV)
        {
            // SRV packets logged during 'SrvInitialization' phase
            mdns::Minimal::Logging::LogReceivedResource(data);
        }
        ParseResource(data);
        break;
    case RecordParsingState::kIdle:
        ChipLogError(Discovery, "Illegal state: received DNSSD resource while IDLE");
        break;
    }
}

void PacketParser::ParseResource(const ResourceData & data)
{
    for (auto & resolver : mResolvers)
    {
        if (resolver.IsActive())
        {
            CHIP_ERROR err = resolver.OnRecord(mInterfaceId, data, mPacketRange);

            //
            // CHIP_ERROR_NO_MEMORY usually gets returned when we have no more memory available to hold the
            // resolved data. This gets emitted fairly frequently in dense environments or when receiving records
            // from devices with lots of interfaces. Consequently, don't log that unless we have DNS verbosity
            // logging enabled.
            //
            if (err != CHIP_NO_ERROR)
            {
#if !CHIP_MINMDNS_HIGH_VERBOSITY
                if (err != CHIP_ERROR_NO_MEMORY)
#endif
                    ChipLogError(Discovery, "DNSSD parse error: %" CHIP_ERROR_FORMAT, err.Format());
            }
        }
    }

    // Once an IP address is received, stop requesting it.
    if (data.GetType() == QType::AAAA)
    {
        mActiveResolves.CompleteIpResolution(data.GetName());
    }
}

void PacketParser::ParseSRVResource(const ResourceData & data)
{
    SrvRecord srv;
    if (!srv.Parse(data.GetData(), mPacketRange))
    {
        ChipLogError(Discovery, "Packet data reporter failed to parse SRV record");
        return;
    }

    for (auto & resolver : mResolvers)
    {
        if (resolver.IsActive() && (resolver.GetRecordName() == data.GetName()))
        {
            ChipLogDetail(Discovery, "SRV record already actively processed.");
            return;
        }
    }

    for (auto & resolver : mResolvers)
    {
        if (resolver.IsActive())
        {
            continue;
        }

        CHIP_ERROR err = resolver.InitializeParsing(data.GetName(), data.GetTtlSeconds(), srv);
        if (err != CHIP_NO_ERROR)
        {
            // Receiving records that we do not need to parse is normal:
            // MinMDNS may receive all DNSSD packets on the network, only
            // interested in a subset that is matter-specific
#ifdef MINMDNS_RESOLVER_OVERLY_VERBOSE
            ChipLogError(Discovery, "Could not start SRV record processing: %" CHIP_ERROR_FORMAT, err.Format());
#endif
        }

        // Done finding an inactive resolver and attempting to use it.
        return;
    }

#if CHIP_MINMDNS_HIGH_VERBOSITY
    ChipLogError(Discovery, "Insufficient parsers to process all SRV entries.");
#endif
}

void PacketParser::ParseSrvRecords(const BytesRange & packet)
{
    MATTER_TRACE_SCOPE("Searching SRV Records", "PacketParser");

    mParsingState = RecordParsingState::kSrvInitialization;
    mPacketRange  = packet;

    if (!ParsePacket(packet, this))
    {
        ChipLogError(Discovery, "DNSSD packet parsing failed (for SRV records)");
    }

    mParsingState = RecordParsingState::kIdle;
}

void PacketParser::ParseNonSrvRecords(Inet::InterfaceId interface, const BytesRange & packet)
{
    MATTER_TRACE_SCOPE("Searching NON-SRV Records", "PacketParser");

    mParsingState = RecordParsingState::kRecordParsing;
    mPacketRange  = packet;
    mInterfaceId  = interface;

    if (!ParsePacket(packet, this))
    {
        ChipLogError(Discovery, "DNSSD packet parsing failed (for non-srv records)");
    }

    mParsingState = RecordParsingState::kIdle;
}

class MinMdnsResolver : public Resolver, public MdnsPacketDelegate
{
public:
    MinMdnsResolver() : mActiveResolves(&chip::System::SystemClock()), mPacketParser(mActiveResolves)
    {
        GlobalMinimalMdnsServer::Instance().SetResponseDelegate(this);
    }
    ~MinMdnsResolver() { SetDiscoveryContext(nullptr); }

    //// MdnsPacketDelegate implementation
    void OnMdnsPacketData(const BytesRange & data, const chip::Inet::IPPacketInfo * info) override;

    ///// Resolver implementation
    CHIP_ERROR Init(chip::Inet::EndPointManager<chip::Inet::UDPEndPoint> * udpEndPointManager) override;
    bool IsInitialized() override;
    void Shutdown() override;
    void SetOperationalDelegate(OperationalResolveDelegate * delegate) override { mOperationalDelegate = delegate; }
    CHIP_ERROR ResolveNodeId(const PeerId & peerId) override;
    void NodeIdResolutionNoLongerNeeded(const PeerId & peerId) override;
    CHIP_ERROR StartDiscovery(DiscoveryType type, DiscoveryFilter filter, DiscoveryContext & context) override;
    CHIP_ERROR StopDiscovery(DiscoveryContext & context) override;
    CHIP_ERROR ReconfirmRecord(const char * hostname, Inet::IPAddress address, Inet::InterfaceId interfaceId) override;

private:
    OperationalResolveDelegate * mOperationalDelegate = nullptr;
    DiscoveryContext * mDiscoveryContext              = nullptr;
    System::Layer * mSystemLayer                      = nullptr;
    ActiveResolveAttempts mActiveResolves;
    PacketParser mPacketParser;

    void SetDiscoveryContext(DiscoveryContext * context);
    void ScheduleIpAddressResolve(SerializedQNameIterator hostName);

    CHIP_ERROR SendAllPendingQueries();
    CHIP_ERROR ScheduleRetries();

    /// Prepare a query for the given schedule attempt
    CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt & attempt);

    /// Prepare a query for specific resolve types
    CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Browse & data, bool firstSend);
    CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Resolve & data, bool firstSend);
    CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::IpResolve & data, bool firstSend);

    /// Clear any incremental resolver that is not waiting for a AAAA address.
    void ExpireIncrementalResolvers();
    void AdvancePendingResolverStates();

    static void RetryCallback(System::Layer *, void * self);

    CHIP_ERROR BrowseNodes(DiscoveryType type, DiscoveryFilter subtype);
    template <typename... Args>
    mdns::Minimal::FullQName CheckAndAllocateQName(Args &&... parts)
    {
        size_t requiredSize = mdns::Minimal::FlatAllocatedQName::RequiredStorageSize(parts...);
        if (requiredSize > kMaxQnameSize)
        {
            return mdns::Minimal::FullQName();
        }
        return mdns::Minimal::FlatAllocatedQName::Build(qnameStorage, parts...);
    }
    static constexpr int kMaxQnameSize = 100;
    char qnameStorage[kMaxQnameSize];
};

void MinMdnsResolver::SetDiscoveryContext(DiscoveryContext * context)
{
    if (mDiscoveryContext != nullptr)
    {
        mDiscoveryContext->Release();
    }

    if (context != nullptr)
    {
        context->Retain();
    }

    mDiscoveryContext = context;
}

void MinMdnsResolver::ScheduleIpAddressResolve(SerializedQNameIterator hostName)
{
    HeapQName target(hostName);
    if (!target.IsOk())
    {
        ChipLogError(Discovery, "Memory allocation error for IP address resolution");
        return;
    }
    mActiveResolves.MarkPending(ActiveResolveAttempts::ScheduledAttempt::IpResolve(std::move(target)));
}

void MinMdnsResolver::AdvancePendingResolverStates()
{
    MATTER_TRACE_SCOPE("Advance pending resolve states", "MinMdnsResolver");

    for (IncrementalResolver * resolver = mPacketParser.ResolverBegin(); resolver != mPacketParser.ResolverEnd(); resolver++)
    {
        if (!resolver->IsActive())
        {
            ChipLogError(Discovery, "resolver inactive, continue to next");
            continue;
        }

        IncrementalResolver::RequiredInformationFlags missing = resolver->GetMissingRequiredInformation();

        if (missing.Has(IncrementalResolver::RequiredInformationBitFlags::kIpAddress))
        {
            if (resolver->IsActiveCommissionParse())
            {
                // Browse wants IP addresses
                ScheduleIpAddressResolve(resolver->GetTargetHostName());
            }
            else if (mActiveResolves.ShouldResolveIpAddress(resolver->OperationalParsePeerId()))
            {
                // Keep searching for IP addresses if an active resolve needs these IP addresses
                // otherwise ignore the data (received a SRV record without IP address, however we do not
                // seem interested in it. Probably just a device that came online).
                ScheduleIpAddressResolve(resolver->GetTargetHostName());
            }
            else
            {
                // This IP address is not interesting enough to run another discovery
                resolver->ResetToInactive();
            }
            continue;
        }

        if (missing.HasAny())
        {
            // Expect either IP missing (ask for it) or done. Anything else is not handled
            ChipLogError(Discovery, "Unexpected state: cannot advance resolver with missing information");
            resolver->ResetToInactive();
            continue;
        }

        // SUCCESS. Call the delegates
        if (resolver->IsActiveCommissionParse())
        {
            MATTER_TRACE_SCOPE("Active commissioning delegate call", "MinMdnsResolver");
            DiscoveredNodeData nodeData;

            CHIP_ERROR err = resolver->Take(nodeData);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(Discovery, "Failed to take discovery result: %" CHIP_ERROR_FORMAT, err.Format());
                continue;
            }

            // TODO: Ideally commissioning delegates should be aware of the
            //       node types they receive, however they are currently not
            //       so try to help out by only calling the delegate when an
            //       active browse exists.
            //
            // This is NOT ok and probably we should have separate comissioner
            // or commissionable delegates or pass in a node type argument.
            bool discoveredNodeIsRelevant = false;

            switch (resolver->GetCurrentType())
            {
            case IncrementalResolver::ServiceNameType::kCommissioner:
                discoveredNodeIsRelevant = mActiveResolves.HasBrowseFor(chip::Dnssd::DiscoveryType::kCommissionerNode);
                mActiveResolves.CompleteCommissioner(nodeData);
                break;
            case IncrementalResolver::ServiceNameType::kCommissionable:
                discoveredNodeIsRelevant = mActiveResolves.HasBrowseFor(chip::Dnssd::DiscoveryType::kCommissionableNode);
                mActiveResolves.CompleteCommissionable(nodeData);
                break;
            default:
                ChipLogError(Discovery, "Unexpected type for browse data parsing");
                continue;
            }

            if (discoveredNodeIsRelevant)
            {
                if (mDiscoveryContext != nullptr)
                {
                    mDiscoveryContext->OnNodeDiscovered(nodeData);
                }
                else
                {
#if CHIP_MINMDNS_HIGH_VERBOSITY
                    ChipLogError(Discovery, "No delegate to report commissioning node discovery");
#endif
                }
            }
        }
        else if (resolver->IsActiveOperationalParse())
        {
            MATTER_TRACE_SCOPE("Active operational delegate call", "MinMdnsResolver");
            ResolvedNodeData nodeResolvedData;
            CHIP_ERROR err = resolver->Take(nodeResolvedData);

            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(Discovery, "Failed to take NodeData - result: %" CHIP_ERROR_FORMAT, err.Format());
                continue;
            }

            if (mActiveResolves.HasBrowseFor(chip::Dnssd::DiscoveryType::kOperational))
            {
                if (mDiscoveryContext != nullptr)
                {
                    DiscoveredNodeData nodeData;
                    OperationalNodeBrowseData opNodeData;

                    opNodeData.peerId     = nodeResolvedData.operationalData.peerId;
                    opNodeData.hasZeroTTL = nodeResolvedData.operationalData.hasZeroTTL;
                    nodeData.Set<OperationalNodeBrowseData>(opNodeData);
                    mDiscoveryContext->OnNodeDiscovered(nodeData);
                }
                else
                {
#if CHIP_MINMDNS_HIGH_VERBOSITY
                    ChipLogError(Discovery, "No delegate to report operational node discovery");
#endif
                }
            }

            mActiveResolves.Complete(nodeResolvedData.operationalData.peerId);
            if (mOperationalDelegate != nullptr)
            {
                mOperationalDelegate->OnOperationalNodeResolved(nodeResolvedData);
            }
            else
            {
#if CHIP_MINMDNS_HIGH_VERBOSITY
                ChipLogError(Discovery, "No delegate to report operational node discovery");
#endif
            }
        }
        else
        {
            ChipLogError(Discovery, "Unexpected state: record type unknown");
            resolver->ResetToInactive();
        }
    }
}

void MinMdnsResolver::OnMdnsPacketData(const BytesRange & data, const chip::Inet::IPPacketInfo * info)
{
    MATTER_TRACE_SCOPE("Received MDNS Packet", "MinMdnsResolver");

    // Fill up any relevant data
    mPacketParser.ParseSrvRecords(data);
    mPacketParser.ParseNonSrvRecords(info->Interface, data);

    AdvancePendingResolverStates();

    ScheduleRetries();
}

CHIP_ERROR MinMdnsResolver::Init(chip::Inet::EndPointManager<chip::Inet::UDPEndPoint> * udpEndPointManager)
{
    /// Note: we do not double-check the port as we assume the APP will always use
    /// the same udpEndPointManager and port for mDNS.
    mSystemLayer = &udpEndPointManager->SystemLayer();

    if (GlobalMinimalMdnsServer::Server().IsListening())
    {
        return CHIP_NO_ERROR;
    }

    return GlobalMinimalMdnsServer::Instance().StartServer(udpEndPointManager, kMdnsPort);
}

bool MinMdnsResolver::IsInitialized()
{
    return GlobalMinimalMdnsServer::Server().IsListening();
}

void MinMdnsResolver::Shutdown()
{
    GlobalMinimalMdnsServer::Instance().ShutdownServer();
}

CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Browse & data,
                                       bool firstSend)
{
    mdns::Minimal::FullQName qname;

    switch (data.type)
    {
    case DiscoveryType::kOperational:
        qname = CheckAndAllocateQName(kOperationalServiceName, kOperationalProtocol, kLocalDomain);
        break;
    case DiscoveryType::kCommissionableNode:
        if (data.filter.type == DiscoveryFilterType::kNone)
        {
            qname = CheckAndAllocateQName(kCommissionableServiceName, kCommissionProtocol, kLocalDomain);
        }
        else if (data.filter.type == DiscoveryFilterType::kInstanceName)
        {
            qname = CheckAndAllocateQName(data.filter.instanceName, kCommissionableServiceName, kCommissionProtocol, kLocalDomain);
        }
        else
        {
            char subtypeStr[Common::kSubTypeMaxLength + 1];
            ReturnErrorOnFailure(MakeServiceSubtype(subtypeStr, sizeof(subtypeStr), data.filter));
            qname = CheckAndAllocateQName(subtypeStr, kSubtypeServiceNamePart, kCommissionableServiceName, kCommissionProtocol,
                                          kLocalDomain);
        }
        break;
    case DiscoveryType::kCommissionerNode:
        if (data.filter.type == DiscoveryFilterType::kNone)
        {
            qname = CheckAndAllocateQName(kCommissionerServiceName, kCommissionProtocol, kLocalDomain);
        }
        else
        {
            char subtypeStr[Common::kSubTypeMaxLength + 1];
            ReturnErrorOnFailure(MakeServiceSubtype(subtypeStr, sizeof(subtypeStr), data.filter));
            qname = CheckAndAllocateQName(subtypeStr, kSubtypeServiceNamePart, kCommissionerServiceName, kCommissionProtocol,
                                          kLocalDomain);
        }
        break;
    case DiscoveryType::kUnknown:
        break;
    }

    ReturnErrorCodeIf(!qname.nameCount, CHIP_ERROR_NO_MEMORY);

    mdns::Minimal::Query query(qname);
    query
        .SetClass(QClass::IN)           //
        .SetType(QType::ANY)            //
        .SetAnswerViaUnicast(firstSend) //
        ;

    mdns::Minimal::Logging::LogSendingQuery(query);
    builder.AddQuery(query);

    return CHIP_NO_ERROR;
}

CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Resolve & data,
                                       bool firstSend)
{
    char nameBuffer[kMaxOperationalServiceNameSize] = "";

    // Node and fabricid are encoded in server names.
    ReturnErrorOnFailure(MakeInstanceName(nameBuffer, sizeof(nameBuffer), data.peerId));

    const char * instanceQName[] = { nameBuffer, kOperationalServiceName, kOperationalProtocol, kLocalDomain };
    Query query(instanceQName);

    query
        .SetClass(QClass::IN)           //
        .SetType(QType::ANY)            //
        .SetAnswerViaUnicast(firstSend) //
        ;

    mdns::Minimal::Logging::LogSendingQuery(query);
    builder.AddQuery(query);

    return CHIP_NO_ERROR;
}

CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::IpResolve & data,
                                       bool firstSend)
{

    Query query(data.hostName.Content());

    query
        .SetClass(QClass::IN)           //
        .SetType(QType::AAAA)           //
        .SetAnswerViaUnicast(firstSend) //
        ;

    mdns::Minimal::Logging::LogSendingQuery(query);
    builder.AddQuery(query);

    return CHIP_NO_ERROR;
}

CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt & attempt)
{
    if (attempt.IsResolve())
    {
        ReturnErrorOnFailure(BuildQuery(builder, attempt.ResolveData(), attempt.firstSend));
    }
    else if (attempt.IsBrowse())
    {
        ReturnErrorOnFailure(BuildQuery(builder, attempt.BrowseData(), attempt.firstSend));
    }
    else if (attempt.IsIpResolve())
    {
        ReturnErrorOnFailure(BuildQuery(builder, attempt.IpResolveData(), attempt.firstSend));
    }
    else
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    ReturnErrorCodeIf(!builder.Ok(), CHIP_ERROR_INTERNAL);
    return CHIP_NO_ERROR;
}

CHIP_ERROR MinMdnsResolver::SendAllPendingQueries()
{
    while (true)
    {
        std::optional<ActiveResolveAttempts::ScheduledAttempt> resolve = mActiveResolves.NextScheduled();

        if (!resolve.has_value())
        {
            break;
        }

        System::PacketBufferHandle buffer = System::PacketBufferHandle::New(kMdnsMaxPacketSize);
        ReturnErrorCodeIf(buffer.IsNull(), CHIP_ERROR_NO_MEMORY);

        QueryBuilder builder(std::move(buffer));
        builder.Header().SetMessageId(0);

        ReturnErrorOnFailure(BuildQuery(builder, *resolve));

        if (resolve->firstSend)
        {
            ReturnErrorOnFailure(GlobalMinimalMdnsServer::Server().BroadcastUnicastQuery(builder.ReleasePacket(), kMdnsPort));
        }
        else
        {
            ReturnErrorOnFailure(GlobalMinimalMdnsServer::Server().BroadcastSend(builder.ReleasePacket(), kMdnsPort));
        }
    }

    ExpireIncrementalResolvers();

    return ScheduleRetries();
}

void MinMdnsResolver::ExpireIncrementalResolvers()
{
    // once all queries are sent, if any SRV cannot receive AAAA addresses, expire it
    for (IncrementalResolver * resolver = mPacketParser.ResolverBegin(); resolver != mPacketParser.ResolverEnd(); resolver++)
    {
        if (!resolver->IsActive())
        {
            continue;
        }

        IncrementalResolver::RequiredInformationFlags missing = resolver->GetMissingRequiredInformation();
        if (missing.Has(IncrementalResolver::RequiredInformationBitFlags::kIpAddress))
        {
            if (mActiveResolves.IsWaitingForIpResolutionFor(resolver->GetTargetHostName()))
            {
                continue;
            }
        }

        // mark as expired: not waiting for anything
        resolver->ResetToInactive();
    }
}

CHIP_ERROR MinMdnsResolver::StartDiscovery(DiscoveryType type, DiscoveryFilter filter, DiscoveryContext & context)
{
    // minmdns currently supports only one discovery context at a time so override the previous context
    SetDiscoveryContext(&context);

    return BrowseNodes(type, filter);
}

CHIP_ERROR MinMdnsResolver::StopDiscovery(DiscoveryContext & context)
{
    SetDiscoveryContext(nullptr);

    return mActiveResolves.CompleteAllBrowses();
}

CHIP_ERROR MinMdnsResolver::ReconfirmRecord(const char * hostname, Inet::IPAddress address, Inet::InterfaceId interfaceId)
{
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR MinMdnsResolver::BrowseNodes(DiscoveryType type, DiscoveryFilter filter)
{
    mActiveResolves.MarkPending(filter, type);

    return SendAllPendingQueries();
}

CHIP_ERROR MinMdnsResolver::ResolveNodeId(const PeerId & peerId)
{
    mActiveResolves.MarkPending(peerId);

    return SendAllPendingQueries();
}

void MinMdnsResolver::NodeIdResolutionNoLongerNeeded(const PeerId & peerId)
{
    mActiveResolves.NodeIdResolutionNoLongerNeeded(peerId);
}

CHIP_ERROR MinMdnsResolver::ScheduleRetries()
{
    MATTER_TRACE_SCOPE("Schedule retries", "MinMdnsResolver");

    ReturnErrorCodeIf(mSystemLayer == nullptr, CHIP_ERROR_INCORRECT_STATE);
    mSystemLayer->CancelTimer(&RetryCallback, this);

    std::optional<System::Clock::Timeout> delay = mActiveResolves.GetTimeUntilNextExpectedResponse();

    if (!delay.has_value())
    {
        return CHIP_NO_ERROR;
    }

    return mSystemLayer->StartTimer(*delay, &RetryCallback, this);
}

void MinMdnsResolver::RetryCallback(System::Layer *, void * self)
{
    reinterpret_cast<MinMdnsResolver *>(self)->SendAllPendingQueries();
}

MinMdnsResolver gResolver;

} // namespace

#if CHIP_DNSSD_DEFAULT_MINIMAL

Resolver & GetDefaultResolver()
{
    return gResolver;
}

#endif // CHIP_DNSSD_DEFAULT_MINIMAL

} // namespace Dnssd
} // namespace chip
