/*
 *  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.
 */

#include "srp_client.hpp"

#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE

#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/random.hpp"
#include "common/settings.hpp"
#include "common/string.hpp"

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

namespace ot {
namespace Srp {

RegisterLogModule("SrpClient");

//---------------------------------------------------------------------
// Client::HostInfo

void Client::HostInfo::Init(void)
{
    Clearable<HostInfo>::Clear();

    // State is directly set on `mState` instead of using `SetState()`
    // to avoid logging.
    mState = OT_SRP_CLIENT_ITEM_STATE_REMOVED;
}

void Client::HostInfo::Clear(void)
{
    Clearable<HostInfo>::Clear();
    SetState(kRemoved);
}

void Client::HostInfo::SetState(ItemState aState)
{
    if (aState != GetState())
    {
        LogInfo("HostInfo %s -> %s", ItemStateToString(GetState()), ItemStateToString(aState));
        mState = MapEnum(aState);
    }
}

void Client::HostInfo::SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses)
{
    mAddresses    = aAddresses;
    mNumAddresses = aNumAddresses;

    LogInfo("HostInfo set %d addrs", GetNumAddresses());

    for (uint8_t index = 0; index < GetNumAddresses(); index++)
    {
        LogInfo("%s", GetAddress(index).ToString().AsCString());
    }
}

//---------------------------------------------------------------------
// Client::Service

Error Client::Service::Init(void)
{
    Error error = kErrorNone;

    VerifyOrExit((GetName() != nullptr) && (GetInstanceName() != nullptr), error = kErrorInvalidArgs);
    VerifyOrExit((GetTxtEntries() != nullptr) || (GetNumTxtEntries() == 0), error = kErrorInvalidArgs);

    // State is directly set on `mState` instead of using `SetState()`
    // to avoid logging.
    mState = OT_SRP_CLIENT_ITEM_STATE_REMOVED;

exit:
    return error;
}

void Client::Service::SetState(ItemState aState)
{
    VerifyOrExit(GetState() != aState);

    LogInfo("Service %s -> %s, \"%s\" \"%s\"", ItemStateToString(GetState()), ItemStateToString(aState),
            GetInstanceName(), GetName());

    if (aState == kToAdd)
    {
        constexpr uint16_t kSubTypeLabelStringSize = 80;

        String<kSubTypeLabelStringSize> string;

        // Log more details only when entering `kToAdd` state.

        if (HasSubType())
        {
            const char *label;

            for (uint16_t index = 0; (label = GetSubTypeLabelAt(index)) != nullptr; index++)
            {
                string.Append("%s\"%s\"", (index != 0) ? ", " : "", label);
            }
        }

        LogInfo("subtypes:[%s] port:%d weight:%d prio:%d txts:%d", string.AsCString(), GetPort(), GetWeight(),
                GetPriority(), GetNumTxtEntries());
    }

    mState = MapEnum(aState);

exit:
    return;
}

bool Client::Service::Matches(const Service &aOther) const
{
    // This method indicates whether or not two service entries match,
    // i.e., have the same service and instance names. This is intended
    // for use by `LinkedList::FindMatching()` to search within the
    // `mServices` list.

    return (strcmp(GetName(), aOther.GetName()) == 0) && (strcmp(GetInstanceName(), aOther.GetInstanceName()) == 0);
}

//---------------------------------------------------------------------
// Client::AutoStart

#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE

Client::AutoStart::AutoStart(void)
{
    Clear();
    mState = kDefaultMode ? kSelectedNone : kDisabled;
}

bool Client::AutoStart::HasSelectedServer(void) const
{
    bool hasSelected = false;

    switch (mState)
    {
    case kDisabled:
    case kSelectedNone:
        break;

    case kSelectedUnicastPreferred:
    case kSelectedUnicast:
    case kSelectedAnycast:
        hasSelected = true;
        break;
    }

    return hasSelected;
}

void Client::AutoStart::SetState(State aState)
{
    if (mState != aState)
    {
        LogInfo("AutoStartState %s -> %s", StateToString(mState), StateToString(aState));
        mState = aState;
    }
}

void Client::AutoStart::SetCallback(AutoStartCallback aCallback, void *aContext)
{
    mCallback = aCallback;
    mContext  = aContext;
}

void Client::AutoStart::InvokeCallback(const Ip6::SockAddr *aServerSockAddr) const
{
    if (mCallback != nullptr)
    {
        mCallback(aServerSockAddr, mContext);
    }
}

#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
const char *Client::AutoStart::StateToString(State aState)
{
    static const char *const kStateStrings[] = {
        "Disabled",    // (0) kDisabled
        "Idle",        // (1) kSelectedNone
        "Unicast-prf", // (2) kSelectedUnicastPreferred
        "Anycast",     // (3) kSelectedAnycast
        "Unicast",     // (4) kSelectedUnicast
    };

    static_assert(0 == kDisabled, "kDisabled value is incorrect");
    static_assert(1 == kSelectedNone, "kSelectedNone value is incorrect");
    static_assert(2 == kSelectedUnicastPreferred, "kSelectedUnicastPreferred value is incorrect");
    static_assert(3 == kSelectedAnycast, "kSelectedAnycast value is incorrect");
    static_assert(4 == kSelectedUnicast, "kSelectedUnicast value is incorrect");

    return kStateStrings[aState];
}
#endif

#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE

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

const char Client::kDefaultDomainName[] = "default.service.arpa";

Client::Client(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mState(kStateStopped)
    , mTxFailureRetryCount(0)
    , mShouldRemoveKeyLease(false)
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
    , mServiceKeyRecordEnabled(false)
#endif
    , mUpdateMessageId(0)
    , mRetryWaitInterval(kMinRetryWaitInterval)
    , mAcceptedLeaseInterval(0)
    , mLeaseInterval(kDefaultLease)
    , mKeyLeaseInterval(kDefaultKeyLease)
    , mSocket(aInstance)
    , mCallback(nullptr)
    , mCallbackContext(nullptr)
    , mDomainName(kDefaultDomainName)
    , mTimer(aInstance, Client::HandleTimer)
{
    mHostInfo.Init();

    // The `Client` implementation uses different constant array of
    // `ItemState` to define transitions between states in `Pause()`,
    // `Stop()`, `SendUpdate`, and `ProcessResponse()`, or to convert
    // an `ItemState` to string. Here, we assert that the enumeration
    // values are correct.

    static_assert(kToAdd == 0, "kToAdd value is not correct");
    static_assert(kAdding == 1, "kAdding value is not correct");
    static_assert(kToRefresh == 2, "kToRefresh value is not correct");
    static_assert(kRefreshing == 3, "kRefreshing value is not correct");
    static_assert(kToRemove == 4, "kToRemove value is not correct");
    static_assert(kRemoving == 5, "kRemoving value is not correct");
    static_assert(kRegistered == 6, "kRegistered value is not correct");
    static_assert(kRemoved == 7, "kRemoved value is not correct");
}

Error Client::Start(const Ip6::SockAddr &aServerSockAddr, Requester aRequester)
{
    Error error;

    VerifyOrExit(GetState() == kStateStopped,
                 error = (aServerSockAddr == GetServerAddress()) ? kErrorNone : kErrorBusy);

    SuccessOrExit(error = mSocket.Open(Client::HandleUdpReceive, this));
    SuccessOrExit(error = mSocket.Connect(aServerSockAddr));

    LogInfo("%starting, server %s", (aRequester == kRequesterUser) ? "S" : "Auto-s",
            aServerSockAddr.ToString().AsCString());

    Resume();

#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
    if (aRequester == kRequesterAuto)
    {
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE && OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE
        Get<Dns::Client>().UpdateDefaultConfigAddress();
#endif
        mAutoStart.InvokeCallback(&aServerSockAddr);
    }
#endif

exit:
    return error;
}

void Client::Stop(Requester aRequester, StopMode aMode)
{
    // Change the state of host info and services so that they are
    // added/removed again once the client is started back. In the
    // case of `kAdding`, we intentionally move to `kToRefresh`
    // instead of `kToAdd` since the server may receive our add
    // request and the item may be registered on the server. This
    // ensures that if we are later asked to remove the item, we do
    // notify server.

    static const ItemState kNewStateOnStop[]{
        /* (0) kToAdd      -> */ kToAdd,
        /* (1) kAdding     -> */ kToRefresh,
        /* (2) kToRefresh  -> */ kToRefresh,
        /* (3) kRefreshing -> */ kToRefresh,
        /* (4) kToRemove   -> */ kToRemove,
        /* (5) kRemoving   -> */ kToRemove,
        /* (6) kRegistered -> */ kToRefresh,
        /* (7) kRemoved    -> */ kRemoved,
    };

    VerifyOrExit(GetState() != kStateStopped);

    // State changes:
    //   kAdding     -> kToRefresh
    //   kRefreshing -> kToRefresh
    //   kRemoving   -> kToRemove
    //   kRegistered -> kToRefresh

    ChangeHostAndServiceStates(kNewStateOnStop);

    IgnoreError(mSocket.Close());

    mShouldRemoveKeyLease = false;
    mTxFailureRetryCount  = 0;

    if (aMode == kResetRetryInterval)
    {
        ResetRetryWaitInterval();
    }

    SetState(kStateStopped);

#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
#if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
    mAutoStart.ResetTimoutFailureCount();
#endif
    if (aRequester == kRequesterAuto)
    {
        mAutoStart.InvokeCallback(nullptr);
    }
#endif

exit:
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
    if (aRequester == kRequesterUser)
    {
        DisableAutoStartMode();
    }
#endif
}

void Client::SetCallback(Callback aCallback, void *aContext)
{
    mCallback        = aCallback;
    mCallbackContext = aContext;
}

void Client::Resume(void)
{
    SetState(kStateUpdated);
    UpdateState();
}

void Client::Pause(void)
{
    // Change the state of host info and services that are are being
    // added or removed so that they are added/removed again once the
    // client is resumed or started back.

    static const ItemState kNewStateOnPause[]{
        /* (0) kToAdd      -> */ kToAdd,
        /* (1) kAdding     -> */ kToRefresh,
        /* (2) kToRefresh  -> */ kToRefresh,
        /* (3) kRefreshing -> */ kToRefresh,
        /* (4) kToRemove   -> */ kToRemove,
        /* (5) kRemoving   -> */ kToRemove,
        /* (6) kRegistered -> */ kRegistered,
        /* (7) kRemoved    -> */ kRemoved,
    };

    // State changes:
    //   kAdding     -> kToRefresh
    //   kRefreshing -> kToRefresh
    //   kRemoving   -> kToRemove

    ChangeHostAndServiceStates(kNewStateOnPause);

    SetState(kStatePaused);
}

void Client::HandleNotifierEvents(Events aEvents)
{
    if (aEvents.Contains(kEventThreadRoleChanged))
    {
        HandleRoleChanged();
    }

#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
    if (aEvents.ContainsAny(kEventThreadNetdataChanged | kEventThreadMeshLocalAddrChanged))
    {
        ProcessAutoStart();
    }
#endif
}

void Client::HandleRoleChanged(void)
{
    if (Get<Mle::Mle>().IsAttached())
    {
        VerifyOrExit(GetState() == kStatePaused);
        Resume();
    }
    else
    {
        VerifyOrExit(GetState() != kStateStopped);
        Pause();
    }

exit:
    return;
}

#if OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE
Error Client::SetDomainName(const char *aName)
{
    Error error = kErrorNone;

    VerifyOrExit((mHostInfo.GetState() == kToAdd) || (mHostInfo.GetState() == kRemoved), error = kErrorInvalidState);

    mDomainName = (aName != nullptr) ? aName : kDefaultDomainName;
    LogInfo("Domain name \"%s\"", mDomainName);

exit:
    return error;
}
#endif

Error Client::SetHostName(const char *aName)
{
    Error error = kErrorNone;

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

    VerifyOrExit((mHostInfo.GetState() == kToAdd) || (mHostInfo.GetState() == kRemoved), error = kErrorInvalidState);

    LogInfo("Host name \"%s\"", aName);
    mHostInfo.SetName(aName);
    mHostInfo.SetState(kToAdd);
    UpdateState();

exit:
    return error;
}

Error Client::SetHostAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses)
{
    Error error = kErrorNone;

    VerifyOrExit((aAddresses != nullptr) && (aNumAddresses > 0), error = kErrorInvalidArgs);

    VerifyOrExit((mHostInfo.GetState() != kToRemove) && (mHostInfo.GetState() != kRemoving),
                 error = kErrorInvalidState);

    if (mHostInfo.GetState() == kRemoved)
    {
        mHostInfo.SetState(kToAdd);
    }
    else if (mHostInfo.GetState() != kToAdd)
    {
        mHostInfo.SetState(kToRefresh);
    }

    mHostInfo.SetAddresses(aAddresses, aNumAddresses);
    UpdateState();

exit:
    return error;
}

Error Client::AddService(Service &aService)
{
    Error error;

    VerifyOrExit(mServices.FindMatching(aService) == nullptr, error = kErrorAlready);

    SuccessOrExit(error = aService.Init());
    mServices.Push(aService);

    aService.SetState(kToAdd);
    UpdateState();

exit:
    return error;
}

Error Client::RemoveService(Service &aService)
{
    Error               error = kErrorNone;
    LinkedList<Service> removedServices;

    VerifyOrExit(mServices.Contains(aService), error = kErrorNotFound);

    UpdateServiceStateToRemove(aService);

    // Check if the service was removed immediately, if so
    // invoke the callback to report the removed service.
    GetRemovedServices(removedServices);

    if (!removedServices.IsEmpty())
    {
        InvokeCallback(kErrorNone, mHostInfo, removedServices.GetHead());
    }

    UpdateState();

exit:
    return error;
}

void Client::UpdateServiceStateToRemove(Service &aService)
{
    if (aService.GetState() == kToAdd)
    {
        // If the service has not been added yet, we can remove it immediately.
        aService.SetState(kRemoved);
    }
    else if (aService.GetState() != kRemoving)
    {
        aService.SetState(kToRemove);
    }
}

Error Client::ClearService(Service &aService)
{
    Error error;

    SuccessOrExit(error = mServices.Remove(aService));
    aService.SetNext(nullptr);
    aService.SetState(kRemoved);
    UpdateState();

exit:
    return error;
}

Error Client::RemoveHostAndServices(bool aShouldRemoveKeyLease, bool aSendUnregToServer)
{
    Error error = kErrorNone;

    LogInfo("Remove host & services");

    VerifyOrExit(mHostInfo.GetState() != kRemoved, error = kErrorAlready);

    if ((mHostInfo.GetState() == kToRemove) || (mHostInfo.GetState() == kRemoving))
    {
        // Host info remove is already ongoing, if "key lease" remove mode is
        // the same, there is no need to send a new update message.
        VerifyOrExit(mShouldRemoveKeyLease != aShouldRemoveKeyLease);
    }

    mShouldRemoveKeyLease = aShouldRemoveKeyLease;

    for (Service &service : mServices)
    {
        UpdateServiceStateToRemove(service);
    }

    if ((mHostInfo.GetState() == kToAdd) && !aSendUnregToServer)
    {
        // Host info is not added yet (not yet registered with
        // server), so we can remove it and all services immediately.
        mHostInfo.SetState(kRemoved);
        HandleUpdateDone();
        ExitNow();
    }

    mHostInfo.SetState(kToRemove);
    UpdateState();

exit:
    return error;
}

void Client::ClearHostAndServices(void)
{
    LogInfo("Clear host & services");

    switch (GetState())
    {
    case kStateStopped:
    case kStatePaused:
        break;

    case kStateToUpdate:
    case kStateUpdating:
    case kStateUpdated:
    case kStateToRetry:
        SetState(kStateUpdated);
        break;
    }

    mTxFailureRetryCount = 0;
    ResetRetryWaitInterval();

    mServices.Clear();
    mHostInfo.Clear();
}

void Client::SetState(State aState)
{
    VerifyOrExit(aState != mState);

    LogInfo("State %s -> %s", StateToString(mState), StateToString(aState));
    mState = aState;

    switch (mState)
    {
    case kStateStopped:
    case kStatePaused:
    case kStateUpdated:
        mTimer.Stop();
        break;

    case kStateToUpdate:
        mTimer.Start(kUpdateTxDelay);
        break;

    case kStateUpdating:
        mTimer.Start(GetRetryWaitInterval());
        break;

    case kStateToRetry:
        break;
    }
exit:
    return;
}

void Client::ChangeHostAndServiceStates(const ItemState *aNewStates)
{
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
    ItemState oldHostState = mHostInfo.GetState();
#endif

    mHostInfo.SetState(aNewStates[mHostInfo.GetState()]);

    for (Service &service : mServices)
    {
        service.SetState(aNewStates[service.GetState()]);
    }

#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
    if ((oldHostState != kRegistered) && (mHostInfo.GetState() == kRegistered))
    {
        Settings::SrpClientInfo info;

        switch (mAutoStart.GetState())
        {
        case AutoStart::kDisabled:
        case AutoStart::kSelectedNone:
            break;

        case AutoStart::kSelectedUnicastPreferred:
        case AutoStart::kSelectedUnicast:
            info.SetServerAddress(GetServerAddress().GetAddress());
            info.SetServerPort(GetServerAddress().GetPort());
            IgnoreError(Get<Settings>().Save(info));
            break;

        case AutoStart::kSelectedAnycast:
            IgnoreError(Get<Settings>().Delete<Settings::SrpClientInfo>());
            break;
        }
    }
#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
}

void Client::InvokeCallback(Error aError) const
{
    InvokeCallback(aError, mHostInfo, nullptr);
}

void Client::InvokeCallback(Error aError, const HostInfo &aHostInfo, const Service *aRemovedServices) const
{
    VerifyOrExit(mCallback != nullptr);
    mCallback(aError, &aHostInfo, mServices.GetHead(), aRemovedServices, mCallbackContext);

exit:
    return;
}

void Client::SendUpdate(void)
{
    static const ItemState kNewStateOnMessageTx[]{
        /* (0) kToAdd      -> */ kAdding,
        /* (1) kAdding     -> */ kAdding,
        /* (2) kToRefresh  -> */ kRefreshing,
        /* (3) kRefreshing -> */ kRefreshing,
        /* (4) kToRemove   -> */ kRemoving,
        /* (5) kRemoving   -> */ kRemoving,
        /* (6) kRegistered -> */ kRegistered,
        /* (7) kRemoved    -> */ kRemoved,
    };

    Error    error   = kErrorNone;
    Message *message = mSocket.NewMessage(0);

    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
    SuccessOrExit(error = PrepareUpdateMessage(*message));
    SuccessOrExit(error = mSocket.SendTo(*message, Ip6::MessageInfo()));

    LogInfo("Send update");

    // State changes:
    //   kToAdd     -> kAdding
    //   kToRefresh -> kRefreshing
    //   kToRemove  -> kRemoving

    ChangeHostAndServiceStates(kNewStateOnMessageTx);

    // Remember the update message tx time to use later to determine the
    // lease renew time.
    mLeaseRenewTime      = TimerMilli::GetNow();
    mTxFailureRetryCount = 0;

    SetState(kStateUpdating);

    if (!Get<Mle::Mle>().IsRxOnWhenIdle())
    {
        // If device is sleepy send fast polls while waiting for
        // the response from server.
        Get<DataPollSender>().SendFastPolls(kFastPollsAfterUpdateTx);
    }

exit:
    if (error != kErrorNone)
    {
        // If there is an error in preparation or transmission of the
        // update message (e.g., no buffer to allocate message), up to
        // `kMaxTxFailureRetries` times, we wait for a short interval
        // `kTxFailureRetryInterval` and try again. After this, we
        // continue to retry using the `mRetryWaitInterval` (which keeps
        // growing on each failure).

        LogInfo("Failed to send update: %s", ErrorToString(error));

        FreeMessage(message);

        SetState(kStateToRetry);

        if (mTxFailureRetryCount < kMaxTxFailureRetries)
        {
            uint32_t interval;

            mTxFailureRetryCount++;
            interval = Random::NonCrypto::AddJitter(kTxFailureRetryInterval, kTxFailureRetryJitter);
            mTimer.Start(interval);

            LogInfo("Quick retry %d in %u msec", mTxFailureRetryCount, interval);

            // Do not report message preparation errors to user
            // until `kMaxTxFailureRetries` are exhausted.
        }
        else
        {
            LogRetryWaitInterval();
            mTimer.Start(Random::NonCrypto::AddJitter(GetRetryWaitInterval(), kRetryIntervalJitter));
            GrowRetryWaitInterval();
            InvokeCallback(error);
        }
    }
}

Error Client::PrepareUpdateMessage(Message &aMessage)
{
    constexpr uint16_t kHeaderOffset = 0;

    Error             error = kErrorNone;
    Dns::UpdateHeader header;
    Info              info;

    info.Clear();

    SuccessOrExit(error = ReadOrGenerateKey(info.mKeyPair));

    // Generate random Message ID and ensure it is different from last one
    do
    {
        SuccessOrExit(error = header.SetRandomMessageId());
    } while (header.GetMessageId() == mUpdateMessageId);

    mUpdateMessageId = header.GetMessageId();

    // SRP Update (DNS Update) message must have exactly one record in
    // Zone section, no records in Prerequisite Section, can have
    // multiple records in Update Section (tracked as they are added),
    // and two records in Additional Data Section (OPT and SIG records).
    // The SIG record itself should not be included in calculation of
    // SIG(0) signature, so the addition record count is set to one
    // here. After signature calculation and appending of SIG record,
    // the additional record count is updated to two and the header is
    // rewritten in the message.

    header.SetZoneRecordCount(1);
    header.SetAdditionalRecordCount(1);
    SuccessOrExit(error = aMessage.Append(header));

    // Prepare Zone section

    info.mDomainNameOffset = aMessage.GetLength();
    SuccessOrExit(error = Dns::Name::AppendName(mDomainName, aMessage));
    SuccessOrExit(error = aMessage.Append(Dns::Zone()));

    // Prepare Update section

    if ((mHostInfo.GetState() != kToRemove) && (mHostInfo.GetState() != kRemoving))
    {
        for (Service &service : mServices)
        {
            SuccessOrExit(error = AppendServiceInstructions(service, aMessage, info));
        }
    }

    SuccessOrExit(error = AppendHostDescriptionInstruction(aMessage, info));

    header.SetUpdateRecordCount(info.mRecordCount);
    aMessage.Write(kHeaderOffset, header);

    // Prepare Additional Data section

    SuccessOrExit(error = AppendUpdateLeaseOptRecord(aMessage));
    SuccessOrExit(error = AppendSignature(aMessage, info));

    header.SetAdditionalRecordCount(2); // Lease OPT and SIG RRs
    aMessage.Write(kHeaderOffset, header);

exit:
    return error;
}

Error Client::ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair)
{
    Error error;

    error = Get<Settings>().Read<Settings::SrpEcdsaKey>(aKeyPair);

    if (error == kErrorNone)
    {
        Crypto::Ecdsa::P256::PublicKey publicKey;

        if (aKeyPair.GetPublicKey(publicKey) == kErrorNone)
        {
            ExitNow();
        }
    }

    SuccessOrExit(error = aKeyPair.Generate());
    IgnoreError(Get<Settings>().Save<Settings::SrpEcdsaKey>(aKeyPair));

exit:
    return error;
}

