Send correct STOP_SENDING/RESET_STREAM frames for different stream types.
Upon receiving RESET_STREAM for a write-only stream, the connection will be closed with error.
gfe-relnote: protected by disabled v99 flag.
PiperOrigin-RevId: 279850700
Change-Id: I9f0e6215a388dac226d430458a340e8934432662
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 205f7ad..3ec2401 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_flow_controller.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
@@ -263,6 +264,8 @@
return;
}
+ stream->OnStopSending(frame.application_error_code);
+
stream->set_stream_error(
static_cast<QuicRstStreamErrorCode>(frame.application_error_code));
SendRstStreamInner(
@@ -302,6 +305,16 @@
return;
}
+ if (VersionHasIetfQuicFrames(transport_version()) &&
+ QuicUtils::GetStreamType(stream_id, perspective(),
+ IsIncomingStream(stream_id)) ==
+ WRITE_UNIDIRECTIONAL) {
+ connection()->CloseConnection(
+ QUIC_INVALID_STREAM_ID, "Received RESET_STREAM for a write-only stream",
+ ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+ return;
+ }
+
if (visitor_) {
visitor_->OnRstStreamReceived(frame);
}
@@ -690,21 +703,23 @@
bool close_write_side_only) {
if (connection()->connected()) {
// Only send if still connected.
- if (close_write_side_only) {
- DCHECK(VersionHasIetfQuicFrames(transport_version()));
- // Send a RST_STREAM frame.
- control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
- } else {
+ if (VersionHasIetfQuicFrames(transport_version())) {
// Send a RST_STREAM frame plus, if version 99, an IETF
// QUIC STOP_SENDING frame. Both sre sent to emulate
// the two-way close that Google QUIC's RST_STREAM does.
- if (VersionHasIetfQuicFrames(transport_version())) {
- QuicConnection::ScopedPacketFlusher flusher(connection());
- control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
- control_frame_manager_.WriteOrBufferStopSending(error, id);
- } else {
+ QuicConnection::ScopedPacketFlusher flusher(connection());
+ if (QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id)) !=
+ READ_UNIDIRECTIONAL) {
control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
}
+ if (!close_write_side_only &&
+ QuicUtils::GetStreamType(id, perspective(), IsIncomingStream(id)) !=
+ WRITE_UNIDIRECTIONAL) {
+ control_frame_manager_.WriteOrBufferStopSending(error, id);
+ }
+ } else {
+ DCHECK(!close_write_side_only);
+ control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
}
connection_->OnStreamReset(id, error);
}