/*
 *
 *    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 the WeaveConnection class. It manages
 *      communication over a TCP connection between Weave nodes.
 *
 */

#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif

#include <inttypes.h>

#include <Weave/Core/WeaveCore.h>
#include <Weave/Support/logging/WeaveLogging.h>
#include <Weave/Support/CodeUtils.h>

#include <SystemLayer/SystemStats.h>
#include <SystemLayer/SystemTimer.h>
#include <InetLayer/InetLayer.h>

#if WEAVE_CONFIG_TCP_CONN_REPAIR_SUPPORTED
#define CONN_REPAIR_APP_CALLBACK_DELAY_MSECS                    (1)
#endif // WEAVE_CONFIG_TCP_CONN_REPAIR_SUPPORTED

namespace nl {
namespace Weave {

/**
 * Reserve a reference to the WeaveConnection object.
 *
 * The AddRef() method increments the reference count associated with the WeaveConnection object.  For every
 * call to AddRef(), the application is responsible for making a corresponding call to either Release(), Close()
 * or Abort().
 */
void WeaveConnection::AddRef()
{
    VerifyOrDie(mRefCount < UINT8_MAX);
    ++mRefCount;
}

/**
 *  Decrement the reference count on the WeaveConnection object.
 *
 *  The Release() method decrements the reference count associated with the WeaveConnection object.  If
 *  this results in the reference count reaching zero, the connection is closed and the connection object
 *  is freed.  When this happens, the application must have no further interactions with the object.
 */
void WeaveConnection::Release()
{
    // If the only reference that will remain after this call is the one that was automatically added
    // when the connection started, close the connection.
    if (mRefCount == 2 && State != kState_ReadyToConnect && State != kState_Closed)
    {
        // Suppress callbacks.
        OnConnectionComplete = NULL;
        OnConnectionClosed = NULL;

        // Perform a graceful close.
        DoClose(WEAVE_NO_ERROR, kDoCloseFlag_SuppressCallback);
    }

    VerifyOrDie(mRefCount != 0);
    mRefCount--;
}

WEAVE_ERROR WeaveConnection::StartConnectToAddressLiteral(const char *peerAddr, size_t peerAddrLen)
{
    WEAVE_ERROR err = WEAVE_ERROR_UNSUPPORTED_WEAVE_FEATURE;

#if WEAVE_CONFIG_RESOLVE_IPADDR_LITERAL
    // Literal address conversion is only supported on BSD sockets network targets
    if (IPAddress::FromString(peerAddr, peerAddrLen, PeerAddr))
        err = StartConnect();
#endif // WEAVE_CONFIG_RESOLVE_IPADDR_LITERAL

    return err;
}

/**
 *  Connect to a Weave node using a fabric IP address derived from the specified node identifier.
 *
 *  @param[in]    peerNodeId    The node identifier of the peer.
 *
 *  @retval #WEAVE_NO_ERROR                      on successful initiation of the connection to the peer.
 *  @retval #WEAVE_ERROR_INCORRECT_STATE         if the WeaveConnection state is incorrect.
 *
 *  @retval #WEAVE_ERROR_UNSUPPORTED_AUTH_MODE   if the requested authentication mode is not supported.
 *
 *  @retval #WEAVE_ERROR_INVALID_ADDRESS         if the destination address cannot be deduced from the
 *                                               node id.
 *
 *  @retval other Inet layer errors generated by the TCPEndPoint connect operations.
 *
 */
WEAVE_ERROR WeaveConnection::Connect(uint64_t peerNodeId)
{
    return Connect(peerNodeId, IPAddress::Any);
}

/**
 *  Connect to a Weave node using a node identifier and/or an IP address.
 *
 *  @note
 *    If peerAddr is IPAddress::Any, the node's fabric IP address will be derived from the peerNodeId field.
 *    If peerNodeId is kNodeIdNotSpecified (0), the node's identifier will be derived (if possible)
 *    from the peerAddr. The connection will be made to the specified port, or the default
 *    #WEAVE_PORT if peerPort is 0.
 *
 *  @param[in]    peerNodeId    The node identifier of the peer, kNodeIdNotSpecified or 0 if
 *                              not known.
 *
 *  @param[in]    peerAddr      The IP address of the peer, IPAddress::Any if not known.
 *
 *  @param[in]    peerPort      The optional port of the peer, default to #WEAVE_PORT.
 *
 *  @retval #WEAVE_NO_ERROR                      on successful initiation of the connection to the peer.
 *  @retval #WEAVE_ERROR_INCORRECT_STATE         if the WeaveConnection state is incorrect.
 *
 *  @retval #WEAVE_ERROR_UNSUPPORTED_AUTH_MODE   if the requested authentication mode is not supported.
 *
 *  @retval #WEAVE_ERROR_INVALID_ADDRESS         if the destination address cannot be deduced from
 *                                               the node id.
 *
 *  @retval other Inet layer errors generated by the TCPEndPoint connect operations.
 *
 */
WEAVE_ERROR WeaveConnection::Connect(uint64_t peerNodeId, const IPAddress &peerAddr, uint16_t peerPort)
{
    return Connect(peerNodeId, kWeaveAuthMode_Unauthenticated, peerAddr, peerPort, INET_NULL_INTERFACEID);
}

/**
 *  Connect to a Weave node using a node identifier and/or an IP address on a specific interface.
 *
 *  @note
 *    If peerAddr is IPAddress::Any, the node's fabric IP address will be derived from the peerNodeId field.
 *    If peerNodeId is kNodeIdNotSpecified (0), the node's identifier will be derived (if possible)
 *    from the peerAddr.  The connection will be made to the specified port, or the default
 *    #WEAVE_PORT if peerPort is 0.
 *
 *  @param[in]    peerNodeId    The node identifier of the peer, kNodeIdNotSpecified or 0 if
 *                              not known.
 *
 *  @param[in]    authMode      The desired authenticate mode for the peer. Only CASE, PASE and Unauthenticated
 *                              modes are supported.
 *
 *  @param[in]    peerAddr      The IP address of the peer, IPAddress::Any if not known.
 *
 *  @param[in]    peerPort      The optional port of the peer, default to #WEAVE_PORT.
 *
 *  @param[in]    intf          The optional interface to use to connect to the peer node,
 *                              default to #INET_NULL_INTERFACEID.
 *
 *  @retval #WEAVE_NO_ERROR                      on successful initiation of the connection to the peer.
 *  @retval #WEAVE_ERROR_INCORRECT_STATE         if the WeaveConnection state is incorrect.
 *
 *  @retval #WEAVE_ERROR_UNSUPPORTED_AUTH_MODE   if the requested authentication mode is not supported.
 *
 *  @retval #WEAVE_ERROR_INVALID_ADDRESS         if the destination address cannot be deduced from the
 *                                               node identifier.
 *
 *  @retval other Inet layer errors generated by the TCPEndPoint connect operations.
 *
 */
WEAVE_ERROR WeaveConnection::Connect(uint64_t peerNodeId, WeaveAuthMode authMode, const IPAddress &peerAddr, uint16_t peerPort, InterfaceId intf)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    VerifyOrExit(State == kState_ReadyToConnect, err = WEAVE_ERROR_INCORRECT_STATE);

    VerifyOrExit(authMode == kWeaveAuthMode_Unauthenticated || IsCASEAuthMode(authMode) || IsPASEAuthMode(authMode), err = WEAVE_ERROR_INVALID_ARGUMENT);

    // Can't request authentication if the security manager is not initialized.
    VerifyOrExit(authMode == kWeaveAuthMode_Unauthenticated || MessageLayer->SecurityMgr != NULL, err = WEAVE_ERROR_UNSUPPORTED_AUTH_MODE);

    // Application has made this an IP-based WeaveConnection.
    NetworkType = kNetworkType_IP;

    PeerNodeId = peerNodeId;
    PeerAddr = peerAddr;
    PeerPort = (peerPort != 0) ? peerPort : WEAVE_PORT;
    mTargetInterface = intf;
    AuthMode = authMode;

    // Bump the reference count when we start the connection process. The corresponding decrement happens when the
    // DoClose() method is called. This ensures the object stays live while there's the possibility of a callback
    // happening from an underlying layer (e.g. TCPEndPoint or DNS resolution).
    mRefCount++;

    WeaveLogProgress(MessageLayer, "Con start %04X %016llX %04X", LogId(), peerNodeId, authMode);

