/* -*- 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 "tcp-factory.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("Cannot create unicast TCP face with 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 does not support FACE_PERSISTENCY_ON_DEMAND");
    onFailure(406, "Outgoing TCP faces do not support on-demand persistency");
    return;
  }

  tcp::Endpoint endpoint(ip::address::from_string(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 a TCP face with an 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 boost::asio::ip::address& localAddress,
                                            const boost::asio::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
