quicsilver 0.3.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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +9 -1
  3. data/.github/workflows/cibuildgem.yaml +117 -0
  4. data/.gitignore +8 -1
  5. data/CHANGELOG.md +82 -0
  6. data/Gemfile.lock +27 -2
  7. data/README.md +205 -29
  8. data/Rakefile +75 -3
  9. data/benchmarks/baseline.rb +175 -0
  10. data/benchmarks/compare.rb +398 -0
  11. data/benchmarks/helpers.rb +138 -64
  12. data/benchmarks/latency.rb +128 -0
  13. data/benchmarks/loss.rb +193 -0
  14. data/benchmarks/mobile.rb +125 -0
  15. data/docs/connection_identity.md +141 -0
  16. data/examples/README.md +44 -91
  17. data/examples/benchmark.rb +191 -0
  18. data/examples/connection_pool_demo.rb +47 -0
  19. data/examples/example_helper.rb +69 -0
  20. data/examples/falcon_middleware.rb +44 -0
  21. data/examples/feature_demo.rb +125 -0
  22. data/examples/grpc_style.rb +97 -0
  23. data/examples/latency_aware_routing.rb +382 -0
  24. data/examples/lifecycle_drain.rb +264 -0
  25. data/examples/minimal_http3_server.rb +6 -18
  26. data/examples/priorities.rb +60 -0
  27. data/examples/protocol_http_server.rb +31 -0
  28. data/examples/rack_http3_server.rb +8 -20
  29. data/examples/rails_feature_test.rb +280 -0
  30. data/examples/server_stats.rb +117 -0
  31. data/examples/simple_client_test.rb +5 -5
  32. data/examples/streaming_sse.rb +33 -0
  33. data/examples/trailers.rb +69 -0
  34. data/examples/webtransport_smoke.rb +546 -0
  35. data/examples/worker_load_balancing.rb +425 -0
  36. data/ext/quicsilver/extconf.rb +111 -12
  37. data/ext/quicsilver/include/msquic.h +2226 -0
  38. data/ext/quicsilver/include/msquic_posix.h +696 -0
  39. data/ext/quicsilver/include/quic_sal_stub.h +314 -0
  40. data/ext/quicsilver/msquic_patch.rb +68 -0
  41. data/ext/quicsilver/patches/reliable-reset.patch +723 -0
  42. data/ext/quicsilver/patches/stream-final-size.patch +47 -0
  43. data/ext/quicsilver/quicsilver.c +1646 -189
  44. data/lib/quicsilver/client/client.rb +546 -88
  45. data/lib/quicsilver/client/connection_pool.rb +202 -0
  46. data/lib/quicsilver/client/request.rb +106 -14
  47. data/lib/quicsilver/errors.rb +39 -0
  48. data/lib/quicsilver/libmsquic.2.dylib +0 -0
  49. data/lib/quicsilver/protocol/adapter.rb +196 -0
  50. data/lib/quicsilver/protocol/capsule.rb +38 -0
  51. data/lib/quicsilver/protocol/connect_stream_decoder.rb +75 -0
  52. data/lib/quicsilver/protocol/control_stream_parser.rb +117 -0
  53. data/lib/quicsilver/protocol/datagram.rb +40 -0
  54. data/lib/quicsilver/protocol/frame_parser.rb +141 -0
  55. data/lib/quicsilver/protocol/frame_reader.rb +84 -0
  56. data/lib/quicsilver/protocol/frames.rb +137 -10
  57. data/lib/quicsilver/protocol/priority.rb +65 -0
  58. data/lib/quicsilver/protocol/qpack/decoder.rb +4 -42
  59. data/lib/quicsilver/protocol/qpack/encoder.rb +49 -21
  60. data/lib/quicsilver/protocol/qpack/header_block_decoder.rb +16 -1
  61. data/lib/quicsilver/protocol/qpack/huffman.rb +4 -4
  62. data/lib/quicsilver/protocol/request_encoder.rb +6 -3
  63. data/lib/quicsilver/protocol/request_parser.rb +43 -141
  64. data/lib/quicsilver/protocol/response_encoder.rb +40 -5
  65. data/lib/quicsilver/protocol/response_parser.rb +26 -128
  66. data/lib/quicsilver/protocol/stream_input.rb +98 -0
  67. data/lib/quicsilver/protocol/stream_output.rb +59 -0
  68. data/lib/quicsilver/protocol/unidirectional_stream.rb +12 -0
  69. data/lib/quicsilver/protocol/web_transport.rb +214 -0
  70. data/lib/quicsilver/rack/context.rb +33 -0
  71. data/lib/quicsilver/response.rb +40 -0
  72. data/lib/quicsilver/server/rack_adapter.rb +77 -0
  73. data/lib/quicsilver/server/receive_queue.rb +106 -0
  74. data/lib/quicsilver/server/request_handler.rb +111 -48
  75. data/lib/quicsilver/server/request_registry.rb +18 -5
  76. data/lib/quicsilver/server/scheduler.rb +50 -0
  77. data/lib/quicsilver/server/schedulers/fiber_scheduler.rb +79 -0
  78. data/lib/quicsilver/server/schedulers/thread_scheduler.rb +76 -0
  79. data/lib/quicsilver/server/server.rb +848 -104
  80. data/lib/quicsilver/server/web_transport_flow_control.rb +270 -0
  81. data/lib/quicsilver/server/web_transport_manager.rb +281 -0
  82. data/lib/quicsilver/server/web_transport_registry.rb +40 -0
  83. data/lib/quicsilver/server/web_transport_session.rb +812 -0
  84. data/lib/quicsilver/server/web_transport_stream.rb +326 -0
  85. data/lib/quicsilver/transport/configuration.rb +113 -11
  86. data/lib/quicsilver/transport/connection.rb +376 -132
  87. data/lib/quicsilver/transport/connection_stats.rb +53 -0
  88. data/lib/quicsilver/transport/event_loop.rb +36 -0
  89. data/lib/quicsilver/transport/inbound_stream.rb +21 -1
  90. data/lib/quicsilver/transport/stream.rb +18 -3
  91. data/lib/quicsilver/transport/stream_event.rb +25 -2
  92. data/lib/quicsilver/transport/stream_id.rb +26 -0
  93. data/lib/quicsilver/version.rb +1 -1
  94. data/lib/quicsilver.rb +45 -11
  95. data/lib/rackup/handler/quicsilver.rb +57 -38
  96. data/quicsilver.gemspec +17 -2
  97. metadata +120 -10
  98. data/benchmarks/concurrent.rb +0 -110
  99. data/benchmarks/quicsilver_server.rb +0 -46
  100. data/benchmarks/rails.rb +0 -170
  101. data/benchmarks/throughput.rb +0 -113
  102. data/examples/setup_certs.sh +0 -57
