/*
 *
 *    Copyright (c) 2020-2025 Project CHIP Authors
 *    Copyright (c) 2013-2018 Nest Labs, Inc.
 *
 *    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 implements the <tt>Inet::TCPEndPoint</tt> class,
 *      where the CHIP Inet Layer encapsulates methods for interacting
 *      with TCP transport endpoints (SOCK_DGRAM sockets on Linux and
 *      BSD-derived systems) or LwIP TCP protocol control blocks, as
 *      the system is configured accordingly.
 *
 */

#include <inet/TCPEndPoint.h>

#include <inet/InetFaultInjection.h>
#include <inet/arpa-inet-compatibility.h>

#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <lib/support/logging/CHIPLogging.h>
#include <system/SystemFaultInjection.h>

#include <stdio.h>
#include <string.h>
#include <utility>

namespace chip {
namespace Inet {

CHIP_ERROR TCPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uint16_t port, bool reuseAddr)
{
    VerifyOrReturnError(mState == State::kReady, CHIP_ERROR_INCORRECT_STATE);
    CHIP_ERROR res = CHIP_NO_ERROR;

    if (addr != IPAddress::Any && addr.Type() != IPAddressType::kAny && addr.Type() != addrType)
    {
        return INET_ERROR_WRONG_ADDRESS_TYPE;
    }

    res = BindImpl(addrType, addr, port, reuseAddr);

    if (res == CHIP_NO_ERROR)
    {
        mState = State::kBound;
    }

    return res;
}

CHIP_ERROR TCPEndPoint::Listen(uint16_t backlog)
{
    VerifyOrReturnError(mState == State::kBound, CHIP_ERROR_INCORRECT_STATE);
    CHIP_ERROR res = CHIP_NO_ERROR;

    res = ListenImpl(backlog);

    if (res == CHIP_NO_ERROR)
    {
        mState = State::kListening;
    }

    return res;
}

CHIP_ERROR TCPEndPoint::Connect(const IPAddress & addr, uint16_t port, InterfaceId intfId)
{
    VerifyOrReturnError(mState == State::kReady || mState == State::kBound, CHIP_ERROR_INCORRECT_STATE);
    CHIP_ERROR res = CHIP_NO_ERROR;

    ReturnErrorOnFailure(ConnectImpl(addr, port, intfId));

    StartConnectTimerIfSet();

    return res;
}

CHIP_ERROR TCPEndPoint::Send(System::PacketBufferHandle && data, bool push)
{
    VerifyOrReturnError(mState == State::kConnected || mState == State::kReceiveShutdown, CHIP_ERROR_INCORRECT_STATE);
    CHIP_ERROR res = CHIP_NO_ERROR;

    bool queueWasEmpty = mSendQueue.IsNull();
    if (queueWasEmpty)
    {
        mSendQueue = std::move(data);
    }
    else
    {
        mSendQueue->AddToEnd(std::move(data));
    }

    ReturnErrorOnFailure(SendQueuedImpl(queueWasEmpty));

    if (push)
    {
        res = DriveSending();
    }

    return res;
}

CHIP_ERROR TCPEndPoint::SetReceivedDataForTesting(System::PacketBufferHandle && data)
{
    VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);

    mRcvQueue = std::move(data);

    return CHIP_NO_ERROR;
}

size_t TCPEndPoint::PendingSendLength()
{
    if (!mSendQueue.IsNull())
    {
        return mSendQueue->TotalLength();
    }
    return 0;
}

size_t TCPEndPoint::PendingReceiveLength()
{
    if (!mRcvQueue.IsNull())
    {
        return mRcvQueue->TotalLength();
    }
    return 0;
}

void TCPEndPoint::Shutdown()
{
    VerifyOrReturn(IsConnected());

    // If fully connected, enter the SendShutdown state.
    if (mState == State::kConnected)
    {
        mState = State::kSendShutdown;
        TEMPORARY_RETURN_IGNORED DriveSending();
    }

    // Otherwise, if the peer has already closed their end of the connection,
    else if (mState == State::kReceiveShutdown)
    {
        DoClose(CHIP_NO_ERROR, false);
    }
}

void TCPEndPoint::Close()
{
    // Clear the receive queue.
    mRcvQueue = nullptr;

    // Suppress closing callbacks, since the application explicitly called Close().
    OnConnectionClosed = nullptr;
    OnPeerClose        = nullptr;
    OnConnectComplete  = nullptr;

    // Perform a graceful close.
    DoClose(CHIP_NO_ERROR, true);
}

void TCPEndPoint::Abort()
{
    // Suppress closing callbacks, since the application explicitly called Abort().
    OnConnectionClosed = nullptr;
    OnPeerClose        = nullptr;
    OnConnectComplete  = nullptr;

    DoClose(CHIP_ERROR_CONNECTION_ABORTED, true);
}

