blob: bab74d352a6bacf9a40fd3a17dc395379be7f34b [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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 <memory>
vasilvv872e7a32019-03-12 16:42:44 -070010#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/core/http/quic_header_list.h"
13#include "net/third_party/quiche/src/quic/core/http/quic_headers_stream.h"
renjietang3a1bb802019-06-11 10:42:41 -070014#include "net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h"
15#include "net/third_party/quiche/src/quic/core/http/quic_send_control_stream.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050016#include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h"
17#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
18#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h"
19#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
20#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
renjietang87cd7de2019-08-16 08:35:10 -070021#include "net/third_party/quiche/src/quic/core/qpack/qpack_receive_stream.h"
22#include "net/third_party/quiche/src/quic/core/qpack/qpack_send_stream.h"
renjietangc2aa5cb2019-06-20 12:22:53 -070023#include "net/third_party/quiche/src/quic/core/qpack/qpack_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050024#include "net/third_party/quiche/src/quic/core/quic_session.h"
25#include "net/third_party/quiche/src/quic/core/quic_versions.h"
26#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050027#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
28#include "net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h"
29
30namespace quic {
31
32namespace test {
33class QuicSpdySessionPeer;
34} // namespace test
35
36// QuicHpackDebugVisitor gathers data used for understanding HPACK HoL
37// dynamics. Specifically, it is to help predict the compression
38// penalty of avoiding HoL by chagning how the dynamic table is used.
39// In chromium, the concrete instance populates an UMA
40// histogram with the data.
41class QUIC_EXPORT_PRIVATE QuicHpackDebugVisitor {
42 public:
43 QuicHpackDebugVisitor();
44 QuicHpackDebugVisitor(const QuicHpackDebugVisitor&) = delete;
45 QuicHpackDebugVisitor& operator=(const QuicHpackDebugVisitor&) = delete;
46
47 virtual ~QuicHpackDebugVisitor();
48
49 // For each HPACK indexed representation processed, |elapsed| is
50 // the time since the corresponding entry was added to the dynamic
51 // table.
52 virtual void OnUseEntry(QuicTime::Delta elapsed) = 0;
53};
54
renjietang69a8eaf2019-08-06 15:55:58 -070055// A QUIC session for HTTP.
QUICHE teama6ef0a62019-03-07 20:34:33 -050056class QUIC_EXPORT_PRIVATE QuicSpdySession
57 : public QuicSession,
58 public QpackEncoder::DecoderStreamErrorDelegate,
renjietangc2aa5cb2019-06-20 12:22:53 -070059 public QpackDecoder::EncoderStreamErrorDelegate {
QUICHE teama6ef0a62019-03-07 20:34:33 -050060 public:
61 // Does not take ownership of |connection| or |visitor|.
62 QuicSpdySession(QuicConnection* connection,
63 QuicSession::Visitor* visitor,
64 const QuicConfig& config,
65 const ParsedQuicVersionVector& supported_versions);
66 QuicSpdySession(const QuicSpdySession&) = delete;
67 QuicSpdySession& operator=(const QuicSpdySession&) = delete;
68
69 ~QuicSpdySession() override;
70
71 void Initialize() override;
72
73 // QpackEncoder::DecoderStreamErrorDelegate implementation.
74 void OnDecoderStreamError(QuicStringPiece error_message) override;
75
QUICHE teama6ef0a62019-03-07 20:34:33 -050076 // QpackDecoder::EncoderStreamErrorDelegate implementation.
77 void OnEncoderStreamError(QuicStringPiece error_message) override;
78
QUICHE teama6ef0a62019-03-07 20:34:33 -050079 // Called by |headers_stream_| when headers with a priority have been
80 // received for a stream. This method will only be called for server streams.
fayang476683a2019-07-25 12:42:16 -070081 virtual void OnStreamHeadersPriority(
82 QuicStreamId stream_id,
83 const spdy::SpdyStreamPrecedence& precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -050084
85 // Called by |headers_stream_| when headers have been completely received
86 // for a stream. |fin| will be true if the fin flag was set in the headers
87 // frame.
88 virtual void OnStreamHeaderList(QuicStreamId stream_id,
89 bool fin,
90 size_t frame_len,
91 const QuicHeaderList& header_list);
92
93 // Called by |headers_stream_| when push promise headers have been
94 // completely received. |fin| will be true if the fin flag was set
95 // in the headers.
96 virtual void OnPromiseHeaderList(QuicStreamId stream_id,
97 QuicStreamId promised_stream_id,
98 size_t frame_len,
99 const QuicHeaderList& header_list);
100
101 // Called by |headers_stream_| when a PRIORITY frame has been received for a
102 // stream. This method will only be called for server streams.
103 virtual void OnPriorityFrame(QuicStreamId stream_id,
fayang476683a2019-07-25 12:42:16 -0700104 const spdy::SpdyStreamPrecedence& precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500105
106 // Sends contents of |iov| to h2_deframer_, returns number of bytes processed.
107 size_t ProcessHeaderData(const struct iovec& iov);
108
109 // Writes |headers| for the stream |id| to the dedicated headers stream.
110 // If |fin| is true, then no more data will be sent for the stream |id|.
111 // If provided, |ack_notifier_delegate| will be registered to be notified when
112 // we have seen ACKs for all packets resulting from this call.
113 virtual size_t WriteHeadersOnHeadersStream(
114 QuicStreamId id,
115 spdy::SpdyHeaderBlock headers,
116 bool fin,
fayang476683a2019-07-25 12:42:16 -0700117 const spdy::SpdyStreamPrecedence& precedence,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500118 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
119
120 // Writes a PRIORITY frame the to peer. Returns the size in bytes of the
121 // resulting PRIORITY frame for QUIC_VERSION_43 and above. Otherwise, does
122 // nothing and returns 0.
123 size_t WritePriority(QuicStreamId id,
124 QuicStreamId parent_stream_id,
125 int weight,
126 bool exclusive);
127
renjietang7498c8c2019-07-02 19:28:42 -0700128 // Writes a HTTP/3 PRIORITY frame to the peer.
129 void WriteH3Priority(const PriorityFrame& priority);
130
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131 // Write |headers| for |promised_stream_id| on |original_stream_id| in a
132 // PUSH_PROMISE frame to peer.
renjietangf4f47122019-07-22 12:08:53 -0700133 virtual void WritePushPromise(QuicStreamId original_stream_id,
134 QuicStreamId promised_stream_id,
135 spdy::SpdyHeaderBlock headers);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500136
137 // Sends SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
QUICHE team2252b702019-05-14 23:55:14 -0400138 void SendMaxHeaderListSize(size_t value);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500139
140 QpackEncoder* qpack_encoder();
141 QpackDecoder* qpack_decoder();
renjietang9818f8c2019-07-16 11:12:27 -0700142 QuicHeadersStream* headers_stream() { return headers_stream_; }
renjietangfbeb5bf2019-04-19 15:06:20 -0700143
renjietang9818f8c2019-07-16 11:12:27 -0700144 const QuicHeadersStream* headers_stream() const { return headers_stream_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145
146 bool server_push_enabled() const { return server_push_enabled_; }
147
bnc5b182b92019-07-30 11:00:15 -0700148 // Called when a setting is parsed from an incoming SETTINGS frame.
149 void OnSetting(uint64_t id, uint64_t value);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500150
151 // Return true if this session wants to release headers stream's buffer
152 // aggressively.
153 virtual bool ShouldReleaseHeadersStreamSequencerBuffer();
154
155 void CloseConnectionWithDetails(QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -0700156 const std::string& details);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157
bnc30d610c2019-07-08 18:39:59 -0700158 // Must be called before Initialize().
159 // TODO(bnc): Move to constructor argument.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160 void set_max_inbound_header_list_size(size_t max_inbound_header_list_size) {
161 max_inbound_header_list_size_ = max_inbound_header_list_size;
162 }
163
renjietang3a1bb802019-06-11 10:42:41 -0700164 size_t max_outbound_header_list_size() const {
165 return max_outbound_header_list_size_;
166 }
167
renjietangfee2cc32019-04-05 11:32:07 -0700168 size_t max_inbound_header_list_size() const {
169 return max_inbound_header_list_size_;
170 }
171
QUICHE teamc2653c42019-03-08 13:30:06 -0800172 // Returns true if the session has active request streams.
173 bool HasActiveRequestStreams() const;
174
renjietang3c3dfb72019-07-26 11:55:52 -0700175 // Called when the size of the compressed frame payload is available.
176 void OnCompressedFrameSize(size_t frame_len);
177
178 // Called when a PUSH_PROMISE frame has been received.
179 void OnPushPromise(spdy::SpdyStreamId stream_id,
180 spdy::SpdyStreamId promised_stream_id);
181
182 // Called when the complete list of headers is available.
183 void OnHeaderList(const QuicHeaderList& header_list);
184
185 QuicStreamId promised_stream_id() const { return promised_stream_id_; }
186
renjietangc04c85f2019-07-25 14:07:27 -0700187 // Initialze HTTP/3 unidirectional streams if |unidirectional| is true and
188 // those streams are not initialized yet.
189 void OnCanCreateNewOutgoingStream(bool unidirectional) override;
190
QUICHE teamc258e4f2019-08-14 10:04:58 -0700191 void set_max_allowed_push_id(QuicStreamId max_allowed_push_id);
192
193 QuicStreamId max_allowed_push_id() { return max_allowed_push_id_; }
194
QUICHE teama6ef0a62019-03-07 20:34:33 -0500195 protected:
196 // Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and
197 // CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
198 // make sure that all data streams are QuicSpdyStreams.
199 QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override = 0;
renjietangbaea59c2019-05-29 15:08:14 -0700200 QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override = 0;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500201 virtual QuicSpdyStream* CreateOutgoingBidirectionalStream() = 0;
202 virtual QuicSpdyStream* CreateOutgoingUnidirectionalStream() = 0;
203
204 QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id);
205
206 // If an incoming stream can be created, return true.
207 virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0;
208
209 // If an outgoing bidirectional/unidirectional stream can be created, return
210 // true.
211 virtual bool ShouldCreateOutgoingBidirectionalStream() = 0;
212 virtual bool ShouldCreateOutgoingUnidirectionalStream() = 0;
213
214 // Returns true if there are open HTTP requests.
215 bool ShouldKeepConnectionAlive() const override;
216
renjietange76b2da2019-05-13 14:50:23 -0700217 // Overridden to buffer incoming unidirectional streams for version 99.
218 bool UsesPendingStreams() const override;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500219
renjietangbb1c4892019-05-24 15:58:44 -0700220 // Overridden to Process HTTP/3 stream types. H/3 streams will be created from
221 // pending streams accordingly if the stream type can be read. Returns true if
222 // unidirectional streams are created.
223 bool ProcessPendingStream(PendingStream* pending) override;
renjietang0c558862019-05-08 13:26:23 -0700224
QUICHE teama6ef0a62019-03-07 20:34:33 -0500225 size_t WriteHeadersOnHeadersStreamImpl(
226 QuicStreamId id,
227 spdy::SpdyHeaderBlock headers,
228 bool fin,
229 QuicStreamId parent_stream_id,
230 int weight,
231 bool exclusive,
232 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
233
234 void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
235
236 bool supports_push_promise() { return supports_push_promise_; }
237
238 // Optional, enables instrumentation related to go/quic-hpack.
239 void SetHpackEncoderDebugVisitor(
240 std::unique_ptr<QuicHpackDebugVisitor> visitor);
241 void SetHpackDecoderDebugVisitor(
242 std::unique_ptr<QuicHpackDebugVisitor> visitor);
243
244 // Sets the maximum size of the header compression table spdy_framer_ is
245 // willing to use to encode header blocks.
246 void UpdateHeaderEncoderTableSize(uint32_t value);
247
248 // Called when SETTINGS_ENABLE_PUSH is received, only supported on
249 // server side.
250 void UpdateEnableServerPush(bool value);
251
252 bool IsConnected() { return connection()->connected(); }
253
renjietang118c8ac2019-07-30 11:43:59 -0700254 const QuicReceiveControlStream* receive_control_stream() const {
255 return receive_control_stream_;
256 }
257
renjietang1a33a0c2019-08-12 12:05:31 -0700258 // Initializes HTTP/3 unidirectional streams if not yet initialzed.
259 virtual void MaybeInitializeHttp3UnidirectionalStreams();
260
QUICHE teamc258e4f2019-08-14 10:04:58 -0700261 void set_max_uncompressed_header_bytes(
262 size_t set_max_uncompressed_header_bytes);
263
264 void SendMaxPushId(QuicStreamId max_allowed_push_id);
265
QUICHE teama6ef0a62019-03-07 20:34:33 -0500266 private:
267 friend class test::QuicSpdySessionPeer;
268
269 class SpdyFramerVisitor;
270
271 // The following methods are called by the SimpleVisitor.
272
273 // Called when a HEADERS frame has been received.
274 void OnHeaders(spdy::SpdyStreamId stream_id,
275 bool has_priority,
fayang476683a2019-07-25 12:42:16 -0700276 const spdy::SpdyStreamPrecedence& precedence,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500277 bool fin);
278
QUICHE teama6ef0a62019-03-07 20:34:33 -0500279 // Called when a PRIORITY frame has been received.
fayang476683a2019-07-25 12:42:16 -0700280 void OnPriority(spdy::SpdyStreamId stream_id,
281 const spdy::SpdyStreamPrecedence& precedence);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500282
QUICHE teama6ef0a62019-03-07 20:34:33 -0500283 std::unique_ptr<QpackEncoder> qpack_encoder_;
284 std::unique_ptr<QpackDecoder> qpack_decoder_;
285
renjietang9818f8c2019-07-16 11:12:27 -0700286 // Pointer to the header stream in stream_map_.
287 QuicHeadersStream* headers_stream_;
renjietangfbeb5bf2019-04-19 15:06:20 -0700288
renjietang87cd7de2019-08-16 08:35:10 -0700289 // HTTP/3 control streams. They are owned by QuicSession inside
renjietang3a1bb802019-06-11 10:42:41 -0700290 // stream map, and can be accessed by those unowned pointers below.
291 QuicSendControlStream* send_control_stream_;
292 QuicReceiveControlStream* receive_control_stream_;
293
renjietang87cd7de2019-08-16 08:35:10 -0700294 // Pointers to HTTP/3 QPACK streams in stream map.
295 QpackReceiveStream* qpack_encoder_receive_stream_;
296 QpackReceiveStream* qpack_decoder_receive_stream_;
297 QpackSendStream* qpack_encoder_send_stream_;
298 QpackSendStream* qpack_decoder_send_stream_;
299
QUICHE teama6ef0a62019-03-07 20:34:33 -0500300 // The maximum size of a header block that will be accepted from the peer,
301 // defined per spec as key + value + overhead per field (uncompressed).
302 size_t max_inbound_header_list_size_;
303
renjietang3a1bb802019-06-11 10:42:41 -0700304 // The maximum size of a header block that can be sent to the peer. This field
305 // is informed and set by the peer via SETTINGS frame.
306 // TODO(renjietang): Honor this field when sending headers.
307 size_t max_outbound_header_list_size_;
308
QUICHE teama6ef0a62019-03-07 20:34:33 -0500309 // Set during handshake. If true, resources in x-associated-content and link
310 // headers will be pushed.
311 bool server_push_enabled_;
312
313 // Data about the stream whose headers are being processed.
314 QuicStreamId stream_id_;
315 QuicStreamId promised_stream_id_;
316 bool fin_;
317 size_t frame_len_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500318
319 bool supports_push_promise_;
320
321 spdy::SpdyFramer spdy_framer_;
322 http2::Http2DecoderAdapter h2_deframer_;
323 std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
QUICHE teamc258e4f2019-08-14 10:04:58 -0700324 QuicStreamId max_allowed_push_id_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500325};
326
327} // namespace quic
328
329#endif // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_