/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2024,  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 "ethernet-channel.hpp"
#include "ethernet-protocol.hpp"
#include "face.hpp"
#include "generic-link-service.hpp"
#include "unicast-ethernet-transport.hpp"
#include "common/global.hpp"

#include <boost/range/adaptor/map.hpp>
#include <pcap/pcap.h>

namespace nfd::face {

NFD_LOG_INIT(EthernetChannel);

EthernetChannel::EthernetChannel(shared_ptr<const ndn::net::NetworkInterface> localEndpoint,
                                 time::nanoseconds idleTimeout)
  : m_localEndpoint(std::move(localEndpoint))
  , m_socket(getGlobalIoService())
  , m_pcap(m_localEndpoint->getName())
  , m_idleFaceTimeout(idleTimeout)
{
  setUri(FaceUri::fromDev(m_localEndpoint->getName()));
  NFD_LOG_CHAN_INFO("Creating channel");
}

void
EthernetChannel::connect(const ethernet::Address& remoteEndpoint,
                         const FaceParams& params,
                         const FaceCreatedCallback& onFaceCreated,
                         const FaceCreationFailedCallback& onConnectFailed)
{
  shared_ptr<Face> face;
  try {
    face = createFace(remoteEndpoint, params).second;
  }
  catch (const boost::system::system_error& e) {
    NFD_LOG_CHAN_DEBUG("Face creation for " << remoteEndpoint << " failed: " << e.what());
    if (onConnectFailed)
      onConnectFailed(504, "Face creation failed: "s + e.what());
    return;
  }

  // Need to invoke the callback regardless of whether or not we had already
  // created the face so that control responses and such can be sent
  onFaceCreated(face);
}

void
EthernetChannel::listen(const FaceCreatedCallback& onFaceCreated,
                        const FaceCreationFailedCallback& onFaceCreationFailed)
{
  if (isListening()) {
    NFD_LOG_CHAN_WARN("Already listening");
    return;
  }
  m_isListening = true;

  try {
    m_pcap.activate(DLT_EN10MB);
    m_socket.assign(m_pcap.getFd());
  }
  catch (const PcapHelper::Error& e) {
    NDN_THROW_NESTED(Error(e.what()));
  }
  updateFilter();

  asyncRead(onFaceCreated, onFaceCreationFailed);
  NFD_LOG_CHAN_DEBUG("Started listening");
}

void
EthernetChannel::asyncRead(const FaceCreatedCallback& onFaceCreated,
                           const FaceCreationFailedCallback& onReceiveFailed)
{
  m_socket.async_wait(boost::asio::posix::stream_descriptor::wait_read, [=] (const auto& e) {
    handleRead(e, onFaceCreated, onReceiveFailed);
  });
}

void
EthernetChannel::handleRead(const boost::system::error_code& error,
                            const FaceCreatedCallback& onFaceCreated,
                            const FaceCreationFailedCallback& onReceiveFailed)
{
  if (error) {
    if (error != boost::asio::error::operation_aborted) {
      NFD_LOG_CHAN_DEBUG("Receive failed: " << error.message());
      if (onReceiveFailed)
        onReceiveFailed(500, "Receive failed: " + error.message());
    }
    return;
  }

  auto [pkt, readErr] = m_pcap.readNextPacket();
  if (pkt.empty()) {
    NFD_LOG_CHAN_WARN("Read error: " << readErr);
  }
  else {
    auto [eh, frameErr] = ethernet::checkFrameHeader(pkt, m_localEndpoint->getEthernetAddress(),
                                                     m_localEndpoint->getEthernetAddress());
    if (eh == nullptr) {
      NFD_LOG_CHAN_DEBUG(frameErr);
    }
    else {
      ethernet::Address sender(eh->ether_shost);
      pkt = pkt.subspan(ethernet::HDR_LEN);
      processIncomingPacket(pkt, sender, onFaceCreated, onReceiveFailed);
    }
  }

#ifndef NDEBUG
  size_t nDropped = m_pcap.getNDropped();
  if (nDropped - m_nDropped > 0)
    NFD_LOG_CHAN_DEBUG("Detected " << nDropped - m_nDropped << " dropped frame(s)");
  m_nDropped = nDropped;
#endif

  asyncRead(onFaceCreated, onReceiveFailed);
}

void
EthernetChannel::processIncomingPacket(span<const uint8_t> packet,
                                       const ethernet::Address& sender,
                                       const FaceCreatedCallback& onFaceCreated,
                                       const FaceCreationFailedCallback& onReceiveFailed)
{
  NFD_LOG_CHAN_TRACE("New peer " << sender);

  bool isCreated = false;
  shared_ptr<Face> face;
  try {
    FaceParams params;
    params.persistency = ndn::nfd::FACE_PERSISTENCY_ON_DEMAND;
    std::tie(isCreated, face) = createFace(sender, params);
  }
  catch (const EthernetTransport::Error& e) {
    NFD_LOG_CHAN_DEBUG("Face creation for " << sender << " failed: " << e.what());
    if (onReceiveFailed)
      onReceiveFailed(504, "Face creation failed: "s + e.what());
    return;
  }

  if (isCreated)
    onFaceCreated(face);
  else
    NFD_LOG_CHAN_DEBUG("Received frame for existing face");

  // dispatch the packet to the face for processing
  auto* transport = static_cast<UnicastEthernetTransport*>(face->getTransport());
  transport->receivePayload(packet, sender);
}

std::pair<bool, shared_ptr<Face>>
EthernetChannel::createFace(const ethernet::Address& remoteEndpoint,
                            const FaceParams& params)
{
  auto it = m_channelFaces.find(remoteEndpoint);
  if (it != m_channelFaces.end()) {
    // we already have a face for this endpoint, so reuse it
    NFD_LOG_CHAN_TRACE("Reusing existing face for " << remoteEndpoint);
    return {false, it->second};
  }

  // else, create a new face
  GenericLinkService::Options options;
  options.allowFragmentation = true;
  options.allowReassembly = true;
  options.reliabilityOptions.isEnabled = params.wantLpReliability;
  if (params.mtu) {
    options.overrideMtu = *params.mtu;
  }

  auto linkService = make_unique<GenericLinkService>(options);
  auto transport = make_unique<UnicastEthernetTransport>(*m_localEndpoint, remoteEndpoint,
                                                         params.persistency, m_idleFaceTimeout);
  auto face = make_shared<Face>(std::move(linkService), std::move(transport));
  face->setChannel(weak_from_this());

  m_channelFaces[remoteEndpoint] = face;
  connectFaceClosedSignal(*face, [this, remoteEndpoint] {
    m_channelFaces.erase(remoteEndpoint);
    updateFilter();
  });
  updateFilter();

  return {true, face};
}

void
EthernetChannel::updateFilter()
{
  if (!isListening())
    return;

  std::string filter = "(ether proto " + std::to_string(ethernet::ETHERTYPE_NDN) +
                       ") && (ether dst " + m_localEndpoint->getEthernetAddress().toString() + ")";
  for (const auto& addr : m_channelFaces | boost::adaptors::map_keys) {
    filter += " && (not ether src " + addr.toString() + ")";
  }
  // "not vlan" must appear last in the filter expression, or the
  // rest of the filter won't work as intended, see pcap-filter(7)
  filter += " && (not vlan)";

  NFD_LOG_CHAN_TRACE("Updating filter: " << filter);
  m_pcap.setPacketFilter(filter.data());
}

} // namespace nfd::face
