MsQuic

This topic describes how to use MsQuic with the Microsoft Game Development Kit (GDK). MsQuic is a Microsoft implementation of the IETF QUIC protocol. It is cross-platform, written in C and designed to be a general purpose QUIC library.

QUIC was originally designed to replace scenarios using "TLS over TCP" such as HTTP, but has since been expanded into a general purpose UDP data transport layer suitable for multiplexing real time unreliable datagram messages and reliable TCP-like streams over a single connection. This makes it particularly appealing as a client/server transport layer and basis for real time game traffic data flows.

MsQuic is tailored for GDK titles, and is also available for a multitude of platforms including Windows server, Linux desktop and server, iOS, Android, and MacOS.

The MsQuic API documentation covers a number of important MsQuic concepts and shows how to code against the MsQuic API surface.

QUIC features

  • All packets are encrypted and handshake is authenticated with TLS 1.3.
  • Parallel streams of reliable and unreliable application data.
  • Exchange application data in the first round trip (0-RTT).
  • Improved congestion control and loss recovery.
  • Survives a change in the clients IP address or port.
  • Stateless load balancing.
  • Easily extendable for new features and extensions.

MsQuic implementation

In addition to being tailored for use with GDK titles, MsQuic has several features that differentiates it from other QUIC implementations:

  • Optimized for client and server.
  • Optimized for maximal throughput and minimal latency.
  • Asynchronous IO.
  • Receive side scaling (RSS) support.
  • UDP send and receive coalescing support.

MsQuic implements the following QUIC RFCs:

MsQuic implements the following QUIC draft extensions:

Acquiring MsQuic

MsQuic is hosted in an open source github repository. You should aquire MsQuic via one of its official releases located here. Xbox Series X|S console support was added in prerelease/1.9, although we recommend that you take the latest official release version when possible for Microsoft Game Development Kit (GDK) titles.

Pre-built MsQuic binaries for a given release are available under the Assets section for a particular release. All build flavors for a particular version of MsQuic are fully compatible with one another. While MsQuic also tries to maintain backwards compatibility for their releases, refer to the MsQuic documentation and release notes for any compatibility expectations among different versions.

Microsoft Game Development Kit (GDK).PC

The msquic_windows_x64_Release_openssl pre-built binary is recommended for Microsoft Game Development Kit (GDK).PC titles.

Microsoft Game Development Kit (GDK) titles on PC run as native x64 Win32 applications. You should use the version of MsQuic built for the x64 platform. On PC, we recommend using the version of MsQuic built with OpenSSL as that supports all OS versions that the Microsoft Game Development Kit (GDK) supports as opposed to Schannel that is only supported on the Windows 11 OS and later.

Microsoft Game Development Kit (GDK).Console

The msquic_gamecore_console_x64_Release_schannel pre-built binary is recommended for Microsoft Game Development Kit (GDK).PC titles.

MsQuic provides a special build flavor for Microsoft Game Development Kit (GDK) titles on Xbox consoles. This flavor restricts MsQuic to the APIs under the WINAPI_PARTITION_GAMES and causes MsQuic to link against the XGamePlatform.lib. In order to consume this build flavor, you must have the XGDK from the October 2021 release or later installed. MsQuic uses Schannel when building for Microsoft Game Development Kit (GDK) console.

Client and Server Authentication

MsQuic automatically utilizes the same authentication and verification paths as used for HTTPS web requests in order to authenticate your server. Client authentication should follow the best practices outlined in best practices for secure client/server communication (NDA topic)Authorization required.

In MsQuic, on both the client and server you should use the ConfigurationLoadCredential API with an appropriate QUIC_CREDENTIAL_CONFIG in order to configure your certificates. All cipher suites included by default in MsQuic are considered secure, but it is important to properly setup how MsQuic validates the certificates on both the client and server to ensure a secure and authenticated communication channel is established.

On the server, in order to use XSTS token client authentication, you should specify the QUIC_CREDENTIAL_FLAG_REQUIRE_CLIENT_AUTHENTICATION, QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED, and QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION flags. When you specify the QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION flag, you must validate the client certificate yourself within the QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED event callback as described in the best practices for secure client/server communication (NDA topic)Authorization required section.

