377 lines
12 KiB
C
377 lines
12 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) Microsoft Corporation.
|
||
|
Licensed under the MIT License.
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This file contains the platform specific definitions for MsQuic structures
|
||
|
and error codes.
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Windows User mode
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#ifndef _MSQUIC_WINUSER_
|
||
|
#define _MSQUIC_WINUSER_
|
||
|
|
||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||
|
#define WIN32_LEAN_AND_MEAN
|
||
|
#endif
|
||
|
|
||
|
#pragma warning(push)
|
||
|
#pragma warning(disable:6553) // Annotation does not apply to value type.
|
||
|
#include <windows.h>
|
||
|
#pragma warning(pop)
|
||
|
#include <winsock2.h>
|
||
|
#include <ws2ipdef.h>
|
||
|
#pragma warning(push)
|
||
|
#pragma warning(disable:6385) // Invalid data: accessing [buffer-name], the readable size is size1 bytes but size2 bytes may be read
|
||
|
#pragma warning(disable:6101) // Returning uninitialized memory
|
||
|
#include <ws2tcpip.h>
|
||
|
#include <mstcpip.h>
|
||
|
#pragma warning(pop)
|
||
|
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#define SUCCESS_HRESULT_FROM_WIN32(x) \
|
||
|
((HRESULT)(((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16)))
|
||
|
|
||
|
#ifndef ERROR_QUIC_HANDSHAKE_FAILURE
|
||
|
#define ERROR_QUIC_HANDSHAKE_FAILURE _HRESULT_TYPEDEF_(0x80410000L)
|
||
|
#endif
|
||
|
|
||
|
#ifndef ERROR_QUIC_VER_NEG_FAILURE
|
||
|
#define ERROR_QUIC_VER_NEG_FAILURE _HRESULT_TYPEDEF_(0x80410001L)
|
||
|
#endif
|
||
|
|
||
|
#ifndef ERROR_QUIC_USER_CANCELED
|
||
|
#define ERROR_QUIC_USER_CANCELED _HRESULT_TYPEDEF_(0x80410002L)
|
||
|
#endif
|
||
|
|
||
|
#ifndef ERROR_QUIC_INTERNAL_ERROR
|
||
|
#define ERROR_QUIC_INTERNAL_ERROR _HRESULT_TYPEDEF_(0x80410003L)
|
||
|
#endif
|
||
|
|
||
|
#ifndef ERROR_QUIC_PROTOCOL_VIOLATION
|
||
|
#define ERROR_QUIC_PROTOCOL_VIOLATION _HRESULT_TYPEDEF_(0x80410004L)
|
||
|
#endif
|
||
|
|
||
|
#ifndef ERROR_QUIC_CONNECTION_IDLE
|
||
|
#define ERROR_QUIC_CONNECTION_IDLE _HRESULT_TYPEDEF_(0x80410005L)
|
||
|
#endif
|
||
|
|
||
|
#ifndef ERROR_QUIC_CONNECTION_TIMEOUT
|
||
|
#define ERROR_QUIC_CONNECTION_TIMEOUT _HRESULT_TYPEDEF_(0x80410006L)
|
||
|
#endif
|
||
|
|
||
|
#ifndef ERROR_QUIC_ALPN_NEG_FAILURE
|
||
|
#define ERROR_QUIC_ALPN_NEG_FAILURE _HRESULT_TYPEDEF_(0x80410007L)
|
||
|
#endif
|
||
|
|
||
|
#ifndef ERROR_QUIC_STREAM_LIMIT_REACHED
|
||
|
#define ERROR_QUIC_STREAM_LIMIT_REACHED _HRESULT_TYPEDEF_(0x80410008L)
|
||
|
#endif
|
||
|
|
||
|
#ifndef ERROR_QUIC_ALPN_IN_USE
|
||
|
#define ERROR_QUIC_ALPN_IN_USE _HRESULT_TYPEDEF_(0x80410009L)
|
||
|
#endif
|
||
|
|
||
|
#ifndef QUIC_TLS_ALERT_HRESULT_PREFIX
|
||
|
#define QUIC_TLS_ALERT_HRESULT_PREFIX _HRESULT_TYPEDEF_(0x80410100L)
|
||
|
#endif
|
||
|
|
||
|
#define QUIC_API __cdecl
|
||
|
#define QUIC_MAIN_EXPORT __cdecl
|
||
|
#define QUIC_STATUS HRESULT
|
||
|
#define QUIC_FAILED(X) FAILED(X)
|
||
|
#define QUIC_SUCCEEDED(X) SUCCEEDED(X)
|
||
|
|
||
|
#define QUIC_STATUS_SUCCESS S_OK // 0x0
|
||
|
#define QUIC_STATUS_PENDING SUCCESS_HRESULT_FROM_WIN32(ERROR_IO_PENDING) // 0x703e5
|
||
|
#define QUIC_STATUS_CONTINUE SUCCESS_HRESULT_FROM_WIN32(ERROR_CONTINUE) // 0x704de
|
||
|
#define QUIC_STATUS_OUT_OF_MEMORY E_OUTOFMEMORY // 0x8007000e
|
||
|
#define QUIC_STATUS_INVALID_PARAMETER E_INVALIDARG // 0x80070057
|
||
|
#define QUIC_STATUS_INVALID_STATE E_NOT_VALID_STATE // 0x8007139f
|
||
|
#define QUIC_STATUS_NOT_SUPPORTED E_NOINTERFACE // 0x80004002
|
||
|
#define QUIC_STATUS_NOT_FOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND) // 0x80070490
|
||
|
#define QUIC_STATUS_BUFFER_TOO_SMALL E_NOT_SUFFICIENT_BUFFER // 0x8007007a
|
||
|
#define QUIC_STATUS_HANDSHAKE_FAILURE ERROR_QUIC_HANDSHAKE_FAILURE // 0x80410000
|
||
|
#define QUIC_STATUS_ABORTED E_ABORT // 0x80004004
|
||
|
#define QUIC_STATUS_ADDRESS_IN_USE HRESULT_FROM_WIN32(WSAEADDRINUSE) // 0x80072740
|
||
|
#define QUIC_STATUS_INVALID_ADDRESS HRESULT_FROM_WIN32(WSAEADDRNOTAVAIL) // 0x80072741
|
||
|
#define QUIC_STATUS_CONNECTION_TIMEOUT ERROR_QUIC_CONNECTION_TIMEOUT // 0x80410006
|
||
|
#define QUIC_STATUS_CONNECTION_IDLE ERROR_QUIC_CONNECTION_IDLE // 0x80410005
|
||
|
#define QUIC_STATUS_UNREACHABLE HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE) // 0x800704d0
|
||
|
#define QUIC_STATUS_INTERNAL_ERROR ERROR_QUIC_INTERNAL_ERROR // 0x80410003
|
||
|
#define QUIC_STATUS_CONNECTION_REFUSED HRESULT_FROM_WIN32(ERROR_CONNECTION_REFUSED) // 0x800704c9
|
||
|
#define QUIC_STATUS_PROTOCOL_ERROR ERROR_QUIC_PROTOCOL_VIOLATION // 0x80410004
|
||
|
#define QUIC_STATUS_VER_NEG_ERROR ERROR_QUIC_VER_NEG_FAILURE // 0x80410001
|
||
|
#define QUIC_STATUS_TLS_ERROR HRESULT_FROM_WIN32(WSA_SECURE_HOST_NOT_FOUND) // 0x80072b18
|
||
|
#define QUIC_STATUS_USER_CANCELED ERROR_QUIC_USER_CANCELED // 0x80410002
|
||
|
#define QUIC_STATUS_ALPN_NEG_FAILURE ERROR_QUIC_ALPN_NEG_FAILURE // 0x80410007
|
||
|
#define QUIC_STATUS_STREAM_LIMIT_REACHED ERROR_QUIC_STREAM_LIMIT_REACHED // 0x80410008
|
||
|
#define QUIC_STATUS_ALPN_IN_USE ERROR_QUIC_ALPN_IN_USE // 0x80410009
|
||
|
|
||
|
#define QUIC_STATUS_TLS_ALERT(Alert) (QUIC_TLS_ALERT_HRESULT_PREFIX | (0xff & Alert))
|
||
|
|
||
|
#define QUIC_STATUS_CLOSE_NOTIFY QUIC_STATUS_TLS_ALERT(0) // Close notify
|
||
|
#define QUIC_STATUS_BAD_CERTIFICATE QUIC_STATUS_TLS_ALERT(42) // Bad Certificate
|
||
|
#define QUIC_STATUS_UNSUPPORTED_CERTIFICATE QUIC_STATUS_TLS_ALERT(43) // Unsupported Certficiate
|
||
|
#define QUIC_STATUS_REVOKED_CERTIFICATE QUIC_STATUS_TLS_ALERT(44) // Revoked Certificate
|
||
|
#define QUIC_STATUS_EXPIRED_CERTIFICATE QUIC_STATUS_TLS_ALERT(45) // Expired Certificate
|
||
|
#define QUIC_STATUS_UNKNOWN_CERTIFICATE QUIC_STATUS_TLS_ALERT(46) // Unknown Certificate
|
||
|
#define QUIC_STATUS_REQUIRED_CERTIFICATE QUIC_STATUS_TLS_ALERT(116) // Required Certificate
|
||
|
|
||
|
#define QUIC_STATUS_CERT_EXPIRED CERT_E_EXPIRED
|
||
|
#define QUIC_STATUS_CERT_UNTRUSTED_ROOT CERT_E_UNTRUSTEDROOT
|
||
|
#define QUIC_STATUS_CERT_NO_CERT SEC_E_NO_CREDENTIALS
|
||
|
|
||
|
//
|
||
|
// Swaps byte orders between host and network endianness.
|
||
|
//
|
||
|
#ifdef htons
|
||
|
#define QuicNetByteSwapShort(x) htons(x)
|
||
|
#else
|
||
|
#define QuicNetByteSwapShort(x) ((uint16_t)((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8)))
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// IP Address Abstraction Helpers
|
||
|
//
|
||
|
|
||
|
typedef ADDRESS_FAMILY QUIC_ADDRESS_FAMILY;
|
||
|
typedef SOCKADDR_INET QUIC_ADDR;
|
||
|
|
||
|
#define QUIC_ADDR_V4_PORT_OFFSET FIELD_OFFSET(SOCKADDR_IN, sin_port)
|
||
|
#define QUIC_ADDR_V4_IP_OFFSET FIELD_OFFSET(SOCKADDR_IN, sin_addr)
|
||
|
|
||
|
#define QUIC_ADDR_V6_PORT_OFFSET FIELD_OFFSET(SOCKADDR_IN6, sin6_port)
|
||
|
#define QUIC_ADDR_V6_IP_OFFSET FIELD_OFFSET(SOCKADDR_IN6, sin6_addr)
|
||
|
|
||
|
#define QUIC_ADDRESS_FAMILY_UNSPEC AF_UNSPEC
|
||
|
#define QUIC_ADDRESS_FAMILY_INET AF_INET
|
||
|
#define QUIC_ADDRESS_FAMILY_INET6 AF_INET6
|
||
|
|
||
|
inline
|
||
|
BOOLEAN
|
||
|
QuicAddrIsValid(
|
||
|
_In_ const QUIC_ADDR* const Addr
|
||
|
)
|
||
|
{
|
||
|
return
|
||
|
Addr->si_family == QUIC_ADDRESS_FAMILY_UNSPEC ||
|
||
|
Addr->si_family == QUIC_ADDRESS_FAMILY_INET ||
|
||
|
Addr->si_family == QUIC_ADDRESS_FAMILY_INET6;
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
BOOLEAN
|
||
|
QuicAddrCompareIp(
|
||
|
_In_ const QUIC_ADDR* const Addr1,
|
||
|
_In_ const QUIC_ADDR* const Addr2
|
||
|
)
|
||
|
{
|
||
|
if (Addr1->si_family == QUIC_ADDRESS_FAMILY_INET) {
|
||
|
return memcmp(&Addr1->Ipv4.sin_addr, &Addr2->Ipv4.sin_addr, sizeof(IN_ADDR)) == 0;
|
||
|
} else {
|
||
|
return memcmp(&Addr1->Ipv6.sin6_addr, &Addr2->Ipv6.sin6_addr, sizeof(IN6_ADDR)) == 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
BOOLEAN
|
||
|
QuicAddrCompare(
|
||
|
_In_ const QUIC_ADDR* const Addr1,
|
||
|
_In_ const QUIC_ADDR* const Addr2
|
||
|
)
|
||
|
{
|
||
|
if (Addr1->si_family != Addr2->si_family ||
|
||
|
Addr1->Ipv4.sin_port != Addr2->Ipv4.sin_port) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
return QuicAddrCompareIp(Addr1, Addr2);
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
BOOLEAN
|
||
|
QuicAddrIsWildCard(
|
||
|
_In_ const QUIC_ADDR* const Addr
|
||
|
)
|
||
|
{
|
||
|
if (Addr->si_family == QUIC_ADDRESS_FAMILY_UNSPEC) {
|
||
|
return TRUE;
|
||
|
} else if (Addr->si_family == QUIC_ADDRESS_FAMILY_INET) {
|
||
|
const IN_ADDR ZeroAddr = {0};
|
||
|
return memcmp(&Addr->Ipv4.sin_addr, &ZeroAddr, sizeof(IN_ADDR)) == 0;
|
||
|
} else {
|
||
|
const IN6_ADDR ZeroAddr = {0};
|
||
|
return memcmp(&Addr->Ipv6.sin6_addr, &ZeroAddr, sizeof(IN6_ADDR)) == 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
QUIC_ADDRESS_FAMILY
|
||
|
QuicAddrGetFamily(
|
||
|
_In_ const QUIC_ADDR* const Addr
|
||
|
)
|
||
|
{
|
||
|
return (QUIC_ADDRESS_FAMILY)Addr->si_family;
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
void
|
||
|
QuicAddrSetFamily(
|
||
|
_Inout_ QUIC_ADDR* Addr,
|
||
|
_In_ QUIC_ADDRESS_FAMILY Family
|
||
|
)
|
||
|
{
|
||
|
Addr->si_family = (ADDRESS_FAMILY)Family;
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
uint16_t // Returns in host byte order.
|
||
|
QuicAddrGetPort(
|
||
|
_In_ const QUIC_ADDR* const Addr
|
||
|
)
|
||
|
{
|
||
|
return QuicNetByteSwapShort(Addr->Ipv4.sin_port);
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
void
|
||
|
QuicAddrSetPort(
|
||
|
_Out_ QUIC_ADDR* Addr,
|
||
|
_In_ uint16_t Port // Host byte order
|
||
|
)
|
||
|
{
|
||
|
Addr->Ipv4.sin_port = QuicNetByteSwapShort(Port);
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
void
|
||
|
QuicAddrSetToLoopback(
|
||
|
_Inout_ QUIC_ADDR* Addr
|
||
|
)
|
||
|
{
|
||
|
if (Addr->si_family == QUIC_ADDRESS_FAMILY_INET) {
|
||
|
Addr->Ipv4.sin_addr.S_un.S_un_b.s_b1 = 127;
|
||
|
Addr->Ipv4.sin_addr.S_un.S_un_b.s_b4 = 1;
|
||
|
} else {
|
||
|
Addr->Ipv6.sin6_addr.u.Byte[15] = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Test only API to increment the IP address value.
|
||
|
//
|
||
|
inline
|
||
|
void
|
||
|
QuicAddrIncrement(
|
||
|
_Inout_ QUIC_ADDR* Addr
|
||
|
)
|
||
|
{
|
||
|
if (Addr->si_family == QUIC_ADDRESS_FAMILY_INET) {
|
||
|
Addr->Ipv4.sin_addr.S_un.S_un_b.s_b4++;
|
||
|
} else {
|
||
|
Addr->Ipv6.sin6_addr.u.Byte[15]++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
uint32_t
|
||
|
QuicAddrHash(
|
||
|
_In_ const QUIC_ADDR* Addr
|
||
|
)
|
||
|
{
|
||
|
uint32_t Hash = 5387; // A random prime number.
|
||
|
#define UPDATE_HASH(byte) Hash = ((Hash << 5) - Hash) + (byte)
|
||
|
if (Addr->si_family == QUIC_ADDRESS_FAMILY_INET) {
|
||
|
UPDATE_HASH(Addr->Ipv4.sin_port & 0xFF);
|
||
|
UPDATE_HASH(Addr->Ipv4.sin_port >> 8);
|
||
|
for (uint8_t i = 0; i < sizeof(Addr->Ipv4.sin_addr); ++i) {
|
||
|
UPDATE_HASH(((uint8_t*)&Addr->Ipv4.sin_addr)[i]);
|
||
|
}
|
||
|
} else {
|
||
|
UPDATE_HASH(Addr->Ipv6.sin6_port & 0xFF);
|
||
|
UPDATE_HASH(Addr->Ipv6.sin6_port >> 8);
|
||
|
for (uint8_t i = 0; i < sizeof(Addr->Ipv6.sin6_addr); ++i) {
|
||
|
UPDATE_HASH(((uint8_t*)&Addr->Ipv6.sin6_addr)[i]);
|
||
|
}
|
||
|
}
|
||
|
return Hash;
|
||
|
}
|
||
|
|
||
|
#define QUIC_LOCALHOST_FOR_AF(Af) "localhost"
|
||
|
|
||
|
//
|
||
|
// Rtl String API's are not allowed in gamecore
|
||
|
//
|
||
|
#if WINAPI_FAMILY != WINAPI_FAMILY_GAMES
|
||
|
|
||
|
inline
|
||
|
_Success_(return != FALSE)
|
||
|
BOOLEAN
|
||
|
QuicAddrFromString(
|
||
|
_In_z_ const char* AddrStr,
|
||
|
_In_ uint16_t Port, // Host byte order
|
||
|
_Out_ QUIC_ADDR* Addr
|
||
|
)
|
||
|
{
|
||
|
if (RtlIpv4StringToAddressExA(AddrStr, FALSE, &Addr->Ipv4.sin_addr, &Addr->Ipv4.sin_port) == NO_ERROR) {
|
||
|
Addr->si_family = QUIC_ADDRESS_FAMILY_INET;
|
||
|
} else if (RtlIpv6StringToAddressExA(AddrStr, &Addr->Ipv6.sin6_addr, &Addr->Ipv6.sin6_scope_id, &Addr->Ipv6.sin6_port) == NO_ERROR) {
|
||
|
Addr->si_family = QUIC_ADDRESS_FAMILY_INET6;
|
||
|
} else {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (Addr->Ipv4.sin_port == 0) {
|
||
|
Addr->Ipv4.sin_port = QuicNetByteSwapShort(Port);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Represents an IP address and (optionally) port number as a string.
|
||
|
//
|
||
|
typedef struct QUIC_ADDR_STR {
|
||
|
char Address[64];
|
||
|
} QUIC_ADDR_STR;
|
||
|
|
||
|
inline
|
||
|
_Success_(return != FALSE)
|
||
|
BOOLEAN
|
||
|
QuicAddrToString(
|
||
|
_In_ const QUIC_ADDR* Addr,
|
||
|
_Out_ QUIC_ADDR_STR* AddrStr
|
||
|
)
|
||
|
{
|
||
|
LONG Status;
|
||
|
ULONG AddrStrLen = ARRAYSIZE(AddrStr->Address);
|
||
|
if (Addr->si_family == QUIC_ADDRESS_FAMILY_INET) {
|
||
|
Status =
|
||
|
RtlIpv4AddressToStringExA(
|
||
|
&Addr->Ipv4.sin_addr,
|
||
|
Addr->Ipv4.sin_port,
|
||
|
AddrStr->Address,
|
||
|
&AddrStrLen);
|
||
|
} else {
|
||
|
Status =
|
||
|
RtlIpv6AddressToStringExA(
|
||
|
&Addr->Ipv6.sin6_addr,
|
||
|
0,
|
||
|
Addr->Ipv6.sin6_port,
|
||
|
AddrStr->Address,
|
||
|
&AddrStrLen);
|
||
|
}
|
||
|
return Status == NO_ERROR;
|
||
|
}
|
||
|
|
||
|
#endif // WINAPI_FAMILY != WINAPI_FAMILY_GAMES
|
||
|
|
||
|
#endif // _MSQUIC_WINUSER_
|