| // 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 "net/third_party/quiche/src/quic/core/quic_packets.h" |
| |
| #include "net/third_party/quiche/src/quic/core/quic_utils.h" |
| #include "net/third_party/quiche/src/quic/core/quic_versions.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h" |
| |
| namespace quic { |
| |
| size_t GetPacketHeaderSize(QuicTransportVersion version, |
| const QuicPacketHeader& header) { |
| return GetPacketHeaderSize(version, header.destination_connection_id_length, |
| header.source_connection_id_length, |
| header.version_flag, header.nonce != nullptr, |
| header.packet_number_length); |
| } |
| |
| size_t GetPacketHeaderSize( |
| QuicTransportVersion version, |
| QuicConnectionIdLength destination_connection_id_length, |
| QuicConnectionIdLength source_connection_id_length, |
| bool include_version, |
| bool include_diversification_nonce, |
| QuicPacketNumberLength packet_number_length) { |
| if (version > QUIC_VERSION_43) { |
| if (include_version) { |
| // Long header. |
| return kPacketHeaderTypeSize + kConnectionIdLengthSize + |
| destination_connection_id_length + source_connection_id_length + |
| (version > QUIC_VERSION_46 ? packet_number_length |
| : PACKET_4BYTE_PACKET_NUMBER) + |
| kQuicVersionSize + |
| (include_diversification_nonce ? kDiversificationNonceSize : 0); |
| } |
| // Short header. |
| return kPacketHeaderTypeSize + destination_connection_id_length + |
| packet_number_length; |
| } |
| return kPublicFlagsSize + destination_connection_id_length + |
| (include_version ? kQuicVersionSize : 0) + packet_number_length + |
| (include_diversification_nonce ? kDiversificationNonceSize : 0); |
| } |
| |
| size_t GetStartOfEncryptedData(QuicTransportVersion version, |
| const QuicPacketHeader& header) { |
| return GetPacketHeaderSize(version, header); |
| } |
| |
| size_t GetStartOfEncryptedData( |
| QuicTransportVersion version, |
| QuicConnectionIdLength destination_connection_id_length, |
| QuicConnectionIdLength source_connection_id_length, |
| bool include_version, |
| bool include_diversification_nonce, |
| QuicPacketNumberLength packet_number_length) { |
| // Encryption starts before private flags. |
| return GetPacketHeaderSize( |
| version, destination_connection_id_length, source_connection_id_length, |
| include_version, include_diversification_nonce, packet_number_length); |
| } |
| |
| QuicPacketHeader::QuicPacketHeader() |
| : destination_connection_id(EmptyQuicConnectionId()), |
| destination_connection_id_length(PACKET_8BYTE_CONNECTION_ID), |
| source_connection_id(EmptyQuicConnectionId()), |
| source_connection_id_length(PACKET_0BYTE_CONNECTION_ID), |
| reset_flag(false), |
| version_flag(false), |
| has_possible_stateless_reset_token(false), |
| packet_number_length(PACKET_4BYTE_PACKET_NUMBER), |
| version(UnsupportedQuicVersion()), |
| nonce(nullptr), |
| form(GOOGLE_QUIC_PACKET), |
| long_packet_type(INITIAL), |
| possible_stateless_reset_token(0) {} |
| |
| QuicPacketHeader::QuicPacketHeader(const QuicPacketHeader& other) = default; |
| |
| QuicPacketHeader::~QuicPacketHeader() {} |
| |
| QuicPublicResetPacket::QuicPublicResetPacket() |
| : connection_id(EmptyQuicConnectionId()), nonce_proof(0) {} |
| |
| QuicPublicResetPacket::QuicPublicResetPacket(QuicConnectionId connection_id) |
| : connection_id(connection_id), nonce_proof(0) {} |
| |
| QuicVersionNegotiationPacket::QuicVersionNegotiationPacket() |
| : connection_id(EmptyQuicConnectionId()) {} |
| |
| QuicVersionNegotiationPacket::QuicVersionNegotiationPacket( |
| QuicConnectionId connection_id) |
| : connection_id(connection_id) {} |
| |
| QuicVersionNegotiationPacket::QuicVersionNegotiationPacket( |
| const QuicVersionNegotiationPacket& other) = default; |
| |
| QuicVersionNegotiationPacket::~QuicVersionNegotiationPacket() {} |
| |
| QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket() |
| : stateless_reset_token(0) {} |
| |
| QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket( |
| const QuicPacketHeader& header, |
| QuicUint128 token) |
| : header(header), stateless_reset_token(token) {} |
| |
| QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket( |
| const QuicIetfStatelessResetPacket& other) = default; |
| |
| QuicIetfStatelessResetPacket::~QuicIetfStatelessResetPacket() {} |
| |
| std::ostream& operator<<(std::ostream& os, const QuicPacketHeader& header) { |
| os << "{ destination_connection_id: " << header.destination_connection_id |
| << ", destination_connection_id_length: " |
| << header.destination_connection_id_length |
| << ", source_connection_id: " << header.source_connection_id |
| << ", source_connection_id_length: " << header.source_connection_id_length |
| << ", packet_number_length: " << header.packet_number_length |
| << ", reset_flag: " << header.reset_flag |
| << ", version_flag: " << header.version_flag; |
| if (header.version_flag) { |
| os << ", version: " << ParsedQuicVersionToString(header.version); |
| } |
| if (header.nonce != nullptr) { |
| os << ", diversification_nonce: " |
| << QuicTextUtils::HexEncode( |
| QuicStringPiece(header.nonce->data(), header.nonce->size())); |
| } |
| os << ", packet_number: " << header.packet_number << " }\n"; |
| return os; |
| } |
| |
| QuicData::QuicData(const char* buffer, size_t length) |
| : buffer_(buffer), length_(length), owns_buffer_(false) {} |
| |
| QuicData::QuicData(const char* buffer, size_t length, bool owns_buffer) |
| : buffer_(buffer), length_(length), owns_buffer_(owns_buffer) {} |
| |
| QuicData::~QuicData() { |
| if (owns_buffer_) { |
| delete[] const_cast<char*>(buffer_); |
| } |
| } |
| |
| QuicPacket::QuicPacket(char* buffer, |
| size_t length, |
| bool owns_buffer, |
| QuicConnectionIdLength destination_connection_id_length, |
| QuicConnectionIdLength source_connection_id_length, |
| bool includes_version, |
| bool includes_diversification_nonce, |
| QuicPacketNumberLength packet_number_length) |
| : QuicData(buffer, length, owns_buffer), |
| buffer_(buffer), |
| destination_connection_id_length_(destination_connection_id_length), |
| source_connection_id_length_(source_connection_id_length), |
| includes_version_(includes_version), |
| includes_diversification_nonce_(includes_diversification_nonce), |
| packet_number_length_(packet_number_length) {} |
| |
| QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer, size_t length) |
| : QuicData(buffer, length) {} |
| |
| QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer, |
| size_t length, |
| bool owns_buffer) |
| : QuicData(buffer, length, owns_buffer) {} |
| |
| std::unique_ptr<QuicEncryptedPacket> QuicEncryptedPacket::Clone() const { |
| char* buffer = new char[this->length()]; |
| memcpy(buffer, this->data(), this->length()); |
| return QuicMakeUnique<QuicEncryptedPacket>(buffer, this->length(), true); |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const QuicEncryptedPacket& s) { |
| os << s.length() << "-byte data"; |
| return os; |
| } |
| |
| QuicReceivedPacket::QuicReceivedPacket(const char* buffer, |
| size_t length, |
| QuicTime receipt_time) |
| : QuicReceivedPacket(buffer, |
| length, |
| receipt_time, |
| false /* owns_buffer */) {} |
| |
| QuicReceivedPacket::QuicReceivedPacket(const char* buffer, |
| size_t length, |
| QuicTime receipt_time, |
| bool owns_buffer) |
| : QuicReceivedPacket(buffer, |
| length, |
| receipt_time, |
| owns_buffer, |
| 0 /* ttl */, |
| true /* ttl_valid */) {} |
| |
| QuicReceivedPacket::QuicReceivedPacket(const char* buffer, |
| size_t length, |
| QuicTime receipt_time, |
| bool owns_buffer, |
| int ttl, |
| bool ttl_valid) |
| : quic::QuicReceivedPacket(buffer, |
| length, |
| receipt_time, |
| owns_buffer, |
| ttl, |
| ttl_valid, |
| nullptr /* packet_headers */, |
| 0 /* headers_length */, |
| false /* owns_header_buffer */) {} |
| |
| QuicReceivedPacket::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) |
| : QuicEncryptedPacket(buffer, length, owns_buffer), |
| receipt_time_(receipt_time), |
| ttl_(ttl_valid ? ttl : -1), |
| packet_headers_(packet_headers), |
| headers_length_(headers_length), |
| owns_header_buffer_(owns_header_buffer) {} |
| |
| QuicReceivedPacket::~QuicReceivedPacket() { |
| if (owns_header_buffer_) { |
| delete[] static_cast<char*>(packet_headers_); |
| } |
| } |
| |
| std::unique_ptr<QuicReceivedPacket> QuicReceivedPacket::Clone() const { |
| char* buffer = new char[this->length()]; |
| memcpy(buffer, this->data(), this->length()); |
| if (this->packet_headers()) { |
| char* headers_buffer = new char[this->headers_length()]; |
| memcpy(headers_buffer, this->packet_headers(), this->headers_length()); |
| return QuicMakeUnique<QuicReceivedPacket>( |
| buffer, this->length(), receipt_time(), true, ttl(), ttl() >= 0, |
| headers_buffer, this->headers_length(), true); |
| } |
| |
| return QuicMakeUnique<QuicReceivedPacket>( |
| buffer, this->length(), receipt_time(), true, ttl(), ttl() >= 0); |
| } |
| |
| std::ostream& operator<<(std::ostream& os, const QuicReceivedPacket& s) { |
| os << s.length() << "-byte data"; |
| return os; |
| } |
| |
| QuicStringPiece QuicPacket::AssociatedData(QuicTransportVersion version) const { |
| return QuicStringPiece( |
| data(), GetStartOfEncryptedData( |
| version, destination_connection_id_length_, |
| source_connection_id_length_, includes_version_, |
| includes_diversification_nonce_, packet_number_length_)); |
| } |
| |
| QuicStringPiece QuicPacket::Plaintext(QuicTransportVersion version) const { |
| const size_t start_of_encrypted_data = GetStartOfEncryptedData( |
| version, destination_connection_id_length_, source_connection_id_length_, |
| includes_version_, includes_diversification_nonce_, |
| packet_number_length_); |
| return QuicStringPiece(data() + start_of_encrypted_data, |
| length() - start_of_encrypted_data); |
| } |
| |
| SerializedPacket::SerializedPacket(QuicPacketNumber packet_number, |
| QuicPacketNumberLength packet_number_length, |
| const char* encrypted_buffer, |
| QuicPacketLength encrypted_length, |
| bool has_ack, |
| bool has_stop_waiting) |
| : encrypted_buffer(encrypted_buffer), |
| encrypted_length(encrypted_length), |
| has_crypto_handshake(NOT_HANDSHAKE), |
| num_padding_bytes(0), |
| packet_number(packet_number), |
| packet_number_length(packet_number_length), |
| encryption_level(ENCRYPTION_NONE), |
| has_ack(has_ack), |
| has_stop_waiting(has_stop_waiting), |
| transmission_type(NOT_RETRANSMISSION) {} |
| |
| SerializedPacket::SerializedPacket(const SerializedPacket& other) = default; |
| |
| SerializedPacket& SerializedPacket::operator=(const SerializedPacket& other) = |
| default; |
| |
| SerializedPacket::SerializedPacket(SerializedPacket&& other) |
| : encrypted_buffer(other.encrypted_buffer), |
| encrypted_length(other.encrypted_length), |
| has_crypto_handshake(other.has_crypto_handshake), |
| num_padding_bytes(other.num_padding_bytes), |
| packet_number(other.packet_number), |
| packet_number_length(other.packet_number_length), |
| encryption_level(other.encryption_level), |
| has_ack(other.has_ack), |
| has_stop_waiting(other.has_stop_waiting), |
| transmission_type(other.transmission_type), |
| original_packet_number(other.original_packet_number), |
| largest_acked(other.largest_acked) { |
| retransmittable_frames.swap(other.retransmittable_frames); |
| } |
| |
| SerializedPacket::~SerializedPacket() {} |
| |
| void ClearSerializedPacket(SerializedPacket* serialized_packet) { |
| if (!serialized_packet->retransmittable_frames.empty()) { |
| DeleteFrames(&serialized_packet->retransmittable_frames); |
| } |
| serialized_packet->encrypted_buffer = nullptr; |
| serialized_packet->encrypted_length = 0; |
| serialized_packet->largest_acked.Clear(); |
| } |
| |
| char* CopyBuffer(const SerializedPacket& packet) { |
| char* dst_buffer = new char[packet.encrypted_length]; |
| memcpy(dst_buffer, packet.encrypted_buffer, packet.encrypted_length); |
| return dst_buffer; |
| } |
| |
| } // namespace quic |