Vendor MsQuic with build and install support, add DeviceManager status to configurable heartbeats, and report only enabled devices. Add the local QUIC gateway, protocol coverage, real MsQuic E2E tests, process smoke tests, and updated integration documentation.
2124 lines
77 KiB
C++
2124 lines
77 KiB
C++
/*++
|
|
|
|
Copyright (c) Microsoft Corporation.
|
|
Licensed under the MIT License.
|
|
|
|
Abstract:
|
|
|
|
Declarations for the MsQuic API, which enables applications and drivers to
|
|
create QUIC connections as a client or server.
|
|
|
|
For more detailed information, see ../docs/API.md
|
|
|
|
Supported Platforms:
|
|
|
|
Windows User mode
|
|
Windows Kernel mode
|
|
Linux User mode
|
|
|
|
--*/
|
|
|
|
#ifndef _MSQUIC_
|
|
#define _MSQUIC_
|
|
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
|
|
#pragma warning(disable:4201) // nonstandard extension used: nameless struct/union
|
|
#pragma warning(disable:4214) // nonstandard extension used: bit field types other than int
|
|
#endif
|
|
|
|
#ifdef _KERNEL_MODE
|
|
#include "msquic_winkernel.h"
|
|
#elif _WIN32
|
|
#include "msquic_winuser.h"
|
|
#elif __linux__ || __APPLE__ || __FreeBSD__
|
|
#include "msquic_posix.h"
|
|
#else
|
|
#error "Unsupported Platform"
|
|
#endif
|
|
|
|
#if defined(__cplusplus)
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef struct QUIC_HANDLE *HQUIC;
|
|
|
|
//
|
|
// The maximum value that can be encoded in a 62-bit integer.
|
|
//
|
|
#define QUIC_UINT62_MAX ((1ULL << 62U) - 1)
|
|
|
|
//
|
|
// Represents a 62-bit integer.
|
|
//
|
|
typedef _In_range_(0, QUIC_UINT62_MAX) uint64_t QUIC_UINT62;
|
|
|
|
//
|
|
// An ALPN must not exceed 255 bytes, and must not be zero-length.
|
|
//
|
|
#define QUIC_MAX_ALPN_LENGTH 255
|
|
|
|
//
|
|
// A server name must not exceed 65535 bytes.
|
|
//
|
|
#define QUIC_MAX_SNI_LENGTH 65535
|
|
|
|
//
|
|
// The maximum number of bytes of application data a server application can
|
|
// send in a resumption ticket.
|
|
//
|
|
#define QUIC_MAX_RESUMPTION_APP_DATA_LENGTH 1000
|
|
|
|
//
|
|
// The number of bytes of stateless reset key.
|
|
//
|
|
#define QUIC_STATELESS_RESET_KEY_LENGTH 32
|
|
|
|
typedef enum QUIC_TLS_PROVIDER {
|
|
QUIC_TLS_PROVIDER_SCHANNEL = 0x0000,
|
|
QUIC_TLS_PROVIDER_OPENSSL = 0x0001,
|
|
} QUIC_TLS_PROVIDER;
|
|
|
|
typedef enum QUIC_EXECUTION_PROFILE {
|
|
QUIC_EXECUTION_PROFILE_LOW_LATENCY, // Default
|
|
QUIC_EXECUTION_PROFILE_TYPE_MAX_THROUGHPUT,
|
|
QUIC_EXECUTION_PROFILE_TYPE_SCAVENGER,
|
|
QUIC_EXECUTION_PROFILE_TYPE_REAL_TIME,
|
|
} QUIC_EXECUTION_PROFILE;
|
|
|
|
typedef enum QUIC_LOAD_BALANCING_MODE {
|
|
QUIC_LOAD_BALANCING_DISABLED, // Default
|
|
QUIC_LOAD_BALANCING_SERVER_ID_IP, // Encodes IP address in Server ID
|
|
QUIC_LOAD_BALANCING_SERVER_ID_FIXED, // Encodes a fixed 4-byte value in Server ID
|
|
QUIC_LOAD_BALANCING_COUNT, // The number of supported load balancing modes
|
|
// MUST BE LAST
|
|
} QUIC_LOAD_BALANCING_MODE;
|
|
|
|
typedef enum QUIC_TLS_ALERT_CODES {
|
|
QUIC_TLS_ALERT_CODE_SUCCESS = 0xFFFF, // Not a real TlsAlert
|
|
QUIC_TLS_ALERT_CODE_UNEXPECTED_MESSAGE = 10,
|
|
QUIC_TLS_ALERT_CODE_BAD_CERTIFICATE = 42,
|
|
QUIC_TLS_ALERT_CODE_UNSUPPORTED_CERTIFICATE = 43,
|
|
QUIC_TLS_ALERT_CODE_CERTIFICATE_REVOKED = 44,
|
|
QUIC_TLS_ALERT_CODE_CERTIFICATE_EXPIRED = 45,
|
|
QUIC_TLS_ALERT_CODE_CERTIFICATE_UNKNOWN = 46,
|
|
QUIC_TLS_ALERT_CODE_ILLEGAL_PARAMETER = 47,
|
|
QUIC_TLS_ALERT_CODE_UNKNOWN_CA = 48,
|
|
QUIC_TLS_ALERT_CODE_ACCESS_DENIED = 49,
|
|
QUIC_TLS_ALERT_CODE_INSUFFICIENT_SECURITY = 71,
|
|
QUIC_TLS_ALERT_CODE_INTERNAL_ERROR = 80,
|
|
QUIC_TLS_ALERT_CODE_USER_CANCELED = 90,
|
|
QUIC_TLS_ALERT_CODE_CERTIFICATE_REQUIRED = 116,
|
|
QUIC_TLS_ALERT_CODE_MAX = 255,
|
|
} QUIC_TLS_ALERT_CODES;
|
|
|
|
typedef enum QUIC_CREDENTIAL_TYPE {
|
|
QUIC_CREDENTIAL_TYPE_NONE,
|
|
QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH,
|
|
QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH_STORE,
|
|
QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT,
|
|
QUIC_CREDENTIAL_TYPE_CERTIFICATE_FILE,
|
|
QUIC_CREDENTIAL_TYPE_CERTIFICATE_FILE_PROTECTED,
|
|
QUIC_CREDENTIAL_TYPE_CERTIFICATE_PKCS12,
|
|
} QUIC_CREDENTIAL_TYPE;
|
|
|
|
typedef enum QUIC_CREDENTIAL_FLAGS {
|
|
QUIC_CREDENTIAL_FLAG_NONE = 0x00000000,
|
|
QUIC_CREDENTIAL_FLAG_CLIENT = 0x00000001, // Lack of client flag indicates server.
|
|
QUIC_CREDENTIAL_FLAG_LOAD_ASYNCHRONOUS = 0x00000002,
|
|
QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION = 0x00000004,
|
|
QUIC_CREDENTIAL_FLAG_ENABLE_OCSP = 0x00000008, // Schannel only currently
|
|
QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED = 0x00000010,
|
|
QUIC_CREDENTIAL_FLAG_DEFER_CERTIFICATE_VALIDATION = 0x00000020,
|
|
QUIC_CREDENTIAL_FLAG_REQUIRE_CLIENT_AUTHENTICATION = 0x00000040,
|
|
QUIC_CREDENTIAL_FLAG_USE_TLS_BUILTIN_CERTIFICATE_VALIDATION = 0x00000080, // OpenSSL only currently
|
|
QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_END_CERT = 0x00000100, // Schannel only currently
|
|
QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CHAIN = 0x00000200, // Schannel only currently
|
|
QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT = 0x00000400, // Schannel only currently
|
|
QUIC_CREDENTIAL_FLAG_IGNORE_NO_REVOCATION_CHECK = 0x00000800, // Schannel only currently
|
|
QUIC_CREDENTIAL_FLAG_IGNORE_REVOCATION_OFFLINE = 0x00001000, // Schannel only currently
|
|
QUIC_CREDENTIAL_FLAG_SET_ALLOWED_CIPHER_SUITES = 0x00002000,
|
|
QUIC_CREDENTIAL_FLAG_USE_PORTABLE_CERTIFICATES = 0x00004000,
|
|
QUIC_CREDENTIAL_FLAG_USE_SUPPLIED_CREDENTIALS = 0x00008000, // Schannel only
|
|
QUIC_CREDENTIAL_FLAG_USE_SYSTEM_MAPPER = 0x00010000, // Schannel only
|
|
QUIC_CREDENTIAL_FLAG_CACHE_ONLY_URL_RETRIEVAL = 0x00020000, // Windows only currently
|
|
QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CACHE_ONLY = 0x00040000, // Windows only currently
|
|
QUIC_CREDENTIAL_FLAG_INPROC_PEER_CERTIFICATE = 0x00080000, // Schannel only
|
|
QUIC_CREDENTIAL_FLAG_SET_CA_CERTIFICATE_FILE = 0x00100000, // OpenSSL only currently
|
|
QUIC_CREDENTIAL_FLAG_DISABLE_AIA = 0x00200000, // Schannel only currently
|
|
} QUIC_CREDENTIAL_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_CREDENTIAL_FLAGS)
|
|
|
|
typedef enum QUIC_ALLOWED_CIPHER_SUITE_FLAGS {
|
|
QUIC_ALLOWED_CIPHER_SUITE_NONE = 0x0,
|
|
QUIC_ALLOWED_CIPHER_SUITE_AES_128_GCM_SHA256 = 0x1,
|
|
QUIC_ALLOWED_CIPHER_SUITE_AES_256_GCM_SHA384 = 0x2,
|
|
QUIC_ALLOWED_CIPHER_SUITE_CHACHA20_POLY1305_SHA256 = 0x4, // Not supported on Schannel
|
|
} QUIC_ALLOWED_CIPHER_SUITE_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_ALLOWED_CIPHER_SUITE_FLAGS);
|
|
|
|
typedef enum QUIC_CERTIFICATE_HASH_STORE_FLAGS {
|
|
QUIC_CERTIFICATE_HASH_STORE_FLAG_NONE = 0x0000,
|
|
QUIC_CERTIFICATE_HASH_STORE_FLAG_MACHINE_STORE = 0x0001,
|
|
} QUIC_CERTIFICATE_HASH_STORE_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_CERTIFICATE_HASH_STORE_FLAGS)
|
|
|
|
typedef enum QUIC_CONNECTION_SHUTDOWN_FLAGS {
|
|
QUIC_CONNECTION_SHUTDOWN_FLAG_NONE = 0x0000,
|
|
QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT = 0x0001, // Don't send the close frame over the network.
|
|
} QUIC_CONNECTION_SHUTDOWN_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_CONNECTION_SHUTDOWN_FLAGS)
|
|
|
|
typedef enum QUIC_SERVER_RESUMPTION_LEVEL {
|
|
QUIC_SERVER_NO_RESUME,
|
|
QUIC_SERVER_RESUME_ONLY,
|
|
QUIC_SERVER_RESUME_AND_ZERORTT,
|
|
} QUIC_SERVER_RESUMPTION_LEVEL;
|
|
|
|
typedef enum QUIC_SEND_RESUMPTION_FLAGS {
|
|
QUIC_SEND_RESUMPTION_FLAG_NONE = 0x0000,
|
|
QUIC_SEND_RESUMPTION_FLAG_FINAL = 0x0001, // Free TLS state after sending this ticket.
|
|
} QUIC_SEND_RESUMPTION_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_SEND_RESUMPTION_FLAGS)
|
|
|
|
typedef enum QUIC_STREAM_SCHEDULING_SCHEME {
|
|
QUIC_STREAM_SCHEDULING_SCHEME_FIFO = 0x0000, // Sends stream data first come, first served. (Default)
|
|
QUIC_STREAM_SCHEDULING_SCHEME_ROUND_ROBIN = 0x0001, // Sends stream data evenly multiplexed.
|
|
QUIC_STREAM_SCHEDULING_SCHEME_COUNT, // The number of stream scheduling schemes.
|
|
} QUIC_STREAM_SCHEDULING_SCHEME;
|
|
|
|
typedef enum QUIC_STREAM_OPEN_FLAGS {
|
|
QUIC_STREAM_OPEN_FLAG_NONE = 0x0000,
|
|
QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL = 0x0001, // Indicates the stream is unidirectional.
|
|
QUIC_STREAM_OPEN_FLAG_0_RTT = 0x0002, // The stream was opened via a 0-RTT packet.
|
|
QUIC_STREAM_OPEN_FLAG_DELAY_ID_FC_UPDATES = 0x0004, // Indicates stream ID flow control limit updates for the
|
|
// connection should be delayed to StreamClose.
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
QUIC_STREAM_OPEN_FLAG_APP_OWNED_BUFFERS = 0x0008, // No buffer will be allocated for the stream, the app must
|
|
// provide buffers (see StreamProvideReceiveBuffers)
|
|
#endif
|
|
} QUIC_STREAM_OPEN_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_STREAM_OPEN_FLAGS)
|
|
|
|
typedef enum QUIC_STREAM_START_FLAGS {
|
|
QUIC_STREAM_START_FLAG_NONE = 0x0000,
|
|
QUIC_STREAM_START_FLAG_IMMEDIATE = 0x0001, // Immediately informs peer that stream is open.
|
|
QUIC_STREAM_START_FLAG_FAIL_BLOCKED = 0x0002, // Only opens the stream if flow control allows.
|
|
QUIC_STREAM_START_FLAG_SHUTDOWN_ON_FAIL = 0x0004, // Shutdown the stream immediately after start failure.
|
|
QUIC_STREAM_START_FLAG_INDICATE_PEER_ACCEPT = 0x0008, // Indicate PEER_ACCEPTED event if not accepted at start.
|
|
QUIC_STREAM_START_FLAG_PRIORITY_WORK = 0x0010, // Higher priority than other connection work.
|
|
} QUIC_STREAM_START_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_STREAM_START_FLAGS)
|
|
|
|
typedef enum QUIC_STREAM_SHUTDOWN_FLAGS {
|
|
QUIC_STREAM_SHUTDOWN_FLAG_NONE = 0x0000,
|
|
QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL = 0x0001, // Cleanly closes the send path.
|
|
QUIC_STREAM_SHUTDOWN_FLAG_ABORT_SEND = 0x0002, // Abruptly closes the send path.
|
|
QUIC_STREAM_SHUTDOWN_FLAG_ABORT_RECEIVE = 0x0004, // Abruptly closes the receive path.
|
|
QUIC_STREAM_SHUTDOWN_FLAG_ABORT = 0x0006, // Abruptly closes both send and receive paths.
|
|
QUIC_STREAM_SHUTDOWN_FLAG_IMMEDIATE = 0x0008, // Immediately sends completion events to app.
|
|
QUIC_STREAM_SHUTDOWN_FLAG_INLINE = 0x0010, // Process the shutdown immediately inline. Only for calls on callbacks.
|
|
// WARNING: Can cause reentrant callbacks!
|
|
} QUIC_STREAM_SHUTDOWN_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_STREAM_SHUTDOWN_FLAGS)
|
|
|
|
typedef enum QUIC_RECEIVE_FLAGS {
|
|
QUIC_RECEIVE_FLAG_NONE = 0x0000,
|
|
QUIC_RECEIVE_FLAG_0_RTT = 0x0001, // Data was encrypted with 0-RTT key.
|
|
QUIC_RECEIVE_FLAG_FIN = 0x0002, // FIN was included with this data.
|
|
} QUIC_RECEIVE_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_RECEIVE_FLAGS)
|
|
|
|
typedef enum QUIC_SEND_FLAGS {
|
|
QUIC_SEND_FLAG_NONE = 0x0000,
|
|
QUIC_SEND_FLAG_ALLOW_0_RTT = 0x0001, // Allows the use of encrypting with 0-RTT key.
|
|
QUIC_SEND_FLAG_START = 0x0002, // Asynchronously starts the stream with the sent data.
|
|
QUIC_SEND_FLAG_FIN = 0x0004, // Indicates the request is the one last sent on the stream.
|
|
QUIC_SEND_FLAG_DGRAM_PRIORITY = 0x0008, // Indicates the datagram is higher priority than others.
|
|
QUIC_SEND_FLAG_DELAY_SEND = 0x0010, // Indicates the send should be delayed because more will be queued soon.
|
|
QUIC_SEND_FLAG_CANCEL_ON_LOSS = 0x0020, // Indicates that a stream is to be cancelled when packet loss is detected.
|
|
QUIC_SEND_FLAG_PRIORITY_WORK = 0x0040, // Higher priority than other connection work.
|
|
QUIC_SEND_FLAG_CANCEL_ON_BLOCKED = 0x0080, // Indicates that a frame should be dropped when it can't be sent immediately.
|
|
} QUIC_SEND_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_SEND_FLAGS)
|
|
|
|
typedef enum QUIC_DATAGRAM_SEND_STATE {
|
|
QUIC_DATAGRAM_SEND_UNKNOWN, // Not yet sent.
|
|
QUIC_DATAGRAM_SEND_SENT, // Sent and awaiting acknowledgment
|
|
QUIC_DATAGRAM_SEND_LOST_SUSPECT, // Suspected as lost, but still tracked
|
|
QUIC_DATAGRAM_SEND_LOST_DISCARDED, // Lost and not longer being tracked
|
|
QUIC_DATAGRAM_SEND_ACKNOWLEDGED, // Acknowledged
|
|
QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS, // Acknowledged after being suspected lost
|
|
QUIC_DATAGRAM_SEND_CANCELED, // Canceled before send
|
|
} QUIC_DATAGRAM_SEND_STATE;
|
|
|
|
//
|
|
// Helper to determine if a datagrams state is final, and no longer tracked
|
|
// by MsQuic.
|
|
//
|
|
#define QUIC_DATAGRAM_SEND_STATE_IS_FINAL(State) \
|
|
((State) >= QUIC_DATAGRAM_SEND_LOST_DISCARDED)
|
|
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
|
|
typedef enum QUIC_GLOBAL_EXECUTION_CONFIG_FLAGS {
|
|
QUIC_GLOBAL_EXECUTION_CONFIG_FLAG_NONE = 0x0000,
|
|
QUIC_GLOBAL_EXECUTION_CONFIG_FLAG_NO_IDEAL_PROC = 0x0008,
|
|
QUIC_GLOBAL_EXECUTION_CONFIG_FLAG_HIGH_PRIORITY = 0x0010,
|
|
QUIC_GLOBAL_EXECUTION_CONFIG_FLAG_AFFINITIZE = 0x0020,
|
|
} QUIC_GLOBAL_EXECUTION_CONFIG_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_GLOBAL_EXECUTION_CONFIG_FLAGS)
|
|
|
|
//
|
|
// A custom configuration for thread execution in QUIC.
|
|
//
|
|
typedef struct QUIC_GLOBAL_EXECUTION_CONFIG {
|
|
|
|
QUIC_GLOBAL_EXECUTION_CONFIG_FLAGS Flags;
|
|
uint32_t PollingIdleTimeoutUs; // Time before a polling thread, with no work to do, sleeps.
|
|
uint32_t ProcessorCount;
|
|
_Field_size_(ProcessorCount)
|
|
uint16_t ProcessorList[1]; // List of processors to use for threads.
|
|
|
|
} QUIC_GLOBAL_EXECUTION_CONFIG;
|
|
|
|
#define QUIC_GLOBAL_EXECUTION_CONFIG_MIN_SIZE \
|
|
(uint32_t)FIELD_OFFSET(QUIC_GLOBAL_EXECUTION_CONFIG, ProcessorList)
|
|
|
|
#ifndef _KERNEL_MODE
|
|
|
|
//
|
|
// Execution Context abstraction, which allows the application layer to
|
|
// completely control execution of all MsQuic work.
|
|
//
|
|
|
|
typedef struct QUIC_EXECUTION_CONFIG {
|
|
uint32_t IdealProcessor;
|
|
QUIC_EVENTQ* EventQ;
|
|
} QUIC_EXECUTION_CONFIG;
|
|
|
|
typedef struct QUIC_EXECUTION QUIC_EXECUTION;
|
|
|
|
//
|
|
// This is called to create the execution contexts.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_EXECUTION_CREATE_FN)(
|
|
_In_ QUIC_GLOBAL_EXECUTION_CONFIG_FLAGS Flags, // Used for datapath type
|
|
_In_ uint32_t PollingIdleTimeoutUs,
|
|
_In_ uint32_t Count,
|
|
_In_reads_(Count) QUIC_EXECUTION_CONFIG* Configs,
|
|
_Out_writes_(Count) QUIC_EXECUTION** Executions
|
|
);
|
|
|
|
//
|
|
// This is called to delete the execution contexts.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_EXECUTION_DELETE_FN)(
|
|
_In_ uint32_t Count,
|
|
_In_reads_(Count) QUIC_EXECUTION** Executions
|
|
);
|
|
|
|
//
|
|
// This is called to allow MsQuic to process any polling work. It returns the
|
|
// number of milliseconds until the next scheduled timer expiration.
|
|
//
|
|
// TODO: Should it return an indication for if we should yield?
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
uint32_t
|
|
(QUIC_API * QUIC_EXECUTION_POLL_FN)(
|
|
_In_ QUIC_EXECUTION* Execution
|
|
);
|
|
|
|
#endif // _KERNEL_MODE
|
|
|
|
#endif // QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
|
|
typedef struct QUIC_REGISTRATION_CONFIG { // All fields may be NULL/zero.
|
|
const char* AppName;
|
|
QUIC_EXECUTION_PROFILE ExecutionProfile;
|
|
} QUIC_REGISTRATION_CONFIG;
|
|
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
_Function_class_(QUIC_CREDENTIAL_LOAD_COMPLETE)
|
|
void
|
|
(QUIC_API QUIC_CREDENTIAL_LOAD_COMPLETE)(
|
|
_In_ HQUIC Configuration,
|
|
_In_opt_ void* Context,
|
|
_In_ QUIC_STATUS Status
|
|
);
|
|
|
|
typedef QUIC_CREDENTIAL_LOAD_COMPLETE *QUIC_CREDENTIAL_LOAD_COMPLETE_HANDLER;
|
|
|
|
typedef struct QUIC_CERTIFICATE_HASH {
|
|
uint8_t ShaHash[20];
|
|
} QUIC_CERTIFICATE_HASH;
|
|
|
|
typedef struct QUIC_CERTIFICATE_HASH_STORE {
|
|
QUIC_CERTIFICATE_HASH_STORE_FLAGS Flags;
|
|
uint8_t ShaHash[20];
|
|
char StoreName[128];
|
|
} QUIC_CERTIFICATE_HASH_STORE;
|
|
|
|
typedef struct QUIC_CERTIFICATE_FILE {
|
|
const char *PrivateKeyFile;
|
|
const char *CertificateFile;
|
|
} QUIC_CERTIFICATE_FILE;
|
|
|
|
typedef struct QUIC_CERTIFICATE_FILE_PROTECTED {
|
|
const char *PrivateKeyFile;
|
|
const char *CertificateFile;
|
|
const char *PrivateKeyPassword;
|
|
} QUIC_CERTIFICATE_FILE_PROTECTED;
|
|
|
|
typedef struct QUIC_CERTIFICATE_PKCS12 {
|
|
const uint8_t *Asn1Blob;
|
|
uint32_t Asn1BlobLength;
|
|
const char *PrivateKeyPassword; // Optional: used if provided. Ignored if NULL
|
|
} QUIC_CERTIFICATE_PKCS12;
|
|
|
|
typedef void QUIC_CERTIFICATE; // Platform specific certificate object
|
|
typedef void QUIC_CERTIFICATE_CHAIN; // Platform specific certificate chain object
|
|
|
|
typedef struct QUIC_CREDENTIAL_CONFIG {
|
|
QUIC_CREDENTIAL_TYPE Type;
|
|
QUIC_CREDENTIAL_FLAGS Flags;
|
|
union {
|
|
QUIC_CERTIFICATE_HASH* CertificateHash;
|
|
QUIC_CERTIFICATE_HASH_STORE* CertificateHashStore;
|
|
QUIC_CERTIFICATE* CertificateContext;
|
|
QUIC_CERTIFICATE_FILE* CertificateFile;
|
|
QUIC_CERTIFICATE_FILE_PROTECTED* CertificateFileProtected;
|
|
QUIC_CERTIFICATE_PKCS12* CertificatePkcs12;
|
|
};
|
|
const char* Principal;
|
|
void* Reserved; // Currently unused
|
|
QUIC_CREDENTIAL_LOAD_COMPLETE_HANDLER AsyncHandler; // Optional
|
|
QUIC_ALLOWED_CIPHER_SUITE_FLAGS AllowedCipherSuites;// Optional
|
|
const char* CaCertificateFile; // Optional
|
|
} QUIC_CREDENTIAL_CONFIG;
|
|
|
|
//
|
|
// The maximum number of QUIC_TICKET_KEY_CONFIG that can be used at one time.
|
|
//
|
|
#define QUIC_MAX_TICKET_KEY_COUNT 16
|
|
|
|
//
|
|
// TLS New Session Ticket encryption key configuration.
|
|
//
|
|
typedef struct QUIC_TICKET_KEY_CONFIG {
|
|
uint8_t Id[16];
|
|
uint8_t Material[64];
|
|
uint8_t MaterialLength;
|
|
} QUIC_TICKET_KEY_CONFIG;
|
|
|
|
//
|
|
// A single contiguous buffer.
|
|
//
|
|
typedef struct QUIC_BUFFER {
|
|
uint32_t Length;
|
|
_Field_size_bytes_(Length)
|
|
uint8_t* Buffer;
|
|
} QUIC_BUFFER;
|
|
|
|
//
|
|
// All the available information describing a new incoming connection.
|
|
//
|
|
typedef struct QUIC_NEW_CONNECTION_INFO {
|
|
uint32_t QuicVersion;
|
|
const QUIC_ADDR* LocalAddress;
|
|
const QUIC_ADDR* RemoteAddress;
|
|
uint32_t CryptoBufferLength;
|
|
uint16_t ClientAlpnListLength;
|
|
uint16_t ServerNameLength;
|
|
uint8_t NegotiatedAlpnLength;
|
|
_Field_size_bytes_(CryptoBufferLength)
|
|
const uint8_t* CryptoBuffer;
|
|
_Field_size_bytes_(ClientAlpnListLength)
|
|
const uint8_t* ClientAlpnList;
|
|
_Field_size_bytes_(NegotiatedAlpnLength)
|
|
const uint8_t* NegotiatedAlpn;
|
|
_Field_size_bytes_opt_(ServerNameLength)
|
|
const char* ServerName;
|
|
} QUIC_NEW_CONNECTION_INFO;
|
|
|
|
typedef enum QUIC_TLS_PROTOCOL_VERSION {
|
|
QUIC_TLS_PROTOCOL_UNKNOWN = 0,
|
|
QUIC_TLS_PROTOCOL_1_3 = 0x3000,
|
|
} QUIC_TLS_PROTOCOL_VERSION;
|
|
|
|
typedef enum QUIC_CIPHER_ALGORITHM {
|
|
QUIC_CIPHER_ALGORITHM_NONE = 0,
|
|
QUIC_CIPHER_ALGORITHM_AES_128 = 0x660E,
|
|
QUIC_CIPHER_ALGORITHM_AES_256 = 0x6610,
|
|
QUIC_CIPHER_ALGORITHM_CHACHA20 = 0x6612, // Not supported on Schannel/BCrypt
|
|
} QUIC_CIPHER_ALGORITHM;
|
|
|
|
typedef enum QUIC_HASH_ALGORITHM {
|
|
QUIC_HASH_ALGORITHM_NONE = 0,
|
|
QUIC_HASH_ALGORITHM_SHA_256 = 0x800C,
|
|
QUIC_HASH_ALGORITHM_SHA_384 = 0x800D,
|
|
} QUIC_HASH_ALGORITHM;
|
|
|
|
typedef enum QUIC_KEY_EXCHANGE_ALGORITHM {
|
|
QUIC_KEY_EXCHANGE_ALGORITHM_NONE = 0,
|
|
} QUIC_KEY_EXCHANGE_ALGORITHM;
|
|
|
|
//
|
|
// See the following IANA registry for the TLS groups:
|
|
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
|
|
//
|
|
typedef enum QUIC_TLS_GROUP {
|
|
QUIC_TLS_GROUP_UNKNOWN = 0,
|
|
QUIC_TLS_GROUP_SECP256R1 = 23,
|
|
QUIC_TLS_GROUP_SECP384R1 = 24,
|
|
QUIC_TLS_GROUP_X25519 = 29,
|
|
QUIC_TLS_GROUP_MLKEM512 = 512,
|
|
QUIC_TLS_GROUP_MLKEM768 = 513,
|
|
QUIC_TLS_GROUP_MLKEM1024 = 514,
|
|
QUIC_TLS_GROUP_SECP256R1MLKEM768 = 4587,
|
|
QUIC_TLS_GROUP_X25519MLKEM768 = 4588,
|
|
QUIC_TLS_GROUP_SECP384R1MLKEM1024 = 4589,
|
|
} QUIC_TLS_GROUP;
|
|
|
|
typedef enum QUIC_CIPHER_SUITE {
|
|
QUIC_CIPHER_SUITE_TLS_AES_128_GCM_SHA256 = 0x1301,
|
|
QUIC_CIPHER_SUITE_TLS_AES_256_GCM_SHA384 = 0x1302,
|
|
QUIC_CIPHER_SUITE_TLS_CHACHA20_POLY1305_SHA256 = 0x1303, // Not supported on Schannel
|
|
} QUIC_CIPHER_SUITE;
|
|
|
|
typedef enum QUIC_CONGESTION_CONTROL_ALGORITHM {
|
|
QUIC_CONGESTION_CONTROL_ALGORITHM_CUBIC,
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
QUIC_CONGESTION_CONTROL_ALGORITHM_BBR,
|
|
#endif
|
|
QUIC_CONGESTION_CONTROL_ALGORITHM_MAX,
|
|
} QUIC_CONGESTION_CONTROL_ALGORITHM;
|
|
|
|
//
|
|
// All the available information describing a handshake.
|
|
//
|
|
typedef struct QUIC_HANDSHAKE_INFO {
|
|
QUIC_TLS_PROTOCOL_VERSION TlsProtocolVersion;
|
|
QUIC_CIPHER_ALGORITHM CipherAlgorithm;
|
|
int32_t CipherStrength;
|
|
QUIC_HASH_ALGORITHM Hash;
|
|
int32_t HashStrength;
|
|
QUIC_KEY_EXCHANGE_ALGORITHM KeyExchangeAlgorithm;
|
|
int32_t KeyExchangeStrength;
|
|
QUIC_CIPHER_SUITE CipherSuite;
|
|
QUIC_TLS_GROUP TlsGroup; // Added in v2.5
|
|
} QUIC_HANDSHAKE_INFO;
|
|
|
|
//
|
|
// All statistics available to query about a connection.
|
|
//
|
|
typedef struct QUIC_STATISTICS {
|
|
uint64_t CorrelationId;
|
|
uint32_t VersionNegotiation : 1;
|
|
uint32_t StatelessRetry : 1;
|
|
uint32_t ResumptionAttempted : 1;
|
|
uint32_t ResumptionSucceeded : 1;
|
|
uint32_t Rtt; // In microseconds
|
|
uint32_t MinRtt; // In microseconds
|
|
uint32_t MaxRtt; // In microseconds
|
|
struct {
|
|
uint64_t Start;
|
|
uint64_t InitialFlightEnd; // Processed all peer's Initial packets
|
|
uint64_t HandshakeFlightEnd; // Processed all peer's Handshake packets
|
|
} Timing;
|
|
struct {
|
|
uint32_t ClientFlight1Bytes; // Sum of TLS payloads
|
|
uint32_t ServerFlight1Bytes; // Sum of TLS payloads
|
|
uint32_t ClientFlight2Bytes; // Sum of TLS payloads
|
|
} Handshake;
|
|
struct {
|
|
uint16_t PathMtu; // Current path MTU.
|
|
uint64_t TotalPackets; // QUIC packets; could be coalesced into fewer UDP datagrams.
|
|
uint64_t RetransmittablePackets;
|
|
uint64_t SuspectedLostPackets;
|
|
uint64_t SpuriousLostPackets; // Actual lost is (SuspectedLostPackets - SpuriousLostPackets)
|
|
uint64_t TotalBytes; // Sum of UDP payloads
|
|
uint64_t TotalStreamBytes; // Sum of stream payloads
|
|
uint32_t CongestionCount; // Number of congestion events
|
|
uint32_t PersistentCongestionCount; // Number of persistent congestion events
|
|
} Send;
|
|
struct {
|
|
uint64_t TotalPackets; // QUIC packets; could be coalesced into fewer UDP datagrams.
|
|
uint64_t ReorderedPackets; // Packets where packet number is less than highest seen.
|
|
uint64_t DroppedPackets; // Includes DuplicatePackets.
|
|
uint64_t DuplicatePackets;
|
|
uint64_t TotalBytes; // Sum of UDP payloads
|
|
uint64_t TotalStreamBytes; // Sum of stream payloads
|
|
uint64_t DecryptionFailures; // Count of packet decryption failures.
|
|
uint64_t ValidAckFrames; // Count of receive ACK frames.
|
|
} Recv;
|
|
struct {
|
|
uint32_t KeyUpdateCount;
|
|
} Misc;
|
|
} QUIC_STATISTICS;
|
|
|
|
//
|
|
// N.B. Consumers of this struct depend on it being the same for 32-bit and
|
|
// 64-bit systems. DO NOT include any fields that have different sizes on those
|
|
// platforms, such as size_t or pointers.
|
|
//
|
|
typedef struct QUIC_STATISTICS_V2 {
|
|
|
|
uint64_t CorrelationId;
|
|
uint32_t VersionNegotiation : 1;
|
|
uint32_t StatelessRetry : 1;
|
|
uint32_t ResumptionAttempted : 1;
|
|
uint32_t ResumptionSucceeded : 1;
|
|
uint32_t GreaseBitNegotiated : 1; // Set if we negotiated the GREASE bit.
|
|
uint32_t EcnCapable : 1;
|
|
uint32_t EncryptionOffloaded : 1; // At least one path successfully offloaded encryption
|
|
uint32_t RESERVED : 25;
|
|
uint32_t Rtt; // In microseconds
|
|
uint32_t MinRtt; // In microseconds
|
|
uint32_t MaxRtt; // In microseconds
|
|
|
|
uint64_t TimingStart;
|
|
uint64_t TimingInitialFlightEnd; // Processed all peer's Initial packets
|
|
uint64_t TimingHandshakeFlightEnd; // Processed all peer's Handshake packets
|
|
|
|
uint32_t HandshakeClientFlight1Bytes; // Sum of TLS payloads
|
|
uint32_t HandshakeServerFlight1Bytes; // Sum of TLS payloads
|
|
uint32_t HandshakeClientFlight2Bytes; // Sum of TLS payloads
|
|
|
|
uint16_t SendPathMtu; // Current path MTU.
|
|
uint64_t SendTotalPackets; // QUIC packets; could be coalesced into fewer UDP datagrams.
|
|
uint64_t SendRetransmittablePackets;
|
|
uint64_t SendSuspectedLostPackets;
|
|
uint64_t SendSpuriousLostPackets; // Actual lost is (SuspectedLostPackets - SpuriousLostPackets)
|
|
uint64_t SendTotalBytes; // Sum of UDP payloads
|
|
uint64_t SendTotalStreamBytes; // Sum of stream payloads
|
|
uint32_t SendCongestionCount; // Number of congestion events
|
|
uint32_t SendPersistentCongestionCount; // Number of persistent congestion events
|
|
|
|
uint64_t RecvTotalPackets; // QUIC packets; could be coalesced into fewer UDP datagrams.
|
|
uint64_t RecvReorderedPackets; // Packets where packet number is less than highest seen.
|
|
uint64_t RecvDroppedPackets; // Includes DuplicatePackets.
|
|
uint64_t RecvDuplicatePackets;
|
|
uint64_t RecvTotalBytes; // Sum of UDP payloads
|
|
uint64_t RecvTotalStreamBytes; // Sum of stream payloads
|
|
uint64_t RecvDecryptionFailures; // Count of packet decryption failures.
|
|
uint64_t RecvValidAckFrames; // Count of receive ACK frames.
|
|
|
|
uint32_t KeyUpdateCount;
|
|
|
|
uint32_t SendCongestionWindow; // Congestion window size
|
|
|
|
uint32_t DestCidUpdateCount; // Number of times the destionation CID changed.
|
|
|
|
uint32_t SendEcnCongestionCount; // Number of congestion events caused by ECN.
|
|
|
|
uint8_t HandshakeHopLimitTTL; // The TTL value in the initial packet of the handshake.
|
|
|
|
uint32_t RttVariance; // In microseconds
|
|
|
|
// N.B. New fields must be appended to end
|
|
|
|
} QUIC_STATISTICS_V2;
|
|
|
|
#define QUIC_STRUCT_SIZE_THRU_FIELD(Struct, Field) \
|
|
(FIELD_OFFSET(Struct, Field) + sizeof(((Struct*)0)->Field))
|
|
|
|
#define QUIC_STATISTICS_V2_SIZE_1 QUIC_STRUCT_SIZE_THRU_FIELD(QUIC_STATISTICS_V2, KeyUpdateCount) // MsQuic v2.0 final size
|
|
#define QUIC_STATISTICS_V2_SIZE_2 QUIC_STRUCT_SIZE_THRU_FIELD(QUIC_STATISTICS_V2, DestCidUpdateCount) // MsQuic v2.1 final size
|
|
#define QUIC_STATISTICS_V2_SIZE_3 QUIC_STRUCT_SIZE_THRU_FIELD(QUIC_STATISTICS_V2, SendEcnCongestionCount) // MsQuic v2.2 final size
|
|
#define QUIC_STATISTICS_V2_SIZE_4 QUIC_STRUCT_SIZE_THRU_FIELD(QUIC_STATISTICS_V2, RttVariance) // MsQuic v2.5 final size
|
|
|
|
typedef struct QUIC_LISTENER_STATISTICS {
|
|
|
|
uint64_t TotalAcceptedConnections;
|
|
uint64_t TotalRejectedConnections;
|
|
|
|
uint64_t BindingRecvDroppedPackets;
|
|
|
|
} QUIC_LISTENER_STATISTICS;
|
|
|
|
typedef enum QUIC_PERFORMANCE_COUNTERS {
|
|
QUIC_PERF_COUNTER_CONN_CREATED, // Total connections ever allocated.
|
|
QUIC_PERF_COUNTER_CONN_HANDSHAKE_FAIL, // Total connections that failed during handshake.
|
|
QUIC_PERF_COUNTER_CONN_APP_REJECT, // Total connections rejected by the application.
|
|
QUIC_PERF_COUNTER_CONN_RESUMED, // Total connections resumed.
|
|
QUIC_PERF_COUNTER_CONN_ACTIVE, // Connections currently allocated.
|
|
QUIC_PERF_COUNTER_CONN_CONNECTED, // Connections currently in the connected state.
|
|
QUIC_PERF_COUNTER_CONN_PROTOCOL_ERRORS, // Total connections shutdown with a protocol error.
|
|
QUIC_PERF_COUNTER_CONN_NO_ALPN, // Total connection attempts with no matching ALPN.
|
|
QUIC_PERF_COUNTER_STRM_ACTIVE, // Current streams allocated.
|
|
QUIC_PERF_COUNTER_PKTS_SUSPECTED_LOST, // Total suspected packets lost
|
|
QUIC_PERF_COUNTER_PKTS_DROPPED, // Total packets dropped for any reason.
|
|
QUIC_PERF_COUNTER_PKTS_DECRYPTION_FAIL, // Total packets with decryption failures.
|
|
QUIC_PERF_COUNTER_UDP_RECV, // Total UDP datagrams received.
|
|
QUIC_PERF_COUNTER_UDP_SEND, // Total UDP datagrams sent.
|
|
QUIC_PERF_COUNTER_UDP_RECV_BYTES, // Total UDP payload bytes received.
|
|
QUIC_PERF_COUNTER_UDP_SEND_BYTES, // Total UDP payload bytes sent.
|
|
QUIC_PERF_COUNTER_UDP_RECV_EVENTS, // Total UDP receive events.
|
|
QUIC_PERF_COUNTER_UDP_SEND_CALLS, // Total UDP send API calls.
|
|
QUIC_PERF_COUNTER_APP_SEND_BYTES, // Total bytes sent by applications.
|
|
QUIC_PERF_COUNTER_APP_RECV_BYTES, // Total bytes received by applications.
|
|
QUIC_PERF_COUNTER_CONN_QUEUE_DEPTH, // Current connections queued for processing.
|
|
QUIC_PERF_COUNTER_CONN_OPER_QUEUE_DEPTH,// Current connection operations queued.
|
|
QUIC_PERF_COUNTER_CONN_OPER_QUEUED, // Total connection operations queued ever.
|
|
QUIC_PERF_COUNTER_CONN_OPER_COMPLETED, // Total connection operations processed ever.
|
|
QUIC_PERF_COUNTER_WORK_OPER_QUEUE_DEPTH,// Current worker operations queued.
|
|
QUIC_PERF_COUNTER_WORK_OPER_QUEUED, // Total worker operations queued ever.
|
|
QUIC_PERF_COUNTER_WORK_OPER_COMPLETED, // Total worker operations processed ever.
|
|
QUIC_PERF_COUNTER_PATH_VALIDATED, // Total path challenges that succeed ever.
|
|
QUIC_PERF_COUNTER_PATH_FAILURE, // Total path challenges that fail ever.
|
|
QUIC_PERF_COUNTER_SEND_STATELESS_RESET, // Total stateless reset packets sent ever.
|
|
QUIC_PERF_COUNTER_SEND_STATELESS_RETRY, // Total stateless retry packets sent ever.
|
|
QUIC_PERF_COUNTER_CONN_LOAD_REJECT, // Total connections rejected due to worker load.
|
|
QUIC_PERF_COUNTER_MAX,
|
|
} QUIC_PERFORMANCE_COUNTERS;
|
|
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
typedef struct QUIC_VERSION_SETTINGS {
|
|
|
|
const uint32_t* AcceptableVersions;
|
|
const uint32_t* OfferedVersions;
|
|
const uint32_t* FullyDeployedVersions;
|
|
uint32_t AcceptableVersionsLength;
|
|
uint32_t OfferedVersionsLength;
|
|
uint32_t FullyDeployedVersionsLength;
|
|
|
|
} QUIC_VERSION_SETTINGS;
|
|
#endif
|
|
|
|
typedef struct QUIC_GLOBAL_SETTINGS {
|
|
union {
|
|
uint64_t IsSetFlags;
|
|
struct {
|
|
uint64_t RetryMemoryLimit : 1;
|
|
uint64_t LoadBalancingMode : 1;
|
|
uint64_t FixedServerID : 1;
|
|
uint64_t RESERVED : 61;
|
|
} IsSet;
|
|
};
|
|
uint16_t RetryMemoryLimit;
|
|
uint16_t LoadBalancingMode;
|
|
uint32_t FixedServerID;
|
|
} QUIC_GLOBAL_SETTINGS;
|
|
|
|
typedef struct QUIC_SETTINGS {
|
|
|
|
union {
|
|
uint64_t IsSetFlags;
|
|
struct {
|
|
uint64_t MaxBytesPerKey : 1;
|
|
uint64_t HandshakeIdleTimeoutMs : 1;
|
|
uint64_t IdleTimeoutMs : 1;
|
|
uint64_t MtuDiscoverySearchCompleteTimeoutUs : 1;
|
|
uint64_t TlsClientMaxSendBuffer : 1;
|
|
uint64_t TlsServerMaxSendBuffer : 1;
|
|
uint64_t StreamRecvWindowDefault : 1;
|
|
uint64_t StreamRecvBufferDefault : 1;
|
|
uint64_t ConnFlowControlWindow : 1;
|
|
uint64_t MaxWorkerQueueDelayUs : 1;
|
|
uint64_t MaxStatelessOperations : 1;
|
|
uint64_t InitialWindowPackets : 1;
|
|
uint64_t SendIdleTimeoutMs : 1;
|
|
uint64_t InitialRttMs : 1;
|
|
uint64_t MaxAckDelayMs : 1;
|
|
uint64_t DisconnectTimeoutMs : 1;
|
|
uint64_t KeepAliveIntervalMs : 1;
|
|
uint64_t CongestionControlAlgorithm : 1;
|
|
uint64_t PeerBidiStreamCount : 1;
|
|
uint64_t PeerUnidiStreamCount : 1;
|
|
uint64_t MaxBindingStatelessOperations : 1;
|
|
uint64_t StatelessOperationExpirationMs : 1;
|
|
uint64_t MinimumMtu : 1;
|
|
uint64_t MaximumMtu : 1;
|
|
uint64_t SendBufferingEnabled : 1;
|
|
uint64_t PacingEnabled : 1;
|
|
uint64_t MigrationEnabled : 1;
|
|
uint64_t DatagramReceiveEnabled : 1;
|
|
uint64_t ServerResumptionLevel : 1;
|
|
uint64_t MaxOperationsPerDrain : 1;
|
|
uint64_t MtuDiscoveryMissingProbeCount : 1;
|
|
uint64_t DestCidUpdateIdleTimeoutMs : 1;
|
|
uint64_t GreaseQuicBitEnabled : 1;
|
|
uint64_t EcnEnabled : 1;
|
|
uint64_t HyStartEnabled : 1;
|
|
uint64_t StreamRecvWindowBidiLocalDefault : 1;
|
|
uint64_t StreamRecvWindowBidiRemoteDefault : 1;
|
|
uint64_t StreamRecvWindowUnidiDefault : 1;
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
uint64_t EncryptionOffloadAllowed : 1;
|
|
uint64_t ReliableResetEnabled : 1;
|
|
uint64_t OneWayDelayEnabled : 1;
|
|
uint64_t NetStatsEventEnabled : 1;
|
|
uint64_t StreamMultiReceiveEnabled : 1;
|
|
uint64_t XdpEnabled : 1;
|
|
uint64_t QTIPEnabled : 1;
|
|
uint64_t RioEnabled : 1;
|
|
uint64_t RESERVED : 18;
|
|
#else
|
|
uint64_t RESERVED : 26;
|
|
#endif
|
|
} IsSet;
|
|
};
|
|
|
|
uint64_t MaxBytesPerKey;
|
|
uint64_t HandshakeIdleTimeoutMs;
|
|
uint64_t IdleTimeoutMs;
|
|
uint64_t MtuDiscoverySearchCompleteTimeoutUs;
|
|
uint32_t TlsClientMaxSendBuffer;
|
|
uint32_t TlsServerMaxSendBuffer;
|
|
uint32_t StreamRecvWindowDefault;
|
|
uint32_t StreamRecvBufferDefault;
|
|
uint32_t ConnFlowControlWindow;
|
|
uint32_t MaxWorkerQueueDelayUs;
|
|
uint32_t MaxStatelessOperations;
|
|
uint32_t InitialWindowPackets;
|
|
uint32_t SendIdleTimeoutMs;
|
|
uint32_t InitialRttMs;
|
|
uint32_t MaxAckDelayMs;
|
|
uint32_t DisconnectTimeoutMs;
|
|
uint32_t KeepAliveIntervalMs;
|
|
uint16_t CongestionControlAlgorithm; // QUIC_CONGESTION_CONTROL_ALGORITHM
|
|
uint16_t PeerBidiStreamCount;
|
|
uint16_t PeerUnidiStreamCount;
|
|
uint16_t MaxBindingStatelessOperations;
|
|
uint16_t StatelessOperationExpirationMs;
|
|
uint16_t MinimumMtu;
|
|
uint16_t MaximumMtu;
|
|
uint8_t SendBufferingEnabled : 1;
|
|
uint8_t PacingEnabled : 1;
|
|
uint8_t MigrationEnabled : 1;
|
|
uint8_t DatagramReceiveEnabled : 1;
|
|
uint8_t ServerResumptionLevel : 2; // QUIC_SERVER_RESUMPTION_LEVEL
|
|
uint8_t GreaseQuicBitEnabled : 1;
|
|
uint8_t EcnEnabled : 1;
|
|
uint8_t MaxOperationsPerDrain;
|
|
uint8_t MtuDiscoveryMissingProbeCount;
|
|
uint32_t DestCidUpdateIdleTimeoutMs;
|
|
union {
|
|
uint64_t Flags;
|
|
struct {
|
|
uint64_t HyStartEnabled : 1;
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
uint64_t EncryptionOffloadAllowed : 1;
|
|
uint64_t ReliableResetEnabled : 1;
|
|
uint64_t OneWayDelayEnabled : 1;
|
|
uint64_t NetStatsEventEnabled : 1;
|
|
uint64_t StreamMultiReceiveEnabled : 1;
|
|
uint64_t XdpEnabled : 1;
|
|
uint64_t QTIPEnabled : 1;
|
|
uint64_t RioEnabled : 1;
|
|
uint64_t ReservedFlags : 55;
|
|
#else
|
|
uint64_t ReservedFlags : 63;
|
|
#endif
|
|
};
|
|
};
|
|
uint32_t StreamRecvWindowBidiLocalDefault;
|
|
uint32_t StreamRecvWindowBidiRemoteDefault;
|
|
uint32_t StreamRecvWindowUnidiDefault;
|
|
|
|
} QUIC_SETTINGS;
|
|
|
|
//
|
|
// This struct enables QUIC applications to support SSLKEYLOGFILE
|
|
// for debugging packet captures with e.g. Wireshark.
|
|
//
|
|
|
|
#define QUIC_TLS_SECRETS_MAX_SECRET_LEN 64
|
|
typedef struct QUIC_TLS_SECRETS {
|
|
uint8_t SecretLength;
|
|
struct {
|
|
uint8_t ClientRandom : 1;
|
|
uint8_t ClientEarlyTrafficSecret : 1;
|
|
uint8_t ClientHandshakeTrafficSecret : 1;
|
|
uint8_t ServerHandshakeTrafficSecret : 1;
|
|
uint8_t ClientTrafficSecret0 : 1;
|
|
uint8_t ServerTrafficSecret0 : 1;
|
|
} IsSet;
|
|
uint8_t ClientRandom[32];
|
|
uint8_t ClientEarlyTrafficSecret[QUIC_TLS_SECRETS_MAX_SECRET_LEN];
|
|
uint8_t ClientHandshakeTrafficSecret[QUIC_TLS_SECRETS_MAX_SECRET_LEN];
|
|
uint8_t ServerHandshakeTrafficSecret[QUIC_TLS_SECRETS_MAX_SECRET_LEN];
|
|
uint8_t ClientTrafficSecret0[QUIC_TLS_SECRETS_MAX_SECRET_LEN];
|
|
uint8_t ServerTrafficSecret0[QUIC_TLS_SECRETS_MAX_SECRET_LEN];
|
|
} QUIC_TLS_SECRETS;
|
|
|
|
typedef struct QUIC_STREAM_STATISTICS {
|
|
uint64_t ConnBlockedBySchedulingUs;
|
|
uint64_t ConnBlockedByPacingUs;
|
|
uint64_t ConnBlockedByAmplificationProtUs;
|
|
uint64_t ConnBlockedByCongestionControlUs;
|
|
uint64_t ConnBlockedByFlowControlUs;
|
|
uint64_t StreamBlockedByIdFlowControlUs;
|
|
uint64_t StreamBlockedByFlowControlUs;
|
|
uint64_t StreamBlockedByAppUs;
|
|
} QUIC_STREAM_STATISTICS;
|
|
|
|
typedef enum QUIC_AEAD_ALGORITHM_TYPE {
|
|
QUIC_AEAD_ALGORITHM_AES_128_GCM = 0,
|
|
QUIC_AEAD_ALGORITHM_AES_256_GCM = 1,
|
|
} QUIC_AEAD_ALGORITHM_TYPE;
|
|
|
|
typedef struct QUIC_STATELESS_RETRY_CONFIG {
|
|
QUIC_AEAD_ALGORITHM_TYPE Algorithm; // AEAD algorithm for the key.
|
|
uint32_t RotationMs; // Key rotation interval in milliseconds.
|
|
uint32_t SecretLength; // Length of the secret.
|
|
_Field_size_bytes_(SecretLength)
|
|
const uint8_t* Secret; // Secret to generate the key.
|
|
} QUIC_STATELESS_RETRY_CONFIG;
|
|
|
|
//
|
|
// Functions for associating application contexts with QUIC handles. MsQuic
|
|
// provides no explicit synchronization between parallel calls to these
|
|
// functions.
|
|
//
|
|
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_SET_CONTEXT_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Handle,
|
|
_In_opt_ void* Context
|
|
);
|
|
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
void*
|
|
(QUIC_API * QUIC_GET_CONTEXT_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Handle
|
|
);
|
|
|
|
//
|
|
// Sets the event handler for the QUIC handle. The type of the handler must be
|
|
// appropriate for the type of the handle. MsQuic provides no explicit
|
|
// synchronization between parallel calls to this function or the ones above.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_SET_CALLBACK_HANDLER_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Handle,
|
|
_In_ void* Handler,
|
|
_In_opt_ void* Context
|
|
);
|
|
|
|
//
|
|
// Get and Set parameters on a handle.
|
|
//
|
|
|
|
#define QUIC_PARAM_PREFIX_GLOBAL 0x01000000
|
|
#define QUIC_PARAM_PREFIX_REGISTRATION 0x02000000
|
|
#define QUIC_PARAM_PREFIX_CONFIGURATION 0x03000000
|
|
#define QUIC_PARAM_PREFIX_LISTENER 0x04000000
|
|
#define QUIC_PARAM_PREFIX_CONNECTION 0x05000000
|
|
#define QUIC_PARAM_PREFIX_TLS 0x06000000
|
|
#define QUIC_PARAM_PREFIX_TLS_SCHANNEL 0x07000000
|
|
#define QUIC_PARAM_PREFIX_STREAM 0x08000000
|
|
|
|
#define QUIC_PARAM_HIGH_PRIORITY 0x40000000 // Combine with any param to make it high priority.
|
|
|
|
#define QUIC_PARAM_IS_GLOBAL(Param) ((Param & 0x3F000000) == QUIC_PARAM_PREFIX_GLOBAL)
|
|
|
|
//
|
|
// Parameters for Global.
|
|
//
|
|
#define QUIC_PARAM_GLOBAL_RETRY_MEMORY_PERCENT 0x01000000 // uint16_t
|
|
#define QUIC_PARAM_GLOBAL_SUPPORTED_VERSIONS 0x01000001 // uint32_t[] - network byte order
|
|
#define QUIC_PARAM_GLOBAL_LOAD_BALACING_MODE 0x01000002 // uint16_t - QUIC_LOAD_BALANCING_MODE
|
|
#define QUIC_PARAM_GLOBAL_PERF_COUNTERS 0x01000003 // uint64_t[] - Array size is QUIC_PERF_COUNTER_MAX
|
|
#define QUIC_PARAM_GLOBAL_LIBRARY_VERSION 0x01000004 // uint32_t[4]
|
|
#define QUIC_PARAM_GLOBAL_SETTINGS 0x01000005 // QUIC_SETTINGS
|
|
#define QUIC_PARAM_GLOBAL_GLOBAL_SETTINGS 0x01000006 // QUIC_GLOBAL_SETTINGS
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
#define QUIC_PARAM_GLOBAL_VERSION_SETTINGS 0x01000007 // QUIC_VERSION_SETTINGS
|
|
#endif
|
|
#define QUIC_PARAM_GLOBAL_LIBRARY_GIT_HASH 0x01000008 // char[64]
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
#define QUIC_PARAM_GLOBAL_EXECUTION_CONFIG 0x01000009 // QUIC_GLOBAL_EXECUTION_CONFIG
|
|
#endif
|
|
#define QUIC_PARAM_GLOBAL_TLS_PROVIDER 0x0100000A // QUIC_TLS_PROVIDER
|
|
#define QUIC_PARAM_GLOBAL_STATELESS_RESET_KEY 0x0100000B // uint8_t[] - Array size is QUIC_STATELESS_RESET_KEY_LENGTH
|
|
#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.
|
|
#define QUIC_PARAM_GLOBAL_STATELESS_RETRY_CONFIG 0x0100000D // QUIC_STATELESS_RETRY_CONFIG
|
|
|
|
//
|
|
// Parameters for Registration.
|
|
//
|
|
|
|
//
|
|
// Parameters for Configuration.
|
|
//
|
|
#define QUIC_PARAM_CONFIGURATION_SETTINGS 0x03000000 // QUIC_SETTINGS
|
|
#define QUIC_PARAM_CONFIGURATION_TICKET_KEYS 0x03000001 // QUIC_TICKET_KEY_CONFIG[]
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
#define QUIC_PARAM_CONFIGURATION_VERSION_SETTINGS 0x03000002 // QUIC_VERSION_SETTINGS
|
|
#endif
|
|
// Schannel-specific Configuration parameter
|
|
typedef struct QUIC_SCHANNEL_CREDENTIAL_ATTRIBUTE_W {
|
|
unsigned long Attribute;
|
|
unsigned long BufferLength;
|
|
void* Buffer;
|
|
} QUIC_SCHANNEL_CREDENTIAL_ATTRIBUTE_W;
|
|
#define QUIC_PARAM_CONFIGURATION_SCHANNEL_CREDENTIAL_ATTRIBUTE_W 0x03000003 // QUIC_SCHANNEL_CREDENTIAL_ATTRIBUTE_W
|
|
|
|
//
|
|
// Parameters for Listener.
|
|
//
|
|
#define QUIC_PARAM_LISTENER_LOCAL_ADDRESS 0x04000000 // QUIC_ADDR
|
|
#define QUIC_PARAM_LISTENER_STATS 0x04000001 // QUIC_LISTENER_STATISTICS
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
#define QUIC_PARAM_LISTENER_CIBIR_ID 0x04000002 // uint8_t[] {offset, id[]}
|
|
#endif
|
|
#define QUIC_PARAM_DOS_MODE_EVENTS 0x04000004 // BOOLEAN
|
|
|
|
//
|
|
// Parameters for Connection.
|
|
//
|
|
#define QUIC_PARAM_CONN_QUIC_VERSION 0x05000000 // uint32_t
|
|
#define QUIC_PARAM_CONN_LOCAL_ADDRESS 0x05000001 // QUIC_ADDR
|
|
#define QUIC_PARAM_CONN_REMOTE_ADDRESS 0x05000002 // QUIC_ADDR
|
|
#define QUIC_PARAM_CONN_IDEAL_PROCESSOR 0x05000003 // uint16_t
|
|
#define QUIC_PARAM_CONN_SETTINGS 0x05000004 // QUIC_SETTINGS
|
|
#define QUIC_PARAM_CONN_STATISTICS 0x05000005 // QUIC_STATISTICS
|
|
#define QUIC_PARAM_CONN_STATISTICS_PLAT 0x05000006 // QUIC_STATISTICS
|
|
#define QUIC_PARAM_CONN_SHARE_UDP_BINDING 0x05000007 // uint8_t (BOOLEAN)
|
|
#define QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT 0x05000008 // uint16_t
|
|
#define QUIC_PARAM_CONN_LOCAL_UNIDI_STREAM_COUNT 0x05000009 // uint16_t
|
|
#define QUIC_PARAM_CONN_MAX_STREAM_IDS 0x0500000A // uint64_t[4]
|
|
#define QUIC_PARAM_CONN_CLOSE_REASON_PHRASE 0x0500000B // char[]
|
|
#define QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME 0x0500000C // QUIC_STREAM_SCHEDULING_SCHEME
|
|
#define QUIC_PARAM_CONN_DATAGRAM_RECEIVE_ENABLED 0x0500000D // uint8_t (BOOLEAN)
|
|
#define QUIC_PARAM_CONN_DATAGRAM_SEND_ENABLED 0x0500000E // uint8_t (BOOLEAN)
|
|
#ifdef QUIC_API_ENABLE_INSECURE_FEATURES
|
|
#define QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION 0x0500000F // uint8_t (BOOLEAN)
|
|
#endif
|
|
#define QUIC_PARAM_CONN_RESUMPTION_TICKET 0x05000010 // uint8_t[]
|
|
#define QUIC_PARAM_CONN_PEER_CERTIFICATE_VALID 0x05000011 // uint8_t (BOOLEAN)
|
|
#define QUIC_PARAM_CONN_LOCAL_INTERFACE 0x05000012 // uint32_t
|
|
#define QUIC_PARAM_CONN_TLS_SECRETS 0x05000013 // QUIC_TLS_SECRETS (SSLKEYLOGFILE compatible)
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
#define QUIC_PARAM_CONN_VERSION_SETTINGS 0x05000014 // QUIC_VERSION_SETTINGS
|
|
#define QUIC_PARAM_CONN_CIBIR_ID 0x05000015 // uint8_t[] {offset, id[]}
|
|
#endif
|
|
#define QUIC_PARAM_CONN_STATISTICS_V2 0x05000016 // QUIC_STATISTICS_V2
|
|
#define QUIC_PARAM_CONN_STATISTICS_V2_PLAT 0x05000017 // QUIC_STATISTICS_V2
|
|
#define QUIC_PARAM_CONN_ORIG_DEST_CID 0x05000018 // uint8_t[]
|
|
#define QUIC_PARAM_CONN_SEND_DSCP 0x05000019 // uint8_t
|
|
|
|
//
|
|
// Parameters for TLS.
|
|
//
|
|
#define QUIC_PARAM_TLS_HANDSHAKE_INFO 0x06000000 // QUIC_HANDSHAKE_INFO
|
|
#define QUIC_PARAM_TLS_NEGOTIATED_ALPN 0x06000001 // uint8_t[] (max 255 bytes)
|
|
|
|
#ifdef WIN32 // Schannel specific TLS parameters
|
|
typedef struct QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_W {
|
|
unsigned long Attribute;
|
|
void* Buffer;
|
|
} QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_W;
|
|
#define QUIC_PARAM_TLS_SCHANNEL_CONTEXT_ATTRIBUTE_W 0x07000000 // QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_W
|
|
typedef struct QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_EX_W {
|
|
unsigned long Attribute;
|
|
unsigned long BufferLength;
|
|
void* Buffer;
|
|
} QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_EX_W;
|
|
#define QUIC_PARAM_TLS_SCHANNEL_CONTEXT_ATTRIBUTE_EX_W 0x07000001 // QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_EX_W
|
|
#define QUIC_PARAM_TLS_SCHANNEL_SECURITY_CONTEXT_TOKEN 0x07000002 // HANDLE
|
|
#endif
|
|
|
|
//
|
|
// Parameters for Stream.
|
|
//
|
|
#define QUIC_PARAM_STREAM_ID 0x08000000 // QUIC_UINT62
|
|
#define QUIC_PARAM_STREAM_0RTT_LENGTH 0x08000001 // uint64_t
|
|
#define QUIC_PARAM_STREAM_IDEAL_SEND_BUFFER_SIZE 0x08000002 // uint64_t - bytes
|
|
#define QUIC_PARAM_STREAM_PRIORITY 0x08000003 // uint16_t - 0 (low) to 0xFFFF (high) - 0x7FFF (default)
|
|
#define QUIC_PARAM_STREAM_STATISTICS 0X08000004 // QUIC_STREAM_STATISTICS
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
#define QUIC_PARAM_STREAM_RELIABLE_OFFSET 0x08000005 // uint64_t
|
|
#endif
|
|
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_SET_PARAM_FN)(
|
|
_When_(QUIC_PARAM_IS_GLOBAL(Param), _Reserved_)
|
|
_When_(!QUIC_PARAM_IS_GLOBAL(Param), _In_ _Pre_defensive_)
|
|
HQUIC Handle,
|
|
_In_ uint32_t Param,
|
|
_In_ uint32_t BufferLength,
|
|
_In_reads_bytes_(BufferLength)
|
|
const void* Buffer
|
|
);
|
|
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_GET_PARAM_FN)(
|
|
_When_(QUIC_PARAM_IS_GLOBAL(Param), _Reserved_)
|
|
_When_(!QUIC_PARAM_IS_GLOBAL(Param), _In_ _Pre_defensive_)
|
|
HQUIC Handle,
|
|
_In_ uint32_t Param,
|
|
_Inout_ _Pre_defensive_ uint32_t* BufferLength,
|
|
_Out_writes_bytes_opt_(*BufferLength)
|
|
void* Buffer
|
|
);
|
|
|
|
//
|
|
// Registration Context Interface.
|
|
//
|
|
|
|
//
|
|
// Opens a new registration.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_REGISTRATION_OPEN_FN)(
|
|
_In_opt_ const QUIC_REGISTRATION_CONFIG* Config,
|
|
_Outptr_ _At_(*Registration, __drv_allocatesMem(Mem)) _Pre_defensive_
|
|
HQUIC* Registration
|
|
);
|
|
|
|
//
|
|
// Closes the registration. This function synchronizes the cleanup of all
|
|
// child objects. It does this by blocking until all those child objects have
|
|
// been closed by the application.
|
|
// N.B. This function will deadlock if called in any MsQuic callbacks.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_REGISTRATION_CLOSE_FN)(
|
|
_In_ _Pre_defensive_ __drv_freesMem(Mem)
|
|
HQUIC Registration
|
|
);
|
|
|
|
//
|
|
// Calls shutdown for all connections in this registration. Don't call on a
|
|
// MsQuic callback thread or it might deadlock.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_REGISTRATION_SHUTDOWN_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Registration,
|
|
_In_ QUIC_CONNECTION_SHUTDOWN_FLAGS Flags,
|
|
_In_ _Pre_defensive_ QUIC_UINT62 ErrorCode // Application defined error code
|
|
);
|
|
|
|
//
|
|
// Configuration Interface.
|
|
//
|
|
|
|
//
|
|
// Opens a new configuration.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_CONFIGURATION_OPEN_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Registration,
|
|
_In_reads_(AlpnBufferCount) _Pre_defensive_
|
|
const QUIC_BUFFER* const AlpnBuffers,
|
|
_In_range_(>, 0) uint32_t AlpnBufferCount,
|
|
_In_reads_bytes_opt_(SettingsSize)
|
|
const QUIC_SETTINGS* Settings,
|
|
_In_ uint32_t SettingsSize,
|
|
_In_opt_ void* Context,
|
|
_Outptr_ _At_(*Configuration, __drv_allocatesMem(Mem)) _Pre_defensive_
|
|
HQUIC* Configuration
|
|
);
|
|
|
|
//
|
|
// Closes an existing configuration.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_CONFIGURATION_CLOSE_FN)(
|
|
_In_ _Pre_defensive_ __drv_freesMem(Mem)
|
|
HQUIC Configuration
|
|
);
|
|
|
|
//
|
|
// Loads the credentials based on the input configuration.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_CONFIGURATION_LOAD_CREDENTIAL_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Configuration,
|
|
_In_ _Pre_defensive_ const QUIC_CREDENTIAL_CONFIG* CredConfig
|
|
);
|
|
|
|
//
|
|
// Listener Context Interface.
|
|
//
|
|
|
|
typedef enum QUIC_LISTENER_EVENT_TYPE {
|
|
QUIC_LISTENER_EVENT_NEW_CONNECTION = 0,
|
|
QUIC_LISTENER_EVENT_STOP_COMPLETE = 1,
|
|
QUIC_LISTENER_EVENT_DOS_MODE_CHANGED = 2,
|
|
} QUIC_LISTENER_EVENT_TYPE;
|
|
|
|
typedef struct QUIC_LISTENER_EVENT {
|
|
QUIC_LISTENER_EVENT_TYPE Type;
|
|
union {
|
|
struct {
|
|
const QUIC_NEW_CONNECTION_INFO* Info;
|
|
HQUIC Connection;
|
|
} NEW_CONNECTION;
|
|
struct {
|
|
BOOLEAN AppCloseInProgress : 1;
|
|
BOOLEAN RESERVED : 7;
|
|
} STOP_COMPLETE;
|
|
struct {
|
|
BOOLEAN DosModeEnabled : 1;
|
|
BOOLEAN RESERVED : 7;
|
|
} DOS_MODE_CHANGED;
|
|
};
|
|
} QUIC_LISTENER_EVENT;
|
|
|
|
typedef
|
|
_When_(
|
|
Event->Type != QUIC_LISTENER_EVENT_DOS_MODE_CHANGED,
|
|
_IRQL_requires_max_(PASSIVE_LEVEL))
|
|
_When_(
|
|
Event->Type == QUIC_LISTENER_EVENT_DOS_MODE_CHANGED,
|
|
_IRQL_requires_max_(DISPATCH_LEVEL))
|
|
_Function_class_(QUIC_LISTENER_CALLBACK)
|
|
QUIC_STATUS
|
|
(QUIC_API QUIC_LISTENER_CALLBACK)(
|
|
_In_ HQUIC Listener,
|
|
_In_opt_ void* Context,
|
|
_Inout_ QUIC_LISTENER_EVENT* Event
|
|
);
|
|
|
|
typedef QUIC_LISTENER_CALLBACK *QUIC_LISTENER_CALLBACK_HANDLER;
|
|
|
|
//
|
|
// Opens a new listener.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_LISTENER_OPEN_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Registration,
|
|
_In_ _Pre_defensive_ QUIC_LISTENER_CALLBACK_HANDLER Handler,
|
|
_In_opt_ void* Context,
|
|
_Outptr_ _At_(*Listener, __drv_allocatesMem(Mem)) _Pre_defensive_
|
|
HQUIC* Listener
|
|
);
|
|
|
|
//
|
|
// Closes an existing listener.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_LISTENER_CLOSE_FN)(
|
|
_In_ _Pre_defensive_ __drv_freesMem(Mem)
|
|
HQUIC Listener
|
|
);
|
|
|
|
//
|
|
// Starts the listener processing incoming connections.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_LISTENER_START_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Listener,
|
|
_In_reads_(AlpnBufferCount) _Pre_defensive_
|
|
const QUIC_BUFFER* const AlpnBuffers,
|
|
_In_range_(>, 0) uint32_t AlpnBufferCount,
|
|
_In_opt_ const QUIC_ADDR* LocalAddress
|
|
);
|
|
|
|
//
|
|
// Asynchronously stops the listener from processing incoming connections.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_LISTENER_STOP_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Listener
|
|
);
|
|
|
|
//
|
|
// Connections
|
|
//
|
|
|
|
typedef enum QUIC_CONNECTION_EVENT_TYPE {
|
|
QUIC_CONNECTION_EVENT_CONNECTED = 0,
|
|
QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_TRANSPORT = 1, // The transport started the shutdown process.
|
|
QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_PEER = 2, // The peer application started the shutdown process.
|
|
QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE = 3, // Ready for the handle to be closed.
|
|
QUIC_CONNECTION_EVENT_LOCAL_ADDRESS_CHANGED = 4,
|
|
QUIC_CONNECTION_EVENT_PEER_ADDRESS_CHANGED = 5,
|
|
QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED = 6,
|
|
QUIC_CONNECTION_EVENT_STREAMS_AVAILABLE = 7,
|
|
QUIC_CONNECTION_EVENT_PEER_NEEDS_STREAMS = 8,
|
|
QUIC_CONNECTION_EVENT_IDEAL_PROCESSOR_CHANGED = 9,
|
|
QUIC_CONNECTION_EVENT_DATAGRAM_STATE_CHANGED = 10,
|
|
QUIC_CONNECTION_EVENT_DATAGRAM_RECEIVED = 11,
|
|
QUIC_CONNECTION_EVENT_DATAGRAM_SEND_STATE_CHANGED = 12,
|
|
QUIC_CONNECTION_EVENT_RESUMED = 13, // Server-only; provides resumption data, if any.
|
|
QUIC_CONNECTION_EVENT_RESUMPTION_TICKET_RECEIVED = 14, // Client-only; provides ticket to persist, if any.
|
|
QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED = 15, // Only with QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED set
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
QUIC_CONNECTION_EVENT_RELIABLE_RESET_NEGOTIATED = 16, // Only indicated if QUIC_SETTINGS.ReliableResetEnabled is TRUE.
|
|
QUIC_CONNECTION_EVENT_ONE_WAY_DELAY_NEGOTIATED = 17, // Only indicated if QUIC_SETTINGS.OneWayDelayEnabled is TRUE.
|
|
QUIC_CONNECTION_EVENT_NETWORK_STATISTICS = 18, // Only indicated if QUIC_SETTINGS.EnableNetStatsEvent is TRUE.
|
|
#endif
|
|
} QUIC_CONNECTION_EVENT_TYPE;
|
|
|
|
typedef struct QUIC_CONNECTION_EVENT {
|
|
QUIC_CONNECTION_EVENT_TYPE Type;
|
|
union {
|
|
struct {
|
|
BOOLEAN SessionResumed;
|
|
_Field_range_(>, 0)
|
|
uint8_t NegotiatedAlpnLength;
|
|
_Field_size_(NegotiatedAlpnLength)
|
|
const uint8_t* NegotiatedAlpn;
|
|
} CONNECTED;
|
|
struct {
|
|
QUIC_STATUS Status;
|
|
QUIC_UINT62 ErrorCode; // Wire format error code.
|
|
} SHUTDOWN_INITIATED_BY_TRANSPORT;
|
|
struct {
|
|
QUIC_UINT62 ErrorCode;
|
|
} SHUTDOWN_INITIATED_BY_PEER;
|
|
struct {
|
|
BOOLEAN HandshakeCompleted : 1;
|
|
BOOLEAN PeerAcknowledgedShutdown : 1;
|
|
BOOLEAN AppCloseInProgress : 1;
|
|
} SHUTDOWN_COMPLETE;
|
|
struct {
|
|
const QUIC_ADDR* Address;
|
|
} LOCAL_ADDRESS_CHANGED;
|
|
struct {
|
|
const QUIC_ADDR* Address;
|
|
} PEER_ADDRESS_CHANGED;
|
|
struct {
|
|
HQUIC Stream;
|
|
QUIC_STREAM_OPEN_FLAGS Flags;
|
|
} PEER_STREAM_STARTED;
|
|
struct {
|
|
uint16_t BidirectionalCount;
|
|
uint16_t UnidirectionalCount;
|
|
} STREAMS_AVAILABLE;
|
|
struct {
|
|
BOOLEAN Bidirectional;
|
|
} PEER_NEEDS_STREAMS;
|
|
struct {
|
|
uint16_t IdealProcessor;
|
|
uint16_t PartitionIndex;
|
|
} IDEAL_PROCESSOR_CHANGED;
|
|
struct {
|
|
BOOLEAN SendEnabled;
|
|
uint16_t MaxSendLength;
|
|
} DATAGRAM_STATE_CHANGED;
|
|
struct {
|
|
const QUIC_BUFFER* Buffer;
|
|
QUIC_RECEIVE_FLAGS Flags;
|
|
} DATAGRAM_RECEIVED;
|
|
struct {
|
|
/* inout */ void* ClientContext;
|
|
QUIC_DATAGRAM_SEND_STATE State;
|
|
} DATAGRAM_SEND_STATE_CHANGED;
|
|
struct {
|
|
uint16_t ResumptionStateLength;
|
|
const uint8_t* ResumptionState;
|
|
} RESUMED;
|
|
struct {
|
|
_Field_range_(>, 0)
|
|
uint32_t ResumptionTicketLength;
|
|
_Field_size_(ResumptionTicketLength)
|
|
const uint8_t* ResumptionTicket;
|
|
} RESUMPTION_TICKET_RECEIVED;
|
|
struct {
|
|
QUIC_CERTIFICATE* Certificate; // Peer certificate (platform specific). Valid only during QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED callback.
|
|
uint32_t DeferredErrorFlags; // Bit flag of errors (only valid with QUIC_CREDENTIAL_FLAG_DEFER_CERTIFICATE_VALIDATION) - Schannel only, zero otherwise.
|
|
QUIC_STATUS DeferredStatus; // Most severe error status (only valid with QUIC_CREDENTIAL_FLAG_DEFER_CERTIFICATE_VALIDATION)
|
|
QUIC_CERTIFICATE_CHAIN* Chain; // Peer certificate chain (platform specific). Valid only during QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED callback.
|
|
} PEER_CERTIFICATE_RECEIVED;
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
struct {
|
|
BOOLEAN IsNegotiated;
|
|
} RELIABLE_RESET_NEGOTIATED;
|
|
struct {
|
|
BOOLEAN SendNegotiated; // TRUE if sending one-way delay timestamps is negotiated.
|
|
BOOLEAN ReceiveNegotiated; // TRUE if receiving one-way delay timestamps is negotiated.
|
|
} ONE_WAY_DELAY_NEGOTIATED;
|
|
struct {
|
|
uint32_t BytesInFlight; // Bytes that were sent on the wire, but not yet acked
|
|
uint64_t PostedBytes; // Total bytes queued, but not yet acked. These may contain sent bytes that may have potentially lost too.
|
|
uint64_t IdealBytes; // Ideal number of bytes required to be available to avoid limiting throughput
|
|
uint64_t SmoothedRTT; // Smoothed RTT value
|
|
uint32_t CongestionWindow; // Congestion Window
|
|
uint64_t Bandwidth; // Estimated bandwidth
|
|
} NETWORK_STATISTICS;
|
|
#endif
|
|
};
|
|
} QUIC_CONNECTION_EVENT;
|
|
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
_Function_class_(QUIC_CONNECTION_CALLBACK)
|
|
QUIC_STATUS
|
|
(QUIC_API QUIC_CONNECTION_CALLBACK)(
|
|
_In_ HQUIC Connection,
|
|
_In_opt_ void* Context,
|
|
_Inout_ QUIC_CONNECTION_EVENT* Event
|
|
);
|
|
|
|
typedef QUIC_CONNECTION_CALLBACK *QUIC_CONNECTION_CALLBACK_HANDLER;
|
|
|
|
//
|
|
// Opens a new connection.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_CONNECTION_OPEN_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Registration,
|
|
_In_ _Pre_defensive_ QUIC_CONNECTION_CALLBACK_HANDLER Handler,
|
|
_In_opt_ void* Context,
|
|
_Outptr_ _At_(*Connection, __drv_allocatesMem(Mem)) _Pre_defensive_
|
|
HQUIC* Connection
|
|
);
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_CONNECTION_OPEN_IN_PARTITION_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Registration,
|
|
_In_ uint16_t PartitionIndex,
|
|
_In_ _Pre_defensive_ QUIC_CONNECTION_CALLBACK_HANDLER Handler,
|
|
_In_opt_ void* Context,
|
|
_Outptr_ _At_(*Connection, __drv_allocatesMem(Mem)) _Pre_defensive_
|
|
HQUIC* Connection
|
|
);
|
|
|
|
//
|
|
// Closes an existing connection.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_CONNECTION_CLOSE_FN)(
|
|
_In_ _Pre_defensive_ __drv_freesMem(Mem)
|
|
HQUIC Connection
|
|
);
|
|
|
|
//
|
|
// Starts the shutdown process on the connection. This immediately and silently
|
|
// shuts down any open streams; which will trigger callbacks for
|
|
// QUIC_CONNECTION_EVENT_STREAM_CLOSED events. Does nothing if already shutdown.
|
|
// Can be passed either a connection or stream handle.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_CONNECTION_SHUTDOWN_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Connection,
|
|
_In_ QUIC_CONNECTION_SHUTDOWN_FLAGS Flags,
|
|
_In_ _Pre_defensive_ QUIC_UINT62 ErrorCode // Application defined error code
|
|
);
|
|
|
|
//
|
|
// Uses the QUIC (client) handle to start a connection attempt to the
|
|
// remote server. Can be passed either a connection or stream handle.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_CONNECTION_START_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Connection,
|
|
_In_ _Pre_defensive_ HQUIC Configuration,
|
|
_In_ QUIC_ADDRESS_FAMILY Family,
|
|
_In_reads_or_z_opt_(QUIC_MAX_SNI_LENGTH)
|
|
const char* ServerName,
|
|
_In_ uint16_t ServerPort // Host byte order
|
|
);
|
|
|
|
//
|
|
// Sets the (server-side) configuration handle for the connection. This must be
|
|
// called on an accepted connection in order to proceed with the QUIC handshake.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_CONNECTION_SET_CONFIGURATION_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Connection,
|
|
_In_ _Pre_defensive_ HQUIC Configuration
|
|
);
|
|
|
|
//
|
|
// Uses the QUIC (server) handle to send a resumption ticket to the remote
|
|
// client, optionally with app-specific data useful during resumption.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_CONNECTION_SEND_RESUMPTION_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Connection,
|
|
_In_ QUIC_SEND_RESUMPTION_FLAGS Flags,
|
|
_In_ uint16_t DataLength,
|
|
_In_reads_bytes_opt_(DataLength)
|
|
const uint8_t* ResumptionData
|
|
);
|
|
|
|
//
|
|
// Uses the QUIC (server) handle to complete resumption ticket validation.
|
|
// This must be called after server app handles ticket validation and then
|
|
// return QUIC_STATUS_PENDING.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_CONNECTION_COMP_RESUMPTION_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Connection,
|
|
_In_ BOOLEAN Result
|
|
);
|
|
|
|
//
|
|
// Uses the QUIC (client) handle to complete certificate validation.
|
|
// This must be called after client app handles certificate validation
|
|
// and then return QUIC_STATUS_PENDING. The TlsAlert value is ignored if Result
|
|
// equals TRUE (recommend just pass QUIC_TLS_ALERT_CODE_SUCCESS).
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_CONNECTION_COMP_CERT_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Connection,
|
|
_In_ BOOLEAN Result,
|
|
_In_ QUIC_TLS_ALERT_CODES TlsAlert
|
|
);
|
|
|
|
//
|
|
// Streams
|
|
//
|
|
|
|
typedef enum QUIC_STREAM_EVENT_TYPE {
|
|
QUIC_STREAM_EVENT_START_COMPLETE = 0,
|
|
QUIC_STREAM_EVENT_RECEIVE = 1,
|
|
QUIC_STREAM_EVENT_SEND_COMPLETE = 2,
|
|
QUIC_STREAM_EVENT_PEER_SEND_SHUTDOWN = 3,
|
|
QUIC_STREAM_EVENT_PEER_SEND_ABORTED = 4,
|
|
QUIC_STREAM_EVENT_PEER_RECEIVE_ABORTED = 5,
|
|
QUIC_STREAM_EVENT_SEND_SHUTDOWN_COMPLETE = 6,
|
|
QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE = 7,
|
|
QUIC_STREAM_EVENT_IDEAL_SEND_BUFFER_SIZE = 8,
|
|
QUIC_STREAM_EVENT_PEER_ACCEPTED = 9,
|
|
QUIC_STREAM_EVENT_CANCEL_ON_LOSS = 10,
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
QUIC_STREAM_EVENT_RECEIVE_BUFFER_NEEDED = 11,
|
|
#endif
|
|
} QUIC_STREAM_EVENT_TYPE;
|
|
|
|
typedef struct QUIC_STREAM_EVENT {
|
|
QUIC_STREAM_EVENT_TYPE Type;
|
|
union {
|
|
struct {
|
|
QUIC_STATUS Status;
|
|
QUIC_UINT62 ID;
|
|
BOOLEAN PeerAccepted : 1;
|
|
BOOLEAN RESERVED : 7;
|
|
} START_COMPLETE;
|
|
struct {
|
|
/* in */ uint64_t AbsoluteOffset;
|
|
/* inout */ uint64_t TotalBufferLength;
|
|
_Field_size_(BufferCount)
|
|
/* in */ const QUIC_BUFFER* Buffers;
|
|
_Field_range_(0, UINT32_MAX)
|
|
/* in */ uint32_t BufferCount;
|
|
/* in */ QUIC_RECEIVE_FLAGS Flags;
|
|
} RECEIVE;
|
|
struct {
|
|
BOOLEAN Canceled;
|
|
void* ClientContext;
|
|
} SEND_COMPLETE;
|
|
struct {
|
|
QUIC_UINT62 ErrorCode;
|
|
} PEER_SEND_ABORTED;
|
|
struct {
|
|
QUIC_UINT62 ErrorCode;
|
|
} PEER_RECEIVE_ABORTED;
|
|
struct {
|
|
BOOLEAN Graceful;
|
|
} SEND_SHUTDOWN_COMPLETE;
|
|
struct {
|
|
BOOLEAN ConnectionShutdown;
|
|
BOOLEAN AppCloseInProgress : 1;
|
|
BOOLEAN ConnectionShutdownByApp : 1;
|
|
BOOLEAN ConnectionClosedRemotely : 1;
|
|
BOOLEAN RESERVED : 5;
|
|
QUIC_UINT62 ConnectionErrorCode;
|
|
QUIC_STATUS ConnectionCloseStatus;
|
|
} SHUTDOWN_COMPLETE;
|
|
struct {
|
|
uint64_t ByteCount;
|
|
} IDEAL_SEND_BUFFER_SIZE;
|
|
struct {
|
|
/* out */ QUIC_UINT62 ErrorCode;
|
|
} CANCEL_ON_LOSS;
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
struct {
|
|
/* in */ uint64_t BufferLengthNeeded;
|
|
} RECEIVE_BUFFER_NEEDED;
|
|
#endif
|
|
};
|
|
} QUIC_STREAM_EVENT;
|
|
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
_Function_class_(QUIC_STREAM_CALLBACK)
|
|
QUIC_STATUS
|
|
(QUIC_API QUIC_STREAM_CALLBACK)(
|
|
_In_ HQUIC Stream,
|
|
_In_opt_ void* Context,
|
|
_Inout_ QUIC_STREAM_EVENT* Event
|
|
);
|
|
|
|
typedef QUIC_STREAM_CALLBACK *QUIC_STREAM_CALLBACK_HANDLER;
|
|
|
|
//
|
|
// Opens a stream on the given connection.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_STREAM_OPEN_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Connection,
|
|
_In_ QUIC_STREAM_OPEN_FLAGS Flags,
|
|
_In_ _Pre_defensive_ QUIC_STREAM_CALLBACK_HANDLER Handler,
|
|
_In_opt_ void* Context,
|
|
_Outptr_ _At_(*Stream, __drv_allocatesMem(Mem)) _Pre_defensive_
|
|
HQUIC* Stream
|
|
);
|
|
|
|
//
|
|
// Closes a stream handle.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_STREAM_CLOSE_FN)(
|
|
_In_ _Pre_defensive_ __drv_freesMem(Mem)
|
|
HQUIC Stream
|
|
);
|
|
|
|
//
|
|
// Starts processing the stream.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_STREAM_START_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Stream,
|
|
_In_ QUIC_STREAM_START_FLAGS Flags
|
|
);
|
|
|
|
//
|
|
// Shuts the stream down as specified, and waits for graceful
|
|
// shutdowns to complete. Does nothing if already shut down.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_STREAM_SHUTDOWN_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Stream,
|
|
_In_ QUIC_STREAM_SHUTDOWN_FLAGS Flags,
|
|
_In_ _Pre_defensive_ QUIC_UINT62 ErrorCode // Application defined error code
|
|
);
|
|
|
|
//
|
|
// Sends data on an open stream.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_STREAM_SEND_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Stream,
|
|
_In_reads_(BufferCount) _Pre_defensive_
|
|
const QUIC_BUFFER* const Buffers,
|
|
_In_ uint32_t BufferCount,
|
|
_In_ QUIC_SEND_FLAGS Flags,
|
|
_In_opt_ void* ClientSendContext
|
|
);
|
|
|
|
//
|
|
// Completes a previously pended receive callback.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
void
|
|
(QUIC_API * QUIC_STREAM_RECEIVE_COMPLETE_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Stream,
|
|
_In_ uint64_t BufferLength
|
|
);
|
|
|
|
//
|
|
// Enables or disables stream receive callbacks.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_STREAM_RECEIVE_SET_ENABLED_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Stream,
|
|
_In_ BOOLEAN IsEnabled
|
|
);
|
|
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
//
|
|
// Provides receive buffers to the stream.
|
|
// The buffers are owned by the caller and must remain valid until a receive
|
|
// indication for all bytes in the buffer, or the stream is closed.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_STREAM_PROVIDE_RECEIVE_BUFFERS_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Stream,
|
|
_In_ uint32_t BufferCount,
|
|
_In_reads_(BufferCount) const QUIC_BUFFER* Buffers
|
|
);
|
|
|
|
#endif
|
|
|
|
//
|
|
// Datagrams
|
|
//
|
|
|
|
//
|
|
// Sends an unreliable datagram on the connection. Note, the total payload
|
|
// of the send must fit in a single QUIC packet.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_DATAGRAM_SEND_FN)(
|
|
_In_ _Pre_defensive_ HQUIC Connection,
|
|
_In_reads_(BufferCount) _Pre_defensive_
|
|
const QUIC_BUFFER* const Buffers,
|
|
_In_ uint32_t BufferCount,
|
|
_In_ QUIC_SEND_FLAGS Flags,
|
|
_In_opt_ void* ClientSendContext
|
|
);
|
|
|
|
//
|
|
// Connection Pool API
|
|
//
|
|
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
|
|
typedef enum QUIC_CONNECTION_POOL_FLAGS {
|
|
QUIC_CONNECTION_POOL_FLAG_NONE = 0x00000000,
|
|
QUIC_CONNECTION_POOL_FLAG_CLOSE_ON_FAILURE = 0x00000001,
|
|
} QUIC_CONNECTION_POOL_FLAGS;
|
|
|
|
DEFINE_ENUM_FLAG_OPERATORS(QUIC_CONNECTION_POOL_FLAGS);
|
|
|
|
typedef struct QUIC_CONNECTION_POOL_CONFIG {
|
|
HQUIC Registration;
|
|
HQUIC Configuration;
|
|
QUIC_CONNECTION_CALLBACK_HANDLER Handler;
|
|
_Field_size_opt_(NumberOfConnections)
|
|
void** Context; // Optional
|
|
_Field_z_ const char* ServerName;
|
|
const QUIC_ADDR* ServerAddress; // Optional
|
|
QUIC_ADDRESS_FAMILY Family;
|
|
uint16_t ServerPort;
|
|
uint16_t NumberOfConnections;
|
|
_At_buffer_(_Curr_, _Iter_, NumberOfConnections, _Field_size_(CibirIdLength))
|
|
_Field_size_opt_(NumberOfConnections)
|
|
uint8_t** CibirIds; // Optional
|
|
uint8_t CibirIdLength; // Zero if not using CIBIR
|
|
QUIC_CONNECTION_POOL_FLAGS Flags;
|
|
} QUIC_CONNECTION_POOL_CONFIG;
|
|
|
|
//
|
|
// Creates a simple pool of NumberOfConnections connections, all with the same
|
|
// Handler, and puts them in the caller-supplied array.
|
|
// Connections are spread evenly across RSS CPUs as much as possible.
|
|
// If NumberOfConnections is more than the number of RSS cores, then multiple
|
|
// connections will be put on the same CPU.
|
|
//
|
|
typedef
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
QUIC_STATUS
|
|
(QUIC_API * QUIC_CONN_POOL_CREATE_FN)(
|
|
_In_ QUIC_CONNECTION_POOL_CONFIG* Config,
|
|
_Out_writes_(Config->NumberOfConnections)
|
|
HQUIC* ConnectionPool
|
|
);
|
|
|
|
#endif // QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
|
|
//
|
|
// Version 2 API Function Table. Returned from MsQuicOpenVersion when Version
|
|
// is 2. Also returned from MsQuicOpen2.
|
|
//
|
|
typedef struct QUIC_API_TABLE {
|
|
|
|
QUIC_SET_CONTEXT_FN SetContext;
|
|
QUIC_GET_CONTEXT_FN GetContext;
|
|
QUIC_SET_CALLBACK_HANDLER_FN SetCallbackHandler;
|
|
|
|
QUIC_SET_PARAM_FN SetParam;
|
|
QUIC_GET_PARAM_FN GetParam;
|
|
|
|
QUIC_REGISTRATION_OPEN_FN RegistrationOpen;
|
|
QUIC_REGISTRATION_CLOSE_FN RegistrationClose;
|
|
QUIC_REGISTRATION_SHUTDOWN_FN RegistrationShutdown;
|
|
|
|
QUIC_CONFIGURATION_OPEN_FN ConfigurationOpen;
|
|
QUIC_CONFIGURATION_CLOSE_FN ConfigurationClose;
|
|
QUIC_CONFIGURATION_LOAD_CREDENTIAL_FN
|
|
ConfigurationLoadCredential;
|
|
|
|
QUIC_LISTENER_OPEN_FN ListenerOpen;
|
|
QUIC_LISTENER_CLOSE_FN ListenerClose;
|
|
QUIC_LISTENER_START_FN ListenerStart;
|
|
QUIC_LISTENER_STOP_FN ListenerStop;
|
|
|
|
QUIC_CONNECTION_OPEN_FN ConnectionOpen;
|
|
QUIC_CONNECTION_CLOSE_FN ConnectionClose;
|
|
QUIC_CONNECTION_SHUTDOWN_FN ConnectionShutdown;
|
|
QUIC_CONNECTION_START_FN ConnectionStart;
|
|
QUIC_CONNECTION_SET_CONFIGURATION_FN
|
|
ConnectionSetConfiguration;
|
|
QUIC_CONNECTION_SEND_RESUMPTION_FN ConnectionSendResumptionTicket;
|
|
|
|
QUIC_STREAM_OPEN_FN StreamOpen;
|
|
QUIC_STREAM_CLOSE_FN StreamClose;
|
|
QUIC_STREAM_START_FN StreamStart;
|
|
QUIC_STREAM_SHUTDOWN_FN StreamShutdown;
|
|
QUIC_STREAM_SEND_FN StreamSend;
|
|
QUIC_STREAM_RECEIVE_COMPLETE_FN StreamReceiveComplete;
|
|
QUIC_STREAM_RECEIVE_SET_ENABLED_FN StreamReceiveSetEnabled;
|
|
|
|
QUIC_DATAGRAM_SEND_FN DatagramSend;
|
|
|
|
QUIC_CONNECTION_COMP_RESUMPTION_FN ConnectionResumptionTicketValidationComplete; // Available from v2.2
|
|
QUIC_CONNECTION_COMP_CERT_FN ConnectionCertificateValidationComplete; // Available from v2.2
|
|
|
|
QUIC_CONNECTION_OPEN_IN_PARTITION_FN
|
|
ConnectionOpenInPartition; // Available from v2.5
|
|
|
|
#ifdef QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
QUIC_STREAM_PROVIDE_RECEIVE_BUFFERS_FN
|
|
StreamProvideReceiveBuffers; // Available from v2.5
|
|
|
|
QUIC_CONN_POOL_CREATE_FN ConnectionPoolCreate; // Available from v2.5
|
|
|
|
#ifndef _KERNEL_MODE
|
|
QUIC_EXECUTION_CREATE_FN ExecutionCreate; // Available from v2.5
|
|
QUIC_EXECUTION_DELETE_FN ExecutionDelete; // Available from v2.5
|
|
QUIC_EXECUTION_POLL_FN ExecutionPoll; // Available from v2.5
|
|
#endif // _KERNEL_MODE
|
|
#endif // QUIC_API_ENABLE_PREVIEW_FEATURES
|
|
|
|
} QUIC_API_TABLE;
|
|
|
|
#define QUIC_API_VERSION_1 1 // Not supported any more
|
|
#define QUIC_API_VERSION_2 2 // Current latest
|
|
|
|
#if defined(_KERNEL_MODE) && !defined(_WIN64)
|
|
|
|
//
|
|
// 32 bit kernel mode is no longer supported, so shim behavior in 32 bit kernel
|
|
// mode
|
|
//
|
|
#define MsQuicClose(QuicApi) UNREFERENCED_PARAMETER((QuicApi))
|
|
#define MsQuicOpenVersion(Version, QuicApi) QUIC_STATUS_NOT_SUPPORTED
|
|
|
|
#else
|
|
|
|
//
|
|
// Opens the API library and initializes it if this is the first call for the
|
|
// process. It returns API function table for the rest of the API's functions.
|
|
// MsQuicClose must be called when the app is done with the function table.
|
|
//
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
_Check_return_
|
|
#if (__cplusplus >= 201703L || _MSVC_LANG >= 201703L)
|
|
[[nodiscard]]
|
|
#endif
|
|
QUIC_STATUS
|
|
QUIC_API
|
|
MsQuicOpenVersion(
|
|
_In_ uint32_t Version,
|
|
_Out_ _Pre_defensive_ const void** QuicApi
|
|
);
|
|
|
|
//
|
|
// Cleans up the function table returned from MsQuicOpenVersion and releases the
|
|
// reference on the API.
|
|
//
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
void
|
|
QUIC_API
|
|
MsQuicClose(
|
|
_In_ _Pre_defensive_ const void* QuicApi
|
|
);
|
|
|
|
#endif
|
|
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
_Check_return_
|
|
typedef
|
|
QUIC_STATUS
|
|
(QUIC_API *MsQuicOpenVersionFn)(
|
|
_In_ uint32_t Version,
|
|
_Out_ _Pre_defensive_ const void** QuicApi
|
|
);
|
|
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
typedef
|
|
void
|
|
(QUIC_API *MsQuicCloseFn)(
|
|
_In_ _Pre_defensive_ const void* QuicApi
|
|
);
|
|
|
|
#ifdef _KERNEL_MODE
|
|
|
|
DECLSPEC_SELECTANY GUID MSQUIC_NPI_ID = {
|
|
0xC43138E3, 0xCD13, 0x4CB1, { 0x9C, 0xAE, 0xE0, 0x05, 0xC8, 0x55, 0x7A, 0xBA }
|
|
}; // C43138E3-CD13-4CB1-9CAE-E005C8557ABA
|
|
|
|
DECLSPEC_SELECTANY GUID MSQUIC_MODULE_ID = {
|
|
0x698F7C72, 0xC2E6, 0x49CD, { 0x8C, 0x39, 0x98, 0x85, 0x1D, 0x50, 0x19, 0x01 }
|
|
}; // 698F7C72-C2E6-49CD-8C39-98851D501901
|
|
|
|
typedef struct MSQUIC_NMR_DISPATCH {
|
|
uint16_t Version;
|
|
uint16_t Reserved;
|
|
MsQuicOpenVersionFn OpenVersion;
|
|
MsQuicCloseFn Close;
|
|
} MSQUIC_NMR_DISPATCH;
|
|
|
|
//
|
|
// Stores the internal NMR client state. It's meant to be opaque to the users.
|
|
//
|
|
typedef struct __MSQUIC_NMR_CLIENT {
|
|
NPI_CLIENT_CHARACTERISTICS NpiClientCharacteristics;
|
|
LONG BindingCount;
|
|
HANDLE NmrClientHandle;
|
|
NPI_MODULEID ModuleId;
|
|
KEVENT RegistrationCompleteEvent;
|
|
MSQUIC_NMR_DISPATCH* ProviderDispatch;
|
|
BOOLEAN Deleting;
|
|
} __MSQUIC_NMR_CLIENT;
|
|
|
|
#define QUIC_GET_DISPATCH(h) (((__MSQUIC_NMR_CLIENT*)(h))->ProviderDispatch)
|
|
|
|
static
|
|
NTSTATUS
|
|
__MsQuicClientAttachProvider(
|
|
_In_ HANDLE NmrBindingHandle,
|
|
_In_ void *ClientContext,
|
|
_In_ const NPI_REGISTRATION_INSTANCE *ProviderRegistrationInstance
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(ProviderRegistrationInstance);
|
|
|
|
NTSTATUS Status;
|
|
__MSQUIC_NMR_CLIENT* Client = (__MSQUIC_NMR_CLIENT*)ClientContext;
|
|
void* ProviderContext;
|
|
|
|
if (InterlockedIncrement(&Client->BindingCount) == 1) {
|
|
#pragma warning(suppress:6387) // _Param_(2) could be '0' - by design.
|
|
Status =
|
|
NmrClientAttachProvider(
|
|
NmrBindingHandle,
|
|
Client,
|
|
NULL,
|
|
&ProviderContext,
|
|
(const void**)&Client->ProviderDispatch);
|
|
if (NT_SUCCESS(Status)) {
|
|
KeSetEvent(&Client->RegistrationCompleteEvent, IO_NO_INCREMENT, FALSE);
|
|
} else {
|
|
InterlockedDecrement(&Client->BindingCount);
|
|
}
|
|
} else {
|
|
Status = STATUS_NOINTERFACE;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
__MsQuicClientDetachProvider(
|
|
_In_ void *ClientBindingContext
|
|
)
|
|
{
|
|
__MSQUIC_NMR_CLIENT* Client = (__MSQUIC_NMR_CLIENT*)ClientBindingContext;
|
|
if (InterlockedOr8((char*)&Client->Deleting, 1)) {
|
|
return STATUS_SUCCESS;
|
|
} else {
|
|
return STATUS_PENDING;
|
|
}
|
|
}
|
|
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
__forceinline
|
|
void
|
|
MsQuicNmrClientDeregister(
|
|
_Inout_ HANDLE* ClientHandle
|
|
)
|
|
{
|
|
__MSQUIC_NMR_CLIENT* Client = (__MSQUIC_NMR_CLIENT*)(*ClientHandle);
|
|
|
|
if (InterlockedOr8((char*)&Client->Deleting, 1)) {
|
|
//
|
|
// We are already in the middle of detaching the client.
|
|
// Complete it now.
|
|
//
|
|
NmrClientDetachProviderComplete(Client->NmrClientHandle);
|
|
}
|
|
|
|
if (Client->NmrClientHandle) {
|
|
if (NmrDeregisterClient(Client->NmrClientHandle) == STATUS_PENDING) {
|
|
//
|
|
// Wait for the deregistration to complete.
|
|
//
|
|
NmrWaitForClientDeregisterComplete(Client->NmrClientHandle);
|
|
}
|
|
Client->NmrClientHandle = NULL;
|
|
}
|
|
|
|
ExFreePoolWithTag(Client, 'cNQM');
|
|
*ClientHandle = NULL;
|
|
}
|
|
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
__forceinline
|
|
NTSTATUS
|
|
MsQuicNmrClientRegister(
|
|
_Out_ HANDLE* ClientHandle,
|
|
_In_ GUID* ClientModuleId,
|
|
_In_ ULONG TimeoutMs // zero = no wait, non-zero = some wait
|
|
)
|
|
{
|
|
NPI_REGISTRATION_INSTANCE *ClientRegistrationInstance;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
__MSQUIC_NMR_CLIENT* Client =
|
|
(__MSQUIC_NMR_CLIENT*)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(*Client), 'cNQM');
|
|
if (Client == NULL) {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto Exit;
|
|
}
|
|
|
|
KeInitializeEvent(&Client->RegistrationCompleteEvent, SynchronizationEvent, FALSE);
|
|
|
|
Client->ModuleId.Length = sizeof(Client->ModuleId);
|
|
Client->ModuleId.Type = MIT_GUID;
|
|
Client->ModuleId.Guid = *ClientModuleId;
|
|
|
|
Client->NpiClientCharacteristics.Length = sizeof(Client->NpiClientCharacteristics);
|
|
Client->NpiClientCharacteristics.ClientAttachProvider = __MsQuicClientAttachProvider;
|
|
Client->NpiClientCharacteristics.ClientDetachProvider = __MsQuicClientDetachProvider;
|
|
|
|
ClientRegistrationInstance = &Client->NpiClientCharacteristics.ClientRegistrationInstance;
|
|
ClientRegistrationInstance->Size = sizeof(*ClientRegistrationInstance);
|
|
ClientRegistrationInstance->Version = 0;
|
|
ClientRegistrationInstance->NpiId = &MSQUIC_NPI_ID;
|
|
ClientRegistrationInstance->ModuleId = &Client->ModuleId;
|
|
|
|
Status =
|
|
NmrRegisterClient(
|
|
&Client->NpiClientCharacteristics, Client, &Client->NmrClientHandle);
|
|
if (!NT_SUCCESS(Status)) {
|
|
goto Exit;
|
|
}
|
|
|
|
LARGE_INTEGER Timeout;
|
|
Timeout.QuadPart = UInt32x32To64(TimeoutMs, 10000);
|
|
Timeout.QuadPart = -Timeout.QuadPart;
|
|
|
|
Status =
|
|
KeWaitForSingleObject(
|
|
&Client->RegistrationCompleteEvent,
|
|
Executive, KernelMode, FALSE,
|
|
&Timeout);
|
|
if (Status != STATUS_SUCCESS) {
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
goto Exit;
|
|
}
|
|
|
|
*ClientHandle = Client;
|
|
|
|
Exit:
|
|
if (!NT_SUCCESS(Status) && Client != NULL) {
|
|
MsQuicNmrClientDeregister((HANDLE*)&Client);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Version specific helpers that wrap MsQuicOpenVersion.
|
|
//
|
|
|
|
#if defined(__cplusplus)
|
|
|
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
|
_Check_return_
|
|
#if (__cplusplus >= 201703L || _MSVC_LANG >= 201703L)
|
|
[[nodiscard]]
|
|
#endif
|
|
#ifdef WIN32
|
|
__forceinline
|
|
#else
|
|
__attribute__((always_inline)) QUIC_INLINE
|
|
#endif
|
|
QUIC_STATUS
|
|
MsQuicOpen2(
|
|
_Out_ _Pre_defensive_ const QUIC_API_TABLE** QuicApi
|
|
)
|
|
{
|
|
return MsQuicOpenVersion(QUIC_API_VERSION_2, (const void**)QuicApi);
|
|
}
|
|
|
|
#else
|
|
|
|
#define MsQuicOpen2(QuicApi) MsQuicOpenVersion(2, (const void**)QuicApi)
|
|
|
|
#endif // defined(__cplusplus)
|
|
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif
|
|
|
|
#endif // _MSQUIC_
|