| // 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. |
| |
| #ifndef QUICHE_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_INLINING_H_ |
| #define QUICHE_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_INLINING_H_ |
| |
| #include <cstddef> |
| |
| #include "absl/container/flat_hash_map.h" |
| #include "absl/strings/string_view.h" |
| #include "absl/types/span.h" |
| #include "quiche/quic/core/quic_inlined_string_view.h" |
| #include "quiche/quic/core/quic_interval.h" |
| #include "quiche/quic/core/quic_interval_deque.h" |
| #include "quiche/quic/core/quic_stream_send_buffer_base.h" |
| #include "quiche/quic/core/quic_types.h" |
| #include "quiche/common/platform/api/quiche_export.h" |
| #include "quiche/common/quiche_buffer_allocator.h" |
| #include "quiche/common/quiche_mem_slice.h" |
| |
| namespace quic { |
| |
| namespace test { |
| class QuicStreamSendBufferPeer; |
| } |
| |
| class QuicDataWriter; |
| |
| constexpr size_t kSendBufferMaxInlinedSize = 15; |
| |
| // BufferedSliceInlining is an entry in the send buffer. It contains a pointer |
| // to the buffered data (or data itself, if it is inlined), the size of the data |
| // and the offset in the buffer. |
| // |
| // BufferedSliceInlining does not own contents of the slice; those are freed |
| // separately. Since we perform a search over an array of BufferedSliceInlining, |
| // it is important for this data structure to be compact. |
| struct QUICHE_EXPORT BufferedSliceInlining { |
| BufferedSliceInlining(absl::string_view slice, QuicStreamOffset offset); |
| BufferedSliceInlining(BufferedSliceInlining&& other); |
| BufferedSliceInlining& operator=(BufferedSliceInlining&& other); |
| |
| BufferedSliceInlining(const BufferedSliceInlining& other) = delete; |
| BufferedSliceInlining& operator=(const BufferedSliceInlining& other) = delete; |
| ~BufferedSliceInlining(); |
| |
| // Return an interval representing the offset and length. |
| QuicInterval<std::size_t> interval() const; |
| |
| // Stream data of this data slice. |
| QuicInlinedStringView<kSendBufferMaxInlinedSize + 1> slice; |
| |
| // Location of this data slice in the stream. |
| QuicStreamOffset offset; |
| }; |
| |
| // QuicStreamSendBuffer contains all of the outstanding (provided by the |
| // application and not yet acknowledged by the peer) stream data. Internally it |
| // is a circular deque of (potentially inlined) QuicheMemSlices, indexed by the |
| // offset in the stream. The stream can be accessed randomly in O(log(n)) time, |
| // though if the offsets are accessed sequentially, the access will be O(1). |
| class QUICHE_EXPORT QuicStreamSendBufferInlining |
| : public QuicStreamSendBufferBase { |
| public: |
| explicit QuicStreamSendBufferInlining( |
| quiche::QuicheBufferAllocator* allocator); |
| |
| // Save |data| to send buffer. |
| void SaveStreamData(absl::string_view data) override; |
| |
| // Save |slice| to send buffer. |
| void SaveMemSlice(quiche::QuicheMemSlice slice) override; |
| |
| // Save all slices in |span| to send buffer. Return total bytes saved. |
| QuicByteCount SaveMemSliceSpan( |
| absl::Span<quiche::QuicheMemSlice> span) override; |
| |
| // Write |data_length| of data starts at |offset|. Returns true if all data |
| // was successfully written. Returns false if the writer fails to write, or if |
| // the data was already marked as acked, or if the data was never saved in the |
| // first place. |
| bool WriteStreamData(QuicStreamOffset offset, QuicByteCount data_length, |
| QuicDataWriter* writer) override; |
| |
| // Number of data slices in send buffer. |
| size_t size() const override; |
| |
| QuicStreamOffset stream_offset() const override { return stream_offset_; } |
| |
| void SetStreamOffsetForTest(QuicStreamOffset new_offset) override; |
| absl::string_view LatestWriteForTest() override; |
| QuicByteCount TotalDataBufferedForTest() override; |
| |
| private: |
| friend class test::QuicStreamSendBufferPeer; |
| |
| // Called when data within offset [start, end) gets acked. Frees fully |
| // acked buffered slices if any. Returns false if the corresponding data does |
| // not exist or has been acked. |
| bool FreeMemSlices(QuicStreamOffset start, QuicStreamOffset end) override; |
| |
| // Cleanup acked data from the start of the interval. |
| void CleanUpBufferedSlices() override; |
| |
| // Frees an individual buffered slice. |
| void ClearSlice(BufferedSliceInlining& slice); |
| |
| // Contains actual stream data. |
| QuicIntervalDeque<BufferedSliceInlining> interval_deque_; |
| |
| // Offset of next inserted byte. |
| QuicStreamOffset stream_offset_ = 0; |
| |
| // For slices that are not inlined, contains a map from the offset of the |
| // slice in the buffer to the slice release callback. Those are stored |
| // separately from `interval_deque_`, since the callbacks themselves can be |
| // quite large, and for many slices, those would not be present. |
| absl::flat_hash_map<QuicStreamOffset, quiche::QuicheMemSlice> owned_slices_; |
| |
| quiche::QuicheBufferAllocator* allocator_; |
| }; |
| |
| } // namespace quic |
| |
| #endif // QUICHE_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_INLINING_H_ |