void TCPEndPoint::Free()
{
    // Ensure no callbacks to the app after this point.
    OnAcceptError        = nullptr;
    OnConnectComplete    = nullptr;
    OnConnectionReceived = nullptr;
    OnConnectionClosed   = nullptr;
    OnPeerClose          = nullptr;
    OnDataReceived       = nullptr;
    OnDataSent           = nullptr;

    // Ensure the end point is Closed or Closing.
    Close();

    Delete();
}

#if INET_TCP_IDLE_CHECK_INTERVAL > 0
void TCPEndPoint::SetIdleTimeout(uint32_t timeoutMS)
{
    uint32_t newIdleTimeout = (timeoutMS + (INET_TCP_IDLE_CHECK_INTERVAL - 1)) / INET_TCP_IDLE_CHECK_INTERVAL;
    bool isIdleTimerRunning = IsIdleTimerRunning(GetEndPointManager());

    if (newIdleTimeout > UINT16_MAX)
    {
        newIdleTimeout = UINT16_MAX;
    }
    mIdleTimeout = mRemainingIdleTime = static_cast<uint16_t>(newIdleTimeout);

    if (!isIdleTimerRunning && mIdleTimeout)
    {
        TEMPORARY_RETURN_IGNORED GetSystemLayer().StartTimer(System::Clock::Milliseconds32(INET_TCP_IDLE_CHECK_INTERVAL),
                                                             HandleIdleTimer, &GetEndPointManager());
    }
}

// static
void TCPEndPoint::HandleIdleTimer(chip::System::Layer * aSystemLayer, void * aAppState)
{
    auto & endPointManager = *reinterpret_cast<EndPointManager<TCPEndPoint> *>(aAppState);
    bool lTimerRequired    = IsIdleTimerRunning(endPointManager);

    endPointManager.ForEachEndPoint([](const TCPEndPointHandle & lEndPoint) -> Loop {
        if (!lEndPoint->IsConnected())
            return Loop::Continue;
        if (lEndPoint->mIdleTimeout == 0)
            return Loop::Continue;

        if (lEndPoint->mRemainingIdleTime == 0)
        {
            lEndPoint->DoClose(INET_ERROR_IDLE_TIMEOUT, false);
        }
        else
        {
            --lEndPoint->mRemainingIdleTime;
        }

        return Loop::Continue;
    });

    if (lTimerRequired)
    {
        TEMPORARY_RETURN_IGNORED aSystemLayer->StartTimer(System::Clock::Milliseconds32(INET_TCP_IDLE_CHECK_INTERVAL),
                                                          HandleIdleTimer, &endPointManager);
    }
}

// static
bool TCPEndPoint::IsIdleTimerRunning(EndPointManager<TCPEndPoint> & endPointManager)
{
    // See if there are any TCP connections with the idle timer check in use.
    return Loop::Break == endPointManager.ForEachEndPoint([](const TCPEndPointHandle & lEndPoint) {
        return (lEndPoint->mIdleTimeout == 0) ? Loop::Continue : Loop::Break;
    });
}

#endif // INET_TCP_IDLE_CHECK_INTERVAL > 0

CHIP_ERROR TCPEndPoint::SetUserTimeout(uint32_t userTimeoutMillis)
{
    VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
    CHIP_ERROR res = CHIP_NO_ERROR;

#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT

    // Store the User timeout configuration if it is being overridden.
    mUserTimeoutMillis = userTimeoutMillis;

#else // !INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT

    res = SetUserTimeoutImpl(userTimeoutMillis);

#endif // !INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT

    return res;
}

void TCPEndPoint::StartConnectTimerIfSet()
{
    if (mConnectTimeoutMsecs > 0)
    {
        TEMPORARY_RETURN_IGNORED GetSystemLayer().StartTimer(System::Clock::Milliseconds32(mConnectTimeoutMsecs),
                                                             TCPConnectTimeoutHandler, this);
    }
}

void TCPEndPoint::StopConnectTimer()
{
    GetSystemLayer().CancelTimer(TCPConnectTimeoutHandler, this);
}

void TCPEndPoint::TCPConnectTimeoutHandler(chip::System::Layer * aSystemLayer, void * aAppState)
{
    TCPEndPoint * tcpEndPoint = reinterpret_cast<TCPEndPoint *>(aAppState);
    VerifyOrDie((aSystemLayer != nullptr) && (tcpEndPoint != nullptr));

    // Close Connection as we have timed out and Connect has not returned to stop this timer.
    tcpEndPoint->DoClose(INET_ERROR_TCP_CONNECT_TIMEOUT, false);
}

bool TCPEndPoint::IsConnected(State state)
{
    return state == State::kConnected || state == State::kSendShutdown || state == State::kReceiveShutdown ||
        state == State::kClosing;
}

CHIP_ERROR TCPEndPoint::DriveSending()
{
    CHIP_ERROR err = DriveSendingImpl();

    if (err != CHIP_NO_ERROR)
    {
        DoClose(err, false);
    }

    CHIP_SYSTEM_FAULT_INJECT_ASYNC_EVENT();

    return err;
}

