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

/**
 * This file implements Inet::TCPEndPoint using LwIP.
 */

#include <inet/TCPEndPointImplLwIP.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>

#include <lwip/tcp.h>
#include <lwip/tcpip.h>

namespace chip {
namespace Inet {

namespace {

/*
 * This logic to register a null operation callback with the LwIP TCP/IP task
 * ensures that the TCP timer loop is started when a connection is established,
 * which is necessary to ensure that initial SYN and SYN-ACK packets are
 * retransmitted during the 3-way handshake.
 */

void nil_tcpip_callback(void * _aContext) {}

err_t start_tcp_timers(void)
{
    return tcpip_callback(nil_tcpip_callback, NULL);
}

} // anonymous namespace

CHIP_ERROR TCPEndPointImplLwIP::BindImpl(IPAddressType addrType, const IPAddress & addr, uint16_t port, bool reuseAddr)
{
    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    // Get the appropriate type of PCB.
    CHIP_ERROR res = GetPCB(addrType);

    // Bind the PCB to the specified address/port.
    ip_addr_t ipAddr;
    if (res == CHIP_NO_ERROR)
    {
        if (reuseAddr)
        {
            ip_set_option(mTCP, SOF_REUSEADDR);
        }
        res = addr.ToLwIPAddr(addrType, ipAddr);
    }

    if (res == CHIP_NO_ERROR)
    {
        res = chip::System::MapErrorLwIP(tcp_bind(mTCP, &ipAddr, port));
    }

    // Unlock LwIP stack
    UNLOCK_TCPIP_CORE();
    return res;
}

CHIP_ERROR TCPEndPointImplLwIP::ListenImpl(uint16_t backlog)
{
    // Start listening for incoming connections.
    mTCP              = tcp_listen(mTCP);
    mLwIPEndPointType = LwIPEndPointType::TCP;

    tcp_arg(mTCP, this);

    tcp_accept(mTCP, LwIPHandleIncomingConnection);

    return CHIP_NO_ERROR;
}

CHIP_ERROR TCPEndPointImplLwIP::ConnectImpl(const IPAddress & addr, uint16_t port, InterfaceId intfId)
{
    CHIP_ERROR res         = CHIP_NO_ERROR;
    IPAddressType addrType = addr.Type();

    // LwIP does not provides an API for initiating a TCP connection via a specific interface.
    // As a work-around, if the destination is an IPv6 link-local address, we bind the PCB
    // to the link local address associated with the source interface; however this is only
    // viable if the endpoint hasn't already been bound.
    if (intfId.IsPresent())
    {
        IPAddress intfLLAddr;

        if (!addr.IsIPv6LinkLocal() || mState == State::kBound)
            return CHIP_ERROR_NOT_IMPLEMENTED;

        res = intfId.GetLinkLocalAddr(&intfLLAddr);
        if (res != CHIP_NO_ERROR)
            return res;

        res = Bind(IPAddressType::kIPv6, intfLLAddr, 0, true);
        if (res != CHIP_NO_ERROR)
            return res;
    }

    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    res = GetPCB(addrType);

    if (res == CHIP_NO_ERROR)
    {
        tcp_arg(mTCP, this);
        tcp_err(mTCP, LwIPHandleError);

        ip_addr_t lwipAddr = addr.ToLwIPAddr();
        res                = chip::System::MapErrorLwIP(tcp_connect(mTCP, &lwipAddr, port, LwIPHandleConnectComplete));

        // Ensure that TCP timers are started
        if (res == CHIP_NO_ERROR)
        {
            err_t error = start_tcp_timers();
            if (error != ERR_OK)
            {
                res = chip::System::MapErrorLwIP(error);
            }
        }

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

    // Unlock LwIP stack
    UNLOCK_TCPIP_CORE();
    return res;
}

CHIP_ERROR TCPEndPointImplLwIP::GetPeerInfo(IPAddress * retAddr, uint16_t * retPort) const
{
    VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);

    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    CHIP_ERROR res = CHIP_ERROR_CONNECTION_ABORTED;
    if (mTCP != nullptr)
    {
        *retPort = mTCP->remote_port;
        *retAddr = IPAddress(mTCP->remote_ip);
        res      = CHIP_NO_ERROR;
    }

    // Unlock LwIP stack
    UNLOCK_TCPIP_CORE();

    return res;
}

CHIP_ERROR TCPEndPointImplLwIP::GetLocalInfo(IPAddress * retAddr, uint16_t * retPort) const
{
    VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);

    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    CHIP_ERROR res = CHIP_ERROR_CONNECTION_ABORTED;
    if (mTCP != nullptr)
    {
        *retPort = mTCP->local_port;
        *retAddr = IPAddress(mTCP->local_ip);
        res      = CHIP_NO_ERROR;
    }

