/*
 *
 *    Copyright (c) 2020-2021 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *  @file
 *    This file contains implementation of Device class. The objects of this
 *    class will be used by Controller applications to interact with CHIP
 *    devices. The class provides mechanism to construct, send and receive
 *    messages to and from the corresponding CHIP devices.
 */

#include <controller/CHIPDevice.h>

#include <controller-clusters/zap-generated/CHIPClusters.h>

#if CONFIG_DEVICE_LAYER
#include <platform/CHIPDeviceLayer.h>
#endif

#if CHIP_SYSTEM_CONFIG_USE_LWIP
#include <lwip/tcp.h>
#include <lwip/tcpip.h>
#endif // CHIP_SYSTEM_CONFIG_USE_LWIP

#include <app/CommandSender.h>
#include <app/ReadPrepareParams.h>
#include <app/util/DataModelHandler.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPEncoding.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/Base64.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ErrorStr.h>
#include <lib/support/PersistentStorageMacros.h>
#include <lib/support/SafeInt.h>
#include <lib/support/TypeTraits.h>
#include <lib/support/logging/CHIPLogging.h>
#include <protocols/Protocols.h>
#include <system/TLVPacketBufferBackingStore.h>
#include <transport/MessageCounter.h>
#include <transport/PeerMessageCounter.h>

using namespace chip::Inet;
using namespace chip::System;
using namespace chip::Callback;