Error Client::AppendServiceInstructions(Service &aService, Message &aMessage, Info &aInfo)
{
    Error               error = kErrorNone;
    Dns::ResourceRecord rr;
    Dns::SrvRecord      srv;
    bool                removing;
    uint16_t            serviceNameOffset;
    uint16_t            instanceNameOffset;
    uint16_t            offset;

    if (aService.GetState() == kRegistered)
    {
        // If the lease needs to be renewed or if we are close to the
        // renewal time of a registered service, we refresh the service
        // early and include it in this update. This helps put more
        // services on the same lease refresh schedule.

        VerifyOrExit(ShouldRenewEarly(aService));
        aService.SetState(kToRefresh);
    }

    removing = ((aService.GetState() == kToRemove) || (aService.GetState() == kRemoving));

    //----------------------------------
    // Service Discovery Instruction

    // PTR record

    // "service name labels" + (pointer to) domain name.
    serviceNameOffset = aMessage.GetLength();
    SuccessOrExit(error = Dns::Name::AppendMultipleLabels(aService.GetName(), aMessage));
    SuccessOrExit(error = Dns::Name::AppendPointerLabel(aInfo.mDomainNameOffset, aMessage));

    // On remove, we use "Delete an RR from an RRSet" where class is set
    // to NONE and TTL to zero (RFC 2136 - section 2.5.4).

    rr.Init(Dns::ResourceRecord::kTypePtr, removing ? Dns::PtrRecord::kClassNone : Dns::PtrRecord::kClassInternet);
    rr.SetTtl(removing ? 0 : mLeaseInterval);
    offset = aMessage.GetLength();
    SuccessOrExit(error = aMessage.Append(rr));

    // "Instance name" + (pointer to) service name.
    instanceNameOffset = aMessage.GetLength();
    SuccessOrExit(error = Dns::Name::AppendLabel(aService.GetInstanceName(), aMessage));
    SuccessOrExit(error = Dns::Name::AppendPointerLabel(serviceNameOffset, aMessage));

    UpdateRecordLengthInMessage(rr, offset, aMessage);
    aInfo.mRecordCount++;

    if (aService.HasSubType())
    {
        const char *subTypeLabel;
        uint16_t    subServiceNameOffset = 0;

        for (uint16_t index = 0; (subTypeLabel = aService.GetSubTypeLabelAt(index)) != nullptr; ++index)
        {
            // subtype label + "_sub" label + (pointer to) service name.

            SuccessOrExit(error = Dns::Name::AppendLabel(subTypeLabel, aMessage));

            if (index == 0)
            {
                subServiceNameOffset = aMessage.GetLength();
                SuccessOrExit(error = Dns::Name::AppendLabel("_sub", aMessage));
                SuccessOrExit(error = Dns::Name::AppendPointerLabel(serviceNameOffset, aMessage));
            }
            else
            {
                SuccessOrExit(error = Dns::Name::AppendPointerLabel(subServiceNameOffset, aMessage));
            }

            // `rr` is already initialized as PTR (add or remove).
            offset = aMessage.GetLength();
            SuccessOrExit(error = aMessage.Append(rr));

            SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage));
            UpdateRecordLengthInMessage(rr, offset, aMessage);
            aInfo.mRecordCount++;
        }
    }

    //----------------------------------
    // Service Description Instruction

    // "Delete all RRsets from a name" for Instance Name.

    SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage));
    SuccessOrExit(error = AppendDeleteAllRrsets(aMessage));
    aInfo.mRecordCount++;

    VerifyOrExit(!removing);

    // SRV RR

    SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage));
    srv.Init();
    srv.SetTtl(mLeaseInterval);
    srv.SetPriority(aService.GetPriority());
    srv.SetWeight(aService.GetWeight());
    srv.SetPort(aService.GetPort());
    offset = aMessage.GetLength();
    SuccessOrExit(error = aMessage.Append(srv));
    SuccessOrExit(error = AppendHostName(aMessage, aInfo));
    UpdateRecordLengthInMessage(srv, offset, aMessage);
    aInfo.mRecordCount++;

    // TXT RR

    SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage));
    rr.Init(Dns::ResourceRecord::kTypeTxt);
    offset = aMessage.GetLength();
    SuccessOrExit(error = aMessage.Append(rr));
    SuccessOrExit(error =
                      Dns::TxtEntry::AppendEntries(aService.GetTxtEntries(), aService.GetNumTxtEntries(), aMessage));
    UpdateRecordLengthInMessage(rr, offset, aMessage);
    aInfo.mRecordCount++;

