/*
 *  Copyright (c) 2020, 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.
 */

/**
 * @file
 *   This file includes definitions for SRP server.
 */

#ifndef NET_SRP_SERVER_HPP_
#define NET_SRP_SERVER_HPP_

#include "openthread-core-config.h"

#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE

#if !OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
#error "OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
#endif

#if !OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
#error "OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
#endif

#if !OPENTHREAD_CONFIG_ECDSA_ENABLE
#error "OPENTHREAD_CONFIG_ECDSA_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
#endif

#include <openthread/ip6.h>
#include <openthread/srp_server.h>

#include "common/array.hpp"
#include "common/as_core_type.hpp"
#include "common/clearable.hpp"
#include "common/heap.hpp"
#include "common/heap_allocatable.hpp"
#include "common/heap_array.hpp"
#include "common/heap_data.hpp"
#include "common/heap_string.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/notifier.hpp"
#include "common/numeric_limits.hpp"
#include "common/retain_ptr.hpp"
#include "common/timer.hpp"
#include "crypto/ecdsa.hpp"
#include "net/dns_types.hpp"
#include "net/ip6.hpp"
#include "net/ip6_address.hpp"
#include "net/udp6.hpp"
#include "thread/network_data_publisher.hpp"

struct otSrpServerHost
{
};

struct otSrpServerService
{
};

namespace ot {

namespace Dns {
namespace ServiceDiscovery {
class Server;
}
} // namespace Dns

namespace Srp {

/**
 * This class implements the SRP server.
 *
 */
class Server : public InstanceLocator, private NonCopyable
{
    friend class NetworkData::Publisher;
    friend class UpdateMetadata;
    friend class Service;
    friend class Host;
    friend class Dns::ServiceDiscovery::Server;

    enum RetainName : bool
    {
        kDeleteName = false,
        kRetainName = true,
    };

    enum NotifyMode : bool
    {
        kDoNotNotifyServiceHandler = false,
        kNotifyServiceHandler      = true,
    };

public:
    static constexpr uint16_t kUdpPortMin = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MIN; ///< The reserved min port.
    static constexpr uint16_t kUdpPortMax = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MAX; ///< The reserved max port.

    static_assert(kUdpPortMin <= kUdpPortMax, "invalid port range");

    /**
     * The ID of SRP service update transaction.
     *
     */
    typedef otSrpServerServiceUpdateId ServiceUpdateId;

    /**
     * This enumeration represents the address mode used by the SRP server.
     *
     * Address mode specifies how the address and port number are determined by the SRP server and how this info ins
     * published in the Thread Network Data.
     *
     */
    enum AddressMode : uint8_t
    {
        kAddressModeUnicast = OT_SRP_SERVER_ADDRESS_MODE_UNICAST, ///< Unicast address mode.
        kAddressModeAnycast = OT_SRP_SERVER_ADDRESS_MODE_ANYCAST, ///< Anycast address mode.
    };

    class Host;

    enum State : uint8_t
    {
        kStateDisabled = OT_SRP_SERVER_STATE_DISABLED,
        kStateRunning  = OT_SRP_SERVER_STATE_RUNNING,
        kStateStopped  = OT_SRP_SERVER_STATE_STOPPED,
    };

