blob: 4faa3cba4e715d133ef48e816178139ea3f7f50c [file] [log] [blame]
// 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_