@@ -0,0 +1,2226 @@
1
+ /*++
2
+
3
+ Copyright (c) Microsoft Corporation.
4
+ Licensed under the MIT License.
5
+
6
+ Abstract:
7
+
8
+ Declarations for the MsQuic API, which enables applications and drivers to
9
+ create QUIC connections as a client or server.
10
+
11
+ For more detailed information, see ../docs/API.md
12
+
13
+ Supported Platforms:
14
+
15
+ Windows User mode
16
+ Windows Kernel mode
17
+ Linux User mode
18
+
19
+ --*/
20
+
21
+ #ifndef _MSQUIC_
22
+ #define _MSQUIC_
23
+
24
+ #ifdef _WIN32
25
+ #pragma once
26
+
27
+ #pragma warning(disable:4201) // nonstandard extension used: nameless struct/union
28
+ #pragma warning(disable:4214) // nonstandard extension used: bit field types other than int
29
+ #endif
30
+
31
+ #ifdef _KERNEL_MODE
32
+ #include "msquic_winkernel.h"
33
+ #elif _WIN32
34
+ #include "msquic_winuser.h"
35
+ #elif __linux__ || __APPLE__ || __FreeBSD__
36
+ #include "msquic_posix.h"
37
+ #else
38
+ #error "Unsupported Platform"
39
+ #endif
40
+
41
+ #if defined(__cplusplus)
42
+ extern "C" {
43
+ #endif
44
+
45
+ typedef struct QUIC_HANDLE *HQUIC;
46
+
47
+ //
48
+ // The maximum value that can be encoded in a 62-bit integer.
49
+ //
50
+ #define QUIC_UINT62_MAX ((1ULL << 62U) - 1)
51
+
52
+ //
53
+ // Represents a 62-bit integer.
54
+ //
55
+ typedef _In_range_(0, QUIC_UINT62_MAX) uint64_t QUIC_UINT62;
56
+
57
+ //
58
+ // An ALPN must not exceed 255 bytes, and must not be zero-length.
59
+ //
60
+ #define QUIC_MAX_ALPN_LENGTH 255
61
+
62
+ //
63
+ // A server name must not exceed 65535 bytes.
64
+ //
65
+ #define QUIC_MAX_SNI_LENGTH 65535
66
+
67
+ //
68
+ // The maximum number of bytes of application data a server application can
69
+ // send in a resumption ticket.
70
+ //
71
+ #define QUIC_MAX_RESUMPTION_APP_DATA_LENGTH 1000
72
+
73
+ //
74
+ // The number of bytes of stateless reset key.
75
+ //
76
+ #define QUIC_STATELESS_RESET_KEY_LENGTH 32
77
+
78
+ typedef enum QUIC_TLS_PROVIDER {
79
+ QUIC_TLS_PROVIDER_SCHANNEL = 0x0000,
80
+ QUIC_TLS_PROVIDER_OPENSSL = 0x0001,
81
+ } QUIC_TLS_PROVIDER;
82
+
83
+ typedef enum QUIC_EXECUTION_PROFILE {
84
+ QUIC_EXECUTION_PROFILE_LOW_LATENCY, // Default
85
+ QUIC_EXECUTION_PROFILE_TYPE_MAX_THROUGHPUT,
86
+ QUIC_EXECUTION_PROFILE_TYPE_SCAVENGER,
87
+ QUIC_EXECUTION_PROFILE_TYPE_REAL_TIME,
88
+ } QUIC_EXECUTION_PROFILE;
89
+
90
+ typedef enum QUIC_LOAD_BALANCING_MODE {
91
+ QUIC_LOAD_BALANCING_DISABLED, // Default
92
+ QUIC_LOAD_BALANCING_SERVER_ID_IP, // Encodes IP address in Server ID
93
+ QUIC_LOAD_BALANCING_SERVER_ID_FIXED, // Encodes a fixed 4-byte value in Server ID
94
+ QUIC_LOAD_BALANCING_COUNT, // The number of supported load balancing modes
95
+ // MUST BE LAST
96
+ } QUIC_LOAD_BALANCING_MODE;
97
+
98
+ typedef enum QUIC_TLS_ALERT_CODES {
99
+ QUIC_TLS_ALERT_CODE_SUCCESS = 0xFFFF, // Not a real TlsAlert
100
+ QUIC_TLS_ALERT_CODE_UNEXPECTED_MESSAGE = 10,
101
+ QUIC_TLS_ALERT_CODE_BAD_CERTIFICATE = 42,
102
+ QUIC_TLS_ALERT_CODE_UNSUPPORTED_CERTIFICATE = 43,
103
+ QUIC_TLS_ALERT_CODE_CERTIFICATE_REVOKED = 44,
104
+ QUIC_TLS_ALERT_CODE_CERTIFICATE_EXPIRED = 45,
105
+ QUIC_TLS_ALERT_CODE_CERTIFICATE_UNKNOWN = 46,
106
+ QUIC_TLS_ALERT_CODE_ILLEGAL_PARAMETER = 47,
107
+ QUIC_TLS_ALERT_CODE_UNKNOWN_CA = 48,
108
+ QUIC_TLS_ALERT_CODE_ACCESS_DENIED = 49,
109
+ QUIC_TLS_ALERT_CODE_INSUFFICIENT_SECURITY = 71,
110
+ QUIC_TLS_ALERT_CODE_INTERNAL_ERROR = 80,
111
+ QUIC_TLS_ALERT_CODE_USER_CANCELED = 90,
112
+ QUIC_TLS_ALERT_CODE_CERTIFICATE_REQUIRED = 116,
113
+ QUIC_TLS_ALERT_CODE_MAX = 255,
114
+ } QUIC_TLS_ALERT_CODES;
115
+
116
+ typedef enum QUIC_CREDENTIAL_TYPE {
117
+ QUIC_CREDENTIAL_TYPE_NONE,
118
+ QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH,
119
+ QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH_STORE,
120
+ QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT,
121
+ QUIC_CREDENTIAL_TYPE_CERTIFICATE_FILE,
122
+ QUIC_CREDENTIAL_TYPE_CERTIFICATE_FILE_PROTECTED,
123
+ QUIC_CREDENTIAL_TYPE_CERTIFICATE_PKCS12,
124
+ } QUIC_CREDENTIAL_TYPE;
125
+
126
+ typedef enum QUIC_CREDENTIAL_FLAGS {
127
+ QUIC_CREDENTIAL_FLAG_NONE = 0x00000000,
128
+ QUIC_CREDENTIAL_FLAG_CLIENT = 0x00000001, // Lack of client flag indicates server.
129
+ QUIC_CREDENTIAL_FLAG_LOAD_ASYNCHRONOUS = 0x00000002,
130
+ QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION = 0x00000004,
131
+ QUIC_CREDENTIAL_FLAG_ENABLE_OCSP = 0x00000008, // Schannel only currently
132
+ QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED = 0x00000010,
133
+ QUIC_CREDENTIAL_FLAG_DEFER_CERTIFICATE_VALIDATION = 0x00000020,
134
+ QUIC_CREDENTIAL_FLAG_REQUIRE_CLIENT_AUTHENTICATION = 0x00000040,
135
+ QUIC_CREDENTIAL_FLAG_USE_TLS_BUILTIN_CERTIFICATE_VALIDATION = 0x00000080, // OpenSSL only currently
136
+ QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_END_CERT = 0x00000100, // Schannel only currently
137
+ QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CHAIN = 0x00000200, // Schannel only currently
138
+ QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT = 0x00000400, // Schannel only currently
139
+ QUIC_CREDENTIAL_FLAG_IGNORE_NO_REVOCATION_CHECK = 0x00000800, // Schannel only currently
140
+ QUIC_CREDENTIAL_FLAG_IGNORE_REVOCATION_OFFLINE = 0x00001000, // Schannel only currently
141
+ QUIC_CREDENTIAL_FLAG_SET_ALLOWED_CIPHER_SUITES = 0x00002000,
142
+ QUIC_CREDENTIAL_FLAG_USE_PORTABLE_CERTIFICATES = 0x00004000,
143
+ QUIC_CREDENTIAL_FLAG_USE_SUPPLIED_CREDENTIALS = 0x00008000, // Schannel only
144
+ QUIC_CREDENTIAL_FLAG_USE_SYSTEM_MAPPER = 0x00010000, // Schannel only
145
+ QUIC_CREDENTIAL_FLAG_CACHE_ONLY_URL_RETRIEVAL = 0x00020000, // Windows only currently
146
+ QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CACHE_ONLY = 0x00040000, // Windows only currently
147
+ QUIC_CREDENTIAL_FLAG_INPROC_PEER_CERTIFICATE = 0x00080000, // Schannel only
148
+ QUIC_CREDENTIAL_FLAG_SET_CA_CERTIFICATE_FILE = 0x00100000, // OpenSSL only currently
149
+ QUIC_CREDENTIAL_FLAG_DISABLE_AIA = 0x00200000, // Schannel only currently
150
+ } QUIC_CREDENTIAL_FLAGS;
151
+
152
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_CREDENTIAL_FLAGS)
153
+
154
+ typedef enum QUIC_ALLOWED_CIPHER_SUITE_FLAGS {
155
+ QUIC_ALLOWED_CIPHER_SUITE_NONE = 0x0,
156
+ QUIC_ALLOWED_CIPHER_SUITE_AES_128_GCM_SHA256 = 0x1,
157
+ QUIC_ALLOWED_CIPHER_SUITE_AES_256_GCM_SHA384 = 0x2,
158
+ QUIC_ALLOWED_CIPHER_SUITE_CHACHA20_POLY1305_SHA256 = 0x4, // Not supported on Schannel
159
+ } QUIC_ALLOWED_CIPHER_SUITE_FLAGS;
160
+
161
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_ALLOWED_CIPHER_SUITE_FLAGS);
162
+
163
+ typedef enum QUIC_CERTIFICATE_HASH_STORE_FLAGS {
164
+ QUIC_CERTIFICATE_HASH_STORE_FLAG_NONE = 0x0000,
165
+ QUIC_CERTIFICATE_HASH_STORE_FLAG_MACHINE_STORE = 0x0001,
166
+ } QUIC_CERTIFICATE_HASH_STORE_FLAGS;
167
+
168
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_CERTIFICATE_HASH_STORE_FLAGS)
169
+
170
+ typedef enum QUIC_CONNECTION_SHUTDOWN_FLAGS {
171
+ QUIC_CONNECTION_SHUTDOWN_FLAG_NONE = 0x0000,
172
+ QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT = 0x0001, // Don't send the close frame over the network.
173
+ } QUIC_CONNECTION_SHUTDOWN_FLAGS;
174
+
175
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_CONNECTION_SHUTDOWN_FLAGS)
176
+
177
+ typedef enum QUIC_SERVER_RESUMPTION_LEVEL {
178
+ QUIC_SERVER_NO_RESUME,
179
+ QUIC_SERVER_RESUME_ONLY,
180
+ QUIC_SERVER_RESUME_AND_ZERORTT,
181
+ } QUIC_SERVER_RESUMPTION_LEVEL;
182
+
183
+ typedef enum QUIC_SEND_RESUMPTION_FLAGS {
184
+ QUIC_SEND_RESUMPTION_FLAG_NONE = 0x0000,
185
+ QUIC_SEND_RESUMPTION_FLAG_FINAL = 0x0001, // Free TLS state after sending this ticket.
186
+ } QUIC_SEND_RESUMPTION_FLAGS;
187
+
188
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_SEND_RESUMPTION_FLAGS)
189
+
190
+ typedef enum QUIC_STREAM_SCHEDULING_SCHEME {
191
+ QUIC_STREAM_SCHEDULING_SCHEME_FIFO = 0x0000, // Sends stream data first come, first served. (Default)
192
+ QUIC_STREAM_SCHEDULING_SCHEME_ROUND_ROBIN = 0x0001, // Sends stream data evenly multiplexed.
193
+ QUIC_STREAM_SCHEDULING_SCHEME_COUNT, // The number of stream scheduling schemes.
194
+ } QUIC_STREAM_SCHEDULING_SCHEME;
195
+
196
+ typedef enum QUIC_STREAM_OPEN_FLAGS {
197
+ QUIC_STREAM_OPEN_FLAG_NONE = 0x0000,
198
+ QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL = 0x0001, // Indicates the stream is unidirectional.
199
+ QUIC_STREAM_OPEN_FLAG_0_RTT = 0x0002, // The stream was opened via a 0-RTT packet.
200
+ QUIC_STREAM_OPEN_FLAG_DELAY_ID_FC_UPDATES = 0x0004, // Indicates stream ID flow control limit updates for the
201
+ // connection should be delayed to StreamClose.
202
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
203
+ QUIC_STREAM_OPEN_FLAG_APP_OWNED_BUFFERS = 0x0008, // No buffer will be allocated for the stream, the app must
204
+ // provide buffers (see StreamProvideReceiveBuffers)
205
+ #endif
206
+ } QUIC_STREAM_OPEN_FLAGS;
207
+
208
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_STREAM_OPEN_FLAGS)
209
+
210
+ typedef enum QUIC_STREAM_START_FLAGS {
211
+ QUIC_STREAM_START_FLAG_NONE = 0x0000,
212
+ QUIC_STREAM_START_FLAG_IMMEDIATE = 0x0001, // Immediately informs peer that stream is open.
213
+ QUIC_STREAM_START_FLAG_FAIL_BLOCKED = 0x0002, // Only opens the stream if flow control allows.
214
+ QUIC_STREAM_START_FLAG_SHUTDOWN_ON_FAIL = 0x0004, // Shutdown the stream immediately after start failure.
215
+ QUIC_STREAM_START_FLAG_INDICATE_PEER_ACCEPT = 0x0008, // Indicate PEER_ACCEPTED event if not accepted at start.
216
+ QUIC_STREAM_START_FLAG_PRIORITY_WORK = 0x0010, // Higher priority than other connection work.
217
+ } QUIC_STREAM_START_FLAGS;
218
+
219
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_STREAM_START_FLAGS)
220
+
221
+ typedef enum QUIC_STREAM_SHUTDOWN_FLAGS {
222
+ QUIC_STREAM_SHUTDOWN_FLAG_NONE = 0x0000,
223
+ QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL = 0x0001, // Cleanly closes the send path.
224
+ QUIC_STREAM_SHUTDOWN_FLAG_ABORT_SEND = 0x0002, // Abruptly closes the send path.
225
+ QUIC_STREAM_SHUTDOWN_FLAG_ABORT_RECEIVE = 0x0004, // Abruptly closes the receive path.
226
+ QUIC_STREAM_SHUTDOWN_FLAG_ABORT = 0x0006, // Abruptly closes both send and receive paths.
227
+ QUIC_STREAM_SHUTDOWN_FLAG_IMMEDIATE = 0x0008, // Immediately sends completion events to app.
228
+ QUIC_STREAM_SHUTDOWN_FLAG_INLINE = 0x0010, // Process the shutdown immediately inline. Only for calls on callbacks.
229
+ // WARNING: Can cause reentrant callbacks!
230
+ } QUIC_STREAM_SHUTDOWN_FLAGS;
231
+
232
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_STREAM_SHUTDOWN_FLAGS)
233
+
234
+ typedef enum QUIC_RECEIVE_FLAGS {
235
+ QUIC_RECEIVE_FLAG_NONE = 0x0000,
236
+ QUIC_RECEIVE_FLAG_0_RTT = 0x0001, // Data was encrypted with 0-RTT key.
237
+ QUIC_RECEIVE_FLAG_FIN = 0x0002, // FIN was included with this data.
238
+ } QUIC_RECEIVE_FLAGS;
239
+
240
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_RECEIVE_FLAGS)
241
+
242
+ typedef enum QUIC_SEND_FLAGS {
243
+ QUIC_SEND_FLAG_NONE = 0x0000,
244
+ QUIC_SEND_FLAG_ALLOW_0_RTT = 0x0001, // Allows the use of encrypting with 0-RTT key.
245
+ QUIC_SEND_FLAG_START = 0x0002, // Asynchronously starts the stream with the sent data.
246
+ QUIC_SEND_FLAG_FIN = 0x0004, // Indicates the request is the one last sent on the stream.
247
+ QUIC_SEND_FLAG_DGRAM_PRIORITY = 0x0008, // Indicates the datagram is higher priority than others.
248
+ QUIC_SEND_FLAG_DELAY_SEND = 0x0010, // Indicates the send should be delayed because more will be queued soon.
249
+ QUIC_SEND_FLAG_CANCEL_ON_LOSS = 0x0020, // Indicates that a stream is to be cancelled when packet loss is detected.
250
+ QUIC_SEND_FLAG_PRIORITY_WORK = 0x0040, // Higher priority than other connection work.
251
+ QUIC_SEND_FLAG_CANCEL_ON_BLOCKED = 0x0080, // Indicates that a frame should be dropped when it can't be sent immediately.
252
+ } QUIC_SEND_FLAGS;
253
+
254
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_SEND_FLAGS)
255
+
256
+ typedef enum QUIC_DATAGRAM_SEND_STATE {
257
+ QUIC_DATAGRAM_SEND_UNKNOWN, // Not yet sent.
258
+ QUIC_DATAGRAM_SEND_SENT, // Sent and awaiting acknowledgment
259
+ QUIC_DATAGRAM_SEND_LOST_SUSPECT, // Suspected as lost, but still tracked
260
+ QUIC_DATAGRAM_SEND_LOST_DISCARDED, // Lost and not longer being tracked
261
+ QUIC_DATAGRAM_SEND_ACKNOWLEDGED, // Acknowledged
262
+ QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS, // Acknowledged after being suspected lost
263
+ QUIC_DATAGRAM_SEND_CANCELED, // Canceled before send
264
+ } QUIC_DATAGRAM_SEND_STATE;
265
+
266
+ //
267
+ // Helper to determine if a datagrams state is final, and no longer tracked
268
+ // by MsQuic.
269
+ //
270
+ #define QUIC_DATAGRAM_SEND_STATE_IS_FINAL(State) \
271
+ ((State) >= QUIC_DATAGRAM_SEND_LOST_DISCARDED)
272
+
273
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
274
+
275
+ typedef enum QUIC_GLOBAL_EXECUTION_CONFIG_FLAGS {
276
+ QUIC_GLOBAL_EXECUTION_CONFIG_FLAG_NONE = 0x0000,
277
+ QUIC_GLOBAL_EXECUTION_CONFIG_FLAG_NO_IDEAL_PROC = 0x0008,
278
+ QUIC_GLOBAL_EXECUTION_CONFIG_FLAG_HIGH_PRIORITY = 0x0010,
279
+ QUIC_GLOBAL_EXECUTION_CONFIG_FLAG_AFFINITIZE = 0x0020,
280
+ } QUIC_GLOBAL_EXECUTION_CONFIG_FLAGS;
281
+
282
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_GLOBAL_EXECUTION_CONFIG_FLAGS)
283
+
284
+ //
285
+ // A custom configuration for thread execution in QUIC.
286
+ //
287
+ typedef struct QUIC_GLOBAL_EXECUTION_CONFIG {
288
+
289
+ QUIC_GLOBAL_EXECUTION_CONFIG_FLAGS Flags;
290
+ uint32_t PollingIdleTimeoutUs; // Time before a polling thread, with no work to do, sleeps.
291
+ uint32_t ProcessorCount;
292
+ _Field_size_(ProcessorCount)
293
+ uint16_t ProcessorList[1]; // List of processors to use for threads.
294
+
295
+ } QUIC_GLOBAL_EXECUTION_CONFIG;
296
+
297
+ #define QUIC_GLOBAL_EXECUTION_CONFIG_MIN_SIZE \
298
+ (uint32_t)FIELD_OFFSET(QUIC_GLOBAL_EXECUTION_CONFIG, ProcessorList)
299
+
300
+ #ifndef _KERNEL_MODE
301
+
302
+ //
303
+ // Execution Context abstraction, which allows the application layer to
304
+ // completely control execution of all MsQuic work.
305
+ //
306
+
307
+ typedef struct QUIC_EXECUTION_CONFIG {
308
+ uint32_t IdealProcessor;
309
+ QUIC_EVENTQ* EventQ;
310
+ } QUIC_EXECUTION_CONFIG;
311
+
312
+ typedef struct QUIC_EXECUTION QUIC_EXECUTION;
313
+
314
+ //
315
+ // This is called to create the execution contexts.
316
+ //
317
+ typedef
318
+ _IRQL_requires_max_(PASSIVE_LEVEL)
319
+ QUIC_STATUS
320
+ (QUIC_API * QUIC_EXECUTION_CREATE_FN)(
321
+ _In_ QUIC_GLOBAL_EXECUTION_CONFIG_FLAGS Flags, // Used for datapath type
322
+ _In_ uint32_t PollingIdleTimeoutUs,
323
+ _In_ uint32_t Count,
324
+ _In_reads_(Count) QUIC_EXECUTION_CONFIG* Configs,
325
+ _Out_writes_(Count) QUIC_EXECUTION** Executions
326
+ );
327
+
328
+ //
329
+ // This is called to delete the execution contexts.
330
+ //
331
+ typedef
332
+ _IRQL_requires_max_(PASSIVE_LEVEL)
333
+ void
334
+ (QUIC_API * QUIC_EXECUTION_DELETE_FN)(
335
+ _In_ uint32_t Count,
336
+ _In_reads_(Count) QUIC_EXECUTION** Executions
337
+ );
338
+
339
+ //
340
+ // This is called to allow MsQuic to process any polling work. It returns the
341
+ // number of milliseconds until the next scheduled timer expiration.
342
+ //
343
+ // TODO: Should it return an indication for if we should yield?
344
+ //
345
+ typedef
346
+ _IRQL_requires_max_(PASSIVE_LEVEL)
347
+ uint32_t
348
+ (QUIC_API * QUIC_EXECUTION_POLL_FN)(
349
+ _In_ QUIC_EXECUTION* Execution
350
+ );
351
+
352
+ #endif // _KERNEL_MODE
353
+
354
+ #endif // QUIC_API_ENABLE_PREVIEW_FEATURES
355
+
356
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
357
+
358
+ //
359
+ // XDP Maps configured for external XDP programs.
360
+ // Passed via SetParam (QUIC_PARAM_GLOBAL_XDP_MAP_CONFIG) after
361
+ // MsQuicOpenVersion but before opening any registrations.
362
+ // QUIC_XDP_MAP_HANDLE is defined per-platform in msquic_winuser.h,
363
+ // msquic_winkernel.h, and msquic_posix.h.
364
+ //
365
+
366
+ typedef struct QUIC_XDP_MAP_CONFIG {
367
+ uint32_t InterfaceIndex; // Network interface this map applies to.
368
+ QUIC_XDP_MAP_HANDLE MapHandle; // XDP map handle.
369
+ } QUIC_XDP_MAP_CONFIG;
370
+
371
+ #endif // QUIC_API_ENABLE_PREVIEW_FEATURES
372
+
373
+ typedef struct QUIC_REGISTRATION_CONFIG { // All fields may be NULL/zero.
374
+ const char* AppName;
375
+ QUIC_EXECUTION_PROFILE ExecutionProfile;
376
+ } QUIC_REGISTRATION_CONFIG;
377
+
378
+ typedef
379
+ _IRQL_requires_max_(PASSIVE_LEVEL)
380
+ _Function_class_(QUIC_CREDENTIAL_LOAD_COMPLETE)
381
+ void
382
+ (QUIC_API QUIC_CREDENTIAL_LOAD_COMPLETE)(
383
+ _In_ HQUIC Configuration,
384
+ _In_opt_ void* Context,
385
+ _In_ QUIC_STATUS Status
386
+ );
387
+
388
+ typedef QUIC_CREDENTIAL_LOAD_COMPLETE *QUIC_CREDENTIAL_LOAD_COMPLETE_HANDLER;
389
+
390
+ typedef struct QUIC_CERTIFICATE_HASH {
391
+ uint8_t ShaHash[20];
392
+ } QUIC_CERTIFICATE_HASH;
393
+
394
+ typedef struct QUIC_CERTIFICATE_HASH_STORE {
395
+ QUIC_CERTIFICATE_HASH_STORE_FLAGS Flags;
396
+ uint8_t ShaHash[20];
397
+ char StoreName[128];
398
+ } QUIC_CERTIFICATE_HASH_STORE;
399
+
400
+ typedef struct QUIC_CERTIFICATE_FILE {
401
+ const char *PrivateKeyFile;
402
+ const char *CertificateFile;
403
+ } QUIC_CERTIFICATE_FILE;
404
+
405
+ typedef struct QUIC_CERTIFICATE_FILE_PROTECTED {
406
+ const char *PrivateKeyFile;
407
+ const char *CertificateFile;
408
+ const char *PrivateKeyPassword;
409
+ } QUIC_CERTIFICATE_FILE_PROTECTED;
410
+
411
+ typedef struct QUIC_CERTIFICATE_PKCS12 {
412
+ const uint8_t *Asn1Blob;
413
+ uint32_t Asn1BlobLength;
414
+ const char *PrivateKeyPassword; // Optional: used if provided. Ignored if NULL
415
+ } QUIC_CERTIFICATE_PKCS12;
416
+
417
+ typedef void QUIC_CERTIFICATE; // Platform specific certificate object
418
+ typedef void QUIC_CERTIFICATE_CHAIN; // Platform specific certificate chain object
419
+
420
+ typedef struct QUIC_CREDENTIAL_CONFIG {
421
+ QUIC_CREDENTIAL_TYPE Type;
422
+ QUIC_CREDENTIAL_FLAGS Flags;
423
+ union {
424
+ QUIC_CERTIFICATE_HASH* CertificateHash;
425
+ QUIC_CERTIFICATE_HASH_STORE* CertificateHashStore;
426
+ QUIC_CERTIFICATE* CertificateContext;
427
+ QUIC_CERTIFICATE_FILE* CertificateFile;
428
+ QUIC_CERTIFICATE_FILE_PROTECTED* CertificateFileProtected;
429
+ QUIC_CERTIFICATE_PKCS12* CertificatePkcs12;
430
+ };
431
+ const char* Principal;
432
+ void* Reserved; // Currently unused
433
+ QUIC_CREDENTIAL_LOAD_COMPLETE_HANDLER AsyncHandler; // Optional
434
+ QUIC_ALLOWED_CIPHER_SUITE_FLAGS AllowedCipherSuites;// Optional
435
+ const char* CaCertificateFile; // Optional
436
+ } QUIC_CREDENTIAL_CONFIG;
437
+
438
+ //
439
+ // The maximum number of QUIC_TICKET_KEY_CONFIG that can be used at one time.
440
+ //
441
+ #define QUIC_MAX_TICKET_KEY_COUNT 16
442
+
443
+ //
444
+ // TLS New Session Ticket encryption key configuration.
445
+ //
446
+ typedef struct QUIC_TICKET_KEY_CONFIG {
447
+ uint8_t Id[16];
448
+ uint8_t Material[64];
449
+ uint8_t MaterialLength;
450
+ } QUIC_TICKET_KEY_CONFIG;
451
+
452
+ //
453
+ // A single contiguous buffer.
454
+ //
455
+ typedef struct QUIC_BUFFER {
456
+ uint32_t Length;
457
+ _Field_size_bytes_(Length)
458
+ uint8_t* Buffer;
459
+ } QUIC_BUFFER;
460
+
461
+ //
462
+ // All the available information describing a new incoming connection.
463
+ //
464
+ typedef struct QUIC_NEW_CONNECTION_INFO {
465
+ uint32_t QuicVersion;
466
+ const QUIC_ADDR* LocalAddress;
467
+ const QUIC_ADDR* RemoteAddress;
468
+ uint32_t CryptoBufferLength;
469
+ uint16_t ClientAlpnListLength;
470
+ uint16_t ServerNameLength;
471
+ uint8_t NegotiatedAlpnLength;
472
+ _Field_size_bytes_(CryptoBufferLength)
473
+ const uint8_t* CryptoBuffer;
474
+ _Field_size_bytes_(ClientAlpnListLength)
475
+ const uint8_t* ClientAlpnList;
476
+ _Field_size_bytes_(NegotiatedAlpnLength)
477
+ const uint8_t* NegotiatedAlpn;
478
+ _Field_size_bytes_opt_(ServerNameLength)
479
+ const char* ServerName;
480
+ } QUIC_NEW_CONNECTION_INFO;
481
+
482
+ typedef enum QUIC_TLS_PROTOCOL_VERSION {
483
+ QUIC_TLS_PROTOCOL_UNKNOWN = 0,
484
+ QUIC_TLS_PROTOCOL_1_3 = 0x3000,
485
+ } QUIC_TLS_PROTOCOL_VERSION;
486
+
487
+ typedef enum QUIC_CIPHER_ALGORITHM {
488
+ QUIC_CIPHER_ALGORITHM_NONE = 0,
489
+ QUIC_CIPHER_ALGORITHM_AES_128 = 0x660E,
490
+ QUIC_CIPHER_ALGORITHM_AES_256 = 0x6610,
491
+ QUIC_CIPHER_ALGORITHM_CHACHA20 = 0x6612, // Not supported on Schannel/BCrypt
492
+ } QUIC_CIPHER_ALGORITHM;
493
+
494
+ typedef enum QUIC_HASH_ALGORITHM {
495
+ QUIC_HASH_ALGORITHM_NONE = 0,
496
+ QUIC_HASH_ALGORITHM_SHA_256 = 0x800C,
497
+ QUIC_HASH_ALGORITHM_SHA_384 = 0x800D,
498
+ } QUIC_HASH_ALGORITHM;
499
+
500
+ typedef enum QUIC_KEY_EXCHANGE_ALGORITHM {
501
+ QUIC_KEY_EXCHANGE_ALGORITHM_NONE = 0,
502
+ } QUIC_KEY_EXCHANGE_ALGORITHM;
503
+
504
+ //
505
+ // See the following IANA registry for the TLS groups:
506
+ // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
507
+ //
508
+ typedef enum QUIC_TLS_GROUP {
509
+ QUIC_TLS_GROUP_UNKNOWN = 0,
510
+ QUIC_TLS_GROUP_SECP256R1 = 23,
511
+ QUIC_TLS_GROUP_SECP384R1 = 24,
512
+ QUIC_TLS_GROUP_X25519 = 29,
513
+ QUIC_TLS_GROUP_MLKEM512 = 512,
514
+ QUIC_TLS_GROUP_MLKEM768 = 513,
515
+ QUIC_TLS_GROUP_MLKEM1024 = 514,
516
+ QUIC_TLS_GROUP_SECP256R1MLKEM768 = 4587,
517
+ QUIC_TLS_GROUP_X25519MLKEM768 = 4588,
518
+ QUIC_TLS_GROUP_SECP384R1MLKEM1024 = 4589,
519
+ } QUIC_TLS_GROUP;
520
+
521
+ typedef enum QUIC_CIPHER_SUITE {
522
+ QUIC_CIPHER_SUITE_TLS_AES_128_GCM_SHA256 = 0x1301,
523
+ QUIC_CIPHER_SUITE_TLS_AES_256_GCM_SHA384 = 0x1302,
524
+ QUIC_CIPHER_SUITE_TLS_CHACHA20_POLY1305_SHA256 = 0x1303, // Not supported on Schannel
525
+ } QUIC_CIPHER_SUITE;
526
+
527
+ typedef enum QUIC_CONGESTION_CONTROL_ALGORITHM {
528
+ QUIC_CONGESTION_CONTROL_ALGORITHM_CUBIC,
529
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
530
+ QUIC_CONGESTION_CONTROL_ALGORITHM_BBR,
531
+ #endif
532
+ QUIC_CONGESTION_CONTROL_ALGORITHM_MAX,
533
+ } QUIC_CONGESTION_CONTROL_ALGORITHM;
534
+
535
+ //
536
+ // All the available information describing a handshake.
537
+ //
538
+ typedef struct QUIC_HANDSHAKE_INFO {
539
+ QUIC_TLS_PROTOCOL_VERSION TlsProtocolVersion;
540
+ QUIC_CIPHER_ALGORITHM CipherAlgorithm;
541
+ int32_t CipherStrength;
542
+ QUIC_HASH_ALGORITHM Hash;
543
+ int32_t HashStrength;
544
+ QUIC_KEY_EXCHANGE_ALGORITHM KeyExchangeAlgorithm;
545
+ int32_t KeyExchangeStrength;
546
+ QUIC_CIPHER_SUITE CipherSuite;
547
+ QUIC_TLS_GROUP TlsGroup; // Added in v2.5
548
+ } QUIC_HANDSHAKE_INFO;
549
+
550
+ //
551
+ // All statistics available to query about a connection.
552
+ //
553
+ typedef struct QUIC_STATISTICS {
554
+ uint64_t CorrelationId;
555
+ uint32_t VersionNegotiation : 1;
556
+ uint32_t StatelessRetry : 1;
557
+ uint32_t ResumptionAttempted : 1;
558
+ uint32_t ResumptionSucceeded : 1;
559
+ uint32_t Rtt; // In microseconds
560
+ uint32_t MinRtt; // In microseconds
561
+ uint32_t MaxRtt; // In microseconds
562
+ struct {
563
+ uint64_t Start;
564
+ uint64_t InitialFlightEnd; // Processed all peer's Initial packets
565
+ uint64_t HandshakeFlightEnd; // Processed all peer's Handshake packets
566
+ } Timing;
567
+ struct {
568
+ uint32_t ClientFlight1Bytes; // Sum of TLS payloads
569
+ uint32_t ServerFlight1Bytes; // Sum of TLS payloads
570
+ uint32_t ClientFlight2Bytes; // Sum of TLS payloads
571
+ } Handshake;
572
+ struct {
573
+ uint16_t PathMtu; // Current path MTU.
574
+ uint64_t TotalPackets; // QUIC packets; could be coalesced into fewer UDP datagrams.
575
+ uint64_t RetransmittablePackets;
576
+ uint64_t SuspectedLostPackets;
577
+ uint64_t SpuriousLostPackets; // Actual lost is (SuspectedLostPackets - SpuriousLostPackets)
578
+ uint64_t TotalBytes; // Sum of UDP payloads
579
+ uint64_t TotalStreamBytes; // Sum of stream payloads
580
+ uint32_t CongestionCount; // Number of congestion events
581
+ uint32_t PersistentCongestionCount; // Number of persistent congestion events
582
+ } Send;
583
+ struct {
584
+ uint64_t TotalPackets; // QUIC packets; could be coalesced into fewer UDP datagrams.
585
+ uint64_t ReorderedPackets; // Packets where packet number is less than highest seen.
586
+ uint64_t DroppedPackets; // Includes DuplicatePackets.
587
+ uint64_t DuplicatePackets;
588
+ uint64_t TotalBytes; // Sum of UDP payloads
589
+ uint64_t TotalStreamBytes; // Sum of stream payloads
590
+ uint64_t DecryptionFailures; // Count of packet decryption failures.
591
+ uint64_t ValidAckFrames; // Count of receive ACK frames.
592
+ } Recv;
593
+ struct {
594
+ uint32_t KeyUpdateCount;
595
+ } Misc;
596
+ } QUIC_STATISTICS;
597
+
598
+ //
599
+ // N.B. Consumers of this struct depend on it being the same for 32-bit and
600
+ // 64-bit systems. DO NOT include any fields that have different sizes on those
601
+ // platforms, such as size_t or pointers.
602
+ //
603
+ typedef struct QUIC_STATISTICS_V2 {
604
+
605
+ uint64_t CorrelationId;
606
+ uint32_t VersionNegotiation : 1;
607
+ uint32_t StatelessRetry : 1;
608
+ uint32_t ResumptionAttempted : 1;
609
+ uint32_t ResumptionSucceeded : 1;
610
+ uint32_t GreaseBitNegotiated : 1; // Set if we negotiated the GREASE bit.
611
+ uint32_t EcnCapable : 1;
612
+ uint32_t EncryptionOffloaded : 1; // At least one path successfully offloaded encryption
613
+ uint32_t RESERVED : 25;
614
+ uint32_t Rtt; // In microseconds
615
+ uint32_t MinRtt; // In microseconds
616
+ uint32_t MaxRtt; // In microseconds
617
+
618
+ uint64_t TimingStart;
619
+ uint64_t TimingInitialFlightEnd; // Processed all peer's Initial packets
620
+ uint64_t TimingHandshakeFlightEnd; // Processed all peer's Handshake packets
621
+
622
+ uint32_t HandshakeClientFlight1Bytes; // Sum of TLS payloads
623
+ uint32_t HandshakeServerFlight1Bytes; // Sum of TLS payloads
624
+ uint32_t HandshakeClientFlight2Bytes; // Sum of TLS payloads
625
+
626
+ uint16_t SendPathMtu; // Current path MTU.
627
+ uint64_t SendTotalPackets; // QUIC packets; could be coalesced into fewer UDP datagrams.
628
+ uint64_t SendRetransmittablePackets;
629
+ uint64_t SendSuspectedLostPackets;
630
+ uint64_t SendSpuriousLostPackets; // Actual lost is (SuspectedLostPackets - SpuriousLostPackets)
631
+ uint64_t SendTotalBytes; // Sum of UDP payloads
632
+ uint64_t SendTotalStreamBytes; // Sum of stream payloads
633
+ uint32_t SendCongestionCount; // Number of congestion events
634
+ uint32_t SendPersistentCongestionCount; // Number of persistent congestion events
635
+
636
+ uint64_t RecvTotalPackets; // QUIC packets; could be coalesced into fewer UDP datagrams.
637
+ uint64_t RecvReorderedPackets; // Packets where packet number is less than highest seen.
638
+ uint64_t RecvDroppedPackets; // Includes DuplicatePackets.
639
+ uint64_t RecvDuplicatePackets;
640
+ uint64_t RecvTotalBytes; // Sum of UDP payloads
641
+ uint64_t RecvTotalStreamBytes; // Sum of stream payloads
642
+ uint64_t RecvDecryptionFailures; // Count of packet decryption failures.
643
+ uint64_t RecvValidAckFrames; // Count of receive ACK frames.
644
+
645
+ uint32_t KeyUpdateCount;
646
+
647
+ uint32_t SendCongestionWindow; // Congestion window size
648
+
649
+ uint32_t DestCidUpdateCount; // Number of times the destionation CID changed.
650
+
651
+ uint32_t SendEcnCongestionCount; // Number of congestion events caused by ECN.
652
+
653
+ uint8_t HandshakeHopLimitTTL; // The TTL value in the initial packet of the handshake.
654
+
655
+ uint32_t RttVariance; // In microseconds
656
+
657
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
658
+ uint32_t ConnectionQueueDelayAvgUs; // Sliding average connection queue delay in microseconds
659
+ uint32_t ConnectionQueueDelayMaxUs; // Maximum connection queue delay in microseconds
660
+ uint32_t SendQueueDelayAvgUs; // Sliding average send queue delay in microseconds
661
+ uint32_t SendQueueDelayMaxUs; // Maximum send queue delay in microseconds
662
+ uint32_t ReceiveQueueDelayAvgUs; // Sliding average receive queue delay in microseconds
663
+ uint32_t ReceiveQueueDelayMaxUs; // Maximum receive queue delay in microseconds
664
+ #endif
665
+
666
+ // N.B. New fields must be appended to end
667
+
668
+ } QUIC_STATISTICS_V2;
669
+
670
+ typedef struct QUIC_NETWORK_STATISTICS
671
+ {
672
+ uint32_t BytesInFlight; // Bytes that were sent on the wire, but not yet acked
673
+ uint64_t PostedBytes; // Total bytes queued, but not yet acked. These may contain sent bytes that may have potentially lost too.
674
+ uint64_t IdealBytes; // Ideal number of bytes required to be available to avoid limiting throughput
675
+ uint64_t SmoothedRTT; // Smoothed RTT value
676
+ uint32_t CongestionWindow; // Congestion Window
677
+ uint64_t Bandwidth; // Estimated bandwidth
678
+
679
+ } QUIC_NETWORK_STATISTICS;
680
+
681
+ #define QUIC_STRUCT_SIZE_THRU_FIELD(Struct, Field) \
682
+ (FIELD_OFFSET(Struct, Field) + sizeof(((Struct*)0)->Field))
683
+
684
+ #define QUIC_STATISTICS_V2_SIZE_1 QUIC_STRUCT_SIZE_THRU_FIELD(QUIC_STATISTICS_V2, KeyUpdateCount) // MsQuic v2.0 final size
685
+ #define QUIC_STATISTICS_V2_SIZE_2 QUIC_STRUCT_SIZE_THRU_FIELD(QUIC_STATISTICS_V2, DestCidUpdateCount) // MsQuic v2.1 final size
686
+ #define QUIC_STATISTICS_V2_SIZE_3 QUIC_STRUCT_SIZE_THRU_FIELD(QUIC_STATISTICS_V2, SendEcnCongestionCount) // MsQuic v2.2 final size
687
+ #define QUIC_STATISTICS_V2_SIZE_4 QUIC_STRUCT_SIZE_THRU_FIELD(QUIC_STATISTICS_V2, RttVariance) // MsQuic v2.5 final size
688
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
689
+ #define QUIC_STATISTICS_V2_SIZE_5 QUIC_STRUCT_SIZE_THRU_FIELD(QUIC_STATISTICS_V2, ReceiveQueueDelayMaxUs) // MsQuic v2.6 preview size
690
+ #endif
691
+
692
+ typedef struct QUIC_LISTENER_STATISTICS {
693
+
694
+ uint64_t TotalAcceptedConnections;
695
+ uint64_t TotalRejectedConnections;
696
+
697
+ uint64_t BindingRecvDroppedPackets;
698
+
699
+ } QUIC_LISTENER_STATISTICS;
700
+
701
+ typedef enum QUIC_PERFORMANCE_COUNTERS {
702
+ QUIC_PERF_COUNTER_CONN_CREATED, // Total connections ever allocated.
703
+ QUIC_PERF_COUNTER_CONN_HANDSHAKE_FAIL, // Total connections that failed during handshake.
704
+ QUIC_PERF_COUNTER_CONN_APP_REJECT, // Total connections rejected by the application.
705
+ QUIC_PERF_COUNTER_CONN_RESUMED, // Total connections resumed.
706
+ QUIC_PERF_COUNTER_CONN_ACTIVE, // Connections currently allocated.
707
+ QUIC_PERF_COUNTER_CONN_CONNECTED, // Connections currently in the connected state.
708
+ QUIC_PERF_COUNTER_CONN_PROTOCOL_ERRORS, // Total connections shutdown with a protocol error.
709
+ QUIC_PERF_COUNTER_CONN_NO_ALPN, // Total connection attempts with no matching ALPN.
710
+ QUIC_PERF_COUNTER_STRM_ACTIVE, // Current streams allocated.
711
+ QUIC_PERF_COUNTER_PKTS_SUSPECTED_LOST, // Total suspected packets lost
712
+ QUIC_PERF_COUNTER_PKTS_DROPPED, // Total packets dropped for any reason.
713
+ QUIC_PERF_COUNTER_PKTS_DECRYPTION_FAIL, // Total packets with decryption failures.
714
+ QUIC_PERF_COUNTER_UDP_RECV, // Total UDP datagrams received.
715
+ QUIC_PERF_COUNTER_UDP_SEND, // Total UDP datagrams sent.
716
+ QUIC_PERF_COUNTER_UDP_RECV_BYTES, // Total UDP payload bytes received.
717
+ QUIC_PERF_COUNTER_UDP_SEND_BYTES, // Total UDP payload bytes sent.
718
+ QUIC_PERF_COUNTER_UDP_RECV_EVENTS, // Total UDP receive events.
719
+ QUIC_PERF_COUNTER_UDP_SEND_CALLS, // Total UDP send API calls.
720
+ QUIC_PERF_COUNTER_APP_SEND_BYTES, // Total bytes sent by applications.
721
+ QUIC_PERF_COUNTER_APP_RECV_BYTES, // Total bytes received by applications.
722
+ QUIC_PERF_COUNTER_CONN_QUEUE_DEPTH, // Current connections queued for processing.
723
+ QUIC_PERF_COUNTER_CONN_OPER_QUEUE_DEPTH,// Current connection operations queued.
724
+ QUIC_PERF_COUNTER_CONN_OPER_QUEUED, // Total connection operations queued ever.
725
+ QUIC_PERF_COUNTER_CONN_OPER_COMPLETED, // Total connection operations processed ever.
726
+ QUIC_PERF_COUNTER_WORK_OPER_QUEUE_DEPTH,// Current worker operations queued.
727
+ QUIC_PERF_COUNTER_WORK_OPER_QUEUED, // Total worker operations queued ever.
728
+ QUIC_PERF_COUNTER_WORK_OPER_COMPLETED, // Total worker operations processed ever.
729
+ QUIC_PERF_COUNTER_PATH_VALIDATED, // Total path challenges that succeed ever.
730
+ QUIC_PERF_COUNTER_PATH_FAILURE, // Total path challenges that fail ever.
731
+ QUIC_PERF_COUNTER_SEND_STATELESS_RESET, // Total stateless reset packets sent ever.
732
+ QUIC_PERF_COUNTER_SEND_STATELESS_RETRY, // Total stateless retry packets sent ever.
733
+ QUIC_PERF_COUNTER_CONN_LOAD_REJECT, // Total connections rejected due to worker load.
734
+ QUIC_PERF_COUNTER_LISTEN_QUEUE_DEPTH, // Current listeners queued for processing.
735
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
736
+ QUIC_PERF_COUNTER_ENCRYPT_DURATION_US, // Total time spent on encryption in microseconds.
737
+ QUIC_PERF_COUNTER_DECRYPT_DURATION_US, // Total time spent on decryption in microseconds.
738
+ #endif
739
+ QUIC_PERF_COUNTER_MAX,
740
+ } QUIC_PERFORMANCE_COUNTERS;
741
+
742
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
743
+ typedef struct QUIC_VERSION_SETTINGS {
744
+
745
+ const uint32_t* AcceptableVersions;
746
+ const uint32_t* OfferedVersions;
747
+ const uint32_t* FullyDeployedVersions;
748
+ uint32_t AcceptableVersionsLength;
749
+ uint32_t OfferedVersionsLength;
750
+ uint32_t FullyDeployedVersionsLength;
751
+
752
+ } QUIC_VERSION_SETTINGS;
753
+ #endif
754
+
755
+ typedef struct QUIC_GLOBAL_SETTINGS {
756
+ union {
757
+ uint64_t IsSetFlags;
758
+ struct {
759
+ uint64_t RetryMemoryLimit : 1;
760
+ uint64_t LoadBalancingMode : 1;
761
+ uint64_t FixedServerID : 1;
762
+ uint64_t RESERVED : 61;
763
+ } IsSet;
764
+ };
765
+ uint16_t RetryMemoryLimit;
766
+ uint16_t LoadBalancingMode;
767
+ uint32_t FixedServerID;
768
+ } QUIC_GLOBAL_SETTINGS;
769
+
770
+ typedef struct QUIC_SETTINGS {
771
+
772
+ union {
773
+ uint64_t IsSetFlags;
774
+ struct {
775
+ uint64_t MaxBytesPerKey : 1;
776
+ uint64_t HandshakeIdleTimeoutMs : 1;
777
+ uint64_t IdleTimeoutMs : 1;
778
+ uint64_t MtuDiscoverySearchCompleteTimeoutUs : 1;
779
+ uint64_t TlsClientMaxSendBuffer : 1;
780
+ uint64_t TlsServerMaxSendBuffer : 1;
781
+ uint64_t StreamRecvWindowDefault : 1;
782
+ uint64_t StreamRecvBufferDefault : 1;
783
+ uint64_t ConnFlowControlWindow : 1;
784
+ uint64_t MaxWorkerQueueDelayUs : 1;
785
+ uint64_t MaxStatelessOperations : 1;
786
+ uint64_t InitialWindowPackets : 1;
787
+ uint64_t SendIdleTimeoutMs : 1;
788
+ uint64_t InitialRttMs : 1;
789
+ uint64_t MaxAckDelayMs : 1;
790
+ uint64_t DisconnectTimeoutMs : 1;
791
+ uint64_t KeepAliveIntervalMs : 1;
792
+ uint64_t CongestionControlAlgorithm : 1;
793
+ uint64_t PeerBidiStreamCount : 1;
794
+ uint64_t PeerUnidiStreamCount : 1;
795
+ uint64_t MaxBindingStatelessOperations : 1;
796
+ uint64_t StatelessOperationExpirationMs : 1;
797
+ uint64_t MinimumMtu : 1;
798
+ uint64_t MaximumMtu : 1;
799
+ uint64_t SendBufferingEnabled : 1;
800
+ uint64_t PacingEnabled : 1;
801
+ uint64_t MigrationEnabled : 1;
802
+ uint64_t DatagramReceiveEnabled : 1;
803
+ uint64_t ServerResumptionLevel : 1;
804
+ uint64_t MaxOperationsPerDrain : 1;
805
+ uint64_t MtuDiscoveryMissingProbeCount : 1;
806
+ uint64_t DestCidUpdateIdleTimeoutMs : 1;
807
+ uint64_t GreaseQuicBitEnabled : 1;
808
+ uint64_t EcnEnabled : 1;
809
+ uint64_t HyStartEnabled : 1;
810
+ uint64_t StreamRecvWindowBidiLocalDefault : 1;
811
+ uint64_t StreamRecvWindowBidiRemoteDefault : 1;
812
+ uint64_t StreamRecvWindowUnidiDefault : 1;
813
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
814
+ uint64_t EncryptionOffloadAllowed : 1;
815
+ uint64_t ReliableResetEnabled : 1;
816
+ uint64_t OneWayDelayEnabled : 1;
817
+ uint64_t NetStatsEventEnabled : 1;
818
+ uint64_t StreamMultiReceiveEnabled : 1;
819
+ uint64_t XdpEnabled : 1;
820
+ uint64_t QTIPEnabled : 1;
821
+ uint64_t ReservedRioEnabled : 1;
822
+ uint64_t RESERVED : 18;
823
+ #else
824
+ uint64_t RESERVED : 26;
825
+ #endif
826
+ } IsSet;
827
+ };
828
+
829
+ uint64_t MaxBytesPerKey;
830
+ uint64_t HandshakeIdleTimeoutMs;
831
+ uint64_t IdleTimeoutMs;
832
+ uint64_t MtuDiscoverySearchCompleteTimeoutUs;
833
+ uint32_t TlsClientMaxSendBuffer;
834
+ uint32_t TlsServerMaxSendBuffer;
835
+ uint32_t StreamRecvWindowDefault;
836
+ uint32_t StreamRecvBufferDefault;
837
+ uint32_t ConnFlowControlWindow;
838
+ uint32_t MaxWorkerQueueDelayUs;
839
+ uint32_t MaxStatelessOperations;
840
+ uint32_t InitialWindowPackets;
841
+ uint32_t SendIdleTimeoutMs;
842
+ uint32_t InitialRttMs;
843
+ uint32_t MaxAckDelayMs;
844
+ uint32_t DisconnectTimeoutMs;
845
+ uint32_t KeepAliveIntervalMs;
846
+ uint16_t CongestionControlAlgorithm; // QUIC_CONGESTION_CONTROL_ALGORITHM
847
+ uint16_t PeerBidiStreamCount;
848
+ uint16_t PeerUnidiStreamCount;
849
+ uint16_t MaxBindingStatelessOperations;
850
+ uint16_t StatelessOperationExpirationMs;
851
+ uint16_t MinimumMtu;
852
+ uint16_t MaximumMtu;
853
+ uint8_t SendBufferingEnabled : 1;
854
+ uint8_t PacingEnabled : 1;
855
+ uint8_t MigrationEnabled : 1;
856
+ uint8_t DatagramReceiveEnabled : 1;
857
+ uint8_t ServerResumptionLevel : 2; // QUIC_SERVER_RESUMPTION_LEVEL
858
+ uint8_t GreaseQuicBitEnabled : 1;
859
+ uint8_t EcnEnabled : 1;
860
+ uint8_t MaxOperationsPerDrain;
861
+ uint8_t MtuDiscoveryMissingProbeCount;
862
+ uint32_t DestCidUpdateIdleTimeoutMs;
863
+ union {
864
+ uint64_t Flags;
865
+ struct {
866
+ uint64_t HyStartEnabled : 1;
867
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
868
+ uint64_t EncryptionOffloadAllowed : 1;
869
+ uint64_t ReliableResetEnabled : 1;
870
+ uint64_t OneWayDelayEnabled : 1;
871
+ uint64_t NetStatsEventEnabled : 1;
872
+ uint64_t StreamMultiReceiveEnabled : 1;
873
+ uint64_t XdpEnabled : 1;
874
+ uint64_t QTIPEnabled : 1;
875
+ uint64_t ReservedRioEnabled : 1;
876
+ uint64_t ReservedFlags : 55;
877
+ #else
878
+ uint64_t ReservedFlags : 63;
879
+ #endif
880
+ };
881
+ };
882
+ uint32_t StreamRecvWindowBidiLocalDefault;
883
+ uint32_t StreamRecvWindowBidiRemoteDefault;
884
+ uint32_t StreamRecvWindowUnidiDefault;
885
+
886
+ } QUIC_SETTINGS;
887
+
888
+ //
889
+ // This struct enables QUIC applications to support SSLKEYLOGFILE
890
+ // for debugging packet captures with e.g. Wireshark.
891
+ //
892
+
893
+ #define QUIC_TLS_SECRETS_MAX_SECRET_LEN 64
894
+ typedef struct QUIC_TLS_SECRETS {
895
+ uint8_t SecretLength;
896
+ struct {
897
+ uint8_t ClientRandom : 1;
898
+ uint8_t ClientEarlyTrafficSecret : 1;
899
+ uint8_t ClientHandshakeTrafficSecret : 1;
900
+ uint8_t ServerHandshakeTrafficSecret : 1;
901
+ uint8_t ClientTrafficSecret0 : 1;
902
+ uint8_t ServerTrafficSecret0 : 1;
903
+ } IsSet;
904
+ uint8_t ClientRandom[32];
905
+ uint8_t ClientEarlyTrafficSecret[QUIC_TLS_SECRETS_MAX_SECRET_LEN];
906
+ uint8_t ClientHandshakeTrafficSecret[QUIC_TLS_SECRETS_MAX_SECRET_LEN];
907
+ uint8_t ServerHandshakeTrafficSecret[QUIC_TLS_SECRETS_MAX_SECRET_LEN];
908
+ uint8_t ClientTrafficSecret0[QUIC_TLS_SECRETS_MAX_SECRET_LEN];
909
+ uint8_t ServerTrafficSecret0[QUIC_TLS_SECRETS_MAX_SECRET_LEN];
910
+ } QUIC_TLS_SECRETS;
911
+
912
+ typedef struct QUIC_STREAM_STATISTICS {
913
+ uint64_t ConnBlockedBySchedulingUs;
914
+ uint64_t ConnBlockedByPacingUs;
915
+ uint64_t ConnBlockedByAmplificationProtUs;
916
+ uint64_t ConnBlockedByCongestionControlUs;
917
+ uint64_t ConnBlockedByFlowControlUs;
918
+ uint64_t StreamBlockedByIdFlowControlUs;
919
+ uint64_t StreamBlockedByFlowControlUs;
920
+ uint64_t StreamBlockedByAppUs;
921
+ } QUIC_STREAM_STATISTICS;
922
+
923
+ typedef enum QUIC_AEAD_ALGORITHM_TYPE {
924
+ QUIC_AEAD_ALGORITHM_AES_128_GCM = 0,
925
+ QUIC_AEAD_ALGORITHM_AES_256_GCM = 1,
926
+ } QUIC_AEAD_ALGORITHM_TYPE;
927
+
928
+ typedef struct QUIC_STATELESS_RETRY_CONFIG {
929
+ QUIC_AEAD_ALGORITHM_TYPE Algorithm; // AEAD algorithm for the key.
930
+ uint32_t RotationMs; // Key rotation interval in milliseconds.
931
+ uint32_t SecretLength; // Length of the secret.
932
+ _Field_size_bytes_(SecretLength)
933
+ const uint8_t* Secret; // Secret to generate the key.
934
+ } QUIC_STATELESS_RETRY_CONFIG;
935
+
936
+ //
937
+ // Functions for associating application contexts with QUIC handles. MsQuic
938
+ // provides no explicit synchronization between parallel calls to these
939
+ // functions.
940
+ //
941
+
942
+ typedef
943
+ _IRQL_requires_max_(DISPATCH_LEVEL)
944
+ void
945
+ (QUIC_API * QUIC_SET_CONTEXT_FN)(
946
+ _In_ _Pre_defensive_ HQUIC Handle,
947
+ _In_opt_ void* Context
948
+ );
949
+
950
+ typedef
951
+ _IRQL_requires_max_(DISPATCH_LEVEL)
952
+ void*
953
+ (QUIC_API * QUIC_GET_CONTEXT_FN)(
954
+ _In_ _Pre_defensive_ HQUIC Handle
955
+ );
956
+
957
+ //
958
+ // Sets the event handler for the QUIC handle. The type of the handler must be
959
+ // appropriate for the type of the handle. MsQuic provides no explicit
960
+ // synchronization between parallel calls to this function or the ones above.
961
+ //
962
+ typedef
963
+ _IRQL_requires_max_(DISPATCH_LEVEL)
964
+ void
965
+ (QUIC_API * QUIC_SET_CALLBACK_HANDLER_FN)(
966
+ _In_ _Pre_defensive_ HQUIC Handle,
967
+ _In_ void* Handler,
968
+ _In_opt_ void* Context
969
+ );
970
+
971
+ //
972
+ // Get and Set parameters on a handle.
973
+ //
974
+
975
+ #define QUIC_PARAM_PREFIX_GLOBAL 0x01000000
976
+ #define QUIC_PARAM_PREFIX_REGISTRATION 0x02000000
977
+ #define QUIC_PARAM_PREFIX_CONFIGURATION 0x03000000
978
+ #define QUIC_PARAM_PREFIX_LISTENER 0x04000000
979
+ #define QUIC_PARAM_PREFIX_CONNECTION 0x05000000
980
+ #define QUIC_PARAM_PREFIX_TLS 0x06000000
981
+ #define QUIC_PARAM_PREFIX_TLS_SCHANNEL 0x07000000
982
+ #define QUIC_PARAM_PREFIX_STREAM 0x08000000
983
+
984
+ #define QUIC_PARAM_HIGH_PRIORITY 0x40000000 // Combine with any param to make it high priority.
985
+
986
+ #define QUIC_PARAM_IS_GLOBAL(Param) ((Param & 0x3F000000) == QUIC_PARAM_PREFIX_GLOBAL)
987
+
988
+ //
989
+ // Parameters for Global.
990
+ //
991
+ #define QUIC_PARAM_GLOBAL_RETRY_MEMORY_PERCENT 0x01000000 // uint16_t
992
+ #define QUIC_PARAM_GLOBAL_SUPPORTED_VERSIONS 0x01000001 // uint32_t[] - network byte order
993
+ #define QUIC_PARAM_GLOBAL_LOAD_BALACING_MODE 0x01000002 // uint16_t - QUIC_LOAD_BALANCING_MODE
994
+ #define QUIC_PARAM_GLOBAL_PERF_COUNTERS 0x01000003 // uint64_t[] - Array size is QUIC_PERF_COUNTER_MAX
995
+ #define QUIC_PARAM_GLOBAL_LIBRARY_VERSION 0x01000004 // uint32_t[4]
996
+ #define QUIC_PARAM_GLOBAL_SETTINGS 0x01000005 // QUIC_SETTINGS
997
+ #define QUIC_PARAM_GLOBAL_GLOBAL_SETTINGS 0x01000006 // QUIC_GLOBAL_SETTINGS
998
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
999
+ #define QUIC_PARAM_GLOBAL_VERSION_SETTINGS 0x01000007 // QUIC_VERSION_SETTINGS
1000
+ #endif
1001
+ #define QUIC_PARAM_GLOBAL_LIBRARY_GIT_HASH 0x01000008 // char[64]
1002
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1003
+ #define QUIC_PARAM_GLOBAL_EXECUTION_CONFIG 0x01000009 // QUIC_GLOBAL_EXECUTION_CONFIG
1004
+ #endif
1005
+ #define QUIC_PARAM_GLOBAL_TLS_PROVIDER 0x0100000A // QUIC_TLS_PROVIDER
1006
+ #define QUIC_PARAM_GLOBAL_STATELESS_RESET_KEY 0x0100000B // uint8_t[] - Array size is QUIC_STATELESS_RESET_KEY_LENGTH
1007
+ #define QUIC_PARAM_GLOBAL_STATISTICS_V2_SIZES 0x0100000C // uint32_t[] - Array of sizes for each QUIC_STATISTICS_V2 version. Get-only. Pass a buffer of uint32_t, output count is variable. See documentation for details.
1008
+ #define QUIC_PARAM_GLOBAL_STATELESS_RETRY_CONFIG 0x0100000D // QUIC_STATELESS_RETRY_CONFIG
1009
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1010
+ #define QUIC_PARAM_GLOBAL_XDP_MAP_CONFIG 0x0100000E // QUIC_XDP_MAP_CONFIG[]
1011
+ #endif
1012
+
1013
+ //
1014
+ // Parameters for Registration.
1015
+ //
1016
+
1017
+ //
1018
+ // Parameters for Configuration.
1019
+ //
1020
+ #define QUIC_PARAM_CONFIGURATION_SETTINGS 0x03000000 // QUIC_SETTINGS
1021
+ #define QUIC_PARAM_CONFIGURATION_TICKET_KEYS 0x03000001 // QUIC_TICKET_KEY_CONFIG[]
1022
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1023
+ #define QUIC_PARAM_CONFIGURATION_VERSION_SETTINGS 0x03000002 // QUIC_VERSION_SETTINGS
1024
+ #endif
1025
+ // Schannel-specific Configuration parameter
1026
+ typedef struct QUIC_SCHANNEL_CREDENTIAL_ATTRIBUTE_W {
1027
+ unsigned long Attribute;
1028
+ unsigned long BufferLength;
1029
+ void* Buffer;
1030
+ } QUIC_SCHANNEL_CREDENTIAL_ATTRIBUTE_W;
1031
+ #define QUIC_PARAM_CONFIGURATION_SCHANNEL_CREDENTIAL_ATTRIBUTE_W 0x03000003 // QUIC_SCHANNEL_CREDENTIAL_ATTRIBUTE_W
1032
+
1033
+ //
1034
+ // Parameters for Listener.
1035
+ //
1036
+ #define QUIC_PARAM_LISTENER_LOCAL_ADDRESS 0x04000000 // QUIC_ADDR
1037
+ #define QUIC_PARAM_LISTENER_STATS 0x04000001 // QUIC_LISTENER_STATISTICS
1038
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1039
+ #define QUIC_PARAM_LISTENER_CIBIR_ID 0x04000002 // uint8_t[] {offset, id[]}
1040
+ #define QUIC_PARAM_LISTENER_PARTITION_INDEX 0x04000005 // uint16_t
1041
+ #endif
1042
+ #define QUIC_PARAM_DOS_MODE_EVENTS 0x04000004 // BOOLEAN
1043
+
1044
+ //
1045
+ // Parameters for Connection.
1046
+ //
1047
+ #define QUIC_PARAM_CONN_QUIC_VERSION 0x05000000 // uint32_t
1048
+ #define QUIC_PARAM_CONN_LOCAL_ADDRESS 0x05000001 // QUIC_ADDR
1049
+ #define QUIC_PARAM_CONN_REMOTE_ADDRESS 0x05000002 // QUIC_ADDR
1050
+ #define QUIC_PARAM_CONN_IDEAL_PROCESSOR 0x05000003 // uint16_t
1051
+ #define QUIC_PARAM_CONN_SETTINGS 0x05000004 // QUIC_SETTINGS
1052
+ #define QUIC_PARAM_CONN_STATISTICS 0x05000005 // QUIC_STATISTICS
1053
+ #define QUIC_PARAM_CONN_STATISTICS_PLAT 0x05000006 // QUIC_STATISTICS
1054
+ #define QUIC_PARAM_CONN_SHARE_UDP_BINDING 0x05000007 // uint8_t (BOOLEAN)
1055
+ #define QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT 0x05000008 // uint16_t
1056
+ #define QUIC_PARAM_CONN_LOCAL_UNIDI_STREAM_COUNT 0x05000009 // uint16_t
1057
+ #define QUIC_PARAM_CONN_MAX_STREAM_IDS 0x0500000A // uint64_t[4]
1058
+ #define QUIC_PARAM_CONN_CLOSE_REASON_PHRASE 0x0500000B // char[]
1059
+ #define QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME 0x0500000C // QUIC_STREAM_SCHEDULING_SCHEME
1060
+ #define QUIC_PARAM_CONN_DATAGRAM_RECEIVE_ENABLED 0x0500000D // uint8_t (BOOLEAN)
1061
+ #define QUIC_PARAM_CONN_DATAGRAM_SEND_ENABLED 0x0500000E // uint8_t (BOOLEAN)
1062
+ #ifdef QUIC_API_ENABLE_INSECURE_FEATURES
1063
+ #define QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION 0x0500000F // uint8_t (BOOLEAN)
1064
+ #endif
1065
+ #define QUIC_PARAM_CONN_RESUMPTION_TICKET 0x05000010 // uint8_t[]
1066
+ #define QUIC_PARAM_CONN_PEER_CERTIFICATE_VALID 0x05000011 // uint8_t (BOOLEAN)
1067
+ #define QUIC_PARAM_CONN_LOCAL_INTERFACE 0x05000012 // uint32_t
1068
+ #define QUIC_PARAM_CONN_TLS_SECRETS 0x05000013 // QUIC_TLS_SECRETS (SSLKEYLOGFILE compatible)
1069
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1070
+ #define QUIC_PARAM_CONN_VERSION_SETTINGS 0x05000014 // QUIC_VERSION_SETTINGS
1071
+ #define QUIC_PARAM_CONN_CIBIR_ID 0x05000015 // uint8_t[] {offset, id[]}
1072
+ #endif
1073
+ #define QUIC_PARAM_CONN_STATISTICS_V2 0x05000016 // QUIC_STATISTICS_V2
1074
+ #define QUIC_PARAM_CONN_STATISTICS_V2_PLAT 0x05000017 // QUIC_STATISTICS_V2
1075
+ #define QUIC_PARAM_CONN_ORIG_DEST_CID 0x05000018 // uint8_t[]
1076
+ #define QUIC_PARAM_CONN_SEND_DSCP 0x05000019 // uint8_t
1077
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1078
+ #define QUIC_PARAM_CONN_NETWORK_STATISTICS 0x05000020 // struct QUIC_NETWORK_STATISTICS
1079
+ #define QUIC_PARAM_CONN_CLOSE_ASYNC 0x0500001A // uint8_t
1080
+ #endif
1081
+
1082
+ //
1083
+ // Parameters for TLS.
1084
+ //
1085
+ #define QUIC_PARAM_TLS_HANDSHAKE_INFO 0x06000000 // QUIC_HANDSHAKE_INFO
1086
+ #define QUIC_PARAM_TLS_NEGOTIATED_ALPN 0x06000001 // uint8_t[] (max 255 bytes)
1087
+
1088
+ #ifdef WIN32 // Schannel specific TLS parameters
1089
+ typedef struct QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_W {
1090
+ unsigned long Attribute;
1091
+ void* Buffer;
1092
+ } QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_W;
1093
+ #define QUIC_PARAM_TLS_SCHANNEL_CONTEXT_ATTRIBUTE_W 0x07000000 // QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_W
1094
+ typedef struct QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_EX_W {
1095
+ unsigned long Attribute;
1096
+ unsigned long BufferLength;
1097
+ void* Buffer;
1098
+ } QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_EX_W;
1099
+ #define QUIC_PARAM_TLS_SCHANNEL_CONTEXT_ATTRIBUTE_EX_W 0x07000001 // QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_EX_W
1100
+ #define QUIC_PARAM_TLS_SCHANNEL_SECURITY_CONTEXT_TOKEN 0x07000002 // HANDLE
1101
+ #endif
1102
+
1103
+ //
1104
+ // Parameters for Stream.
1105
+ //
1106
+ #define QUIC_PARAM_STREAM_ID 0x08000000 // QUIC_UINT62
1107
+ #define QUIC_PARAM_STREAM_0RTT_LENGTH 0x08000001 // uint64_t
1108
+ #define QUIC_PARAM_STREAM_IDEAL_SEND_BUFFER_SIZE 0x08000002 // uint64_t - bytes
1109
+ #define QUIC_PARAM_STREAM_PRIORITY 0x08000003 // uint16_t - 0 (low) to 0xFFFF (high) - 0x7FFF (default)
1110
+ #define QUIC_PARAM_STREAM_STATISTICS 0X08000004 // QUIC_STREAM_STATISTICS
1111
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1112
+ #define QUIC_PARAM_STREAM_RELIABLE_OFFSET 0x08000005 // uint64_t
1113
+ #endif
1114
+
1115
+ typedef
1116
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1117
+ QUIC_STATUS
1118
+ (QUIC_API * QUIC_SET_PARAM_FN)(
1119
+ _When_(QUIC_PARAM_IS_GLOBAL(Param), _Reserved_)
1120
+ _When_(!QUIC_PARAM_IS_GLOBAL(Param), _In_ _Pre_defensive_)
1121
+ HQUIC Handle,
1122
+ _In_ uint32_t Param,
1123
+ _In_ uint32_t BufferLength,
1124
+ _In_reads_bytes_(BufferLength)
1125
+ const void* Buffer
1126
+ );
1127
+
1128
+ typedef
1129
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1130
+ QUIC_STATUS
1131
+ (QUIC_API * QUIC_GET_PARAM_FN)(
1132
+ _When_(QUIC_PARAM_IS_GLOBAL(Param), _Reserved_)
1133
+ _When_(!QUIC_PARAM_IS_GLOBAL(Param), _In_ _Pre_defensive_)
1134
+ HQUIC Handle,
1135
+ _In_ uint32_t Param,
1136
+ _Inout_ _Pre_defensive_ uint32_t* BufferLength,
1137
+ _Out_writes_bytes_opt_(*BufferLength)
1138
+ void* Buffer
1139
+ );
1140
+
1141
+ //
1142
+ // Registration Context Interface.
1143
+ //
1144
+
1145
+ //
1146
+ // Opens a new registration.
1147
+ //
1148
+ typedef
1149
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1150
+ QUIC_STATUS
1151
+ (QUIC_API * QUIC_REGISTRATION_OPEN_FN)(
1152
+ _In_opt_ const QUIC_REGISTRATION_CONFIG* Config,
1153
+ _Outptr_ _At_(*Registration, __drv_allocatesMem(Mem)) _Pre_defensive_
1154
+ HQUIC* Registration
1155
+ );
1156
+
1157
+ //
1158
+ // Closes the registration. This function synchronizes the cleanup of all
1159
+ // child objects. It does this by blocking until all those child objects have
1160
+ // been closed by the application.
1161
+ // N.B. This function will deadlock if called in any MsQuic callbacks.
1162
+ //
1163
+ typedef
1164
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1165
+ void
1166
+ (QUIC_API * QUIC_REGISTRATION_CLOSE_FN)(
1167
+ _In_ _Pre_defensive_ __drv_freesMem(Mem)
1168
+ HQUIC Registration
1169
+ );
1170
+
1171
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1172
+
1173
+ typedef
1174
+ _Function_class_(QUIC_REGISTRATION_CLOSE_CALLBACK)
1175
+ void
1176
+ (QUIC_API QUIC_REGISTRATION_CLOSE_CALLBACK)(
1177
+ _In_opt_ void* Context
1178
+ );
1179
+
1180
+ typedef QUIC_REGISTRATION_CLOSE_CALLBACK *QUIC_REGISTRATION_CLOSE_CALLBACK_HANDLER;
1181
+
1182
+ //
1183
+ // Closes the registration. This function synchronizes the cleanup of all child
1184
+ // objects. The callback handler is invoked once all those child objects have
1185
+ // been closed by the application.
1186
+ //
1187
+ typedef
1188
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1189
+ void
1190
+ (QUIC_API * QUIC_REGISTRATION_CLOSE2_FN)(
1191
+ _In_ _Pre_defensive_ __drv_freesMem(Mem)
1192
+ HQUIC Registration,
1193
+ _In_ _Pre_defensive_ QUIC_REGISTRATION_CLOSE_CALLBACK_HANDLER Handler,
1194
+ _In_opt_ void* Context
1195
+ );
1196
+
1197
+ #endif // QUIC_API_ENABLE_PREVIEW_FEATURES
1198
+
1199
+ //
1200
+ // Calls shutdown for all connections in this registration. Don't call on a
1201
+ // MsQuic callback thread or it might deadlock.
1202
+ //
1203
+ typedef
1204
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1205
+ void
1206
+ (QUIC_API * QUIC_REGISTRATION_SHUTDOWN_FN)(
1207
+ _In_ _Pre_defensive_ HQUIC Registration,
1208
+ _In_ QUIC_CONNECTION_SHUTDOWN_FLAGS Flags,
1209
+ _In_ _Pre_defensive_ QUIC_UINT62 ErrorCode // Application defined error code
1210
+ );
1211
+
1212
+ //
1213
+ // Configuration Interface.
1214
+ //
1215
+
1216
+ //
1217
+ // Opens a new configuration.
1218
+ //
1219
+ typedef
1220
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1221
+ QUIC_STATUS
1222
+ (QUIC_API * QUIC_CONFIGURATION_OPEN_FN)(
1223
+ _In_ _Pre_defensive_ HQUIC Registration,
1224
+ _In_reads_(AlpnBufferCount) _Pre_defensive_
1225
+ const QUIC_BUFFER* const AlpnBuffers,
1226
+ _In_range_(>, 0) uint32_t AlpnBufferCount,
1227
+ _In_reads_bytes_opt_(SettingsSize)
1228
+ const QUIC_SETTINGS* Settings,
1229
+ _In_ uint32_t SettingsSize,
1230
+ _In_opt_ void* Context,
1231
+ _Outptr_ _At_(*Configuration, __drv_allocatesMem(Mem)) _Pre_defensive_
1232
+ HQUIC* Configuration
1233
+ );
1234
+
1235
+ //
1236
+ // Closes an existing configuration.
1237
+ //
1238
+ typedef
1239
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1240
+ void
1241
+ (QUIC_API * QUIC_CONFIGURATION_CLOSE_FN)(
1242
+ _In_ _Pre_defensive_ __drv_freesMem(Mem)
1243
+ HQUIC Configuration
1244
+ );
1245
+
1246
+ //
1247
+ // Loads the credentials based on the input configuration.
1248
+ //
1249
+ typedef
1250
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1251
+ QUIC_STATUS
1252
+ (QUIC_API * QUIC_CONFIGURATION_LOAD_CREDENTIAL_FN)(
1253
+ _In_ _Pre_defensive_ HQUIC Configuration,
1254
+ _In_ _Pre_defensive_ const QUIC_CREDENTIAL_CONFIG* CredConfig
1255
+ );
1256
+
1257
+ //
1258
+ // Listener Context Interface.
1259
+ //
1260
+
1261
+ typedef enum QUIC_LISTENER_EVENT_TYPE {
1262
+ QUIC_LISTENER_EVENT_NEW_CONNECTION = 0,
1263
+ QUIC_LISTENER_EVENT_STOP_COMPLETE = 1,
1264
+ QUIC_LISTENER_EVENT_DOS_MODE_CHANGED = 2,
1265
+ } QUIC_LISTENER_EVENT_TYPE;
1266
+
1267
+ typedef struct QUIC_LISTENER_EVENT {
1268
+ QUIC_LISTENER_EVENT_TYPE Type;
1269
+ union {
1270
+ struct {
1271
+ const QUIC_NEW_CONNECTION_INFO* Info;
1272
+ HQUIC Connection;
1273
+ } NEW_CONNECTION;
1274
+ struct {
1275
+ BOOLEAN AppCloseInProgress : 1;
1276
+ BOOLEAN RESERVED : 7;
1277
+ } STOP_COMPLETE;
1278
+ struct {
1279
+ BOOLEAN DosModeEnabled : 1;
1280
+ BOOLEAN RESERVED : 7;
1281
+ } DOS_MODE_CHANGED;
1282
+ };
1283
+ } QUIC_LISTENER_EVENT;
1284
+
1285
+ typedef
1286
+ _When_(
1287
+ Event->Type != QUIC_LISTENER_EVENT_DOS_MODE_CHANGED,
1288
+ _IRQL_requires_max_(PASSIVE_LEVEL))
1289
+ _When_(
1290
+ Event->Type == QUIC_LISTENER_EVENT_DOS_MODE_CHANGED,
1291
+ _IRQL_requires_max_(DISPATCH_LEVEL))
1292
+ _Function_class_(QUIC_LISTENER_CALLBACK)
1293
+ QUIC_STATUS
1294
+ (QUIC_API QUIC_LISTENER_CALLBACK)(
1295
+ _In_ HQUIC Listener,
1296
+ _In_opt_ void* Context,
1297
+ _Inout_ QUIC_LISTENER_EVENT* Event
1298
+ );
1299
+
1300
+ typedef QUIC_LISTENER_CALLBACK *QUIC_LISTENER_CALLBACK_HANDLER;
1301
+
1302
+ //
1303
+ // Opens a new listener.
1304
+ //
1305
+ typedef
1306
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1307
+ QUIC_STATUS
1308
+ (QUIC_API * QUIC_LISTENER_OPEN_FN)(
1309
+ _In_ _Pre_defensive_ HQUIC Registration,
1310
+ _In_ _Pre_defensive_ QUIC_LISTENER_CALLBACK_HANDLER Handler,
1311
+ _In_opt_ void* Context,
1312
+ _Outptr_ _At_(*Listener, __drv_allocatesMem(Mem)) _Pre_defensive_
1313
+ HQUIC* Listener
1314
+ );
1315
+
1316
+ //
1317
+ // Closes an existing listener.
1318
+ //
1319
+ typedef
1320
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1321
+ void
1322
+ (QUIC_API * QUIC_LISTENER_CLOSE_FN)(
1323
+ _In_ _Pre_defensive_ __drv_freesMem(Mem)
1324
+ HQUIC Listener
1325
+ );
1326
+
1327
+ //
1328
+ // Starts the listener processing incoming connections.
1329
+ //
1330
+ typedef
1331
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1332
+ QUIC_STATUS
1333
+ (QUIC_API * QUIC_LISTENER_START_FN)(
1334
+ _In_ _Pre_defensive_ HQUIC Listener,
1335
+ _In_reads_(AlpnBufferCount) _Pre_defensive_
1336
+ const QUIC_BUFFER* const AlpnBuffers,
1337
+ _In_range_(>, 0) uint32_t AlpnBufferCount,
1338
+ _In_opt_ const QUIC_ADDR* LocalAddress
1339
+ );
1340
+
1341
+ //
1342
+ // Asynchronously stops the listener from processing incoming connections.
1343
+ //
1344
+ typedef
1345
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1346
+ void
1347
+ (QUIC_API * QUIC_LISTENER_STOP_FN)(
1348
+ _In_ _Pre_defensive_ HQUIC Listener
1349
+ );
1350
+
1351
+ //
1352
+ // Connections
1353
+ //
1354
+
1355
+ typedef enum QUIC_CONNECTION_EVENT_TYPE {
1356
+ QUIC_CONNECTION_EVENT_CONNECTED = 0,
1357
+ QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_TRANSPORT = 1, // The transport started the shutdown process.
1358
+ QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_PEER = 2, // The peer application started the shutdown process.
1359
+ QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE = 3, // Ready for the handle to be closed.
1360
+ QUIC_CONNECTION_EVENT_LOCAL_ADDRESS_CHANGED = 4,
1361
+ QUIC_CONNECTION_EVENT_PEER_ADDRESS_CHANGED = 5,
1362
+ QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED = 6,
1363
+ QUIC_CONNECTION_EVENT_STREAMS_AVAILABLE = 7,
1364
+ QUIC_CONNECTION_EVENT_PEER_NEEDS_STREAMS = 8,
1365
+ QUIC_CONNECTION_EVENT_IDEAL_PROCESSOR_CHANGED = 9,
1366
+ QUIC_CONNECTION_EVENT_DATAGRAM_STATE_CHANGED = 10,
1367
+ QUIC_CONNECTION_EVENT_DATAGRAM_RECEIVED = 11,
1368
+ QUIC_CONNECTION_EVENT_DATAGRAM_SEND_STATE_CHANGED = 12,
1369
+ QUIC_CONNECTION_EVENT_RESUMED = 13, // Server-only; provides resumption data, if any.
1370
+ QUIC_CONNECTION_EVENT_RESUMPTION_TICKET_RECEIVED = 14, // Client-only; provides ticket to persist, if any.
1371
+ QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED = 15, // Only with QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED set
1372
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1373
+ QUIC_CONNECTION_EVENT_RELIABLE_RESET_NEGOTIATED = 16, // Only indicated if QUIC_SETTINGS.ReliableResetEnabled is TRUE.
1374
+ QUIC_CONNECTION_EVENT_ONE_WAY_DELAY_NEGOTIATED = 17, // Only indicated if QUIC_SETTINGS.OneWayDelayEnabled is TRUE.
1375
+ QUIC_CONNECTION_EVENT_NETWORK_STATISTICS = 18, // Only indicated if QUIC_SETTINGS.EnableNetStatsEvent is TRUE.
1376
+ #endif
1377
+ } QUIC_CONNECTION_EVENT_TYPE;
1378
+
1379
+ typedef struct QUIC_CONNECTION_EVENT {
1380
+ QUIC_CONNECTION_EVENT_TYPE Type;
1381
+ union {
1382
+ struct {
1383
+ BOOLEAN SessionResumed;
1384
+ _Field_range_(>, 0)
1385
+ uint8_t NegotiatedAlpnLength;
1386
+ _Field_size_(NegotiatedAlpnLength)
1387
+ const uint8_t* NegotiatedAlpn;
1388
+ } CONNECTED;
1389
+ struct {
1390
+ QUIC_STATUS Status;
1391
+ QUIC_UINT62 ErrorCode; // Wire format error code.
1392
+ } SHUTDOWN_INITIATED_BY_TRANSPORT;
1393
+ struct {
1394
+ QUIC_UINT62 ErrorCode;
1395
+ } SHUTDOWN_INITIATED_BY_PEER;
1396
+ struct {
1397
+ BOOLEAN HandshakeCompleted : 1;
1398
+ BOOLEAN PeerAcknowledgedShutdown : 1;
1399
+ BOOLEAN AppCloseInProgress : 1;
1400
+ } SHUTDOWN_COMPLETE;
1401
+ struct {
1402
+ const QUIC_ADDR* Address;
1403
+ } LOCAL_ADDRESS_CHANGED;
1404
+ struct {
1405
+ const QUIC_ADDR* Address;
1406
+ } PEER_ADDRESS_CHANGED;
1407
+ struct {
1408
+ HQUIC Stream;
1409
+ QUIC_STREAM_OPEN_FLAGS Flags;
1410
+ } PEER_STREAM_STARTED;
1411
+ struct {
1412
+ uint16_t BidirectionalCount;
1413
+ uint16_t UnidirectionalCount;
1414
+ } STREAMS_AVAILABLE;
1415
+ struct {
1416
+ BOOLEAN Bidirectional;
1417
+ } PEER_NEEDS_STREAMS;
1418
+ struct {
1419
+ uint16_t IdealProcessor;
1420
+ uint16_t PartitionIndex;
1421
+ } IDEAL_PROCESSOR_CHANGED;
1422
+ struct {
1423
+ BOOLEAN SendEnabled;
1424
+ uint16_t MaxSendLength;
1425
+ } DATAGRAM_STATE_CHANGED;
1426
+ struct {
1427
+ const QUIC_BUFFER* Buffer;
1428
+ QUIC_RECEIVE_FLAGS Flags;
1429
+ } DATAGRAM_RECEIVED;
1430
+ struct {
1431
+ /* inout */ void* ClientContext;
1432
+ QUIC_DATAGRAM_SEND_STATE State;
1433
+ } DATAGRAM_SEND_STATE_CHANGED;
1434
+ struct {
1435
+ uint16_t ResumptionStateLength;
1436
+ const uint8_t* ResumptionState;
1437
+ } RESUMED;
1438
+ struct {
1439
+ _Field_range_(>, 0)
1440
+ uint32_t ResumptionTicketLength;
1441
+ _Field_size_(ResumptionTicketLength)
1442
+ const uint8_t* ResumptionTicket;
1443
+ } RESUMPTION_TICKET_RECEIVED;
1444
+ struct {
1445
+ QUIC_CERTIFICATE* Certificate; // Peer certificate (platform specific). Valid only during QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED callback.
1446
+ uint32_t DeferredErrorFlags; // Bit flag of errors (only valid with QUIC_CREDENTIAL_FLAG_DEFER_CERTIFICATE_VALIDATION) - Schannel only, zero otherwise.
1447
+ QUIC_STATUS DeferredStatus; // Most severe error status (only valid with QUIC_CREDENTIAL_FLAG_DEFER_CERTIFICATE_VALIDATION)
1448
+ QUIC_CERTIFICATE_CHAIN* Chain; // Peer certificate chain (platform specific). Valid only during QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED callback.
1449
+ } PEER_CERTIFICATE_RECEIVED;
1450
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1451
+ struct {
1452
+ BOOLEAN IsNegotiated;
1453
+ } RELIABLE_RESET_NEGOTIATED;
1454
+ struct {
1455
+ BOOLEAN SendNegotiated; // TRUE if sending one-way delay timestamps is negotiated.
1456
+ BOOLEAN ReceiveNegotiated; // TRUE if receiving one-way delay timestamps is negotiated.
1457
+ } ONE_WAY_DELAY_NEGOTIATED;
1458
+ QUIC_NETWORK_STATISTICS NETWORK_STATISTICS;
1459
+ #endif
1460
+ };
1461
+ } QUIC_CONNECTION_EVENT;
1462
+
1463
+ typedef
1464
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1465
+ _Function_class_(QUIC_CONNECTION_CALLBACK)
1466
+ QUIC_STATUS
1467
+ (QUIC_API QUIC_CONNECTION_CALLBACK)(
1468
+ _In_ HQUIC Connection,
1469
+ _In_opt_ void* Context,
1470
+ _Inout_ QUIC_CONNECTION_EVENT* Event
1471
+ );
1472
+
1473
+ typedef QUIC_CONNECTION_CALLBACK *QUIC_CONNECTION_CALLBACK_HANDLER;
1474
+
1475
+ //
1476
+ // Opens a new connection.
1477
+ //
1478
+ typedef
1479
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1480
+ QUIC_STATUS
1481
+ (QUIC_API * QUIC_CONNECTION_OPEN_FN)(
1482
+ _In_ _Pre_defensive_ HQUIC Registration,
1483
+ _In_ _Pre_defensive_ QUIC_CONNECTION_CALLBACK_HANDLER Handler,
1484
+ _In_opt_ void* Context,
1485
+ _Outptr_ _At_(*Connection, __drv_allocatesMem(Mem)) _Pre_defensive_
1486
+ HQUIC* Connection
1487
+ );
1488
+ typedef
1489
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1490
+ QUIC_STATUS
1491
+ (QUIC_API * QUIC_CONNECTION_OPEN_IN_PARTITION_FN)(
1492
+ _In_ _Pre_defensive_ HQUIC Registration,
1493
+ _In_ uint16_t PartitionIndex,
1494
+ _In_ _Pre_defensive_ QUIC_CONNECTION_CALLBACK_HANDLER Handler,
1495
+ _In_opt_ void* Context,
1496
+ _Outptr_ _At_(*Connection, __drv_allocatesMem(Mem)) _Pre_defensive_
1497
+ HQUIC* Connection
1498
+ );
1499
+
1500
+ //
1501
+ // Closes an existing connection.
1502
+ //
1503
+ typedef
1504
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1505
+ void
1506
+ (QUIC_API * QUIC_CONNECTION_CLOSE_FN)(
1507
+ _In_ _Pre_defensive_ __drv_freesMem(Mem)
1508
+ HQUIC Connection
1509
+ );
1510
+
1511
+ //
1512
+ // Starts the shutdown process on the connection. This immediately and silently
1513
+ // shuts down any open streams; which will trigger callbacks for
1514
+ // QUIC_CONNECTION_EVENT_STREAM_CLOSED events. Does nothing if already shutdown.
1515
+ // Can be passed either a connection or stream handle.
1516
+ //
1517
+ typedef
1518
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1519
+ void
1520
+ (QUIC_API * QUIC_CONNECTION_SHUTDOWN_FN)(
1521
+ _In_ _Pre_defensive_ HQUIC Connection,
1522
+ _In_ QUIC_CONNECTION_SHUTDOWN_FLAGS Flags,
1523
+ _In_ _Pre_defensive_ QUIC_UINT62 ErrorCode // Application defined error code
1524
+ );
1525
+
1526
+ //
1527
+ // Uses the QUIC (client) handle to start a connection attempt to the
1528
+ // remote server. Can be passed either a connection or stream handle.
1529
+ //
1530
+ typedef
1531
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1532
+ QUIC_STATUS
1533
+ (QUIC_API * QUIC_CONNECTION_START_FN)(
1534
+ _In_ _Pre_defensive_ HQUIC Connection,
1535
+ _In_ _Pre_defensive_ HQUIC Configuration,
1536
+ _In_ QUIC_ADDRESS_FAMILY Family,
1537
+ _In_reads_or_z_opt_(QUIC_MAX_SNI_LENGTH)
1538
+ const char* ServerName,
1539
+ _In_ uint16_t ServerPort // Host byte order
1540
+ );
1541
+
1542
+ //
1543
+ // Sets the (server-side) configuration handle for the connection. This must be
1544
+ // called on an accepted connection in order to proceed with the QUIC handshake.
1545
+ //
1546
+ typedef
1547
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1548
+ QUIC_STATUS
1549
+ (QUIC_API * QUIC_CONNECTION_SET_CONFIGURATION_FN)(
1550
+ _In_ _Pre_defensive_ HQUIC Connection,
1551
+ _In_ _Pre_defensive_ HQUIC Configuration
1552
+ );
1553
+
1554
+ //
1555
+ // Uses the QUIC (server) handle to send a resumption ticket to the remote
1556
+ // client, optionally with app-specific data useful during resumption.
1557
+ //
1558
+ typedef
1559
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1560
+ QUIC_STATUS
1561
+ (QUIC_API * QUIC_CONNECTION_SEND_RESUMPTION_FN)(
1562
+ _In_ _Pre_defensive_ HQUIC Connection,
1563
+ _In_ QUIC_SEND_RESUMPTION_FLAGS Flags,
1564
+ _In_ uint16_t DataLength,
1565
+ _In_reads_bytes_opt_(DataLength)
1566
+ const uint8_t* ResumptionData
1567
+ );
1568
+
1569
+ //
1570
+ // Uses the QUIC (server) handle to complete resumption ticket validation.
1571
+ // This must be called after server app handles ticket validation and then
1572
+ // return QUIC_STATUS_PENDING.
1573
+ //
1574
+ typedef
1575
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1576
+ QUIC_STATUS
1577
+ (QUIC_API * QUIC_CONNECTION_COMP_RESUMPTION_FN)(
1578
+ _In_ _Pre_defensive_ HQUIC Connection,
1579
+ _In_ BOOLEAN Result
1580
+ );
1581
+
1582
+ //
1583
+ // Uses the QUIC (client) handle to complete certificate validation.
1584
+ // This must be called after client app handles certificate validation
1585
+ // and then return QUIC_STATUS_PENDING. The TlsAlert value is ignored if Result
1586
+ // equals TRUE (recommend just pass QUIC_TLS_ALERT_CODE_SUCCESS).
1587
+ //
1588
+ typedef
1589
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1590
+ QUIC_STATUS
1591
+ (QUIC_API * QUIC_CONNECTION_COMP_CERT_FN)(
1592
+ _In_ _Pre_defensive_ HQUIC Connection,
1593
+ _In_ BOOLEAN Result,
1594
+ _In_ QUIC_TLS_ALERT_CODES TlsAlert
1595
+ );
1596
+
1597
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1598
+
1599
+ typedef struct QUIC_KEYING_MATERIAL_CONFIG {
1600
+ _Field_z_ const char* Label;
1601
+ uint32_t ContextLength;
1602
+ _Field_size_bytes_opt_(ContextLength) const uint8_t* Context;
1603
+ uint32_t OutputLength;
1604
+ } QUIC_KEYING_MATERIAL_CONFIG;
1605
+
1606
+ //
1607
+ // Exports keying material derived from the connection's TLS session.
1608
+ // The connection's handshake must be complete and the TLS context still alive.
1609
+ //
1610
+ typedef
1611
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1612
+ QUIC_STATUS
1613
+ (QUIC_API * QUIC_CONNECTION_EXPORT_KEYING_MATERIAL_FN)(
1614
+ _In_ _Pre_defensive_ HQUIC Connection,
1615
+ _In_ _Pre_defensive_ const QUIC_KEYING_MATERIAL_CONFIG* Config,
1616
+ _Out_writes_bytes_(Config->OutputLength)
1617
+ uint8_t* Output
1618
+ );
1619
+ #endif // QUIC_API_ENABLE_PREVIEW_FEATURES
1620
+
1621
+ //
1622
+ // Streams
1623
+ //
1624
+
1625
+ typedef enum QUIC_STREAM_EVENT_TYPE {
1626
+ QUIC_STREAM_EVENT_START_COMPLETE = 0,
1627
+ QUIC_STREAM_EVENT_RECEIVE = 1,
1628
+ QUIC_STREAM_EVENT_SEND_COMPLETE = 2,
1629
+ QUIC_STREAM_EVENT_PEER_SEND_SHUTDOWN = 3,
1630
+ QUIC_STREAM_EVENT_PEER_SEND_ABORTED = 4,
1631
+ QUIC_STREAM_EVENT_PEER_RECEIVE_ABORTED = 5,
1632
+ QUIC_STREAM_EVENT_SEND_SHUTDOWN_COMPLETE = 6,
1633
+ QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE = 7,
1634
+ QUIC_STREAM_EVENT_IDEAL_SEND_BUFFER_SIZE = 8,
1635
+ QUIC_STREAM_EVENT_PEER_ACCEPTED = 9,
1636
+ QUIC_STREAM_EVENT_CANCEL_ON_LOSS = 10,
1637
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1638
+ QUIC_STREAM_EVENT_RECEIVE_BUFFER_NEEDED = 11,
1639
+ #endif
1640
+ } QUIC_STREAM_EVENT_TYPE;
1641
+
1642
+ typedef struct QUIC_STREAM_EVENT {
1643
+ QUIC_STREAM_EVENT_TYPE Type;
1644
+ union {
1645
+ struct {
1646
+ QUIC_STATUS Status;
1647
+ QUIC_UINT62 ID;
1648
+ BOOLEAN PeerAccepted : 1;
1649
+ BOOLEAN RESERVED : 7;
1650
+ } START_COMPLETE;
1651
+ struct {
1652
+ /* in */ uint64_t AbsoluteOffset;
1653
+ /* inout */ uint64_t TotalBufferLength;
1654
+ _Field_size_(BufferCount)
1655
+ /* in */ const QUIC_BUFFER* Buffers;
1656
+ _Field_range_(0, UINT32_MAX)
1657
+ /* in */ uint32_t BufferCount;
1658
+ /* in */ QUIC_RECEIVE_FLAGS Flags;
1659
+ } RECEIVE;
1660
+ struct {
1661
+ BOOLEAN Canceled;
1662
+ void* ClientContext;
1663
+ } SEND_COMPLETE;
1664
+ struct {
1665
+ QUIC_UINT62 ErrorCode;
1666
+ } PEER_SEND_ABORTED;
1667
+ struct {
1668
+ QUIC_UINT62 ErrorCode;
1669
+ } PEER_RECEIVE_ABORTED;
1670
+ struct {
1671
+ BOOLEAN Graceful;
1672
+ } SEND_SHUTDOWN_COMPLETE;
1673
+ struct {
1674
+ BOOLEAN ConnectionShutdown;
1675
+ BOOLEAN AppCloseInProgress : 1;
1676
+ BOOLEAN ConnectionShutdownByApp : 1;
1677
+ BOOLEAN ConnectionClosedRemotely : 1;
1678
+ BOOLEAN RESERVED : 5;
1679
+ QUIC_UINT62 ConnectionErrorCode;
1680
+ QUIC_STATUS ConnectionCloseStatus;
1681
+ } SHUTDOWN_COMPLETE;
1682
+ struct {
1683
+ uint64_t ByteCount;
1684
+ } IDEAL_SEND_BUFFER_SIZE;
1685
+ struct {
1686
+ /* out */ QUIC_UINT62 ErrorCode;
1687
+ } CANCEL_ON_LOSS;
1688
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1689
+ struct {
1690
+ /* in */ uint64_t BufferLengthNeeded;
1691
+ } RECEIVE_BUFFER_NEEDED;
1692
+ #endif
1693
+ };
1694
+ } QUIC_STREAM_EVENT;
1695
+
1696
+ typedef
1697
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1698
+ _Function_class_(QUIC_STREAM_CALLBACK)
1699
+ QUIC_STATUS
1700
+ (QUIC_API QUIC_STREAM_CALLBACK)(
1701
+ _In_ HQUIC Stream,
1702
+ _In_opt_ void* Context,
1703
+ _Inout_ QUIC_STREAM_EVENT* Event
1704
+ );
1705
+
1706
+ typedef QUIC_STREAM_CALLBACK *QUIC_STREAM_CALLBACK_HANDLER;
1707
+
1708
+ //
1709
+ // Opens a stream on the given connection.
1710
+ //
1711
+ typedef
1712
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1713
+ QUIC_STATUS
1714
+ (QUIC_API * QUIC_STREAM_OPEN_FN)(
1715
+ _In_ _Pre_defensive_ HQUIC Connection,
1716
+ _In_ QUIC_STREAM_OPEN_FLAGS Flags,
1717
+ _In_ _Pre_defensive_ QUIC_STREAM_CALLBACK_HANDLER Handler,
1718
+ _In_opt_ void* Context,
1719
+ _Outptr_ _At_(*Stream, __drv_allocatesMem(Mem)) _Pre_defensive_
1720
+ HQUIC* Stream
1721
+ );
1722
+
1723
+ //
1724
+ // Closes a stream handle.
1725
+ //
1726
+ typedef
1727
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1728
+ void
1729
+ (QUIC_API * QUIC_STREAM_CLOSE_FN)(
1730
+ _In_ _Pre_defensive_ __drv_freesMem(Mem)
1731
+ HQUIC Stream
1732
+ );
1733
+
1734
+ //
1735
+ // Starts processing the stream.
1736
+ //
1737
+ typedef
1738
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1739
+ QUIC_STATUS
1740
+ (QUIC_API * QUIC_STREAM_START_FN)(
1741
+ _In_ _Pre_defensive_ HQUIC Stream,
1742
+ _In_ QUIC_STREAM_START_FLAGS Flags
1743
+ );
1744
+
1745
+ //
1746
+ // Shuts the stream down as specified, and waits for graceful
1747
+ // shutdowns to complete. Does nothing if already shut down.
1748
+ //
1749
+ typedef
1750
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1751
+ QUIC_STATUS
1752
+ (QUIC_API * QUIC_STREAM_SHUTDOWN_FN)(
1753
+ _In_ _Pre_defensive_ HQUIC Stream,
1754
+ _In_ QUIC_STREAM_SHUTDOWN_FLAGS Flags,
1755
+ _In_ _Pre_defensive_ QUIC_UINT62 ErrorCode // Application defined error code
1756
+ );
1757
+
1758
+ //
1759
+ // Sends data on an open stream.
1760
+ //
1761
+ typedef
1762
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1763
+ QUIC_STATUS
1764
+ (QUIC_API * QUIC_STREAM_SEND_FN)(
1765
+ _In_ _Pre_defensive_ HQUIC Stream,
1766
+ _In_reads_(BufferCount) _Pre_defensive_
1767
+ const QUIC_BUFFER* const Buffers,
1768
+ _In_ uint32_t BufferCount,
1769
+ _In_ QUIC_SEND_FLAGS Flags,
1770
+ _In_opt_ void* ClientSendContext
1771
+ );
1772
+
1773
+ //
1774
+ // Completes a previously pended receive callback.
1775
+ //
1776
+ typedef
1777
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1778
+ void
1779
+ (QUIC_API * QUIC_STREAM_RECEIVE_COMPLETE_FN)(
1780
+ _In_ _Pre_defensive_ HQUIC Stream,
1781
+ _In_ uint64_t BufferLength
1782
+ );
1783
+
1784
+ //
1785
+ // Enables or disables stream receive callbacks.
1786
+ //
1787
+ typedef
1788
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1789
+ QUIC_STATUS
1790
+ (QUIC_API * QUIC_STREAM_RECEIVE_SET_ENABLED_FN)(
1791
+ _In_ _Pre_defensive_ HQUIC Stream,
1792
+ _In_ BOOLEAN IsEnabled
1793
+ );
1794
+
1795
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1796
+ //
1797
+ // Provides receive buffers to the stream.
1798
+ // The buffers are owned by the caller and must remain valid until a receive
1799
+ // indication for all bytes in the buffer, or the stream is closed.
1800
+ //
1801
+ typedef
1802
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1803
+ QUIC_STATUS
1804
+ (QUIC_API * QUIC_STREAM_PROVIDE_RECEIVE_BUFFERS_FN)(
1805
+ _In_ _Pre_defensive_ HQUIC Stream,
1806
+ _In_ uint32_t BufferCount,
1807
+ _In_reads_(BufferCount) const QUIC_BUFFER* Buffers
1808
+ );
1809
+
1810
+ #endif
1811
+
1812
+ //
1813
+ // Datagrams
1814
+ //
1815
+
1816
+ //
1817
+ // Sends an unreliable datagram on the connection. Note, the total payload
1818
+ // of the send must fit in a single QUIC packet.
1819
+ //
1820
+ typedef
1821
+ _IRQL_requires_max_(DISPATCH_LEVEL)
1822
+ QUIC_STATUS
1823
+ (QUIC_API * QUIC_DATAGRAM_SEND_FN)(
1824
+ _In_ _Pre_defensive_ HQUIC Connection,
1825
+ _In_reads_(BufferCount) _Pre_defensive_
1826
+ const QUIC_BUFFER* const Buffers,
1827
+ _In_ uint32_t BufferCount,
1828
+ _In_ QUIC_SEND_FLAGS Flags,
1829
+ _In_opt_ void* ClientSendContext
1830
+ );
1831
+
1832
+ //
1833
+ // Connection Pool API
1834
+ //
1835
+
1836
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1837
+
1838
+ typedef enum QUIC_CONNECTION_POOL_FLAGS {
1839
+ QUIC_CONNECTION_POOL_FLAG_NONE = 0x00000000,
1840
+ QUIC_CONNECTION_POOL_FLAG_CLOSE_ON_FAILURE = 0x00000001,
1841
+ } QUIC_CONNECTION_POOL_FLAGS;
1842
+
1843
+ DEFINE_ENUM_FLAG_OPERATORS(QUIC_CONNECTION_POOL_FLAGS);
1844
+
1845
+ typedef struct QUIC_CONNECTION_POOL_CONFIG {
1846
+ HQUIC Registration;
1847
+ HQUIC Configuration;
1848
+ QUIC_CONNECTION_CALLBACK_HANDLER Handler;
1849
+ _Field_size_opt_(NumberOfConnections)
1850
+ void** Context; // Optional
1851
+ _Field_z_ const char* ServerName;
1852
+ const QUIC_ADDR* ServerAddress; // Optional
1853
+ QUIC_ADDRESS_FAMILY Family;
1854
+ uint16_t ServerPort;
1855
+ uint16_t NumberOfConnections;
1856
+ _At_buffer_(_Curr_, _Iter_, NumberOfConnections, _Field_size_(CibirIdLength))
1857
+ _Field_size_opt_(NumberOfConnections)
1858
+ uint8_t** CibirIds; // Optional
1859
+ uint8_t CibirIdLength; // Zero if not using CIBIR
1860
+ QUIC_CONNECTION_POOL_FLAGS Flags;
1861
+ } QUIC_CONNECTION_POOL_CONFIG;
1862
+
1863
+ //
1864
+ // Creates a simple pool of NumberOfConnections connections, all with the same
1865
+ // Handler, and puts them in the caller-supplied array.
1866
+ // Connections are spread evenly across RSS CPUs as much as possible.
1867
+ // If NumberOfConnections is more than the number of RSS cores, then multiple
1868
+ // connections will be put on the same CPU.
1869
+ //
1870
+ typedef
1871
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1872
+ QUIC_STATUS
1873
+ (QUIC_API * QUIC_CONN_POOL_CREATE_FN)(
1874
+ _In_ QUIC_CONNECTION_POOL_CONFIG* Config,
1875
+ _Out_writes_(Config->NumberOfConnections)
1876
+ HQUIC* ConnectionPool
1877
+ );
1878
+
1879
+ #endif // QUIC_API_ENABLE_PREVIEW_FEATURES
1880
+
1881
+ //
1882
+ // Version 2 API Function Table. Returned from MsQuicOpenVersion when Version
1883
+ // is 2. Also returned from MsQuicOpen2.
1884
+ //
1885
+ typedef struct QUIC_API_TABLE {
1886
+
1887
+ QUIC_SET_CONTEXT_FN SetContext;
1888
+ QUIC_GET_CONTEXT_FN GetContext;
1889
+ QUIC_SET_CALLBACK_HANDLER_FN SetCallbackHandler;
1890
+
1891
+ QUIC_SET_PARAM_FN SetParam;
1892
+ QUIC_GET_PARAM_FN GetParam;
1893
+
1894
+ QUIC_REGISTRATION_OPEN_FN RegistrationOpen;
1895
+ QUIC_REGISTRATION_CLOSE_FN RegistrationClose;
1896
+ QUIC_REGISTRATION_SHUTDOWN_FN RegistrationShutdown;
1897
+
1898
+ QUIC_CONFIGURATION_OPEN_FN ConfigurationOpen;
1899
+ QUIC_CONFIGURATION_CLOSE_FN ConfigurationClose;
1900
+ QUIC_CONFIGURATION_LOAD_CREDENTIAL_FN
1901
+ ConfigurationLoadCredential;
1902
+
1903
+ QUIC_LISTENER_OPEN_FN ListenerOpen;
1904
+ QUIC_LISTENER_CLOSE_FN ListenerClose;
1905
+ QUIC_LISTENER_START_FN ListenerStart;
1906
+ QUIC_LISTENER_STOP_FN ListenerStop;
1907
+
1908
+ QUIC_CONNECTION_OPEN_FN ConnectionOpen;
1909
+ QUIC_CONNECTION_CLOSE_FN ConnectionClose;
1910
+ QUIC_CONNECTION_SHUTDOWN_FN ConnectionShutdown;
1911
+ QUIC_CONNECTION_START_FN ConnectionStart;
1912
+ QUIC_CONNECTION_SET_CONFIGURATION_FN
1913
+ ConnectionSetConfiguration;
1914
+ QUIC_CONNECTION_SEND_RESUMPTION_FN ConnectionSendResumptionTicket;
1915
+
1916
+ QUIC_STREAM_OPEN_FN StreamOpen;
1917
+ QUIC_STREAM_CLOSE_FN StreamClose;
1918
+ QUIC_STREAM_START_FN StreamStart;
1919
+ QUIC_STREAM_SHUTDOWN_FN StreamShutdown;
1920
+ QUIC_STREAM_SEND_FN StreamSend;
1921
+ QUIC_STREAM_RECEIVE_COMPLETE_FN StreamReceiveComplete;
1922
+ QUIC_STREAM_RECEIVE_SET_ENABLED_FN StreamReceiveSetEnabled;
1923
+
1924
+ QUIC_DATAGRAM_SEND_FN DatagramSend;
1925
+
1926
+ QUIC_CONNECTION_COMP_RESUMPTION_FN ConnectionResumptionTicketValidationComplete; // Available from v2.2
1927
+ QUIC_CONNECTION_COMP_CERT_FN ConnectionCertificateValidationComplete; // Available from v2.2
1928
+
1929
+ QUIC_CONNECTION_OPEN_IN_PARTITION_FN
1930
+ ConnectionOpenInPartition; // Available from v2.5
1931
+
1932
+ #ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
1933
+ QUIC_STREAM_PROVIDE_RECEIVE_BUFFERS_FN
1934
+ StreamProvideReceiveBuffers; // Available from v2.5
1935
+
1936
+ QUIC_CONN_POOL_CREATE_FN ConnectionPoolCreate; // Available from v2.5
1937
+
1938
+ #ifndef _KERNEL_MODE
1939
+ #define QUIC_API_EXECUTION_CONTEXT
1940
+ QUIC_EXECUTION_CREATE_FN ExecutionCreate; // Available from v2.5
1941
+ QUIC_EXECUTION_DELETE_FN ExecutionDelete; // Available from v2.5
1942
+ QUIC_EXECUTION_POLL_FN ExecutionPoll; // Available from v2.5
1943
+ #endif // _KERNEL_MODE
1944
+ QUIC_REGISTRATION_CLOSE2_FN RegistrationClose2; // Available from v2.6
1945
+
1946
+ QUIC_CONNECTION_EXPORT_KEYING_MATERIAL_FN
1947
+ ConnectionExportKeyingMaterial; // Available from v2.6
1948
+ #endif // QUIC_API_ENABLE_PREVIEW_FEATURES
1949
+
1950
+ } QUIC_API_TABLE;
1951
+
1952
+ #define QUIC_API_VERSION_1 1 // Not supported any more
1953
+ #define QUIC_API_VERSION_2 2 // Current latest
1954
+
1955
+ #if defined(_KERNEL_MODE) && !defined(_WIN64)
1956
+
1957
+ //
1958
+ // 32 bit kernel mode is no longer supported, so shim behavior in 32 bit kernel
1959
+ // mode
1960
+ //
1961
+ #define MsQuicClose(QuicApi) UNREFERENCED_PARAMETER((QuicApi))
1962
+ #define MsQuicOpenVersion(Version, QuicApi) QUIC_STATUS_NOT_SUPPORTED
1963
+
1964
+ #else
1965
+
1966
+ //
1967
+ // Opens the API library and initializes it if this is the first call for the
1968
+ // process. It returns API function table for the rest of the API's functions.
1969
+ // MsQuicClose must be called when the app is done with the function table.
1970
+ //
1971
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1972
+ _Check_return_
1973
+ #if (__cplusplus >= 201703L || _MSVC_LANG >= 201703L)
1974
+ [[nodiscard]]
1975
+ #endif
1976
+ QUIC_STATUS
1977
+ QUIC_API
1978
+ MsQuicOpenVersion(
1979
+ _In_ uint32_t Version,
1980
+ _Out_ _Pre_defensive_ const void** QuicApi
1981
+ );
1982
+
1983
+ //
1984
+ // Cleans up the function table returned from MsQuicOpenVersion and releases the
1985
+ // reference on the API.
1986
+ //
1987
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1988
+ void
1989
+ QUIC_API
1990
+ MsQuicClose(
1991
+ _In_ _Pre_defensive_ const void* QuicApi
1992
+ );
1993
+
1994
+ #endif
1995
+
1996
+ _IRQL_requires_max_(PASSIVE_LEVEL)
1997
+ _Check_return_
1998
+ typedef
1999
+ QUIC_STATUS
2000
+ (QUIC_API *MsQuicOpenVersionFn)(
2001
+ _In_ uint32_t Version,
2002
+ _Out_ _Pre_defensive_ const void** QuicApi
2003
+ );
2004
+
2005
+ _IRQL_requires_max_(PASSIVE_LEVEL)
2006
+ typedef
2007
+ void
2008
+ (QUIC_API *MsQuicCloseFn)(
2009
+ _In_ _Pre_defensive_ const void* QuicApi
2010
+ );
2011
+
2012
+ #ifdef _KERNEL_MODE
2013
+
2014
+ DECLSPEC_SELECTANY GUID MSQUIC_NPI_ID = {
2015
+ 0xC43138E3, 0xCD13, 0x4CB1, { 0x9C, 0xAE, 0xE0, 0x05, 0xC8, 0x55, 0x7A, 0xBA }
2016
+ }; // C43138E3-CD13-4CB1-9CAE-E005C8557ABA
2017
+
2018
+ DECLSPEC_SELECTANY GUID MSQUIC_MODULE_ID = {
2019
+ 0x698F7C72, 0xC2E6, 0x49CD, { 0x8C, 0x39, 0x98, 0x85, 0x1D, 0x50, 0x19, 0x01 }
2020
+ }; // 698F7C72-C2E6-49CD-8C39-98851D501901
2021
+
2022
+ typedef struct MSQUIC_NMR_DISPATCH {
2023
+ uint16_t Version;
2024
+ uint16_t Reserved;
2025
+ MsQuicOpenVersionFn OpenVersion;
2026
+ MsQuicCloseFn Close;
2027
+ } MSQUIC_NMR_DISPATCH;
2028
+
2029
+ //
2030
+ // Stores the internal NMR client state. It's meant to be opaque to the users.
2031
+ //
2032
+ typedef struct __MSQUIC_NMR_CLIENT {
2033
+ NPI_CLIENT_CHARACTERISTICS NpiClientCharacteristics;
2034
+ LONG BindingCount;
2035
+ HANDLE NmrClientHandle;
2036
+ NPI_MODULEID ModuleId;
2037
+ KEVENT RegistrationCompleteEvent;
2038
+ MSQUIC_NMR_DISPATCH* ProviderDispatch;
2039
+ BOOLEAN Deleting;
2040
+ } __MSQUIC_NMR_CLIENT;
2041
+
2042
+ #define QUIC_GET_DISPATCH(h) (((__MSQUIC_NMR_CLIENT*)(h))->ProviderDispatch)
2043
+
2044
+ static
2045
+ NTSTATUS
2046
+ __MsQuicClientAttachProvider(
2047
+ _In_ HANDLE NmrBindingHandle,
2048
+ _In_ void *ClientContext,
2049
+ _In_ const NPI_REGISTRATION_INSTANCE *ProviderRegistrationInstance
2050
+ )
2051
+ {
2052
+ UNREFERENCED_PARAMETER(ProviderRegistrationInstance);
2053
+
2054
+ NTSTATUS Status;
2055
+ __MSQUIC_NMR_CLIENT* Client = (__MSQUIC_NMR_CLIENT*)ClientContext;
2056
+ void* ProviderContext;
2057
+
2058
+ if (InterlockedIncrement(&Client->BindingCount) == 1) {
2059
+ #pragma warning(suppress:6387) // _Param_(2) could be '0' - by design.
2060
+ Status =
2061
+ NmrClientAttachProvider(
2062
+ NmrBindingHandle,
2063
+ Client,
2064
+ NULL,
2065
+ &ProviderContext,
2066
+ (const void**)&Client->ProviderDispatch);
2067
+ if (NT_SUCCESS(Status)) {
2068
+ KeSetEvent(&Client->RegistrationCompleteEvent, IO_NO_INCREMENT, FALSE);
2069
+ } else {
2070
+ InterlockedDecrement(&Client->BindingCount);
2071
+ }
2072
+ } else {
2073
+ Status = STATUS_NOINTERFACE;
2074
+ }
2075
+
2076
+ return Status;
2077
+ }
2078
+
2079
+ static
2080
+ NTSTATUS
2081
+ __MsQuicClientDetachProvider(
2082
+ _In_ void *ClientBindingContext
2083
+ )
2084
+ {
2085
+ __MSQUIC_NMR_CLIENT* Client = (__MSQUIC_NMR_CLIENT*)ClientBindingContext;
2086
+ if (InterlockedOr8((char*)&Client->Deleting, 1)) {
2087
+ return STATUS_SUCCESS;
2088
+ } else {
2089
+ return STATUS_PENDING;
2090
+ }
2091
+ }
2092
+
2093
+ _IRQL_requires_max_(PASSIVE_LEVEL)
2094
+ __forceinline
2095
+ void
2096
+ MsQuicNmrClientDeregister(
2097
+ _Inout_ HANDLE* ClientHandle
2098
+ )
2099
+ {
2100
+ __MSQUIC_NMR_CLIENT* Client = (__MSQUIC_NMR_CLIENT*)(*ClientHandle);
2101
+
2102
+ if (InterlockedOr8((char*)&Client->Deleting, 1)) {
2103
+ //
2104
+ // We are already in the middle of detaching the client.
2105
+ // Complete it now.
2106
+ //
2107
+ NmrClientDetachProviderComplete(Client->NmrClientHandle);
2108
+ }
2109
+
2110
+ if (Client->NmrClientHandle) {
2111
+ if (NmrDeregisterClient(Client->NmrClientHandle) == STATUS_PENDING) {
2112
+ //
2113
+ // Wait for the deregistration to complete.
2114
+ //
2115
+ NmrWaitForClientDeregisterComplete(Client->NmrClientHandle);
2116
+ }
2117
+ Client->NmrClientHandle = NULL;
2118
+ }
2119
+
2120
+ ExFreePoolWithTag(Client, 'cNQM');
2121
+ *ClientHandle = NULL;
2122
+ }
2123
+
2124
+ _IRQL_requires_max_(PASSIVE_LEVEL)
2125
+ __forceinline
2126
+ NTSTATUS
2127
+ MsQuicNmrClientRegister(
2128
+ _Out_ HANDLE* ClientHandle,
2129
+ _In_ GUID* ClientModuleId,
2130
+ _In_ ULONG TimeoutMs // zero = no wait, non-zero = some wait
2131
+ )
2132
+ {
2133
+ NPI_REGISTRATION_INSTANCE *ClientRegistrationInstance;
2134
+ NTSTATUS Status = STATUS_SUCCESS;
2135
+
2136
+ __MSQUIC_NMR_CLIENT* Client =
2137
+ (__MSQUIC_NMR_CLIENT*)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(*Client), 'cNQM');
2138
+ if (Client == NULL) {
2139
+ Status = STATUS_INSUFFICIENT_RESOURCES;
2140
+ goto Exit;
2141
+ }
2142
+
2143
+ KeInitializeEvent(&Client->RegistrationCompleteEvent, SynchronizationEvent, FALSE);
2144
+
2145
+ Client->ModuleId.Length = sizeof(Client->ModuleId);
2146
+ Client->ModuleId.Type = MIT_GUID;
2147
+ Client->ModuleId.Guid = *ClientModuleId;
2148
+
2149
+ Client->NpiClientCharacteristics.Length = sizeof(Client->NpiClientCharacteristics);
2150
+ Client->NpiClientCharacteristics.ClientAttachProvider = __MsQuicClientAttachProvider;
2151
+ Client->NpiClientCharacteristics.ClientDetachProvider = __MsQuicClientDetachProvider;
2152
+
2153
+ ClientRegistrationInstance = &Client->NpiClientCharacteristics.ClientRegistrationInstance;
2154
+ ClientRegistrationInstance->Size = sizeof(*ClientRegistrationInstance);
2155
+ ClientRegistrationInstance->Version = 0;
2156
+ ClientRegistrationInstance->NpiId = &MSQUIC_NPI_ID;
2157
+ ClientRegistrationInstance->ModuleId = &Client->ModuleId;
2158
+
2159
+ Status =
2160
+ NmrRegisterClient(
2161
+ &Client->NpiClientCharacteristics, Client, &Client->NmrClientHandle);
2162
+ if (!NT_SUCCESS(Status)) {
2163
+ goto Exit;
2164
+ }
2165
+
2166
+ LARGE_INTEGER Timeout;
2167
+ Timeout.QuadPart = UInt32x32To64(TimeoutMs, 10000);
2168
+ Timeout.QuadPart = -Timeout.QuadPart;
2169
+
2170
+ Status =
2171
+ KeWaitForSingleObject(
2172
+ &Client->RegistrationCompleteEvent,
2173
+ Executive, KernelMode, FALSE,
2174
+ &Timeout);
2175
+ if (Status != STATUS_SUCCESS) {
2176
+ Status = STATUS_UNSUCCESSFUL;
2177
+ goto Exit;
2178
+ }
2179
+
2180
+ *ClientHandle = Client;
2181
+
2182
+ Exit:
2183
+ if (!NT_SUCCESS(Status) && Client != NULL) {
2184
+ MsQuicNmrClientDeregister((HANDLE*)&Client);
2185
+ }
2186
+
2187
+ return Status;
2188
+ }
2189
+
2190
+ #endif
2191
+
2192
+ //
2193
+ // Version specific helpers that wrap MsQuicOpenVersion.
2194
+ //
2195
+
2196
+ #if defined(__cplusplus)
2197
+
2198
+ _IRQL_requires_max_(PASSIVE_LEVEL)
2199
+ _Check_return_
2200
+ #if (__cplusplus >= 201703L || _MSVC_LANG >= 201703L)
2201
+ [[nodiscard]]
2202
+ #endif
2203
+ #ifdef WIN32
2204
+ __forceinline
2205
+ #else
2206
+ __attribute__((always_inline)) QUIC_INLINE
2207
+ #endif
2208
+ QUIC_STATUS
2209
+ MsQuicOpen2(
2210
+ _Out_ _Pre_defensive_ const QUIC_API_TABLE** QuicApi
2211
+ )
2212
+ {
2213
+ return MsQuicOpenVersion(QUIC_API_VERSION_2, (const void**)QuicApi);
2214
+ }
2215
+
2216
+ #else
2217
+
2218
+ #define MsQuicOpen2(QuicApi) MsQuicOpenVersion(2, (const void**)QuicApi)
2219
+
2220
+ #endif // defined(__cplusplus)
2221
+
2222
+ #if defined(__cplusplus)
2223
+ }
2224
+ #endif
2225
+
2226
+ #endif // _MSQUIC_