• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 // The base class for streams which deliver data to/from an application.
6 // In each direction, the data on such a stream first contains compressed
7 // headers then body data.
8 
9 #ifndef QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_H_
10 #define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_H_
11 
12 #include <sys/types.h>
13 
14 #include <cstddef>
15 #include <list>
16 #include <memory>
17 #include <string>
18 
19 #include "absl/base/attributes.h"
20 #include "absl/strings/string_view.h"
21 #include "absl/types/span.h"
22 #include "quiche/quic/core/http/http_decoder.h"
23 #include "quiche/quic/core/http/http_encoder.h"
24 #include "quiche/quic/core/http/quic_header_list.h"
25 #include "quiche/quic/core/http/quic_spdy_stream_body_manager.h"
26 #include "quiche/quic/core/http/web_transport_stream_adapter.h"
27 #include "quiche/quic/core/qpack/qpack_decoded_headers_accumulator.h"
28 #include "quiche/quic/core/quic_error_codes.h"
29 #include "quiche/quic/core/quic_packets.h"
30 #include "quiche/quic/core/quic_session.h"
31 #include "quiche/quic/core/quic_stream.h"
32 #include "quiche/quic/core/quic_stream_priority.h"
33 #include "quiche/quic/core/quic_stream_sequencer.h"
34 #include "quiche/quic/core/quic_types.h"
35 #include "quiche/quic/core/web_transport_interface.h"
36 #include "quiche/quic/platform/api/quic_export.h"
37 #include "quiche/quic/platform/api/quic_flags.h"
38 #include "quiche/quic/platform/api/quic_socket_address.h"
39 #include "quiche/common/capsule.h"
40 #include "quiche/common/platform/api/quiche_mem_slice.h"
41 #include "quiche/spdy/core/http2_header_block.h"
42 #include "quiche/spdy/core/spdy_framer.h"
43 
44 namespace quic {
45 
46 namespace test {
47 class QuicSpdyStreamPeer;
48 class QuicStreamPeer;
49 }  // namespace test
50 
51 class QuicSpdySession;
52 class WebTransportHttp3;
53 
54 // A QUIC stream that can send and receive HTTP2 (SPDY) headers.
55 class QUIC_EXPORT_PRIVATE QuicSpdyStream
56     : public QuicStream,
57       public quiche::CapsuleParser::Visitor,
58       public QpackDecodedHeadersAccumulator::Visitor {
59  public:
60   // Visitor receives callbacks from the stream.
61   class QUIC_EXPORT_PRIVATE Visitor {
62    public:
Visitor()63     Visitor() {}
64     Visitor(const Visitor&) = delete;
65     Visitor& operator=(const Visitor&) = delete;
66 
67     // Called when the stream is closed.
68     virtual void OnClose(QuicSpdyStream* stream) = 0;
69 
70     // Allows subclasses to override and do work.
OnPromiseHeadersComplete(QuicStreamId,size_t)71     virtual void OnPromiseHeadersComplete(QuicStreamId /*promised_id*/,
72                                           size_t /*frame_len*/) {}
73 
74    protected:
~Visitor()75     virtual ~Visitor() {}
76   };
77 
78   QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session,
79                  StreamType type);
80   QuicSpdyStream(PendingStream* pending, QuicSpdySession* spdy_session);
81   QuicSpdyStream(const QuicSpdyStream&) = delete;
82   QuicSpdyStream& operator=(const QuicSpdyStream&) = delete;
83   ~QuicSpdyStream() override;
84 
85   // QuicStream implementation
86   void OnClose() override;
87 
88   // Override to maybe close the write side after writing.
89   void OnCanWrite() override;
90 
91   // Called by the session when headers with a priority have been received
92   // for this stream.  This method will only be called for server streams.
93   virtual void OnStreamHeadersPriority(
94       const spdy::SpdyStreamPrecedence& precedence);
95 
96   // Called by the session when decompressed headers have been completely
97   // delivered to this stream.  If |fin| is true, then this stream
98   // should be closed; no more data will be sent by the peer.
99   virtual void OnStreamHeaderList(bool fin, size_t frame_len,
100                                   const QuicHeaderList& header_list);
101 
102   // Called by the session when decompressed push promise headers have
103   // been completely delivered to this stream.
104   virtual void OnPromiseHeaderList(QuicStreamId promised_id, size_t frame_len,
105                                    const QuicHeaderList& header_list);
106 
107   // Called by the session when a PRIORITY frame has been been received for this
108   // stream. This method will only be called for server streams.
109   void OnPriorityFrame(const spdy::SpdyStreamPrecedence& precedence);
110 
111   // Override the base class to not discard response when receiving
112   // QUIC_STREAM_NO_ERROR.
113   void OnStreamReset(const QuicRstStreamFrame& frame) override;
114   void ResetWithError(QuicResetStreamError error) override;
115   bool OnStopSending(QuicResetStreamError error) override;
116 
117   // Called by the sequencer when new data is available. Decodes the data and
118   // calls OnBodyAvailable() to pass to the upper layer.
119   void OnDataAvailable() override;
120 
121   // Called in OnDataAvailable() after it finishes the decoding job.
122   virtual void OnBodyAvailable() = 0;
123 
124   // Writes the headers contained in |header_block| on the dedicated headers
125   // stream or on this stream, depending on VersionUsesHttp3().  Returns the
126   // number of bytes sent, including data sent on the encoder stream when using
127   // QPACK.
128   virtual size_t WriteHeaders(
129       spdy::Http2HeaderBlock header_block, bool fin,
130       quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
131           ack_listener);
132 
133   // Sends |data| to the peer, or buffers if it can't be sent immediately.
134   virtual void WriteOrBufferBody(absl::string_view data, bool fin);
135 
136   // Writes the trailers contained in |trailer_block| on the dedicated headers
137   // stream or on this stream, depending on VersionUsesHttp3().  Trailers will
138   // always have the FIN flag set.  Returns the number of bytes sent, including
139   // data sent on the encoder stream when using QPACK.
140   virtual size_t WriteTrailers(
141       spdy::Http2HeaderBlock trailer_block,
142       quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
143           ack_listener);
144 
145   // Override to report newly acked bytes via ack_listener_.
146   bool OnStreamFrameAcked(QuicStreamOffset offset, QuicByteCount data_length,
147                           bool fin_acked, QuicTime::Delta ack_delay_time,
148                           QuicTime receive_timestamp,
149                           QuicByteCount* newly_acked_length) override;
150 
151   // Override to report bytes retransmitted via ack_listener_.
152   void OnStreamFrameRetransmitted(QuicStreamOffset offset,
153                                   QuicByteCount data_length,
154                                   bool fin_retransmitted) override;
155 
156   // Does the same thing as WriteOrBufferBody except this method takes iovec
157   // as the data input. Right now it only calls WritevData.
158   QuicConsumedData WritevBody(const struct iovec* iov, int count, bool fin);
159 
160   // Does the same thing as WriteOrBufferBody except this method takes
161   // memslicespan as the data input. Right now it only calls WriteMemSlices.
162   QuicConsumedData WriteBodySlices(absl::Span<quiche::QuicheMemSlice> slices,
163                                    bool fin);
164 
165   // Marks the trailers as consumed. This applies to the case where this object
166   // receives headers and trailers as QuicHeaderLists via calls to
167   // OnStreamHeaderList(). Trailer data will be consumed from the sequencer only
168   // once all body data has been consumed.
169   void MarkTrailersConsumed();
170 
171   // Clears |header_list_|.
172   void ConsumeHeaderList();
173 
174   // This block of functions wraps the sequencer's functions of the same
175   // name.  These methods return uncompressed data until that has
176   // been fully processed.  Then they simply delegate to the sequencer.
177   virtual size_t Readv(const struct iovec* iov, size_t iov_len);
178   virtual int GetReadableRegions(iovec* iov, size_t iov_len) const;
179   void MarkConsumed(size_t num_bytes);
180 
181   // Returns true if header contains a valid 3-digit status and parse the status
182   // code to |status_code|.
183   static bool ParseHeaderStatusCode(const spdy::Http2HeaderBlock& header,
184                                     int* status_code);
185   // Returns true if status_value (associated with :status) contains a valid
186   // 3-digit status and parse the status code to |status_code|.
187   static bool ParseHeaderStatusCode(absl::string_view status_value,
188                                     int* status_code);
189 
190   // Returns true when all data from the peer has been read and consumed,
191   // including the fin.
192   bool IsDoneReading() const;
193   bool HasBytesToRead() const;
194 
set_visitor(Visitor * visitor)195   void set_visitor(Visitor* visitor) { visitor_ = visitor; }
196 
headers_decompressed()197   bool headers_decompressed() const { return headers_decompressed_; }
198 
199   // Returns total amount of body bytes that have been read.
200   uint64_t total_body_bytes_read() const;
201 
header_list()202   const QuicHeaderList& header_list() const { return header_list_; }
203 
trailers_decompressed()204   bool trailers_decompressed() const { return trailers_decompressed_; }
205 
206   // Returns whatever trailers have been received for this stream.
received_trailers()207   const spdy::Http2HeaderBlock& received_trailers() const {
208     return received_trailers_;
209   }
210 
211   // Returns true if headers have been fully read and consumed.
212   bool FinishedReadingHeaders() const;
213 
214   // Returns true if FIN has been received and either trailers have been fully
215   // read and consumed or there are no trailers.
216   bool FinishedReadingTrailers() const;
217 
218   // Returns true if the sequencer has delivered the FIN, and no more body bytes
219   // will be available.
IsSequencerClosed()220   bool IsSequencerClosed() { return sequencer()->IsClosed(); }
221 
222   // QpackDecodedHeadersAccumulator::Visitor implementation.
223   void OnHeadersDecoded(QuicHeaderList headers,
224                         bool header_list_size_limit_exceeded) override;
225   void OnHeaderDecodingError(QuicErrorCode error_code,
226                              absl::string_view error_message) override;
227 
spdy_session()228   QuicSpdySession* spdy_session() const { return spdy_session_; }
229 
230   // Send PRIORITY_UPDATE frame and update |last_sent_priority_| if
231   // |last_sent_priority_| is different from current priority.
232   void MaybeSendPriorityUpdateFrame() override;
233 
234   // Returns the WebTransport session owned by this stream, if one exists.
web_transport()235   WebTransportHttp3* web_transport() { return web_transport_.get(); }
236 
237   // Returns the WebTransport data stream associated with this QUIC stream, or
238   // null if this is not a WebTransport data stream.
web_transport_stream()239   WebTransportStream* web_transport_stream() {
240     if (web_transport_data_ == nullptr) {
241       return nullptr;
242     }
243     return &web_transport_data_->adapter;
244   }
245 
246   // Sends a WEBTRANSPORT_STREAM frame and sets up the appropriate metadata.
247   void ConvertToWebTransportDataStream(WebTransportSessionId session_id);
248 
249   void OnCanWriteNewData() override;
250 
251   // If this stream is a WebTransport data stream, closes the connection with an
252   // error, and returns false.
253   bool AssertNotWebTransportDataStream(absl::string_view operation);
254 
255   // Indicates whether a call to WriteBodySlices will be successful and not
256   // rejected due to buffer being full.  |write_size| must be non-zero.
257   bool CanWriteNewBodyData(QuicByteCount write_size) const;
258 
259   // From CapsuleParser::Visitor.
260   bool OnCapsule(const quiche::Capsule& capsule) override;
261   void OnCapsuleParseFailure(absl::string_view error_message) override;
262 
263   // Sends an HTTP/3 datagram. The stream ID is not part of |payload|. Virtual
264   // to allow mocking in tests.
265   virtual MessageStatus SendHttp3Datagram(absl::string_view payload);
266 
267   class QUIC_EXPORT_PRIVATE Http3DatagramVisitor {
268    public:
~Http3DatagramVisitor()269     virtual ~Http3DatagramVisitor() {}
270 
271     // Called when an HTTP/3 datagram is received. |payload| does not contain
272     // the stream ID.
273     virtual void OnHttp3Datagram(QuicStreamId stream_id,
274                                  absl::string_view payload) = 0;
275 
276     // Called when a Capsule with an unknown type is received.
277     virtual void OnUnknownCapsule(QuicStreamId stream_id,
278                                   const quiche::UnknownCapsule& capsule) = 0;
279   };
280 
281   // Registers |visitor| to receive HTTP/3 datagrams and enables Capsule
282   // Protocol by registering a CapsuleParser. |visitor| must be valid until a
283   // corresponding call to UnregisterHttp3DatagramVisitor.
284   void RegisterHttp3DatagramVisitor(Http3DatagramVisitor* visitor);
285 
286   // Unregisters an HTTP/3 datagram visitor. Must only be called after a call to
287   // RegisterHttp3DatagramVisitor.
288   void UnregisterHttp3DatagramVisitor();
289 
290   // Replaces the current HTTP/3 datagram visitor with a different visitor.
291   // Mainly meant to be used by the visitors' move operators.
292   void ReplaceHttp3DatagramVisitor(Http3DatagramVisitor* visitor);
293 
294   class QUIC_EXPORT_PRIVATE ConnectIpVisitor {
295    public:
~ConnectIpVisitor()296     virtual ~ConnectIpVisitor() {}
297 
298     virtual bool OnAddressAssignCapsule(
299         const quiche::AddressAssignCapsule& capsule) = 0;
300     virtual bool OnAddressRequestCapsule(
301         const quiche::AddressRequestCapsule& capsule) = 0;
302     virtual bool OnRouteAdvertisementCapsule(
303         const quiche::RouteAdvertisementCapsule& capsule) = 0;
304     virtual void OnHeadersWritten() = 0;
305   };
306 
307   // Registers |visitor| to receive CONNECT-IP capsules. |visitor| must be
308   // valid until a corresponding call to UnregisterConnectIpVisitor.
309   void RegisterConnectIpVisitor(ConnectIpVisitor* visitor);
310 
311   // Unregisters a CONNECT-IP visitor. Must only be called after a call to
312   // RegisterConnectIpVisitor.
313   void UnregisterConnectIpVisitor();
314 
315   // Replaces the current CONNECT-IP visitor with a different visitor.
316   // Mainly meant to be used by the visitors' move operators.
317   void ReplaceConnectIpVisitor(ConnectIpVisitor* visitor);
318 
319   // Sets max datagram time in queue.
320   void SetMaxDatagramTimeInQueue(QuicTime::Delta max_time_in_queue);
321 
322   void OnDatagramReceived(QuicDataReader* reader);
323 
324   QuicByteCount GetMaxDatagramSize() const;
325 
326   // Writes |capsule| onto the DATA stream.
327   void WriteCapsule(const quiche::Capsule& capsule, bool fin = false);
328 
329   void WriteGreaseCapsule();
330 
331  protected:
332   // Called when the received headers are too large. By default this will
333   // reset the stream.
334   virtual void OnHeadersTooLarge();
335 
336   virtual void OnInitialHeadersComplete(bool fin, size_t frame_len,
337                                         const QuicHeaderList& header_list);
338   virtual void OnTrailingHeadersComplete(bool fin, size_t frame_len,
339                                          const QuicHeaderList& header_list);
340   virtual size_t WriteHeadersImpl(
341       spdy::Http2HeaderBlock header_block, bool fin,
342       quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
343           ack_listener);
344 
345   virtual bool CopyAndValidateTrailers(const QuicHeaderList& header_list,
346                                        bool expect_final_byte_offset,
347                                        size_t* final_byte_offset,
348                                        spdy::Http2HeaderBlock* trailers);
349 
visitor()350   Visitor* visitor() { return visitor_; }
351 
set_headers_decompressed(bool val)352   void set_headers_decompressed(bool val) { headers_decompressed_ = val; }
353 
set_ack_listener(quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> ack_listener)354   void set_ack_listener(
355       quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface>
356           ack_listener) {
357     ack_listener_ = std::move(ack_listener);
358   }
359 
360   void OnWriteSideInDataRecvdState() override;
361 
362   virtual bool AreHeadersValid(const QuicHeaderList& header_list) const;
363   // TODO(b/202433856) Merge AreHeaderFieldValueValid into AreHeadersValid once
364   // all flags guarding the behavior of AreHeadersValid has been rolled out.
365   virtual bool AreHeaderFieldValuesValid(
366       const QuicHeaderList& header_list) const;
367 
368   // Reset stream upon invalid request headers.
369   virtual void OnInvalidHeaders();
370 
371  private:
372   friend class test::QuicSpdyStreamPeer;
373   friend class test::QuicStreamPeer;
374   friend class QuicStreamUtils;
375   class HttpDecoderVisitor;
376 
377   struct QUIC_EXPORT_PRIVATE WebTransportDataStream {
378     WebTransportDataStream(QuicSpdyStream* stream,
379                            WebTransportSessionId session_id);
380 
381     WebTransportSessionId session_id;
382     WebTransportStreamAdapter adapter;
383   };
384 
385   // Called by HttpDecoderVisitor.
386   bool OnDataFrameStart(QuicByteCount header_length,
387                         QuicByteCount payload_length);
388   bool OnDataFramePayload(absl::string_view payload);
389   bool OnDataFrameEnd();
390   bool OnHeadersFrameStart(QuicByteCount header_length,
391                            QuicByteCount payload_length);
392   bool OnHeadersFramePayload(absl::string_view payload);
393   bool OnHeadersFrameEnd();
394   void OnWebTransportStreamFrameType(QuicByteCount header_length,
395                                      WebTransportSessionId session_id);
396   bool OnUnknownFrameStart(uint64_t frame_type, QuicByteCount header_length,
397                            QuicByteCount payload_length);
398   bool OnUnknownFramePayload(absl::string_view payload);
399   bool OnUnknownFrameEnd();
400 
401   // Given the interval marked by [|offset|, |offset| + |data_length|), return
402   // the number of frame header bytes contained in it.
403   QuicByteCount GetNumFrameHeadersInInterval(QuicStreamOffset offset,
404                                              QuicByteCount data_length) const;
405 
406   void MaybeProcessSentWebTransportHeaders(spdy::Http2HeaderBlock& headers);
407   void MaybeProcessReceivedWebTransportHeaders();
408 
409   // Writes HTTP/3 DATA frame header. If |force_write| is true, use
410   // WriteOrBufferData if send buffer cannot accomodate the header + data.
411   ABSL_MUST_USE_RESULT bool WriteDataFrameHeader(QuicByteCount data_length,
412                                                  bool force_write);
413 
414   // Simply calls OnBodyAvailable() unless capsules are in use, in which case
415   // pass the capsule fragments to the capsule manager.
416   void HandleBodyAvailable();
417 
418   // Called when a datagram frame or capsule is received.
419   void HandleReceivedDatagram(absl::string_view payload);
420 
421   QuicSpdySession* spdy_session_;
422 
423   bool on_body_available_called_because_sequencer_is_closed_;
424 
425   Visitor* visitor_;
426 
427   // True if read side processing is blocked while waiting for callback from
428   // QPACK decoder.
429   bool blocked_on_decoding_headers_;
430   // True if the headers have been completely decompressed.
431   bool headers_decompressed_;
432   // True if uncompressed headers or trailers exceed maximum allowed size
433   // advertised to peer via SETTINGS_MAX_HEADER_LIST_SIZE.
434   bool header_list_size_limit_exceeded_;
435   // Contains a copy of the decompressed header (name, value) pairs until they
436   // are consumed via Readv.
437   QuicHeaderList header_list_;
438   // Length of most recently received HEADERS frame payload.
439   QuicByteCount headers_payload_length_;
440 
441   // True if the trailers have been completely decompressed.
442   bool trailers_decompressed_;
443   // True if the trailers have been consumed.
444   bool trailers_consumed_;
445 
446   // The parsed trailers received from the peer.
447   spdy::Http2HeaderBlock received_trailers_;
448 
449   // Headers accumulator for decoding HEADERS frame payload.
450   std::unique_ptr<QpackDecodedHeadersAccumulator>
451       qpack_decoded_headers_accumulator_;
452   // Visitor of the HttpDecoder.
453   std::unique_ptr<HttpDecoderVisitor> http_decoder_visitor_;
454   // HttpDecoder for processing raw incoming stream frames.
455   HttpDecoder decoder_;
456   // Object that manages references to DATA frame payload fragments buffered by
457   // the sequencer and calculates how much data should be marked consumed with
458   // the sequencer each time new stream data is processed.
459   QuicSpdyStreamBodyManager body_manager_;
460 
461   std::unique_ptr<quiche::CapsuleParser> capsule_parser_;
462 
463   // Sequencer offset keeping track of how much data HttpDecoder has processed.
464   // Initial value is zero for fresh streams, or sequencer()->NumBytesConsumed()
465   // at time of construction if a PendingStream is converted to account for the
466   // length of the unidirectional stream type at the beginning of the stream.
467   QuicStreamOffset sequencer_offset_;
468 
469   // True when inside an HttpDecoder::ProcessInput() call.
470   // Used for detecting reentrancy.
471   bool is_decoder_processing_input_;
472 
473   // Ack listener of this stream, and it is notified when any of written bytes
474   // are acked or retransmitted.
475   quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> ack_listener_;
476 
477   // Offset of unacked frame headers.
478   QuicIntervalSet<QuicStreamOffset> unacked_frame_headers_offsets_;
479 
480   // Priority parameters sent in the last PRIORITY_UPDATE frame, or default
481   // values defined by RFC9218 if no PRIORITY_UPDATE frame has been sent.
482   QuicStreamPriority last_sent_priority_;
483 
484   // If this stream is a WebTransport extended CONNECT stream, contains the
485   // WebTransport session associated with this stream.
486   std::unique_ptr<WebTransportHttp3> web_transport_;
487 
488   // If this stream is a WebTransport data stream, |web_transport_data_|
489   // contains all of the associated metadata.
490   std::unique_ptr<WebTransportDataStream> web_transport_data_;
491 
492   // HTTP/3 Datagram support.
493   Http3DatagramVisitor* datagram_visitor_ = nullptr;
494   // CONNECT-IP support.
495   ConnectIpVisitor* connect_ip_visitor_ = nullptr;
496 };
497 
498 }  // namespace quic
499 
500 #endif  // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_H_
501