Map QuicErrorCodes to proper IETF QUIC Close Connection information.
THis CL maps a QuicErrorCode to either an IETF QUIC Application Connection
Close or Transport Connection Close. In the latter case, the mapping also
produces the correct IETF QUIC TransportErrorCode to use.
gfe-relnote: N/A code exercised only for IETF QUIC.
PiperOrigin-RevId: 261741702
Change-Id: I1e928046b18c86ff0a7cbcf013e0d9219c27d2dd
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 773db66..39d2760 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -1437,11 +1437,27 @@
header.packet_number = QuicPacketNumber(number);
- QuicConnectionCloseFrame qccf(QUIC_PEER_GOING_AWAY, "");
+ QuicErrorCode kQuicErrorCode = QUIC_PEER_GOING_AWAY;
+ // This QuicConnectionCloseFrame will default to being for a Google QUIC
+ // close. If doing IETF QUIC then set fields appropriately for CC/T or CC/A,
+ // depending on the mapping.
+ QuicConnectionCloseFrame qccf(kQuicErrorCode, "");
if (VersionHasIetfQuicFrames(peer_framer_.transport_version())) {
- // Default close-type is Google QUIC. If doing IETF QUIC then
- // set close type to be IETF CC/T.
- qccf.close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
+ QuicErrorCodeToIetfMapping mapping =
+ QuicErrorCodeToTransportErrorCode(kQuicErrorCode);
+ if (mapping.is_transport_close_) {
+ // Maps to a transport close
+ qccf.close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE;
+ qccf.transport_error_code = mapping.transport_error_code_;
+ // TODO(fkastenholz) need to change "0" to get the frame type currently
+ // being processed so that it can be inserted into the frame.
+ qccf.transport_close_frame_type = 0;
+ } else {
+ // Maps to an application close.
+ qccf.close_type = IETF_QUIC_APPLICATION_CONNECTION_CLOSE;
+ qccf.application_error_code = mapping.application_error_code_;
+ }
+ qccf.extracted_error_code = kQuicErrorCode;
}
QuicFrames frames;
@@ -1556,7 +1572,32 @@
const std::vector<QuicConnectionCloseFrame>& connection_close_frames =
writer_->connection_close_frames();
ASSERT_EQ(1u, connection_close_frames.size());
- EXPECT_EQ(expected_code, connection_close_frames[0].quic_error_code);
+ if (!VersionHasIetfQuicFrames(version().transport_version)) {
+ EXPECT_EQ(expected_code, connection_close_frames[0].quic_error_code);
+ EXPECT_EQ(GOOGLE_QUIC_CONNECTION_CLOSE,
+ connection_close_frames[0].close_type);
+ return;
+ }
+
+ QuicErrorCodeToIetfMapping mapping =
+ QuicErrorCodeToTransportErrorCode(expected_code);
+
+ if (mapping.is_transport_close_) {
+ // This Google QUIC Error Code maps to a transport close,
+ EXPECT_EQ(IETF_QUIC_TRANSPORT_CONNECTION_CLOSE,
+ connection_close_frames[0].close_type);
+ EXPECT_EQ(mapping.transport_error_code_,
+ connection_close_frames[0].transport_error_code);
+ // TODO(fkastenholz): when the extracted error code CL lands,
+ // need to test that extracted==expected.
+ } else {
+ // This maps to an application close.
+ EXPECT_EQ(expected_code, connection_close_frames[0].quic_error_code);
+ EXPECT_EQ(IETF_QUIC_APPLICATION_CONNECTION_CLOSE,
+ connection_close_frames[0].close_type);
+ // TODO(fkastenholz): when the extracted error code CL lands,
+ // need to test that extracted==expected.
+ }
}
QuicConnectionId connection_id_;
@@ -1597,6 +1638,36 @@
QuicConnectionTest,
::testing::ValuesIn(GetTestParams()));
+// These two tests ensure that the QuicErrorCode mapping works correctly.
+// Both tests expect to see a Google QUIC close if not running IETF QUIC.
+// If running IETF QUIC, the first will generate a transport connection
+// close, the second an application connection close.
+// The connection close codes for the two tests are manually chosen;
+// they are expected to always map to transport- and application-
+// closes, respectively. If that changes, mew codes should be chosen.
+TEST_P(QuicConnectionTest, CloseErrorCodeTestTransport) {
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
+ connection_.CloseConnection(
+ IETF_QUIC_PROTOCOL_VIOLATION, "Should be transport close",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ EXPECT_FALSE(connection_.connected());
+ TestConnectionCloseQuicErrorCode(IETF_QUIC_PROTOCOL_VIOLATION);
+}
+
+// Test that the IETF QUIC Error code mapping function works
+// properly for application connection close codes.
+TEST_P(QuicConnectionTest, CloseErrorCodeTestApplication) {
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
+ connection_.CloseConnection(
+ QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE,
+ "Should be application close",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ EXPECT_FALSE(connection_.connected());
+ TestConnectionCloseQuicErrorCode(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE);
+}
+
TEST_P(QuicConnectionTest, SelfAddressChangeAtClient) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -1942,8 +2013,13 @@
TestConnectionCloseQuicErrorCode(QUIC_INTERNAL_ERROR);
const std::vector<QuicConnectionCloseFrame>& connection_close_frames =
writer_->connection_close_frames();
- EXPECT_EQ("Packet written out of order.",
- connection_close_frames[0].error_details);
+ if (VersionHasIetfQuicFrames(version().transport_version)) {
+ EXPECT_EQ("1:Packet written out of order.",
+ connection_close_frames[0].error_details);
+ } else {
+ EXPECT_EQ("Packet written out of order.",
+ connection_close_frames[0].error_details);
+ }
}
TEST_P(QuicConnectionTest, DiscardQueuedPacketsAfterConnectionClose) {