OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef NET_QUIC_CORE_QUIC_SPDY_SESSION_H_ | 5 #ifndef NET_QUIC_CORE_QUIC_SPDY_SESSION_H_ |
6 #define NET_QUIC_CORE_QUIC_SPDY_SESSION_H_ | 6 #define NET_QUIC_CORE_QUIC_SPDY_SESSION_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
11 | 11 |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "net/quic/core/quic_header_list.h" | 13 #include "net/quic/core/quic_header_list.h" |
14 #include "net/quic/core/quic_headers_stream.h" | 14 #include "net/quic/core/quic_headers_stream.h" |
15 #include "net/quic/core/quic_session.h" | 15 #include "net/quic/core/quic_session.h" |
16 #include "net/quic/core/quic_spdy_stream.h" | 16 #include "net/quic/core/quic_spdy_stream.h" |
17 #include "net/quic/platform/api/quic_export.h" | 17 #include "net/quic/platform/api/quic_export.h" |
18 | 18 |
19 namespace net { | 19 namespace net { |
20 | 20 |
21 namespace test { | 21 namespace test { |
22 class QuicSpdySessionPeer; | 22 class QuicSpdySessionPeer; |
23 } // namespace test | 23 } // namespace test |
24 | 24 |
| 25 // QuicHpackDebugVisitor gathers data used for understanding HPACK HoL |
| 26 // dynamics. Specifically, it is to help predict the compression |
| 27 // penalty of avoiding HoL by chagning how the dynamic table is used. |
| 28 // In chromium, the concrete instance populates an UMA |
| 29 // histogram with the data. |
| 30 class QUIC_EXPORT_PRIVATE QuicHpackDebugVisitor { |
| 31 public: |
| 32 QuicHpackDebugVisitor(); |
| 33 |
| 34 virtual ~QuicHpackDebugVisitor(); |
| 35 |
| 36 // For each HPACK indexed representation processed, |elapsed| is |
| 37 // the time since the corresponding entry was added to the dynamic |
| 38 // table. |
| 39 virtual void OnUseEntry(QuicTime::Delta elapsed) = 0; |
| 40 |
| 41 private: |
| 42 DISALLOW_COPY_AND_ASSIGN(QuicHpackDebugVisitor); |
| 43 }; |
| 44 |
25 // A QUIC session with a headers stream. | 45 // A QUIC session with a headers stream. |
26 class QUIC_EXPORT_PRIVATE QuicSpdySession : public QuicSession { | 46 class QUIC_EXPORT_PRIVATE QuicSpdySession : public QuicSession { |
27 public: | 47 public: |
28 // Does not take ownership of |connection| or |visitor|. | 48 // Does not take ownership of |connection| or |visitor|. |
29 QuicSpdySession(QuicConnection* connection, | 49 QuicSpdySession(QuicConnection* connection, |
30 QuicSession::Visitor* visitor, | 50 QuicSession::Visitor* visitor, |
31 const QuicConfig& config); | 51 const QuicConfig& config); |
32 | 52 |
33 ~QuicSpdySession() override; | 53 ~QuicSpdySession() override; |
34 | 54 |
(...skipping 14 matching lines...) Expand all Loading... |
49 const QuicHeaderList& header_list); | 69 const QuicHeaderList& header_list); |
50 | 70 |
51 // Called by |headers_stream_| when push promise headers have been | 71 // Called by |headers_stream_| when push promise headers have been |
52 // completely received. |fin| will be true if the fin flag was set | 72 // completely received. |fin| will be true if the fin flag was set |
53 // in the headers. | 73 // in the headers. |
54 virtual void OnPromiseHeaderList(QuicStreamId stream_id, | 74 virtual void OnPromiseHeaderList(QuicStreamId stream_id, |
55 QuicStreamId promised_stream_id, | 75 QuicStreamId promised_stream_id, |
56 size_t frame_len, | 76 size_t frame_len, |
57 const QuicHeaderList& header_list); | 77 const QuicHeaderList& header_list); |
58 | 78 |
| 79 // Sends contents of |iov| to spdy_framer_, returns number of bytes processd. |
| 80 size_t ProcessHeaderData(const struct iovec& iov, QuicTime timestamp); |
| 81 |
59 // Writes |headers| for the stream |id| to the dedicated headers stream. | 82 // Writes |headers| for the stream |id| to the dedicated headers stream. |
60 // If |fin| is true, then no more data will be sent for the stream |id|. | 83 // If |fin| is true, then no more data will be sent for the stream |id|. |
61 // If provided, |ack_notifier_delegate| will be registered to be notified when | 84 // If provided, |ack_notifier_delegate| will be registered to be notified when |
62 // we have seen ACKs for all packets resulting from this call. | 85 // we have seen ACKs for all packets resulting from this call. |
63 virtual size_t WriteHeaders( | 86 virtual size_t WriteHeaders( |
64 QuicStreamId id, | 87 QuicStreamId id, |
65 SpdyHeaderBlock headers, | 88 SpdyHeaderBlock headers, |
66 bool fin, | 89 bool fin, |
67 SpdyPriority priority, | 90 SpdyPriority priority, |
68 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); | 91 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); |
69 | 92 |
| 93 // Write |headers| for |promised_stream_id| on |original_stream_id| in a |
| 94 // PUSH_PROMISE frame to peer. |
| 95 // Return the size, in bytes, of the resulting PUSH_PROMISE frame. |
| 96 virtual size_t WritePushPromise(QuicStreamId original_stream_id, |
| 97 QuicStreamId promised_stream_id, |
| 98 SpdyHeaderBlock headers); |
| 99 |
| 100 // For forcing HOL blocking. This encapsulates data from other |
| 101 // streams into HTTP/2 data frames on the headers stream. |
| 102 QuicConsumedData WritevStreamData( |
| 103 QuicStreamId id, |
| 104 QuicIOVector iov, |
| 105 QuicStreamOffset offset, |
| 106 bool fin, |
| 107 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); |
| 108 |
| 109 // Sends SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame. |
| 110 size_t SendMaxHeaderListSize(size_t value); |
| 111 |
70 QuicHeadersStream* headers_stream() { return headers_stream_.get(); } | 112 QuicHeadersStream* headers_stream() { return headers_stream_.get(); } |
71 | 113 |
72 // Called when Head of Line Blocking happens in the headers stream. | 114 // Called when Head of Line Blocking happens in the headers stream. |
73 // |delta| indicates how long that piece of data has been blocked. | 115 // |delta| indicates how long that piece of data has been blocked. |
74 virtual void OnHeadersHeadOfLineBlocking(QuicTime::Delta delta); | 116 virtual void OnHeadersHeadOfLineBlocking(QuicTime::Delta delta); |
75 | 117 |
76 // Called by the stream on creation to set priority in the write blocked list. | 118 // Called by the stream on creation to set priority in the write blocked list. |
77 void RegisterStreamPriority(QuicStreamId id, SpdyPriority priority); | 119 void RegisterStreamPriority(QuicStreamId id, SpdyPriority priority); |
78 // Called by the stream on deletion to clear priority crom the write blocked | 120 // Called by the stream on deletion to clear priority crom the write blocked |
79 // list. | 121 // list. |
80 void UnregisterStreamPriority(QuicStreamId id); | 122 void UnregisterStreamPriority(QuicStreamId id); |
81 // Called by the stream on SetPriority to update priority on the write blocked | 123 // Called by the stream on SetPriority to update priority on the write blocked |
82 // list. | 124 // list. |
83 void UpdateStreamPriority(QuicStreamId id, SpdyPriority new_priority); | 125 void UpdateStreamPriority(QuicStreamId id, SpdyPriority new_priority); |
84 | 126 |
85 void OnConfigNegotiated() override; | 127 void OnConfigNegotiated() override; |
86 | 128 |
87 // Called by |headers_stream_| when |force_hol_blocking_| is true. | 129 // Called by |headers_stream_| when |force_hol_blocking_| is true. |
88 virtual void OnStreamFrameData(QuicStreamId stream_id, | 130 virtual void OnStreamFrameData(QuicStreamId stream_id, |
89 const char* data, | 131 const char* data, |
90 size_t len, | 132 size_t len, |
91 bool fin); | 133 bool fin); |
92 | 134 |
93 bool force_hol_blocking() const { return force_hol_blocking_; } | 135 bool force_hol_blocking() const { return force_hol_blocking_; } |
94 | 136 |
95 bool server_push_enabled() const { return server_push_enabled_; } | 137 bool server_push_enabled() const { return server_push_enabled_; } |
96 | 138 |
| 139 void UpdateCurMaxTimeStamp(QuicTime timestamp) { |
| 140 cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_); |
| 141 } |
| 142 |
97 // Called by |QuicHeadersStream::UpdateEnableServerPush()| with | 143 // Called by |QuicHeadersStream::UpdateEnableServerPush()| with |
98 // value from SETTINGS_ENABLE_PUSH. | 144 // value from SETTINGS_ENABLE_PUSH. |
99 void set_server_push_enabled(bool enable) { server_push_enabled_ = enable; } | 145 void set_server_push_enabled(bool enable) { server_push_enabled_ = enable; } |
100 | 146 |
101 // Return true if this session wants to release headers stream's buffer | 147 // Return true if this session wants to release headers stream's buffer |
102 // aggressively. | 148 // aggressively. |
103 virtual bool ShouldReleaseHeadersStreamSequencerBuffer(); | 149 virtual bool ShouldReleaseHeadersStreamSequencerBuffer(); |
104 | 150 |
| 151 SpdyFramer* spdy_framer() { return &spdy_framer_; } |
| 152 |
| 153 void CloseConnectionWithDetails(QuicErrorCode error, |
| 154 const std::string& details); |
| 155 |
| 156 // Sets how much encoded data the hpack decoder of spdy_framer_ is willing to |
| 157 // buffer. |
| 158 void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) { |
| 159 spdy_framer_.set_max_decode_buffer_size_bytes(max_decode_buffer_size_bytes); |
| 160 } |
| 161 |
105 protected: | 162 protected: |
106 // Override CreateIncomingDynamicStream() and CreateOutgoingDynamicStream() | 163 // Override CreateIncomingDynamicStream() and CreateOutgoingDynamicStream() |
107 // with QuicSpdyStream return type to make sure that all data streams are | 164 // with QuicSpdyStream return type to make sure that all data streams are |
108 // QuicSpdyStreams. | 165 // QuicSpdyStreams. |
109 QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override = 0; | 166 QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override = 0; |
110 QuicSpdyStream* CreateOutgoingDynamicStream(SpdyPriority priority) override = | 167 QuicSpdyStream* CreateOutgoingDynamicStream(SpdyPriority priority) override = |
111 0; | 168 0; |
112 | 169 |
113 QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id); | 170 QuicSpdyStream* GetSpdyDataStream(const QuicStreamId stream_id); |
114 | 171 |
115 // If an incoming stream can be created, return true. | 172 // If an incoming stream can be created, return true. |
116 virtual bool ShouldCreateIncomingDynamicStream(QuicStreamId id) = 0; | 173 virtual bool ShouldCreateIncomingDynamicStream(QuicStreamId id) = 0; |
117 | 174 |
118 // If an outgoing stream can be created, return true. | 175 // If an outgoing stream can be created, return true. |
119 virtual bool ShouldCreateOutgoingDynamicStream() = 0; | 176 virtual bool ShouldCreateOutgoingDynamicStream() = 0; |
120 | 177 |
121 void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override; | 178 void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override; |
122 | 179 |
| 180 bool supports_push_promise() { return supports_push_promise_; } |
| 181 |
| 182 // Experimental: force HPACK to use static table and huffman coding |
| 183 // only. Part of exploring improvements related to headers stream |
| 184 // induced HOL blocking in QUIC. |
| 185 void DisableHpackDynamicTable(); |
| 186 |
| 187 // Optional, enables instrumentation related to go/quic-hpack. |
| 188 void SetHpackEncoderDebugVisitor( |
| 189 std::unique_ptr<QuicHpackDebugVisitor> visitor); |
| 190 void SetHpackDecoderDebugVisitor( |
| 191 std::unique_ptr<QuicHpackDebugVisitor> visitor); |
| 192 |
| 193 // Sets the maximum size of the header compression table spdy_framer_ is |
| 194 // willing to use to decode header blocks. |
| 195 void UpdateHeaderEncoderTableSize(uint32_t value); |
| 196 |
| 197 // Called when SETTINGS_ENABLE_PUSH is received, only supported on |
| 198 // server side. |
| 199 void UpdateEnableServerPush(bool value); |
| 200 |
| 201 void set_max_uncompressed_header_bytes( |
| 202 size_t set_max_uncompressed_header_bytes); |
| 203 |
| 204 bool IsConnected() { return connection()->connected(); } |
| 205 |
123 private: | 206 private: |
124 friend class test::QuicSpdySessionPeer; | 207 friend class test::QuicSpdySessionPeer; |
125 | 208 |
| 209 class SpdyFramerVisitor; |
| 210 |
| 211 // The following methods are called by the SimpleVisitor. |
| 212 |
| 213 // Called when a HEADERS frame has been received. |
| 214 void OnHeaders(SpdyStreamId stream_id, |
| 215 bool has_priority, |
| 216 SpdyPriority priority, |
| 217 bool fin); |
| 218 |
| 219 // Called when a PUSH_PROMISE frame has been received. |
| 220 void OnPushPromise(SpdyStreamId stream_id, |
| 221 SpdyStreamId promised_stream_id, |
| 222 bool end); |
| 223 |
| 224 // Called when the complete list of headers is available. |
| 225 void OnHeaderList(const QuicHeaderList& header_list); |
| 226 |
| 227 // Called when the size of the compressed frame payload is available. |
| 228 void OnCompressedFrameSize(size_t frame_len); |
| 229 |
| 230 // For force HOL blocking, where stream frames from all streams are |
| 231 // plumbed through headers stream as HTTP/2 data frames. |
| 232 // The following two return false if force_hol_blocking_ is false. |
| 233 bool OnDataFrameHeader(QuicStreamId stream_id, size_t length, bool fin); |
| 234 bool OnStreamFrameData(QuicStreamId stream_id, const char* data, size_t len); |
| 235 |
| 236 // Helper for |WritevStreamData()|. |
| 237 void WriteDataFrame( |
| 238 QuicStreamId stream_id, |
| 239 base::StringPiece data, |
| 240 bool fin, |
| 241 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); |
| 242 |
| 243 // This was formerly QuicHeadersStream::WriteHeaders. Needs to be |
| 244 // separate from QuicSpdySession::WriteHeaders because tests call |
| 245 // this but mock the latter. |
| 246 size_t WriteHeadersImpl( |
| 247 QuicStreamId id, |
| 248 SpdyHeaderBlock headers, |
| 249 bool fin, |
| 250 SpdyPriority priority, |
| 251 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener); |
| 252 |
126 std::unique_ptr<QuicHeadersStream> headers_stream_; | 253 std::unique_ptr<QuicHeadersStream> headers_stream_; |
127 | 254 |
128 // If set, redirect all data through the headers stream in order to | 255 // If set, redirect all data through the headers stream in order to |
129 // simulate forced HOL blocking between streams as happens in | 256 // simulate forced HOL blocking between streams as happens in |
130 // HTTP/2 over TCP. | 257 // HTTP/2 over TCP. |
131 bool force_hol_blocking_; | 258 bool force_hol_blocking_; |
132 | 259 |
133 // Set during handshake. If true, resources in x-associated-content and link | 260 // Set during handshake. If true, resources in x-associated-content and link |
134 // headers will be pushed. | 261 // headers will be pushed. |
135 bool server_push_enabled_; | 262 bool server_push_enabled_; |
136 | 263 |
| 264 // Data about the stream whose headers are being processed. |
| 265 QuicStreamId stream_id_; |
| 266 QuicStreamId promised_stream_id_; |
| 267 bool fin_; |
| 268 size_t frame_len_; |
| 269 size_t uncompressed_frame_len_; |
| 270 |
| 271 bool supports_push_promise_; |
| 272 |
| 273 // Timestamps used to measure HOL blocking, these are recorded by |
| 274 // the sequencer approximate to the time of arrival off the wire. |
| 275 // |cur_max_timestamp_| tracks the most recent arrival time of |
| 276 // frames for current (at the headers stream level) processed |
| 277 // stream's headers, and |prev_max_timestamp_| tracks the most |
| 278 // recent arrival time of lower numbered streams. |
| 279 QuicTime cur_max_timestamp_; |
| 280 QuicTime prev_max_timestamp_; |
| 281 |
| 282 SpdyFramer spdy_framer_; |
| 283 std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_; |
| 284 |
137 DISALLOW_COPY_AND_ASSIGN(QuicSpdySession); | 285 DISALLOW_COPY_AND_ASSIGN(QuicSpdySession); |
138 }; | 286 }; |
139 | 287 |
140 } // namespace net | 288 } // namespace net |
141 | 289 |
142 #endif // NET_QUIC_CORE_QUIC_SPDY_SESSION_H_ | 290 #endif // NET_QUIC_CORE_QUIC_SPDY_SESSION_H_ |
OLD | NEW |