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 IOBuffer { 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(const char* buffer, 91 size_t buf_len, 92 const quic::QuicIpAddress& self_address, 93 const quic::QuicSocketAddress& peer_address, 94 quic::PerPacketOptions* options) override; 95 bool IsWriteBlocked() const override; 96 void SetWritable() override; 97 absl::optional<int> MessageTooBigErrorCode() const override; 98 quic::QuicByteCount GetMaxPacketSize( 99 const quic::QuicSocketAddress& peer_address) const override; 100 bool SupportsReleaseTime() const override; 101 bool IsBatchMode() const override; 102 quic::QuicPacketBuffer GetNextWriteLocation( 103 const quic::QuicIpAddress& self_address, 104 const quic::QuicSocketAddress& peer_address) override; 105 quic::WriteResult Flush() override; 106 107 void OnWriteComplete(int rv); 108 109 private: 110 void SetPacket(const char* buffer, size_t buf_len); 111 bool MaybeRetryAfterWriteError(int rv); 112 void RetryPacketAfterNoBuffers(); 113 quic::WriteResult WritePacketToSocketImpl(); 114 raw_ptr<DatagramClientSocket, DanglingUntriaged> socket_; // Unowned. 115 raw_ptr<Delegate, DanglingUntriaged> delegate_ = nullptr; // Unowned. 116 // Reused for every packet write for the lifetime of the writer. Is 117 // moved to the delegate in the case of a write error. 118 scoped_refptr<ReusableIOBuffer> packet_; 119 120 // Whether a write is currently in progress: true if an asynchronous write is 121 // in flight, or a retry of a previous write is in progress, or session is 122 // handling write error of a previous write. 123 bool write_in_progress_ = false; 124 125 // If ture, IsWriteBlocked() will return true regardless of 126 // |write_in_progress_|. 127 bool force_write_blocked_ = false; 128 129 int retry_count_ = 0; 130 // Timer set when a packet should be retried after ENOBUFS. 131 base::OneShotTimer retry_timer_; 132 133 CompletionRepeatingCallback write_callback_; 134 base::WeakPtrFactory<QuicChromiumPacketWriter> weak_factory_{this}; 135 }; 136 137 } // namespace net 138 139 #endif // NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_ 140