quicsilver 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +9 -1
- data/.github/workflows/cibuildgem.yaml +29 -5
- data/.gitignore +5 -0
- data/CHANGELOG.md +50 -0
- data/Gemfile.lock +8 -1
- data/README.md +128 -15
- data/Rakefile +10 -3
- data/benchmarks/baseline.rb +175 -0
- data/benchmarks/compare.rb +398 -0
- data/benchmarks/helpers.rb +138 -64
- data/benchmarks/latency.rb +128 -0
- data/benchmarks/loss.rb +193 -0
- data/benchmarks/mobile.rb +125 -0
- data/docs/connection_identity.md +141 -0
- data/examples/benchmark.rb +80 -0
- data/examples/connection_pool_demo.rb +1 -1
- data/examples/example_helper.rb +51 -0
- data/examples/feature_demo.rb +7 -7
- data/examples/grpc_style.rb +2 -2
- data/examples/latency_aware_routing.rb +382 -0
- data/examples/lifecycle_drain.rb +264 -0
- data/examples/priorities.rb +2 -2
- data/examples/rails_feature_test.rb +92 -72
- data/examples/server_stats.rb +117 -0
- data/examples/simple_client_test.rb +3 -3
- data/examples/trailers.rb +23 -23
- data/examples/webtransport_smoke.rb +546 -0
- data/examples/worker_load_balancing.rb +425 -0
- data/ext/quicsilver/extconf.rb +100 -15
- data/ext/quicsilver/include/msquic.h +2226 -0
- data/ext/quicsilver/include/msquic_posix.h +696 -0
- data/ext/quicsilver/include/quic_sal_stub.h +314 -0
- data/ext/quicsilver/msquic_patch.rb +68 -0
- data/ext/quicsilver/patches/reliable-reset.patch +723 -0
- data/ext/quicsilver/patches/stream-final-size.patch +47 -0
- data/ext/quicsilver/quicsilver.c +1640 -222
- data/lib/quicsilver/client/client.rb +419 -60
- data/lib/quicsilver/client/connection_pool.rb +122 -26
- data/lib/quicsilver/client/request.rb +106 -14
- data/lib/quicsilver/errors.rb +39 -0
- data/lib/quicsilver/libmsquic.2.dylib +0 -0
- data/lib/quicsilver/protocol/adapter.rb +41 -21
- data/lib/quicsilver/protocol/capsule.rb +38 -0
- data/lib/quicsilver/protocol/connect_stream_decoder.rb +75 -0
- data/lib/quicsilver/protocol/control_stream_parser.rb +12 -1
- data/lib/quicsilver/protocol/datagram.rb +40 -0
- data/lib/quicsilver/protocol/frame_parser.rb +5 -6
- data/lib/quicsilver/protocol/frame_reader.rb +31 -2
- data/lib/quicsilver/protocol/frames.rb +128 -12
- data/lib/quicsilver/protocol/priority.rb +9 -0
- data/lib/quicsilver/protocol/qpack/decoder.rb +4 -42
- data/lib/quicsilver/protocol/qpack/encoder.rb +10 -20
- data/lib/quicsilver/protocol/qpack/huffman.rb +4 -4
- data/lib/quicsilver/protocol/request_encoder.rb +6 -3
- data/lib/quicsilver/protocol/request_parser.rb +16 -2
- data/lib/quicsilver/protocol/response_encoder.rb +18 -8
- data/lib/quicsilver/protocol/response_parser.rb +6 -0
- data/lib/quicsilver/protocol/stream_input.rb +3 -3
- data/lib/quicsilver/protocol/unidirectional_stream.rb +12 -0
- data/lib/quicsilver/protocol/web_transport.rb +214 -0
- data/lib/quicsilver/rack/context.rb +33 -0
- data/lib/quicsilver/response.rb +40 -0
- data/lib/quicsilver/server/rack_adapter.rb +77 -0
- data/lib/quicsilver/server/receive_queue.rb +106 -0
- data/lib/quicsilver/server/request_handler.rb +24 -13
- data/lib/quicsilver/server/request_registry.rb +18 -5
- data/lib/quicsilver/server/scheduler.rb +50 -0
- data/lib/quicsilver/server/schedulers/fiber_scheduler.rb +79 -0
- data/lib/quicsilver/server/schedulers/thread_scheduler.rb +76 -0
- data/lib/quicsilver/server/server.rb +655 -185
- data/lib/quicsilver/server/web_transport_flow_control.rb +270 -0
- data/lib/quicsilver/server/web_transport_manager.rb +281 -0
- data/lib/quicsilver/server/web_transport_registry.rb +40 -0
- data/lib/quicsilver/server/web_transport_session.rb +812 -0
- data/lib/quicsilver/server/web_transport_stream.rb +326 -0
- data/lib/quicsilver/transport/configuration.rb +103 -10
- data/lib/quicsilver/transport/connection.rb +302 -87
- data/lib/quicsilver/transport/connection_stats.rb +53 -0
- data/lib/quicsilver/transport/event_loop.rb +36 -0
- data/lib/quicsilver/transport/inbound_stream.rb +21 -1
- data/lib/quicsilver/transport/stream.rb +18 -3
- data/lib/quicsilver/transport/stream_event.rb +25 -2
- data/lib/quicsilver/transport/stream_id.rb +26 -0
- data/lib/quicsilver/version.rb +1 -1
- data/lib/quicsilver.rb +22 -11
- data/lib/rackup/handler/quicsilver.rb +57 -38
- data/quicsilver.gemspec +10 -3
- metadata +54 -8
- data/benchmarks/concurrent.rb +0 -110
- data/benchmarks/quicsilver_server.rb +0 -46
- data/benchmarks/rails.rb +0 -170
- data/benchmarks/throughput.rb +0 -113
- data/lib/quicsilver/quicsilver.bundle +0 -0
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
/*++
|
|
2
|
+
|
|
3
|
+
Copyright (c) Microsoft Corporation.
|
|
4
|
+
Licensed under the MIT License.
|
|
5
|
+
|
|
6
|
+
Abstract:
|
|
7
|
+
|
|
8
|
+
This file contains the platform specific definitions for MsQuic structures
|
|
9
|
+
and error codes.
|
|
10
|
+
|
|
11
|
+
Environment:
|
|
12
|
+
|
|
13
|
+
POSIX (Linux and macOS)
|
|
14
|
+
|
|
15
|
+
--*/
|
|
16
|
+
|
|
17
|
+
#ifdef _WIN32
|
|
18
|
+
#pragma once
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
#ifndef _MSQUIC_POSIX_
|
|
22
|
+
#define _MSQUIC_POSIX_
|
|
23
|
+
|
|
24
|
+
#include <stdlib.h>
|
|
25
|
+
#include <stdio.h>
|
|
26
|
+
#include <stdint.h>
|
|
27
|
+
#include <sys/types.h>
|
|
28
|
+
#include <string.h>
|
|
29
|
+
#include <assert.h>
|
|
30
|
+
#include <inttypes.h>
|
|
31
|
+
#include <stddef.h>
|
|
32
|
+
#include <netdb.h>
|
|
33
|
+
#include <netinet/ip.h>
|
|
34
|
+
#include <unistd.h>
|
|
35
|
+
#include <sys/socket.h>
|
|
36
|
+
#include <arpa/inet.h>
|
|
37
|
+
#include <netdb.h>
|
|
38
|
+
#include <errno.h>
|
|
39
|
+
#include "quic_sal_stub.h"
|
|
40
|
+
|
|
41
|
+
#define QUIC_INLINE static inline
|
|
42
|
+
|
|
43
|
+
#ifdef __cplusplus
|
|
44
|
+
extern "C++" {
|
|
45
|
+
template <size_t S> struct _ENUM_FLAG_INTEGER_FOR_SIZE;
|
|
46
|
+
template <> struct _ENUM_FLAG_INTEGER_FOR_SIZE<1> {
|
|
47
|
+
typedef uint8_t type;
|
|
48
|
+
};
|
|
49
|
+
template <> struct _ENUM_FLAG_INTEGER_FOR_SIZE<2> {
|
|
50
|
+
typedef uint16_t type;
|
|
51
|
+
};
|
|
52
|
+
template <> struct _ENUM_FLAG_INTEGER_FOR_SIZE<4> {
|
|
53
|
+
typedef uint32_t type;
|
|
54
|
+
};
|
|
55
|
+
template <> struct _ENUM_FLAG_INTEGER_FOR_SIZE<8> {
|
|
56
|
+
typedef uint64_t type;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// used as an approximation of std::underlying_type<T>
|
|
60
|
+
template <class T> struct _ENUM_FLAG_SIZED_INTEGER
|
|
61
|
+
{
|
|
62
|
+
typedef typename _ENUM_FLAG_INTEGER_FOR_SIZE<sizeof(T)>::type type;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) \
|
|
67
|
+
extern "C++" { \
|
|
68
|
+
QUIC_INLINE ENUMTYPE operator | (ENUMTYPE a, ENUMTYPE b) throw() { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) | ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
|
|
69
|
+
QUIC_INLINE ENUMTYPE &operator |= (ENUMTYPE &a, ENUMTYPE b) throw() { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) |= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
|
|
70
|
+
QUIC_INLINE ENUMTYPE operator & (ENUMTYPE a, ENUMTYPE b) throw() { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) & ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
|
|
71
|
+
QUIC_INLINE ENUMTYPE &operator &= (ENUMTYPE &a, ENUMTYPE b) throw() { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) &= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
|
|
72
|
+
QUIC_INLINE ENUMTYPE operator ~ (ENUMTYPE a) throw() { return ENUMTYPE(~((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a)); } \
|
|
73
|
+
QUIC_INLINE ENUMTYPE operator ^ (ENUMTYPE a, ENUMTYPE b) throw() { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) ^ ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
|
|
74
|
+
QUIC_INLINE ENUMTYPE &operator ^= (ENUMTYPE &a, ENUMTYPE b) throw() { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) ^= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
|
|
75
|
+
}
|
|
76
|
+
#else
|
|
77
|
+
#define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) // NOP, C allows these operators.
|
|
78
|
+
#endif
|
|
79
|
+
|
|
80
|
+
#define QUIC_API
|
|
81
|
+
#define QUIC_MAIN_EXPORT
|
|
82
|
+
#define QUIC_STATUS unsigned int
|
|
83
|
+
#ifdef __cplusplus
|
|
84
|
+
#define QUIC_FAILED(X) (static_cast<int>(X) > 0)
|
|
85
|
+
#define QUIC_SUCCEEDED(X) (static_cast<int>(X) <= 0)
|
|
86
|
+
#else
|
|
87
|
+
#define QUIC_FAILED(X) ((int)(X) > 0)
|
|
88
|
+
#define QUIC_SUCCEEDED(X) ((int)(X) <= 0)
|
|
89
|
+
#endif // __cplusplus
|
|
90
|
+
|
|
91
|
+
//
|
|
92
|
+
// The type of an error code generated by the system is mostly 'int'. In most
|
|
93
|
+
// situations, we use the value of a system-generated error code as the value
|
|
94
|
+
// of QUIC_STATUS. In some situations, we use a custom value for QUIC_STATUS.
|
|
95
|
+
// In order to ensure that custom values don't conflict with system-generated
|
|
96
|
+
// values, the custom values are all kept outside the range of any possible
|
|
97
|
+
// 'int' value. There are static asserts to ensure that QUIC_STATUS type is
|
|
98
|
+
// large enough for this purpose.
|
|
99
|
+
//
|
|
100
|
+
|
|
101
|
+
#ifndef ESTRPIPE // undefined on macOS
|
|
102
|
+
#define ESTRPIPE 86
|
|
103
|
+
#endif // ESTRPIPE
|
|
104
|
+
|
|
105
|
+
#ifndef ENOKEY // undefined om macOS
|
|
106
|
+
#define ENOKEY 126
|
|
107
|
+
#endif // ENOKEY
|
|
108
|
+
|
|
109
|
+
#define ERROR_BASE 200000000 // 0xBEBC200
|
|
110
|
+
#define TLS_ERROR_BASE 256 + ERROR_BASE // 0xBEBC300
|
|
111
|
+
#define CERT_ERROR_BASE 512 + ERROR_BASE // 0xBEBC400
|
|
112
|
+
|
|
113
|
+
#ifdef __cplusplus
|
|
114
|
+
#define QUIC_STATUS_DEF(x) (static_cast<QUIC_STATUS>(x))
|
|
115
|
+
#else
|
|
116
|
+
#define QUIC_STATUS_DEF(x) ((QUIC_STATUS)(x))
|
|
117
|
+
#endif
|
|
118
|
+
|
|
119
|
+
#define QUIC_STATUS_SUCCESS QUIC_STATUS_DEF(0) // 0
|
|
120
|
+
#define QUIC_STATUS_PENDING QUIC_STATUS_DEF(-2) // -2
|
|
121
|
+
#define QUIC_STATUS_CONTINUE QUIC_STATUS_DEF(-1) // -1
|
|
122
|
+
#define QUIC_STATUS_OUT_OF_MEMORY QUIC_STATUS_DEF(ENOMEM) // 12
|
|
123
|
+
#define QUIC_STATUS_INVALID_PARAMETER QUIC_STATUS_DEF(EINVAL) // 22
|
|
124
|
+
#define QUIC_STATUS_INVALID_STATE QUIC_STATUS_DEF(EPERM) // 1
|
|
125
|
+
#define QUIC_STATUS_NOT_SUPPORTED QUIC_STATUS_DEF(EOPNOTSUPP) // 95 (102 on macOS)
|
|
126
|
+
#define QUIC_STATUS_NOT_FOUND QUIC_STATUS_DEF(ENOENT) // 2
|
|
127
|
+
#define QUIC_STATUS_FILE_NOT_FOUND QUIC_STATUS_NOT_FOUND // 2
|
|
128
|
+
#define QUIC_STATUS_BUFFER_TOO_SMALL QUIC_STATUS_DEF(EOVERFLOW) // 75 (84 on macOS)
|
|
129
|
+
#define QUIC_STATUS_HANDSHAKE_FAILURE QUIC_STATUS_DEF(ECONNABORTED) // 103 (53 on macOS)
|
|
130
|
+
#define QUIC_STATUS_ABORTED QUIC_STATUS_DEF(ECANCELED) // 125 (89 on macOS)
|
|
131
|
+
#define QUIC_STATUS_ADDRESS_IN_USE QUIC_STATUS_DEF(EADDRINUSE) // 98 (48 on macOS)
|
|
132
|
+
#define QUIC_STATUS_INVALID_ADDRESS QUIC_STATUS_DEF(EAFNOSUPPORT) // 97 (47 on macOS)
|
|
133
|
+
#define QUIC_STATUS_CONNECTION_TIMEOUT QUIC_STATUS_DEF(ETIMEDOUT) // 110 (60 on macOS)
|
|
134
|
+
#define QUIC_STATUS_CONNECTION_IDLE QUIC_STATUS_DEF(ETIME) // 62 (101 on macOS)
|
|
135
|
+
#define QUIC_STATUS_INTERNAL_ERROR QUIC_STATUS_DEF(EIO) // 5
|
|
136
|
+
#define QUIC_STATUS_CONNECTION_REFUSED QUIC_STATUS_DEF(ECONNREFUSED) // 111 (61 on macOS)
|
|
137
|
+
#define QUIC_STATUS_PROTOCOL_ERROR QUIC_STATUS_DEF(EPROTO) // 71 (100 on macOS)
|
|
138
|
+
#define QUIC_STATUS_VER_NEG_ERROR QUIC_STATUS_DEF(EPROTONOSUPPORT) // 93 (43 on macOS)
|
|
139
|
+
#define QUIC_STATUS_UNREACHABLE QUIC_STATUS_DEF(EHOSTUNREACH) // 113 (65 on macOS)
|
|
140
|
+
#define QUIC_STATUS_TLS_ERROR QUIC_STATUS_DEF(ENOKEY) // 126
|
|
141
|
+
#define QUIC_STATUS_USER_CANCELED QUIC_STATUS_DEF(EOWNERDEAD) // 130 (105 on macOS)
|
|
142
|
+
#define QUIC_STATUS_ALPN_NEG_FAILURE QUIC_STATUS_DEF(ENOPROTOOPT) // 92 (42 on macOS)
|
|
143
|
+
#define QUIC_STATUS_STREAM_LIMIT_REACHED QUIC_STATUS_DEF(ESTRPIPE) // 86
|
|
144
|
+
#define QUIC_STATUS_ALPN_IN_USE QUIC_STATUS_DEF(EPROTOTYPE) // 91 (41 on macOS)
|
|
145
|
+
#define QUIC_STATUS_ADDRESS_NOT_AVAILABLE QUIC_STATUS_DEF(EADDRNOTAVAIL) // 99 (47 on macOS)
|
|
146
|
+
|
|
147
|
+
#define QUIC_STATUS_TLS_ALERT(Alert) QUIC_STATUS_DEF((0xff & Alert)+ TLS_ERROR_BASE)
|
|
148
|
+
|
|
149
|
+
#define QUIC_STATUS_CLOSE_NOTIFY QUIC_STATUS_TLS_ALERT(0) // 0xBEBC300 - Close notify
|
|
150
|
+
#define QUIC_STATUS_BAD_CERTIFICATE QUIC_STATUS_TLS_ALERT(42) // 0xBEBC32A - Bad Certificate
|
|
151
|
+
#define QUIC_STATUS_UNSUPPORTED_CERTIFICATE QUIC_STATUS_TLS_ALERT(43) // 0xBEBC32B - Unsupported Certficiate
|
|
152
|
+
#define QUIC_STATUS_REVOKED_CERTIFICATE QUIC_STATUS_TLS_ALERT(44) // 0xBEBC32C - Revoked Certificate
|
|
153
|
+
#define QUIC_STATUS_EXPIRED_CERTIFICATE QUIC_STATUS_TLS_ALERT(45) // 0xBEBC32D - Expired Certificate
|
|
154
|
+
#define QUIC_STATUS_UNKNOWN_CERTIFICATE QUIC_STATUS_TLS_ALERT(46) // 0xBEBC32E - Unknown Certificate
|
|
155
|
+
#define QUIC_STATUS_REQUIRED_CERTIFICATE QUIC_STATUS_TLS_ALERT(116) // 0xBEBC374 - Required Certificate
|
|
156
|
+
|
|
157
|
+
#define QUIC_STATUS_CERT_ERROR(Val) QUIC_STATUS_DEF(Val + CERT_ERROR_BASE)
|
|
158
|
+
|
|
159
|
+
#define QUIC_STATUS_CERT_EXPIRED QUIC_STATUS_CERT_ERROR(1) // 0xBEBC401
|
|
160
|
+
#define QUIC_STATUS_CERT_UNTRUSTED_ROOT QUIC_STATUS_CERT_ERROR(2) // 0xBEBC402
|
|
161
|
+
#define QUIC_STATUS_CERT_NO_CERT QUIC_STATUS_CERT_ERROR(3) // 0xBEBC403
|
|
162
|
+
|
|
163
|
+
typedef unsigned char BOOLEAN;
|
|
164
|
+
typedef struct in_addr IN_ADDR;
|
|
165
|
+
typedef struct in6_addr IN6_ADDR;
|
|
166
|
+
typedef struct addrinfo ADDRINFO;
|
|
167
|
+
typedef sa_family_t QUIC_ADDRESS_FAMILY;
|
|
168
|
+
|
|
169
|
+
#define QUIC_ADDRESS_FAMILY_UNSPEC AF_UNSPEC
|
|
170
|
+
#define QUIC_ADDRESS_FAMILY_INET AF_INET
|
|
171
|
+
#define QUIC_ADDRESS_FAMILY_INET6 AF_INET6
|
|
172
|
+
|
|
173
|
+
typedef union QUIC_ADDR {
|
|
174
|
+
struct sockaddr Ip;
|
|
175
|
+
struct sockaddr_in Ipv4;
|
|
176
|
+
struct sockaddr_in6 Ipv6;
|
|
177
|
+
} QUIC_ADDR;
|
|
178
|
+
|
|
179
|
+
#ifndef RTL_FIELD_SIZE
|
|
180
|
+
#define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
|
|
181
|
+
#endif
|
|
182
|
+
|
|
183
|
+
#define FIELD_OFFSET(type, field) offsetof(type, field)
|
|
184
|
+
|
|
185
|
+
#define QUIC_ADDR_V4_PORT_OFFSET FIELD_OFFSET(struct sockaddr_in, sin_port)
|
|
186
|
+
#define QUIC_ADDR_V4_IP_OFFSET FIELD_OFFSET(struct sockaddr_in, sin_addr)
|
|
187
|
+
|
|
188
|
+
#define QUIC_ADDR_V6_PORT_OFFSET FIELD_OFFSET(struct sockaddr_in6, sin6_port)
|
|
189
|
+
#define QUIC_ADDR_V6_IP_OFFSET FIELD_OFFSET(struct sockaddr_in6, sin6_addr)
|
|
190
|
+
|
|
191
|
+
#ifndef FALSE
|
|
192
|
+
#define FALSE 0
|
|
193
|
+
#define TRUE 1
|
|
194
|
+
#endif
|
|
195
|
+
|
|
196
|
+
#define INITCODE
|
|
197
|
+
#define PAGEDX
|
|
198
|
+
#define QUIC_CACHEALIGN
|
|
199
|
+
|
|
200
|
+
#if defined(__cplusplus)
|
|
201
|
+
extern "C" {
|
|
202
|
+
#endif
|
|
203
|
+
|
|
204
|
+
#if defined(CX_PLATFORM_DARWIN)
|
|
205
|
+
#define QUIC_LOCALHOST_FOR_AF(Af) ("localhost")
|
|
206
|
+
#else
|
|
207
|
+
#define QUIC_LOCALHOST_FOR_AF(Af) ((Af == QUIC_ADDRESS_FAMILY_INET) ? "localhost" : "ip6-localhost")
|
|
208
|
+
#endif
|
|
209
|
+
|
|
210
|
+
#define QUIC_CERTIFICATE_FLAG_IGNORE_REVOCATION 0x00000080
|
|
211
|
+
#define QUIC_CERTIFICATE_FLAG_IGNORE_UNKNOWN_CA 0x00000100
|
|
212
|
+
#define QUIC_CERTIFICATE_FLAG_IGNORE_WRONG_USAGE 0x00000200
|
|
213
|
+
#define QUIC_CERTIFICATE_FLAG_IGNORE_CERTIFICATE_CN_INVALID 0x00001000 // bad common name in X509 Cert.
|
|
214
|
+
#define QUIC_CERTIFICATE_FLAG_IGNORE_CERTIFICATE_DATE_INVALID 0x00002000 // expired X509 Cert.
|
|
215
|
+
#define QUIC_CERTIFICATE_FLAG_IGNORE_WEAK_SIGNATURE 0x00010000
|
|
216
|
+
|
|
217
|
+
#if defined(__clang__)
|
|
218
|
+
#define QUIC_NO_SANITIZE(X) __attribute__((no_sanitize(X)))
|
|
219
|
+
#else
|
|
220
|
+
#define QUIC_NO_SANITIZE(X)
|
|
221
|
+
#endif
|
|
222
|
+
|
|
223
|
+
//
|
|
224
|
+
// Helpers for Windows string functions.
|
|
225
|
+
//
|
|
226
|
+
|
|
227
|
+
#define _strnicmp strncasecmp
|
|
228
|
+
#define sprintf_s(dst, dst_len, format, ...) snprintf(dst, dst_len, format, __VA_ARGS__)
|
|
229
|
+
#define _vsnprintf_s(dst, dst_len, flag, format, ...) vsnprintf(dst, dst_len, format, __VA_ARGS__)
|
|
230
|
+
|
|
231
|
+
//
|
|
232
|
+
// IP Address Abstraction Helpers
|
|
233
|
+
//
|
|
234
|
+
|
|
235
|
+
QUIC_INLINE
|
|
236
|
+
BOOLEAN
|
|
237
|
+
QuicAddrFamilyIsValid(
|
|
238
|
+
_In_ QUIC_ADDRESS_FAMILY Family
|
|
239
|
+
)
|
|
240
|
+
{
|
|
241
|
+
return
|
|
242
|
+
Family == QUIC_ADDRESS_FAMILY_UNSPEC ||
|
|
243
|
+
Family == QUIC_ADDRESS_FAMILY_INET ||
|
|
244
|
+
Family == QUIC_ADDRESS_FAMILY_INET6;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
QUIC_INLINE
|
|
248
|
+
BOOLEAN
|
|
249
|
+
QuicAddrIsValid(
|
|
250
|
+
_In_ const QUIC_ADDR* const Addr
|
|
251
|
+
)
|
|
252
|
+
{
|
|
253
|
+
return QuicAddrFamilyIsValid(Addr->Ip.sa_family);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
QUIC_INLINE
|
|
257
|
+
BOOLEAN
|
|
258
|
+
QuicAddrCompareIp(
|
|
259
|
+
_In_ const QUIC_ADDR* const Addr1,
|
|
260
|
+
_In_ const QUIC_ADDR* const Addr2
|
|
261
|
+
)
|
|
262
|
+
{
|
|
263
|
+
if (QUIC_ADDRESS_FAMILY_INET == Addr1->Ip.sa_family) {
|
|
264
|
+
return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0;
|
|
265
|
+
} else {
|
|
266
|
+
return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
QUIC_INLINE
|
|
271
|
+
BOOLEAN
|
|
272
|
+
QuicAddrCompare(
|
|
273
|
+
_In_ const QUIC_ADDR* const Addr1,
|
|
274
|
+
_In_ const QUIC_ADDR* const Addr2
|
|
275
|
+
)
|
|
276
|
+
{
|
|
277
|
+
if (Addr1->Ip.sa_family != Addr2->Ip.sa_family ||
|
|
278
|
+
Addr1->Ipv4.sin_port != Addr2->Ipv4.sin_port) {
|
|
279
|
+
return FALSE;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (QUIC_ADDRESS_FAMILY_INET == Addr1->Ip.sa_family) {
|
|
283
|
+
return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0;
|
|
284
|
+
} else {
|
|
285
|
+
return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
QUIC_INLINE
|
|
290
|
+
QUIC_ADDRESS_FAMILY
|
|
291
|
+
QuicAddrGetFamily(
|
|
292
|
+
_In_ const QUIC_ADDR* const Addr
|
|
293
|
+
)
|
|
294
|
+
{
|
|
295
|
+
return Addr->Ip.sa_family;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
QUIC_INLINE
|
|
299
|
+
void
|
|
300
|
+
QuicAddrSetFamily(
|
|
301
|
+
_In_ QUIC_ADDR* Addr,
|
|
302
|
+
_In_ QUIC_ADDRESS_FAMILY Family
|
|
303
|
+
)
|
|
304
|
+
{
|
|
305
|
+
Addr->Ip.sa_family = Family;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
QUIC_INLINE
|
|
309
|
+
uint16_t
|
|
310
|
+
QuicAddrGetPort(
|
|
311
|
+
_In_ const QUIC_ADDR* const Addr
|
|
312
|
+
)
|
|
313
|
+
{
|
|
314
|
+
if (QUIC_ADDRESS_FAMILY_INET == Addr->Ip.sa_family) {
|
|
315
|
+
return ntohs(Addr->Ipv4.sin_port);
|
|
316
|
+
} else {
|
|
317
|
+
return ntohs(Addr->Ipv6.sin6_port);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
QUIC_INLINE
|
|
322
|
+
void
|
|
323
|
+
QuicAddrSetPort(
|
|
324
|
+
_Out_ QUIC_ADDR* Addr,
|
|
325
|
+
_In_ uint16_t Port
|
|
326
|
+
)
|
|
327
|
+
{
|
|
328
|
+
if (QUIC_ADDRESS_FAMILY_INET == Addr->Ip.sa_family) {
|
|
329
|
+
Addr->Ipv4.sin_port = htons(Port);
|
|
330
|
+
} else {
|
|
331
|
+
Addr->Ipv6.sin6_port = htons(Port);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
//
|
|
336
|
+
// Test only API to increment the IP address value.
|
|
337
|
+
//
|
|
338
|
+
QUIC_INLINE
|
|
339
|
+
void
|
|
340
|
+
QuicAddrIncrement(
|
|
341
|
+
_Inout_ QUIC_ADDR* Addr
|
|
342
|
+
)
|
|
343
|
+
{
|
|
344
|
+
if (Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_INET) {
|
|
345
|
+
((uint8_t*)&Addr->Ipv4.sin_addr)[3]++;
|
|
346
|
+
} else {
|
|
347
|
+
((uint8_t*)&Addr->Ipv6.sin6_addr)[15]++;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
QUIC_INLINE
|
|
352
|
+
void
|
|
353
|
+
QuicAddrSetToLoopback(
|
|
354
|
+
_Inout_ QUIC_ADDR* Addr
|
|
355
|
+
)
|
|
356
|
+
{
|
|
357
|
+
if (Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_INET) {
|
|
358
|
+
Addr->Ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
359
|
+
} else {
|
|
360
|
+
Addr->Ipv6.sin6_addr = in6addr_loopback;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
QUIC_INLINE
|
|
365
|
+
uint32_t
|
|
366
|
+
QUIC_NO_SANITIZE("unsigned-integer-overflow")
|
|
367
|
+
QuicAddrHash(
|
|
368
|
+
_In_ const QUIC_ADDR* Addr
|
|
369
|
+
)
|
|
370
|
+
{
|
|
371
|
+
uint32_t Hash = 5387; // A random prime number.
|
|
372
|
+
#define UPDATE_HASH(byte) Hash = ((Hash << 5) - Hash) + (byte)
|
|
373
|
+
if (Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_INET) {
|
|
374
|
+
UPDATE_HASH(Addr->Ipv4.sin_port & 0xFF);
|
|
375
|
+
UPDATE_HASH(Addr->Ipv4.sin_port >> 8);
|
|
376
|
+
for (uint8_t i = 0; i < sizeof(Addr->Ipv4.sin_addr); ++i) {
|
|
377
|
+
UPDATE_HASH(((uint8_t*)&Addr->Ipv4.sin_addr)[i]);
|
|
378
|
+
}
|
|
379
|
+
} else {
|
|
380
|
+
UPDATE_HASH(Addr->Ipv6.sin6_port & 0xFF);
|
|
381
|
+
UPDATE_HASH(Addr->Ipv6.sin6_port >> 8);
|
|
382
|
+
for (uint8_t i = 0; i < sizeof(Addr->Ipv6.sin6_addr); ++i) {
|
|
383
|
+
UPDATE_HASH(((uint8_t*)&Addr->Ipv6.sin6_addr)[i]);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return Hash;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
QUIC_INLINE
|
|
390
|
+
BOOLEAN
|
|
391
|
+
QuicAddrIsWildCard(
|
|
392
|
+
_In_ const QUIC_ADDR* const Addr
|
|
393
|
+
)
|
|
394
|
+
{
|
|
395
|
+
if (Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_UNSPEC) {
|
|
396
|
+
return TRUE;
|
|
397
|
+
} else if (Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_INET) {
|
|
398
|
+
const IN_ADDR ZeroAddr = {0};
|
|
399
|
+
return memcmp(&Addr->Ipv4.sin_addr.s_addr, &ZeroAddr, sizeof(IN_ADDR)) == 0;
|
|
400
|
+
} else {
|
|
401
|
+
const IN6_ADDR ZeroAddr = {0};
|
|
402
|
+
return memcmp(&Addr->Ipv6.sin6_addr, &ZeroAddr, sizeof(IN6_ADDR)) == 0;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
QUIC_INLINE
|
|
407
|
+
BOOLEAN
|
|
408
|
+
QuicAddr4FromString(
|
|
409
|
+
_In_z_ const char* AddrStr,
|
|
410
|
+
_Out_ QUIC_ADDR* Addr
|
|
411
|
+
)
|
|
412
|
+
{
|
|
413
|
+
if (AddrStr[0] == '[') {
|
|
414
|
+
return FALSE;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const char* PortStart = strchr(AddrStr, ':');
|
|
418
|
+
if (PortStart != NULL) {
|
|
419
|
+
if (strchr(PortStart+1, ':') != NULL) {
|
|
420
|
+
return FALSE;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
char TmpAddrStr[16];
|
|
424
|
+
size_t AddrLength = PortStart - AddrStr;
|
|
425
|
+
if (AddrLength >= sizeof(TmpAddrStr)) {
|
|
426
|
+
return FALSE;
|
|
427
|
+
}
|
|
428
|
+
memcpy(TmpAddrStr, AddrStr, AddrLength);
|
|
429
|
+
TmpAddrStr[AddrLength] = '\0';
|
|
430
|
+
|
|
431
|
+
if (inet_pton(AF_INET, TmpAddrStr, &Addr->Ipv4.sin_addr) != 1) {
|
|
432
|
+
return FALSE;
|
|
433
|
+
}
|
|
434
|
+
Addr->Ipv4.sin_port = htons(atoi(PortStart+1));
|
|
435
|
+
} else {
|
|
436
|
+
if (inet_pton(AF_INET, AddrStr, &Addr->Ipv4.sin_addr) != 1) {
|
|
437
|
+
return FALSE;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
Addr->Ip.sa_family = QUIC_ADDRESS_FAMILY_INET;
|
|
441
|
+
return TRUE;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
QUIC_INLINE
|
|
445
|
+
BOOLEAN
|
|
446
|
+
QuicAddr6FromString(
|
|
447
|
+
_In_z_ const char* AddrStr,
|
|
448
|
+
_Out_ QUIC_ADDR* Addr
|
|
449
|
+
)
|
|
450
|
+
{
|
|
451
|
+
char TmpAddrStr[64];
|
|
452
|
+
if (AddrStr[0] == '[') {
|
|
453
|
+
const char* BracketEnd = strchr(AddrStr, ']');
|
|
454
|
+
if (BracketEnd == NULL || *(BracketEnd+1) != ':') {
|
|
455
|
+
return FALSE;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const size_t AddrLength = BracketEnd - AddrStr - 1;
|
|
459
|
+
if (AddrLength >= sizeof(TmpAddrStr)) {
|
|
460
|
+
return FALSE;
|
|
461
|
+
}
|
|
462
|
+
memcpy(TmpAddrStr, AddrStr + 1, AddrLength);
|
|
463
|
+
TmpAddrStr[AddrLength] = '\0';
|
|
464
|
+
Addr->Ipv6.sin6_port = htons(atoi(BracketEnd+2));
|
|
465
|
+
} else {
|
|
466
|
+
const size_t AddrLength = strlen(AddrStr);
|
|
467
|
+
if (AddrLength >= sizeof(TmpAddrStr)) {
|
|
468
|
+
return FALSE;
|
|
469
|
+
}
|
|
470
|
+
//
|
|
471
|
+
// Copy the string including the null terminator.
|
|
472
|
+
//
|
|
473
|
+
memcpy(TmpAddrStr, AddrStr, AddrLength + 1);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
Addr->Ipv6.sin6_scope_id = 0;
|
|
477
|
+
char* ScopeStart = strchr(TmpAddrStr, '%');
|
|
478
|
+
if (ScopeStart != NULL) {
|
|
479
|
+
*ScopeStart++ = '\0';
|
|
480
|
+
if (*ScopeStart == '\0') {
|
|
481
|
+
return FALSE;
|
|
482
|
+
}
|
|
483
|
+
do {
|
|
484
|
+
if (*ScopeStart < '0' || *ScopeStart > '9' ||
|
|
485
|
+
Addr->Ipv6.sin6_scope_id > (UINT32_MAX - (*ScopeStart - '0')) / 10) {
|
|
486
|
+
return FALSE;
|
|
487
|
+
}
|
|
488
|
+
Addr->Ipv6.sin6_scope_id =
|
|
489
|
+
Addr->Ipv6.sin6_scope_id * 10 + (uint32_t)(*ScopeStart++ - '0');
|
|
490
|
+
} while (*ScopeStart != '\0');
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (inet_pton(AF_INET6, TmpAddrStr, &Addr->Ipv6.sin6_addr) != 1) {
|
|
494
|
+
return FALSE;
|
|
495
|
+
}
|
|
496
|
+
Addr->Ip.sa_family = QUIC_ADDRESS_FAMILY_INET6;
|
|
497
|
+
return TRUE;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
QUIC_INLINE
|
|
501
|
+
BOOLEAN
|
|
502
|
+
QuicAddrFromString(
|
|
503
|
+
_In_z_ const char* AddrStr,
|
|
504
|
+
_In_ uint16_t Port, // Host byte order
|
|
505
|
+
_Out_ QUIC_ADDR* Addr
|
|
506
|
+
)
|
|
507
|
+
{
|
|
508
|
+
Addr->Ipv4.sin_port = htons(Port);
|
|
509
|
+
return
|
|
510
|
+
QuicAddr4FromString(AddrStr, Addr) ||
|
|
511
|
+
QuicAddr6FromString(AddrStr, Addr);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
typedef int QUIC_XDP_MAP_HANDLE;
|
|
515
|
+
|
|
516
|
+
QUIC_INLINE
|
|
517
|
+
BOOLEAN
|
|
518
|
+
CxPlatIsIpLiteral(
|
|
519
|
+
_In_z_ const char* AddrStr
|
|
520
|
+
)
|
|
521
|
+
{
|
|
522
|
+
IN_ADDR Ipv4Addr = {0};
|
|
523
|
+
IN6_ADDR Ipv6Addr = {0};
|
|
524
|
+
return
|
|
525
|
+
inet_pton(AF_INET, AddrStr, &Ipv4Addr) == 1 ||
|
|
526
|
+
inet_pton(AF_INET6, AddrStr, &Ipv6Addr) == 1;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
//
|
|
530
|
+
// Represents an IP address and (optionally) port number as a string.
|
|
531
|
+
//
|
|
532
|
+
typedef struct QUIC_ADDR_STR {
|
|
533
|
+
char Address[65];
|
|
534
|
+
} QUIC_ADDR_STR;
|
|
535
|
+
|
|
536
|
+
//
|
|
537
|
+
// Formats only the IP literal, excluding the port and IPv6 brackets. For
|
|
538
|
+
// example, an IPv6 address with port 443 is formatted as "2001:db8::1".
|
|
539
|
+
//
|
|
540
|
+
QUIC_INLINE
|
|
541
|
+
BOOLEAN
|
|
542
|
+
QuicAddrIpToString(
|
|
543
|
+
_In_ const QUIC_ADDR* Addr,
|
|
544
|
+
_Out_ QUIC_ADDR_STR* AddrStr
|
|
545
|
+
)
|
|
546
|
+
{
|
|
547
|
+
const void* IpAddress;
|
|
548
|
+
AddrStr->Address[0] = '\0';
|
|
549
|
+
if (Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_INET) {
|
|
550
|
+
IpAddress = &Addr->Ipv4.sin_addr;
|
|
551
|
+
} else if (Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_INET6) {
|
|
552
|
+
IpAddress = &Addr->Ipv6.sin6_addr;
|
|
553
|
+
} else {
|
|
554
|
+
return FALSE;
|
|
555
|
+
}
|
|
556
|
+
return
|
|
557
|
+
inet_ntop(
|
|
558
|
+
Addr->Ip.sa_family,
|
|
559
|
+
IpAddress,
|
|
560
|
+
AddrStr->Address,
|
|
561
|
+
sizeof(AddrStr->Address)) != NULL;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
//
|
|
565
|
+
// Formats the complete endpoint, including a nonzero port and the brackets
|
|
566
|
+
// required around IPv6 when a port is present. For example, an IPv6 address
|
|
567
|
+
// with port 443 is formatted as "[2001:db8::1]:443".
|
|
568
|
+
//
|
|
569
|
+
QUIC_INLINE
|
|
570
|
+
BOOLEAN
|
|
571
|
+
QuicAddrToString(
|
|
572
|
+
_In_ const QUIC_ADDR* Addr,
|
|
573
|
+
_Out_ QUIC_ADDR_STR* AddrStr
|
|
574
|
+
)
|
|
575
|
+
{
|
|
576
|
+
size_t AvailSpace = sizeof(AddrStr->Address);
|
|
577
|
+
char* Address = AddrStr->Address;
|
|
578
|
+
if (Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_INET6 && Addr->Ipv6.sin6_port != 0) {
|
|
579
|
+
Address[0] = '[';
|
|
580
|
+
Address++;
|
|
581
|
+
AvailSpace--;
|
|
582
|
+
}
|
|
583
|
+
if (inet_ntop(
|
|
584
|
+
Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_INET ? AF_INET : AF_INET6,
|
|
585
|
+
Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_INET ? (void*)&Addr->Ipv4.sin_addr : (void*)&Addr->Ipv6.sin6_addr,
|
|
586
|
+
Address,
|
|
587
|
+
AvailSpace) == NULL) {
|
|
588
|
+
return FALSE;
|
|
589
|
+
}
|
|
590
|
+
if (Addr->Ipv4.sin_port != 0) {
|
|
591
|
+
Address += strlen(Address);
|
|
592
|
+
if (Addr->Ip.sa_family == QUIC_ADDRESS_FAMILY_INET6) {
|
|
593
|
+
Address[0] = ']';
|
|
594
|
+
Address++;
|
|
595
|
+
}
|
|
596
|
+
AvailSpace = sizeof(AddrStr->Address) - (Address - AddrStr->Address);
|
|
597
|
+
snprintf(Address, AvailSpace, ":%hu", ntohs(Addr->Ipv4.sin_port));
|
|
598
|
+
}
|
|
599
|
+
return TRUE;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
//
|
|
603
|
+
// Event Queue Abstraction
|
|
604
|
+
//
|
|
605
|
+
|
|
606
|
+
#if __linux__
|
|
607
|
+
|
|
608
|
+
//
|
|
609
|
+
// TODO: build on other 64-bit architectures
|
|
610
|
+
//
|
|
611
|
+
#if CXPLAT_USE_IO_URING && (defined(__x86_64__) || defined(__aarch64__)) // liburing
|
|
612
|
+
#define LIBURING_INTERNAL
|
|
613
|
+
|
|
614
|
+
#if defined(__cplusplus)
|
|
615
|
+
extern "C++" {
|
|
616
|
+
#endif
|
|
617
|
+
#include <liburing.h>
|
|
618
|
+
#if defined(__cplusplus)
|
|
619
|
+
} // extern "C++"
|
|
620
|
+
#endif
|
|
621
|
+
|
|
622
|
+
typedef struct CXPLAT_EVENTQ QUIC_EVENTQ;
|
|
623
|
+
typedef struct io_uring_cqe* CXPLAT_CQE;
|
|
624
|
+
typedef
|
|
625
|
+
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
626
|
+
void
|
|
627
|
+
(CXPLAT_EVENT_COMPLETION)(
|
|
628
|
+
_In_ CXPLAT_CQE* Cqe
|
|
629
|
+
);
|
|
630
|
+
typedef CXPLAT_EVENT_COMPLETION *CXPLAT_EVENT_COMPLETION_HANDLER;
|
|
631
|
+
#define CXPLAT_USE_EVENT_BATCH_COMPLETION
|
|
632
|
+
typedef
|
|
633
|
+
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
634
|
+
void
|
|
635
|
+
(CXPLAT_EVENT_BATCH_COMPLETION)(
|
|
636
|
+
_Inout_ CXPLAT_CQE** Cqes,
|
|
637
|
+
_Inout_ uint32_t* Count
|
|
638
|
+
);
|
|
639
|
+
typedef CXPLAT_EVENT_BATCH_COMPLETION *CXPLAT_EVENT_BATCH_COMPLETION_HANDLER;
|
|
640
|
+
typedef struct CXPLAT_SQE QUIC_SQE;
|
|
641
|
+
|
|
642
|
+
#else // epoll
|
|
643
|
+
|
|
644
|
+
#include <sys/epoll.h>
|
|
645
|
+
#include <sys/eventfd.h>
|
|
646
|
+
|
|
647
|
+
typedef int QUIC_EVENTQ;
|
|
648
|
+
|
|
649
|
+
typedef struct epoll_event QUIC_CQE;
|
|
650
|
+
|
|
651
|
+
typedef
|
|
652
|
+
void
|
|
653
|
+
(QUIC_EVENT_COMPLETION)(
|
|
654
|
+
_In_ QUIC_CQE* Cqe
|
|
655
|
+
);
|
|
656
|
+
typedef QUIC_EVENT_COMPLETION *QUIC_EVENT_COMPLETION_HANDLER;
|
|
657
|
+
|
|
658
|
+
typedef struct QUIC_SQE {
|
|
659
|
+
int fd;
|
|
660
|
+
QUIC_EVENT_COMPLETION_HANDLER Completion;
|
|
661
|
+
} QUIC_SQE;
|
|
662
|
+
|
|
663
|
+
#endif // epoll
|
|
664
|
+
|
|
665
|
+
#elif __APPLE__ || __FreeBSD__ // kqueue
|
|
666
|
+
|
|
667
|
+
#include <sys/event.h>
|
|
668
|
+
#include <fcntl.h>
|
|
669
|
+
|
|
670
|
+
typedef int QUIC_EVENTQ;
|
|
671
|
+
|
|
672
|
+
typedef struct kevent QUIC_CQE;
|
|
673
|
+
|
|
674
|
+
typedef
|
|
675
|
+
void
|
|
676
|
+
(QUIC_EVENT_COMPLETION)(
|
|
677
|
+
_In_ QUIC_CQE* Cqe
|
|
678
|
+
);
|
|
679
|
+
typedef QUIC_EVENT_COMPLETION *QUIC_EVENT_COMPLETION_HANDLER;
|
|
680
|
+
|
|
681
|
+
typedef struct QUIC_SQE {
|
|
682
|
+
uintptr_t Handle;
|
|
683
|
+
QUIC_EVENT_COMPLETION_HANDLER Completion;
|
|
684
|
+
} QUIC_SQE;
|
|
685
|
+
|
|
686
|
+
#else
|
|
687
|
+
|
|
688
|
+
#error Unsupported Platform
|
|
689
|
+
|
|
690
|
+
#endif
|
|
691
|
+
|
|
692
|
+
#if defined(__cplusplus)
|
|
693
|
+
}
|
|
694
|
+
#endif
|
|
695
|
+
|
|
696
|
+
#endif
|