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

#include "common/privilege-helper.hpp"

#include <boost/asio/ip/multicast.hpp>
#include <boost/asio/ip/v6_only.hpp>
#include <boost/functional/hash.hpp>

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

namespace nfd::face {

NFD_LOG_MEMBER_INIT_SPECIALIZED((DatagramTransport<boost::asio::ip::udp, Multicast>), MulticastUdpTransport);

MulticastUdpTransport::MulticastUdpTransport(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(m_sendSocket.local_endpoint()));
  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(m_sendSocket.local_endpoint()));

  protocol::socket::send_buffer_size sendBufferSizeOption;
  boost::system::error_code error;
  m_sendSocket.get_option(sendBufferSizeOption);
  if (error) {
    NFD_LOG_FACE_WARN("Failed to obtain send queue capacity from socket: " << error.message());
    this->setSendQueueCapacity(QUEUE_ERROR);
  }
  else {
    this->setSendQueueCapacity(sendBufferSizeOption.value());
  }

  NFD_LOG_FACE_DEBUG("Creating transport");
}

ssize_t
MulticastUdpTransport::getSendQueueLength()
{
  ssize_t queueLength = getTxQueueLength(m_sendSocket.native_handle());
  if (queueLength == QUEUE_ERROR) {
    NFD_LOG_FACE_WARN("Failed to obtain send queue length from socket: " << std::strerror(errno));
  }
  return queueLength;
}

void
MulticastUdpTransport::doSend(const Block& packet)
{
  NFD_LOG_FACE_TRACE(__func__);

  m_sendSocket.async_send_to(boost::asio::buffer(packet), m_multicastGroup,
                             // 'packet' is copied into the lambda to retain the underlying Buffer
                             [this, packet] (auto&&... args) {
                               this->handleSend(std::forward<decltype(args)>(args)...);
                             });
}

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();
}

static void
bindToDevice(int fd, const std::string& ifname)
{
  // 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.
  // We dont't set SO_BINDTODEVICE on Android because this operation requires root privilege
  // which is not allowed on Android, it will cause "Operation not permitted" error.

#if defined(__linux__) && !defined(__ANDROID__)
  PrivilegeHelper::runElevated([=] {
    if (::setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname.data(), ifname.size() + 1) < 0) {
      NDN_THROW_ERRNO(MulticastUdpTransport::Error("Cannot bind multicast rx socket to " + ifname));
    }
  });
#endif
}

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));

  if (multicastGroup.address().is_v4()) {
    BOOST_ASSERT(localAddress.is_v4());
    sock.bind(multicastGroup);
    sock.set_option(boost::asio::ip::multicast::join_group(multicastGroup.address().to_v4(),
                                                           localAddress.to_v4()));
  }
  else {
    BOOST_ASSERT(localAddress.is_v6());
    sock.set_option(boost::asio::ip::v6_only(true));
#ifdef NFD_WITH_TESTS
    // To simplify unit tests, we bind to the "any" IPv6 address if the supplied multicast
    // address lacks a scope id. Calling bind() without a scope id would otherwise fail.
    if (multicastGroup.address().to_v6().scope_id() == 0)
      sock.bind(protocol::endpoint(boost::asio::ip::address_v6::any(), multicastGroup.port()));
    else
#endif
      sock.bind(multicastGroup);
    sock.set_option(boost::asio::ip::multicast::join_group(multicastGroup.address().to_v6()));
  }

  if (netif)
    bindToDevice(sock.native_handle(), netif->getName());
}

void
MulticastUdpTransport::openTxSocket(protocol::socket& sock,
                                    const protocol::endpoint& localEndpoint,
                                    const shared_ptr<const ndn::net::NetworkInterface>& netif,
                                    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));

  if (localEndpoint.address().is_v4()) {
    sock.bind(localEndpoint);
    if (!localEndpoint.address().is_unspecified())
      sock.set_option(boost::asio::ip::multicast::outbound_interface(localEndpoint.address().to_v4()));
  }
  else {
    sock.set_option(boost::asio::ip::v6_only(true));
    sock.bind(localEndpoint);
    if (netif)
      sock.set_option(boost::asio::ip::multicast::outbound_interface(netif->getIndex()));
  }
}

template<>
EndpointId
DatagramTransport<boost::asio::ip::udp, Multicast>::makeEndpointId(const protocol::endpoint& ep)
{
  if (ep.address().is_v4()) {
    return (static_cast<uint64_t>(ep.port()) << 32) |
            static_cast<uint64_t>(ep.address().to_v4().to_ulong());
  }
  else {
    size_t seed = 0;
    const auto& addrBytes = ep.address().to_v6().to_bytes();
    boost::hash_range(seed, addrBytes.begin(), addrBytes.end());
    boost::hash_combine(seed, ep.port());
    return seed;
  }
}

} // namespace nfd::face
