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


namespace nl {
namespace Weave {

WEAVE_ERROR WeaveConnection::StartConnectToAddressLiteral(const char aAddressLiteral[])
{
    WEAVE_ERROR lReturn = 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(aAddressLiteral, PeerAddr))
        lReturn = StartConnect();
#endif // WEAVE_CONFIG_RESOLVE_IPADDR_LITERAL

    return lReturn;
}

/**
 *  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:
 *
 *    <host-name>
 *    <host-name>:<port>
 *    <ip-4-addr>
 *    <ip-4-addr>:<port>
 *    <ip-6-addr>
 *    [<ip-6-addr>]:<port>
 *
 *  @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:
 *
 *    <host-name>
 *    <host-name>:<port>
 *    <ip-4-addr>
 *    <ip-4-addr>:<port>
 *    <ip-6-addr>
 *    [<ip-6-addr>]:<port>
 *
 *  @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)
{
    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, WEAVE_CONFIG_CONNECT_IP_ADDRS, mPeerAddrs, HandleResolveComplete, this);
#else // !WEAVE_CONFIG_ENABLE_DNS_RESOLVER
    err = StartConnectToAddressLiteral(hostName);
#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)
{
    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;

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


#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() frees 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.
 *
 *  A call to Close() terminates the WeaveConnection. Any further use of a WeaveConnection needs to be
 *  initiated by a call to WeaveMessageLayer::NewConnection();
 *
 *  @sa Shutdown() and Abort().
 *
 *  @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() frees 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.
 *
 *  A call to Close() terminates the WeaveConnection. Any further use of a WeaveConnection needs to be
 *  initiated by a call to WeaveMessageLayer::NewConnection();
 *
 *  @param[in]    suppressCloseLog    true if logs need to be suppressed, false otherwise.
 *
 *  @sa Shutdown() and Abort().
 *
 *  @return #WEAVE_NO_ERROR unconditionally.
 *
 */
WEAVE_ERROR WeaveConnection::Close(bool suppressCloseLog)
{
    VerifyOrDie(mRefCount != 0);

    // 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()).
    mRefCount--;

    return WEAVE_NO_ERROR;
}

/**
 *  Performs an un-graceful close of the TCP- or BLE-based WeaveConnection, freeing all local state
 *  without informing the remote host.
 *
 *  A call to Abort() terminates the WeaveConnection. Any further use of a WeaveConnection needs to be
 *  initiated by a call to WeaveMessageLayer::NewConnection();
 *
 *  @sa Shutdown() and Close().
 *
 */
void WeaveConnection::Abort()
{
    VerifyOrDie(mRefCount != 0);

    // 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()).
    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)
            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", LogId(), hostName);
        State = kState_Resolving;
        err = MessageLayer->Inet->ResolveHostAddress(hostName, strlen(hostName), WEAVE_CONFIG_CONNECT_IP_ADDRS,
                                                     mPeerAddrs, HandleResolveComplete, this);
#else // !WEAVE_CONFIG_ENABLE_DNS_RESOLVER
        err = StartConnectToAddressLiteral(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;
        uint16_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 data.
        err = msgLayer->DecodeMessageWithLength(data, con->PeerNodeId, con, &msgInfo, &payload, &payloadLen, &frameLen);

        // If the data buffer contains only part of a 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;
}

// 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;
    uint16_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