    // Unlock LwIP stack
    UNLOCK_TCPIP_CORE();

    return res;
}

CHIP_ERROR TCPEndPointImplLwIP::GetInterfaceId(InterfaceId * retInterface)
{
    VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);

    // TODO: Does netif_get_by_index(mTCP->netif_idx) do the right thing?  I
    // can't quite tell whether LwIP supports a specific interface id for TCP at
    // all.  For now just claim no particular interface id.
    *retInterface = InterfaceId::Null();
    return CHIP_NO_ERROR;
}

CHIP_ERROR TCPEndPointImplLwIP::SendQueuedImpl(bool queueWasEmpty)
{
#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
    if (!mUserTimeoutTimerRunning)
    {
        // Timer was not running before this send. So, start
        // the timer.
        StartTCPUserTimeoutTimer();
    }
#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
    return CHIP_NO_ERROR;
}

CHIP_ERROR TCPEndPointImplLwIP::EnableNoDelay()
{
    VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);

    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    CHIP_ERROR res = CHIP_ERROR_CONNECTION_ABORTED;
    if (mTCP != nullptr)
    {
        tcp_nagle_disable(mTCP);
        res = CHIP_NO_ERROR;
    }

    // Unlock LwIP stack
    UNLOCK_TCPIP_CORE();

    return res;
}

CHIP_ERROR TCPEndPointImplLwIP::EnableKeepAlive(uint16_t interval, uint16_t timeoutCount)
{
    VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
    CHIP_ERROR res = CHIP_ERROR_NOT_IMPLEMENTED;

#if LWIP_TCP_KEEPALIVE

    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    if (mTCP != NULL)
    {
        // Set the idle interval
        mTCP->keep_idle = (uint32_t) interval * 1000;

        // Set the probe retransmission interval.
        mTCP->keep_intvl = (uint32_t) interval * 1000;

        // Set the probe timeout count
        mTCP->keep_cnt = timeoutCount;

        // Enable keepalives for the connection.
        ip_set_option(mTCP, SOF_KEEPALIVE);
        res = CHIP_NO_ERROR;
    }
    else
    {
        res = CHIP_ERROR_CONNECTION_ABORTED;
    }

    // Unlock LwIP stack
    UNLOCK_TCPIP_CORE();

#endif // LWIP_TCP_KEEPALIVE

    return res;
}

CHIP_ERROR TCPEndPointImplLwIP::DisableKeepAlive()
{
    VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
    CHIP_ERROR res = CHIP_ERROR_NOT_IMPLEMENTED;

#if LWIP_TCP_KEEPALIVE

    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    if (mTCP != NULL)
    {
        // Disable keepalives on the connection.
        ip_reset_option(mTCP, SOF_KEEPALIVE);
        res = CHIP_NO_ERROR;
    }
    else
    {
        res = CHIP_ERROR_CONNECTION_ABORTED;
    }

    // Unlock LwIP stack
    UNLOCK_TCPIP_CORE();

#endif // LWIP_TCP_KEEPALIVE

    return res;
}

