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

#include "dns_dso.hpp"

#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE

#include "common/array.hpp"
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"

/**
 * @file
 *   This file implements the DNS Stateful Operations (DSO) per RFC 8490.
 */

namespace ot {
namespace Dns {

RegisterLogModule("DnsDso");

//---------------------------------------------------------------------------------------------------------------------
// otPlatDso transport callbacks

extern "C" otInstance *otPlatDsoGetInstance(otPlatDsoConnection *aConnection)
{
    return &AsCoreType(aConnection).GetInstance();
}

extern "C" otPlatDsoConnection *otPlatDsoAccept(otInstance *aInstance, const otSockAddr *aPeerSockAddr)
{
    return AsCoreType(aInstance).Get<Dso>().AcceptConnection(AsCoreType(aPeerSockAddr));
}

extern "C" void otPlatDsoHandleConnected(otPlatDsoConnection *aConnection)
{
    AsCoreType(aConnection).HandleConnected();
}

extern "C" void otPlatDsoHandleReceive(otPlatDsoConnection *aConnection, otMessage *aMessage)
{
    AsCoreType(aConnection).HandleReceive(AsCoreType(aMessage));
}

extern "C" void otPlatDsoHandleDisconnected(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode)
{
    AsCoreType(aConnection).HandleDisconnected(MapEnum(aMode));
}

//---------------------------------------------------------------------------------------------------------------------
// Dso::Connection

Dso::Connection::Connection(Instance &           aInstance,
                            const Ip6::SockAddr &aPeerSockAddr,
                            Callbacks &          aCallbacks,
                            uint32_t             aInactivityTimeout,
                            uint32_t             aKeepAliveInterval)
    : InstanceLocator(aInstance)
    , mNext(nullptr)
    , mCallbacks(aCallbacks)
    , mPeerSockAddr(aPeerSockAddr)
    , mState(kStateDisconnected)
    , mIsServer(false)
    , mInactivity(aInactivityTimeout)
    , mKeepAlive(aKeepAliveInterval)
{
    OT_ASSERT(aKeepAliveInterval >= kMinKeepAliveInterval);
    Init(/* aIsServer */ false);
}

void Dso::Connection::Init(bool aIsServer)
{
    mNextMessageId       = 1;
    mIsServer            = aIsServer;
    mStateDidChange      = false;
    mLongLivedOperation  = false;
    mRetryDelay          = 0;
    mRetryDelayErrorCode = Dns::Header::kResponseSuccess;
    mDisconnectReason    = kReasonUnknown;
}

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

    LogInfo("State: %s -> %s on connection with %s", StateToString(mState), StateToString(aState),
            mPeerSockAddr.ToString().AsCString());

