/*
 *
 *    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 runs a BDXServer acting as a simple client that will upload/download
 *      the specified file by connecting to a server that you specify.  The callbacks
 *      used to define application logic are defined in weave-bdx-common.*
 *      To run the client on the same local machine as the server for testing purposes,
 *      use this command:
 *          ./weave-bdx-client 1@127.0.0.1 [...]
 *      If you used the same advice given in weave-bdx-server.cpp, the server will be
 *      bound to the localhost address and so contacting that IP address will properly
 *      route messages to it to that process while allowing both processes to use the
 *      same Weave port.
 *
 */

#define __STDC_FORMAT_MACROS

#define WEAVE_CONFIG_BDX_NAMESPACE kWeaveManagedNamespace_Development

#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>

#include <Weave/Core/WeaveSecurityMgr.h>
#include <Weave/Profiles/security/WeaveSecurity.h>
#include <Weave/Profiles/bulk-data-transfer/Development/BulkDataTransfer.h>
#include <Weave/Support/logging/WeaveLogging.h>

#include "ToolCommon.h"
#include "weave-bdx-common-development.h"

#define TOOL_NAME "weave-bdx-client-development"

#define BDX_CLIENT_DEFAULT_START_OFFSET    0
#define BDX_CLIENT_DEFAULT_FILE_LENGTH     0
#define BDX_CLIENT_DEFAULT_MAX_BLOCK_SIZE  512

using nl::StatusReportStr;
using namespace nl::Weave::Profiles;
using namespace nl::Weave::Profiles::WeaveMakeManagedNamespaceIdentifier(BDX, kWeaveManagedNamespaceDesignation_Development);
using namespace nl::Weave::Profiles::Security;
using namespace nl::Weave::Logging;

static bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg);
static bool HandleNonOptionArgs(const char *progName, int argc, char *argv[]);
static void PreTest();
static void HandleConnectionReceived(WeaveMessageLayer *msgLayer, WeaveConnection *con);
static void StartClientConnection(System::Layer* lSystemLayer, void* aAppState, System::Error aError);
static void StartUDPUpload();
static void StartUDPDownload();
static void HandleConnectionComplete(WeaveConnection *con, WEAVE_ERROR conErr);
static void HandleConnectionClosed(WeaveConnection *con, WEAVE_ERROR conErr);
static void HandleTransferTimeout(System::Layer* aSystemLayer, void* aAppState, System::Error aError);
static WEAVE_ERROR PrepareBinding();
static void HandleBindingEvent(void *const ctx, const Binding::EventType event, const Binding::InEventParam &inParam, Binding::OutEventParam &outParam);

BdxClient BDXClient;
BdxAppState * appState;

bool Listening = false;
uint32_t ConnectInterval = 200;  //ms
uint32_t TransferTimeout = 3000;  //ms
uint32_t ConnectTry = 0;
uint32_t ConnectMaxTry = 3;
uint64_t StartOffset = BDX_CLIENT_DEFAULT_START_OFFSET;
uint64_t FileLength = BDX_CLIENT_DEFAULT_FILE_LENGTH;
uint64_t MaxBlockSize = BDX_CLIENT_DEFAULT_MAX_BLOCK_SIZE;
bool Upload = false; // download by default
bool UseTCP = true;
const char *DestIPAddrStr = NULL;
const char *RequestedFileName = NULL;
const char *ReceivedFileLocation = NULL;
bool ClientConEstablished = false;
bool Pretest = false;

//Globals used by BDX-client
bool WaitingForBDXResp = false;
uint64_t DestNodeId = 1;
IPAddress DestIPAddr;
WeaveConnection *Con = NULL;
nl::Weave::Binding *TheBinding = NULL;


static OptionDef gToolOptionDefs[] =
{
    { "requested-file", kArgumentRequired, 'r' },
    { "start-offset",   kArgumentRequired, 's' },
    { "length",         kArgumentRequired, 'l' },
    { "block-size",     kArgumentRequired, 'b' },
    { "dest-addr",      kArgumentRequired, 'D' },
    { "received-loc",   kArgumentRequired, 'R' },
    { "debug",          kArgumentRequired, 'd' },
    { "upload",         kNoArgument,       'p' },
    { "tcp",            kNoArgument,       't' },
    { "udp",            kNoArgument,       'u' },
    { "pretest",        kNoArgument,       'T' },
    { }
};