CHIP_ERROR TCPEndPointImplLwIP::SetUserTimeoutImpl(uint32_t userTimeoutMillis)
{
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR TCPEndPointImplLwIP::DriveSendingImpl()
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    // If the connection hasn't been aborted ...
    if (mTCP != NULL)
    {
        err_t lwipErr;

        // Determine the current send window size. This is the maximum amount we can write to the connection.
        uint16_t sendWindowSize = tcp_sndbuf(mTCP);

        // If there's data to be sent and the send window is open...
        bool canSend = (RemainingToSend() > 0 && sendWindowSize > 0);
        if (canSend)
        {
            // Find first packet buffer with remaining data to send by skipping
            // all sent but un-acked data.
            TCPEndPointImplLwIP::BufferOffset startOfUnsent = FindStartOfUnsent();

            // While there's data to be sent and a window to send it in...
            do
            {
                VerifyOrDie(!startOfUnsent.buffer.IsNull());

                uint16_t bufDataLen = startOfUnsent.buffer->DataLength();

                // Get a pointer to the start of unsent data within the first buffer on the unsent queue.
                const uint8_t * sendData = startOfUnsent.buffer->Start() + startOfUnsent.offset;

                // Determine the amount of data to send from the current buffer.
                uint16_t sendLen = static_cast<uint16_t>(bufDataLen - startOfUnsent.offset);
                if (sendLen > sendWindowSize)
                    sendLen = sendWindowSize;

                // Call LwIP to queue the data to be sent, telling it if there's more data to come.
                // Data is queued in-place as a reference within the source packet buffer. It is
                // critical that the underlying packet buffer not be freed until the data
                // is acknowledged, otherwise retransmissions could use an invalid
                // backing. Using TCP_WRITE_FLAG_COPY would eliminate this requirement, but overall
                // requires many more memory allocations which may be problematic when very
                // memory-constrained or when using pool-based allocations.
                lwipErr = tcp_write(mTCP, sendData, sendLen, (canSend) ? TCP_WRITE_FLAG_MORE : 0);
                if (lwipErr != ERR_OK)
                {
                    err = chip::System::MapErrorLwIP(lwipErr);
                    break;
                }
                // Start accounting for the data sent as yet-to-be-acked.
                // This cast is safe, because mUnackedLength + sendLen <= bufDataLen, which fits in uint16_t.
                mUnackedLength = static_cast<uint16_t>(mUnackedLength + sendLen);

                // Adjust the unsent data offset by the length of data that was written.
                // If the entire buffer has been sent advance to the next one.
                // This cast is safe, because startOfUnsent.offset + sendLen <= bufDataLen, which fits in uint16_t.
                startOfUnsent.offset = static_cast<uint16_t>(startOfUnsent.offset + sendLen);
                if (startOfUnsent.offset == bufDataLen)
                {
                    startOfUnsent.buffer.Advance();
                    startOfUnsent.offset = 0;
                }

                // Adjust the remaining window size.
                sendWindowSize = static_cast<uint16_t>(sendWindowSize - sendLen);

                // Determine if there's more data to be sent after this buffer.
                canSend = (RemainingToSend() > 0 && sendWindowSize > 0);
            } while (canSend);

            // Call LwIP to send the queued data.
            INET_FAULT_INJECT(FaultInjection::kFault_Send, err = chip::System::MapErrorLwIP(ERR_RTE));

            if (err == CHIP_NO_ERROR)
            {
                lwipErr = tcp_output(mTCP);

                if (lwipErr != ERR_OK)
                    err = chip::System::MapErrorLwIP(lwipErr);
            }
        }

        if (err == CHIP_NO_ERROR)
        {
            // If in the SendShutdown state and the unsent queue is now empty, shutdown the PCB for sending.
            if (mState == State::kSendShutdown && (RemainingToSend() == 0))
            {
                lwipErr = tcp_shutdown(mTCP, 0, 1);
                if (lwipErr != ERR_OK)
                    err = chip::System::MapErrorLwIP(lwipErr);
            }
        }
    }

    else
        err = CHIP_ERROR_CONNECTION_ABORTED;

    // Unlock LwIP stack
    UNLOCK_TCPIP_CORE();

    return err;
}

