Allow QuicSimpleServerStream to send CONNECT response
This will allow us to support MASQUE CONNECT-UDP in a subsequent change. This class is not used in production and therefore does not require flag protection.
PiperOrigin-RevId: 344288735
Change-Id: I4e5d75943b36b928e0db55ad5de435b19cb81355
diff --git a/quic/tools/quic_simple_server_stream.cc b/quic/tools/quic_simple_server_stream.cc
index 93b4356..8fee04a 100644
--- a/quic/tools/quic_simple_server_stream.cc
+++ b/quic/tools/quic_simple_server_stream.cc
@@ -7,6 +7,7 @@
#include <list>
#include <utility>
+#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/string_view.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h"
@@ -63,6 +64,16 @@
SendErrorResponse();
}
ConsumeHeaderList();
+ if (!fin) {
+ // CONNECT and other CONNECT-like methods (such as CONNECT-UDP) require
+ // sending the response right after parsing the headers even though the FIN
+ // bit has not been received on the request stream.
+ auto it = request_headers_.find(":method");
+ if (it != request_headers_.end() &&
+ absl::StartsWith(it->second, "CONNECT")) {
+ SendResponse();
+ }
+ }
}
void QuicSimpleServerStream::OnTrailingHeadersComplete(
diff --git a/quic/tools/quic_simple_server_stream_test.cc b/quic/tools/quic_simple_server_stream_test.cc
index 4b21cca..c21088a 100644
--- a/quic/tools/quic_simple_server_stream_test.cc
+++ b/quic/tools/quic_simple_server_stream_test.cc
@@ -76,12 +76,22 @@
void set_body(std::string body) { body_ = std::move(body); }
const std::string& body() const { return body_; }
int content_length() const { return content_length_; }
+ bool send_response_was_called() const { return send_response_was_called_; }
absl::string_view GetHeader(absl::string_view key) const {
auto it = request_headers_.find(key);
DCHECK(it != request_headers_.end());
return it->second;
}
+
+ protected:
+ void SendResponse() override {
+ send_response_was_called_ = true;
+ QuicSimpleServerStream::SendResponse();
+ }
+
+ private:
+ bool send_response_was_called_ = false;
};
namespace {
@@ -782,6 +792,29 @@
stream_->OnStreamFrame(frame);
}
+TEST_P(QuicSimpleServerStreamTest, ConnectSendsResponseBeforeFinReceived) {
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _))
+ .WillRepeatedly(
+ Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
+ QuicHeaderList header_list;
+ header_list.OnHeaderBlockStart();
+ header_list.OnHeader(":authority", "www.google.com:4433");
+ header_list.OnHeader(":method", "CONNECT-SILLY");
+ header_list.OnHeaderBlockEnd(128, 128);
+ EXPECT_CALL(*stream_, WriteHeadersMock(/*fin=*/false));
+ stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
+ std::unique_ptr<char[]> buffer;
+ QuicByteCount header_length =
+ HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
+ std::string header = std::string(buffer.get(), header_length);
+ std::string data = UsesHttp3() ? header + body_ : body_;
+ stream_->OnStreamFrame(
+ QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
+ EXPECT_EQ("CONNECT-SILLY", StreamHeadersValue(":method"));
+ EXPECT_EQ(body_, StreamBody());
+ EXPECT_TRUE(stream_->send_response_was_called());
+}
+
} // namespace
} // namespace test
} // namespace quic