blob: 5d9c3cce49c92e7b0952e4faa6a7bc196168de86 [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]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),
[email protected]a5d4eee22012-12-13 09:09:0139 fin_buffered_(false),
[email protected]b007e632013-10-28 08:39:2540 fin_sent_(false),
41 is_server_(session_->is_server()) {
[email protected]9c0b1352012-11-04 00:03:2742}
43
44ReliableQuicStream::~ReliableQuicStream() {
45}
46
47bool ReliableQuicStream::WillAcceptStreamFrame(
48 const QuicStreamFrame& frame) const {
49 if (read_side_closed_) {
[email protected]044ac2b2012-11-13 21:41:0650 return true;
[email protected]9c0b1352012-11-04 00:03:2751 }
52 if (frame.stream_id != id_) {
53 LOG(ERROR) << "Error!";
54 return false;
55 }
56 return sequencer_.WillAcceptStreamFrame(frame);
57}
58
59bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
60 DCHECK_EQ(frame.stream_id, id_);
61 if (read_side_closed_) {
[email protected]3e5fed12013-11-22 22:21:4162 DVLOG(1) << ENDPOINT << "Ignoring frame " << frame.stream_id;
[email protected]044ac2b2012-11-13 21:41:0663 // We don't want to be reading: blackhole the data.
64 return true;
[email protected]9c0b1352012-11-04 00:03:2765 }
[email protected]9db443912013-02-25 05:27:0366 // Note: This count include duplicate data received.
[email protected]5dafdb62013-11-14 01:24:2667 stream_bytes_read_ += frame.data.TotalBufferSize();
[email protected]9c0b1352012-11-04 00:03:2768
69 bool accepted = sequencer_.OnStreamFrame(frame);
70
[email protected]9c0b1352012-11-04 00:03:2771 return accepted;
72}
73
[email protected]74bda142013-03-31 02:49:1174void ReliableQuicStream::OnStreamReset(QuicRstStreamErrorCode error) {
75 stream_error_ = error;
[email protected]2adef90e2013-12-02 20:26:5776 CloseWriteSide();
77 CloseReadSide();
[email protected]9c0b1352012-11-04 00:03:2778}
79
[email protected]2cfc6bb82013-10-27 03:40:4480void ReliableQuicStream::OnConnectionClosed(QuicErrorCode error,
81 bool from_peer) {
[email protected]4e49b6a2013-06-18 16:39:2882 if (read_side_closed_ && write_side_closed_) {
[email protected]a57e0272013-04-26 07:31:4783 return;
84 }
[email protected]74bda142013-03-31 02:49:1185 if (error != QUIC_NO_ERROR) {
86 stream_error_ = QUIC_STREAM_CONNECTION_ERROR;
87 connection_error_ = error;
88 }
89
[email protected]2adef90e2013-12-02 20:26:5790 CloseWriteSide();
[email protected]9c0b1352012-11-04 00:03:2791 CloseReadSide();
92}
93
[email protected]2adef90e2013-12-02 20:26:5794void ReliableQuicStream::OnFinRead() {
95 DCHECK(sequencer_.IsClosed());
96 CloseReadSide();
97}
98
99void ReliableQuicStream::Reset(QuicRstStreamErrorCode error) {
100 DCHECK_NE(QUIC_STREAM_NO_ERROR, error);
[email protected]74bda142013-03-31 02:49:11101 stream_error_ = error;
[email protected]2adef90e2013-12-02 20:26:57102 // Sending a RstStream results in calling CloseStream.
103 session()->SendRstStream(id(), error);
[email protected]9c0b1352012-11-04 00:03:27104}
105
[email protected]2cfc6bb82013-10-27 03:40:44106void ReliableQuicStream::CloseConnection(QuicErrorCode error) {
107 session()->connection()->SendConnectionClose(error);
108}
109
110void ReliableQuicStream::CloseConnectionWithDetails(QuicErrorCode error,
111 const string& details) {
112 session()->connection()->SendConnectionCloseWithDetails(error, details);
113}
114
[email protected]c05a6d222013-12-16 19:42:03115QuicVersion ReliableQuicStream::version() {
116 return session()->connection()->version();
117}
118
[email protected]457d6952013-12-13 09:24:58119void ReliableQuicStream::WriteOrBufferData(StringPiece data, bool fin) {
[email protected]25c31dc2013-06-05 17:56:04120 DCHECK(data.size() > 0 || fin);
[email protected]a5d4eee22012-12-13 09:09:01121 DCHECK(!fin_buffered_);
122
[email protected]cff7b7b52013-01-11 08:49:07123 QuicConsumedData consumed_data(0, false);
[email protected]a5d4eee22012-12-13 09:09:01124 fin_buffered_ = fin;
125
126 if (queued_data_.empty()) {
[email protected]457d6952013-12-13 09:24:58127 struct iovec iov(MakeIovec(data));
128 consumed_data = WritevData(&iov, 1, fin, NULL);
[email protected]c995c572013-01-18 05:43:20129 DCHECK_LE(consumed_data.bytes_consumed, data.length());
[email protected]a5d4eee22012-12-13 09:09:01130 }
[email protected]cff7b7b52013-01-11 08:49:07131
[email protected]c995c572013-01-18 05:43:20132 // If there's unconsumed data or an unconsumed fin, queue it.
133 if (consumed_data.bytes_consumed < data.length() ||
[email protected]cff7b7b52013-01-11 08:49:07134 (fin && !consumed_data.fin_consumed)) {
135 queued_data_.push_back(
136 string(data.data() + consumed_data.bytes_consumed,
137 data.length() - consumed_data.bytes_consumed));
[email protected]a5d4eee22012-12-13 09:09:01138 }
[email protected]a5d4eee22012-12-13 09:09:01139}
140
141void ReliableQuicStream::OnCanWrite() {
142 bool fin = false;
[email protected]610a7e942012-12-18 00:21:39143 while (!queued_data_.empty()) {
[email protected]a5d4eee22012-12-13 09:09:01144 const string& data = queued_data_.front();
145 if (queued_data_.size() == 1 && fin_buffered_) {
146 fin = true;
147 }
[email protected]457d6952013-12-13 09:24:58148 struct iovec iov(MakeIovec(data));
149 QuicConsumedData consumed_data = WritevData(&iov, 1, fin, NULL);
[email protected]cff7b7b52013-01-11 08:49:07150 if (consumed_data.bytes_consumed == data.size() &&
151 fin == consumed_data.fin_consumed) {
[email protected]a5d4eee22012-12-13 09:09:01152 queued_data_.pop_front();
153 } else {
[email protected]cff7b7b52013-01-11 08:49:07154 queued_data_.front().erase(0, consumed_data.bytes_consumed);
[email protected]610a7e942012-12-18 00:21:39155 break;
[email protected]a5d4eee22012-12-13 09:09:01156 }
157 }
158}
159
[email protected]457d6952013-12-13 09:24:58160QuicConsumedData ReliableQuicStream::WritevData(
[email protected]0ac0c5b2013-11-20 05:55:58161 const struct iovec* iov,
162 int iov_count,
163 bool fin,
164 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
[email protected]9c0b1352012-11-04 00:03:27165 if (write_side_closed_) {
[email protected]b007e632013-10-28 08:39:25166 DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed";
[email protected]cff7b7b52013-01-11 08:49:07167 return QuicConsumedData(0, false);
[email protected]9c0b1352012-11-04 00:03:27168 }
169
[email protected]24e5bc52013-09-18 15:36:58170 size_t write_length = 0u;
[email protected]4d1789c32013-09-18 23:54:36171 for (int i = 0; i < iov_count; ++i) {
[email protected]24e5bc52013-09-18 15:36:58172 write_length += iov[i].iov_len;
173 }
[email protected]0ac0c5b2013-11-20 05:55:58174 QuicConsumedData consumed_data = session()->WritevData(
175 id(), iov, iov_count, stream_bytes_written_, fin, ack_notifier_delegate);
[email protected]cff7b7b52013-01-11 08:49:07176 stream_bytes_written_ += consumed_data.bytes_consumed;
[email protected]24e5bc52013-09-18 15:36:58177 if (consumed_data.bytes_consumed == write_length) {
[email protected]cff7b7b52013-01-11 08:49:07178 if (fin && consumed_data.fin_consumed) {
[email protected]a5d4eee22012-12-13 09:09:01179 fin_sent_ = true;
180 CloseWriteSide();
[email protected]25c31dc2013-06-05 17:56:04181 } else if (fin && !consumed_data.fin_consumed) {
[email protected]24e5bc52013-09-18 15:36:58182 session_->MarkWriteBlocked(id(), EffectivePriority());
[email protected]a5d4eee22012-12-13 09:09:01183 }
184 } else {
[email protected]24e5bc52013-09-18 15:36:58185 session_->MarkWriteBlocked(id(), EffectivePriority());
[email protected]9c0b1352012-11-04 00:03:27186 }
[email protected]cff7b7b52013-01-11 08:49:07187 return consumed_data;
[email protected]9c0b1352012-11-04 00:03:27188}
189
[email protected]9c0b1352012-11-04 00:03:27190void ReliableQuicStream::CloseReadSide() {
[email protected]044ac2b2012-11-13 21:41:06191 if (read_side_closed_) {
192 return;
193 }
[email protected]3e5fed12013-11-22 22:21:41194 DVLOG(1) << ENDPOINT << "Done reading from stream " << id();
[email protected]9c0b1352012-11-04 00:03:27195
196 read_side_closed_ = true;
197 if (write_side_closed_) {
[email protected]3e5fed12013-11-22 22:21:41198 DVLOG(1) << ENDPOINT << "Closing stream: " << id();
[email protected]9c0b1352012-11-04 00:03:27199 session_->CloseStream(id());
200 }
201}
202
[email protected]9c0b1352012-11-04 00:03:27203void ReliableQuicStream::CloseWriteSide() {
[email protected]044ac2b2012-11-13 21:41:06204 if (write_side_closed_) {
205 return;
206 }
[email protected]3e5fed12013-11-22 22:21:41207 DVLOG(1) << ENDPOINT << "Done writing to stream " << id();
[email protected]9c0b1352012-11-04 00:03:27208
209 write_side_closed_ = true;
210 if (read_side_closed_) {
[email protected]3e5fed12013-11-22 22:21:41211 DVLOG(1) << ENDPOINT << "Closing stream: " << id();
[email protected]9c0b1352012-11-04 00:03:27212 session_->CloseStream(id());
213 }
214}
215
[email protected]6adeb922013-09-01 22:43:25216bool ReliableQuicStream::HasBufferedData() {
217 return !queued_data_.empty();
218}
219
[email protected]63534512012-12-23 18:49:00220void ReliableQuicStream::OnClose() {
[email protected]a57e0272013-04-26 07:31:47221 CloseReadSide();
222 CloseWriteSide();
[email protected]8edeb8d2013-08-28 06:11:43223}
224
[email protected]9c0b1352012-11-04 00:03:27225} // namespace net