/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "api/LifecycleAPIHooks.h"
#include "iocore/net/UDPNet.h"
#include "tscore/ink_config.h"
#include "../../iocore/net/P_SSLNextProtocolAccept.h"
#include "proxy/ProtocolProbeSessionAccept.h"
#include "proxy/ReverseProxy.h"
#include "proxy/http/HttpConfig.h"
#include "proxy/http/HttpProxyServerMain.h"
#include "proxy/http/HttpSessionAccept.h"
#include "proxy/http/HttpSessionManager.h"
#include "proxy/http/PreWarmManager.h"
#include "proxy/http2/Http2SessionAccept.h"
#ifdef USE_HTTP_DEBUG_LISTS
#include "proxy/http/Http1ClientSession.h"
#endif
#if TS_USE_QUIC == 1
#include "../../iocore/net/P_QUICNetProcessor.h"
#include "../../iocore/net/P_QUICNextProtocolAccept.h"
#include "proxy/http3/Http3SessionAccept.h"
#elif TS_USE_QMUX == 1
#include "proxy/http3/Http3SessionAccept.h"
#endif

#include <vector>

HttpSessionAccept                                    *plugin_http_accept             = nullptr;
HttpSessionAccept                                    *plugin_http_transparent_accept = nullptr;
extern std::function<PoolableSession *()>             create_h1_server_session;
extern std::function<PoolableSession *()>             create_h2_server_session;
extern std::map<int, std::function<ProxySession *()>> ProtocolSessionCreateMap;

static SLL<SSLNextProtocolAccept> ssl_plugin_acceptors;
static Ptr<ProxyMutex>            ssl_plugin_mutex;

std::mutex              proxyServerMutex;
std::condition_variable proxyServerCheck;
bool                    et_net_threads_ready = false;

std::mutex              etUdpMutex;
std::condition_variable etUdpCheck;
bool                    et_udp_threads_ready = false;

// File / process scope initializations
static bool HTTP_SERVER_INITIALIZED __attribute__((unused)) = []() -> bool {
  swoc::bwf::Global_Names().assign("ts-thread", [](swoc::BufferWriter &w, swoc::bwf::Spec const &spec) -> swoc::BufferWriter & {
    return bwformat(w, spec, this_thread());
  });
  swoc::bwf::Global_Names().assign("ts-ethread", [](swoc::BufferWriter &w, swoc::bwf::Spec const &spec) -> swoc::BufferWriter & {
    return bwformat(w, spec, this_ethread());
  });
  return true;
}();

bool
ssl_register_protocol(const char *protocol, Continuation *contp)
{
  SCOPED_MUTEX_LOCK(lock, ssl_plugin_mutex, this_ethread());

  for (SSLNextProtocolAccept *ssl = ssl_plugin_acceptors.head; ssl; ssl = ssl_plugin_acceptors.next(ssl)) {
    if (!ssl->registerEndpoint(protocol, contp)) {
      return false;
    }
  }

  return true;
}

/////////////////////////////////////////////////////////////////
//
//  main()
//
/////////////////////////////////////////////////////////////////

/** Data about an acceptor.

    This is used to separate setting up the proxy ports and
    starting to accept on them.

*/
struct HttpProxyAcceptor {
  /// Accept continuation.
  Continuation *_accept = nullptr;
  /// Options for @c NetProcessor.
  NetProcessor::AcceptOptions _net_opt;

  /// Default constructor.
  HttpProxyAcceptor() {}
};

/** Global acceptors.

    This is parallel to @c HttpProxyPort::global(), each generated
    from the corresponding port descriptor.

    @internal We use @c Continuation instead of @c HttpAccept because
    @c SSLNextProtocolAccept is a subclass of @c Cont instead of @c
    HttpAccept.
*/
std::vector<HttpProxyAcceptor> HttpProxyAcceptors;

