Support IETF QUIC reset error codes. Currently, we use gQUIC error codes everywhere, and then map gQUIC to IETF before sending it on the wire. This CL introduces QuicResetErrorCode, a (gQUIC, IETF) error code tuple that is passed around instead. Protected by FLAGS_quic_reloadable_flag_quic_match_ietf_reset_code. PiperOrigin-RevId: 398129312
diff --git a/quic/core/frames/quic_frames_test.cc b/quic/core/frames/quic_frames_test.cc index 038924e..43eabf7 100644 --- a/quic/core/frames/quic_frames_test.cc +++ b/quic/core/frames/quic_frames_test.cc
@@ -85,7 +85,8 @@ std::ostringstream stream; stream << rst_stream; EXPECT_EQ( - "{ control_frame_id: 1, stream_id: 1, byte_offset: 3, error_code: 6 }\n", + "{ control_frame_id: 1, stream_id: 1, byte_offset: 3, error_code: 6, " + "ietf_error_code: 0 }\n", stream.str()); EXPECT_TRUE(IsControlFrame(frame.type)); }
diff --git a/quic/core/frames/quic_rst_stream_frame.cc b/quic/core/frames/quic_rst_stream_frame.cc index d70f217..873868c 100644 --- a/quic/core/frames/quic_rst_stream_frame.cc +++ b/quic/core/frames/quic_rst_stream_frame.cc
@@ -18,12 +18,23 @@ ietf_error_code(RstStreamErrorCodeToIetfResetStreamErrorCode(error_code)), byte_offset(bytes_written) {} +QuicRstStreamFrame::QuicRstStreamFrame(QuicControlFrameId control_frame_id, + QuicStreamId stream_id, + QuicResetStreamError error, + QuicStreamOffset bytes_written) + : control_frame_id(control_frame_id), + stream_id(stream_id), + error_code(error.internal_code()), + ietf_error_code(error.ietf_application_code()), + byte_offset(bytes_written) {} + std::ostream& operator<<(std::ostream& os, const QuicRstStreamFrame& rst_frame) { os << "{ control_frame_id: " << rst_frame.control_frame_id << ", stream_id: " << rst_frame.stream_id << ", byte_offset: " << rst_frame.byte_offset - << ", error_code: " << rst_frame.error_code << " }\n"; + << ", error_code: " << rst_frame.error_code + << ", ietf_error_code: " << rst_frame.ietf_error_code << " }\n"; return os; }
diff --git a/quic/core/frames/quic_rst_stream_frame.h b/quic/core/frames/quic_rst_stream_frame.h index 9c9e42e..744a227 100644 --- a/quic/core/frames/quic_rst_stream_frame.h +++ b/quic/core/frames/quic_rst_stream_frame.h
@@ -16,13 +16,14 @@ struct QUIC_EXPORT_PRIVATE QuicRstStreamFrame { QuicRstStreamFrame() = default; QuicRstStreamFrame(QuicControlFrameId control_frame_id, - QuicStreamId stream_id, - QuicRstStreamErrorCode error_code, + QuicStreamId stream_id, QuicRstStreamErrorCode error_code, + QuicStreamOffset bytes_written); + QuicRstStreamFrame(QuicControlFrameId control_frame_id, + QuicStreamId stream_id, QuicResetStreamError error, QuicStreamOffset bytes_written); friend QUIC_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, - const QuicRstStreamFrame& r); + std::ostream& os, const QuicRstStreamFrame& r); // A unique identifier of this control frame. 0 when this frame is received, // and non-zero when sent. @@ -45,6 +46,11 @@ // that stream. This can be done through normal termination (data packet with // FIN) or through a RST. QuicStreamOffset byte_offset = 0; + + // Returns a tuple of both |error_code| and |ietf_error_code|. + QuicResetStreamError error() const { + return QuicResetStreamError(error_code, ietf_error_code); + } }; } // namespace quic
diff --git a/quic/core/frames/quic_stop_sending_frame.cc b/quic/core/frames/quic_stop_sending_frame.cc index 93eed75..396288e 100644 --- a/quic/core/frames/quic_stop_sending_frame.cc +++ b/quic/core/frames/quic_stop_sending_frame.cc
@@ -11,11 +11,16 @@ QuicStopSendingFrame::QuicStopSendingFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id, QuicRstStreamErrorCode error_code) + : QuicStopSendingFrame(control_frame_id, stream_id, + QuicResetStreamError::FromInternal(error_code)) {} + +QuicStopSendingFrame::QuicStopSendingFrame(QuicControlFrameId control_frame_id, + QuicStreamId stream_id, + QuicResetStreamError error) : control_frame_id(control_frame_id), stream_id(stream_id), - error_code(error_code), - ietf_error_code( - RstStreamErrorCodeToIetfResetStreamErrorCode(error_code)) {} + error_code(error.internal_code()), + ietf_error_code(error.ietf_application_code()) {} std::ostream& operator<<(std::ostream& os, const QuicStopSendingFrame& frame) { os << "{ control_frame_id: " << frame.control_frame_id
diff --git a/quic/core/frames/quic_stop_sending_frame.h b/quic/core/frames/quic_stop_sending_frame.h index 60158b2..b575e75 100644 --- a/quic/core/frames/quic_stop_sending_frame.h +++ b/quic/core/frames/quic_stop_sending_frame.h
@@ -18,6 +18,8 @@ QuicStopSendingFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id, QuicRstStreamErrorCode error_code); + QuicStopSendingFrame(QuicControlFrameId control_frame_id, + QuicStreamId stream_id, QuicResetStreamError error); friend QUIC_EXPORT_PRIVATE std::ostream& operator<<( std::ostream& os, @@ -35,6 +37,11 @@ // On-the-wire application error code of the frame. uint64_t ietf_error_code = 0; + + // Returns a tuple of both |error_code| and |ietf_error_code|. + QuicResetStreamError error() const { + return QuicResetStreamError(error_code, ietf_error_code); + } }; } // namespace quic
diff --git a/quic/core/http/quic_send_control_stream.cc b/quic/core/http/quic_send_control_stream.cc index 79555e0..92831f2 100644 --- a/quic/core/http/quic_send_control_stream.cc +++ b/quic/core/http/quic_send_control_stream.cc
@@ -31,7 +31,7 @@ << "OnStreamReset() called for write unidirectional stream."; } -bool QuicSendControlStream::OnStopSending(QuicRstStreamErrorCode /* code */) { +bool QuicSendControlStream::OnStopSending(QuicResetStreamError /* code */) { stream_delegate()->OnStreamError( QUIC_HTTP_CLOSED_CRITICAL_STREAM, "STOP_SENDING received for send control stream");
diff --git a/quic/core/http/quic_send_control_stream.h b/quic/core/http/quic_send_control_stream.h index face806..d376a63 100644 --- a/quic/core/http/quic_send_control_stream.h +++ b/quic/core/http/quic_send_control_stream.h
@@ -31,7 +31,7 @@ // Overriding QuicStream::OnStopSending() to make sure control stream is never // closed before connection. void OnStreamReset(const QuicRstStreamFrame& frame) override; - bool OnStopSending(QuicRstStreamErrorCode code) override; + bool OnStopSending(QuicResetStreamError code) override; // Send SETTINGS frame if it hasn't been sent yet. Settings frame must be the // first frame sent on this stream.
diff --git a/quic/core/http/quic_send_control_stream_test.cc b/quic/core/http/quic_send_control_stream_test.cc index 3066cb3..45de224 100644 --- a/quic/core/http/quic_send_control_stream_test.cc +++ b/quic/core/http/quic_send_control_stream_test.cc
@@ -216,7 +216,8 @@ Initialize(); EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM, _, _)); - send_control_stream_->OnStopSending(QUIC_STREAM_CANCELLED); + send_control_stream_->OnStopSending( + QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED)); } TEST_P(QuicSendControlStreamTest, ReceiveDataOnSendControlStream) {
diff --git a/quic/core/http/quic_spdy_server_stream_base_test.cc b/quic/core/http/quic_spdy_server_stream_base_test.cc index 41dfe71..aa41b3c 100644 --- a/quic/core/http/quic_spdy_server_stream_base_test.cc +++ b/quic/core/http/quic_spdy_server_stream_base_test.cc
@@ -54,10 +54,15 @@ stream_->StopReading(); if (session_.version().UsesHttp3()) { - EXPECT_CALL(session_, MaybeSendStopSendingFrame(_, QUIC_STREAM_NO_ERROR)) + EXPECT_CALL(session_, + MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal( + QUIC_STREAM_NO_ERROR))) .Times(1); } else { - EXPECT_CALL(session_, MaybeSendRstStreamFrame(_, QUIC_STREAM_NO_ERROR, _)) + EXPECT_CALL( + session_, + MaybeSendRstStreamFrame( + _, QuicResetStreamError::FromInternal(QUIC_STREAM_NO_ERROR), _)) .Times(1); } QuicStreamPeer::SetFinSent(stream_); @@ -71,9 +76,10 @@ EXPECT_CALL(session_, MaybeSendRstStreamFrame( _, - VersionHasIetfQuicFrames(session_.transport_version()) - ? QUIC_STREAM_CANCELLED - : QUIC_RST_ACKNOWLEDGEMENT, + QuicResetStreamError::FromInternal( + VersionHasIetfQuicFrames(session_.transport_version()) + ? QUIC_STREAM_CANCELLED + : QUIC_RST_ACKNOWLEDGEMENT), _)) .Times(1); QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc index 5ac34fc..4dcfe01 100644 --- a/quic/core/http/quic_spdy_session.cc +++ b/quic/core/http/quic_spdy_session.cc
@@ -1413,7 +1413,9 @@ default: break; } - MaybeSendStopSendingFrame(pending->id(), QUIC_STREAM_STREAM_CREATION_ERROR); + MaybeSendStopSendingFrame( + pending->id(), + QuicResetStreamError::FromInternal(QUIC_STREAM_STREAM_CREATION_ERROR)); pending->StopReading(); return nullptr; }
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc index 2ff3b3a..f4fa3ee 100644 --- a/quic/core/http/quic_spdy_stream.cc +++ b/quic/core/http/quic_spdy_stream.cc
@@ -726,11 +726,11 @@ << "Received QUIC_STREAM_NO_ERROR, not discarding response"; set_rst_received(true); MaybeIncreaseHighestReceivedOffset(frame.byte_offset); - set_stream_error(frame.error_code); + set_stream_error(frame.error()); CloseWriteSide(); } -void QuicSpdyStream::Reset(QuicRstStreamErrorCode error) { +void QuicSpdyStream::ResetWithError(QuicResetStreamError error) { if (VersionUsesHttp3(transport_version()) && !fin_received() && spdy_session_->qpack_decoder() && web_transport_data_ == nullptr) { QUIC_CODE_COUNT_N(quic_abort_qpack_on_stream_reset, 2, 2); @@ -741,7 +741,7 @@ } } - QuicStream::Reset(error); + QuicStream::ResetWithError(error); } void QuicSpdyStream::OnDataAvailable() {
diff --git a/quic/core/http/quic_spdy_stream.h b/quic/core/http/quic_spdy_stream.h index 7a019e0..e3e3d6a 100644 --- a/quic/core/http/quic_spdy_stream.h +++ b/quic/core/http/quic_spdy_stream.h
@@ -111,7 +111,7 @@ // QUIC_STREAM_NO_ERROR. void OnStreamReset(const QuicRstStreamFrame& frame) override; - void Reset(QuicRstStreamErrorCode error) override; + void ResetWithError(QuicResetStreamError error) override; // Called by the sequencer when new data is available. Decodes the data and // calls OnBodyAvailable() to pass to the upper layer.
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc index 40ee645..63a77ce 100644 --- a/quic/core/http/quic_spdy_stream_test.cc +++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -510,8 +510,11 @@ stream_->OnStreamHeadersPriority( spdy::SpdyStreamPrecedence(kV3HighestPriority)); - EXPECT_CALL(*session_, MaybeSendRstStreamFrame(stream_->id(), - QUIC_HEADERS_TOO_LARGE, 0)); + EXPECT_CALL( + *session_, + MaybeSendRstStreamFrame( + stream_->id(), + QuicResetStreamError::FromInternal(QUIC_HEADERS_TOO_LARGE), 0)); stream_->OnStreamHeaderList(false, 1 << 20, headers); EXPECT_THAT(stream_->stream_error(), IsStreamError(QUIC_HEADERS_TOO_LARGE)); @@ -526,10 +529,14 @@ QuicStreamFrame frame(stream_->id(), false, 0, headers); - EXPECT_CALL(*session_, - MaybeSendStopSendingFrame(stream_->id(), QUIC_HEADERS_TOO_LARGE)); - EXPECT_CALL(*session_, MaybeSendRstStreamFrame(stream_->id(), - QUIC_HEADERS_TOO_LARGE, 0)); + EXPECT_CALL(*session_, MaybeSendStopSendingFrame( + stream_->id(), QuicResetStreamError::FromInternal( + QUIC_HEADERS_TOO_LARGE))); + EXPECT_CALL( + *session_, + MaybeSendRstStreamFrame( + stream_->id(), + QuicResetStreamError::FromInternal(QUIC_HEADERS_TOO_LARGE), 0)); auto qpack_decoder_stream = QuicSpdySessionPeer::GetQpackDecoderSendStream(session_.get()); @@ -2462,10 +2469,14 @@ /* offset = */ 1, _, _, _)); // Reset stream by this endpoint, for example, due to stream cancellation. - EXPECT_CALL(*session_, - MaybeSendStopSendingFrame(stream_->id(), QUIC_STREAM_CANCELLED)); - EXPECT_CALL(*session_, - MaybeSendRstStreamFrame(stream_->id(), QUIC_STREAM_CANCELLED, _)); + EXPECT_CALL(*session_, MaybeSendStopSendingFrame( + stream_->id(), QuicResetStreamError::FromInternal( + QUIC_STREAM_CANCELLED))); + EXPECT_CALL( + *session_, + MaybeSendRstStreamFrame( + stream_->id(), + QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED), _)); stream_->Reset(QUIC_STREAM_CANCELLED); // Deliver dynamic table entry to decoder. @@ -2908,10 +2919,14 @@ EXPECT_CALL(*session_, WritevData(qpack_decoder_stream->id(), /* write_length = */ 1, /* offset = */ 1, _, _, _)); - EXPECT_CALL(*session_, - MaybeSendStopSendingFrame(stream_->id(), QUIC_STREAM_CANCELLED)); - EXPECT_CALL(*session_, - MaybeSendRstStreamFrame(stream_->id(), QUIC_STREAM_CANCELLED, _)); + EXPECT_CALL(*session_, MaybeSendStopSendingFrame( + stream_->id(), QuicResetStreamError::FromInternal( + QUIC_STREAM_CANCELLED))); + EXPECT_CALL( + *session_, + MaybeSendRstStreamFrame( + stream_->id(), + QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED), _)); stream_->Reset(QUIC_STREAM_CANCELLED); } @@ -3003,8 +3018,11 @@ EXPECT_TRUE(stream_->read_side_closed()); EXPECT_FALSE(stream_->write_side_closed()); } else { - EXPECT_CALL(*session_, MaybeSendRstStreamFrame( - stream_->id(), QUIC_RST_ACKNOWLEDGEMENT, _)); + EXPECT_CALL( + *session_, + MaybeSendRstStreamFrame( + stream_->id(), + QuicResetStreamError::FromInternal(QUIC_RST_ACKNOWLEDGEMENT), _)); EXPECT_QUIC_BUG( stream_->OnStreamReset(rst_frame2), "The stream should've already sent RST in response to STOP_SENDING");
diff --git a/quic/core/qpack/qpack_send_stream.cc b/quic/core/qpack/qpack_send_stream.cc index 0d5d8af..626d063 100644 --- a/quic/core/qpack/qpack_send_stream.cc +++ b/quic/core/qpack/qpack_send_stream.cc
@@ -21,7 +21,7 @@ << "OnStreamReset() called for write unidirectional stream."; } -bool QpackSendStream::OnStopSending(QuicRstStreamErrorCode /* code */) { +bool QpackSendStream::OnStopSending(QuicResetStreamError /* code */) { stream_delegate()->OnStreamError( QUIC_HTTP_CLOSED_CRITICAL_STREAM, "STOP_SENDING received for QPACK send stream");
diff --git a/quic/core/qpack/qpack_send_stream.h b/quic/core/qpack/qpack_send_stream.h index fad159c..086ad63 100644 --- a/quic/core/qpack/qpack_send_stream.h +++ b/quic/core/qpack/qpack_send_stream.h
@@ -33,7 +33,7 @@ // Overriding QuicStream::OnStopSending() to make sure QPACK stream is never // closed before connection. void OnStreamReset(const QuicRstStreamFrame& frame) override; - bool OnStopSending(QuicRstStreamErrorCode code) override; + bool OnStopSending(QuicResetStreamError code) override; // The send QPACK stream is write unidirectional, so this method // should never be called.
diff --git a/quic/core/qpack/qpack_send_stream_test.cc b/quic/core/qpack/qpack_send_stream_test.cc index df4668b..5a98951 100644 --- a/quic/core/qpack/qpack_send_stream_test.cc +++ b/quic/core/qpack/qpack_send_stream_test.cc
@@ -119,7 +119,8 @@ TEST_P(QpackSendStreamTest, StopSendingQpackStream) { EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_CLOSED_CRITICAL_STREAM, _, _)); - qpack_send_stream_->OnStopSending(QUIC_STREAM_CANCELLED); + qpack_send_stream_->OnStopSending( + QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED)); } TEST_P(QpackSendStreamTest, ReceiveDataOnSendStream) {
diff --git a/quic/core/quic_control_frame_manager.cc b/quic/core/quic_control_frame_manager.cc index afcdabc..39e768c 100644 --- a/quic/core/quic_control_frame_manager.cc +++ b/quic/core/quic_control_frame_manager.cc
@@ -59,7 +59,7 @@ } void QuicControlFrameManager::WriteOrBufferRstStream( - QuicStreamId id, QuicRstStreamErrorCode error, + QuicStreamId id, QuicResetStreamError error, QuicStreamOffset bytes_written) { QUIC_DVLOG(1) << "Writing RST_STREAM_FRAME"; WriteOrBufferQuicFrame((QuicFrame(new QuicRstStreamFrame( @@ -104,10 +104,10 @@ } void QuicControlFrameManager::WriteOrBufferStopSending( - QuicRstStreamErrorCode code, QuicStreamId stream_id) { + QuicResetStreamError error, QuicStreamId stream_id) { QUIC_DVLOG(1) << "Writing STOP_SENDING_FRAME"; WriteOrBufferQuicFrame(QuicFrame( - new QuicStopSendingFrame(++last_control_frame_id_, stream_id, code))); + new QuicStopSendingFrame(++last_control_frame_id_, stream_id, error))); } void QuicControlFrameManager::WriteOrBufferHandshakeDone() {
diff --git a/quic/core/quic_control_frame_manager.h b/quic/core/quic_control_frame_manager.h index 962733a..e83fc3b 100644 --- a/quic/core/quic_control_frame_manager.h +++ b/quic/core/quic_control_frame_manager.h
@@ -11,6 +11,7 @@ #include "absl/container/flat_hash_map.h" #include "quic/core/frames/quic_frame.h" #include "quic/core/quic_connection_id.h" +#include "quic/core/quic_error_codes.h" #include "quic/core/quic_types.h" #include "common/quiche_circular_deque.h" #include "common/quiche_linked_hash_map.h" @@ -53,8 +54,7 @@ // Tries to send a WINDOW_UPDATE_FRAME. Buffers the frame if it cannot be sent // immediately. - void WriteOrBufferRstStream(QuicControlFrameId id, - QuicRstStreamErrorCode error, + void WriteOrBufferRstStream(QuicControlFrameId id, QuicResetStreamError error, QuicStreamOffset bytes_written); // Tries to send a GOAWAY_FRAME. Buffers the frame if it cannot be sent @@ -81,7 +81,7 @@ // Tries to send an IETF-QUIC STOP_SENDING frame. The frame is buffered if it // can not be sent immediately. - void WriteOrBufferStopSending(QuicRstStreamErrorCode code, + void WriteOrBufferStopSending(QuicResetStreamError error, QuicStreamId stream_id); // Tries to send an HANDSHAKE_DONE frame. The frame is buffered if it can not @@ -96,8 +96,7 @@ // Tries to send a NEW_CONNECTION_ID frame. The frame is buffered if it cannot // be sent immediately. void WriteOrBufferNewConnectionId( - const QuicConnectionId& connection_id, - uint64_t sequence_number, + const QuicConnectionId& connection_id, uint64_t sequence_number, uint64_t retire_prior_to, const StatelessResetToken& stateless_reset_token);
diff --git a/quic/core/quic_control_frame_manager_test.cc b/quic/core/quic_control_frame_manager_test.cc index 9d6b434..6d20811 100644 --- a/quic/core/quic_control_frame_manager_test.cc +++ b/quic/core/quic_control_frame_manager_test.cc
@@ -66,12 +66,16 @@ EXPECT_FALSE(manager_->WillingToWrite()); EXPECT_CALL(*session_, WriteControlFrame(_, _)).WillOnce(Return(false)); - manager_->WriteOrBufferRstStream(kTestStreamId, QUIC_STREAM_CANCELLED, 0); + manager_->WriteOrBufferRstStream( + kTestStreamId, + QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED), 0); manager_->WriteOrBufferGoAway(QUIC_PEER_GOING_AWAY, kTestStreamId, "Going away."); manager_->WriteOrBufferWindowUpdate(kTestStreamId, 100); manager_->WriteOrBufferBlocked(kTestStreamId); - manager_->WriteOrBufferStopSending(kTestStopSendingCode, kTestStreamId); + manager_->WriteOrBufferStopSending( + QuicResetStreamError::FromInternal(kTestStopSendingCode), + kTestStreamId); number_of_frames_ = 5u; EXPECT_EQ(number_of_frames_, QuicControlFrameManagerPeer::QueueSize(manager_.get())); @@ -341,14 +345,18 @@ // Write 995 control frames. EXPECT_CALL(*session_, WriteControlFrame(_, _)).WillOnce(Return(false)); for (size_t i = 0; i < 995; ++i) { - manager_->WriteOrBufferRstStream(kTestStreamId, QUIC_STREAM_CANCELLED, 0); + manager_->WriteOrBufferRstStream( + kTestStreamId, + QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED), 0); } // Verify write one more control frame causes connection close. EXPECT_CALL( *connection_, CloseConnection(QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES, _, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET)); - manager_->WriteOrBufferRstStream(kTestStreamId, QUIC_STREAM_CANCELLED, 0); + manager_->WriteOrBufferRstStream( + kTestStreamId, QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED), + 0); } } // namespace
diff --git a/quic/core/quic_error_codes.cc b/quic/core/quic_error_codes.cc index c3fcb88..afd0bfb 100644 --- a/quic/core/quic_error_codes.cc +++ b/quic/core/quic_error_codes.cc
@@ -939,6 +939,19 @@ return QUIC_STREAM_UNKNOWN_APPLICATION_ERROR_CODE; } +// static +QuicResetStreamError QuicResetStreamError::FromInternal( + QuicRstStreamErrorCode code) { + return QuicResetStreamError( + code, RstStreamErrorCodeToIetfResetStreamErrorCode(code)); +} + +// static +QuicResetStreamError QuicResetStreamError::FromIetf(uint64_t code) { + return QuicResetStreamError( + IetfResetStreamErrorCodeToRstStreamErrorCode(code), code); +} + #undef RETURN_STRING_LITERAL // undef for jumbo builds } // namespace quic
diff --git a/quic/core/quic_error_codes.h b/quic/core/quic_error_codes.h index 53a8810..f43ad0a 100644 --- a/quic/core/quic_error_codes.h +++ b/quic/core/quic_error_codes.h
@@ -609,6 +609,45 @@ static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()), "QuicErrorCode exceeds four octets"); +// Represents a reason for resetting a stream in both gQUIC and IETF error code +// space. Both error codes have to be present. +class QUIC_EXPORT_PRIVATE QuicResetStreamError { + public: + // Constructs a QuicResetStreamError from QuicRstStreamErrorCode; the IETF + // error code is inferred. + static QuicResetStreamError FromInternal(QuicRstStreamErrorCode code); + // Constructs a QuicResetStreamError from an IETF error code; the internal + // error code is inferred. + static QuicResetStreamError FromIetf(uint64_t code); + // Constructs a QuicResetStreamError with no error. + static QuicResetStreamError NoError() { + return FromInternal(QUIC_STREAM_NO_ERROR); + } + + QuicResetStreamError(QuicRstStreamErrorCode internal_code, + uint64_t ietf_application_code) + : internal_code_(internal_code), + ietf_application_code_(ietf_application_code) {} + + QuicRstStreamErrorCode internal_code() const { return internal_code_; } + uint64_t ietf_application_code() const { return ietf_application_code_; } + + bool operator==(const QuicResetStreamError& other) const { + return internal_code() == other.internal_code() && + ietf_application_code() == other.ietf_application_code(); + } + + // Returns true if the object holds no error. + bool ok() const { return internal_code() == QUIC_STREAM_NO_ERROR; } + + private: + // Error code used in gQUIC. Even when IETF QUIC is in use, this needs to be + // populated as we use those internally. + QuicRstStreamErrorCode internal_code_; + // Application error code used in IETF QUIC. + uint64_t ietf_application_code_; +}; + // Convert TLS alert code to QuicErrorCode. QUIC_EXPORT_PRIVATE QuicErrorCode TlsAlertToQuicErrorCode(uint8_t desc); @@ -645,8 +684,7 @@ QuicIetfTransportErrorCodes c); QUIC_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, - const QuicIetfTransportErrorCodes& c); + std::ostream& os, const QuicIetfTransportErrorCodes& c); // A transport error code (if is_transport_close is true) or application error // code (if is_transport_close is false) to be used in CONNECTION_CLOSE frames.
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h index 5945ed6..c4af7b4 100644 --- a/quic/core/quic_flags_list.h +++ b/quic/core/quic_flags_list.h
@@ -107,6 +107,8 @@ QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false) // If true, validate that peer owns the new address once the server detects peer migration or is probed from that address, and also apply anti-amplification limit while sending to that address. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3, true) +// When receiving STOP_SENDING, send a RESET_STREAM with a matching error code. +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_match_ietf_reset_code, false) // When the STMP connection option is sent by the client, timestamps in the QUIC ACK frame are sent and processed. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_timestamps, false) // When true, QuicDispatcher will silently drop QUIC packets that have invalid flags.
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc index 60a2b45..e720221 100644 --- a/quic/core/quic_session.cc +++ b/quic/core/quic_session.cc
@@ -276,7 +276,7 @@ return; } - stream->OnStopSending(frame.error_code); + stream->OnStopSending(frame.error()); } void QuicSession::OnPacketDecrypted(EncryptionLevel level) { @@ -854,12 +854,12 @@ } QuicConnection::ScopedPacketFlusher flusher(connection()); - MaybeSendStopSendingFrame(id, error); - MaybeSendRstStreamFrame(id, error, 0); + MaybeSendStopSendingFrame(id, QuicResetStreamError::FromInternal(error)); + MaybeSendRstStreamFrame(id, QuicResetStreamError::FromInternal(error), 0); } void QuicSession::MaybeSendRstStreamFrame(QuicStreamId id, - QuicRstStreamErrorCode error, + QuicResetStreamError error, QuicStreamOffset bytes_written) { if (!connection()->connected()) { return; @@ -870,11 +870,11 @@ control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written); } - connection_->OnStreamReset(id, error); + connection_->OnStreamReset(id, error.internal_code()); } void QuicSession::MaybeSendStopSendingFrame(QuicStreamId id, - QuicRstStreamErrorCode error) { + QuicResetStreamError error) { if (!connection()->connected()) { return; }
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h index 431824b..d9de347 100644 --- a/quic/core/quic_session.h +++ b/quic/core/quic_session.h
@@ -580,12 +580,12 @@ // Does actual work of sending RESET_STREAM, if the stream type allows. // Also informs the connection so that pending stream frames can be flushed. virtual void MaybeSendRstStreamFrame(QuicStreamId id, - QuicRstStreamErrorCode error, + QuicResetStreamError error, QuicStreamOffset bytes_written); // Sends a STOP_SENDING frame if the stream type allows. virtual void MaybeSendStopSendingFrame(QuicStreamId id, - QuicRstStreamErrorCode error); + QuicResetStreamError error); // Returns the encryption level to send application data. EncryptionLevel GetEncryptionLevelToSendApplicationData() const;
diff --git a/quic/core/quic_stream.cc b/quic/core/quic_stream.cc index e87bc01..4c83fe8 100644 --- a/quic/core/quic_stream.cc +++ b/quic/core/quic_stream.cc
@@ -142,7 +142,7 @@ connection_flow_controller_->AddBytesConsumed(bytes); } -void PendingStream::Reset(QuicRstStreamErrorCode /*error*/) { +void PendingStream::ResetWithError(QuicResetStreamError /*error*/) { // Currently PendingStream is only read-unidirectional. It shouldn't send // Reset. QUIC_NOTREACHED(); @@ -330,7 +330,7 @@ stream_delegate_(session), precedence_(CalculateDefaultPriority(session)), stream_bytes_read_(stream_bytes_read), - stream_error_(QUIC_STREAM_NO_ERROR), + stream_error_(QuicResetStreamError::NoError()), connection_error_(QUIC_NO_ERROR), read_side_closed_(false), write_side_closed_(false), @@ -472,7 +472,7 @@ sequencer_.OnStreamFrame(frame); } -bool QuicStream::OnStopSending(QuicRstStreamErrorCode code) { +bool QuicStream::OnStopSending(QuicResetStreamError error) { // Do not reset the stream if all data has been sent and acknowledged. if (write_side_closed() && !IsWaitingForAcks()) { QUIC_DVLOG(1) << ENDPOINT @@ -490,8 +490,14 @@ return false; } - stream_error_ = code; - MaybeSendRstStream(code); + stream_error_ = error; + if (GetQuicReloadableFlag(quic_match_ietf_reset_code)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_match_ietf_reset_code); + MaybeSendRstStream(error); + } else { + MaybeSendRstStream( + QuicResetStreamError::FromInternal(error.internal_code())); + } return true; } @@ -536,7 +542,7 @@ return; } - stream_error_ = frame.error_code; + stream_error_ = frame.error(); // Google QUIC closes both sides of the stream in response to a // RESET_STREAM, IETF QUIC closes only the read side. if (!VersionHasIetfQuicFrames(transport_version())) { @@ -551,7 +557,8 @@ return; } if (error != QUIC_NO_ERROR) { - stream_error_ = QUIC_STREAM_CONNECTION_ERROR; + stream_error_ = + QuicResetStreamError::FromInternal(QUIC_STREAM_CONNECTION_ERROR); connection_error_ = error; } @@ -576,6 +583,10 @@ } void QuicStream::Reset(QuicRstStreamErrorCode error) { + ResetWithError(QuicResetStreamError::FromInternal(error)); +} + +void QuicStream::ResetWithError(QuicResetStreamError error) { stream_error_ = error; QuicConnection::ScopedPacketFlusher flusher(session()->connection()); MaybeSendStopSending(error); @@ -818,12 +829,12 @@ } } -void QuicStream::MaybeSendStopSending(QuicRstStreamErrorCode error) { +void QuicStream::MaybeSendStopSending(QuicResetStreamError error) { if (stop_sending_sent_) { return; } - if (!session()->version().UsesHttp3() && error != QUIC_STREAM_NO_ERROR) { + if (!session()->version().UsesHttp3() && !error.ok()) { // In gQUIC, RST with error closes both read and write side. return; } @@ -831,21 +842,21 @@ if (session()->version().UsesHttp3()) { session()->MaybeSendStopSendingFrame(id(), error); } else { - QUICHE_DCHECK_EQ(QUIC_STREAM_NO_ERROR, error); - session()->MaybeSendRstStreamFrame(id(), QUIC_STREAM_NO_ERROR, + QUICHE_DCHECK_EQ(QUIC_STREAM_NO_ERROR, error.internal_code()); + session()->MaybeSendRstStreamFrame(id(), QuicResetStreamError::NoError(), stream_bytes_written()); } stop_sending_sent_ = true; CloseReadSide(); } -void QuicStream::MaybeSendRstStream(QuicRstStreamErrorCode error) { +void QuicStream::MaybeSendRstStream(QuicResetStreamError error) { if (rst_sent_) { return; } if (!session()->version().UsesHttp3()) { - QUIC_BUG_IF(quic_bug_12570_5, error == QUIC_STREAM_NO_ERROR); + QUIC_BUG_IF(quic_bug_12570_5, error.ok()); stop_sending_sent_ = true; CloseReadSide(); } @@ -1150,7 +1161,7 @@ } bool QuicStream::IsWaitingForAcks() const { - return (!rst_sent_ || stream_error_ == QUIC_STREAM_NO_ERROR) && + return (!rst_sent_ || stream_error_.ok()) && (send_buffer_.stream_bytes_outstanding() || fin_outstanding_); }
diff --git a/quic/core/quic_stream.h b/quic/core/quic_stream.h index 10ef313..64e79bd 100644 --- a/quic/core/quic_stream.h +++ b/quic/core/quic_stream.h
@@ -25,6 +25,7 @@ #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "absl/types/span.h" +#include "quic/core/quic_error_codes.h" #include "quic/core/quic_flow_controller.h" #include "quic/core/quic_packets.h" #include "quic/core/quic_stream_send_buffer.h" @@ -59,7 +60,7 @@ void OnDataAvailable() override; void OnFinRead() override; void AddBytesConsumed(QuicByteCount bytes) override; - void Reset(QuicRstStreamErrorCode error) override; + void ResetWithError(QuicResetStreamError error) override; void OnUnrecoverableError(QuicErrorCode error, const std::string& details) override; void OnUnrecoverableError(QuicErrorCode error, @@ -156,7 +157,11 @@ // Called by the subclass or the sequencer to reset the stream from this // end. - void Reset(QuicRstStreamErrorCode error) override; + void ResetWithError(QuicResetStreamError error) override; + // Convenience wrapper for the method above. + // TODO(b/200606367): switch all calls to using QuicResetStreamError + // interface. + void Reset(QuicRstStreamErrorCode error); // Called by the subclass or the sequencer to close the entire connection from // this end. @@ -204,7 +209,9 @@ // Number of bytes available to read. QuicByteCount ReadableBytes() const; - QuicRstStreamErrorCode stream_error() const { return stream_error_; } + QuicRstStreamErrorCode stream_error() const { + return stream_error_.internal_code(); + } QuicErrorCode connection_error() const { return connection_error_; } bool reading_stopped() const { @@ -353,7 +360,7 @@ // Handle received StopSending frame. Returns true if the processing finishes // gracefully. - virtual bool OnStopSending(QuicRstStreamErrorCode code); + virtual bool OnStopSending(QuicResetStreamError error); // Returns true if the stream is static. bool is_static() const { return is_static_; } @@ -415,10 +422,18 @@ void SetFinSent(); // Send STOP_SENDING if it hasn't been sent yet. - void MaybeSendStopSending(QuicRstStreamErrorCode error); + void MaybeSendStopSending(QuicResetStreamError error); // Send RESET_STREAM if it hasn't been sent yet. - void MaybeSendRstStream(QuicRstStreamErrorCode error); + void MaybeSendRstStream(QuicResetStreamError error); + + // Convenience warppers for two methods above. + void MaybeSendRstStream(QuicRstStreamErrorCode error) { + MaybeSendRstStream(QuicResetStreamError::FromInternal(error)); + } + void MaybeSendStopSending(QuicRstStreamErrorCode error) { + MaybeSendStopSending(QuicResetStreamError::FromInternal(error)); + } // Close the write side of the socket. Further writes will fail. // Can be called by the subclass or internally. @@ -426,7 +441,7 @@ virtual void CloseWriteSide(); void set_rst_received(bool rst_received) { rst_received_ = rst_received; } - void set_stream_error(QuicRstStreamErrorCode error) { stream_error_ = error; } + void set_stream_error(QuicResetStreamError error) { stream_error_ = error; } StreamDelegateInterface* stream_delegate() { return stream_delegate_; } @@ -492,7 +507,7 @@ // Stream error code received from a RstStreamFrame or error code sent by the // visitor or sequencer in the RstStreamFrame. - QuicRstStreamErrorCode stream_error_; + QuicResetStreamError stream_error_; // Connection error code due to which the stream was closed. |stream_error_| // is set to |QUIC_STREAM_CONNECTION_ERROR| when this happens and consumers // should check |connection_error_|.
diff --git a/quic/core/quic_stream_sequencer.cc b/quic/core/quic_stream_sequencer.cc index 88a51bd..1dbe5df 100644 --- a/quic/core/quic_stream_sequencer.cc +++ b/quic/core/quic_stream_sequencer.cc
@@ -236,7 +236,8 @@ << "Invalid argument to MarkConsumed." << " expect to consume: " << num_bytes_consumed << ", but not enough bytes available. " << DebugString(); - stream_->Reset(QUIC_ERROR_PROCESSING_STREAM); + stream_->ResetWithError( + QuicResetStreamError::FromInternal(QUIC_ERROR_PROCESSING_STREAM)); return; } stream_->AddBytesConsumed(num_bytes_consumed);
diff --git a/quic/core/quic_stream_sequencer.h b/quic/core/quic_stream_sequencer.h index b7ea49d..fe96f25 100644 --- a/quic/core/quic_stream_sequencer.h +++ b/quic/core/quic_stream_sequencer.h
@@ -37,7 +37,7 @@ virtual void AddBytesConsumed(QuicByteCount bytes) = 0; // Called when an error has occurred which should result in the stream // being reset. - virtual void Reset(QuicRstStreamErrorCode error) = 0; + virtual void ResetWithError(QuicResetStreamError error) = 0; // Called when an error has occurred which should result in the connection // being closed. virtual void OnUnrecoverableError(QuicErrorCode error,
diff --git a/quic/core/quic_stream_sequencer_test.cc b/quic/core/quic_stream_sequencer_test.cc index b097bc5..0a15e96 100644 --- a/quic/core/quic_stream_sequencer_test.cc +++ b/quic/core/quic_stream_sequencer_test.cc
@@ -43,7 +43,7 @@ QuicIetfTransportErrorCodes ietf_error, const std::string& details), (override)); - MOCK_METHOD(void, Reset, (QuicRstStreamErrorCode error), (override)); + MOCK_METHOD(void, ResetWithError, (QuicResetStreamError error), (override)); MOCK_METHOD(void, AddBytesConsumed, (QuicByteCount bytes), (override)); QuicStreamId id() const override { return 1; } @@ -566,7 +566,8 @@ // Now, attempt to mark consumed more data than was readable and expect the // stream to be closed. - EXPECT_CALL(stream_, Reset(QUIC_ERROR_PROCESSING_STREAM)); + EXPECT_CALL(stream_, ResetWithError(QuicResetStreamError::FromInternal( + QUIC_ERROR_PROCESSING_STREAM))); EXPECT_QUIC_BUG(sequencer_->MarkConsumed(4), "Invalid argument to MarkConsumed." " expect to consume: 4, but not enough bytes available.");
diff --git a/quic/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc index 9d37128..f412870 100644 --- a/quic/core/quic_stream_test.cc +++ b/quic/core/quic_stream_test.cc
@@ -129,12 +129,9 @@ } QuicConsumedData CloseStreamOnWriteError( - QuicStreamId id, - QuicByteCount /*write_length*/, - QuicStreamOffset /*offset*/, - StreamSendingState /*state*/, - TransmissionType /*type*/, - absl::optional<EncryptionLevel> /*level*/) { + QuicStreamId id, QuicByteCount /*write_length*/, + QuicStreamOffset /*offset*/, StreamSendingState /*state*/, + TransmissionType /*type*/, absl::optional<EncryptionLevel> /*level*/) { session_->ResetStream(id, QUIC_STREAM_CANCELLED); return QuicConsumedData(1, false); } @@ -168,8 +165,7 @@ 1); }; -INSTANTIATE_TEST_SUITE_P(QuicStreamTests, - QuicStreamTest, +INSTANTIATE_TEST_SUITE_P(QuicStreamTests, QuicStreamTest, ::testing::ValuesIn(AllSupportedVersions()), ::testing::PrintToStringParamName()); @@ -998,8 +994,11 @@ QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 9); - EXPECT_CALL(*session_, MaybeSendRstStreamFrame(stream_->id(), - QUIC_RST_ACKNOWLEDGEMENT, 9)); + EXPECT_CALL( + *session_, + MaybeSendRstStreamFrame( + stream_->id(), + QuicResetStreamError::FromInternal(QUIC_RST_ACKNOWLEDGEMENT), 9)); stream_->OnStreamReset(rst_frame); EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size()); // Stream stops waiting for acks as it does not finish sending and rst is @@ -1041,8 +1040,11 @@ stream_->WriteOrBufferData(kData1, false, nullptr); EXPECT_TRUE(stream_->IsWaitingForAcks()); EXPECT_TRUE(session_->HasUnackedStreamData()); - EXPECT_CALL(*session_, MaybeSendRstStreamFrame(stream_->id(), - QUIC_RST_ACKNOWLEDGEMENT, 9)); + EXPECT_CALL( + *session_, + MaybeSendRstStreamFrame( + stream_->id(), + QuicResetStreamError::FromInternal(QUIC_RST_ACKNOWLEDGEMENT), 9)); QuicConnectionPeer::SetConnectionClose(connection_); stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR, ConnectionCloseSource::FROM_SELF); @@ -1564,10 +1566,14 @@ // Verify stream gets reset because TTL expires. if (session_->version().UsesHttp3()) { EXPECT_CALL(*session_, - MaybeSendStopSendingFrame(_, QUIC_STREAM_TTL_EXPIRED)) + MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal( + QUIC_STREAM_TTL_EXPIRED))) .Times(1); } - EXPECT_CALL(*session_, MaybeSendRstStreamFrame(_, QUIC_STREAM_TTL_EXPIRED, _)) + EXPECT_CALL( + *session_, + MaybeSendRstStreamFrame( + _, QuicResetStreamError::FromInternal(QUIC_STREAM_TTL_EXPIRED), _)) .Times(1); stream_->OnCanWrite(); } @@ -1588,10 +1594,14 @@ // Verify stream gets reset because TTL expires. if (session_->version().UsesHttp3()) { EXPECT_CALL(*session_, - MaybeSendStopSendingFrame(_, QUIC_STREAM_TTL_EXPIRED)) + MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal( + QUIC_STREAM_TTL_EXPIRED))) .Times(1); } - EXPECT_CALL(*session_, MaybeSendRstStreamFrame(_, QUIC_STREAM_TTL_EXPIRED, _)) + EXPECT_CALL( + *session_, + MaybeSendRstStreamFrame( + _, QuicResetStreamError::FromInternal(QUIC_STREAM_TTL_EXPIRED), _)) .Times(1); stream_->RetransmitStreamData(0, 100, false, PTO_RETRANSMISSION); } @@ -1662,6 +1672,15 @@ stream_->OnStreamFrame(empty_stream_frame); } +TEST_P(QuicStreamTest, SendRstWithCustomIetfCode) { + Initialize(); + QuicResetStreamError error(QUIC_STREAM_CANCELLED, 0x1234abcd); + EXPECT_CALL(*session_, MaybeSendRstStreamFrame(kTestStreamId, error, _)) + .Times(1); + stream_->ResetWithError(error); + EXPECT_TRUE(rst_sent()); +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/core/tls_chlo_extractor.h b/quic/core/tls_chlo_extractor.h index c6d0455..4b1cf31 100644 --- a/quic/core/tls_chlo_extractor.h +++ b/quic/core/tls_chlo_extractor.h
@@ -177,7 +177,7 @@ void OnDataAvailable() override; void OnFinRead() override {} void AddBytesConsumed(QuicByteCount /*bytes*/) override {} - void Reset(QuicRstStreamErrorCode /*error*/) override {} + void ResetWithError(QuicResetStreamError /*error*/) override {} void OnUnrecoverableError(QuicErrorCode error, const std::string& details) override; void OnUnrecoverableError(QuicErrorCode error,
diff --git a/quic/qbone/qbone_stream_test.cc b/quic/qbone/qbone_stream_test.cc index fc2ce81..8e724a4 100644 --- a/quic/qbone/qbone_stream_test.cc +++ b/quic/qbone/qbone_stream_test.cc
@@ -31,11 +31,8 @@ class MockQuicSession : public QboneSessionBase { public: MockQuicSession(QuicConnection* connection, const QuicConfig& config) - : QboneSessionBase(connection, - nullptr /*visitor*/, - config, - CurrentSupportedVersions(), - nullptr /*writer*/) {} + : QboneSessionBase(connection, nullptr /*visitor*/, config, + CurrentSupportedVersions(), nullptr /*writer*/) {} ~MockQuicSession() override {} @@ -56,16 +53,12 @@ } // Called by QuicStream when they want to close stream. - MOCK_METHOD(void, - MaybeSendRstStreamFrame, - (QuicStreamId stream_id, - QuicRstStreamErrorCode error, + MOCK_METHOD(void, MaybeSendRstStreamFrame, + (QuicStreamId stream_id, QuicResetStreamError error, QuicStreamOffset bytes_written), (override)); - MOCK_METHOD(void, - MaybeSendStopSendingFrame, - (QuicStreamId stream_id, QuicRstStreamErrorCode error), - (override)); + MOCK_METHOD(void, MaybeSendStopSendingFrame, + (QuicStreamId stream_id, QuicResetStreamError error), (override)); // Sets whether data is written to buffer, or else if this is write blocked. void set_writable(bool writable) { writable_ = writable; } @@ -104,8 +97,7 @@ DummyPacketWriter() {} // QuicPacketWriter overrides. - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* options) override { @@ -181,8 +173,7 @@ SimpleBufferAllocator buffer_allocator_; MockClock clock_; const QuicStreamId kStreamId = QuicUtils::GetFirstUnidirectionalStreamId( - CurrentSupportedVersions()[0].transport_version, - Perspective::IS_CLIENT); + CurrentSupportedVersions()[0].transport_version, Perspective::IS_CLIENT); }; // Read an entire string. @@ -240,9 +231,13 @@ std::string packet = "0123456789"; int iterations = (QboneConstants::kMaxQbonePacketBytes / packet.size()) + 2; EXPECT_CALL(*session_, MaybeSendStopSendingFrame( - kStreamId, QUIC_BAD_APPLICATION_PAYLOAD)); - EXPECT_CALL(*session_, MaybeSendRstStreamFrame( - kStreamId, QUIC_BAD_APPLICATION_PAYLOAD, _)); + kStreamId, QuicResetStreamError::FromInternal( + QUIC_BAD_APPLICATION_PAYLOAD))); + EXPECT_CALL( + *session_, + MaybeSendRstStreamFrame( + kStreamId, + QuicResetStreamError::FromInternal(QUIC_BAD_APPLICATION_PAYLOAD), _)); for (int i = 0; i < iterations; ++i) { QuicStreamFrame frame(kStreamId, i == (iterations - 1), i * packet.size(), packet);
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h index fa0362e..0831b81 100644 --- a/quic/test_tools/quic_test_utils.h +++ b/quic/test_tools/quic_test_utils.h
@@ -24,6 +24,7 @@ #include "quic/core/http/quic_spdy_session.h" #include "quic/core/quic_connection.h" #include "quic/core/quic_connection_id.h" +#include "quic/core/quic_error_codes.h" #include "quic/core/quic_framer.h" #include "quic/core/quic_packet_writer.h" #include "quic/core/quic_path_validator.h" @@ -777,12 +778,11 @@ MOCK_METHOD(bool, WriteControlFrame, (const QuicFrame& frame, TransmissionType type), (override)); MOCK_METHOD(void, MaybeSendRstStreamFrame, - (QuicStreamId stream_id, QuicRstStreamErrorCode error, + (QuicStreamId stream_id, QuicResetStreamError error, QuicStreamOffset bytes_written), (override)); MOCK_METHOD(void, MaybeSendStopSendingFrame, - (QuicStreamId stream_id, QuicRstStreamErrorCode error), - (override)); + (QuicStreamId stream_id, QuicResetStreamError error), (override)); MOCK_METHOD(bool, ShouldKeepConnectionAlive, (), (const, override)); MOCK_METHOD(std::vector<std::string>, GetAlpnsToOffer, (), (const, override)); @@ -802,7 +802,8 @@ void ReallyMaybeSendRstStreamFrame(QuicStreamId id, QuicRstStreamErrorCode error, QuicStreamOffset bytes_written) { - QuicSession::MaybeSendRstStreamFrame(id, error, bytes_written); + QuicSession::MaybeSendRstStreamFrame( + id, QuicResetStreamError::FromInternal(error), bytes_written); } private: @@ -891,12 +892,11 @@ EncryptionLevel level), (override)); MOCK_METHOD(void, MaybeSendRstStreamFrame, - (QuicStreamId stream_id, QuicRstStreamErrorCode error, + (QuicStreamId stream_id, QuicResetStreamError error, QuicStreamOffset bytes_written), (override)); MOCK_METHOD(void, MaybeSendStopSendingFrame, - (QuicStreamId stream_id, QuicRstStreamErrorCode error), - (override)); + (QuicStreamId stream_id, QuicResetStreamError error), (override)); MOCK_METHOD(void, SendWindowUpdate, (QuicStreamId id, QuicStreamOffset byte_offset), (override)); MOCK_METHOD(void, SendBlocked, (QuicStreamId id), (override));
diff --git a/quic/tools/quic_simple_server_session.cc b/quic/tools/quic_simple_server_session.cc index 1e5734d..d1e9a73 100644 --- a/quic/tools/quic_simple_server_session.cc +++ b/quic/tools/quic_simple_server_session.cc
@@ -136,8 +136,9 @@ promised_streams_[index].is_cancelled = true; } } - control_frame_manager().WriteOrBufferRstStream(frame.stream_id, - QUIC_RST_ACKNOWLEDGEMENT, 0); + control_frame_manager().WriteOrBufferRstStream( + frame.stream_id, + QuicResetStreamError::FromInternal(QUIC_RST_ACKNOWLEDGEMENT), 0); connection()->OnStreamReset(frame.stream_id, QUIC_RST_ACKNOWLEDGEMENT); } }
diff --git a/quic/tools/quic_simple_server_stream_test.cc b/quic/tools/quic_simple_server_stream_test.cc index 50b20b2..aa07703 100644 --- a/quic/tools/quic_simple_server_stream_test.cc +++ b/quic/tools/quic_simple_server_stream_test.cc
@@ -158,12 +158,11 @@ const spdy::SpdyStreamPrecedence& precedence), (override)); MOCK_METHOD(void, MaybeSendRstStreamFrame, - (QuicStreamId stream_id, QuicRstStreamErrorCode error, + (QuicStreamId stream_id, QuicResetStreamError error, QuicStreamOffset bytes_written), (override)); MOCK_METHOD(void, MaybeSendStopSendingFrame, - (QuicStreamId stream_id, QuicRstStreamErrorCode error), - (override)); + (QuicStreamId stream_id, QuicResetStreamError error), (override)); using QuicSession::ActivateStream; @@ -322,10 +321,15 @@ stream_->CloseWriteSide(); if (session_.version().UsesHttp3()) { - EXPECT_CALL(session_, MaybeSendStopSendingFrame(_, QUIC_STREAM_NO_ERROR)) + EXPECT_CALL(session_, + MaybeSendStopSendingFrame(_, QuicResetStreamError::FromInternal( + QUIC_STREAM_NO_ERROR))) .Times(1); } else { - EXPECT_CALL(session_, MaybeSendRstStreamFrame(_, QUIC_STREAM_NO_ERROR, _)) + EXPECT_CALL( + session_, + MaybeSendRstStreamFrame( + _, QuicResetStreamError::FromInternal(QUIC_STREAM_NO_ERROR), _)) .Times(1); } stream_->StopReading(); @@ -452,11 +456,16 @@ InSequence s; if (session_.version().UsesHttp3()) { - EXPECT_CALL(session_, MaybeSendStopSendingFrame(promised_stream->id(), - QUIC_STREAM_CANCELLED)); + EXPECT_CALL(session_, + MaybeSendStopSendingFrame( + promised_stream->id(), + QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED))); } - EXPECT_CALL(session_, MaybeSendRstStreamFrame(promised_stream->id(), - QUIC_STREAM_CANCELLED, 0)); + EXPECT_CALL( + session_, + MaybeSendRstStreamFrame( + promised_stream->id(), + QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED), 0)); promised_stream->DoSendResponse(); } @@ -667,11 +676,14 @@ .Times(AnyNumber()); } - EXPECT_CALL(session_, MaybeSendRstStreamFrame(_, - session_.version().UsesHttp3() - ? QUIC_STREAM_CANCELLED - : QUIC_RST_ACKNOWLEDGEMENT, - _)) + EXPECT_CALL( + session_, + MaybeSendRstStreamFrame( + _, + session_.version().UsesHttp3() + ? QuicResetStreamError::FromInternal(QUIC_STREAM_CANCELLED) + : QuicResetStreamError::FromInternal(QUIC_RST_ACKNOWLEDGEMENT), + _)) .Times(1); QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 1234);