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