Refactor WebTransport API to make it independent of QUIC.

This moves web_transport_interface.h types into their own namespace and directory, removes dependencies on QUIC types, and cleans the API in a bunch of other ways (notably, adds more documentation).

A notable functional outcome of this refactor is that we accept datagrams as string_views instead of memslices.  For HTTP/3 use cases, this will typically reduce one copy, since we always copy the contents of the datagram while appending the stream ID.

PiperOrigin-RevId: 499584983
diff --git a/quiche/quic/core/http/end_to_end_test.cc b/quiche/quic/core/http/end_to_end_test.cc
index f3b7f03..80161dd 100644
--- a/quiche/quic/core/http/end_to_end_test.cc
+++ b/quiche/quic/core/http/end_to_end_test.cc
@@ -6759,7 +6759,7 @@
 
   quiche::SimpleBufferAllocator allocator;
   for (int i = 0; i < 10; i++) {
-    session->SendOrQueueDatagram(MemSliceFromString("test"));
+    session->SendOrQueueDatagram("test");
   }
 
   int received = 0;
diff --git a/quiche/quic/core/http/web_transport_http3.cc b/quiche/quic/core/http/web_transport_http3.cc
index 84f1d33..d74071d 100644
--- a/quiche/quic/core/http/web_transport_http3.cc
+++ b/quiche/quic/core/http/web_transport_http3.cc
@@ -21,6 +21,7 @@
 #include "quiche/quic/core/quic_versions.h"
 #include "quiche/quic/platform/api/quic_bug_tracker.h"
 #include "quiche/common/platform/api/quiche_logging.h"
+#include "quiche/web_transport/web_transport.h"
 
 #define ENDPOINT \
   (session_->perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
@@ -266,10 +267,10 @@
   return stream->interface();
 }
 
