/*
 *
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      This file implements the WeaveConnection class. It manages
 *      communication over a TCP connection between Weave nodes.
 *
 */

#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif

#include <inttypes.h>

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

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

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

namespace nl {
namespace Weave {

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

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

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

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

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

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

    return err;
}

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

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

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

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

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

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

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

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

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

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

    err = StartConnect();
    SuccessOrExit(err);

exit:
    return err;
}

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

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

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

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

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

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

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

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

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

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

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

    PeerNodeId = peerNodeId;
    AuthMode = authMode;

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

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

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

exit:
    return err;
}

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

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

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

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

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

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

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

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

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

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

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

exit:
    return err;
}

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

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

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

    return WEAVE_NO_ERROR;
}

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

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

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

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

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

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

    VerifyOrDie(mRefCount != 0);

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

    // TODO: implement back pressure

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

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

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

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

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

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

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

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

    return res;
}

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

    VerifyOrDie(mRefCount != 0);

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

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

    return WEAVE_NO_ERROR;
}

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

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

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

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

    return WEAVE_NO_ERROR;
}

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

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

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

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

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

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

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

    if (!StateAllowsSend())
        return WEAVE_ERROR_INCORRECT_STATE;

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

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

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

    if (!StateAllowsSend())
        return WEAVE_ERROR_INCORRECT_STATE;

    return mTcpEndPoint->DisableKeepAlive();
}

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

    if (!StateAllowsSend())
        return WEAVE_ERROR_INCORRECT_STATE;

    return mTcpEndPoint->SetUserTimeout(userTimeoutMillis);
}

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

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

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

    return WEAVE_NO_ERROR;
}

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

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

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

        uint8_t oldState = State;
        State = kState_Closed;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return err;
}

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

        WEAVE_ERROR err;

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

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

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

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

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

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

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

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

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

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

    mRefCount++;

    State = kState_Connecting;

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

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

    WeaveLogProgress(MessageLayer, "Connection successfully repaired");

    // Set the connection variables
    PeerAddr = repairInfo.dstIP;
    PeerNodeId = peerNodeId;
    PeerPort = repairInfo.dstPort;
    IsRepaired = true;

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

exit:

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

    return err;
}
#endif // WEAVE_CONFIG_TCP_CONN_REPAIR_SUPPORTED

WEAVE_ERROR WeaveConnection::StartConnect()
{
    WEAVE_ERROR err;

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

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

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

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

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

    State = kState_Connecting;

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

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

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

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

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

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

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

            return;
        }

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

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

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

            return;
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            con->DisconnectOnError(err);
            break;
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    AppState = NULL;
    mRefCount++;

    ReceiveEnabled = true;

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

    State = kState_Connected;
}

#if CONFIG_NETWORK_LAYER_BLE

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

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

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

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

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

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

    AuthMode = authMode;

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

    // Enter the connecting state.
    State = kState_Connecting;

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

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

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

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

exit:
    return err;
}

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

    if (err != BLE_NO_ERROR)
        ExitNow();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    State = kState_Connected;

    mRefCount++;
}

#endif // CONFIG_NETWORK_LAYER_BLE

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

    DoClose(err, 0);

}

} // namespace nl
} // namespace Weave
