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

Side by Side Diff: net/quic/quic_headers_stream.cc

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 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/quic_headers_stream.h ('k') | net/quic/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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/quic/quic_headers_stream.h"
6
7 #include <utility>
8
9 #include "base/macros.h"
10 #include "base/metrics/histogram_macros.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/stringprintf.h"
13 #include "net/quic/quic_bug_tracker.h"
14 #include "net/quic/quic_flags.h"
15 #include "net/quic/quic_header_list.h"
16 #include "net/quic/quic_spdy_session.h"
17 #include "net/quic/quic_time.h"
18 #include "net/spdy/spdy_protocol.h"
19
20 using base::StringPiece;
21 using net::HTTP2;
22 using net::SpdyFrameType;
23 using std::string;
24
25 namespace net {
26
27 namespace {
28
29 class HeaderTableDebugVisitor : public HpackHeaderTable::DebugVisitorInterface {
30 public:
31 HeaderTableDebugVisitor(
32 const QuicClock* clock,
33 std::unique_ptr<QuicHeadersStream::HpackDebugVisitor> visitor)
34 : clock_(clock), headers_stream_hpack_visitor_(std::move(visitor)) {}
35
36 int64_t OnNewEntry(const HpackEntry& entry) override {
37 DVLOG(1) << entry.GetDebugString();
38 return (clock_->ApproximateNow() - QuicTime::Zero()).ToMicroseconds();
39 }
40
41 void OnUseEntry(const HpackEntry& entry) override {
42 const QuicTime::Delta elapsed(
43 clock_->ApproximateNow() -
44 QuicTime::Delta::FromMicroseconds(entry.time_added()) -
45 QuicTime::Zero());
46 DVLOG(1) << entry.GetDebugString() << " " << elapsed.ToMilliseconds()
47 << " ms";
48 headers_stream_hpack_visitor_->OnUseEntry(elapsed);
49 }
50
51 private:
52 const QuicClock* clock_;
53 std::unique_ptr<QuicHeadersStream::HpackDebugVisitor>
54 headers_stream_hpack_visitor_;
55
56 DISALLOW_COPY_AND_ASSIGN(HeaderTableDebugVisitor);
57 };
58
59 // When forced HOL blocking is enabled, extra bytes in the form of
60 // HTTP/2 DATA frame headers are inserted on the way down to the
61 // session layer. |ForceAckListener| filters the |OnPacketAcked()|
62 // notifications generated by the session layer to not count the extra
63 // bytes. Otherwise, code that is using ack listener on streams might
64 // consider it an error if more bytes are acked than were written to
65 // the stream, it is the case with some internal stats gathering code.
66 class ForceHolAckListener : public QuicAckListenerInterface {
67 public:
68 // |extra_bytes| should be initialized to the size of the HTTP/2
69 // DATA frame header inserted when forced HOL blocking is enabled.
70 ForceHolAckListener(QuicAckListenerInterface* stream_ack_listener,
71 int extra_bytes)
72 : stream_ack_listener_(stream_ack_listener), extra_bytes_(extra_bytes) {
73 DCHECK_GE(extra_bytes, 0);
74 }
75
76 void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override {
77 if (extra_bytes_ > 0) {
78 // Don't count the added HTTP/2 DATA frame header bytes
79 int delta = std::min(extra_bytes_, acked_bytes);
80 extra_bytes_ -= delta;
81 acked_bytes -= delta;
82 }
83 stream_ack_listener_->OnPacketAcked(acked_bytes, ack_delay_time);
84 }
85
86 void OnPacketRetransmitted(int retransmitted_bytes) override {
87 stream_ack_listener_->OnPacketRetransmitted(retransmitted_bytes);
88 }
89
90 private:
91 ~ForceHolAckListener() override {}
92
93 scoped_refptr<QuicAckListenerInterface> stream_ack_listener_;
94 int extra_bytes_;
95
96 DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener);
97 };
98
99 } // namespace
100
101 QuicHeadersStream::HpackDebugVisitor::HpackDebugVisitor() {}
102
103 QuicHeadersStream::HpackDebugVisitor::~HpackDebugVisitor() {}
104
105 // A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to
106 // the QuicSpdyStream, and closes the connection if any unexpected frames
107 // are received.
108 class QuicHeadersStream::SpdyFramerVisitor
109 : public SpdyFramerVisitorInterface,
110 public SpdyFramerDebugVisitorInterface {
111 public:
112 explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {}
113
114 // SpdyFramerVisitorInterface implementation
115 void OnSynStream(SpdyStreamId stream_id,
116 SpdyStreamId associated_stream_id,
117 SpdyPriority priority,
118 bool fin,
119 bool unidirectional) override {
120 CloseConnection("SPDY SYN_STREAM frame received.");
121 }
122
123 void OnSynReply(SpdyStreamId stream_id, bool fin) override {
124 CloseConnection("SPDY SYN_REPLY frame received.");
125 }
126
127 bool OnControlFrameHeaderData(SpdyStreamId stream_id,
128 const char* header_data,
129 size_t len) override {
130 if (!stream_->IsConnected()) {
131 return false;
132 }
133 stream_->OnControlFrameHeaderData(stream_id, header_data, len);
134 return true;
135 }
136
137 void OnStreamFrameData(SpdyStreamId stream_id,
138 const char* data,
139 size_t len) override {
140 if (stream_->OnStreamFrameData(stream_id, data, len)) {
141 return;
142 }
143 CloseConnection("SPDY DATA frame received.");
144 }
145
146 void OnStreamEnd(SpdyStreamId stream_id) override {
147 // The framer invokes OnStreamEnd after processing a SYN_STREAM
148 // or SYN_REPLY frame that had the fin bit set.
149 }
150
151 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
152 CloseConnection("SPDY frame padding received.");
153 }
154
155 SpdyHeadersHandlerInterface* OnHeaderFrameStart(
156 SpdyStreamId /* stream_id */) override {
157 return &header_list_;
158 }
159
160 void OnHeaderFrameEnd(SpdyStreamId /* stream_id */,
161 bool end_headers) override {
162 if (end_headers) {
163 if (stream_->IsConnected()) {
164 stream_->OnHeaderList(header_list_);
165 }
166 header_list_.Clear();
167 }
168 }
169
170 void OnError(SpdyFramer* framer) override {
171 CloseConnection(base::StringPrintf(
172 "SPDY framing error: %s",
173 SpdyFramer::ErrorCodeToString(framer->error_code())));
174 }
175
176 void OnDataFrameHeader(SpdyStreamId stream_id,
177 size_t length,
178 bool fin) override {
179 if (stream_->OnDataFrameHeader(stream_id, length, fin)) {
180 return;
181 }
182 CloseConnection("SPDY DATA frame received.");
183 }
184
185 void OnRstStream(SpdyStreamId stream_id,
186 SpdyRstStreamStatus status) override {
187 CloseConnection("SPDY RST_STREAM frame received.");
188 }
189
190 void OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) override {
191 if (!FLAGS_quic_respect_http2_settings_frame) {
192 CloseConnection("SPDY SETTINGS frame received.");
193 return;
194 }
195 switch (id) {
196 case SETTINGS_HEADER_TABLE_SIZE:
197 stream_->UpdateHeaderEncoderTableSize(value);
198 break;
199 // TODO(fayang): Need to support SETTINGS_MAX_HEADER_LIST_SIZE when
200 // clients are actually sending it.
201 default:
202 CloseConnection("Unsupported field of HTTP/2 SETTINGS frame: " +
203 base::IntToString(id));
204 }
205 }
206
207 void OnSettingsAck() override {
208 if (!FLAGS_quic_respect_http2_settings_frame) {
209 CloseConnection("SPDY SETTINGS frame received.");
210 }
211 }
212
213 void OnSettingsEnd() override {
214 if (!FLAGS_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 private:
301 void CloseConnection(const string& details) {
302 if (stream_->IsConnected()) {
303 stream_->CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
304 details);
305 }
306 }
307
308 private:
309 QuicHeadersStream* stream_;
310 QuicHeaderList header_list_;
311
312 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
313 };
314
315 QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session)
316 : ReliableQuicStream(kHeadersStreamId, session),
317 spdy_session_(session),
318 stream_id_(kInvalidStreamId),
319 promised_stream_id_(kInvalidStreamId),
320 fin_(false),
321 frame_len_(0),
322 uncompressed_frame_len_(0),
323 measure_headers_hol_blocking_time_(
324 FLAGS_quic_measure_headers_hol_blocking_time),
325 supports_push_promise_(session->perspective() == Perspective::IS_CLIENT &&
326 FLAGS_quic_supports_push_promise),
327 cur_max_timestamp_(QuicTime::Zero()),
328 prev_max_timestamp_(QuicTime::Zero()),
329 spdy_framer_(HTTP2),
330 spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
331 spdy_framer_.set_visitor(spdy_framer_visitor_.get());
332 spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
333 // The headers stream is exempt from connection level flow control.
334 DisableConnectionFlowControlForThisStream();
335 }
336
337 QuicHeadersStream::~QuicHeadersStream() {}
338
339 size_t QuicHeadersStream::WriteHeaders(QuicStreamId stream_id,
340 SpdyHeaderBlock headers,
341 bool fin,
342 SpdyPriority priority,
343 QuicAckListenerInterface* ack_listener) {
344 SpdyHeadersIR headers_frame(stream_id, std::move(headers));
345 headers_frame.set_fin(fin);
346 if (session()->perspective() == Perspective::IS_CLIENT) {
347 headers_frame.set_has_priority(true);
348 headers_frame.set_weight(Spdy3PriorityToHttp2Weight(priority));
349 }
350 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
351 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
352 ack_listener);
353 return frame.size();
354 }
355
356 size_t QuicHeadersStream::WritePushPromise(
357 QuicStreamId original_stream_id,
358 QuicStreamId promised_stream_id,
359 SpdyHeaderBlock headers,
360 QuicAckListenerInterface* ack_listener) {
361 if (session()->perspective() == Perspective::IS_CLIENT) {
362 QUIC_BUG << "Client shouldn't send PUSH_PROMISE";
363 return 0;
364 }
365
366 SpdyPushPromiseIR push_promise(original_stream_id, promised_stream_id,
367 std::move(headers));
368
369 // PUSH_PROMISE must not be the last frame sent out, at least followed by
370 // response headers.
371 push_promise.set_fin(false);
372
373 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(push_promise));
374 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
375 ack_listener);
376 return frame.size();
377 }
378
379 QuicConsumedData QuicHeadersStream::WritevStreamData(
380 QuicStreamId id,
381 QuicIOVector iov,
382 QuicStreamOffset offset,
383 bool fin,
384 QuicAckListenerInterface* ack_notifier_delegate) {
385 const size_t max_len = kSpdyInitialFrameSizeLimit -
386 SpdyConstants::GetDataFrameMinimumSize(HTTP2);
387
388 QuicConsumedData result(0, false);
389 size_t total_length = iov.total_length;
390
391 // Encapsulate the data into HTTP/2 DATA frames. The outer loop
392 // handles each element of the source iov, the inner loop handles
393 // the possibility of fragmenting eacho of those into multiple DATA
394 // frames, as the DATA frames have a max size of 16KB.
395 for (int i = 0; i < iov.iov_count; i++) {
396 size_t offset = 0;
397 const struct iovec* src_iov = &iov.iov[i];
398 do {
399 size_t len =
400 std::min(std::min(src_iov->iov_len - offset, max_len), total_length);
401 char* data = static_cast<char*>(src_iov->iov_base) + offset;
402 SpdyDataIR spdy_data(id, StringPiece(data, len));
403 offset += len;
404 // fin handling, set it only it only very last generated HTTP/2
405 // DATA frame.
406 bool last_iov = i == iov.iov_count - 1;
407 bool last_fragment_within_iov = offset >= src_iov->iov_len;
408 bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false;
409 spdy_data.set_fin(frame_fin);
410 if (frame_fin) {
411 result.fin_consumed = true;
412 }
413 SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data));
414 DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len "
415 << len << " fin " << spdy_data.fin() << " remaining "
416 << src_iov->iov_len - offset;
417
418 scoped_refptr<ForceHolAckListener> ack_listener;
419 if (ack_notifier_delegate != nullptr) {
420 ack_listener =
421 new ForceHolAckListener(ack_notifier_delegate, frame.size() - len);
422 }
423
424 WriteOrBufferData(StringPiece(frame.data(), frame.size()), false,
425 ack_listener.get());
426 result.bytes_consumed += len;
427 total_length -= len;
428 if (total_length <= 0) {
429 return result;
430 }
431 } while (offset < src_iov->iov_len);
432 }
433 return result;
434 }
435
436 void QuicHeadersStream::OnDataAvailable() {
437 char buffer[1024];
438 struct iovec iov;
439 QuicTime timestamp(QuicTime::Zero());
440 while (true) {
441 iov.iov_base = buffer;
442 iov.iov_len = arraysize(buffer);
443 if (measure_headers_hol_blocking_time_) {
444 if (!sequencer()->GetReadableRegion(&iov, &timestamp)) {
445 // No more data to read.
446 break;
447 }
448 DCHECK(timestamp.IsInitialized());
449 cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_);
450 } else {
451 if (sequencer()->GetReadableRegions(&iov, 1) != 1) {
452 // No more data to read.
453 break;
454 }
455 }
456 if (spdy_framer_.ProcessInput(static_cast<char*>(iov.iov_base),
457 iov.iov_len) != iov.iov_len) {
458 // Error processing data.
459 return;
460 }
461 sequencer()->MarkConsumed(iov.iov_len);
462 }
463 }
464
465 void QuicHeadersStream::OnHeaders(SpdyStreamId stream_id,
466 bool has_priority,
467 SpdyPriority priority,
468 bool fin) {
469 if (has_priority) {
470 if (session()->perspective() == Perspective::IS_CLIENT) {
471 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
472 "Server must not send priorities.");
473 return;
474 }
475 spdy_session_->OnStreamHeadersPriority(stream_id, priority);
476 } else {
477 if (session()->perspective() == Perspective::IS_SERVER) {
478 CloseConnectionWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA,
479 "Client must send priorities.");
480 return;
481 }
482 }
483 DCHECK_EQ(kInvalidStreamId, stream_id_);
484 DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
485 stream_id_ = stream_id;
486 fin_ = fin;
487 }
488
489 void QuicHeadersStream::OnPushPromise(SpdyStreamId stream_id,
490 SpdyStreamId promised_stream_id,
491 bool end) {
492 DCHECK_EQ(kInvalidStreamId, stream_id_);
493 DCHECK_EQ(kInvalidStreamId, promised_stream_id_);
494 stream_id_ = stream_id;
495 promised_stream_id_ = promised_stream_id;
496 }
497
498 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id,
499 const char* header_data,
500 size_t len) {
501 DCHECK_EQ(stream_id_, stream_id);
502 if (len == 0) {
503 DCHECK_NE(0u, stream_id_);
504 DCHECK_NE(0u, frame_len_);
505 if (measure_headers_hol_blocking_time_) {
506 if (prev_max_timestamp_ > cur_max_timestamp_) {
507 // prev_max_timestamp_ > cur_max_timestamp_ implies that
508 // headers from lower numbered streams actually came off the
509 // wire after headers for the current stream, hence there was
510 // HOL blocking.
511 QuicTime::Delta delta = prev_max_timestamp_ - cur_max_timestamp_;
512 DVLOG(1) << "stream " << stream_id
513 << ": Net.QuicSession.HeadersHOLBlockedTime "
514 << delta.ToMilliseconds();
515 spdy_session_->OnHeadersHeadOfLineBlocking(delta);
516 }
517 prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_);
518 cur_max_timestamp_ = QuicTime::Zero();
519 }
520 if (promised_stream_id_ == kInvalidStreamId) {
521 spdy_session_->OnStreamHeadersComplete(stream_id_, fin_, frame_len_);
522 } else {
523 spdy_session_->OnPromiseHeadersComplete(stream_id_, promised_stream_id_,
524 frame_len_);
525 }
526 if (uncompressed_frame_len_ != 0) {
527 int compression_pct = 100 - (100 * frame_len_) / uncompressed_frame_len_;
528 DVLOG(1) << "Net.QuicHpackDecompressionPercentage: " << compression_pct;
529 UMA_HISTOGRAM_PERCENTAGE("Net.QuicHpackDecompressionPercentage",
530 compression_pct);
531 }
532 // Reset state for the next frame.
533 promised_stream_id_ = kInvalidStreamId;
534 stream_id_ = kInvalidStreamId;
535 fin_ = false;
536 frame_len_ = 0;
537 uncompressed_frame_len_ = 0;
538 } else {
539 uncompressed_frame_len_ += len;
540 if (promised_stream_id_ == kInvalidStreamId) {
541 spdy_session_->OnStreamHeaders(stream_id_, StringPiece(header_data, len));
542 } else {
543 spdy_session_->OnPromiseHeaders(stream_id_,
544 StringPiece(header_data, len));
545 }
546 }
547 }
548
549 void QuicHeadersStream::OnHeaderList(const QuicHeaderList& header_list) {
550 DVLOG(1) << "Received header list for stream " << stream_id_ << ": "
551 << header_list.DebugString();
552 if (measure_headers_hol_blocking_time_) {
553 if (prev_max_timestamp_ > cur_max_timestamp_) {
554 // prev_max_timestamp_ > cur_max_timestamp_ implies that
555 // headers from lower numbered streams actually came off the
556 // wire after headers for the current stream, hence there was
557 // HOL blocking.
558 QuicTime::Delta delta = prev_max_timestamp_ - cur_max_timestamp_;
559 DVLOG(1) << "stream " << stream_id_
560 << ": Net.QuicSession.HeadersHOLBlockedTime "
561 << delta.ToMilliseconds();
562 spdy_session_->OnHeadersHeadOfLineBlocking(delta);
563 }
564 prev_max_timestamp_ = std::max(prev_max_timestamp_, cur_max_timestamp_);
565 cur_max_timestamp_ = QuicTime::Zero();
566 }
567 if (promised_stream_id_ == kInvalidStreamId) {
568 spdy_session_->OnStreamHeaderList(stream_id_, fin_, frame_len_,
569 header_list);
570 } else {
571 spdy_session_->OnPromiseHeaderList(stream_id_, promised_stream_id_,
572 frame_len_, header_list);
573 }
574 // Reset state for the next frame.
575 promised_stream_id_ = kInvalidStreamId;
576 stream_id_ = kInvalidStreamId;
577 fin_ = false;
578 frame_len_ = 0;
579 uncompressed_frame_len_ = 0;
580 }
581
582 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
583 frame_len_ += frame_len;
584 }
585
586 bool QuicHeadersStream::IsConnected() {
587 return session()->connection()->connected();
588 }
589
590 void QuicHeadersStream::DisableHpackDynamicTable() {
591 spdy_framer_.UpdateHeaderEncoderTableSize(0);
592 }
593
594 void QuicHeadersStream::SetHpackEncoderDebugVisitor(
595 std::unique_ptr<HpackDebugVisitor> visitor) {
596 spdy_framer_.SetEncoderHeaderTableDebugVisitor(
597 std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
598 session()->connection()->helper()->GetClock(), std::move(visitor))));
599 }
600
601 void QuicHeadersStream::SetHpackDecoderDebugVisitor(
602 std::unique_ptr<HpackDebugVisitor> visitor) {
603 spdy_framer_.SetDecoderHeaderTableDebugVisitor(
604 std::unique_ptr<HeaderTableDebugVisitor>(new HeaderTableDebugVisitor(
605 session()->connection()->helper()->GetClock(), std::move(visitor))));
606 }
607
608 void QuicHeadersStream::UpdateHeaderEncoderTableSize(uint32_t value) {
609 spdy_framer_.UpdateHeaderEncoderTableSize(value);
610 }
611
612 bool QuicHeadersStream::OnDataFrameHeader(QuicStreamId stream_id,
613 size_t length,
614 bool fin) {
615 if (!spdy_session_->force_hol_blocking()) {
616 return false;
617 }
618 if (!IsConnected()) {
619 return true;
620 }
621 DVLOG(1) << "DATA frame header for stream " << stream_id << " length "
622 << length << " fin " << fin;
623 fin_ = fin;
624 frame_len_ = length;
625 if (fin && length == 0) {
626 OnStreamFrameData(stream_id, "", 0);
627 }
628 return true;
629 }
630
631 bool QuicHeadersStream::OnStreamFrameData(QuicStreamId stream_id,
632 const char* data,
633 size_t len) {
634 if (!spdy_session_->force_hol_blocking()) {
635 return false;
636 }
637 if (!IsConnected()) {
638 return true;
639 }
640 frame_len_ -= len;
641 // Ignore fin_ while there is more data coming, if frame_len_ > 0.
642 spdy_session_->OnStreamFrameData(stream_id, data, len,
643 frame_len_ > 0 ? false : fin_);
644 return true;
645 }
646
647 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_headers_stream.h ('k') | net/quic/quic_headers_stream_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698