    err = StartConnect();
    SuccessOrExit(err);

exit:
    return err;
}

/**
 *  Connect to a Weave node using a node identifier and/or a string host name.  If supplied, peerAddr can
 *  be any of:
 *  @code
 *    <host-name>
 *    <host-name>:<port>
 *    <ip-4-addr>
 *    <ip-4-addr>:<port>
 *    <ip-6-addr>
 *    [<ip-6-addr>]:<port>
 *  @endcode
 *  @note
 *    If `<port>` is not supplied, defaultPort is used.  If defaultPort is 0, the default #WEAVE_PORT is used.
 *    If peerAddr is null, the node's fabric IP address will be derived from the peerNodeId field.  If peerNodeId
 *    is kNodeIdNotSpecified (0), the node's identifier will be derived (if possible) from the peer's IP address.
 *
 *  @param[in]    peerNodeId    The node identifier of the peer, kNodeIdNotSpecified or 0 if
 *                              not known.
 *
 *  @param[in]    authMode      The desired authenticate mode for the peer. Only CASE, PASE and Unauthenticated
 *                              modes are supported.
 *
 *  @param[in]    peerAddr      The address or hostname of the peer as a NULL-terminated C string.
 *
 *  @param[in]    defaultPort   The optional default port to use for the connection if not supplied in the peerAddr
 *                              string.
 *
 *  @retval #WEAVE_NO_ERROR                      on successful initiation of the connection to the peer.
 *  @retval #WEAVE_ERROR_INCORRECT_STATE         if the WeaveConnection state is incorrect.
 *
 *  @retval #WEAVE_ERROR_UNSUPPORTED_AUTH_MODE   if the requested authentication mode is not supported.
 *
 *  @retval #WEAVE_ERROR_INVALID_ADDRESS         if the destination address cannot be deduced from the node id.
 *
 *  @retval other Inet layer errors generated by the TCPEndPoint connect operations.
 *
 */
WEAVE_ERROR WeaveConnection::Connect(uint64_t peerNodeId, WeaveAuthMode authMode, const char *peerAddr, uint16_t defaultPort)
{
    return Connect(peerNodeId, authMode, peerAddr, (peerAddr != NULL) ? strlen(peerAddr) : 0, defaultPort);
}

/**
 *  Connect to a Weave node using a node identifier and/or a string peer address.
 *
 *  If supplied, peerAddr can be any of:
 *  @code
 *    <host-name>
 *    <host-name>:<port>
 *    <ip-4-addr>
 *    <ip-4-addr>:<port>
 *    <ip-6-addr>
 *    [<ip-6-addr>]:<port>
 *  @endcode
 *  @note
 *    If `<port>` is not supplied, defaultPort is used.  If defaultPort is 0, the default Weave port is used.
 *    If peerAddr is null, the node's fabric IP address will be derived from the peerNodeId field.  If peerNodeId
 *    is kNodeIdNotSpecified (0), the node's identifier will be derived (if possible) from the peer's IP address.
 *
 *  @param[in]    peerNodeId    The node identifier of the peer, kNodeIdNotSpecified or 0 if
 *                              not known.
 *
 *  @param[in]    authMode      The desired authenticate mode for the peer. Only CASE, PASE and Unauthenticated
 *                              modes are supported.
 *
 *  @param[in]    peerAddr      The address or hostname of the peer as a non-NULL-terminated C string.
 *
 *  @param[in]    peerAddrLen   The length of the peerAddr string.
 *
 *  @param[in]    defaultPort   The optional default port to use for the connection if not supplied in the peerAddr
 *                              string.
 *
 *  @retval #WEAVE_NO_ERROR                      on successful initiation of the connection to the peer.
 *  @retval #WEAVE_ERROR_INCORRECT_STATE         if the WeaveConnection state is incorrect.
 *
 *  @retval #WEAVE_ERROR_UNSUPPORTED_AUTH_MODE   if the requested authentication mode is not supported.
 *
 *  @retval #WEAVE_ERROR_INVALID_ADDRESS         if the destination address cannot be deduced from the node id.
 *
 *  @retval other Inet layer errors generated by the TCPEndPoint connect operations.
 *
 */
WEAVE_ERROR WeaveConnection::Connect(uint64_t peerNodeId, WeaveAuthMode authMode, const char *peerAddr,
                                     uint16_t peerAddrLen, uint16_t defaultPort)
{
#if WEAVE_CONFIG_ENABLE_DNS_RESOLVER
    const uint8_t dnsOptions = ::nl::Inet::kDNSOption_Default;
#else
    const uint8_t dnsOptions = 0;
#endif
    return Connect(peerNodeId, authMode, peerAddr, peerAddrLen, dnsOptions, defaultPort);
}

/**
 *  Connect to a Weave node using a node identifier and/or a string peer address.
 *
 *  If supplied, peerAddr can be any of:
 *  @code
 *    <host-name>
 *    <host-name>:<port>
 *    <ip-4-addr>
 *    <ip-4-addr>:<port>
 *    <ip-6-addr>
 *    [<ip-6-addr>]:<port>
 *  @endcode
 *  @note
 *    If `<port>` is not supplied, defaultPort is used.  If defaultPort is 0, the default Weave port is used.
 *    If peerAddr is null, the node's fabric IP address will be derived from the peerNodeId field.  If peerNodeId
 *    is kNodeIdNotSpecified (0), the node's identifier will be derived (if possible) from the peer's IP address.
 *
 *  @param[in]    peerNodeId    The node identifier of the peer, kNodeIdNotSpecified or 0 if
 *                              not known.
 *
 *  @param[in]    authMode      The desired authenticate mode for the peer. Only CASE, PASE and Unauthenticated
 *                              modes are supported.
 *
 *  @param[in]    peerAddr      The address or hostname of the peer as a non-NULL-terminated C string.
 *
 *  @param[in]    peerAddrLen   The length of the peerAddr string.
 *
 *  @param[in]    dnsOptions    An integer value controlling how host name resolution is performed.
 *                              Value should be the OR of one or more values from from the
 *                              #::nl::Inet::DNSOptions enumeration.
 *
 *  @param[in]    defaultPort   The optional default port to use for the connection if not supplied in the peerAddr
 *                              string.
 *
 *  @retval #WEAVE_NO_ERROR                      on successful initiation of the connection to the peer.
 *  @retval #WEAVE_ERROR_INCORRECT_STATE         if the WeaveConnection state is incorrect.
 *
 *  @retval #WEAVE_ERROR_UNSUPPORTED_AUTH_MODE   if the requested authentication mode is not supported.
 *
 *  @retval #WEAVE_ERROR_INVALID_ADDRESS         if the destination address cannot be deduced from the node id.
 *
 *  @retval other Inet layer errors generated by the TCPEndPoint connect operations.
 *
 */
WEAVE_ERROR WeaveConnection::Connect(uint64_t peerNodeId, WeaveAuthMode authMode, const char *peerAddr,
                                     uint16_t peerAddrLen, uint8_t dnsOptions, uint16_t defaultPort)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    const char *hostName;
    uint16_t hostNameLen;
    const char *intfName;
    uint16_t intfNameLen;

    VerifyOrExit(State == kState_ReadyToConnect, err = WEAVE_ERROR_INCORRECT_STATE);

    VerifyOrExit(authMode == kWeaveAuthMode_Unauthenticated || IsCASEAuthMode(authMode) || IsPASEAuthMode(authMode), err = WEAVE_ERROR_INVALID_ARGUMENT);

    // Can't request authentication if the security manager is not initialized.
    VerifyOrExit(authMode == kWeaveAuthMode_Unauthenticated || MessageLayer->SecurityMgr != NULL, err = WEAVE_ERROR_UNSUPPORTED_AUTH_MODE);

    // If no peer address given, connect using the node id.
    if (peerAddr == NULL || peerAddrLen == 0)
    {
        err = Connect(peerNodeId, authMode, IPAddress::Any, defaultPort);
        ExitNow();
    }

    // Application has made this an IP-based WeaveConnection.
    NetworkType = kNetworkType_IP;

    // Parse the address into a host, port and interface name.
    err = nl::Inet::ParseHostPortAndInterface(peerAddr, peerAddrLen, hostName, hostNameLen, PeerPort, intfName, intfNameLen);
    SuccessOrExit(err);
    if (PeerPort == 0)
        PeerPort = (defaultPort != 0) ? defaultPort : WEAVE_PORT;

    // If an interface name has been specified, attempt to convert it to a network interface id.
    if (intfName != NULL)
    {
        err = InterfaceNameToId(intfName, mTargetInterface);
        SuccessOrExit(err);
    }

    // Clear the list of resolved peer addresses in preparation for resolving the host name.
    memset(mPeerAddrs, 0, sizeof(mPeerAddrs));

    PeerNodeId = peerNodeId;
    AuthMode = authMode;

    // Bump the reference count when we start the connection process. The corresponding decrement happens when the
    // DoClose() method is called. This ensures the object stays live while there's the possibility of a callback
    // happening from an underlying layer (e.g. TCPEndPoint or DNS resolution).
    mRefCount++;

    WeaveLogProgress(MessageLayer, "Con start %04X %016llX %04X", LogId(), peerNodeId, authMode);

#if WEAVE_CONFIG_ENABLE_DNS_RESOLVER
    // Initiate the host name resolution.
    State = kState_Resolving;
    err = MessageLayer->Inet->ResolveHostAddress(hostName, hostNameLen, dnsOptions, WEAVE_CONFIG_CONNECT_IP_ADDRS, mPeerAddrs, HandleResolveComplete, this);
#else // !WEAVE_CONFIG_ENABLE_DNS_RESOLVER
    err = StartConnectToAddressLiteral(hostName, hostNameLen);
#endif // !WEAVE_CONFIG_ENABLE_DNS_RESOLVER

exit:
    return err;
}

/**
 *  Connect to a Weave node using a node identifier and/or a list of hostname and ports.
 *
 *  @param[in]    peerNodeId    The node identifier of the peer.
 *
 *  @param[in]    authMode      The authentication mode used for the connection.
 *
 *  @param[in]    hostPortList  The list of hostnames and ports.
 *
 *  @param[in]    intf          The optional interface to use to connect to the peer node,
 *                              default to #INET_NULL_INTERFACEID.
 *
 *  @retval #WEAVE_NO_ERROR                      on successful initiation of the connection to the peer.
 *  @retval #WEAVE_ERROR_INCORRECT_STATE         if the WeaveConnection state is incorrect.
 *
 *  @retval #WEAVE_ERROR_UNSUPPORTED_AUTH_MODE   if the requested authentication mode is not supported.
 *
 *  @retval #WEAVE_ERROR_INVALID_ADDRESS         if the destination address cannot be deduced from the node id.
 *
 *  @retval other Inet layer errors generated by the TCPEndPoint connect operations.
 *
 */
WEAVE_ERROR WeaveConnection::Connect(uint64_t peerNodeId, WeaveAuthMode authMode, HostPortList hostPortList,
                                     InterfaceId intf)
{
#if WEAVE_CONFIG_ENABLE_DNS_RESOLVER
    const uint8_t dnsOptions = ::nl::Inet::kDNSOption_Default;
#else
    const uint8_t dnsOptions = 0;
#endif
    return Connect(peerNodeId, authMode, hostPortList, dnsOptions, intf);
}

/**
 *  Connect to a Weave node using a node identifier and/or a list of hostname and ports.
 *
 *  @param[in]    peerNodeId    The node identifier of the peer.
 *
 *  @param[in]    authMode      The authentication mode used for the connection.
 *
 *  @param[in]    hostPortList  The list of hostnames and ports.
 *
 *  @param[in]    dnsOptions    An integer value controlling how host name resolution is performed.
 *                              Value should be the OR of one or more values from from the
 *                              #::nl::Inet::DNSOptions enumeration.
 *
 *  @param[in]    intf          The optional interface to use to connect to the peer node,
 *                              default to #INET_NULL_INTERFACEID.
 *
 *  @retval #WEAVE_NO_ERROR                      on successful initiation of the connection to the peer.
 *  @retval #WEAVE_ERROR_INCORRECT_STATE         if the WeaveConnection state is incorrect.
 *
 *  @retval #WEAVE_ERROR_UNSUPPORTED_AUTH_MODE   if the requested authentication mode is not supported.
 *
 *  @retval #WEAVE_ERROR_INVALID_ADDRESS         if the destination address cannot be deduced from the node id.
 *
 *  @retval other Inet layer errors generated by the TCPEndPoint connect operations.
 *
 */
