1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_ 6 #define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_ 7 8 #include <cstddef> 9 #include <cstdint> 10 #include <list> 11 #include <memory> 12 #include <string> 13 14 #include "absl/container/flat_hash_map.h" 15 #include "absl/container/flat_hash_set.h" 16 #include "absl/strings/string_view.h" 17 #include "absl/types/optional.h" 18 #include "quiche/quic/core/http/http_frames.h" 19 #include "quiche/quic/core/http/quic_header_list.h" 20 #include "quiche/quic/core/http/quic_headers_stream.h" 21 #include "quiche/quic/core/http/quic_receive_control_stream.h" 22 #include "quiche/quic/core/http/quic_send_control_stream.h" 23 #include "quiche/quic/core/http/quic_spdy_stream.h" 24 #include "quiche/quic/core/qpack/qpack_decoder.h" 25 #include "quiche/quic/core/qpack/qpack_encoder.h" 26 #include "quiche/quic/core/qpack/qpack_receive_stream.h" 27 #include "quiche/quic/core/qpack/qpack_send_stream.h" 28 #include "quiche/quic/core/quic_session.h" 29 #include "quiche/quic/core/quic_stream_priority.h" 30 #include "quiche/quic/core/quic_time.h" 31 #include "quiche/quic/core/quic_types.h" 32 #include "quiche/quic/core/quic_versions.h" 33 #include "quiche/quic/platform/api/quic_export.h" 34 #include "quiche/spdy/core/http2_frame_decoder_adapter.h" 35 #include "quiche/spdy/core/http2_header_block.h" 36 37 namespace quic { 38 39 namespace test { 40 class QuicSpdySessionPeer; 41 } // namespace test 42 43 class WebTransportHttp3UnidirectionalStream; 44 45 QUIC_EXPORT_PRIVATE extern const size_t kMaxUnassociatedWebTransportStreams; 46 47 class QUIC_EXPORT_PRIVATE Http3DebugVisitor { 48 public: 49 Http3DebugVisitor(); 50 Http3DebugVisitor(const Http3DebugVisitor&) = delete; 51 Http3DebugVisitor& operator=(const Http3DebugVisitor&) = delete; 52 53 virtual ~Http3DebugVisitor(); 54 55 // TODO(https://crbug.com/1062700): Remove default implementation of all 56 // methods after Chrome's QuicHttp3Logger has overrides. This is to make sure 57 // QUICHE merge is not blocked on having to add those overrides, they can 58 // happen asynchronously. 59 60 // Creation of unidirectional streams. 61 62 // Called when locally-initiated control stream is created. 63 virtual void OnControlStreamCreated(QuicStreamId /*stream_id*/) = 0; 64 // Called when locally-initiated QPACK encoder stream is created. 65 virtual void OnQpackEncoderStreamCreated(QuicStreamId /*stream_id*/) = 0; 66 // Called when locally-initiated QPACK decoder stream is created. 67 virtual void OnQpackDecoderStreamCreated(QuicStreamId /*stream_id*/) = 0; 68 // Called when peer's control stream type is received. 69 virtual void OnPeerControlStreamCreated(QuicStreamId /*stream_id*/) = 0; 70 // Called when peer's QPACK encoder stream type is received. 71 virtual void OnPeerQpackEncoderStreamCreated(QuicStreamId /*stream_id*/) = 0; 72 // Called when peer's QPACK decoder stream type is received. 73 virtual void OnPeerQpackDecoderStreamCreated(QuicStreamId /*stream_id*/) = 0; 74 75 // Incoming HTTP/3 frames in ALPS TLS extension. OnSettingsFrameReceivedViaAlps(const SettingsFrame &)76 virtual void OnSettingsFrameReceivedViaAlps(const SettingsFrame& /*frame*/) {} OnAcceptChFrameReceivedViaAlps(const AcceptChFrame &)77 virtual void OnAcceptChFrameReceivedViaAlps(const AcceptChFrame& /*frame*/) {} 78 79 // Incoming HTTP/3 frames on the control stream. 80 virtual void OnSettingsFrameReceived(const SettingsFrame& /*frame*/) = 0; 81 virtual void OnGoAwayFrameReceived(const GoAwayFrame& /*frame*/) = 0; 82 virtual void OnPriorityUpdateFrameReceived( 83 const PriorityUpdateFrame& /*frame*/) = 0; OnAcceptChFrameReceived(const AcceptChFrame &)84 virtual void OnAcceptChFrameReceived(const AcceptChFrame& /*frame*/) {} 85 86 // Incoming HTTP/3 frames on request or push streams. 87 virtual void OnDataFrameReceived(QuicStreamId /*stream_id*/, 88 QuicByteCount /*payload_length*/) = 0; 89 virtual void OnHeadersFrameReceived( 90 QuicStreamId /*stream_id*/, 91 QuicByteCount /*compressed_headers_length*/) = 0; 92 virtual void OnHeadersDecoded(QuicStreamId /*stream_id*/, 93 QuicHeaderList /*headers*/) = 0; 94 95 // Incoming HTTP/3 frames of unknown type on any stream. 96 virtual void OnUnknownFrameReceived(QuicStreamId /*stream_id*/, 97 uint64_t /*frame_type*/, 98 QuicByteCount /*payload_length*/) = 0; 99 100 // Outgoing HTTP/3 frames on the control stream. 101 virtual void OnSettingsFrameSent(const SettingsFrame& /*frame*/) = 0; 102 virtual void OnGoAwayFrameSent(QuicStreamId /*stream_id*/) = 0; 103 virtual void OnPriorityUpdateFrameSent( 104 const PriorityUpdateFrame& /*frame*/) = 0; 105 106 // Outgoing HTTP/3 frames on request or push streams. 107 virtual void OnDataFrameSent(QuicStreamId /*stream_id*/, 108 QuicByteCount /*payload_length*/) = 0; 109 virtual void OnHeadersFrameSent( 110 QuicStreamId /*stream_id*/, 111 const spdy::Http2HeaderBlock& /*header_block*/) = 0; 112 113 // 0-RTT related events. 114 virtual void OnSettingsFrameResumed(const SettingsFrame& /*frame*/) = 0; 115 }; 116 117 // Whether HTTP Datagrams are supported on this session and if so which version 118 // is currently in use. 119 enum class HttpDatagramSupport : uint8_t { 120 kNone, // HTTP Datagrams are not supported for this session. 121 kDraft04, 122 kRfc, 123 kRfcAndDraft04, // Only used locally for sending, we only negotiate one 124 // version. 125 }; 126 127 QUIC_EXPORT_PRIVATE std::string HttpDatagramSupportToString( 128 HttpDatagramSupport http_datagram_support); 129 QUIC_EXPORT_PRIVATE std::ostream& operator<<( 130 std::ostream& os, const HttpDatagramSupport& http_datagram_support); 131 132 // A QUIC session for HTTP. 133 class QUIC_EXPORT_PRIVATE QuicSpdySession 134 : public QuicSession, 135 public QpackEncoder::DecoderStreamErrorDelegate, 136 public QpackDecoder::EncoderStreamErrorDelegate { 137 public: 138 // Does not take ownership of |connection| or |visitor|. 139 QuicSpdySession(QuicConnection* connection, QuicSession::Visitor* visitor, 140 const QuicConfig& config, 141 const ParsedQuicVersionVector& supported_versions); 142 QuicSpdySession(const QuicSpdySession&) = delete; 143 QuicSpdySession& operator=(const QuicSpdySession&) = delete; 144 145 ~QuicSpdySession() override; 146 147 void Initialize() override; 148 149 // QpackEncoder::DecoderStreamErrorDelegate implementation. 150 void OnDecoderStreamError(QuicErrorCode error_code, 151 absl::string_view error_message) override; 152 153 // QpackDecoder::EncoderStreamErrorDelegate implementation. 154 void OnEncoderStreamError(QuicErrorCode error_code, 155 absl::string_view error_message) override; 156 157 // Called by |headers_stream_| when headers with a priority have been 158 // received for a stream. This method will only be called for server streams. 159 virtual void OnStreamHeadersPriority( 160 QuicStreamId stream_id, const spdy::SpdyStreamPrecedence& precedence); 161 162 // Called by |headers_stream_| when headers have been completely received 163 // for a stream. |fin| will be true if the fin flag was set in the headers 164 // frame. 165 virtual void OnStreamHeaderList(QuicStreamId stream_id, bool fin, 166 size_t frame_len, 167 const QuicHeaderList& header_list); 168 169 // Called by |headers_stream_| when push promise headers have been 170 // completely received. |fin| will be true if the fin flag was set 171 // in the headers. 172 virtual void OnPromiseHeaderList(QuicStreamId stream_id, 173 QuicStreamId promised_stream_id, 174 size_t frame_len, 175 const QuicHeaderList& header_list); 176 177 // Called by |headers_stream_| when a PRIORITY frame has been received for a 178 // stream. This method will only be called for server streams. 179 virtual void OnPriorityFrame(QuicStreamId stream_id, 180 const spdy::SpdyStreamPrecedence& precedence); 181 182 // Called when an HTTP/3 PRIORITY_UPDATE frame has been received for a request 183 // stream. Returns false and closes connection if |stream_id| is invalid. 184 bool OnPriorityUpdateForRequestStream(QuicStreamId stream_id, 185 HttpStreamPriority priority); 186 187 // Called when an HTTP/3 ACCEPT_CH frame has been received. 188 // This method will only be called for client sessions. OnAcceptChFrame(const AcceptChFrame &)189 virtual void OnAcceptChFrame(const AcceptChFrame& /*frame*/) {} 190 191 // Called when an HTTP/3 frame of unknown type has been received. OnUnknownFrameStart(QuicStreamId,uint64_t,QuicByteCount,QuicByteCount)192 virtual void OnUnknownFrameStart(QuicStreamId /*stream_id*/, 193 uint64_t /*frame_type*/, 194 QuicByteCount /*header_length*/, 195 QuicByteCount /*payload_length*/) {} OnUnknownFramePayload(QuicStreamId,absl::string_view)196 virtual void OnUnknownFramePayload(QuicStreamId /*stream_id*/, 197 absl::string_view /*payload*/) {} 198 199 // Sends contents of |iov| to h2_deframer_, returns number of bytes processed. 200 size_t ProcessHeaderData(const struct iovec& iov); 201 202 // Writes |headers| for the stream |id| to the dedicated headers stream. 203 // If |fin| is true, then no more data will be sent for the stream |id|. 204 // If provided, |ack_notifier_delegate| will be registered to be notified when 205 // we have seen ACKs for all packets resulting from this call. 206 virtual size_t WriteHeadersOnHeadersStream( 207 QuicStreamId id, spdy::Http2HeaderBlock headers, bool fin, 208 const spdy::SpdyStreamPrecedence& precedence, 209 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> 210 ack_listener); 211 212 // Writes an HTTP/2 PRIORITY frame the to peer. Returns the size in bytes of 213 // the resulting PRIORITY frame. 214 size_t WritePriority(QuicStreamId stream_id, QuicStreamId parent_stream_id, 215 int weight, bool exclusive); 216 217 // Writes an HTTP/3 PRIORITY_UPDATE frame to the peer. 218 void WriteHttp3PriorityUpdate(QuicStreamId stream_id, 219 HttpStreamPriority priority); 220 221 // Process received HTTP/3 GOAWAY frame. When sent from server to client, 222 // |id| is a stream ID. When sent from client to server, |id| is a push ID. 223 virtual void OnHttp3GoAway(uint64_t id); 224 225 // Send GOAWAY if the peer is blocked on the implementation max. 226 bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override; 227 228 // Write GOAWAY frame with maximum stream ID on the control stream. Called to 229 // initite graceful connection shutdown. Do not use smaller stream ID, in 230 // case client does not implement retry on GOAWAY. Do not send GOAWAY if one 231 // has already been sent. Send connection close with |error_code| and |reason| 232 // before encryption gets established. 233 void SendHttp3GoAway(QuicErrorCode error_code, const std::string& reason); 234 235 // Write |headers| for |promised_stream_id| on |original_stream_id| in a 236 // PUSH_PROMISE frame to peer. 237 virtual void WritePushPromise(QuicStreamId original_stream_id, 238 QuicStreamId promised_stream_id, 239 spdy::Http2HeaderBlock headers); 240 241 QpackEncoder* qpack_encoder(); 242 QpackDecoder* qpack_decoder(); headers_stream()243 QuicHeadersStream* headers_stream() { return headers_stream_; } 244 headers_stream()245 const QuicHeadersStream* headers_stream() const { return headers_stream_; } 246 247 // Called when the control stream receives HTTP/3 SETTINGS. 248 // Returns false in case of 0-RTT if received settings are incompatible with 249 // cached values, true otherwise. 250 virtual bool OnSettingsFrame(const SettingsFrame& frame); 251 252 // Called when an HTTP/3 SETTINGS frame is received via ALPS. 253 // Returns an error message if an error has occurred, or nullopt otherwise. 254 // May or may not close the connection on error. 255 absl::optional<std::string> OnSettingsFrameViaAlps( 256 const SettingsFrame& frame); 257 258 // Called when a setting is parsed from a SETTINGS frame received on the 259 // control stream or from cached application state. 260 // Returns true on success. 261 // Returns false if received setting is incompatible with cached value (in 262 // case of 0-RTT) or with previously received value (in case of ALPS). 263 // Also closes the connection on error. 264 bool OnSetting(uint64_t id, uint64_t value); 265 266 // Return true if this session wants to release headers stream's buffer 267 // aggressively. 268 virtual bool ShouldReleaseHeadersStreamSequencerBuffer(); 269 270 void CloseConnectionWithDetails(QuicErrorCode error, 271 const std::string& details); 272 273 // Must not be called after Initialize(). 274 // TODO(bnc): Move to constructor argument. set_qpack_maximum_dynamic_table_capacity(uint64_t qpack_maximum_dynamic_table_capacity)275 void set_qpack_maximum_dynamic_table_capacity( 276 uint64_t qpack_maximum_dynamic_table_capacity) { 277 qpack_maximum_dynamic_table_capacity_ = 278 qpack_maximum_dynamic_table_capacity; 279 } 280 281 // Must not be called after Initialize(). 282 // TODO(bnc): Move to constructor argument. set_qpack_maximum_blocked_streams(uint64_t qpack_maximum_blocked_streams)283 void set_qpack_maximum_blocked_streams( 284 uint64_t qpack_maximum_blocked_streams) { 285 qpack_maximum_blocked_streams_ = qpack_maximum_blocked_streams; 286 } 287 288 // Should only be used by IETF QUIC server side. 289 // Must not be called after Initialize(). 290 // TODO(bnc): Move to constructor argument. set_max_inbound_header_list_size(size_t max_inbound_header_list_size)291 void set_max_inbound_header_list_size(size_t max_inbound_header_list_size) { 292 max_inbound_header_list_size_ = max_inbound_header_list_size; 293 } 294 295 // Must not be called after Initialize(). 296 void set_allow_extended_connect(bool allow_extended_connect); 297 max_outbound_header_list_size()298 size_t max_outbound_header_list_size() const { 299 return max_outbound_header_list_size_; 300 } 301 max_inbound_header_list_size()302 size_t max_inbound_header_list_size() const { 303 return max_inbound_header_list_size_; 304 } 305 allow_extended_connect()306 bool allow_extended_connect() const { return allow_extended_connect_; } 307 308 // Returns true if the session has active request streams. 309 bool HasActiveRequestStreams() const; 310 311 // Called when the size of the compressed frame payload is available. 312 void OnCompressedFrameSize(size_t frame_len); 313 314 // Called when a PUSH_PROMISE frame has been received. 315 // TODO(b/171463363): Remove. 316 void OnPushPromise(spdy::SpdyStreamId stream_id, 317 spdy::SpdyStreamId promised_stream_id); 318 319 // Called when the complete list of headers is available. 320 void OnHeaderList(const QuicHeaderList& header_list); 321 promised_stream_id()322 QuicStreamId promised_stream_id() const { return promised_stream_id_; } 323 324 // Initialze HTTP/3 unidirectional streams if |unidirectional| is true and 325 // those streams are not initialized yet. 326 void OnCanCreateNewOutgoingStream(bool unidirectional) override; 327 destruction_indicator()328 int32_t destruction_indicator() const { return destruction_indicator_; } 329 set_debug_visitor(Http3DebugVisitor * debug_visitor)330 void set_debug_visitor(Http3DebugVisitor* debug_visitor) { 331 debug_visitor_ = debug_visitor; 332 } 333 debug_visitor()334 Http3DebugVisitor* debug_visitor() { return debug_visitor_; } 335 336 // When using Google QUIC, return whether a transport layer GOAWAY frame has 337 // been received or sent. 338 // When using IETF QUIC, return whether an HTTP/3 GOAWAY frame has been 339 // received or sent. 340 bool goaway_received() const; 341 bool goaway_sent() const; 342 343 // Log header compression ratio histogram. 344 // |using_qpack| is true for QPACK, false for HPACK. 345 // |is_sent| is true for sent headers, false for received ones. 346 // Ratio is recorded as percentage. Smaller value means more efficient 347 // compression. Compressed size might be larger than uncompressed size, but 348 // recorded ratio is trunckated at 200%. 349 // Uncompressed size can be zero for an empty header list, and compressed size 350 // can be zero for an empty header list when using HPACK. (QPACK always emits 351 // a header block prefix of at least two bytes.) This method records nothing 352 // if either |compressed| or |uncompressed| is not positive. 353 // In order for measurements for different protocol to be comparable, the 354 // caller must ensure that uncompressed size is the total length of header 355 // names and values without any overhead. 356 static void LogHeaderCompressionRatioHistogram(bool using_qpack, bool is_sent, 357 QuicByteCount compressed, 358 QuicByteCount uncompressed); 359 360 // True if any dynamic table entries have been referenced from either a sent 361 // or received header block. Used for stats. dynamic_table_entry_referenced()362 bool dynamic_table_entry_referenced() const { 363 return (qpack_encoder_ && 364 qpack_encoder_->dynamic_table_entry_referenced()) || 365 (qpack_decoder_ && qpack_decoder_->dynamic_table_entry_referenced()); 366 } 367 368 void OnStreamCreated(QuicSpdyStream* stream); 369 370 // Decode SETTINGS from |cached_state| and apply it to the session. 371 bool ResumeApplicationState(ApplicationState* cached_state) override; 372 373 absl::optional<std::string> OnAlpsData(const uint8_t* alps_data, 374 size_t alps_length) override; 375 376 // Called when ACCEPT_CH frame is parsed out of data received in TLS ALPS 377 // extension. 378 virtual void OnAcceptChFrameReceivedViaAlps(const AcceptChFrame& /*frame*/); 379 380 // Whether HTTP datagrams are supported on this session and which draft is in 381 // use, based on received SETTINGS. http_datagram_support()382 HttpDatagramSupport http_datagram_support() const { 383 return http_datagram_support_; 384 } 385 386 // This must not be used except by QuicSpdyStream::SendHttp3Datagram. 387 MessageStatus SendHttp3Datagram(QuicStreamId stream_id, 388 absl::string_view payload); 389 // This must not be used except by QuicSpdyStream::SetMaxDatagramTimeInQueue. 390 void SetMaxDatagramTimeInQueueForStreamId(QuicStreamId stream_id, 391 QuicTime::Delta max_time_in_queue); 392 393 // Override from QuicSession to support HTTP/3 datagrams. 394 void OnMessageReceived(absl::string_view message) override; 395 396 // Indicates whether the HTTP/3 session supports WebTransport. 397 bool SupportsWebTransport(); 398 399 // Indicates whether both the peer and us support HTTP/3 Datagrams. 400 bool SupportsH3Datagram() const; 401 402 // Indicates whether the HTTP/3 session will indicate WebTransport support to 403 // the peer. 404 bool WillNegotiateWebTransport(); 405 406 // Returns a WebTransport session by its session ID. Returns nullptr if no 407 // session is associated with the given ID. 408 WebTransportHttp3* GetWebTransportSession(WebTransportSessionId id); 409 410 // If true, no data on bidirectional streams will be processed by the server 411 // until the SETTINGS are received. Only works for HTTP/3. This is currently 412 // required either (1) for WebTransport because WebTransport needs settings to 413 // correctly parse requests or (2) when multiple versions of HTTP Datagrams 414 // are supported to ensure we know which one is used. The HTTP Datagram check 415 // will be removed once we drop support for draft04. ShouldBufferRequestsUntilSettings()416 bool ShouldBufferRequestsUntilSettings() { 417 return version().UsesHttp3() && perspective() == Perspective::IS_SERVER && 418 (ShouldNegotiateWebTransport() || 419 LocalHttpDatagramSupport() == HttpDatagramSupport::kRfcAndDraft04); 420 } 421 422 // Returns if the incoming bidirectional streams should process data. This is 423 // usually true, but in certain cases we would want to wait until the settings 424 // are received. 425 bool ShouldProcessIncomingRequests(); 426 427 void OnStreamWaitingForClientSettings(QuicStreamId id); 428 429 // Links the specified stream with a WebTransport session. If the session is 430 // not present, it is buffered until a corresponding stream is found. 431 void AssociateIncomingWebTransportStreamWithSession( 432 WebTransportSessionId session_id, QuicStreamId stream_id); 433 434 void ProcessBufferedWebTransportStreamsForSession(WebTransportHttp3* session); 435 CanOpenOutgoingUnidirectionalWebTransportStream(WebTransportSessionId)436 bool CanOpenOutgoingUnidirectionalWebTransportStream( 437 WebTransportSessionId /*id*/) { 438 return CanOpenNextOutgoingUnidirectionalStream(); 439 } CanOpenOutgoingBidirectionalWebTransportStream(WebTransportSessionId)440 bool CanOpenOutgoingBidirectionalWebTransportStream( 441 WebTransportSessionId /*id*/) { 442 return CanOpenNextOutgoingBidirectionalStream(); 443 } 444 445 // Creates an outgoing unidirectional WebTransport stream. Returns nullptr if 446 // the stream cannot be created due to flow control or some other reason. 447 WebTransportHttp3UnidirectionalStream* 448 CreateOutgoingUnidirectionalWebTransportStream(WebTransportHttp3* session); 449 450 // Creates an outgoing bidirectional WebTransport stream. Returns nullptr if 451 // the stream cannot be created due to flow control or some other reason. 452 QuicSpdyStream* CreateOutgoingBidirectionalWebTransportStream( 453 WebTransportHttp3* session); 454 455 QuicSpdyStream* GetOrCreateSpdyDataStream(const QuicStreamId stream_id); 456 457 // Indicates whether the client should check that the 458 // `Sec-Webtransport-Http3-Draft` header is valid. 459 // TODO(vasilvv): remove this once this is enabled in Chromium. 460 virtual bool ShouldValidateWebTransportVersion() const; 461 462 protected: 463 // Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and 464 // CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to 465 // make sure that all data streams are QuicSpdyStreams. 466 QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override = 0; 467 QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override = 0; 468 virtual QuicSpdyStream* CreateOutgoingBidirectionalStream() = 0; 469 virtual QuicSpdyStream* CreateOutgoingUnidirectionalStream() = 0; 470 471 // If an incoming stream can be created, return true. 472 virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0; 473 474 // If an outgoing bidirectional/unidirectional stream can be created, return 475 // true. 476 virtual bool ShouldCreateOutgoingBidirectionalStream() = 0; 477 virtual bool ShouldCreateOutgoingUnidirectionalStream() = 0; 478 479 // Indicates whether the underlying backend can accept and process 480 // WebTransport sessions over HTTP/3. 481 virtual bool ShouldNegotiateWebTransport(); 482 483 // Returns true if there are open HTTP requests. 484 bool ShouldKeepConnectionAlive() const override; 485 486 // Overridden to buffer incoming unidirectional streams for version 99. 487 bool UsesPendingStreamForFrame(QuicFrameType type, 488 QuicStreamId stream_id) const override; 489 490 // Processes incoming unidirectional streams; parses the stream type, and 491 // creates a new stream of the corresponding type. Returns the pointer to the 492 // newly created stream, or nullptr if the stream type is not yet available. 493 QuicStream* ProcessPendingStream(PendingStream* pending) override; 494 495 size_t WriteHeadersOnHeadersStreamImpl( 496 QuicStreamId id, spdy::Http2HeaderBlock headers, bool fin, 497 QuicStreamId parent_stream_id, int weight, bool exclusive, 498 quiche::QuicheReferenceCountedPointer<QuicAckListenerInterface> 499 ack_listener); 500 501 void OnNewEncryptionKeyAvailable( 502 EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter) override; 503 504 // Sets the maximum size of the header compression table spdy_framer_ is 505 // willing to use to encode header blocks. 506 void UpdateHeaderEncoderTableSize(uint32_t value); 507 IsConnected()508 bool IsConnected() { return connection()->connected(); } 509 receive_control_stream()510 const QuicReceiveControlStream* receive_control_stream() const { 511 return receive_control_stream_; 512 } 513 settings()514 const SettingsFrame& settings() const { return settings_; } 515 516 // Initializes HTTP/3 unidirectional streams if not yet initialzed. 517 virtual void MaybeInitializeHttp3UnidirectionalStreams(); 518 519 // QuicConnectionVisitorInterface method. 520 void BeforeConnectionCloseSent() override; 521 522 // Called whenever a datagram is dequeued or dropped from datagram_queue(). 523 virtual void OnDatagramProcessed(absl::optional<MessageStatus> status); 524 525 // Returns which version of the HTTP/3 datagram extension we should advertise 526 // in settings and accept remote settings for. 527 virtual HttpDatagramSupport LocalHttpDatagramSupport(); 528 529 // Sends any data which should be sent at the start of a connection, including 530 // the initial SETTINGS frame. When using 0-RTT, this method is called twice: 531 // once when encryption is established, and again when 1-RTT keys are 532 // available. 533 void SendInitialData(); 534 535 private: 536 friend class test::QuicSpdySessionPeer; 537 538 class SpdyFramerVisitor; 539 540 // Proxies OnDatagramProcessed() calls to the session. 541 class QUIC_EXPORT_PRIVATE DatagramObserver 542 : public QuicDatagramQueue::Observer { 543 public: DatagramObserver(QuicSpdySession * session)544 explicit DatagramObserver(QuicSpdySession* session) : session_(session) {} 545 void OnDatagramProcessed(absl::optional<MessageStatus> status) override; 546 547 private: 548 QuicSpdySession* session_; // not owned 549 }; 550 551 struct QUIC_EXPORT_PRIVATE BufferedWebTransportStream { 552 WebTransportSessionId session_id; 553 QuicStreamId stream_id; 554 }; 555 556 // The following methods are called by the SimpleVisitor. 557 558 // Called when a HEADERS frame has been received. 559 void OnHeaders(spdy::SpdyStreamId stream_id, bool has_priority, 560 const spdy::SpdyStreamPrecedence& precedence, bool fin); 561 562 // Called when a PRIORITY frame has been received. 563 void OnPriority(spdy::SpdyStreamId stream_id, 564 const spdy::SpdyStreamPrecedence& precedence); 565 566 void CloseConnectionOnDuplicateHttp3UnidirectionalStreams( 567 absl::string_view type); 568 569 void FillSettingsFrame(); 570 571 bool VerifySettingIsZeroOrOne(uint64_t id, uint64_t value); 572 573 std::unique_ptr<QpackEncoder> qpack_encoder_; 574 std::unique_ptr<QpackDecoder> qpack_decoder_; 575 576 // Pointer to the header stream in stream_map_. 577 QuicHeadersStream* headers_stream_; 578 579 // HTTP/3 control streams. They are owned by QuicSession inside 580 // stream map, and can be accessed by those unowned pointers below. 581 QuicSendControlStream* send_control_stream_; 582 QuicReceiveControlStream* receive_control_stream_; 583 584 // Pointers to HTTP/3 QPACK streams in stream map. 585 QpackReceiveStream* qpack_encoder_receive_stream_; 586 QpackReceiveStream* qpack_decoder_receive_stream_; 587 QpackSendStream* qpack_encoder_send_stream_; 588 QpackSendStream* qpack_decoder_send_stream_; 589 590 SettingsFrame settings_; 591 592 // Maximum dynamic table capacity as defined at 593 // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#maximum-dynamic-table-capacity 594 // for the decoding context. Value will be sent via 595 // SETTINGS_QPACK_MAX_TABLE_CAPACITY. 596 // |qpack_maximum_dynamic_table_capacity_| also serves as an upper bound for 597 // the dynamic table capacity of the encoding context, to limit memory usage 598 // if a larger SETTINGS_QPACK_MAX_TABLE_CAPACITY value is received. 599 uint64_t qpack_maximum_dynamic_table_capacity_; 600 601 // Maximum number of blocked streams as defined at 602 // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#blocked-streams 603 // for the decoding context. Value will be sent via 604 // SETTINGS_QPACK_BLOCKED_STREAMS. 605 uint64_t qpack_maximum_blocked_streams_; 606 607 // The maximum size of a header block that will be accepted from the peer, 608 // defined per spec as key + value + overhead per field (uncompressed). 609 // Value will be sent via SETTINGS_MAX_HEADER_LIST_SIZE. 610 size_t max_inbound_header_list_size_; 611 612 // The maximum size of a header block that can be sent to the peer. This field 613 // is informed and set by the peer via SETTINGS frame. 614 // TODO(b/148616439): Honor this field when sending headers. 615 size_t max_outbound_header_list_size_; 616 617 // Data about the stream whose headers are being processed. 618 QuicStreamId stream_id_; 619 QuicStreamId promised_stream_id_; 620 size_t frame_len_; 621 bool fin_; 622 623 spdy::SpdyFramer spdy_framer_; 624 http2::Http2DecoderAdapter h2_deframer_; 625 std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_; 626 627 // Not owned by the session. 628 Http3DebugVisitor* debug_visitor_; 629 630 // Priority values received in PRIORITY_UPDATE frames for streams that are not 631 // open yet. 632 absl::flat_hash_map<QuicStreamId, HttpStreamPriority> 633 buffered_stream_priorities_; 634 635 // An integer used for live check. The indicator is assigned a value in 636 // constructor. As long as it is not the assigned value, that would indicate 637 // an use-after-free. 638 int32_t destruction_indicator_; 639 640 // The identifier in the most recently received GOAWAY frame. Unset if no 641 // GOAWAY frame has been received yet. 642 absl::optional<uint64_t> last_received_http3_goaway_id_; 643 // The identifier in the most recently sent GOAWAY frame. Unset if no GOAWAY 644 // frame has been sent yet. 645 absl::optional<uint64_t> last_sent_http3_goaway_id_; 646 647 // Whether both this endpoint and our peer support HTTP datagrams and which 648 // draft is in use for this session. 649 HttpDatagramSupport http_datagram_support_ = HttpDatagramSupport::kNone; 650 651 // Whether the peer has indicated WebTransport support. 652 bool peer_supports_webtransport_ = false; 653 654 // Whether any settings have been received, either from the peer or from a 655 // session ticket. 656 bool any_settings_received_ = false; 657 658 // If ShouldBufferRequestsUntilSettings() is true, all streams that are 659 // blocked by that are tracked here. 660 absl::flat_hash_set<QuicStreamId> streams_waiting_for_settings_; 661 662 // WebTransport streams that do not have a session associated with them. 663 // Limited to kMaxUnassociatedWebTransportStreams; when the list is full, 664 // oldest streams are evicated first. 665 std::list<BufferedWebTransportStream> buffered_streams_; 666 667 // On the server side, if true, advertise and accept extended CONNECT method. 668 // On the client side, true if the peer advertised extended CONNECT. 669 bool allow_extended_connect_; 670 }; 671 672 } // namespace quic 673 674 #endif // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_ 675