// Copyright (c) 2020 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/core/quic_legacy_version_encapsulator.h"

#include "quiche/quic/core/crypto/crypto_handshake_message.h"
#include "quiche/quic/core/crypto/crypto_protocol.h"
#include "quiche/quic/core/quic_utils.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"

namespace quic {

QuicLegacyVersionEncapsulator::QuicLegacyVersionEncapsulator(
    QuicPacketBuffer packet_buffer)
    : packet_buffer_(packet_buffer) {}

QuicLegacyVersionEncapsulator::~QuicLegacyVersionEncapsulator() {}

// static
QuicByteCount QuicLegacyVersionEncapsulator::GetMinimumOverhead(
    absl::string_view sni) {
  // The number 52 is the sum of:
  // - Flags (1 byte)
  // - Server Connection ID (8 bytes)
  // - Version (4 bytes)
  // - Packet Number (1 byte)
  // - Message Authentication Hash (12 bytes)
  // - Frame Type (1 byte)
  // - Stream ID (1 byte)
  // - ClientHello tag (4 bytes)
  // - ClientHello num tags (2 bytes)
  // - Padding (2 bytes)
  // - SNI tag (4 bytes)
  // - SNI end offset (4 bytes)
  // - QLVE tag (4 bytes)
  // - QLVE end offset (4 bytes)
  return 52 + sni.length();
}

QuicPacketBuffer QuicLegacyVersionEncapsulator::GetPacketBuffer() {
  return packet_buffer_;
}

void QuicLegacyVersionEncapsulator::OnSerializedPacket(
    SerializedPacket serialized_packet) {
  if (encrypted_length_ != 0) {
    unrecoverable_failure_encountered_ = true;
    QUIC_BUG(quic_bug_10615_1) << "OnSerializedPacket called twice";
    return;
  }
  if (serialized_packet.encrypted_length == 0) {
    unrecoverable_failure_encountered_ = true;
    QUIC_BUG(quic_bug_10615_2) << "OnSerializedPacket called with empty packet";
    return;
  }
  encrypted_length_ = serialized_packet.encrypted_length;
}

void QuicLegacyVersionEncapsulator::OnUnrecoverableError(
    QuicErrorCode error, const std::string& error_details) {
  unrecoverable_failure_encountered_ = true;
  QUIC_BUG(quic_bug_10615_3) << "QuicLegacyVersionEncapsulator received error "
                             << error << ": " << error_details;
}

bool QuicLegacyVersionEncapsulator::ShouldGeneratePacket(
    HasRetransmittableData /*retransmittable*/, IsHandshake /*handshake*/) {
  return true;
}

const QuicFrames
QuicLegacyVersionEncapsulator::MaybeBundleAckOpportunistically() {
  // We do not want to ever include any ACKs here, return an empty array.
  return QuicFrames();
}

SerializedPacketFate QuicLegacyVersionEncapsulator::GetSerializedPacketFate(
    bool /*is_mtu_discovery*/, EncryptionLevel /*encryption_level*/) {
  return SEND_TO_WRITER;
}

// static
QuicPacketLength QuicLegacyVersionEncapsulator::Encapsulate(
    absl::string_view sni, absl::string_view inner_packet,
    const QuicConnectionId& server_connection_id, QuicTime creation_time,
    QuicByteCount outer_max_packet_length, char* out) {
  if (outer_max_packet_length > kMaxOutgoingPacketSize) {
    outer_max_packet_length = kMaxOutgoingPacketSize;
  }
  CryptoHandshakeMessage outer_chlo;
  outer_chlo.set_tag(kCHLO);
  outer_chlo.SetStringPiece(kSNI, sni);
  outer_chlo.SetStringPiece(kQLVE, inner_packet);
  const QuicData& serialized_outer_chlo = outer_chlo.GetSerialized();
  QUICHE_DCHECK(!LegacyVersionForEncapsulation().UsesCryptoFrames());
  QUICHE_DCHECK(LegacyVersionForEncapsulation().UsesQuicCrypto());
  QuicStreamFrame outer_stream_frame(
      QuicUtils::GetCryptoStreamId(
          LegacyVersionForEncapsulation().transport_version),
      /*fin=*/false,
      /*offset=*/0, serialized_outer_chlo.AsStringPiece());
  QuicFramer outer_framer(
      ParsedQuicVersionVector{LegacyVersionForEncapsulation()}, creation_time,
      Perspective::IS_CLIENT, kQuicDefaultConnectionIdLength);
  outer_framer.SetInitialObfuscators(server_connection_id);
  char outer_encrypted_packet[kMaxOutgoingPacketSize];
  QuicPacketBuffer outer_packet_buffer(outer_encrypted_packet, nullptr);
  QuicLegacyVersionEncapsulator creator_delegate(outer_packet_buffer);
  QuicPacketCreator outer_creator(server_connection_id, &outer_framer,
                                  &creator_delegate);
  outer_creator.SetMaxPacketLength(outer_max_packet_length);
  outer_creator.set_encryption_level(ENCRYPTION_INITIAL);
  outer_creator.SetTransmissionType(NOT_RETRANSMISSION);
  if (!outer_creator.AddPaddedSavedFrame(QuicFrame(outer_stream_frame),
                                         NOT_RETRANSMISSION)) {
    QUIC_BUG(quic_bug_10615_4)
        << "Failed to add Legacy Version Encapsulation stream frame "
           "(max packet length is "
        << outer_creator.max_packet_length() << ") " << outer_stream_frame;
    return 0;
  }
  outer_creator.FlushCurrentPacket();
  const QuicPacketLength encrypted_length = creator_delegate.encrypted_length_;
  if (creator_delegate.unrecoverable_failure_encountered_ ||
      encrypted_length == 0) {
    QUIC_BUG(quic_bug_10615_5)
        << "Failed to perform Legacy Version Encapsulation of "
        << inner_packet.length() << " bytes";
    return 0;
  }
  if (encrypted_length > kMaxOutgoingPacketSize) {
    QUIC_BUG(quic_bug_10615_6)
        << "Legacy Version Encapsulation outer creator generated a "
           "packet with unexpected length "
        << encrypted_length;
    return 0;
  }

  QUIC_DLOG(INFO) << "Successfully performed Legacy Version Encapsulation from "
                  << inner_packet.length() << " bytes to " << encrypted_length;

  // Replace our current packet with the encapsulated one.
  memcpy(out, outer_encrypted_packet, encrypted_length);
  return encrypted_length;
}

}  // namespace quic