WEAVE_ERROR WeaveConnection::Connect(uint64_t peerNodeId, WeaveAuthMode authMode, HostPortList hostPortList,
                                     uint8_t dnsOptions, InterfaceId intf)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    VerifyOrExit(State == kState_ReadyToConnect, err = WEAVE_ERROR_INCORRECT_STATE);

    VerifyOrExit(authMode == kWeaveAuthMode_Unauthenticated || IsCASEAuthMode(authMode) || IsPASEAuthMode(authMode), err = WEAVE_ERROR_INVALID_ARGUMENT);

    // Can't request authentication if the security manager is not initialized.
    VerifyOrExit(authMode == kWeaveAuthMode_Unauthenticated || MessageLayer->SecurityMgr != NULL, err = WEAVE_ERROR_UNSUPPORTED_AUTH_MODE);

    // Application has made this an IP-based WeaveConnection.
    NetworkType = kNetworkType_IP;

    // Clear the list of resolved peer addresses in preparation for resolving the first host name.
    memset(mPeerAddrs, 0, sizeof(mPeerAddrs));

    PeerNodeId = peerNodeId;
    AuthMode = authMode;
    mPeerHostPortList = hostPortList;
    mTargetInterface = intf;
#if WEAVE_CONFIG_ENABLE_DNS_RESOLVER
    mDNSOptions = dnsOptions;
#endif

    // Bump the reference count when we start the connection process. The corresponding decrement happens when the
    // DoClose() method is called. This ensures the object stays live while there's the possibility of a callback
    // happening from an underlying layer (e.g. TCPEndPoint or DNS resolution).
    mRefCount++;

    WeaveLogProgress(MessageLayer, "Con start %04X %016llX %04X", LogId(), peerNodeId, authMode);

    err = TryNextPeerAddress(WEAVE_ERROR_HOST_PORT_LIST_EMPTY);
    SuccessOrExit(err);

exit:
    return err;
}

/**
 * @brief   Set timeout for Connect to succeed or return an error.
 *
 * @param[in]   connTimeoutMsecs
 *
 * @note
 *  Setting a value of zero means use system defaults.
 */
void WeaveConnection::SetConnectTimeout(const uint32_t connTimeoutMsecs)
{
    mConnectTimeout = connTimeoutMsecs;
}

/**
 *  Get the IP address information of the peer.
 *
 *  @param[out]  addrInfo  A reference to the IPPacketInfo object.
 *
 *  @retval  #WEAVE_NO_ERROR On success.
 *  @retval  #WEAVE_ERROR_NOT_IMPLEMENTED    If this function is invoked for an incompatible endpoint
 *                                           (e.g., BLE) in the network layer.
 *
 */
WEAVE_ERROR WeaveConnection::GetPeerAddressInfo(IPPacketInfo& addrInfo)
{
#if CONFIG_NETWORK_LAYER_BLE
    if (mBleEndPoint != NULL)
        return WEAVE_ERROR_NOT_IMPLEMENTED;
#endif

    addrInfo.Clear();
    addrInfo.SrcAddress = PeerAddr;
    addrInfo.SrcPort = PeerPort;

    return WEAVE_NO_ERROR;
}

/**
 * Constructs a string describing the peer node associated with the connection.
 *
 * @param[in] buf                       A pointer to a buffer into which the string should be written. The supplied
 *                                      buffer should be at least as big as kGetPeerDescription_MaxLength. If a
 *                                      smaller buffer is given the string will be truncated to fit. The output
 *                                      will include a NUL termination character in all cases.
 * @param[in] bufSize                   The size of the buffer pointed at by buf.
 */
void WeaveConnection::GetPeerDescription(char * buf, size_t bufSize) const
{
    WeaveMessageLayer::GetPeerDescription(buf, bufSize, PeerNodeId,
            (NetworkType == kNetworkType_IP) ? &PeerAddr : NULL,
            (NetworkType == kNetworkType_IP) ? PeerPort : 0,
            INET_NULL_INTERFACEID,
            this);
}

#if WEAVE_CONFIG_ENABLE_TUNNELING
/**
 *  Send a tunneled Weave message over an established connection.
 *
 *  @param[in] msgInfo        A pointer to a WeaveMessageInfo object.
 *
 *  @param[in] msgBuf           A pointer to the PacketBuffer object holding the packet to send.
 *
 *  @retval    #WEAVE_NO_ERROR                             on successfully sending the message down to
 *                                                         the network layer.
 *  @retval    #WEAVE_ERROR_INCORRECT_STATE                if the WeaveConnection object is not
 *                                                         in the correct state for sending messages.
 *  @retval    #WEAVE_ERROR_INVALID_DESTINATION_NODE_ID    if the destination node identifier is unspecified.
 *  @retval    #WEAVE_ERROR_SENDING_BLOCKED                if the message is too long to be sent.
 *  @retval    other Inet layer errors related to the specific endpoint send operations.
 *
 */
WEAVE_ERROR WeaveConnection::SendTunneledMessage (WeaveMessageInfo *msgInfo, PacketBuffer *msgBuf)
{

    //Set message version to V2
    msgInfo->MessageVersion = kWeaveMessageVersion_V2;

    //Set the tunneling flag
    msgInfo->Flags |= kWeaveMessageFlag_TunneledData;

    return SendMessage(msgInfo, msgBuf);
}
#endif // WEAVE_CONFIG_ENABLE_TUNNELING

/**
 *  Send a Weave message over an established connection.
 *
 *  @param[in] msgInfo        A pointer to a WeaveMessageInfo object.
 *
 *  @param[in] msgBuf           A pointer to the PacketBuffer object holding the packet to send.
 *
 *  @retval    #WEAVE_NO_ERROR                             on successfully sending the message down to
 *                                                         the network layer.
 *  @retval    #WEAVE_ERROR_INCORRECT_STATE                if the WeaveConnection object is not
 *                                                         in the correct state for sending messages.
 *  @retval    #WEAVE_ERROR_INVALID_DESTINATION_NODE_ID    if the destination node identifier is unspecified.
 *  @retval    #WEAVE_ERROR_SENDING_BLOCKED                if the message is too long to be sent.
 *  @retval    other Inet layer errors related to the specific endpoint send operations.
 *
 */
WEAVE_ERROR WeaveConnection::SendMessage (WeaveMessageInfo *msgInfo, PacketBuffer *msgBuf)
{
    WEAVE_ERROR res = WEAVE_NO_ERROR;

    VerifyOrDie(mRefCount != 0);

    if (!StateAllowsSend())
    {
        ExitNow(res = WEAVE_ERROR_INCORRECT_STATE);
    }

    // TODO: implement back pressure

    // Set the source node identifier in the message header.
    msgInfo->SourceNodeId = MessageLayer->FabricState->LocalNodeId;

    // If necessary, arrange for the source node identifier field to be encoded in the message.
    if (SendSourceNodeId)
    {
        msgInfo->Flags |= kWeaveMessageFlag_SourceNodeId;
    }

    // If the caller didn't supply a destination node id, use the peer's node id.
    if ((msgInfo->Flags & kWeaveMessageFlag_DestNodeId) == 0 && msgInfo->DestNodeId == kNodeIdNotSpecified)
    {
        msgInfo->DestNodeId = PeerNodeId;
    }

    // Fail immediately if the caller didn't provide a valid destination node id.
    if (msgInfo->DestNodeId == kNodeIdNotSpecified)
    {
        ExitNow(res = WEAVE_ERROR_INVALID_DESTINATION_NODE_ID);
    }

    // If we determined when the connection was established that the destination node identifier should always be sent,
    // OR if the destination node identifier for the current message does not match the peer node id, then force the
    // destination node identifier field to be encoded in the message.
    if (SendDestNodeId || msgInfo->DestNodeId != PeerNodeId)
    {
        msgInfo->Flags |= kWeaveMessageFlag_DestNodeId;
    }
    // Encode the Weave message. NOTE that this results in the payload buffer containing the entire encoded message.
    // If the encoded message would have exceeded the sent limit, return WEAVE_ERROR_SENDING_BLOCKED to the caller.
    res = MessageLayer->EncodeMessageWithLength(msgInfo, msgBuf, this, UINT16_MAX);
    if (res != WEAVE_NO_ERROR)
    {
        ExitNow(res = (res == WEAVE_ERROR_MESSAGE_TOO_LONG) ? WEAVE_ERROR_SENDING_BLOCKED : res);
    }

    // Copy msg to a right-sized buffer if applicable
    msgBuf = PacketBuffer::RightSize(msgBuf);

#if CONFIG_NETWORK_LAYER_BLE
    if (mBleEndPoint != NULL)
    {
        res = mBleEndPoint->Send(msgBuf);
    }
    else
#endif
    {
        res = mTcpEndPoint->Send(msgBuf, true);
    }
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
    {
        PacketBuffer::Free(msgBuf);
        msgBuf = NULL;
    }

    return res;
}

/**
 *  Performs a graceful TCP send-shutdown, ensuring all outgoing data has been sent and received
 *  by the peer's TCP stack. With most (but not all) TCP implementations, receipt of a send-shutdown
 *  will cause the remote host to shutdown their side of the connection as well, resulting in a
 *  connection close. A subsequent call to Close() would terminate the WeaveConnection.
 *
 *  @note
 *    This method is not available for BLE WeaveConnections. There is no Weave over BLE protocol
 *    mechanism to perform a send-shutdown. Application protocols/profiles must perform their own
 *    acknowledgements of message receipt e.g. via Status Report messages before they close a
 *    WeaveConnection. This is good practice with TCP-based WeaveConnections as well.
 *
 *  @sa Close() and Abort().
 *
 *  @retval  #WEAVE_NO_ERROR                     on successful shutdown of the tcp connection.
 *  @retval  #WEAVE_ERROR_NOT_IMPLEMENTED        if this function is invoked for an incompatible
 *                                               endpoint (e.g., BLE) in the network layer.
 *  @retval  #WEAVE_ERROR_INCORRECT_STATE        if the WeaveConnection object is not
 *                                               in the correct state before initiating
 *                                               a shutdown.
 *  @retval  other Inet layer errors related to the specific endpoint shutdown operations.
 *
 */
