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

#ifndef NDN_CXX_NET_NETLINK_MESSAGE_HPP
#define NDN_CXX_NET_NETLINK_MESSAGE_HPP

#include "ndn-cxx/detail/common.hpp"
#include "ndn-cxx/net/ethernet.hpp"

#ifndef NDN_CXX_HAVE_NETLINK
#error "This file should not be included ..."
#endif

#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <string.h>

#include <cstring>
#include <map>

#include <boost/asio/ip/address.hpp>

namespace ndn {
namespace net {

template<typename T>
constexpr size_t
getAttributeLength(const T* attr);

template<>
constexpr size_t
getAttributeLength(const nlattr* attr)
{
  return attr->nla_len;
}

template<>
constexpr size_t
getAttributeLength(const rtattr* attr)
{
  return attr->rta_len;
}

template<typename T>
constexpr size_t
getAttributeLengthAligned(const T* attr);

template<>
constexpr size_t
getAttributeLengthAligned(const nlattr* attr)
{
  return NLA_ALIGN(attr->nla_len);
}

template<>
constexpr size_t
getAttributeLengthAligned(const rtattr* attr)
{
  return RTA_ALIGN(attr->rta_len);
}

template<typename T>
constexpr uint16_t
getAttributeType(const T* attr);

template<>
constexpr uint16_t
getAttributeType(const nlattr* attr)
{
  return attr->nla_type & NLA_TYPE_MASK;
}

template<>
constexpr uint16_t
getAttributeType(const rtattr* attr)
{
  return attr->rta_type;
}

template<typename T>
const uint8_t*
getAttributeValue(const T* attr);

template<>
inline const uint8_t*
getAttributeValue(const nlattr* attr)
{
  return reinterpret_cast<const uint8_t*>(attr) + NLA_HDRLEN;
}

template<>
inline const uint8_t*
getAttributeValue(const rtattr* attr)
{
  return reinterpret_cast<const uint8_t*>(RTA_DATA(const_cast<rtattr*>(attr)));
}

template<typename T>
constexpr size_t
getAttributeValueLength(const T* attr);

template<>
constexpr size_t
getAttributeValueLength(const nlattr* attr)
{
  return attr->nla_len - NLA_HDRLEN;
}

template<>
constexpr size_t
getAttributeValueLength(const rtattr* attr)
{
  return RTA_PAYLOAD(attr);
}

template<typename T>
class NetlinkMessageAttributes;

class NetlinkMessage
{
public:
  explicit
  NetlinkMessage(const uint8_t* buf, size_t buflen) noexcept
    : m_msg(reinterpret_cast<const nlmsghdr*>(buf))
    , m_length(buflen)
  {
    BOOST_ASSERT(buf != nullptr);
  }

  const nlmsghdr&
  operator*() const noexcept
  {
    return *m_msg;
  }

  const nlmsghdr*
  operator->() const noexcept
  {
    return m_msg;
  }

  bool
  isValid() const noexcept
  {
    return NLMSG_OK(m_msg, m_length);
  }

  NetlinkMessage
  getNext() const noexcept
  {
    BOOST_ASSERT(isValid());

    // mimic NLMSG_NEXT
    auto thisLen = NLMSG_ALIGN(m_msg->nlmsg_len);
    return NetlinkMessage{reinterpret_cast<const uint8_t*>(m_msg) + thisLen, m_length - thisLen};
  }

  template<typename T>
  const T*
  getPayload() const noexcept
  {
    BOOST_ASSERT(isValid());

    if (m_msg->nlmsg_len < NLMSG_LENGTH(sizeof(T)))
      return nullptr;

    return reinterpret_cast<const T*>(NLMSG_DATA(const_cast<nlmsghdr*>(m_msg)));
  }

  template<typename AttributeT, typename PayloadT>
  NetlinkMessageAttributes<AttributeT>
  getAttributes(const PayloadT* p) const noexcept
  {
    BOOST_ASSERT(isValid());

    auto begin = reinterpret_cast<const uint8_t*>(p) + NLMSG_ALIGN(sizeof(PayloadT));
    auto length = NLMSG_PAYLOAD(m_msg, sizeof(PayloadT));
    return NetlinkMessageAttributes<AttributeT>{reinterpret_cast<const AttributeT*>(begin), length};
  }

private:
  const nlmsghdr* m_msg;
  size_t m_length;
};

template<typename T>
class NetlinkMessageAttributes
{
  // empty type used to implement tag dispatching in getAttributeByType()
  template<typename U>
  struct AttrValueTypeTag {};

public:
  explicit
  NetlinkMessageAttributes(const T* begin, size_t length) noexcept
  {
    for (; isAttrValid(begin, length); begin = getNextAttr(begin, length)) {
      m_attrs[getAttributeType(begin)] = begin;
    }
  }

  size_t
  size() const noexcept
  {
    return m_attrs.size();
  }

  template<typename U>
  optional<U>
  getAttributeByType(uint16_t attrType) const
  {
    auto it = m_attrs.find(attrType);
    if (it == m_attrs.end())
      return nullopt;

    return convertAttrValue(getAttributeValue(it->second),
                            getAttributeValueLength(it->second),
                            AttrValueTypeTag<U>{});
  }

private:
  static bool
  isAttrValid(const T* attr, size_t nBytesRemaining) noexcept
  {
    return attr != nullptr &&
           nBytesRemaining >= sizeof(T) &&
           getAttributeLength(attr) >= sizeof(T) &&
           getAttributeLength(attr) <= nBytesRemaining;
  }

  static const T*
  getNextAttr(const T* attr, size_t& nBytesRemaining) noexcept
  {
    auto len = getAttributeLengthAligned(attr);
    if (len > nBytesRemaining) // prevent integer underflow
      return nullptr;

    nBytesRemaining -= len;
    return reinterpret_cast<const T*>(reinterpret_cast<const uint8_t*>(attr) + len);
  }

  template<typename Integral>
  static std::enable_if_t<std::is_integral<Integral>::value, optional<Integral>>
  convertAttrValue(const uint8_t* val, size_t len, AttrValueTypeTag<Integral>)
  {
    if (len < sizeof(Integral))
      return nullopt;

    Integral i;
    std::memcpy(&i, val, sizeof(Integral));
    return i;
  }

  static optional<std::string>
  convertAttrValue(const uint8_t* val, size_t len, AttrValueTypeTag<std::string>)
  {
    auto str = reinterpret_cast<const char*>(val);
    if (::strnlen(str, len) >= len)
      return nullopt;

    return std::string(str);
  }

  static optional<ethernet::Address>
  convertAttrValue(const uint8_t* val, size_t len, AttrValueTypeTag<ethernet::Address>)
  {
    if (len < ethernet::ADDR_LEN)
      return nullopt;

    return ethernet::Address(val);
  }

  template<typename IpAddress>
  static std::enable_if_t<std::is_same<IpAddress, boost::asio::ip::address_v4>::value ||
                          std::is_same<IpAddress, boost::asio::ip::address_v6>::value,
                          optional<IpAddress>>
  convertAttrValue(const uint8_t* val, size_t len, AttrValueTypeTag<IpAddress>)
  {
    typename IpAddress::bytes_type bytes;
    if (len < bytes.size())
      return nullopt;

    std::copy_n(val, bytes.size(), bytes.begin());
    return IpAddress(bytes);
  }

private:
  std::map<uint16_t, const T*> m_attrs;
};

} // namespace net
} // namespace ndn

#endif // NDN_CXX_NET_NETLINK_MESSAGE_HPP
