// Copyright (c) 2017 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 "net/third_party/quiche/src/quic/quartc/quartc_factory.h"

#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
#include "net/third_party/quiche/src/quic/core/uber_received_packet_manager.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_session.h"

namespace quic {

std::unique_ptr<QuartcSession> CreateQuartcClientSession(
    const QuartcSessionConfig& quartc_session_config,
    const QuicClock* clock,
    QuicAlarmFactory* alarm_factory,
    QuicConnectionHelperInterface* connection_helper,
    const ParsedQuicVersionVector& supported_versions,
    QuicStringPiece server_crypto_config,
    QuartcPacketTransport* packet_transport) {
  DCHECK(packet_transport);

  // QuartcSession will eventually own both |writer| and |quic_connection|.
  auto writer = std::make_unique<QuartcPacketWriter>(
      packet_transport, quartc_session_config.max_packet_size);

  // While the QuicConfig is not directly used by the connection, creating it
  // also sets flag values which must be set before creating the connection.
  QuicConfig quic_config = CreateQuicConfig(quartc_session_config);

  // |dummy_id| and |dummy_address| are used because Quartc network layer will
  // not use these two.
  QuicConnectionId dummy_id = QuicUtils::CreateZeroConnectionId(
      supported_versions[0].transport_version);
  QuicSocketAddress dummy_address(QuicIpAddress::Any4(), /*port=*/0);
  std::unique_ptr<QuicConnection> quic_connection = CreateQuicConnection(
      dummy_id, dummy_address, connection_helper, alarm_factory, writer.get(),
      Perspective::IS_CLIENT, supported_versions);

  // Quartc sets its own ack delay; get that ack delay and copy it over
  // to the QuicConfig so that it can be properly advertised to the peer
  // via transport parameter negotiation.
  quic_config.SetMaxAckDelayToSendMs(quic_connection->received_packet_manager()
                                         .max_ack_delay()
                                         .ToMilliseconds());

  return std::make_unique<QuartcClientSession>(
      std::move(quic_connection), quic_config, supported_versions, clock,
      std::move(writer),
      CreateCryptoClientConfig(quartc_session_config.pre_shared_key),
      server_crypto_config);
}

void ConfigureGlobalQuicSettings() {
  // Fixes behavior of StopReading() with level-triggered stream sequencers.
  SetQuicReloadableFlag(quic_stop_reading_when_level_triggered, true);

  // Enable version 47 to enable variable-length connection ids.
  SetQuicReloadableFlag(quic_enable_version_47, true);

  // Ensure that we don't drop data because QUIC streams refuse to buffer it.
  // TODO(b/120099046):  Replace this with correct handling of WriteMemSlices().
  SetQuicFlag(FLAGS_quic_buffered_data_threshold,
              std::numeric_limits<int>::max());

  // Enable and request QUIC to include receive timestamps in ACK frames.
  SetQuicReloadableFlag(quic_send_timestamps, true);

  // Enable ACK_DECIMATION_WITH_REORDERING. It requires ack_decimation to be
  // false.
  SetQuicReloadableFlag(quic_enable_ack_decimation, false);

  // Note: flag settings have no effect for Exoblaze builds since
  // SetQuicReloadableFlag() gets stubbed out.
  SetQuicReloadableFlag(quic_bbr_less_probe_rtt, true);  // Enable BBR6,7,8.
  SetQuicReloadableFlag(quic_unified_iw_options, true);  // Enable IWXX opts.
  SetQuicReloadableFlag(quic_bbr_flexible_app_limited, true);  // Enable BBR9.
}

QuicConfig CreateQuicConfig(const QuartcSessionConfig& quartc_session_config) {
  // TODO(b/124398962): Figure out a better way to initialize QUIC flags.
  // Creating a config shouldn't have global side-effects on flags.  However,
  // this has the advantage of ensuring that flag values stay in sync with the
  // options requested by configs, so simply splitting the config and flag
  // settings doesn't seem preferable.
  ConfigureGlobalQuicSettings();

  // In exoblaze this may return false. DCHECK to avoid problems caused by
  // incorrect flags configuration.
  DCHECK(GetQuicReloadableFlag(quic_enable_version_47))
      << "Your build does not support quic reloadable flags and shouldn't "
         "place Quartc calls";

  QuicTagVector copt;
  copt.push_back(kNSTP);

  // Enable and request QUIC to include receive timestamps in ACK frames.
  copt.push_back(kSTMP);

  // Enable ACK_DECIMATION_WITH_REORDERING. It requires ack_decimation to be
  // false.
  copt.push_back(kAKD2);

  // Use unlimited decimation in order to reduce number of unbundled ACKs.
  copt.push_back(kAKDU);

  // Enable time-based loss detection.
  copt.push_back(kTIME);

  copt.push_back(kBBR3);  // Stay in low-gain until in-flight < BDP.
  copt.push_back(kBBR5);  // 40 RTT ack aggregation.
  copt.push_back(kBBR6);  // Use a 0.75 * BDP cwnd during PROBE_RTT.
  copt.push_back(kBBR8);  // Skip PROBE_RTT if app-limited.
  copt.push_back(kBBR9);  // Ignore app-limited if enough data is in flight.
  copt.push_back(kBBQ1);  // 2.773 pacing gain in STARTUP.
  copt.push_back(kBBQ2);  // 2.0 CWND gain in STARTUP.
  copt.push_back(k1RTT);  // Exit STARTUP after 1 RTT with no gains.
  copt.push_back(kIW10);  // 10-packet (14600 byte) initial cwnd.

  if (!quartc_session_config.enable_tail_loss_probe) {
    copt.push_back(kNTLP);
  }

  // TODO(b/112192153):  Test and possible enable slower startup when pipe
  // filling is ready to use.  Slower startup is kBBRS.

  QuicConfig quic_config;

  // Use the limits for the session & stream flow control. The default 16KB
  // limit leads to significantly undersending (not reaching BWE on the outgoing
  // bitrate) due to blocked frames, and it leads to high latency (and one-way
  // delay). Setting it to its limits is not going to cause issues (our streams
  // are small generally, and if we were to buffer 24MB it wouldn't be the end
  // of the world). We can consider setting different limits in future (e.g. 1MB
  // stream, 1.5MB session). It's worth noting that on 1mbps bitrate, limit of
  // 24MB can capture approx 4 minutes of the call, and the default increase in
  // size of the window (half of the window size) is approximately 2 minutes of
  // the call.
  quic_config.SetInitialSessionFlowControlWindowToSend(
      kSessionReceiveWindowLimit);
  quic_config.SetInitialStreamFlowControlWindowToSend(
      kStreamReceiveWindowLimit);
  quic_config.SetConnectionOptionsToSend(copt);
  quic_config.SetClientConnectionOptions(copt);
  if (quartc_session_config.max_time_before_crypto_handshake >
      QuicTime::Delta::Zero()) {
    quic_config.set_max_time_before_crypto_handshake(
        quartc_session_config.max_time_before_crypto_handshake);
  }
  if (quartc_session_config.max_idle_time_before_crypto_handshake >
      QuicTime::Delta::Zero()) {
    quic_config.set_max_idle_time_before_crypto_handshake(
        quartc_session_config.max_idle_time_before_crypto_handshake);
  }
  if (quartc_session_config.idle_network_timeout > QuicTime::Delta::Zero()) {
    quic_config.SetIdleNetworkTimeout(
        quartc_session_config.idle_network_timeout,
        quartc_session_config.idle_network_timeout);
  }

  // The ICE transport provides a unique 5-tuple for each connection. Save
  // overhead by omitting the connection id.
  quic_config.SetBytesForConnectionIdToSend(0);

  // Allow up to 1000 incoming streams at once. Quartc streams typically contain
  // one audio or video frame and close immediately. However, when a video frame
  // becomes larger than one packet, there is some delay between the start and
  // end of each stream. The default maximum of 100 only leaves about 1 second
  // of headroom (Quartc sends ~30 video frames per second) before QUIC starts
  // to refuse incoming streams. Back-pressure should clear backlogs of
  // incomplete streams, but targets 1 second for recovery. Increasing the
  // number of open streams gives sufficient headroom to recover before QUIC
  // refuses new streams.
  quic_config.SetMaxIncomingBidirectionalStreamsToSend(1000);

  return quic_config;
}

std::unique_ptr<QuicConnection> CreateQuicConnection(
    QuicConnectionId connection_id,
    const QuicSocketAddress& peer_address,
    QuicConnectionHelperInterface* connection_helper,
    QuicAlarmFactory* alarm_factory,
    QuicPacketWriter* packet_writer,
    Perspective perspective,
    ParsedQuicVersionVector supported_versions) {
  auto quic_connection = std::make_unique<QuicConnection>(
      connection_id, peer_address, connection_helper, alarm_factory,
      packet_writer,
      /*owns_writer=*/false, perspective, supported_versions);
  quic_connection->SetMaxPacketLength(
      packet_writer->GetMaxPacketSize(peer_address));

  QuicSentPacketManager& sent_packet_manager =
      quic_connection->sent_packet_manager();
  UberReceivedPacketManager& received_packet_manager =
      quic_connection->received_packet_manager();

  // Default delayed ack time is 25ms.
  // If data packets are sent less often (e.g. because p-time was modified),
  // we would force acks to be sent every 25ms regardless, increasing
  // overhead. Since generally we guarantee a packet every 20ms, changing
  // this value should have miniscule effect on quality on good connections,
  // but on poor connections, changing this number significantly reduced the
  // number of ack-only packets.
  // The p-time can go up to as high as 120ms, and when it does, it's
  // when the low overhead is the most important thing. Ideally it should be
  // above 120ms, but it cannot be higher than 0.5*RTO, which equals to 100ms.
  received_packet_manager.set_max_ack_delay(
      QuicTime::Delta::FromMilliseconds(100));
  sent_packet_manager.set_peer_max_ack_delay(
      QuicTime::Delta::FromMilliseconds(100));

  quic_connection->set_fill_up_link_during_probing(true);

  // We start ack decimation after 15 packets. Typically, we would see
  // 1-2 crypto handshake packets, one media packet, and 10 probing packets.
  // We want to get acks for the probing packets as soon as possible,
  // but we can start using ack decimation right after first probing completes.
  // The default was to not start ack decimation for the first 100 packets.
  quic_connection->set_min_received_before_ack_decimation(15);

  return quic_connection;
}

}  // namespace quic
