@fails-components/webtransport 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +42 -111
- package/build.js +4 -4
- package/dist/lib/dom.d.ts +6 -0
- package/dist/lib/dom.d.ts.map +1 -1
- package/dist/lib/event-loop.d.ts +8 -3
- package/dist/lib/event-loop.d.ts.map +1 -1
- package/dist/lib/server.d.ts +3 -2
- package/dist/lib/server.d.ts.map +1 -1
- package/dist/lib/session.d.ts +78 -18
- package/dist/lib/session.d.ts.map +1 -1
- package/dist/lib/stream.d.ts +13 -5
- package/dist/lib/stream.d.ts.map +1 -1
- package/dist/lib/transport.d.ts.map +1 -1
- package/dist/lib/types.d.ts +11 -2
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/webtransport.d.ts +22 -0
- package/dist/lib/webtransport.d.ts.map +1 -1
- package/dist/test/bidirectional-streams.spec.d.ts.map +1 -1
- package/dist/test/datagrams.spec.d.ts.map +1 -1
- package/dist/test/fixtures/p-timeout.d.ts +8 -0
- package/dist/test/fixtures/p-timeout.d.ts.map +1 -0
- package/dist/test/fixtures/read-stream.d.ts.map +1 -1
- package/dist/test/unidirectional-streams.spec.d.ts.map +1 -1
- package/lib/dom.ts +7 -2
- package/lib/event-loop.js +13 -7
- package/lib/server.js +1 -1
- package/lib/session.js +71 -21
- package/lib/stream.js +137 -12
- package/lib/transport.js +3 -1
- package/lib/types.ts +13 -2
- package/lib/webtransport.js +31 -0
- package/package.json +5 -4
- package/platform/base/strings/utf_ostream_operators.h +5 -0
- package/platform/quiche/quic/core/io/socket_win.inc +3 -0
- package/platform/quiche_platform_impl/quiche_command_line_flags_impl.h +7 -0
- package/platform/quiche_platform_impl/quiche_export_impl.h +3 -9
- package/platform/quiche_platform_impl/quiche_server_stats_impl.h +1 -22
- package/platform/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h +1 -4
- package/platform/quiche_platform_impl/quiche_time_utils_impl.h +1 -13
- package/platform/quiche_platform_impl/quiche_udp_socket_platform_impl.h +9 -0
- package/readme.md +3 -1
- package/src/http3client.cc +13 -29
- package/src/http3client.h +2 -6
- package/src/http3clientsession.cc +51 -40
- package/src/http3clientsession.h +44 -31
- package/src/http3clientstream.cc +17 -0
- package/src/http3clientstream.h +10 -0
- package/src/http3eventloop.cc +81 -61
- package/src/http3eventloop.h +10 -7
- package/src/http3server.cc +1 -1
- package/src/http3serversession.cc +1 -136
- package/src/http3serversession.h +7 -77
- package/src/http3serverstream.cc +0 -49
- package/src/http3serverstream.h +0 -5
- package/src/http3wtsessionvisitor.cc +1 -1
- package/src/http3wtsessionvisitor.h +24 -37
- package/src/http3wtstreamvisitor.cc +35 -8
- package/src/http3wtstreamvisitor.h +81 -3
- package/test/bidirectional-streams.spec.js +16 -7
- package/test/datagrams.spec.js +31 -20
- package/test/fixtures/p-timeout.js +33 -0
- package/test/fixtures/read-stream.js +4 -1
- package/test/unidirectional-streams.spec.js +24 -15
- package/platform/net/quiche/common/platform/impl/quiche_flags_impl.h +0 -12
- package/platform/poll.h +0 -2
- package/platform/quiche/quic/core/io/quic_poll_event_loop.h +0 -8
- package/platform/quiche_platform_impl/quic_testvalue_impl.h +0 -19
- package/platform/quiche_platform_impl/quic_udp_socket_winsock.cc +0 -732
- package/platform/quiche_platform_impl/quiche_time_utils_impl.cc +0 -43
- package/platform/quiche_platform_impl/socket_winsock.cc +0 -535
|
@@ -1,732 +0,0 @@
|
|
|
1
|
-
// Port to Windows Marten Richter
|
|
2
|
-
// taken from quiche
|
|
3
|
-
// Copyright 2019 The Chromium Authors. All rights reserved.
|
|
4
|
-
// Use of this source code is governed by a BSD-style license that can be
|
|
5
|
-
// found in the LICENSE file.
|
|
6
|
-
|
|
7
|
-
#include <winsock2.h>
|
|
8
|
-
#include <ws2tcpip.h>
|
|
9
|
-
#include <mswsock.h>
|
|
10
|
-
// note we left linux stuff in here, in case we need to port them later
|
|
11
|
-
|
|
12
|
-
#include "absl/base/optimization.h"
|
|
13
|
-
#include "quiche/quic/core/io/socket.h"
|
|
14
|
-
#include "quiche/quic/core/quic_udp_socket.h"
|
|
15
|
-
#include "quiche/quic/platform/api/quic_bug_tracker.h"
|
|
16
|
-
#include "quiche/quic/platform/api/quic_ip_address_family.h"
|
|
17
|
-
#include "quiche/quic/platform/api/quic_udp_socket_platform_api.h"
|
|
18
|
-
|
|
19
|
-
#define UCHAR *WSA_CMSG_DATA(LPWSACMSGHDR pcmsg);
|
|
20
|
-
|
|
21
|
-
#if defined(__linux__) && !defined(__ANDROID__)
|
|
22
|
-
#define QUIC_UDP_SOCKET_SUPPORT_TTL 1
|
|
23
|
-
#endif
|
|
24
|
-
namespace quic
|
|
25
|
-
{
|
|
26
|
-
namespace
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
|
|
30
|
-
#define QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING 1
|
|
31
|
-
// This is the structure that SO_TIMESTAMPING fills into the cmsg header.
|
|
32
|
-
// It is well-defined, but does not have a definition in a public header.
|
|
33
|
-
// See https://www.kernel.org/doc/Documentation/networking/timestamping.txt
|
|
34
|
-
// for more information.
|
|
35
|
-
struct LinuxSoTimestamping
|
|
36
|
-
{
|
|
37
|
-
// The converted system time of the timestamp.
|
|
38
|
-
struct timespec systime;
|
|
39
|
-
// Deprecated; serves only as padding.
|
|
40
|
-
struct timespec hwtimetrans;
|
|
41
|
-
// The raw hardware timestamp.
|
|
42
|
-
struct timespec hwtimeraw;
|
|
43
|
-
};
|
|
44
|
-
const size_t kCmsgSpaceForRecvTimestamp =
|
|
45
|
-
CMSG_SPACE(sizeof(LinuxSoTimestamping));
|
|
46
|
-
#else
|
|
47
|
-
const size_t kCmsgSpaceForRecvTimestamp = 0;
|
|
48
|
-
#endif
|
|
49
|
-
|
|
50
|
-
const size_t kMinCmsgSpaceForRead =
|
|
51
|
-
CMSG_SPACE(sizeof(uint32_t)) // Dropped packet count
|
|
52
|
-
+ CMSG_SPACE(sizeof(in_pktinfo)) // V4 Self IP
|
|
53
|
-
+ CMSG_SPACE(sizeof(in6_pktinfo)) // V6 Self IP
|
|
54
|
-
+ kCmsgSpaceForRecvTimestamp + CMSG_SPACE(sizeof(int)) // TTL
|
|
55
|
-
+ kCmsgSpaceForGooglePacketHeader;
|
|
56
|
-
|
|
57
|
-
void SetV4SelfIpInControlMessage(const QuicIpAddress &self_address,
|
|
58
|
-
cmsghdr *cmsg)
|
|
59
|
-
{
|
|
60
|
-
QUICHE_DCHECK(self_address.IsIPv4());
|
|
61
|
-
in_pktinfo *pktinfo = reinterpret_cast<in_pktinfo *>(WSA_CMSG_DATA(cmsg));
|
|
62
|
-
memset(pktinfo, 0, sizeof(in_pktinfo));
|
|
63
|
-
pktinfo->ipi_ifindex = 0;
|
|
64
|
-
std::string address_string = self_address.ToPackedString();
|
|
65
|
-
memcpy(&pktinfo->ipi_addr, address_string.c_str(),
|
|
66
|
-
address_string.length());
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
void SetV6SelfIpInControlMessage(const QuicIpAddress &self_address,
|
|
70
|
-
cmsghdr *cmsg)
|
|
71
|
-
{
|
|
72
|
-
QUICHE_DCHECK(self_address.IsIPv6());
|
|
73
|
-
in6_pktinfo *pktinfo = reinterpret_cast<in6_pktinfo *>(WSA_CMSG_DATA(cmsg));
|
|
74
|
-
memset(pktinfo, 0, sizeof(in6_pktinfo));
|
|
75
|
-
std::string address_string = self_address.ToPackedString();
|
|
76
|
-
memcpy(&pktinfo->ipi6_addr, address_string.c_str(), address_string.length());
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
void PopulatePacketInfoFromControlMessage(struct cmsghdr *cmsg,
|
|
80
|
-
QuicUdpPacketInfo *packet_info,
|
|
81
|
-
BitMask64 packet_info_interested)
|
|
82
|
-
{
|
|
83
|
-
#if defined(__linux__) && defined(SO_RXQ_OVFL)
|
|
84
|
-
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
|
|
85
|
-
{
|
|
86
|
-
if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::DROPPED_PACKETS))
|
|
87
|
-
{
|
|
88
|
-
packet_info->SetDroppedPackets(
|
|
89
|
-
*(reinterpret_cast<uint32_t *> WSA_CMSG_DATA(cmsg)));
|
|
90
|
-
}
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
#endif
|
|
94
|
-
|
|
95
|
-
#if defined(QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING)
|
|
96
|
-
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING)
|
|
97
|
-
{
|
|
98
|
-
if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::RECV_TIMESTAMP))
|
|
99
|
-
{
|
|
100
|
-
LinuxSoTimestamping *linux_ts =
|
|
101
|
-
reinterpret_cast<LinuxSoTimestamping *>(WSA_CMSG_DATA(cmsg));
|
|
102
|
-
timespec *ts = &linux_ts->systime;
|
|
103
|
-
int64_t usec = (static_cast<int64_t>(ts->tv_sec) * 1000 * 1000) +
|
|
104
|
-
(static_cast<int64_t>(ts->tv_nsec) / 1000);
|
|
105
|
-
packet_info->SetReceiveTimestamp(
|
|
106
|
-
QuicWallTime::FromUNIXMicroseconds(usec));
|
|
107
|
-
}
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
#endif
|
|
111
|
-
|
|
112
|
-
if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO)
|
|
113
|
-
{
|
|
114
|
-
if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V6_SELF_IP))
|
|
115
|
-
{
|
|
116
|
-
const in6_pktinfo *info = reinterpret_cast<in6_pktinfo *>(WSA_CMSG_DATA(cmsg));
|
|
117
|
-
const char *addr_data = reinterpret_cast<const char *>(&info->ipi6_addr);
|
|
118
|
-
int addr_len = sizeof(in6_addr);
|
|
119
|
-
QuicIpAddress self_v6_ip;
|
|
120
|
-
if (self_v6_ip.FromPackedString(addr_data, addr_len))
|
|
121
|
-
{
|
|
122
|
-
packet_info->SetSelfV6Ip(self_v6_ip);
|
|
123
|
-
}
|
|
124
|
-
else
|
|
125
|
-
{
|
|
126
|
-
QUIC_BUG(quic_bug_10751_1) << "QuicIpAddress::FromPackedString failed";
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
|
|
133
|
-
{
|
|
134
|
-
if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::V4_SELF_IP))
|
|
135
|
-
{
|
|
136
|
-
const in_pktinfo *info = reinterpret_cast<in_pktinfo *>(WSA_CMSG_DATA(cmsg));
|
|
137
|
-
const char *addr_data = reinterpret_cast<const char *>(&info->ipi_addr);
|
|
138
|
-
int addr_len = sizeof(in_addr);
|
|
139
|
-
QuicIpAddress self_v4_ip;
|
|
140
|
-
if (self_v4_ip.FromPackedString(addr_data, addr_len))
|
|
141
|
-
{
|
|
142
|
-
packet_info->SetSelfV4Ip(self_v4_ip);
|
|
143
|
-
}
|
|
144
|
-
else
|
|
145
|
-
{
|
|
146
|
-
QUIC_BUG(quic_bug_10751_2) << "QuicIpAddress::FromPackedString failed";
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TTL) ||
|
|
153
|
-
(cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT))
|
|
154
|
-
{
|
|
155
|
-
if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::TTL))
|
|
156
|
-
{
|
|
157
|
-
packet_info->SetTtl(*(reinterpret_cast<int *>(WSA_CMSG_DATA(cmsg))));
|
|
158
|
-
}
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (packet_info_interested.IsSet(
|
|
163
|
-
QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER))
|
|
164
|
-
{
|
|
165
|
-
BufferSpan google_packet_headers;
|
|
166
|
-
if (GetGooglePacketHeadersFromControlMessage(
|
|
167
|
-
cmsg, &google_packet_headers.buffer,
|
|
168
|
-
&google_packet_headers.buffer_len))
|
|
169
|
-
{
|
|
170
|
-
packet_info->SetGooglePacketHeaders(google_packet_headers);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
bool NextCmsg(WSAMSG *hdr, char *control_buffer, size_t control_buffer_len,
|
|
176
|
-
int cmsg_level, int cmsg_type, size_t data_size,
|
|
177
|
-
cmsghdr **cmsg /*in, out*/)
|
|
178
|
-
{
|
|
179
|
-
// msg_controllen needs to be increased first, otherwise CMSG_NXTHDR will
|
|
180
|
-
// return nullptr.
|
|
181
|
-
hdr->Control.len += CMSG_SPACE(data_size);
|
|
182
|
-
if (hdr->Control.len > control_buffer_len)
|
|
183
|
-
{
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if ((*cmsg) == nullptr)
|
|
188
|
-
{
|
|
189
|
-
QUICHE_DCHECK_EQ(nullptr, hdr->Control.buf);
|
|
190
|
-
memset(control_buffer, 0, control_buffer_len);
|
|
191
|
-
hdr->Control.buf = control_buffer;
|
|
192
|
-
(*cmsg) = CMSG_FIRSTHDR(hdr);
|
|
193
|
-
}
|
|
194
|
-
else
|
|
195
|
-
{
|
|
196
|
-
QUICHE_DCHECK_NE(nullptr, hdr->Control.buf);
|
|
197
|
-
(*cmsg) = CMSG_NXTHDR(hdr, (*cmsg));
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (nullptr == (*cmsg))
|
|
201
|
-
{
|
|
202
|
-
return false;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
(*cmsg)->cmsg_len = CMSG_LEN(data_size);
|
|
206
|
-
(*cmsg)->cmsg_level = cmsg_level;
|
|
207
|
-
(*cmsg)->cmsg_type = cmsg_type;
|
|
208
|
-
|
|
209
|
-
return true;
|
|
210
|
-
}
|
|
211
|
-
} // namespace
|
|
212
|
-
|
|
213
|
-
LPFN_WSARECVMSG WSARecvMsg = nullptr;
|
|
214
|
-
LPFN_WSASENDMSG WSASendMsg = nullptr;
|
|
215
|
-
|
|
216
|
-
WSADATA WSAData;
|
|
217
|
-
|
|
218
|
-
bool initSockets()
|
|
219
|
-
{
|
|
220
|
-
int res;
|
|
221
|
-
|
|
222
|
-
// Initialize Winsock
|
|
223
|
-
res = WSAStartup(MAKEWORD(2, 2), &WSAData);
|
|
224
|
-
if (res != 0)
|
|
225
|
-
{
|
|
226
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
227
|
-
<< "WSAStartup failed: %d\n"
|
|
228
|
-
<< res;
|
|
229
|
-
return false;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
SOCKET sock = INVALID_SOCKET;
|
|
233
|
-
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
|
234
|
-
|
|
235
|
-
// should we buffer this somewhere? Does it take time...
|
|
236
|
-
GUID grv = WSAID_WSARECVMSG;
|
|
237
|
-
DWORD dwBytesReturned = 0;
|
|
238
|
-
if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &grv, sizeof(grv), &WSARecvMsg, sizeof(WSARecvMsg),
|
|
239
|
-
&dwBytesReturned, NULL, NULL) != 0)
|
|
240
|
-
{
|
|
241
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
242
|
-
<< "WSARecvMsg is not available ";
|
|
243
|
-
return false;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// should we buffer this somewhere? Does it take time...
|
|
247
|
-
GUID gsnd = WSAID_WSASENDMSG;
|
|
248
|
-
if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &gsnd, sizeof(gsnd), &WSASendMsg, sizeof(WSASendMsg),
|
|
249
|
-
&dwBytesReturned, NULL, NULL) != 0)
|
|
250
|
-
{
|
|
251
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
252
|
-
<< "WSASendMsg is not available ";
|
|
253
|
-
return false;
|
|
254
|
-
}
|
|
255
|
-
closesocket(sock);
|
|
256
|
-
return true;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
bool destroySockets()
|
|
260
|
-
{
|
|
261
|
-
WSACleanup();
|
|
262
|
-
return true;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
QuicUdpSocketFd QuicUdpSocketApi::Create(int address_family,
|
|
266
|
-
int receive_buffer_size,
|
|
267
|
-
int send_buffer_size, bool ipv6_only)
|
|
268
|
-
{
|
|
269
|
-
// QUICHE_DCHECK here so the program exits early(before reading packets) in
|
|
270
|
-
// debug mode. This should have been a static_assert, however it can't be done
|
|
271
|
-
// on ios/osx because CMSG_SPACE isn't a constant expression there.
|
|
272
|
-
QUICHE_DCHECK_GE(kDefaultUdpPacketControlBufferSize, kMinCmsgSpaceForRead);
|
|
273
|
-
|
|
274
|
-
absl::StatusOr<SocketFd> socket =
|
|
275
|
-
socket_api::CreateSocket(quiche::FromPlatformAddressFamily(address_family),
|
|
276
|
-
socket_api::SocketProtocol::kUdp,
|
|
277
|
-
/*blocking=*/false);
|
|
278
|
-
|
|
279
|
-
if (!socket.ok())
|
|
280
|
-
{
|
|
281
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
282
|
-
<< "UDP non-blocking socket creation for address_family="
|
|
283
|
-
<< address_family << " failed: " << socket.status();
|
|
284
|
-
return kQuicInvalidSocketFd;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
SetGoogleSocketOptions(socket.value());
|
|
288
|
-
|
|
289
|
-
if (!SetupSocket(socket.value(), address_family, receive_buffer_size,
|
|
290
|
-
send_buffer_size, ipv6_only))
|
|
291
|
-
{
|
|
292
|
-
Destroy(socket.value());
|
|
293
|
-
return kQuicInvalidSocketFd;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
return socket.value();
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
bool QuicUdpSocketApi::SetupSocket(QuicUdpSocketFd fd, int address_family,
|
|
300
|
-
int receive_buffer_size,
|
|
301
|
-
int send_buffer_size, bool ipv6_only)
|
|
302
|
-
{
|
|
303
|
-
// Receive buffer size.
|
|
304
|
-
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char *>(&receive_buffer_size),
|
|
305
|
-
sizeof(receive_buffer_size)) != 0)
|
|
306
|
-
{
|
|
307
|
-
QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to set socket recv size";
|
|
308
|
-
return false;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// Send buffer size.
|
|
312
|
-
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char *>(&send_buffer_size),
|
|
313
|
-
sizeof(send_buffer_size)) != 0)
|
|
314
|
-
{
|
|
315
|
-
QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to set socket send size";
|
|
316
|
-
return false;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
if (!(address_family == AF_INET6 && ipv6_only))
|
|
320
|
-
{
|
|
321
|
-
if (!EnableReceiveSelfIpAddressForV4(fd))
|
|
322
|
-
{
|
|
323
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
324
|
-
<< "Failed to enable receiving of self v4 ip";
|
|
325
|
-
return false;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
if (address_family == AF_INET6)
|
|
330
|
-
{
|
|
331
|
-
if (!EnableReceiveSelfIpAddressForV6(fd))
|
|
332
|
-
{
|
|
333
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
334
|
-
<< "Failed to enable receiving of self v6 ip";
|
|
335
|
-
return false;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
return true;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
void QuicUdpSocketApi::Destroy(QuicUdpSocketFd fd)
|
|
343
|
-
{
|
|
344
|
-
if (fd != kQuicInvalidSocketFd)
|
|
345
|
-
{
|
|
346
|
-
absl::Status result = socket_api::Close(fd);
|
|
347
|
-
if (!result.ok())
|
|
348
|
-
{
|
|
349
|
-
QUIC_LOG_FIRST_N(WARNING, 100)
|
|
350
|
-
<< "Failed to close UDP socket with error " << result;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
bool QuicUdpSocketApi::Bind(QuicUdpSocketFd fd, QuicSocketAddress address)
|
|
356
|
-
{
|
|
357
|
-
sockaddr_storage addr = address.generic_address();
|
|
358
|
-
int addr_len =
|
|
359
|
-
address.host().IsIPv4() ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
|
|
360
|
-
return 0 == bind(fd, reinterpret_cast<sockaddr *>(&addr), addr_len);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
bool QuicUdpSocketApi::EnableDroppedPacketCount(QuicUdpSocketFd fd)
|
|
364
|
-
{
|
|
365
|
-
#if defined(__linux__) && defined(SO_RXQ_OVFL)
|
|
366
|
-
int get_overflow = 1;
|
|
367
|
-
return 0 == setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
|
|
368
|
-
sizeof(get_overflow));
|
|
369
|
-
#else
|
|
370
|
-
(void)fd;
|
|
371
|
-
return false;
|
|
372
|
-
#endif
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd)
|
|
376
|
-
{
|
|
377
|
-
int get_self_ip = 1;
|
|
378
|
-
return 0 == setsockopt(fd, IPPROTO_IP, IP_PKTINFO, reinterpret_cast<const char *>(&get_self_ip),
|
|
379
|
-
sizeof(get_self_ip));
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV6(QuicUdpSocketFd fd)
|
|
383
|
-
{
|
|
384
|
-
int get_self_ip = 1;
|
|
385
|
-
// was IPV6_RECVPKTINFO
|
|
386
|
-
return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, reinterpret_cast<const char *>(&get_self_ip),
|
|
387
|
-
sizeof(get_self_ip));
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
bool QuicUdpSocketApi::EnableReceiveTimestamp(QuicUdpSocketFd fd)
|
|
391
|
-
{
|
|
392
|
-
#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
|
|
393
|
-
int timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
|
|
394
|
-
return 0 == setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, ×tamping,
|
|
395
|
-
sizeof(timestamping));
|
|
396
|
-
#else
|
|
397
|
-
(void)fd;
|
|
398
|
-
return false;
|
|
399
|
-
#endif
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
bool QuicUdpSocketApi::EnableReceiveTtlForV4(QuicUdpSocketFd fd)
|
|
403
|
-
{
|
|
404
|
-
#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
|
|
405
|
-
int get_ttl = 1;
|
|
406
|
-
return 0 == setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &get_ttl, sizeof(get_ttl));
|
|
407
|
-
#else
|
|
408
|
-
(void)fd;
|
|
409
|
-
return false;
|
|
410
|
-
#endif
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
bool QuicUdpSocketApi::EnableReceiveTtlForV6(QuicUdpSocketFd fd)
|
|
414
|
-
{
|
|
415
|
-
#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
|
|
416
|
-
int get_ttl = 1;
|
|
417
|
-
return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &get_ttl,
|
|
418
|
-
sizeof(get_ttl));
|
|
419
|
-
#else
|
|
420
|
-
(void)fd;
|
|
421
|
-
return false;
|
|
422
|
-
#endif
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
bool QuicUdpSocketApi::WaitUntilReadable(QuicUdpSocketFd fd,
|
|
426
|
-
QuicTime::Delta timeout)
|
|
427
|
-
{
|
|
428
|
-
fd_set read_fds;
|
|
429
|
-
FD_ZERO(&read_fds);
|
|
430
|
-
FD_SET(fd, &read_fds);
|
|
431
|
-
|
|
432
|
-
timeval select_timeout;
|
|
433
|
-
select_timeout.tv_sec = timeout.ToSeconds();
|
|
434
|
-
select_timeout.tv_usec = timeout.ToMicroseconds() % 1000000;
|
|
435
|
-
|
|
436
|
-
return 1 == select(1 + fd, &read_fds, nullptr, nullptr, &select_timeout);
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
void QuicUdpSocketApi::ReadPacket(QuicUdpSocketFd fd,
|
|
440
|
-
BitMask64 packet_info_interested,
|
|
441
|
-
ReadPacketResult *result)
|
|
442
|
-
{
|
|
443
|
-
result->ok = false;
|
|
444
|
-
BufferSpan &packet_buffer = result->packet_buffer;
|
|
445
|
-
BufferSpan &control_buffer = result->control_buffer;
|
|
446
|
-
QuicUdpPacketInfo *packet_info = &result->packet_info;
|
|
447
|
-
|
|
448
|
-
QUICHE_DCHECK_GE(control_buffer.buffer_len, kMinCmsgSpaceForRead);
|
|
449
|
-
|
|
450
|
-
ULONG bufferlen = packet_buffer.buffer_len;
|
|
451
|
-
WSABUF iov = {bufferlen, const_cast<char *>(packet_buffer.buffer)};
|
|
452
|
-
struct sockaddr_storage raw_peer_address;
|
|
453
|
-
|
|
454
|
-
if (control_buffer.buffer_len > 0)
|
|
455
|
-
{
|
|
456
|
-
reinterpret_cast<struct cmsghdr *>(control_buffer.buffer)->cmsg_len =
|
|
457
|
-
control_buffer.buffer_len;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
WSAMSG hdr;
|
|
461
|
-
hdr.name = reinterpret_cast<LPSOCKADDR>(&raw_peer_address);
|
|
462
|
-
hdr.namelen = sizeof(raw_peer_address);
|
|
463
|
-
hdr.lpBuffers = &iov;
|
|
464
|
-
hdr.dwBufferCount = 1;
|
|
465
|
-
hdr.dwFlags = 0;
|
|
466
|
-
hdr.Control.buf = control_buffer.buffer;
|
|
467
|
-
hdr.Control.len = control_buffer.buffer_len;
|
|
468
|
-
|
|
469
|
-
DWORD bytes_read = 0;
|
|
470
|
-
|
|
471
|
-
int ret = WSARecvMsg(fd, &hdr, &bytes_read, nullptr, nullptr);
|
|
472
|
-
if (ret == SOCKET_ERROR)
|
|
473
|
-
{
|
|
474
|
-
const int error_num = WSAGetLastError();
|
|
475
|
-
if (error_num != WSAEWOULDBLOCK)
|
|
476
|
-
{
|
|
477
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
478
|
-
<< "Error reading packet: " << error_num;
|
|
479
|
-
}
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
if (ABSL_PREDICT_FALSE(hdr.dwFlags & MSG_CTRUNC))
|
|
484
|
-
{
|
|
485
|
-
QUIC_BUG(quic_bug_10751_3)
|
|
486
|
-
<< "Control buffer too small. size:" << control_buffer.buffer_len;
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
if (ABSL_PREDICT_FALSE(hdr.dwFlags & MSG_TRUNC) ||
|
|
491
|
-
// Normally "bytes_read > packet_buffer.buffer_len" implies the MSG_TRUNC
|
|
492
|
-
// bit is set, but it is not the case if tested with config=android_arm64.
|
|
493
|
-
static_cast<size_t>(bytes_read) > packet_buffer.buffer_len)
|
|
494
|
-
{
|
|
495
|
-
QUIC_LOG_FIRST_N(WARNING, 100)
|
|
496
|
-
<< "Received truncated QUIC packet: buffer size:"
|
|
497
|
-
<< packet_buffer.buffer_len << " packet size:" << bytes_read;
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
packet_buffer.buffer_len = bytes_read;
|
|
502
|
-
if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::PEER_ADDRESS))
|
|
503
|
-
{
|
|
504
|
-
packet_info->SetPeerAddress(QuicSocketAddress(raw_peer_address));
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
if (hdr.Control.len > 0)
|
|
508
|
-
{
|
|
509
|
-
for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr;
|
|
510
|
-
cmsg = CMSG_NXTHDR(&hdr, cmsg))
|
|
511
|
-
{
|
|
512
|
-
BitMask64 prior_bitmask = packet_info->bitmask();
|
|
513
|
-
PopulatePacketInfoFromControlMessage(cmsg, packet_info,
|
|
514
|
-
packet_info_interested);
|
|
515
|
-
if (packet_info->bitmask() == prior_bitmask)
|
|
516
|
-
{
|
|
517
|
-
QUIC_DLOG(INFO) << "Ignored cmsg_level:" << cmsg->cmsg_level
|
|
518
|
-
<< ", cmsg_type:" << cmsg->cmsg_type;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
result->ok = true;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
size_t QuicUdpSocketApi::ReadMultiplePackets(QuicUdpSocketFd fd,
|
|
527
|
-
BitMask64 packet_info_interested,
|
|
528
|
-
ReadPacketResults *results)
|
|
529
|
-
{
|
|
530
|
-
// Potential TODO WinSock supports similar stuff
|
|
531
|
-
#if defined(__linux__) && !defined(__ANDROID__)
|
|
532
|
-
// Use recvmmsg.
|
|
533
|
-
size_t hdrs_size = sizeof(mmsghdr) * results->size();
|
|
534
|
-
mmsghdr *hdrs = static_cast<mmsghdr *>(alloca(hdrs_size));
|
|
535
|
-
memset(hdrs, 0, hdrs_size);
|
|
536
|
-
|
|
537
|
-
struct TempPerPacketData
|
|
538
|
-
{
|
|
539
|
-
iovec iov;
|
|
540
|
-
sockaddr_storage raw_peer_address;
|
|
541
|
-
};
|
|
542
|
-
TempPerPacketData *packet_data_array = static_cast<TempPerPacketData *>(
|
|
543
|
-
alloca(sizeof(TempPerPacketData) * results->size()));
|
|
544
|
-
|
|
545
|
-
for (size_t i = 0; i < results->size(); ++i)
|
|
546
|
-
{
|
|
547
|
-
(*results)[i].ok = false;
|
|
548
|
-
|
|
549
|
-
msghdr *hdr = &hdrs[i].msg_hdr;
|
|
550
|
-
TempPerPacketData *packet_data = &packet_data_array[i];
|
|
551
|
-
packet_data->iov.iov_base = (*results)[i].packet_buffer.buffer;
|
|
552
|
-
packet_data->iov.iov_len = (*results)[i].packet_buffer.buffer_len;
|
|
553
|
-
|
|
554
|
-
hdr->msg_name = &packet_data->raw_peer_address;
|
|
555
|
-
hdr->msg_namelen = sizeof(sockaddr_storage);
|
|
556
|
-
hdr->msg_iov = &packet_data->iov;
|
|
557
|
-
hdr->msg_iovlen = 1;
|
|
558
|
-
hdr->msg_flags = 0;
|
|
559
|
-
hdr->msg_control = (*results)[i].control_buffer.buffer;
|
|
560
|
-
hdr->msg_controllen = (*results)[i].control_buffer.buffer_len;
|
|
561
|
-
|
|
562
|
-
QUICHE_DCHECK_GE(hdr->msg_controllen, kMinCmsgSpaceForRead);
|
|
563
|
-
}
|
|
564
|
-
// If MSG_TRUNC is set on Linux, recvmmsg will return the real packet size in
|
|
565
|
-
// |hdrs[i].msg_len| even if packet buffer is too small to receive it.
|
|
566
|
-
int packets_read = recvmmsg(fd, hdrs, results->size(), MSG_TRUNC, nullptr);
|
|
567
|
-
if (packets_read <= 0)
|
|
568
|
-
{
|
|
569
|
-
const int error_num = errno;
|
|
570
|
-
if (error_num != EAGAIN)
|
|
571
|
-
{
|
|
572
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
573
|
-
<< "Error reading packets: " << strerror(error_num);
|
|
574
|
-
}
|
|
575
|
-
return 0;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
for (int i = 0; i < packets_read; ++i)
|
|
579
|
-
{
|
|
580
|
-
if (hdrs[i].msg_len == 0)
|
|
581
|
-
{
|
|
582
|
-
continue;
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
msghdr &hdr = hdrs[i].msg_hdr;
|
|
586
|
-
if (ABSL_PREDICT_FALSE(hdr.msg_flags & MSG_CTRUNC))
|
|
587
|
-
{
|
|
588
|
-
QUIC_BUG(quic_bug_10751_4) << "Control buffer too small. size:"
|
|
589
|
-
<< (*results)[i].control_buffer.buffer_len
|
|
590
|
-
<< ", need:" << hdr.msg_controllen;
|
|
591
|
-
continue;
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
if (ABSL_PREDICT_FALSE(hdr.msg_flags & MSG_TRUNC))
|
|
595
|
-
{
|
|
596
|
-
QUIC_LOG_FIRST_N(WARNING, 100)
|
|
597
|
-
<< "Received truncated QUIC packet: buffer size:"
|
|
598
|
-
<< (*results)[i].packet_buffer.buffer_len
|
|
599
|
-
<< " packet size:" << hdrs[i].msg_len;
|
|
600
|
-
continue;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
(*results)[i].ok = true;
|
|
604
|
-
(*results)[i].packet_buffer.buffer_len = hdrs[i].msg_len;
|
|
605
|
-
|
|
606
|
-
QuicUdpPacketInfo *packet_info = &(*results)[i].packet_info;
|
|
607
|
-
if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::PEER_ADDRESS))
|
|
608
|
-
{
|
|
609
|
-
packet_info->SetPeerAddress(
|
|
610
|
-
QuicSocketAddress(packet_data_array[i].raw_peer_address));
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
if (hdr.msg_controllen > 0)
|
|
614
|
-
{
|
|
615
|
-
for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr); cmsg != nullptr;
|
|
616
|
-
cmsg = CMSG_NXTHDR(&hdr, cmsg))
|
|
617
|
-
{
|
|
618
|
-
PopulatePacketInfoFromControlMessage(cmsg, packet_info,
|
|
619
|
-
packet_info_interested);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
return packets_read;
|
|
624
|
-
#else
|
|
625
|
-
size_t num_packets = 0;
|
|
626
|
-
for (ReadPacketResult &result : *results)
|
|
627
|
-
{
|
|
628
|
-
result.ok = false;
|
|
629
|
-
}
|
|
630
|
-
for (ReadPacketResult &result : *results)
|
|
631
|
-
{
|
|
632
|
-
ReadPacket(fd, packet_info_interested, &result);
|
|
633
|
-
if (!result.ok && WSAGetLastError() == WSAEWOULDBLOCK)
|
|
634
|
-
{
|
|
635
|
-
break;
|
|
636
|
-
}
|
|
637
|
-
++num_packets;
|
|
638
|
-
}
|
|
639
|
-
return num_packets;
|
|
640
|
-
#endif
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
WriteResult QuicUdpSocketApi::WritePacket(
|
|
644
|
-
QuicUdpSocketFd fd, const char *packet_buffer, size_t packet_buffer_len,
|
|
645
|
-
const QuicUdpPacketInfo &packet_info)
|
|
646
|
-
{
|
|
647
|
-
if (!packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS))
|
|
648
|
-
{
|
|
649
|
-
return WriteResult(WRITE_STATUS_ERROR, EINVAL);
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
char control_buffer[512];
|
|
653
|
-
sockaddr_storage raw_peer_address =
|
|
654
|
-
packet_info.peer_address().generic_address();
|
|
655
|
-
ULONG bufferlen = packet_buffer_len;
|
|
656
|
-
WSABUF iov = {bufferlen, const_cast<char *>(packet_buffer)};
|
|
657
|
-
|
|
658
|
-
WSAMSG hdr;
|
|
659
|
-
hdr.name = reinterpret_cast<LPSOCKADDR>(&raw_peer_address);
|
|
660
|
-
hdr.namelen = packet_info.peer_address().host().IsIPv4()
|
|
661
|
-
? sizeof(sockaddr_in)
|
|
662
|
-
: sizeof(sockaddr_in6);
|
|
663
|
-
hdr.lpBuffers = &iov;
|
|
664
|
-
hdr.dwBufferCount = 1;
|
|
665
|
-
hdr.dwFlags = 0;
|
|
666
|
-
hdr.Control.buf = nullptr;
|
|
667
|
-
hdr.Control.len = 0;
|
|
668
|
-
|
|
669
|
-
cmsghdr *cmsg = nullptr;
|
|
670
|
-
|
|
671
|
-
// Set self IP.
|
|
672
|
-
if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP) &&
|
|
673
|
-
packet_info.self_v4_ip().IsInitialized())
|
|
674
|
-
{
|
|
675
|
-
if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), IPPROTO_IP,
|
|
676
|
-
IP_PKTINFO, sizeof(in_pktinfo), &cmsg))
|
|
677
|
-
{
|
|
678
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
679
|
-
<< "Not enough buffer to set self v4 ip address.";
|
|
680
|
-
return WriteResult(WRITE_STATUS_ERROR, EINVAL);
|
|
681
|
-
}
|
|
682
|
-
SetV4SelfIpInControlMessage(packet_info.self_v4_ip(), cmsg);
|
|
683
|
-
}
|
|
684
|
-
else if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP) &&
|
|
685
|
-
packet_info.self_v6_ip().IsInitialized())
|
|
686
|
-
{
|
|
687
|
-
if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), IPPROTO_IPV6,
|
|
688
|
-
IPV6_PKTINFO, sizeof(in6_pktinfo), &cmsg))
|
|
689
|
-
{
|
|
690
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
691
|
-
<< "Not enough buffer to set self v6 ip address.";
|
|
692
|
-
return WriteResult(WRITE_STATUS_ERROR, EINVAL);
|
|
693
|
-
}
|
|
694
|
-
SetV6SelfIpInControlMessage(packet_info.self_v6_ip(), cmsg);
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
|
|
698
|
-
// Set ttl.
|
|
699
|
-
if (packet_info.HasValue(QuicUdpPacketInfoBit::TTL))
|
|
700
|
-
{
|
|
701
|
-
int cmsg_level =
|
|
702
|
-
packet_info.peer_address().host().IsIPv4() ? IPPROTO_IP : IPPROTO_IPV6;
|
|
703
|
-
int cmsg_type =
|
|
704
|
-
packet_info.peer_address().host().IsIPv4() ? IP_TTL : IPV6_HOPLIMIT;
|
|
705
|
-
if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), cmsg_level,
|
|
706
|
-
cmsg_type, sizeof(int), &cmsg))
|
|
707
|
-
{
|
|
708
|
-
QUIC_LOG_FIRST_N(ERROR, 100) << "Not enough buffer to set ttl.";
|
|
709
|
-
return WriteResult(WRITE_STATUS_ERROR, EINVAL);
|
|
710
|
-
}
|
|
711
|
-
*reinterpret_cast<int *>(WSA_CMSG_DATA(cmsg)) = packet_info.ttl();
|
|
712
|
-
}
|
|
713
|
-
#endif
|
|
714
|
-
|
|
715
|
-
int rc;
|
|
716
|
-
DWORD bytessend;
|
|
717
|
-
do
|
|
718
|
-
{
|
|
719
|
-
rc = WSASendMsg(fd, &hdr, 0, &bytessend, nullptr, nullptr);
|
|
720
|
-
} while (rc == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
|
|
721
|
-
if (bytessend >= 0)
|
|
722
|
-
{
|
|
723
|
-
return WriteResult(WRITE_STATUS_OK, bytessend);
|
|
724
|
-
}
|
|
725
|
-
int error = WSAGetLastError();
|
|
726
|
-
return WriteResult((error == WSAEWOULDBLOCK)
|
|
727
|
-
? WRITE_STATUS_BLOCKED
|
|
728
|
-
: WRITE_STATUS_ERROR,
|
|
729
|
-
error);
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
} // namespace quic
|