@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.
Files changed (70) hide show
  1. package/CMakeLists.txt +42 -111
  2. package/build.js +4 -4
  3. package/dist/lib/dom.d.ts +6 -0
  4. package/dist/lib/dom.d.ts.map +1 -1
  5. package/dist/lib/event-loop.d.ts +8 -3
  6. package/dist/lib/event-loop.d.ts.map +1 -1
  7. package/dist/lib/server.d.ts +3 -2
  8. package/dist/lib/server.d.ts.map +1 -1
  9. package/dist/lib/session.d.ts +78 -18
  10. package/dist/lib/session.d.ts.map +1 -1
  11. package/dist/lib/stream.d.ts +13 -5
  12. package/dist/lib/stream.d.ts.map +1 -1
  13. package/dist/lib/transport.d.ts.map +1 -1
  14. package/dist/lib/types.d.ts +11 -2
  15. package/dist/lib/types.d.ts.map +1 -1
  16. package/dist/lib/webtransport.d.ts +22 -0
  17. package/dist/lib/webtransport.d.ts.map +1 -1
  18. package/dist/test/bidirectional-streams.spec.d.ts.map +1 -1
  19. package/dist/test/datagrams.spec.d.ts.map +1 -1
  20. package/dist/test/fixtures/p-timeout.d.ts +8 -0
  21. package/dist/test/fixtures/p-timeout.d.ts.map +1 -0
  22. package/dist/test/fixtures/read-stream.d.ts.map +1 -1
  23. package/dist/test/unidirectional-streams.spec.d.ts.map +1 -1
  24. package/lib/dom.ts +7 -2
  25. package/lib/event-loop.js +13 -7
  26. package/lib/server.js +1 -1
  27. package/lib/session.js +71 -21
  28. package/lib/stream.js +137 -12
  29. package/lib/transport.js +3 -1
  30. package/lib/types.ts +13 -2
  31. package/lib/webtransport.js +31 -0
  32. package/package.json +5 -4
  33. package/platform/base/strings/utf_ostream_operators.h +5 -0
  34. package/platform/quiche/quic/core/io/socket_win.inc +3 -0
  35. package/platform/quiche_platform_impl/quiche_command_line_flags_impl.h +7 -0
  36. package/platform/quiche_platform_impl/quiche_export_impl.h +3 -9
  37. package/platform/quiche_platform_impl/quiche_server_stats_impl.h +1 -22
  38. package/platform/quiche_platform_impl/quiche_stream_buffer_allocator_impl.h +1 -4
  39. package/platform/quiche_platform_impl/quiche_time_utils_impl.h +1 -13
  40. package/platform/quiche_platform_impl/quiche_udp_socket_platform_impl.h +9 -0
  41. package/readme.md +3 -1
  42. package/src/http3client.cc +13 -29
  43. package/src/http3client.h +2 -6
  44. package/src/http3clientsession.cc +51 -40
  45. package/src/http3clientsession.h +44 -31
  46. package/src/http3clientstream.cc +17 -0
  47. package/src/http3clientstream.h +10 -0
  48. package/src/http3eventloop.cc +81 -61
  49. package/src/http3eventloop.h +10 -7
  50. package/src/http3server.cc +1 -1
  51. package/src/http3serversession.cc +1 -136
  52. package/src/http3serversession.h +7 -77
  53. package/src/http3serverstream.cc +0 -49
  54. package/src/http3serverstream.h +0 -5
  55. package/src/http3wtsessionvisitor.cc +1 -1
  56. package/src/http3wtsessionvisitor.h +24 -37
  57. package/src/http3wtstreamvisitor.cc +35 -8
  58. package/src/http3wtstreamvisitor.h +81 -3
  59. package/test/bidirectional-streams.spec.js +16 -7
  60. package/test/datagrams.spec.js +31 -20
  61. package/test/fixtures/p-timeout.js +33 -0
  62. package/test/fixtures/read-stream.js +4 -1
  63. package/test/unidirectional-streams.spec.js +24 -15
  64. package/platform/net/quiche/common/platform/impl/quiche_flags_impl.h +0 -12
  65. package/platform/poll.h +0 -2
  66. package/platform/quiche/quic/core/io/quic_poll_event_loop.h +0 -8
  67. package/platform/quiche_platform_impl/quic_testvalue_impl.h +0 -19
  68. package/platform/quiche_platform_impl/quic_udp_socket_winsock.cc +0 -732
  69. package/platform/quiche_platform_impl/quiche_time_utils_impl.cc +0 -43
  70. 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, &timestamping,
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