| // Copyright (c) 2019 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_PLATFORM_IMPL_BATCH_WRITER_QUIC_BATCH_WRITER_BUFFER_H_ |
| #define QUICHE_QUIC_PLATFORM_IMPL_BATCH_WRITER_QUIC_BATCH_WRITER_BUFFER_H_ |
| |
| #include "absl/base/optimization.h" |
| #include "quic/core/quic_linux_socket_utils.h" |
| #include "quic/core/quic_packet_writer.h" |
| #include "quic/platform/api/quic_ip_address.h" |
| #include "quic/platform/api/quic_socket_address.h" |
| #include "common/quiche_circular_deque.h" |
| |
| namespace quic { |
| |
| // QuicBatchWriterBuffer manages an internal buffer to hold data from multiple |
| // packets. Packet data are placed continuously within the internal buffer such |
| // that they can be sent by a QuicGsoBatchWriter. |
| // This class can also be used by a QuicBatchWriter which uses sendmmsg, |
| // although it is not optimized for that use case. |
| class QUIC_EXPORT_PRIVATE QuicBatchWriterBuffer { |
| public: |
| QuicBatchWriterBuffer(); |
| |
| // Clear all buffered writes, but leave the internal buffer intact. |
| void Clear(); |
| |
| char* GetNextWriteLocation() const; |
| |
| // Push a buffered write to the back. |
| struct QUIC_EXPORT_PRIVATE PushResult { |
| bool succeeded; |
| // True in one of the following cases: |
| // 1) The packet buffer is external and copied to the internal buffer, or |
| // 2) The packet buffer is from the internal buffer and moved within it. |
| // This only happens if PopBufferedWrite is called in the middle of a |
| // in-place push. |
| // Only valid if |succeeded| is true. |
| bool buffer_copied; |
| }; |
| |
| PushResult PushBufferedWrite(const char* buffer, |
| size_t buf_len, |
| const QuicIpAddress& self_address, |
| const QuicSocketAddress& peer_address, |
| const PerPacketOptions* options, |
| uint64_t release_time); |
| |
| void UndoLastPush(); |
| |
| // Pop |num_buffered_writes| buffered writes from the front. |
| // |num_buffered_writes| will be capped to [0, buffered_writes().size()] |
| // before it is used. |
| struct QUIC_EXPORT_PRIVATE PopResult { |
| int32_t num_buffers_popped; |
| // True if after |num_buffers_popped| buffers are popped from front, the |
| // remaining buffers are moved to the beginning of the internal buffer. |
| // This should normally be false. |
| bool moved_remaining_buffers; |
| }; |
| PopResult PopBufferedWrite(int32_t num_buffered_writes); |
| |
| const quiche::QuicheCircularDeque<BufferedWrite>& buffered_writes() const { |
| return buffered_writes_; |
| } |
| |
| bool IsExternalBuffer(const char* buffer, size_t buf_len) const { |
| return (buffer + buf_len) <= buffer_ || buffer >= buffer_end(); |
| } |
| bool IsInternalBuffer(const char* buffer, size_t buf_len) const { |
| return buffer >= buffer_ && (buffer + buf_len) <= buffer_end(); |
| } |
| |
| // Number of bytes used in |buffer_|. |
| // PushBufferedWrite() increases this; PopBufferedWrite decreases this. |
| size_t SizeInUse() const; |
| |
| // Rounded up from |kMaxGsoPacketSize|, which is the maximum allowed |
| // size of a GSO packet. |
| static const size_t kBufferSize = 64 * 1024; |
| |
| std::string DebugString() const; |
| |
| protected: |
| // Whether the invariants of the buffer are upheld. For debug & test only. |
| bool Invariants() const; |
| const char* buffer_end() const { return buffer_ + sizeof(buffer_); } |
| ABSL_CACHELINE_ALIGNED char buffer_[kBufferSize]; |
| quiche::QuicheCircularDeque<BufferedWrite> buffered_writes_; |
| }; |
| |
| } // namespace quic |
| |
| #endif // QUICHE_QUIC_PLATFORM_IMPL_BATCH_WRITER_QUIC_BATCH_WRITER_BUFFER_H_ |