• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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