WEAVE_ERROR WeaveConnection::Shutdown()
{
#if CONFIG_NETWORK_LAYER_BLE
    if (mBleEndPoint != NULL)
        return WEAVE_ERROR_NOT_IMPLEMENTED;
#endif

    VerifyOrDie(mRefCount != 0);

    if (State != kState_Connected && State != kState_SendShutdown && State != kState_Closed)
        return WEAVE_ERROR_INCORRECT_STATE;

    if (State == kState_Connected)
    {
        State = kState_SendShutdown;
        mTcpEndPoint->Shutdown();
    }

    return WEAVE_NO_ERROR;
}

/**
 *  Performs a non-blocking graceful close of the TCP- or BLE-based WeaveConnection, delivering any
 *  remaining outgoing data before politely informing the remote host that we have reset the connection.
 *
 *  This method provides no strong guarantee that any outgoing message not acknowledged at the application
 *  protocol level has been received by the remote peer. For both TCP and BLE, the underlying protocol stack
 *  will make a best-effort to deliver any pending outgoing data before resetting the connection. For TCP,
 *  Shutdown() should be used before Close() if a transport-layer message receipt confirmation is required
 *  before closing the connection.  BLE connections provide no Shutdown() equivalent.
 *
 *  For BLE-based connections, Close() closes the WeaveConnection and returns immediately, but may cause the
 *  underlying BLEEndPoint object to linger until all outgoing data has been sent. This is a side effect of
 *  the Weave over BLE transport protocol implementation existing within the Weave BleLayer.
 *
 *  Once Close() has been called, the WeaveConnection object can no longer be used for further communication.
 *
 *  Calling Close() decrements the reference count associated with the WeaveConnection object, whether or not
 *  the connection is open/active at the time the method is called.  If this results in the reference count
 *  reaching zero, the resources associated with the connection object are freed.  When this happens, the
 *  application must have no further interactions with the object.
 *
 *  @sa Shutdown(), Abort(), AddRef() and Release().
 *
 *  @return #WEAVE_NO_ERROR unconditionally.
 *
 */
WEAVE_ERROR WeaveConnection::Close()
{
    return Close(false);
}

/**
 *  Performs a non-blocking graceful close of the TCP- or BLE-based WeaveConnection, delivering any
 *  remaining outgoing data before politely informing the remote host that we have reset the connection.
 *
 *  This method provides no strong guarantee that any outgoing message not acknowledged at the application
 *  protocol level has been received by the remote peer. For both TCP and BLE, the underlying protocol stack
 *  will make a best-effort to deliver any pending outgoing data before resetting the connection. For TCP,
 *  Shutdown() should be used before Close() if a transport-layer message receipt confirmation is required
 *  before closing the connection.  BLE connections provide no Shutdown() equivalent.
 *
 *  For BLE-based connections, Close() closes the WeaveConnection and returns immediately, but may cause the
 *  underlying BLEEndPoint object to linger until all outgoing data has been sent. This is a side effect of
 *  the Weave over BLE transport protocol implementation existing within the Weave BleLayer.
 *
 *  Once Close() has been called, the WeaveConnection object can no longer be used for further communication.
 *
 *  Calling Close() decrements the reference count associated with the WeaveConnection object, whether or not
 *  the connection is open/active at the time the method is called.  If this results in the reference count
 *  reaching zero, the resources associated with the connection object are freed.  When this happens, the
 *  application must have no further interactions with the object.
 *
 *  @param[in]    suppressCloseLog    true if logs need to be suppressed, false otherwise.
 *
 *  @sa Shutdown(), Abort(), AddRef() and Release().
 *
 *  @return #WEAVE_NO_ERROR unconditionally.
 *
 */
WEAVE_ERROR WeaveConnection::Close(bool suppressCloseLog)
{
    // Suppress callbacks.
    OnConnectionComplete = NULL;
    OnConnectionClosed = NULL;

    // Perform a graceful close.
    DoClose(WEAVE_NO_ERROR, kDoCloseFlag_SuppressCallback | (suppressCloseLog ? kDoCloseFlag_SuppressLogging : 0));

    // Decrement the ref count that was added when the WeaveConnection object
    // was allocated (in WeaveMessageLayer::NewConnection()).
    VerifyOrDie(mRefCount != 0);
    mRefCount--;

    return WEAVE_NO_ERROR;
}

/**
 *  Performs an un-graceful close of the TCP- or BLE-based WeaveConnection, discarding any data that might be
 *  in flight to or from the peer.
 *
 *  A call to Abort() immediately terminates the underlying connection.  After this point, the WeaveConnection
 *  object can no longer be used for further communication.
 *
 *  Calling Abort() decrements the reference count associated with the WeaveConnection object, whether or not
 *  the connection is open/active at the time the method is called.  If this results in the reference count
 *  reaching zero, the resources associated with the connection object are freed.  When this happens, the
 *  application must have no further interactions with the object.
 *
 *  @sa Shutdown(), Abort(), AddRef() and Release().
 *
 */
void WeaveConnection::Abort()
{
    // Suppress callbacks.
    OnConnectionComplete = NULL;
    OnConnectionClosed = NULL;

    // Perform an abortive close of the connection.
    DoClose(WEAVE_ERROR_CONNECTION_ABORTED, kDoCloseFlag_SuppressCallback);

    // Decrement the ref count that was added when the WeaveConnection object
    // was allocated (in WeaveMessageLayer::NewConnection()).
    VerifyOrDie(mRefCount != 0);
    mRefCount--;
}

/**
 *   Enable receiving over this WeaveConnection. This method is used by the
 *   application to indicate to the WeaveConnection object that it is ready
 *   to receive any data that arrives over the TCP connection.
 *
 *   @sa DisableReceive()
 *
 */
void WeaveConnection::EnableReceive()
{
    // If receiving was disabled, enable it and process any pending received data.
    if (!ReceiveEnabled)
    {
        ReceiveEnabled = true;
        //ProcessReceivedData();
        // TODO: fix this
    }
}

/**
 *   Disable receiving over this WeaveConnection. This method is used by the application
 *   to indicate that it is not ready to receive any arrived data over the TCP connection.
 *   In order to re-enable receiving, the application needs to call EnableReceive() to
 *   allow WeaveConnection to hand over any received data by invoking the approrpiate
 *   callbacks.
 *
 *   @sa EnableReceive()
 *
 */
void WeaveConnection::DisableReceive()
{
    ReceiveEnabled = false;
    // TODO: make this disable received in the TcpEndPoint.
}

/**
 *  WeaveConnection::EnableKeepAlive
 *
 *  @brief
 *    Enable TCP keepalive probes on the underlying TCP connection.
 *
 *  @param[in]  interval
 *    The interval (in seconds) between keepalive probes.  This value also controls
 *    the time between last data packet sent and the transmission of the first keepalive
 *    probe.
 *
 *  @param[in]  timeoutCount
 *    The maximum number of unacknowledged probes before the connection will be deemed
 *    to have failed.
 *
 *  @note
 *     -This method can only be called on a Weave connection backed by a TCP connection.
 *
 *     -This method can only be called when the connection is in a state that allows sending.
 *
 *     -This method can be called multiple times to adjust the keepalive interval or timeout
 *      count.
 *
 *  @retval  #WEAVE_NO_ERROR                     on successful enabling of TCP keepalive probes
 *                                               on the connection.
 *  @retval  #WEAVE_ERROR_NOT_IMPLEMENTED        if this function is invoked for an incompatible
 *                                               endpoint (e.g., BLE) in the network layer.
 *  @retval  #WEAVE_ERROR_INCORRECT_STATE        if the WeaveConnection object is not
 *                                               in the correct state for sending messages.
 *  @retval  other Inet layer errors related to the TCP endpoint enable keepalive operation.
 *
 */

WEAVE_ERROR WeaveConnection::EnableKeepAlive(uint16_t interval, uint16_t timeoutCount)
{
#if CONFIG_NETWORK_LAYER_BLE
    if (mBleEndPoint != NULL)
        return WEAVE_ERROR_NOT_IMPLEMENTED;
#endif

    if (!StateAllowsSend())
        return WEAVE_ERROR_INCORRECT_STATE;

    return mTcpEndPoint->EnableKeepAlive(interval, timeoutCount);
}

/**
 *  WeaveConnection::DisableKeepAlive
 *
 *  @brief
 *    Disable TCP keepalive probes on the underlying TCP connection.
 *
 *  @note
 *    This method can only be called on a Weave connection backed by a TCP connection.
 *
 *    This method can only be called when the connection is in a state that allows sending.
 *
 *    This method does nothing if keepalives have not been enabled on the connection.
 *
 *  @retval  #WEAVE_NO_ERROR                     on successful disabling of TCP keepalive probes
 *                                               on the connection.
 *  @retval  #WEAVE_ERROR_NOT_IMPLEMENTED        if this function is invoked for an incompatible
 *                                               endpoint (e.g., BLE) in the network layer.
 *  @retval  #WEAVE_ERROR_INCORRECT_STATE        if the WeaveConnection object is not
 *                                               in the correct state for sending messages.
 *  @retval  other Inet layer errors related to the TCP endpoint enable keepalive operation.
 *
 */

WEAVE_ERROR WeaveConnection::DisableKeepAlive()
{
#if CONFIG_NETWORK_LAYER_BLE
    if (mBleEndPoint != NULL)
        return WEAVE_ERROR_NOT_IMPLEMENTED;
#endif

    if (!StateAllowsSend())
        return WEAVE_ERROR_INCORRECT_STATE;

    return mTcpEndPoint->DisableKeepAlive();
}