static const char *gToolOptionHelp =
    "  -r, --requested-file <filename>\n"
    "       File to request from the sender for an upload, or file to send for a download.\n"
    "       Normally a URL for upload (ex. www.google.com), and a local path for download\n"
    "       (ex. testing.txt). Accepts paths relative to current working directory\n"
    "\n"
    "  -s, --start-offset <num>\n"
    "       Start offset to request when downloading (in bytes)\n"
    "\n"
    "  -l, --length <num>\n"
    "       Length of file to request when downloading (in bytes). 0 means indefinite (whole file).\n"
    "\n"
    "  -b, --block-size <num>\n"
    "       Max block size to propose in a transfer. Defaults to 512.\n"
    "\n"
    "  -D, --dest-addr <ip-addr>\n"
    "       Send ReceiveInit requests to a specific address rather than one\n"
    "       derived from the destination node id.  <ip-addr> can be an IPv4 or IPv6 address.\n"
    "\n"
    "  -R, --received-loc <path>\n"
    "       Location to save a file from a receive transfer.\n"
    "\n"
    "  -p, --upload\n"
    "       Upload a file to the BDX server rather than download one from it, which is the default.\n"
    "\n"
    "  -t, --tcp\n"
    "       Use TCP to send BDX Requests. This is the default.\n"
    "\n"
    "  -u, --udp\n"
    "       Use UDP to send BDX Requests.\n"
    "\n"
    "  -T, --pretest\n"
    "       Perform initial unit tests.\n"
    "\n"
    "  -d, --debug\n"
    "       Enable debug messages.\n"
    "\n";

static OptionSet gToolOptions =
{
    HandleOption,
    gToolOptionDefs,
    "GENERAL OPTIONS",
    gToolOptionHelp
};

static HelpOptions gHelpOptions(
    TOOL_NAME,
    "Usage: " TOOL_NAME " [<options...>] <dest-node-id>[@<dest-ip-addr>]\n",
    WEAVE_VERSION_STRING "\n" WEAVE_TOOL_COPYRIGHT
);

static OptionSet *gToolOptionSets[] =
{
    &gToolOptions,
    &gNetworkOptions,
    &gWeaveNodeOptions,
    &gWRMPOptions,
    &gFaultInjectionOptions,
    &gHelpOptions,
    NULL
};

static void ResetTestContext(void)
{
    appState->mDone = false;
}

static bool sTransferTimerIsRunning = false;

static int32_t GetNumAsyncEventsAvailable(void)
{
    int32_t retval = 0;

    if (sTransferTimerIsRunning)
    {
        retval = 1;
    }

    return retval;
}

static void ExpireTimer(int32_t argument)
{
    (void)argument;

    SystemLayer.StartTimer(0, HandleTransferTimeout, NULL);
}

