Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: net/quic/core/quic_spdy_session.cc

Issue 2609493002: Landing Recent QUIC changes until 05:15 PM, Dec 24, 2016 UTC (Closed)
Patch Set: Fix random. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/core/quic_spdy_session.h ('k') | net/quic/core/quic_spdy_stream.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "net/quic/core/quic_spdy_session.h" 5 #include "net/quic/core/quic_spdy_session.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "net/quic/core/quic_bug_tracker.h" 9 #include "net/quic/core/quic_bug_tracker.h"
10 #include "net/quic/core/quic_flags.h"
10 #include "net/quic/core/quic_headers_stream.h" 11 #include "net/quic/core/quic_headers_stream.h"
12 #include "net/quic/platform/api/quic_str_cat.h"
11 13
12 using base::StringPiece; 14 using base::StringPiece;
13 using std::string; 15 using std::string;
14 16
15 namespace net { 17 namespace net {
16 18
19 namespace {
20
21 class HeaderTableDebugVisitor
22 : public HpackHeaderTable::DebugVisitorInterface {
23 public:
24 HeaderTableDebugVisitor(const QuicClock* clock,
25 std::unique_ptr<QuicHpackDebugVisitor> visitor)
26 : clock_(clock), headers_stream_hpack_visitor_(std::move(visitor)) {}
27
28 int64_t OnNewEntry(const HpackEntry& entry) override {
29 DVLOG(1) << entry.GetDebugString();
30 return (clock_->ApproximateNow() - QuicTime::Zero()).ToMicroseconds();
31 }
32
33 void OnUseEntry(const HpackEntry& entry) override {
34 const QuicTime::Delta elapsed(
35 clock_->ApproximateNow() -
36 QuicTime::Delta::FromMicroseconds(entry.time_added()) -
37 QuicTime::Zero());
38 DVLOG(1) << entry.GetDebugString() << " " << elapsed.ToMilliseconds()
39 << " ms";
40 headers_stream_hpack_visitor_->OnUseEntry(elapsed);
41 }
42
43 private:
44 const QuicClock* clock_;
45 std::unique_ptr<QuicHpackDebugVisitor> headers_stream_hpack_visitor_;
46
47 DISALLOW_COPY_AND_ASSIGN(HeaderTableDebugVisitor);
48 };
49
50 // When forced HOL blocking is enabled, extra bytes in the form of
51 // HTTP/2 DATA frame headers are inserted on the way down to the
52 // session layer. |ForceAckListener| filters the |OnPacketAcked()|
53 // notifications generated by the session layer to not count the extra
54 // bytes. Otherwise, code that is using ack listener on streams might
55 // consider it an error if more bytes are acked than were written to
56 // the stream, it is the case with some internal stats gathering code.
57 class ForceHolAckListener : public QuicAckListenerInterface {
58 public:
59 // |extra_bytes| should be initialized to the size of the HTTP/2
60 // DATA frame header inserted when forced HOL blocking is enabled.
61 ForceHolAckListener(
62 QuicReferenceCountedPointer<QuicAckListenerInterface> stream_ack_listener,
63 int extra_bytes)
64 : stream_ack_listener_(std::move(stream_ack_listener)),
65 extra_bytes_(extra_bytes) {
66 DCHECK_GE(extra_bytes, 0);
67 }
68
69 void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override {
70 if (extra_bytes_ > 0) {
71 // Don't count the added HTTP/2 DATA frame header bytes
72 int delta = std::min(extra_bytes_, acked_bytes);
73 extra_bytes_ -= delta;
74 acked_bytes -= delta;
75 }
76 stream_ack_listener_->OnPacketAcked(acked_bytes, ack_delay_time);
77 }
78
79 void OnPacketRetransmitted(int retransmitted_bytes) override {
80 stream_ack_listener_->OnPacketRetransmitted(retransmitted_bytes);
81 }
82
83 protected:
84 ~ForceHolAckListener() override {}
85
86 private:
87 QuicReferenceCountedPointer<QuicAckListenerInterface> stream_ack_listener_;
88 int extra_bytes_;
89
90 DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener);
91 };
92
93 } // namespace
94
95 // A SpdyFramerVisitor that passes HEADERS frames to the QuicSpdyStream, and
96 // closes the connection if any unexpected frames are received.
97 class QuicSpdySession::SpdyFramerVisitor
98 : public SpdyFramerVisitorInterface,
99 public SpdyFramerDebugVisitorInterface {
100 public:
101 explicit SpdyFramerVisitor(QuicSpdySession* session) : session_(session) {}
102
103 SpdyHeadersHandlerInterface* OnHeaderFrameStart(
104 SpdyStreamId /* stream_id */) override {
105 return &header_list_;
106 }
107
108 void OnHeaderFrameEnd(SpdyStreamId /* stream_id */,
109 bool end_headers) override {
110 if (end_headers) {
111 if (session_->IsConnected()) {
112 session_->OnHeaderList(header_list_);
113 }
114 header_list_.Clear();
115 }
116 }
117
118 void OnStreamFrameData(SpdyStreamId stream_id,
119 const char* data,
120 size_t len) override {
121 if (session_->OnStreamFrameData(stream_id, data, len)) {
122 return;
123 }
124 CloseConnection("SPDY DATA frame received.");
125 }
126
127 void OnStreamEnd(SpdyStreamId stream_id) override {
128 // The framer invokes OnStreamEnd after processing a frame that had the fin
129 // bit set.
130 }
131
132 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
133 CloseConnection("SPDY frame padding received.");
134 }
135
136 void OnError(SpdyFramer* framer) override {
137 CloseConnection(
138 QuicStrCat("SPDY framing error: ",
139 SpdyFramer::ErrorCodeToString(framer->error_code())));
140 }
141
142 void OnDataFrameHeader(SpdyStreamId stream_id,
143 size_t length,
144 bool fin) override {
145 if (session_->OnDataFrameHeader(stream_id, length, fin)) {
146 return;
147 }
148 CloseConnection("SPDY DATA frame received.");
149 }
150
151 void OnRstStream(SpdyStreamId stream_id,
152 SpdyRstStreamStatus status) override {
153 CloseConnection("SPDY RST_STREAM frame received.");
154 }
155
156 void OnSetting(SpdySettingsIds id, uint32_t value) override {
157 if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
158 CloseConnection("SPDY SETTINGS frame received.");
159 return;
160 }
161 switch (id) {
162 case SETTINGS_HEADER_TABLE_SIZE:
163 session_->UpdateHeaderEncoderTableSize(value);
164 break;
165 case SETTINGS_ENABLE_PUSH:
166 if (FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default &&
167 session_->perspective() == Perspective::IS_SERVER) {
168 // See rfc7540, Section 6.5.2.
169 if (value > 1) {
170 CloseConnection(
171 QuicStrCat("Invalid value for SETTINGS_ENABLE_PUSH: ", value));
172 return;
173 }
174 session_->UpdateEnableServerPush(value > 0);
175 break;
176 } else {
177 CloseConnection(
178 QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
179 }
180 break;
181 // TODO(fayang): Need to support SETTINGS_MAX_HEADER_LIST_SIZE when
182 // clients are actually sending it.
183 case SETTINGS_MAX_HEADER_LIST_SIZE:
184 if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size) {
185 break;
186 }
187 default:
188 CloseConnection(
189 QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
190 }
191 }
192
193 void OnSettingsAck() override {
194 if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
195 CloseConnection("SPDY SETTINGS frame received.");
196 }
197 }
198
199 void OnSettingsEnd() override {
200 if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
201 CloseConnection("SPDY SETTINGS frame received.");
202 }
203 }
204
205 void OnPing(SpdyPingId unique_id, bool is_ack) override {
206 CloseConnection("SPDY PING frame received.");
207 }
208
209 void OnGoAway(SpdyStreamId last_accepted_stream_id,
210 SpdyGoAwayStatus status) override {
211 CloseConnection("SPDY GOAWAY frame received.");
212 }
213
214 void OnHeaders(SpdyStreamId stream_id,
215 bool has_priority,
216 int weight,
217 SpdyStreamId /*parent_stream_id*/,
218 bool /*exclusive*/,
219 bool fin,
220 bool end) override {
221 if (!session_->IsConnected()) {
222 return;
223 }
224
225 // TODO(mpw): avoid down-conversion and plumb SpdyStreamPrecedence through
226 // QuicHeadersStream.
227 SpdyPriority priority =
228 has_priority ? Http2WeightToSpdy3Priority(weight) : 0;
229 session_->OnHeaders(stream_id, has_priority, priority, fin);
230 }
231
232 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
233 CloseConnection("SPDY WINDOW_UPDATE frame received.");
234 }
235
236 void OnPushPromise(SpdyStreamId stream_id,
237 SpdyStreamId promised_stream_id,
238 bool end) override {
239 if (!session_->supports_push_promise()) {
240 CloseConnection("PUSH_PROMISE not supported.");
241 return;
242 }
243 if (!session_->IsConnected()) {
244 return;
245 }
246 session_->OnPushPromise(stream_id, promised_stream_id, end);
247 }
248
249 void OnContinuation(SpdyStreamId stream_id, bool end) override {}
250
251 void OnPriority(SpdyStreamId stream_id,
252 SpdyStreamId parent_id,
253 int weight,
254 bool exclusive) override {
255 CloseConnection("SPDY PRIORITY frame received.");
256 }
257
258 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
259 CloseConnection("Unknown frame type received.");
260 return false;
261 }
262
263 // SpdyFramerDebugVisitorInterface implementation
264 void OnSendCompressedFrame(SpdyStreamId stream_id,
265 SpdyFrameType type,
266 size_t payload_len,
267 size_t frame_len) override {
268 if (payload_len == 0) {
269 QUIC_BUG << "Zero payload length.";
270 return;
271 }
272 int compression_pct = 100 - (100 * frame_len) / payload_len;
273 DVLOG(1) << "Net.QuicHpackCompressionPercentage: " << compression_pct;
274 }
275
276 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
277 SpdyFrameType type,
278 size_t frame_len) override {
279 if (session_->IsConnected()) {
280 session_->OnCompressedFrameSize(frame_len);
281 }
282 }
283
284 void set_max_uncompressed_header_bytes(
285 size_t set_max_uncompressed_header_bytes) {
286 header_list_.set_max_uncompressed_header_bytes(
287 set_max_uncompressed_header_bytes);
288 }
289
290 private:
291 void CloseConnection(const string& details) {
292 if (session_->IsConnected()) {
293 session_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
294 details);
295 }
296 }
297
298 private:
299 QuicSpdySession* session_;
300 QuicHeaderList header_list_;
301
302 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
303 };
304
305 QuicHpackDebugVisitor::QuicHpackDebugVisitor() {}
306
307 QuicHpackDebugVisitor::~QuicHpackDebugVisitor() {}
308
17 QuicSpdySession::QuicSpdySession(QuicConnection* connection, 309 QuicSpdySession::QuicSpdySession(QuicConnection* connection,
18 QuicSession::Visitor* visitor, 310 QuicSession::Visitor* visitor,
19 const QuicConfig& config) 311 const QuicConfig& config)
20 : QuicSession(connection, visitor, config), 312 : QuicSession(connection, visitor, config),
21 force_hol_blocking_(false), 313 force_hol_blocking_(false),
22 server_push_enabled_(false) {} 314 server_push_enabled_(false),
315 stream_id_(kInvalidStreamId),
316 promised_stream_id_(kInvalidStreamId),
317 fin_(false),
318 frame_len_(0),
319 uncompressed_frame_len_(0),
320 supports_push_promise_(perspective() == Perspective::IS_CLIENT),
321 cur_max_timestamp_(QuicTime::Zero()),
322 prev_max_timestamp_(QuicTime::Zero()),
323 spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
324 spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
325 spdy_framer_.set_visitor(spdy_framer_visitor_.get());
326 spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
327 }
23 328
24 QuicSpdySession::~QuicSpdySession() { 329 QuicSpdySession::~QuicSpdySession() {
25 // Set the streams' session pointers in closed and dynamic stream lists 330 // Set the streams' session pointers in closed and dynamic stream lists
26 // to null to avoid subsequent use of this session. 331 // to null to avoid subsequent use of this session.
27 for (auto& stream : *closed_streams()) { 332 for (auto& stream : *closed_streams()) {
28 static_cast<QuicSpdyStream*>(stream.get())->ClearSession(); 333 static_cast<QuicSpdyStream*>(stream.get())->ClearSession();
29 } 334 }
30 for (auto const& kv : dynamic_streams()) { 335 for (auto const& kv : dynamic_streams()) {
31 static_cast<QuicSpdyStream*>(kv.second.get())->ClearSession(); 336 static_cast<QuicSpdyStream*>(kv.second.get())->ClearSession();
32 } 337 }
(...skipping 29 matching lines...) Expand all
62 size_t frame_len, 367 size_t frame_len,
63 const QuicHeaderList& header_list) { 368 const QuicHeaderList& header_list) {
64 QuicSpdyStream* stream = GetSpdyDataStream(stream_id); 369 QuicSpdyStream* stream = GetSpdyDataStream(stream_id);
65 if (!stream) { 370 if (!stream) {
66 // It's quite possible to receive headers after a stream has been reset. 371 // It's quite possible to receive headers after a stream has been reset.
67 return; 372 return;
68 } 373 }
69 stream->OnStreamHeaderList(fin, frame_len, header_list); 374 stream->OnStreamHeaderList(fin, frame_len, header_list);
70 } 375 }
71 376
377 size_t QuicSpdySession::ProcessHeaderData(const struct iovec& iov,
378 QuicTime timestamp) {
379 DCHECK(timestamp.IsInitialized());
380 UpdateCurMaxTimeStamp(timestamp);
381 return spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base),
382 iov.iov_len);
383 }
384
72 size_t QuicSpdySession::WriteHeaders( 385 size_t QuicSpdySession::WriteHeaders(
73 QuicStreamId id, 386 QuicStreamId id,
74 SpdyHeaderBlock headers, 387 SpdyHeaderBlock headers,
75 bool fin, 388 bool fin,
76 SpdyPriority priority, 389 SpdyPriority priority,
77 QuicReferenceCountedPointer<QuicAckListenerInterface> 390 QuicReferenceCountedPointer<QuicAckListenerInterface>
78 ack_notifier_delegate) { 391 ack_notifier_delegate) {
79 return headers_stream_->WriteHeaders(id, std::move(headers), fin, priority, 392 return WriteHeadersImpl(id, std::move(headers), fin, priority,
80 std::move(ack_notifier_delegate)); 393 std::move(ack_notifier_delegate));
394 }
395
396 size_t QuicSpdySession::WriteHeadersImpl(
397 QuicStreamId id,
398 SpdyHeaderBlock headers,
399 bool fin,
400 SpdyPriority priority,
401 QuicReferenceCountedPointer<QuicAckListenerInterface>
402 ack_notifier_delegate) {
403 SpdyHeadersIR headers_frame(id, std::move(headers));
404 headers_frame.set_fin(fin);
405 if (perspective() == Perspective::IS_CLIENT) {
406 headers_frame.set_has_priority(true);
407 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority));
408 }
409 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
410 headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
411 false, std::move(ack_notifier_delegate));
412 return frame.size();
413 }
414
415 size_t QuicSpdySession::WritePushPromise(QuicStreamId original_stream_id,
416 QuicStreamId promised_stream_id,
417 SpdyHeaderBlock headers) {
418 if (perspective() == Perspective::IS_CLIENT) {
419 QUIC_BUG << "Client shouldn't send PUSH_PROMISE";
420 return 0;
421 }
422
423 SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
424 std::move(headers));
425 // PUSH_PROMISE must not be the last frame sent out, at least followed by
426 // response headers.
427 push_promise.set_fin(false);
428
429 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
430 headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
431 false, nullptr);
432 return frame.size();
433 }
434
435 void QuicSpdySession::WriteDataFrame(
436 QuicStreamId id,
437 StringPiece data,
438 bool fin,
439 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
440 SpdyDataIR spdy_data(id, data);
441 spdy_data.set_fin(fin);
442 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
443 QuicReferenceCountedPointer<ForceHolAckListener> force_hol_ack_listener;
444 if (ack_listener != nullptr) {
445 force_hol_ack_listener = new ForceHolAckListener(
446 std::move(ack_listener), frame.size() - data.length());
447 }
448 // Use buffered writes so that coherence of framing is preserved
449 // between streams.
450 headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
451 false, std::move(force_hol_ack_listener));
452 }
453
454 QuicConsumedData QuicSpdySession::WritevStreamData(
455 QuicStreamId id,
456 QuicIOVector iov,
457 QuicStreamOffset offset,
458 bool fin,
459 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
460 const size_t max_len =
461 kSpdyInitialFrameSizeLimit - kDataFrameMinimumSize;
462
463 QuicConsumedData result(0, false);
464 size_t total_length = iov.total_length;
465
466 if (total_length == 0 && fin) {
467 WriteDataFrame(id, StringPiece(), true, std::move(ack_listener));
468 result.fin_consumed = true;
469 return result;
470 }
471
472 // Encapsulate the data into HTTP/2 DATA frames. The outer loop
473 // handles each element of the source iov, the inner loop handles
474 // the possibility of fragmenting each of those into multiple DATA
475 // frames, as the DATA frames have a max size of 16KB.
476 for (int i = 0; i < iov.iov_count; i++) {
477 size_t src_iov_offset = 0;
478 const struct iovec* src_iov = &iov.iov[i];
479 do {
480 if (headers_stream_->queued_data_bytes() > 0) {
481 // Limit the amount of buffering to the minimum needed to
482 // preserve framing.
483 return result;
484 }
485 size_t len = std::min(
486 std::min(src_iov->iov_len - src_iov_offset, max_len), total_length);
487 char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset;
488 src_iov_offset += len;
489 offset += len;
490 // fin handling, only set it for the final HTTP/2 DATA frame.
491 bool last_iov = i == iov.iov_count - 1;
492 bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len;
493 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
494 WriteDataFrame(id, StringPiece(data, len), frame_fin, ack_listener);
495 result.bytes_consumed += len;
496 if (frame_fin) {
497 result.fin_consumed = true;
498 }
499 DCHECK_GE(total_length, len);
500 total_length -= len;
501 if (total_length <= 0) {
502 return result;
503 }
504 } while (src_iov_offset < src_iov->iov_len);
505 }
506
507 return result;
508 }
509
510 size_t QuicSpdySession::SendMaxHeaderListSize(size_t value) {
511 SpdySettingsIR settings_frame;
512 settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, value);
513
514 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame));
515 headers_stream_->WriteOrBufferData(StringPiece(frame.data(), frame.size()),
516 false, nullptr);
517 return frame.size();
81 } 518 }
82 519
83 void QuicSpdySession::OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) { 520 void QuicSpdySession::OnHeadersHeadOfLineBlocking(QuicTime::Delta delta) {
84 // Implemented in Chromium for stats tracking. 521 // Implemented in Chromium for stats tracking.
85 } 522 }
86 523
87 void QuicSpdySession::RegisterStreamPriority(QuicStreamId id, 524 void QuicSpdySession::RegisterStreamPriority(QuicStreamId id,
88 SpdyPriority priority) { 525 SpdyPriority priority) {
89 write_blocked_streams()->RegisterStream(id, priority); 526 write_blocked_streams()->RegisterStream(id, priority);
90 } 527 }
91 528
92 void QuicSpdySession::UnregisterStreamPriority(QuicStreamId id) { 529 void QuicSpdySession::UnregisterStreamPriority(QuicStreamId id) {
93 write_blocked_streams()->UnregisterStream(id); 530 write_blocked_streams()->UnregisterStream(id);
94 } 531 }
95 532
96 void QuicSpdySession::UpdateStreamPriority(QuicStreamId id, 533 void QuicSpdySession::UpdateStreamPriority(QuicStreamId id,
97 SpdyPriority new_priority) { 534 SpdyPriority new_priority) {
98 write_blocked_streams()->UpdateStreamPriority(id, new_priority); 535 write_blocked_streams()->UpdateStreamPriority(id, new_priority);
99 } 536 }
100 537
101 QuicSpdyStream* QuicSpdySession::GetSpdyDataStream( 538 QuicSpdyStream* QuicSpdySession::GetSpdyDataStream(
102 const QuicStreamId stream_id) { 539 const QuicStreamId stream_id) {
103 return static_cast<QuicSpdyStream*>(GetOrCreateDynamicStream(stream_id)); 540 return static_cast<QuicSpdyStream*>(GetOrCreateDynamicStream(stream_id));
104 } 541 }
105 542
106 void QuicSpdySession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { 543 void QuicSpdySession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
107 QuicSession::OnCryptoHandshakeEvent(event); 544 QuicSession::OnCryptoHandshakeEvent(event);
108 if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size && 545 if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size &&
109 event == HANDSHAKE_CONFIRMED && config()->SupportMaxHeaderListSize()) { 546 event == HANDSHAKE_CONFIRMED && config()->SupportMaxHeaderListSize()) {
110 headers_stream()->SendMaxHeaderListSize(kDefaultMaxUncompressedHeaderSize); 547 SendMaxHeaderListSize(kDefaultMaxUncompressedHeaderSize);
111 } 548 }
112 } 549 }
113 550
114 void QuicSpdySession::OnPromiseHeaderList(QuicStreamId stream_id, 551 void QuicSpdySession::OnPromiseHeaderList(QuicStreamId stream_id,
115 QuicStreamId promised_stream_id, 552 QuicStreamId promised_stream_id,
116 size_t frame_len, 553 size_t frame_len,
117 const QuicHeaderList& header_list) { 554 const QuicHeaderList& header_list) {
118 string error = "OnPromiseHeaderList should be overriden in client code."; 555 string error = "OnPromiseHeaderList should be overriden in client code.";
119 QUIC_BUG << error; 556 QUIC_BUG << error;
120 connection()->CloseConnection(QUIC_INTERNAL_ERROR, error, 557 connection()->CloseConnection(QUIC_INTERNAL_ERROR, error,
121 ConnectionCloseBehavior::SILENT_CLOSE); 558 ConnectionCloseBehavior::SILENT_CLOSE);
122 } 559 }
123 560
124 void QuicSpdySession::OnConfigNegotiated() { 561 void QuicSpdySession::OnConfigNegotiated() {
125 QuicSession::OnConfigNegotiated(); 562 QuicSession::OnConfigNegotiated();
126 if (config()->HasClientSentConnectionOption(kDHDT, perspective())) { 563 if (config()->HasClientSentConnectionOption(kDHDT, perspective())) {
127 headers_stream_->DisableHpackDynamicTable(); 564 DisableHpackDynamicTable();
128 } 565 }
129 const QuicVersion version = connection()->version(); 566 const QuicVersion version = connection()->version();
130 if (FLAGS_quic_reloadable_flag_quic_enable_force_hol_blocking && 567 if (FLAGS_quic_reloadable_flag_quic_enable_force_hol_blocking &&
131 version > QUIC_VERSION_35 && config()->ForceHolBlocking(perspective())) { 568 version > QUIC_VERSION_35 && config()->ForceHolBlocking(perspective())) {
132 force_hol_blocking_ = true; 569 force_hol_blocking_ = true;
133 // Since all streams are tunneled through the headers stream, it 570 // Since all streams are tunneled through the headers stream, it
134 // is important that headers stream never flow control blocks. 571 // is important that headers stream never flow control blocks.
135 // Otherwise, busy-loop behaviour can ensue where data streams 572 // Otherwise, busy-loop behaviour can ensue where data streams
136 // data try repeatedly to write data not realizing that the 573 // data try repeatedly to write data not realizing that the
137 // tunnel through the headers stream is blocked. 574 // tunnel through the headers stream is blocked.
(...skipping 22 matching lines...) Expand all
160 const QuicStreamFrame frame(stream_id, fin, offset, StringPiece(data, len)); 597 const QuicStreamFrame frame(stream_id, fin, offset, StringPiece(data, len));
161 DVLOG(1) << "De-encapsulating DATA frame for stream " << stream_id 598 DVLOG(1) << "De-encapsulating DATA frame for stream " << stream_id
162 << " offset " << offset << " len " << len << " fin " << fin; 599 << " offset " << offset << " len " << len << " fin " << fin;
163 OnStreamFrame(frame); 600 OnStreamFrame(frame);
164 } 601 }
165 602
166 bool QuicSpdySession::ShouldReleaseHeadersStreamSequencerBuffer() { 603 bool QuicSpdySession::ShouldReleaseHeadersStreamSequencerBuffer() {
167 return false; 604 return false;
168 } 605 }
169 606
607 void QuicSpdySession::OnHeaders(SpdyStreamId stream_id,
608 bool has_priority,
609 SpdyPriority priority,
610 bool fin) {
611 if (has_priority) {
612 if (perspective() == Perspective::IS_CLIENT) {
613 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
614 "Server must not send priorities.");
615 return;
616 }
617 OnStreamHeadersPriority(stream_id, priority);
618 } else {
619 if (perspective() == Perspective::IS_SERVER) {
620 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
621 "Client must send priorities.");
622 return;
623 }
624 }
625 DCHECK_EQ(kInvalidStreamId, stream_id_);
626 DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
627 stream_id_ = stream_id;
628 fin_ = fin;
629 }
630
631 void QuicSpdySession::OnPushPromise(SpdyStreamId stream_id,
632 SpdyStreamId promised_stream_id,
633 bool end) {
634 DCHECK_EQ(kInvalidStreamId, stream_id_);
635 DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
636 stream_id_ = stream_id;
637 promised_stream_id_ = promised_stream_id;
638 }
639
640 void QuicSpdySession::OnHeaderList(const QuicHeaderList& header_list) {
641 DVLOG(1) << "Received header list for stream " << stream_id_ << ": "
642 << header_list.DebugString();
643 if (prev_max_timestamp_ > cur_max_timestamp_) {
644 // prev_max_timestamp_ > cur_max_timestamp_ implies that
645 // headers from lower numbered streams actually came off the
646 // wire after headers for the current stream, hence there was
647 // HOL blocking.
648 QuicTime::Delta delta = prev_max_timestamp_ - cur_max_timestamp_;
649 DVLOG(1) << "stream " << stream_id_
650 << ": Net.QuicSession.HeadersHOLBlockedTime "
651 << delta.ToMilliseconds();
652 OnHeadersHeadOfLineBlocking(delta);
653 }
654 prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_);
655 cur_max_timestamp_ = QuicTime::Zero();
656 if (promised_stream_id_ == kInvalidStreamId) {
657 OnStreamHeaderList(stream_id_, fin_, frame_len_, header_list);
658 } else {
659 OnPromiseHeaderList(stream_id_, promised_stream_id_, frame_len_,
660 header_list);
661 }
662 // Reset state for the next frame.
663 promised_stream_id_ = kInvalidStreamId;
664 stream_id_ = kInvalidStreamId;
665 fin_ = false;
666 frame_len_ = 0;
667 uncompressed_frame_len_ = 0;
668 }
669
670 void QuicSpdySession::OnCompressedFrameSize(size_t frame_len) {
671 frame_len_ += frame_len;
672 }
673
674 void QuicSpdySession::DisableHpackDynamicTable() {
675 spdy_framer_.UpdateHeaderEncoderTableSize(0);
676 }
677
678 void QuicSpdySession::SetHpackEncoderDebugVisitor(
679 std::unique_ptr<QuicHpackDebugVisitor> visitor) {
680 spdy_framer_.SetEncoderHeaderTableDebugVisitor(
681 std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
682 connection()->helper()->GetClock(), std::move(visitor))));
683 }
684
685 void QuicSpdySession::SetHpackDecoderDebugVisitor(
686 std::unique_ptr<QuicHpackDebugVisitor> visitor) {
687 spdy_framer_.SetDecoderHeaderTableDebugVisitor(
688 std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
689 connection()->helper()->GetClock(), std::move(visitor))));
690 }
691
692 void QuicSpdySession::UpdateHeaderEncoderTableSize(uint32_t value) {
693 spdy_framer_.UpdateHeaderEncoderTableSize(value);
694 }
695
696 void QuicSpdySession::UpdateEnableServerPush(bool value) {
697 set_server_push_enabled(value);
698 }
699
700 bool QuicSpdySession::OnDataFrameHeader(QuicStreamId stream_id,
701 size_t length,
702 bool fin) {
703 if (!force_hol_blocking()) {
704 return false;
705 }
706 if (!IsConnected()) {
707 return true;
708 }
709 DVLOG(1) << "DATA frame header for stream " << stream_id << " length "
710 << length << " fin " << fin;
711 fin_ = fin;
712 frame_len_ = length;
713 if (fin && length == 0) {
714 OnStreamFrameData(stream_id, "", 0);
715 }
716 return true;
717 }
718
719 bool QuicSpdySession::OnStreamFrameData(QuicStreamId stream_id,
720 const char* data,
721 size_t len) {
722 if (!force_hol_blocking()) {
723 return false;
724 }
725 if (!IsConnected()) {
726 return true;
727 }
728 frame_len_ -= len;
729 // Ignore fin_ while there is more data coming, if frame_len_ > 0.
730 OnStreamFrameData(stream_id, data, len, frame_len_ > 0 ? false : fin_);
731 return true;
732 }
733
734 void QuicSpdySession::set_max_uncompressed_header_bytes(
735 size_t set_max_uncompressed_header_bytes) {
736 spdy_framer_visitor_->set_max_uncompressed_header_bytes(
737 set_max_uncompressed_header_bytes);
738 }
739
740 void QuicSpdySession::CloseConnectionWithDetails(QuicErrorCode error,
741 const string& details) {
742 connection()->CloseConnection(
743 error, details, ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
744 }
745
170 } // namespace net 746 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/core/quic_spdy_session.h ('k') | net/quic/core/quic_spdy_stream.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698