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