quic_data_stream.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_data_stream.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_session.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_utils.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_write_blocked_list.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::StringPiece;
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using std::min;
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace net {
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define ENDPOINT (session()->is_server() ? "Server: " : " Client: ")
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This is somewhat arbitrary.  It's possible, but unlikely, we will either fail
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// to set a priority client-side, or cancel a stream before stripping the
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// priority from the wire server-side.  In either case, start out with a
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// priority in the middle.
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicPriority kDefaultPriority = 3;
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream::QuicDataStream(QuicStreamId id,
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               QuicSession* session)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : ReliableQuicStream(id, session),
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      visitor_(NULL),
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      headers_decompressed_(false),
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      priority_(kDefaultPriority),
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      decompression_failed_(false),
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      priority_parsed_(false) {
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_NE(kCryptoStreamId, id);
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Don't receive any callbacks from the sequencer until headers
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // are complete.
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  sequencer()->SetBlockedUntilFlush();
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicDataStream::~QuicDataStream() {
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)size_t QuicDataStream::WriteHeaders(
4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const SpdyHeaderBlock& header_block,
4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bool fin,
4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  size_t bytes_written = session()->WriteHeaders(
5123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      id(), header_block, fin, ack_notifier_delegate);
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (fin) {
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // TODO(rch): Add test to ensure fin_sent_ is set whenever a fin is sent.
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    set_fin_sent(true);
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloseWriteSide();
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return bytes_written;
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)size_t QuicDataStream::Readv(const struct iovec* iov, size_t iov_len) {
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (FinishedReadingHeaders()) {
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If the headers have been read, simply delegate to the sequencer's
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Readv method.
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return sequencer()->Readv(iov, iov_len);
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Otherwise, copy decompressed header data into |iov|.
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t bytes_consumed = 0;
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t iov_index = 0;
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  while (iov_index < iov_len &&
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         decompressed_headers_.length() > bytes_consumed) {
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size_t bytes_to_read = min(iov[iov_index].iov_len,
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               decompressed_headers_.length() - bytes_consumed);
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base);
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    memcpy(iov_ptr,
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           decompressed_headers_.data() + bytes_consumed, bytes_to_read);
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bytes_consumed += bytes_to_read;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ++iov_index;
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  decompressed_headers_.erase(0, bytes_consumed);
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (FinishedReadingHeaders()) {
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sequencer()->FlushBufferedFrames();
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return bytes_consumed;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int QuicDataStream::GetReadableRegions(iovec* iov, size_t iov_len) {
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (FinishedReadingHeaders()) {
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return sequencer()->GetReadableRegions(iov, iov_len);
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (iov_len == 0) {
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  iov[0].iov_base = static_cast<void*>(
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const_cast<char*>(decompressed_headers_.data()));
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  iov[0].iov_len = decompressed_headers_.length();
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return 1;
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicDataStream::IsDoneReading() const {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!headers_decompressed_ || !decompressed_headers_.empty()) {
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return sequencer()->IsClosed();
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicDataStream::HasBytesToRead() const {
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return !decompressed_headers_.empty() || sequencer()->HasBytesToRead();
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicDataStream::set_priority(QuicPriority priority) {
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(0u, stream_bytes_written());
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  priority_ = priority;
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicPriority QuicDataStream::EffectivePriority() const {
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return priority();
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)uint32 QuicDataStream::ProcessRawData(const char* data, uint32 data_len) {
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!FinishedReadingHeaders()) {
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(DFATAL) << "ProcessRawData called before headers have been finished";
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return ProcessData(data, data_len);
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const IPEndPoint& QuicDataStream::GetPeerAddress() {
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return session()->peer_address();
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicDataStream::GetSSLInfo(SSLInfo* ssl_info) {
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return session()->GetSSLInfo(ssl_info);
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)uint32 QuicDataStream::ProcessHeaderData() {
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (decompressed_headers_.empty()) {
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t bytes_processed = ProcessData(decompressed_headers_.data(),
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       decompressed_headers_.length());
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (bytes_processed == decompressed_headers_.length()) {
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    decompressed_headers_.clear();
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    decompressed_headers_ = decompressed_headers_.erase(0, bytes_processed);
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return bytes_processed;
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicDataStream::OnStreamHeaders(StringPiece headers_data) {
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  headers_data.AppendToString(&decompressed_headers_);
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProcessHeaderData();
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicDataStream::OnStreamHeadersPriority(QuicPriority priority) {
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(session()->connection()->is_server());
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  set_priority(priority);
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicDataStream::OnStreamHeadersComplete(bool fin, size_t frame_len) {
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  headers_decompressed_ = true;
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (fin) {
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sequencer()->OnStreamFrame(QuicStreamFrame(id(), fin, 0, IOVector()));
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProcessHeaderData();
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (FinishedReadingHeaders()) {
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sequencer()->FlushBufferedFrames();
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicDataStream::OnClose() {
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ReliableQuicStream::OnClose();
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (visitor_) {
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Visitor* visitor = visitor_;
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Calling Visitor::OnClose() may result the destruction of the visitor,
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // so we need to ensure we don't call it again.
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    visitor_ = NULL;
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    visitor->OnClose(this);
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool QuicDataStream::FinishedReadingHeaders() {
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return headers_decompressed_ && decompressed_headers_.empty();
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void QuicDataStream::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DVLOG(1) << "Received WindowUpdateFrame for stream: " << id()
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           << ", with byte offset: " << frame.byte_offset;
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(rjshade): Adjust flow control window.
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace net
194