Furthermore on the server, you should provide a properly rooted certificate in order to allow the client to authenticate your server just as you would in an HTTPS web server.

On the client, you should never specify the QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION flag, as the default MsQuic behavior for server authentication is the easiest and most secure way to validate identity. Instead, for XSTS token client authentication you should specify the QUIC_CREDENTIAL_FLAG_CLIENT flag along with the certificate generated by your server as described in the best practices for secure client/server communication (NDA topic)Authorization required section. We recommend to supply the client certificate by specifying the QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT mode and using APIs such as CertCreateContext to generate the context directly from your web request response data.

Network initialization

MsQuic doesn't automatically handle network initialization for Microsoft Game Development Kit (GDK) titles. Wait for the network to become initialized after your title is launched and after each resume before initializing MsQuic with MsQuicOpenVersion or MsQuicOpen.

Suspend and resume

You should register for suspend and resume events via RegisterAppStateChangeNotification. On suspend, you should close any open streams and subsequently close MsQuic. Then, on resume, you should wait for network initialization and then re-open MsQuic.

In order to close all MsQuic streams quickly within the suspend timeout, you should first for each open stream call StreamShutdown with the QUIC_STREAM_SHUTDOWN_FLAG_ABORT and QUIC_STREAM_SHUTDOWN_FLAG_IMMEDIATE flags. This will immediately trigger a QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE event at which point it is safe to call StreamClose to close the stream. Once all streams have been closed for a given connection, you should call ConnectionShutdown with the QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT flag followed by ConnectionClose. Once all connections have been closed, you should call RegistrationClose and ConfigurationClose for any outstanding registrations and configurations followed by MsQuicClose.

Preferred port

Microsoft Game Development Kit (GDK) titles are encouraged to use the preferred local UDP multiplayer port for your main game traffic. You can set this port in MsQuic with via the SetParam function with the QUIC_PARAM_CONN_LOCAL_ADDRESS setting on a connection object handle before calling ConnectionStart.

When setting the QUIC_PARAM_CONN_LOCAL_ADDRESS, we recommend specifying the AF_UNSPEC family to allow for dual-stack IPv4 and IPv6 sockets. Here is an example of how you might set the preferred port given MsQuicCallTable was returned from MsQuicOpen and MsQuicConnectionHandle was returned from ConnectionOpen.

uint16_t preferredPort;
if (SUCCEEDED(XNetworkingQueryPreferredLocalUdpMultiplayerPort(&preferredPort)))
{
    QUIC_ADDR localAddress = {};
    localAddress.si_family = AF_UNSPEC;
    localAddress.Ipv4.sin_port = htons(preferredPort);

    QUIC_STATUS status = MsQuicCallTable->SetParam(
        MsQuicConnectionHandle,
        QUIC_PARAM_LEVEL_CONNECTION,
        QUIC_PARAM_CONN_LOCAL_ADDRESS,
        sizeof(localAddress),
        &localAddress);
}

Memory considerations

MsQuic's performant implementation allows for high bandwidths to be transfered to and from your Microsoft Game Development Kit (GDK) title. As an extension to WinSock Memory Considerations, when using MsQuic you should follow these best practices in order to minimize the memory consumption by the kernel:

Microsoft Game Development Kit (GDK) titles should keep any execution time in the callback to a minimum. MsQuic does not use separate threads for the protocol execution and upcalls to the app. Therefore, any significant delays in the callback will delay the protocol and increase the memory consumption required by the kernel. Any significant time or work needed to be completed by the title must happen on its own thread.

Microsoft Game Development Kit (GDK) titles should manage their send buffers efficiently in order to minimize kernel memory usage. See Send buffering in MsQuic for more details on how MsQuic allows your title to manage this.

We highly recommend using asynchronous receives with MsQuic to ensure that any received data is transfered to user mode buffers efficiently. Receiving in MsQuic has additional details about how to handle asynchronous receives. Furthermore, we recommend not using the partial data acceptance feature in MsQuic GDK clients to minimize the amount of kernel memory consumed.

See also

MsQuic

MsQuic API documentation

MsQuic releases

Building MsQuic documentation