/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2019 Google LLC.
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    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 implements a process to effect a functional test for
 *      the InetLayer Internet Protocol stack abstraction interfaces.
 *
 */

#include <signal.h>
#include <stdint.h>
#include <string.h>
#include <type_traits>
#include <unistd.h>

#include <CHIPVersion.h>

#include <inet/InetArgParser.h>
#include <lib/support/CodeUtils.h>

#include "TestInetCommon.h"
#include "TestInetCommonOptions.h"
#include "TestInetLayerCommon.hpp"
#include "TestSetupFaultInjection.h"
#include "TestSetupSignalling.h"

using namespace chip;
using namespace chip::Inet;
using namespace chip::ArgParser;
using namespace chip::System;

/* Preprocessor Macros */

#define kToolName "TestInetLayer"

#define kToolOptTCPIP 't'

#define kToolOptExpectedRxSize (kToolOptBase + 0)
#define kToolOptExpectedTxSize (kToolOptBase + 1)

/* Type Definitions */

enum OptFlags
{
    kOptFlagExpectedRxSize = 0x00010000,
    kOptFlagExpectedTxSize = 0x00020000,

    kOptFlagUseTCPIP = 0x00040000
};

struct TestState
{
    TransferStats mStats;
    TestStatus mStatus;
};

/* Function Declarations */

static void HandleSignal(int aSignal);
static bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue);
static bool HandleNonOptionArgs(const char * aProgram, int argc, char * const argv[]);

static void StartTest();
static void CleanupTest();

/* Global Variables */

static const uint32_t kExpectedRxSizeDefault = 1523;
static const uint32_t kExpectedTxSizeDefault = kExpectedRxSizeDefault;

static const uint32_t kOptFlagsDefault = (kOptFlagUseIPv6 | kOptFlagUseUDPIP);

static TCPEndPoint * sTCPIPEndPoint       = nullptr; // Used for connect/send/receive
static TCPEndPoint * sTCPIPListenEndPoint = nullptr; // Used for accept/listen
static UDPEndPoint * sUDPIPEndPoint       = nullptr;

static const uint16_t kTCPPort = kUDPPort;
// clang-format off
static TestState         sTestState             =
{
    { { 0, 0 }, { 0, 0 } },
    { false, false }
};
// clang-format on

static IPAddress sDestinationAddress   = IPAddress::Any;
static const char * sDestinationString = nullptr;

// clang-format off
static OptionDef         sToolOptionDefs[] =
{
    { "interface",                 kArgumentRequired,  kToolOptInterface              },
    { "expected-rx-size",          kArgumentRequired,  kToolOptExpectedRxSize         },
    { "expected-tx-size",          kArgumentRequired,  kToolOptExpectedTxSize         },
    { "interval",                  kArgumentRequired,  kToolOptInterval               },
#if INET_CONFIG_ENABLE_IPV4
    { "ipv4",                      kNoArgument,        kToolOptIPv4Only               },
#endif // INET_CONFIG_ENABLE_IPV4
    { "ipv6",                      kNoArgument,        kToolOptIPv6Only               },
    { "listen",                    kNoArgument,        kToolOptListen                 },
    { "send-size",                 kArgumentRequired,  kToolOptSendSize               },
    { "tcp",                       kNoArgument,        kToolOptTCPIP                  },
    { "udp",                       kNoArgument,        kToolOptUDPIP                  },
    { }
};

static const char *      sToolOptionHelp =
    "  -I, --interface <interface>\n"
    "       The network interface to bind to and from which to send and receive all packets.\n"
    "\n"
    "  --expected-rx-size <size>\n"
    "       Expect to receive size bytes of user data (default 1523).\n"
    "\n"
    "  --expected-tx-size <size>\n"
    "       Expect to send size bytes of user data (default 1523).\n"
    "\n"
    "  -i, --interval <interval>\n"
    "       Wait interval milliseconds between sending each packet (default: 1000 ms).\n"
    "\n"
    "  -l, --listen\n"
    "       Act as a server (i.e., listen) for packets rather than send them.\n"
    "\n"