#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
    if (mServiceKeyRecordEnabled)
    {
        // KEY RR is optional in "Service Description Instruction". It
        // is added here under `REFERENCE_DEVICE` config and is intended
        // for testing only.

        SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage));
        SuccessOrExit(error = AppendKeyRecord(aMessage, aInfo));
    }
#endif

exit:
    return error;
}

Error Client::AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo) const
{
    Error               error = kErrorNone;
    Dns::ResourceRecord rr;

    //----------------------------------
    // Host Description Instruction

    // "Delete all RRsets from a name" for Host Name.

    SuccessOrExit(error = AppendHostName(aMessage, aInfo));
    SuccessOrExit(error = AppendDeleteAllRrsets(aMessage));
    aInfo.mRecordCount++;

    // AAAA RRs

    rr.Init(Dns::ResourceRecord::kTypeAaaa);
    rr.SetTtl(mLeaseInterval);
    rr.SetLength(sizeof(Ip6::Address));

    for (uint8_t index = 0; index < mHostInfo.GetNumAddresses(); index++)
    {
        SuccessOrExit(error = AppendHostName(aMessage, aInfo));
        SuccessOrExit(error = aMessage.Append(rr));
        SuccessOrExit(error = aMessage.Append(mHostInfo.GetAddress(index)));
        aInfo.mRecordCount++;
    }

    // KEY RR

    SuccessOrExit(error = AppendHostName(aMessage, aInfo));
    SuccessOrExit(error = AppendKeyRecord(aMessage, aInfo));

exit:
    return error;
}