    /**
     * This class implements a server-side SRP service.
     *
     */
    class Service : public otSrpServerService,
                    public LinkedListEntry<Service>,
                    private Heap::Allocatable<Service>,
                    private NonCopyable
    {
        friend class Server;
        friend class LinkedList<Service>;
        friend class LinkedListEntry<Service>;
        friend class Heap::Allocatable<Service>;

    public:
        /**
         * This type represents the flags which indicates which services to include or exclude when searching in (or
         * iterating over) the list of SRP services.
         *
         */
        typedef otSrpServerServiceFlags Flags;

        /**
         * This `Flags` constant indicates to include base services (not a sub-type).
         *
         */
        static constexpr Flags kFlagBaseType = OT_SRP_SERVER_SERVICE_FLAG_BASE_TYPE;

        /**
         * This `Flags` constant indicates to include sub-type services.
         *
         */
        static constexpr Flags kFlagSubType = OT_SRP_SERVER_SERVICE_FLAG_SUB_TYPE;

        /**
         * This `Flags` constant indicates to include active (not deleted) services.
         *
         */
        static constexpr Flags kFlagActive = OT_SRP_SERVER_SERVICE_FLAG_ACTIVE;

        /**
         * This `Flags` constant indicates to include deleted services.
         *
         */
        static constexpr Flags kFlagDeleted = OT_SRP_SERVER_SERVICE_FLAG_DELETED;

        /**
         * This method tells if the SRP service has been deleted.
         *
         * A SRP service can be deleted but retains its name for future uses.
         * In this case, the service instance is not removed from the SRP server/registry.
         * It is guaranteed that all services are deleted if the host is deleted.
         *
         * @returns  TRUE if the service has been deleted, FALSE if not.
         *
         */
        bool IsDeleted(void) const { return mIsDeleted; }

        /**
         * This method indicates whether the SRP service is a sub-type.
         *
         * @retval TRUE    If the service is a sub-type.
         * @retval FALSE   If the service is not a sub-type.
         *
         */
        bool IsSubType(void) const { return mIsSubType; }

        /**
         * This method gets the full service instance name of the service.
         *
         * @returns  A pointer service instance name (as a null-terminated C string).
         *
         */
        const char *GetInstanceName(void) const { return mDescription->mInstanceName.AsCString(); }

        /**
         * This method gets the full service name of the service.
         *
         * @returns  A pointer service name (as a null-terminated C string).
         *
         */
        const char *GetServiceName(void) const { return mServiceName.AsCString(); }

        /**
         * This method gets the sub-type label from service name.
         *
         * The full service name for a sub-type service follows "<sub-label>._sub.<service-labels>.<domain>.". This
         * method copies the `<sub-label>` into the @p aLabel buffer.
         *
         * The @p aLabel is ensured to always be null-terminated after returning even in case of failure.
         *
         * @param[out] aLabel        A pointer to a buffer to copy the sub-type label name.
         * @param[in]  aMaxSize      Maximum size of @p aLabel buffer.
         *
         * @retval kErrorNone         @p aLabel was updated successfully.
         * @retval kErrorNoBufs       The sub-type label could not fit in @p aLabel buffer (number of chars from label
         *                            that could fit are copied in @p aLabel ensuring it is null-terminated).
         * @retval kErrorInvalidArgs  SRP service is not a sub-type.
         *
         */
        Error GetServiceSubTypeLabel(char *aLabel, uint8_t aMaxSize) const;

        /**
         * This method returns the port of the service instance.
         *
         * @returns  The port of the service.
         *
         */
        uint16_t GetPort(void) const { return mDescription->mPort; }

        /**
         * This method returns the weight of the service instance.
         *
         * @returns  The weight of the service.
         *
         */
        uint16_t GetWeight(void) const { return mDescription->mWeight; }

        /**
         * This method returns the priority of the service instance.
         *
         * @returns  The priority of the service.
         *
         */
        uint16_t GetPriority(void) const { return mDescription->mPriority; }

        /**
         * This method returns the TXT record data of the service instance.
         *
         * @returns A pointer to the buffer containing the TXT record data.
         *
         */
        const uint8_t *GetTxtData(void) const { return mDescription->mTxtData.GetBytes(); }

        /**
         * This method returns the TXT record data length of the service instance.
         *
         * @return The TXT record data length (number of bytes in buffer returned from `GetTxtData()`).
         *
         */
        uint16_t GetTxtDataLength(void) const { return mDescription->mTxtData.GetLength(); }

        /**
         * This method returns the host which the service instance reside on.
         *
         * @returns  A reference to the host instance.
         *
         */
        const Host &GetHost(void) const { return *mDescription->mHost; }

        /**
         * This method returns the expire time (in milliseconds) of the service.
         *
         * @returns  The service expire time in milliseconds.
         *
         */
        TimeMilli GetExpireTime(void) const;

        /**
         * This method returns the key expire time (in milliseconds) of the service.
         *
         * @returns  The service key expire time in milliseconds.
         *
         */
        TimeMilli GetKeyExpireTime(void) const;

        /**
         * This method indicates whether this service matches a given service instance name.
         *
         * @param[in]  aInstanceName  The service instance name.
         *
         * @retval  TRUE   If the service matches the service instance name.
         * @retval  FALSE  If the service does not match the service instance name.
         *
         */
        bool MatchesInstanceName(const char *aInstanceName) const;

        /**
         * This method tells whether this service matches a given service name.
         *
         * @param[in] aServiceName  The full service name to match.
         *
         * @retval  TRUE   If the service matches the full service name.
         * @retval  FALSE  If the service does not match the full service name.
         *
         */
        bool MatchesServiceName(const char *aServiceName) const;

    private:
        struct Description : public LinkedListEntry<Description>,
                             public Heap::Allocatable<Description>,
                             public RetainCountable,
                             private NonCopyable
        {
            Error       Init(const char *aInstanceName, Host &aHost);
            const char *GetInstanceName(void) const { return mInstanceName.AsCString(); }
            bool        Matches(const char *aInstanceName) const;
            void        ClearResources(void);
            void        TakeResourcesFrom(Description &aDescription);
            Error       SetTxtDataFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);

            Description *mNext;
            Heap::String mInstanceName;
            Host *       mHost;
            Heap::Data   mTxtData;
            uint16_t     mPriority;
            uint16_t     mWeight;
            uint16_t     mPort;
            uint32_t     mLease;    // The LEASE time in seconds.
            uint32_t     mKeyLease; // The KEY-LEASE time in seconds.
            TimeMilli    mUpdateTime;
        };

