• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_QUIC_CORE_HTTP_WEB_TRANSPORT_HTTP3_H_
6 #define QUICHE_QUIC_CORE_HTTP_WEB_TRANSPORT_HTTP3_H_
7 
8 #include <memory>
9 
10 #include "absl/base/attributes.h"
11 #include "absl/container/flat_hash_set.h"
12 #include "absl/time/time.h"
13 #include "absl/types/optional.h"
14 #include "quiche/quic/core/http/quic_spdy_session.h"
15 #include "quiche/quic/core/http/web_transport_stream_adapter.h"
16 #include "quiche/quic/core/quic_error_codes.h"
17 #include "quiche/quic/core/quic_stream.h"
18 #include "quiche/quic/core/quic_types.h"
19 #include "quiche/quic/core/web_transport_interface.h"
20 #include "quiche/common/platform/api/quiche_mem_slice.h"
21 #include "quiche/web_transport/web_transport.h"
22 #include "quiche/spdy/core/http2_header_block.h"
23 
24 namespace quic {
25 
26 class QuicSpdySession;
27 class QuicSpdyStream;
28 
29 enum class WebTransportHttp3RejectionReason {
30   kNone,
31   kNoStatusCode,
32   kWrongStatusCode,
33   kMissingDraftVersion,
34   kUnsupportedDraftVersion,
35 };
36 
37 // A session of WebTransport over HTTP/3.  The session is owned by
38 // QuicSpdyStream object for the CONNECT stream that established it.
39 //
40 // WebTransport over HTTP/3 specification:
41 // <https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3>
42 class QUIC_EXPORT_PRIVATE WebTransportHttp3
43     : public WebTransportSession,
44       public QuicSpdyStream::Http3DatagramVisitor {
45  public:
46   WebTransportHttp3(QuicSpdySession* session, QuicSpdyStream* connect_stream,
47                     WebTransportSessionId id);
48 
49   void HeadersReceived(const spdy::Http2HeaderBlock& headers);
SetVisitor(std::unique_ptr<WebTransportVisitor> visitor)50   void SetVisitor(std::unique_ptr<WebTransportVisitor> visitor) {
51     visitor_ = std::move(visitor);
52   }
53 
id()54   WebTransportSessionId id() { return id_; }
ready()55   bool ready() { return ready_; }
56 
57   void AssociateStream(QuicStreamId stream_id);
OnStreamClosed(QuicStreamId stream_id)58   void OnStreamClosed(QuicStreamId stream_id) { streams_.erase(stream_id); }
59   void OnConnectStreamClosing();
60 
NumberOfAssociatedStreams()61   size_t NumberOfAssociatedStreams() { return streams_.size(); }
62 
63   void CloseSession(WebTransportSessionError error_code,
64                     absl::string_view error_message) override;
65   void OnCloseReceived(WebTransportSessionError error_code,
66                        absl::string_view error_message);
67   void OnConnectStreamFinReceived();
68 
69   // It is legal for WebTransport to be closed without a
70   // CLOSE_WEBTRANSPORT_SESSION capsule.  We always send a capsule, but we still
71   // need to ensure we handle this case correctly.
72   void CloseSessionWithFinOnlyForTests();
73 
74   // Return the earliest incoming stream that has been received by the session
75   // but has not been accepted.  Returns nullptr if there are no incoming
76   // streams.
77   WebTransportStream* AcceptIncomingBidirectionalStream() override;
78   WebTransportStream* AcceptIncomingUnidirectionalStream() override;
79 
80   bool CanOpenNextOutgoingBidirectionalStream() override;
81   bool CanOpenNextOutgoingUnidirectionalStream() override;
82   WebTransportStream* OpenOutgoingBidirectionalStream() override;
83   WebTransportStream* OpenOutgoingUnidirectionalStream() override;
84 
85   webtransport::Stream* GetStreamById(webtransport::StreamId id) override;
86 
87   webtransport::DatagramStatus SendOrQueueDatagram(
88       absl::string_view datagram) override;
89   QuicByteCount GetMaxDatagramSize() const override;
90   void SetDatagramMaxTimeInQueue(absl::Duration max_time_in_queue) override;
91 
92   // From QuicSpdyStream::Http3DatagramVisitor.
93   void OnHttp3Datagram(QuicStreamId stream_id,
94                        absl::string_view payload) override;
OnUnknownCapsule(QuicStreamId,const quiche::UnknownCapsule &)95   void OnUnknownCapsule(QuicStreamId /*stream_id*/,
96                         const quiche::UnknownCapsule& /*capsule*/) override {}
97 
close_received()98   bool close_received() const { return close_received_; }
rejection_reason()99   WebTransportHttp3RejectionReason rejection_reason() const {
100     return rejection_reason_;
101   }
102 
103  private:
104   // Notifies the visitor that the connection has been closed.  Ensures that the
105   // visitor is only ever called once.
106   void MaybeNotifyClose();
107 
108   QuicSpdySession* const session_;        // Unowned.
109   QuicSpdyStream* const connect_stream_;  // Unowned.
110   const WebTransportSessionId id_;
111   // |ready_| is set to true when the peer has seen both sets of headers.
112   bool ready_ = false;
113   std::unique_ptr<WebTransportVisitor> visitor_;
114   absl::flat_hash_set<QuicStreamId> streams_;
115   quiche::QuicheCircularDeque<QuicStreamId> incoming_bidirectional_streams_;
116   quiche::QuicheCircularDeque<QuicStreamId> incoming_unidirectional_streams_;
117 
118   bool close_sent_ = false;
119   bool close_received_ = false;
120   bool close_notified_ = false;
121 
122   WebTransportHttp3RejectionReason rejection_reason_ =
123       WebTransportHttp3RejectionReason::kNone;
124   // Those are set to default values, which are used if the session is not
125   // closed cleanly using an appropriate capsule.
126   WebTransportSessionError error_code_ = 0;
127   std::string error_message_ = "";
128 };
129 
130 class QUIC_EXPORT_PRIVATE WebTransportHttp3UnidirectionalStream
131     : public QuicStream {
132  public:
133   // Incoming stream.
134   WebTransportHttp3UnidirectionalStream(PendingStream* pending,
135                                         QuicSpdySession* session);
136   // Outgoing stream.
137   WebTransportHttp3UnidirectionalStream(QuicStreamId id,
138                                         QuicSpdySession* session,
139                                         WebTransportSessionId session_id);
140 
141   // Sends the stream type and the session ID on the stream.
142   void WritePreamble();
143 
144   // Implementation of QuicStream.
145   void OnDataAvailable() override;
146   void OnCanWriteNewData() override;
147   void OnClose() override;
148   void OnStreamReset(const QuicRstStreamFrame& frame) override;
149   bool OnStopSending(QuicResetStreamError error) override;
150   void OnWriteSideInDataRecvdState() override;
151 
interface()152   WebTransportStream* interface() { return &adapter_; }
SetUnblocked()153   void SetUnblocked() { sequencer()->SetUnblocked(); }
154 
155  private:
156   QuicSpdySession* session_;
157   WebTransportStreamAdapter adapter_;
158   absl::optional<WebTransportSessionId> session_id_;
159   bool needs_to_send_preamble_;
160 
161   bool ReadSessionId();
162   // Closes the stream if all of the data has been received.
163   void MaybeCloseIncompleteStream();
164 };
165 
166 // Remaps HTTP/3 error code into a WebTransport error code.  Returns nullopt if
167 // the provided code is outside of valid range.
168 QUIC_EXPORT_PRIVATE absl::optional<WebTransportStreamError>
169 Http3ErrorToWebTransport(uint64_t http3_error_code);
170 
171 // Same as above, but returns default error value (zero) when none could be
172 // mapped.
173 QUIC_EXPORT_PRIVATE WebTransportStreamError
174 Http3ErrorToWebTransportOrDefault(uint64_t http3_error_code);
175 
176 // Remaps WebTransport error code into an HTTP/3 error code.
177 QUIC_EXPORT_PRIVATE uint64_t
178 WebTransportErrorToHttp3(WebTransportStreamError webtransport_error_code);
179 
180 }  // namespace quic
181 
182 #endif  // QUICHE_QUIC_CORE_HTTP_WEB_TRANSPORT_HTTP3_H_
183