/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2019,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "tcp-transport.hpp"
#include "daemon/global.hpp"

#if defined(__linux__)
#include <linux/sockios.h>
#include <sys/ioctl.h>
#endif

namespace nfd {
namespace face {

NFD_LOG_MEMBER_INIT_SPECIALIZED(StreamTransport<boost::asio::ip::tcp>, TcpTransport);

time::milliseconds TcpTransport::s_initialReconnectWait = 1_s;
time::milliseconds TcpTransport::s_maxReconnectWait = 5_min;
float TcpTransport::s_reconnectWaitMultiplier = 2.0f;

TcpTransport::TcpTransport(protocol::socket&& socket,
                           ndn::nfd::FacePersistency persistency,
                           ndn::nfd::FaceScope faceScope)
  : StreamTransport(std::move(socket))
  , m_remoteEndpoint(m_socket.remote_endpoint())
  , m_nextReconnectWait(s_initialReconnectWait)
{
  this->setLocalUri(FaceUri(m_socket.local_endpoint()));
  this->setRemoteUri(FaceUri(m_socket.remote_endpoint()));
  this->setScope(faceScope);
  this->setPersistency(persistency);
  this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
  this->setMtu(MTU_UNLIMITED);

  NFD_LOG_FACE_INFO("Creating transport");
}

ssize_t
TcpTransport::getSendQueueLength()
{
  int queueLength = getSendQueueBytes();

  // We want to obtain the amount of "not sent" bytes instead of the amount of "not sent" + "not
  // acked" bytes. On Linux, we use SIOCOUTQNSD for this reason. However, macOS does not provide an
  // efficient mechanism to obtain this value (SO_NWRITE includes both "not sent" and "not acked").
#if defined(__linux__)
  int nsd;
  if (ioctl(m_socket.native_handle(), SIOCOUTQNSD, &nsd) < 0) {
    NFD_LOG_FACE_WARN("Failed to obtain send queue length from socket: " << std::strerror(errno));
  }
  else if (nsd > 0) {
    NFD_LOG_FACE_TRACE("SIOCOUTQNSD=" << nsd);
    queueLength += nsd;
  }
#endif

  return queueLength;
}

bool
TcpTransport::canChangePersistencyToImpl(ndn::nfd::FacePersistency newPersistency) const
{
  return true;
}

void
TcpTransport::afterChangePersistency(ndn::nfd::FacePersistency oldPersistency)
{
  // if persistency was changed from permanent to any other value
  if (oldPersistency == ndn::nfd::FACE_PERSISTENCY_PERMANENT) {
    if (this->getState() == TransportState::DOWN) {
      // non-permanent transport cannot be in DOWN state, so fail hard
      this->setState(TransportState::FAILED);
      doClose();
    }
  }
}

void
TcpTransport::handleError(const boost::system::error_code& error)
{
  if (this->getPersistency() == ndn::nfd::FACE_PERSISTENCY_PERMANENT) {
    NFD_LOG_FACE_TRACE("TCP socket error: " << error.message());
    this->setState(TransportState::DOWN);

    // cancel all outstanding operations
    boost::system::error_code ec;
    m_socket.cancel(ec);

    // do this asynchronously because there could be some callbacks still pending
    getGlobalIoService().post([this] { reconnect(); });
  }
  else {
    StreamTransport::handleError(error);
  }
}

void
TcpTransport::reconnect()
{
  NFD_LOG_FACE_TRACE(__func__);

  if (getState() == TransportState::CLOSING ||
      getState() == TransportState::FAILED ||
      getState() == TransportState::CLOSED) {
    // transport is shutting down, don't attempt to reconnect
    return;
  }

  BOOST_ASSERT(getPersistency() == ndn::nfd::FACE_PERSISTENCY_PERMANENT);
  BOOST_ASSERT(getState() == TransportState::DOWN);

  // recreate the socket
  m_socket = protocol::socket(m_socket.get_io_service());
  this->resetReceiveBuffer();
  this->resetSendQueue();

  m_reconnectEvent = getScheduler().schedule(m_nextReconnectWait,
                                             [this] { this->handleReconnectTimeout(); });
  m_socket.async_connect(m_remoteEndpoint, [this] (const auto& e) { this->handleReconnect(e); });
}

void
TcpTransport::handleReconnect(const boost::system::error_code& error)
{
  if (getState() == TransportState::CLOSING ||
      getState() == TransportState::FAILED ||
      getState() == TransportState::CLOSED ||
      error == boost::asio::error::operation_aborted) {
    // transport is shutting down, abort the reconnection attempt and ignore any errors
    return;
  }

  if (error) {
    NFD_LOG_FACE_TRACE("Reconnection attempt failed: " << error.message());
    return;
  }

  m_reconnectEvent.cancel();
  m_nextReconnectWait = s_initialReconnectWait;

  this->setLocalUri(FaceUri(m_socket.local_endpoint()));
  NFD_LOG_FACE_TRACE("TCP connection reestablished");
  this->setState(TransportState::UP);
  this->startReceive();
}

void
TcpTransport::handleReconnectTimeout()
{
  // abort the reconnection attempt
  boost::system::error_code error;
  m_socket.close(error);

  // exponentially back off the reconnection timer
  m_nextReconnectWait =
      std::min(time::duration_cast<time::milliseconds>(m_nextReconnectWait * s_reconnectWaitMultiplier),
               s_maxReconnectWait);

  // do this asynchronously because there could be some callbacks still pending
  getGlobalIoService().post([this] { reconnect(); });
}

void
TcpTransport::doClose()
{
  m_reconnectEvent.cancel();
  StreamTransport::doClose();
}

} // namespace face
} // namespace nfd