#if INET_CONFIG_ENABLE_IPV4
    "  -4, --ipv4\n"
    "       Use IPv4 only.\n"
    "\n"
#endif // INET_CONFIG_ENABLE_IPV4
    "  -6, --ipv6\n"
    "       Use IPv6 only (default).\n"
    "\n"
    "  -s, --send-size <size>\n"
    "       Send size bytes of user data (default: 59 bytes)\n"
    "\n"
    "  -t, --tcp\n"
    "       Use TCP over IP.\n"
    "\n"
    "  -u, --udp\n"
    "       Use UDP over IP (default).\n"
    "\n";

static OptionSet         sToolOptions =
{
    HandleOption,
    sToolOptionDefs,
    "GENERAL OPTIONS",
    sToolOptionHelp
};

static HelpOptions       sHelpOptions(
    kToolName,
    "Usage: " kToolName " [ <options> ] <dest-node-addr>\n"
    "       " kToolName " [ <options> ] --listen\n",
    CHIP_VERSION_STRING "\n" CHIP_TOOL_COPYRIGHT
);

static OptionSet *       sToolOptionSets[] =
{
    &sToolOptions,
    &gNetworkOptions,
    &gFaultInjectionOptions,
    &sHelpOptions,
    nullptr
};
// clang-format on

namespace chip {
namespace Inet {

class TCPTest
{
public:
    static bool StateIsConnected(const TCPEndPoint * endPoint) { return endPoint->mState == TCPEndPoint::State::kConnected; }
    static bool StateIsConnectedOrReceiveShutdown(const TCPEndPoint * endPoint)
    {
        return endPoint->mState == TCPEndPoint::State::kConnected || endPoint->mState == TCPEndPoint::State::kReceiveShutdown;
    }
};

} // namespace Inet
} // namespace chip

static void CheckSucceededOrFailed(TestState & aTestState, bool & aOutSucceeded, bool & aOutFailed)
{
    const TransferStats & lStats = aTestState.mStats;

#ifdef DEBUG_TCP_TEST
    printf("%u/%u sent, %u/%u received\n", lStats.mTransmit.mActual, lStats.mTransmit.mExpected, lStats.mReceive.mActual,
           lStats.mReceive.mExpected);
#endif

    if (((lStats.mTransmit.mExpected > 0) && (lStats.mTransmit.mActual > lStats.mTransmit.mExpected)) ||
        ((lStats.mReceive.mExpected > 0) && (lStats.mReceive.mActual > lStats.mReceive.mExpected)))
    {
        aOutFailed = true;
    }
    else if (((lStats.mTransmit.mExpected > 0) && (lStats.mTransmit.mActual < lStats.mTransmit.mExpected)) ||
             ((lStats.mReceive.mExpected > 0) && (lStats.mReceive.mActual < lStats.mReceive.mExpected)))
    {
        aOutSucceeded = false;
    }

    if (aOutSucceeded || aOutFailed)
    {
        if (aOutSucceeded)
            aTestState.mStatus.mSucceeded = true;

        if (aOutFailed)
            SetStatusFailed(aTestState.mStatus);
    }
}

static void HandleSignal(int aSignal)
{
    switch (aSignal)
    {

    case SIGUSR1:
        SetStatusFailed(sTestState.mStatus);
        break;
    }
}

