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