/*++ 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 #pragma warning(pop) #include #include #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 #include #pragma warning(pop) #include #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_