        enum Action : uint8_t
        {
            kAddNew,
            kUpdateExisting,
            kRemoveButRetainName,
            kFullyRemove,
            kLeaseExpired,
            kKeyLeaseExpired,
        };

        Error Init(const char *aServiceName, Description &aDescription, bool aIsSubType, TimeMilli aUpdateTime);
        bool  MatchesFlags(Flags aFlags) const;
        const TimeMilli &GetUpdateTime(void) const { return mUpdateTime; }
        void             Log(Action aAction) const;

        Heap::String           mServiceName;
        RetainPtr<Description> mDescription;
        Service *              mNext;
        TimeMilli              mUpdateTime;
        bool                   mIsDeleted : 1;
        bool                   mIsSubType : 1;
        bool                   mIsCommitted : 1;
    };

    /**
     * This class implements the Host which registers services on the SRP server.
     *
     */
    class Host : public otSrpServerHost,
                 public InstanceLocator,
                 public LinkedListEntry<Host>,
                 private Heap::Allocatable<Host>,
                 private NonCopyable
    {
        friend class Server;
        friend class LinkedListEntry<Host>;
        friend class Heap::Allocatable<Host>;

    public:
        /**
         * This method tells whether the Host object has been deleted.
         *
         * The Host object retains event if the host has been deleted by the SRP client,
         * because the host name may retain.
         *
         * @returns  TRUE if the host is deleted, FALSE if the host is not deleted.
         *
         */
        bool IsDeleted(void) const { return (mLease == 0); }

        /**
         * This method returns the full name of the host.
         *
         * @returns  A pointer to the null-terminated full host name.
         *
         */
        const char *GetFullName(void) const { return mFullName.AsCString(); }

        /**
         * This method returns addresses of the host.
         *
         * @param[out]  aAddressesNum  The number of the addresses.
         *
         * @returns  A pointer to the addresses array or `nullptr` if no addresses.
         *
         */
        const Ip6::Address *GetAddresses(uint8_t &aAddressesNum) const
        {
            aAddressesNum = static_cast<uint8_t>(OT_MIN(mAddresses.GetLength(), NumericLimits<uint8_t>::kMax));
            return mAddresses.AsCArray();
        }

        /**
         * This method returns the LEASE time of the host.
         *
         * @returns  The LEASE time in seconds.
         *
         */
        uint32_t GetLease(void) const { return mLease; }

        /**
         * This method returns the KEY-LEASE time of the key of the host.
         *
         * @returns  The KEY-LEASE time in seconds.
         *
         */
        uint32_t GetKeyLease(void) const { return mKeyLease; }

        /**
         * This method returns the KEY resource record of the host.
         *
         * @returns  A pointer to the ECDSA P 256 public key resource record
         *           if there is valid one. `nullptr` if no valid key exists.
         *
         */
        const Dns::Ecdsa256KeyRecord *GetKeyRecord(void) const { return mKeyRecord.IsValid() ? &mKeyRecord : nullptr; }

        /**
         * This method returns the expire time (in milliseconds) of the host.
         *
         * @returns  The expire time in milliseconds.
         *
         */
        TimeMilli GetExpireTime(void) const;

        /**
         * This method returns the expire time (in milliseconds) of the key of the host.
         *
         * @returns  The expire time of the key in milliseconds.
         *
         */
        TimeMilli GetKeyExpireTime(void) const;

        /**
         * This method returns the `Service` linked list associated with the host.
         *
         * @returns The `Service` linked list.
         *
         */
        const LinkedList<Service> &GetServices(void) const { return mServices; }

        /**
         * This method finds the next matching service on the host.
         *
         * @param[in] aPrevService   A pointer to the previous service or `nullptr` to start from beginning of the list.
         * @param[in] aFlags         Flags indicating which services to include (base/sub-type, active/deleted).
         * @param[in] aServiceName   The service name to match. Set to `nullptr` to accept any name.
         * @param[in] aInstanceName  The service instance name to match. Set to `nullptr` to accept any name.
         *
         * @returns  A pointer to the next matching service or `nullptr` if no matching service could be found.
         *
         */
        const Service *FindNextService(const Service *aPrevService,
                                       Service::Flags aFlags        = kFlagsAnyService,
                                       const char *   aServiceName  = nullptr,
                                       const char *   aInstanceName = nullptr) const;

        /**
         * This method tells whether the host matches a given full name.
         *
         * @param[in]  aFullName  The full name.
         *
         * @returns  A boolean that indicates whether the host matches the given name.
         *
         */
        bool Matches(const char *aFullName) const;

    private:
        Host(Instance &aInstance, TimeMilli aUpdateTime);
        ~Host(void);

        Error                SetFullName(const char *aFullName);
        void                 SetKeyRecord(Dns::Ecdsa256KeyRecord &aKeyRecord);
        void                 SetLease(uint32_t aLease) { mLease = aLease; }
        void                 SetKeyLease(uint32_t aKeyLease) { mKeyLease = aKeyLease; }
        LinkedList<Service> &GetServices(void) { return mServices; }
        Service *            AddNewService(const char *aServiceName,
                                           const char *aInstanceName,
                                           bool        aIsSubType,
                                           TimeMilli   aUpdateTime);
        void                 RemoveService(Service *aService, RetainName aRetainName, NotifyMode aNotifyServiceHandler);
        void                 FreeAllServices(void);
        void                 ClearResources(void);
        Error                MergeServicesAndResourcesFrom(Host &aHost);
        Error                AddIp6Address(const Ip6::Address &aIp6Address);
        bool                 HasServiceInstance(const char *aInstanceName) const;
        RetainPtr<Service::Description>       FindServiceDescription(const char *aInstanceName);
        const RetainPtr<Service::Description> FindServiceDescription(const char *aInstanceName) const;
        Service *                             FindService(const char *aServiceName, const char *aInstanceName);
        const Service *                       FindService(const char *aServiceName, const char *aInstanceName) const;

        Host *                    mNext;
        Heap::String              mFullName;
        Heap::Array<Ip6::Address> mAddresses;

        // TODO(wgtdkp): there is no necessary to save the entire resource
        // record, saving only the ECDSA-256 public key should be enough.
        Dns::Ecdsa256KeyRecord mKeyRecord;
        uint32_t               mLease;    // The LEASE time in seconds.
        uint32_t               mKeyLease; // The KEY-LEASE time in seconds.
        TimeMilli              mUpdateTime;
        LinkedList<Service>    mServices;
    };

