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

Side by Side Diff: net/quic/core/quic_headers_stream.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_headers_stream.h ('k') | net/quic/core/quic_headers_stream_test.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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_headers_stream.h" 5 #include "net/quic/core/quic_headers_stream.h"
6 6
7 #include <algorithm>
8 #include <cstdint>
9 #include <string>
10 #include <utility>
11
12 #include "base/macros.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "net/quic/core/quic_bug_tracker.h"
15 #include "net/quic/core/quic_flags.h" 7 #include "net/quic/core/quic_flags.h"
16 #include "net/quic/core/quic_header_list.h"
17 #include "net/quic/core/quic_server_session_base.h"
18 #include "net/quic/core/quic_spdy_session.h" 8 #include "net/quic/core/quic_spdy_session.h"
19 #include "net/quic/core/quic_time.h"
20 #include "net/quic/platform/api/quic_str_cat.h"
21 #include "net/spdy/spdy_protocol.h"
22
23 using base::StringPiece;
24 using std::string;
25 9
26 namespace net { 10 namespace net {
27 11
28 namespace {
29
30 class HeaderTableDebugVisitor : public HpackHeaderTable::DebugVisitorInterface {
31 public:
32 HeaderTableDebugVisitor(
33 const QuicClock* clock,
34 std::unique_ptr<QuicHeadersStream::HpackDebugVisitor> visitor)
35 : clock_(clock), headers_stream_hpack_visitor_(std::move(visitor)) {}
36
37 int64_t OnNewEntry(const HpackEntry& entry) override {
38 DVLOG(1) << entry.GetDebugString();
39 return (clock_->ApproximateNow() - QuicTime::Zero()).ToMicroseconds();
40 }
41
42 void OnUseEntry(const HpackEntry& entry) override {
43 const QuicTime::Delta elapsed(
44 clock_->ApproximateNow() -
45 QuicTime::Delta::FromMicroseconds(entry.time_added()) -
46 QuicTime::Zero());
47 DVLOG(1) << entry.GetDebugString() << " " << elapsed.ToMilliseconds()
48 << " ms";
49 headers_stream_hpack_visitor_->OnUseEntry(elapsed);
50 }
51
52 private:
53 const QuicClock* clock_;
54 std::unique_ptr<QuicHeadersStream::HpackDebugVisitor>
55 headers_stream_hpack_visitor_;
56
57 DISALLOW_COPY_AND_ASSIGN(HeaderTableDebugVisitor);
58 };
59
60 // When forced HOL blocking is enabled, extra bytes in the form of
61 // HTTP/2 DATA frame headers are inserted on the way down to the
62 // session layer. |ForceAckListener| filters the |OnPacketAcked()|
63 // notifications generated by the session layer to not count the extra
64 // bytes. Otherwise, code that is using ack listener on streams might
65 // consider it an error if more bytes are acked than were written to
66 // the stream, it is the case with some internal stats gathering code.
67 class ForceHolAckListener : public QuicAckListenerInterface {
68 public:
69 // |extra_bytes| should be initialized to the size of the HTTP/2
70 // DATA frame header inserted when forced HOL blocking is enabled.
71 ForceHolAckListener(
72 QuicReferenceCountedPointer<QuicAckListenerInterface> stream_ack_listener,
73 int extra_bytes)
74 : stream_ack_listener_(std::move(stream_ack_listener)),
75 extra_bytes_(extra_bytes) {
76 DCHECK_GE(extra_bytes, 0);
77 }
78
79 void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override {
80 if (extra_bytes_ > 0) {
81 // Don't count the added HTTP/2 DATA frame header bytes
82 int delta = std::min(extra_bytes_, acked_bytes);
83 extra_bytes_ -= delta;
84 acked_bytes -= delta;
85 }
86 stream_ack_listener_->OnPacketAcked(acked_bytes, ack_delay_time);
87 }
88
89 void OnPacketRetransmitted(int retransmitted_bytes) override {
90 stream_ack_listener_->OnPacketRetransmitted(retransmitted_bytes);
91 }
92
93 protected:
94 ~ForceHolAckListener() override {}
95
96 private:
97 QuicReferenceCountedPointer<QuicAckListenerInterface> stream_ack_listener_;
98 int extra_bytes_;
99
100 DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener);
101 };
102
103 } // namespace
104
105 QuicHeadersStream::HpackDebugVisitor::HpackDebugVisitor() {}
106
107 QuicHeadersStream::HpackDebugVisitor::~HpackDebugVisitor() {}
108
109 // A SpdyFramerVisitor that passes HEADERS frames to the QuicSpdyStream, and
110 // closes the connection if any unexpected frames are received.
111 class QuicHeadersStream::SpdyFramerVisitor
112 : public SpdyFramerVisitorInterface,
113 public SpdyFramerDebugVisitorInterface {
114 public:
115 explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {}
116
117 SpdyHeadersHandlerInterface* OnHeaderFrameStart(
118 SpdyStreamId /* stream_id */) override {
119 return &header_list_;
120 }
121
122 void OnHeaderFrameEnd(SpdyStreamId /* stream_id */,
123 bool end_headers) override {
124 if (end_headers) {
125 if (stream_->IsConnected()) {
126 stream_->OnHeaderList(header_list_);
127 }
128 header_list_.Clear();
129 }
130 }
131
132 void OnStreamFrameData(SpdyStreamId stream_id,
133 const char* data,
134 size_t len) override {
135 if (stream_->OnStreamFrameData(stream_id, data, len)) {
136 return;
137 }
138 CloseConnection("SPDY DATA frame received.");
139 }
140
141 void OnStreamEnd(SpdyStreamId stream_id) override {
142 // The framer invokes OnStreamEnd after processing a frame that had the fin
143 // bit set.
144 }
145
146 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
147 CloseConnection("SPDY frame padding received.");
148 }
149
150 void OnError(SpdyFramer* framer) override {
151 CloseConnection(
152 QuicStrCat("SPDY framing error: ",
153 SpdyFramer::ErrorCodeToString(framer->error_code())));
154 }
155
156 void OnDataFrameHeader(SpdyStreamId stream_id,
157 size_t length,
158 bool fin) override {
159 if (stream_->OnDataFrameHeader(stream_id, length, fin)) {
160 return;
161 }
162 CloseConnection("SPDY DATA frame received.");
163 }
164
165 void OnRstStream(SpdyStreamId stream_id,
166 SpdyRstStreamStatus status) override {
167 CloseConnection("SPDY RST_STREAM frame received.");
168 }
169
170 void OnSetting(SpdySettingsIds id, uint32_t value) override {
171 if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
172 CloseConnection("SPDY SETTINGS frame received.");
173 return;
174 }
175 switch (id) {
176 case SETTINGS_HEADER_TABLE_SIZE:
177 stream_->UpdateHeaderEncoderTableSize(value);
178 break;
179 case SETTINGS_ENABLE_PUSH:
180 if (FLAGS_quic_reloadable_flag_quic_enable_server_push_by_default &&
181 stream_->session()->perspective() == Perspective::IS_SERVER) {
182 // See rfc7540, Section 6.5.2.
183 if (value > 1) {
184 CloseConnection(
185 QuicStrCat("Invalid value for SETTINGS_ENABLE_PUSH: ", value));
186 return;
187 }
188 stream_->UpdateEnableServerPush(value > 0);
189 break;
190 } else {
191 CloseConnection(
192 QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
193 }
194 break;
195 // TODO(fayang): Need to support SETTINGS_MAX_HEADER_LIST_SIZE when
196 // clients are actually sending it.
197 case SETTINGS_MAX_HEADER_LIST_SIZE:
198 if (FLAGS_quic_reloadable_flag_quic_send_max_header_list_size) {
199 break;
200 }
201 default:
202 CloseConnection(
203 QuicStrCat("Unsupported field of HTTP/2 SETTINGS frame: ", id));
204 }
205 }
206
207 void OnSettingsAck() override {
208 if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
209 CloseConnection("SPDY SETTINGS frame received.");
210 }
211 }
212
213 void OnSettingsEnd() override {
214 if (!FLAGS_quic_reloadable_flag_quic_respect_http2_settings_frame) {
215 CloseConnection("SPDY SETTINGS frame received.");
216 }
217 }
218
219 void OnPing(SpdyPingId unique_id, bool is_ack) override {
220 CloseConnection("SPDY PING frame received.");
221 }
222
223 void OnGoAway(SpdyStreamId last_accepted_stream_id,
224 SpdyGoAwayStatus status) override {
225 CloseConnection("SPDY GOAWAY frame received.");
226 }
227
228 void OnHeaders(SpdyStreamId stream_id,
229 bool has_priority,
230 int weight,
231 SpdyStreamId /*parent_stream_id*/,
232 bool /*exclusive*/,
233 bool fin,
234 bool end) override {
235 if (!stream_->IsConnected()) {
236 return;
237 }
238
239 // TODO(mpw): avoid down-conversion and plumb SpdyStreamPrecedence through
240 // QuicHeadersStream.
241 SpdyPriority priority =
242 has_priority ? Http2WeightToSpdy3Priority(weight) : 0;
243 stream_->OnHeaders(stream_id, has_priority, priority, fin);
244 }
245
246 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
247 CloseConnection("SPDY WINDOW_UPDATE frame received.");
248 }
249
250 void OnPushPromise(SpdyStreamId stream_id,
251 SpdyStreamId promised_stream_id,
252 bool end) override {
253 if (!stream_->supports_push_promise()) {
254 CloseConnection("PUSH_PROMISE not supported.");
255 return;
256 }
257 if (!stream_->IsConnected()) {
258 return;
259 }
260 stream_->OnPushPromise(stream_id, promised_stream_id, end);
261 }
262
263 void OnContinuation(SpdyStreamId stream_id, bool end) override {}
264
265 void OnPriority(SpdyStreamId stream_id,
266 SpdyStreamId parent_id,
267 int weight,
268 bool exclusive) override {
269 CloseConnection("SPDY PRIORITY frame received.");
270 }
271
272 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
273 CloseConnection("Unknown frame type received.");
274 return false;
275 }
276
277 // SpdyFramerDebugVisitorInterface implementation
278 void OnSendCompressedFrame(SpdyStreamId stream_id,
279 SpdyFrameType type,
280 size_t payload_len,
281 size_t frame_len) override {
282 if (payload_len == 0) {
283 QUIC_BUG << "Zero payload length.";
284 return;
285 }
286 int compression_pct = 100 - (100 * frame_len) / payload_len;
287 DVLOG(1) << "Net.QuicHpackCompressionPercentage: " << compression_pct;
288 UMA_HISTOGRAM_PERCENTAGE("Net.QuicHpackCompressionPercentage",
289 compression_pct);
290 }
291
292 void OnReceiveCompressedFrame(SpdyStreamId stream_id,
293 SpdyFrameType type,
294 size_t frame_len) override {
295 if (stream_->IsConnected()) {
296 stream_->OnCompressedFrameSize(frame_len);
297 }
298 }
299
300 void set_max_uncompressed_header_bytes(
301 size_t set_max_uncompressed_header_bytes) {
302 header_list_.set_max_uncompressed_header_bytes(
303 set_max_uncompressed_header_bytes);
304 }
305
306 private:
307 void CloseConnection(const string& details) {
308 if (stream_->IsConnected()) {
309 stream_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
310 details);
311 }
312 }
313
314 private:
315 QuicHeadersStream* stream_;
316 QuicHeaderList header_list_;
317
318 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
319 };
320
321 QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session) 12 QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session)
322 : QuicStream(kHeadersStreamId, session), 13 : QuicStream(kHeadersStreamId, session), spdy_session_(session) {
323 spdy_session_(session),
324 stream_id_(kInvalidStreamId),
325 promised_stream_id_(kInvalidStreamId),
326 fin_(false),
327 frame_len_(0),
328 uncompressed_frame_len_(0),
329 supports_push_promise_(session->perspective() == Perspective::IS_CLIENT),
330 cur_max_timestamp_(QuicTime::Zero()),
331 prev_max_timestamp_(QuicTime::Zero()),
332 spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
333 spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
334 spdy_framer_.set_visitor(spdy_framer_visitor_.get());
335 spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
336 // The headers stream is exempt from connection level flow control. 14 // The headers stream is exempt from connection level flow control.
337 DisableConnectionFlowControlForThisStream(); 15 DisableConnectionFlowControlForThisStream();
338 } 16 }
339 17
340 QuicHeadersStream::~QuicHeadersStream() {} 18 QuicHeadersStream::~QuicHeadersStream() {}
341 19
342 size_t QuicHeadersStream::WriteHeaders(
343 QuicStreamId stream_id,
344 SpdyHeaderBlock headers,
345 bool fin,
346 SpdyPriority priority,
347 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
348 SpdyHeadersIR headers_frame(stream_id, std::move(headers));
349 headers_frame.set_fin(fin);
350 if (session()->perspective() == Perspective::IS_CLIENT) {
351 headers_frame.set_has_priority(true);
352 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority));
353 }
354 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
355 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
356 std::move(ack_listener));
357 return frame.size();
358 }
359
360 size_t QuicHeadersStream::WritePushPromise(QuicStreamId original_stream_id,
361 QuicStreamId promised_stream_id,
362 SpdyHeaderBlock headers) {
363 if (session()->perspective() == Perspective::IS_CLIENT) {
364 QUIC_BUG << "Client shouldn't send PUSH_PROMISE";
365 return 0;
366 }
367
368 SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
369 std::move(headers));
370
371 // PUSH_PROMISE must not be the last frame sent out, at least followed by
372 // response headers.
373 push_promise.set_fin(false);
374
375 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
376 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr);
377 return frame.size();
378 }
379
380 void QuicHeadersStream::WriteDataFrame(
381 QuicStreamId id,
382 StringPiece data,
383 bool fin,
384 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
385 SpdyDataIR spdy_data(id, data);
386 spdy_data.set_fin(fin);
387 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
388 QuicReferenceCountedPointer<ForceHolAckListener> force_hol_ack_listener;
389 if (ack_listener != nullptr) {
390 force_hol_ack_listener = new ForceHolAckListener(
391 std::move(ack_listener), frame.size() - data.length());
392 }
393 // Use buffered writes so that coherence of framing is preserved
394 // between streams.
395 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
396 std::move(force_hol_ack_listener));
397 }
398
399 QuicConsumedData QuicHeadersStream::WritevStreamData(
400 QuicStreamId id,
401 QuicIOVector iov,
402 QuicStreamOffset offset,
403 bool fin,
404 QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
405 const size_t max_len = kSpdyInitialFrameSizeLimit - kDataFrameMinimumSize;
406
407 QuicConsumedData result(0, false);
408 size_t total_length = iov.total_length;
409
410 if (total_length == 0 && fin) {
411 WriteDataFrame(id, StringPiece(), true, std::move(ack_listener));
412 result.fin_consumed = true;
413 return result;
414 }
415
416 // Encapsulate the data into HTTP/2 DATA frames. The outer loop
417 // handles each element of the source iov, the inner loop handles
418 // the possibility of fragmenting each of those into multiple DATA
419 // frames, as the DATA frames have a max size of 16KB.
420 for (int i = 0; i < iov.iov_count; i++) {
421 size_t src_iov_offset = 0;
422 const struct iovec* src_iov = &iov.iov[i];
423 do {
424 if (queued_data_bytes() > 0) {
425 // Limit the amount of buffering to the minimum needed to
426 // preserve framing.
427 return result;
428 }
429 size_t len = std::min(
430 std::min(src_iov->iov_len - src_iov_offset, max_len), total_length);
431 char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset;
432 src_iov_offset += len;
433 offset += len;
434 // fin handling, only set it for the final HTTP/2 DATA frame.
435 bool last_iov = i == iov.iov_count - 1;
436 bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len;
437 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
438 WriteDataFrame(id, StringPiece(data, len), frame_fin, ack_listener);
439 result.bytes_consumed += len;
440 if (frame_fin) {
441 result.fin_consumed = true;
442 }
443 DCHECK_GE(total_length, len);
444 total_length -= len;
445 if (total_length <= 0) {
446 return result;
447 }
448 } while (src_iov_offset < src_iov->iov_len);
449 }
450
451 return result;
452 }
453
454 void QuicHeadersStream::OnDataAvailable() { 20 void QuicHeadersStream::OnDataAvailable() {
455 char buffer[1024]; 21 char buffer[1024];
456 struct iovec iov; 22 struct iovec iov;
457 QuicTime timestamp(QuicTime::Zero()); 23 QuicTime timestamp(QuicTime::Zero());
458 while (true) { 24 while (true) {
459 iov.iov_base = buffer; 25 iov.iov_base = buffer;
460 iov.iov_len = arraysize(buffer); 26 iov.iov_len = arraysize(buffer);
461 if (!sequencer()->GetReadableRegion(&iov, &timestamp)) { 27 if (!sequencer()->GetReadableRegion(&iov, &timestamp)) {
462 // No more data to read. 28 // No more data to read.
463 break; 29 break;
464 } 30 }
465 DCHECK(timestamp.IsInitialized()); 31 if (spdy_session_->ProcessHeaderData(iov, timestamp) != iov.iov_len) {
466 cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_);
467 if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base),
468 iov.iov_len) != iov.iov_len) {
469 // Error processing data. 32 // Error processing data.
470 return; 33 return;
471 } 34 }
472 sequencer()->MarkConsumed(iov.iov_len); 35 sequencer()->MarkConsumed(iov.iov_len);
473 MaybeReleaseSequencerBuffer(); 36 MaybeReleaseSequencerBuffer();
474 } 37 }
475 } 38 }
476 39
477 void QuicHeadersStream::set_max_uncompressed_header_bytes(
478 size_t set_max_uncompressed_header_bytes) {
479 spdy_framer_visitor_->set_max_uncompressed_header_bytes(
480 set_max_uncompressed_header_bytes);
481 }
482
483 void QuicHeadersStream::OnHeaders(SpdyStreamId stream_id,
484 bool has_priority,
485 SpdyPriority priority,
486 bool fin) {
487 if (has_priority) {
488 if (session()->perspective() == Perspective::IS_CLIENT) {
489 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
490 "Server must not send priorities.");
491 return;
492 }
493 spdy_session_->OnStreamHeadersPriority(stream_id, priority);
494 } else {
495 if (session()->perspective() == Perspective::IS_SERVER) {
496 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
497 "Client must send priorities.");
498 return;
499 }
500 }
501 DCHECK_EQ(kInvalidStreamId, stream_id_);
502 DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
503 stream_id_ = stream_id;
504 fin_ = fin;
505 }
506
507 void QuicHeadersStream::OnPushPromise(SpdyStreamId stream_id,
508 SpdyStreamId promised_stream_id,
509 bool end) {
510 DCHECK_EQ(kInvalidStreamId, stream_id_);
511 DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
512 stream_id_ = stream_id;
513 promised_stream_id_ = promised_stream_id;
514 }
515
516 void QuicHeadersStream::OnHeaderList(const QuicHeaderList& header_list) {
517 DVLOG(1) << "Received header list for stream " << stream_id_ << ": "
518 << header_list.DebugString();
519 if (prev_max_timestamp_ > cur_max_timestamp_) {
520 // prev_max_timestamp_ > cur_max_timestamp_ implies that
521 // headers from lower numbered streams actually came off the
522 // wire after headers for the current stream, hence there was
523 // HOL blocking.
524 QuicTime::Delta delta = prev_max_timestamp_ - cur_max_timestamp_;
525 DVLOG(1) << "stream " << stream_id_
526 << ": Net.QuicSession.HeadersHOLBlockedTime "
527 << delta.ToMilliseconds();
528 spdy_session_->OnHeadersHeadOfLineBlocking(delta);
529 }
530
531 prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_);
532 cur_max_timestamp_ = QuicTime::Zero();
533 if (promised_stream_id_ == kInvalidStreamId) {
534 spdy_session_->OnStreamHeaderList(stream_id_, fin_, frame_len_,
535 header_list);
536 } else {
537 spdy_session_->OnPromiseHeaderList(stream_id_, promised_stream_id_,
538 frame_len_, header_list);
539 }
540 // Reset state for the next frame.
541 promised_stream_id_ = kInvalidStreamId;
542 stream_id_ = kInvalidStreamId;
543 fin_ = false;
544 frame_len_ = 0;
545 uncompressed_frame_len_ = 0;
546 }
547
548 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
549 frame_len_ += frame_len;
550 }
551
552 bool QuicHeadersStream::IsConnected() {
553 return session()->connection()->connected();
554 }
555
556 void QuicHeadersStream::DisableHpackDynamicTable() {
557 spdy_framer_.UpdateHeaderEncoderTableSize(0);
558 }
559
560 void QuicHeadersStream::SetHpackEncoderDebugVisitor(
561 std::unique_ptr<HpackDebugVisitor> visitor) {
562 spdy_framer_.SetEncoderHeaderTableDebugVisitor(
563 std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
564 session()->connection()->helper()->GetClock(), std::move(visitor))));
565 }
566
567 void QuicHeadersStream::SetHpackDecoderDebugVisitor(
568 std::unique_ptr<HpackDebugVisitor> visitor) {
569 spdy_framer_.SetDecoderHeaderTableDebugVisitor(
570 std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
571 session()->connection()->helper()->GetClock(), std::move(visitor))));
572 }
573
574 void QuicHeadersStream::UpdateHeaderEncoderTableSize(uint32_t value) {
575 spdy_framer_.UpdateHeaderEncoderTableSize(value);
576 }
577
578 void QuicHeadersStream::UpdateEnableServerPush(bool value) {
579 spdy_session_->set_server_push_enabled(value);
580 }
581
582 void QuicHeadersStream::MaybeReleaseSequencerBuffer() { 40 void QuicHeadersStream::MaybeReleaseSequencerBuffer() {
583 if (FLAGS_quic_reloadable_flag_quic_headers_stream_release_sequencer_buffer && 41 if (FLAGS_quic_reloadable_flag_quic_headers_stream_release_sequencer_buffer &&
584 spdy_session_->ShouldReleaseHeadersStreamSequencerBuffer()) { 42 spdy_session_->ShouldReleaseHeadersStreamSequencerBuffer()) {
585 sequencer()->ReleaseBufferIfEmpty(); 43 sequencer()->ReleaseBufferIfEmpty();
586 } 44 }
587 } 45 }
588 46
589 size_t QuicHeadersStream::SendMaxHeaderListSize(size_t value) {
590 SpdySettingsIR settings_frame;
591 settings_frame.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, value);
592
593 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(settings_frame));
594 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, nullptr);
595 return frame.size();
596 }
597
598 bool QuicHeadersStream::OnDataFrameHeader(QuicStreamId stream_id,
599 size_t length,
600 bool fin) {
601 if (!spdy_session_->force_hol_blocking()) {
602 return false;
603 }
604 if (!IsConnected()) {
605 return true;
606 }
607 DVLOG(1) << "DATA frame header for stream " << stream_id << " length "
608 << length << " fin " << fin;
609 fin_ = fin;
610 frame_len_ = length;
611 if (fin && length == 0) {
612 OnStreamFrameData(stream_id, "", 0);
613 }
614 return true;
615 }
616
617 bool QuicHeadersStream::OnStreamFrameData(QuicStreamId stream_id,
618 const char* data,
619 size_t len) {
620 if (!spdy_session_->force_hol_blocking()) {
621 return false;
622 }
623 if (!IsConnected()) {
624 return true;
625 }
626 frame_len_ -= len;
627 // Ignore fin_ while there is more data coming, if frame_len_ > 0.
628 spdy_session_->OnStreamFrameData(stream_id, data, len,
629 frame_len_ > 0 ? false : fin_);
630 return true;
631 }
632
633 } // namespace net 47 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/core/quic_headers_stream.h ('k') | net/quic/core/quic_headers_stream_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698