void TCPEndPointImplLwIP::HandleConnectCompleteImpl() {}

void TCPEndPointImplLwIP::DoCloseImpl(CHIP_ERROR err, State oldState)
{
    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    // If the LwIP PCB hasn't been closed yet...
    if (mTCP != NULL)
    {
        // If the endpoint was a connection endpoint (vs. a listening endpoint)...
        if (oldState != State::kListening)
        {
            // Prevent further callbacks for incoming data.  This has the effect of instructing
            // LwIP to discard any further data received from the peer.
            tcp_recv(mTCP, NULL);

            // If entering the Closed state...
            if (mState == State::kClosed)
            {
                // Prevent further callbacks to the error handler.
                //
                // Note: It is important to understand that LwIP can continue to make callbacks after
                // a PCB has been closed via the tcp_close() API. In particular, LwIP will continue
                // to call the 'data sent' callback to signal the acknowledgment of data that was
                // sent, but not acknowledged, prior to the close call. Additionally, LwIP will call
                // the error callback if the peer fails to respond in a timely manner to the either
                // sent data or the FIN. Unfortunately, there is no callback in the case where the
                // connection closes successfully. Because of this, it is impossible know definitively
                // when LwIP will no longer make callbacks to its user. Thus we must block further
                // callbacks to prevent them from happening after the endpoint has been freed.
                //
                tcp_err(mTCP, NULL);

                // If the endpoint is being closed without error, THEN call tcp_close() to close the underlying
                // TCP connection gracefully, preserving any in-transit send data.
                if (err == CHIP_NO_ERROR)
                {
                    tcp_close(mTCP);
                }

                // OTHERWISE, call tcp_abort() to abort the TCP connection, discarding any in-transit data.
                else
                {
                    tcp_abort(mTCP);
                }

                // Discard the reference to the PCB to ensure there is no further interaction with it
                // after this point.
                mTCP              = NULL;
                mLwIPEndPointType = LwIPEndPointType::Unknown;
            }
        }

        // OTHERWISE the endpoint was being used for listening, so simply close it.
        else
        {
            tcp_close(mTCP);

            // Discard the reference to the PCB to ensure there is no further interaction with it
            // after this point.
            mTCP              = NULL;
            mLwIPEndPointType = LwIPEndPointType::Unknown;
        }
    }

    // Unlock LwIP stack
    UNLOCK_TCPIP_CORE();

    if (mState == State::kClosed)
    {
        mUnackedLength = 0;
    }
}

CHIP_ERROR TCPEndPointImplLwIP::AckReceive(uint16_t len)
{
    VerifyOrReturnError(IsConnected(), CHIP_ERROR_INCORRECT_STATE);
    CHIP_ERROR res = CHIP_NO_ERROR;

    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    if (mTCP != nullptr)
        tcp_recved(mTCP, len);
    else
        res = CHIP_ERROR_CONNECTION_ABORTED;

    // Unlock LwIP stack
    UNLOCK_TCPIP_CORE();

    return res;
}

#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
void TCPEndPointImplLwIP::TCPUserTimeoutHandler()
{
    // Set the timer running flag to false
    mUserTimeoutTimerRunning = false;

    // Close Connection as we have timed out and there is still
    // data not sent out successfully.
    DoClose(INET_ERROR_TCP_USER_TIMEOUT, false);
}
#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT

uint16_t TCPEndPointImplLwIP::RemainingToSend()
{
    if (mSendQueue.IsNull())
    {
        return 0;
    }
    else
    {
        // We can never have reported more unacked data than there is pending
        // in the send queue! This would indicate a critical accounting bug.
        VerifyOrDie(mUnackedLength <= mSendQueue->TotalLength());

        return static_cast<uint16_t>(mSendQueue->TotalLength() - mUnackedLength);
    }
}

