/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2017,  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 "multicast-udp-transport.hpp"
#include "udp-protocol.hpp"

#ifdef __linux__
#include <cerrno>       // for errno
#include <cstring>      // for std::strerror()
#include <sys/socket.h> // for setsockopt()
#endif // __linux__

namespace nfd {
namespace face {

NFD_LOG_INCLASS_2TEMPLATE_SPECIALIZATION_DEFINE(DatagramTransport, MulticastUdpTransport::protocol,
                                                Multicast, "MulticastUdpTransport");

MulticastUdpTransport::MulticastUdpTransport(const protocol::endpoint& localEndpoint,
                                             const protocol::endpoint& multicastGroup,
                                             protocol::socket&& recvSocket,
                                             protocol::socket&& sendSocket,
                                             ndn::nfd::LinkType linkType)
  : DatagramTransport(std::move(recvSocket))
  , m_multicastGroup(multicastGroup)
  , m_sendSocket(std::move(sendSocket))
{
  this->setLocalUri(FaceUri(localEndpoint));
  this->setRemoteUri(FaceUri(multicastGroup));
  this->setScope(ndn::nfd::FACE_SCOPE_NON_LOCAL);
  this->setPersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT);
  this->setLinkType(linkType);
  this->setMtu(udp::computeMtu(localEndpoint));

  NFD_LOG_FACE_INFO("Creating transport");
}

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

  m_sendSocket.async_send_to(boost::asio::buffer(packet.packet), m_multicastGroup,
                             bind(&MulticastUdpTransport::handleSend, this,
                                  boost::asio::placeholders::error,
                                  boost::asio::placeholders::bytes_transferred,
                                  packet.packet));
}

void
MulticastUdpTransport::doClose()
{
  if (m_sendSocket.is_open()) {
    NFD_LOG_FACE_TRACE("Closing sending socket");

    // Cancel all outstanding operations and close the socket.
    // Use the non-throwing variants and ignore errors, if any.
    boost::system::error_code error;
    m_sendSocket.cancel(error);
    m_sendSocket.close(error);
  }

  DatagramTransport::doClose();
}

void
MulticastUdpTransport::openRxSocket(protocol::socket& sock,
                                    const protocol::endpoint& multicastGroup,
                                    const boost::asio::ip::address& localAddress,
                                    const shared_ptr<const ndn::net::NetworkInterface>& netif)
{
  BOOST_ASSERT(!sock.is_open());

  sock.open(multicastGroup.protocol());
  sock.set_option(protocol::socket::reuse_address(true));
  sock.bind(protocol::endpoint(multicastGroup.protocol(), multicastGroup.port()));

  if (multicastGroup.address().is_v4()) {
    BOOST_ASSERT(localAddress.is_v4());
    sock.set_option(boost::asio::ip::multicast::join_group(multicastGroup.address().to_v4(),
                                                           localAddress.to_v4()));
  }
  else {
    // IPv6 multicast is not supported
    BOOST_ASSERT(false);
  }

#ifdef __linux__
  if (netif) {
    // On Linux, if there is more than one MulticastUdpTransport for the same multicast
    // group but they are on different network interfaces, each socket needs to be bound
    // to the corresponding interface using SO_BINDTODEVICE, otherwise the transport will
    // receive all packets sent to the other interfaces as well.
    // This is needed only on Linux. On macOS, the boost::asio::ip::multicast::join_group
    // option is sufficient to obtain the desired behavior.
    if (::setsockopt(sock.native_handle(), SOL_SOCKET, SO_BINDTODEVICE,
                     netif->getName().data(), netif->getName().size() + 1) < 0) {
      BOOST_THROW_EXCEPTION(Error("Cannot bind multicast rx socket to " + netif->getName() +
                                  ": " + std::strerror(errno)));
    }
  }
#endif // __linux__
}

void
MulticastUdpTransport::openTxSocket(protocol::socket& sock,
                                    const protocol::endpoint& localEndpoint,
                                    bool enableLoopback)
{
  BOOST_ASSERT(!sock.is_open());

  sock.open(localEndpoint.protocol());
  sock.set_option(protocol::socket::reuse_address(true));
  sock.set_option(boost::asio::ip::multicast::enable_loopback(enableLoopback));
  sock.bind(localEndpoint);

  if (localEndpoint.address().is_v4()) {
    if (!localEndpoint.address().is_unspecified())
      sock.set_option(boost::asio::ip::multicast::outbound_interface(localEndpoint.address().to_v4()));
  }
  else {
    // IPv6 multicast is not supported
    BOOST_ASSERT(false);
  }
}

template<>
Transport::EndpointId
DatagramTransport<boost::asio::ip::udp, Multicast>::makeEndpointId(const protocol::endpoint& ep)
{
  // IPv6 multicast is not supported
  BOOST_ASSERT(ep.address().is_v4());

  return (static_cast<uint64_t>(ep.port()) << 32) |
          static_cast<uint64_t>(ep.address().to_v4().to_ulong());
}

} // namespace face
} // namespace nfd