-MessageStatus WebTransportHttp3::SendOrQueueDatagram(
-    quiche::QuicheMemSlice datagram) {
-  return connect_stream_->SendHttp3Datagram(
-      absl::string_view(datagram.data(), datagram.length()));
+webtransport::DatagramStatus WebTransportHttp3::SendOrQueueDatagram(
+    absl::string_view datagram) {
+  return MessageStatusToWebTransportStatus(
+      connect_stream_->SendHttp3Datagram(datagram));
 }
 
 QuicByteCount WebTransportHttp3::GetMaxDatagramSize() const {
@@ -277,8 +278,9 @@
 }
 
 void WebTransportHttp3::SetDatagramMaxTimeInQueue(
-    QuicTime::Delta max_time_in_queue) {
-  connect_stream_->SetMaxDatagramTimeInQueue(max_time_in_queue);
+    absl::Duration max_time_in_queue) {
+  connect_stream_->SetMaxDatagramTimeInQueue(
+      QuicTime::Delta::FromAbsl(max_time_in_queue));
 }
 
 void WebTransportHttp3::OnHttp3Datagram(QuicStreamId stream_id,
diff --git a/quiche/quic/core/http/web_transport_http3.h b/quiche/quic/core/http/web_transport_http3.h
index 67c2fc8..8744449 100644
--- a/quiche/quic/core/http/web_transport_http3.h
+++ b/quiche/quic/core/http/web_transport_http3.h
@@ -9,6 +9,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/container/flat_hash_set.h"
+#include "absl/time/time.h"
 #include "absl/types/optional.h"
 #include "quiche/quic/core/http/quic_spdy_session.h"
 #include "quiche/quic/core/http/web_transport_stream_adapter.h"
@@ -17,6 +18,7 @@
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/quic/core/web_transport_interface.h"
 #include "quiche/common/platform/api/quiche_mem_slice.h"
+#include "quiche/web_transport/web_transport.h"
 #include "quiche/spdy/core/http2_header_block.h"
 
 namespace quic {
@@ -80,9 +82,10 @@
   WebTransportStream* OpenOutgoingBidirectionalStream() override;
   WebTransportStream* OpenOutgoingUnidirectionalStream() override;
 
-  MessageStatus SendOrQueueDatagram(quiche::QuicheMemSlice datagram) override;
+  webtransport::DatagramStatus SendOrQueueDatagram(
+      absl::string_view datagram) override;
   QuicByteCount GetMaxDatagramSize() const override;
-  void SetDatagramMaxTimeInQueue(QuicTime::Delta max_time_in_queue) override;
+  void SetDatagramMaxTimeInQueue(absl::Duration max_time_in_queue) override;
 
   // From QuicSpdyStream::Http3DatagramVisitor.
   void OnHttp3Datagram(QuicStreamId stream_id,
diff --git a/quiche/quic/core/http/web_transport_stream_adapter.cc b/quiche/quic/core/http/web_transport_stream_adapter.cc
index b6eca7b..24d7bf5 100644
--- a/quiche/quic/core/http/web_transport_stream_adapter.cc
+++ b/quiche/quic/core/http/web_transport_stream_adapter.cc
@@ -6,7 +6,9 @@
 
 #include "quiche/quic/core/http/web_transport_http3.h"
 #include "quiche/quic/core/quic_error_codes.h"
+#include "quiche/quic/core/quic_types.h"
 #include "quiche/common/platform/api/quiche_mem_slice.h"
+#include "quiche/web_transport/web_transport.h"
 
 namespace quic {
 
@@ -15,10 +17,10 @@
     : session_(session), stream_(stream), sequencer_(sequencer) {}
 
 WebTransportStream::ReadResult WebTransportStreamAdapter::Read(
-    char* buffer, size_t buffer_size) {
+    absl::Span<char> buffer) {
   iovec iov;
-  iov.iov_base = buffer;
-  iov.iov_len = buffer_size;
+  iov.iov_base = buffer.data();
+  iov.iov_len = buffer.size();
   const size_t result = sequencer_->Readv(&iov, 1);
   if (!fin_read_ && sequencer_->IsClosed()) {
     fin_read_ = true;
@@ -32,7 +34,8 @@
   const size_t old_size = output->size();
   const size_t bytes_to_read = ReadableBytes();
   output->resize(old_size + bytes_to_read);
-  ReadResult result = Read(&(*output)[old_size], bytes_to_read);
+  ReadResult result =
+      Read(absl::Span<char>(&(*output)[old_size], bytes_to_read));
   QUICHE_DCHECK_EQ(bytes_to_read, result.bytes_read);
   output->resize(old_size + result.bytes_read);
   return result;
diff --git a/quiche/quic/core/http/web_transport_stream_adapter.h b/quiche/quic/core/http/web_transport_stream_adapter.h
index 7e8eeea..621120b 100644
--- a/quiche/quic/core/http/web_transport_stream_adapter.h
+++ b/quiche/quic/core/http/web_transport_stream_adapter.h
@@ -10,6 +10,7 @@
 #include "quiche/quic/core/quic_stream_sequencer.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/quic/core/web_transport_interface.h"
+#include "quiche/web_transport/web_transport.h"
 
 namespace quic {
 
@@ -22,8 +23,7 @@
                             QuicStreamSequencer* sequencer);
 
   // WebTransportStream implementation.
-  ABSL_MUST_USE_RESULT ReadResult Read(char* buffer,
-                                       size_t buffer_size) override;
+  ABSL_MUST_USE_RESULT ReadResult Read(absl::Span<char> output) override;
   ABSL_MUST_USE_RESULT ReadResult Read(std::string* output) override;
   ABSL_MUST_USE_RESULT bool Write(absl::string_view data) override;
   ABSL_MUST_USE_RESULT bool SendFin() override;
diff --git a/quiche/quic/core/quic_time.h b/quiche/quic/core/quic_time.h
index 21bad68..a148888 100644
--- a/quiche/quic/core/quic_time.h
+++ b/quiche/quic/core/quic_time.h
@@ -19,6 +19,7 @@
 #include <ostream>
 #include <string>
 
+#include "absl/time/time.h"
 #include "quiche/quic/platform/api/quic_export.h"
 
 // TODO(vasilvv): replace with ABSL_MUST_USE_RESULT once we're using absl.
@@ -60,6 +61,14 @@
     // Converts a number of microseconds to a time offset.
     static constexpr Delta FromMicroseconds(int64_t us) { return Delta(us); }
 
+    // Converts from Abseil duration type.
+    static constexpr Delta FromAbsl(absl::Duration duration) {
+      if (ABSL_PREDICT_FALSE(duration == absl::InfiniteDuration())) {
+        return Infinite();
+      }
+      return Delta(absl::ToInt64Microseconds(duration));
+    }
+
     // Converts the time offset to a rounded number of seconds.
     constexpr int64_t ToSeconds() const { return time_offset_ / 1000 / 1000; }
 
@@ -69,6 +78,14 @@
     // Converts the time offset to a rounded number of microseconds.
     constexpr int64_t ToMicroseconds() const { return time_offset_; }
 
+    // Converts the time offset to an Abseil duration.
+    constexpr absl::Duration ToAbsl() {
+      if (ABSL_PREDICT_FALSE(IsInfinite())) {
+        return absl::InfiniteDuration();
+      }
+      return absl::Microseconds(time_offset_);
+    }
+
     constexpr bool IsZero() const { return time_offset_ == 0; }
 
     constexpr bool IsInfinite() const {
diff --git a/quiche/quic/core/web_transport_interface.h b/quiche/quic/core/web_transport_interface.h
index bfccf7d..f87768c 100644
--- a/quiche/quic/core/web_transport_interface.h
+++ b/quiche/quic/core/web_transport_interface.h
@@ -8,145 +8,41 @@
 #ifndef QUICHE_QUIC_CORE_WEB_TRANSPORT_INTERFACE_H_
 #define QUICHE_QUIC_CORE_WEB_TRANSPORT_INTERFACE_H_
 
-#include <cstddef>
-#include <memory>
-
-#include "absl/base/attributes.h"
-#include "absl/strings/string_view.h"
-#include "quiche/quic/core/quic_datagram_queue.h"
 #include "quiche/quic/core/quic_types.h"
-#include "quiche/quic/platform/api/quic_export.h"
-#include "quiche/common/platform/api/quiche_mem_slice.h"
-#include "quiche/spdy/core/http2_header_block.h"
+#include "quiche/web_transport/web_transport.h"
 
 namespace quic {
 
-// Visitor that gets notified about events related to a WebTransport stream.
-class QUIC_EXPORT_PRIVATE WebTransportStreamVisitor {
- public:
-  virtual ~WebTransportStreamVisitor() {}
+using WebTransportSessionError = webtransport::SessionErrorCode;
+using WebTransportStreamError = webtransport::StreamErrorCode;
 
-  // Called whenever the stream has readable data available.
-  virtual void OnCanRead() = 0;
-  // Called whenever the stream is not write-blocked and can accept new data.
-  virtual void OnCanWrite() = 0;
+using WebTransportStreamVisitor = webtransport::StreamVisitor;
+using WebTransportStream = webtransport::Stream;
+using WebTransportVisitor = webtransport::SessionVisitor;
+using WebTransportSession = webtransport::Session;
 
-  // Called when RESET_STREAM is received for the stream.
-  virtual void OnResetStreamReceived(WebTransportStreamError error) = 0;
-  // Called when STOP_SENDING is received for the stream.
-  virtual void OnStopSendingReceived(WebTransportStreamError error) = 0;
-  // Called when the write side of the stream is closed and all of the data sent
-  // has been acknowledged ("Data Recvd" state of RFC 9000).
-  virtual void OnWriteSideInDataRecvdState() = 0;
-};
-
-// A stream (either bidirectional or unidirectional) that is contained within a
-// WebTransport session.
-class QUIC_EXPORT_PRIVATE WebTransportStream {
- public:
-  struct QUIC_EXPORT_PRIVATE ReadResult {
-    // Number of bytes actually read.
-    size_t bytes_read;
-    // Whether the FIN has been received; if true, no further data will arrive
-    // on the stream, and the stream object can be soon potentially garbage
-    // collected.
-    bool fin;
-  };
-
-  virtual ~WebTransportStream() {}
-
-  // Reads at most |buffer_size| bytes into |buffer|.
-  ABSL_MUST_USE_RESULT virtual ReadResult Read(char* buffer,
-                                               size_t buffer_size) = 0;
-  // Reads all available data and appends it to the end of |output|.
-  ABSL_MUST_USE_RESULT virtual ReadResult Read(std::string* output) = 0;
-  // Writes |data| into the stream.  Returns true on success.
-  ABSL_MUST_USE_RESULT virtual bool Write(absl::string_view data) = 0;
-  // Sends the FIN on the stream.  Returns true on success.
-  ABSL_MUST_USE_RESULT virtual bool SendFin() = 0;
-
-  // Indicates whether it is possible to write into stream right now.
-  virtual bool CanWrite() const = 0;
-  // Indicates the number of bytes that can be read from the stream.
-  virtual size_t ReadableBytes() const = 0;
-
-  // An ID that is unique within the session.  Those are not exposed to the user
-  // via the web API, but can be used internally for bookkeeping and
-  // diagnostics.
-  virtual QuicStreamId GetStreamId() const = 0;
-
-  // Resets the stream with the specified error code.
-  virtual void ResetWithUserCode(WebTransportStreamError error) = 0;
-  virtual void ResetDueToInternalError() = 0;
-  virtual void SendStopSending(WebTransportStreamError error) = 0;
-  // Called when the owning object has been garbage-collected.
-  virtual void MaybeResetDueToStreamObjectGone() = 0;
-
-  virtual WebTransportStreamVisitor* visitor() = 0;
-  virtual void SetVisitor(
-      std::unique_ptr<WebTransportStreamVisitor> visitor) = 0;
-};
-
-// Visitor that gets notified about events related to a WebTransport session.
-class QUIC_EXPORT_PRIVATE WebTransportVisitor {
- public:
-  virtual ~WebTransportVisitor() {}
-
-  // Notifies the visitor when the session is ready to exchange application
-  // data.
-  virtual void OnSessionReady(const spdy::Http2HeaderBlock& headers) = 0;
-
-  // Notifies the visitor when the session has been closed.
-  virtual void OnSessionClosed(WebTransportSessionError error_code,
-                               const std::string& error_message) = 0;
-
-  // Notifies the visitor when a new stream has been received.  The stream in
-  // question can be retrieved using AcceptIncomingBidirectionalStream() or
-  // AcceptIncomingUnidirectionalStream().
-  virtual void OnIncomingBidirectionalStreamAvailable() = 0;
-  virtual void OnIncomingUnidirectionalStreamAvailable() = 0;
-
-  // Notifies the visitor when a new datagram has been received.
-  virtual void OnDatagramReceived(absl::string_view datagram) = 0;
-
-  // Notifies the visitor that a new outgoing stream can now be created.
-  virtual void OnCanCreateNewOutgoingBidirectionalStream() = 0;
-  virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0;
-};
-
-// An abstract interface for a WebTransport session.
-class QUIC_EXPORT_PRIVATE WebTransportSession {
- public:
-  virtual ~WebTransportSession() {}
-
-  // Closes the WebTransport session in question with the specified |error_code|
-  // and |error_message|.
-  virtual void CloseSession(WebTransportSessionError error_code,
-                            absl::string_view error_message) = 0;
-
-  // Return the earliest incoming stream that has been received by the session
-  // but has not been accepted.  Returns nullptr if there are no incoming
-  // streams.
-  virtual WebTransportStream* AcceptIncomingBidirectionalStream() = 0;
-  virtual WebTransportStream* AcceptIncomingUnidirectionalStream() = 0;
-
-  // Returns true if flow control allows opening a new stream.
-  virtual bool CanOpenNextOutgoingBidirectionalStream() = 0;
-  virtual bool CanOpenNextOutgoingUnidirectionalStream() = 0;
-  // Opens a new WebTransport stream, or returns nullptr if that is not possible
-  // due to flow control.
-  virtual WebTransportStream* OpenOutgoingBidirectionalStream() = 0;
-  virtual WebTransportStream* OpenOutgoingUnidirectionalStream() = 0;
-
-  virtual MessageStatus SendOrQueueDatagram(
-      quiche::QuicheMemSlice datagram) = 0;
-  // Returns a conservative estimate of the largest datagram size that the
-  // session would be able to send.
-  virtual QuicByteCount GetMaxDatagramSize() const = 0;
-  // Sets the largest duration that a datagram can spend in the queue before
-  // being silently dropped.
-  virtual void SetDatagramMaxTimeInQueue(QuicTime::Delta max_time_in_queue) = 0;
-};
+inline webtransport::DatagramStatus MessageStatusToWebTransportStatus(
+    MessageStatus status) {
+  switch (status) {
+    case MESSAGE_STATUS_SUCCESS:
+      return webtransport::DatagramStatus(
+          webtransport::DatagramStatusCode::kSuccess, "");
+    case MESSAGE_STATUS_BLOCKED:
+      return webtransport::DatagramStatus(
+          webtransport::DatagramStatusCode::kBlocked,
+          "QUIC connection write-blocked");
+    case MESSAGE_STATUS_TOO_LARGE:
+      return webtransport::DatagramStatus(
+          webtransport::DatagramStatusCode::kTooBig,
+          "Datagram payload exceeded maximum allowed size");
+    case MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED:
+    case MESSAGE_STATUS_INTERNAL_ERROR:
+    case MESSAGE_STATUS_UNSUPPORTED:
+      return webtransport::DatagramStatus(
+          webtransport::DatagramStatusCode::kInternalError,
+          absl::StrCat("Internal error: ", MessageStatusToString(status)));
+  }
+}
 
 }  // namespace quic
 
diff --git a/quiche/quic/tools/web_transport_test_visitors.h b/quiche/quic/tools/web_transport_test_visitors.h
index 368e53a..c311ff4 100644
--- a/quiche/quic/tools/web_transport_test_visitors.h
+++ b/quiche/quic/tools/web_transport_test_visitors.h
@@ -224,9 +224,7 @@
   }
 
   void OnDatagramReceived(absl::string_view datagram) override {
-    quiche::QuicheMemSlice slice(
-        quiche::QuicheBuffer::Copy(&allocator_, datagram));
-    session_->SendOrQueueDatagram(std::move(slice));
+    session_->SendOrQueueDatagram(datagram);
   }
 
   void OnCanCreateNewOutgoingBidirectionalStream() override {