    /**
     * This class handles LEASE and KEY-LEASE configurations.
     *
     */
    class LeaseConfig : public otSrpServerLeaseConfig
    {
        friend class Server;

    public:
        /**
         * This constructor initialize to default LEASE and KEY-LEASE configurations.
         *
         */
        LeaseConfig(void);

    private:
        bool     IsValid(void) const;
        uint32_t GrantLease(uint32_t aLease) const;
        uint32_t GrantKeyLease(uint32_t aKeyLease) const;
    };

    /**
     * This constant defines a `Service::Flags` combination accepting any service (base/sub-type, active/deleted).
     *
     */
    static constexpr Service::Flags kFlagsAnyService = OT_SRP_SERVER_FLAGS_ANY_SERVICE;

    /**
     * This constant defines a `Service::Flags` combination accepting base services only.
     *
     */
    static constexpr Service::Flags kFlagsBaseTypeServiceOnly = OT_SRP_SERVER_FLAGS_BASE_TYPE_SERVICE_ONLY;

    /**
     * This constant defines a `Service::Flags` combination accepting sub-type services only.
     *
     */
    static constexpr Service::Flags kFlagsSubTypeServiceOnly = OT_SRP_SERVER_FLAGS_SUB_TYPE_SERVICE_ONLY;

    /**
     * This constant defines a `Service::Flags` combination accepting any active services (not deleted).
     *
     */
    static constexpr Service::Flags kFlagsAnyTypeActiveService = OT_SRP_SERVER_FLAGS_ANY_TYPE_ACTIVE_SERVICE;

