Use IETF application error codes for STOP_SENDING frames. Add ietf_error_code member to QuicStopSendingFrame, and use IetfResetStreamErrorCodeToRstStreamErrorCode() and RstStreamErrorCodeToIetfResetStreamErrorCode() to convert to and from QuicRstStreamErrorCode. This closely mirrors behavior of QuicRstStreamFrame. This is the reland of cl/330521460 with EndToEndTests/EndToEndTest.ClientRstStats fixed. See b/168041589 for flakiness caused by original CL. Locally verified that 100 runs pass both with and without FLAGS_gfe2_reloadable_flag_quic_stop_sending_uses_ietf_error_code. Protected by FLAGS_quic_reloadable_flag_quic_stop_sending_uses_application_error_code. PiperOrigin-RevId: 331000553 Change-Id: Ie5ac10b4e75fe98858d1e79bd07c108525452caa
diff --git a/quic/core/frames/quic_frames_test.cc b/quic/core/frames/quic_frames_test.cc index 2b84822..3177b0c 100644 --- a/quic/core/frames/quic_frames_test.cc +++ b/quic/core/frames/quic_frames_test.cc
@@ -96,10 +96,14 @@ EXPECT_EQ(1u, GetControlFrameId(frame)); stop_sending.stream_id = 321; stop_sending.error_code = QUIC_STREAM_CANCELLED; + stop_sending.ietf_error_code = + static_cast<uint64_t>(QuicHttp3ErrorCode::REQUEST_CANCELLED); std::ostringstream stream; stream << stop_sending; - EXPECT_EQ("{ control_frame_id: 1, stream_id: 321, error_code: 6 }\n", - stream.str()); + EXPECT_EQ( + "{ control_frame_id: 1, stream_id: 321, error_code: 6, ietf_error_code: " + "268 }\n", + stream.str()); EXPECT_TRUE(IsControlFrame(frame.type)); }
diff --git a/quic/core/frames/quic_stop_sending_frame.cc b/quic/core/frames/quic_stop_sending_frame.cc index d3c1cdd..0a8d546 100644 --- a/quic/core/frames/quic_stop_sending_frame.cc +++ b/quic/core/frames/quic_stop_sending_frame.cc
@@ -11,12 +11,17 @@ QuicRstStreamErrorCode error_code) : control_frame_id(control_frame_id), stream_id(stream_id), - error_code(error_code) {} + error_code(error_code), + ietf_error_code( + GetQuicReloadableFlag(quic_stop_sending_uses_ietf_error_code) + ? RstStreamErrorCodeToIetfResetStreamErrorCode(error_code) + : error_code) {} std::ostream& operator<<(std::ostream& os, const QuicStopSendingFrame& frame) { os << "{ control_frame_id: " << frame.control_frame_id << ", stream_id: " << frame.stream_id - << ", error_code: " << frame.error_code << " }\n"; + << ", error_code: " << frame.error_code + << ", ietf_error_code: " << frame.ietf_error_code << " }\n"; return os; }
diff --git a/quic/core/frames/quic_stop_sending_frame.h b/quic/core/frames/quic_stop_sending_frame.h index f54ae0e..57114d7 100644 --- a/quic/core/frames/quic_stop_sending_frame.h +++ b/quic/core/frames/quic_stop_sending_frame.h
@@ -28,8 +28,13 @@ QuicControlFrameId control_frame_id = kInvalidControlFrameId; QuicStreamId stream_id = 0; - // QuicRstStreamErrorCode associated with the frame. + // For an outgoing frame, the error code generated by the application that + // determines |ietf_error_code| to be sent on the wire; for an incoming frame, + // the error code inferred from |ietf_error_code| received on the wire. QuicRstStreamErrorCode error_code = QUIC_STREAM_NO_ERROR; + + // On-the-wire application error code of the frame. + uint64_t ietf_error_code = 0; }; } // namespace quic
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc index 82bfab6..77a5a00 100644 --- a/quic/core/http/quic_spdy_session.cc +++ b/quic/core/http/quic_spdy_session.cc
@@ -1308,9 +1308,13 @@ return true; } default: - SendStopSending(static_cast<QuicRstStreamErrorCode>( - QuicHttp3ErrorCode::STREAM_CREATION_ERROR), - pending->id()); + if (GetQuicReloadableFlag(quic_stop_sending_uses_ietf_error_code)) { + SendStopSending(QUIC_STREAM_STREAM_CREATION_ERROR, pending->id()); + } else { + SendStopSending(static_cast<QuicRstStreamErrorCode>( + QuicHttp3ErrorCode::STREAM_CREATION_ERROR), + pending->id()); + } pending->StopReading(); } return false;
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc index 6012638..accb2a0 100644 --- a/quic/core/http/quic_spdy_session_test.cc +++ b/quic/core/http/quic_spdy_session_test.cc
@@ -2278,8 +2278,15 @@ QuicStopSendingFrame* stop_sending = frame.stop_sending_frame; EXPECT_EQ(stream_id, stop_sending->stream_id); - EXPECT_EQ(QuicHttp3ErrorCode::STREAM_CREATION_ERROR, - static_cast<QuicHttp3ErrorCode>(stop_sending->error_code)); + EXPECT_EQ( + GetQuicReloadableFlag(quic_stop_sending_uses_ietf_error_code) + ? QUIC_STREAM_STREAM_CREATION_ERROR + : static_cast<QuicRstStreamErrorCode>( + QuicHttp3ErrorCode::STREAM_CREATION_ERROR), + stop_sending->error_code); + EXPECT_EQ( + static_cast<uint64_t>(QuicHttp3ErrorCode::STREAM_CREATION_ERROR), + stop_sending->ietf_error_code); return ClearControlFrame(frame); }));
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index 6be7633..b30e564 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -1476,7 +1476,8 @@ } QUIC_DLOG(INFO) << ENDPOINT << "STOP_SENDING frame received for stream: " - << frame.stream_id << " with error: " << frame.error_code; + << frame.stream_id + << " with error: " << frame.ietf_error_code; visitor_->OnStopSendingFrame(frame); return connected_;
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index 5bfccb2..07ea943 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -621,7 +621,7 @@ // static size_t QuicFramer::GetStopSendingFrameSize(const QuicStopSendingFrame& frame) { return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(frame.stream_id) + - QuicDataWriter::GetVarInt62Len(frame.error_code); + QuicDataWriter::GetVarInt62Len(frame.ietf_error_code); } // static @@ -5907,20 +5907,27 @@ return false; } - uint64_t error_code; - if (!reader->ReadVarInt62(&error_code)) { + if (!reader->ReadVarInt62(&stop_sending_frame->ietf_error_code)) { set_detailed_error("Unable to read stop sending application error code."); return false; } + + if (GetQuicReloadableFlag(quic_stop_sending_uses_ietf_error_code)) { + stop_sending_frame->error_code = + IetfResetStreamErrorCodeToRstStreamErrorCode( + stop_sending_frame->ietf_error_code); + return true; + } + // TODO(fkastenholz): when error codes go to uint64_t, remove this. - if (error_code > 0xffff) { + if (stop_sending_frame->ietf_error_code > 0xffff) { stop_sending_frame->error_code = static_cast<QuicRstStreamErrorCode>(0xffff); - QUIC_DLOG(ERROR) << "Stop sending error code (" << error_code - << ") > 0xffff"; + QUIC_DLOG(ERROR) << "Stop sending error code (" + << stop_sending_frame->ietf_error_code << ") > 0xffff"; } else { - stop_sending_frame->error_code = - static_cast<QuicRstStreamErrorCode>(error_code); + stop_sending_frame->error_code = static_cast<QuicRstStreamErrorCode>( + stop_sending_frame->ietf_error_code); } return true; } @@ -5933,7 +5940,7 @@ return false; } if (!writer->WriteVarInt62( - static_cast<uint64_t>(stop_sending_frame.error_code))) { + static_cast<uint64_t>(stop_sending_frame.ietf_error_code))) { set_detailed_error("Can not write application error code"); return false; }
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc index b67eaf3..46cfe61 100644 --- a/quic/core/quic_framer_test.cc +++ b/quic/core/quic_framer_test.cc
@@ -10977,7 +10977,14 @@ PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID)); EXPECT_EQ(kStreamId, visitor_.stop_sending_frame_.stream_id); - EXPECT_EQ(0x7654, visitor_.stop_sending_frame_.error_code); + if (GetQuicReloadableFlag(quic_stop_sending_uses_ietf_error_code)) { + EXPECT_EQ(QUIC_STREAM_UNKNOWN_APPLICATION_ERROR_CODE, + visitor_.stop_sending_frame_.error_code); + } else { + EXPECT_EQ(0x7654, visitor_.stop_sending_frame_.error_code); + } + EXPECT_EQ(static_cast<uint64_t>(0x7654), + visitor_.stop_sending_frame_.ietf_error_code); CheckFramingBoundaries(packet99, QUIC_INVALID_STOP_SENDING_FRAME_DATA); } @@ -10996,7 +11003,9 @@ QuicStopSendingFrame frame; frame.stream_id = kStreamId; - frame.error_code = static_cast<QuicRstStreamErrorCode>(0xffff); + frame.error_code = QUIC_STREAM_ENCODER_STREAM_ERROR; + frame.ietf_error_code = + static_cast<uint64_t>(QuicHttpQpackErrorCode::ENCODER_STREAM_ERROR); QuicFrames frames = {QuicFrame(&frame)}; // clang-format off @@ -11013,7 +11022,7 @@ // Stream ID kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, // Application error code - kVarInt62FourBytes + 0x00, 0x00, 0xff, 0xff + kVarInt62TwoBytes + 0x02, 0x01, }; // clang-format on