Error Client::AppendKeyRecord(Message &aMessage, Info &aInfo) const
{
    Error                          error;
    Dns::KeyRecord                 key;
    Crypto::Ecdsa::P256::PublicKey publicKey;

    key.Init();
    key.SetTtl(mLeaseInterval);
    key.SetFlags(Dns::KeyRecord::kAuthConfidPermitted, Dns::KeyRecord::kOwnerNonZone,
                 Dns::KeyRecord::kSignatoryFlagGeneral);
    key.SetProtocol(Dns::KeyRecord::kProtocolDnsSec);
    key.SetAlgorithm(Dns::KeyRecord::kAlgorithmEcdsaP256Sha256);
    key.SetLength(sizeof(Dns::KeyRecord) - sizeof(Dns::ResourceRecord) + sizeof(Crypto::Ecdsa::P256::PublicKey));
    SuccessOrExit(error = aMessage.Append(key));
    SuccessOrExit(error = aInfo.mKeyPair.GetPublicKey(publicKey));
    SuccessOrExit(error = aMessage.Append(publicKey));
    aInfo.mRecordCount++;

exit:
    return error;
}

Error Client::AppendDeleteAllRrsets(Message &aMessage) const
{
    // "Delete all RRsets from a name" (RFC 2136 - 2.5.3)
    // Name should be already appended in the message.

    Dns::ResourceRecord rr;

    rr.Init(Dns::ResourceRecord::kTypeAny, Dns::ResourceRecord::kClassAny);
    rr.SetTtl(0);
    rr.SetLength(0);

    return aMessage.Append(rr);
}

