/*
 *
 *    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 <InetLayer/InetLayer.h>


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);
    }
}

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
    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
