// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quiche/quic/tools/quic_server.h"

#include <cerrno>
#include <cstdint>
#include <cstring>
#include <memory>
#include <utility>

#include "absl/status/statusor.h"
#include "quiche/quic/core/crypto/crypto_handshake_message.h"
#include "quiche/quic/core/crypto/proof_source.h"
#include "quiche/quic/core/crypto/quic_crypto_server_config.h"
#include "quiche/quic/core/crypto/quic_random.h"
#include "quiche/quic/core/io/event_loop_socket_factory.h"
#include "quiche/quic/core/io/quic_default_event_loop.h"
#include "quiche/quic/core/io/quic_event_loop.h"
#include "quiche/quic/core/io/quic_server_io_harness.h"
#include "quiche/quic/core/io/socket.h"
#include "quiche/quic/core/quic_connection_id.h"
#include "quiche/quic/core/quic_constants.h"
#include "quiche/quic/core/quic_crypto_server_stream_base.h"
#include "quiche/quic/core/quic_default_clock.h"
#include "quiche/quic/core/quic_default_connection_helper.h"
#include "quiche/quic/core/quic_default_packet_writer.h"
#include "quiche/quic/core/quic_dispatcher.h"
#include "quiche/quic/core/quic_packet_writer.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/core/quic_udp_socket.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/quic/tools/quic_simple_crypto_server_stream_helper.h"
#include "quiche/quic/tools/quic_simple_dispatcher.h"
#include "quiche/quic/tools/quic_simple_server_backend.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/simple_buffer_allocator.h"

namespace quic {

namespace {

const char kSourceAddressTokenSecret[] = "secret";

}  // namespace

QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source,
                       std::unique_ptr<ProofVerifier> proof_verifier,
                       QuicSimpleServerBackend* quic_simple_server_backend)
    : QuicServer(std::move(proof_source), std::move(proof_verifier),
                 quic_simple_server_backend, AllSupportedVersions()) {}

QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source,
                       std::unique_ptr<ProofVerifier> proof_verifier,
                       QuicSimpleServerBackend* quic_simple_server_backend,
                       const ParsedQuicVersionVector& supported_versions)
    : QuicServer(std::move(proof_source), std::move(proof_verifier),
                 QuicConfig(), QuicCryptoServerConfig::ConfigOptions(),
                 supported_versions, quic_simple_server_backend,
                 kQuicDefaultConnectionIdLength) {}

QuicServer::QuicServer(
    std::unique_ptr<ProofSource> proof_source,
    std::unique_ptr<ProofVerifier> proof_verifier, const QuicConfig& config,
    const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
    const ParsedQuicVersionVector& supported_versions,
    QuicSimpleServerBackend* quic_simple_server_backend,
    uint8_t expected_server_connection_id_length)
    : silent_close_(false),
      config_(config),
      crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance(),
                     std::move(proof_source), KeyExchangeSource::Default(),
                     std::move(proof_verifier)),
      crypto_config_options_(crypto_config_options),
      version_manager_(supported_versions),
      quic_simple_server_backend_(quic_simple_server_backend),
      expected_server_connection_id_length_(
          expected_server_connection_id_length),
      connection_id_generator_(expected_server_connection_id_length) {
  QUICHE_DCHECK(quic_simple_server_backend_);
  Initialize();
}

void QuicServer::Initialize() {
  // If an initial flow control window has not explicitly been set, then use a
  // sensible value for a server: 1 MB for session, 64 KB for each stream.
  const uint32_t kInitialSessionFlowControlWindow = 1 * 1024 * 1024;  // 1 MB
  const uint32_t kInitialStreamFlowControlWindow = 64 * 1024;         // 64 KB
  if (config_.GetInitialStreamFlowControlWindowToSend() ==
      kDefaultFlowControlSendWindow) {
    config_.SetInitialStreamFlowControlWindowToSend(
        kInitialStreamFlowControlWindow);
  }
  if (config_.GetInitialSessionFlowControlWindowToSend() ==
      kDefaultFlowControlSendWindow) {
    config_.SetInitialSessionFlowControlWindowToSend(
        kInitialSessionFlowControlWindow);
  }

  std::unique_ptr<CryptoHandshakeMessage> scfg(crypto_config_.AddDefaultConfig(
      QuicRandom::GetInstance(), QuicDefaultClock::Get(),
      crypto_config_options_));
}

QuicServer::~QuicServer() {
  // Ensure the I/O harness is gone before closing the socket.
  io_.reset();

  (void)socket_api::Close(fd_);
  fd_ = kInvalidSocketFd;

  // Should be fine without because nothing should send requests to the backend
  // after `this` is destroyed, but for extra pointer safety, clear the socket
  // factory from the backend before the socket factory is destroyed.
  quic_simple_server_backend_->SetSocketFactory(nullptr);
}

bool QuicServer::CreateUDPSocketAndListen(const QuicSocketAddress& address) {
  event_loop_ = CreateEventLoop();

  socket_factory_ = std::make_unique<EventLoopSocketFactory>(
      event_loop_.get(), quiche::SimpleBufferAllocator::Get());
  quic_simple_server_backend_->SetSocketFactory(socket_factory_.get());

  dispatcher_.reset(CreateQuicDispatcher());

  absl::StatusOr<SocketFd> fd = CreateAndBindServerSocket(address);
  if (!fd.ok()) {
    QUIC_LOG(ERROR) << "Failed to create and bind socket: " << fd;
    return false;
  }
  fd_ = *fd;
  dispatcher_->InitializeWithWriter(CreateWriter(fd_));

  absl::StatusOr<std::unique_ptr<QuicServerIoHarness>> io =
      QuicServerIoHarness::Create(event_loop_.get(), dispatcher_.get(), fd_);
  if (!io.ok()) {
    QUICHE_LOG(ERROR) << "Failed to create I/O harness: " << io.status();
    return false;
  }
  io_ = *std::move(io);

  QUIC_LOG(INFO) << "Listening on " << io_->local_address();

  return true;
}

QuicPacketWriter* QuicServer::CreateWriter(int fd) {
  return new QuicDefaultPacketWriter(fd);
}

QuicDispatcher* QuicServer::CreateQuicDispatcher() {
  return new QuicSimpleDispatcher(
      &config_, &crypto_config_, &version_manager_,
      std::make_unique<QuicDefaultConnectionHelper>(),
      std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
          new QuicSimpleCryptoServerStreamHelper()),
      event_loop_->CreateAlarmFactory(), quic_simple_server_backend_,
      expected_server_connection_id_length_, connection_id_generator_);
}

std::unique_ptr<QuicEventLoop> QuicServer::CreateEventLoop() {
  return GetDefaultEventLoop()->Create(QuicDefaultClock::Get());
}

void QuicServer::HandleEventsForever() {
  while (true) {
    WaitForEvents();
  }
}

void QuicServer::WaitForEvents() {
  event_loop_->RunEventLoopOnce(QuicTime::Delta::FromMilliseconds(50));
}

void QuicServer::Shutdown() {
  if (!silent_close_) {
    // Before we shut down the epoll server, give all active sessions a chance
    // to notify clients that they're closing.
    dispatcher_->Shutdown();
  }

  io_.reset();
  dispatcher_.reset();
  event_loop_.reset();
}

}  // namespace quic