int main(int argc, char *argv[])
{
    WEAVE_ERROR err;
    nl::Weave::System::Stats::Snapshot before;
    nl::Weave::System::Stats::Snapshot after;
    const bool printStats = true;
    uint32_t iter;

    InitToolCommon();

    SetupFaultInjectionContext(argc, argv, GetNumAsyncEventsAvailable, ExpireTimer);
    SetSIGUSR1Handler();

    if (!ParseArgsFromEnvVar(TOOL_NAME, TOOL_OPTIONS_ENV_VAR_NAME, gToolOptionSets, NULL, true) ||
        !ParseArgs(TOOL_NAME, argc, argv, gToolOptionSets, HandleNonOptionArgs) ||
        !ResolveWeaveNetworkOptions(TOOL_NAME, gWeaveNodeOptions, gNetworkOptions))
    {
        exit(EXIT_FAILURE);
    }

    // This test program enables faults and stats prints always (no option taken from the CLI)
    gFaultInjectionOptions.DebugResourceUsage = true;
    gFaultInjectionOptions.PrintFaultCounters = true;

    if (Pretest)
        PreTest();

    if (RequestedFileName == NULL)
    {
        printf("No destination file name given in -r argument\n");
        exit(EXIT_FAILURE);
    }

    InitSystemLayer();
    InitNetwork();
    InitWeaveStack(Listening || !UseTCP, true);
    ResetAppStates();

    nl::Weave::Stats::UpdateSnapshot(before);

    appState = NewAppState();

    // Arrange to get called for various activity in the message layer.
    MessageLayer.OnConnectionReceived = HandleConnectionReceived;
    MessageLayer.OnReceiveError = HandleMessageReceiveError;
    MessageLayer.OnAcceptError = HandleAcceptConnectionError;

    PrintNodeConfig();

    if (DestNodeId == 0)
        printf("Sending BDX requests to node at %s\n", DestIPAddrStr);
    else if (DestIPAddrStr == NULL)
        printf("Sending BDX requests to node %" PRIX64 "\n", DestNodeId);
    else
        printf("Sending BDX requests to node %" PRIX64 " at %s\n", DestNodeId, DestIPAddrStr);

    appState->mDone = false;

#if !(WEAVE_CONFIG_BDX_CLIENT_SEND_SUPPORT)
    if (Upload)
    {
        printf("Cannot upload with WEAVE_CONFIG_BDX_CLIENT_SEND_SUPPORT disabled.\n");
        exit(EXIT_FAILURE);
    }
#endif

#if !(WEAVE_CONFIG_BDX_CLIENT_RECEIVE_SUPPORT)
    if (!Upload)
    {
        printf("Cannot download with WEAVE_CONFIG_BDX_CLIENT_RECEIVE_SUPPORT disabled.\n");
        exit(EXIT_FAILURE);
    }
#endif

    err = BDXClient.Init(&ExchangeMgr);
    if (err != WEAVE_NO_ERROR)
    {
        printf("BulkDataTransferClient::Init failed: %s\n", ErrorStr(err));
        exit(EXIT_FAILURE);
    }

    for (iter = 0; iter < gFaultInjectionOptions.TestIterations; iter++)
    {
        printf("Iteration %u\n", iter);

        // Init the client again in case the previous iteration failed with a timeout
        (void)BDXClient.Init(&ExchangeMgr);

        if (UseTCP)
        {
            err = SystemLayer.StartTimer(ConnectInterval, StartClientConnection, NULL);
            if (err != WEAVE_NO_ERROR)
            {
                printf("Inet.StartTimer failed\n");
                exit(EXIT_FAILURE);
            }
        }
        else
        {
            err = PrepareBinding();
            if (err != WEAVE_NO_ERROR)
            {
                appState->mDone = true;
            }
        }

        while (!appState->mDone)
        {
            struct timeval sleepTime;
            sleepTime.tv_sec = 0;
            sleepTime.tv_usec = 100000;

            ServiceNetwork(sleepTime);
        }

        if (appState->mFile)
        {
            fclose(appState->mFile);
            appState->mFile = NULL;
        }

        if (Con)
        {
            Con->Close();
            Con = NULL;
        }

        if (TheBinding)
        {
            TheBinding->Release();
            TheBinding = NULL;
        }

        SystemLayer.CancelTimer(HandleTransferTimeout, NULL);
        sTransferTimerIsRunning = false;

        ResetTestContext();
    }

    BDXClient.Shutdown();

    ProcessStats(before, after, printStats, NULL);
    PrintFaultInjectionCounters();

    ShutdownWeaveStack();

    return EXIT_SUCCESS;
}

static void HandleTransferTimeout(System::Layer* aSystemLayer, void* aAppState, System::Error aError)
{
    printf("transfer timeout\n");

    sTransferTimerIsRunning = false;
    appState->mDone = true;
    BDXClient.Shutdown();
}