/**
 *  WeaveConnection::SetUserTimeout
 *
 *  @brief
 *    Set the TCP user timeout socket option.
 *
 *  @param[in]   userTimeoutMillis
 *    Tcp user timeout value in milliseconds.
 *
 *  @details
 *    When the value is greater than 0, it specifies the maximum amount of
 *    time in milliseconds that transmitted data may remain
 *    unacknowledged before TCP will forcibly close the
 *    corresponding connection. If the option value is specified as 0,
 *    TCP will use the system default.
 *    See RFC 5482, for further details.
 *
 *  @note
 *     -This method can only be called on a Weave connection backed by a TCP connection.
 *
 *     -This method can only be called when the connection is in a state that allows sending.
 *
 *     -This method can be called multiple times to adjust the TCP user timeout.
 *
 *  @retval  #WEAVE_NO_ERROR                     on successful setting of TCP user timeout
 *                                               on the connection.
 *  @retval  #WEAVE_ERROR_NOT_IMPLEMENTED        if this function is invoked for an incompatible
 *                                               endpoint (e.g., BLE) in the network layer.
 *  @retval  #WEAVE_ERROR_INCORRECT_STATE        if the WeaveConnection object is not
 *                                               in the correct state for sending messages.
 *  @retval  other Inet layer errors related to the TCP endpoint setting of the TCP user timeout.
 *
 */
WEAVE_ERROR WeaveConnection::SetUserTimeout(uint32_t userTimeoutMillis)
{
#if CONFIG_NETWORK_LAYER_BLE
    if (mBleEndPoint != NULL)
        return WEAVE_ERROR_NOT_IMPLEMENTED;
#endif

    if (!StateAllowsSend())
        return WEAVE_ERROR_INCORRECT_STATE;

    return mTcpEndPoint->SetUserTimeout(userTimeoutMillis);
}

/**
 *  WeaveConnection::ResetUserTimeout
 *
 *  @brief
 *    Reset the TCP user timeout socket option to the system default.
 *
 *  @note
 *     -This method can only be called on a Weave connection backed by a TCP connection.
 *
 *     -This method can only be called when the connection is in a state that allows sending.
 *
 *     -This method does nothing if user timeout has not been set on the connection.
 *
 *  @retval  #WEAVE_NO_ERROR                     on successful resetting of TCP user timeout
 *                                               on the connection.
 *  @retval  #WEAVE_ERROR_NOT_IMPLEMENTED        if this function is invoked for an incompatible
 *                                               endpoint (e.g., BLE) in the network layer.
 *  @retval  #WEAVE_ERROR_INCORRECT_STATE        if the WeaveConnection object is not
 *                                               in the correct state for sending messages.
 *  @retval  other Inet layer errors related to the TCP endpoint resetting of the TCP user timeout.
 *
 */
WEAVE_ERROR WeaveConnection::ResetUserTimeout(void)
{
    return SetUserTimeout(0);
}

/**
 *  Set the idle timeout on the underlying network layer connection.
 *
 *  @param[in]    timeoutMS    the timeout in milliseconds.
 *
 *  @retval  #WEAVE_NO_ERROR                     on successful setting of the idle timeout
 *                                               for the connection.
 *  @retval  #WEAVE_ERROR_INCORRECT_STATE        if the WeaveConnection object is not
 *                                               in the correct state for receiving messages.
 *
 */
WEAVE_ERROR WeaveConnection::SetIdleTimeout(uint32_t timeoutMS)
{
    if (!StateAllowsReceive())
        return WEAVE_ERROR_INCORRECT_STATE;

#if CONFIG_NETWORK_LAYER_BLE
    if (mBleEndPoint)
    {
        //TODO COM-320: implement for BLEEndPoint. Use InetTimer until we have separate PlatformLayer.
    }
    else
#endif
    {
        mTcpEndPoint->SetIdleTimeout(timeoutMS);
    }

    return WEAVE_NO_ERROR;
}

void WeaveConnection::DoClose(WEAVE_ERROR err, uint8_t flags)
{
    if (State != kState_Closed)
    {
#if CONFIG_NETWORK_LAYER_BLE
        if (mBleEndPoint != NULL)
        {
            if (err == WEAVE_NO_ERROR)
            {
                mBleEndPoint->Close();
            }
            else
            {
                // Cancel pending BLEEndPoint transmission(s) if WeaveConnection has been aborted.
                mBleEndPoint->Abort();
            }

            // BleEndPoint frees itself once it finishes the close operation. It must stick around to negotiate the
            // close, potentially after it's emptied the remainder of its WoBle transmit buffer.
            mBleEndPoint = NULL;
        }
        else
#endif
        {
            if (mTcpEndPoint != NULL)
            {
                if (err == WEAVE_NO_ERROR)
                    err = mTcpEndPoint->Close();
                if (err != WEAVE_NO_ERROR)
                    mTcpEndPoint->Abort();
                mTcpEndPoint->Free();
                mTcpEndPoint = NULL;
            }

#if WEAVE_CONFIG_ENABLE_DNS_RESOLVER
            // Cancel any outstanding DNS query that may still be active.  (This situation can
            // arise if the application initiates a connection to a peer using a DNS name and
            // then aborts/closes the connection before the DNS lookup completes).
            MessageLayer->Inet->CancelResolveHostAddress(HandleResolveComplete, this);
#endif // WEAVE_CONFIG_ENABLE_DNS_RESOLVER
        }

        uint8_t oldState = State;
        State = kState_Closed;

        if ((flags & kDoCloseFlag_SuppressLogging) == 0)
            WeaveLogProgress(MessageLayer, "Con closed %04X %ld", LogId(), (long)err);

        // If the exchange manager has been initialized, call its callback.
        if (MessageLayer->ExchangeMgr != NULL)
            MessageLayer->ExchangeMgr->HandleConnectionClosed(this, err);

        // Call the Fabric state object to alert it of the connection close.
        MessageLayer->FabricState->HandleConnectionClosed(this);

        // Call the appropriate app callback if allowed.
        if ((flags & kDoCloseFlag_SuppressCallback) == 0)
        {
            if (oldState == kState_Resolving || oldState == kState_Connecting || oldState == kState_EstablishingSession)
            {
                if (OnConnectionComplete != NULL)
                    OnConnectionComplete(this, err);
            }
            else if (OnConnectionClosed != NULL)
                OnConnectionClosed(this, err);
        }

        // Decrement the ref count that was added when the connection started.
        if (oldState != kState_ReadyToConnect && oldState != kState_Closed)
        {
            VerifyOrDie(mRefCount != 0);
            mRefCount--;
        }
    }
}

void WeaveConnection::HandleResolveComplete(void *appState, INET_ERROR dnsRes, uint8_t addrCount, IPAddress *addrArray)
{
    WeaveConnection *con = (WeaveConnection *)appState;

    // It is legal for a DNS entry to exist but contain no A/AAAA records. If this happens, return a reasonable error
    // to the user.
    if (dnsRes == INET_NO_ERROR && addrCount == 0)
        dnsRes = INET_ERROR_HOST_NOT_FOUND;

    WeaveLogProgress(MessageLayer, "Con DNS complete %04X %ld", con->LogId(), (long)dnsRes);

    // Attempt to connect to the first resolved address (if any).
    con->TryNextPeerAddress(dnsRes);
}

WEAVE_ERROR WeaveConnection::TryNextPeerAddress(WEAVE_ERROR lastErr)
{
    WEAVE_ERROR err = lastErr; // If there are no more addresses to try, lastErr will become the error returned to the user.

    // Search the list of peer addresses for one we haven't tried yet...
    for (int i = 0; i < WEAVE_CONFIG_CONNECT_IP_ADDRS; i++)
        if (mPeerAddrs[i] != IPAddress::Any)
        {
            // Select the next address, removing it from the list so it won't get tried again.
            PeerAddr = mPeerAddrs[i];
            mPeerAddrs[i] = IPAddress::Any;

            // Initiate a connection to the new address.
            err = StartConnect();
            ExitNow();
        }

    // If Connect() was called with a host/port list and there are additional entries in the list, then...
    if (!mPeerHostPortList.IsEmpty())
    {
        char hostName[256]; // Per spec, max DNS name length is 253.

        // Pop the next host/port pair from the list.
        err = mPeerHostPortList.Pop(hostName, sizeof(hostName), PeerPort);
        SuccessOrExit(err);

#if WEAVE_CONFIG_ENABLE_DNS_RESOLVER
        // Initiate name resolution for the new host name.
        //
        // NOTE: there was a moment, maybe it's passed now, when the
        // log statement below was very useful since in showed exactly
        // which host we thought we were getting a particular service
        // from. for now i'm leaving it in place, protected by an
        // ifdef 0 at the top of the file.
        //
        WeaveLogProgress(MessageLayer, "Con DNS start %04" PRIX16 " %s %02" PRIX8, LogId(), hostName, mDNSOptions);
        State = kState_Resolving;
        err = MessageLayer->Inet->ResolveHostAddress(hostName, strlen(hostName), mDNSOptions,
                                                     WEAVE_CONFIG_CONNECT_IP_ADDRS,
                                                     mPeerAddrs, HandleResolveComplete, this);
#else // !WEAVE_CONFIG_ENABLE_DNS_RESOLVER
        err = StartConnectToAddressLiteral(hostName, strlen(hostName));
#endif // !WEAVE_CONFIG_ENABLE_DNS_RESOLVER
    }

exit:
    // Enter the closed state if an error occurred.
    if (err != WEAVE_NO_ERROR)
        DoClose(err, 0);

    return err;
}

void WeaveConnection::StartSession()
{
    // If the application requested authentication
    if (AuthMode != kWeaveAuthMode_Unauthenticated)
    {
        // Enter the establishing session state.
        State = kState_EstablishingSession;

        WEAVE_ERROR err;

        // Call the security manager to initiate secure CASE session.
        if (IsCASEAuthMode(AuthMode))
            err = MessageLayer->SecurityMgr->StartCASESession(this, PeerNodeId, PeerAddr, PeerPort,
                                                              AuthMode, NULL, HandleSecureSessionEstablished, HandleSecureSessionError);
        // Call the security manager to initiate secure PASE session.
        else if (IsPASEAuthMode(AuthMode))
            err = MessageLayer->SecurityMgr->StartPASESession(this, AuthMode, NULL,
                                                              HandleSecureSessionEstablished, HandleSecureSessionError);
        else
            err = WEAVE_ERROR_UNSUPPORTED_AUTH_MODE;

        if (err != WEAVE_NO_ERROR)
            DoClose(err, 0);
    }

    // Otherwise...
    else
    {
        // Enter the connected state.
        State = kState_Connected;

        WeaveLogProgress(MessageLayer, "Con complete %04X", LogId());

        // Call the app's completion function.
        if (OnConnectionComplete != NULL)
            OnConnectionComplete(this, WEAVE_NO_ERROR);
    }
}

