Support unidirectional streams in WebTransport over HTTP/3.
This CL adds support for sending, receiving, buffering, tracking and closing unidirectional streams attached to a WebTransport over HTTP/3 session.
This also fills in some of the missing gaps in the API and testing infrastructure to make this work.
PiperOrigin-RevId: 366108288
Change-Id: I16b779f8905b597b5f948f02a7c37e656ae44659
diff --git a/quic/tools/web_transport_test_visitors.h b/quic/tools/web_transport_test_visitors.h
new file mode 100644
index 0000000..9e99a51
--- /dev/null
+++ b/quic/tools/web_transport_test_visitors.h
@@ -0,0 +1,128 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_TOOLS_WEB_TRANSPORT_TEST_VISITORS_H_
+#define QUICHE_QUIC_TOOLS_WEB_TRANSPORT_TEST_VISITORS_H_
+
+#include <string>
+
+#include "quic/core/web_transport_interface.h"
+#include "quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+// Discards any incoming data.
+class WebTransportDiscardVisitor : public WebTransportStreamVisitor {
+ public:
+ WebTransportDiscardVisitor(WebTransportStream* stream) : stream_(stream) {}
+
+ void OnCanRead() override {
+ std::string buffer;
+ size_t bytes_read = stream_->Read(&buffer);
+ QUIC_DVLOG(2) << "Read " << bytes_read << " bytes from WebTransport stream "
+ << stream_->GetStreamId();
+ }
+
+ void OnFinRead() override {}
+ void OnCanWrite() override {}
+
+ private:
+ WebTransportStream* stream_;
+};
+
+// Echoes any incoming data back on the same stream.
+class WebTransportBidirectionalEchoVisitor : public WebTransportStreamVisitor {
+ public:
+ WebTransportBidirectionalEchoVisitor(WebTransportStream* stream)
+ : stream_(stream) {}
+
+ void OnCanRead() override {
+ stream_->Read(&buffer_);
+ OnCanWrite();
+ }
+
+ void OnFinRead() override {
+ bool success = stream_->SendFin();
+ QUICHE_DCHECK(success);
+ }
+
+ void OnCanWrite() override {
+ if (buffer_.empty()) {
+ return;
+ }
+
+ bool success = stream_->Write(buffer_);
+ if (success) {
+ buffer_ = "";
+ }
+ }
+
+ private:
+ WebTransportStream* stream_;
+ std::string buffer_;
+};
+
+// Buffers all of the data and calls |callback| with the entirety of the stream
+// data.
+class WebTransportUnidirectionalEchoReadVisitor
+ : public WebTransportStreamVisitor {
+ public:
+ using Callback = std::function<void(const std::string&)>;
+
+ WebTransportUnidirectionalEchoReadVisitor(WebTransportStream* stream,
+ Callback callback)
+ : stream_(stream), callback_(std::move(callback)) {}
+
+ void OnCanRead() override {
+ bool success = stream_->Read(&buffer_);
+ QUIC_DVLOG(1) << "Attempted reading on WebTransport unidirectional stream "
+ << stream_->GetStreamId() << ", result: " << success;
+ }
+
+ void OnFinRead() override {
+ QUIC_DVLOG(1) << "Finished receiving data on a WebTransport stream "
+ << stream_->GetStreamId() << ", queueing up the echo";
+ callback_(buffer_);
+ }
+
+ void OnCanWrite() override { QUIC_NOTREACHED(); }
+
+ private:
+ WebTransportStream* stream_;
+ std::string buffer_;
+ Callback callback_;
+};
+
+// Sends supplied data.
+class WebTransportUnidirectionalEchoWriteVisitor
+ : public WebTransportStreamVisitor {
+ public:
+ WebTransportUnidirectionalEchoWriteVisitor(WebTransportStream* stream,
+ const std::string& data)
+ : stream_(stream), data_(data) {}
+
+ void OnCanRead() override { QUIC_NOTREACHED(); }
+ void OnFinRead() override { QUIC_NOTREACHED(); }
+ void OnCanWrite() override {
+ if (data_.empty()) {
+ return;
+ }
+ if (!stream_->Write(data_)) {
+ return;
+ }
+ data_ = "";
+ bool fin_sent = stream_->SendFin();
+ QUICHE_DVLOG(1)
+ << "WebTransportUnidirectionalEchoWriteVisitor finished sending data.";
+ QUICHE_DCHECK(fin_sent);
+ }
+
+ private:
+ WebTransportStream* stream_;
+ std::string data_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_TOOLS_WEB_TRANSPORT_TEST_VISITORS_H_