static void StartClientConnection(System::Layer* lSystemLayer, void* aAppState, System::Error aError)
{
    printf("@@@ 0 StartClientConnection entering (Con: %p)\n", Con);

    if (Con != NULL && Con->State == WeaveConnection::kState_Closed)
    {
        printf("@@@ 1 remove previous con (currently closed)\n");
        Con->Close();
        Con = NULL;
    }

    // Do nothing if a connect attempt is already in progress.
    if (Con != NULL)
    {
        printf("@@@ 2 (Con: %p) previous Con likely hanging\n", Con);
        return;
    }

    //TODO: move this to BDX logic
    Con = MessageLayer.NewConnection();
    if (Con == NULL)
    {
        printf("@@@ 3 WeaveConnection.Connect failed: no memory\n");
        return;
    }
    printf("@@@ 3+ (Con: %p)\n", Con);
    Con->OnConnectionComplete = HandleConnectionComplete;
    Con->OnConnectionClosed = HandleConnectionClosed;

    printf("@@@ 3++ (DestNodeId: %" PRIX64 ", DestIPAddrStr: %s)\n", DestNodeId, DestIPAddrStr);

    WEAVE_ERROR err;
    if (DestIPAddrStr)
    {
        IPAddress::FromString(DestIPAddrStr, DestIPAddr);
        err = Con->Connect(DestNodeId, kWeaveAuthMode_Unauthenticated, DestIPAddr);
    }
    else // not specified, derive from NodeID
    {
        err = Con->Connect(DestNodeId);
    }

    if (err != WEAVE_NO_ERROR)
    {
        printf("@@@ 4 WeaveConnection.Connect failed: %X (%s)\n", err, ErrorStr(err));
        Con->Close();
        Con = NULL;
        return;
    }

    ConnectTry++;
    printf("@@@ 5 StartClientConnection exiting\n");
}

void StartUDPUpload()
{
#if WEAVE_CONFIG_BDX_CLIENT_SEND_SUPPORT
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    BDXTransfer *xfer;
    ReferencedString refRequestedFileName, refFileName;
    char *filename = NULL;

    refRequestedFileName.init((uint16_t)strlen(RequestedFileName), (char *)RequestedFileName);

    BDXHandlers handlers =
    {
        BdxSendAcceptHandler, // SendAcceptHandler
        NULL,                 // ReceiveAcceptHandler
        BdxRejectHandler,     // RejectHandler
        BdxGetBlockHandler,   // GetBlockHandler
        NULL,                 // PutBlockHandler
        BdxXferErrorHandler,  // XferErrorHandler
        BdxXferDoneHandler,   // XferDoneHandler
        BdxErrorHandler       // ErrorHandler
    };

    err = BDXClient.NewTransfer(TheBinding, handlers, refRequestedFileName, appState, xfer);

    if (err != WEAVE_NO_ERROR)
    {
        printf("@@@ 6 BDXClient.NewTransfer() failed: %d\n", err);
        appState->mDone = true;
        TheBinding->Release();
        TheBinding = NULL;
        return;
    }

    xfer->mMaxBlockSize = MaxBlockSize;
    xfer->mStartOffset = StartOffset;
    xfer->mLength = FileLength;

    if (err == WEAVE_NO_ERROR)
    {
        // In the test-app, we need to make sure we only send the file name
        // in the mFileDesignator.
        filename = strrchr(refRequestedFileName.theString, '/');
        if (filename != NULL)
        {
            filename++; //skip over '/'
            refFileName.init((uint16_t)strlen(filename), filename);
            xfer->mFileDesignator = refFileName;
        }

        err = BDXClient.InitBdxSend(*xfer, true, false, false, NULL);

        // Set it back to what it was before so we can grab it when we're sending
        xfer->mFileDesignator = refRequestedFileName;

        WaitingForBDXResp = true;
    }
    else
    {
        printf("@@@ 6 BDXClient.StartUDPUpload() failed: %d\n", err);
        appState->mDone = true;
        BDXClient.ShutdownTransfer(xfer);
        TheBinding->Release();
        TheBinding = NULL;
    }
#endif // WEAVE_CONFIG_BDX_CLIENT_SEND_SUPPORT
}

