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

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

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