#if WEAVE_CONFIG_TCP_CONN_REPAIR_SUPPORTED
void WeaveConnection::AppCallbackAfterConnectionRepair(System::Layer* aSystemLayer, void* aAppState, System::Error aError)
{
    WeaveConnection* con = static_cast<WeaveConnection*>(aAppState);

    con->mTcpEndPoint->OnConnectComplete(con->mTcpEndPoint, INET_NO_ERROR);
}

/**
 *  Attempt to repair the TCP connection using a given TCP RepairInfo.
 *
 *  @param[in]    peerNodeId      NodeId of the peer with which to repair TCP
 *                                connection.
 *
 *  @param[in]    repairInfo      A reference to the TCP Connection repair info.
 *
 *  @param[in]    intf            InterfaceId over which the connection is
 *                                expected to be made.
 *
 *  @note
 *   The TCP connection restoration can only be attempted from the client side.
 *   Upon failure to restore, the client would fall back to establishing a
 *   negotiated TCP connection.
 *
 */
WEAVE_ERROR WeaveConnection::TryConnectionRepair(uint64_t peerNodeId, const TCPConnRepairInfo &repairInfo, InterfaceId intf)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Allocate a new TCP end point.
    err = MessageLayer->Inet->NewTCPEndPoint(&mTcpEndPoint);
    SuccessOrExit(err);

    mTcpEndPoint->AppState = this;
    mTcpEndPoint->OnConnectComplete = HandleConnectComplete;

    mRefCount++;

    State = kState_Connecting;

    WeaveLogProgress(MessageLayer, "Trying to repair connection to node %" PRIx64 "", peerNodeId);

    // Call into TCPEndPoint to repair the TCP connection with the fetched
    // repair info.
    err = mTcpEndPoint->RepairConnection(repairInfo, intf);
    SuccessOrExit(err);

    WeaveLogProgress(MessageLayer, "Connection successfully repaired");

    // Set the connection variables
    PeerAddr = repairInfo.dstIP;
    PeerNodeId = peerNodeId;

    // If the peer address is not a ULA, or if the interface identifier portion of the peer address does not match
    // the peer node id, then force the destination node identifier field to be encoded in all sent messages.
    if (!PeerAddr.IsIPv6ULA() || IPv6InterfaceIdToWeaveNodeId(PeerAddr.InterfaceId()) != PeerNodeId)
    {
        SendDestNodeId = true;
    }

    PeerPort = repairInfo.dstPort;
    IsRepaired = true;

    // After repairing connection, set an immediate timer to call the OnConnectComplete callback.
    // This is necessary to allow the call stack to unwind and also prevent the
    // caller of this function to inadvertently change state variables after the
    // application has been called back.
    MessageLayer->SystemLayer->StartTimer(CONN_REPAIR_APP_CALLBACK_DELAY_MSECS, AppCallbackAfterConnectionRepair, this);

exit:

    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogProgress(MessageLayer, "Failed to repair connection to node %" PRIx64 ", err = %ld" , peerNodeId, (long)err);
        if (mTcpEndPoint != NULL)
        {
            mTcpEndPoint->Abort();
            mTcpEndPoint->Free();
            mTcpEndPoint = NULL;
        }
    }

    return err;
}
#endif // WEAVE_CONFIG_TCP_CONN_REPAIR_SUPPORTED

WEAVE_ERROR WeaveConnection::StartConnect()
{
    WEAVE_ERROR err;

    // TODO: this is wrong. PeerNodeId should only be set once we have a successful connection (including security).

    // Determine the peer address/node identifier based on the information given by the caller.
    err = MessageLayer->SelectDestNodeIdAndAddress(PeerNodeId, PeerAddr);
    if (err != WEAVE_NO_ERROR)
        return err;

    // Allocate a new TCP end point.
    err = MessageLayer->Inet->NewTCPEndPoint(&mTcpEndPoint);
    if (err != WEAVE_NO_ERROR)
        return err;

    // If the peer address is not a ULA, or if the interface identifier portion of the peer address does not match
    // the peer node id, then force the destination node identifier field to be encoded in all sent messages.
    if (!PeerAddr.IsIPv6ULA() || IPv6InterfaceIdToWeaveNodeId(PeerAddr.InterfaceId()) != PeerNodeId)
    {
        SendDestNodeId = true;
    }

#if WEAVE_CONFIG_ENABLE_TARGETED_LISTEN
    // TEMPORARY TESTING CODE: If the destination address is IPv6, and an IPv6 listening address has been specified,
    // bind the end point to the listening address so that packets sent over the connection have the listening
    // address as their source address.  This makes it possible to assign multiple simulated fabric addresses to a
    // single interface (e.g. the loopback interface) and ensure that packets sent from a particular node have the
    // correct source address.
#if INET_CONFIG_ENABLE_IPV4
    if (!PeerAddr.IsIPv4() && MessageLayer->FabricState->ListenIPv6Addr != IPAddress::Any)
#else // !INET_CONFIG_ENABLE_IPV4
    if (MessageLayer->FabricState->ListenIPv6Addr != IPAddress::Any)
#endif // !INET_CONFIG_ENABLE_IPV4
    {
        err = mTcpEndPoint->Bind(kIPAddressType_IPv6, MessageLayer->FabricState->ListenIPv6Addr, 0, true);
        if (err != WEAVE_NO_ERROR)
            return err;
    }
#endif

    State = kState_Connecting;

    mTcpEndPoint->AppState = this;
    mTcpEndPoint->OnConnectComplete = HandleConnectComplete;
    mTcpEndPoint->SetConnectTimeout(mConnectTimeout);

#if WEAVE_PROGRESS_LOGGING
    {
        char ipAddrStr[64];
        PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        WeaveLogProgress(MessageLayer, "TCP con start %04" PRIX16 " %s %d", LogId(), ipAddrStr, (int)PeerPort);
    }
#endif
    // Initiate the TCP connection.
    return mTcpEndPoint->Connect(PeerAddr, PeerPort, mTargetInterface);
}

void WeaveConnection::HandleConnectComplete(TCPEndPoint *endPoint, INET_ERROR conRes)
{
    WeaveConnection *con = (WeaveConnection *) endPoint->AppState;

    WeaveLogProgress(MessageLayer, "TCP con complete %04X %ld", con->LogId(), (long)conRes);

    // If the connection was successful...
    if (conRes == INET_NO_ERROR)
    {
        INET_ERROR err;
        IPAddress localAddr;
        uint16_t localPort;

        // If the peer node identifier is unknown, attempt to infer it from the address of the peer.
        if (con->PeerNodeId == kNodeIdNotSpecified && con->PeerAddr.IsIPv6ULA())
            con->PeerNodeId = IPv6InterfaceIdToWeaveNodeId(con->PeerAddr.InterfaceId());

        // Get the local address that was used for the connection.
        err = endPoint->GetLocalInfo(&localAddr, &localPort);
        if (err != INET_NO_ERROR)
        {
            con->DoClose(err, 0);

            return;
        }

        // If the local address is not a ULA, or if the interface identifier portion of the local address does not match
        // the local node id, then arrange to encode the source node identifier field in messages sent to the peer.
        //
        // We rely on this behavior in the case of Thread-assisted pairing. In this case, the (non-ULA) link-local
        // address used by the new device while provisionally joined to the assisting device's PAN forces it to
        // encode its source node identifier in all messages sent to the remote commissioning device. If the new device's
        // local address were a ULA in this scenario, it would be unable to receive communications from the remote
        // comissioner. The new device, having a ULA, would not encode its source node identifier in messages sent to the
        // commissioner, and the comissioner, on a different network than the new device, would be unable to see
        // the new device's ULA and use it to infer that device's node id.
        if (!localAddr.IsIPv6ULA() || IPv6InterfaceIdToWeaveNodeId(localAddr.InterfaceId()) != con->MessageLayer->FabricState->LocalNodeId)
        {
            con->SendSourceNodeId = true;
        }

        // Setup various callbacks on the end point.
        endPoint->OnDataReceived = HandleDataReceived;
        endPoint->OnDataSent = NULL; // TODO: should handle flow control
        endPoint->OnConnectionClosed = HandleTcpConnectionClosed;

        // Disable TCP Nagle buffering by setting TCP_NODELAY socket option to true
        err = endPoint->EnableNoDelay();
        if (err != INET_NO_ERROR)
        {
            con->DoClose(err, 0);

            return;
        }

        // Negotiate secure session (or not) based on AuthMode.
        con->StartSession();
    }

    // Otherwise the connection failed...
    else
    {
        // Release the end point object.
        endPoint->Free();
        con->mTcpEndPoint = NULL;

        // Attempt to connect to another address if available.
        con->TryNextPeerAddress(conRes);
    }
}