TCPEndPointImplLwIP::BufferOffset TCPEndPointImplLwIP::FindStartOfUnsent()
{
    // Find first packet buffer with remaining data to send by skipping
    // all sent but un-acked data. This is necessary because of the Consume()
    // call in HandleDataSent(), which potentially releases backing memory for
    // fully-sent packet buffers, causing an invalidation of all possible
    // offsets one might have cached. The TCP acnowledgements may come back
    // with a variety of sizes depending on prior activity, and size of the
    // send window. The only way to ensure we get the correct offsets into
    // unsent data while retaining the buffers that have un-acked data is to
    // traverse all sent-but-unacked data in the chain to reach the beginning
    // of ready-to-send data.
    TCPEndPointImplLwIP::BufferOffset startOfUnsent(mSendQueue.Retain());
    uint16_t leftToSkip = mUnackedLength;

    VerifyOrDie(leftToSkip < mSendQueue->TotalLength());

    while (leftToSkip > 0)
    {
        VerifyOrDie(!startOfUnsent.buffer.IsNull());
        uint16_t bufDataLen = startOfUnsent.buffer->DataLength();
        if (leftToSkip >= bufDataLen)
        {
            // We have more to skip than current packet buffer size.
            // Follow the chain to continue.
            startOfUnsent.buffer.Advance();
            leftToSkip = static_cast<uint16_t>(leftToSkip - bufDataLen);
        }
        else
        {
            // Done skipping all data, currentUnsentBuf is first packet buffer
            // containing unsent data.
            startOfUnsent.offset = leftToSkip;
            leftToSkip           = 0;
        }
    }

    return startOfUnsent;
}

CHIP_ERROR TCPEndPointImplLwIP::GetPCB(IPAddressType addrType)
{
    // IMMPORTANT: This method MUST be called with the LwIP stack LOCKED!
    if (mTCP == NULL)
    {
        switch (addrType)
        {
        case IPAddressType::kIPv6:
            mTCP = tcp_new_ip_type(IPADDR_TYPE_V6);
            break;

#if INET_CONFIG_ENABLE_IPV4
        case IPAddressType::kIPv4:
            mTCP = tcp_new_ip_type(IPADDR_TYPE_V4);
            break;
#endif // INET_CONFIG_ENABLE_IPV4

        default:
            return INET_ERROR_WRONG_ADDRESS_TYPE;
        }

        if (mTCP == NULL)
        {
            return CHIP_ERROR_NO_MEMORY;
        }
        else
        {
            mLwIPEndPointType = LwIPEndPointType::TCP;
        }
    }
    else
    {
        switch (IP_GET_TYPE(&mTCP->local_ip))
        {
        case IPADDR_TYPE_V6:
            if (addrType != IPAddressType::kIPv6)
                return INET_ERROR_WRONG_ADDRESS_TYPE;
            break;

#if INET_CONFIG_ENABLE_IPV4
        case IPADDR_TYPE_V4:
            if (addrType != IPAddressType::kIPv4)
                return INET_ERROR_WRONG_ADDRESS_TYPE;
            break;
#endif // INET_CONFIG_ENABLE_IPV4

        default:
            break;
        }
    }

    return CHIP_NO_ERROR;
}

