/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 * @author Davide Pesavento <davide.pesavento@lip6.fr>
 */

#include "network-monitor-impl-rtnl.hpp"
#include "linux-if-constants.hpp"
#include "../network-address.hpp"
#include "../network-interface.hpp"
#include "../../util/logger.hpp"
#include "../../util/time.hpp"

#include <boost/asio/write.hpp>

#include <cerrno>
#include <cstdlib>
#include <net/if_arp.h>
#include <sys/socket.h>

NDN_LOG_INIT(ndn.NetworkMonitor);

namespace ndn {
namespace net {

NetworkMonitor::Impl::Impl(NetworkMonitor& nm, boost::asio::io_service& io)
  : m_nm(nm)
  , m_socket(make_shared<boost::asio::posix::stream_descriptor>(io))
  , m_pid(0)
  , m_sequenceNo(static_cast<uint32_t>(time::system_clock::now().time_since_epoch().count()))
  , m_isEnumeratingLinks(false)
  , m_isEnumeratingAddresses(false)
{
  initSocket();
  asyncRead();

  NDN_LOG_TRACE("enumerating links");
  sendDumpRequest(RTM_GETLINK);
  m_isEnumeratingLinks = true;
}

NetworkMonitor::Impl::~Impl()
{
  boost::system::error_code error;
  m_socket->close(error);
}

shared_ptr<NetworkInterface>
NetworkMonitor::Impl::getNetworkInterface(const std::string& ifname) const
{
  for (const auto& e : m_interfaces) {
    if (e.second->getName() == ifname)
      return e.second;
  }
  return nullptr;
}

std::vector<shared_ptr<NetworkInterface>>
NetworkMonitor::Impl::listNetworkInterfaces() const
{
  std::vector<shared_ptr<NetworkInterface>> v;
  v.reserve(m_interfaces.size());

  for (const auto& e : m_interfaces) {
    v.push_back(e.second);
  }
  return v;
}

bool
NetworkMonitor::Impl::isEnumerating() const
{
  return m_isEnumeratingLinks || m_isEnumeratingAddresses;
}

void
NetworkMonitor::Impl::initSocket()
{
  NDN_LOG_TRACE("creating netlink socket");

  int fd = ::socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
  if (fd < 0) {
    BOOST_THROW_EXCEPTION(Error(std::string("Cannot create netlink socket (") +
                                std::strerror(errno) + ")"));
  }
  m_socket->assign(fd);

  sockaddr_nl addr{};
  addr.nl_family = AF_NETLINK;
  addr.nl_groups = RTMGRP_LINK | RTMGRP_NOTIFY |
                   RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
                   RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
  if (::bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
    BOOST_THROW_EXCEPTION(Error(std::string("Cannot bind netlink socket (") +
                                std::strerror(errno) + ")"));
  }

  // find out what pid has been assigned to us
  socklen_t len = sizeof(addr);
  if (::getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &len) < 0) {
    BOOST_THROW_EXCEPTION(Error(std::string("Cannot obtain netlink socket address (") +
                                std::strerror(errno) + ")"));
  }
  if (len != sizeof(addr)) {
    BOOST_THROW_EXCEPTION(Error("Wrong address length (" + to_string(len) + ")"));
  }
  if (addr.nl_family != AF_NETLINK) {
    BOOST_THROW_EXCEPTION(Error("Wrong address family (" + to_string(addr.nl_family) + ")"));
  }
  m_pid = addr.nl_pid;
  NDN_LOG_TRACE("our pid is " << m_pid);
}

void
NetworkMonitor::Impl::sendDumpRequest(uint16_t nlmsgType)
{
  auto request = make_shared<RtnlRequest>();
  request->nlh.nlmsg_len = sizeof(RtnlRequest);
  request->nlh.nlmsg_type = nlmsgType;
  request->nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
  request->nlh.nlmsg_seq = ++m_sequenceNo;
  request->nlh.nlmsg_pid = m_pid;
  request->ifi.ifi_family = AF_UNSPEC;
  request->rta.rta_type = IFLA_EXT_MASK;
  request->rta.rta_len = RTA_LENGTH(sizeof(request->rtext));
  request->rtext = 1 << 3; // RTEXT_FILTER_SKIP_STATS

  boost::asio::async_write(*m_socket, boost::asio::buffer(request.get(), sizeof(RtnlRequest)),
    // capture 'request' to prevent its premature deallocation
    [request] (const boost::system::error_code& error, size_t) {
      if (error && error != boost::asio::error::operation_aborted) {
        NDN_LOG_ERROR("write failed: " << error.message());
        BOOST_THROW_EXCEPTION(Error("Failed to send netlink request (" + error.message() + ")"));
      }
    });
}

static const char*
nlmsgTypeToString(uint16_t type)
{
#define NDN_NLMSG_STRING(x) case NLMSG_##x: return "<" #x ">"
#define NDN_RTM_STRING(x) case RTM_##x: return "<" #x ">"
  switch (type) {
    NDN_NLMSG_STRING(NOOP);
    NDN_NLMSG_STRING(ERROR);
    NDN_NLMSG_STRING(DONE);
    NDN_NLMSG_STRING(OVERRUN);
    NDN_RTM_STRING(NEWLINK);
    NDN_RTM_STRING(DELLINK);
    NDN_RTM_STRING(NEWADDR);
    NDN_RTM_STRING(DELADDR);
    NDN_RTM_STRING(NEWROUTE);
    NDN_RTM_STRING(DELROUTE);
    default:
      return "";
  }
#undef NDN_NLMSG_STRING
#undef NDN_RTM_STRING
}

static InterfaceType
ifiTypeToInterfaceType(uint16_t type)
{
  switch (type) {
    case ARPHRD_ETHER:
      return InterfaceType::ETHERNET;
    case ARPHRD_LOOPBACK:
      return InterfaceType::LOOPBACK;
    default:
      return InterfaceType::UNKNOWN;
  }
}

static AddressFamily
ifaFamilyToAddressFamily(uint8_t family)
{
  switch (family) {
    case AF_INET:
      return AddressFamily::V4;
    case AF_INET6:
      return AddressFamily::V6;
    default:
      return AddressFamily::UNSPECIFIED;
  }
}

static AddressScope
ifaScopeToAddressScope(uint8_t scope)
{
  switch (scope) {
    case RT_SCOPE_NOWHERE:
      return AddressScope::NOWHERE;
    case RT_SCOPE_HOST:
      return AddressScope::HOST;
    case RT_SCOPE_LINK:
      return AddressScope::LINK;
    default:
      return AddressScope::GLOBAL;
  }
}

void
NetworkMonitor::Impl::asyncRead()
{
  m_socket->async_read_some(boost::asio::buffer(m_buffer),
                            bind(&Impl::handleRead, this, _1, _2, m_socket));
}

void
NetworkMonitor::Impl::handleRead(const boost::system::error_code& error, size_t nBytesRead,
                                 const shared_ptr<boost::asio::posix::stream_descriptor>& socket)
{
  if (!socket->is_open() ||
      error == boost::asio::error::operation_aborted) {
    // socket was closed, ignore the error
    NDN_LOG_TRACE("socket closed or operation aborted");
    return;
  }
  if (error) {
    NDN_LOG_ERROR("read failed: " << error.message());
    BOOST_THROW_EXCEPTION(Error("Netlink socket read failed (" + error.message() + ")"));
  }

  NDN_LOG_TRACE("read " << nBytesRead << " bytes from netlink socket");

  const nlmsghdr* nlh = reinterpret_cast<const nlmsghdr*>(m_buffer.data());
  if (!isEnumerating() || (nlh->nlmsg_seq == m_sequenceNo && nlh->nlmsg_pid == m_pid)) {
    parseNetlinkMessage(nlh, nBytesRead);
  }
  else {
    NDN_LOG_TRACE("seq/pid mismatch, ignoring");
  }

  asyncRead();
}

void
NetworkMonitor::Impl::parseNetlinkMessage(const nlmsghdr* nlh, size_t len)
{
  while (NLMSG_OK(nlh, len)) {
    NDN_LOG_TRACE("parsing " << (nlh->nlmsg_flags & NLM_F_MULTI ? "multi-part " : "") <<
                  "message type=" << nlh->nlmsg_type << nlmsgTypeToString(nlh->nlmsg_type) <<
                  " len=" << nlh->nlmsg_len <<
                  " seq=" << nlh->nlmsg_seq <<
                  " pid=" << nlh->nlmsg_pid);

    if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
      NDN_LOG_ERROR("netlink dump was interrupted");
      // TODO: technically we should retry the dump...
      break;
    }

    if (nlh->nlmsg_type == NLMSG_DONE)
      break;

    switch (nlh->nlmsg_type) {
      case RTM_NEWLINK:
      case RTM_DELLINK:
        parseLinkMessage(nlh, reinterpret_cast<const ifinfomsg*>(NLMSG_DATA(nlh)));
        if (!isEnumerating())
          m_nm.onNetworkStateChanged(); // backward compat
        break;

      case RTM_NEWADDR:
      case RTM_DELADDR:
        parseAddressMessage(nlh, reinterpret_cast<const ifaddrmsg*>(NLMSG_DATA(nlh)));
        if (!isEnumerating())
          m_nm.onNetworkStateChanged(); // backward compat
        break;

      case RTM_NEWROUTE:
      case RTM_DELROUTE:
        parseRouteMessage(nlh, reinterpret_cast<const rtmsg*>(NLMSG_DATA(nlh)));
        if (!isEnumerating())
          m_nm.onNetworkStateChanged(); // backward compat
        break;

      case NLMSG_ERROR: {
        const nlmsgerr* err = reinterpret_cast<const nlmsgerr*>(NLMSG_DATA(nlh));
        if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(nlmsgerr)))
          NDN_LOG_ERROR("truncated NLMSG_ERROR");
        else if (err->error == 0)
          // an error code of zero indicates an ACK message, not an error
          NDN_LOG_TRACE("ACK");
        else
          NDN_LOG_ERROR("NLMSG_ERROR: " << std::strerror(std::abs(err->error)));
        break;
      }
    }

    nlh = NLMSG_NEXT(nlh, len);
  }

  if (nlh->nlmsg_type == NLMSG_DONE && m_isEnumeratingLinks) {
    // links enumeration complete, now request all the addresses
    m_isEnumeratingLinks = false;
    NDN_LOG_TRACE("enumerating addresses");
    sendDumpRequest(RTM_GETADDR);
    m_isEnumeratingAddresses = true;
  }
  else if (nlh->nlmsg_type == NLMSG_DONE && m_isEnumeratingAddresses) {
    // links and addresses enumeration complete
    m_isEnumeratingAddresses = false;
    // TODO: enumerate routes
    NDN_LOG_DEBUG("enumeration complete");
    m_nm.onEnumerationCompleted();
  }
}