void WeaveConnection::HandleDataReceived(TCPEndPoint *endPoint, PacketBuffer *data)
{
    WEAVE_ERROR err;
    WeaveConnection *con = (WeaveConnection *) endPoint->AppState;
    WeaveMessageLayer *msgLayer = con->MessageLayer;

    // While in a state that allows receiving, process the received data...
    while (data != NULL &&
           con->StateAllowsReceive() &&
           con->ReceiveEnabled &&
           (con->OnMessageReceived != NULL
#if WEAVE_CONFIG_ENABLE_TUNNELING
            || con->OnTunneledMessageReceived != NULL
#endif
          ))
    {
        IPPacketInfo        packetInfo;
        WeaveMessageInfo    msgInfo;
        uint8_t*            payload;
        uint16_t            payloadLen;
        PacketBuffer*       payloadBuf = NULL;
        uint32_t            frameLen;

        packetInfo.Clear();
        con->GetPeerAddressInfo(packetInfo);

        msgInfo.Clear();
        msgInfo.InPacketInfo = &packetInfo;
        msgInfo.InCon = con;

        // Attempt to parse an message from the head of the received queue.
        err = msgLayer->DecodeMessageWithLength(data, con->PeerNodeId, con, &msgInfo, &payload, &payloadLen, &frameLen);

        // If the initial buffer in the receive queue is not big enough to hold the entirety of
        // the incoming message...
        if (err == WEAVE_ERROR_MESSAGE_TOO_LONG)
        {
            // The Weave message decoding logic expects message data to be in contiguous memory.
            // Therefore, if the packet buffer containing the initial portion of the message is
            // not big enough to hold the entirety of the message, the data must be moved into
            // a new buffer that is big enough.
            //
            // This situation can arise, for example, when when a TCP segment arrives containing
            // part of a Weave message and the underlying network interface chooses to place the
            // packet into a buffer that is smaller than the Weave message.
            //
            // Note that the logic here implies that when a system runs low on buffers, message
            // reception can fail for lack of an appropriately sized buffer, resulting in the TCP
            // connection being aborted.  The only way to avoid this is for the underlying network
            // interface to always place packets into buffers that are big enough to hold the
            // maximum size Weave message. If such a buffer is not available when a packet comes
            // in, the network interface can simply discard the packet, resulting in the peer
            // retransmitting it and the system recovering gracefully once the buffer pressure
            // subsides.

            // Attempt to allocate a buffer big enough to hold the entire message.  Fail with
            // WEAVE_ERROR_MESSAGE_TOO_LONG if no such buffer is available.
            PacketBuffer * newBuf = PacketBuffer::NewWithAvailableSize(0, frameLen);
            if (newBuf == NULL)
            {
                break;
            }

            // Prepend the new buffer to the receive queue and copy the received message data into
            // the new buffer, discarding the original buffer(s).
            newBuf->AddToEnd(data);
            data = newBuf;
            data->CompactHead();

            // Try again to decode the message.
            continue;
        }

        // If the initial buffer in the receive queue contains only part of the next message...
        if (err == WEAVE_ERROR_MESSAGE_INCOMPLETE)
        {
            // If there are more buffers in the queue, move as much data as possible into the head buffer
            // and try again.
            if (data->Next() != NULL)
            {
                data->CompactHead();
                continue;
            }

            // Otherwise, we must wait for more data from the peer...

            // Open the receive window just enough to allow the remainder of the message to be received.
            // This is necessary in the case where the message size exceeds the TCP window size to ensure
            // the peer has enough window to send us the entire message.
            uint16_t neededLen = frameLen - data->DataLength();
            err = endPoint->AckReceive(neededLen);
            if (err == WEAVE_NO_ERROR)
                break;
        }

        // If we successfully parsed a message, open the TCP receive window by the size of the message.
        if (err == WEAVE_NO_ERROR)
            err = endPoint->AckReceive(frameLen);

        // Verify that destination node identifier refers to the local node.
        if (err == WEAVE_NO_ERROR)
        {
            if (msgInfo.DestNodeId != msgLayer->FabricState->LocalNodeId && msgInfo.DestNodeId != kAnyNodeId)
                err = WEAVE_ERROR_INVALID_DESTINATION_NODE_ID;
        }

        if (err == WEAVE_NO_ERROR)
        {
            // If there's no more data in the current buffer beyond the message that was just parsed,
            // then avoid a copy by giving the buffer to the application layer.
            if (data->DataLength() == 0)
            {
                // Detach the buffer from the data queue.
                payloadBuf = data;
                data = data->DetachTail();

                // Adjust the buffer to point at the payload of the message.
                payloadBuf->SetStart(payload);
                payloadBuf->SetDataLength(payloadLen);
            }

            // Otherwise we need to keep the buffer so we can parse the remaining data, so copy the
            // payload data into a new buffer and arrange to pass the new buffer to the application.
            else
            {
                payloadBuf = PacketBuffer::New(0);
                if (payloadBuf != NULL)
                {
                    memcpy(payloadBuf->Start(), payload, payloadLen);
                    payloadBuf->SetDataLength(payloadLen);
                }
                else
                    err = WEAVE_ERROR_NO_MEMORY;
            }
        }

        // Disconnect if an error occurred.
        if (err != WEAVE_NO_ERROR)
        {
            WeaveLogError(MessageLayer, "Con rcv data err %04X %ld", con->LogId(), err);

            // Send key error response to the peer if required.
            if (msgLayer->SecurityMgr->IsKeyError(err))
            {
                if (data != NULL)
                {
                    PacketBuffer::Free(data);
                    data = NULL;
                }

                msgLayer->SecurityMgr->SendKeyErrorMsg(&msgInfo, NULL, con, err);
            }

            con->DisconnectOnError(err);
            break;
        }

        //Check if message carries tunneled data and needs to be sent to Tunnel Agent
        if (msgInfo.MessageVersion == kWeaveMessageVersion_V2)
        {
            if (msgInfo.Flags & kWeaveMessageFlag_TunneledData)
            {
#if WEAVE_CONFIG_ENABLE_TUNNELING
                // Dispatch the tunneled data message to the application if it is not a duplicate.
                // Although TCP guarantees in-order, at-most-once delivery in normal conditions,
                // checking for and eliminating duplicate tunneled messages here prevents replay
                // of messages by a malicious man-in-the-middle.
                if (!(msgInfo.Flags & kWeaveMessageFlag_DuplicateMessage))
                {
                    if (con->OnTunneledMessageReceived)
                    {
                        con->OnTunneledMessageReceived(con, &msgInfo, payloadBuf);
                    }
                    else
                    {
                        con->DisconnectOnError(WEAVE_ERROR_NO_MESSAGE_HANDLER);
                        break;
                    }
                }
#endif
            }
            else
            {
                if (con->OnMessageReceived)
                {
                    con->OnMessageReceived(con, &msgInfo, payloadBuf);
                }
                else
                {
                    con->DisconnectOnError(WEAVE_ERROR_NO_MESSAGE_HANDLER);
                    break;
                }

            }
        }
        else if (msgInfo.MessageVersion == kWeaveMessageVersion_V1)
        {
            // Pass the message header and payload to the application.
            // NOTE that when this function returns, the state of the connection may have changed.
            if (con->OnMessageReceived)
            {
                con->OnMessageReceived(con, &msgInfo, payloadBuf);
            }
            else
            {
                con->DisconnectOnError(WEAVE_ERROR_NO_MESSAGE_HANDLER);
                break;
            }
        }
    }

    // If we couldn't process all the received data push it back into the end point. When
    // more data arrives, it will call us back with this data plus the new data. If the underlying
    // TCP connection is closed (which means we're never going to receive any more data), fail with
    // a MESSAGE_INCOMPLETE error.  If the WeaveConnection is closed (e.g. the app called close)
    // then simply discard the received data.
    if (data != NULL)
    {
        if (con->StateAllowsReceive())
        {
            if (endPoint->State == TCPEndPoint::kState_Connected ||
                endPoint->State == TCPEndPoint::kState_SendShutdown)
            {
                endPoint->PutBackReceivedData(data);
                data = NULL;
            }
            else
                con->DoClose(WEAVE_ERROR_MESSAGE_INCOMPLETE, 0);
        }
        if (data != NULL)
            PacketBuffer::Free(data);
    }
}

void WeaveConnection::HandleTcpConnectionClosed(TCPEndPoint *endPoint, INET_ERROR err)
{
    WeaveConnection *con = (WeaveConnection *) endPoint->AppState;
    if (err == INET_NO_ERROR && con->State == kState_EstablishingSession)
        err = WEAVE_ERROR_CONNECTION_CLOSED_UNEXPECTEDLY;
    con->DoClose(err, 0);
}

void WeaveConnection::HandleSecureSessionEstablished(WeaveSecurityManager *sm, WeaveConnection *con, void *reqState,
        uint16_t sessionKeyId, uint64_t peerNodeId, uint8_t encType)
{
    // Establish the peer node identifier and the default key and encryption type to be used to send messages.
    con->PeerNodeId = peerNodeId;
    con->DefaultKeyId = sessionKeyId;
    con->DefaultEncryptionType = encType;

    // Enter the connected state.
    con->State = kState_Connected;

    WeaveLogProgress(MessageLayer, "Con complete %04X", con->LogId());

    // Invoke the app's completion function.
    if (con->OnConnectionComplete != NULL)
        con->OnConnectionComplete(con, WEAVE_NO_ERROR);
}

void WeaveConnection::HandleSecureSessionError(WeaveSecurityManager *sm, WeaveConnection *con, void *reqState,
        WEAVE_ERROR localErr, uint64_t peerNodeId, Profiles::StatusReporting::StatusReport *statusReport)
{
    // Couldn't get a secure session, so fail the connect attempt.
    con->DoClose(localErr, 0);
}

void WeaveConnection::Init(WeaveMessageLayer *msgLayer)
{
    // NOTE: Please keep these in declared order to make it easier keep in sync.
    PeerNodeId = 0;
    PeerAddr = IPAddress::Any;
    MessageLayer = msgLayer;
    AppState = NULL;
    PeerPort = 0;
    DefaultKeyId = WeaveKeyId::kNone;
    AuthMode = kWeaveAuthMode_NotSpecified;
    DefaultEncryptionType = kWeaveEncryptionType_None;
    State = WeaveConnection::kState_ReadyToConnect;
    NetworkType = kNetworkType_Unassigned;
    ReceiveEnabled = true;
    OnConnectionComplete = NULL;
    OnMessageReceived = NULL;
#if WEAVE_CONFIG_ENABLE_TUNNELING
    OnTunneledMessageReceived = NULL;
#endif
    OnConnectionClosed = DefaultConnectionClosedHandler;
    OnReceiveError = NULL;
    memset(&mPeerAddrs, 0, sizeof(mPeerAddrs));
    mTcpEndPoint = NULL;
#if CONFIG_NETWORK_LAYER_BLE
    mBleEndPoint = NULL;
#endif
    mPeerHostPortList.Clear();
    mTargetInterface = INET_NULL_INTERFACEID;
    mRefCount = 1;
    SendSourceNodeId = false;
    SendDestNodeId = false;
    mConnectTimeout = 0;
#if WEAVE_CONFIG_ENABLE_DNS_RESOLVER
    mDNSOptions = 0;
#endif

#if WEAVE_CONFIG_TCP_CONN_REPAIR_SUPPORTED
    IsRepaired = false;
#endif // WEAVE_CONFIG_TCP_CONN_REPAIR_SUPPORTED
    mFlags = 0;
}