int main(int argc, char * argv[])
{
    bool lSuccessful = true;
    CHIP_ERROR lStatus;

    InitTestInetCommon();

    SetupFaultInjectionContext(argc, argv);

    SetSignalHandler(HandleSignal);

    if (argc == 1)
    {
        sHelpOptions.PrintBriefUsage(stderr);
        lSuccessful = false;
        goto exit;
    }

    if (!ParseArgsFromEnvVar(kToolName, TOOL_OPTIONS_ENV_VAR_NAME, sToolOptionSets, nullptr, true) ||
        !ParseArgs(kToolName, argc, argv, sToolOptionSets, HandleNonOptionArgs))
    {
        lSuccessful = false;
        goto exit;
    }

    InitSystemLayer();

    InitNetwork();

    // At this point, we should have valid network interfaces,
    // including LwIP TUN/TAP shim interfaces. Validate the
    // -I/--interface argument, if present.

    if (gInterfaceName != nullptr)
    {
        lStatus = InterfaceId::InterfaceNameToId(gInterfaceName, gInterfaceId);
        if (lStatus != CHIP_NO_ERROR)
        {
            PrintArgError("%s: unknown network interface %s\n", kToolName, gInterfaceName);
            lSuccessful = false;
            goto shutdown;
        }
    }

    StartTest();

    while (Common::IsTesting(sTestState.mStatus))
    {
        bool lSucceeded = true;
        bool lFailed    = false;

        constexpr uint32_t kSleepTimeMilliseconds = 10;
        ServiceNetwork(kSleepTimeMilliseconds);

        CheckSucceededOrFailed(sTestState, lSucceeded, lFailed);

#ifdef DEBUG_TCP_TEST
        // clang-format off
        printf("%s %s number of expected bytes\n",
               ((lSucceeded) ? "successfully" :
                ((lFailed) ? "failed to" :
                 "has not yet")),
               ((lSucceeded) ? (Common::IsReceiver() ? "received" : "sent") :
                ((lFailed) ? (Common::IsReceiver() ? "receive" : "send") :
                 Common::IsReceiver() ? "received" : "sent"))
               );
        // clang-format on
#endif
    }

    CleanupTest();

shutdown:
    ShutdownNetwork();
    ShutdownSystemLayer();

    lSuccessful = Common::WasSuccessful(sTestState.mStatus);

    ShutdownTestInetCommon();

exit:
    return (lSuccessful ? EXIT_SUCCESS : EXIT_FAILURE);
}

static bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue)
{
    bool retval = true;

    switch (aIdentifier)
    {

    case kToolOptInterval:
        if (!ParseInt(aValue, gSendIntervalMs))
        {
            PrintArgError("%s: invalid value specified for send interval: %s\n", aProgram, aValue);
            retval = false;
        }
        break;

    case kToolOptListen:
        gOptFlags |= kOptFlagListen;
        break;

    case kToolOptExpectedRxSize:
        if (!ParseInt(aValue, sTestState.mStats.mReceive.mExpected) || sTestState.mStats.mReceive.mExpected > UINT32_MAX)
        {
            PrintArgError("%s: Invalid value specified for max receive: %s\n", aProgram, aValue);
            retval = false;
        }
        gOptFlags |= kOptFlagExpectedRxSize;
        break;

    case kToolOptExpectedTxSize:
        if (!ParseInt(aValue, sTestState.mStats.mTransmit.mExpected) || sTestState.mStats.mTransmit.mExpected > UINT32_MAX)
        {
            PrintArgError("%s: Invalid value specified for max send: %s\n", aProgram, aValue);
            retval = false;
        }
        gOptFlags |= kOptFlagExpectedTxSize;
        break;

#if INET_CONFIG_ENABLE_IPV4
    case kToolOptIPv4Only:
        if (gOptFlags & kOptFlagUseIPv6)
        {
            PrintArgError("%s: the use of --ipv4 is exclusive with --ipv6. Please select only one of the two options.\n", aProgram);
            retval = false;
        }
        gOptFlags |= kOptFlagUseIPv4;
        break;
#endif // INET_CONFIG_ENABLE_IPV4

    case kToolOptIPv6Only:
        if (gOptFlags & kOptFlagUseIPv4)
        {
            PrintArgError("%s: the use of --ipv6 is exclusive with --ipv4. Please select only one of the two options.\n", aProgram);
            retval = false;
        }
        gOptFlags |= kOptFlagUseIPv6;
        break;

    case kToolOptInterface:

        // NOTE: When using LwIP on a hosted OS, the interface will
        // not actually be available until AFTER InitNetwork,
        // consequently, we cannot do any meaningful validation
        // here. Simply save the value off and we will validate it
        // later.

        gInterfaceName = aValue;
        break;

    case kToolOptTCPIP:
        if (gOptFlags & kOptFlagUseUDPIP)
        {
            PrintArgError("%s: the use of --tcp is exclusive with --udp. Please select only one of the two options.\n", aProgram);
            retval = false;
        }
        gOptFlags |= kOptFlagUseTCPIP;
        break;

    case kToolOptSendSize:
        if (!ParseInt(aValue, gSendSize))
        {
            PrintArgError("%s: invalid value specified for send size: %s\n", aProgram, aValue);
            return false;
        }
        break;

    case kToolOptUDPIP:
        if (gOptFlags & kOptFlagUseTCPIP)
        {
            PrintArgError("%s: the use of --udp is exclusive with --tcp. Please select only one of the two options.\n", aProgram);
            retval = false;
        }
        gOptFlags |= kOptFlagUseUDPIP;
        break;

    default:
        PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", aProgram, aName);
        retval = false;
        break;
    }

    return (retval);
}