Error Client::AppendHostName(Message &aMessage, Info &aInfo, bool aDoNotCompress) const
{
    Error error;

    if (aDoNotCompress)
    {
        // Uncompressed (canonical form) of host name is used for SIG(0)
        // calculation.
        SuccessOrExit(error = Dns::Name::AppendMultipleLabels(mHostInfo.GetName(), aMessage));
        error = Dns::Name::AppendName(mDomainName, aMessage);
        ExitNow();
    }

    // If host name was previously added in the message, add it
    // compressed as pointer to the previous one. Otherwise,
    // append it and remember the offset.

    if (aInfo.mHostNameOffset != Info::kUnknownOffset)
    {
        ExitNow(error = Dns::Name::AppendPointerLabel(aInfo.mHostNameOffset, aMessage));
    }

    aInfo.mHostNameOffset = aMessage.GetLength();
    SuccessOrExit(error = Dns::Name::AppendMultipleLabels(mHostInfo.GetName(), aMessage));
    error = Dns::Name::AppendPointerLabel(aInfo.mDomainNameOffset, aMessage);

exit:
    return error;
}

Error Client::AppendUpdateLeaseOptRecord(Message &aMessage) const
{
    Error            error;
    Dns::OptRecord   optRecord;
    Dns::LeaseOption leaseOption;

    // Append empty (root domain) as OPT RR name.
    SuccessOrExit(error = Dns::Name::AppendTerminator(aMessage));

    // `Init()` sets the type and clears (set to zero) the extended
    // Response Code, version and all flags.
    optRecord.Init();
    optRecord.SetUdpPayloadSize(kUdpPayloadSize);
    optRecord.SetDnsSecurityFlag();
    optRecord.SetLength(sizeof(Dns::LeaseOption));

    SuccessOrExit(error = aMessage.Append(optRecord));

    leaseOption.Init();

    if ((mHostInfo.GetState() == kToRemove) || (mHostInfo.GetState() == kRemoving))
    {
        leaseOption.SetLeaseInterval(0);
        leaseOption.SetKeyLeaseInterval(mShouldRemoveKeyLease ? 0 : mKeyLeaseInterval);
    }
    else
    {
        leaseOption.SetLeaseInterval(mLeaseInterval);
        leaseOption.SetKeyLeaseInterval(mKeyLeaseInterval);
    }

    error = aMessage.Append(leaseOption);

exit:
    return error;
}

Error Client::AppendSignature(Message &aMessage, Info &aInfo)
{
    Error                          error;
    Dns::SigRecord                 sig;
    Crypto::Sha256                 sha256;
    Crypto::Sha256::Hash           hash;
    Crypto::Ecdsa::P256::Signature signature;
    uint16_t                       offset;
    uint16_t                       len;

    // Prepare SIG RR: TTL, type covered, labels count should be set
    // to zero. Since we have no clock, inception and expiration time
    // are also set to zero. The RDATA length will be set later (not
    // yet known due to variably (and possible compression) of signer's
    // name.

    sig.Clear();
    sig.Init(Dns::ResourceRecord::kClassAny);
    sig.SetAlgorithm(Dns::KeyRecord::kAlgorithmEcdsaP256Sha256);

    // Append the SIG RR with full uncompressed form of the host name
    // as the signer's name. This is used for SIG(0) calculation only.
    // It will be overwritten with host name compressed.

    offset = aMessage.GetLength();
    SuccessOrExit(error = aMessage.Append(sig));
    SuccessOrExit(error = AppendHostName(aMessage, aInfo, /* aDoNotCompress */ true));

    // Calculate signature (RFC 2931): Calculated over "data" which is
    // concatenation of (1) the SIG RR RDATA wire format (including
    // the canonical form of the signer's name), entirely omitting the
    // signature subfield, (2) DNS query message, including DNS header
    // but not UDP/IP header before the header RR counts have been
    // adjusted for the inclusion of SIG(0).

    sha256.Start();

    // (1) SIG RR RDATA wire format
    len = aMessage.GetLength() - offset - sizeof(Dns::ResourceRecord);
    sha256.Update(aMessage, offset + sizeof(Dns::ResourceRecord), len);

    // (2) Message from DNS header before SIG
    sha256.Update(aMessage, 0, offset);

    sha256.Finish(hash);
    SuccessOrExit(error = aInfo.mKeyPair.Sign(hash, signature));

    // Move back in message and append SIG RR now with compressed host
    // name (as signer's name) along with the calculated signature.

    IgnoreError(aMessage.SetLength(offset));

    // SIG(0) uses owner name of root (single zero byte).
    SuccessOrExit(error = Dns::Name::AppendTerminator(aMessage));

    offset = aMessage.GetLength();
    SuccessOrExit(error = aMessage.Append(sig));
    SuccessOrExit(error = AppendHostName(aMessage, aInfo));
    SuccessOrExit(error = aMessage.Append(signature));
    UpdateRecordLengthInMessage(sig, offset, aMessage);

exit:
    return error;
}

void Client::UpdateRecordLengthInMessage(Dns::ResourceRecord &aRecord, uint16_t aOffset, Message &aMessage) const
{
    // This method is used to calculate an RR DATA length and update
    // (rewrite) it in a message. This should be called immediately
    // after all the fields in the record are written in the message.
    // `aOffset` gives the offset in the message to the start of the
    // record.

    aRecord.SetLength(aMessage.GetLength() - aOffset - sizeof(Dns::ResourceRecord));
    aMessage.Write(aOffset, aRecord);
}

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

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