// Default OnConnectionClosed handler.
//
// This handler is installed in the OnConnectionClosed callback of all new WeaveConnection objects.
// The function automatically releases the application's reference to the object whenever the connection
// closes spontaneously from the network side.  This eliminates the need for boiler-plate code to release
// the object in every Weave application that uses connections, and helps to avoid bugs in applications
// that fail to properly take care of this themselves.
//
// Note that this behavior only applies to closes initiated from the network.  If the application itself
// calls Close() or Abort() on the connection, this function is never called.
//
void WeaveConnection::DefaultConnectionClosedHandler(WeaveConnection *con, WEAVE_ERROR conErr)
{
    // Call Close() on the connection object to release the application's reference to the connection.
    con->Close();
}

void WeaveConnection::MakeConnectedTcp(TCPEndPoint *endPoint, const IPAddress &localAddr, const IPAddress &peerAddr)
{
    mTcpEndPoint = endPoint;
    NetworkType = kNetworkType_IP;
    endPoint->AppState = this;
    endPoint->OnDataReceived = HandleDataReceived;
    endPoint->OnDataSent = NULL; // TODO: should handle flow control
    endPoint->OnConnectionClosed = HandleTcpConnectionClosed;

    PeerNodeId = (peerAddr.IsIPv6ULA()) ? IPv6InterfaceIdToWeaveNodeId(peerAddr.InterfaceId()) : kNodeIdNotSpecified;
    PeerAddr = peerAddr;

    // If the local address is not a ULA, or if the interface identifier portion of the local address does not match
    // the local node id, then arrange to encode the source node identifier field in all messages sent to the peer.
    if (!localAddr.IsIPv6ULA() || IPv6InterfaceIdToWeaveNodeId(localAddr.InterfaceId()) != MessageLayer->FabricState->LocalNodeId)
    {
        SendSourceNodeId = true;
    }

    // Similarly, if we were unable do derive the node identifier of the peer from its address, then arrange for the
    // destination node identifier field to be encoded in all sent messages.
    if (PeerNodeId == kNodeIdNotSpecified)
    {
        SendDestNodeId = true;
    }

    AppState = NULL;
    mRefCount++;

    ReceiveEnabled = true;

    // Disable TCP Nagle buffering by setting TCP_NODELAY socket option to true
    endPoint->EnableNoDelay();

    State = kState_Connected;
}

#if CONFIG_NETWORK_LAYER_BLE

/**
 *  Bind WeaveConnection to BLE connection handle from application.
 *  The application must call this function when and only when it, acting in the role
 *  of a BLE Central, has actively connected to a BLE Peripheral which supports the
 *  Weave BLE service.
 *
 *  If this function and the WeaveConnection's OnConnectionComplete callback both
 *  return without error, Weave has accepted the BLE connection.
 *  However, if Weave accepts a BLE connection, the platform MUST notify Weave via
 *  the appropriate BleLayer callback if the central's subscription is canceled or the
 *  underlying BLE connection is closed, otherwise the associated WeaveConnection
 *  will never be closed or freed.
 *
 *  @note
 *    A downcall to this method may call OnConnectionComplete before it returns.
 *
 *  @param[in]    connObj    The BLE connection object.
 *
 *  @param[in]    authMode   The desired authenticate mode for the peer. Only CASE, PASE and Unauthenticated
 *                           modes are supported.
 *
 *  @param[in]    autoClose  true if automatic closing is enabled upon a long period of
 *                           inactivity, otherwise false.
 *
 *  @retval #WEAVE_NO_ERROR                      on successful initiation of the BLE connection to
 *                                               the peer.
 *  @retval #WEAVE_ERROR_INCORRECT_STATE         if the WeaveConnection state is not ready to connect.
 *
 *  @retval #WEAVE_ERROR_UNSUPPORTED_AUTH_MODE   if the requested authentication mode is not supported or
 *                                               the security manager is not initialized.
 *
 *  @retval other Inet layer errors generated by the BleEndPoint create and connect operations.
 *
 *
 */

WEAVE_ERROR WeaveConnection::ConnectBle(BLE_CONNECTION_OBJECT connObj, WeaveAuthMode authMode, bool autoClose)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    VerifyOrExit(State == kState_ReadyToConnect && MessageLayer->mBle != NULL, err = WEAVE_ERROR_INCORRECT_STATE);

    VerifyOrExit(authMode == kWeaveAuthMode_Unauthenticated || IsCASEAuthMode(authMode) || IsPASEAuthMode(authMode), err = WEAVE_ERROR_INVALID_ARGUMENT);

    // Can't request authentication if the security manager is not initialized.
    VerifyOrExit(authMode == kWeaveAuthMode_Unauthenticated || MessageLayer->SecurityMgr != NULL, err = WEAVE_ERROR_UNSUPPORTED_AUTH_MODE);

    // Application has made us a BLE-based WeaveConnection.
    NetworkType = kNetworkType_BLE;

    AuthMode = authMode;

    // Only BLE centrals can form new GATT connections, so specify this role in our creation of the BLEEndPoint.
    err = MessageLayer->mBle->NewBleEndPoint(&mBleEndPoint, connObj, kBleRole_Central, autoClose);
    SuccessOrExit(err);

    // Enter the connecting state.
    State = kState_Connecting;

    // Set up callbacks we need to negotiate WoBle connection.
    mBleEndPoint->mAppState = this;
    mBleEndPoint->OnConnectComplete = HandleBleConnectComplete;
    mBleEndPoint->OnConnectionClosed = HandleBleConnectionClosed;

    // Must always send SourceNodeId over BLE-based WeaveConnection, as peer cannot infer it from source address.
    SendSourceNodeId = true;

    // Bump the reference count when we start the connection process. The corresponding decrement happens when the
    // DoClose() method is called. This ensures the object stays live while there's the possibility of a callback
    // happening from an underlying layer (e.g. a BLE GATT subscribe request).
    mRefCount++;

    // Initiate Weave over BLE protocol connection.
    err = mBleEndPoint->StartConnect();
    SuccessOrExit(err);

exit:
    return err;
}

void WeaveConnection::HandleBleConnectComplete(BLEEndPoint *endPoint, BLE_ERROR err)
{
    WeaveConnection *con = static_cast<WeaveConnection *>(endPoint->mAppState);

    if (err != BLE_NO_ERROR)
        ExitNow();

    WeaveLogProgress(MessageLayer, "WoBle con complete %04X\n", con->LogId());

    // Set message received callback.
    con->mBleEndPoint->OnMessageReceived = HandleBleMessageReceived;

    // Negotiate secure session (or not) based on AuthMode.
    con->StartSession();

exit:
    if (err != BLE_NO_ERROR)
    {
        WeaveLogError(MessageLayer, "WoBle con failed %04X %d", con->LogId(), err);
        con->DoClose(err, 0);
    }
}

void WeaveConnection::HandleBleMessageReceived(BLEEndPoint *endPoint, PacketBuffer *data)
{
    WeaveConnection *con = (WeaveConnection *) endPoint->mAppState;
    WeaveMessageLayer *msgLayer = con->MessageLayer;

    // Weave's BLE layer reassembles received messages in their entirety before it passes them up the stack,
    // so there's no need for received buffer compaction or reassembly at this layer.

    WeaveMessageInfo msgInfo;
    uint8_t *payload;
    uint16_t payloadLen;
    PacketBuffer *payloadBuf;
    uint32_t frameLen;
    WEAVE_ERROR err;

    // Initialize the message info structure.
    msgInfo.Clear();
    msgInfo.InCon = con;

    // Verify received buffer is not part of a multi-buffer chain.
    VerifyOrExit(data->Next() == NULL, err = BLE_ERROR_BAD_ARGS);

    // Attempt to parse the message.
    err = msgLayer->DecodeMessageWithLength(data, con->PeerNodeId, con, &msgInfo, &payload,
            &payloadLen, &frameLen);
    SuccessOrExit(err);

    // Verify that destination node id refers to the local node.
    VerifyOrExit(((msgInfo.DestNodeId == msgLayer->FabricState->LocalNodeId) ||
            (msgInfo.DestNodeId == kAnyNodeId)),
            err = WEAVE_ERROR_INVALID_DESTINATION_NODE_ID);

    // Verify that the received buffer contained exactly one Weave message.
    VerifyOrExit(data->DataLength() == 0, err = BLE_ERROR_RECEIVED_MESSAGE_TOO_BIG);

    // Assign received data to payload buffer.
    payloadBuf = data;
    data = NULL;

    // Adjust the buffer to point at the payload of the message.
    payloadBuf->SetStart(payload);
    payloadBuf->SetDataLength(payloadLen);

    // Pass the message header and payload to the application.
    // NOTE that when this function returns, the state of the connection may have changed.
    con->OnMessageReceived(con, &msgInfo, payloadBuf);

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(MessageLayer, "HandleBleMessageReceived failed, err = %d", err);

        if (data != NULL)
            PacketBuffer::Free(data);

        // Send key error response to the peer if required.
        if (msgLayer->SecurityMgr->IsKeyError(err))
            msgLayer->SecurityMgr->SendKeyErrorMsg(&msgInfo, NULL, con, err);
    }
}

void WeaveConnection::HandleBleConnectionClosed(BLEEndPoint *endPoint, BLE_ERROR err)
{
    WeaveConnection *con = (WeaveConnection *) endPoint->mAppState;
    con->DoClose(err, 0);
}

void WeaveConnection::MakeConnectedBle(BLEEndPoint *endPoint)
{
    mBleEndPoint = endPoint;
    NetworkType = kNetworkType_BLE;

    endPoint->mAppState = this;
    endPoint->OnMessageReceived = HandleBleMessageReceived;
    endPoint->OnConnectionClosed = HandleBleConnectionClosed;
    endPoint->mState = BLEEndPoint::kState_Connected;

    // Must always send SourceNodeId over BLE connection since peer cannot infer it from source address.
    SendSourceNodeId = true;

    State = kState_Connected;

    mRefCount++;
}

#endif // CONFIG_NETWORK_LAYER_BLE

void WeaveConnection::DisconnectOnError (WEAVE_ERROR err)
{
    if (OnReceiveError != NULL)
    {
        OnReceiveError(this, err);
    }
    else if (MessageLayer->OnReceiveError != NULL)
    {
        IPPacketInfo addrInfo;
        GetPeerAddressInfo(addrInfo);
        MessageLayer->OnReceiveError(MessageLayer, err, &addrInfo);
    }

    DoClose(err, 0);

}

} // namespace nl
} // namespace Weave