    /**
     * This constant defines a `Service::Flags` combination accepting any deleted services.
     *
     */
    static constexpr Service::Flags kFlagsAnyTypeDeletedService = OT_SRP_SERVER_FLAGS_ANY_TYPE_DELETED_SERVICE;

    /**
     * This constructor initializes the SRP server object.
     *
     * @param[in]  aInstance  A reference to the OpenThread instance.
     *
     */
    explicit Server(Instance &aInstance);

    /**
     * This method sets the SRP service events handler.
     *
     * @param[in]  aServiceHandler         A service events handler.
     * @param[in]  aServiceHandlerContext  A pointer to arbitrary context information.
     *
     * @note  The handler SHOULD call HandleServiceUpdateResult to report the result of its processing.
     *        Otherwise, a SRP update will be considered failed.
     *
     * @sa  HandleServiceUpdateResult
     *
     */
    void SetServiceHandler(otSrpServerServiceUpdateHandler aServiceHandler, void *aServiceHandlerContext);

    /**
     * This method returns the domain authorized to the SRP server.
     *
     * If the domain if not set by SetDomain, "default.service.arpa." will be returned.
     * A trailing dot is always appended even if the domain is set without it.
     *
     * @returns A pointer to the dot-joined domain string.
     *
     */
    const char *GetDomain(void) const { return mDomain.AsCString(); }

