1 // Copyright 2013 The Chromium Authors 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 NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_ 6 #define NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_ 7 8 #include <stddef.h> 9 10 #include "base/memory/raw_ptr.h" 11 #include "base/memory/weak_ptr.h" 12 #include "base/task/sequenced_task_runner.h" 13 #include "base/timer/timer.h" 14 #include "net/base/completion_repeating_callback.h" 15 #include "net/base/io_buffer.h" 16 #include "net/base/net_export.h" 17 #include "net/socket/datagram_client_socket.h" 18 #include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h" 19 #include "net/third_party/quiche/src/quiche/quic/core/quic_packet_writer.h" 20 #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h" 21 #include "net/third_party/quiche/src/quiche/quic/core/quic_types.h" 22 23 namespace net { 24 25 // Chrome specific packet writer which uses a datagram Socket for writing data. 26 class NET_EXPORT_PRIVATE QuicChromiumPacketWriter 27 : public quic::QuicPacketWriter { 28 public: 29 // Define a specific IO buffer that can be allocated once, but be 30 // assigned new contents and reused, avoiding the alternative of 31 // repeated memory allocations. This packet writer only ever has a 32 // single write in flight, a constraint inherited from the interface 33 // of the underlying datagram Socket. 34 class NET_EXPORT_PRIVATE ReusableIOBuffer : public IOBufferWithSize { 35 public: 36 explicit ReusableIOBuffer(size_t capacity); 37 capacity()38 size_t capacity() const { return capacity_; } size()39 size_t size() const { return size_; } 40 41 // Does memcpy from |buffer| into this->data(). |buf_len <= 42 // capacity()| must be true, |HasOneRef()| must be true. 43 void Set(const char* buffer, size_t buf_len); 44 45 private: 46 ~ReusableIOBuffer() override; 47 size_t capacity_; 48 size_t size_ = 0; 49 }; 50 // Delegate interface which receives notifications on socket write events. 51 class NET_EXPORT_PRIVATE Delegate { 52 public: 53 // Called when a socket write attempt results in a failure, so 54 // that the delegate may recover from it by perhaps rewriting the 55 // packet to a different socket. An implementation must return the 56 // return value from the rewrite attempt if there is one, and 57 // |error_code| otherwise. 58 virtual int HandleWriteError( 59 int error_code, 60 scoped_refptr<ReusableIOBuffer> last_packet) = 0; 61 62 // Called to propagate the final write error to the delegate. 63 virtual void OnWriteError(int error_code) = 0; 64 65 // Called when the writer is unblocked due to a write completion. 66 virtual void OnWriteUnblocked() = 0; 67 }; 68 69 // |socket| and |task_runner| must outlive writer. 70 QuicChromiumPacketWriter(DatagramClientSocket* socket, 71 base::SequencedTaskRunner* task_runner); 72 73 QuicChromiumPacketWriter(const QuicChromiumPacketWriter&) = delete; 74 QuicChromiumPacketWriter& operator=(const QuicChromiumPacketWriter&) = delete; 75 76 ~QuicChromiumPacketWriter() override; 77 78 // |delegate| must outlive writer. set_delegate(Delegate * delegate)79 void set_delegate(Delegate* delegate) { delegate_ = delegate; } 80 81 // This method may unblock the packet writer if |force_write_blocked| is 82 // false. 83 void set_force_write_blocked(bool force_write_blocked); 84 85 // Writes |packet| to the socket and handles write result if the write 86 // completes synchronously. 87 void WritePacketToSocket(scoped_refptr<ReusableIOBuffer> packet); 88 89 // quic::QuicPacketWriter 90 quic::WriteResult WritePacket( 91 const char* buffer, 92 size_t buf_len, 93 const quic::QuicIpAddress& self_address, 94 const quic::QuicSocketAddress& peer_address, 95 quic::PerPacketOptions* options, 96 const quic::QuicPacketWriterParams& params) override; 97 bool IsWriteBlocked() const override; 98 void SetWritable() override; 99 std::optional<int> MessageTooBigErrorCode() const override; 100 quic::QuicByteCount GetMaxPacketSize( 101 const quic::QuicSocketAddress& peer_address) const override; 102 bool SupportsReleaseTime() const override; 103 bool IsBatchMode() const override; 104 bool SupportsEcn() const override; 105 quic::QuicPacketBuffer GetNextWriteLocation( 106 const quic::QuicIpAddress& self_address, 107 const quic::QuicSocketAddress& peer_address) override; 108 quic::WriteResult Flush() override; 109 110 void OnWriteComplete(int rv); 111 112 // If the writer has enqueued a task to retry, OnSocketClosed() must be called 113 // when the socket is closed to avoid using an invalid socket. 114 bool OnSocketClosed(DatagramClientSocket* socket); 115 116 private: 117 void SetPacket(const char* buffer, size_t buf_len); 118 bool MaybeRetryAfterWriteError(int rv); 119 void RetryPacketAfterNoBuffers(); 120 quic::WriteResult WritePacketToSocketImpl(); 121 raw_ptr<DatagramClientSocket, DanglingUntriaged> socket_; // Unowned. 122 raw_ptr<Delegate> delegate_ = nullptr; // Unowned. 123 // Reused for every packet write for the lifetime of the writer. Is 124 // moved to the delegate in the case of a write error. 125 scoped_refptr<ReusableIOBuffer> packet_; 126 127 // Whether a write is currently in progress: true if an asynchronous write is 128 // in flight, or a retry of a previous write is in progress, or session is 129 // handling write error of a previous write. 130 bool write_in_progress_ = false; 131 132 // If ture, IsWriteBlocked() will return true regardless of 133 // |write_in_progress_|. 134 bool force_write_blocked_ = false; 135 136 int retry_count_ = 0; 137 // Timer set when a packet should be retried after ENOBUFS. 138 base::OneShotTimer retry_timer_; 139 140 CompletionRepeatingCallback write_callback_; 141 base::WeakPtrFactory<QuicChromiumPacketWriter> weak_factory_{this}; 142 }; 143 144 } // namespace net 145 146 #endif // NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_ 147