@fails-components/webtransport 0.0.6 → 0.0.8
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 +11 -6
- package/package.json +1 -1
- package/platform/quiche_platform_impl/quic_udp_socket_winsock.cc +605 -523
- package/src/http3client.cc +86 -72
- package/src/http3client.h +6 -0
- package/src/http3dispatcher.cc +5 -3
- package/src/http3dispatcher.h +2 -1
- package/src/http3eventloop.cc +53 -37
- package/src/http3eventloop.h +18 -1
- package/src/http3server.cc +47 -10
- package/src/http3server.h +2 -1
- package/src/http3wtstreamvisitor.cc +8 -11
- package/src/webtransport.js +11 -3
- package/test/testsuite.js +8 -8
|
@@ -21,630 +21,712 @@
|
|
|
21
21
|
#if defined(__linux__) && !defined(__ANDROID__)
|
|
22
22
|
#define QUIC_UDP_SOCKET_SUPPORT_TTL 1
|
|
23
23
|
#endif
|
|
24
|
-
namespace quic
|
|
25
|
-
|
|
24
|
+
namespace quic
|
|
25
|
+
{
|
|
26
|
+
namespace
|
|
27
|
+
{
|
|
26
28
|
|
|
27
29
|
#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
|
|
28
30
|
#define QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING 1
|
|
29
|
-
// This is the structure that SO_TIMESTAMPING fills into the cmsg header.
|
|
30
|
-
// It is well-defined, but does not have a definition in a public header.
|
|
31
|
-
// See https://www.kernel.org/doc/Documentation/networking/timestamping.txt
|
|
32
|
-
// for more information.
|
|
33
|
-
struct LinuxSoTimestamping
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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));
|
|
43
46
|
#else
|
|
44
|
-
const size_t kCmsgSpaceForRecvTimestamp = 0;
|
|
47
|
+
const size_t kCmsgSpaceForRecvTimestamp = 0;
|
|
45
48
|
#endif
|
|
46
49
|
|
|
47
|
-
const size_t kMinCmsgSpaceForRead =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
void SetV4SelfIpInControlMessage(const QuicIpAddress&
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
void SetV6SelfIpInControlMessage(const QuicIpAddress& self_address,
|
|
66
|
-
cmsghdr* cmsg) {
|
|
67
|
-
QUICHE_DCHECK(self_address.IsIPv6());
|
|
68
|
-
in6_pktinfo* pktinfo = reinterpret_cast<in6_pktinfo*>(WSA_CMSG_DATA(cmsg));
|
|
69
|
-
memset(pktinfo, 0, sizeof(in6_pktinfo));
|
|
70
|
-
std::string address_string = self_address.ToPackedString();
|
|
71
|
-
memcpy(&pktinfo->ipi6_addr, address_string.c_str(), address_string.length());
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
void PopulatePacketInfoFromControlMessage(struct cmsghdr* cmsg,
|
|
75
|
-
QuicUdpPacketInfo* packet_info,
|
|
76
|
-
BitMask64 packet_info_interested) {
|
|
77
|
-
#if defined(__linux__) && defined(SO_RXQ_OVFL)
|
|
78
|
-
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL) {
|
|
79
|
-
if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::DROPPED_PACKETS)) {
|
|
80
|
-
packet_info->SetDroppedPackets(
|
|
81
|
-
*(reinterpret_cast<uint32_t*> WSA_CMSG_DATA(cmsg)));
|
|
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());
|
|
82
67
|
}
|
|
83
|
-
|
|
84
|
-
|
|
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
|
+
}
|
|
85
93
|
#endif
|
|
86
94
|
|
|
87
95
|
#if defined(QUIC_UDP_SOCKET_SUPPORT_LINUX_TIMESTAMPING)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
+
}
|
|
100
110
|
#endif
|
|
101
111
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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;
|
|
112
130
|
}
|
|
113
|
-
}
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
131
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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;
|
|
127
150
|
}
|
|
128
|
-
}
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
151
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
+
}
|
|
139
161
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
+
}
|
|
147
173
|
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
bool NextCmsg(WSAMSG* hdr, char* control_buffer, size_t control_buffer_len,
|
|
152
|
-
int cmsg_level, int cmsg_type, size_t data_size,
|
|
153
|
-
cmsghdr** cmsg /*in, out*/) {
|
|
154
|
-
// msg_controllen needs to be increased first, otherwise CMSG_NXTHDR will
|
|
155
|
-
// return nullptr.
|
|
156
|
-
hdr->Control.len += CMSG_SPACE(data_size);
|
|
157
|
-
if (hdr->Control.len > control_buffer_len) {
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if ((*cmsg) == nullptr) {
|
|
162
|
-
QUICHE_DCHECK_EQ(nullptr, hdr->Control.buf);
|
|
163
|
-
memset(control_buffer, 0, control_buffer_len);
|
|
164
|
-
hdr->Control.buf = control_buffer;
|
|
165
|
-
(*cmsg) = CMSG_FIRSTHDR(hdr);
|
|
166
|
-
} else {
|
|
167
|
-
QUICHE_DCHECK_NE(nullptr, hdr->Control.buf);
|
|
168
|
-
(*cmsg) = CMSG_NXTHDR(hdr, (*cmsg));
|
|
169
|
-
}
|
|
170
174
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
+
}
|
|
174
186
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
+
}
|
|
178
199
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
200
|
+
if (nullptr == (*cmsg))
|
|
201
|
+
{
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
182
204
|
|
|
205
|
+
(*cmsg)->cmsg_len = CMSG_LEN(data_size);
|
|
206
|
+
(*cmsg)->cmsg_level = cmsg_level;
|
|
207
|
+
(*cmsg)->cmsg_type = cmsg_type;
|
|
183
208
|
|
|
184
|
-
|
|
185
|
-
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
} // namespace
|
|
186
212
|
|
|
187
|
-
|
|
213
|
+
LPFN_WSARECVMSG WSARecvMsg = nullptr;
|
|
214
|
+
LPFN_WSASENDMSG WSASendMsg = nullptr;
|
|
188
215
|
|
|
189
|
-
|
|
190
|
-
{
|
|
191
|
-
int res;
|
|
216
|
+
WSADATA WSAData;
|
|
192
217
|
|
|
193
|
-
|
|
194
|
-
res = WSAStartup(MAKEWORD(2, 2), &WSAData);
|
|
195
|
-
if (res != 0)
|
|
218
|
+
bool initSockets()
|
|
196
219
|
{
|
|
197
|
-
|
|
198
|
-
<< "WSAStartup failed: %d\n"
|
|
199
|
-
<< res;
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
220
|
+
int res;
|
|
202
221
|
|
|
203
|
-
|
|
204
|
-
|
|
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
|
+
}
|
|
205
231
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
DWORD dwBytesReturned = 0;
|
|
209
|
-
if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &grv, sizeof(grv), &WSARecvMsg, sizeof(WSARecvMsg),
|
|
210
|
-
&dwBytesReturned, NULL, NULL) != 0)
|
|
211
|
-
{
|
|
212
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
213
|
-
<< "WSARecvMsg is not available ";
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
232
|
+
SOCKET sock = INVALID_SOCKET;
|
|
233
|
+
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
|
216
234
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
return true;
|
|
228
|
-
}
|
|
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
|
+
}
|
|
229
245
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// on ios/osx because CMSG_SPACE isn't a constant expression there.
|
|
242
|
-
QUICHE_DCHECK_GE(kDefaultUdpPacketControlBufferSize, kMinCmsgSpaceForRead);
|
|
243
|
-
|
|
244
|
-
absl::StatusOr<SocketFd> socket =
|
|
245
|
-
socket_api::CreateSocket(FromPlatformAddressFamily(address_family),
|
|
246
|
-
socket_api::SocketProtocol::kUdp,
|
|
247
|
-
/*blocking=*/false);
|
|
248
|
-
|
|
249
|
-
if (!socket.ok()) {
|
|
250
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
251
|
-
<< "UDP non-blocking socket creation for address_family="
|
|
252
|
-
<< address_family << " failed: " << socket.status();
|
|
253
|
-
return kQuicInvalidSocketFd;
|
|
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;
|
|
254
257
|
}
|
|
255
258
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
Destroy(socket.value());
|
|
261
|
-
return kQuicInvalidSocketFd;
|
|
259
|
+
bool destroySockets()
|
|
260
|
+
{
|
|
261
|
+
WSACleanup();
|
|
262
|
+
return true;
|
|
262
263
|
}
|
|
263
264
|
|
|
264
|
-
|
|
265
|
-
|
|
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
|
+
}
|
|
266
286
|
|
|
267
|
-
|
|
268
|
-
int receive_buffer_size,
|
|
269
|
-
int send_buffer_size, bool ipv6_only) {
|
|
270
|
-
// Receive buffer size.
|
|
271
|
-
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>(&receive_buffer_size),
|
|
272
|
-
sizeof(receive_buffer_size)) != 0) {
|
|
273
|
-
QUIC_LOG_FIRST_N(ERROR, 100) << "Failed to set socket recv size";
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
287
|
+
SetGoogleSocketOptions(socket.value());
|
|
276
288
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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();
|
|
282
297
|
}
|
|
283
298
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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";
|
|
288
308
|
return false;
|
|
289
309
|
}
|
|
290
|
-
}
|
|
291
310
|
|
|
292
|
-
|
|
293
|
-
if (
|
|
294
|
-
|
|
295
|
-
|
|
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";
|
|
296
316
|
return false;
|
|
297
317
|
}
|
|
298
|
-
}
|
|
299
318
|
|
|
300
|
-
|
|
301
|
-
|
|
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
|
+
}
|
|
302
328
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
+
}
|
|
309
337
|
}
|
|
338
|
+
|
|
339
|
+
return true;
|
|
310
340
|
}
|
|
311
|
-
}
|
|
312
341
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
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
|
+
}
|
|
319
362
|
|
|
320
|
-
bool QuicUdpSocketApi::EnableDroppedPacketCount(QuicUdpSocketFd fd)
|
|
363
|
+
bool QuicUdpSocketApi::EnableDroppedPacketCount(QuicUdpSocketFd fd)
|
|
364
|
+
{
|
|
321
365
|
#if defined(__linux__) && defined(SO_RXQ_OVFL)
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
366
|
+
int get_overflow = 1;
|
|
367
|
+
return 0 == setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
|
|
368
|
+
sizeof(get_overflow));
|
|
325
369
|
#else
|
|
326
|
-
|
|
327
|
-
|
|
370
|
+
(void)fd;
|
|
371
|
+
return false;
|
|
328
372
|
#endif
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
bool QuicUdpSocketApi::EnableReceiveSelfIpAddressForV4(QuicUdpSocketFd fd)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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
|
+
{
|
|
345
392
|
#if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 21)
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
393
|
+
int timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
|
|
394
|
+
return 0 == setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, ×tamping,
|
|
395
|
+
sizeof(timestamping));
|
|
349
396
|
#else
|
|
350
|
-
|
|
351
|
-
|
|
397
|
+
(void)fd;
|
|
398
|
+
return false;
|
|
352
399
|
#endif
|
|
353
|
-
}
|
|
400
|
+
}
|
|
354
401
|
|
|
355
|
-
bool QuicUdpSocketApi::EnableReceiveTtlForV4(QuicUdpSocketFd fd)
|
|
402
|
+
bool QuicUdpSocketApi::EnableReceiveTtlForV4(QuicUdpSocketFd fd)
|
|
403
|
+
{
|
|
356
404
|
#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
|
|
357
|
-
|
|
358
|
-
|
|
405
|
+
int get_ttl = 1;
|
|
406
|
+
return 0 == setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &get_ttl, sizeof(get_ttl));
|
|
359
407
|
#else
|
|
360
|
-
|
|
361
|
-
|
|
408
|
+
(void)fd;
|
|
409
|
+
return false;
|
|
362
410
|
#endif
|
|
363
|
-
}
|
|
411
|
+
}
|
|
364
412
|
|
|
365
|
-
bool QuicUdpSocketApi::EnableReceiveTtlForV6(QuicUdpSocketFd fd)
|
|
413
|
+
bool QuicUdpSocketApi::EnableReceiveTtlForV6(QuicUdpSocketFd fd)
|
|
414
|
+
{
|
|
366
415
|
#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
416
|
+
int get_ttl = 1;
|
|
417
|
+
return 0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &get_ttl,
|
|
418
|
+
sizeof(get_ttl));
|
|
370
419
|
#else
|
|
371
|
-
|
|
372
|
-
|
|
420
|
+
(void)fd;
|
|
421
|
+
return false;
|
|
373
422
|
#endif
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
bool QuicUdpSocketApi::WaitUntilReadable(QuicUdpSocketFd fd,
|
|
377
|
-
QuicTime::Delta timeout) {
|
|
378
|
-
fd_set read_fds;
|
|
379
|
-
FD_ZERO(&read_fds);
|
|
380
|
-
FD_SET(fd, &read_fds);
|
|
381
|
-
|
|
382
|
-
timeval select_timeout;
|
|
383
|
-
select_timeout.tv_sec = timeout.ToSeconds();
|
|
384
|
-
select_timeout.tv_usec = timeout.ToMicroseconds() % 1000000;
|
|
385
|
-
|
|
386
|
-
return 1 == select(1 + fd, &read_fds, nullptr, nullptr, &select_timeout);
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
void QuicUdpSocketApi::ReadPacket(QuicUdpSocketFd fd,
|
|
390
|
-
BitMask64 packet_info_interested,
|
|
391
|
-
ReadPacketResult* result) {
|
|
392
|
-
result->ok = false;
|
|
393
|
-
BufferSpan& packet_buffer = result->packet_buffer;
|
|
394
|
-
BufferSpan& control_buffer = result->control_buffer;
|
|
395
|
-
QuicUdpPacketInfo* packet_info = &result->packet_info;
|
|
396
|
-
|
|
397
|
-
QUICHE_DCHECK_GE(control_buffer.buffer_len, kMinCmsgSpaceForRead);
|
|
398
|
-
|
|
399
|
-
ULONG bufferlen = packet_buffer.buffer_len;
|
|
400
|
-
WSABUF iov = { bufferlen, const_cast<char*>(packet_buffer.buffer)};
|
|
401
|
-
struct sockaddr_storage raw_peer_address;
|
|
402
|
-
|
|
403
|
-
if (control_buffer.buffer_len > 0) {
|
|
404
|
-
reinterpret_cast<struct cmsghdr*>(control_buffer.buffer)->cmsg_len =
|
|
405
|
-
control_buffer.buffer_len;
|
|
406
423
|
}
|
|
407
424
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
hdr.Control.buf = control_buffer.buffer;
|
|
415
|
-
hdr.Control.len = control_buffer.buffer_len;
|
|
416
|
-
|
|
417
|
-
|
|
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);
|
|
418
431
|
|
|
419
|
-
|
|
432
|
+
timeval select_timeout;
|
|
433
|
+
select_timeout.tv_sec = timeout.ToSeconds();
|
|
434
|
+
select_timeout.tv_usec = timeout.ToMicroseconds() % 1000000;
|
|
420
435
|
|
|
421
|
-
|
|
422
|
-
if (ret == SOCKET_ERROR) {
|
|
423
|
-
const int error_num = WSAGetLastError();
|
|
424
|
-
if (error_num != WSAEWOULDBLOCK) {
|
|
425
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
426
|
-
<< "Error reading packet: " << error_num;
|
|
427
|
-
}
|
|
428
|
-
return;
|
|
436
|
+
return 1 == select(1 + fd, &read_fds, nullptr, nullptr, &select_timeout);
|
|
429
437
|
}
|
|
430
438
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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;
|
|
436
447
|
|
|
437
|
-
|
|
438
|
-
// Normally "bytes_read > packet_buffer.buffer_len" implies the MSG_TRUNC
|
|
439
|
-
// bit is set, but it is not the case if tested with config=android_arm64.
|
|
440
|
-
static_cast<size_t>(bytes_read) > packet_buffer.buffer_len) {
|
|
441
|
-
QUIC_LOG_FIRST_N(WARNING, 100)
|
|
442
|
-
<< "Received truncated QUIC packet: buffer size:"
|
|
443
|
-
<< packet_buffer.buffer_len << " packet size:" << bytes_read;
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
448
|
+
QUICHE_DCHECK_GE(control_buffer.buffer_len, kMinCmsgSpaceForRead);
|
|
446
449
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
450
|
+
ULONG bufferlen = packet_buffer.buffer_len;
|
|
451
|
+
WSABUF iov = {bufferlen, const_cast<char *>(packet_buffer.buffer)};
|
|
452
|
+
struct sockaddr_storage raw_peer_address;
|
|
451
453
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
PopulatePacketInfoFromControlMessage(cmsg, packet_info,
|
|
457
|
-
packet_info_interested);
|
|
458
|
-
if (packet_info->bitmask() == prior_bitmask) {
|
|
459
|
-
QUIC_DLOG(INFO) << "Ignored cmsg_level:" << cmsg->cmsg_level
|
|
460
|
-
<< ", cmsg_type:" << cmsg->cmsg_type;
|
|
461
|
-
}
|
|
454
|
+
if (control_buffer.buffer_len > 0)
|
|
455
|
+
{
|
|
456
|
+
reinterpret_cast<struct cmsghdr *>(control_buffer.buffer)->cmsg_len =
|
|
457
|
+
control_buffer.buffer_len;
|
|
462
458
|
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
result->ok = true;
|
|
466
|
-
}
|
|
467
459
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
TempPerPacketData* packet_data = &packet_data_array[i];
|
|
490
|
-
packet_data->iov.iov_base = (*results)[i].packet_buffer.buffer;
|
|
491
|
-
packet_data->iov.iov_len = (*results)[i].packet_buffer.buffer_len;
|
|
492
|
-
|
|
493
|
-
hdr->msg_name = &packet_data->raw_peer_address;
|
|
494
|
-
hdr->msg_namelen = sizeof(sockaddr_storage);
|
|
495
|
-
hdr->msg_iov = &packet_data->iov;
|
|
496
|
-
hdr->msg_iovlen = 1;
|
|
497
|
-
hdr->msg_flags = 0;
|
|
498
|
-
hdr->msg_control = (*results)[i].control_buffer.buffer;
|
|
499
|
-
hdr->msg_controllen = (*results)[i].control_buffer.buffer_len;
|
|
500
|
-
|
|
501
|
-
QUICHE_DCHECK_GE(hdr->msg_controllen, kMinCmsgSpaceForRead);
|
|
502
|
-
}
|
|
503
|
-
// If MSG_TRUNC is set on Linux, recvmmsg will return the real packet size in
|
|
504
|
-
// |hdrs[i].msg_len| even if packet buffer is too small to receive it.
|
|
505
|
-
int packets_read = recvmmsg(fd, hdrs, results->size(), MSG_TRUNC, nullptr);
|
|
506
|
-
if (packets_read <= 0) {
|
|
507
|
-
const int error_num = errno;
|
|
508
|
-
if (error_num != EAGAIN) {
|
|
509
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
510
|
-
<< "Error reading packets: " << strerror(error_num);
|
|
511
|
-
}
|
|
512
|
-
return 0;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
for (int i = 0; i < packets_read; ++i) {
|
|
516
|
-
if (hdrs[i].msg_len == 0) {
|
|
517
|
-
continue;
|
|
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;
|
|
518
481
|
}
|
|
519
482
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
QUIC_BUG(
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
continue;
|
|
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;
|
|
526
488
|
}
|
|
527
489
|
|
|
528
|
-
if (ABSL_PREDICT_FALSE(hdr.
|
|
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
|
+
{
|
|
529
495
|
QUIC_LOG_FIRST_N(WARNING, 100)
|
|
530
496
|
<< "Received truncated QUIC packet: buffer size:"
|
|
531
|
-
<<
|
|
532
|
-
|
|
533
|
-
continue;
|
|
497
|
+
<< packet_buffer.buffer_len << " packet size:" << bytes_read;
|
|
498
|
+
return;
|
|
534
499
|
}
|
|
535
500
|
|
|
536
|
-
|
|
537
|
-
(
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
if (packet_info_interested.IsSet(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
|
|
541
|
-
packet_info->SetPeerAddress(
|
|
542
|
-
QuicSocketAddress(packet_data_array[i].raw_peer_address));
|
|
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));
|
|
543
505
|
}
|
|
544
506
|
|
|
545
|
-
if (hdr.
|
|
546
|
-
|
|
547
|
-
|
|
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();
|
|
548
513
|
PopulatePacketInfoFromControlMessage(cmsg, packet_info,
|
|
549
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
|
+
}
|
|
550
520
|
}
|
|
551
521
|
}
|
|
522
|
+
|
|
523
|
+
result->ok = true;
|
|
552
524
|
}
|
|
553
|
-
|
|
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;
|
|
554
624
|
#else
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
for (ReadPacketResult& result : *results) {
|
|
560
|
-
ReadPacket(fd, packet_info_interested, &result);
|
|
561
|
-
if (!result.ok && WSAGetLastError() == WSAEWOULDBLOCK) {
|
|
562
|
-
break;
|
|
625
|
+
size_t num_packets = 0;
|
|
626
|
+
for (ReadPacketResult &result : *results)
|
|
627
|
+
{
|
|
628
|
+
result.ok = false;
|
|
563
629
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
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;
|
|
567
640
|
#endif
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
WriteResult QuicUdpSocketApi::WritePacket(
|
|
571
|
-
QuicUdpSocketFd fd, const char* packet_buffer, size_t packet_buffer_len,
|
|
572
|
-
const QuicUdpPacketInfo& packet_info) {
|
|
573
|
-
if (!packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
|
|
574
|
-
return WriteResult(WRITE_STATUS_ERROR, EINVAL);
|
|
575
641
|
}
|
|
576
642
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
packet_info
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
WSAMSG hdr;
|
|
584
|
-
hdr.name = reinterpret_cast<LPSOCKADDR> (&raw_peer_address);
|
|
585
|
-
hdr.namelen = packet_info.peer_address().host().IsIPv4()
|
|
586
|
-
? sizeof(sockaddr_in)
|
|
587
|
-
: sizeof(sockaddr_in6);
|
|
588
|
-
hdr.lpBuffers = &iov;
|
|
589
|
-
hdr.dwBufferCount = 1;
|
|
590
|
-
hdr.dwFlags = 0;
|
|
591
|
-
hdr.Control.buf = nullptr;
|
|
592
|
-
hdr.Control.len = 0;
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
cmsghdr* cmsg = nullptr;
|
|
596
|
-
|
|
597
|
-
// Set self IP.
|
|
598
|
-
if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP) &&
|
|
599
|
-
packet_info.self_v4_ip().IsInitialized()) {
|
|
600
|
-
if (!NextCmsg(&hdr, control_buffer, sizeof(control_buffer), IPPROTO_IP,
|
|
601
|
-
IP_PKTINFO, sizeof(in_pktinfo), &cmsg)) {
|
|
602
|
-
QUIC_LOG_FIRST_N(ERROR, 100)
|
|
603
|
-
<< "Not enough buffer to set self v4 ip address.";
|
|
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
|
+
{
|
|
604
649
|
return WriteResult(WRITE_STATUS_ERROR, EINVAL);
|
|
605
650
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
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);
|
|
614
695
|
}
|
|
615
|
-
SetV6SelfIpInControlMessage(packet_info.self_v6_ip(), cmsg);
|
|
616
|
-
}
|
|
617
696
|
|
|
618
697
|
#if defined(QUIC_UDP_SOCKET_SUPPORT_TTL)
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
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();
|
|
629
712
|
}
|
|
630
|
-
*reinterpret_cast<int*>(WSA_CMSG_DATA(cmsg)) = packet_info.ttl();
|
|
631
|
-
}
|
|
632
713
|
#endif
|
|
633
714
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
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);
|
|
642
730
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
? WRITE_STATUS_BLOCKED
|
|
646
|
-
: WRITE_STATUS_ERROR,
|
|
647
|
-
error);
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
} // namespace quic
|
|
731
|
+
|
|
732
|
+
} // namespace quic
|