void Client::ProcessResponse(Message &aMessage)
{
    static const ItemState kNewStateOnUpdateDone[]{
        /* (0) kToAdd      -> */ kToAdd,
        /* (1) kAdding     -> */ kRegistered,
        /* (2) kToRefresh  -> */ kToRefresh,
        /* (3) kRefreshing -> */ kRegistered,
        /* (4) kToRemove   -> */ kToRemove,
        /* (5) kRemoving   -> */ kRemoved,
        /* (6) kRegistered -> */ kRegistered,
        /* (7) kRemoved    -> */ kRemoved,
    };

    Error               error = kErrorNone;
    Dns::UpdateHeader   header;
    uint16_t            offset = aMessage.GetOffset();
    uint16_t            recordCount;
    LinkedList<Service> removedServices;

    VerifyOrExit(GetState() == kStateUpdating);

    SuccessOrExit(error = aMessage.Read(offset, header));

    VerifyOrExit(header.GetType() == Dns::Header::kTypeResponse, error = kErrorParse);
    VerifyOrExit(header.GetQueryType() == Dns::Header::kQueryTypeUpdate, error = kErrorParse);
    VerifyOrExit(header.GetMessageId() == mUpdateMessageId, error = kErrorDrop);

    if (!Get<Mle::Mle>().IsRxOnWhenIdle())
    {
        Get<DataPollSender>().StopFastPolls();
    }

    // Response is for the earlier request message.

    LogInfo("Received response");

#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
    mAutoStart.ResetTimoutFailureCount();
#endif

    error = Dns::Header::ResponseCodeToError(header.GetResponseCode());

    if (error != kErrorNone)
    {
        LogInfo("Server rejected %s code:%d", ErrorToString(error), header.GetResponseCode());

        if (mHostInfo.GetState() == kAdding)
        {
            // Since server rejected the update message, we go back to
            // `kToAdd` state to allow user to give a new name using
            // `SetHostName()`.
            mHostInfo.SetState(kToAdd);
        }

        // Wait for the timer to expire to retry. Note that timer is
        // already scheduled for the current wait interval when state
        // was changed to `kStateUpdating`.

        LogRetryWaitInterval();
        GrowRetryWaitInterval();
        SetState(kStateToRetry);
        InvokeCallback(error);

#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
        if ((error == kErrorDuplicated) || (error == kErrorSecurity))
        {
            // If the server rejects the update with specific errors
            // (indicating duplicate name and/or security error), we
            // try to switch the server (we check if another can be
            // found in the Network Data).
            //
            // Note that this is done after invoking the callback and
            // notifying the user of the error from server. This works
            // correctly even if user makes changes from callback
            // (e.g., calls SRP client APIs like `Stop` or disables
            // auto-start), since we have a guard check at the top of
            // `SelectNextServer()` to verify that client is still
            // running and auto-start is enabled and selected the
            // server.

            SelectNextServer(/* aDisallowSwitchOnRegisteredHost */ true);
        }
#endif
        ExitNow(error = kErrorNone);
    }

    offset += sizeof(header);

    // Skip over all sections till Additional Data section
    // SPEC ENHANCEMENT: Server can echo the request back or not
    // include any of RRs. Would be good to explicitly require SRP server
    // to not echo back RRs.

    if (header.GetZoneRecordCount() != 0)
    {
        VerifyOrExit(header.GetZoneRecordCount() == 1, error = kErrorParse);
        SuccessOrExit(error = Dns::Name::ParseName(aMessage, offset));
        VerifyOrExit(offset + sizeof(Dns::Zone) <= aMessage.GetLength(), error = kErrorParse);
        offset += sizeof(Dns::Zone);
    }

    // Check for Update Lease OPT RR. This determines the lease
    // interval accepted by server. If not present, then use the
    // transmitted lease interval from the update request message.

    mAcceptedLeaseInterval = mLeaseInterval;
    recordCount =
        header.GetPrerequisiteRecordCount() + header.GetUpdateRecordCount() + header.GetAdditionalRecordCount();

    while (recordCount > 0)
    {
        uint16_t            startOffset = offset;
        Dns::ResourceRecord rr;

        SuccessOrExit(error = ReadResourceRecord(aMessage, offset, rr));
        recordCount--;

        if (rr.GetType() == Dns::ResourceRecord::kTypeOpt)
        {
            SuccessOrExit(error = ProcessOptRecord(aMessage, startOffset, static_cast<Dns::OptRecord &>(rr)));
        }
    }

    // Calculate the lease renew time based on update message tx time
    // and the lease time. `kLeaseRenewGuardInterval` is used to
    // ensure that we renew the lease before server expires it. In the
    // unlikely (but maybe useful for testing) case where the accepted
    // lease interval is too short (shorter than the guard time) we
    // just use half of the accepted lease interval.

    if (mAcceptedLeaseInterval > kLeaseRenewGuardInterval)
    {
        mLeaseRenewTime += Time::SecToMsec(mAcceptedLeaseInterval - kLeaseRenewGuardInterval);
    }
    else
    {
        mLeaseRenewTime += Time::SecToMsec(mAcceptedLeaseInterval) / 2;
    }

    for (Service &service : mServices)
    {
        if ((service.GetState() == kAdding) || (service.GetState() == kRefreshing))
        {
            service.SetLeaseRenewTime(mLeaseRenewTime);
        }
    }

    // State changes:
    //   kAdding     -> kRegistered
    //   kRefreshing -> kRegistered
    //   kRemoving   -> kRemoved

    ChangeHostAndServiceStates(kNewStateOnUpdateDone);

    HandleUpdateDone();
    UpdateState();

exit:
    if (error != kErrorNone)
    {
        LogInfo("Failed to process response %s", ErrorToString(error));
    }
}

void Client::HandleUpdateDone(void)
{
    HostInfo            hostInfoCopy = mHostInfo;
    LinkedList<Service> removedServices;

    if (mHostInfo.GetState() == kRemoved)
    {
        mHostInfo.Clear();
    }

    ResetRetryWaitInterval();
    SetState(kStateUpdated);

    GetRemovedServices(removedServices);
    InvokeCallback(kErrorNone, hostInfoCopy, removedServices.GetHead());
}

void Client::GetRemovedServices(LinkedList<Service> &aRemovedServices)
{
    mServices.RemoveAllMatching(kRemoved, aRemovedServices);
}

Error Client::ReadResourceRecord(const Message &aMessage, uint16_t &aOffset, Dns::ResourceRecord &aRecord)
{
    // Reads and skips over a Resource Record (RR) from message at
    // given offset. On success, `aOffset` is updated to point to end
    // of RR.

    Error error;

    SuccessOrExit(error = Dns::Name::ParseName(aMessage, aOffset));
    SuccessOrExit(error = aMessage.Read(aOffset, aRecord));
    VerifyOrExit(aOffset + aRecord.GetSize() <= aMessage.GetLength(), error = kErrorParse);
    aOffset += static_cast<uint16_t>(aRecord.GetSize());

exit:
    return error;
}

Error Client::ProcessOptRecord(const Message &aMessage, uint16_t aOffset, const Dns::OptRecord &aOptRecord)
{
    // Read and process all options (in an OPT RR) from a message.
    // The `aOffset` points to beginning of record in `aMessage`.

    Error    error = kErrorNone;
    uint16_t len;

    IgnoreError(Dns::Name::ParseName(aMessage, aOffset));
    aOffset += sizeof(Dns::OptRecord);

    len = aOptRecord.GetLength();

    while (len > 0)
    {
        Dns::LeaseOption leaseOption;
        Dns::Option &    option = leaseOption;
        uint16_t         size;

        SuccessOrExit(error = aMessage.Read(aOffset, option));

        VerifyOrExit(aOffset + option.GetSize() <= aMessage.GetLength(), error = kErrorParse);

        if ((option.GetOptionCode() == Dns::Option::kUpdateLease) &&
            (option.GetOptionLength() >= Dns::LeaseOption::kOptionLength))
        {
            SuccessOrExit(error = aMessage.Read(aOffset, leaseOption));

            mAcceptedLeaseInterval = leaseOption.GetLeaseInterval();

            if (mAcceptedLeaseInterval > kMaxLease)
            {
                mAcceptedLeaseInterval = kMaxLease;
            }
        }

        size = static_cast<uint16_t>(option.GetSize());
        aOffset += size;
        len -= size;
    }

exit:
    return error;
}

