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

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