void
NetworkMonitor::Impl::parseLinkMessage(const nlmsghdr* nlh, const ifinfomsg* ifi)
{
  if (ifiTypeToInterfaceType(ifi->ifi_type) == InterfaceType::UNKNOWN) {
    NDN_LOG_DEBUG("unhandled interface type " << ifi->ifi_type);
    return;
  }

  shared_ptr<NetworkInterface> interface;
  auto it = m_interfaces.find(ifi->ifi_index);
  if (it != m_interfaces.end()) {
    interface = it->second;
    BOOST_ASSERT(interface != nullptr);
    BOOST_ASSERT(interface->getIndex() == ifi->ifi_index);
  }

  if (nlh->nlmsg_type == RTM_DELLINK) {
    if (interface != nullptr) {
      NDN_LOG_DEBUG("removing interface " << interface->getName());
      m_interfaces.erase(it);
      m_nm.onInterfaceRemoved(interface);
    }
    return;
  }

  if (interface == nullptr) {
    // cannot use make_shared because NetworkInterface constructor is private
    interface.reset(new NetworkInterface);
    interface->setIndex(ifi->ifi_index);
  }
  interface->setType(ifiTypeToInterfaceType(ifi->ifi_type));
  interface->setFlags(ifi->ifi_flags);

  const rtattr* rta = reinterpret_cast<const rtattr*>(IFLA_RTA(ifi));
  size_t rtaTotalLen = IFLA_PAYLOAD(nlh);
  uint8_t operState = linux_if::OPER_STATE_UNKNOWN;

  while (RTA_OK(rta, rtaTotalLen)) {
    size_t attrLen = RTA_PAYLOAD(rta);

    switch (rta->rta_type) {
      case IFLA_ADDRESS:
        if (attrLen == ethernet::ADDR_LEN) {
          ethernet::Address addr(reinterpret_cast<const uint8_t*>(RTA_DATA(rta)));
          interface->setEthernetAddress(addr);
        }
        break;

      case IFLA_BROADCAST:
        if (attrLen == ethernet::ADDR_LEN) {
          ethernet::Address addr(reinterpret_cast<const uint8_t*>(RTA_DATA(rta)));
          interface->setEthernetBroadcastAddress(addr);
        }
        break;

      case IFLA_IFNAME: {
        auto attrData = reinterpret_cast<const char*>(RTA_DATA(rta));
        if (::strnlen(attrData, attrLen) <= attrLen)
          interface->setName(attrData);
        break;
      }

      case IFLA_MTU:
        if (attrLen == sizeof(uint32_t))
          interface->setMtu(*(reinterpret_cast<const uint32_t*>(RTA_DATA(rta))));
        break;

      case IFLA_OPERSTATE:
        if (attrLen == sizeof(uint8_t))
          operState = *(reinterpret_cast<const uint8_t*>RTA_DATA(rta));
        break;
    }

    rta = RTA_NEXT(rta, rtaTotalLen);
  }

  updateInterfaceState(*interface, operState);

  if (it == m_interfaces.end()) {
    NDN_LOG_DEBUG("adding interface " << interface->getName());
    m_interfaces[interface->getIndex()] = interface;
    m_nm.onInterfaceAdded(interface);
  }
}

