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