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