gfe-relnote: In QUIC, do not use framer object in QuicDispatcher. Protected by gfe2_restart_flag_quic_no_framer_object_in_dispatcher.
Also, dispatcher does not parse and validate packet number anymore.
PiperOrigin-RevId: 247959538
Change-Id: Ia0f7901428537f392b05ffd6beb2984bffd00232
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index a9c6c4a..fa6fda7 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -10,6 +10,7 @@
#include "net/third_party/quiche/src/quic/core/chlo_extractor.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
@@ -303,8 +304,14 @@
last_error_(QUIC_NO_ERROR),
new_sessions_allowed_per_event_loop_(0u),
accept_new_connections_(true),
- allow_short_initial_connection_ids_(false) {
- framer_.set_visitor(this);
+ allow_short_initial_connection_ids_(false),
+ last_version_label_(0),
+ expected_connection_id_length_(expected_connection_id_length),
+ should_update_expected_connection_id_length_(false),
+ no_framer_(GetQuicRestartFlag(quic_no_framer_object_in_dispatcher)) {
+ if (!no_framer_) {
+ framer_.set_visitor(this);
+ }
}
QuicDispatcher::~QuicDispatcher() {
@@ -326,21 +333,60 @@
// GetClientAddress must be called after current_peer_address_ is set.
current_client_address_ = GetClientAddress();
current_packet_ = &packet;
- // ProcessPacket will cause the packet to be dispatched in
- // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
- // in OnUnauthenticatedHeader.
- framer_.ProcessPacket(packet);
- // TODO(rjshade): Return a status describing if/why a packet was dropped,
- // and log somehow. Maybe expose as a varz.
- // TODO(wub): Consider invalidate the current_* variables so processing of the
- // next packet does not use them incorrectly.
+ if (!no_framer_) {
+ // ProcessPacket will cause the packet to be dispatched in
+ // OnUnauthenticatedPublicHeader, or sent to the time wait list manager
+ // in OnUnauthenticatedHeader.
+ framer_.ProcessPacket(packet);
+ // TODO(rjshade): Return a status describing if/why a packet was dropped,
+ // and log somehow. Maybe expose as a varz.
+ return;
+ }
+ QUIC_RESTART_FLAG_COUNT(quic_no_framer_object_in_dispatcher);
+ QuicPacketHeader header;
+ uint8_t destination_connection_id_length;
+ string detailed_error;
+ const QuicErrorCode error = QuicFramer::ProcessPacketDispatcher(
+ packet, expected_connection_id_length_, &header.form,
+ &header.version_flag, &last_version_label_,
+ &destination_connection_id_length, &header.destination_connection_id,
+ &detailed_error);
+ if (error != QUIC_NO_ERROR) {
+ // Packet has framing error.
+ SetLastError(error);
+ QUIC_DLOG(ERROR) << detailed_error;
+ return;
+ }
+ header.version = ParseQuicVersionLabel(last_version_label_);
+ if (destination_connection_id_length != expected_connection_id_length_ &&
+ !should_update_expected_connection_id_length_ &&
+ !QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+ header.version.transport_version)) {
+ SetLastError(QUIC_INVALID_PACKET_HEADER);
+ QUIC_DLOG(ERROR) << "Invalid Connection Id Length";
+ return;
+ }
+ if (should_update_expected_connection_id_length_) {
+ expected_connection_id_length_ = destination_connection_id_length;
+ }
+ // TODO(fayang): Instead of passing in QuicPacketHeader, pass format,
+ // version_flag, version and destination_connection_id. Combine
+ // OnUnauthenticatedPublicHeader and OnUnauthenticatedHeader to a single
+ // function when deprecating quic_no_framer_object_in_dispatcher.
+ if (!OnUnauthenticatedPublicHeader(header)) {
+ return;
+ }
+ OnUnauthenticatedHeader(header);
+ // TODO(wub): Consider invalidate the current_* variables so processing of
+ // the next packet does not use them incorrectly.
}
QuicConnectionId QuicDispatcher::MaybeReplaceConnectionId(
QuicConnectionId connection_id,
ParsedQuicVersion version) {
const uint8_t expected_connection_id_length =
- framer_.GetExpectedConnectionIdLength();
+ no_framer_ ? expected_connection_id_length_
+ : framer_.GetExpectedConnectionIdLength();
if (connection_id.length() == expected_connection_id_length) {
return connection_id;
}
@@ -383,16 +429,18 @@
// connection ID, the dispatcher picks a new one of its expected length.
// Therefore we should never receive a connection ID that is smaller
// than 64 bits and smaller than what we expect.
+ const uint8_t expected_connection_id_length =
+ no_framer_ ? expected_connection_id_length_
+ : framer_.GetExpectedConnectionIdLength();
if (connection_id.length() < kQuicMinimumInitialConnectionIdLength &&
- connection_id.length() < framer_.GetExpectedConnectionIdLength() &&
+ connection_id.length() < expected_connection_id_length &&
!allow_short_initial_connection_ids_) {
DCHECK(header.version_flag);
DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion(
header.version.transport_version));
QUIC_DLOG(INFO) << "Packet with short destination connection ID "
<< connection_id << " expected "
- << static_cast<int>(
- framer_.GetExpectedConnectionIdLength());
+ << static_cast<int>(expected_connection_id_length);
ProcessUnauthenticatedHeaderFate(kFateTimeWait, connection_id, header.form,
header.version_flag, header.version);
return false;
@@ -449,12 +497,14 @@
ParsedQuicVersion version = GetSupportedVersions().front();
if (header.version_flag) {
ParsedQuicVersion packet_version = header.version;
- if (framer_.supported_versions() != GetSupportedVersions()) {
+ if (!no_framer_ && framer_.supported_versions() != GetSupportedVersions()) {
// Reset framer's version if version flags change in flight.
framer_.SetSupportedVersions(GetSupportedVersions());
}
- if (!framer_.IsSupportedVersion(packet_version)) {
- if (ShouldCreateSessionForUnknownVersion(framer_.last_version_label())) {
+ if (!IsSupportedVersion(packet_version)) {
+ if (ShouldCreateSessionForUnknownVersion(
+ no_framer_ ? last_version_label_
+ : framer_.last_version_label())) {
return true;
}
if (!crypto_config()->validate_chlo_size() ||
@@ -470,8 +520,10 @@
}
version = packet_version;
}
- // Set the framer's version and continue processing.
- framer_.set_version(version);
+ if (!no_framer_) {
+ // Set the framer's version and continue processing.
+ framer_.set_version(version);
+ }
if (version.HasHeaderProtection()) {
ProcessHeader(header);
@@ -573,6 +625,11 @@
return kFateTimeWait;
}
+ if (no_framer_) {
+ // Let the connection parse and validate packet number.
+ return kFateProcess;
+ }
+
// initial packet number of 0 is always invalid.
if (!framer_.version().HasHeaderProtection()) {
if (!header.packet_number.IsInitialized()) {
@@ -797,7 +854,7 @@
}
// If the version is known and supported by framer, send a connection close.
- if (framer_.IsSupportedVersion(version)) {
+ if (IsSupportedVersion(version)) {
QUIC_DVLOG(1)
<< "Statelessly terminating " << connection_id
<< " based on an ietf-long packet, which has a supported version:"
@@ -852,6 +909,7 @@
bool QuicDispatcher::OnProtocolVersionMismatch(
ParsedQuicVersion /*received_version*/,
PacketHeaderFormat /*form*/) {
+ DCHECK(!no_framer_);
QUIC_BUG_IF(
!time_wait_list_manager_->IsConnectionIdInTimeWait(
current_connection_id_) &&
@@ -1146,7 +1204,7 @@
EnqueuePacketResult rs = buffered_packets_.EnqueuePacket(
current_connection_id_, form != GOOGLE_QUIC_PACKET, *current_packet_,
current_self_address_, current_peer_address_,
- /*is_chlo=*/true, current_alpn_, framer_.version());
+ /*is_chlo=*/true, current_alpn_, version);
if (rs != EnqueuePacketResult::SUCCESS) {
OnBufferPacketFailure(rs, current_connection_id_);
}
@@ -1155,11 +1213,10 @@
QuicConnectionId original_connection_id = current_connection_id_;
current_connection_id_ =
- MaybeReplaceConnectionId(current_connection_id_, framer_.version());
+ MaybeReplaceConnectionId(current_connection_id_, version);
// Creates a new session and process all buffered packets for this connection.
- QuicSession* session =
- CreateQuicSession(current_connection_id_, current_peer_address_,
- current_alpn_, framer_.version());
+ QuicSession* session = CreateQuicSession(
+ current_connection_id_, current_peer_address_, current_alpn_, version);
if (original_connection_id != current_connection_id_) {
session->connection()->AddIncomingConnectionId(original_connection_id);
}
@@ -1338,7 +1395,9 @@
current_self_address_ = current_self_address;
current_packet_ = current_packet.get();
current_connection_id_ = rejector->connection_id();
- framer_.set_version(first_version);
+ if (!no_framer_) {
+ framer_.set_version(first_version);
+ }
// Stop buffering packets on this connection
const auto num_erased =
@@ -1391,7 +1450,7 @@
break;
case StatelessRejector::REJECTED: {
- QUIC_BUG_IF(first_version != framer_.version())
+ QUIC_BUG_IF(!no_framer_ && first_version != framer_.version())
<< "SREJ: Client's version: "
<< QuicVersionToString(first_version.transport_version)
<< " is different from current dispatcher framer's version: "
@@ -1438,7 +1497,22 @@
}
void QuicDispatcher::DisableFlagValidation() {
- framer_.set_validate_flags(false);
+ if (!no_framer_) {
+ framer_.set_validate_flags(false);
+ }
+}
+
+bool QuicDispatcher::IsSupportedVersion(const ParsedQuicVersion version) {
+ if (!no_framer_) {
+ return framer_.IsSupportedVersion(version);
+ }
+ for (const ParsedQuicVersion& supported_version :
+ version_manager_->GetSupportedVersions()) {
+ if (version == supported_version) {
+ return true;
+ }
+ }
+ return false;
}
} // namespace quic
diff --git a/quic/core/quic_dispatcher.h b/quic/core/quic_dispatcher.h
index 0c951ed..6adf5f3 100644
--- a/quic/core/quic_dispatcher.h
+++ b/quic/core/quic_dispatcher.h
@@ -131,6 +131,9 @@
// QuicFramerVisitorInterface implementation. Not expected to be called
// outside of this class.
+ // TODO(fayang): Make QuicDispatcher no longer implement
+ // QuicFramerVisitorInterface when deprecating
+ // quic_no_framer_object_in_dispatcher.
void OnPacket() override;
// Called when the public header has been parsed. Returns false when just the
// public header is enough to dispatch the packet; true if the framer needs to
@@ -361,8 +364,13 @@
// to the received destination connection ID length of all IETF long headers.
void SetShouldUpdateExpectedConnectionIdLength(
bool should_update_expected_connection_id_length) {
- framer_.SetShouldUpdateExpectedConnectionIdLength(
- should_update_expected_connection_id_length);
+ if (!no_framer_) {
+ framer_.SetShouldUpdateExpectedConnectionIdLength(
+ should_update_expected_connection_id_length);
+ return;
+ }
+ should_update_expected_connection_id_length_ =
+ should_update_expected_connection_id_length;
}
// If true, the dispatcher will allow incoming initial packets that have
@@ -435,6 +443,9 @@
QuicConnectionId MaybeReplaceConnectionId(QuicConnectionId connection_id,
ParsedQuicVersion version);
+ // Returns true if |version| is a supported protocol version.
+ bool IsSupportedVersion(const ParsedQuicVersion version);
+
void set_new_sessions_allowed_per_event_loop(
int16_t new_sessions_allowed_per_event_loop) {
new_sessions_allowed_per_event_loop_ = new_sessions_allowed_per_event_loop;
@@ -515,6 +526,28 @@
// If false, the dispatcher follows the IETF spec and rejects packets with
// invalid connection IDs lengths below 64 bits. If true they are allowed.
bool allow_short_initial_connection_ids_;
+
+ // The last QUIC version label received. Used when no_framer_ is true.
+ // TODO(fayang): remove this member variable, instead, add an argument to
+ // OnUnauthenticatedPublicHeader when deprecating
+ // quic_no_framer_object_in_dispatcher.
+ QuicVersionLabel last_version_label_;
+
+ // IETF short headers contain a destination connection ID but do not
+ // encode its length. This variable contains the length we expect to read.
+ // This is also used to signal an error when a long header packet with
+ // different destination connection ID length is received when
+ // should_update_expected_connection_id_length_ is false and packet's version
+ // does not allow variable length connection ID. Used when no_framer_ is true.
+ uint8_t expected_connection_id_length_;
+
+ // If true, change expected_connection_id_length_ to be the received
+ // destination connection ID length of all IETF long headers. Used when
+ // no_framer_ is true.
+ bool should_update_expected_connection_id_length_;
+
+ // Latched value of quic_no_framer_object_in_dispatcher.
+ const bool no_framer_;
};
} // namespace quic
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc
index 9c7cd1e..03b281b 100644
--- a/quic/core/quic_dispatcher_test.cc
+++ b/quic/core/quic_dispatcher_test.cc
@@ -815,7 +815,8 @@
}
TEST_F(QuicDispatcherTest, TooBigSeqNoPacketToTimeWaitListManager) {
- if (CurrentSupportedVersions().front().HasHeaderProtection()) {
+ if (CurrentSupportedVersions().front().HasHeaderProtection() ||
+ GetQuicRestartFlag(quic_no_framer_object_in_dispatcher)) {
// When header protection is in use, we don't put packets in the time wait
// list manager based on packet number.
return;
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 243529d..8d0dec2 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -449,6 +449,11 @@
"each time such a packet is dropped");
}
+PacketHeaderFormat GetIetfPacketHeaderFormat(uint8_t type_byte) {
+ return type_byte & FLAGS_LONG_HEADER ? IETF_QUIC_LONG_HEADER_PACKET
+ : IETF_QUIC_SHORT_HEADER_PACKET;
+}
+
} // namespace
QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
@@ -2511,8 +2516,7 @@
}
header->type_byte = type;
// Determine whether this is a long or short header.
- header->form = type & FLAGS_LONG_HEADER ? IETF_QUIC_LONG_HEADER_PACKET
- : IETF_QUIC_SHORT_HEADER_PACKET;
+ header->form = GetIetfPacketHeaderFormat(type);
if (header->form == IETF_QUIC_LONG_HEADER_PACKET) {
// Version is always present in long headers.
header->version_flag = true;
@@ -2610,13 +2614,19 @@
}
// static
-bool QuicFramer::ValidateIetfConnectionIdLength(
- uint8_t connection_id_lengths_byte,
+bool QuicFramer::ProcessAndValidateIetfConnectionIdLength(
+ QuicDataReader* reader,
ParsedQuicVersion version,
bool should_update_expected_connection_id_length,
uint8_t* expected_connection_id_length,
uint8_t* destination_connection_id_length,
- uint8_t* source_connection_id_length) {
+ uint8_t* source_connection_id_length,
+ std::string* detailed_error) {
+ uint8_t connection_id_lengths_byte;
+ if (!reader->ReadBytes(&connection_id_lengths_byte, 1)) {
+ *detailed_error = "Unable to read ConnectionId length.";
+ return false;
+ }
uint8_t dcil =
(connection_id_lengths_byte & kDestinationConnectionIdLengthMask) >> 4;
if (dcil != 0) {
@@ -2642,6 +2652,7 @@
// OnProtocolVersionMismatch call is moved to before this is run.
QUIC_DVLOG(1) << "dcil: " << static_cast<uint32_t>(dcil)
<< ", scil: " << static_cast<uint32_t>(scil);
+ *detailed_error = "Invalid ConnectionId length.";
return false;
}
*destination_connection_id_length = dcil;
@@ -2664,18 +2675,11 @@
? expected_connection_id_length_
: 0;
if (header->form == IETF_QUIC_LONG_HEADER_PACKET) {
- // Read and validate connection ID length.
- uint8_t connection_id_lengths_byte;
- if (!reader->ReadBytes(&connection_id_lengths_byte, 1)) {
- set_detailed_error("Unable to read ConnectionId length.");
- return false;
- }
- if (!ValidateIetfConnectionIdLength(
- connection_id_lengths_byte, header->version,
+ if (!ProcessAndValidateIetfConnectionIdLength(
+ reader, header->version,
should_update_expected_connection_id_length_,
&expected_connection_id_length_, &destination_connection_id_length,
- &source_connection_id_length)) {
- set_detailed_error("Invalid ConnectionId length.");
+ &source_connection_id_length, &detailed_error_)) {
return false;
}
}
@@ -6054,5 +6058,75 @@
supports_multiple_packet_number_spaces_ = true;
}
+// static
+QuicErrorCode QuicFramer::ProcessPacketDispatcher(
+ const QuicEncryptedPacket& packet,
+ uint8_t expected_connection_id_length,
+ PacketHeaderFormat* format,
+ bool* version_flag,
+ QuicVersionLabel* version_label,
+ uint8_t* destination_connection_id_length,
+ QuicConnectionId* destination_connection_id,
+ std::string* detailed_error) {
+ QuicDataReader reader(packet.data(), packet.length());
+
+ uint8_t first_byte;
+ if (!reader.ReadBytes(&first_byte, 1)) {
+ *detailed_error = "Unable to read first byte.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ if (!QuicUtils::IsIetfPacketHeader(first_byte)) {
+ *format = GOOGLE_QUIC_PACKET;
+ *version_flag = (first_byte & PACKET_PUBLIC_FLAGS_VERSION) != 0;
+ *destination_connection_id_length =
+ first_byte & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
+ if (*destination_connection_id_length == 0 ||
+ !reader.ReadConnectionId(destination_connection_id,
+ *destination_connection_id_length)) {
+ *detailed_error = "Unable to read ConnectionId.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ if (*version_flag && !ProcessVersionLabel(&reader, version_label)) {
+ *detailed_error = "Unable to read protocol version.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ return QUIC_NO_ERROR;
+ }
+
+ *format = GetIetfPacketHeaderFormat(first_byte);
+ QUIC_DVLOG(1) << "Dispatcher: Processing IETF QUIC packet, format: "
+ << *format;
+ *version_flag = *format == IETF_QUIC_LONG_HEADER_PACKET;
+ if (*format == IETF_QUIC_LONG_HEADER_PACKET) {
+ if (!ProcessVersionLabel(&reader, version_label)) {
+ *detailed_error = "Unable to read protocol version.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ // Set should_update_expected_connection_id_length to true to bypass
+ // connection ID lengths validation.
+ uint8_t unused_source_connection_id_length = 0;
+ uint8_t unused_expected_connection_id_length = 0;
+ if (!ProcessAndValidateIetfConnectionIdLength(
+ &reader, ParseQuicVersionLabel(*version_label),
+ /*should_update_expected_connection_id_length=*/true,
+ &unused_expected_connection_id_length,
+ destination_connection_id_length,
+ &unused_source_connection_id_length, detailed_error)) {
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ } else {
+ // For short header packets, expected_connection_id_length is used to
+ // determine the destination_connection_id_length.
+ *destination_connection_id_length = expected_connection_id_length;
+ }
+ // Read destination connection ID.
+ if (!reader.ReadConnectionId(destination_connection_id,
+ *destination_connection_id_length)) {
+ *detailed_error = "Unable to read Destination ConnectionId.";
+ return QUIC_INVALID_PACKET_HEADER;
+ }
+ return QUIC_NO_ERROR;
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h
index e2d7b4d..59e300c 100644
--- a/quic/core/quic_framer.h
+++ b/quic/core/quic_framer.h
@@ -373,6 +373,21 @@
uint64_t retry_token_length,
QuicVariableLengthIntegerLength length_length);
+ // Lightweight parsing of |packet| and populates |format|, |version_flag|,
+ // |version_label|, |destination_connection_id_length|,
+ // |destination_connection_id| and |detailed_error|. Please note,
+ // |expected_connection_id_length| is only used to determine IETF short header
+ // packet's destination connection ID length.
+ static QuicErrorCode ProcessPacketDispatcher(
+ const QuicEncryptedPacket& packet,
+ uint8_t expected_connection_id_length,
+ PacketHeaderFormat* format,
+ bool* version_flag,
+ QuicVersionLabel* version_label,
+ uint8_t* destination_connection_id_length,
+ QuicConnectionId* destination_connection_id,
+ std::string* detailed_error);
+
// Serializes a packet containing |frames| into |buffer|.
// Returns the length of the packet, which must not be longer than
// |packet_length|. Returns 0 if it fails to serialize.
@@ -665,13 +680,14 @@
// Validates and updates |destination_connection_id_length| and
// |source_connection_id_length|.
- static bool ValidateIetfConnectionIdLength(
- uint8_t connection_id_lengths_byte,
+ static bool ProcessAndValidateIetfConnectionIdLength(
+ QuicDataReader* reader,
ParsedQuicVersion version,
bool should_update_expected_connection_id_length,
uint8_t* expected_connection_id_length,
uint8_t* destination_connection_id_length,
- uint8_t* source_connection_id_length);
+ uint8_t* source_connection_id_length,
+ std::string* detailed_error);
bool ProcessIetfHeaderTypeByte(QuicDataReader* reader,
QuicPacketHeader* header);
@@ -921,6 +937,8 @@
// Updated by WritePacketHeader.
QuicConnectionId last_serialized_connection_id_;
// The last QUIC version label received.
+ // TODO(fayang): Remove this when deprecating
+ // quic_no_framer_object_in_dispatcher.
QuicVersionLabel last_version_label_;
// Version of the protocol being used.
ParsedQuicVersion version_;
@@ -975,10 +993,14 @@
// encode its length. This variable contains the length we expect to read.
// This is also used to validate the long header connection ID lengths in
// older versions of QUIC.
+ // TODO(fayang): Remove this when deprecating
+ // quic_no_framer_object_in_dispatcher.
uint8_t expected_connection_id_length_;
// When this is true, QuicFramer will change expected_connection_id_length_
// to the received destination connection ID length of all IETF long headers.
+ // TODO(fayang): Remove this when deprecating
+ // quic_no_framer_object_in_dispatcher.
bool should_update_expected_connection_id_length_;
// Indicates whether this framer supports multiple packet number spaces.
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index 4af5b3a..96f335c 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -913,6 +913,22 @@
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
+
+ PacketHeaderFormat format;
+ bool version_flag;
+ uint8_t destination_connection_id_length;
+ QuicConnectionId destination_connection_id;
+ QuicVersionLabel version_label;
+ std::string detailed_error;
+ EXPECT_EQ(QUIC_NO_ERROR, QuicFramer::ProcessPacketDispatcher(
+ *encrypted, kQuicDefaultConnectionIdLength,
+ &format, &version_flag, &version_label,
+ &destination_connection_id_length,
+ &destination_connection_id, &detailed_error));
+ EXPECT_EQ(GOOGLE_QUIC_PACKET, format);
+ EXPECT_FALSE(version_flag);
+ EXPECT_EQ(kQuicDefaultConnectionIdLength, destination_connection_id_length);
+ EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
}
TEST_P(QuicFramerTest, LongPacketHeader) {
@@ -975,6 +991,22 @@
CheckFramingBoundaries(
framer_.transport_version() > QUIC_VERSION_44 ? packet46 : packet44,
QUIC_INVALID_PACKET_HEADER);
+
+ PacketHeaderFormat format;
+ bool version_flag;
+ uint8_t destination_connection_id_length;
+ QuicConnectionId destination_connection_id;
+ QuicVersionLabel version_label;
+ std::string detailed_error;
+ EXPECT_EQ(QUIC_NO_ERROR, QuicFramer::ProcessPacketDispatcher(
+ *encrypted, kQuicDefaultConnectionIdLength,
+ &format, &version_flag, &version_label,
+ &destination_connection_id_length,
+ &destination_connection_id, &detailed_error));
+ EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
+ EXPECT_TRUE(version_flag);
+ EXPECT_EQ(kQuicDefaultConnectionIdLength, destination_connection_id_length);
+ EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
}
TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
@@ -13251,6 +13283,34 @@
FramerTestConnectionIdNineBytes());
EXPECT_EQ(visitor_.header_.get()->packet_number,
QuicPacketNumber(UINT64_C(0x13374233)));
+
+ PacketHeaderFormat format;
+ bool version_flag;
+ uint8_t destination_connection_id_length;
+ QuicConnectionId destination_connection_id;
+ QuicVersionLabel version_label;
+ std::string detailed_error;
+ EXPECT_EQ(QUIC_NO_ERROR,
+ QuicFramer::ProcessPacketDispatcher(
+ QuicEncryptedPacket(AsChars(long_header_packet),
+ QUIC_ARRAYSIZE(long_header_packet)),
+ kQuicDefaultConnectionIdLength, &format, &version_flag,
+ &version_label, &destination_connection_id_length,
+ &destination_connection_id, &detailed_error));
+ EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
+ EXPECT_TRUE(version_flag);
+ EXPECT_EQ(9, destination_connection_id_length);
+ EXPECT_EQ(FramerTestConnectionIdNineBytes(), destination_connection_id);
+
+ EXPECT_EQ(QUIC_NO_ERROR,
+ QuicFramer::ProcessPacketDispatcher(
+ short_header_encrypted, 9, &format, &version_flag,
+ &version_label, &destination_connection_id_length,
+ &destination_connection_id, &detailed_error));
+ EXPECT_EQ(IETF_QUIC_SHORT_HEADER_PACKET, format);
+ EXPECT_FALSE(version_flag);
+ EXPECT_EQ(9, destination_connection_id_length);
+ EXPECT_EQ(FramerTestConnectionIdNineBytes(), destination_connection_id);
}
TEST_P(QuicFramerTest, MultiplePacketNumberSpaces) {