reliable_quic_stream.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/reliable_quic_stream.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_session.h"
8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/quic/quic_spdy_decompressor.h"
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/spdy/write_blocked_list.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece;
12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)using std::min;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace {
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// This is somewhat arbitrary.  It's possible, but unlikely, we will either fail
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// to set a priority client-side, or cancel a stream before stripping the
20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// priority from the wire server-side.  In either case, start out with a
21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// priority in the middle.
22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)QuicPriority kDefaultPriority = 3;
23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Appends bytes from data into partial_data_buffer.  Once partial_data_buffer
25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// reaches 4 bytes, copies the data into 'result' and clears
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// partial_data_buffer.
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Returns the number of bytes consumed.
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)uint32 StripUint32(const char* data, uint32 data_len,
29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   string* partial_data_buffer,
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   uint32* result) {
31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK_GT(4u, partial_data_buffer->length());
32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  size_t missing_size = 4 - partial_data_buffer->length();
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (data_len < missing_size) {
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    StringPiece(data, data_len).AppendToString(partial_data_buffer);
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return data_len;
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  StringPiece(data, missing_size).AppendToString(partial_data_buffer);
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK_EQ(4u, partial_data_buffer->length());
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memcpy(result, partial_data_buffer->data(), 4);
40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  partial_data_buffer->clear();
41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return missing_size;
42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace
45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream::ReliableQuicStream(QuicStreamId id,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       QuicSession* session)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : sequencer_(this),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      id_(id),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_(session),
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      visitor_(NULL),
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream_bytes_read_(0),
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream_bytes_written_(0),
54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      headers_decompressed_(false),
55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      priority_(kDefaultPriority),
56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      headers_id_(0),
57558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      decompression_failed_(false),
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stream_error_(QUIC_STREAM_NO_ERROR),
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      connection_error_(QUIC_NO_ERROR),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_side_closed_(false),
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      write_side_closed_(false),
62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      priority_parsed_(false),
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin_buffered_(false),
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      fin_sent_(false),
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      is_server_(session_->is_server()) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream::~ReliableQuicStream() {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::WillAcceptStreamFrame(
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const QuicStreamFrame& frame) const {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_side_closed_) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame.stream_id != id_) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Error!";
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sequencer_.WillAcceptStreamFrame(frame);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(frame.stream_id, id_);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_side_closed_) {
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << ENDPOINT << "Ignoring frame " << frame.stream_id;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We don't want to be reading: blackhole the data.
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note: This count include duplicate data received.
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  stream_bytes_read_ += frame.data.TotalBufferSize();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool accepted = sequencer_.OnStreamFrame(frame);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return accepted;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ReliableQuicStream::OnStreamReset(QuicRstStreamErrorCode error) {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream_error_ = error;
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CloseWriteSide();
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CloseReadSide();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ReliableQuicStream::OnConnectionClosed(QuicErrorCode error,
1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                            bool from_peer) {
1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (read_side_closed_ && write_side_closed_) {
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != QUIC_NO_ERROR) {
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stream_error_ = QUIC_STREAM_CONNECTION_ERROR;
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    connection_error_ = error;
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CloseWriteSide();
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CloseReadSide();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ReliableQuicStream::OnFinRead() {
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(sequencer_.IsClosed());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseReadSide();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ReliableQuicStream::Reset(QuicRstStreamErrorCode error) {
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK_NE(QUIC_STREAM_NO_ERROR, error);
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream_error_ = error;
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Sending a RstStream results in calling CloseStream.
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  session()->SendRstStream(id(), error);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ReliableQuicStream::CloseConnection(QuicErrorCode error) {
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  session()->connection()->SendConnectionClose(error);
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ReliableQuicStream::CloseConnectionWithDetails(QuicErrorCode error,
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                    const string& details) {
1361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  session()->connection()->SendConnectionCloseWithDetails(error, details);
1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1395e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)size_t ReliableQuicStream::Readv(const struct iovec* iov, size_t iov_len) {
140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_decompressed_ && decompressed_headers_.empty()) {
141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return sequencer_.Readv(iov, iov_len);
142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t bytes_consumed = 0;
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  size_t iov_index = 0;
145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  while (iov_index < iov_len &&
146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)         decompressed_headers_.length() > bytes_consumed) {
1475e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    size_t bytes_to_read = min(iov[iov_index].iov_len,
1485e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                               decompressed_headers_.length() - bytes_consumed);
149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base);
150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    memcpy(iov_ptr,
151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)           decompressed_headers_.data() + bytes_consumed, bytes_to_read);
152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bytes_consumed += bytes_to_read;
153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    ++iov_index;
154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  decompressed_headers_.erase(0, bytes_consumed);
156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return bytes_consumed;
157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int ReliableQuicStream::GetReadableRegions(iovec* iov, size_t iov_len) {
160b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_decompressed_ && decompressed_headers_.empty()) {
161b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return sequencer_.GetReadableRegions(iov, iov_len);
162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
163b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (iov_len == 0) {
164b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return 0;
165b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
166b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  iov[0].iov_base = static_cast<void*>(
167b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      const_cast<char*>(decompressed_headers_.data()));
168b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  iov[0].iov_len = decompressed_headers_.length();
169b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return 1;
170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ReliableQuicStream::IsDoneReading() const {
173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!headers_decompressed_ || !decompressed_headers_.empty()) {
174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return sequencer_.IsClosed();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::HasBytesToRead() const {
180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return !decompressed_headers_.empty() || sequencer_.HasBytesToRead();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const IPEndPoint& ReliableQuicStream::GetPeerAddress() const {
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return session_->peer_address();
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicSpdyCompressor* ReliableQuicStream::compressor() {
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return session_->compressor();
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool ReliableQuicStream::GetSSLInfo(SSLInfo* ssl_info) {
1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return session_->GetSSLInfo(ssl_info);
1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WriteData(StringPiece data, bool fin) {
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(data.size() > 0 || fin);
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return WriteOrBuffer(data, fin);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ReliableQuicStream::set_priority(QuicPriority priority) {
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(0u, stream_bytes_written_);
203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  priority_ = priority;
204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WriteOrBuffer(StringPiece data, bool fin) {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!fin_buffered_);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicConsumedData consumed_data(0, false);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fin_buffered_ = fin;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (queued_data_.empty()) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    consumed_data = WriteDataInternal(string(data.data(), data.length()), fin);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_LE(consumed_data.bytes_consumed, data.length());
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there's unconsumed data or an unconsumed fin, queue it.
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (consumed_data.bytes_consumed < data.length() ||
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (fin && !consumed_data.fin_consumed)) {
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    queued_data_.push_back(
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        string(data.data() + consumed_data.bytes_consumed,
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               data.length() - consumed_data.bytes_consumed));
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return QuicConsumedData(data.size(), true);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReliableQuicStream::OnCanWrite() {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool fin = false;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!queued_data_.empty()) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const string& data = queued_data_.front();
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (queued_data_.size() == 1 && fin_buffered_) {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin = true;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicConsumedData consumed_data = WriteDataInternal(data, fin);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (consumed_data.bytes_consumed == data.size() &&
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fin == consumed_data.fin_consumed) {
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      queued_data_.pop_front();
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      queued_data_.front().erase(0, consumed_data.bytes_consumed);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WriteDataInternal(
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StringPiece data, bool fin) {
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  struct iovec iov = {const_cast<char*>(data.data()),
249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                      static_cast<size_t>(data.size())};
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return WritevDataInternal(&iov, 1, fin, NULL);
251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WritevDataInternal(
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const struct iovec* iov,
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int iov_count,
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool fin,
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (write_side_closed_) {
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed";
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return QuicConsumedData(0, false);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  size_t write_length = 0u;
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (int i = 0; i < iov_count; ++i) {
265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    write_length += iov[i].iov_len;
266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QuicConsumedData consumed_data = session()->WritevData(
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      id(), iov, iov_count, stream_bytes_written_, fin, ack_notifier_delegate);
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream_bytes_written_ += consumed_data.bytes_consumed;
270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (consumed_data.bytes_consumed == write_length) {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (fin && consumed_data.fin_consumed) {
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin_sent_ = true;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CloseWriteSide();
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else if (fin && !consumed_data.fin_consumed) {
275d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      session_->MarkWriteBlocked(id(), EffectivePriority());
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    session_->MarkWriteBlocked(id(), EffectivePriority());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return consumed_data;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)QuicPriority ReliableQuicStream::EffectivePriority() const {
284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return priority();
285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::CloseReadSide() {
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (read_side_closed_) {
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "Done reading from stream " << id();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_side_closed_ = true;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (write_side_closed_) {
295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << ENDPOINT << "Closing stream: " << id();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_->CloseStream(id());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_NE(0u, data_len);
302b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (id() == kCryptoStreamId) {
303b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // The crypto stream does not use compression.
304b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return ProcessData(data, data_len);
305b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
306424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  uint32 total_bytes_consumed = 0;
308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_id_ == 0u) {
309424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    total_bytes_consumed += StripPriorityAndHeaderId(data, data_len);
310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data += total_bytes_consumed;
311424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data_len -= total_bytes_consumed;
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (data_len == 0 || total_bytes_consumed == 0) {
313424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return total_bytes_consumed;
314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
315b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
316b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK_NE(0u, headers_id_);
317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Once the headers are finished, we simply pass the data through.
319b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_decompressed_) {
320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // Some buffered header data remains.
321b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!decompressed_headers_.empty()) {
322b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      ProcessHeaderData();
323b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
324558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    if (decompressed_headers_.empty()) {
325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      DVLOG(1) << "Delegating procesing to ProcessData";
326b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      total_bytes_consumed += ProcessData(data, data_len);
327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return total_bytes_consumed;
329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
330b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  QuicHeaderId current_header_id =
332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      session_->decompressor()->current_header_id();
333b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Ensure that this header id looks sane.
334b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_id_ < current_header_id ||
335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      headers_id_ > kMaxHeaderIdDelta + current_header_id) {
3361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DVLOG(1) << ENDPOINT
3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)             << "Invalid headers for stream: " << id()
338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             << " header_id: " << headers_id_
339b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             << " current_header_id: " << current_header_id;
340b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    session_->connection()->SendConnectionClose(QUIC_INVALID_HEADER_ID);
341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return total_bytes_consumed;
342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
343b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
344b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // If we are head-of-line blocked on decompression, then back up.
345b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (current_header_id != headers_id_) {
346b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    session_->MarkDecompressionBlocked(headers_id_, id());
3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DVLOG(1) << ENDPOINT
3481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)             << "Unable to decompress header data for stream: " << id()
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)             << " header_id: " << headers_id_;
350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return total_bytes_consumed;
351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
353b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Decompressed data will be delivered to decompressed_headers_.
354b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t bytes_consumed = session_->decompressor()->DecompressData(
355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      StringPiece(data, data_len), this);
356558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK_NE(0u, bytes_consumed);
357558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (bytes_consumed > data_len) {
358558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    DCHECK(false) << "DecompressData returned illegal value";
359558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    OnDecompressionError();
360558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return total_bytes_consumed;
361558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
362b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  total_bytes_consumed += bytes_consumed;
363558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  data += bytes_consumed;
364558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  data_len -= bytes_consumed;
365558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
366558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (decompression_failed_) {
367558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    // The session will have been closed in OnDecompressionError.
368558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return total_bytes_consumed;
369558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
370b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
371b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Headers are complete if the decompressor has moved on to the
372b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // next stream.
373b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  headers_decompressed_ =
374b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      session_->decompressor()->current_header_id() != headers_id_;
375558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!headers_decompressed_) {
376558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    DCHECK_EQ(0u, data_len);
377558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
379b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProcessHeaderData();
380b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
381558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!headers_decompressed_ || !decompressed_headers_.empty()) {
382558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return total_bytes_consumed;
383558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
384558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // We have processed all of the decompressed data but we might
386b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // have some more raw data to process.
387558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (data_len > 0) {
388558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    total_bytes_consumed += ProcessData(data, data_len);
389b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
390b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
391b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // The sequencer will push any additional buffered frames if this data
392b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // has been completely consumed.
393b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return total_bytes_consumed;
394b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
395b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
396b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)uint32 ReliableQuicStream::ProcessHeaderData() {
397b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (decompressed_headers_.empty()) {
398b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return 0;
399b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
400b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
401b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t bytes_processed = ProcessData(decompressed_headers_.data(),
402b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                       decompressed_headers_.length());
403b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (bytes_processed == decompressed_headers_.length()) {
404b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    decompressed_headers_.clear();
405b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  } else {
406b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    decompressed_headers_ = decompressed_headers_.erase(0, bytes_processed);
407b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
408b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return bytes_processed;
409b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
410b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ReliableQuicStream::OnDecompressorAvailable() {
412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK_EQ(headers_id_,
413b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            session_->decompressor()->current_header_id());
414b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(!headers_decompressed_);
415558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!decompression_failed_);
416b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK_EQ(0u, decompressed_headers_.length());
417b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  while (!headers_decompressed_) {
419558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    struct iovec iovec;
420558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    if (sequencer_.GetReadableRegions(&iovec, 1) == 0) {
421b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return;
422b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
423b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
424558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    size_t bytes_consumed = session_->decompressor()->DecompressData(
425558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        StringPiece(static_cast<char*>(iovec.iov_base),
426558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                    iovec.iov_len),
427558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        this);
428558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    DCHECK_LE(bytes_consumed, iovec.iov_len);
429558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    if (decompression_failed_) {
430558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      return;
431b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
432558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    sequencer_.MarkConsumed(bytes_consumed);
433558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
434558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    headers_decompressed_ =
435558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        session_->decompressor()->current_header_id() != headers_id_;
436b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
437b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
438b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Either the headers are complete, or the all data as been consumed.
439b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProcessHeaderData();  // Unprocessed headers remain in decompressed_headers_.
440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IsDoneReading()) {
441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    OnFinRead();
4427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else if (headers_decompressed_ && decompressed_headers_.empty()) {
443b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    sequencer_.FlushBufferedFrames();
444b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
445b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
446b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
447b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool ReliableQuicStream::OnDecompressedData(StringPiece data) {
448b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  data.AppendToString(&decompressed_headers_);
449b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return true;
450b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
451b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
45290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ReliableQuicStream::OnDecompressionError() {
453558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!decompression_failed_);
454558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  decompression_failed_ = true;
45590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  session_->connection()->SendConnectionClose(QUIC_DECOMPRESSION_FAILURE);
45690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
45790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
45890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::CloseWriteSide() {
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (write_side_closed_) {
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "Done writing to stream " << id();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_side_closed_ = true;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_side_closed_) {
467f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << ENDPOINT << "Closing stream: " << id();
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_->CloseStream(id());
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool ReliableQuicStream::HasBufferedData() {
47358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return !queued_data_.empty();
47458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
47558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReliableQuicStream::OnClose() {
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CloseReadSide();
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CloseWriteSide();
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (visitor_) {
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Visitor* visitor = visitor_;
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Calling Visitor::OnClose() may result the destruction of the visitor,
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // so we need to ensure we don't call it again.
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    visitor_ = NULL;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    visitor->OnClose(this);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
489424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)uint32 ReliableQuicStream::StripPriorityAndHeaderId(
490424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const char* data, uint32 data_len) {
491424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  uint32 total_bytes_parsed = 0;
492424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
49368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!priority_parsed_ && session_->connection()->is_server()) {
494d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    QuicPriority temporary_priority = priority_;
495424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    total_bytes_parsed = StripUint32(
496d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        data, data_len, &headers_id_and_priority_buffer_, &temporary_priority);
497a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (total_bytes_parsed > 0 && headers_id_and_priority_buffer_.empty()) {
498424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      priority_parsed_ = true;
4990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
500d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // Spdy priorities are inverted, so the highest numerical value is the
501d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // lowest legal priority.
502d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (temporary_priority > static_cast<QuicPriority>(kLowestPriority)) {
503d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        session_->connection()->SendConnectionClose(QUIC_INVALID_PRIORITY);
504d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return 0;
505d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      priority_ = temporary_priority;
507424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
508424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data += total_bytes_parsed;
509424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data_len -= total_bytes_parsed;
510424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
511424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (data_len > 0 && headers_id_ == 0u) {
512424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // The headers ID has not yet been read.  Strip it from the beginning of
513424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // the data stream.
514424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    total_bytes_parsed += StripUint32(
515424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        data, data_len, &headers_id_and_priority_buffer_, &headers_id_);
516424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
517424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return total_bytes_parsed;
518424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
519424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
521