void TCPEndPoint::DriveReceiving(const TCPEndPointHandle & handle)
{
    // If there's data in the receive queue and the app is ready to receive it then call the app's callback
    // with the entire receive queue.
    if (!mRcvQueue.IsNull() && mReceiveEnabled && OnDataReceived != nullptr)
    {
        // Acknowledgement is done after handling the buffers to allow the
        // application processing to throttle flow.
        size_t ackLength = mRcvQueue->TotalLength();
        CHIP_ERROR err   = OnDataReceived(handle, std::move(mRcvQueue));
        if (err != CHIP_NO_ERROR)
        {
            DoClose(err, false);
            return;
        }
        TEMPORARY_RETURN_IGNORED AckReceive(ackLength);
    }

    // If the connection is closing, and the receive queue is now empty, call DoClose() to complete
    // the process of closing the connection.
    if (mState == State::kClosing && mRcvQueue.IsNull())
    {
        DoClose(CHIP_NO_ERROR, false);
    }
}

void TCPEndPoint::HandleConnectComplete(CHIP_ERROR err)
{
    TCPEndPointHandle handle(this);
    // If the connect succeeded enter the Connected state and call the app's callback.
    if (err == CHIP_NO_ERROR)
    {
        // Stop the TCP Connect timer in case it is still running.
        StopConnectTimer();

        // Mark the connection as being active.
        MarkActive();

        mState = State::kConnected;

        HandleConnectCompleteImpl();

        if (OnConnectComplete != nullptr)
        {
            OnConnectComplete(handle, CHIP_NO_ERROR);
        }
    }

    // Otherwise, close the connection with an error.
    else
    {
        DoClose(err, false);
    }
}

void TCPEndPoint::DoClose(CHIP_ERROR err, bool suppressCallback)
{
    State oldState = mState;

    // If in one of the connected states (Connected, LocalShutdown, PeerShutdown or Closing)
    // AND this is a graceful close (i.e. not prompted by an error)
    // AND there is data waiting to be processed on either the send or receive queues
    // ... THEN enter the Closing state, allowing the queued data to drain,
    // ... OTHERWISE go straight to the Closed state.
    if (IsConnected() && err == CHIP_NO_ERROR && (!mSendQueue.IsNull() || !mRcvQueue.IsNull()))
    {
        mState = State::kClosing;
    }
    else
    {
        mState = State::kClosed;
    }

    if (oldState != State::kClosed)
    {
        // Stop the Connect timer in case it is still running.
        StopConnectTimer();
    }

    // If not making a state transition, return immediately.
    if (mState == oldState)
    {
        return;
    }

    DoCloseImpl(err, oldState);

#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
    // Stop the TCP UserTimeout timer if it is running.
    StopTCPUserTimeoutTimer();
#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT

    // If entering the Closed state...
    if (mState == State::kClosed)
    {
        // Clear clear the send and receive queues.
        mSendQueue = nullptr;
        mRcvQueue  = nullptr;

        // Call the appropriate app callback if allowed.
        if (!suppressCallback)
        {
            if (oldState == State::kConnecting)
            {
                if (OnConnectComplete != nullptr)
                {
                    TCPEndPointHandle handle(this);
                    OnConnectComplete(handle, err);
                }
            }
            else if ((oldState == State::kConnected || oldState == State::kSendShutdown || oldState == State::kReceiveShutdown ||
                      oldState == State::kClosing) &&
                     OnConnectionClosed != nullptr)
            {
                TCPEndPointHandle handle(this);
                OnConnectionClosed(handle, err);
            }
        }
    }
}

#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT

void TCPEndPoint::ScheduleNextTCPUserTimeoutPoll(uint32_t aTimeOut)
{
    TEMPORARY_RETURN_IGNORED GetSystemLayer().StartTimer(System::Clock::Milliseconds32(aTimeOut), TCPUserTimeoutHandler, this);
}

void TCPEndPoint::StartTCPUserTimeoutTimer()
{
    ScheduleNextTCPUserTimeoutPoll(mUserTimeoutMillis);
    mUserTimeoutTimerRunning = true;
}

void TCPEndPoint::StopTCPUserTimeoutTimer()
{
    GetSystemLayer().CancelTimer(TCPUserTimeoutHandler, this);
    mUserTimeoutTimerRunning = false;
}

void TCPEndPoint::RestartTCPUserTimeoutTimer()
{
    StopTCPUserTimeoutTimer();
    StartTCPUserTimeoutTimer();
}

// static
void TCPEndPoint::TCPUserTimeoutHandler(chip::System::Layer * aSystemLayer, void * aAppState)
{
    TCPEndPoint * tcpEndPoint = reinterpret_cast<TCPEndPoint *>(aAppState);
    VerifyOrDie((aSystemLayer != nullptr) && (tcpEndPoint != nullptr));
    tcpEndPoint->TCPUserTimeoutHandler();
}

#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT

#if INET_CONFIG_TEST
bool TCPEndPoint::sForceEarlyFailureIncomingConnection = false;
#endif

} // namespace Inet
} // namespace chip
