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