blob: c2cb3f1ff5214ac1feba89f3021c9735c4f6bfb9 [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]9c0b1352012-11-04 00:03:279
10using base::StringPiece;
[email protected]c244c5a12013-05-07 20:55:0411using std::min;
[email protected]9c0b1352012-11-04 00:03:2712
13namespace net {
14
15ReliableQuicStream::ReliableQuicStream(QuicStreamId id,
16 QuicSession* session)
17 : sequencer_(this),
18 id_(id),
[email protected]9c0b1352012-11-04 00:03:2719 session_(session),
[email protected]63534512012-12-23 18:49:0020 visitor_(NULL),
21 stream_bytes_read_(0),
22 stream_bytes_written_(0),
[email protected]2532de12013-05-09 12:29:3323 headers_decompressed_(false),
[email protected]c244c5a12013-05-07 20:55:0424 headers_id_(0),
[email protected]48878092013-07-26 14:51:5625 decompression_failed_(false),
[email protected]74bda142013-03-31 02:49:1126 stream_error_(QUIC_STREAM_NO_ERROR),
27 connection_error_(QUIC_NO_ERROR),
[email protected]9c0b1352012-11-04 00:03:2728 read_side_closed_(false),
[email protected]a5d4eee22012-12-13 09:09:0129 write_side_closed_(false),
30 fin_buffered_(false),
31 fin_sent_(false) {
[email protected]9c0b1352012-11-04 00:03:2732}
33
34ReliableQuicStream::~ReliableQuicStream() {
35}
36
37bool ReliableQuicStream::WillAcceptStreamFrame(
38 const QuicStreamFrame& frame) const {
39 if (read_side_closed_) {
[email protected]044ac2b2012-11-13 21:41:0640 return true;
[email protected]9c0b1352012-11-04 00:03:2741 }
42 if (frame.stream_id != id_) {
43 LOG(ERROR) << "Error!";
44 return false;
45 }
46 return sequencer_.WillAcceptStreamFrame(frame);
47}
48
49bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
50 DCHECK_EQ(frame.stream_id, id_);
51 if (read_side_closed_) {
[email protected]044ac2b2012-11-13 21:41:0652 DLOG(INFO) << "Ignoring frame " << frame.stream_id;
53 // We don't want to be reading: blackhole the data.
54 return true;
[email protected]9c0b1352012-11-04 00:03:2755 }
[email protected]9db443912013-02-25 05:27:0356 // Note: This count include duplicate data received.
57 stream_bytes_read_ += frame.data.length();
[email protected]9c0b1352012-11-04 00:03:2758
59 bool accepted = sequencer_.OnStreamFrame(frame);
60
[email protected]9c0b1352012-11-04 00:03:2761 return accepted;
62}
63
[email protected]74bda142013-03-31 02:49:1164void ReliableQuicStream::OnStreamReset(QuicRstStreamErrorCode error) {
65 stream_error_ = error;
[email protected]9db443912013-02-25 05:27:0366 TerminateFromPeer(false); // Full close.
[email protected]9c0b1352012-11-04 00:03:2767}
68
69void ReliableQuicStream::ConnectionClose(QuicErrorCode error, bool from_peer) {
[email protected]4e49b6a2013-06-18 16:39:2870 if (read_side_closed_ && write_side_closed_) {
[email protected]a57e0272013-04-26 07:31:4771 return;
72 }
[email protected]74bda142013-03-31 02:49:1173 if (error != QUIC_NO_ERROR) {
74 stream_error_ = QUIC_STREAM_CONNECTION_ERROR;
75 connection_error_ = error;
76 }
77
[email protected]9c0b1352012-11-04 00:03:2778 if (from_peer) {
79 TerminateFromPeer(false);
80 } else {
81 CloseWriteSide();
82 CloseReadSide();
83 }
84}
85
86void ReliableQuicStream::TerminateFromPeer(bool half_close) {
87 if (!half_close) {
88 CloseWriteSide();
89 }
90 CloseReadSide();
91}
92
[email protected]74bda142013-03-31 02:49:1193void ReliableQuicStream::Close(QuicRstStreamErrorCode error) {
94 stream_error_ = error;
[email protected]25c31dc2013-06-05 17:56:0495 if (error != QUIC_STREAM_NO_ERROR) {
96 // Sending a RstStream results in calling CloseStream.
97 session()->SendRstStream(id(), error);
98 } else {
99 session_->CloseStream(id());
100 }
[email protected]9c0b1352012-11-04 00:03:27101}
102
[email protected]d6ce2eb2013-06-11 13:36:57103size_t ReliableQuicStream::Readv(const struct iovec* iov, size_t iov_len) {
[email protected]2532de12013-05-09 12:29:33104 if (headers_decompressed_ && decompressed_headers_.empty()) {
[email protected]c244c5a12013-05-07 20:55:04105 return sequencer_.Readv(iov, iov_len);
106 }
107 size_t bytes_consumed = 0;
[email protected]b064310782013-05-30 21:12:17108 size_t iov_index = 0;
[email protected]c244c5a12013-05-07 20:55:04109 while (iov_index < iov_len &&
110 decompressed_headers_.length() > bytes_consumed) {
[email protected]d6ce2eb2013-06-11 13:36:57111 size_t bytes_to_read = min(iov[iov_index].iov_len,
112 decompressed_headers_.length() - bytes_consumed);
[email protected]c244c5a12013-05-07 20:55:04113 char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base);
114 memcpy(iov_ptr,
115 decompressed_headers_.data() + bytes_consumed, bytes_to_read);
116 bytes_consumed += bytes_to_read;
117 ++iov_index;
118 }
119 decompressed_headers_.erase(0, bytes_consumed);
120 return bytes_consumed;
121}
122
[email protected]b064310782013-05-30 21:12:17123int ReliableQuicStream::GetReadableRegions(iovec* iov, size_t iov_len) {
[email protected]2532de12013-05-09 12:29:33124 if (headers_decompressed_ && decompressed_headers_.empty()) {
[email protected]c244c5a12013-05-07 20:55:04125 return sequencer_.GetReadableRegions(iov, iov_len);
126 }
127 if (iov_len == 0) {
128 return 0;
129 }
130 iov[0].iov_base = static_cast<void*>(
131 const_cast<char*>(decompressed_headers_.data()));
132 iov[0].iov_len = decompressed_headers_.length();
133 return 1;
134}
135
[email protected]2ff600a2012-11-11 19:22:19136bool ReliableQuicStream::IsHalfClosed() const {
[email protected]2532de12013-05-09 12:29:33137 if (!headers_decompressed_ || !decompressed_headers_.empty()) {
[email protected]c244c5a12013-05-07 20:55:04138 return false;
139 }
[email protected]9c0b1352012-11-04 00:03:27140 return sequencer_.IsHalfClosed();
141}
142
[email protected]2ff600a2012-11-11 19:22:19143bool ReliableQuicStream::HasBytesToRead() const {
[email protected]c244c5a12013-05-07 20:55:04144 return !decompressed_headers_.empty() || sequencer_.HasBytesToRead();
[email protected]9c0b1352012-11-04 00:03:27145}
146
[email protected]f702d572012-12-04 15:56:20147const IPEndPoint& ReliableQuicStream::GetPeerAddress() const {
148 return session_->peer_address();
149}
150
[email protected]821555c2013-05-16 20:20:17151QuicSpdyCompressor* ReliableQuicStream::compressor() {
152 return session_->compressor();
153}
154
[email protected]a69af0522013-07-12 19:23:47155bool ReliableQuicStream::GetSSLInfo(SSLInfo* ssl_info) {
156 return session_->GetSSLInfo(ssl_info);
157}
158
[email protected]cff7b7b52013-01-11 08:49:07159QuicConsumedData ReliableQuicStream::WriteData(StringPiece data, bool fin) {
[email protected]25c31dc2013-06-05 17:56:04160 DCHECK(data.size() > 0 || fin);
[email protected]a5d4eee22012-12-13 09:09:01161 return WriteOrBuffer(data, fin);
162}
163
[email protected]cff7b7b52013-01-11 08:49:07164QuicConsumedData ReliableQuicStream::WriteOrBuffer(StringPiece data, bool fin) {
[email protected]a5d4eee22012-12-13 09:09:01165 DCHECK(!fin_buffered_);
166
[email protected]cff7b7b52013-01-11 08:49:07167 QuicConsumedData consumed_data(0, false);
[email protected]a5d4eee22012-12-13 09:09:01168 fin_buffered_ = fin;
169
170 if (queued_data_.empty()) {
[email protected]cff7b7b52013-01-11 08:49:07171 consumed_data = WriteDataInternal(string(data.data(), data.length()), fin);
[email protected]c995c572013-01-18 05:43:20172 DCHECK_LE(consumed_data.bytes_consumed, data.length());
[email protected]a5d4eee22012-12-13 09:09:01173 }
[email protected]cff7b7b52013-01-11 08:49:07174
[email protected]c995c572013-01-18 05:43:20175 // If there's unconsumed data or an unconsumed fin, queue it.
176 if (consumed_data.bytes_consumed < data.length() ||
[email protected]cff7b7b52013-01-11 08:49:07177 (fin && !consumed_data.fin_consumed)) {
178 queued_data_.push_back(
179 string(data.data() + consumed_data.bytes_consumed,
180 data.length() - consumed_data.bytes_consumed));
[email protected]a5d4eee22012-12-13 09:09:01181 }
[email protected]cff7b7b52013-01-11 08:49:07182
183 return QuicConsumedData(data.size(), true);
[email protected]a5d4eee22012-12-13 09:09:01184}
185
186void ReliableQuicStream::OnCanWrite() {
187 bool fin = false;
[email protected]610a7e942012-12-18 00:21:39188 while (!queued_data_.empty()) {
[email protected]a5d4eee22012-12-13 09:09:01189 const string& data = queued_data_.front();
190 if (queued_data_.size() == 1 && fin_buffered_) {
191 fin = true;
192 }
[email protected]cff7b7b52013-01-11 08:49:07193 QuicConsumedData consumed_data = WriteDataInternal(data, fin);
194 if (consumed_data.bytes_consumed == data.size() &&
195 fin == consumed_data.fin_consumed) {
[email protected]a5d4eee22012-12-13 09:09:01196 queued_data_.pop_front();
197 } else {
[email protected]cff7b7b52013-01-11 08:49:07198 queued_data_.front().erase(0, consumed_data.bytes_consumed);
[email protected]610a7e942012-12-18 00:21:39199 break;
[email protected]a5d4eee22012-12-13 09:09:01200 }
201 }
202}
203
[email protected]cff7b7b52013-01-11 08:49:07204QuicConsumedData ReliableQuicStream::WriteDataInternal(
205 StringPiece data, bool fin) {
[email protected]9c0b1352012-11-04 00:03:27206 if (write_side_closed_) {
207 DLOG(ERROR) << "Attempt to write when the write side is closed";
[email protected]cff7b7b52013-01-11 08:49:07208 return QuicConsumedData(0, false);
[email protected]9c0b1352012-11-04 00:03:27209 }
210
[email protected]cff7b7b52013-01-11 08:49:07211 QuicConsumedData consumed_data =
[email protected]9db443912013-02-25 05:27:03212 session()->WriteData(id(), data, stream_bytes_written_, fin);
[email protected]cff7b7b52013-01-11 08:49:07213 stream_bytes_written_ += consumed_data.bytes_consumed;
214 if (consumed_data.bytes_consumed == data.length()) {
215 if (fin && consumed_data.fin_consumed) {
[email protected]a5d4eee22012-12-13 09:09:01216 fin_sent_ = true;
217 CloseWriteSide();
[email protected]25c31dc2013-06-05 17:56:04218 } else if (fin && !consumed_data.fin_consumed) {
219 session_->MarkWriteBlocked(id());
[email protected]a5d4eee22012-12-13 09:09:01220 }
221 } else {
222 session_->MarkWriteBlocked(id());
[email protected]9c0b1352012-11-04 00:03:27223 }
[email protected]cff7b7b52013-01-11 08:49:07224 return consumed_data;
[email protected]9c0b1352012-11-04 00:03:27225}
226
227void ReliableQuicStream::CloseReadSide() {
[email protected]044ac2b2012-11-13 21:41:06228 if (read_side_closed_) {
229 return;
230 }
[email protected]9c0b1352012-11-04 00:03:27231 DLOG(INFO) << "Done reading from stream " << id();
232
233 read_side_closed_ = true;
234 if (write_side_closed_) {
[email protected]f702d572012-12-04 15:56:20235 DLOG(INFO) << "Closing stream: " << id();
[email protected]9c0b1352012-11-04 00:03:27236 session_->CloseStream(id());
237 }
238}
239
[email protected]c244c5a12013-05-07 20:55:04240uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
241 if (id() == kCryptoStreamId) {
[email protected]dbeea412013-07-16 17:38:46242 if (data_len == 0) {
243 return 0;
244 }
[email protected]c244c5a12013-05-07 20:55:04245 // The crypto stream does not use compression.
246 return ProcessData(data, data_len);
247 }
248 uint32 total_bytes_consumed = 0;
249 if (headers_id_ == 0u) {
250 // The headers ID has not yet been read. Strip it from the beginning of
251 // the data stream.
252 DCHECK_GT(4u, headers_id_buffer_.length());
253 size_t missing_size = 4 - headers_id_buffer_.length();
254 if (data_len < missing_size) {
255 StringPiece(data, data_len).AppendToString(&headers_id_buffer_);
256 return data_len;
257 }
258 total_bytes_consumed += missing_size;
259 StringPiece(data, missing_size).AppendToString(&headers_id_buffer_);
260 DCHECK_EQ(4u, headers_id_buffer_.length());
261 memcpy(&headers_id_, headers_id_buffer_.data(), 4);
262 headers_id_buffer_.clear();
263 data += missing_size;
264 data_len -= missing_size;
265 }
266 DCHECK_NE(0u, headers_id_);
[email protected]48878092013-07-26 14:51:56267 if (data_len == 0) {
268 return total_bytes_consumed;
269 }
[email protected]c244c5a12013-05-07 20:55:04270
271 // Once the headers are finished, we simply pass the data through.
[email protected]2532de12013-05-09 12:29:33272 if (headers_decompressed_) {
273 // Some buffered header data remains.
274 if (!decompressed_headers_.empty()) {
275 ProcessHeaderData();
276 }
[email protected]48878092013-07-26 14:51:56277 if (decompressed_headers_.empty()) {
[email protected]2532de12013-05-09 12:29:33278 DVLOG(1) << "Delegating procesing to ProcessData";
279 total_bytes_consumed += ProcessData(data, data_len);
280 }
281 return total_bytes_consumed;
[email protected]c244c5a12013-05-07 20:55:04282 }
283
284 QuicHeaderId current_header_id =
285 session_->decompressor()->current_header_id();
286 // Ensure that this header id looks sane.
287 if (headers_id_ < current_header_id ||
288 headers_id_ > kMaxHeaderIdDelta + current_header_id) {
[email protected]2532de12013-05-09 12:29:33289 DVLOG(1) << "Invalid headers for stream: " << id()
290 << " header_id: " << headers_id_
291 << " current_header_id: " << current_header_id;
[email protected]c244c5a12013-05-07 20:55:04292 session_->connection()->SendConnectionClose(QUIC_INVALID_HEADER_ID);
[email protected]2532de12013-05-09 12:29:33293 return total_bytes_consumed;
[email protected]c244c5a12013-05-07 20:55:04294 }
295
296 // If we are head-of-line blocked on decompression, then back up.
297 if (current_header_id != headers_id_) {
298 session_->MarkDecompressionBlocked(headers_id_, id());
[email protected]821555c2013-05-16 20:20:17299 DVLOG(1) << "Unable to decompress header data for stream: " << id()
300 << " header_id: " << headers_id_;
[email protected]c244c5a12013-05-07 20:55:04301 return total_bytes_consumed;
302 }
303
304 // Decompressed data will be delivered to decompressed_headers_.
305 size_t bytes_consumed = session_->decompressor()->DecompressData(
306 StringPiece(data, data_len), this);
[email protected]48878092013-07-26 14:51:56307 DCHECK_NE(0u, bytes_consumed);
308 if (bytes_consumed > data_len) {
309 DCHECK(false) << "DecompressData returned illegal value";
310 OnDecompressionError();
311 return total_bytes_consumed;
312 }
[email protected]c244c5a12013-05-07 20:55:04313 total_bytes_consumed += bytes_consumed;
[email protected]48878092013-07-26 14:51:56314 data += bytes_consumed;
315 data_len -= bytes_consumed;
316
317 if (decompression_failed_) {
318 // The session will have been closed in OnDecompressionError.
319 return total_bytes_consumed;
320 }
[email protected]c244c5a12013-05-07 20:55:04321
322 // Headers are complete if the decompressor has moved on to the
323 // next stream.
[email protected]2532de12013-05-09 12:29:33324 headers_decompressed_ =
[email protected]c244c5a12013-05-07 20:55:04325 session_->decompressor()->current_header_id() != headers_id_;
[email protected]48878092013-07-26 14:51:56326 if (!headers_decompressed_) {
327 DCHECK_EQ(0u, data_len);
328 }
[email protected]c244c5a12013-05-07 20:55:04329
[email protected]2532de12013-05-09 12:29:33330 ProcessHeaderData();
[email protected]c244c5a12013-05-07 20:55:04331
[email protected]48878092013-07-26 14:51:56332 if (!headers_decompressed_ || !decompressed_headers_.empty()) {
333 return total_bytes_consumed;
334 }
335
[email protected]c244c5a12013-05-07 20:55:04336 // We have processed all of the decompressed data but we might
337 // have some more raw data to process.
[email protected]48878092013-07-26 14:51:56338 if (data_len > 0) {
339 total_bytes_consumed += ProcessData(data, data_len);
[email protected]c244c5a12013-05-07 20:55:04340 }
341
342 // The sequencer will push any additional buffered frames if this data
343 // has been completely consumed.
344 return total_bytes_consumed;
345}
346
347uint32 ReliableQuicStream::ProcessHeaderData() {
348 if (decompressed_headers_.empty()) {
349 return 0;
350 }
351
352 size_t bytes_processed = ProcessData(decompressed_headers_.data(),
353 decompressed_headers_.length());
354 if (bytes_processed == decompressed_headers_.length()) {
355 decompressed_headers_.clear();
356 } else {
357 decompressed_headers_ = decompressed_headers_.erase(0, bytes_processed);
358 }
359 return bytes_processed;
360}
361
362void ReliableQuicStream::OnDecompressorAvailable() {
363 DCHECK_EQ(headers_id_,
364 session_->decompressor()->current_header_id());
[email protected]2532de12013-05-09 12:29:33365 DCHECK(!headers_decompressed_);
[email protected]48878092013-07-26 14:51:56366 DCHECK(!decompression_failed_);
[email protected]c244c5a12013-05-07 20:55:04367 DCHECK_EQ(0u, decompressed_headers_.length());
368
[email protected]2532de12013-05-09 12:29:33369 while (!headers_decompressed_) {
[email protected]8fb9adb2013-07-28 14:04:37370 struct iovec iovec;
371 if (sequencer_.GetReadableRegions(&iovec, 1) == 0) {
[email protected]c244c5a12013-05-07 20:55:04372 return;
373 }
[email protected]c244c5a12013-05-07 20:55:04374
[email protected]8fb9adb2013-07-28 14:04:37375 size_t bytes_consumed = session_->decompressor()->DecompressData(
376 StringPiece(static_cast<char*>(iovec.iov_base),
377 iovec.iov_len),
378 this);
379 DCHECK_LE(bytes_consumed, iovec.iov_len);
380 if (decompression_failed_) {
381 return;
[email protected]c244c5a12013-05-07 20:55:04382 }
[email protected]8fb9adb2013-07-28 14:04:37383 sequencer_.MarkConsumed(bytes_consumed);
384
385 headers_decompressed_ =
386 session_->decompressor()->current_header_id() != headers_id_;
[email protected]c244c5a12013-05-07 20:55:04387 }
388
389 // Either the headers are complete, or the all data as been consumed.
[email protected]c244c5a12013-05-07 20:55:04390 ProcessHeaderData(); // Unprocessed headers remain in decompressed_headers_.
[email protected]4e49b6a2013-06-18 16:39:28391 if (IsHalfClosed()) {
392 TerminateFromPeer(true);
393 } else if (headers_decompressed_ && decompressed_headers_.empty()) {
[email protected]c244c5a12013-05-07 20:55:04394 sequencer_.FlushBufferedFrames();
395 }
396}
397
398bool ReliableQuicStream::OnDecompressedData(StringPiece data) {
399 data.AppendToString(&decompressed_headers_);
400 return true;
401}
402
[email protected]899951652013-05-16 12:52:39403void ReliableQuicStream::OnDecompressionError() {
[email protected]48878092013-07-26 14:51:56404 DCHECK(!decompression_failed_);
405 decompression_failed_ = true;
[email protected]899951652013-05-16 12:52:39406 session_->connection()->SendConnectionClose(QUIC_DECOMPRESSION_FAILURE);
407}
408
409
[email protected]9c0b1352012-11-04 00:03:27410void ReliableQuicStream::CloseWriteSide() {
[email protected]044ac2b2012-11-13 21:41:06411 if (write_side_closed_) {
412 return;
413 }
[email protected]9c0b1352012-11-04 00:03:27414 DLOG(INFO) << "Done writing to stream " << id();
415
416 write_side_closed_ = true;
417 if (read_side_closed_) {
[email protected]f702d572012-12-04 15:56:20418 DLOG(INFO) << "Closing stream: " << id();
[email protected]9c0b1352012-11-04 00:03:27419 session_->CloseStream(id());
420 }
421}
422
[email protected]63534512012-12-23 18:49:00423void ReliableQuicStream::OnClose() {
[email protected]a57e0272013-04-26 07:31:47424 CloseReadSide();
425 CloseWriteSide();
426
[email protected]63534512012-12-23 18:49:00427 if (visitor_) {
428 Visitor* visitor = visitor_;
429 // Calling Visitor::OnClose() may result the destruction of the visitor,
430 // so we need to ensure we don't call it again.
431 visitor_ = NULL;
432 visitor->OnClose(this);
433 }
434}
435
[email protected]9c0b1352012-11-04 00:03:27436} // namespace net