void TCPEndPointImplLwIP::HandleDataSent(uint16_t lenSent)
{
    if (IsConnected())
    {
        // Ensure we do not have internal inconsistency in the lwIP, which
        // could cause invalid pointer accesses.
        if (lenSent > mUnackedLength)
        {
            ChipLogError(Inet, "Got more ACKed bytes (%d) than were pending (%d)", (int) lenSent, (int) mUnackedLength);
            DoClose(CHIP_ERROR_UNEXPECTED_EVENT, false);
            return;
        }
        else if (mSendQueue.IsNull())
        {
            ChipLogError(Inet, "Got ACK for %d bytes but data backing gone", (int) lenSent);
            DoClose(CHIP_ERROR_UNEXPECTED_EVENT, false);
            return;
        }

        // Consume data off the head of the send queue equal to the amount of data being acknowledged.
        mSendQueue.Consume(lenSent);
        mUnackedLength = static_cast<uint16_t>(mUnackedLength - lenSent);

#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT
        // Only change the UserTimeout timer if lenSent > 0,
        // indicating progress being made in sending data
        // across.
        if (lenSent > 0)
        {
            if (RemainingToSend() == 0)
            {
                // If the output queue has been flushed then stop the timer.
                StopTCPUserTimeoutTimer();
            }
            else
            {
                // Progress is being made. So, shift the timer
                // forward if it was started.
                RestartTCPUserTimeoutTimer();
            }
        }
#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT

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

        // If requested, call the app's OnDataSent callback.
        if (OnDataSent != NULL)
            OnDataSent(this, lenSent);

        // If unsent data exists, attempt to send it now...
        if (RemainingToSend() > 0)
            DriveSending();

        // If in the closing state and the send queue is now empty, attempt to transition to closed.
        if ((mState == State::kClosing) && (RemainingToSend() == 0))
            DoClose(CHIP_NO_ERROR, false);
    }
}

void TCPEndPointImplLwIP::HandleDataReceived(System::PacketBufferHandle && buf)
{
    // Only receive new data while in the Connected or SendShutdown states.
    if (mState == State::kConnected || mState == State::kSendShutdown)
    {
        // Mark the connection as being active.
        MarkActive();

        // If we received a data buffer, queue it on the receive queue.  If there's already data in
        // the queue, compact the data into the head buffer.
        if (!buf.IsNull())
        {
            if (mRcvQueue.IsNull())
            {
                mRcvQueue = std::move(buf);
            }
            else
            {
                mRcvQueue->AddToEnd(std::move(buf));
                mRcvQueue->CompactHead();
            }
        }

        // Otherwise buf == NULL means the other side closed the connection, so ...
        else
        {

            // If in the Connected state and the app has provided an OnPeerClose callback,
            // enter the ReceiveShutdown state.  Providing an OnPeerClose callback allows
            // the app to decide whether to keep the send side of the connection open after
            // the peer has closed. If no OnPeerClose is provided, we assume that the app
            // wants to close both directions and automatically enter the Closing state.
            if (mState == State::kConnected && OnPeerClose != NULL)
                mState = State::kReceiveShutdown;
            else
                mState = State::kClosing;

            // Call the app's OnPeerClose.
            if (OnPeerClose != NULL)
                OnPeerClose(this);
        }

        // Drive the received data into the app.
        DriveReceiving();
    }
}

void TCPEndPointImplLwIP::HandleIncomingConnection(TCPEndPoint * conEP)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    IPAddress peerAddr;
    uint16_t peerPort;

    if (mState == State::kListening)
    {
        // If there's no callback available, fail with an error.
        if (OnConnectionReceived == NULL)
            err = CHIP_ERROR_NO_CONNECTION_HANDLER;

        // Extract the peer's address information.
        if (err == CHIP_NO_ERROR)
            err = conEP->GetPeerInfo(&peerAddr, &peerPort);

        // If successful, call the app's callback function.
        if (err == CHIP_NO_ERROR)
            OnConnectionReceived(this, conEP, peerAddr, peerPort);

        // Otherwise clean up and call the app's error callback.
        else if (OnAcceptError != NULL)
            OnAcceptError(this, err);
    }
    else
        err = CHIP_ERROR_INCORRECT_STATE;

    // If something failed above, abort and free the connection end point.
    if (err != CHIP_NO_ERROR)
        conEP->Free();
}