    /**
     * This method sets the domain on the SRP server.
     *
     * A trailing dot will be appended to @p aDomain if it is not already there.
     * This method should only be called before the SRP server is enabled.
     *
     * @param[in]  aDomain  The domain to be set. MUST NOT be `nullptr`.
     *
     * @retval  kErrorNone          Successfully set the domain to @p aDomain.
     * @retval  kErrorInvalidState  The SRP server is already enabled and the Domain cannot be changed.
     * @retval  kErrorInvalidArgs   The argument @p aDomain is not a valid DNS domain name.
     * @retval  kErrorNoBufs        There is no memory to store content of @p aDomain.
     *
     */
    Error SetDomain(const char *aDomain);

    /**
     * This method returns the address mode being used by the SRP server.
     *
     * @returns The SRP server's address mode.
     *
     */
    AddressMode GetAddressMode(void) const { return mAddressMode; }

    /**
     * This method sets the address mode to be used by the SRP server.
     *
     * @param[in] aMode      The address mode to use.
     *
     * @retval kErrorNone           Successfully set the address mode.
     * @retval kErrorInvalidState   The SRP server is enabled and the address mode cannot be changed.
     *
     */
    Error SetAddressMode(AddressMode aMode);

    /**
     * This method gets the sequence number used with anycast address mode.
     *
     * The sequence number is included in "DNS/SRP Service Anycast Address" entry published in the Network Data.
     *
     * @returns The anycast sequence number.
     *
     */
    uint8_t GetAnycastModeSequenceNumber(void) const { return mAnycastSequenceNumber; }

    /**
     * This method sets the sequence number used with anycast address mode.
     *
     * @param[in] aSequenceNumber  The sequence number to use.
     *
     * @retval kErrorNone           Successfully set the address mode.
     * @retval kErrorInvalidState   The SRP server is enabled and the sequence number cannot be changed.
     *
     */
    Error SetAnycastModeSequenceNumber(uint8_t aSequenceNumber);

    /**
     * This method tells whether the SRP server is currently running.
     *
     * @returns  A boolean that indicates whether the server is running.
     *
     */
    bool IsRunning(void) const { return (mState == kStateRunning); }

    /**
     * This method tells the state of the SRP server.
     *
     * @returns  An enum that represents the state of the server.
     *
     */
    State GetState(void) const { return mState; }

    /**
     * This method enables/disables the SRP server.
     *
     * @param[in]  aEnabled  A boolean to enable/disable the SRP server.
     *
     */
    void SetEnabled(bool aEnabled);

    /**
     * This method returns the LEASE and KEY-LEASE configurations.
     *
     * @param[out]  aLeaseConfig  A reference to the `LeaseConfig` instance.
     *
     */
    void GetLeaseConfig(LeaseConfig &aLeaseConfig) const { aLeaseConfig = mLeaseConfig; }

    /**
     * This method sets the LEASE and KEY-LEASE configurations.
     *
     * When a LEASE time is requested from a client, the granted value will be
     * limited in range [aMinLease, aMaxLease]; and a KEY-LEASE will be granted
     * in range [aMinKeyLease, aMaxKeyLease].
     *
     * @param[in]  aLeaseConfig  A reference to the `LeaseConfig` instance.
     *
     * @retval  kErrorNone         Successfully set the LEASE and KEY-LEASE ranges.
     * @retval  kErrorInvalidArgs  The LEASE or KEY-LEASE range is not valid.
     *
     */
    Error SetLeaseConfig(const LeaseConfig &aLeaseConfig);

    /**
     * This method returns the next registered SRP host.
     *
     * @param[in]  aHost  The current SRP host; use `nullptr` to get the first SRP host.
     *
     * @returns  A pointer to the next SRP host or `nullptr` if no more SRP hosts can be found.
     *
     */
    const Host *GetNextHost(const Host *aHost);

    /**
     * This method receives the service update result from service handler set by
     * SetServiceHandler.
     *
     * @param[in]  aId     The ID of the service update transaction.
     * @param[in]  aError  The service update result.
     *
     */
    void HandleServiceUpdateResult(ServiceUpdateId aId, Error aError);

private:
    static constexpr uint16_t kUdpPayloadSize = Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header);