void StartUDPDownload()
{
#if WEAVE_CONFIG_BDX_CLIENT_RECEIVE_SUPPORT
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    BDXTransfer *xfer;
    ReferencedString refRequestedFileName;

    refRequestedFileName.init((uint16_t)strlen(RequestedFileName), (char *)RequestedFileName);

    BDXHandlers handlers =
    {
        NULL,                    // SendAcceptHandler
        BdxReceiveAcceptHandler, // ReceiveAcceptHandler
        BdxRejectHandler,        // RejectHandler
        NULL,                    // GetBlockHandler
        BdxPutBlockHandler,      // PutBlockHandler
        BdxXferErrorHandler,     // XferErrorHandler
        BdxXferDoneHandler,      // XferDoneHandler
        BdxErrorHandler          // ErrorHandler
    };

    err = BDXClient.NewTransfer(TheBinding, handlers, refRequestedFileName, appState, xfer);

    if (err != WEAVE_NO_ERROR)
    {
        printf("@@@ 6 BDXClient.NewTransfer() failed: %d\n", err);
        appState->mDone = true;
        TheBinding->Release();
        TheBinding = NULL;
        return;
    }

    xfer->mMaxBlockSize = MaxBlockSize;
    xfer->mStartOffset = StartOffset;
    xfer->mLength = FileLength;

    err = BDXClient.InitBdxReceive(*xfer, true, false, false, NULL);

    if (err == WEAVE_NO_ERROR)
    {
        WaitingForBDXResp = true;
    }
    else
    {
        printf("@@@ 6 BDXClient.StartUDPDownload() failed: %d\n", err);
        appState->mDone = true;
        BDXClient.ShutdownTransfer(xfer);
        TheBinding->Release();
        TheBinding = NULL;
    }
#endif // WEAVE_CONFIG_BDX_CLIENT_RECEIVE_SUPPORT
}

bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg)
{
    switch (id)
    {
    case 'r':
        RequestedFileName = arg;
        break;
    case 's':
        if (!ParseInt(arg, StartOffset))
        {
            PrintArgError("%s: Invalid value specified for start offset: %s\n", progName, arg);
            return false;
        }
        break;
    case 'l':
        if (!ParseInt(arg, FileLength))
        {
            PrintArgError("%s: Invalid value specified for length: %s\n", progName, arg);
            return false;
        }
        break;
    case 'b':
        if (!ParseInt(arg, MaxBlockSize))
        {
            PrintArgError("%s: Invalid value specified for max block size: %s\n", progName, arg);
            return false;
        }
        break;
    case 'R':
        ReceivedFileLocation = arg;
        SetReceivedFileLocation(ReceivedFileLocation);
        break;
    case 'p':
        Upload = true;
        break;
    case 'T':
        Pretest = true;
        break;
    case 't':
        UseTCP = true;
        break;
    case 'u':
        UseTCP = false;
        break;
    case 'D':
        DestIPAddrStr = arg;
        break;
    default:
        PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name);
        return false;
    }

    return true;
}

bool HandleNonOptionArgs(const char *progName, int argc, char *argv[])
{
    if (argc < 1)
    {
        PrintArgError("%s: Please specify a destination node id\n", progName);
        return false;
    }

    if (argc > 1)
    {
        PrintArgError("%s: Unexpected argument: %s\n", progName, argv[1]);
        return false;
    }

    const char *nodeId = argv[0];
    char *p = (char *)strchr(nodeId, '@');
    if (p != NULL)
    {
        *p = 0;
        DestIPAddrStr = p+1;
    }

    if (!ParseNodeId(nodeId, DestNodeId))
    {
        PrintArgError("%s: Invalid value specified for destination node-id: %s\n", progName, nodeId);
        return false;
    }

    return true;
}

void HandleConnectionReceived(WeaveMessageLayer *msgLayer, WeaveConnection *con)
{
    char ipAddrStr[64];
    con->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));

    printf("Connection received from node %" PRIX64 " (%s)\n", con->PeerNodeId, ipAddrStr);

    con->OnConnectionClosed = HandleConnectionClosed;
}