void TCPEndPointImplLwIP::HandleError(CHIP_ERROR err)
{
    if (mState == State::kListening)
    {
        if (OnAcceptError != NULL)
            OnAcceptError(this, err);
    }
    else
        DoClose(err, false);
}

err_t TCPEndPointImplLwIP::LwIPHandleConnectComplete(void * arg, struct tcp_pcb * tpcb, err_t lwipErr)
{
    err_t res = ERR_OK;

    if (arg != NULL)
    {
        TCPEndPointImplLwIP * ep = static_cast<TCPEndPointImplLwIP *>(arg);

        if (lwipErr == ERR_OK)
        {
            // Setup LwIP callback functions for data transmission.
            tcp_recv(ep->mTCP, LwIPHandleDataReceived);
            tcp_sent(ep->mTCP, LwIPHandleDataSent);
        }

        // Post callback to HandleConnectComplete.
        ep->Retain();
        CHIP_ERROR err = ep->GetSystemLayer().ScheduleLambda([ep, conErr = System::MapErrorLwIP(lwipErr)] {
            ep->HandleConnectComplete(conErr);
            ep->Release();
        });
        if (err != CHIP_NO_ERROR)
        {
            ep->Release();
            res = ERR_ABRT;
        }
    }
    else
        res = ERR_ABRT;

    if (res != ERR_OK)
        tcp_abort(tpcb);

    return res;
}

err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_pcb * tpcb, err_t lwipErr)
{
    CHIP_ERROR err = chip::System::MapErrorLwIP(lwipErr);

    if (arg != NULL)
    {
        TCPEndPointImplLwIP * listenEP = static_cast<TCPEndPointImplLwIP *>(arg);
        TCPEndPointImplLwIP * conEP    = NULL;
        System::Layer & lSystemLayer   = listenEP->GetSystemLayer();

        // Tell LwIP we've accepted the connection so it can decrement the listen PCB's pending_accepts counter.
        tcp_accepted(listenEP->mTCP);

        // If we did in fact receive a connection, rather than an error, attempt to allocate an end point object.
        //
        // NOTE: Although most of the LwIP callbacks defer the real work to happen on the endpoint's thread
        // (by posting events to the thread's event queue) we can't do that here because as soon as this
        // function returns, LwIP is free to begin calling callbacks on the new PCB. For that to work we need
        // to have an end point associated with the PCB.
        //
        if (err == CHIP_NO_ERROR)
        {
            TCPEndPoint * connectEndPoint = nullptr;
            err                           = listenEP->GetEndPointManager().NewEndPoint(&connectEndPoint);
            conEP                         = static_cast<TCPEndPointImplLwIP *>(connectEndPoint);
        }

        // Ensure that TCP timers have been started
        if (err == CHIP_NO_ERROR)
        {
            err_t error = start_tcp_timers();
            if (error != ERR_OK)
            {
                err = chip::System::MapErrorLwIP(error);
            }
        }

        // If successful in allocating an end point...
        if (err == CHIP_NO_ERROR)
        {
            // Put the new end point into the Connected state.
            conEP->mState            = State::kConnected;
            conEP->mTCP              = tpcb;
            conEP->mLwIPEndPointType = LwIPEndPointType::TCP;
            conEP->Retain();

            // Setup LwIP callback functions for the new PCB.
            tcp_arg(tpcb, conEP);
            tcp_recv(tpcb, LwIPHandleDataReceived);
            tcp_sent(tpcb, LwIPHandleDataSent);
            tcp_err(tpcb, LwIPHandleError);

            // Post a callback to the HandleConnectionReceived() function, passing it the new end point.
            listenEP->Retain();
            conEP->Retain();
            err = lSystemLayer.ScheduleLambda([listenEP, conEP] {
                listenEP->HandleIncomingConnection(conEP);
                conEP->Release();
                listenEP->Release();
            });
            if (err != CHIP_NO_ERROR)
            {
                conEP->Release(); // for the Ref in ScheduleLambda
                listenEP->Release();
                err = CHIP_ERROR_CONNECTION_ABORTED;
                conEP->Release(); // for the Retain() above
                conEP->Release(); // for the implied Retain() on construction
            }
        }

        // Otherwise, there was an error accepting the connection, so post a callback to the HandleError function.
        else
        {
            listenEP->Retain();
            err = lSystemLayer.ScheduleLambda([listenEP, err] {
                listenEP->HandleError(err);
                listenEP->Release();
            });
            if (err != CHIP_NO_ERROR)
            {
                listenEP->Release();
            }
        }
    }
    else
        err = CHIP_ERROR_CONNECTION_ABORTED;

    if (err != CHIP_NO_ERROR && tpcb != NULL)
    {
        tcp_abort(tpcb);
        return ERR_ABRT;
    }
    else
    {
        return ERR_OK;
    }
}

