reliable_quic_stream.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
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)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_session.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_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)
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define ENDPOINT (is_server_ ? "Server: " : " Client: ")
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace {
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct iovec MakeIovec(StringPiece data) {
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  struct iovec iov = {const_cast<char*>(data.data()),
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      static_cast<size_t>(data.size())};
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return iov;
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Wrapper that aggregates OnAckNotifications for packets sent using
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// WriteOrBufferData and delivers them to the original
3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// QuicAckNotifier::DelegateInterface after all bytes written using
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// WriteOrBufferData are acked.  This level of indirection is
3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// necessary because the delegate interface provides no mechanism that
3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// WriteOrBufferData can use to inform it that the write required
3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// multiple WritevData calls or that only part of the data has been
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// sent out by the time ACKs start arriving.
3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)class ReliableQuicStream::ProxyAckNotifierDelegate
3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : public QuicAckNotifier::DelegateInterface {
3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public:
3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  explicit ProxyAckNotifierDelegate(DelegateInterface* delegate)
4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      : delegate_(delegate),
4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        pending_acks_(0),
4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        wrote_last_data_(false),
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        num_original_packets_(0),
4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        num_original_bytes_(0),
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        num_retransmitted_packets_(0),
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        num_retransmitted_bytes_(0) {
4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual void OnAckNotification(int num_original_packets,
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                 int num_original_bytes,
5123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                 int num_retransmitted_packets,
5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                 int num_retransmitted_bytes) OVERRIDE {
5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DCHECK_LT(0, pending_acks_);
5423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    --pending_acks_;
5523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    num_original_packets_ += num_original_packets;
5623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    num_original_bytes_ += num_original_bytes;
5723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    num_retransmitted_packets_ += num_retransmitted_packets;
5823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    num_retransmitted_bytes_ += num_retransmitted_bytes;
5923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (wrote_last_data_ && pending_acks_ == 0) {
6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      delegate_->OnAckNotification(num_original_packets_,
6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                   num_original_bytes_,
6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                   num_retransmitted_packets_,
6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                   num_retransmitted_bytes_);
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  void WroteData(bool last_data) {
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    DCHECK(!wrote_last_data_);
7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ++pending_acks_;
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    wrote_last_data_ = last_data;
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) protected:
7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Delegates are ref counted.
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual ~ProxyAckNotifierDelegate() {
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private:
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Original delegate.  delegate_->OnAckNotification will be called when:
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  //   wrote_last_data_ == true and pending_acks_ == 0
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_refptr<DelegateInterface> delegate_;
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Number of outstanding acks.
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int pending_acks_;
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // True if no pending writes remain.
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool wrote_last_data_;
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Accumulators.
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int num_original_packets_;
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int num_original_bytes_;
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int num_retransmitted_packets_;
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int num_retransmitted_bytes_;
9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ProxyAckNotifierDelegate);
9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)};
9823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ReliableQuicStream::PendingData::PendingData(
10023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    string data_in, scoped_refptr<ProxyAckNotifierDelegate> delegate_in)
10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : data(data_in), delegate(delegate_in) {
10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
10323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ReliableQuicStream::PendingData::~PendingData() {
10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream::ReliableQuicStream(QuicStreamId id,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       QuicSession* session)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : sequencer_(this),
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      id_(id),
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_(session),
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream_bytes_read_(0),
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream_bytes_written_(0),
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      stream_error_(QUIC_STREAM_NO_ERROR),
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      connection_error_(QUIC_NO_ERROR),
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_side_closed_(false),
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      write_side_closed_(false),
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin_buffered_(false),
1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      fin_sent_(false),
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      rst_sent_(false),
1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      is_server_(session_->is_server()) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReliableQuicStream::~ReliableQuicStream() {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::WillAcceptStreamFrame(
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const QuicStreamFrame& frame) const {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_side_closed_) {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame.stream_id != id_) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Error!";
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sequencer_.WillAcceptStreamFrame(frame);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(frame.stream_id, id_);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_side_closed_) {
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << ENDPOINT << "Ignoring frame " << frame.stream_id;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We don't want to be reading: blackhole the data.
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note: This count include duplicate data received.
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  stream_bytes_read_ += frame.data.TotalBufferSize();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool accepted = sequencer_.OnStreamFrame(frame);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return accepted;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ReliableQuicStream::OnStreamReset(const QuicRstStreamFrame& frame) {
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  stream_error_ = frame.error_code;
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CloseWriteSide();
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CloseReadSide();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ReliableQuicStream::OnConnectionClosed(QuicErrorCode error,
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                            bool from_peer) {
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (read_side_closed_ && write_side_closed_) {
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != QUIC_NO_ERROR) {
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stream_error_ = QUIC_STREAM_CONNECTION_ERROR;
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    connection_error_ = error;
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CloseWriteSide();
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CloseReadSide();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ReliableQuicStream::OnFinRead() {
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(sequencer_.IsClosed());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseReadSide();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ReliableQuicStream::Reset(QuicRstStreamErrorCode error) {
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK_NE(QUIC_STREAM_NO_ERROR, error);
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stream_error_ = error;
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Sending a RstStream results in calling CloseStream.
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  session()->SendRstStream(id(), error, stream_bytes_written_);
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  rst_sent_ = true;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ReliableQuicStream::CloseConnection(QuicErrorCode error) {
1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  session()->connection()->SendConnectionClose(error);
1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ReliableQuicStream::CloseConnectionWithDetails(QuicErrorCode error,
1921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                                    const string& details) {
1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  session()->connection()->SendConnectionCloseWithDetails(error, details);
1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicVersion ReliableQuicStream::version() const {
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return session()->connection()->version();
198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
20023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ReliableQuicStream::WriteOrBufferData(
20123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    StringPiece data,
20223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bool fin,
20323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (data.empty() && !fin) {
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(DFATAL) << "data.empty() && !fin";
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
207b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (fin_buffered_) {
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(DFATAL) << "Fin already buffered";
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
212b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_refptr<ProxyAckNotifierDelegate> proxy_delegate;
21523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (ack_notifier_delegate != NULL) {
21623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    proxy_delegate = new ProxyAckNotifierDelegate(ack_notifier_delegate);
21723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
21823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicConsumedData consumed_data(0, false);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fin_buffered_ = fin;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (queued_data_.empty()) {
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    struct iovec iov(MakeIovec(data));
22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    consumed_data = WritevData(&iov, 1, fin, proxy_delegate.get());
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_LE(consumed_data.bytes_consumed, data.length());
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool write_completed;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there's unconsumed data or an unconsumed fin, queue it.
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (consumed_data.bytes_consumed < data.length() ||
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (fin && !consumed_data.fin_consumed)) {
23223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    StringPiece remainder(data.substr(consumed_data.bytes_consumed));
23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    queued_data_.push_back(PendingData(remainder.as_string(), proxy_delegate));
23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    write_completed = false;
23523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
23623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    write_completed = true;
23723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
23823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
23923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if ((proxy_delegate.get() != NULL) &&
24023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      (consumed_data.bytes_consumed > 0 || consumed_data.fin_consumed)) {
24123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    proxy_delegate->WroteData(write_completed);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReliableQuicStream::OnCanWrite() {
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool fin = false;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!queued_data_.empty()) {
24823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    PendingData* pending_data = &queued_data_.front();
24923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ProxyAckNotifierDelegate* delegate = pending_data->delegate.get();
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (queued_data_.size() == 1 && fin_buffered_) {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin = true;
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
25323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    struct iovec iov(MakeIovec(pending_data->data));
25423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    QuicConsumedData consumed_data = WritevData(&iov, 1, fin, delegate);
25523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (consumed_data.bytes_consumed == pending_data->data.size() &&
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fin == consumed_data.fin_consumed) {
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      queued_data_.pop_front();
25823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (delegate != NULL) {
25923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        delegate->WroteData(true);
26023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      }
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
26223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (consumed_data.bytes_consumed > 0) {
26323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        pending_data->data.erase(0, consumed_data.bytes_consumed);
26423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        if (delegate != NULL) {
26523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          delegate->WroteData(false);
26623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        }
26723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      }
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicConsumedData ReliableQuicStream::WritevData(
274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const struct iovec* iov,
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int iov_count,
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool fin,
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (write_side_closed_) {
2791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed";
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return QuicConsumedData(0, false);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  size_t write_length = 0u;
284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (int i = 0; i < iov_count; ++i) {
285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    write_length += iov[i].iov_len;
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // TODO(rjshade): Maybe block write based on available flow control window.
287d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Fill an IOVector with bytes from the iovec.
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  IOVector data;
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  data.AppendIovecAtMostBytes(iov, iov_count, write_length);
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QuicConsumedData consumed_data = session()->WritevData(
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      id(), data, stream_bytes_written_, fin, ack_notifier_delegate);
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream_bytes_written_ += consumed_data.bytes_consumed;
296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (consumed_data.bytes_consumed == write_length) {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (fin && consumed_data.fin_consumed) {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fin_sent_ = true;
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CloseWriteSide();
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else if (fin && !consumed_data.fin_consumed) {
301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      session_->MarkWriteBlocked(id(), EffectivePriority());
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    session_->MarkWriteBlocked(id(), EffectivePriority());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return consumed_data;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::CloseReadSide() {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (read_side_closed_) {
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "Done reading from stream " << id();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_side_closed_ = true;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (write_side_closed_) {
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << ENDPOINT << "Closing stream: " << id();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_->CloseStream(id());
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReliableQuicStream::CloseWriteSide() {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (write_side_closed_) {
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << ENDPOINT << "Done writing to stream " << id();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_side_closed_ = true;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (read_side_closed_) {
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DVLOG(1) << ENDPOINT << "Closing stream: " << id();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_->CloseStream(id());
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool ReliableQuicStream::HasBufferedData() {
33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return !queued_data_.empty();
33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReliableQuicStream::OnClose() {
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CloseReadSide();
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CloseWriteSide();
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (version() > QUIC_VERSION_13 &&
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !fin_sent_ && !rst_sent_) {
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // For flow control accounting, we must tell the peer how many bytes we have
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // written on this stream before termination. Done here if needed, using a
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // RST frame.
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(1) << ENDPOINT << "Sending RST in OnClose: " << id();
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    session_->SendRstStream(id(), QUIC_STREAM_NO_ERROR, stream_bytes_written_);
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    rst_sent_ = true;
351424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
352424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
353424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
355