blob: 00f241e27559a8659d43582cfc8b6448c910a721 [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>
10
11#include "base/macros.h"
12#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"
14#include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h"
15#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
16#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h"
17#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
18#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
19#include "net/third_party/quiche/src/quic/core/quic_session.h"
20#include "net/third_party/quiche/src/quic/core/quic_versions.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
22#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
23#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
24#include "net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h"
25
26namespace quic {
27
28namespace test {
29class QuicSpdySessionPeer;
30} // namespace test
31
32// QuicHpackDebugVisitor gathers data used for understanding HPACK HoL
33// dynamics. Specifically, it is to help predict the compression
34// penalty of avoiding HoL by chagning how the dynamic table is used.
35// In chromium, the concrete instance populates an UMA
36// histogram with the data.
37class QUIC_EXPORT_PRIVATE QuicHpackDebugVisitor {
38 public:
39 QuicHpackDebugVisitor();
40 QuicHpackDebugVisitor(const QuicHpackDebugVisitor&) = delete;
41 QuicHpackDebugVisitor& operator=(const QuicHpackDebugVisitor&) = delete;
42
43 virtual ~QuicHpackDebugVisitor();
44
45 // For each HPACK indexed representation processed, |elapsed| is
46 // the time since the corresponding entry was added to the dynamic
47 // table.
48 virtual void OnUseEntry(QuicTime::Delta elapsed) = 0;
49};
50
51// A QUIC session with a headers stream.
52class QUIC_EXPORT_PRIVATE QuicSpdySession
53 : public QuicSession,
54 public QpackEncoder::DecoderStreamErrorDelegate,
55 public QpackEncoderStreamSender::Delegate,
56 public QpackDecoder::EncoderStreamErrorDelegate,
57 public QpackDecoderStreamSender::Delegate {
58 public:
59 // Does not take ownership of |connection| or |visitor|.
60 QuicSpdySession(QuicConnection* connection,
61 QuicSession::Visitor* visitor,
62 const QuicConfig& config,
63 const ParsedQuicVersionVector& supported_versions);
64 QuicSpdySession(const QuicSpdySession&) = delete;
65 QuicSpdySession& operator=(const QuicSpdySession&) = delete;
66
67 ~QuicSpdySession() override;
68
69 void Initialize() override;
70
71 // QpackEncoder::DecoderStreamErrorDelegate implementation.
72 void OnDecoderStreamError(QuicStringPiece error_message) override;
73
74 // QpackEncoderStreamSender::Delegate implemenation.
75 void WriteEncoderStreamData(QuicStringPiece data) override;
76
77 // QpackDecoder::EncoderStreamErrorDelegate implementation.
78 void OnEncoderStreamError(QuicStringPiece error_message) override;
79
80 // QpackDecoderStreamSender::Delegate implementation.
81 void WriteDecoderStreamData(QuicStringPiece data) override;
82
83 // Called by |headers_stream_| when headers with a priority have been
84 // received for a stream. This method will only be called for server streams.
85 virtual void OnStreamHeadersPriority(QuicStreamId stream_id,
86 spdy::SpdyPriority priority);
87
88 // Called by |headers_stream_| when headers have been completely received
89 // for a stream. |fin| will be true if the fin flag was set in the headers
90 // frame.
91 virtual void OnStreamHeaderList(QuicStreamId stream_id,
92 bool fin,
93 size_t frame_len,
94 const QuicHeaderList& header_list);
95
96 // Called by |headers_stream_| when push promise headers have been
97 // completely received. |fin| will be true if the fin flag was set
98 // in the headers.
99 virtual void OnPromiseHeaderList(QuicStreamId stream_id,
100 QuicStreamId promised_stream_id,
101 size_t frame_len,
102 const QuicHeaderList& header_list);
103
104 // Called by |headers_stream_| when a PRIORITY frame has been received for a
105 // stream. This method will only be called for server streams.
106 virtual void OnPriorityFrame(QuicStreamId stream_id,
107 spdy::SpdyPriority priority);
108
109 // Sends contents of |iov| to h2_deframer_, returns number of bytes processed.
110 size_t ProcessHeaderData(const struct iovec& iov);
111
112 // Writes |headers| for the stream |id| to the dedicated headers stream.
113 // If |fin| is true, then no more data will be sent for the stream |id|.
114 // If provided, |ack_notifier_delegate| will be registered to be notified when
115 // we have seen ACKs for all packets resulting from this call.
116 virtual size_t WriteHeadersOnHeadersStream(
117 QuicStreamId id,
118 spdy::SpdyHeaderBlock headers,
119 bool fin,
120 spdy::SpdyPriority priority,
121 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
122
123 // Writes a PRIORITY frame the to peer. Returns the size in bytes of the
124 // resulting PRIORITY frame for QUIC_VERSION_43 and above. Otherwise, does
125 // nothing and returns 0.
126 size_t WritePriority(QuicStreamId id,
127 QuicStreamId parent_stream_id,
128 int weight,
129 bool exclusive);
130
131 // Write |headers| for |promised_stream_id| on |original_stream_id| in a
132 // PUSH_PROMISE frame to peer.
133 // Return the size, in bytes, of the resulting PUSH_PROMISE frame.
134 virtual size_t WritePushPromise(QuicStreamId original_stream_id,
135 QuicStreamId promised_stream_id,
136 spdy::SpdyHeaderBlock headers);
137
138 // Sends SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
139 size_t SendMaxHeaderListSize(size_t value);
140
141 QpackEncoder* qpack_encoder();
142 QpackDecoder* qpack_decoder();
143 QuicHeadersStream* headers_stream() { return headers_stream_.get(); }
144
145 bool server_push_enabled() const { return server_push_enabled_; }
146
147 // Called by |QuicHeadersStream::UpdateEnableServerPush()| with
148 // value from SETTINGS_ENABLE_PUSH.
149 void set_server_push_enabled(bool enable) { server_push_enabled_ = enable; }
150
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,
156 const QuicString& details);
157
158 void set_max_inbound_header_list_size(size_t max_inbound_header_list_size) {
159 max_inbound_header_list_size_ = max_inbound_header_list_size;
160 }
161
162 protected:
163 // Override CreateIncomingStream(), CreateOutgoingBidirectionalStream() and
164 // CreateOutgoingUnidirectionalStream() with QuicSpdyStream return type to
165 // make sure that all data streams are QuicSpdyStreams.
166 QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override = 0;
167 QuicSpdyStream* CreateIncomingStream(PendingStream pending) override = 0;
168 virtual QuicSpdyStream* CreateOutgoingBidirectionalStream() = 0;
169 virtual QuicSpdyStream* CreateOutgoingUnidirectionalStream() = 0;
170
171 QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id);
172
173 // If an incoming stream can be created, return true.
174 virtual bool ShouldCreateIncomingStream(QuicStreamId id) = 0;
175
176 // If an outgoing bidirectional/unidirectional stream can be created, return
177 // true.
178 virtual bool ShouldCreateOutgoingBidirectionalStream() = 0;
179 virtual bool ShouldCreateOutgoingUnidirectionalStream() = 0;
180
181 // Returns true if there are open HTTP requests.
182 bool ShouldKeepConnectionAlive() const override;
183
184 // Overridden to buffer incoming streams for version 99.
185 bool ShouldBufferIncomingStream(QuicStreamId id) const override;
186
187 size_t WriteHeadersOnHeadersStreamImpl(
188 QuicStreamId id,
189 spdy::SpdyHeaderBlock headers,
190 bool fin,
191 QuicStreamId parent_stream_id,
192 int weight,
193 bool exclusive,
194 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
195
196 void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
197
198 bool supports_push_promise() { return supports_push_promise_; }
199
200 // Optional, enables instrumentation related to go/quic-hpack.
201 void SetHpackEncoderDebugVisitor(
202 std::unique_ptr<QuicHpackDebugVisitor> visitor);
203 void SetHpackDecoderDebugVisitor(
204 std::unique_ptr<QuicHpackDebugVisitor> visitor);
205
206 // Sets the maximum size of the header compression table spdy_framer_ is
207 // willing to use to encode header blocks.
208 void UpdateHeaderEncoderTableSize(uint32_t value);
209
210 // Called when SETTINGS_ENABLE_PUSH is received, only supported on
211 // server side.
212 void UpdateEnableServerPush(bool value);
213
214 bool IsConnected() { return connection()->connected(); }
215
216 // Sets how much encoded data the hpack decoder of h2_deframer_ is willing to
217 // buffer.
218 void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) {
219 h2_deframer_.GetHpackDecoder()->set_max_decode_buffer_size_bytes(
220 max_decode_buffer_size_bytes);
221 }
222
223 void set_max_uncompressed_header_bytes(
224 size_t set_max_uncompressed_header_bytes);
225
226 private:
227 friend class test::QuicSpdySessionPeer;
228
229 class SpdyFramerVisitor;
230
231 // The following methods are called by the SimpleVisitor.
232
233 // Called when a HEADERS frame has been received.
234 void OnHeaders(spdy::SpdyStreamId stream_id,
235 bool has_priority,
236 spdy::SpdyPriority priority,
237 bool fin);
238
239 // Called when a PUSH_PROMISE frame has been received.
240 void OnPushPromise(spdy::SpdyStreamId stream_id,
241 spdy::SpdyStreamId promised_stream_id,
242 bool end);
243
244 // Called when a PRIORITY frame has been received.
245 void OnPriority(spdy::SpdyStreamId stream_id, spdy::SpdyPriority priority);
246
247 // Called when the complete list of headers is available.
248 void OnHeaderList(const QuicHeaderList& header_list);
249
250 // Called when the size of the compressed frame payload is available.
251 void OnCompressedFrameSize(size_t frame_len);
252
253 std::unique_ptr<QpackEncoder> qpack_encoder_;
254 std::unique_ptr<QpackDecoder> qpack_decoder_;
255
256 // TODO(123528590): Remove this member.
257 std::unique_ptr<QuicHeadersStream> headers_stream_;
258
259 // The maximum size of a header block that will be accepted from the peer,
260 // defined per spec as key + value + overhead per field (uncompressed).
261 size_t max_inbound_header_list_size_;
262
263 // Set during handshake. If true, resources in x-associated-content and link
264 // headers will be pushed.
265 bool server_push_enabled_;
266
267 // Data about the stream whose headers are being processed.
268 QuicStreamId stream_id_;
269 QuicStreamId promised_stream_id_;
270 bool fin_;
271 size_t frame_len_;
272 size_t uncompressed_frame_len_;
273
274 bool supports_push_promise_;
275
276 spdy::SpdyFramer spdy_framer_;
277 http2::Http2DecoderAdapter h2_deframer_;
278 std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
279};
280
281} // namespace quic
282
283#endif // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_