bool HandleNonOptionArgs(const char * aProgram, int argc, char * const argv[])
{
    if (Common::IsSender())
    {
        if (argc == 0)
        {
            PrintArgError("%s: Please specify a destination address.\n", aProgram);
            return false;
        }

        if (!IPAddress::FromString(argv[0], sDestinationAddress))
        {
            PrintArgError("%s: Please specify a valid destination address: %s\n", aProgram, argv[0]);
            return false;
        }

        sDestinationString = argv[0];

        argc--;
        argv++;
    }

    if (argc > 0)
    {
        PrintArgError("%s: unexpected argument: %s\n", aProgram, argv[0]);
        return false;
    }

    // If no IP version or transport flags were specified, use the defaults.

    if (!(gOptFlags & (kOptFlagUseIPv4 | kOptFlagUseIPv6 | kOptFlagUseTCPIP | kOptFlagUseUDPIP)))
    {
        gOptFlags |= kOptFlagsDefault;
    }

    // If no expected send or receive lengths were specified, use the defaults.

    if (!(gOptFlags & kOptFlagExpectedRxSize))
    {
        sTestState.mStats.mReceive.mExpected = kExpectedRxSizeDefault;
    }

    if (!(gOptFlags & kOptFlagExpectedTxSize))
    {
        sTestState.mStats.mTransmit.mExpected = kExpectedTxSizeDefault;
    }

    return true;
}

static void PrintReceivedStats(const TransferStats & aStats)
{
    printf("%" PRIu32 "/%" PRIu32 "received\n", aStats.mReceive.mActual, aStats.mReceive.mExpected);
}

static bool HandleDataReceived(const PacketBufferHandle & aBuffer, bool aCheckBuffer, uint8_t aFirstValue)
{
    constexpr bool lStatsByPacket = true;

    if (!Common::HandleDataReceived(aBuffer, sTestState.mStats, !lStatsByPacket, aCheckBuffer, aFirstValue))
    {
        return false;
    }

    PrintReceivedStats(sTestState.mStats);

    return true;
}

static bool HandleDataReceived(const PacketBufferHandle & aBuffer, bool aCheckBuffer)
{
    constexpr uint8_t lFirstValue = 0;
    return HandleDataReceived(aBuffer, aCheckBuffer, lFirstValue);
}

// TCP Endpoint Callbacks

