• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 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_QUIC_UDP_SOCKET_H_
6 #define QUICHE_QUIC_CORE_QUIC_UDP_SOCKET_H_
7 
8 #include <cstddef>
9 #include <cstdint>
10 #include <type_traits>
11 
12 #include "quiche/quic/core/io/socket.h"
13 #include "quiche/quic/core/quic_types.h"
14 #include "quiche/quic/core/quic_utils.h"
15 #include "quiche/quic/platform/api/quic_ip_address.h"
16 #include "quiche/quic/platform/api/quic_socket_address.h"
17 
18 #ifndef UDP_GRO
19 #define UDP_GRO 104
20 #endif
21 
22 namespace quic {
23 
24 using QuicUdpSocketFd = SocketFd;
25 inline constexpr QuicUdpSocketFd kQuicInvalidSocketFd = kInvalidSocketFd;
26 
27 inline constexpr size_t kDefaultUdpPacketControlBufferSize = 512;
28 
29 enum class QuicUdpPacketInfoBit : uint8_t {
30   DROPPED_PACKETS = 0,   // Read
31   V4_SELF_IP,            // Read
32   V6_SELF_IP,            // Read
33   PEER_ADDRESS,          // Read & Write
34   RECV_TIMESTAMP,        // Read
35   TTL,                   // Read & Write
36   ECN,                   // Read
37   GOOGLE_PACKET_HEADER,  // Read
38   NUM_BITS,
39   IS_GRO,  // Read
40 };
41 static_assert(static_cast<size_t>(QuicUdpPacketInfoBit::NUM_BITS) <=
42                   BitMask64::NumBits(),
43               "BitMask64 not wide enough to hold all bits.");
44 
45 // BufferSpan points to an unowned buffer, copying this structure only copies
46 // the pointer and length, not the buffer itself.
47 struct QUIC_EXPORT_PRIVATE BufferSpan {
BufferSpanBufferSpan48   BufferSpan(char* buffer, size_t buffer_len)
49       : buffer(buffer), buffer_len(buffer_len) {}
50 
51   BufferSpan() = default;
52   BufferSpan(const BufferSpan& other) = default;
53   BufferSpan& operator=(const BufferSpan& other) = default;
54 
55   char* buffer = nullptr;
56   size_t buffer_len = 0;
57 };
58 
59 // QuicUdpPacketInfo contains per-packet information used for sending and
60 // receiving.
61 class QUIC_EXPORT_PRIVATE QuicUdpPacketInfo {
62  public:
bitmask()63   BitMask64 bitmask() const { return bitmask_; }
64 
Reset()65   void Reset() { bitmask_.ClearAll(); }
66 
HasValue(QuicUdpPacketInfoBit bit)67   bool HasValue(QuicUdpPacketInfoBit bit) const { return bitmask_.IsSet(bit); }
68 
dropped_packets()69   QuicPacketCount dropped_packets() const {
70     QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS));
71     return dropped_packets_;
72   }
73 
SetDroppedPackets(QuicPacketCount dropped_packets)74   void SetDroppedPackets(QuicPacketCount dropped_packets) {
75     dropped_packets_ = dropped_packets;
76     bitmask_.Set(QuicUdpPacketInfoBit::DROPPED_PACKETS);
77   }
78 
set_gso_size(size_t gso_size)79   void set_gso_size(size_t gso_size) {
80     gso_size_ = gso_size;
81     bitmask_.Set(QuicUdpPacketInfoBit::IS_GRO);
82   }
83 
gso_size()84   size_t gso_size() { return gso_size_; }
85 
self_v4_ip()86   const QuicIpAddress& self_v4_ip() const {
87     QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::V4_SELF_IP));
88     return self_v4_ip_;
89   }
90 
SetSelfV4Ip(QuicIpAddress self_v4_ip)91   void SetSelfV4Ip(QuicIpAddress self_v4_ip) {
92     self_v4_ip_ = self_v4_ip;
93     bitmask_.Set(QuicUdpPacketInfoBit::V4_SELF_IP);
94   }
95 
self_v6_ip()96   const QuicIpAddress& self_v6_ip() const {
97     QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::V6_SELF_IP));
98     return self_v6_ip_;
99   }
100 
SetSelfV6Ip(QuicIpAddress self_v6_ip)101   void SetSelfV6Ip(QuicIpAddress self_v6_ip) {
102     self_v6_ip_ = self_v6_ip;
103     bitmask_.Set(QuicUdpPacketInfoBit::V6_SELF_IP);
104   }
105 
SetSelfIp(QuicIpAddress self_ip)106   void SetSelfIp(QuicIpAddress self_ip) {
107     if (self_ip.IsIPv4()) {
108       SetSelfV4Ip(self_ip);
109     } else {
110       SetSelfV6Ip(self_ip);
111     }
112   }
113 
peer_address()114   const QuicSocketAddress& peer_address() const {
115     QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS));
116     return peer_address_;
117   }
118 
SetPeerAddress(QuicSocketAddress peer_address)119   void SetPeerAddress(QuicSocketAddress peer_address) {
120     peer_address_ = peer_address;
121     bitmask_.Set(QuicUdpPacketInfoBit::PEER_ADDRESS);
122   }
123 
receive_timestamp()124   QuicWallTime receive_timestamp() const {
125     QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
126     return receive_timestamp_;
127   }
128 
SetReceiveTimestamp(QuicWallTime receive_timestamp)129   void SetReceiveTimestamp(QuicWallTime receive_timestamp) {
130     receive_timestamp_ = receive_timestamp;
131     bitmask_.Set(QuicUdpPacketInfoBit::RECV_TIMESTAMP);
132   }
133 
ttl()134   int ttl() const {
135     QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::TTL));
136     return ttl_;
137   }
138 
SetTtl(int ttl)139   void SetTtl(int ttl) {
140     ttl_ = ttl;
141     bitmask_.Set(QuicUdpPacketInfoBit::TTL);
142   }
143 
google_packet_headers()144   BufferSpan google_packet_headers() const {
145     QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER));
146     return google_packet_headers_;
147   }
148 
SetGooglePacketHeaders(BufferSpan google_packet_headers)149   void SetGooglePacketHeaders(BufferSpan google_packet_headers) {
150     google_packet_headers_ = google_packet_headers;
151     bitmask_.Set(QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER);
152   }
153 
ecn_codepoint()154   QuicEcnCodepoint ecn_codepoint() const { return ecn_codepoint_; }
155 
SetEcnCodepoint(const QuicEcnCodepoint ecn_codepoint)156   void SetEcnCodepoint(const QuicEcnCodepoint ecn_codepoint) {
157     ecn_codepoint_ = ecn_codepoint;
158     bitmask_.Set(QuicUdpPacketInfoBit::ECN);
159   }
160 
161  private:
162   BitMask64 bitmask_;
163   QuicPacketCount dropped_packets_;
164   QuicIpAddress self_v4_ip_;
165   QuicIpAddress self_v6_ip_;
166   QuicSocketAddress peer_address_;
167   QuicWallTime receive_timestamp_ = QuicWallTime::Zero();
168   int ttl_;
169   BufferSpan google_packet_headers_;
170   size_t gso_size_ = 0;
171   QuicEcnCodepoint ecn_codepoint_ = ECN_NOT_ECT;
172 };
173 
174 // QuicUdpSocketApi provides a minimal set of apis for sending and receiving
175 // udp packets. The low level udp socket apis differ between kernels and kernel
176 // versions, the goal of QuicUdpSocketApi is to hide such differences.
177 // We use non-static functions because it is easier to be mocked in tests when
178 // needed.
179 class QUIC_EXPORT_PRIVATE QuicUdpSocketApi {
180  public:
181   // Creates a non-blocking udp socket, sets the receive/send buffer and enable
182   // receiving of self ip addresses on read.
183   // If address_family == AF_INET6 and ipv6_only is true, receiving of IPv4 self
184   // addresses is disabled. This is only necessary for IPv6 sockets on iOS - all
185   // other platforms can ignore this parameter. Return kQuicInvalidSocketFd if
186   // failed.
187   QuicUdpSocketFd Create(int address_family, int receive_buffer_size,
188                          int send_buffer_size, bool ipv6_only = false);
189 
190   // Closes |fd|. No-op if |fd| equals to kQuicInvalidSocketFd.
191   void Destroy(QuicUdpSocketFd fd);
192 
193   // Bind |fd| to |address|. If |address|'s port number is 0, kernel will choose
194   // a random port to bind to. Caller can use QuicSocketAddress::FromSocket(fd)
195   // to get the bound random port.
196   bool Bind(QuicUdpSocketFd fd, QuicSocketAddress address);
197 
198   // Bind |fd| to |interface_name|. Returns true if the setsockopt call
199   // succeeded. Returns false if |interface_name| is empty, its length exceeds
200   // IFNAMSIZ, or setsockopt experienced an error. Only implemented for
201   // non-Android Linux.
202   bool BindInterface(QuicUdpSocketFd fd, const std::string& interface_name);
203 
204   // Enable receiving of various per-packet information. Return true if the
205   // corresponding information can be received on read.
206   bool EnableDroppedPacketCount(QuicUdpSocketFd fd);
207   bool EnableReceiveTimestamp(QuicUdpSocketFd fd);
208   bool EnableReceiveTtlForV4(QuicUdpSocketFd fd);
209   bool EnableReceiveTtlForV6(QuicUdpSocketFd fd);
210 
211   // Wait for |fd| to become readable, up to |timeout|.
212   // Return true if |fd| is readable upon return.
213   bool WaitUntilReadable(QuicUdpSocketFd fd, QuicTime::Delta timeout);
214 
215   struct QUIC_EXPORT_PRIVATE ReadPacketResult {
216     bool ok = false;
217     QuicUdpPacketInfo packet_info;
218     BufferSpan packet_buffer;
219     BufferSpan control_buffer;
220 
ResetReadPacketResult221     void Reset(size_t packet_buffer_length) {
222       ok = false;
223       packet_info.Reset();
224       packet_buffer.buffer_len = packet_buffer_length;
225     }
226   };
227   // Read a packet from |fd|:
228   // packet_info_interested: Bitmask indicating what information caller wants to
229   //                         receive into |result->packet_info|.
230   // result->packet_info:    Received per packet information.
231   // result->packet_buffer:  The packet buffer, to be filled with packet data.
232   //                         |result->packet_buffer.buffer_len| is set to the
233   //                         packet length on a successful return.
234   // result->control_buffer: The control buffer, used by ReadPacket internally.
235   //                         It is recommended to be
236   //                         |kDefaultUdpPacketControlBufferSize| bytes.
237   // result->ok:             True iff a packet is successfully received.
238   //
239   // If |*result| is reused for subsequent ReadPacket() calls, caller needs to
240   // call result->Reset() before each ReadPacket().
241   void ReadPacket(QuicUdpSocketFd fd, BitMask64 packet_info_interested,
242                   ReadPacketResult* result);
243 
244   using ReadPacketResults = std::vector<ReadPacketResult>;
245   // Read up to |results->size()| packets from |fd|. The meaning of each element
246   // in |*results| has been documented on top of |ReadPacket|.
247   // Return the number of elements populated into |*results|, note it is
248   // possible for some of the populated elements to have ok=false.
249   size_t ReadMultiplePackets(QuicUdpSocketFd fd,
250                              BitMask64 packet_info_interested,
251                              ReadPacketResults* results);
252 
253   // Write a packet to |fd|.
254   // packet_buffer, packet_buffer_len:  The packet buffer to write.
255   // packet_info:                       The per packet information to set.
256   WriteResult WritePacket(QuicUdpSocketFd fd, const char* packet_buffer,
257                           size_t packet_buffer_len,
258                           const QuicUdpPacketInfo& packet_info);
259 
260  protected:
261   bool SetupSocket(QuicUdpSocketFd fd, int address_family,
262                    int receive_buffer_size, int send_buffer_size,
263                    bool ipv6_only);
264   bool EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd);
265   bool EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd);
266 };
267 
268 }  // namespace quic
269 
270 #endif  // QUICHE_QUIC_CORE_QUIC_UDP_SOCKET_H_
271