    mState          = aState;
    mStateDidChange = true;

exit:
    return;
}

void Dso::Connection::SignalAnyStateChange(void)
{
    VerifyOrExit(mStateDidChange);
    mStateDidChange = false;

    switch (mState)
    {
    case kStateDisconnected:
        mCallbacks.mHandleDisconnected(*this);
        break;

    case kStateConnectedButSessionless:
        mCallbacks.mHandleConnected(*this);
        break;

    case kStateSessionEstablished:
        mCallbacks.mHandleSessionEstablished(*this);
        break;

    case kStateConnecting:
    case kStateEstablishingSession:
        break;
    };

exit:
    return;
}

Message *Dso::Connection::NewMessage(void)
{
    return Get<MessagePool>().Allocate(Message::kTypeOther, sizeof(Dns::Header),
                                       Message::Settings(Message::kPriorityNormal));
}

void Dso::Connection::Connect(void)
{
    OT_ASSERT(mState == kStateDisconnected);

    Init(/* aIsServer */ false);
    Get<Dso>().mClientConnections.Push(*this);
    MarkAsConnecting();
    otPlatDsoConnect(this, &mPeerSockAddr);
}

void Dso::Connection::Accept(void)
{
    OT_ASSERT(mState == kStateDisconnected);

    Init(/* aIsServer */ true);
    Get<Dso>().mServerConnections.Push(*this);
    MarkAsConnecting();
}

void Dso::Connection::MarkAsConnecting(void)
{
    SetState(kStateConnecting);

    // While in `kStateConnecting` state we use the `mKeepAlive` to
    // track the `kConnectingTimeout` (if connection is not established
    // within the timeout, we consider it as failure and close it).

    mKeepAlive.SetExpirationTime(TimerMilli::GetNow() + kConnectingTimeout);
    Get<Dso>().mTimer.FireAtIfEarlier(mKeepAlive.GetExpirationTime());

    // Wait for `HandleConnected()` or `HandleDisconnected()` callbacks
    // or timeout.
}

void Dso::Connection::HandleConnected(void)
{
    OT_ASSERT(mState == kStateConnecting);

    SetState(kStateConnectedButSessionless);
    ResetTimeouts(/* aIsKeepAliveMessage */ false);

    SignalAnyStateChange();
}

void Dso::Connection::Disconnect(DisconnectMode aMode, DisconnectReason aReason)
{
    VerifyOrExit(mState != kStateDisconnected);

    mDisconnectReason = aReason;
    MarkAsDisconnected();

    otPlatDsoDisconnect(this, MapEnum(aMode));

exit:
    return;
}

void Dso::Connection::HandleDisconnected(DisconnectMode aMode)
{
    VerifyOrExit(mState != kStateDisconnected);

    if (mState == kStateConnecting)
    {
        mDisconnectReason = kReasonFailedToConnect;
    }
    else
    {
        switch (aMode)
        {
        case kGracefullyClose:
            mDisconnectReason = kReasonPeerClosed;
            break;

        case kForciblyAbort:
            mDisconnectReason = kReasonPeerAborted;
        }
    }

    MarkAsDisconnected();
    SignalAnyStateChange();

exit:
    return;
}

void Dso::Connection::MarkAsDisconnected(void)
{
    if (IsClient())
    {
        IgnoreError(Get<Dso>().mClientConnections.Remove(*this));
    }
    else
    {
        IgnoreError(Get<Dso>().mServerConnections.Remove(*this));
    }

    mPendingRequests.Clear();
    SetState(kStateDisconnected);

    LogInfo("Disconnect reason: %s", DisconnectReasonToString(mDisconnectReason));
}

void Dso::Connection::MarkSessionEstablished(void)
{
    switch (mState)
    {
    case kStateConnectedButSessionless:
    case kStateEstablishingSession:
    case kStateSessionEstablished:
        break;

    case kStateDisconnected:
    case kStateConnecting:
        OT_ASSERT(false);
    }

    SetState(kStateSessionEstablished);
}

Error Dso::Connection::SendRequestMessage(Message &aMessage, MessageId &aMessageId, uint32_t aResponseTimeout)
{
    return SendMessage(aMessage, kRequestMessage, aMessageId, Dns::Header::kResponseSuccess, aResponseTimeout);
}

Error Dso::Connection::SendUnidirectionalMessage(Message &aMessage)
{
    MessageId messageId = 0;

    return SendMessage(aMessage, kUnidirectionalMessage, messageId);
}

Error Dso::Connection::SendResponseMessage(Message &aMessage, MessageId aResponseId)
{
    return SendMessage(aMessage, kResponseMessage, aResponseId);
}

void Dso::Connection::SetLongLivedOperation(bool aLongLivedOperation)
{
    VerifyOrExit(mLongLivedOperation != aLongLivedOperation);

    mLongLivedOperation = aLongLivedOperation;

    LogInfo("Long-lived operation %s", mLongLivedOperation ? "started" : "stopped");

    if (!mLongLivedOperation)
    {
        TimeMilli now = TimerMilli::GetNow();
        TimeMilli nextTime;

        nextTime = GetNextFireTime(now);

        if (nextTime != now.GetDistantFuture())
        {
            Get<Dso>().mTimer.FireAtIfEarlier(nextTime);
        }
    }

exit:
    return;
}

Error Dso::Connection::SendRetryDelayMessage(uint32_t aDelay, Dns::Header::Response aResponseCode)
{
    Error         error   = kErrorNone;
    Message *     message = nullptr;
    RetryDelayTlv retryDelayTlv;
    MessageId     messageId;

    switch (mState)
    {
    case kStateSessionEstablished:
        OT_ASSERT(IsServer());
        break;

    case kStateConnectedButSessionless:
    case kStateEstablishingSession:
    case kStateDisconnected:
    case kStateConnecting:
        OT_ASSERT(false);
    }

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

    retryDelayTlv.Init();
    retryDelayTlv.SetRetryDelay(aDelay);
    SuccessOrExit(error = message->Append(retryDelayTlv));
    error = SendMessage(*message, kUnidirectionalMessage, messageId, aResponseCode);

exit:
    FreeMessageOnError(message, error);
    return error;
}

Error Dso::Connection::SetTimeouts(uint32_t aInactivityTimeout, uint32_t aKeepAliveInterval)
{
    Error error = kErrorNone;

    VerifyOrExit(aKeepAliveInterval >= kMinKeepAliveInterval, error = kErrorInvalidArgs);

    // If acting as server, the timeout values are the ones we grant
    // to a connecting clients. If acting as client, the timeout
    // values are what to request when sending Keep Alive message.
    // If in `kStateDisconnected` we set both (since we don't know
    // yet whether we are going to connect as client or server).

    if ((mState == kStateDisconnected) || IsServer())
    {
        mKeepAlive.SetInterval(aKeepAliveInterval);
        AdjustInactivityTimeout(aInactivityTimeout);
    }

    if ((mState == kStateDisconnected) || IsClient())
    {
        mKeepAlive.SetRequestInterval(aKeepAliveInterval);
        mInactivity.SetRequestInterval(aInactivityTimeout);
    }

    switch (mState)
    {
    case kStateDisconnected:
    case kStateConnecting:
        break;

    case kStateConnectedButSessionless:
    case kStateEstablishingSession:
        if (IsServer())
        {
            break;
        }

        OT_FALL_THROUGH;

    case kStateSessionEstablished:
        error = SendKeepAliveMessage();
    }

exit:
    return error;
}

Error Dso::Connection::SendKeepAliveMessage(void)
{
    return SendKeepAliveMessage(IsServer() ? kUnidirectionalMessage : kRequestMessage, 0);
}

Error Dso::Connection::SendKeepAliveMessage(MessageType aMessageType, MessageId aResponseId)
{
    // Sends a Keep Alive message of a given type. This is a common
    // method used by both client and server. `aResponseId` is
    // applicable and used only when the message type is
    // `kResponseMessage`.

    Error        error   = kErrorNone;
    Message *    message = nullptr;
    KeepAliveTlv keepAliveTlv;

    switch (mState)
    {
    case kStateConnectedButSessionless:
    case kStateEstablishingSession:
        if (IsServer())
        {
            // While session is being established, server is only allowed
            // to send a Keep Alive response to a request from client.
            OT_ASSERT(aMessageType == kResponseMessage);
        }
        break;

    case kStateSessionEstablished:
        break;

    case kStateDisconnected:
    case kStateConnecting:
        OT_ASSERT(false);
    }

    // Server can send Keep Alive response (to a request from client)
    // or a unidirectional Keep Alive message. Client can send
    // KeepAlive request message.

    if (IsServer())
    {
        if (aMessageType == kResponseMessage)
        {
            OT_ASSERT(aResponseId != 0);
        }
        else
        {
            OT_ASSERT(aMessageType == kUnidirectionalMessage);
        }
    }
    else
    {
        OT_ASSERT(aMessageType == kRequestMessage);
    }

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

    keepAliveTlv.Init();

    if (IsServer())
    {
        keepAliveTlv.SetInactivityTimeout(mInactivity.GetInterval());
        keepAliveTlv.SetKeepAliveInterval(mKeepAlive.GetInterval());
    }
    else
    {
        keepAliveTlv.SetInactivityTimeout(mInactivity.GetRequestInterval());
        keepAliveTlv.SetKeepAliveInterval(mKeepAlive.GetRequestInterval());
    }

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

    error = SendMessage(*message, aMessageType, aResponseId);

exit:
    FreeMessageOnError(message, error);
    return error;
}

Error Dso::Connection::SendMessage(Message &             aMessage,
                                   MessageType           aMessageType,
                                   MessageId &           aMessageId,
                                   Dns::Header::Response aResponseCode,
                                   uint32_t              aResponseTimeout)
{
    Error       error          = kErrorNone;
    Tlv::Type   primaryTlvType = Tlv::kReservedType;
    Dns::Header header;

    switch (mState)
    {
    case kStateConnectedButSessionless:
        // To establish session, client MUST send a request message.
        // Server is not allowed to send any messages. Unidirectional
        // messages are not allowed before session is established.
        OT_ASSERT(IsClient());
        OT_ASSERT(aMessageType == kRequestMessage);
        break;

    case kStateEstablishingSession:
        // During session establishment, client is allowed to send
        // additional request messages, server is only allowed to
        // send response.
        if (IsClient())
        {
            OT_ASSERT(aMessageType == kRequestMessage);
        }
        else
        {
            OT_ASSERT(aMessageType == kResponseMessage);
        }
        break;

    case kStateSessionEstablished:
        // All message types are allowed.
        break;

    case kStateDisconnected:
    case kStateConnecting:
        OT_ASSERT(false);
    }

    // A DSO request or unidirectional message MUST contain at
    // least one TLV. The first TLV is the "Primary TLV" and
    // determines the nature of the operation being performed.
    // A DSO response message may contain no TLVs, or may contain
    // one or more TLVs. Response Primary TLV(s) MUST appear first
    // in a DSO response message.

    aMessage.SetOffset(0);
    IgnoreError(ReadPrimaryTlv(aMessage, primaryTlvType));

    switch (aMessageType)
    {
    case kResponseMessage:
        break;
    case kRequestMessage:
    case kUnidirectionalMessage:
        OT_ASSERT(primaryTlvType != Tlv::kReservedType);
    }

    // `header` is cleared from its constructor call so all fields
    // start as zero.

    switch (aMessageType)
    {
    case kRequestMessage:
        header.SetType(Dns::Header::kTypeQuery);
        aMessageId = mNextMessageId;
        break;

    case kResponseMessage:
        header.SetType(Dns::Header::kTypeResponse);
        break;

    case kUnidirectionalMessage:
        header.SetType(Dns::Header::kTypeQuery);
        aMessageId = 0;
        break;
    }

    header.SetMessageId(aMessageId);
    header.SetQueryType(Dns::Header::kQueryTypeDso);
    header.SetResponseCode(aResponseCode);
    SuccessOrExit(error = aMessage.Prepend(header));

    SuccessOrExit(error = AppendPadding(aMessage));

    // Update `mPendingRequests` list with the new request info

    if (aMessageType == kRequestMessage)
    {
        SuccessOrExit(
            error = mPendingRequests.Add(mNextMessageId, primaryTlvType, TimerMilli::GetNow() + aResponseTimeout));

        if (++mNextMessageId == 0)
        {
            mNextMessageId = 1;
        }
    }

    LogInfo("Sending %s message with id %u to %s", MessageTypeToString(aMessageType), aMessageId,
            mPeerSockAddr.ToString().AsCString());

    switch (mState)
    {
    case kStateConnectedButSessionless:
        // On client we transition from "connected" state to
        // "establishing session" state on successfully sending a
        // request message.
        if (IsClient())
        {
            SetState(kStateEstablishingSession);
        }
        break;

    case kStateEstablishingSession:
        // On server we transition from "establishing session" state
        // to "established" on sending a response with success
        // response code.
        if (IsServer() && (aResponseCode == Dns::Header::kResponseSuccess))
        {
            SetState(kStateSessionEstablished);
        }

    default:
        break;
    }

    ResetTimeouts(/* aIsKeepAliveMessage*/ (primaryTlvType == KeepAliveTlv::kType));

    otPlatDsoSend(this, &aMessage);

    // Signal any state changes. This is done at the very end when the
    // `SendMessage()` is fully processed (all state and local
    // variables are updated) to ensure that we do not have any
    // reentrancy issues (e.g., if the callback signalling state
    // change triggers another tx).

    SignalAnyStateChange();

exit:
    return error;
}

Error Dso::Connection::AppendPadding(Message &aMessage)
{
    // This method appends Encryption Padding TLV to a DSO message.
    // It uses the padding policy "Random-Block-Length Padding" from
    // RFC 8467.

    static const uint16_t kBlockLengths[] = {8, 11, 17, 21};

    Error                error = kErrorNone;
    uint16_t             blockLength;
    EncryptionPaddingTlv paddingTlv;

    // We pick a random block length. The random selection can be
    // based on a "weak" source of randomness (so the use of
    // `NonCrypto` is fine). We add padding to the message such
    // that its padded length is a multiple of the chosen block
    // length.

    blockLength = kBlockLengths[Random::NonCrypto::GetUint8InRange(0, GetArrayLength(kBlockLengths))];

    paddingTlv.Init((blockLength - ((aMessage.GetLength() + sizeof(Tlv)) % blockLength)) % blockLength);

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

    for (uint16_t len = paddingTlv.GetLength(); len > 0; len--)
    {
        SuccessOrExit(error = aMessage.Append<uint8_t>(0));
    }

exit:
    return error;
}

void Dso::Connection::HandleReceive(Message &aMessage)
{
    Error       error          = kErrorAbort;
    Tlv::Type   primaryTlvType = Tlv::kReservedType;
    Dns::Header header;

    SuccessOrExit(aMessage.Read(0, header));

    if (header.GetQueryType() != Dns::Header::kQueryTypeDso)
    {
        if (header.GetType() == Dns::Header::kTypeQuery)
        {
            SendErrorResponse(header, Dns::Header::kResponseNotImplemented);
            error = kErrorNone;
        }

        ExitNow();
    }

    switch (mState)
    {
    case kStateConnectedButSessionless:
        // After connection is established, client should initiate
        // establishing session (by sending a request). So no rx is
        // allowed before this. On server, we allow rx of a request
        // message only.
        VerifyOrExit(IsServer() && (header.GetType() == Dns::Header::kTypeQuery) && (header.GetMessageId() != 0));
        break;

    case kStateEstablishingSession:
        // Unidirectional message are allowed after session is
        // established. While session is being established, on client,
        // we allow rx on response message. On server we can rx
        // request or response.

        VerifyOrExit(header.GetMessageId() != 0);

        if (IsClient())
        {
            VerifyOrExit(header.GetType() == Dns::Header::kTypeResponse);
        }
        break;

    case kStateSessionEstablished:
        // All message types are allowed.
        break;

    case kStateDisconnected:
    case kStateConnecting:
        ExitNow();
    }

    // All count fields MUST be set to zero in the header.
    VerifyOrExit((header.GetQuestionCount() == 0) && (header.GetAnswerCount() == 0) &&
                 (header.GetAuthorityRecordCount() == 0) && (header.GetAdditionalRecordCount() == 0));

    aMessage.SetOffset(sizeof(header));

    switch (ReadPrimaryTlv(aMessage, primaryTlvType))
    {
    case kErrorNone:
        VerifyOrExit(primaryTlvType != Tlv::kReservedType);
        break;

    case kErrorNotFound:
        // The `primaryTlvType` is set to `Tlv::kReservedType`
        // (value zero) to indicate that there is no primary TLV.
        break;

    default:
        ExitNow();
    }

    switch (header.GetType())
    {
    case Dns::Header::kTypeQuery:
        error = ProcessRequestOrUnidirectionalMessage(header, aMessage, primaryTlvType);
        break;

    case Dns::Header::kTypeResponse:
        error = ProcessResponseMessage(header, aMessage, primaryTlvType);
        break;
    }

exit:
    aMessage.Free();

    if (error == kErrorNone)
    {
        ResetTimeouts(/* aIsKeepAliveMessage */ (primaryTlvType == KeepAliveTlv::kType));
    }
    else
    {
        Disconnect(kForciblyAbort, kReasonPeerMisbehavior);
    }

    // We signal any state change at the very end when the received
    // message is fully processed (all state and local variables are
    // updated) to ensure that we do not have any reentrancy issues
    // (e.g., if a `Connection` method happens to be called from the
    // callback).

    SignalAnyStateChange();
}

Error Dso::Connection::ReadPrimaryTlv(const Message &aMessage, Tlv::Type &aPrimaryTlvType) const
{
    // Read and validate the primary TLV (first TLV  after the header).
    // The `aMessage.GetOffset()` must point to the first TLV. If no
    // TLV then `kErrorNotFound` is returned. If TLV in message is not
    // well-formed `kErrorParse` is returned. The read TLV type is
    // returned in `aPrimaryTlvType` (set to `Tlv::kReservedType`
    // (value zero) when `kErrorNotFound`).

    Error error = kErrorNotFound;
    Tlv   tlv;

    aPrimaryTlvType = Tlv::kReservedType;

    SuccessOrExit(aMessage.Read(aMessage.GetOffset(), tlv));
    VerifyOrExit(aMessage.GetOffset() + tlv.GetSize() <= aMessage.GetLength(), error = kErrorParse);
    aPrimaryTlvType = tlv.GetType();
    error           = kErrorNone;

exit:
    return error;
}

Error Dso::Connection::ProcessRequestOrUnidirectionalMessage(const Dns::Header &aHeader,
                                                             const Message &    aMessage,
                                                             Tlv::Type          aPrimaryTlvType)
{
    Error error = kErrorAbort;

    if (IsServer() && (mState == kStateConnectedButSessionless))
    {
        SetState(kStateEstablishingSession);
    }

    // A DSO request or unidirectional message MUST contain at
    // least one TLV which is the "Primary TLV" and determines
    // the nature of the operation being performed.

    switch (aPrimaryTlvType)
    {
    case KeepAliveTlv::kType:
        error = ProcessKeepAliveMessage(aHeader, aMessage);
        break;

    case RetryDelayTlv::kType:
        error = ProcessRetryDelayMessage(aHeader, aMessage);
        break;

    case Tlv::kReservedType:
    case EncryptionPaddingTlv::kType:
        // Misbehavior by peer.
        break;

    default:
        if (aHeader.GetMessageId() == 0)
        {
            LogInfo("Received unidirectional message from %s", mPeerSockAddr.ToString().AsCString());

            error = mCallbacks.mProcessUnidirectionalMessage(*this, aMessage, aPrimaryTlvType);
        }
        else
        {
            MessageId messageId = aHeader.GetMessageId();

            LogInfo("Received request message with id %u from %s", messageId, mPeerSockAddr.ToString().AsCString());

            error = mCallbacks.mProcessRequestMessage(*this, messageId, aMessage, aPrimaryTlvType);

            // `kErrorNotFound` indicates that TLV type is not known.

            if (error == kErrorNotFound)
            {
                SendErrorResponse(aHeader, Dns::Header::kDsoTypeNotImplemented);
                error = kErrorNone;
            }
        }
        break;
    }

    return error;
}

Error Dso::Connection::ProcessResponseMessage(const Dns::Header &aHeader,
                                              const Message &    aMessage,
                                              Tlv::Type          aPrimaryTlvType)
{
    Error     error = kErrorAbort;
    Tlv::Type requestPrimaryTlvType;

    // If a client or server receives a response where the message
    // ID is zero, or is any other value that does not match the
    // message ID of any of its outstanding operations, this is a
    // fatal error and the recipient MUST forcibly abort the
    // connection immediately.

    VerifyOrExit(aHeader.GetMessageId() != 0);
    VerifyOrExit(mPendingRequests.Contains(aHeader.GetMessageId(), requestPrimaryTlvType));

    // If the response has no error and contains a primary TLV, it
    // MUST match the request primary TLV.

    if ((aHeader.GetResponseCode() == Dns::Header::kResponseSuccess) && (aPrimaryTlvType != Tlv::kReservedType))
    {
        VerifyOrExit(aPrimaryTlvType == requestPrimaryTlvType);
    }

    mPendingRequests.Remove(aHeader.GetMessageId());

    switch (requestPrimaryTlvType)
    {
    case KeepAliveTlv::kType:
        SuccessOrExit(error = ProcessKeepAliveMessage(aHeader, aMessage));
        break;

    default:
        SuccessOrExit(error = mCallbacks.mProcessResponseMessage(*this, aHeader, aMessage, aPrimaryTlvType,
                                                                 requestPrimaryTlvType));
        break;
    }

    // DSO session is established when client sends a request message
    // and receives a response from server with no error code.

    if (IsClient() && (mState == kStateEstablishingSession) &&
        (aHeader.GetResponseCode() == Dns::Header::kResponseSuccess))
    {
        SetState(kStateSessionEstablished);
    }

exit:
    return error;
}

Error Dso::Connection::ProcessKeepAliveMessage(const Dns::Header &aHeader, const Message &aMessage)
{
    Error        error  = kErrorAbort;
    uint16_t     offset = aMessage.GetOffset();
    Tlv          tlv;
    KeepAliveTlv keepAliveTlv;

    if (aHeader.GetType() == Dns::Header::kTypeResponse)
    {
        // A Keep Alive response message is allowed on a client from a sever.

        VerifyOrExit(IsClient());

        if (aHeader.GetResponseCode() != Dns::Header::kResponseSuccess)
        {
            // We got an error response code from server for our
            // Keep Alive request message. If this happens while
            // establishing the DSO session, it indicates that server
            // does not support DSO, so we close the connection. If
            // this happens while session is already established, it
            // is a misbehavior (fatal error) by server.

            if (mState == kStateEstablishingSession)
            {
                Disconnect(kGracefullyClose, kReasonPeerDoesNotSupportDso);
                error = kErrorNone;
            }

            ExitNow();
        }
    }

    // Parse and validate the Keep Alive Message

    SuccessOrExit(aMessage.Read(offset, keepAliveTlv));
    offset += keepAliveTlv.GetSize();

    VerifyOrExit((keepAliveTlv.GetType() == KeepAliveTlv::kType) && keepAliveTlv.IsValid());

    // Keep Alive message MUST contain only one Keep Alive TLV.

    while (offset < aMessage.GetLength())
    {
        SuccessOrExit(aMessage.Read(offset, tlv));
        offset += tlv.GetSize();

        VerifyOrExit((tlv.GetType() != KeepAliveTlv::kType) && (tlv.GetType() != RetryDelayTlv::kType));
    }

    VerifyOrExit(offset == aMessage.GetLength());

    if (aHeader.GetType() == Dns::Header::kTypeQuery)
    {
        if (IsServer())
        {
            // Received a Keep Alive message from client. It MUST
            // be a request message (not unidirectional). We prepare
            // and send a Keep Alive response.

            VerifyOrExit(aHeader.GetMessageId() != 0);

            LogInfo("Received KeepAlive request message from client %s", mPeerSockAddr.ToString().AsCString());

            IgnoreError(SendKeepAliveMessage(kResponseMessage, aHeader.GetMessageId()));
            error = kErrorNone;
            ExitNow();
        }

        // Received a Keep Alive message on client from server. Server
        // Keep Alive message MUST be unidirectional (message ID
        // zero).

        VerifyOrExit(aHeader.GetMessageId() == 0);
    }

    LogInfo("Received Keep Alive %s message from server %s",
            (aHeader.GetMessageId() == 0) ? "unidirectional" : "response", mPeerSockAddr.ToString().AsCString());

    // Receiving a Keep Alive interval value from server less than the
    // minimum (ten seconds) is a fatal error and client MUST then
    // abort the connection.

    VerifyOrExit(keepAliveTlv.GetKeepAliveInterval() >= kMinKeepAliveInterval);

    // Update the timeout intervals on the connection from
    // the new values we got from the server. The receive
    // of the Keep Alive message does not itself reset the
    // inactivity timer. So we use `AdjustInactivityTimeout`
    // which takes into account the time elapsed since the
    // last activity.

    AdjustInactivityTimeout(keepAliveTlv.GetInactivityTimeout());
    mKeepAlive.SetInterval(keepAliveTlv.GetKeepAliveInterval());

    LogInfo("Timeouts Inactivity:%u, KeepAlive:%u", mInactivity.GetInterval(), mKeepAlive.GetInterval());

    error = kErrorNone;

exit:
    return error;
}

Error Dso::Connection::ProcessRetryDelayMessage(const Dns::Header &aHeader, const Message &aMessage)

{
    Error         error = kErrorAbort;
    RetryDelayTlv retryDelayTlv;

    // Retry Delay TLV can be used as the Primary TLV only in
    // a unidirectional message sent from server to client.
    // It is used by the server to instruct the client to
    // close the session and its underlying connection, and not
    // to reconnect for the indicated time interval.

    VerifyOrExit(IsClient() && (aHeader.GetMessageId() == 0));

    SuccessOrExit(aMessage.Read(aMessage.GetOffset(), retryDelayTlv));
    VerifyOrExit(retryDelayTlv.IsValid());

    mRetryDelayErrorCode = aHeader.GetResponseCode();
    mRetryDelay          = retryDelayTlv.GetRetryDelay();

    LogInfo("Received Retry Delay message from server %s", mPeerSockAddr.ToString().AsCString());
    LogInfo("   RetryDelay:%u ms, ResponseCode:%d", mRetryDelay, mRetryDelayErrorCode);

    Disconnect(kGracefullyClose, kReasonServerRetryDelayRequest);

exit:
    return error;
}

void Dso::Connection::SendErrorResponse(const Dns::Header &aHeader, Dns::Header::Response aResponseCode)
{
    Message *   response = NewMessage();
    Dns::Header header;

    VerifyOrExit(response != nullptr);

    header.SetMessageId(aHeader.GetMessageId());
    header.SetType(Dns::Header::kTypeResponse);
    header.SetQueryType(aHeader.GetQueryType());
    header.SetResponseCode(aResponseCode);

    SuccessOrExit(response->Prepend(header));

    otPlatDsoSend(this, response);
    response = nullptr;

exit:
    FreeMessage(response);
}

void Dso::Connection::AdjustInactivityTimeout(uint32_t aNewTimeout)
{
    // This method sets the inactivity timeout interval to a new value
    // and updates the expiration time based on the new timeout value.
    //
    // On client, it is called on receiving a Keep Alive response or
    // unidirectional message from server. Note that the receive of
    // the Keep Alive message does not itself reset the inactivity
    // timer. So the time elapsed since the last activity should be
    // taken into account with the new inactivity timeout value.
    //
    // On server this method is called from `SetTimeouts()` when a new
    // inactivity timeout value is set.

    TimeMilli now = TimerMilli::GetNow();
    TimeMilli start;
    TimeMilli newExpiration;

    if (mState == kStateDisconnected)
    {
        mInactivity.SetInterval(aNewTimeout);
        ExitNow();
    }

    VerifyOrExit(aNewTimeout != mInactivity.GetInterval());

    // Calculate the start time (i.e., the last time inactivity timer
    // was cleared). If the previous inactivity time is set to
    // `kInfinite` value (`IsUsed()` returns `false`) then
    // `GetExpirationTime()` returns the start time. Otherwise, we
    // calculate it going back from the current expiration time with
    // the current wait interval.

    if (!mInactivity.IsUsed())
    {
        start = mInactivity.GetExpirationTime();
    }
    else if (IsClient())
    {
        start = mInactivity.GetExpirationTime() - mInactivity.GetInterval();
    }
    else
    {
        start = mInactivity.GetExpirationTime() - CalculateServerInactivityWaitTime();
    }

    mInactivity.SetInterval(aNewTimeout);

    if (!mInactivity.IsUsed())
    {
        newExpiration = start;
    }
    else if (IsClient())
    {
        newExpiration = start + aNewTimeout;

        if (newExpiration < now)
        {
            newExpiration = now;
        }
    }
    else
    {
        newExpiration = start + CalculateServerInactivityWaitTime();

        if (newExpiration < now)
        {
            // If the server abruptly reduces the inactivity timeout
            // such that current elapsed time is already more than
            // twice the new inactivity timeout, then the client is
            // immediately considered delinquent (server can forcibly
            // abort the connection). So to give the client time to
            // close the connection gracefully, the server SHOULD
            // give the client an additional grace period of either
            // five seconds or one quarter of the new inactivity
            // timeout, whichever is greater [RFC 8490 - 7.1.1].

            newExpiration = now + OT_MAX(kMinServerInactivityWaitTime, aNewTimeout / 4);
        }
    }

    mInactivity.SetExpirationTime(newExpiration);

exit:
    return;
}

uint32_t Dso::Connection::CalculateServerInactivityWaitTime(void) const
{
    // A server will abort an idle session after five seconds
    // (`kMinServerInactivityWaitTime`) or twice the inactivity
    // timeout value, whichever is greater [RFC 8490 - 6.4.1].

    OT_ASSERT(mInactivity.IsUsed());

    return OT_MAX(mInactivity.GetInterval() * 2, kMinServerInactivityWaitTime);
}

void Dso::Connection::ResetTimeouts(bool aIsKeepAliveMessage)
{
    TimeMilli now = TimerMilli::GetNow();
    TimeMilli nextTime;

    // At both servers and clients, the generation or reception of any
    // complete DNS message resets both timers for that DSO
    // session, with the one exception being that a DSO Keep Alive
    // message resets only the keep alive timer, not the inactivity
    // timeout timer [RFC 8490 - 6.3]

    if (mKeepAlive.IsUsed())
    {
        // On client, we wait for the Keep Alive interval but on server
        // we wait for twice the interval before considering Keep Alive
        // timeout.
        //
        // Note that we limit the interval to `Timeout::kMaxInterval`
        // (which is ~12 days). This max limit ensures that even twice
        // the interval is less than max OpenThread timer duration so
        // that the expiration time calculations below stay within the
        // `TimerMilli` range.

        mKeepAlive.SetExpirationTime(now + mKeepAlive.GetInterval() * (IsServer() ? 2 : 1));
    }

    if (!aIsKeepAliveMessage)
    {
        if (mInactivity.IsUsed())
        {
            mInactivity.SetExpirationTime(
                now + (IsServer() ? CalculateServerInactivityWaitTime() : mInactivity.GetInterval()));
        }
        else
        {
            // When Inactivity timeout is not used (i.e., interval is set
            // to the special `kInfinite` value), we still need to track
            // the time so that if/when later the inactivity interval
            // gets changed, we can adjust the remaining time correctly
            // from `AdjustInactivityTimeout()`. In this case, we just
            // track the current time as "expiration time".

            mInactivity.SetExpirationTime(now);
        }
    }

    nextTime = GetNextFireTime(now);

    if (nextTime != now.GetDistantFuture())
    {
        Get<Dso>().mTimer.FireAtIfEarlier(nextTime);
    }
}

TimeMilli Dso::Connection::GetNextFireTime(TimeMilli aNow) const
{
    TimeMilli nextTime = aNow.GetDistantFuture();

    switch (mState)
    {
    case kStateDisconnected:
        break;

    case kStateConnecting:
        // While in `kStateConnecting`, Keep Alive timer is
        // used for `kConnectingTimeout`.
        VerifyOrExit(mKeepAlive.GetExpirationTime() > aNow, nextTime = aNow);
        nextTime = mKeepAlive.GetExpirationTime();
        break;

    case kStateConnectedButSessionless:
    case kStateEstablishingSession:
    case kStateSessionEstablished:
        nextTime = OT_MIN(nextTime, mPendingRequests.GetNextFireTime(aNow));

        if (mKeepAlive.IsUsed())
        {
            VerifyOrExit(mKeepAlive.GetExpirationTime() > aNow, nextTime = aNow);
            nextTime = OT_MIN(nextTime, mKeepAlive.GetExpirationTime());
        }

        if (mInactivity.IsUsed() && mPendingRequests.IsEmpty() && !mLongLivedOperation)
        {
            // An operation being active on a DSO Session includes
            // a request message waiting for a response, or an
            // active long-lived operation.

            VerifyOrExit(mInactivity.GetExpirationTime() > aNow, nextTime = aNow);
            nextTime = OT_MIN(nextTime, mInactivity.GetExpirationTime());
        }

        break;
    }

exit:
    return nextTime;
}

void Dso::Connection::HandleTimer(TimeMilli aNow, TimeMilli &aNextTime)
{
    switch (mState)
    {
    case kStateDisconnected:
        break;

    case kStateConnecting:
        if (mKeepAlive.IsExpired(aNow))
        {
            Disconnect(kGracefullyClose, kReasonFailedToConnect);
        }
        break;

    case kStateConnectedButSessionless:
    case kStateEstablishingSession:
    case kStateSessionEstablished:
        if (mPendingRequests.HasAnyTimedOut(aNow))
        {
            // If server sends no response to a request, client
            // waits for 30 seconds (`kResponseTimeout`) after which
            // client MUST forcibly abort the connection.
            Disconnect(kForciblyAbort, kReasonResponseTimeout);
            ExitNow();
        }

        // The inactivity timer is kept clear, while an operation is
        // active on the session (which includes a request waiting for
        // response or an active long-lived operation).

        if (mInactivity.IsUsed() && mPendingRequests.IsEmpty() && !mLongLivedOperation && mInactivity.IsExpired(aNow))
        {
            // On client, if the inactivity timeout is reached, the
            // connection is closed gracefully. On server, if too much
            // time (`CalculateServerInactivityWaitTime()`, i.e., five
            // seconds or twice the current inactivity timeout interval,
            // whichever is grater) elapses server MUST consider the
            // client delinquent and MUST forcibly abort the connection.

            Disconnect(IsClient() ? kGracefullyClose : kForciblyAbort, kReasonInactivityTimeout);
            ExitNow();
        }

        if (mKeepAlive.IsUsed() && mKeepAlive.IsExpired(aNow))
        {
            // On client, if the Keep Alive interval elapses without any
            // DNS messages being sent or received, the client MUST take
            // action and send a DSO Keep Alive message.
            //
            // On server, if twice the Keep Alive interval value elapses
            // without any messages being sent or received, the server
            // considers the client delinquent and aborts the connection.

            if (IsClient())
            {
                IgnoreError(SendKeepAliveMessage());
            }
            else
            {
                Disconnect(kForciblyAbort, kReasonKeepAliveTimeout);
                ExitNow();
            }
        }
        break;
    }

exit:
    aNextTime = OT_MIN(aNextTime, GetNextFireTime(aNow));
    SignalAnyStateChange();
}

const char *Dso::Connection::StateToString(State aState)
{
    static const char *const kStateStrings[] = {
        "Disconnected",            // (0) kStateDisconnected,
        "Connecting",              // (1) kStateConnecting,
        "ConnectedButSessionless", // (2) kStateConnectedButSessionless,
        "EstablishingSession",     // (3) kStateEstablishingSession,
        "SessionEstablished",      // (4) kStateSessionEstablished,
    };

    static_assert(0 == kStateDisconnected, "kStateDisconnected value is incorrect");
    static_assert(1 == kStateConnecting, "kStateConnecting value is incorrect");
    static_assert(2 == kStateConnectedButSessionless, "kStateConnectedButSessionless value is incorrect");
    static_assert(3 == kStateEstablishingSession, "kStateEstablishingSession value is incorrect");
    static_assert(4 == kStateSessionEstablished, "kStateSessionEstablished value is incorrect");

    return kStateStrings[aState];
}

const char *Dso::Connection::MessageTypeToString(MessageType aMessageType)
{
    static const char *const kMessageTypeStrings[] = {
        "Request",        // (0) kRequestMessage
        "Response",       // (1) kResponseMessage
        "Unidirectional", // (2) kUnidirectionalMessage
    };

    static_assert(0 == kRequestMessage, "kRequestMessage value is incorrect");
    static_assert(1 == kResponseMessage, "kResponseMessage value is incorrect");
    static_assert(2 == kUnidirectionalMessage, "kUnidirectionalMessage value is incorrect");

    return kMessageTypeStrings[aMessageType];
}

const char *Dso::Connection::DisconnectReasonToString(DisconnectReason aReason)
{
    static const char *const kDisconnectReasonStrings[] = {
        "FailedToConnect",         // (0) kReasonFailedToConnect
        "ResponseTimeout",         // (1) kReasonResponseTimeout
        "PeerDoesNotSupportDso",   // (2) kReasonPeerDoesNotSupportDso
        "PeerClosed",              // (3) kReasonPeerClosed
        "PeerAborted",             // (4) kReasonPeerAborted
        "InactivityTimeout",       // (5) kReasonInactivityTimeout
        "KeepAliveTimeout",        // (6) kReasonKeepAliveTimeout
        "ServerRetryDelayRequest", // (7) kReasonServerRetryDelayRequest
        "PeerMisbehavior",         // (8) kReasonPeerMisbehavior
        "Unknown",                 // (9) kReasonUnknown
    };

    static_assert(0 == kReasonFailedToConnect, "kReasonFailedToConnect value is incorrect");
    static_assert(1 == kReasonResponseTimeout, "kReasonResponseTimeout value is incorrect");
    static_assert(2 == kReasonPeerDoesNotSupportDso, "kReasonPeerDoesNotSupportDso value is incorrect");
    static_assert(3 == kReasonPeerClosed, "kReasonPeerClosed value is incorrect");
    static_assert(4 == kReasonPeerAborted, "kReasonPeerAborted value is incorrect");
    static_assert(5 == kReasonInactivityTimeout, "kReasonInactivityTimeout value is incorrect");
    static_assert(6 == kReasonKeepAliveTimeout, "kReasonKeepAliveTimeout value is incorrect");
    static_assert(7 == kReasonServerRetryDelayRequest, "kReasonServerRetryDelayRequest value is incorrect");
    static_assert(8 == kReasonPeerMisbehavior, "kReasonPeerMisbehavior value is incorrect");
    static_assert(9 == kReasonUnknown, "kReasonUnknown value is incorrect");

    return kDisconnectReasonStrings[aReason];
}

//---------------------------------------------------------------------------------------------------------------------
// Dso::Connection::PendingRequests

bool Dso::Connection::PendingRequests::Contains(MessageId aMessageId, Tlv::Type &aPrimaryTlvType) const
{
    bool         contains = true;
    const Entry *entry    = mRequests.FindMatching(aMessageId);

    VerifyOrExit(entry != nullptr, contains = false);
    aPrimaryTlvType = entry->mPrimaryTlvType;

exit:
    return contains;
}

Error Dso::Connection::PendingRequests::Add(MessageId aMessageId, Tlv::Type aPrimaryTlvType, TimeMilli aResponseTimeout)
{
    Error  error = kErrorNone;
    Entry *entry = mRequests.PushBack();

    VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
    entry->mMessageId      = aMessageId;
    entry->mPrimaryTlvType = aPrimaryTlvType;
    entry->mTimeout        = aResponseTimeout;

exit:
    return error;
}

void Dso::Connection::PendingRequests::Remove(MessageId aMessageId)
{
    Entry *entry = mRequests.FindMatching(aMessageId);
    Entry *lastEntry;

    VerifyOrExit(entry != nullptr);

    // Remove last entry from the `mRequests` array, if it is not the
    // `entry` we want to remove, replace `entry` with `lastEntry.

    lastEntry = mRequests.PopBack();
    VerifyOrExit(lastEntry != entry);
    *entry = *lastEntry;

exit:
    return;
}

bool Dso::Connection::PendingRequests::HasAnyTimedOut(TimeMilli aNow) const
{
    bool timedOut = false;

    for (const Entry &entry : mRequests)
    {
        if (entry.mTimeout <= aNow)
        {
            timedOut = true;
            break;
        }
    }

    return timedOut;
}

TimeMilli Dso::Connection::PendingRequests::GetNextFireTime(TimeMilli aNow) const
{
    TimeMilli nextTime = aNow.GetDistantFuture();

    for (const Entry &entry : mRequests)
    {
        VerifyOrExit(entry.mTimeout > aNow, nextTime = aNow);
        nextTime = OT_MIN(entry.mTimeout, nextTime);
    }

exit:
    return nextTime;
}

//---------------------------------------------------------------------------------------------------------------------
// Dso

Dso::Dso(Instance &aInstance)
    : InstanceLocator(aInstance)
    , mAcceptHandler(nullptr)
    , mTimer(aInstance, HandleTimer)
{
}

void Dso::StartListening(AcceptHandler aAcceptHandler)
{
    mAcceptHandler = aAcceptHandler;
    otPlatDsoEnableListening(&GetInstance(), true);
}

void Dso::StopListening(void)
{
    otPlatDsoEnableListening(&GetInstance(), false);
}

Dso::Connection *Dso::FindClientConnection(const Ip6::SockAddr &aPeerSockAddr)
{
    return mClientConnections.FindMatching(aPeerSockAddr);
}

Dso::Connection *Dso::FindServerConnection(const Ip6::SockAddr &aPeerSockAddr)
{
    return mServerConnections.FindMatching(aPeerSockAddr);
}

Dso::Connection *Dso::AcceptConnection(const Ip6::SockAddr &aPeerSockAddr)
{
    Connection *connection = nullptr;

    VerifyOrExit(mAcceptHandler != nullptr);
    connection = mAcceptHandler(GetInstance(), aPeerSockAddr);

    VerifyOrExit(connection != nullptr);
    connection->Accept();

exit:
    return connection;
}

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

void Dso::HandleTimer(void)
{
    TimeMilli   now      = TimerMilli::GetNow();
    TimeMilli   nextTime = now.GetDistantFuture();
    Connection *conn;
    Connection *next;

    for (conn = mClientConnections.GetHead(); conn != nullptr; conn = next)
    {
        next = conn->GetNext();
        conn->HandleTimer(now, nextTime);
    }

    for (conn = mServerConnections.GetHead(); conn != nullptr; conn = next)
    {
        next = conn->GetNext();
        conn->HandleTimer(now, nextTime);
    }

    if (nextTime != now.GetDistantFuture())
    {
        mTimer.FireAtIfEarlier(nextTime);
    }
}

} // namespace Dns
} // namespace ot

#endif // OPENTHREAD_CONFIG_DNS_DSO_ENABLE