// Called from InkAPI.cc
NetProcessor::AcceptOptions
make_net_accept_options(const HttpProxyPort *port, unsigned nthreads)
{
  NetProcessor::AcceptOptions net;

  net.accept_threads = nthreads;

  net.packet_mark   = RecGetRecordInt("proxy.config.net.sock_packet_mark_in").value_or(0);
  net.packet_tos    = RecGetRecordInt("proxy.config.net.sock_packet_tos_in").value_or(0);
  net.recv_bufsize  = RecGetRecordInt("proxy.config.net.sock_recv_buffer_size_in").value_or(0);
  net.send_bufsize  = RecGetRecordInt("proxy.config.net.sock_send_buffer_size_in").value_or(0);
  net.sockopt_flags = RecGetRecordInt("proxy.config.net.sock_option_flag_in").value_or(0);
  net.defer_accept  = RecGetRecordInt("proxy.config.net.defer_accept").value_or(0);

#if TCP_NOTSENT_LOWAT
  net.packet_notsent_lowat = RecGetRecordInt("proxy.config.net.sock_notsent_lowat").value_or(0);
#endif

#ifdef TCP_FASTOPEN
  net.tfo_queue_length = RecGetRecordInt("proxy.config.net.sock_option_tfo_queue_size_in").value_or(0);
#endif

  if (port) {
    net.f_inbound_transparent       = port->m_inbound_transparent_p;
    net.f_mptcp                     = port->m_mptcp;
    net.ip_family                   = port->m_family;
    net.local_port                  = port->m_port;
    net.f_proxy_protocol            = port->m_proxy_protocol;
    net.f_proxy_protocol_client_src = port->m_proxy_protocol_client_src;

    if (port->m_inbound_ip.isValid()) {
      net.local_ip = port->m_inbound_ip;
    } else if (AF_INET6 == port->m_family && HttpConfig::m_master.inbound.has_ip6()) {
      net.local_ip = HttpConfig::m_master.inbound.ip6().network_order();
    } else if (AF_INET == port->m_family && HttpConfig::m_master.inbound.has_ip4()) {
      net.local_ip = HttpConfig::m_master.inbound.ip4().network_order();
    } else if (AF_UNIX == port->m_family) {
      net.local_path = port->m_unix_path;
      net.unix_perm  = port->m_unix_perm;
      net.unix_uid   = port->m_unix_uid;
      net.unix_gid   = port->m_unix_gid;
      net.sockopt_flags &=
        ~(NetVCOptions::SOCK_OPT_NO_DELAY | NetVCOptions::SOCK_OPT_TCP_FAST_OPEN | NetVCOptions::SOCK_OPT_TCP_NOTSENT_LOWAT);
    }
  }
  return net;
}