void HandleConnectionComplete(WeaveConnection *con, WEAVE_ERROR conErr)
{
    printf("@@@ 1 HandleConnectionComplete entering\n");

    WEAVE_ERROR err;
    char ipAddrStr[64];

    con->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));

    if (conErr != WEAVE_NO_ERROR)
    {
        printf("Connection FAILED to node %" PRIX64 " (%s): %s\n", con->PeerNodeId, ipAddrStr, ErrorStr(conErr));
        con->Close();
        Con = NULL;

        if (ConnectTry < ConnectMaxTry)
        {
            err = SystemLayer.StartTimer(ConnectInterval, StartClientConnection, NULL);
            if (err != WEAVE_NO_ERROR)
            {
                printf("Inet.StartTimer failed\n");
                exit(EXIT_FAILURE);
            }
        }
        else
        {
            printf("Connection FAILED to node %" PRIX64 " (%s) after %d attempts\n", con->PeerNodeId, ipAddrStr, ConnectTry);
            exit(EXIT_FAILURE);
        }

        ClientConEstablished = false;
        return;
    }

    printf("Connection established to node %" PRIX64 " (%s)\n", con->PeerNodeId, ipAddrStr);

    err = SystemLayer.StartTimer(TransferTimeout, HandleTransferTimeout, NULL);
    if (err != WEAVE_NO_ERROR)
    {
        printf("Inet.StartTimer failed\n");
        exit(EXIT_FAILURE);
    }
    sTransferTimerIsRunning = true;

    ClientConEstablished = true;

    //Send the ReceiveInit or SendInit request
    if (Con != NULL)
    {
        ReferencedString refRequestedFileName, refFileName;
        refRequestedFileName.init((uint16_t)strlen(RequestedFileName), (char *)RequestedFileName);

        // Initialize the BDX-client application.
        appState->mFile = NULL;

        printf("@@@ 4 Sending TCP bdx request\n");
        if (Upload)
        {
#if WEAVE_CONFIG_BDX_CLIENT_SEND_SUPPORT
            char *filename = NULL;
            BDXTransfer * xfer;
            BDXHandlers handlers =
            {
                BdxSendAcceptHandler, // SendAcceptHandler
                NULL,                 // ReceiveAcceptHandler
                BdxRejectHandler,     // RejectHandler
                BdxGetBlockHandler,   // GetBlockHandler
                NULL,                 // PutBlockHandler
                BdxXferErrorHandler,  // XferErrorHandler
                BdxXferDoneHandler,   // XferDoneHandler
                BdxErrorHandler       // ErrorHandler
            };

            err = BDXClient.NewTransfer(Con, handlers, refRequestedFileName, appState, xfer);

            if (err == WEAVE_NO_ERROR)
            {
                // In the test-app, we need to make sure we only send the file name
                // in the mFileDesignator.
                WeaveLogDetail(BDX, "%s", refRequestedFileName.theString);

                filename = strrchr(refRequestedFileName.theString, '/');
                if (filename != NULL)
                {
                    filename++; //skip over '/'
                    refFileName.init((uint16_t)strlen(filename), filename);
                    xfer->mFileDesignator = refFileName;
                }

                err = BDXClient.InitBdxSend(*xfer, true, false, false, NULL);

                // Set it back to what it was before so we can grab it when we're sending
                xfer->mFileDesignator = refRequestedFileName;
            }
#endif // WEAVE_CONFIG_BDX_CLIENT_SEND_SUPPORT
        }
        else
        {
#if WEAVE_CONFIG_BDX_CLIENT_RECEIVE_SUPPORT
            BDXTransfer * xfer;
            BDXHandlers handlers =
            {
                NULL,                    // SendAcceptHandler
                BdxReceiveAcceptHandler, // ReceiveAcceptHandler
                BdxRejectHandler,        // RejectHandler
                NULL,                    // GetBlockHandler
                BdxPutBlockHandler,      // PutBlockHandler
                BdxXferErrorHandler,     // XferErrorHandler
                BdxXferDoneHandler,      // XferDoneHandler
                BdxErrorHandler          // ErrorHandler
            };

            err = BDXClient.NewTransfer(Con, handlers, refRequestedFileName, appState, xfer);

            if (err == WEAVE_NO_ERROR)
            {
                err = BDXClient.InitBdxReceive(*xfer, true, false, false, NULL);
            }
#endif // WEAVE_CONFIG_BDX_CLIENT_RECEIVE_SUPPORT
        }
    }
    else
    {
        printf("Non-connection Init Requests not supported!\n");
        exit(EXIT_FAILURE);
    }

    if (err == WEAVE_NO_ERROR)
    {
        WaitingForBDXResp = true;
    }
    else
    {
        printf("@@@ 6 BDXClient.SendRequest() failed: %X\n", err);
        if (Con)
        {
            Con->Close();
            Con = NULL;
        }
    }

    printf("@@@ 7 HandleConnectionComplete exiting\n");
}

