blob: bc099e2fe4aa1107add929cb978e0f156f0f41cd [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
[email protected]497bfb22014-01-08 01:28:037#include "base/logging.h"
[email protected]9c0b1352012-11-04 00:03:278#include "net/quic/quic_session.h"
[email protected]9f0dcd4e2014-01-16 15:58:149#include "net/quic/quic_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]457d6952013-12-13 09:24:5816#define ENDPOINT (is_server_ ? "Server: " : " Client: ")
17
[email protected]8edeb8d2013-08-28 06:11:4318namespace {
19
[email protected]457d6952013-12-13 09:24:5820struct iovec MakeIovec(StringPiece data) {
21 struct iovec iov = {const_cast<char*>(data.data()),
22 static_cast<size_t>(data.size())};
23 return iov;
[email protected]8edeb8d2013-08-28 06:11:4324}
25
26} // namespace
27
[email protected]9c0b1352012-11-04 00:03:2728ReliableQuicStream::ReliableQuicStream(QuicStreamId id,
29 QuicSession* session)
30 : sequencer_(this),
31 id_(id),
[email protected]9c0b1352012-11-04 00:03:2732 session_(session),
[email protected]63534512012-12-23 18:49:0033 stream_bytes_read_(0),
34 stream_bytes_written_(0),
[email protected]74bda142013-03-31 02:49:1135 stream_error_(QUIC_STREAM_NO_ERROR),
36 connection_error_(QUIC_NO_ERROR),
[email protected]9c0b1352012-11-04 00:03:2737 read_side_closed_(false),
[email protected]a5d4eee22012-12-13 09:09:0138 write_side_closed_(false),
39 fin_buffered_(false),
[email protected]b007e632013-10-28 08:39:2540 fin_sent_(false),
[email protected]459a7402014-02-10 12:58:5241 rst_sent_(false),
[email protected]b007e632013-10-28 08:39:2542 is_server_(session_->is_server()) {
[email protected]9c0b1352012-11-04 00:03:2743}
44
45ReliableQuicStream::~ReliableQuicStream() {
46}
47
48bool ReliableQuicStream::WillAcceptStreamFrame(
49 const QuicStreamFrame& frame) const {
50 if (read_side_closed_) {
[email protected]044ac2b2012-11-13 21:41:0651 return true;
[email protected]9c0b1352012-11-04 00:03:2752 }
53 if (frame.stream_id != id_) {
54 LOG(ERROR) << "Error!";
55 return false;
56 }
57 return sequencer_.WillAcceptStreamFrame(frame);
58}
59
60bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
61 DCHECK_EQ(frame.stream_id, id_);
62 if (read_side_closed_) {
[email protected]3e5fed12013-11-22 22:21:4163 DVLOG(1) << ENDPOINT << "Ignoring frame " << frame.stream_id;
[email protected]044ac2b2012-11-13 21:41:0664 // We don't want to be reading: blackhole the data.
65 return true;
[email protected]9c0b1352012-11-04 00:03:2766 }
[email protected]9db443912013-02-25 05:27:0367 // Note: This count include duplicate data received.
[email protected]5dafdb62013-11-14 01:24:2668 stream_bytes_read_ += frame.data.TotalBufferSize();
[email protected]9c0b1352012-11-04 00:03:2769
70 bool accepted = sequencer_.OnStreamFrame(frame);
71
[email protected]9c0b1352012-11-04 00:03:2772 return accepted;
73}
74
[email protected]bdf2d432014-02-09 10:45:4175void ReliableQuicStream::OnStreamReset(const QuicRstStreamFrame& frame) {
76 stream_error_ = frame.error_code;
[email protected]2adef90e2013-12-02 20:26:5777 CloseWriteSide();
78 CloseReadSide();
[email protected]9c0b1352012-11-04 00:03:2779}
80
[email protected]2cfc6bb82013-10-27 03:40:4481void ReliableQuicStream::OnConnectionClosed(QuicErrorCode error,
82 bool from_peer) {
[email protected]4e49b6a2013-06-18 16:39:2883 if (read_side_closed_ && write_side_closed_) {
[email protected]a57e0272013-04-26 07:31:4784 return;
85 }
[email protected]74bda142013-03-31 02:49:1186 if (error != QUIC_NO_ERROR) {
87 stream_error_ = QUIC_STREAM_CONNECTION_ERROR;
88 connection_error_ = error;
89 }
90
[email protected]2adef90e2013-12-02 20:26:5791 CloseWriteSide();
[email protected]9c0b1352012-11-04 00:03:2792 CloseReadSide();
93}
94
[email protected]2adef90e2013-12-02 20:26:5795void ReliableQuicStream::OnFinRead() {
96 DCHECK(sequencer_.IsClosed());
97 CloseReadSide();
98}
99
100void ReliableQuicStream::Reset(QuicRstStreamErrorCode error) {
101 DCHECK_NE(QUIC_STREAM_NO_ERROR, error);
[email protected]74bda142013-03-31 02:49:11102 stream_error_ = error;
[email protected]2adef90e2013-12-02 20:26:57103 // Sending a RstStream results in calling CloseStream.
[email protected]6ae6e342014-02-06 02:21:42104 session()->SendRstStream(id(), error, stream_bytes_written_);
[email protected]459a7402014-02-10 12:58:52105 rst_sent_ = true;
[email protected]9c0b1352012-11-04 00:03:27106}
107
[email protected]2cfc6bb82013-10-27 03:40:44108void ReliableQuicStream::CloseConnection(QuicErrorCode error) {
109 session()->connection()->SendConnectionClose(error);
110}
111
112void ReliableQuicStream::CloseConnectionWithDetails(QuicErrorCode error,
113 const string& details) {
114 session()->connection()->SendConnectionCloseWithDetails(error, details);
115}
116
[email protected]cb23a922014-02-20 17:42:38117QuicVersion ReliableQuicStream::version() const {
[email protected]c05a6d222013-12-16 19:42:03118 return session()->connection()->version();
119}
120
[email protected]457d6952013-12-13 09:24:58121void ReliableQuicStream::WriteOrBufferData(StringPiece data, bool fin) {
[email protected]b55bf4f2014-01-24 21:30:26122 if (data.empty() && !fin) {
123 LOG(DFATAL) << "data.empty() && !fin";
124 return;
125 }
126
127 if (fin_buffered_) {
128 LOG(DFATAL) << "Fin already buffered";
129 return;
130 }
[email protected]a5d4eee22012-12-13 09:09:01131
[email protected]cff7b7b52013-01-11 08:49:07132 QuicConsumedData consumed_data(0, false);
[email protected]a5d4eee22012-12-13 09:09:01133 fin_buffered_ = fin;
134
135 if (queued_data_.empty()) {
[email protected]457d6952013-12-13 09:24:58136 struct iovec iov(MakeIovec(data));
137 consumed_data = WritevData(&iov, 1, fin, NULL);
[email protected]c995c572013-01-18 05:43:20138 DCHECK_LE(consumed_data.bytes_consumed, data.length());
[email protected]a5d4eee22012-12-13 09:09:01139 }
[email protected]cff7b7b52013-01-11 08:49:07140
[email protected]c995c572013-01-18 05:43:20141 // If there's unconsumed data or an unconsumed fin, queue it.
142 if (consumed_data.bytes_consumed < data.length() ||
[email protected]cff7b7b52013-01-11 08:49:07143 (fin && !consumed_data.fin_consumed)) {
144 queued_data_.push_back(
145 string(data.data() + consumed_data.bytes_consumed,
146 data.length() - consumed_data.bytes_consumed));
[email protected]a5d4eee22012-12-13 09:09:01147 }
[email protected]a5d4eee22012-12-13 09:09:01148}
149
150void ReliableQuicStream::OnCanWrite() {
151 bool fin = false;
[email protected]610a7e942012-12-18 00:21:39152 while (!queued_data_.empty()) {
[email protected]a5d4eee22012-12-13 09:09:01153 const string& data = queued_data_.front();
154 if (queued_data_.size() == 1 && fin_buffered_) {
155 fin = true;
156 }
[email protected]457d6952013-12-13 09:24:58157 struct iovec iov(MakeIovec(data));
158 QuicConsumedData consumed_data = WritevData(&iov, 1, fin, NULL);
[email protected]cff7b7b52013-01-11 08:49:07159 if (consumed_data.bytes_consumed == data.size() &&
160 fin == consumed_data.fin_consumed) {
[email protected]a5d4eee22012-12-13 09:09:01161 queued_data_.pop_front();
162 } else {
[email protected]cff7b7b52013-01-11 08:49:07163 queued_data_.front().erase(0, consumed_data.bytes_consumed);
[email protected]610a7e942012-12-18 00:21:39164 break;
[email protected]a5d4eee22012-12-13 09:09:01165 }
166 }
167}
168
[email protected]457d6952013-12-13 09:24:58169QuicConsumedData ReliableQuicStream::WritevData(
[email protected]0ac0c5b2013-11-20 05:55:58170 const struct iovec* iov,
171 int iov_count,
172 bool fin,
173 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
[email protected]9c0b1352012-11-04 00:03:27174 if (write_side_closed_) {
[email protected]b007e632013-10-28 08:39:25175 DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed";
[email protected]cff7b7b52013-01-11 08:49:07176 return QuicConsumedData(0, false);
[email protected]9c0b1352012-11-04 00:03:27177 }
178
[email protected]24e5bc52013-09-18 15:36:58179 size_t write_length = 0u;
[email protected]4d1789c32013-09-18 23:54:36180 for (int i = 0; i < iov_count; ++i) {
[email protected]24e5bc52013-09-18 15:36:58181 write_length += iov[i].iov_len;
[email protected]cb23a922014-02-20 17:42:38182 // TODO(rjshade): Maybe block write based on available flow control window.
[email protected]24e5bc52013-09-18 15:36:58183 }
[email protected]93dd91f2014-02-27 00:09:03184
185 // Fill an IOVector with bytes from the iovec.
186 IOVector data;
187 data.AppendIovecAtMostBytes(iov, iov_count, write_length);
188
[email protected]0ac0c5b2013-11-20 05:55:58189 QuicConsumedData consumed_data = session()->WritevData(
[email protected]93dd91f2014-02-27 00:09:03190 id(), data, stream_bytes_written_, fin, ack_notifier_delegate);
[email protected]cff7b7b52013-01-11 08:49:07191 stream_bytes_written_ += consumed_data.bytes_consumed;
[email protected]24e5bc52013-09-18 15:36:58192 if (consumed_data.bytes_consumed == write_length) {
[email protected]cff7b7b52013-01-11 08:49:07193 if (fin && consumed_data.fin_consumed) {
[email protected]a5d4eee22012-12-13 09:09:01194 fin_sent_ = true;
195 CloseWriteSide();
[email protected]25c31dc2013-06-05 17:56:04196 } else if (fin && !consumed_data.fin_consumed) {
[email protected]24e5bc52013-09-18 15:36:58197 session_->MarkWriteBlocked(id(), EffectivePriority());
[email protected]a5d4eee22012-12-13 09:09:01198 }
199 } else {
[email protected]24e5bc52013-09-18 15:36:58200 session_->MarkWriteBlocked(id(), EffectivePriority());
[email protected]9c0b1352012-11-04 00:03:27201 }
[email protected]cff7b7b52013-01-11 08:49:07202 return consumed_data;
[email protected]9c0b1352012-11-04 00:03:27203}
204
205void ReliableQuicStream::CloseReadSide() {
[email protected]044ac2b2012-11-13 21:41:06206 if (read_side_closed_) {
207 return;
208 }
[email protected]3e5fed12013-11-22 22:21:41209 DVLOG(1) << ENDPOINT << "Done reading from stream " << id();
[email protected]9c0b1352012-11-04 00:03:27210
211 read_side_closed_ = true;
212 if (write_side_closed_) {
[email protected]3e5fed12013-11-22 22:21:41213 DVLOG(1) << ENDPOINT << "Closing stream: " << id();
[email protected]9c0b1352012-11-04 00:03:27214 session_->CloseStream(id());
215 }
216}
217
218void ReliableQuicStream::CloseWriteSide() {
[email protected]044ac2b2012-11-13 21:41:06219 if (write_side_closed_) {
220 return;
221 }
[email protected]3e5fed12013-11-22 22:21:41222 DVLOG(1) << ENDPOINT << "Done writing to stream " << id();
[email protected]9c0b1352012-11-04 00:03:27223
224 write_side_closed_ = true;
225 if (read_side_closed_) {
[email protected]3e5fed12013-11-22 22:21:41226 DVLOG(1) << ENDPOINT << "Closing stream: " << id();
[email protected]9c0b1352012-11-04 00:03:27227 session_->CloseStream(id());
228 }
229}
230
[email protected]6adeb922013-09-01 22:43:25231bool ReliableQuicStream::HasBufferedData() {
232 return !queued_data_.empty();
233}
234
[email protected]63534512012-12-23 18:49:00235void ReliableQuicStream::OnClose() {
[email protected]a57e0272013-04-26 07:31:47236 CloseReadSide();
237 CloseWriteSide();
[email protected]459a7402014-02-10 12:58:52238
239 if (version() > QUIC_VERSION_13 &&
240 !fin_sent_ && !rst_sent_) {
241 // For flow control accounting, we must tell the peer how many bytes we have
242 // written on this stream before termination. Done here if needed, using a
243 // RST frame.
244 DVLOG(1) << ENDPOINT << "Sending RST in OnClose: " << id();
245 session_->SendRstStream(id(), QUIC_STREAM_NO_ERROR, stream_bytes_written_);
246 rst_sent_ = true;
247 }
[email protected]8edeb8d2013-08-28 06:11:43248}
249
[email protected]9c0b1352012-11-04 00:03:27250} // namespace net