Project import generated by Copybara.
PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/quic_stream_sequencer.h b/quic/core/quic_stream_sequencer.h
new file mode 100644
index 0000000..3feee5e
--- /dev/null
+++ b/quic/core/quic_stream_sequencer.h
@@ -0,0 +1,212 @@
+// Copyright (c) 2012 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.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_STREAM_SEQUENCER_H_
+#define QUICHE_QUIC_CORE_QUIC_STREAM_SEQUENCER_H_
+
+#include <cstddef>
+#include <map>
+
+#include "base/macros.h"
+#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+
+namespace quic {
+
+namespace test {
+class QuicStreamSequencerPeer;
+} // namespace test
+
+// Buffers frames until we have something which can be passed
+// up to the next layer.
+class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
+ public:
+ // Interface that thie Sequencer uses to communicate with the Stream.
+ class StreamInterface {
+ public:
+ virtual ~StreamInterface() = default;
+
+ // Called when new data is available to be read from the sequencer.
+ virtual void OnDataAvailable() = 0;
+ // Called when the end of the stream has been read.
+ virtual void OnFinRead() = 0;
+ // Called when bytes have been consumed from the sequencer.
+ virtual void AddBytesConsumed(QuicByteCount bytes) = 0;
+ // TODO(rch): Clean up this interface via OnUnrecoverableError and
+ // remove PeerAddressOfLatestPacket().
+ // Called when an error has occurred which should result in the stream
+ // being reset.
+ virtual void Reset(QuicRstStreamErrorCode error) = 0;
+ // Called when an error has occurred which should result in the connection
+ // being closed.
+ virtual void CloseConnectionWithDetails(QuicErrorCode error,
+ const QuicString& details) = 0;
+
+ // Returns the stream id of this stream.
+ virtual QuicStreamId id() const = 0;
+ // Returns the peer address of the last packet received for this stream.
+ virtual const QuicSocketAddress& PeerAddressOfLatestPacket() const = 0;
+ };
+
+ explicit QuicStreamSequencer(StreamInterface* quic_stream);
+ QuicStreamSequencer(const QuicStreamSequencer&) = delete;
+ QuicStreamSequencer(QuicStreamSequencer&&) = default;
+ QuicStreamSequencer& operator=(const QuicStreamSequencer&) = delete;
+ virtual ~QuicStreamSequencer();
+
+ // If the frame is the next one we need in order to process in-order data,
+ // ProcessData will be immediately called on the stream until all buffered
+ // data is processed or the stream fails to consume data. Any unconsumed
+ // data will be buffered. If the frame is not the next in line, it will be
+ // buffered.
+ void OnStreamFrame(const QuicStreamFrame& frame);
+
+ // If the frame is the next one we need in order to process in-order data,
+ // ProcessData will be immediately called on the crypto stream until all
+ // buffered data is processed or the crypto stream fails to consume data. Any
+ // unconsumed data will be buffered. If the frame is not the next in line, it
+ // will be buffered.
+ void OnCryptoFrame(const QuicCryptoFrame& frame);
+
+ // Once data is buffered, it's up to the stream to read it when the stream
+ // can handle more data. The following three functions make that possible.
+
+ // Fills in up to iov_len iovecs with the next readable regions. Returns the
+ // number of iovs used. Non-destructive of the underlying data.
+ int GetReadableRegions(iovec* iov, size_t iov_len) const;
+
+ // Fills in one iovec with the next readable region. Returns false if there
+ // is no readable region available.
+ bool GetReadableRegion(iovec* iov) const;
+
+ // Fill in one iovec with the next unread region for the quic spdy stream.
+ // Returns false if no readable region is available.
+ bool PrefetchNextRegion(iovec* iov);
+
+ // Copies the data into the iov_len buffers provided. Returns the number of
+ // bytes read. Any buffered data no longer in use will be released.
+ // TODO(rch): remove this method and instead implement it as a helper method
+ // based on GetReadableRegions and MarkConsumed.
+ int Readv(const struct iovec* iov, size_t iov_len);
+
+ // Consumes |num_bytes| data. Used in conjunction with |GetReadableRegions|
+ // to do zero-copy reads.
+ void MarkConsumed(size_t num_bytes);
+
+ // Appends all of the readable data to |buffer| and marks all of the appended
+ // data as consumed.
+ void Read(QuicString* buffer);
+
+ // Returns true if the sequncer has bytes available for reading.
+ bool HasBytesToRead() const;
+
+ // Number of bytes available to read.
+ size_t ReadableBytes() const;
+
+ // Returns true if the sequencer has delivered the fin.
+ bool IsClosed() const;
+
+ // Calls |OnDataAvailable| on |stream_| if there is buffered data that can
+ // be processed, and causes |OnDataAvailable| to be called as new data
+ // arrives.
+ void SetUnblocked();
+
+ // Blocks processing of frames until |SetUnblocked| is called.
+ void SetBlockedUntilFlush();
+
+ // Sets the sequencer to discard all incoming data itself and not call
+ // |stream_->OnDataAvailable()|. |stream_->OnFinRead()| will be called
+ // automatically when the FIN is consumed (which may be immediately).
+ void StopReading();
+
+ // Free the memory of underlying buffer.
+ void ReleaseBuffer();
+
+ // Free the memory of underlying buffer when no bytes remain in it.
+ void ReleaseBufferIfEmpty();
+
+ // Number of bytes in the buffer right now.
+ size_t NumBytesBuffered() const;
+
+ // Number of bytes has been consumed.
+ QuicStreamOffset NumBytesConsumed() const;
+
+ QuicStreamOffset close_offset() const { return close_offset_; }
+
+ int num_frames_received() const { return num_frames_received_; }
+
+ int num_duplicate_frames_received() const {
+ return num_duplicate_frames_received_;
+ }
+
+ bool ignore_read_data() const { return ignore_read_data_; }
+
+ void set_level_triggered(bool level_triggered) {
+ level_triggered_ = level_triggered;
+ }
+
+ bool level_triggered() const { return level_triggered_; }
+
+ void set_stream(StreamInterface* stream) { stream_ = stream; }
+
+ // Returns string describing internal state.
+ const QuicString DebugString() const;
+
+ private:
+ friend class test::QuicStreamSequencerPeer;
+
+ // Deletes and records as consumed any buffered data that is now in-sequence.
+ // (To be called only after StopReading has been called.)
+ void FlushBufferedFrames();
+
+ // Wait until we've seen 'offset' bytes, and then terminate the stream.
+ void CloseStreamAtOffset(QuicStreamOffset offset);
+
+ // If we've received a FIN and have processed all remaining data, then inform
+ // the stream of FIN, and clear buffers.
+ bool MaybeCloseStream();
+
+ // Shared implementation between OnStreamFrame and OnCryptoFrame.
+ void OnFrameData(QuicStreamOffset byte_offset,
+ size_t data_len,
+ const char* data_buffer);
+
+ // The stream which owns this sequencer.
+ StreamInterface* stream_;
+
+ // Stores received data in offset order.
+ QuicStreamSequencerBuffer buffered_frames_;
+
+ // The offset, if any, we got a stream termination for. When this many bytes
+ // have been processed, the sequencer will be closed.
+ QuicStreamOffset close_offset_;
+
+ // If true, the sequencer is blocked from passing data to the stream and will
+ // buffer all new incoming data until FlushBufferedFrames is called.
+ bool blocked_;
+
+ // Count of the number of frames received.
+ int num_frames_received_;
+
+ // Count of the number of duplicate frames received.
+ int num_duplicate_frames_received_;
+
+ // If true, all incoming data will be discarded.
+ bool ignore_read_data_;
+
+ // If false, only call OnDataAvailable() when it becomes newly unblocked.
+ // Otherwise, call OnDataAvailable() when number of readable bytes changes.
+ bool level_triggered_;
+
+ // Latched value of quic_stop_reading_when_level_triggered flag. When true,
+ // the sequencer will discard incoming data (but not FIN bits) after
+ // StopReading is called, even in level_triggered_ mode.
+ const bool stop_reading_when_level_triggered_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_STREAM_SEQUENCER_H_