blob: f3178407007ccbccf3f66f1f260b8577e1ba7390 [file] [log] [blame]
// 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.
#ifndef QUICHE_QUIC_CORE_QUIC_PACKETS_H_
#define QUICHE_QUIC_CORE_QUIC_PACKETS_H_
#include <sys/types.h>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <ostream>
#include <string>
#include <utility>
#include "absl/strings/string_view.h"
#include "quiche/quic/core/frames/quic_frame.h"
#include "quiche/quic/core/quic_ack_listener_interface.h"
#include "quiche/quic/core/quic_bandwidth.h"
#include "quiche/quic/core/quic_constants.h"
#include "quiche/quic/core/quic_error_codes.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/platform/api/quic_export.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
namespace quic {
class QuicPacket;
struct QuicPacketHeader;
// Returns the destination connection ID of |header| when |perspective| is
// server, and the source connection ID when |perspective| is client.
QUICHE_EXPORT QuicConnectionId GetServerConnectionIdAsRecipient(
const QuicPacketHeader& header, Perspective perspective);
// Returns the destination connection ID of |header| when |perspective| is
// client, and the source connection ID when |perspective| is server.
QUICHE_EXPORT QuicConnectionId GetClientConnectionIdAsRecipient(
const QuicPacketHeader& header, Perspective perspective);
// Returns the destination connection ID of |header| when |perspective| is
// client, and the source connection ID when |perspective| is server.
QUICHE_EXPORT QuicConnectionId GetServerConnectionIdAsSender(
const QuicPacketHeader& header, Perspective perspective);
// Returns the destination connection ID included of |header| when |perspective|
// is client, and the source connection ID included when |perspective| is
// server.
QUICHE_EXPORT QuicConnectionIdIncluded GetServerConnectionIdIncludedAsSender(
const QuicPacketHeader& header, Perspective perspective);
// Returns the destination connection ID of |header| when |perspective| is
// server, and the source connection ID when |perspective| is client.
QUICHE_EXPORT QuicConnectionId GetClientConnectionIdAsSender(
const QuicPacketHeader& header, Perspective perspective);
// Returns the destination connection ID included of |header| when |perspective|
// is server, and the source connection ID included when |perspective| is
// client.
QUICHE_EXPORT QuicConnectionIdIncluded GetClientConnectionIdIncludedAsSender(
const QuicPacketHeader& header, Perspective perspective);
// Number of connection ID bytes that are actually included over the wire.
QUICHE_EXPORT uint8_t
GetIncludedConnectionIdLength(QuicConnectionId connection_id,
QuicConnectionIdIncluded connection_id_included);
// Number of destination connection ID bytes that are actually included over the
// wire for this particular header.
QUICHE_EXPORT uint8_t
GetIncludedDestinationConnectionIdLength(const QuicPacketHeader& header);
// Number of source connection ID bytes that are actually included over the
// wire for this particular header.
QUICHE_EXPORT uint8_t
GetIncludedSourceConnectionIdLength(const QuicPacketHeader& header);
// Size in bytes of the data packet header.
QUICHE_EXPORT size_t GetPacketHeaderSize(QuicTransportVersion version,
const QuicPacketHeader& header);
QUICHE_EXPORT size_t GetPacketHeaderSize(
QuicTransportVersion version, uint8_t destination_connection_id_length,
uint8_t source_connection_id_length, bool include_version,
bool include_diversification_nonce,
QuicPacketNumberLength packet_number_length,
quiche::QuicheVariableLengthIntegerLength retry_token_length_length,
QuicByteCount retry_token_length,
quiche::QuicheVariableLengthIntegerLength length_length);
// Index of the first byte in a QUIC packet of encrypted data.
QUICHE_EXPORT size_t GetStartOfEncryptedData(QuicTransportVersion version,
const QuicPacketHeader& header);
QUICHE_EXPORT size_t GetStartOfEncryptedData(
QuicTransportVersion version, uint8_t destination_connection_id_length,
uint8_t source_connection_id_length, bool include_version,
bool include_diversification_nonce,
QuicPacketNumberLength packet_number_length,
quiche::QuicheVariableLengthIntegerLength retry_token_length_length,
QuicByteCount retry_token_length,
quiche::QuicheVariableLengthIntegerLength length_length);
struct QUICHE_EXPORT QuicPacketHeader {
QuicPacketHeader();
QuicPacketHeader(const QuicPacketHeader& other);
~QuicPacketHeader();
QuicPacketHeader& operator=(const QuicPacketHeader& other);
QUICHE_EXPORT friend std::ostream& operator<<(std::ostream& os,
const QuicPacketHeader& header);
// Universal header. All QuicPacket headers will have a connection_id and
// public flags.
QuicConnectionId destination_connection_id;
QuicConnectionIdIncluded destination_connection_id_included;
QuicConnectionId source_connection_id;
QuicConnectionIdIncluded source_connection_id_included;
// This is only used for Google QUIC.
bool reset_flag;
// For Google QUIC, version flag in packets from the server means version
// negotiation packet. For IETF QUIC, version flag means long header.
bool version_flag;
// Indicates whether |possible_stateless_reset_token| contains a valid value
// parsed from the packet buffer. IETF QUIC only, always false for GQUIC.
bool has_possible_stateless_reset_token;
QuicPacketNumberLength packet_number_length;
uint8_t type_byte;
ParsedQuicVersion version;
// nonce contains an optional, 32-byte nonce value. If not included in the
// packet, |nonce| will be empty.
DiversificationNonce* nonce;
QuicPacketNumber packet_number;
// Format of this header.
PacketHeaderFormat form;
// Short packet type is reflected in packet_number_length.
QuicLongHeaderType long_packet_type;
// Only valid if |has_possible_stateless_reset_token| is true.
// Stores last 16 bytes of a this packet, used to check whether this packet is
// a stateless reset packet on decryption failure.
StatelessResetToken possible_stateless_reset_token;
// Length of the retry token length variable length integer field,
// carried only by v99 IETF Initial packets.
quiche::QuicheVariableLengthIntegerLength retry_token_length_length;
// Retry token, carried only by v99 IETF Initial packets.
absl::string_view retry_token;
// Length of the length variable length integer field,
// carried only by v99 IETF Initial, 0-RTT and Handshake packets.
quiche::QuicheVariableLengthIntegerLength length_length;
// Length of the packet number and payload, carried only by v99 IETF Initial,
// 0-RTT and Handshake packets. Also includes the length of the
// diversification nonce in server to client 0-RTT packets.
QuicByteCount remaining_packet_length;
bool operator==(const QuicPacketHeader& other) const;
bool operator!=(const QuicPacketHeader& other) const;
};
struct QUICHE_EXPORT QuicPublicResetPacket {
QuicPublicResetPacket();
explicit QuicPublicResetPacket(QuicConnectionId connection_id);
QuicConnectionId connection_id;
QuicPublicResetNonceProof nonce_proof;
QuicSocketAddress client_address;
// An arbitrary string to identify an endpoint. Used by clients to
// differentiate traffic from Google servers vs Non-google servers.
// Will not be used if empty().
std::string endpoint_id;
};
struct QUICHE_EXPORT QuicVersionNegotiationPacket {
QuicVersionNegotiationPacket();
explicit QuicVersionNegotiationPacket(QuicConnectionId connection_id);
QuicVersionNegotiationPacket(const QuicVersionNegotiationPacket& other);
~QuicVersionNegotiationPacket();
QuicConnectionId connection_id;
ParsedQuicVersionVector versions;
};
struct QUICHE_EXPORT QuicIetfStatelessResetPacket {
QuicIetfStatelessResetPacket();
QuicIetfStatelessResetPacket(const QuicPacketHeader& header,
StatelessResetToken token);
QuicIetfStatelessResetPacket(const QuicIetfStatelessResetPacket& other);
~QuicIetfStatelessResetPacket();
QuicPacketHeader header;
StatelessResetToken stateless_reset_token;
};
class QUICHE_EXPORT QuicData {
public:
// Creates a QuicData from a buffer and length. Does not own the buffer.
QuicData(const char* buffer, size_t length);
// Creates a QuicData from a buffer and length,
// optionally taking ownership of the buffer.
QuicData(const char* buffer, size_t length, bool owns_buffer);
// Creates a QuicData from a absl::string_view. Does not own the
// buffer.
QuicData(absl::string_view data);
QuicData(const QuicData&) = delete;
QuicData& operator=(const QuicData&) = delete;
virtual ~QuicData();
absl::string_view AsStringPiece() const {
return absl::string_view(data(), length());
}
const char* data() const { return buffer_; }
size_t length() const { return length_; }
private:
const char* buffer_;
size_t length_;
bool owns_buffer_;
};
class QUICHE_EXPORT QuicPacket : public QuicData {
public:
QuicPacket(
char* buffer, size_t length, bool owns_buffer,
uint8_t destination_connection_id_length,
uint8_t source_connection_id_length, bool includes_version,
bool includes_diversification_nonce,
QuicPacketNumberLength packet_number_length,
quiche::QuicheVariableLengthIntegerLength retry_token_length_length,
QuicByteCount retry_token_length,
quiche::QuicheVariableLengthIntegerLength length_length);
QuicPacket(QuicTransportVersion version, char* buffer, size_t length,
bool owns_buffer, const QuicPacketHeader& header);
QuicPacket(const QuicPacket&) = delete;
QuicPacket& operator=(const QuicPacket&) = delete;
absl::string_view AssociatedData(QuicTransportVersion version) const;
absl::string_view Plaintext(QuicTransportVersion version) const;
char* mutable_data() { return buffer_; }
private:
char* buffer_;
const uint8_t destination_connection_id_length_;
const uint8_t source_connection_id_length_;
const bool includes_version_;
const bool includes_diversification_nonce_;
const QuicPacketNumberLength packet_number_length_;
const quiche::QuicheVariableLengthIntegerLength retry_token_length_length_;
const QuicByteCount retry_token_length_;
const quiche::QuicheVariableLengthIntegerLength length_length_;
};
class QUICHE_EXPORT QuicEncryptedPacket : public QuicData {
public:
// Creates a QuicEncryptedPacket from a buffer and length.
// Does not own the buffer.
QuicEncryptedPacket(const char* buffer, size_t length);
// Creates a QuicEncryptedPacket from a buffer and length,
// optionally taking ownership of the buffer.
QuicEncryptedPacket(const char* buffer, size_t length, bool owns_buffer);
// Creates a QuicEncryptedPacket from a absl::string_view.
// Does not own the buffer.
QuicEncryptedPacket(absl::string_view data);
QuicEncryptedPacket(const QuicEncryptedPacket&) = delete;
QuicEncryptedPacket& operator=(const QuicEncryptedPacket&) = delete;
// Clones the packet into a new packet which owns the buffer.
std::unique_ptr<QuicEncryptedPacket> Clone() const;
// By default, gtest prints the raw bytes of an object. The bool data
// member (in the base class QuicData) causes this object to have padding
// bytes, which causes the default gtest object printer to read
// uninitialize memory. So we need to teach gtest how to print this object.
QUICHE_EXPORT friend std::ostream& operator<<(std::ostream& os,
const QuicEncryptedPacket& s);
};
namespace test {
class QuicReceivedPacketPeer;
} // namespace test
// A received encrypted QUIC packet, with a recorded time of receipt.
class QUICHE_EXPORT QuicReceivedPacket : public QuicEncryptedPacket {
public:
QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time);
QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time,
bool owns_buffer);
QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time,
bool owns_buffer, int ttl, bool ttl_valid);
QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time,
bool owns_buffer, int ttl, bool ttl_valid,
char* packet_headers, size_t headers_length,
bool owns_header_buffer);
QuicReceivedPacket(const char* buffer, size_t length, QuicTime receipt_time,
bool owns_buffer, int ttl, bool ttl_valid,
char* packet_headers, size_t headers_length,
bool owns_header_buffer, QuicEcnCodepoint ecn_codepoint);
~QuicReceivedPacket();
QuicReceivedPacket(const QuicReceivedPacket&) = delete;
QuicReceivedPacket& operator=(const QuicReceivedPacket&) = delete;
// Clones the packet into a new packet which owns the buffer.
std::unique_ptr<QuicReceivedPacket> Clone() const;
// Returns the time at which the packet was received.
QuicTime receipt_time() const { return receipt_time_; }
// This is the TTL of the packet, assuming ttl_vaild_ is true.
int ttl() const { return ttl_; }
// Start of packet headers.
char* packet_headers() const { return packet_headers_; }
// Length of packet headers.
int headers_length() const { return headers_length_; }
// By default, gtest prints the raw bytes of an object. The bool data
// member (in the base class QuicData) causes this object to have padding
// bytes, which causes the default gtest object printer to read
// uninitialize memory. So we need to teach gtest how to print this object.
QUICHE_EXPORT friend std::ostream& operator<<(std::ostream& os,
const QuicReceivedPacket& s);
QuicEcnCodepoint ecn_codepoint() const { return ecn_codepoint_; }
private:
friend class test::QuicReceivedPacketPeer;
const QuicTime receipt_time_;
int ttl_;
// Points to the start of packet headers.
char* packet_headers_;
// Length of packet headers.
int headers_length_;
// Whether owns the buffer for packet headers.
bool owns_header_buffer_;
QuicEcnCodepoint ecn_codepoint_;
};
// SerializedPacket contains information of a serialized(encrypted) packet.
//
// WARNING:
//
// If you add a member field to this class, please make sure it is properly
// copied in |CopySerializedPacket|.
//
struct QUICHE_EXPORT SerializedPacket {
SerializedPacket(QuicPacketNumber packet_number,
QuicPacketNumberLength packet_number_length,
const char* encrypted_buffer,
QuicPacketLength encrypted_length, bool has_ack,
bool has_stop_waiting);
// Copy constructor & assignment are deleted. Use |CopySerializedPacket| to
// make a copy.
SerializedPacket(const SerializedPacket& other) = delete;
SerializedPacket& operator=(const SerializedPacket& other) = delete;
SerializedPacket(SerializedPacket&& other);
~SerializedPacket();
// TODO(wub): replace |encrypted_buffer|+|release_encrypted_buffer| by a
// QuicOwnedPacketBuffer.
// Not owned if |release_encrypted_buffer| is nullptr. Otherwise it is
// released by |release_encrypted_buffer| on destruction.
const char* encrypted_buffer;
QuicPacketLength encrypted_length;
std::function<void(const char*)> release_encrypted_buffer;
QuicFrames retransmittable_frames;
QuicFrames nonretransmittable_frames;
IsHandshake has_crypto_handshake;
QuicPacketNumber packet_number;
QuicPacketNumberLength packet_number_length;
EncryptionLevel encryption_level;
// TODO(fayang): Remove has_ack and has_stop_waiting.
bool has_ack;
bool has_stop_waiting;
bool has_ack_ecn = false; // ack frame contains ECN counts.
TransmissionType transmission_type;
// The largest acked of the AckFrame in this packet if has_ack is true,
// 0 otherwise.
QuicPacketNumber largest_acked;
// Indicates whether this packet has a copy of ack frame in
// nonretransmittable_frames.
bool has_ack_frame_copy;
bool has_ack_frequency;
bool has_message;
SerializedPacketFate fate;
QuicSocketAddress peer_address;
// Sum of bytes from frames that are not retransmissions. This field is only
// populated for packets with "mixed frames": at least one frame of a
// retransmission type and at least one frame of NOT_RETRANSMISSION type.
std::optional<QuicByteCount> bytes_not_retransmitted;
// Only populated if encryption_level is ENCRYPTION_INITIAL.
// TODO(b/265777524): remove this.
std::optional<QuicPacketHeader> initial_header;
};
// Make a copy of |serialized| (including the underlying frames). |copy_buffer|
// indicates whether the encrypted buffer should be copied.
QUICHE_EXPORT SerializedPacket* CopySerializedPacket(
const SerializedPacket& serialized,
quiche::QuicheBufferAllocator* allocator, bool copy_buffer);
// Allocates a new char[] of size |packet.encrypted_length| and copies in
// |packet.encrypted_buffer|.
QUICHE_EXPORT char* CopyBuffer(const SerializedPacket& packet);
// Allocates a new char[] of size |encrypted_length| and copies in
// |encrypted_buffer|.
QUICHE_EXPORT char* CopyBuffer(const char* encrypted_buffer,
QuicPacketLength encrypted_length);
// Context for an incoming packet.
struct QUICHE_EXPORT QuicPerPacketContext {
virtual ~QuicPerPacketContext() {}
};
// ReceivedPacketInfo comprises information obtained by parsing the unencrypted
// bytes of a received packet.
struct QUICHE_EXPORT ReceivedPacketInfo {
ReceivedPacketInfo(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet);
ReceivedPacketInfo(const ReceivedPacketInfo& other) = default;
~ReceivedPacketInfo();
std::string ToString() const;
QUICHE_EXPORT friend std::ostream& operator<<(
std::ostream& os, const ReceivedPacketInfo& packet_info);
const QuicSocketAddress& self_address;
const QuicSocketAddress& peer_address;
const QuicReceivedPacket& packet;
PacketHeaderFormat form;
// This is only used if the form is IETF_QUIC_LONG_HEADER_PACKET.
QuicLongHeaderType long_packet_type;
bool version_flag;
bool use_length_prefix;
QuicVersionLabel version_label;
ParsedQuicVersion version;
QuicConnectionId destination_connection_id;
QuicConnectionId source_connection_id;
std::optional<absl::string_view> retry_token;
};
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_PACKETS_H_