blob: 0ac6ecd4885d00a1e9055301ffa505b62eab5232 [file] [log] [blame]
[email protected]9c0b1352012-11-04 00:03:271// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/quic/reliable_quic_stream.h"
6
7#include "net/quic/quic_session.h"
[email protected]c244c5a12013-05-07 20:55:048#include "net/quic/quic_spdy_decompressor.h"
[email protected]24e5bc52013-09-18 15:36:589#include "net/spdy/write_blocked_list.h"
[email protected]9c0b1352012-11-04 00:03:2710
11using base::StringPiece;
[email protected]c244c5a12013-05-07 20:55:0412using std::min;
[email protected]9c0b1352012-11-04 00:03:2713
14namespace net {
15
[email protected]8edeb8d2013-08-28 06:11:4316namespace {
17
18// This is somewhat arbitrary. It's possible, but unlikely, we will either fail
19// to set a priority client-side, or cancel a stream before stripping the
20// priority from the wire server-side. In either case, start out with a
21// priority in the middle.
22QuicPriority kDefaultPriority = 3;
23
24// Appends bytes from data into partial_data_buffer. Once partial_data_buffer
25// reaches 4 bytes, copies the data into 'result' and clears
26// partial_data_buffer.
27// Returns the number of bytes consumed.
28uint32 StripUint32(const char* data, uint32 data_len,
29 string* partial_data_buffer,
30 uint32* result) {
31 DCHECK_GT(4u, partial_data_buffer->length());
32 size_t missing_size = 4 - partial_data_buffer->length();
33 if (data_len < missing_size) {
34 StringPiece(data, data_len).AppendToString(partial_data_buffer);
35 return data_len;
36 }
37 StringPiece(data, missing_size).AppendToString(partial_data_buffer);
38 DCHECK_EQ(4u, partial_data_buffer->length());
39 memcpy(result, partial_data_buffer->data(), 4);
40 partial_data_buffer->clear();
41 return missing_size;
42}
43
44} // namespace
45
[email protected]9c0b1352012-11-04 00:03:2746ReliableQuicStream::ReliableQuicStream(QuicStreamId id,
47 QuicSession* session)
48 : sequencer_(this),
49 id_(id),
[email protected]9c0b1352012-11-04 00:03:2750 session_(session),
[email protected]63534512012-12-23 18:49:0051 visitor_(NULL),
52 stream_bytes_read_(0),
53 stream_bytes_written_(0),
[email protected]2532de12013-05-09 12:29:3354 headers_decompressed_(false),
[email protected]8edeb8d2013-08-28 06:11:4355 priority_(kDefaultPriority),
[email protected]c244c5a12013-05-07 20:55:0456 headers_id_(0),
[email protected]48878092013-07-26 14:51:5657 decompression_failed_(false),
[email protected]74bda142013-03-31 02:49:1158 stream_error_(QUIC_STREAM_NO_ERROR),
59 connection_error_(QUIC_NO_ERROR),
[email protected]9c0b1352012-11-04 00:03:2760 read_side_closed_(false),
[email protected]a5d4eee22012-12-13 09:09:0161 write_side_closed_(false),
[email protected]8edeb8d2013-08-28 06:11:4362 priority_parsed_(false),
[email protected]a5d4eee22012-12-13 09:09:0163 fin_buffered_(false),
64 fin_sent_(false) {
[email protected]9c0b1352012-11-04 00:03:2765}
66
67ReliableQuicStream::~ReliableQuicStream() {
68}
69
70bool ReliableQuicStream::WillAcceptStreamFrame(
71 const QuicStreamFrame& frame) const {
72 if (read_side_closed_) {
[email protected]044ac2b2012-11-13 21:41:0673 return true;
[email protected]9c0b1352012-11-04 00:03:2774 }
75 if (frame.stream_id != id_) {
76 LOG(ERROR) << "Error!";
77 return false;
78 }
79 return sequencer_.WillAcceptStreamFrame(frame);
80}
81
82bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
83 DCHECK_EQ(frame.stream_id, id_);
84 if (read_side_closed_) {
[email protected]044ac2b2012-11-13 21:41:0685 DLOG(INFO) << "Ignoring frame " << frame.stream_id;
86 // We don't want to be reading: blackhole the data.
87 return true;
[email protected]9c0b1352012-11-04 00:03:2788 }
[email protected]9db443912013-02-25 05:27:0389 // Note: This count include duplicate data received.
90 stream_bytes_read_ += frame.data.length();
[email protected]9c0b1352012-11-04 00:03:2791
92 bool accepted = sequencer_.OnStreamFrame(frame);
93
[email protected]9c0b1352012-11-04 00:03:2794 return accepted;
95}
96
[email protected]74bda142013-03-31 02:49:1197void ReliableQuicStream::OnStreamReset(QuicRstStreamErrorCode error) {
98 stream_error_ = error;
[email protected]9db443912013-02-25 05:27:0399 TerminateFromPeer(false); // Full close.
[email protected]9c0b1352012-11-04 00:03:27100}
101
[email protected]2cfc6bb82013-10-27 03:40:44102void ReliableQuicStream::OnConnectionClosed(QuicErrorCode error,
103 bool from_peer) {
[email protected]4e49b6a2013-06-18 16:39:28104 if (read_side_closed_ && write_side_closed_) {
[email protected]a57e0272013-04-26 07:31:47105 return;
106 }
[email protected]74bda142013-03-31 02:49:11107 if (error != QUIC_NO_ERROR) {
108 stream_error_ = QUIC_STREAM_CONNECTION_ERROR;
109 connection_error_ = error;
110 }
111
[email protected]9c0b1352012-11-04 00:03:27112 if (from_peer) {
113 TerminateFromPeer(false);
114 } else {
115 CloseWriteSide();
116 CloseReadSide();
117 }
118}
119
120void ReliableQuicStream::TerminateFromPeer(bool half_close) {
121 if (!half_close) {
122 CloseWriteSide();
123 }
124 CloseReadSide();
125}
126
[email protected]74bda142013-03-31 02:49:11127void ReliableQuicStream::Close(QuicRstStreamErrorCode error) {
128 stream_error_ = error;
[email protected]25c31dc2013-06-05 17:56:04129 if (error != QUIC_STREAM_NO_ERROR) {
130 // Sending a RstStream results in calling CloseStream.
131 session()->SendRstStream(id(), error);
132 } else {
133 session_->CloseStream(id());
134 }
[email protected]9c0b1352012-11-04 00:03:27135}
136
[email protected]2cfc6bb82013-10-27 03:40:44137void ReliableQuicStream::CloseConnection(QuicErrorCode error) {
138 session()->connection()->SendConnectionClose(error);
139}
140
141void ReliableQuicStream::CloseConnectionWithDetails(QuicErrorCode error,
142 const string& details) {
143 session()->connection()->SendConnectionCloseWithDetails(error, details);
144}
145
[email protected]d6ce2eb2013-06-11 13:36:57146size_t ReliableQuicStream::Readv(const struct iovec* iov, size_t iov_len) {
[email protected]2532de12013-05-09 12:29:33147 if (headers_decompressed_ && decompressed_headers_.empty()) {
[email protected]c244c5a12013-05-07 20:55:04148 return sequencer_.Readv(iov, iov_len);
149 }
150 size_t bytes_consumed = 0;
[email protected]b064310782013-05-30 21:12:17151 size_t iov_index = 0;
[email protected]c244c5a12013-05-07 20:55:04152 while (iov_index < iov_len &&
153 decompressed_headers_.length() > bytes_consumed) {
[email protected]d6ce2eb2013-06-11 13:36:57154 size_t bytes_to_read = min(iov[iov_index].iov_len,
155 decompressed_headers_.length() - bytes_consumed);
[email protected]c244c5a12013-05-07 20:55:04156 char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base);
157 memcpy(iov_ptr,
158 decompressed_headers_.data() + bytes_consumed, bytes_to_read);
159 bytes_consumed += bytes_to_read;
160 ++iov_index;
161 }
162 decompressed_headers_.erase(0, bytes_consumed);
163 return bytes_consumed;
164}
165
[email protected]b064310782013-05-30 21:12:17166int ReliableQuicStream::GetReadableRegions(iovec* iov, size_t iov_len) {
[email protected]2532de12013-05-09 12:29:33167 if (headers_decompressed_ && decompressed_headers_.empty()) {
[email protected]c244c5a12013-05-07 20:55:04168 return sequencer_.GetReadableRegions(iov, iov_len);
169 }
170 if (iov_len == 0) {
171 return 0;
172 }
173 iov[0].iov_base = static_cast<void*>(
174 const_cast<char*>(decompressed_headers_.data()));
175 iov[0].iov_len = decompressed_headers_.length();
176 return 1;
177}
178
[email protected]2ff600a2012-11-11 19:22:19179bool ReliableQuicStream::IsHalfClosed() const {
[email protected]2532de12013-05-09 12:29:33180 if (!headers_decompressed_ || !decompressed_headers_.empty()) {
[email protected]c244c5a12013-05-07 20:55:04181 return false;
182 }
[email protected]9c0b1352012-11-04 00:03:27183 return sequencer_.IsHalfClosed();
184}
185
[email protected]2ff600a2012-11-11 19:22:19186bool ReliableQuicStream::HasBytesToRead() const {
[email protected]c244c5a12013-05-07 20:55:04187 return !decompressed_headers_.empty() || sequencer_.HasBytesToRead();
[email protected]9c0b1352012-11-04 00:03:27188}
189
[email protected]f702d572012-12-04 15:56:20190const IPEndPoint& ReliableQuicStream::GetPeerAddress() const {
191 return session_->peer_address();
192}
193
[email protected]821555c2013-05-16 20:20:17194QuicSpdyCompressor* ReliableQuicStream::compressor() {
195 return session_->compressor();
196}
197
[email protected]a69af0522013-07-12 19:23:47198bool ReliableQuicStream::GetSSLInfo(SSLInfo* ssl_info) {
199 return session_->GetSSLInfo(ssl_info);
200}
201
[email protected]cff7b7b52013-01-11 08:49:07202QuicConsumedData ReliableQuicStream::WriteData(StringPiece data, bool fin) {
[email protected]25c31dc2013-06-05 17:56:04203 DCHECK(data.size() > 0 || fin);
[email protected]a5d4eee22012-12-13 09:09:01204 return WriteOrBuffer(data, fin);
205}
206
[email protected]24e5bc52013-09-18 15:36:58207
208void ReliableQuicStream::set_priority(QuicPriority priority) {
209 DCHECK_EQ(0u, stream_bytes_written_);
210 priority_ = priority;
211}
212
[email protected]cff7b7b52013-01-11 08:49:07213QuicConsumedData ReliableQuicStream::WriteOrBuffer(StringPiece data, bool fin) {
[email protected]a5d4eee22012-12-13 09:09:01214 DCHECK(!fin_buffered_);
215
[email protected]cff7b7b52013-01-11 08:49:07216 QuicConsumedData consumed_data(0, false);
[email protected]a5d4eee22012-12-13 09:09:01217 fin_buffered_ = fin;
218
219 if (queued_data_.empty()) {
[email protected]cff7b7b52013-01-11 08:49:07220 consumed_data = WriteDataInternal(string(data.data(), data.length()), fin);
[email protected]c995c572013-01-18 05:43:20221 DCHECK_LE(consumed_data.bytes_consumed, data.length());
[email protected]a5d4eee22012-12-13 09:09:01222 }
[email protected]cff7b7b52013-01-11 08:49:07223
[email protected]c995c572013-01-18 05:43:20224 // If there's unconsumed data or an unconsumed fin, queue it.
225 if (consumed_data.bytes_consumed < data.length() ||
[email protected]cff7b7b52013-01-11 08:49:07226 (fin && !consumed_data.fin_consumed)) {
227 queued_data_.push_back(
228 string(data.data() + consumed_data.bytes_consumed,
229 data.length() - consumed_data.bytes_consumed));
[email protected]a5d4eee22012-12-13 09:09:01230 }
[email protected]cff7b7b52013-01-11 08:49:07231
232 return QuicConsumedData(data.size(), true);
[email protected]a5d4eee22012-12-13 09:09:01233}
234
235void ReliableQuicStream::OnCanWrite() {
236 bool fin = false;
[email protected]610a7e942012-12-18 00:21:39237 while (!queued_data_.empty()) {
[email protected]a5d4eee22012-12-13 09:09:01238 const string& data = queued_data_.front();
239 if (queued_data_.size() == 1 && fin_buffered_) {
240 fin = true;
241 }
[email protected]cff7b7b52013-01-11 08:49:07242 QuicConsumedData consumed_data = WriteDataInternal(data, fin);
243 if (consumed_data.bytes_consumed == data.size() &&
244 fin == consumed_data.fin_consumed) {
[email protected]a5d4eee22012-12-13 09:09:01245 queued_data_.pop_front();
246 } else {
[email protected]cff7b7b52013-01-11 08:49:07247 queued_data_.front().erase(0, consumed_data.bytes_consumed);
[email protected]610a7e942012-12-18 00:21:39248 break;
[email protected]a5d4eee22012-12-13 09:09:01249 }
250 }
251}
252
[email protected]cff7b7b52013-01-11 08:49:07253QuicConsumedData ReliableQuicStream::WriteDataInternal(
254 StringPiece data, bool fin) {
[email protected]24e5bc52013-09-18 15:36:58255 struct iovec iov = {const_cast<char*>(data.data()),
256 static_cast<size_t>(data.size())};
257 return WritevDataInternal(&iov, 1, fin);
258}
259
260QuicConsumedData ReliableQuicStream::WritevDataInternal(const struct iovec* iov,
[email protected]4d1789c32013-09-18 23:54:36261 int iov_count,
[email protected]24e5bc52013-09-18 15:36:58262 bool fin) {
[email protected]9c0b1352012-11-04 00:03:27263 if (write_side_closed_) {
264 DLOG(ERROR) << "Attempt to write when the write side is closed";
[email protected]cff7b7b52013-01-11 08:49:07265 return QuicConsumedData(0, false);
[email protected]9c0b1352012-11-04 00:03:27266 }
267
[email protected]24e5bc52013-09-18 15:36:58268 size_t write_length = 0u;
[email protected]4d1789c32013-09-18 23:54:36269 for (int i = 0; i < iov_count; ++i) {
[email protected]24e5bc52013-09-18 15:36:58270 write_length += iov[i].iov_len;
271 }
[email protected]cff7b7b52013-01-11 08:49:07272 QuicConsumedData consumed_data =
[email protected]4d1789c32013-09-18 23:54:36273 session()->WritevData(id(), iov, iov_count, stream_bytes_written_, fin);
[email protected]cff7b7b52013-01-11 08:49:07274 stream_bytes_written_ += consumed_data.bytes_consumed;
[email protected]24e5bc52013-09-18 15:36:58275 if (consumed_data.bytes_consumed == write_length) {
[email protected]cff7b7b52013-01-11 08:49:07276 if (fin && consumed_data.fin_consumed) {
[email protected]a5d4eee22012-12-13 09:09:01277 fin_sent_ = true;
278 CloseWriteSide();
[email protected]25c31dc2013-06-05 17:56:04279 } else if (fin && !consumed_data.fin_consumed) {
[email protected]24e5bc52013-09-18 15:36:58280 session_->MarkWriteBlocked(id(), EffectivePriority());
[email protected]a5d4eee22012-12-13 09:09:01281 }
282 } else {
[email protected]24e5bc52013-09-18 15:36:58283 session_->MarkWriteBlocked(id(), EffectivePriority());
[email protected]9c0b1352012-11-04 00:03:27284 }
[email protected]cff7b7b52013-01-11 08:49:07285 return consumed_data;
[email protected]9c0b1352012-11-04 00:03:27286}
287
[email protected]24e5bc52013-09-18 15:36:58288QuicPriority ReliableQuicStream::EffectivePriority() const {
289 return priority();
290}
291
[email protected]9c0b1352012-11-04 00:03:27292void ReliableQuicStream::CloseReadSide() {
[email protected]044ac2b2012-11-13 21:41:06293 if (read_side_closed_) {
294 return;
295 }
[email protected]9c0b1352012-11-04 00:03:27296 DLOG(INFO) << "Done reading from stream " << id();
297
298 read_side_closed_ = true;
299 if (write_side_closed_) {
[email protected]f702d572012-12-04 15:56:20300 DLOG(INFO) << "Closing stream: " << id();
[email protected]9c0b1352012-11-04 00:03:27301 session_->CloseStream(id());
302 }
303}
304
[email protected]c244c5a12013-05-07 20:55:04305uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
[email protected]4d1789c32013-09-18 23:54:36306 DCHECK_NE(0u, data_len);
[email protected]c244c5a12013-05-07 20:55:04307 if (id() == kCryptoStreamId) {
[email protected]c244c5a12013-05-07 20:55:04308 // The crypto stream does not use compression.
309 return ProcessData(data, data_len);
310 }
[email protected]8edeb8d2013-08-28 06:11:43311
[email protected]c244c5a12013-05-07 20:55:04312 uint32 total_bytes_consumed = 0;
313 if (headers_id_ == 0u) {
[email protected]8edeb8d2013-08-28 06:11:43314 total_bytes_consumed += StripPriorityAndHeaderId(data, data_len);
315 data += total_bytes_consumed;
316 data_len -= total_bytes_consumed;
[email protected]24e5bc52013-09-18 15:36:58317 if (data_len == 0 || !session_->connection()->connected()) {
[email protected]8edeb8d2013-08-28 06:11:43318 return total_bytes_consumed;
[email protected]c244c5a12013-05-07 20:55:04319 }
[email protected]c244c5a12013-05-07 20:55:04320 }
321 DCHECK_NE(0u, headers_id_);
322
323 // Once the headers are finished, we simply pass the data through.
[email protected]2532de12013-05-09 12:29:33324 if (headers_decompressed_) {
325 // Some buffered header data remains.
326 if (!decompressed_headers_.empty()) {
327 ProcessHeaderData();
328 }
[email protected]48878092013-07-26 14:51:56329 if (decompressed_headers_.empty()) {
[email protected]2532de12013-05-09 12:29:33330 DVLOG(1) << "Delegating procesing to ProcessData";
331 total_bytes_consumed += ProcessData(data, data_len);
332 }
333 return total_bytes_consumed;
[email protected]c244c5a12013-05-07 20:55:04334 }
335
336 QuicHeaderId current_header_id =
337 session_->decompressor()->current_header_id();
338 // Ensure that this header id looks sane.
339 if (headers_id_ < current_header_id ||
340 headers_id_ > kMaxHeaderIdDelta + current_header_id) {
[email protected]2532de12013-05-09 12:29:33341 DVLOG(1) << "Invalid headers for stream: " << id()
342 << " header_id: " << headers_id_
343 << " current_header_id: " << current_header_id;
[email protected]c244c5a12013-05-07 20:55:04344 session_->connection()->SendConnectionClose(QUIC_INVALID_HEADER_ID);
[email protected]2532de12013-05-09 12:29:33345 return total_bytes_consumed;
[email protected]c244c5a12013-05-07 20:55:04346 }
347
348 // If we are head-of-line blocked on decompression, then back up.
349 if (current_header_id != headers_id_) {
350 session_->MarkDecompressionBlocked(headers_id_, id());
[email protected]821555c2013-05-16 20:20:17351 DVLOG(1) << "Unable to decompress header data for stream: " << id()
352 << " header_id: " << headers_id_;
[email protected]c244c5a12013-05-07 20:55:04353 return total_bytes_consumed;
354 }
355
356 // Decompressed data will be delivered to decompressed_headers_.
357 size_t bytes_consumed = session_->decompressor()->DecompressData(
358 StringPiece(data, data_len), this);
[email protected]48878092013-07-26 14:51:56359 DCHECK_NE(0u, bytes_consumed);
360 if (bytes_consumed > data_len) {
361 DCHECK(false) << "DecompressData returned illegal value";
362 OnDecompressionError();
363 return total_bytes_consumed;
364 }
[email protected]c244c5a12013-05-07 20:55:04365 total_bytes_consumed += bytes_consumed;
[email protected]48878092013-07-26 14:51:56366 data += bytes_consumed;
367 data_len -= bytes_consumed;
368
369 if (decompression_failed_) {
370 // The session will have been closed in OnDecompressionError.
371 return total_bytes_consumed;
372 }
[email protected]c244c5a12013-05-07 20:55:04373
374 // Headers are complete if the decompressor has moved on to the
375 // next stream.
[email protected]2532de12013-05-09 12:29:33376 headers_decompressed_ =
[email protected]c244c5a12013-05-07 20:55:04377 session_->decompressor()->current_header_id() != headers_id_;
[email protected]48878092013-07-26 14:51:56378 if (!headers_decompressed_) {
379 DCHECK_EQ(0u, data_len);
380 }
[email protected]c244c5a12013-05-07 20:55:04381
[email protected]2532de12013-05-09 12:29:33382 ProcessHeaderData();
[email protected]c244c5a12013-05-07 20:55:04383
[email protected]48878092013-07-26 14:51:56384 if (!headers_decompressed_ || !decompressed_headers_.empty()) {
385 return total_bytes_consumed;
386 }
387
[email protected]c244c5a12013-05-07 20:55:04388 // We have processed all of the decompressed data but we might
389 // have some more raw data to process.
[email protected]48878092013-07-26 14:51:56390 if (data_len > 0) {
391 total_bytes_consumed += ProcessData(data, data_len);
[email protected]c244c5a12013-05-07 20:55:04392 }
393
394 // The sequencer will push any additional buffered frames if this data
395 // has been completely consumed.
396 return total_bytes_consumed;
397}
398
399uint32 ReliableQuicStream::ProcessHeaderData() {
400 if (decompressed_headers_.empty()) {
401 return 0;
402 }
403
404 size_t bytes_processed = ProcessData(decompressed_headers_.data(),
405 decompressed_headers_.length());
406 if (bytes_processed == decompressed_headers_.length()) {
407 decompressed_headers_.clear();
408 } else {
409 decompressed_headers_ = decompressed_headers_.erase(0, bytes_processed);
410 }
411 return bytes_processed;
412}
413
414void ReliableQuicStream::OnDecompressorAvailable() {
415 DCHECK_EQ(headers_id_,
416 session_->decompressor()->current_header_id());
[email protected]2532de12013-05-09 12:29:33417 DCHECK(!headers_decompressed_);
[email protected]48878092013-07-26 14:51:56418 DCHECK(!decompression_failed_);
[email protected]c244c5a12013-05-07 20:55:04419 DCHECK_EQ(0u, decompressed_headers_.length());
420
[email protected]2532de12013-05-09 12:29:33421 while (!headers_decompressed_) {
[email protected]8fb9adb2013-07-28 14:04:37422 struct iovec iovec;
423 if (sequencer_.GetReadableRegions(&iovec, 1) == 0) {
[email protected]c244c5a12013-05-07 20:55:04424 return;
425 }
[email protected]c244c5a12013-05-07 20:55:04426
[email protected]8fb9adb2013-07-28 14:04:37427 size_t bytes_consumed = session_->decompressor()->DecompressData(
428 StringPiece(static_cast<char*>(iovec.iov_base),
429 iovec.iov_len),
430 this);
431 DCHECK_LE(bytes_consumed, iovec.iov_len);
432 if (decompression_failed_) {
433 return;
[email protected]c244c5a12013-05-07 20:55:04434 }
[email protected]8fb9adb2013-07-28 14:04:37435 sequencer_.MarkConsumed(bytes_consumed);
436
437 headers_decompressed_ =
438 session_->decompressor()->current_header_id() != headers_id_;
[email protected]c244c5a12013-05-07 20:55:04439 }
440
441 // Either the headers are complete, or the all data as been consumed.
[email protected]c244c5a12013-05-07 20:55:04442 ProcessHeaderData(); // Unprocessed headers remain in decompressed_headers_.
[email protected]4e49b6a2013-06-18 16:39:28443 if (IsHalfClosed()) {
444 TerminateFromPeer(true);
445 } else if (headers_decompressed_ && decompressed_headers_.empty()) {
[email protected]c244c5a12013-05-07 20:55:04446 sequencer_.FlushBufferedFrames();
447 }
448}
449
450bool ReliableQuicStream::OnDecompressedData(StringPiece data) {
451 data.AppendToString(&decompressed_headers_);
452 return true;
453}
454
[email protected]899951652013-05-16 12:52:39455void ReliableQuicStream::OnDecompressionError() {
[email protected]48878092013-07-26 14:51:56456 DCHECK(!decompression_failed_);
457 decompression_failed_ = true;
[email protected]899951652013-05-16 12:52:39458 session_->connection()->SendConnectionClose(QUIC_DECOMPRESSION_FAILURE);
459}
460
461
[email protected]9c0b1352012-11-04 00:03:27462void ReliableQuicStream::CloseWriteSide() {
[email protected]044ac2b2012-11-13 21:41:06463 if (write_side_closed_) {
464 return;
465 }
[email protected]9c0b1352012-11-04 00:03:27466 DLOG(INFO) << "Done writing to stream " << id();
467
468 write_side_closed_ = true;
469 if (read_side_closed_) {
[email protected]f702d572012-12-04 15:56:20470 DLOG(INFO) << "Closing stream: " << id();
[email protected]9c0b1352012-11-04 00:03:27471 session_->CloseStream(id());
472 }
473}
474
[email protected]6adeb922013-09-01 22:43:25475bool ReliableQuicStream::HasBufferedData() {
476 return !queued_data_.empty();
477}
478
[email protected]63534512012-12-23 18:49:00479void ReliableQuicStream::OnClose() {
[email protected]a57e0272013-04-26 07:31:47480 CloseReadSide();
481 CloseWriteSide();
482
[email protected]63534512012-12-23 18:49:00483 if (visitor_) {
484 Visitor* visitor = visitor_;
485 // Calling Visitor::OnClose() may result the destruction of the visitor,
486 // so we need to ensure we don't call it again.
487 visitor_ = NULL;
488 visitor->OnClose(this);
489 }
490}
491
[email protected]8edeb8d2013-08-28 06:11:43492uint32 ReliableQuicStream::StripPriorityAndHeaderId(
493 const char* data, uint32 data_len) {
494 uint32 total_bytes_parsed = 0;
495
[email protected]c67a82cb2013-09-24 02:53:21496 if (!priority_parsed_ && session_->connection()->is_server()) {
[email protected]24e5bc52013-09-18 15:36:58497 QuicPriority temporary_priority = priority_;
[email protected]8edeb8d2013-08-28 06:11:43498 total_bytes_parsed = StripUint32(
[email protected]24e5bc52013-09-18 15:36:58499 data, data_len, &headers_id_and_priority_buffer_, &temporary_priority);
[email protected]8edeb8d2013-08-28 06:11:43500 if (total_bytes_parsed > 0 && headers_id_and_priority_buffer_.size() == 0) {
[email protected]8edeb8d2013-08-28 06:11:43501 priority_parsed_ = true;
[email protected]24e5bc52013-09-18 15:36:58502 // Spdy priorities are inverted, so the highest numerical value is the
503 // lowest legal priority.
504 if (temporary_priority > static_cast<QuicPriority>(kLowestPriority)) {
505 session_->connection()->SendConnectionClose(QUIC_INVALID_PRIORITY);
506 return 0;
507 }
508 priority_ = temporary_priority;
[email protected]8edeb8d2013-08-28 06:11:43509 }
510 data += total_bytes_parsed;
511 data_len -= total_bytes_parsed;
512 }
513 if (data_len > 0 && headers_id_ == 0u) {
514 // The headers ID has not yet been read. Strip it from the beginning of
515 // the data stream.
516 total_bytes_parsed += StripUint32(
517 data, data_len, &headers_id_and_priority_buffer_, &headers_id_);
518 }
519 return total_bytes_parsed;
520}
521
[email protected]9c0b1352012-11-04 00:03:27522} // namespace net