err_t TCPEndPointImplLwIP::LwIPHandleDataReceived(void * arg, struct tcp_pcb * tpcb, struct pbuf * p, err_t _err)
{
    err_t res = ERR_OK;

    if (arg != NULL)
    {
        TCPEndPointImplLwIP * ep = static_cast<TCPEndPointImplLwIP *>(arg);

        // Post callback to HandleDataReceived.
        ep->Retain();
        CHIP_ERROR err = ep->GetSystemLayer().ScheduleLambda([ep, p] {
            ep->HandleDataReceived(System::PacketBufferHandle::Adopt(p));
            ep->Release();
        });
        if (err != CHIP_NO_ERROR)
        {
            ep->Release();
            res = ERR_ABRT;
        }
    }
    else
        res = ERR_ABRT;

    if (res != ERR_OK)
    {
        if (p != nullptr)
        {
            pbuf_free(p);
        }
        tcp_abort(tpcb);
    }

    return res;
}

err_t TCPEndPointImplLwIP::LwIPHandleDataSent(void * arg, struct tcp_pcb * tpcb, u16_t len)
{
    err_t res = ERR_OK;

    if (arg != NULL)
    {
        TCPEndPointImplLwIP * ep = static_cast<TCPEndPointImplLwIP *>(arg);

        // Post callback to HandleDataReceived.
        ep->Retain();
        CHIP_ERROR err = ep->GetSystemLayer().ScheduleLambda([ep, len] {
            ep->HandleDataSent(len);
            ep->Release();
        });
        if (err != CHIP_NO_ERROR)
        {
            ep->Release();
            res = ERR_ABRT;
        }
    }
    else
        res = ERR_ABRT;

    if (res != ERR_OK)
        tcp_abort(tpcb);

    return res;
}

void TCPEndPointImplLwIP::LwIPHandleError(void * arg, err_t lwipErr)
{
    if (arg != NULL)
    {
        TCPEndPointImplLwIP * ep             = static_cast<TCPEndPointImplLwIP *>(arg);
        System::LayerFreeRTOS & lSystemLayer = static_cast<System::LayerFreeRTOS &>(ep->GetSystemLayer());

        // At this point LwIP has already freed the PCB.  Since the thread that owns the TCPEndPoint may
        // try to use the PCB before it receives the TCPError event posted below, we set the PCB to NULL
        // as a means to signal the other thread that the connection has been aborted.  The implication
        // of this is that the mTCP field is shared state between the two threads and thus must only be
        // accessed with the LwIP lock held.
        ep->mTCP              = NULL;
        ep->mLwIPEndPointType = LwIPEndPointType::Unknown;

        // Post callback to HandleError.
        ep->Retain();
        CHIP_ERROR err = lSystemLayer.ScheduleLambda([ep, conErr = System::MapErrorLwIP(lwipErr)] {
            ep->HandleError(conErr);
            ep->Release();
        });
        if (err != CHIP_NO_ERROR)
            ep->Release();
    }
}

} // namespace Inet
} // namespace chip