static void
MakeHttpProxyAcceptor(HttpProxyAcceptor &acceptor, HttpProxyPort &port, unsigned nthreads)
{
  NetProcessor::AcceptOptions &net_opt    = acceptor._net_opt;
  auto                         accept_opt = std::make_shared<HttpSessionAccept::Options>();

  net_opt = make_net_accept_options(&port, nthreads);

  accept_opt->f_outbound_transparent = port.m_outbound_transparent_p;
  accept_opt->transport_type         = port.m_type;
  accept_opt->setHostResPreference(port.m_host_res_preference);
  accept_opt->setTransparentPassthrough(port.m_transparent_passthrough);
  accept_opt->setSessionProtocolPreference(port.m_session_protocol_preference);

  accept_opt->outbound += HttpConfig::m_master.outbound;
  accept_opt->outbound += port.m_outbound; // top priority, override master and base options.

  // OK the way this works is that the fallback for each port is a protocol
  // probe acceptor. For SSL ports, we can stack a NPN+ALPN acceptor in front
  // of that, and these ports will fall back to the probe if no NPN+ALPN endpoint
  // was negotiated.

  // XXX the protocol probe should be a configuration option.

  // A QUIC port is dispatched to the QUIC acceptor below, which has no probe fallback, so building a
  // probe for one only leaks it. Every other port type ends up behind the probe, either directly or
  // as the SSL acceptor's fallback. Without QUIC compiled in no port can be a QUIC port, so this is
  // always true there.
  bool const needs_probe = !port.isQUIC();

  ProtocolProbeSessionAccept *probe = nullptr;
  HttpSessionAccept          *http  = nullptr; // don't allocate this unless it will be used.

  if (needs_probe) {
    probe                       = new ProtocolProbeSessionAccept();
    probe->proxyPort            = &port;
    probe->proxy_protocol_ipmap = &HttpConfig::m_master.config_proxy_protocol_ip_addrs;

    if (port.m_session_protocol_preference.intersects(HTTP_PROTOCOL_SET)) {
      http = new HttpSessionAccept(accept_opt, &port);
      probe->registerEndpoint(ProtocolProbeSessionAccept::ProtoGroupKey::HTTP, http);
    }

    if (port.m_session_protocol_preference.intersects(HTTP2_PROTOCOL_SET)) {
      probe->registerEndpoint(ProtocolProbeSessionAccept::ProtoGroupKey::HTTP2, new Http2SessionAccept(accept_opt, &port));
    }
  }

  ProtocolSessionCreateMap.insert({TS_ALPN_PROTOCOL_INDEX_HTTP_1_0, create_h1_server_session});
  ProtocolSessionCreateMap.insert({TS_ALPN_PROTOCOL_INDEX_HTTP_1_1, create_h1_server_session});
  ProtocolSessionCreateMap.insert({TS_ALPN_PROTOCOL_INDEX_HTTP_2_0, create_h2_server_session});

  if (port.isSSL()) {
    SSLNextProtocolAccept *ssl = new SSLNextProtocolAccept(probe, port.m_transparent_passthrough, port.m_allow_plain);

    // ALPN selects the first server-offered protocol,
    // so make sure that we offer the newest protocol first.
    // But since registerEndpoint prepends you want to
    // register them backwards, so you'd want to register
    // the least important protocol first:
    // http/1.0, http/1.1, h2

    ssl->enableProtocols(port.m_session_protocol_preference);
    ssl->registerEndpoint(TS_ALPN_PROTOCOL_HTTP_1_0, http);
    ssl->registerEndpoint(TS_ALPN_PROTOCOL_HTTP_1_1, http);
    ssl->registerEndpoint(TS_ALPN_PROTOCOL_HTTP_2_0, new Http2SessionAccept(accept_opt, &port));
#if TS_USE_QMUX
    ssl->registerEndpoint(TS_ALPN_PROTOCOL_H3QX, new Http3SessionAccept(accept_opt, &port));
#endif

    SCOPED_MUTEX_LOCK(lock, ssl_plugin_mutex, this_ethread());
    ssl_plugin_acceptors.push(ssl);
    ssl->proxyPort   = &port;
    acceptor._accept = ssl;
#if TS_USE_QUIC == 1
  } else if (port.isQUIC()) {
    QUICNextProtocolAccept *quic = new QUICNextProtocolAccept();

    quic->enableProtocols(port.m_session_protocol_preference);

    // HTTP/0.9 over QUIC draft-29 (for interop only, will be removed)
    quic->registerEndpoint(TS_ALPN_PROTOCOL_HTTP_QUIC_D29, new Http3SessionAccept(accept_opt, &port));

    // HTTP/3 draft-29
    quic->registerEndpoint(TS_ALPN_PROTOCOL_HTTP_3_D29, new Http3SessionAccept(accept_opt, &port));

    // HTTP/0.9 over QUIC (for interop only, will be removed)
    quic->registerEndpoint(TS_ALPN_PROTOCOL_HTTP_QUIC, new Http3SessionAccept(accept_opt, &port));

    // HTTP/3
    quic->registerEndpoint(TS_ALPN_PROTOCOL_HTTP_3, new Http3SessionAccept(accept_opt, &port));

    quic->proxyPort  = &port;
    acceptor._accept = quic;
#endif
  } else {
    acceptor._accept = probe;
  }
}

/// Do all pre-thread initialization / setup.
void
prep_HttpProxyServer()
{
  httpSessionManager.init();
}

/** Set up all the accepts and sockets.
 */
