xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/batch_writer/quic_batch_writer_base.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_QUIC_CORE_BATCH_WRITER_QUIC_BATCH_WRITER_BASE_H_
6 #define QUICHE_QUIC_CORE_BATCH_WRITER_QUIC_BATCH_WRITER_BASE_H_
7 
8 #include <cstdint>
9 
10 #include "quiche/quic/core/batch_writer/quic_batch_writer_buffer.h"
11 #include "quiche/quic/core/quic_packet_writer.h"
12 #include "quiche/quic/core/quic_types.h"
13 #include "quiche/quic/platform/api/quic_ip_address.h"
14 #include "quiche/quic/platform/api/quic_socket_address.h"
15 
16 namespace quic {
17 
18 // QuicBatchWriterBase implements logic common to all derived batch writers,
19 // including maintaining write blockage state and a skeleton implemention of
20 // WritePacket().
21 // A derived batch writer must override the FlushImpl() function to send all
22 // buffered writes in a batch. It must also override the CanBatch() function
23 // to control whether/when a WritePacket() call should flush.
24 class QUICHE_EXPORT QuicBatchWriterBase : public QuicPacketWriter {
25  public:
26   explicit QuicBatchWriterBase(
27       std::unique_ptr<QuicBatchWriterBuffer> batch_buffer);
28 
29   // ATTENTION: If this write triggered a flush, and the flush failed, all
30   // buffered packets will be dropped to allow the next write to work. The
31   // number of dropped packets can be found in WriteResult.dropped_packets.
32   WriteResult WritePacket(const char* buffer, size_t buf_len,
33                           const QuicIpAddress& self_address,
34                           const QuicSocketAddress& peer_address,
35                           PerPacketOptions* options,
36                           const QuicPacketWriterParams& params) override;
37 
IsWriteBlocked()38   bool IsWriteBlocked() const final { return write_blocked_; }
39 
SetWritable()40   void SetWritable() final { write_blocked_ = false; }
41 
MessageTooBigErrorCode()42   std::optional<int> MessageTooBigErrorCode() const override {
43     return EMSGSIZE;
44   }
45 
GetMaxPacketSize(const QuicSocketAddress &)46   QuicByteCount GetMaxPacketSize(
47       const QuicSocketAddress& /*peer_address*/) const final {
48     return kMaxOutgoingPacketSize;
49   }
50 
SupportsReleaseTime()51   bool SupportsReleaseTime() const override { return false; }
52 
IsBatchMode()53   bool IsBatchMode() const final { return true; }
54 
SupportsEcn()55   bool SupportsEcn() const override { return false; }
56 
GetNextWriteLocation(const QuicIpAddress &,const QuicSocketAddress &)57   QuicPacketBuffer GetNextWriteLocation(
58       const QuicIpAddress& /*self_address*/,
59       const QuicSocketAddress& /*peer_address*/) final {
60     // No need to explicitly delete QuicBatchWriterBuffer.
61     return {batch_buffer_->GetNextWriteLocation(), nullptr};
62   }
63 
64   WriteResult Flush() override;
65 
66  protected:
batch_buffer()67   const QuicBatchWriterBuffer& batch_buffer() const { return *batch_buffer_; }
batch_buffer()68   QuicBatchWriterBuffer& batch_buffer() { return *batch_buffer_; }
69 
buffered_writes()70   const quiche::QuicheCircularDeque<BufferedWrite>& buffered_writes() const {
71     return batch_buffer_->buffered_writes();
72   }
73 
74   // Given the release delay in |options| and the state of |batch_buffer_|, get
75   // the absolute release time.
76   struct QUICHE_EXPORT ReleaseTime {
77     // The actual (absolute) release time.
78     uint64_t actual_release_time = 0;
79     // The difference between |actual_release_time| and ideal release time,
80     // which is (now + |options->release_time_delay|).
81     QuicTime::Delta release_time_offset = QuicTime::Delta::Zero();
82   };
GetReleaseTime(const QuicPacketWriterParams &)83   virtual ReleaseTime GetReleaseTime(
84       const QuicPacketWriterParams& /*params*/) const {
85     QUICHE_DCHECK(false)
86         << "Should not be called since release time is unsupported.";
87     return ReleaseTime{0, QuicTime::Delta::Zero()};
88   }
89 
90   struct QUICHE_EXPORT CanBatchResult {
CanBatchResultCanBatchResult91     CanBatchResult(bool can_batch, bool must_flush)
92         : can_batch(can_batch), must_flush(must_flush) {}
93     // Whether this write can be batched with existing buffered writes.
94     bool can_batch;
95     // If |can_batch|, whether the caller must flush after this packet is
96     // buffered.
97     // Always true if not |can_batch|.
98     bool must_flush;
99   };
100 
101   // Given the existing buffered writes(in buffered_writes()), whether a new
102   // write(in the arguments) can be batched.
103   virtual CanBatchResult CanBatch(const char* buffer, size_t buf_len,
104                                   const QuicIpAddress& self_address,
105                                   const QuicSocketAddress& peer_address,
106                                   const PerPacketOptions* options,
107                                   const QuicPacketWriterParams& params,
108                                   uint64_t release_time) const = 0;
109 
110   struct QUICHE_EXPORT FlushImplResult {
111     // The return value of the Flush() interface, which is:
112     // - WriteResult(WRITE_STATUS_OK, <bytes_flushed>) if all buffered writes
113     //   were sent successfully.
114     // - WRITE_STATUS_BLOCKED or WRITE_STATUS_ERROR, if the batch write is
115     //   blocked or returned an error while sending. If a portion of buffered
116     //   writes were sent successfully, |FlushImplResult.num_packets_sent| and
117     //   |FlushImplResult.bytes_written| contain the number of successfully sent
118     //   packets and their total bytes.
119     WriteResult write_result;
120     int num_packets_sent;
121     // If write_result.status == WRITE_STATUS_OK, |bytes_written| will be equal
122     // to write_result.bytes_written. Otherwise |bytes_written| will be the
123     // number of bytes written before WRITE_BLOCK or WRITE_ERROR happened.
124     int bytes_written;
125   };
126 
127   // Send all buffered writes(in buffered_writes()) in a batch.
128   // buffered_writes() is guaranteed to be non-empty when this function is
129   // called.
130   virtual FlushImplResult FlushImpl() = 0;
131 
132  private:
133   WriteResult InternalWritePacket(const char* buffer, size_t buf_len,
134                                   const QuicIpAddress& self_address,
135                                   const QuicSocketAddress& peer_address,
136                                   PerPacketOptions* options,
137                                   const QuicPacketWriterParams& params);
138 
139   // Calls FlushImpl() and check its post condition.
140   FlushImplResult CheckedFlush();
141 
142   bool write_blocked_;
143   std::unique_ptr<QuicBatchWriterBuffer> batch_buffer_;
144 };
145 
146 // QuicUdpBatchWriter is a batch writer backed by a UDP socket.
147 class QUICHE_EXPORT QuicUdpBatchWriter : public QuicBatchWriterBase {
148  public:
QuicUdpBatchWriter(std::unique_ptr<QuicBatchWriterBuffer> batch_buffer,int fd)149   QuicUdpBatchWriter(std::unique_ptr<QuicBatchWriterBuffer> batch_buffer,
150                      int fd)
151       : QuicBatchWriterBase(std::move(batch_buffer)), fd_(fd) {}
152 
fd()153   int fd() const { return fd_; }
154 
155  private:
156   const int fd_;
157 };
158 
159 }  // namespace quic
160 
161 #endif  // QUICHE_QUIC_CORE_BATCH_WRITER_QUIC_BATCH_WRITER_BASE_H_
162