#ifndef NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_
#define NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_
#include <stddef.h>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/timer/timer.h"
#include "net/base/completion_repeating_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_export.h"
#include "net/socket/datagram_client_socket.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_packet_writer.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_types.h"
namespace net {
class NET_EXPORT_PRIVATE QuicChromiumPacketWriter
: public quic::QuicPacketWriter {
public:
class NET_EXPORT_PRIVATE ReusableIOBuffer : public IOBufferWithSize {
public:
explicit ReusableIOBuffer(size_t capacity);
size_t capacity() const { return capacity_; }
size_t size() const { return size_; }
void Set(const char* buffer, size_t buf_len);
private:
~ReusableIOBuffer() override;
size_t capacity_;
size_t size_ = 0;
};
class NET_EXPORT_PRIVATE Delegate {
public:
virtual int HandleWriteError(
int error_code,
scoped_refptr<ReusableIOBuffer> last_packet) = 0;
virtual void OnWriteError(int error_code) = 0;
virtual void OnWriteUnblocked() = 0;
};
QuicChromiumPacketWriter(DatagramClientSocket* socket,
base::SequencedTaskRunner* task_runner);
QuicChromiumPacketWriter(const QuicChromiumPacketWriter&) = delete;
QuicChromiumPacketWriter& operator=(const QuicChromiumPacketWriter&) = delete;
~QuicChromiumPacketWriter() override;
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
void set_force_write_blocked(bool force_write_blocked);
void WritePacketToSocket(scoped_refptr<ReusableIOBuffer> packet);
quic::WriteResult WritePacket(
const char* buffer,
size_t buf_len,
const quiche::QuicheIpAddress& self_address,
const quic::QuicSocketAddress& peer_address,
quic::PerPacketOptions* options,
const quic::QuicPacketWriterParams& params) override;
bool IsWriteBlocked() const override;
void SetWritable() override;
std::optional<int> MessageTooBigErrorCode() const override;
quic::QuicByteCount GetMaxPacketSize(
const quic::QuicSocketAddress& peer_address) const override;
bool SupportsReleaseTime() const override;
bool IsBatchMode() const override;
bool SupportsEcn() const override;
quic::QuicPacketBuffer GetNextWriteLocation(
const quiche::QuicheIpAddress& self_address,
const quic::QuicSocketAddress& peer_address) override;
quic::WriteResult Flush() override;
void OnWriteComplete(int rv);
bool OnSocketClosed(DatagramClientSocket* socket);
void RegisterQuicConnectionClosePayload(base::span<uint8_t> payload);
void UnregisterQuicConnectionClosePayload();
private:
void SetPacket(const char* buffer, size_t buf_len);
bool MaybeRetryAfterWriteError(int rv);
void RetryPacketAfterNoBuffers();
quic::WriteResult WritePacketToSocketImpl();
raw_ptr<DatagramClientSocket> socket_;
raw_ptr<Delegate> delegate_ = nullptr;
scoped_refptr<ReusableIOBuffer> packet_;
bool write_in_progress_ = false;
bool force_write_blocked_ = false;
EcnCodePoint outgoing_ecn_ = ECN_NOT_ECT;
uint8_t outgoing_ecn_history_ = 0;
int retry_count_ = 0;
base::OneShotTimer retry_timer_;
CompletionRepeatingCallback write_callback_;
base::WeakPtrFactory<QuicChromiumPacketWriter> weak_factory_{this};
};
}
#endif