reliable_quic_stream.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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_) {
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DLOG(INFO) << 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.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream_bytes_read_ += frame.data.length();
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;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TerminateFromPeer(false);  // Full close.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ReliableQuicStream::OnConnectionClosed(QuicErrorCode error,
1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                            bool from_peer) {
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (read_side_closed_ && write_side_closed_) {
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != QUIC_NO_ERROR) {
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stream_error_ = QUIC_STREAM_CONNECTION_ERROR;
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    connection_error_ = error;
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (from_peer) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TerminateFromPeer(false);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseWriteSide();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseReadSide();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::TerminateFromPeer(bool half_close) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!half_close) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseWriteSide();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseReadSide();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ReliableQuicStream::Close(QuicRstStreamErrorCode error) {
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream_error_ = error;
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error != QUIC_STREAM_NO_ERROR)  {
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Sending a RstStream results in calling CloseStream.
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    session()->SendRstStream(id(), error);
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    session_->CloseStream(id());
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ReliableQuicStream::CloseConnection(QuicErrorCode error) {
1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  session()->connection()->SendConnectionClose(error);
1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ReliableQuicStream::CloseConnectionWithDetails(QuicErrorCode error,
1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                    const string& details) {
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  session()->connection()->SendConnectionCloseWithDetails(error, details);
1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1475e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)size_t ReliableQuicStream::Readv(const struct iovec* iov, size_t iov_len) {
148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_decompressed_ && decompressed_headers_.empty()) {
149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return sequencer_.Readv(iov, iov_len);
150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t bytes_consumed = 0;
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  size_t iov_index = 0;
153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  while (iov_index < iov_len &&
154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)         decompressed_headers_.length() > bytes_consumed) {
1555e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    size_t bytes_to_read = min(iov[iov_index].iov_len,
1565e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                               decompressed_headers_.length() - bytes_consumed);
157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base);
158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    memcpy(iov_ptr,
159b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)           decompressed_headers_.data() + bytes_consumed, bytes_to_read);
160b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bytes_consumed += bytes_to_read;
161b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    ++iov_index;
162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
163b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  decompressed_headers_.erase(0, bytes_consumed);
164b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return bytes_consumed;
165b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
166b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int ReliableQuicStream::GetReadableRegions(iovec* iov, size_t iov_len) {
168b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_decompressed_ && decompressed_headers_.empty()) {
169b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return sequencer_.GetReadableRegions(iov, iov_len);
170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (iov_len == 0) {
172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return 0;
173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  iov[0].iov_base = static_cast<void*>(
175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      const_cast<char*>(decompressed_headers_.data()));
176b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  iov[0].iov_len = decompressed_headers_.length();
177b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return 1;
178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
179b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::IsHalfClosed() const {
181b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!headers_decompressed_ || !decompressed_headers_.empty()) {
182b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
183b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sequencer_.IsHalfClosed();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::HasBytesToRead() const {
188b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return !decompressed_headers_.empty() || sequencer_.HasBytesToRead();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const IPEndPoint& ReliableQuicStream::GetPeerAddress() const {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return session_->peer_address();
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)QuicSpdyCompressor* ReliableQuicStream::compressor() {
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return session_->compressor();
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool ReliableQuicStream::GetSSLInfo(SSLInfo* ssl_info) {
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return session_->GetSSLInfo(ssl_info);
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WriteData(StringPiece data, bool fin) {
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(data.size() > 0 || fin);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return WriteOrBuffer(data, fin);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ReliableQuicStream::set_priority(QuicPriority priority) {
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(0u, stream_bytes_written_);
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  priority_ = priority;
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WriteOrBuffer(StringPiece data, bool fin) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!fin_buffered_);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicConsumedData consumed_data(0, false);
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fin_buffered_ = fin;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (queued_data_.empty()) {
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    consumed_data = WriteDataInternal(string(data.data(), data.length()), fin);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_LE(consumed_data.bytes_consumed, data.length());
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there's unconsumed data or an unconsumed fin, queue it.
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (consumed_data.bytes_consumed < data.length() ||
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (fin && !consumed_data.fin_consumed)) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    queued_data_.push_back(
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        string(data.data() + consumed_data.bytes_consumed,
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               data.length() - consumed_data.bytes_consumed));
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return QuicConsumedData(data.size(), true);
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReliableQuicStream::OnCanWrite() {
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool fin = false;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!queued_data_.empty()) {
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const string& data = queued_data_.front();
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (queued_data_.size() == 1 && fin_buffered_) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin = true;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicConsumedData consumed_data = WriteDataInternal(data, fin);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (consumed_data.bytes_consumed == data.size() &&
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fin == consumed_data.fin_consumed) {
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      queued_data_.pop_front();
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      queued_data_.front().erase(0, consumed_data.bytes_consumed);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WriteDataInternal(
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StringPiece data, bool fin) {
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  struct iovec iov = {const_cast<char*>(data.data()),
257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                      static_cast<size_t>(data.size())};
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return WritevDataInternal(&iov, 1, fin);
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)QuicConsumedData ReliableQuicStream::WritevDataInternal(const struct iovec* iov,
262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                        int iov_count,
263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                        bool fin) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (write_side_closed_) {
2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed";
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return QuicConsumedData(0, false);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  size_t write_length = 0u;
270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (int i = 0; i < iov_count; ++i) {
271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    write_length += iov[i].iov_len;
272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicConsumedData consumed_data =
274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      session()->WritevData(id(), iov, iov_count, stream_bytes_written_, fin);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream_bytes_written_ += consumed_data.bytes_consumed;
276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (consumed_data.bytes_consumed == write_length) {
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (fin && consumed_data.fin_consumed) {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin_sent_ = true;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CloseWriteSide();
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else if (fin && !consumed_data.fin_consumed) {
281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      session_->MarkWriteBlocked(id(), EffectivePriority());
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    session_->MarkWriteBlocked(id(), EffectivePriority());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return consumed_data;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)QuicPriority ReliableQuicStream::EffectivePriority() const {
290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return priority();
291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::CloseReadSide() {
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (read_side_closed_) {
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DLOG(INFO) << ENDPOINT << "Done reading from stream " << id();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_side_closed_ = true;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (write_side_closed_) {
3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DLOG(INFO) << ENDPOINT << "Closing stream: " << id();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_->CloseStream(id());
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_NE(0u, data_len);
308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (id() == kCryptoStreamId) {
309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // The crypto stream does not use compression.
310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return ProcessData(data, data_len);
311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
312424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  uint32 total_bytes_consumed = 0;
314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_id_ == 0u) {
315424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    total_bytes_consumed += StripPriorityAndHeaderId(data, data_len);
316424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data += total_bytes_consumed;
317424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data_len -= total_bytes_consumed;
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (data_len == 0 || !session_->connection()->connected()) {
319424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return total_bytes_consumed;
320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
321b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
322b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK_NE(0u, headers_id_);
323b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
324b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Once the headers are finished, we simply pass the data through.
325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_decompressed_) {
326b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // Some buffered header data remains.
327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!decompressed_headers_.empty()) {
328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      ProcessHeaderData();
329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
330558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    if (decompressed_headers_.empty()) {
331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      DVLOG(1) << "Delegating procesing to ProcessData";
332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      total_bytes_consumed += ProcessData(data, data_len);
333b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
334b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return total_bytes_consumed;
335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
337b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  QuicHeaderId current_header_id =
338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      session_->decompressor()->current_header_id();
339b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Ensure that this header id looks sane.
340b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (headers_id_ < current_header_id ||
341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      headers_id_ > kMaxHeaderIdDelta + current_header_id) {
3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DVLOG(1) << ENDPOINT
3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)             << "Invalid headers for stream: " << id()
344b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             << " header_id: " << headers_id_
345b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             << " current_header_id: " << current_header_id;
346b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    session_->connection()->SendConnectionClose(QUIC_INVALID_HEADER_ID);
347b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return total_bytes_consumed;
348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
349b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // If we are head-of-line blocked on decompression, then back up.
351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (current_header_id != headers_id_) {
352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    session_->MarkDecompressionBlocked(headers_id_, id());
3531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DVLOG(1) << ENDPOINT
3541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)             << "Unable to decompress header data for stream: " << id()
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)             << " header_id: " << headers_id_;
356b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return total_bytes_consumed;
357b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
358b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
359b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Decompressed data will be delivered to decompressed_headers_.
360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t bytes_consumed = session_->decompressor()->DecompressData(
361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      StringPiece(data, data_len), this);
362558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK_NE(0u, bytes_consumed);
363558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (bytes_consumed > data_len) {
364558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    DCHECK(false) << "DecompressData returned illegal value";
365558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    OnDecompressionError();
366558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return total_bytes_consumed;
367558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
368b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  total_bytes_consumed += bytes_consumed;
369558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  data += bytes_consumed;
370558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  data_len -= bytes_consumed;
371558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
372558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (decompression_failed_) {
373558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    // The session will have been closed in OnDecompressionError.
374558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return total_bytes_consumed;
375558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
376b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
377b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Headers are complete if the decompressor has moved on to the
378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // next stream.
379b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  headers_decompressed_ =
380b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      session_->decompressor()->current_header_id() != headers_id_;
381558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!headers_decompressed_) {
382558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    DCHECK_EQ(0u, data_len);
383558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
384b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProcessHeaderData();
386b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
387558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!headers_decompressed_ || !decompressed_headers_.empty()) {
388558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return total_bytes_consumed;
389558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
390558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
391b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // We have processed all of the decompressed data but we might
392b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // have some more raw data to process.
393558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (data_len > 0) {
394558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    total_bytes_consumed += ProcessData(data, data_len);
395b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
396b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
397b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // The sequencer will push any additional buffered frames if this data
398b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // has been completely consumed.
399b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return total_bytes_consumed;
400b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
401b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
402b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)uint32 ReliableQuicStream::ProcessHeaderData() {
403b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (decompressed_headers_.empty()) {
404b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return 0;
405b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
406b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
407b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  size_t bytes_processed = ProcessData(decompressed_headers_.data(),
408b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                       decompressed_headers_.length());
409b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (bytes_processed == decompressed_headers_.length()) {
410b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    decompressed_headers_.clear();
411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  } else {
412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    decompressed_headers_ = decompressed_headers_.erase(0, bytes_processed);
413b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
414b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return bytes_processed;
415b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
416b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
417b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ReliableQuicStream::OnDecompressorAvailable() {
418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK_EQ(headers_id_,
419b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            session_->decompressor()->current_header_id());
420b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(!headers_decompressed_);
421558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!decompression_failed_);
422b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK_EQ(0u, decompressed_headers_.length());
423b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
424b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  while (!headers_decompressed_) {
425558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    struct iovec iovec;
426558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    if (sequencer_.GetReadableRegions(&iovec, 1) == 0) {
427b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return;
428b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
429b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
430558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    size_t bytes_consumed = session_->decompressor()->DecompressData(
431558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        StringPiece(static_cast<char*>(iovec.iov_base),
432558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                    iovec.iov_len),
433558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        this);
434558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    DCHECK_LE(bytes_consumed, iovec.iov_len);
435558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    if (decompression_failed_) {
436558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      return;
437b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
438558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    sequencer_.MarkConsumed(bytes_consumed);
439558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
440558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    headers_decompressed_ =
441558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        session_->decompressor()->current_header_id() != headers_id_;
442b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
443b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
444b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Either the headers are complete, or the all data as been consumed.
445b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ProcessHeaderData();  // Unprocessed headers remain in decompressed_headers_.
4467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (IsHalfClosed()) {
4477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    TerminateFromPeer(true);
4487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else if (headers_decompressed_ && decompressed_headers_.empty()) {
449b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    sequencer_.FlushBufferedFrames();
450b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
451b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
452b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
453b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool ReliableQuicStream::OnDecompressedData(StringPiece data) {
454b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  data.AppendToString(&decompressed_headers_);
455b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return true;
456b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
457b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
45890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ReliableQuicStream::OnDecompressionError() {
459558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!decompression_failed_);
460558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  decompression_failed_ = true;
46190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  session_->connection()->SendConnectionClose(QUIC_DECOMPRESSION_FAILURE);
46290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
46390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::CloseWriteSide() {
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (write_side_closed_) {
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DLOG(INFO) << ENDPOINT << "Done writing to stream " << id();
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_side_closed_ = true;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_side_closed_) {
4731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DLOG(INFO) << ENDPOINT << "Closing stream: " << id();
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_->CloseStream(id());
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool ReliableQuicStream::HasBufferedData() {
47958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return !queued_data_.empty();
48058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
48158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReliableQuicStream::OnClose() {
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CloseReadSide();
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CloseWriteSide();
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (visitor_) {
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Visitor* visitor = visitor_;
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Calling Visitor::OnClose() may result the destruction of the visitor,
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // so we need to ensure we don't call it again.
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    visitor_ = NULL;
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    visitor->OnClose(this);
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
495424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)uint32 ReliableQuicStream::StripPriorityAndHeaderId(
496424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const char* data, uint32 data_len) {
497424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  uint32 total_bytes_parsed = 0;
498424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
49968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!priority_parsed_ && session_->connection()->is_server()) {
500d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    QuicPriority temporary_priority = priority_;
501424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    total_bytes_parsed = StripUint32(
502d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        data, data_len, &headers_id_and_priority_buffer_, &temporary_priority);
503424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (total_bytes_parsed > 0 && headers_id_and_priority_buffer_.size() == 0) {
504424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      priority_parsed_ = true;
505d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // Spdy priorities are inverted, so the highest numerical value is the
506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // lowest legal priority.
507d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (temporary_priority > static_cast<QuicPriority>(kLowestPriority)) {
508d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        session_->connection()->SendConnectionClose(QUIC_INVALID_PRIORITY);
509d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return 0;
510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      priority_ = temporary_priority;
512424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
513424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data += total_bytes_parsed;
514424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data_len -= total_bytes_parsed;
515424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
516424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (data_len > 0 && headers_id_ == 0u) {
517424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // The headers ID has not yet been read.  Strip it from the beginning of
518424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // the data stream.
519424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    total_bytes_parsed += StripUint32(
520424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        data, data_len, &headers_id_and_priority_buffer_, &headers_id_);
521424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
522424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return total_bytes_parsed;
523424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
524424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
526