    static constexpr uint32_t kDefaultMinLease             = 60u * 30;        // 30 min (in seconds).
    static constexpr uint32_t kDefaultMaxLease             = 3600u * 2;       // 2 hours (in seconds).
    static constexpr uint32_t kDefaultMinKeyLease          = 3600u * 24;      // 1 day (in seconds).
    static constexpr uint32_t kDefaultMaxKeyLease          = 3600u * 24 * 14; // 14 days (in seconds).
    static constexpr uint32_t kDefaultEventsHandlerTimeout = OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT;

    static constexpr AddressMode kDefaultAddressMode =
        static_cast<AddressMode>(OPENTHREAD_CONFIG_SRP_SERVER_DEFAULT_ADDDRESS_MODE);

    static constexpr uint16_t kAnycastAddressModePort = 53;

    // Metdata for a received SRP Update message.
    struct MessageMetadata
    {
        // Indicates whether the `Message` is received directly from a
        // client or from an SRPL partner.
        bool IsDirectRxFromClient(void) const { return (mMessageInfo != nullptr); }

        Dns::UpdateHeader       mDnsHeader;
        Dns::Zone               mDnsZone;
        uint16_t                mOffset;
        TimeMilli               mRxTime;
        LeaseConfig             mLeaseConfig;
        const Ip6::MessageInfo *mMessageInfo; // Set to `nullptr` when from SRPL.
    };

    // This class includes metadata for processing a SRP update (register, deregister)
    // and sending DNS response to the client.
    class UpdateMetadata : public InstanceLocator,
                           public LinkedListEntry<UpdateMetadata>,
                           public Heap::Allocatable<UpdateMetadata>
    {
        friend class LinkedListEntry<UpdateMetadata>;
        friend class Heap::Allocatable<UpdateMetadata>;

    public:
        TimeMilli                GetExpireTime(void) const { return mExpireTime; }
        const Dns::UpdateHeader &GetDnsHeader(void) const { return mDnsHeader; }
        ServiceUpdateId          GetId(void) const { return mId; }
        const LeaseConfig &      GetLeaseConfig(void) const { return mLeaseConfig; }
        Host &                   GetHost(void) { return mHost; }
        const Ip6::MessageInfo & GetMessageInfo(void) const { return mMessageInfo; }
        bool                     IsDirectRxFromClient(void) const { return mIsDirectRxFromClient; }
        bool                     Matches(ServiceUpdateId aId) const { return mId == aId; }

    private:
        UpdateMetadata(Instance &aInstance, Host &aHost, const MessageMetadata &aMessageMetadata);

        UpdateMetadata *  mNext;
        TimeMilli         mExpireTime;
        Dns::UpdateHeader mDnsHeader;
        ServiceUpdateId   mId;          // The ID of this service update transaction.
        LeaseConfig       mLeaseConfig; // Lease config to use when processing the message.
        Host &            mHost;        // The `UpdateMetadata` has no ownership of this host.
        Ip6::MessageInfo  mMessageInfo; // Valid when `mIsDirectRxFromClient` is true.
        bool              mIsDirectRxFromClient;
    };

    void              Start(void);
    void              Stop(void);
    void              SelectPort(void);
    void              PrepareSocket(void);
    Ip6::Udp::Socket &GetSocket(void);

#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
    void  HandleDnssdServerStateChange(void);
    Error HandleDnssdServerUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
#endif

