/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2023,  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 "tcp-factory.hpp"

#include <boost/lexical_cast.hpp>

namespace nfd::face {

namespace ip = boost::asio::ip;

NFD_LOG_INIT(TcpFactory);
NFD_REGISTER_PROTOCOL_FACTORY(TcpFactory);

const std::string&
TcpFactory::getId() noexcept
{
  static std::string id("tcp");
  return id;
}

void
TcpFactory::doProcessConfig(OptionalConfigSection configSection,
                            FaceSystem::ConfigContext& context)
{
  // tcp
  // {
  //   listen yes
  //   port 6363
  //   enable_v4 yes
  //   enable_v6 yes
  // }

  m_wantCongestionMarking = context.generalConfig.wantCongestionMarking;

  if (!configSection) {
    if (!context.isDryRun && !m_channels.empty()) {
      NFD_LOG_WARN("Cannot disable TCP channels after initialization");
    }
    return;
  }

  bool wantListen = true;
  uint16_t port = 6363;
  bool enableV4 = true;
  bool enableV6 = true;
  IpAddressPredicate local;
  bool isLocalConfigured = false;

  for (const auto& pair : *configSection) {
    const std::string& key = pair.first;

    if (key == "listen") {
      wantListen = ConfigFile::parseYesNo(pair, "face_system.tcp");
    }
    else if (key == "port") {
      port = ConfigFile::parseNumber<uint16_t>(pair, "face_system.tcp");
    }
    else if (key == "enable_v4") {
      enableV4 = ConfigFile::parseYesNo(pair, "face_system.tcp");
    }
    else if (key == "enable_v6") {
      enableV6 = ConfigFile::parseYesNo(pair, "face_system.tcp");
    }
    else if (key == "local") {
      isLocalConfigured = true;
      for (const auto& localPair : pair.second) {
        const std::string& localKey = localPair.first;
        if (localKey == "whitelist") {
          local.parseWhitelist(localPair.second);
        }
        else if (localKey == "blacklist") {
          local.parseBlacklist(localPair.second);
        }
        else {
          NDN_THROW(ConfigFile::Error("Unrecognized option face_system.tcp.local." + localKey));
        }
      }
    }
    else {
      NDN_THROW(ConfigFile::Error("Unrecognized option face_system.tcp." + key));
    }
  }
  if (!isLocalConfigured) {
    local.assign({{"subnet", "127.0.0.0/8"}, {"subnet", "::1/128"}}, {});
  }

  if (!enableV4 && !enableV6) {
    NDN_THROW(ConfigFile::Error(
      "IPv4 and IPv6 TCP channels have been disabled. Remove face_system.tcp section to disable "
      "TCP channels or enable at least one channel type."));
  }

  if (context.isDryRun) {
    return;
  }

  providedSchemes.insert("tcp");

  if (enableV4) {
    tcp::Endpoint endpoint(ip::tcp::v4(), port);
    auto v4Channel = this->createChannel(endpoint);
    if (wantListen && !v4Channel->isListening()) {
      v4Channel->listen(this->addFace, nullptr);
    }
    providedSchemes.insert("tcp4");
  }
  else if (providedSchemes.count("tcp4") > 0) {
    NFD_LOG_WARN("Cannot close tcp4 channel after its creation");
  }

  if (enableV6) {
    tcp::Endpoint endpoint(ip::tcp::v6(), port);
    auto v6Channel = this->createChannel(endpoint);
    if (wantListen && !v6Channel->isListening()) {
      v6Channel->listen(this->addFace, nullptr);
    }
    providedSchemes.insert("tcp6");
  }
  else if (providedSchemes.count("tcp6") > 0) {
    NFD_LOG_WARN("Cannot close tcp6 channel after its creation");
  }

  m_local = std::move(local);
}

void
TcpFactory::doCreateFace(const CreateFaceRequest& req,
                         const FaceCreatedCallback& onCreated,
                         const FaceCreationFailedCallback& onFailure)
{
  if (req.localUri) {
    NFD_LOG_TRACE("createFace: unsupported LocalUri");
    onFailure(406, "Unicast TCP faces cannot be created with a LocalUri");
    return;
  }

  if (req.params.persistency == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) {
    NFD_LOG_TRACE("createFace: unsupported FacePersistency");
    onFailure(406, "Outgoing TCP faces do not support on-demand persistency");
    return;
  }

  tcp::Endpoint endpoint(ip::make_address(req.remoteUri.getHost()),
                         boost::lexical_cast<uint16_t>(req.remoteUri.getPort()));

  // a canonical tcp4/tcp6 FaceUri cannot have a multicast address
  BOOST_ASSERT(!endpoint.address().is_multicast());

  if (req.params.wantLocalFields && !endpoint.address().is_loopback()) {
    NFD_LOG_TRACE("createFace: cannot create non-local face with local fields enabled");
    onFailure(406, "Local fields can only be enabled on faces with local scope");
    return;
  }

  if (req.params.mtu) {
    NFD_LOG_TRACE("createFace: cannot create TCP face with overridden MTU");
    onFailure(406, "TCP faces do not support MTU overrides");
    return;
  }

  // very simple logic for now
  for (const auto& i : m_channels) {
    if ((i.first.address().is_v4() && endpoint.address().is_v4()) ||
        (i.first.address().is_v6() && endpoint.address().is_v6())) {
      i.second->connect(endpoint, req.params, onCreated, onFailure);
      return;
    }
  }

  NFD_LOG_TRACE("No channels available to connect to " << endpoint);
  onFailure(504, "No channels available to connect");
}

shared_ptr<TcpChannel>
TcpFactory::createChannel(const tcp::Endpoint& endpoint)
{
  auto it = m_channels.find(endpoint);
  if (it != m_channels.end())
    return it->second;

  auto channel = make_shared<TcpChannel>(endpoint, m_wantCongestionMarking, [this] (auto&&... args) {
    return determineFaceScopeFromAddresses(std::forward<decltype(args)>(args)...);
  });
  m_channels[endpoint] = channel;
  return channel;
}

std::vector<shared_ptr<const Channel>>
TcpFactory::doGetChannels() const
{
  return getChannelsFromMap(m_channels);
}

ndn::nfd::FaceScope
TcpFactory::determineFaceScopeFromAddresses(const ip::address& localAddress,
                                            const ip::address& remoteAddress) const
{
  if (m_local(localAddress) && m_local(remoteAddress)) {
    return ndn::nfd::FACE_SCOPE_LOCAL;
  }
  return ndn::nfd::FACE_SCOPE_NON_LOCAL;
}

} // namespace nfd::face
