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.cc b/quic/core/quic_connection.cc index 0c33604..a577bf1 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -2683,12 +2683,23 @@ !GetUpdatedAckFrame().ack_frame->packets.Empty()) { SendAck(); } - QuicConnectionCloseFrame* frame = - new QuicConnectionCloseFrame(error, details); - // If version99/IETF QUIC set the close type. Default close type is Google - // QUIC. + QuicConnectionCloseFrame* frame; if (VersionHasIetfQuicFrames(transport_version())) { - frame->close_type = IETF_QUIC_TRANSPORT_CONNECTION_CLOSE; + QuicErrorCodeToIetfMapping mapping = + QuicErrorCodeToTransportErrorCode(error); + if (mapping.is_transport_close_) { + // Maps to a transport close + // TODO(fkastenholz) need to change "0" to get the frame type currently + // being processed so that it can be inserted into the frame. + frame = new QuicConnectionCloseFrame(error, details, + mapping.transport_error_code_, 0); + } else { + // Maps to an application close. + frame = new QuicConnectionCloseFrame(error, details, + mapping.application_error_code_); + } + } else { + frame = new QuicConnectionCloseFrame(error, details); } packet_generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame)); packet_generator_.FlushAllQueuedFrames();
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) {
diff --git a/quic/core/quic_types.cc b/quic/core/quic_types.cc index 102b60e..38572f1 100644 --- a/quic/core/quic_types.cc +++ b/quic/core/quic_types.cc
@@ -124,4 +124,309 @@ return os; } +QuicErrorCodeToIetfMapping QuicErrorCodeToTransportErrorCode( + QuicErrorCode error) { + switch (error) { + // TODO(fkastenholz): Currently, all QuicError codes will map + // to application error codes and the original Google QUIC error + // code. This will change over time as we go through all calls to + // CloseConnection() and see whether the call is a Transport or an + // Application close and what the translated code should be. + case QUIC_NO_ERROR: + return {true, {static_cast<uint64_t>(QUIC_NO_ERROR)}}; + case QUIC_INTERNAL_ERROR: + return {true, {static_cast<uint64_t>(QUIC_INTERNAL_ERROR)}}; + case QUIC_STREAM_DATA_AFTER_TERMINATION: + return {true, + {static_cast<uint64_t>(QUIC_STREAM_DATA_AFTER_TERMINATION)}}; + case QUIC_INVALID_PACKET_HEADER: + return {true, {static_cast<uint64_t>(QUIC_INVALID_PACKET_HEADER)}}; + case QUIC_INVALID_FRAME_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_FRAME_DATA)}}; + case QUIC_MISSING_PAYLOAD: + return {true, {static_cast<uint64_t>(QUIC_MISSING_PAYLOAD)}}; + case QUIC_INVALID_FEC_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_FEC_DATA)}}; + case QUIC_INVALID_STREAM_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_STREAM_DATA)}}; + case QUIC_OVERLAPPING_STREAM_DATA: + return {true, {static_cast<uint64_t>(QUIC_OVERLAPPING_STREAM_DATA)}}; + case QUIC_UNENCRYPTED_STREAM_DATA: + return {true, {static_cast<uint64_t>(QUIC_UNENCRYPTED_STREAM_DATA)}}; + case QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA: + return {true, + {static_cast<uint64_t>( + QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA)}}; + case QUIC_MAYBE_CORRUPTED_MEMORY: + return {true, {static_cast<uint64_t>(QUIC_MAYBE_CORRUPTED_MEMORY)}}; + case QUIC_UNENCRYPTED_FEC_DATA: + return {true, {static_cast<uint64_t>(QUIC_UNENCRYPTED_FEC_DATA)}}; + case QUIC_INVALID_RST_STREAM_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_RST_STREAM_DATA)}}; + case QUIC_INVALID_CONNECTION_CLOSE_DATA: + return {true, + {static_cast<uint64_t>(QUIC_INVALID_CONNECTION_CLOSE_DATA)}}; + case QUIC_INVALID_GOAWAY_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_GOAWAY_DATA)}}; + case QUIC_INVALID_WINDOW_UPDATE_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_WINDOW_UPDATE_DATA)}}; + case QUIC_INVALID_BLOCKED_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_BLOCKED_DATA)}}; + case QUIC_INVALID_STOP_WAITING_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_STOP_WAITING_DATA)}}; + case QUIC_INVALID_PATH_CLOSE_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_PATH_CLOSE_DATA)}}; + case QUIC_INVALID_ACK_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_ACK_DATA)}}; + case QUIC_INVALID_MESSAGE_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_MESSAGE_DATA)}}; + case QUIC_INVALID_VERSION_NEGOTIATION_PACKET: + return {true, + {static_cast<uint64_t>(QUIC_INVALID_VERSION_NEGOTIATION_PACKET)}}; + case QUIC_INVALID_PUBLIC_RST_PACKET: + return {true, {static_cast<uint64_t>(QUIC_INVALID_PUBLIC_RST_PACKET)}}; + case QUIC_DECRYPTION_FAILURE: + return {true, {static_cast<uint64_t>(QUIC_DECRYPTION_FAILURE)}}; + case QUIC_ENCRYPTION_FAILURE: + return {true, {static_cast<uint64_t>(QUIC_ENCRYPTION_FAILURE)}}; + case QUIC_PACKET_TOO_LARGE: + return {true, {static_cast<uint64_t>(QUIC_PACKET_TOO_LARGE)}}; + case QUIC_PEER_GOING_AWAY: + return {true, {static_cast<uint64_t>(QUIC_PEER_GOING_AWAY)}}; + case QUIC_INVALID_STREAM_ID: + return {true, {static_cast<uint64_t>(QUIC_INVALID_STREAM_ID)}}; + case QUIC_INVALID_PRIORITY: + return {true, {static_cast<uint64_t>(QUIC_INVALID_PRIORITY)}}; + case QUIC_TOO_MANY_OPEN_STREAMS: + return {true, {static_cast<uint64_t>(QUIC_TOO_MANY_OPEN_STREAMS)}}; + case QUIC_TOO_MANY_AVAILABLE_STREAMS: + return {true, {static_cast<uint64_t>(QUIC_TOO_MANY_AVAILABLE_STREAMS)}}; + case QUIC_PUBLIC_RESET: + return {true, {static_cast<uint64_t>(QUIC_PUBLIC_RESET)}}; + case QUIC_INVALID_VERSION: + return {true, {static_cast<uint64_t>(QUIC_INVALID_VERSION)}}; + case QUIC_INVALID_HEADER_ID: + return {true, {static_cast<uint64_t>(QUIC_INVALID_HEADER_ID)}}; + case QUIC_INVALID_NEGOTIATED_VALUE: + return {true, {static_cast<uint64_t>(QUIC_INVALID_NEGOTIATED_VALUE)}}; + case QUIC_DECOMPRESSION_FAILURE: + return {true, {static_cast<uint64_t>(QUIC_DECOMPRESSION_FAILURE)}}; + case QUIC_NETWORK_IDLE_TIMEOUT: + return {true, {static_cast<uint64_t>(QUIC_NETWORK_IDLE_TIMEOUT)}}; + case QUIC_HANDSHAKE_TIMEOUT: + return {true, {static_cast<uint64_t>(QUIC_HANDSHAKE_TIMEOUT)}}; + case QUIC_ERROR_MIGRATING_ADDRESS: + return {true, {static_cast<uint64_t>(QUIC_ERROR_MIGRATING_ADDRESS)}}; + case QUIC_ERROR_MIGRATING_PORT: + return {true, {static_cast<uint64_t>(QUIC_ERROR_MIGRATING_PORT)}}; + case QUIC_PACKET_WRITE_ERROR: + return {true, {static_cast<uint64_t>(QUIC_PACKET_WRITE_ERROR)}}; + case QUIC_PACKET_READ_ERROR: + return {true, {static_cast<uint64_t>(QUIC_PACKET_READ_ERROR)}}; + case QUIC_EMPTY_STREAM_FRAME_NO_FIN: + return {true, {static_cast<uint64_t>(QUIC_EMPTY_STREAM_FRAME_NO_FIN)}}; + case QUIC_INVALID_HEADERS_STREAM_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_HEADERS_STREAM_DATA)}}; + case QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE: + return { + true, + {static_cast<uint64_t>(QUIC_HEADERS_STREAM_DATA_DECOMPRESS_FAILURE)}}; + case QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA: + return { + true, + {static_cast<uint64_t>(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA)}}; + case QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA: + return {true, + {static_cast<uint64_t>(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA)}}; + case QUIC_FLOW_CONTROL_INVALID_WINDOW: + return {true, {static_cast<uint64_t>(QUIC_FLOW_CONTROL_INVALID_WINDOW)}}; + case QUIC_CONNECTION_IP_POOLED: + return {true, {static_cast<uint64_t>(QUIC_CONNECTION_IP_POOLED)}}; + case QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS: + return {true, + {static_cast<uint64_t>(QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS)}}; + case QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS: + return { + true, + {static_cast<uint64_t>(QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS)}}; + case QUIC_CONNECTION_CANCELLED: + return {true, {static_cast<uint64_t>(QUIC_CONNECTION_CANCELLED)}}; + case QUIC_BAD_PACKET_LOSS_RATE: + return {true, {static_cast<uint64_t>(QUIC_BAD_PACKET_LOSS_RATE)}}; + case QUIC_PUBLIC_RESETS_POST_HANDSHAKE: + return {true, {static_cast<uint64_t>(QUIC_PUBLIC_RESETS_POST_HANDSHAKE)}}; + case QUIC_FAILED_TO_SERIALIZE_PACKET: + return {true, {static_cast<uint64_t>(QUIC_FAILED_TO_SERIALIZE_PACKET)}}; + case QUIC_TOO_MANY_RTOS: + return {true, {static_cast<uint64_t>(QUIC_TOO_MANY_RTOS)}}; + case QUIC_HANDSHAKE_FAILED: + return {true, {static_cast<uint64_t>(QUIC_HANDSHAKE_FAILED)}}; + case QUIC_CRYPTO_TAGS_OUT_OF_ORDER: + return {true, {static_cast<uint64_t>(QUIC_CRYPTO_TAGS_OUT_OF_ORDER)}}; + case QUIC_CRYPTO_TOO_MANY_ENTRIES: + return {true, {static_cast<uint64_t>(QUIC_CRYPTO_TOO_MANY_ENTRIES)}}; + case QUIC_CRYPTO_INVALID_VALUE_LENGTH: + return {true, {static_cast<uint64_t>(QUIC_CRYPTO_INVALID_VALUE_LENGTH)}}; + case QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE: + return {true, + {static_cast<uint64_t>( + QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE)}}; + case QUIC_INVALID_CRYPTO_MESSAGE_TYPE: + return {true, {static_cast<uint64_t>(QUIC_INVALID_CRYPTO_MESSAGE_TYPE)}}; + case QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER: + return {true, + {static_cast<uint64_t>(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER)}}; + case QUIC_INVALID_CHANNEL_ID_SIGNATURE: + return {true, {static_cast<uint64_t>(QUIC_INVALID_CHANNEL_ID_SIGNATURE)}}; + case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: + return {true, + {static_cast<uint64_t>(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND)}}; + case QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP: + return { + true, + {static_cast<uint64_t>(QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP)}}; + case QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND: + return {true, + {static_cast<uint64_t>(QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND)}}; + case QUIC_UNSUPPORTED_PROOF_DEMAND: + return {true, {static_cast<uint64_t>(QUIC_UNSUPPORTED_PROOF_DEMAND)}}; + case QUIC_CRYPTO_INTERNAL_ERROR: + return {true, {static_cast<uint64_t>(QUIC_CRYPTO_INTERNAL_ERROR)}}; + case QUIC_CRYPTO_VERSION_NOT_SUPPORTED: + return {true, {static_cast<uint64_t>(QUIC_CRYPTO_VERSION_NOT_SUPPORTED)}}; + case QUIC_CRYPTO_NO_SUPPORT: + return {true, {static_cast<uint64_t>(QUIC_CRYPTO_NO_SUPPORT)}}; + case QUIC_CRYPTO_TOO_MANY_REJECTS: + return {true, {static_cast<uint64_t>(QUIC_CRYPTO_TOO_MANY_REJECTS)}}; + case QUIC_PROOF_INVALID: + return {true, {static_cast<uint64_t>(QUIC_PROOF_INVALID)}}; + case QUIC_CRYPTO_DUPLICATE_TAG: + return {true, {static_cast<uint64_t>(QUIC_CRYPTO_DUPLICATE_TAG)}}; + case QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT: + return {true, + {static_cast<uint64_t>(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT)}}; + case QUIC_CRYPTO_SERVER_CONFIG_EXPIRED: + return {true, {static_cast<uint64_t>(QUIC_CRYPTO_SERVER_CONFIG_EXPIRED)}}; + case QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED: + return {true, + {static_cast<uint64_t>(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED)}}; + case QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO: + return {true, + {static_cast<uint64_t>( + QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO)}}; + case QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE: + return {true, + {static_cast<uint64_t>( + QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE)}}; + case QUIC_CRYPTO_CHLO_TOO_LARGE: + return {true, {static_cast<uint64_t>(QUIC_CRYPTO_CHLO_TOO_LARGE)}}; + case QUIC_VERSION_NEGOTIATION_MISMATCH: + return {true, {static_cast<uint64_t>(QUIC_VERSION_NEGOTIATION_MISMATCH)}}; + case QUIC_BAD_MULTIPATH_FLAG: + return {true, {static_cast<uint64_t>(QUIC_BAD_MULTIPATH_FLAG)}}; + case QUIC_MULTIPATH_PATH_DOES_NOT_EXIST: + return {true, + {static_cast<uint64_t>(QUIC_MULTIPATH_PATH_DOES_NOT_EXIST)}}; + case QUIC_MULTIPATH_PATH_NOT_ACTIVE: + return {true, {static_cast<uint64_t>(QUIC_MULTIPATH_PATH_NOT_ACTIVE)}}; + case QUIC_IP_ADDRESS_CHANGED: + return {true, {static_cast<uint64_t>(QUIC_IP_ADDRESS_CHANGED)}}; + case QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS: + return {true, + {static_cast<uint64_t>( + QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS)}}; + case QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES: + return { + true, + {static_cast<uint64_t>(QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES)}}; + case QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK: + return { + true, + {static_cast<uint64_t>(QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK)}}; + case QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM: + return {true, + {static_cast<uint64_t>( + QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM)}}; + case QUIC_CONNECTION_MIGRATION_DISABLED_BY_CONFIG: + return {true, + {static_cast<uint64_t>( + QUIC_CONNECTION_MIGRATION_DISABLED_BY_CONFIG)}}; + case QUIC_CONNECTION_MIGRATION_INTERNAL_ERROR: + return { + true, + {static_cast<uint64_t>(QUIC_CONNECTION_MIGRATION_INTERNAL_ERROR)}}; + case QUIC_CONNECTION_MIGRATION_HANDSHAKE_UNCONFIRMED: + return {true, + {static_cast<uint64_t>( + QUIC_CONNECTION_MIGRATION_HANDSHAKE_UNCONFIRMED)}}; + case QUIC_TOO_MANY_STREAM_DATA_INTERVALS: + return {true, + {static_cast<uint64_t>(QUIC_TOO_MANY_STREAM_DATA_INTERVALS)}}; + case QUIC_STREAM_SEQUENCER_INVALID_STATE: + return {true, + {static_cast<uint64_t>(QUIC_STREAM_SEQUENCER_INVALID_STATE)}}; + case QUIC_TOO_MANY_SESSIONS_ON_SERVER: + return {true, {static_cast<uint64_t>(QUIC_TOO_MANY_SESSIONS_ON_SERVER)}}; + case QUIC_STREAM_LENGTH_OVERFLOW: + return {true, {static_cast<uint64_t>(QUIC_STREAM_LENGTH_OVERFLOW)}}; + case QUIC_INVALID_MAX_DATA_FRAME_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_MAX_DATA_FRAME_DATA)}}; + case QUIC_INVALID_MAX_STREAM_DATA_FRAME_DATA: + return {true, + {static_cast<uint64_t>(QUIC_INVALID_MAX_STREAM_DATA_FRAME_DATA)}}; + case QUIC_MAX_STREAMS_DATA: + return {true, {static_cast<uint64_t>(QUIC_MAX_STREAMS_DATA)}}; + case QUIC_STREAMS_BLOCKED_DATA: + return {true, {static_cast<uint64_t>(QUIC_STREAMS_BLOCKED_DATA)}}; + case QUIC_INVALID_STREAM_BLOCKED_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_STREAM_BLOCKED_DATA)}}; + case QUIC_INVALID_NEW_CONNECTION_ID_DATA: + return {true, + {static_cast<uint64_t>(QUIC_INVALID_NEW_CONNECTION_ID_DATA)}}; + case QUIC_INVALID_STOP_SENDING_FRAME_DATA: + return {true, + {static_cast<uint64_t>(QUIC_INVALID_STOP_SENDING_FRAME_DATA)}}; + case QUIC_INVALID_PATH_CHALLENGE_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_PATH_CHALLENGE_DATA)}}; + case QUIC_INVALID_PATH_RESPONSE_DATA: + return {true, {static_cast<uint64_t>(QUIC_INVALID_PATH_RESPONSE_DATA)}}; + case IETF_QUIC_PROTOCOL_VIOLATION: + return {true, {static_cast<uint64_t>(IETF_QUIC_PROTOCOL_VIOLATION)}}; + case QUIC_INVALID_NEW_TOKEN: + return {true, {static_cast<uint64_t>(QUIC_INVALID_NEW_TOKEN)}}; + case QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM: + return {true, + {static_cast<uint64_t>( + QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM)}}; + case QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM: + return {true, + {static_cast<uint64_t>( + QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM)}}; + case QUIC_INVALID_RETIRE_CONNECTION_ID_DATA: + return {true, + {static_cast<uint64_t>(QUIC_INVALID_RETIRE_CONNECTION_ID_DATA)}}; + case QUIC_STREAMS_BLOCKED_ERROR: + return {true, {static_cast<uint64_t>(QUIC_STREAMS_BLOCKED_ERROR)}}; + case QUIC_MAX_STREAMS_ERROR: + return {true, {static_cast<uint64_t>(QUIC_MAX_STREAMS_ERROR)}}; + case QUIC_HTTP_DECODER_ERROR: + return {true, {static_cast<uint64_t>(QUIC_HTTP_DECODER_ERROR)}}; + case QUIC_STALE_CONNECTION_CANCELLED: + return {true, {static_cast<uint64_t>(QUIC_STALE_CONNECTION_CANCELLED)}}; + case QUIC_IETF_GQUIC_ERROR_MISSING: + return {true, {static_cast<uint64_t>(QUIC_IETF_GQUIC_ERROR_MISSING)}}; + case QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM: + return {true, + {static_cast<uint64_t>( + QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM)}}; + case QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES: + return {true, + {static_cast<uint64_t>(QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES)}}; + case QUIC_LAST_ERROR: + return {false, {static_cast<uint64_t>(QUIC_LAST_ERROR)}}; + } + // If it's an unknown code, indicate it's an application error code. + return {false, {NO_IETF_QUIC_ERROR}}; +} + } // namespace quic
diff --git a/quic/core/quic_types.h b/quic/core/quic_types.h index c3f70e7..8a5434e 100644 --- a/quic/core/quic_types.h +++ b/quic/core/quic_types.h
@@ -523,6 +523,21 @@ std::ostream& os, const QuicIetfTransportErrorCodes& c); +// Returns the mapping of the QuicErrorCode to an IETF TransportErrorCode. If +// first element of the pair is false, it means that an IETF Application Close +// should be done instead. + +struct QuicErrorCodeToIetfMapping { + bool is_transport_close_; + union { + uint64_t application_error_code_; + QuicIetfTransportErrorCodes transport_error_code_; + }; +}; + +QUIC_EXPORT_PRIVATE QuicErrorCodeToIetfMapping +QuicErrorCodeToTransportErrorCode(QuicErrorCode error); + // Please note, this value cannot used directly for packet serialization. enum QuicLongHeaderType : uint8_t { VERSION_NEGOTIATION,