File: quic_chromium_packet_writer.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (164 lines) | stat: -rw-r--r-- 6,550 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_
#define NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_

#include <stddef.h>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/timer/timer.h"
#include "net/base/completion_repeating_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_export.h"
#include "net/socket/datagram_client_socket.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_packet_writer.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_types.h"

namespace net {

// Chrome specific packet writer which uses a datagram Socket for writing data.
class NET_EXPORT_PRIVATE QuicChromiumPacketWriter
    : public quic::QuicPacketWriter {
 public:
  // Define a specific IO buffer that can be allocated once, but be
  // assigned new contents and reused, avoiding the alternative of
  // repeated memory allocations.  This packet writer only ever has a
  // single write in flight, a constraint inherited from the interface
  // of the underlying datagram Socket.
  class NET_EXPORT_PRIVATE ReusableIOBuffer : public IOBufferWithSize {
   public:
    explicit ReusableIOBuffer(size_t capacity);

    size_t capacity() const { return capacity_; }
    size_t size() const { return size_; }

    // Does memcpy from |buffer| into this->data(). |buf_len <=
    // capacity()| must be true, |HasOneRef()| must be true.
    void Set(const char* buffer, size_t buf_len);

   private:
    ~ReusableIOBuffer() override;
    size_t capacity_;
    size_t size_ = 0;
  };
  // Delegate interface which receives notifications on socket write events.
  class NET_EXPORT_PRIVATE Delegate {
   public:
    // Called when a socket write attempt results in a failure, so
    // that the delegate may recover from it by perhaps rewriting the
    // packet to a different socket. An implementation must return the
    // return value from the rewrite attempt if there is one, and
    // |error_code| otherwise.
    virtual int HandleWriteError(
        int error_code,
        scoped_refptr<ReusableIOBuffer> last_packet) = 0;

    // Called to propagate the final write error to the delegate.
    virtual void OnWriteError(int error_code) = 0;

    // Called when the writer is unblocked due to a write completion.
    virtual void OnWriteUnblocked() = 0;
  };

  // |socket| and |task_runner| must outlive writer.
  QuicChromiumPacketWriter(DatagramClientSocket* socket,
                           base::SequencedTaskRunner* task_runner);

  QuicChromiumPacketWriter(const QuicChromiumPacketWriter&) = delete;
  QuicChromiumPacketWriter& operator=(const QuicChromiumPacketWriter&) = delete;

  ~QuicChromiumPacketWriter() override;

  // |delegate| must outlive writer.
  void set_delegate(Delegate* delegate) { delegate_ = delegate; }

  // This method may unblock the packet writer if |force_write_blocked| is
  // false.
  void set_force_write_blocked(bool force_write_blocked);

  // Writes |packet| to the socket and handles write result if the write
  // completes synchronously.
  void WritePacketToSocket(scoped_refptr<ReusableIOBuffer> packet);

  // quic::QuicPacketWriter
  quic::WriteResult WritePacket(
      const char* buffer,
      size_t buf_len,
      const quiche::QuicheIpAddress& self_address,
      const quic::QuicSocketAddress& peer_address,
      quic::PerPacketOptions* options,
      const quic::QuicPacketWriterParams& params) override;
  bool IsWriteBlocked() const override;
  void SetWritable() override;
  std::optional<int> MessageTooBigErrorCode() const override;
  quic::QuicByteCount GetMaxPacketSize(
      const quic::QuicSocketAddress& peer_address) const override;
  bool SupportsReleaseTime() const override;
  bool IsBatchMode() const override;
  bool SupportsEcn() const override;
  quic::QuicPacketBuffer GetNextWriteLocation(
      const quiche::QuicheIpAddress& self_address,
      const quic::QuicSocketAddress& peer_address) override;
  quic::WriteResult Flush() override;

  void OnWriteComplete(int rv);

  // If the writer has enqueued a task to retry, OnSocketClosed() must be called
  // when the socket is closed to avoid using an invalid socket.
  bool OnSocketClosed(DatagramClientSocket* socket);

  // Register a QUIC UDP payload that can close a QUIC connection and the
  // underlying socket to the Android system server. When the app loses network
  // access, the system server destroys the registered socket and sends the
  // registered UDP payload to the server.
  void RegisterQuicConnectionClosePayload(base::span<uint8_t> payload);

  // Unregister the underlying socket and its associated UDP payload that were
  // previously registered by RegisterQuicConnectionClosePayload
  void UnregisterQuicConnectionClosePayload();

 private:
  void SetPacket(const char* buffer, size_t buf_len);
  bool MaybeRetryAfterWriteError(int rv);
  void RetryPacketAfterNoBuffers();
  quic::WriteResult WritePacketToSocketImpl();
  raw_ptr<DatagramClientSocket> socket_;  // Unowned.
  raw_ptr<Delegate> delegate_ = nullptr;  // Unowned.
  // Reused for every packet write for the lifetime of the writer.  Is
  // moved to the delegate in the case of a write error.
  scoped_refptr<ReusableIOBuffer> packet_;

  // Whether a write is currently in progress: true if an asynchronous write is
  // in flight, or a retry of a previous write is in progress, or session is
  // handling write error of a previous write.
  bool write_in_progress_ = false;

  // If ture, IsWriteBlocked() will return true regardless of
  // |write_in_progress_|.
  bool force_write_blocked_ = false;

  // The current ECN codepoint the UDP socket is sending.
  EcnCodePoint outgoing_ecn_ = ECN_NOT_ECT;

  // Bitmap of outgoing IP ECN marks observed on this session. Bit 0 = Not-ECT,
  // Bit 1 = ECT(1), Bit 2 = ECT(0), Bit 3 = CE. Reported to metrics at the
  // end of the session.
  uint8_t outgoing_ecn_history_ = 0;

  int retry_count_ = 0;
  // Timer set when a packet should be retried after ENOBUFS.
  base::OneShotTimer retry_timer_;

  CompletionRepeatingCallback write_callback_;
  base::WeakPtrFactory<QuicChromiumPacketWriter> weak_factory_{this};
};

}  // namespace net

#endif  // NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_