London interop tuesday 11:21
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc index 0e4bb8c..9f73f74 100644 --- a/quic/core/http/end_to_end_test.cc +++ b/quic/core/http/end_to_end_test.cc
@@ -211,8 +211,9 @@ chlo_multiplier_(0), stream_factory_(nullptr), support_server_push_(false), - override_connection_id_(nullptr), - expected_connection_id_length_(kQuicDefaultConnectionIdLength) { + override_server_connection_id_(nullptr), + override_client_connection_id_(nullptr), + expected_server_connection_id_length_(kQuicDefaultConnectionIdLength) { SetQuicFlag(FLAGS_quic_supports_tls_handshake, true); SetQuicRestartFlag(quic_no_server_conn_ver_negotiation2, true); SetQuicReloadableFlag(quic_no_client_conn_ver_negotiation, true); @@ -259,8 +260,11 @@ if (!pre_shared_key_client_.empty()) { client->client()->SetPreSharedKey(pre_shared_key_client_); } - if (override_connection_id_ != nullptr) { - client->UseConnectionId(*override_connection_id_); + if (override_server_connection_id_ != nullptr) { + client->UseConnectionId(*override_server_connection_id_); + } + if (override_client_connection_id_ != nullptr) { + client->UseClientConnectionId(*override_client_connection_id_); } client->Connect(); return client; @@ -375,7 +379,7 @@ auto* test_server = new QuicTestServer( crypto_test_utils::ProofSourceForTesting(), server_config_, server_supported_versions_, &memory_cache_backend_, - expected_connection_id_length_); + expected_server_connection_id_length_); server_thread_ = QuicMakeUnique<ServerThread>(test_server, server_address_); if (chlo_multiplier_ != 0) { server_thread_->server()->SetChloMultiplier(chlo_multiplier_); @@ -538,8 +542,9 @@ bool support_server_push_; std::string pre_shared_key_client_; std::string pre_shared_key_server_; - QuicConnectionId* override_connection_id_; - uint8_t expected_connection_id_length_; + QuicConnectionId* override_server_connection_id_; + QuicConnectionId* override_client_connection_id_; + uint8_t expected_server_connection_id_length_; }; // Run all end to end tests with all supported versions. @@ -603,8 +608,8 @@ TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) { QuicConnectionId connection_id = QuicUtils::CreateZeroConnectionId( GetParam().negotiated_version.transport_version); - override_connection_id_ = &connection_id; - expected_connection_id_length_ = connection_id.length(); + override_server_connection_id_ = &connection_id; + expected_server_connection_id_length_ = connection_id.length(); ASSERT_TRUE(Initialize()); EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); @@ -628,7 +633,7 @@ } QuicConnectionId connection_id = TestConnectionIdNineBytesLong(UINT64_C(0xBADbadBADbad)); - override_connection_id_ = &connection_id; + override_server_connection_id_ = &connection_id; ASSERT_TRUE(Initialize()); EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); EXPECT_EQ("200", client_->response_headers()->find(":status")->second); @@ -639,6 +644,43 @@ .length()); } +TEST_P(EndToEndTest, ClientConnectionId) { + if (!GetParam().negotiated_version.SupportsClientConnectionIds()) { + ASSERT_TRUE(Initialize()); + return; + } + QuicConnectionId client_connection_id = + TestConnectionId(UINT64_C(0xc1c2c3c4c5c6c7c8)); + override_client_connection_id_ = &client_connection_id; + ASSERT_TRUE(Initialize()); + EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); + EXPECT_EQ("200", client_->response_headers()->find(":status")->second); + EXPECT_EQ(client_connection_id, client_->client() + ->client_session() + ->connection() + ->client_connection_id()); +} + +TEST_P(EndToEndTest, ForcedVersionNegotiationAndClientConnectionId) { + if (!GetParam().negotiated_version.SupportsClientConnectionIds()) { + ASSERT_TRUE(Initialize()); + return; + } + client_supported_versions_.insert(client_supported_versions_.begin(), + QuicVersionReservedForNegotiation()); + QuicConnectionId client_connection_id = + TestConnectionId(UINT64_C(0xc1c2c3c4c5c6c7c8)); + override_client_connection_id_ = &client_connection_id; + ASSERT_TRUE(Initialize()); + ASSERT_TRUE(ServerSendsVersionNegotiation()); + EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); + EXPECT_EQ("200", client_->response_headers()->find(":status")->second); + EXPECT_EQ(client_connection_id, client_->client() + ->client_session() + ->connection() + ->client_connection_id()); +} + TEST_P(EndToEndTest, ForcedVersionNegotiationAndBadConnectionIdLength) { if (!GetQuicRestartFlag( quic_allow_variable_length_connection_id_for_negotiation)) { @@ -654,7 +696,7 @@ QuicVersionReservedForNegotiation()); QuicConnectionId connection_id = TestConnectionIdNineBytesLong(UINT64_C(0xBADbadBADbad)); - override_connection_id_ = &connection_id; + override_server_connection_id_ = &connection_id; ASSERT_TRUE(Initialize()); ASSERT_TRUE(ServerSendsVersionNegotiation()); EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); @@ -676,9 +718,9 @@ // Start client_ which will use a bad connection ID length. QuicConnectionId connection_id = TestConnectionIdNineBytesLong(UINT64_C(0xBADbadBADbad)); - override_connection_id_ = &connection_id; + override_server_connection_id_ = &connection_id; ASSERT_TRUE(Initialize()); - override_connection_id_ = nullptr; + override_server_connection_id_ = nullptr; // Start client2 which will use a good connection ID length. std::unique_ptr<QuicTestClient> client2(CreateQuicClient(nullptr)); @@ -767,8 +809,8 @@ TEST_P(EndToEndTest, MultipleRequestResponseZeroConnectionID) { QuicConnectionId connection_id = QuicUtils::CreateZeroConnectionId( GetParam().negotiated_version.transport_version); - override_connection_id_ = &connection_id; - expected_connection_id_length_ = connection_id.length(); + override_server_connection_id_ = &connection_id; + expected_server_connection_id_length_ = connection_id.length(); ASSERT_TRUE(Initialize()); EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); @@ -2355,7 +2397,7 @@ TestConnectionIdToUInt64(client_connection->connection_id()) + 1); std::unique_ptr<QuicEncryptedPacket> packet( QuicFramer::BuildVersionNegotiationPacket( - incorrect_connection_id, + incorrect_connection_id, EmptyQuicConnectionId(), client_connection->transport_version() > QUIC_VERSION_43, server_supported_versions_)); testing::NiceMock<MockQuicConnectionDebugVisitor> visitor;
diff --git a/quic/core/http/quic_send_control_stream.cc b/quic/core/http/quic_send_control_stream.cc index 40b6111..8ca7bc8 100644 --- a/quic/core/http/quic_send_control_stream.cc +++ b/quic/core/http/quic_send_control_stream.cc
@@ -14,7 +14,9 @@ QuicSendControlStream::QuicSendControlStream(QuicStreamId id, QuicSpdySession* session) : QuicStream(id, session, /*is_static = */ true, WRITE_UNIDIRECTIONAL), - settings_sent_(false) {} + settings_sent_(false) { + DisableConnectionFlowControlForThisStream(); +} void QuicSendControlStream::OnStreamReset(const QuicRstStreamFrame& frame) { // TODO(renjietang) Change the error code to H/3 specific @@ -26,6 +28,10 @@ void QuicSendControlStream::SendSettingsFrame(const SettingsFrame& settings) { DCHECK(!settings_sent_); + // Send the stream type byte on the wire so peer knows about this stream. + char type[] = {0x00}; + WriteOrBufferData(QuicStringPiece(type, 1), false, nullptr); + std::unique_ptr<char[]> buffer; QuicByteCount frame_length = encoder_.SerializeSettingsFrame(settings, &buffer); @@ -33,5 +39,4 @@ /*fin = */ false, nullptr); settings_sent_ = true; } - } // namespace quic
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc index 93d10e1..acc42d8 100644 --- a/quic/core/http/quic_spdy_session.cc +++ b/quic/core/http/quic_spdy_session.cc
@@ -9,6 +9,21 @@ #include <string> #include <utility> +<<<<<<< +||||||| +#include "net/third_party/quic/core/http/quic_headers_stream.h" +#include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/platform/api/quic_bug_tracker.h" +#include "net/third_party/quic/platform/api/quic_fallthrough.h" +#include "net/third_party/quic/platform/api/quic_flag_utils.h" +======= +#include "net/third_party/quic/core/http/quic_headers_stream.h" +#include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/core/quic_versions.h" +#include "net/third_party/quic/platform/api/quic_bug_tracker.h" +#include "net/third_party/quic/platform/api/quic_fallthrough.h" +#include "net/third_party/quic/platform/api/quic_flag_utils.h" +>>>>>>> #include "net/third_party/quiche/src/quic/core/http/quic_headers_stream.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" @@ -361,17 +376,27 @@ qpack_decoder_ = QuicMakeUnique<QpackDecoder>(this, this); } - headers_stream_ = QuicMakeUnique<QuicHeadersStream>((this)); - DCHECK_EQ(QuicUtils::GetHeadersStreamId(connection()->transport_version()), - headers_stream_->id()); - if (!eliminate_static_stream_map()) { - RegisterStaticStream( - QuicUtils::GetHeadersStreamId(connection()->transport_version()), - headers_stream_.get()); - } else { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 7, 17); - unowned_headers_stream_ = headers_stream_.get(); - RegisterStaticStreamNew(std::move(headers_stream_)); + if (!VersionUsesQpack(connection()->transport_version())) { + headers_stream_ = QuicMakeUnique<QuicHeadersStream>((this)); + DCHECK_EQ(QuicUtils::GetHeadersStreamId(connection()->transport_version()), + headers_stream_->id()); + if (!eliminate_static_stream_map()) { + RegisterStaticStream( + QuicUtils::GetHeadersStreamId(connection()->transport_version()), + headers_stream_.get()); + } else { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_eliminate_static_stream_map_3, 7, 17); + unowned_headers_stream_ = headers_stream_.get(); + RegisterStaticStreamNew(std::move(headers_stream_)); + } + } + + if (VersionHasControlStreams(connection()->transport_version()) && + eliminate_static_stream_map()) { + auto send_control = QuicMakeUnique<QuicSendControlStream>( + GetNextOutgoingUnidirectionalStreamId(), this); + send_control_stream_ = send_control.get(); + RegisterStaticStreamNew(std::move(send_control)); } set_max_uncompressed_header_bytes(max_inbound_header_list_size_); @@ -520,12 +545,17 @@ } void QuicSpdySession::SendMaxHeaderListSize(size_t value) { - SpdySettingsIR settings_frame; - settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, value); - - SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame)); - headers_stream()->WriteOrBufferData( - QuicStringPiece(frame.data(), frame.size()), false, nullptr); + if (!VersionHasControlStreams(connection()->transport_version())) { + SpdySettingsIR settings_frame; + settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, value); + SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame)); + headers_stream()->WriteOrBufferData( + QuicStringPiece(frame.data(), frame.size()), false, nullptr); + } else { + SettingsFrame settings; + settings.values[6] = value; + send_control_stream_->SendSettingsFrame(settings); + } } QpackEncoder* QuicSpdySession::qpack_encoder() { @@ -564,7 +594,7 @@ bool QuicSpdySession::UsesPendingStreams() const { DCHECK(VersionHasControlStreams(connection()->transport_version())); - return false; + return true; } size_t QuicSpdySession::WriteHeadersOnHeadersStreamImpl( @@ -743,15 +773,20 @@ if (!reader.ReadVarInt62(&stream_type)) { return; } - CreateIncomingStreamFromPending(pending->id(), stream_type); + CreateIncomingStreamFromPending(pending, stream_type); } -void QuicSpdySession::CreateIncomingStreamFromPending(QuicStreamId id, +void QuicSpdySession::CreateIncomingStreamFromPending(PendingStream* pending, uint64_t stream_type) { switch (stream_type) { - case 0x00: // HTTP/3 control stream. - // TODO(renjietang): Create incoming control stream. + case 0x00: { // HTTP/3 control stream. + auto receive_stream = + QuicMakeUnique<QuicReceiveControlStream>(std::move(*pending)); + receive_control_stream_ = receive_stream.get(); + RegisterStaticStreamNew(std::move(receive_stream)); + pending_streams().erase(pending_streams().find(pending->id())); break; + } case 0x01: // Push Stream. break; case 0x02: // QPACK encoder stream. @@ -761,7 +796,7 @@ // TODO(bnc): Create QPACK decoder stream. break; default: - SendStopSending(0x0D, id); + SendStopSending(0x0D, pending->id()); return; } }
diff --git a/quic/core/http/quic_spdy_session.h b/quic/core/http/quic_spdy_session.h index 1935a2f..43b4cb1 100644 --- a/quic/core/http/quic_spdy_session.h +++ b/quic/core/http/quic_spdy_session.h
@@ -9,6 +9,22 @@ #include <memory> #include <string> +<<<<<<< +||||||| +#include "net/third_party/quic/core/http/quic_header_list.h" +#include "net/third_party/quic/core/http/quic_headers_stream.h" +#include "net/third_party/quic/core/http/quic_spdy_stream.h" +#include "net/third_party/quic/core/qpack/qpack_decoder.h" +#include "net/third_party/quic/core/qpack/qpack_decoder_stream_sender.h" +======= +#include "net/third_party/quic/core/http/quic_header_list.h" +#include "net/third_party/quic/core/http/quic_headers_stream.h" +#include "net/third_party/quic/core/http/quic_receive_control_stream.h" +#include "net/third_party/quic/core/http/quic_send_control_stream.h" +#include "net/third_party/quic/core/http/quic_spdy_stream.h" +#include "net/third_party/quic/core/qpack/qpack_decoder.h" +#include "net/third_party/quic/core/qpack/qpack_decoder_stream_sender.h" +>>>>>>> #include "net/third_party/quiche/src/quic/core/http/quic_header_list.h" #include "net/third_party/quiche/src/quic/core/http/quic_headers_stream.h" #include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h" @@ -243,7 +259,7 @@ // Creates HTTP/3 unidirectional stream of |id| and |type|. Sends // STOP_SENDING frame if |type| is not supported. - void CreateIncomingStreamFromPending(QuicStreamId id, uint64_t type); + void CreateIncomingStreamFromPending(PendingStream* pending, uint64_t type); private: friend class test::QuicSpdySessionPeer; @@ -285,6 +301,10 @@ // is deprecated. QuicHeadersStream* unowned_headers_stream_; + // HTTP/3 control streams. + QuicSendControlStream* send_control_stream_; + QuicReceiveControlStream* receive_control_stream_; + // The maximum size of a header block that will be accepted from the peer, // defined per spec as key + value + overhead per field (uncompressed). size_t max_inbound_header_list_size_;
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc index 1a33fd1..57c7e95 100644 --- a/quic/core/http/quic_spdy_session_test.cc +++ b/quic/core/http/quic_spdy_session_test.cc
@@ -380,6 +380,13 @@ return QuicUtils::StreamIdDelta(connection_->transport_version()); } + std::string EncodeSettings(const SettingsFrame& settings) { + HttpEncoder encoder; + std::unique_ptr<char[]> buffer; + auto header_length = encoder.SerializeSettingsFrame(settings, &buffer); + return std::string(buffer.get(), header_length); + } + QuicStreamId StreamCountToId(QuicStreamCount stream_count, Perspective perspective, bool bidirectional) { @@ -420,7 +427,7 @@ if (!VersionHasControlStreams(transport_version())) { return; } - EXPECT_FALSE(session_.UsesPendingStreams()); + EXPECT_TRUE(session_.UsesPendingStreams()); } TEST_P(QuicSpdySessionTestServer, PeerAddress) { @@ -705,7 +712,7 @@ MockPacketWriter* writer = static_cast<MockPacketWriter*>( QuicConnectionPeer::GetWriter(session_.connection())); EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)) - .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0))); + .WillRepeatedly(Return(WriteResult(WRITE_STATUS_OK, 0))); session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); // Drive congestion control manually. @@ -1622,7 +1629,7 @@ if (!VersionHasControlStreams(transport_version())) { return; } - EXPECT_FALSE(session_.UsesPendingStreams()); + EXPECT_TRUE(session_.UsesPendingStreams()); } TEST_P(QuicSpdySessionTestClient, AvailableStreamsClient) { @@ -1958,6 +1965,32 @@ session_.ProcessPendingStream(&pending); } +TEST_P(QuicSpdySessionTestServer, ReceiveControlStream) { + if (!VersionHasControlStreams(transport_version()) || + !GetQuicReloadableFlag(quic_eliminate_static_stream_map_2)) { + return; + } + // Use a arbitrary stream id. + QuicStreamId stream_id = + GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3); + char type[] = {0x00}; + + QuicStreamFrame data1(stream_id, false, 0, QuicStringPiece(type, 1)); + session_.OnStreamFrame(data1); + EXPECT_EQ(stream_id, + QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id()); + + SettingsFrame settings; + settings.values[3] = 2; + settings.values[6] = 5; + std::string data = EncodeSettings(settings); + QuicStreamFrame frame(stream_id, false, 1, QuicStringPiece(data)); + + EXPECT_NE(5u, session_.max_inbound_header_list_size()); + session_.OnStreamFrame(frame); + EXPECT_EQ(5u, session_.max_inbound_header_list_size()); +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index a8672f5..558271a 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -376,8 +376,7 @@ if (use_uber_received_packet_manager_) { QUIC_RELOADABLE_FLAG_COUNT(quic_use_uber_received_packet_manager); } - QUIC_DLOG(INFO) << ENDPOINT - << "Created connection with server connection_id: " + QUIC_DLOG(INFO) << ENDPOINT << "Created connection with server connection ID " << server_connection_id << " and version: " << ParsedQuicVersionToString(version()); @@ -822,31 +821,55 @@ QuicConnectionId server_connection_id = GetServerConnectionIdAsRecipient(header, perspective_); - if (server_connection_id == server_connection_id_ || - HasIncomingConnectionId(server_connection_id)) { - return true; - } + if (server_connection_id != server_connection_id_ && + !HasIncomingConnectionId(server_connection_id)) { + if (PacketCanReplaceConnectionId(header, perspective_)) { + QUIC_DLOG(INFO) << ENDPOINT << "Accepting packet with new connection ID " + << server_connection_id << " instead of " + << server_connection_id_; + return true; + } - if (PacketCanReplaceConnectionId(header, perspective_)) { - QUIC_DLOG(INFO) << ENDPOINT << "Accepting packet with new connection ID " + ++stats_.packets_dropped; + QUIC_DLOG(INFO) << ENDPOINT + << "Ignoring packet from unexpected server connection ID " << server_connection_id << " instead of " << server_connection_id_; + QUIC_BUG << ENDPOINT + << "Ignoring packet from unexpected server connection ID " + << server_connection_id << " instead of " << server_connection_id_ + << " header " << header; + if (debug_visitor_ != nullptr) { + debug_visitor_->OnIncorrectConnectionId(server_connection_id); + } + // If this is a server, the dispatcher routes each packet to the + // QuicConnection responsible for the packet's connection ID. So if control + // arrives here and this is a server, the dispatcher must be malfunctioning. + DCHECK_NE(Perspective::IS_SERVER, perspective_); + return false; + } + + if (!version().SupportsClientConnectionIds()) { return true; } - ++stats_.packets_dropped; - QUIC_DLOG(INFO) << ENDPOINT - << "Ignoring packet from unexpected ConnectionId: " - << server_connection_id << " instead of " - << server_connection_id_; - if (debug_visitor_ != nullptr) { - debug_visitor_->OnIncorrectConnectionId(server_connection_id); + QuicConnectionId client_connection_id = + GetClientConnectionIdAsRecipient(header, perspective_); + + if (client_connection_id != client_connection_id_) { + ++stats_.packets_dropped; + QUIC_DLOG(INFO) << ENDPOINT + << "Ignoring packet from unexpected client connection ID " + << client_connection_id << " instead of " + << client_connection_id_; + QUIC_BUG << ENDPOINT + << "Ignoring packet from unexpected client connection ID " + << client_connection_id << " instead of " << client_connection_id_ + << " header " << header; + return false; } - // If this is a server, the dispatcher routes each packet to the - // QuicConnection responsible for the packet's connection ID. So if control - // arrives here and this is a server, the dispatcher must be malfunctioning. - DCHECK_NE(Perspective::IS_SERVER, perspective_); - return false; + + return true; } bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) { @@ -2396,8 +2419,17 @@ } ResetAckStates(); - QUIC_DVLOG(1) << ENDPOINT << "Bundle an ACK opportunistically"; - frames.push_back(GetUpdatedAckFrame()); + QuicFrame updated_ack_frame = GetUpdatedAckFrame(); + if (!updated_ack_frame.ack_frame->packets.Empty()) { + QUIC_DVLOG(1) << ENDPOINT << "Bundle an ACK opportunistically"; + frames.push_back(updated_ack_frame); + } else { + QUIC_BUG << "Trying to opportunistically bundle ACK at " + << QuicUtils::EncryptionLevelToString(encryption_level_) << " " + << (has_pending_ack ? "" : "!") + << "has_pending_ack, stop_waiting_count_ " << stop_waiting_count_; + } + if (!no_stop_waiting_frames_) { QuicStopWaitingFrame stop_waiting; PopulateStopWaitingFrame(&stop_waiting); @@ -4022,7 +4054,9 @@ } if (sent_packet_manager_.handshake_confirmed()) { // A forward secure packet has been received. - QUIC_BUG_IF(encryption_level_ != ENCRYPTION_FORWARD_SECURE); + QUIC_BUG_IF(encryption_level_ != ENCRYPTION_FORWARD_SECURE) + << "Unexpected connection close encryption level " + << QuicUtils::EncryptionLevelToString(encryption_level_); return ENCRYPTION_FORWARD_SECURE; } if (framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_ZERO_RTT)) { @@ -4223,5 +4257,22 @@ return received_packet_manager_.ack_frame(); } +void QuicConnection::set_client_connection_id( + QuicConnectionId client_connection_id) { + if (!version().SupportsClientConnectionIds()) { + QUIC_BUG_IF(!client_connection_id.IsEmpty()) + << ENDPOINT << "Attempted to use client connection ID " + << client_connection_id << " with unsupported version " << version(); + return; + } + client_connection_id_ = client_connection_id; + QUIC_DLOG(INFO) << ENDPOINT << "setting client connection ID to " + << client_connection_id_ + << " for connection with server connection ID " + << server_connection_id_; + packet_generator_.SetClientConnectionId(client_connection_id_); + framer_.SetExpectedClientConnectionIdLength(client_connection_id_.length()); +} + #undef ENDPOINT // undef for jumbo builds } // namespace quic
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h index b274266..00902a9 100644 --- a/quic/core/quic_connection.h +++ b/quic/core/quic_connection.h
@@ -583,6 +583,10 @@ return effective_peer_address_; } QuicConnectionId connection_id() const { return server_connection_id_; } + QuicConnectionId client_connection_id() const { + return client_connection_id_; + } + void set_client_connection_id(QuicConnectionId client_connection_id); const QuicClock* clock() const { return clock_; } QuicRandom* random_generator() const { return random_generator_; } QuicByteCount max_packet_length() const; @@ -1169,6 +1173,7 @@ QuicRandom* random_generator_; QuicConnectionId server_connection_id_; + QuicConnectionId client_connection_id_; // Address on the last successfully processed packet received from the // direct peer. QuicSocketAddress self_address_;
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc index 0d09430..e4886b6 100644 --- a/quic/core/quic_connection_test.cc +++ b/quic/core/quic_connection_test.cc
@@ -6877,7 +6877,8 @@ // Send a version negotiation packet. std::unique_ptr<QuicEncryptedPacket> encrypted( peer_framer_.BuildVersionNegotiationPacket( - connection_id_, connection_.transport_version() > QUIC_VERSION_43, + connection_id_, EmptyQuicConnectionId(), + connection_.transport_version() > QUIC_VERSION_43, AllSupportedVersions())); std::unique_ptr<QuicReceivedPacket> received( ConstructReceivedPacket(*encrypted, QuicTime::Zero())); @@ -6932,7 +6933,8 @@ ConnectionCloseSource::FROM_SELF)); std::unique_ptr<QuicEncryptedPacket> encrypted( framer_.BuildVersionNegotiationPacket( - connection_id_, connection_.transport_version() > QUIC_VERSION_43, + connection_id_, EmptyQuicConnectionId(), + connection_.transport_version() > QUIC_VERSION_43, AllSupportedVersions())); std::unique_ptr<QuicReceivedPacket> received( ConstructReceivedPacket(*encrypted, QuicTime::Zero()));
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc index 049a63f..fa995da 100644 --- a/quic/core/quic_dispatcher.cc +++ b/quic/core/quic_dispatcher.cc
@@ -19,9 +19,20 @@ #include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" +<<<<<<< #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h" #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" +||||||| +#include "net/third_party/quic/platform/api/quic_ptr_util.h" +#include "net/third_party/quic/platform/api/quic_stack_trace.h" +#include "net/third_party/quic/platform/api/quic_string_piece.h" +======= +#include "net/third_party/quic/platform/api/quic_ptr_util.h" +#include "net/third_party/quic/platform/api/quic_stack_trace.h" +#include "net/third_party/quic/platform/api/quic_string_piece.h" +#include "net/third_party/quic/platform/api/quic_text_utils.h" +>>>>>>> namespace quic { @@ -287,7 +298,7 @@ std::unique_ptr<QuicConnectionHelperInterface> helper, std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, std::unique_ptr<QuicAlarmFactory> alarm_factory, - uint8_t expected_connection_id_length) + uint8_t expected_server_connection_id_length) : config_(config), crypto_config_(crypto_config), compressed_certs_cache_( @@ -303,14 +314,15 @@ framer_(GetSupportedVersions(), /*unused*/ QuicTime::Zero(), Perspective::IS_SERVER, - expected_connection_id_length), + expected_server_connection_id_length), last_error_(QUIC_NO_ERROR), new_sessions_allowed_per_event_loop_(0u), accept_new_connections_(true), allow_short_initial_server_connection_ids_(false), last_version_label_(0), - expected_connection_id_length_(expected_connection_id_length), - should_update_expected_connection_id_length_(false), + expected_server_connection_id_length_( + expected_server_connection_id_length), + should_update_expected_server_connection_id_length_(false), no_framer_(GetQuicRestartFlag(quic_no_framer_object_in_dispatcher)) { if (!no_framer_) { framer_.set_visitor(this); @@ -331,6 +343,10 @@ void QuicDispatcher::ProcessPacket(const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address, const QuicReceivedPacket& packet) { + QUIC_DVLOG(2) << "Dispatcher received encrypted " << packet.length() + << " bytes:" << std::endl + << QuicTextUtils::HexDump( + QuicStringPiece(packet.data(), packet.length())); current_self_address_ = self_address; current_peer_address_ = peer_address; // GetClientAddress must be called after current_peer_address_ is set. @@ -347,12 +363,11 @@ } QUIC_RESTART_FLAG_COUNT(quic_no_framer_object_in_dispatcher); QuicPacketHeader header; - uint8_t destination_connection_id_length; std::string detailed_error; const QuicErrorCode error = QuicFramer::ProcessPacketDispatcher( - packet, expected_connection_id_length_, &header.form, + packet, expected_server_connection_id_length_, &header.form, &header.version_flag, &last_version_label_, - &destination_connection_id_length, &header.destination_connection_id, + &header.destination_connection_id, &header.source_connection_id, &detailed_error); if (error != QUIC_NO_ERROR) { // Packet has framing error. @@ -361,16 +376,18 @@ return; } header.version = ParseQuicVersionLabel(last_version_label_); - if (destination_connection_id_length != expected_connection_id_length_ && - !should_update_expected_connection_id_length_ && + if (header.destination_connection_id.length() != + expected_server_connection_id_length_ && + !should_update_expected_server_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; + if (should_update_expected_server_connection_id_length_) { + expected_server_connection_id_length_ = + header.destination_connection_id.length(); } // TODO(fayang): Instead of passing in QuicPacketHeader, pass format, // version_flag, version and destination_connection_id. Combine @@ -387,10 +404,10 @@ QuicConnectionId QuicDispatcher::MaybeReplaceServerConnectionId( QuicConnectionId server_connection_id, ParsedQuicVersion version) { - const uint8_t expected_connection_id_length = - no_framer_ ? expected_connection_id_length_ - : framer_.GetExpectedConnectionIdLength(); - if (server_connection_id.length() == expected_connection_id_length) { + const uint8_t expected_server_connection_id_length = + no_framer_ ? expected_server_connection_id_length_ + : framer_.GetExpectedServerConnectionIdLength(); + if (server_connection_id.length() == expected_server_connection_id_length) { return server_connection_id; } DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion( @@ -402,7 +419,7 @@ QuicConnectionId new_connection_id = session_helper_->GenerateConnectionIdForReject(version.transport_version, server_connection_id); - DCHECK_EQ(expected_connection_id_length, new_connection_id.length()); + DCHECK_EQ(expected_server_connection_id_length, new_connection_id.length()); connection_id_map_.insert( std::make_pair(server_connection_id, new_connection_id)); QUIC_DLOG(INFO) << "Replacing incoming connection ID " << server_connection_id @@ -413,6 +430,7 @@ bool QuicDispatcher::OnUnauthenticatedPublicHeader( const QuicPacketHeader& header) { current_server_connection_id_ = header.destination_connection_id; + current_client_connection_id_ = header.source_connection_id; // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC. // Given that we can't even send a reply rejecting the packet, just drop the @@ -427,24 +445,25 @@ return false; } QuicConnectionId server_connection_id = header.destination_connection_id; + QuicConnectionId client_connection_id = header.source_connection_id; // The IETF spec requires the client to generate an initial server // connection ID that is at least 64 bits long. After that initial // 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(); + const uint8_t expected_server_connection_id_length = + no_framer_ ? expected_server_connection_id_length_ + : framer_.GetExpectedServerConnectionIdLength(); if (server_connection_id.length() < kQuicMinimumInitialConnectionIdLength && - server_connection_id.length() < expected_connection_id_length && + server_connection_id.length() < expected_server_connection_id_length && !allow_short_initial_server_connection_ids_) { DCHECK(header.version_flag); DCHECK(QuicUtils::VariableLengthConnectionIdAllowedForVersion( header.version.transport_version)); QUIC_DLOG(INFO) << "Packet with short destination connection ID " << server_connection_id << " expected " - << static_cast<int>(expected_connection_id_length); + << static_cast<int>(expected_server_connection_id_length); ProcessUnauthenticatedHeaderFate(kFateTimeWait, server_connection_id, header.form, header.version_flag, header.version); @@ -517,9 +536,10 @@ // Since the version is not supported, send a version negotiation // packet and stop processing the current packet. time_wait_list_manager()->SendVersionNegotiationPacket( - server_connection_id, header.form != GOOGLE_QUIC_PACKET, - GetSupportedVersions(), current_self_address_, - current_peer_address_, GetPerPacketContext()); + server_connection_id, client_connection_id, + header.form != GOOGLE_QUIC_PACKET, GetSupportedVersions(), + current_self_address_, current_peer_address_, + GetPerPacketContext()); } return false; } @@ -891,7 +911,8 @@ // with an empty version list, which can be understood by the client. std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets; termination_packets.push_back(QuicFramer::BuildVersionNegotiationPacket( - server_connection_id, /*ietf_quic=*/format != GOOGLE_QUIC_PACKET, + server_connection_id, EmptyQuicConnectionId(), + /*ietf_quic=*/format != GOOGLE_QUIC_PACKET, ParsedQuicVersionVector{UnsupportedQuicVersion()})); if (format == GOOGLE_QUIC_PACKET) { QUIC_RELOADABLE_FLAG_COUNT_N(quic_terminate_gquic_connection_as_ietf, 2, 2); @@ -1132,6 +1153,24 @@ if (original_connection_id != server_connection_id) { session->connection()->AddIncomingConnectionId(original_connection_id); } + if (packet_list.version.SupportsClientConnectionIds()) { + // Parse out the first packet's source connection ID and set it as the + // connection's client connection ID. + QuicPacketHeader header; + QuicVersionLabel version_label; + std::string detailed_error; + const QuicErrorCode error = QuicFramer::ProcessPacketDispatcher( + *packets.front().packet, expected_server_connection_id_length_, + &header.form, &header.version_flag, &version_label, + &header.destination_connection_id, &header.source_connection_id, + &detailed_error); + if (error == QUIC_NO_ERROR) { + session->connection()->set_client_connection_id( + header.source_connection_id); + } else { + QUIC_DLOG(ERROR) << detailed_error; + } + } QUIC_DLOG(INFO) << "Created new session for " << server_connection_id; session_map_.insert( std::make_pair(server_connection_id, QuicWrapUnique(session))); @@ -1236,6 +1275,10 @@ if (original_connection_id != current_server_connection_id_) { session->connection()->AddIncomingConnectionId(original_connection_id); } + if (version.SupportsClientConnectionIds()) { + session->connection()->set_client_connection_id( + current_client_connection_id_); + } QUIC_DLOG(INFO) << "Created new session for " << current_server_connection_id_; session_map_.insert(
diff --git a/quic/core/quic_dispatcher.h b/quic/core/quic_dispatcher.h index 1798a0d..5e755dd 100644 --- a/quic/core/quic_dispatcher.h +++ b/quic/core/quic_dispatcher.h
@@ -49,7 +49,7 @@ std::unique_ptr<QuicConnectionHelperInterface> helper, std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, std::unique_ptr<QuicAlarmFactory> alarm_factory, - uint8_t expected_connection_id_length); + uint8_t expected_server_connection_id_length); QuicDispatcher(const QuicDispatcher&) = delete; QuicDispatcher& operator=(const QuicDispatcher&) = delete; @@ -364,14 +364,14 @@ // If true, our framer will change its expected connection ID length // to the received destination connection ID length of all IETF long headers. void SetShouldUpdateExpectedConnectionIdLength( - bool should_update_expected_connection_id_length) { + bool should_update_expected_server_connection_id_length) { if (!no_framer_) { framer_.SetShouldUpdateExpectedConnectionIdLength( - should_update_expected_connection_id_length); + should_update_expected_server_connection_id_length); return; } - should_update_expected_connection_id_length_ = - should_update_expected_connection_id_length; + should_update_expected_server_connection_id_length_ = + should_update_expected_server_connection_id_length; } // If true, the dispatcher will allow incoming initial packets that have @@ -509,6 +509,7 @@ // If |current_packet_| is a CHLO packet, the extracted alpn. std::string current_alpn_; QuicConnectionId current_server_connection_id_; + QuicConnectionId current_client_connection_id_; // Used to get the supported versions based on flag. Does not own. QuicVersionManager* version_manager_; @@ -541,14 +542,15 @@ // 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_; + // should_update_expected_server_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_server_connection_id_length_; - // If true, change expected_connection_id_length_ to be the received + // If true, change expected_server_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_; + bool should_update_expected_server_connection_id_length_; // Latched value of quic_no_framer_object_in_dispatcher. const bool no_framer_;
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc index de06c52..668541b 100644 --- a/quic/core/quic_dispatcher_test.cc +++ b/quic/core/quic_dispatcher_test.cc
@@ -493,7 +493,7 @@ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0); EXPECT_CALL(*time_wait_list_manager_, - SendVersionNegotiationPacket(_, _, _, _, _, _)) + SendVersionNegotiationPacket(_, _, _, _, _, _, _)) .Times(1); QuicTransportVersion version = static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1); @@ -512,7 +512,7 @@ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0); EXPECT_CALL(*time_wait_list_manager_, - SendVersionNegotiationPacket(_, _, _, _, _, _)) + SendVersionNegotiationPacket(_, _, _, _, _, _, _)) .Times(0); QuicTransportVersion version = static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1); @@ -538,7 +538,7 @@ EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0); EXPECT_CALL(*time_wait_list_manager_, - SendVersionNegotiationPacket(_, _, _, _, _, _)) + SendVersionNegotiationPacket(_, _, _, _, _, _, _)) .Times(1); QuicTransportVersion version = static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1);
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index eff8f49..c35c076 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -459,10 +459,11 @@ QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions, QuicTime creation_time, Perspective perspective, - uint8_t expected_connection_id_length) + uint8_t expected_server_connection_id_length) : visitor_(nullptr), error_(QUIC_NO_ERROR), last_serialized_server_connection_id_(EmptyQuicConnectionId()), + last_serialized_client_connection_id_(EmptyQuicConnectionId()), last_version_label_(0), version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), supported_versions_(supported_versions), @@ -478,8 +479,10 @@ data_producer_(nullptr), infer_packet_header_type_from_version_(perspective == Perspective::IS_CLIENT), - expected_connection_id_length_(expected_connection_id_length), - should_update_expected_connection_id_length_(false), + expected_server_connection_id_length_( + expected_server_connection_id_length), + expected_client_connection_id_length_(0), + should_update_expected_server_connection_id_length_(false), supports_multiple_packet_number_spaces_(false), last_written_packet_number_length_(0) { DCHECK(!supported_versions.empty()); @@ -1387,14 +1390,17 @@ // static std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket( - QuicConnectionId connection_id, + QuicConnectionId server_connection_id, + QuicConnectionId client_connection_id, bool ietf_quic, const ParsedQuicVersionVector& versions) { if (ietf_quic) { - return BuildIetfVersionNegotiationPacket(connection_id, versions); + return BuildIetfVersionNegotiationPacket(server_connection_id, + client_connection_id, versions); } + DCHECK(client_connection_id.IsEmpty()); DCHECK(!versions.empty()); - size_t len = kPublicFlagsSize + connection_id.length() + + size_t len = kPublicFlagsSize + server_connection_id.length() + versions.size() * kQuicVersionSize; std::unique_ptr<char[]> buffer(new char[len]); // Endianness is not a concern here, version negotiation packet does not have @@ -1409,7 +1415,7 @@ return nullptr; } - if (!writer.WriteConnectionId(connection_id)) { + if (!writer.WriteConnectionId(server_connection_id)) { return nullptr; } @@ -1427,13 +1433,14 @@ // static std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildIetfVersionNegotiationPacket( - QuicConnectionId source_connection_id, + QuicConnectionId server_connection_id, + QuicConnectionId client_connection_id, const ParsedQuicVersionVector& versions) { QUIC_DVLOG(1) << "Building IETF version negotiation packet: " << ParsedQuicVersionVectorToString(versions); DCHECK(!versions.empty()); size_t len = kPacketHeaderTypeSize + kConnectionIdLengthSize + - source_connection_id.length() + + client_connection_id.length() + server_connection_id.length() + (versions.size() + 1) * kQuicVersionSize; std::unique_ptr<char[]> buffer(new char[len]); QuicDataWriter writer(len, buffer.get()); @@ -1452,8 +1459,8 @@ return nullptr; } - if (!AppendIetfConnectionIds(true, EmptyQuicConnectionId(), - source_connection_id, &writer)) { + if (!AppendIetfConnectionIds(true, client_connection_id, server_connection_id, + &writer)) { return nullptr; } @@ -2195,6 +2202,9 @@ } last_serialized_server_connection_id_ = server_connection_id; + if (version_.SupportsClientConnectionIds()) { + last_serialized_client_connection_id_ = GetClientConnectionIdAsSender(header, perspective_); + } if (QuicVersionHasLongHeaderLengths(transport_version()) && header.version_flag) { @@ -2521,11 +2531,15 @@ // connection ID, and those received by server must include 8-byte // destination connection ID. header->destination_connection_id_included = - perspective_ == Perspective::IS_CLIENT ? CONNECTION_ID_ABSENT - : CONNECTION_ID_PRESENT; + (perspective_ == Perspective::IS_SERVER || + version_.SupportsClientConnectionIds()) + ? CONNECTION_ID_PRESENT + : CONNECTION_ID_ABSENT; header->source_connection_id_included = - perspective_ == Perspective::IS_CLIENT ? CONNECTION_ID_PRESENT - : CONNECTION_ID_ABSENT; + (perspective_ == Perspective::IS_CLIENT || + version_.SupportsClientConnectionIds()) + ? CONNECTION_ID_PRESENT + : CONNECTION_ID_ABSENT; // Read version tag. QuicVersionLabel version_label; if (!ProcessVersionLabel(reader, &version_label)) { @@ -2580,8 +2594,10 @@ // Connection ID length depends on the perspective. Client does not expect // destination connection ID, and server expects destination connection ID. header->destination_connection_id_included = - perspective_ == Perspective::IS_CLIENT ? CONNECTION_ID_ABSENT - : CONNECTION_ID_PRESENT; + (perspective_ == Perspective::IS_SERVER || + version_.SupportsClientConnectionIds()) + ? CONNECTION_ID_PRESENT + : CONNECTION_ID_ABSENT; header->source_connection_id_included = CONNECTION_ID_ABSENT; if (infer_packet_header_type_from_version_ && transport_version() > QUIC_VERSION_44 && !(type & FLAGS_FIXED_BIT)) { @@ -2614,11 +2630,21 @@ bool QuicFramer::ProcessAndValidateIetfConnectionIdLength( QuicDataReader* reader, ParsedQuicVersion version, - bool should_update_expected_connection_id_length, - uint8_t* expected_connection_id_length, + Perspective perspective, + bool should_update_expected_server_connection_id_length, + uint8_t* expected_server_connection_id_length, uint8_t* destination_connection_id_length, uint8_t* source_connection_id_length, std::string* detailed_error) { + QUIC_LOG(ERROR) << "ds33 should_update_expected_server_connection_id_length " + << (should_update_expected_server_connection_id_length ? "Y" + : "N") + << " expected_server_connection_id_length " + << (int)*expected_server_connection_id_length + << " destination_connection_id_length " + << (int)*destination_connection_id_length + << " source_connection_id_length " + << (int)*source_connection_id_length; uint8_t connection_id_lengths_byte; if (!reader->ReadBytes(&connection_id_lengths_byte, 1)) { *detailed_error = "Unable to read ConnectionId length."; @@ -2629,18 +2655,21 @@ if (dcil != 0) { dcil += kConnectionIdLengthAdjustment; } - if (should_update_expected_connection_id_length && - *expected_connection_id_length != dcil) { - QUIC_DVLOG(1) << "Updating expected_connection_id_length: " - << static_cast<int>(*expected_connection_id_length) << " -> " - << static_cast<int>(dcil); - *expected_connection_id_length = dcil; - } uint8_t scil = connection_id_lengths_byte & kSourceConnectionIdLengthMask; if (scil != 0) { scil += kConnectionIdLengthAdjustment; } - if (!should_update_expected_connection_id_length && + if (should_update_expected_server_connection_id_length) { + uint8_t server_connection_id_length = + perspective == Perspective::IS_SERVER ? dcil : scil; + if (*expected_server_connection_id_length != server_connection_id_length) { + QUIC_DVLOG(1) << "Updating expected_server_connection_id_length: " + << static_cast<int>(*expected_server_connection_id_length) + << " -> " << static_cast<int>(server_connection_id_length); + *expected_server_connection_id_length = server_connection_id_length; + } + } + if (!should_update_expected_server_connection_id_length && (dcil != *destination_connection_id_length || scil != *source_connection_id_length) && !QuicUtils::VariableLengthConnectionIdAllowedForVersion( @@ -2665,18 +2694,35 @@ uint8_t destination_connection_id_length = header->destination_connection_id_included == CONNECTION_ID_PRESENT - ? expected_connection_id_length_ + ? (perspective_ == Perspective::IS_SERVER + ? expected_server_connection_id_length_ + : expected_client_connection_id_length_) : 0; uint8_t source_connection_id_length = header->source_connection_id_included == CONNECTION_ID_PRESENT - ? expected_connection_id_length_ + ? (perspective_ == Perspective::IS_CLIENT + ? expected_server_connection_id_length_ + : expected_client_connection_id_length_) : 0; + QUIC_LOG(ERROR) << ENDPOINT + << "ds33 should_update_expected_server_connection_id_length_ " + << (should_update_expected_server_connection_id_length_ ? "Y" + : "N") + << " expected_server_connection_id_length_ " + << (int)expected_server_connection_id_length_ + << " expected_client_connection_id_length_ " + << (int)expected_client_connection_id_length_ + << " destination_connection_id_length " + << (int)destination_connection_id_length + << " source_connection_id_length " + << (int)source_connection_id_length << " header " << *header; if (header->form == IETF_QUIC_LONG_HEADER_PACKET) { if (!ProcessAndValidateIetfConnectionIdLength( - reader, header->version, - should_update_expected_connection_id_length_, - &expected_connection_id_length_, &destination_connection_id_length, - &source_connection_id_length, &detailed_error_)) { + reader, header->version, perspective_, + should_update_expected_server_connection_id_length_, + &expected_server_connection_id_length_, + &destination_connection_id_length, &source_connection_id_length, + &detailed_error_)) { return false; } } @@ -2715,7 +2761,11 @@ QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 5, 5); if (header->source_connection_id_included == CONNECTION_ID_ABSENT) { DCHECK_EQ(EmptyQuicConnectionId(), header->source_connection_id); - header->source_connection_id = last_serialized_server_connection_id_; + if (perspective_ == Perspective::IS_CLIENT) { + header->source_connection_id = last_serialized_server_connection_id_; + } else { + header->source_connection_id = last_serialized_client_connection_id_; + } } } @@ -6042,28 +6092,30 @@ // static QuicErrorCode QuicFramer::ProcessPacketDispatcher( const QuicEncryptedPacket& packet, - uint8_t expected_connection_id_length, + uint8_t expected_server_connection_id_length, PacketHeaderFormat* format, bool* version_flag, QuicVersionLabel* version_label, - uint8_t* destination_connection_id_length, QuicConnectionId* destination_connection_id, + QuicConnectionId* source_connection_id, std::string* detailed_error) { QuicDataReader reader(packet.data(), packet.length()); + *source_connection_id = EmptyQuicConnectionId(); uint8_t first_byte; if (!reader.ReadBytes(&first_byte, 1)) { *detailed_error = "Unable to read first byte."; return QUIC_INVALID_PACKET_HEADER; } + uint8_t destination_connection_id_length = 0, source_connection_id_length = 0; if (!QuicUtils::IsIetfPacketHeader(first_byte)) { *format = GOOGLE_QUIC_PACKET; *version_flag = (first_byte & PACKET_PUBLIC_FLAGS_VERSION) != 0; - *destination_connection_id_length = + destination_connection_id_length = first_byte & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID; - if (*destination_connection_id_length == 0 || + if (destination_connection_id_length == 0 || !reader.ReadConnectionId(destination_connection_id, - *destination_connection_id_length)) { + destination_connection_id_length)) { *detailed_error = "Unable to read ConnectionId."; return QUIC_INVALID_PACKET_HEADER; } @@ -6083,27 +6135,33 @@ *detailed_error = "Unable to read protocol version."; return QUIC_INVALID_PACKET_HEADER; } - // Set should_update_expected_connection_id_length to true to bypass + // Set should_update_expected_server_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; + uint8_t unused_expected_server_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)) { + Perspective::IS_SERVER, + /*should_update_expected_server_connection_id_length=*/true, + &unused_expected_server_connection_id_length, + &destination_connection_id_length, &source_connection_id_length, + detailed_error)) { return QUIC_INVALID_PACKET_HEADER; } } else { - // For short header packets, expected_connection_id_length is used to + // For short header packets, expected_server_connection_id_length is used to // determine the destination_connection_id_length. - *destination_connection_id_length = expected_connection_id_length; + destination_connection_id_length = expected_server_connection_id_length; } // Read destination connection ID. if (!reader.ReadConnectionId(destination_connection_id, - *destination_connection_id_length)) { - *detailed_error = "Unable to read Destination ConnectionId."; + destination_connection_id_length)) { + *detailed_error = "Unable to read destination connection ID."; + return QUIC_INVALID_PACKET_HEADER; + } + // Read source connection ID. + if (!reader.ReadConnectionId(source_connection_id, + source_connection_id_length)) { + *detailed_error = "Unable to read source connection ID."; return QUIC_INVALID_PACKET_HEADER; } return QUIC_NO_ERROR; @@ -6234,13 +6292,14 @@ *detailed_error = "Packet is not a version negotiation packet"; return false; } - uint8_t expected_connection_id_length = 0, + uint8_t expected_server_connection_id_length = 0, destination_connection_id_length = 0, source_connection_id_length = 0; if (!ProcessAndValidateIetfConnectionIdLength( - &reader, UnsupportedQuicVersion(), - /*should_update_expected_connection_id_length=*/true, - &expected_connection_id_length, &destination_connection_id_length, - &source_connection_id_length, detailed_error)) { + &reader, UnsupportedQuicVersion(), Perspective::IS_CLIENT, + /*should_update_expected_server_connection_id_length=*/true, + &expected_server_connection_id_length, + &destination_connection_id_length, &source_connection_id_length, + detailed_error)) { return false; } if (destination_connection_id_length != 0) {
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h index e56aba2..931dd4a 100644 --- a/quic/core/quic_framer.h +++ b/quic/core/quic_framer.h
@@ -226,7 +226,7 @@ QuicFramer(const ParsedQuicVersionVector& supported_versions, QuicTime creation_time, Perspective perspective, - uint8_t expected_connection_id_length); + uint8_t expected_server_connection_id_length); QuicFramer(const QuicFramer&) = delete; QuicFramer& operator=(const QuicFramer&) = delete; @@ -374,18 +374,18 @@ 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. + // |version_label|, |destination_connection_id|, |source_connection_id| and + // |detailed_error|. Please note, |expected_server_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, + uint8_t expected_server_connection_id_length, PacketHeaderFormat* format, bool* version_flag, QuicVersionLabel* version_label, - uint8_t* destination_connection_id_length, QuicConnectionId* destination_connection_id, + QuicConnectionId* source_connection_id, std::string* detailed_error); // Serializes a packet containing |frames| into |buffer|. @@ -435,13 +435,15 @@ // Returns a new version negotiation packet. static std::unique_ptr<QuicEncryptedPacket> BuildVersionNegotiationPacket( - QuicConnectionId connection_id, + QuicConnectionId server_connection_id, + QuicConnectionId client_connection_id, bool ietf_quic, const ParsedQuicVersionVector& versions); // Returns a new IETF version negotiation packet. static std::unique_ptr<QuicEncryptedPacket> BuildIetfVersionNegotiationPacket( - QuicConnectionId source_connection_id, + QuicConnectionId server_connection_id, + QuicConnectionId client_connection_id, const ParsedQuicVersionVector& versions); // If header.version_flag is set, the version in the @@ -576,14 +578,23 @@ // If true, QuicFramer will change its expected connection ID length // to the received destination connection ID length of all IETF long headers. void SetShouldUpdateExpectedConnectionIdLength( - bool should_update_expected_connection_id_length) { - should_update_expected_connection_id_length_ = - should_update_expected_connection_id_length; + bool should_update_expected_server_connection_id_length) { + should_update_expected_server_connection_id_length_ = + should_update_expected_server_connection_id_length; } - // The connection ID length the framer expects on incoming IETF short headers. - uint8_t GetExpectedConnectionIdLength() { - return expected_connection_id_length_; + // The connection ID length the framer expects on incoming IETF short headers + // on the server. + uint8_t GetExpectedServerConnectionIdLength() { + return expected_server_connection_id_length_; + } + + // Change the expected destination connection ID length for short headers on + // the client. + void SetExpectedClientConnectionIdLength( + uint8_t expected_client_connection_id_length) { + expected_client_connection_id_length_ = + expected_client_connection_id_length; } void EnableMultiplePacketNumberSpacesSupport(); @@ -715,8 +726,9 @@ static bool ProcessAndValidateIetfConnectionIdLength( QuicDataReader* reader, ParsedQuicVersion version, - bool should_update_expected_connection_id_length, - uint8_t* expected_connection_id_length, + Perspective perspective, + bool should_update_expected_server_connection_id_length, + uint8_t* expected_server_connection_id_length, uint8_t* destination_connection_id_length, uint8_t* source_connection_id_length, std::string* detailed_error); @@ -960,6 +972,8 @@ QuicPacketNumber largest_decrypted_packet_numbers_[NUM_PACKET_NUMBER_SPACES]; // Last server connection ID seen on the wire. QuicConnectionId last_serialized_server_connection_id_; + // Last client connection ID seen on the wire. + QuicConnectionId last_serialized_client_connection_id_; // The last QUIC version label received. // TODO(fayang): Remove this when deprecating // quic_no_framer_object_in_dispatcher. @@ -1014,18 +1028,18 @@ bool infer_packet_header_type_from_version_; // 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 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_; + // encode its length. These variables contains the length we expect to read. + // This is also used to validate the long header destination connection ID + // lengths in older versions of QUIC. + uint8_t expected_server_connection_id_length_; + uint8_t expected_client_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. + // When this is true, QuicFramer will change + // expected_server_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_; + bool should_update_expected_server_connection_id_length_; // Indicates whether this framer supports multiple packet number spaces. bool supports_multiple_packet_number_spaces_;
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc index 85af7ea..5f46e8e 100644 --- a/quic/core/quic_framer_test.cc +++ b/quic/core/quic_framer_test.cc
@@ -916,18 +916,17 @@ PacketHeaderFormat format; bool version_flag; - uint8_t destination_connection_id_length; - QuicConnectionId destination_connection_id; + QuicConnectionId destination_connection_id, source_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(QUIC_NO_ERROR, + QuicFramer::ProcessPacketDispatcher( + *encrypted, kQuicDefaultConnectionIdLength, &format, + &version_flag, &version_label, &destination_connection_id, + &source_connection_id, &detailed_error)); EXPECT_EQ(GOOGLE_QUIC_PACKET, format); EXPECT_FALSE(version_flag); - EXPECT_EQ(kQuicDefaultConnectionIdLength, destination_connection_id_length); + EXPECT_EQ(kQuicDefaultConnectionIdLength, destination_connection_id.length()); EXPECT_EQ(FramerTestConnectionId(), destination_connection_id); } @@ -994,18 +993,17 @@ PacketHeaderFormat format; bool version_flag; - uint8_t destination_connection_id_length; - QuicConnectionId destination_connection_id; + QuicConnectionId destination_connection_id, source_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(QUIC_NO_ERROR, + QuicFramer::ProcessPacketDispatcher( + *encrypted, kQuicDefaultConnectionIdLength, &format, + &version_flag, &version_label, &destination_connection_id, + &source_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(kQuicDefaultConnectionIdLength, destination_connection_id.length()); EXPECT_EQ(FramerTestConnectionId(), destination_connection_id); } @@ -6626,7 +6624,8 @@ QuicConnectionId connection_id = FramerTestConnectionId(); std::unique_ptr<QuicEncryptedPacket> data( framer_.BuildVersionNegotiationPacket( - connection_id, framer_.transport_version() > QUIC_VERSION_43, + connection_id, EmptyQuicConnectionId(), + framer_.transport_version() > QUIC_VERSION_43, SupportedVersions(GetParam()))); test::CompareCharArraysWithHexError("constructed packet", data->data(), data->length(), AsChars(p), p_size); @@ -13182,8 +13181,8 @@ QuicConnectionId connection_id(connection_id_bytes, sizeof(connection_id_bytes)); QuicFramerPeer::SetLargestPacketNumber(&framer_, kPacketNumber - 2); - QuicFramerPeer::SetExpectedConnectionIDLength(&framer_, - connection_id.length()); + QuicFramerPeer::SetExpectedServerConnectionIDLength(&framer_, + connection_id.length()); // clang-format off PacketFragments packet = { @@ -13320,8 +13319,7 @@ PacketHeaderFormat format; bool version_flag; - uint8_t destination_connection_id_length; - QuicConnectionId destination_connection_id; + QuicConnectionId destination_connection_id, source_connection_id; QuicVersionLabel version_label; std::string detailed_error; EXPECT_EQ(QUIC_NO_ERROR, @@ -13329,21 +13327,21 @@ 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)); + &version_label, &destination_connection_id, + &source_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(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( + QUIC_NO_ERROR, + QuicFramer::ProcessPacketDispatcher( + short_header_encrypted, 9, &format, &version_flag, &version_label, + &destination_connection_id, &source_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(9, destination_connection_id.length()); EXPECT_EQ(FramerTestConnectionIdNineBytes(), destination_connection_id); }
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc index e69ac85..fbc21a8 100644 --- a/quic/core/quic_packet_creator.cc +++ b/quic/core/quic_packet_creator.cc
@@ -75,6 +75,7 @@ server_connection_id_included_(CONNECTION_ID_PRESENT), packet_size_(0), server_connection_id_(server_connection_id), + client_connection_id_(EmptyQuicConnectionId()), packet_(QuicPacketNumber(), PACKET_1BYTE_PACKET_NUMBER, nullptr, @@ -627,6 +628,7 @@ DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective()); std::unique_ptr<QuicEncryptedPacket> encrypted = QuicFramer::BuildVersionNegotiationPacket(server_connection_id_, + client_connection_id_, ietf_quic, supported_versions); DCHECK(encrypted); DCHECK_GE(max_packet_length_, encrypted->length()); @@ -741,7 +743,7 @@ } QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 1, 5); if (framer_->perspective() == Perspective::IS_SERVER) { - return EmptyQuicConnectionId(); + return client_connection_id_; } return server_connection_id_; } @@ -752,7 +754,7 @@ } QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 6, 6); if (framer_->perspective() == Perspective::IS_CLIENT) { - return EmptyQuicConnectionId(); + return client_connection_id_; } return server_connection_id_; } @@ -763,7 +765,8 @@ GetQuicRestartFlag(quic_do_not_override_connection_id)) { // Packets sent by client always include destination connection ID, and // those sent by the server do not include destination connection ID. - return framer_->perspective() == Perspective::IS_CLIENT + return (framer_->perspective() == Perspective::IS_CLIENT || + framer_->version().SupportsClientConnectionIds()) ? CONNECTION_ID_PRESENT : CONNECTION_ID_ABSENT; } @@ -773,7 +776,9 @@ QuicConnectionIdIncluded QuicPacketCreator::GetSourceConnectionIdIncluded() const { // Long header packets sent by server include source connection ID. - if (HasIetfLongHeader() && framer_->perspective() == Perspective::IS_SERVER) { + if (HasIetfLongHeader() && + (framer_->perspective() == Perspective::IS_SERVER || + framer_->version().SupportsClientConnectionIds())) { return CONNECTION_ID_PRESENT; } if (GetQuicRestartFlag(quic_do_not_override_connection_id) && @@ -1038,6 +1043,13 @@ server_connection_id_ = server_connection_id; } +void QuicPacketCreator::SetClientConnectionId( + QuicConnectionId client_connection_id) { + DCHECK(client_connection_id.IsEmpty() || + framer_->version().SupportsClientConnectionIds()); + client_connection_id_ = client_connection_id; +} + void QuicPacketCreator::SetTransmissionType(TransmissionType type) { DCHECK(can_set_transmission_type_);
diff --git a/quic/core/quic_packet_creator.h b/quic/core/quic_packet_creator.h index 259b577..b666f71 100644 --- a/quic/core/quic_packet_creator.h +++ b/quic/core/quic_packet_creator.h
@@ -226,9 +226,12 @@ void SetServerConnectionIdIncluded( QuicConnectionIdIncluded server_connection_id_included); - // Update the connection ID used in outgoing packets. + // Update the server connection ID used in outgoing packets. void SetServerConnectionId(QuicConnectionId server_connection_id); + // Update the client connection ID used in outgoing packets. + void SetClientConnectionId(QuicConnectionId client_connection_id); + // Sets the encryption level that will be applied to new packets. void set_encryption_level(EncryptionLevel level) { packet_.encryption_level = level; @@ -405,6 +408,7 @@ // QuicEncryptedPacket has been flattened into SerializedPacket. size_t packet_size_; QuicConnectionId server_connection_id_; + QuicConnectionId client_connection_id_; // Packet used to invoke OnSerializedPacket. SerializedPacket packet_;
diff --git a/quic/core/quic_packet_generator.cc b/quic/core/quic_packet_generator.cc index f490900..766f8ca 100644 --- a/quic/core/quic_packet_generator.cc +++ b/quic/core/quic_packet_generator.cc
@@ -574,4 +574,9 @@ packet_creator_.SetServerConnectionId(server_connection_id); } +void QuicPacketGenerator::SetClientConnectionId( + QuicConnectionId client_connection_id) { + packet_creator_.SetClientConnectionId(client_connection_id); +} + } // namespace quic
diff --git a/quic/core/quic_packet_generator.h b/quic/core/quic_packet_generator.h index 6ea8215..ec25550 100644 --- a/quic/core/quic_packet_generator.h +++ b/quic/core/quic_packet_generator.h
@@ -238,6 +238,9 @@ // Update the server connection ID used in outgoing packets. void SetServerConnectionId(QuicConnectionId server_connection_id); + // Update the client connection ID used in outgoing packets. + void SetClientConnectionId(QuicConnectionId client_connection_id); + void set_debug_delegate(QuicPacketCreator::DebugDelegate* debug_delegate) { packet_creator_.set_debug_delegate(debug_delegate); }
diff --git a/quic/core/quic_packets.cc b/quic/core/quic_packets.cc index 57bda54..738cc6e 100644 --- a/quic/core/quic_packets.cc +++ b/quic/core/quic_packets.cc
@@ -27,6 +27,16 @@ return header.source_connection_id; } +QuicConnectionId GetClientConnectionIdAsRecipient( + const QuicPacketHeader& header, + Perspective perspective) { + DCHECK(GetQuicRestartFlag(quic_do_not_override_connection_id)); + if (perspective == Perspective::IS_CLIENT) { + return header.destination_connection_id; + } + return header.source_connection_id; +} + QuicConnectionId GetServerConnectionIdAsSender(const QuicPacketHeader& header, Perspective perspective) { if (perspective == Perspective::IS_CLIENT || @@ -48,6 +58,16 @@ return header.source_connection_id_included; } +QuicConnectionId GetClientConnectionIdAsSender(const QuicPacketHeader& header, + Perspective perspective) { + if (perspective == Perspective::IS_CLIENT || + !GetQuicRestartFlag(quic_do_not_override_connection_id)) { + return header.source_connection_id; + } + QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 3, 5); + return header.destination_connection_id; +} + QuicConnectionIdIncluded GetClientConnectionIdIncludedAsSender( const QuicPacketHeader& header, Perspective perspective) {
diff --git a/quic/core/quic_packets.h b/quic/core/quic_packets.h index d3c2600..b1964e7 100644 --- a/quic/core/quic_packets.h +++ b/quic/core/quic_packets.h
@@ -41,6 +41,12 @@ // Returns the destination connection ID of |header| when |perspective| is // client, and the source connection ID when |perspective| is server. QUIC_EXPORT_PRIVATE 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. +QUIC_EXPORT_PRIVATE QuicConnectionId GetServerConnectionIdAsSender(const QuicPacketHeader& header, Perspective perspective); @@ -51,6 +57,12 @@ 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. +QUIC_EXPORT_PRIVATE 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.
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h index 5e527f3..a48446f 100644 --- a/quic/core/quic_session.h +++ b/quic/core/quic_session.h
@@ -506,6 +506,8 @@ return dynamic_stream_map_; } + PendingStreamMap& pending_streams() { return pending_stream_map_; } + ClosedStreams* closed_streams() { return &closed_streams_; } const ZombieStreamMap& zombie_streams() const { return zombie_streams_; }
diff --git a/quic/core/quic_time_wait_list_manager.cc b/quic/core/quic_time_wait_list_manager.cc index fa62fc5..d646f41 100644 --- a/quic/core/quic_time_wait_list_manager.cc +++ b/quic/core/quic_time_wait_list_manager.cc
@@ -200,7 +200,8 @@ } void QuicTimeWaitListManager::SendVersionNegotiationPacket( - QuicConnectionId connection_id, + QuicConnectionId server_connection_id, + QuicConnectionId client_connection_id, bool ietf_quic, const ParsedQuicVersionVector& supported_versions, const QuicSocketAddress& self_address, @@ -209,7 +210,8 @@ SendOrQueuePacket(QuicMakeUnique<QueuedPacket>( self_address, peer_address, QuicFramer::BuildVersionNegotiationPacket( - connection_id, ietf_quic, supported_versions)), + server_connection_id, client_connection_id, + ietf_quic, supported_versions)), packet_context.get()); }
diff --git a/quic/core/quic_time_wait_list_manager.h b/quic/core/quic_time_wait_list_manager.h index dee5d11..26e894d 100644 --- a/quic/core/quic_time_wait_list_manager.h +++ b/quic/core/quic_time_wait_list_manager.h
@@ -121,7 +121,8 @@ // Sends a version negotiation packet for |connection_id| announcing support // for |supported_versions| to |peer_address| from |self_address|. virtual void SendVersionNegotiationPacket( - QuicConnectionId connection_id, + QuicConnectionId server_connection_id, + QuicConnectionId client_connection_id, bool ietf_quic, const ParsedQuicVersionVector& supported_versions, const QuicSocketAddress& self_address,
diff --git a/quic/core/quic_time_wait_list_manager_test.cc b/quic/core/quic_time_wait_list_manager_test.cc index a391390..c1dadba 100644 --- a/quic/core/quic_time_wait_list_manager_test.cc +++ b/quic/core/quic_time_wait_list_manager_test.cc
@@ -251,15 +251,16 @@ TEST_F(QuicTimeWaitListManagerTest, SendVersionNegotiationPacket) { std::unique_ptr<QuicEncryptedPacket> packet( - QuicFramer::BuildVersionNegotiationPacket(connection_id_, false, + QuicFramer::BuildVersionNegotiationPacket(connection_id_, + EmptyQuicConnectionId(), false, AllSupportedVersions())); EXPECT_CALL(writer_, WritePacket(_, packet->length(), self_address_.host(), peer_address_, _)) .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1))); time_wait_list_manager_.SendVersionNegotiationPacket( - connection_id_, false, AllSupportedVersions(), self_address_, - peer_address_, QuicMakeUnique<QuicPerPacketContext>()); + connection_id_, EmptyQuicConnectionId(), false, AllSupportedVersions(), + self_address_, peer_address_, QuicMakeUnique<QuicPerPacketContext>()); EXPECT_EQ(0u, time_wait_list_manager_.num_connections()); }
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc index a4a241b..45bccc9 100644 --- a/quic/core/quic_versions.cc +++ b/quic/core/quic_versions.cc
@@ -55,6 +55,16 @@ return transport_version > QUIC_VERSION_46; } +bool ParsedQuicVersion::SupportsClientConnectionIds() const { + if (!GetQuicRestartFlag(quic_do_not_override_connection_id)) { + // Do not enable this feature in a production version until this flag has + // been deprecated. + return false; + } + return transport_version >= QUIC_VERSION_99 || + transport_version == QUIC_VERSION_UNSUPPORTED; +} + std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version) { os << ParsedQuicVersionToString(version); return os;
diff --git a/quic/core/quic_versions.h b/quic/core/quic_versions.h index fb811cf..02a0681 100644 --- a/quic/core/quic_versions.h +++ b/quic/core/quic_versions.h
@@ -162,6 +162,9 @@ // Returns whether this version supports IETF RETRY packets. bool SupportsRetry() const; + + // Returns whether this version supports client connection ID. + bool SupportsClientConnectionIds() const; }; QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion();
diff --git a/quic/test_tools/mock_quic_time_wait_list_manager.h b/quic/test_tools/mock_quic_time_wait_list_manager.h index d13d5ac..8a39442 100644 --- a/quic/test_tools/mock_quic_time_wait_list_manager.h +++ b/quic/test_tools/mock_quic_time_wait_list_manager.h
@@ -45,8 +45,9 @@ PacketHeaderFormat header_format, std::unique_ptr<QuicPerPacketContext> packet_context)); - MOCK_METHOD6(SendVersionNegotiationPacket, - void(QuicConnectionId connection_id, + MOCK_METHOD7(SendVersionNegotiationPacket, + void(QuicConnectionId server_connection_id, + QuicConnectionId client_connection_id, bool ietf_quic, const ParsedQuicVersionVector& supported_versions, const QuicSocketAddress& server_address,
diff --git a/quic/test_tools/quic_framer_peer.cc b/quic/test_tools/quic_framer_peer.cc index dcb0e94..6eedd60 100644 --- a/quic/test_tools/quic_framer_peer.cc +++ b/quic/test_tools/quic_framer_peer.cc
@@ -337,11 +337,11 @@ } // static -void QuicFramerPeer::SetExpectedConnectionIDLength( +void QuicFramerPeer::SetExpectedServerConnectionIDLength( QuicFramer* framer, - uint8_t expected_connection_id_length) { - *const_cast<uint8_t*>(&framer->expected_connection_id_length_) = - expected_connection_id_length; + uint8_t expected_server_connection_id_length) { + *const_cast<uint8_t*>(&framer->expected_server_connection_id_length_) = + expected_server_connection_id_length; } // static
diff --git a/quic/test_tools/quic_framer_peer.h b/quic/test_tools/quic_framer_peer.h index e363105..0b17c19 100644 --- a/quic/test_tools/quic_framer_peer.h +++ b/quic/test_tools/quic_framer_peer.h
@@ -160,9 +160,9 @@ QuicPacketNumberLength packet_number_length); static void SetFirstSendingPacketNumber(QuicFramer* framer, uint64_t packet_number); - static void SetExpectedConnectionIDLength( + static void SetExpectedServerConnectionIDLength( QuicFramer* framer, - uint8_t expected_connection_id_length); + uint8_t expected_server_connection_id_length); static QuicPacketNumber GetLargestDecryptedPacketNumber( QuicFramer* framer, PacketNumberSpace packet_number_space);
diff --git a/quic/test_tools/quic_spdy_session_peer.cc b/quic/test_tools/quic_spdy_session_peer.cc index 956cd88..6a49bb7 100644 --- a/quic/test_tools/quic_spdy_session_peer.cc +++ b/quic/test_tools/quic_spdy_session_peer.cc
@@ -81,5 +81,11 @@ return session->GetNextOutgoingUnidirectionalStreamId(); } +// static +QuicReceiveControlStream* QuicSpdySessionPeer::GetReceiveControlStream( + QuicSpdySession* session) { + return session->receive_control_stream_; +} + } // namespace test } // namespace quic
diff --git a/quic/test_tools/quic_spdy_session_peer.h b/quic/test_tools/quic_spdy_session_peer.h index 47b55e1..414662d 100644 --- a/quic/test_tools/quic_spdy_session_peer.h +++ b/quic/test_tools/quic_spdy_session_peer.h
@@ -5,6 +5,17 @@ #ifndef QUICHE_QUIC_TEST_TOOLS_QUIC_SPDY_SESSION_PEER_H_ #define QUICHE_QUIC_TEST_TOOLS_QUIC_SPDY_SESSION_PEER_H_ +<<<<<<< +||||||| +#include "net/third_party/quic/core/quic_packets.h" +#include "net/third_party/quic/core/quic_write_blocked_list.h" +#include "net/third_party/spdy/core/spdy_framer.h" +======= +#include "net/third_party/quic/core/http/quic_receive_control_stream.h" +#include "net/third_party/quic/core/quic_packets.h" +#include "net/third_party/quic/core/quic_write_blocked_list.h" +#include "net/third_party/spdy/core/spdy_framer.h" +>>>>>>> #include "net/third_party/quiche/src/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h" #include "net/third_party/quiche/src/spdy/core/spdy_framer.h" @@ -46,6 +57,8 @@ // |session| can't be nullptr. static QuicStreamId GetNextOutgoingUnidirectionalStreamId( QuicSpdySession* session); + static QuicReceiveControlStream* GetReceiveControlStream( + QuicSpdySession* session); }; } // namespace test
diff --git a/quic/test_tools/quic_test_client.cc b/quic/test_tools/quic_test_client.cc index 497dd8a..a290e7d 100644 --- a/quic/test_tools/quic_test_client.cc +++ b/quic/test_tools/quic_test_client.cc
@@ -209,8 +209,10 @@ this), QuicWrapUnique( new RecordingProofVerifier(std::move(proof_verifier)))), - override_connection_id_(EmptyQuicConnectionId()), - connection_id_overridden_(false) {} + override_server_connection_id_(EmptyQuicConnectionId()), + server_connection_id_overridden_(false), + override_client_connection_id_(EmptyQuicConnectionId()), + client_connection_id_overridden_(false) {} MockableQuicClient::~MockableQuicClient() { if (connected()) { @@ -231,13 +233,26 @@ } QuicConnectionId MockableQuicClient::GenerateNewConnectionId() { - return connection_id_overridden_ ? override_connection_id_ - : QuicClient::GenerateNewConnectionId(); + return server_connection_id_overridden_ + ? override_server_connection_id_ + : QuicClient::GenerateNewConnectionId(); } -void MockableQuicClient::UseConnectionId(QuicConnectionId connection_id) { - connection_id_overridden_ = true; - override_connection_id_ = connection_id; +void MockableQuicClient::UseConnectionId( + QuicConnectionId server_connection_id) { + server_connection_id_overridden_ = true; + override_server_connection_id_ = server_connection_id; +} + +QuicConnectionId MockableQuicClient::GetClientConnectionId() { + return client_connection_id_overridden_ ? override_client_connection_id_ + : QuicClient::GetClientConnectionId(); +} + +void MockableQuicClient::UseClientConnectionId( + QuicConnectionId client_connection_id) { + client_connection_id_overridden_ = true; + override_client_connection_id_ = client_connection_id; } void MockableQuicClient::UseWriter(QuicPacketWriterWrapper* writer) { @@ -759,9 +774,15 @@ client_->UseWriter(writer); } -void QuicTestClient::UseConnectionId(QuicConnectionId connection_id) { +void QuicTestClient::UseConnectionId(QuicConnectionId server_connection_id) { DCHECK(!connected()); - client_->UseConnectionId(connection_id); + client_->UseConnectionId(server_connection_id); +} + +void QuicTestClient::UseClientConnectionId( + QuicConnectionId client_connection_id) { + DCHECK(!connected()); + client_->UseClientConnectionId(client_connection_id); } bool QuicTestClient::MigrateSocket(const QuicIpAddress& new_host) {
diff --git a/quic/test_tools/quic_test_client.h b/quic/test_tools/quic_test_client.h index 353c29e..5f1b6fa 100644 --- a/quic/test_tools/quic_test_client.h +++ b/quic/test_tools/quic_test_client.h
@@ -55,7 +55,9 @@ ~MockableQuicClient() override; QuicConnectionId GenerateNewConnectionId() override; - void UseConnectionId(QuicConnectionId connection_id); + void UseConnectionId(QuicConnectionId server_connection_id); + QuicConnectionId GetClientConnectionId() override; + void UseClientConnectionId(QuicConnectionId client_connection_id); void UseWriter(QuicPacketWriterWrapper* writer); void set_peer_address(const QuicSocketAddress& address); @@ -69,9 +71,12 @@ const MockableQuicClientEpollNetworkHelper* mockable_network_helper() const; private: - // ConnectionId to use, if connection_id_overridden_ - QuicConnectionId override_connection_id_; - bool connection_id_overridden_; + // Server connection ID to use, if server_connection_id_overridden_ + QuicConnectionId override_server_connection_id_; + bool server_connection_id_overridden_; + // Client connection ID to use, if client_connection_id_overridden_ + QuicConnectionId override_client_connection_id_; + bool client_connection_id_overridden_; CachedNetworkParameters cached_network_paramaters_; }; @@ -219,9 +224,12 @@ // Configures client_ to take ownership of and use the writer. // Must be called before initial connect. void UseWriter(QuicPacketWriterWrapper* writer); - // If the given ConnectionId is nonzero, configures client_ to use a specific - // ConnectionId instead of a random one. - void UseConnectionId(QuicConnectionId connection_id); + // Configures client_ to use a specific server connection ID instead of a + // random one. + void UseConnectionId(QuicConnectionId server_connection_id); + // Configures client_ to use a specific client connection ID instead of an + // empty one. + void UseClientConnectionId(QuicConnectionId client_connection_id); // Returns nullptr if the maximum number of streams have already been created. QuicSpdyClientStream* GetOrCreateStream();
diff --git a/quic/test_tools/quic_test_server.cc b/quic/test_tools/quic_test_server.cc index bda2148..68c500e 100644 --- a/quic/test_tools/quic_test_server.cc +++ b/quic/test_tools/quic_test_server.cc
@@ -77,7 +77,7 @@ std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, std::unique_ptr<QuicAlarmFactory> alarm_factory, QuicSimpleServerBackend* quic_simple_server_backend, - uint8_t expected_connection_id_length) + uint8_t expected_server_connection_id_length) : QuicSimpleDispatcher(config, crypto_config, version_manager, @@ -85,7 +85,7 @@ std::move(session_helper), std::move(alarm_factory), quic_simple_server_backend, - expected_connection_id_length), + expected_server_connection_id_length), session_factory_(nullptr), stream_factory_(nullptr), crypto_stream_factory_(nullptr) {} @@ -170,13 +170,13 @@ const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, QuicSimpleServerBackend* quic_simple_server_backend, - uint8_t expected_connection_id_length) + uint8_t expected_server_connection_id_length) : QuicServer(std::move(proof_source), config, QuicCryptoServerConfig::ConfigOptions(), supported_versions, quic_simple_server_backend, - expected_connection_id_length) {} + expected_server_connection_id_length) {} QuicDispatcher* QuicTestServer::CreateQuicDispatcher() { return new QuicTestDispatcher( @@ -186,7 +186,7 @@ std::unique_ptr<QuicCryptoServerStream::Helper>( new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())), QuicMakeUnique<QuicEpollAlarmFactory>(epoll_server()), server_backend(), - expected_connection_id_length()); + expected_server_connection_id_length()); } void QuicTestServer::SetSessionFactory(SessionFactory* factory) {
diff --git a/quic/test_tools/quic_test_server.h b/quic/test_tools/quic_test_server.h index 52fb7c5..3661b7a 100644 --- a/quic/test_tools/quic_test_server.h +++ b/quic/test_tools/quic_test_server.h
@@ -69,7 +69,7 @@ const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, QuicSimpleServerBackend* quic_simple_server_backend, - uint8_t expected_connection_id_length); + uint8_t expected_server_connection_id_length); // Create a custom dispatcher which creates custom sessions. QuicDispatcher* CreateQuicDispatcher() override;
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc index 506d323..6bfdefd 100644 --- a/quic/test_tools/quic_test_utils.cc +++ b/quic/test_tools/quic_test_utils.cc
@@ -1180,6 +1180,14 @@ QuicUtils::StreamIdDelta(version) * n; } +QuicStreamId GetNthClientInitiatedUnidirectionalStreamId( + QuicTransportVersion version, + int n) { + return QuicUtils::GetFirstUnidirectionalStreamId(version, + Perspective::IS_CLIENT) + + QuicUtils::StreamIdDelta(version) * n; +} + StreamType DetermineStreamType(QuicStreamId id, QuicTransportVersion version, Perspective perspective,
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h index f64ddbd..3d265fb 100644 --- a/quic/test_tools/quic_test_utils.h +++ b/quic/test_tools/quic_test_utils.h
@@ -1178,6 +1178,9 @@ QuicStreamId GetNthServerInitiatedUnidirectionalStreamId( QuicTransportVersion version, int n); +QuicStreamId GetNthClientInitiatedUnidirectionalStreamId( + QuicTransportVersion version, + int n); StreamType DetermineStreamType(QuicStreamId id, QuicTransportVersion version,
diff --git a/quic/tools/quic_client_base.cc b/quic/tools/quic_client_base.cc index 57cbd9a..679a0d1 100644 --- a/quic/tools/quic_client_base.cc +++ b/quic/tools/quic_client_base.cc
@@ -109,6 +109,11 @@ void QuicClientBase::StartConnect() { DCHECK(initialized_); DCHECK(!connected()); + network_helper_->CleanUpAllUDPSockets(); + if (!network_helper_->CreateUDPSocketAndBind(server_address_, + bind_to_address_, local_port_)) { + return; + } QuicPacketWriter* writer = network_helper_->CreateQuicPacketWriter(); ParsedQuicVersion mutual_version = UnsupportedQuicVersion(); const bool can_reconnect_with_different_version = @@ -135,6 +140,7 @@ can_reconnect_with_different_version ? ParsedQuicVersionVector{mutual_version} : supported_versions())); + session()->connection()->set_client_connection_id(GetClientConnectionId()); if (initial_max_packet_length_ != 0) { session()->connection()->SetMaxPacketLength(initial_max_packet_length_); } @@ -333,6 +339,10 @@ return QuicUtils::CreateRandomConnectionId(); } +QuicConnectionId QuicClientBase::GetClientConnectionId() { + return EmptyQuicConnectionId(); +} + bool QuicClientBase::CanReconnectWithDifferentVersion( ParsedQuicVersion* version) const { if (session_ == nullptr || session_->connection() == nullptr ||
diff --git a/quic/tools/quic_client_base.h b/quic/tools/quic_client_base.h index 0cc4d71..134404b 100644 --- a/quic/tools/quic_client_base.h +++ b/quic/tools/quic_client_base.h
@@ -268,6 +268,9 @@ // connection ID). virtual QuicConnectionId GenerateNewConnectionId(); + // Returns the client connection ID to use. + virtual QuicConnectionId GetClientConnectionId(); + QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); } // Subclasses may need to explicitly clear the session on destruction
diff --git a/quic/tools/quic_server.cc b/quic/tools/quic_server.cc index 4ac1dac..3696b7c 100644 --- a/quic/tools/quic_server.cc +++ b/quic/tools/quic_server.cc
@@ -64,7 +64,7 @@ const QuicCryptoServerConfig::ConfigOptions& crypto_config_options, const ParsedQuicVersionVector& supported_versions, QuicSimpleServerBackend* quic_simple_server_backend, - uint8_t expected_connection_id_length) + uint8_t expected_server_connection_id_length) : port_(0), fd_(-1), packets_dropped_(0), @@ -80,7 +80,8 @@ version_manager_(supported_versions), packet_reader_(new QuicPacketReader()), quic_simple_server_backend_(quic_simple_server_backend), - expected_connection_id_length_(expected_connection_id_length) { + expected_server_connection_id_length_( + expected_server_connection_id_length) { DCHECK(quic_simple_server_backend_); Initialize(); } @@ -159,7 +160,7 @@ new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())), std::unique_ptr<QuicEpollAlarmFactory>( new QuicEpollAlarmFactory(&epoll_server_)), - quic_simple_server_backend_, expected_connection_id_length_); + quic_simple_server_backend_, expected_server_connection_id_length_); } void QuicServer::HandleEventsForever() {
diff --git a/quic/tools/quic_server.h b/quic/tools/quic_server.h index 6fb1646..1f9c225 100644 --- a/quic/tools/quic_server.h +++ b/quic/tools/quic_server.h
@@ -43,7 +43,7 @@ const QuicCryptoServerConfig::ConfigOptions& server_config_options, const ParsedQuicVersionVector& supported_versions, QuicSimpleServerBackend* quic_simple_server_backend, - uint8_t expected_connection_id_length); + uint8_t expected_server_connection_id_length); QuicServer(const QuicServer&) = delete; QuicServer& operator=(const QuicServer&) = delete; @@ -103,8 +103,8 @@ void set_silent_close(bool value) { silent_close_ = value; } - uint8_t expected_connection_id_length() { - return expected_connection_id_length_; + uint8_t expected_server_connection_id_length() { + return expected_server_connection_id_length_; } private: @@ -155,7 +155,7 @@ QuicSimpleServerBackend* quic_simple_server_backend_; // unowned. // Connection ID length expected to be read on incoming IETF short headers. - uint8_t expected_connection_id_length_; + uint8_t expected_server_connection_id_length_; }; } // namespace quic
diff --git a/quic/tools/quic_simple_dispatcher.cc b/quic/tools/quic_simple_dispatcher.cc index 4706b60..0f4d447 100644 --- a/quic/tools/quic_simple_dispatcher.cc +++ b/quic/tools/quic_simple_dispatcher.cc
@@ -16,14 +16,14 @@ std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, std::unique_ptr<QuicAlarmFactory> alarm_factory, QuicSimpleServerBackend* quic_simple_server_backend, - uint8_t expected_connection_id_length) + uint8_t expected_server_connection_id_length) : QuicDispatcher(config, crypto_config, version_manager, std::move(helper), std::move(session_helper), std::move(alarm_factory), - expected_connection_id_length), + expected_server_connection_id_length), quic_simple_server_backend_(quic_simple_server_backend) {} QuicSimpleDispatcher::~QuicSimpleDispatcher() = default;
diff --git a/quic/tools/quic_simple_dispatcher.h b/quic/tools/quic_simple_dispatcher.h index 46d976c..8a6cf85 100644 --- a/quic/tools/quic_simple_dispatcher.h +++ b/quic/tools/quic_simple_dispatcher.h
@@ -21,7 +21,7 @@ std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, std::unique_ptr<QuicAlarmFactory> alarm_factory, QuicSimpleServerBackend* quic_simple_server_backend, - uint8_t expected_connection_id_length); + uint8_t expected_server_connection_id_length); ~QuicSimpleDispatcher() override;