/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2015,  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"

namespace nfd {
namespace face {

NFD_LOG_INIT("WebSocketTransport");

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 (sock.local_endpoint().address().is_loopback() &&
      sock.remote_endpoint().address().is_loopback())
    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_INFO("Creating transport");
}

void
WebSocketTransport::beforeChangePersistency(ndn::nfd::FacePersistency newPersistency)
{
  if (newPersistency != ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
    BOOST_THROW_EXCEPTION(
      std::invalid_argument("WebSocketTransport supports only FACE_PERSISTENCY_ON_DEMAND"));
  }
}

void
WebSocketTransport::doSend(Transport::Packet&& packet)
{
  NFD_LOG_FACE_TRACE(__func__);

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

  NFD_LOG_FACE_TRACE("Successfully sent: " << packet.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.c_str()), msg.size());
  if (!isOk) {
    NFD_LOG_FACE_WARN("Failed to parse message payload");
    return;
  }

  this->receive(Transport::Packet(std::move(element)));
}

void
WebSocketTransport::schedulePing()
{
  m_pingEventId = scheduler::schedule(m_pingInterval, bind(&WebSocketTransport::sendPing, this));
}

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

  ++this->nOutPings;

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

  this->schedulePing();
}

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

  ++this->nInPongs;
}

void
WebSocketTransport::handlePongTimeout()
{
  NFD_LOG_FACE_WARN(__func__);
  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_WARN("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
