| // 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_ |