void Client::UpdateState(void)
{
    TimeMilli now               = TimerMilli::GetNow();
    TimeMilli earliestRenewTime = now.GetDistantFuture();
    bool      shouldUpdate      = false;

    VerifyOrExit((GetState() != kStateStopped) && (GetState() != kStatePaused));
    VerifyOrExit(mHostInfo.GetName() != nullptr);

    // Go through the host info and all the services to check if there
    // are any new changes (i.e., anything new to add or remove). This
    // is used to determine whether to send an SRP update message or
    // not. Also keep track of the earliest renew time among the
    // previously registered services. This is used to schedule the
    // timer for next refresh.

    switch (mHostInfo.GetState())
    {
    case kAdding:
    case kRefreshing:
    case kRemoving:
        break;

    case kRegistered:
        if (now < mLeaseRenewTime)
        {
            break;
        }

        mHostInfo.SetState(kToRefresh);

        // Fall through

    case kToAdd:
    case kToRefresh:
        // Make sure we have at least one service and at least one
        // host address, otherwise no need to send SRP update message.
        // The exception is when removing host info where we allow
        // for empty service list.
        VerifyOrExit(!mServices.IsEmpty() && (mHostInfo.GetNumAddresses() > 0));

        // Fall through

    case kToRemove:
        shouldUpdate = true;
        break;

    case kRemoved:
        ExitNow();
    }

    // If host info is being removed, we skip over checking service list
    // for new adds (or removes). This handles the situation where while
    // remove is ongoing and before we get a response from the server,
    // user adds a new service to be registered. We wait for remove to
    // finish (receive response from server) before starting with a new
    // service adds.

    if (mHostInfo.GetState() != kRemoving)
    {
        for (Service &service : mServices)
        {
            switch (service.GetState())
            {
            case kToAdd:
            case kToRefresh:
            case kToRemove:
                shouldUpdate = true;
                break;

            case kRegistered:
                if (service.GetLeaseRenewTime() <= now)
                {
                    service.SetState(kToRefresh);
                    shouldUpdate = true;
                }
                else if (service.GetLeaseRenewTime() < earliestRenewTime)
                {
                    earliestRenewTime = service.GetLeaseRenewTime();
                }

                break;

            case kAdding:
            case kRefreshing:
            case kRemoving:
            case kRemoved:
                break;
            }
        }
    }

    if (shouldUpdate)
    {
        SetState(kStateToUpdate);
        ExitNow();
    }

    if ((GetState() == kStateUpdated) && (earliestRenewTime != now.GetDistantFuture()))
    {
        mTimer.FireAt(earliestRenewTime);
    }

exit:
    return;
}

void Client::GrowRetryWaitInterval(void)
{
    mRetryWaitInterval =
        mRetryWaitInterval / kRetryIntervalGrowthFactorDenominator * kRetryIntervalGrowthFactorNumerator;

    if (mRetryWaitInterval > kMaxRetryWaitInterval)
    {
        mRetryWaitInterval = kMaxRetryWaitInterval;
    }
}

uint32_t Client::GetBoundedLeaseInterval(uint32_t aInterval, uint32_t aDefaultInterval) const
{
    uint32_t boundedInterval = aDefaultInterval;

    if (aInterval != 0)
    {
        boundedInterval = OT_MIN(aInterval, static_cast<uint32_t>(kMaxLease));
    }

    return boundedInterval;
}

bool Client::ShouldRenewEarly(const Service &aService) const
{
    // Check if we reached the service renew time or close to it. The
    // "early renew interval" is used to allow early refresh. It is
    // calculated as a factor of the `mAcceptedLeaseInterval`. The
    // "early lease renew factor" is given as a fraction (numerator and
    // denominator). If the denominator is set to zero (i.e., factor is
    // set to infinity), then service is always included in all SRP
    // update messages.

    bool shouldRenew;

#if OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_DENOMINATOR != 0
    uint32_t earlyRenewInterval =
        Time::SecToMsec(mAcceptedLeaseInterval) / kEarlyLeaseRenewFactorDenominator * kEarlyLeaseRenewFactorNumerator;

    shouldRenew = (aService.GetLeaseRenewTime() <= TimerMilli::GetNow() + earlyRenewInterval);
#else
    OT_UNUSED_VARIABLE(aService);
    shouldRenew = true;
#endif

    return shouldRenew;
}

void Client::HandleTimer(Timer &aTimer)
{
    aTimer.Get<Client>().HandleTimer();
}

void Client::HandleTimer(void)
{
    switch (GetState())
    {
    case kStateStopped:
    case kStatePaused:
        break;

    case kStateToUpdate:
    case kStateToRetry:
        SendUpdate();
        break;

    case kStateUpdating:
        LogRetryWaitInterval();
        LogInfo("Timed out, no response");
        GrowRetryWaitInterval();
        SetState(kStateToUpdate);
        InvokeCallback(kErrorResponseTimeout);

#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE

        // After certain number of back-to-back timeout failures, we try
        // to switch the server. This is again done after invoking the
        // callback. It works correctly due to the guard check at the
        // top of `SelectNextServer()`.

        mAutoStart.IncrementTimoutFailureCount();

        if (mAutoStart.GetTimoutFailureCount() >= kMaxTimeoutFailuresToSwitchServer)
        {
            SelectNextServer(kDisallowSwitchOnRegisteredHost);
        }
#endif
        break;

    case kStateUpdated:
        UpdateState();
        break;
    }
}

#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE

void Client::EnableAutoStartMode(AutoStartCallback aCallback, void *aContext)
{
    mAutoStart.SetCallback(aCallback, aContext);

    VerifyOrExit(mAutoStart.GetState() == AutoStart::kDisabled);

    mAutoStart.SetState(AutoStart::kSelectedNone);
    ProcessAutoStart();

exit:
    return;
}

void Client::ProcessAutoStart(void)
{
    Ip6::SockAddr       serverSockAddr;
    DnsSrpAnycast::Info anycastInfo;
    DnsSrpUnicast::Info unicastInfo;
    bool                shouldRestart = false;

    // If auto start mode is enabled, we check the Network Data entries
    // to discover and select the preferred SRP server to register with.
    // If we currently have a selected server, we ensure that it is
    // still present in the Network Data and is still the preferred one.

    VerifyOrExit(mAutoStart.GetState() != AutoStart::kDisabled);

    // If SRP client is running, we check to make sure that auto-start
    // did select the current server, and server was not specified by
    // user directly.

    if (IsRunning())
    {
        VerifyOrExit(mAutoStart.GetState() != AutoStart::kSelectedNone);
    }

    // There are three types of entries in Network Data:
    //
    // 1) Preferred unicast entries with address included in service data.
    // 2) Anycast entries (each having a seq number).
    // 3) Unicast entries with address info included in server data.

    serverSockAddr.Clear();

    if (SelectUnicastEntry(DnsSrpUnicast::kFromServiceData, unicastInfo) == kErrorNone)
    {
        mAutoStart.SetState(AutoStart::kSelectedUnicastPreferred);
        serverSockAddr = unicastInfo.mSockAddr;
    }
    else if (Get<NetworkData::Service::Manager>().FindPreferredDnsSrpAnycastInfo(anycastInfo) == kErrorNone)
    {
        serverSockAddr.SetAddress(anycastInfo.mAnycastAddress);
        serverSockAddr.SetPort(kAnycastServerPort);

        // We check if we are selecting an anycast entry for first
        // time, or if the seq number has changed. Even if the
        // anycast address remains the same as before, on a seq
        // number change, the client still needs to restart to
        // re-register its info.

        if ((mAutoStart.GetState() != AutoStart::kSelectedAnycast) ||
            (mAutoStart.GetAnycastSeqNum() != anycastInfo.mSequenceNumber))
        {
            shouldRestart = true;
            mAutoStart.SetAnycastSeqNum(anycastInfo.mSequenceNumber);
        }

        mAutoStart.SetState(AutoStart::kSelectedAnycast);
    }
    else if (SelectUnicastEntry(DnsSrpUnicast::kFromServerData, unicastInfo) == kErrorNone)
    {
        mAutoStart.SetState(AutoStart::kSelectedUnicast);
        serverSockAddr = unicastInfo.mSockAddr;
    }

    if (IsRunning())
    {
        VerifyOrExit((GetServerAddress() != serverSockAddr) || shouldRestart);
        Stop(kRequesterAuto, kResetRetryInterval);
    }

    if (!serverSockAddr.GetAddress().IsUnspecified())
    {
        IgnoreError(Start(serverSockAddr, kRequesterAuto));
    }
    else
    {
        mAutoStart.SetState(AutoStart::kSelectedNone);
    }

exit:
    return;
}