void HandleTCPConnectionComplete(TCPEndPoint * aEndPoint, CHIP_ERROR aError)
{
    CHIP_ERROR lStatus;

    if (aError == CHIP_NO_ERROR)
    {
        IPAddress lPeerAddress;
        uint16_t lPeerPort;
        char lPeerAddressBuffer[INET6_ADDRSTRLEN];

        lStatus = aEndPoint->GetPeerInfo(&lPeerAddress, &lPeerPort);
        INET_FAIL_ERROR(lStatus, "TCPEndPoint::GetPeerInfo failed");

        lPeerAddress.ToString(lPeerAddressBuffer);

        printf("TCP connection established to %s:%u\n", lPeerAddressBuffer, lPeerPort);

        if (sTCPIPEndPoint->PendingReceiveLength() == 0)
            sTCPIPEndPoint->SetReceivedDataForTesting(nullptr);

        sTCPIPEndPoint->DisableReceive();
        sTCPIPEndPoint->EnableKeepAlive(10, 100);
        sTCPIPEndPoint->DisableKeepAlive();
        sTCPIPEndPoint->EnableReceive();

        DriveSend();
    }
    else
    {
        printf("TCP connection FAILED: %s\n", ErrorStr(aError));

        aEndPoint->Free();
        aEndPoint = nullptr;

        gSendIntervalExpired = false;
        gSystemLayer.CancelTimer(Common::HandleSendTimerComplete, nullptr);
        gSystemLayer.StartTimer(System::Clock::Milliseconds32(gSendIntervalMs), Common::HandleSendTimerComplete, nullptr);

        SetStatusFailed(sTestState.mStatus);
    }
}

static void HandleTCPConnectionClosed(TCPEndPoint * aEndPoint, CHIP_ERROR aError)
{
    if (aError == CHIP_NO_ERROR)
    {
        printf("TCP connection closed\n");
    }
    else
    {
        printf("TCP connection closed with error: %s\n", ErrorStr(aError));

        SetStatusFailed(sTestState.mStatus);
    }

    aEndPoint->Free();

    if (aEndPoint == sTCPIPEndPoint)
    {
        sTCPIPEndPoint = nullptr;
    }
}

static void HandleTCPDataSent(TCPEndPoint * aEndPoint, size_t len) {}