namespace chip {
namespace Controller {
CHIP_ERROR Device::LoadSecureSessionParametersIfNeeded(bool & didLoad)
{
    didLoad = false;

    // If there is no secure connection to the device, try establishing it
    if (mState != ConnectionState::SecureConnected)
    {
        ReturnErrorOnFailure(LoadSecureSessionParameters());
        didLoad = true;
    }
    else
    {
        if (mSecureSession.HasValue())
        {
            Transport::SecureSession * secureSession = mSessionManager->GetSecureSession(mSecureSession.Value());
            // Check if the connection state has the correct transport information
            if (secureSession->GetPeerAddress().GetTransportType() == Transport::Type::kUndefined)
            {
                mState = ConnectionState::NotConnected;
                ReturnErrorOnFailure(LoadSecureSessionParameters());
                didLoad = true;
            }
        }
        else
        {
            mState = ConnectionState::NotConnected;
            ReturnErrorOnFailure(LoadSecureSessionParameters());
            didLoad = true;
        }
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR Device::SendCommands(app::CommandSender * commandObj)
{
    bool loadedSecureSession = false;
    ReturnErrorOnFailure(LoadSecureSessionParametersIfNeeded(loadedSecureSession));
    VerifyOrReturnError(mState == ConnectionState::SecureConnected, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(GetSecureSession().HasValue(), CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(commandObj != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    return commandObj->SendCommandRequest(mSecureSession.Value());
}

CHIP_ERROR Device::Serialize(SerializedDevice & output)
{
    SerializableDevice serializable;

    static_assert(BASE64_ENCODED_LEN(sizeof(serializable)) <= sizeof(output.inner),
                  "Size of serializable should be <= size of output");

    CHIP_ZERO_AT(serializable);
    CHIP_ZERO_AT(output);

    serializable.mOpsCreds    = mPairing;
    serializable.mDeviceId    = Encoding::LittleEndian::HostSwap64(mDeviceId);
    serializable.mDevicePort  = Encoding::LittleEndian::HostSwap16(mDeviceAddress.GetPort());
    serializable.mFabricIndex = Encoding::LittleEndian::HostSwap16(mFabricIndex);

    // The connection state could be null if the device is moving from PASE connection to CASE connection.
    // The device parameters (e.g. mDeviceOperationalCertProvisioned) are updated during this transition.
    // The state during this transistion is being persisted so that the next access of the device will
    // trigger the CASE based secure session.
    if (mSecureSession.HasValue())
    {
        Transport::SecureSession * secureSession = mSessionManager->GetSecureSession(mSecureSession.Value());
        const uint32_t localMessageCounter       = secureSession->GetSessionMessageCounter().GetLocalMessageCounter().Value();
        const uint32_t peerMessageCounter        = secureSession->GetSessionMessageCounter().GetPeerMessageCounter().GetCounter();

        serializable.mLocalMessageCounter = Encoding::LittleEndian::HostSwap32(localMessageCounter);
        serializable.mPeerMessageCounter  = Encoding::LittleEndian::HostSwap32(peerMessageCounter);
    }
    else
    {
        serializable.mLocalMessageCounter = 0;
        serializable.mPeerMessageCounter  = 0;
    }

    serializable.mDeviceOperationalCertProvisioned = (mDeviceOperationalCertProvisioned) ? 1 : 0;

    serializable.mDeviceTransport = to_underlying(mDeviceAddress.GetTransportType());

    ReturnErrorOnFailure(mDeviceAddress.GetInterface().GetInterfaceName(Uint8::to_char(serializable.mInterfaceName),
                                                                        sizeof(serializable.mInterfaceName)));
    static_assert(sizeof(serializable.mDeviceAddr) <= INET6_ADDRSTRLEN, "Size of device address must fit within INET6_ADDRSTRLEN");
    mDeviceAddress.GetIPAddress().ToString(Uint8::to_char(serializable.mDeviceAddr), sizeof(serializable.mDeviceAddr));

    const uint16_t serializedLen = chip::Base64Encode(Uint8::to_const_uchar(reinterpret_cast<uint8_t *>(&serializable)),
                                                      static_cast<uint16_t>(sizeof(serializable)), Uint8::to_char(output.inner));
    VerifyOrReturnError(serializedLen > 0, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(serializedLen < sizeof(output.inner), CHIP_ERROR_INVALID_ARGUMENT);
    output.inner[serializedLen] = '\0';

    return CHIP_NO_ERROR;
}

CHIP_ERROR Device::Deserialize(const SerializedDevice & input)
{
    SerializableDevice serializable;
    constexpr size_t maxlen = BASE64_ENCODED_LEN(sizeof(serializable));
    const size_t len        = strnlen(Uint8::to_const_char(&input.inner[0]), maxlen);

    VerifyOrReturnError(len < sizeof(SerializedDevice), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_INVALID_ARGUMENT);

    CHIP_ZERO_AT(serializable);
    const uint16_t deserializedLen = Base64Decode(Uint8::to_const_char(input.inner), static_cast<uint16_t>(len),
                                                  Uint8::to_uchar(reinterpret_cast<uint8_t *>(&serializable)));

    VerifyOrReturnError(deserializedLen > 0, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(deserializedLen <= sizeof(serializable), CHIP_ERROR_INVALID_ARGUMENT);

    // The second parameter to FromString takes the strlen value. We are subtracting 1
    // from the sizeof(serializable.mDeviceAddr) to account for null termination, since
    // strlen doesn't include null character in the size.
    Inet::IPAddress ipAddress = {};
    VerifyOrReturnError(
        IPAddress::FromString(Uint8::to_const_char(serializable.mDeviceAddr), sizeof(serializable.mDeviceAddr) - 1, ipAddress),
        CHIP_ERROR_INVALID_ADDRESS);

    mPairing             = serializable.mOpsCreds;
    mDeviceId            = Encoding::LittleEndian::HostSwap64(serializable.mDeviceId);
    const uint16_t port  = Encoding::LittleEndian::HostSwap16(serializable.mDevicePort);
    const uint16_t index = Encoding::LittleEndian::HostSwap16(serializable.mFabricIndex);
    mLocalMessageCounter = Encoding::LittleEndian::HostSwap32(serializable.mLocalMessageCounter);
    mPeerMessageCounter  = Encoding::LittleEndian::HostSwap32(serializable.mPeerMessageCounter);

    VerifyOrReturnError(CanCastTo<FabricIndex>(index), CHIP_ERROR_INVALID_ARGUMENT);
    mFabricIndex = static_cast<FabricIndex>(index);

    // TODO - Remove the hack that's incrementing message counter while deserializing device
    // This hack was added as a quick workaround for TE3 testing. The commissioning code
    // is closing the exchange after the device has already been serialized and persisted to the storage.
    // While closing the exchange, the outstanding ack gets sent to the device, thus incrementing
    // the local message counter. As the device information was stored prior to sending the ack, it now has
    // the old counter value (which is 1 less than the updated counter).
    mLocalMessageCounter++;

    mDeviceOperationalCertProvisioned = (serializable.mDeviceOperationalCertProvisioned != 0);

    // The InterfaceNameToId() API requires initialization of mInterface, and lock/unlock of
    // LwIP stack.
    Inet::InterfaceId interfaceId;
    if (serializable.mInterfaceName[0] != '\0')
    {
#if CHIP_SYSTEM_CONFIG_USE_LWIP
        LOCK_TCPIP_CORE();
#endif
        CHIP_ERROR inetErr = Inet::InterfaceId::InterfaceNameToId(Uint8::to_const_char(serializable.mInterfaceName), interfaceId);
#if CHIP_SYSTEM_CONFIG_USE_LWIP
        UNLOCK_TCPIP_CORE();
#endif
        ReturnErrorOnFailure(inetErr);
    }

    static_assert(std::is_same<std::underlying_type<decltype(mDeviceAddress.GetTransportType())>::type, uint8_t>::value,
                  "The underlying type of Transport::Type is not uint8_t.");
    switch (static_cast<Transport::Type>(serializable.mDeviceTransport))
    {
    case Transport::Type::kUdp:
        mDeviceAddress = Transport::PeerAddress::UDP(ipAddress, port, interfaceId);
        break;
    case Transport::Type::kBle:
        mDeviceAddress = Transport::PeerAddress::BLE();
        break;
    case Transport::Type::kTcp:
    case Transport::Type::kUndefined:
    default:
        return CHIP_ERROR_INTERNAL;
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR Device::Persist()
{
    CHIP_ERROR error = CHIP_NO_ERROR;
    if (mStorageDelegate != nullptr)
    {
        SerializedDevice serialized;
        ReturnErrorOnFailure(Serialize(serialized));

        // TODO: no need to base-64 the serialized values AGAIN
        PERSISTENT_KEY_OP(GetDeviceId(), kPairedDeviceKeyPrefix, key,
                          error = mStorageDelegate->SyncSetKeyValue(key, serialized.inner, sizeof(serialized.inner)));
        if (error != CHIP_NO_ERROR)
        {
            ChipLogError(Controller, "Failed to persist device %" CHIP_ERROR_FORMAT, error.Format());
        }
    }
    return error;
}

void Device::OnNewConnection(SessionHandle session)
{
    // Only allow update if the session has been initialized and matches
    if (mSecureSession.HasValue() && !MatchesSession(session))
    {
        return;
    }

    mState = ConnectionState::SecureConnected;
    mSecureSession.SetValue(session);

    // Reset the message counters here because this is the first time we get a handle to the secure session.
    // Since CHIPDevices can be serialized/deserialized in the middle of what is conceptually a single PASE session
    // we need to restore the session counters along with the session information.
    Transport::SecureSession * secureSession = mSessionManager->GetSecureSession(mSecureSession.Value());
    VerifyOrReturn(secureSession != nullptr);
    MessageCounter & localCounter = secureSession->GetSessionMessageCounter().GetLocalMessageCounter();
    if (localCounter.SetCounter(mLocalMessageCounter) != CHIP_NO_ERROR)
    {
        ChipLogError(Controller, "Unable to restore local counter to %" PRIu32, mLocalMessageCounter);
    }
    Transport::PeerMessageCounter & peerCounter = secureSession->GetSessionMessageCounter().GetPeerMessageCounter();
    peerCounter.SetCounter(mPeerMessageCounter);
}

void Device::OnConnectionExpired(SessionHandle session)
{
    VerifyOrReturn(mSecureSession.HasValue() && mSecureSession.Value() == session,
                   ChipLogDetail(Controller, "Connection expired, but it doesn't match the current session"));
    mState = ConnectionState::NotConnected;
    mSecureSession.ClearValue();
}

CHIP_ERROR Device::OnMessageReceived(Messaging::ExchangeContext * exchange, const PayloadHeader & payloadHeader,
                                     System::PacketBufferHandle && msgBuf)
{
    if (mState == ConnectionState::SecureConnected)
    {
        if (mStatusDelegate != nullptr)
        {
            mStatusDelegate->OnMessage(std::move(msgBuf));
        }
        else
        {
            HandleDataModelMessage(exchange, std::move(msgBuf));
        }
    }
    return CHIP_NO_ERROR;
}

void Device::OnResponseTimeout(Messaging::ExchangeContext * ec) {}

void Device::OnOpenPairingWindowSuccessResponse(void * context)
{
    ChipLogProgress(Controller, "Successfully opened pairing window on the device");
    Device * device = reinterpret_cast<Device *>(context);
    if (device->mCommissioningWindowCallback != nullptr)
    {
        device->mCommissioningWindowCallback->mCall(device->mCommissioningWindowCallback->mContext, device->GetDeviceId(),
                                                    CHIP_NO_ERROR, device->mSetupPayload);
    }
}

void Device::OnOpenPairingWindowFailureResponse(void * context, uint8_t status)
{
    ChipLogError(Controller, "Failed to open pairing window on the device. Status %d", status);
    Device * device = reinterpret_cast<Device *>(context);
    if (device->mCommissioningWindowCallback != nullptr)
    {
        CHIP_ERROR error = CHIP_ERROR_INVALID_PASE_PARAMETER;
        // TODO - Use cluster enum chip::app::Clusters::AdministratorCommissioning::StatusCode::kBusy
        if (status == 1)
        {
            error = CHIP_ERROR_ANOTHER_COMMISSIONING_IN_PROGRESS;
        }
        device->mCommissioningWindowCallback->mCall(device->mCommissioningWindowCallback->mContext, device->GetDeviceId(), error,
                                                    SetupPayload());
    }
}

CHIP_ERROR Device::ComputePASEVerifier(uint32_t iterations, uint32_t setupPincode, const ByteSpan & salt,
                                       PASEVerifier & outVerifier, uint32_t & outPasscodeId)
{
    ReturnErrorOnFailure(PASESession::GeneratePASEVerifier(outVerifier, iterations, salt, /* useRandomPIN= */ false, setupPincode));

    outPasscodeId = mPAKEVerifierID++;
    return CHIP_NO_ERROR;
}

CHIP_ERROR Device::OpenCommissioningWindow(uint16_t timeout, uint32_t iteration, CommissioningWindowOption option,
                                           const ByteSpan & salt, Callback::Callback<OnOpenCommissioningWindow> * callback,
                                           SetupPayload & setupPayload)
{
    constexpr EndpointId kAdministratorCommissioningClusterEndpoint = 0;

    chip::Controller::AdministratorCommissioningCluster cluster;
    cluster.Associate(this, kAdministratorCommissioningClusterEndpoint);

    Callback::Cancelable * successCallback = mOpenPairingSuccessCallback.Cancel();
    Callback::Cancelable * failureCallback = mOpenPairingFailureCallback.Cancel();

    mCommissioningWindowCallback = callback;
    if (option != CommissioningWindowOption::kOriginalSetupCode)
    {
        bool randomSetupPIN = (option == CommissioningWindowOption::kTokenWithRandomPIN);
        PASEVerifier verifier;

        ReturnErrorOnFailure(
            PASESession::GeneratePASEVerifier(verifier, iteration, salt, randomSetupPIN, setupPayload.setUpPINCode));

        uint8_t serializedVerifier[2 * kSpake2p_WS_Length];
        VerifyOrReturnError(sizeof(serializedVerifier) == sizeof(verifier), CHIP_ERROR_INTERNAL);

        memcpy(serializedVerifier, verifier.mW0, kSpake2p_WS_Length);
        memcpy(&serializedVerifier[kSpake2p_WS_Length], verifier.mL, kSpake2p_WS_Length);

        ReturnErrorOnFailure(cluster.OpenCommissioningWindow(successCallback, failureCallback, timeout,
                                                             ByteSpan(serializedVerifier, sizeof(serializedVerifier)),
                                                             setupPayload.discriminator, iteration, salt, mPAKEVerifierID++));
    }
    else
    {
        ReturnErrorOnFailure(cluster.OpenBasicCommissioningWindow(successCallback, failureCallback, timeout));
    }

    setupPayload.version               = 0;
    setupPayload.rendezvousInformation = RendezvousInformationFlags(RendezvousInformationFlag::kOnNetwork);

    mSetupPayload = setupPayload;

    return CHIP_NO_ERROR;
}

CHIP_ERROR Device::OpenPairingWindow(uint16_t timeout, CommissioningWindowOption option, SetupPayload & setupPayload)
{
    ByteSpan salt(reinterpret_cast<const uint8_t *>(kSpake2pKeyExchangeSalt), strlen(kSpake2pKeyExchangeSalt));

    return OpenCommissioningWindow(timeout, kPBKDFMinimumIterations, option, salt, nullptr, setupPayload);
}

void Device::UpdateSession(bool connected)
{
    SessionHandle session =
        SessionHandle(mDeviceId, mCASESession.GetLocalSessionId(), mCASESession.GetPeerSessionId(), mFabricIndex);
    if (connected)
    {
        OnNewConnection(session);
    }
    else
    {
        OnConnectionExpired(session);
    }
}

CHIP_ERROR Device::CloseSession()
{
    ReturnErrorCodeIf(mState != ConnectionState::SecureConnected, CHIP_ERROR_INCORRECT_STATE);
    if (mSecureSession.HasValue())
    {
        mSessionManager->ExpirePairing(mSecureSession.Value());
    }
    mState = ConnectionState::NotConnected;
    return CHIP_NO_ERROR;
}

CHIP_ERROR Device::UpdateAddress(const Transport::PeerAddress & addr)
{
    bool didLoad;

    mDeviceAddress = addr;

    ReturnErrorOnFailure(LoadSecureSessionParametersIfNeeded(didLoad));

    if (!mSecureSession.HasValue())
    {
        // Nothing needs to be done here.  It's not an error to not have a
        // secureSession.  For one thing, we could have gotten an different
        // UpdateAddress already and that caused connections to be torn down and
        // whatnot.
        return CHIP_NO_ERROR;
    }

    Transport::SecureSession * secureSession = mSessionManager->GetSecureSession(mSecureSession.Value());
    secureSession->SetPeerAddress(addr);

    return CHIP_NO_ERROR;
}

void Device::Reset()
{
    if (IsActive() && mStorageDelegate != nullptr && mSessionManager != nullptr)
    {
        // If a session can be found, persist the device so that we track the newest message counter values

        if (mSecureSession.HasValue())
        {
            Persist();
        }
    }

    SetActive(false);
    mCASESession.Clear();

    mState          = ConnectionState::NotConnected;
    mSessionManager = nullptr;
    mStatusDelegate = nullptr;
    mInetLayer      = nullptr;
#if CONFIG_NETWORK_LAYER_BLE
    mBleLayer = nullptr;
#endif
    if (mExchangeMgr)
    {
        // Ensure that any exchange contexts we have open get closed now,
        // because we don't want them to call back in to us after this
        // point.
        mExchangeMgr->CloseAllContextsForDelegate(this);
    }
    mExchangeMgr = nullptr;

    ReleaseDAC();
    ReleasePAI();
}

CHIP_ERROR Device::LoadSecureSessionParameters()
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    PASESession pairingSession;

    if (mSessionManager == nullptr || mState == ConnectionState::SecureConnected)
    {
        ExitNow(err = CHIP_ERROR_INCORRECT_STATE);
    }

    if (mState == ConnectionState::Connecting)
    {
        ExitNow(err = CHIP_NO_ERROR);
    }

    if (IsOperationalCertProvisioned())
    {
        err = WarmupCASESession();
        SuccessOrExit(err);
    }
    else
    {
        err = pairingSession.FromSerializable(mPairing);
        SuccessOrExit(err);

        err = mSessionManager->NewPairing(Optional<Transport::PeerAddress>::Value(mDeviceAddress), mDeviceId, &pairingSession,
                                          CryptoContext::SessionRole::kInitiator, mFabricIndex);
        SuccessOrExit(err);
    }

exit:

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Controller, "LoadSecureSessionParameters returning error %" CHIP_ERROR_FORMAT, err.Format());
    }
    return err;
}

bool Device::GetAddress(Inet::IPAddress & addr, uint16_t & port) const
{
    if (mState == ConnectionState::NotConnected)
        return false;

    addr = mDeviceAddress.GetIPAddress();
    port = mDeviceAddress.GetPort();
    return true;
}

void Device::OperationalCertProvisioned()
{
    VerifyOrReturn(!mDeviceOperationalCertProvisioned,
                   ChipLogDetail(Controller, "Operational certificates already provisioned for this device"));

    ChipLogDetail(Controller, "Enabling CASE session establishment for the device");
    mDeviceOperationalCertProvisioned = true;

    Persist();
    CloseSession();
    mState = ConnectionState::NotConnected;
}

CHIP_ERROR Device::WarmupCASESession()
{
    VerifyOrReturnError(mDeviceOperationalCertProvisioned, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(mState == ConnectionState::NotConnected, CHIP_NO_ERROR);

    // Create a UnauthenticatedSession for CASE pairing.
    // Don't use mSecureSession here, because mSecureSession is the secure session.
    Optional<SessionHandle> session = mSessionManager->CreateUnauthenticatedSession(mDeviceAddress);
    if (!session.HasValue())
    {
        return CHIP_ERROR_NO_MEMORY;
    }
    Messaging::ExchangeContext * exchange = mExchangeMgr->NewContext(session.Value(), &mCASESession);
    VerifyOrReturnError(exchange != nullptr, CHIP_ERROR_INTERNAL);

    ReturnErrorOnFailure(mCASESession.MessageDispatch().Init(mSessionManager));

    uint16_t keyID = 0;
    ReturnErrorOnFailure(mIDAllocator->Allocate(keyID));

    mLocalMessageCounter = 0;
    mPeerMessageCounter  = 0;

    FabricInfo * fabric = mFabricsTable->FindFabricWithIndex(mFabricIndex);
    ReturnErrorCodeIf(fabric == nullptr, CHIP_ERROR_INCORRECT_STATE);

    ReturnErrorOnFailure(mCASESession.EstablishSession(mDeviceAddress, fabric, mDeviceId, keyID, exchange, this));

    mState = ConnectionState::Connecting;

    return CHIP_NO_ERROR;
}

void Device::OnSessionEstablishmentError(CHIP_ERROR error)
{
    mState = ConnectionState::NotConnected;
    mIDAllocator->Free(mCASESession.GetLocalSessionId());

    Cancelable ready;
    mConnectionFailure.DequeueAll(ready);
    while (ready.mNext != &ready)
    {
        Callback::Callback<OnDeviceConnectionFailure> * cb =
            Callback::Callback<OnDeviceConnectionFailure>::FromCancelable(ready.mNext);

        cb->Cancel();
        cb->mCall(cb->mContext, GetDeviceId(), error);
    }
}

void Device::OnSessionEstablished()
{
    CHIP_ERROR err = mSessionManager->NewPairing(Optional<Transport::PeerAddress>::Value(mDeviceAddress), mDeviceId, &mCASESession,
                                                 CryptoContext::SessionRole::kInitiator, mFabricIndex);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Controller, "Failed in setting up CASE secure channel: err %s", ErrorStr(err));
        OnSessionEstablishmentError(err);
        return;
    }

    Cancelable ready;
    mConnectionSuccess.DequeueAll(ready);
    while (ready.mNext != &ready)
    {
        Callback::Callback<OnDeviceConnected> * cb = Callback::Callback<OnDeviceConnected>::FromCancelable(ready.mNext);

        cb->Cancel();
        cb->mCall(cb->mContext, this);
    }
}

void Device::ReleaseDAC()
{
    if (mDAC != nullptr)
    {
        Platform::MemoryFree(mDAC);
    }
    mDACLen = 0;
    mDAC    = nullptr;
}

CHIP_ERROR Device::SetDAC(const ByteSpan & dac)
{
    if (dac.size() == 0)
    {
        ReleaseDAC();
        return CHIP_NO_ERROR;
    }

    VerifyOrReturnError(dac.size() <= Credentials::kMaxDERCertLength, CHIP_ERROR_INVALID_ARGUMENT);
    if (mDACLen != 0)
    {
        ReleaseDAC();
    }

    VerifyOrReturnError(CanCastTo<uint16_t>(dac.size()), CHIP_ERROR_INVALID_ARGUMENT);
    if (mDAC == nullptr)
    {
        mDAC = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(dac.size()));
    }
    VerifyOrReturnError(mDAC != nullptr, CHIP_ERROR_NO_MEMORY);
    mDACLen = static_cast<uint16_t>(dac.size());
    memcpy(mDAC, dac.data(), mDACLen);

    return CHIP_NO_ERROR;
}

void Device::ReleasePAI()
{
    if (mPAI != nullptr)
    {
        chip::Platform::MemoryFree(mPAI);
    }
    mPAILen = 0;
    mPAI    = nullptr;
}

CHIP_ERROR Device::SetPAI(const chip::ByteSpan & pai)
{
    if (pai.size() == 0)
    {
        ReleasePAI();
        return CHIP_NO_ERROR;
    }

    VerifyOrReturnError(pai.size() <= Credentials::kMaxDERCertLength, CHIP_ERROR_INVALID_ARGUMENT);
    if (mPAILen != 0)
    {
        ReleasePAI();
    }

    VerifyOrReturnError(CanCastTo<uint16_t>(pai.size()), CHIP_ERROR_INVALID_ARGUMENT);
    if (mPAI == nullptr)
    {
        mPAI = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(pai.size()));
    }
    VerifyOrReturnError(mPAI != nullptr, CHIP_ERROR_NO_MEMORY);
    mPAILen = static_cast<uint16_t>(pai.size());
    memcpy(mPAI, pai.data(), mPAILen);

    return CHIP_NO_ERROR;
}

CHIP_ERROR Device::EstablishConnectivity(Callback::Callback<OnDeviceConnected> * onConnection,
                                         Callback::Callback<OnDeviceConnectionFailure> * onFailure)
{
    bool loadedSecureSession = false;
    ReturnErrorOnFailure(LoadSecureSessionParametersIfNeeded(loadedSecureSession));

    if (loadedSecureSession)
    {
        if (IsOperationalCertProvisioned())
        {
            if (onConnection != nullptr)
            {
                mConnectionSuccess.Enqueue(onConnection->Cancel());
            }

            if (onFailure != nullptr)
            {
                mConnectionFailure.Enqueue(onFailure->Cancel());
            }
        }
        else
        {
            if (onConnection != nullptr)
            {
                onConnection->mCall(onConnection->mContext, this);
            }
        }
    }

    return CHIP_NO_ERROR;
}

void Device::AddIMResponseHandler(void * commandObj, Callback::Cancelable * onSuccessCallback,
                                  Callback::Cancelable * onFailureCallback, app::TLVDataFilter tlvDataFilter)
{
    // Interaction model uses the object instead of a sequence number as the identifier of transactions.
    // Since the objects can be identified by its pointer which fits into a uint64 value (the type of NodeId), we use it for the
    // "node id" field in callback manager.
    static_assert(std::is_same<chip::NodeId, uint64_t>::value, "chip::NodeId is not uint64_t");
    chip::NodeId transactionId = reinterpret_cast<chip::NodeId>(commandObj);
    mCallbacksMgr.AddResponseCallback(transactionId, 0 /* seqNum, always 0 for IM before #6559 */, onSuccessCallback,
                                      onFailureCallback, tlvDataFilter);
}

void Device::CancelIMResponseHandler(void * commandObj)
{
    // Interaction model uses the object instead of a sequence number as the identifier of transactions.
    // Since the objects can be identified by its pointer which fits into a uint64 value (the type of NodeId), we use it for the
    // "node id" field in callback manager.
    static_assert(std::is_same<chip::NodeId, uint64_t>::value, "chip::NodeId is not uint64_t");
    chip::NodeId transactionId = reinterpret_cast<chip::NodeId>(commandObj);
    mCallbacksMgr.CancelResponseCallback(transactionId, 0 /* seqNum, always 0 for IM before #6559 */);
}

void Device::AddReportHandler(EndpointId endpoint, ClusterId cluster, AttributeId attribute,
                              Callback::Cancelable * onReportCallback, app::TLVDataFilter tlvDataFilter)
{
    mCallbacksMgr.AddReportCallback(mDeviceId, endpoint, cluster, attribute, onReportCallback, tlvDataFilter);
}

CHIP_ERROR Device::SendReadAttributeRequest(app::AttributePathParams aPath, Callback::Cancelable * onSuccessCallback,
                                            Callback::Cancelable * onFailureCallback, app::TLVDataFilter aTlvDataFilter)
{
    bool loadedSecureSession = false;

    ReturnErrorOnFailure(LoadSecureSessionParametersIfNeeded(loadedSecureSession));
    VerifyOrReturnError(mState == ConnectionState::SecureConnected, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(GetSecureSession().HasValue(), CHIP_ERROR_INCORRECT_STATE);

    app::ReadClient * readClient = nullptr;
    ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->NewReadClient(
        &readClient, app::ReadClient::InteractionType::Read, mpIMDelegate));

    if (onSuccessCallback != nullptr || onFailureCallback != nullptr)
    {
        AddIMResponseHandler(readClient, onSuccessCallback, onFailureCallback, aTlvDataFilter);
    }
    // The application context is used to identify different requests from client application the type of it is intptr_t, here we
    // use the seqNum.
    chip::app::ReadPrepareParams readPrepareParams(mSecureSession.Value());
    readPrepareParams.mpAttributePathParamsList    = &aPath;
    readPrepareParams.mAttributePathParamsListSize = 1;

    CHIP_ERROR err = readClient->SendReadRequest(readPrepareParams);
    if (err != CHIP_NO_ERROR)
    {
        CancelIMResponseHandler(readClient);
    }
    return err;
}

CHIP_ERROR Device::SendSubscribeAttributeRequest(app::AttributePathParams aPath, uint16_t mMinIntervalFloorSeconds,
                                                 uint16_t mMaxIntervalCeilingSeconds, Callback::Cancelable * onSuccessCallback,
                                                 Callback::Cancelable * onFailureCallback)
{
    bool loadedSecureSession = false;

    ReturnErrorOnFailure(LoadSecureSessionParametersIfNeeded(loadedSecureSession));

    app::ReadClient * readClient = nullptr;
    ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->NewReadClient(
        &readClient, app::ReadClient::InteractionType::Subscribe, mpIMDelegate));

    app::AttributePathParams * path = mpIMDelegate->AllocateAttributePathParam(1, reinterpret_cast<uint64_t>(readClient));

    VerifyOrReturnError(path != nullptr, CHIP_ERROR_NO_MEMORY);

    *path = aPath;

    // The application context is used to identify different requests from client application the type of it is intptr_t, here we
    // use the seqNum.
    VerifyOrReturnError(GetSecureSession().HasValue(), CHIP_ERROR_INCORRECT_STATE);
    app::ReadPrepareParams params(GetSecureSession().Value());
    params.mpAttributePathParamsList    = path;
    params.mAttributePathParamsListSize = 1;
    params.mMinIntervalFloorSeconds     = mMinIntervalFloorSeconds;
    params.mMaxIntervalCeilingSeconds   = mMaxIntervalCeilingSeconds;
    params.mKeepSubscriptions           = false;

    CHIP_ERROR err = readClient->SendSubscribeRequest(params);
    if (err != CHIP_NO_ERROR)
    {
        mpIMDelegate->FreeAttributePathParam(reinterpret_cast<uint64_t>(readClient));
        readClient->Shutdown();
        return err;
    }

    if (onSuccessCallback != nullptr || onFailureCallback != nullptr)
    {
        AddIMResponseHandler(readClient, onSuccessCallback, onFailureCallback);
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR Device::ShutdownSubscriptions()
{
    return app::InteractionModelEngine::GetInstance()->ShutdownSubscriptions(mFabricIndex, mDeviceId);
}

CHIP_ERROR Device::SendWriteAttributeRequest(app::WriteClientHandle aHandle, Callback::Cancelable * onSuccessCallback,
                                             Callback::Cancelable * onFailureCallback)
{
    bool loadedSecureSession = false;
    CHIP_ERROR err           = CHIP_NO_ERROR;

    ReturnErrorOnFailure(LoadSecureSessionParametersIfNeeded(loadedSecureSession));
    VerifyOrReturnError(mState == ConnectionState::SecureConnected, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(GetSecureSession().HasValue(), CHIP_ERROR_INCORRECT_STATE);

    app::WriteClient * writeClient = aHandle.Get();

    if (onSuccessCallback != nullptr || onFailureCallback != nullptr)
    {
        AddIMResponseHandler(writeClient, onSuccessCallback, onFailureCallback);
    }
    if ((err = aHandle.SendWriteRequest(mSecureSession.Value())) != CHIP_NO_ERROR)
    {
        CancelIMResponseHandler(writeClient);
    }
    return err;
}

Device::~Device()
{
    if (mExchangeMgr)
    {
        // Ensure that any exchange contexts we have open get closed now,
        // because we don't want them to call back in to us after this
        // point.
        mExchangeMgr->CloseAllContextsForDelegate(this);
    }

    ReleaseDAC();
    ReleasePAI();
}

CHIP_ERROR Device::SetNOCCertBufferSize(size_t new_size)
{
    ReturnErrorCodeIf(new_size > sizeof(mNOCCertBuffer), CHIP_ERROR_INVALID_ARGUMENT);
    mNOCCertBufferSize = new_size;
    return CHIP_NO_ERROR;
}

CHIP_ERROR Device::SetICACertBufferSize(size_t new_size)
{
    ReturnErrorCodeIf(new_size > sizeof(mICACertBuffer), CHIP_ERROR_INVALID_ARGUMENT);
    mICACertBufferSize = new_size;
    return CHIP_NO_ERROR;
}

} // namespace Controller
} // namespace chip
