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