/* -*- 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 "websocket-transport.hpp"
#include "common/global.hpp"

namespace nfd {
namespace face {

NFD_LOG_INIT(WebSocketTransport);

static bool
isLoopback(const boost::asio::ip::address& addr)
{
  if (addr.is_loopback()) {
    return true;
  }
  // Workaround for loopback IPv4-mapped IPv6 addresses
  // see https://svn.boost.org/trac/boost/ticket/9084
  else if (addr.is_v6()) {
    auto addr6 = addr.to_v6();
    if (addr6.is_v4_mapped()) {
      return addr6.to_v4().is_loopback();
    }
  }

  return false;
}

WebSocketTransport::WebSocketTransport(websocketpp::connection_hdl hdl,
                                       websocket::Server& server,
                                       time::milliseconds pingInterval)
  : m_handle(hdl)
  , m_server(server)
  , m_pingInterval(pingInterval)
{
  const auto& sock = m_server.get_con_from_hdl(hdl)->get_socket();
  this->setLocalUri(FaceUri(sock.local_endpoint(), "ws"));
  this->setRemoteUri(FaceUri(sock.remote_endpoint(), "wsclient"));

  if (isLoopback(sock.local_endpoint().address()) &&
      isLoopback(sock.remote_endpoint().address())) {
    this->setScope(ndn::nfd::FACE_SCOPE_LOCAL);
  }
  else {
    this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
  }

  this->setPersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
  this->setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT);
  this->setMtu(MTU_UNLIMITED);

  this->schedulePing();

  NFD_LOG_FACE_DEBUG("Creating transport");
}

void
WebSocketTransport::doSend(const Block& packet, const EndpointId&)
{
  NFD_LOG_FACE_TRACE(__func__);

  websocketpp::lib::error_code error;
  m_server.send(m_handle, packet.wire(), packet.size(),
                websocketpp::frame::opcode::binary, error);
  if (error)
    return processErrorCode(error);

  NFD_LOG_FACE_TRACE("Successfully sent: " << packet.size() << " bytes");
}

void
WebSocketTransport::receiveMessage(const std::string& msg)
{
  NFD_LOG_FACE_TRACE("Received: " << msg.size() << " bytes");

  bool isOk = false;
  Block element;
  std::tie(isOk, element) = Block::fromBuffer(reinterpret_cast<const uint8_t*>(msg.data()), msg.size());
  if (!isOk) {
    NFD_LOG_FACE_WARN("Failed to parse message payload");
    return;
  }

  this->receive(element);
}

void
WebSocketTransport::schedulePing()
{
  m_pingEventId = getScheduler().schedule(m_pingInterval, [this] { sendPing(); });
}

void
WebSocketTransport::sendPing()
{
  NFD_LOG_FACE_TRACE(__func__);

  websocketpp::lib::error_code error;
  m_server.ping(m_handle, "NFD-WebSocket", error);
  if (error)
    return processErrorCode(error);

  ++this->nOutPings;

  this->schedulePing();
}

void
WebSocketTransport::handlePong()
{
  NFD_LOG_FACE_TRACE(__func__);

  ++this->nInPongs;
}

void
WebSocketTransport::handlePongTimeout()
{
  NFD_LOG_FACE_ERROR("Pong timeout");
  this->setState(TransportState::FAILED);
  doClose();
}

void
WebSocketTransport::processErrorCode(const websocketpp::lib::error_code& error)
{
  NFD_LOG_FACE_TRACE(__func__);

  if (getState() == TransportState::CLOSING ||
      getState() == TransportState::FAILED ||
      getState() == TransportState::CLOSED)
    // transport is shutting down, ignore any errors
    return;

  NFD_LOG_FACE_ERROR("Send or ping operation failed: " << error.message());
  this->setState(TransportState::FAILED);
  doClose();
}

void
WebSocketTransport::doClose()
{
  NFD_LOG_FACE_TRACE(__func__);

  m_pingEventId.cancel();

  // use the non-throwing variant and ignore errors, if any
  websocketpp::lib::error_code error;
  m_server.close(m_handle, websocketpp::close::status::normal, "closed by NFD", error);

  this->setState(TransportState::CLOSED);
}

} // namespace face
} // namespace nfd