void HandleConnectionClosed(WeaveConnection *con, WEAVE_ERROR conErr)
{
    char ipAddrStr[64];
    con->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));

    if (conErr == WEAVE_NO_ERROR)
        printf("Connection closed to node %" PRIX64 " (%s)\n", con->PeerNodeId, ipAddrStr);
    else
        printf("Connection ABORTED to node %" PRIX64 " (%s): %s\n", con->PeerNodeId, ipAddrStr, ErrorStr(conErr));

    WaitingForBDXResp = false;

    if (Listening)
        con->Close();
    else if (con == Con)
    {
        con->Close();
        Con = NULL;
    }
}

WEAVE_ERROR PrepareBinding()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Get the binding.
    TheBinding = ExchangeMgr.NewBinding(HandleBindingEvent, NULL);
    if (TheBinding == NULL)
    {
        printf("NewBinding failed: no memory\n");
        err = WEAVE_ERROR_NO_MEMORY;
        ExitNow();
    }
    else
    {
        // Configure the binding.
        nl::Weave::Binding::Configuration bindingConfig = TheBinding->BeginConfiguration()
            .Target_NodeId(DestNodeId)
            .Transport_UDP()
            .Security_None();

        if (DestIPAddrStr)
        {
            IPAddress::FromString(DestIPAddrStr, DestIPAddr);
            bindingConfig.TargetAddress_IP(DestIPAddr);
        }

        // Prepare the binding. Will finish asynchronously.
        err = bindingConfig.PrepareBinding();
        VerifyOrExit(err == WEAVE_NO_ERROR, printf("PrepareBinding failed\n"));
    }

exit:
    return err;
}

void HandleBindingEvent(void *const ctx, const Binding::EventType event, const Binding::InEventParam &inParam, Binding::OutEventParam &outParam)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    switch (event)
    {
    case nl::Weave::Binding::kEvent_BindingReady:
        err = SystemLayer.StartTimer(TransferTimeout, HandleTransferTimeout, NULL);
        if (err != WEAVE_NO_ERROR)
        {
            printf("Inet.StartTimer failed\n");
            return;
        }
        sTransferTimerIsRunning = true;

        if (Upload)
        {
            StartUDPUpload();
        }
        else
        {
            StartUDPDownload();
        }

        break;
    case nl::Weave::Binding::kEvent_PrepareFailed:
        printf("Binding prepare failed\n");
        break;
    default:
        nl::Weave::Binding::DefaultEventHandler(ctx, event, inParam, outParam);
    }
}

// unit tests to cover the codes that functional test failed to cover
void PreTest()
{
    SendInit sendInit;
    SendAccept sendAccept;
    ReceiveAccept receiveAccept;
    BlockQuery blockQuery;
    BlockSend blockSend;
    BlockSendV1 blockSendV1;
    BlockQueryV1 blockQueryV1;

    if (!(sendInit == sendInit)) {
        printf("SendAccept::operator== failed\n");
        exit(EXIT_FAILURE);
    }
    printf("the default length of SendInit is %d\n", sendInit.packedLength());

    if (!(sendAccept == sendAccept)) {
        printf("SendAccept::operator== failed\n");
        exit(EXIT_FAILURE);
    }
    printf("the default length of SendAccept is %d\n", sendAccept.packedLength());

    if (!(receiveAccept == receiveAccept)) {
        printf("ReceiveAccept::operator== failed\n");
        exit(EXIT_FAILURE);
    }
    printf("the default length of ReceiveAccept is %d\n", receiveAccept.packedLength());

    if (!(blockQuery == blockQuery)) {
        printf("BlockQuery::operator== failed\n");
        exit(EXIT_FAILURE);
    }
    printf("the default length of BlockQuery is %d\n", blockQuery.packedLength());

    if (!(blockSend == blockSend)) {
        printf("BlockSend::operator== failed\n");
        exit(EXIT_FAILURE);
    }
    printf("the default length of BlockSend is %d\n", blockSend.packedLength());

    if (!(blockSendV1 == blockSendV1)) {
        printf("BlockSendV1::operator== failed\n");
        exit(EXIT_FAILURE);
    }
    printf("the default length of BlockSendV1 is %d\n", blockSendV1.packedLength());

    if (!(blockQueryV1 == blockQueryV1)) {
        printf("BlockQueryV1::operator== failed\n");
        exit(EXIT_FAILURE);
    }
    printf("the default length of BlockQueryV1 is %d\n", blockQueryV1.packedLength());
}