void
NetworkMonitor::Impl::parseAddressMessage(const nlmsghdr* nlh, const ifaddrmsg* ifa)
{
  auto it = m_interfaces.find(ifa->ifa_index);
  if (it == m_interfaces.end()) {
    // unknown interface, ignore message
    NDN_LOG_TRACE("unknown interface index " << ifa->ifa_index);
    return;
  }
  auto interface = it->second;
  BOOST_ASSERT(interface != nullptr);

  namespace ip = boost::asio::ip;

  NetworkAddress address;
  address.m_family = ifaFamilyToAddressFamily(ifa->ifa_family);
  BOOST_ASSERT(address.m_family != AddressFamily::UNSPECIFIED);
  address.m_prefixLength = ifa->ifa_prefixlen;
  address.m_flags = ifa->ifa_flags; // will be overridden by IFA_FLAGS below, if the attribute is present
  address.m_scope = ifaScopeToAddressScope(ifa->ifa_scope);

  const rtattr* rta = reinterpret_cast<const rtattr*>(IFA_RTA(ifa));
  size_t rtaTotalLen = IFA_PAYLOAD(nlh);

  while (RTA_OK(rta, rtaTotalLen)) {
    auto attrData = reinterpret_cast<const unsigned char*>(RTA_DATA(rta));
    size_t attrLen = RTA_PAYLOAD(rta);

    switch (rta->rta_type) {
      case IFA_LOCAL:
        if (ifa->ifa_family == AF_INET && attrLen == sizeof(ip::address_v4::bytes_type)) {
          ip::address_v4::bytes_type bytes;
          std::copy_n(attrData, bytes.size(), bytes.begin());
          address.m_ip = ip::address_v4(bytes);
        }
        break;

      case IFA_ADDRESS:
        if (ifa->ifa_family == AF_INET6 && attrLen == sizeof(ip::address_v6::bytes_type)) {
          ip::address_v6::bytes_type bytes;
          std::copy_n(attrData, bytes.size(), bytes.begin());
          address.m_ip = ip::address_v6(bytes);
        }
        break;

      case IFA_BROADCAST:
        if (ifa->ifa_family == AF_INET && attrLen == sizeof(ip::address_v4::bytes_type)) {
          ip::address_v4::bytes_type bytes;
          std::copy_n(attrData, bytes.size(), bytes.begin());
          address.m_broadcast = ip::address_v4(bytes);
        }
        break;

#ifdef NDN_CXX_HAVE_IFA_FLAGS
      case IFA_FLAGS:
        if (attrLen == sizeof(uint32_t))
          address.m_flags = *(reinterpret_cast<const uint32_t*>(attrData));
        break;
#endif // NDN_CXX_HAVE_IFA_FLAGS
    }

    rta = RTA_NEXT(rta, rtaTotalLen);
  }

  if (nlh->nlmsg_type == RTM_NEWADDR)
    interface->addNetworkAddress(address);
  else if (nlh->nlmsg_type == RTM_DELADDR)
    interface->removeNetworkAddress(address);
}

void
NetworkMonitor::Impl::parseRouteMessage(const nlmsghdr* nlh, const rtmsg* rtm)
{
  // TODO
}

void
NetworkMonitor::Impl::updateInterfaceState(NetworkInterface& interface, uint8_t operState)
{
  if (operState == linux_if::OPER_STATE_UP) {
    interface.setState(InterfaceState::RUNNING);
  }
  else if (operState == linux_if::OPER_STATE_DORMANT) {
    interface.setState(InterfaceState::DORMANT);
  }
  else {
    // fallback to flags
    auto flags = interface.getFlags();
    if ((flags & linux_if::FLAG_LOWER_UP) && !(flags & linux_if::FLAG_DORMANT))
      interface.setState(InterfaceState::RUNNING);
    else if (flags & IFF_UP)
      interface.setState(InterfaceState::NO_CARRIER);
    else
      interface.setState(InterfaceState::DOWN);
  }
}

} // namespace net
} // namespace ndn