void
init_accept_HttpProxyServer(int n_accept_threads)
{
  HttpProxyPort::Group &proxy_ports = HttpProxyPort::global();

  init_reverse_proxy();

#ifdef USE_HTTP_DEBUG_LISTS
  ink_mutex_init(&debug_sm_list_mutex);
  ink_mutex_init(&debug_cs_list_mutex);
#endif

  // Used to give plugins the ability to create http requests
  //   The equivalent of the connecting to localhost on the  proxy
  //   port but without going through the operating system
  //
  if (plugin_http_accept == nullptr) {
    plugin_http_accept = new HttpSessionAccept();
  }

  // Same as plugin_http_accept except outbound transparent.
  if (!plugin_http_transparent_accept) {
    HttpSessionAccept::Options ha_opt;
    ha_opt.setOutboundTransparent(true);
    plugin_http_transparent_accept = new HttpSessionAccept(ha_opt);
  }

  if (!ssl_plugin_mutex) {
    ssl_plugin_mutex = new_ProxyMutex();
  }

  // Do the configuration defined ports.
  // Assign temporary empty objects of proxy ports size
  HttpProxyAcceptors.assign(proxy_ports.size(), HttpProxyAcceptor());
  for (int i = 0, n = proxy_ports.size(); i < n; ++i) {
    MakeHttpProxyAcceptor(HttpProxyAcceptors.at(i), proxy_ports[i], n_accept_threads);
  }
}

/** Increment the counter to keep track of how many et_net threads
 *  we have started. This function is scheduled at the start of each
 *  et_net thread using schedule_spawn(). We also check immediately
 *  after incrementing the counter to see whether all of the et_net
 *  threads have started such that we can notify main() to call
 *  start_HttpProxyServer().
 */
void
init_HttpProxyServer()
{
  if (eventProcessor.has_tg_started(ET_NET)) {
    std::unique_lock<std::mutex> lock(proxyServerMutex);
    et_net_threads_ready = true;
    lock.unlock();
    proxyServerCheck.notify_one();
  }

#if TS_USE_QUIC == 1
  if (eventProcessor.has_tg_started(ET_UDP)) {
    std::unique_lock<std::mutex> lock(etUdpMutex);
    et_udp_threads_ready = true;
    lock.unlock();
    etUdpCheck.notify_one();
  }
#endif
}

void
start_HttpProxyServer()
{
  static bool           called_once = false;
  HttpProxyPort::Group &proxy_ports = HttpProxyPort::global();

  ///////////////////////////////////
  // start accepting connections   //
  ///////////////////////////////////

  ink_assert(!called_once);
  ink_assert(proxy_ports.size() == HttpProxyAcceptors.size());

  for (int i = 0, n = proxy_ports.size(); i < n; ++i) {
    HttpProxyAcceptor &acceptor = HttpProxyAcceptors[i];
    HttpProxyPort     &port     = proxy_ports[i];
    if (port.isSSL()) {
      if (nullptr == sslNetProcessor.main_accept(acceptor._accept, port.m_fd, acceptor._net_opt)) {
        return;
      }
#if TS_USE_QUIC == 1
    } else if (port.isQUIC()) {
      if (nullptr == quic_NetProcessor.main_accept(acceptor._accept, port.m_fd, acceptor._net_opt)) {
        return;
      }
#endif
    } else if (!port.isPlugin()) {
      if (nullptr == netProcessor.main_accept(acceptor._accept, port.m_fd, acceptor._net_opt)) {
        return;
      }
    }
    // XXX although we make a good pretence here, I don't believe that NetProcessor::main_accept() ever actually returns
    // NULL. It would be useful to be able to detect errors and spew them here though.
  }

  // Alert plugins that connections will be accepted.
  APIHook *hook = g_lifecycle_hooks->get(TS_LIFECYCLE_PORTS_READY_HOOK);
  while (hook) {
    hook->invoke(TS_EVENT_LIFECYCLE_PORTS_READY, nullptr);
    hook = hook->next();
  }

  prewarmManager.start();
}

void
stop_HttpProxyServer()
{
  sslNetProcessor.stop_accept();
  netProcessor.stop_accept();

  for (auto &acceptor : HttpProxyAcceptors) {
    delete acceptor._accept;
    acceptor._accept = nullptr;
  }
  HttpProxyAcceptors.clear();

  delete plugin_http_accept;
  plugin_http_accept = nullptr;

  delete plugin_http_transparent_accept;
  plugin_http_transparent_accept = nullptr;
}
