Project import generated by Copybara.

PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/quartc/quartc_stream.cc b/quic/quartc/quartc_stream.cc
new file mode 100644
index 0000000..49ade23
--- /dev/null
+++ b/quic/quartc/quartc_stream.cc
@@ -0,0 +1,171 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/quartc/quartc_stream.h"
+
+#include <memory>
+#include <utility>
+
+#include "net/third_party/quiche/src/quic/core/quic_ack_listener_interface.h"
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h"
+#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer.h"
+#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+
+namespace quic {
+
+QuartcStream::QuartcStream(QuicStreamId id, QuicSession* session)
+    : QuicStream(id, session, /*is_static=*/false, BIDIRECTIONAL) {
+  sequencer()->set_level_triggered(true);
+}
+
+QuartcStream::QuartcStream(PendingStream pending)
+    : QuicStream(std::move(pending), BIDIRECTIONAL) {
+  sequencer()->set_level_triggered(true);
+}
+
+QuartcStream::~QuartcStream() {}
+
+void QuartcStream::OnDataAvailable() {
+  bool fin = sequencer()->ReadableBytes() + sequencer()->NumBytesConsumed() ==
+             sequencer()->close_offset();
+
+  // Upper bound on number of readable regions.  Each complete block's worth of
+  // data crosses at most one region boundary.  The remainder may cross one more
+  // boundary.  Number of regions is one more than the number of region
+  // boundaries crossed.
+  size_t iov_length = sequencer()->ReadableBytes() /
+                          QuicStreamSequencerBuffer::kBlockSizeBytes +
+                      2;
+  std::unique_ptr<iovec[]> iovecs = QuicMakeUnique<iovec[]>(iov_length);
+  iov_length = sequencer()->GetReadableRegions(iovecs.get(), iov_length);
+
+  sequencer()->MarkConsumed(
+      delegate_->OnReceived(this, iovecs.get(), iov_length, fin));
+  if (sequencer()->IsClosed()) {
+    OnFinRead();
+  }
+}
+
+void QuartcStream::OnClose() {
+  QuicStream::OnClose();
+  DCHECK(delegate_);
+  delegate_->OnClose(this);
+}
+
+void QuartcStream::OnStreamDataConsumed(size_t bytes_consumed) {
+  QuicStream::OnStreamDataConsumed(bytes_consumed);
+
+  DCHECK(delegate_);
+  delegate_->OnBufferChanged(this);
+}
+
+void QuartcStream::OnDataBuffered(
+    QuicStreamOffset offset,
+    QuicByteCount data_length,
+    const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener) {
+  DCHECK(delegate_);
+  delegate_->OnBufferChanged(this);
+}
+
+bool QuartcStream::OnStreamFrameAcked(QuicStreamOffset offset,
+                                      QuicByteCount data_length,
+                                      bool fin_acked,
+                                      QuicTime::Delta ack_delay_time,
+                                      QuicByteCount* newly_acked_length) {
+  // Previous losses of acked data are no longer relevant to the retransmission
+  // count.  Once data is acked, it will never be retransmitted.
+  lost_frame_counter_.RemoveInterval(
+      QuicInterval<QuicStreamOffset>(offset, offset + data_length));
+
+  return QuicStream::OnStreamFrameAcked(offset, data_length, fin_acked,
+                                        ack_delay_time, newly_acked_length);
+}
+
+void QuartcStream::OnStreamFrameRetransmitted(QuicStreamOffset offset,
+                                              QuicByteCount data_length,
+                                              bool fin_retransmitted) {
+  QuicStream::OnStreamFrameRetransmitted(offset, data_length,
+                                         fin_retransmitted);
+
+  DCHECK(delegate_);
+  delegate_->OnBufferChanged(this);
+}
+
+void QuartcStream::OnStreamFrameLost(QuicStreamOffset offset,
+                                     QuicByteCount data_length,
+                                     bool fin_lost) {
+  QuicStream::OnStreamFrameLost(offset, data_length, fin_lost);
+
+  lost_frame_counter_.AddInterval(
+      QuicInterval<QuicStreamOffset>(offset, offset + data_length));
+
+  DCHECK(delegate_);
+  delegate_->OnBufferChanged(this);
+}
+
+void QuartcStream::OnCanWrite() {
+  if (lost_frame_counter_.MaxCount() >
+          static_cast<size_t>(max_retransmission_count_) &&
+      HasPendingRetransmission()) {
+    Reset(QUIC_STREAM_CANCELLED);
+    return;
+  }
+  QuicStream::OnCanWrite();
+}
+
+bool QuartcStream::cancel_on_loss() {
+  return max_retransmission_count_ == 0;
+}
+
+void QuartcStream::set_cancel_on_loss(bool cancel_on_loss) {
+  if (cancel_on_loss) {
+    max_retransmission_count_ = 0;
+  } else {
+    max_retransmission_count_ = std::numeric_limits<int>::max();
+  }
+}
+
+int QuartcStream::max_retransmission_count() const {
+  return max_retransmission_count_;
+}
+
+void QuartcStream::set_max_retransmission_count(int max_retransmission_count) {
+  max_retransmission_count_ = max_retransmission_count;
+}
+
+QuicByteCount QuartcStream::BytesPendingRetransmission() {
+  if (lost_frame_counter_.MaxCount() >
+      static_cast<size_t>(max_retransmission_count_)) {
+    return 0;  // Lost bytes will never be retransmitted.
+  }
+  QuicByteCount bytes = 0;
+  for (const auto& interval : send_buffer().pending_retransmissions()) {
+    bytes += interval.Length();
+  }
+  return bytes;
+}
+
+QuicStreamOffset QuartcStream::ReadOffset() {
+  return sequencer()->NumBytesConsumed();
+}
+
+void QuartcStream::FinishWriting() {
+  WriteOrBufferData(QuicStringPiece(nullptr, 0), true, nullptr);
+}
+
+void QuartcStream::SetDelegate(Delegate* delegate) {
+  if (delegate_) {
+    LOG(WARNING) << "The delegate for Stream " << id()
+                 << " has already been set.";
+  }
+  delegate_ = delegate;
+  DCHECK(delegate_);
+}
+
+}  // namespace quic