static CHIP_ERROR HandleTCPDataReceived(TCPEndPoint * aEndPoint, PacketBufferHandle && aBuffer)
{
    const uint32_t lFirstValueReceived = sTestState.mStats.mReceive.mActual;
    const uint8_t lFirstValue          = uint8_t(lFirstValueReceived);
    const bool lCheckBuffer            = true;
    IPAddress lPeerAddress;
    uint16_t lPeerPort;
    char lPeerAddressBuffer[INET6_ADDRSTRLEN];
    bool lCheckPassed;
    CHIP_ERROR lStatus = CHIP_NO_ERROR;

    // Check that we did not lose information in our narrowing cast.
    VerifyOrExit(lFirstValue == lFirstValueReceived, lStatus = CHIP_ERROR_UNEXPECTED_EVENT);

    VerifyOrExit(aEndPoint != nullptr, lStatus = CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrExit(!aBuffer.IsNull(), lStatus = CHIP_ERROR_INVALID_ARGUMENT);

    if (!TCPTest::StateIsConnected(aEndPoint))
    {
        lStatus = aEndPoint->SetReceivedDataForTesting(std::move(aBuffer));
        INET_FAIL_ERROR(lStatus, "TCPEndPoint::PutBackReceivedData failed");
        goto exit;
    }

    lStatus = aEndPoint->GetPeerInfo(&lPeerAddress, &lPeerPort);
    INET_FAIL_ERROR(lStatus, "TCPEndPoint::GetPeerInfo failed");

    lPeerAddress.ToString(lPeerAddressBuffer);

    printf("TCP message received from %s:%u (%u bytes)\n", lPeerAddressBuffer, lPeerPort,
           static_cast<unsigned int>(aBuffer->DataLength()));

    lCheckPassed = HandleDataReceived(aBuffer, lCheckBuffer, lFirstValue);
    VerifyOrExit(lCheckPassed == true, lStatus = CHIP_ERROR_UNEXPECTED_EVENT);

    lStatus = aEndPoint->AckReceive(aBuffer->TotalLength());
    INET_FAIL_ERROR(lStatus, "TCPEndPoint::AckReceive failed");

exit:
    if (lStatus != CHIP_NO_ERROR)
    {
        SetStatusFailed(sTestState.mStatus);
    }
    return lStatus;
}

static void HandleTCPAcceptError(TCPEndPoint * aEndPoint, CHIP_ERROR aError)
{
    printf("TCP accept error: %s\n", ErrorStr(aError));

    SetStatusFailed(sTestState.mStatus);
}

static void HandleTCPConnectionReceived(TCPEndPoint * aListenEndPoint, TCPEndPoint * aConnectEndPoint,
                                        const IPAddress & aPeerAddress, uint16_t aPeerPort)
{
    char lPeerAddressBuffer[INET6_ADDRSTRLEN];

    aPeerAddress.ToString(lPeerAddressBuffer);

    printf("TCP connection accepted from %s:%u\n", lPeerAddressBuffer, aPeerPort);

    aConnectEndPoint->OnConnectComplete  = HandleTCPConnectionComplete;
    aConnectEndPoint->OnConnectionClosed = HandleTCPConnectionClosed;
    aConnectEndPoint->OnDataSent         = HandleTCPDataSent;
    aConnectEndPoint->OnDataReceived     = HandleTCPDataReceived;

    sTCPIPEndPoint = aConnectEndPoint;
}

// UDP Endpoint Callbacks

static void HandleUDPMessageReceived(UDPEndPoint * aEndPoint, PacketBufferHandle && aBuffer, const IPPacketInfo * aPacketInfo)
{
    const bool lCheckBuffer = true;
    bool lStatus;

    VerifyOrExit(aEndPoint != nullptr, lStatus = false);
    VerifyOrExit(!aBuffer.IsNull(), lStatus = false);
    VerifyOrExit(aPacketInfo != nullptr, lStatus = false);

    Common::HandleUDPMessageReceived(aEndPoint, aBuffer, aPacketInfo);

    lStatus = HandleDataReceived(aBuffer, lCheckBuffer);

exit:
    if (!lStatus)
    {
        SetStatusFailed(sTestState.mStatus);
    }
}

static void HandleUDPReceiveError(UDPEndPoint * aEndPoint, CHIP_ERROR aError, const IPPacketInfo * aPacketInfo)
{
    Common::HandleUDPReceiveError(aEndPoint, aError, aPacketInfo);

    SetStatusFailed(sTestState.mStatus);
}

static bool IsTransportReadyForSend()
{
    if ((gOptFlags & kOptFlagUseUDPIP) == kOptFlagUseUDPIP)
    {
        return (sUDPIPEndPoint != nullptr);
    }

    if ((gOptFlags & kOptFlagUseTCPIP) == kOptFlagUseTCPIP)
    {
        return (sTCPIPEndPoint != nullptr) && (sTCPIPEndPoint->PendingSendLength() == 0) &&
            TCPTest::StateIsConnectedOrReceiveShutdown(sTCPIPEndPoint);
    }

    return false;
}

static CHIP_ERROR PrepareTransportForSend()
{
    CHIP_ERROR lStatus = CHIP_NO_ERROR;

    if (gOptFlags & kOptFlagUseTCPIP)
    {
        if (sTCPIPEndPoint == nullptr)
        {
            lStatus = gTCP.NewEndPoint(&sTCPIPEndPoint);
            INET_FAIL_ERROR(lStatus, "TCP NewEndPoint failed");

            sTCPIPEndPoint->OnConnectComplete  = HandleTCPConnectionComplete;
            sTCPIPEndPoint->OnConnectionClosed = HandleTCPConnectionClosed;
            sTCPIPEndPoint->OnDataSent         = HandleTCPDataSent;
            sTCPIPEndPoint->OnDataReceived     = HandleTCPDataReceived;

            lStatus = sTCPIPEndPoint->Connect(sDestinationAddress, kTCPPort, gInterfaceId);
            INET_FAIL_ERROR(lStatus, "TCPEndPoint::Connect failed");
        }
    }

    return (lStatus);
}

static CHIP_ERROR DriveSendForDestination(const IPAddress & aAddress, uint16_t aSize)
{
    PacketBufferHandle lBuffer;

    if ((gOptFlags & kOptFlagUseUDPIP) == kOptFlagUseUDPIP)
    {
        const uint8_t lFirstValue = 0;

        // For UDP, we'll send n aSize or smaller datagrams, each
        // patterned from zero to aSize - 1.

        lBuffer = Common::MakeDataBuffer(aSize, lFirstValue);
        VerifyOrReturnError(!lBuffer.IsNull(), CHIP_ERROR_NO_MEMORY);

        ReturnErrorOnFailure(sUDPIPEndPoint->SendTo(aAddress, kUDPPort, std::move(lBuffer)));
    }
    else if ((gOptFlags & kOptFlagUseTCPIP) == kOptFlagUseTCPIP)
    {
        const uint32_t lFirstValue = sTestState.mStats.mTransmit.mActual;
        VerifyOrReturnError(lFirstValue < 256u, CHIP_ERROR_UNEXPECTED_EVENT);

        // For TCP, we'll send one byte stream of
        // sTestState.mStats.mTransmit.mExpected in n aSize or
        // smaller transactions, patterned from zero to
        // sTestState.mStats.mTransmit.mExpected - 1.

        lBuffer = Common::MakeDataBuffer(aSize, uint8_t(lFirstValue));
        VerifyOrReturnError(!lBuffer.IsNull(), CHIP_ERROR_NO_MEMORY);

        ReturnErrorOnFailure(sTCPIPEndPoint->Send(std::move(lBuffer)));
    }

    return CHIP_NO_ERROR;
}

void DriveSend()
{
    CHIP_ERROR lStatus = CHIP_NO_ERROR;

    if (!Common::IsSender())
        goto exit;

    if (!gSendIntervalExpired)
        goto exit;

    if (!IsTransportReadyForSend())
    {
        lStatus = PrepareTransportForSend();
        SuccessOrExit(lStatus);
    }
    else
    {
        gSendIntervalExpired = false;
        gSystemLayer.StartTimer(System::Clock::Milliseconds32(gSendIntervalMs), Common::HandleSendTimerComplete, nullptr);

        if (sTestState.mStats.mTransmit.mActual < sTestState.mStats.mTransmit.mExpected)
        {
            const uint32_t lRemaining = (sTestState.mStats.mTransmit.mExpected - sTestState.mStats.mTransmit.mActual);
            const uint32_t lSendSize  = chip::min(lRemaining, static_cast<uint32_t>(gSendSize));

            // gSendSize is uint16_t, so this cast is safe: the value has to be
            // in the uint16_t range.
            static_assert(std::is_same<decltype(gSendSize), uint16_t>::value, "Unexpected type for gSendSize");
            lStatus = DriveSendForDestination(sDestinationAddress, uint16_t(lSendSize));
            SuccessOrExit(lStatus);

            sTestState.mStats.mTransmit.mActual += lSendSize;

            printf("%" PRIu32 "/%" PRIu32 "transmitted to %s\n", sTestState.mStats.mTransmit.mActual,
                   sTestState.mStats.mTransmit.mExpected, sDestinationString);
        }
    }

exit:
    if (lStatus != CHIP_NO_ERROR)
    {
        SetStatusFailed(sTestState.mStatus);
    }
}

static void StartTest()
{
    IPAddressType lIPAddressType = IPAddressType::kIPv6;
    IPAddress lAddress           = chip::Inet::IPAddress::Any;
    CHIP_ERROR lStatus;

    if (!gNetworkOptions.LocalIPv6Addr.empty())
        lAddress = gNetworkOptions.LocalIPv6Addr[0];

#if INET_CONFIG_ENABLE_IPV4
    if (gOptFlags & kOptFlagUseIPv4)
    {
        lIPAddressType = IPAddressType::kIPv4;
        if (!gNetworkOptions.LocalIPv6Addr.empty())
            lAddress = gNetworkOptions.LocalIPv4Addr[0];
        else
            lAddress = chip::Inet::IPAddress::Any;
    }
#endif // INET_CONFIG_ENABLE_IPV4

    // clang-format off
    printf("Using %sIP%s, device interface: %s (w/%c LwIP)\n",
           ((gOptFlags & kOptFlagUseTCPIP) ? "TCP/" : "UDP/"),
           ((gOptFlags & kOptFlagUseIPv4) ? "v4" : "v6"),
           ((gInterfaceName) ? gInterfaceName : "<none>"),
           (CHIP_SYSTEM_CONFIG_USE_LWIP ? '\0' : 'o'));
    // clang-format on

    // Allocate the endpoints for sending or receiving.

    if (gOptFlags & kOptFlagUseUDPIP)
    {
        lStatus = gUDP.NewEndPoint(&sUDPIPEndPoint);
        INET_FAIL_ERROR(lStatus, "UDP NewEndPoint failed");

        if (gInterfaceId.IsPresent())
        {
            lStatus = sUDPIPEndPoint->BindInterface(lIPAddressType, gInterfaceId);
            INET_FAIL_ERROR(lStatus, "UDPEndPoint::BindInterface failed");
        }
    }

    if (Common::IsReceiver())
    {
        if (gOptFlags & kOptFlagUseUDPIP)
        {
            lStatus = sUDPIPEndPoint->Bind(lIPAddressType, IPAddress::Any, kUDPPort);
            INET_FAIL_ERROR(lStatus, "UDPEndPoint::Bind failed");

            lStatus = sUDPIPEndPoint->Listen(HandleUDPMessageReceived, HandleUDPReceiveError);
            INET_FAIL_ERROR(lStatus, "UDPEndPoint::Listen failed");
        }
        else if (gOptFlags & kOptFlagUseTCPIP)
        {
            const uint16_t lConnectionBacklogMax = 1;
            const bool lReuseAddress             = true;

            lStatus = gTCP.NewEndPoint(&sTCPIPListenEndPoint);
            INET_FAIL_ERROR(lStatus, "TCP NewEndPoint failed");

            sTCPIPListenEndPoint->OnConnectionReceived = HandleTCPConnectionReceived;
            sTCPIPListenEndPoint->OnAcceptError        = HandleTCPAcceptError;

            lStatus = sTCPIPListenEndPoint->Bind(lIPAddressType, IPAddress::Any, kTCPPort, lReuseAddress);
            INET_FAIL_ERROR(lStatus, "TCPEndPoint::Bind failed");

            lStatus = sTCPIPListenEndPoint->Listen(lConnectionBacklogMax);
            INET_FAIL_ERROR(lStatus, "TCPEndPoint::Listen failed");
        }
    }

    if (Common::IsReceiver())
        printf("Listening...\n");
    else
        DriveSend();
}

static void CleanupTest()
{
    gSendIntervalExpired = false;
    gSystemLayer.CancelTimer(Common::HandleSendTimerComplete, nullptr);

    // Release the resources associated with the allocated end points.

    if (sTCPIPEndPoint != nullptr)
    {
        sTCPIPEndPoint->Close();
        sTCPIPEndPoint->Free();
    }

    if (sTCPIPListenEndPoint != nullptr)
    {
        sTCPIPListenEndPoint->Shutdown();
        sTCPIPListenEndPoint->Free();
    }

    if (sUDPIPEndPoint != nullptr)
    {
        sUDPIPEndPoint->Free();
    }
}
