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