blob: 534273c1d5f123e58f57ff49623d333ca3690e48 [file] [log] [blame]
wubcfddec82020-01-13 07:45:27 -08001// 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
11#include <type_traits>
12
QUICHE team5be974e2020-12-29 18:35:24 -050013#include "quic/core/quic_types.h"
14#include "quic/core/quic_utils.h"
15#include "quic/platform/api/quic_ip_address.h"
16#include "quic/platform/api/quic_socket_address.h"
wubcfddec82020-01-13 07:45:27 -080017
18namespace quic {
19
20#if defined(_WIN32)
21using QuicUdpSocketFd = SOCKET;
22const QuicUdpSocketFd kQuicInvalidSocketFd = INVALID_SOCKET;
23#else
24using QuicUdpSocketFd = int;
25const QuicUdpSocketFd kQuicInvalidSocketFd = -1;
26#endif
27
wuba27a3c92020-01-28 08:43:21 -080028const size_t kDefaultUdpPacketControlBufferSize = 512;
29
wubcfddec82020-01-13 07:45:27 -080030enum class QuicUdpPacketInfoBit : uint8_t {
31 DROPPED_PACKETS = 0, // Read
32 V4_SELF_IP, // Read
33 V6_SELF_IP, // Read
34 PEER_ADDRESS, // Read & Write
35 RECV_TIMESTAMP, // Read
36 TTL, // Read & Write
37 GOOGLE_PACKET_HEADER, // Read
38 NUM_BITS,
39};
40static_assert(static_cast<size_t>(QuicUdpPacketInfoBit::NUM_BITS) <=
41 BitMask64::NumBits(),
42 "BitMask64 not wide enough to hold all bits.");
43
44// BufferSpan points to an unowned buffer, copying this structure only copies
45// the pointer and length, not the buffer itself.
46struct QUIC_EXPORT_PRIVATE BufferSpan {
47 BufferSpan(char* buffer, size_t buffer_len)
48 : buffer(buffer), buffer_len(buffer_len) {}
49
50 BufferSpan() = default;
51 BufferSpan(const BufferSpan& other) = default;
52 BufferSpan& operator=(const BufferSpan& other) = default;
53
54 char* buffer = nullptr;
55 size_t buffer_len = 0;
56};
57
58// QuicUdpPacketInfo contains per-packet information used for sending and
59// receiving.
60class QUIC_EXPORT_PRIVATE QuicUdpPacketInfo {
61 public:
62 BitMask64 bitmask() const { return bitmask_; }
63
wub1dc01cf2020-01-27 13:04:14 -080064 void Reset() { bitmask_.ClearAll(); }
65
wubcfddec82020-01-13 07:45:27 -080066 bool HasValue(QuicUdpPacketInfoBit bit) const { return bitmask_.IsSet(bit); }
67
68 QuicPacketCount dropped_packets() const {
vasilvv5cef78e2021-01-30 11:11:14 -080069 QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::DROPPED_PACKETS));
wubcfddec82020-01-13 07:45:27 -080070 return dropped_packets_;
71 }
72
73 void SetDroppedPackets(QuicPacketCount dropped_packets) {
74 dropped_packets_ = dropped_packets;
75 bitmask_.Set(QuicUdpPacketInfoBit::DROPPED_PACKETS);
76 }
77
78 const QuicIpAddress& self_v4_ip() const {
vasilvv5cef78e2021-01-30 11:11:14 -080079 QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::V4_SELF_IP));
wubcfddec82020-01-13 07:45:27 -080080 return self_v4_ip_;
81 }
82
83 void SetSelfV4Ip(QuicIpAddress self_v4_ip) {
84 self_v4_ip_ = self_v4_ip;
85 bitmask_.Set(QuicUdpPacketInfoBit::V4_SELF_IP);
86 }
87
88 const QuicIpAddress& self_v6_ip() const {
vasilvv5cef78e2021-01-30 11:11:14 -080089 QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::V6_SELF_IP));
wubcfddec82020-01-13 07:45:27 -080090 return self_v6_ip_;
91 }
92
93 void SetSelfV6Ip(QuicIpAddress self_v6_ip) {
94 self_v6_ip_ = self_v6_ip;
95 bitmask_.Set(QuicUdpPacketInfoBit::V6_SELF_IP);
96 }
97
98 void SetSelfIp(QuicIpAddress self_ip) {
99 if (self_ip.IsIPv4()) {
100 SetSelfV4Ip(self_ip);
101 } else {
102 SetSelfV6Ip(self_ip);
103 }
104 }
105
106 const QuicSocketAddress& peer_address() const {
vasilvv5cef78e2021-01-30 11:11:14 -0800107 QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS));
wubcfddec82020-01-13 07:45:27 -0800108 return peer_address_;
109 }
110
111 void SetPeerAddress(QuicSocketAddress peer_address) {
112 peer_address_ = peer_address;
113 bitmask_.Set(QuicUdpPacketInfoBit::PEER_ADDRESS);
114 }
115
116 QuicWallTime receive_timestamp() const {
vasilvv5cef78e2021-01-30 11:11:14 -0800117 QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::RECV_TIMESTAMP));
wubcfddec82020-01-13 07:45:27 -0800118 return receive_timestamp_;
119 }
120
121 void SetReceiveTimestamp(QuicWallTime receive_timestamp) {
122 receive_timestamp_ = receive_timestamp;
123 bitmask_.Set(QuicUdpPacketInfoBit::RECV_TIMESTAMP);
124 }
125
126 int ttl() const {
vasilvv5cef78e2021-01-30 11:11:14 -0800127 QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::TTL));
wubcfddec82020-01-13 07:45:27 -0800128 return ttl_;
129 }
130
131 void SetTtl(int ttl) {
132 ttl_ = ttl;
133 bitmask_.Set(QuicUdpPacketInfoBit::TTL);
134 }
135
wub1dc01cf2020-01-27 13:04:14 -0800136 BufferSpan google_packet_headers() const {
vasilvv5cef78e2021-01-30 11:11:14 -0800137 QUICHE_DCHECK(HasValue(QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER));
wub1dc01cf2020-01-27 13:04:14 -0800138 return google_packet_headers_;
139 }
140
wubcfddec82020-01-13 07:45:27 -0800141 void SetGooglePacketHeaders(BufferSpan google_packet_headers) {
142 google_packet_headers_ = google_packet_headers;
143 bitmask_.Set(QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER);
144 }
145
146 private:
147 BitMask64 bitmask_;
148 QuicPacketCount dropped_packets_;
149 QuicIpAddress self_v4_ip_;
150 QuicIpAddress self_v6_ip_;
151 QuicSocketAddress peer_address_;
152 QuicWallTime receive_timestamp_ = QuicWallTime::Zero();
153 int ttl_;
154 BufferSpan google_packet_headers_;
155};
156
157// QuicUdpSocketApi provides a minimal set of apis for sending and receiving
158// udp packets. The low level udp socket apis differ between kernels and kernel
159// versions, the goal of QuicUdpSocketApi is to hide such differences.
160// We use non-static functions because it is easier to be mocked in tests when
161// needed.
162class QUIC_EXPORT_PRIVATE QuicUdpSocketApi {
163 public:
164 // Creates a non-blocking udp socket, sets the receive/send buffer and enable
165 // receiving of self ip addresses on read.
QUICHE team82d5e872020-05-28 15:20:20 -0700166 // If address_family == AF_INET6 and ipv6_only is true, receiving of IPv4 self
167 // addresses is disabled. This is only necessary for IPv6 sockets on iOS - all
168 // other platforms can ignore this parameter. Return kQuicInvalidSocketFd if
169 // failed.
wubcfddec82020-01-13 07:45:27 -0800170 QuicUdpSocketFd Create(int address_family,
171 int receive_buffer_size,
QUICHE team82d5e872020-05-28 15:20:20 -0700172 int send_buffer_size,
173 bool ipv6_only = false);
wubcfddec82020-01-13 07:45:27 -0800174
175 // Closes |fd|. No-op if |fd| equals to kQuicInvalidSocketFd.
176 void Destroy(QuicUdpSocketFd fd);
177
178 // Bind |fd| to |address|. If |address|'s port number is 0, kernel will choose
179 // a random port to bind to. Caller can use QuicSocketAddress::FromSocket(fd)
180 // to get the bound random port.
181 bool Bind(QuicUdpSocketFd fd, QuicSocketAddress address);
182
183 // Enable receiving of various per-packet information. Return true if the
184 // corresponding information can be received on read.
185 bool EnableDroppedPacketCount(QuicUdpSocketFd fd);
186 bool EnableReceiveTimestamp(QuicUdpSocketFd fd);
187 bool EnableReceiveTtlForV4(QuicUdpSocketFd fd);
188 bool EnableReceiveTtlForV6(QuicUdpSocketFd fd);
189
190 // Wait for |fd| to become readable, up to |timeout|.
191 // Return true if |fd| is readable upon return.
192 bool WaitUntilReadable(QuicUdpSocketFd fd, QuicTime::Delta timeout);
193
194 struct QUIC_EXPORT_PRIVATE ReadPacketResult {
195 bool ok = false;
196 QuicUdpPacketInfo packet_info;
197 BufferSpan packet_buffer;
198 BufferSpan control_buffer;
wub1dc01cf2020-01-27 13:04:14 -0800199
200 void Reset(size_t packet_buffer_length) {
201 ok = false;
202 packet_info.Reset();
203 packet_buffer.buffer_len = packet_buffer_length;
204 }
wubcfddec82020-01-13 07:45:27 -0800205 };
206 // Read a packet from |fd|:
207 // packet_info_interested: Bitmask indicating what information caller wants to
208 // receive into |result->packet_info|.
209 // result->packet_info: Received per packet information.
210 // result->packet_buffer: The packet buffer, to be filled with packet data.
wub1dc01cf2020-01-27 13:04:14 -0800211 // |result->packet_buffer.buffer_len| is set to the
212 // packet length on a successful return.
wubcfddec82020-01-13 07:45:27 -0800213 // result->control_buffer: The control buffer, used by ReadPacket internally.
wuba27a3c92020-01-28 08:43:21 -0800214 // It is recommended to be
215 // |kDefaultUdpPacketControlBufferSize| bytes.
wubcfddec82020-01-13 07:45:27 -0800216 // result->ok: True iff a packet is successfully received.
wub1dc01cf2020-01-27 13:04:14 -0800217 //
218 // If |*result| is reused for subsequent ReadPacket() calls, caller needs to
219 // call result->Reset() before each ReadPacket().
wubcfddec82020-01-13 07:45:27 -0800220 void ReadPacket(QuicUdpSocketFd fd,
221 BitMask64 packet_info_interested,
222 ReadPacketResult* result);
223
224 using ReadPacketResults = std::vector<ReadPacketResult>;
225 // Read up to |results->size()| packets from |fd|. The meaning of each element
226 // in |*results| has been documented on top of |ReadPacket|.
wub77cd0a32020-01-21 12:53:24 -0800227 // Return the number of elements populated into |*results|, note it is
228 // possible for some of the populated elements to have ok=false.
wubcfddec82020-01-13 07:45:27 -0800229 size_t ReadMultiplePackets(QuicUdpSocketFd fd,
230 BitMask64 packet_info_interested,
231 ReadPacketResults* results);
232
233 // Write a packet to |fd|.
234 // packet_buffer, packet_buffer_len: The packet buffer to write.
235 // packet_info: The per packet information to set.
236 WriteResult WritePacket(QuicUdpSocketFd fd,
237 const char* packet_buffer,
238 size_t packet_buffer_len,
239 const QuicUdpPacketInfo& packet_info);
240
241 protected:
242 bool SetupSocket(QuicUdpSocketFd fd,
243 int address_family,
244 int receive_buffer_size,
QUICHE team82d5e872020-05-28 15:20:20 -0700245 int send_buffer_size,
246 bool ipv6_only);
wubcfddec82020-01-13 07:45:27 -0800247 bool EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd);
248 bool EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd);
249};
250
251} // namespace quic
252
253#endif // QUICHE_QUIC_CORE_QUIC_UDP_SOCKET_H_