Error Client::SelectUnicastEntry(DnsSrpUnicast::Origin aOrigin, DnsSrpUnicast::Info &aInfo) const
{
    Error                                   error = kErrorNotFound;
    DnsSrpUnicast::Info                     unicastInfo;
    NetworkData::Service::Manager::Iterator iterator;
    uint16_t                                numServers = 0;
#if OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
    Settings::SrpClientInfo savedInfo;
    bool                    hasSavedServerInfo = false;

    if (!IsRunning())
    {
        hasSavedServerInfo = (Get<Settings>().Read(savedInfo) == kErrorNone);
    }
#endif

    while (Get<NetworkData::Service::Manager>().GetNextDnsSrpUnicastInfo(iterator, unicastInfo) == kErrorNone)
    {
        if (unicastInfo.mOrigin != aOrigin)
        {
            continue;
        }

        if (mAutoStart.HasSelectedServer() && (GetServerAddress() == unicastInfo.mSockAddr))
        {
            aInfo = unicastInfo;
            error = kErrorNone;
            ExitNow();
        }

#if OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
        if (hasSavedServerInfo && (unicastInfo.mSockAddr.GetAddress() == savedInfo.GetServerAddress()) &&
            (unicastInfo.mSockAddr.GetPort() == savedInfo.GetServerPort()))
        {
            // Stop the search if we see a match for the previously
            // saved server info in the network data entries.

            aInfo = unicastInfo;
            error = kErrorNone;
            ExitNow();
        }
#endif
        numServers++;

        // Choose a server randomly (with uniform distribution) from
        // the list of servers. As we iterate through server entries,
        // with probability `1/numServers`, we choose to switch the
        // current selected server with the new entry. This approach
        // results in a uniform/same probability of selection among
        // all server entries.

        if ((numServers == 1) || (Random::NonCrypto::GetUint16InRange(0, numServers) == 0))
        {
            aInfo = unicastInfo;
            error = kErrorNone;
        }
    }

exit:
    return error;
}

#if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
void Client::SelectNextServer(bool aDisallowSwitchOnRegisteredHost)
{
    // This method tries to find the next unicast server info entry in the
    // Network Data after the current one selected. If found, it
    // restarts the client with the new server (keeping the retry wait
    // interval as before).

    Ip6::SockAddr         serverSockAddr;
    bool                  selectNext = false;
    DnsSrpUnicast::Origin origin     = DnsSrpUnicast::kFromServiceData;

    serverSockAddr.Clear();

    // Ensure that client is running, auto-start is enabled and
    // auto-start selected the server and it is a unicast entry.

    VerifyOrExit(IsRunning());

    switch (mAutoStart.GetState())
    {
    case AutoStart::kSelectedUnicastPreferred:
        origin = DnsSrpUnicast::kFromServiceData;
        break;

    case AutoStart::kSelectedUnicast:
        origin = DnsSrpUnicast::kFromServerData;
        break;

    case AutoStart::kSelectedAnycast:
    case AutoStart::kDisabled:
    case AutoStart::kSelectedNone:
        ExitNow();
    }

    if (aDisallowSwitchOnRegisteredHost)
    {
        // Ensure that host info is not yet registered (indicating that no
        // service has yet been registered either).
        VerifyOrExit((mHostInfo.GetState() == kAdding) || (mHostInfo.GetState() == kToAdd));
    }

    // We go through all entries to find the one matching the currently
    // selected one, then set `selectNext` to `true` so to select the
    // next one.

    do
    {
        DnsSrpUnicast::Info                     unicastInfo;
        NetworkData::Service::Manager::Iterator iterator;

        while (Get<NetworkData::Service::Manager>().GetNextDnsSrpUnicastInfo(iterator, unicastInfo) == kErrorNone)
        {
            if (unicastInfo.mOrigin != origin)
            {
                continue;
            }

            if (selectNext)
            {
                serverSockAddr = unicastInfo.mSockAddr;
                ExitNow();
            }

            if (GetServerAddress() == unicastInfo.mSockAddr)
            {
                selectNext = true;
            }
        }

        // We loop back to handle the case where the current entry
        // is the last one.

    } while (selectNext);

    // If we reach here it indicates we could not find the entry
    // associated with currently selected server in the list. This
    // situation is rather unlikely but can still happen if Network
    // Data happens to be changed and the entry removed but
    // the "changed" event from `Notifier` may have not yet been
    // processed (note that events are emitted from their own
    // tasklet). In such a case we keep `serverSockAddr` as empty.

exit:
    if (!serverSockAddr.GetAddress().IsUnspecified() && (GetServerAddress() != serverSockAddr))
    {
        // We specifically update `mHostInfo` to `kToAdd` state. This
        // ensures that `Stop()` will keep it as kToAdd` and we detect
        // that the host info has not been registered yet and allow the
        // `SelectNextServer()` to happen again if the timeouts/failures
        // continue to happen with the new server.

        mHostInfo.SetState(kToAdd);
        Stop(kRequesterAuto, kKeepRetryInterval);
        IgnoreError(Start(serverSockAddr, kRequesterAuto));
    }
}
#endif // OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE

#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE

const char *Client::ItemStateToString(ItemState aState)
{
    static const char *const kItemStateStrings[] = {
        "ToAdd",      // kToAdd      (0)
        "Adding",     // kAdding     (1)
        "ToRefresh",  // kToRefresh  (2)
        "Refreshing", // kRefreshing (3)
        "ToRemove",   // kToRemove   (4)
        "Removing",   // kRemoving   (5)
        "Registered", // kRegistered (6)
        "Removed",    // kRemoved    (7)
    };

    return kItemStateStrings[aState];
}

#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)

const char *Client::StateToString(State aState)
{
    static const char *const kStateStrings[] = {
        "Stopped",  // kStateStopped  (0)
        "Paused",   // kStatePaused   (1)
        "ToUpdate", // kStateToUpdate (2)
        "Updating", // kStateUpdating (3)
        "Updated",  // kStateUpdated  (4)
        "ToRetry",  // kStateToRetry  (5)
    };

    static_assert(kStateStopped == 0, "kStateStopped value is not correct");
    static_assert(kStatePaused == 1, "kStatePaused value is not correct");
    static_assert(kStateToUpdate == 2, "kStateToUpdate value is not correct");
    static_assert(kStateUpdating == 3, "kStateUpdating value is not correct");
    static_assert(kStateUpdated == 4, "kStateUpdated value is not correct");
    static_assert(kStateToRetry == 5, "kStateToRetry value is not correct");

    return kStateStrings[aState];
}

void Client::LogRetryWaitInterval(void) const
{
    constexpr uint16_t kLogInMsecLimit = 5000; // Max interval (in msec) to log the value in msec unit

    uint32_t interval = GetRetryWaitInterval();

    LogInfo("Retry interval %u %s", (interval < kLogInMsecLimit) ? interval : Time::MsecToSec(interval),
            (interval < kLogInMsecLimit) ? "ms" : "sec");
}

#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)

} // namespace Srp
} // namespace ot

#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