    void HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent);

    ServiceUpdateId AllocateId(void) { return mServiceUpdateId++; }

    void  CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata);
    void  CommitSrpUpdate(Error aError, UpdateMetadata &aUpdateMetadata);
    void  CommitSrpUpdate(Error                    aError,
                          Host &                   aHost,
                          const Dns::UpdateHeader &aDnsHeader,
                          const Ip6::MessageInfo * aMessageInfo,
                          const LeaseConfig &      aLeaseConfig);
    Error ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
    Error ProcessMessage(Message &               aMessage,
                         TimeMilli               aRxTime,
                         const LeaseConfig &     aLeaseConfig,
                         const Ip6::MessageInfo *aMessageInfo);
    void  ProcessDnsUpdate(Message &aMessage, MessageMetadata &aMetadata);
    Error ProcessUpdateSection(Host &aHost, const Message &aMessage, MessageMetadata &aMetadata) const;
    Error ProcessAdditionalSection(Host *aHost, const Message &aMessage, MessageMetadata &aMetadata) const;
    Error VerifySignature(const Dns::Ecdsa256KeyRecord &aKeyRecord,
                          const Message &               aMessage,
                          Dns::UpdateHeader             aDnsHeader,
                          uint16_t                      aSigOffset,
                          uint16_t                      aSigRdataOffset,
                          uint16_t                      aSigRdataLength,
                          const char *                  aSignerName) const;
    Error ProcessZoneSection(const Message &aMessage, MessageMetadata &aMetadata) const;
    Error ProcessHostDescriptionInstruction(Host &                 aHost,
                                            const Message &        aMessage,
                                            const MessageMetadata &aMetadata) const;
    Error ProcessServiceDiscoveryInstructions(Host &                 aHost,
                                              const Message &        aMessage,
                                              const MessageMetadata &aMetadata) const;
    Error ProcessServiceDescriptionInstructions(Host &aHost, const Message &aMessage, MessageMetadata &aMetadata) const;

    static bool IsValidDeleteAllRecord(const Dns::ResourceRecord &aRecord);

    void        HandleUpdate(Host &aHost, const MessageMetadata &aMetadata);
    void        AddHost(Host &aHost);
    void        RemoveHost(Host *aHost, RetainName aRetainName, NotifyMode aNotifyServiceHandler);
    bool        HasNameConflictsWith(Host &aHost) const;
    void        SendResponse(const Dns::UpdateHeader &   aHeader,
                             Dns::UpdateHeader::Response aResponseCode,
                             const Ip6::MessageInfo &    aMessageInfo);
    void        SendResponse(const Dns::UpdateHeader &aHeader,
                             uint32_t                 aLease,
                             uint32_t                 aKeyLease,
                             const Ip6::MessageInfo & aMessageInfo);
    static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
    void        HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
    static void HandleLeaseTimer(Timer &aTimer);
    void        HandleLeaseTimer(void);
    static void HandleOutstandingUpdatesTimer(Timer &aTimer);
    void        HandleOutstandingUpdatesTimer(void);

    void                  HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError);
    const UpdateMetadata *FindOutstandingUpdate(const MessageMetadata &aMessageMetadata) const;
    static const char *   AddressModeToString(AddressMode aMode);

    Ip6::Udp::Socket                mSocket;
    otSrpServerServiceUpdateHandler mServiceUpdateHandler;
    void *                          mServiceUpdateHandlerContext;

    Heap::String mDomain;

    LeaseConfig mLeaseConfig;

    LinkedList<Host> mHosts;
    TimerMilli       mLeaseTimer;

    TimerMilli                 mOutstandingUpdatesTimer;
    LinkedList<UpdateMetadata> mOutstandingUpdates;

    ServiceUpdateId mServiceUpdateId;
    uint16_t        mPort;
    State           mState;
    AddressMode     mAddressMode;
    uint8_t         mAnycastSequenceNumber;
    bool            mHasRegisteredAnyService : 1;
};

} // namespace Srp

DefineCoreType(otSrpServerLeaseConfig, Srp::Server::LeaseConfig);
DefineCoreType(otSrpServerHost, Srp::Server::Host);
DefineCoreType(otSrpServerService, Srp::Server::Service);
DefineMapEnum(otSrpServerState, Srp::Server::State);
DefineMapEnum(otSrpServerAddressMode, Srp::Server::AddressMode);

} // namespace ot

#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
#endif // NET_SRP_SERVER_HPP_
