MsQuic

repository·main·Indexed 26 days ago

https://github.com/microsoft/msquic

A high-performance, cross-platform implementation of the IETF QUIC protocol written in C. MsQuic supports asynchronous IO, TLS 1.3 encryption, 0-RTT data exchange, and kernel stack bypass via XDP. It provides official interop layers for Rust, C#, and C++, and includes performance testing tools via SecNetPerf, as well as debugging extensions for WinDbg and Windows Performance Analyzer (WPA).

Tokens
63.4K
Snippets
100
Records
284
Agent score
86%

What's inside msquic

  1. Overview of MsQuic

    main

    MsQuic is a cross-platform, general-purpose implementation of the IETF QUIC protocol written in C. It is designed for high performance, offering optimized client and server implementations with a focus on maximal throughput and minimal latency.

    Key features include:

    • Asynchronous IO: Non-blocking operations for efficient resource usage.
    • Performance Optimizations: Support for Receive Side Scaling (RSS), UDP send/receive coalescing, and kernel stack bypass via XDP.
    • Protocol Benefits: TLS 1.3 encryption, parallel streams (reliable and unreliable), 0-RTT data exchange, improved congestion control, and connection migration (surviving IP/port changes).
  2. Understand MsQuic language support and implementation

    main

    MsQuic is implemented in pure C to ensure compatibility with the Windows Kernel mode. However, the MsQuic API is projected/exposed for use in several other languages, including:

    • C++
    • C#
    • Rust
  3. Available TLS Implementations

    main

    MsQuic supports several implementations of the TLS abstraction layer depending on the platform:

    • Schannel: Officially supported for Windows user mode and Windows kernel mode. Requires recent Windows versions (Windows Server 2022 or Insider Preview) for TLS 1.3 support. Note: 0-RTT is not supported, and resumption is only partially supported.
    • OpenSSL: The primary TLS library for Linux. While it works on Windows, Schannel is preferred if available.

    Note on OpenSSL: Because standard OpenSSL lacks official QUIC API support, MsQuic currently uses a quictls fork of OpenSSL as a temporary stopgap to expose necessary QUIC functionality.

  4. Understand MsQuic Receive Buffer Architecture

    main

    The MsQuic receive buffer manages incoming stream data by tracking byte offsets, maintaining a reading head, and managing memory allocations. It handles re-ordering bytes based on their stream offsets and manages the lifetime of memory chunks shared with the application.

    Key components include:

    • WrittenRanges: A QUIC_RANGE tracking all byte offsets written to the buffer since creation.
    • Chunks: QUIC_RECV_CHUNK structures containing the actual allocated memory.
    • Reading Head: Points to the first byte not yet drained, tracked via BaseOffset (the stream index) and ReadStart (the offset within the first active chunk).

    Chunks are categorized as:

    • Active: Available for new 'read' or 'write' operations.
    • Retired: Waiting for deletion; currently referenced by the application but containing no new data or data already drained/copied.
  5. Manage Threading and Concurrency in MsQuic

    main

    By default, MsQuic manages its own threading to optimize performance and alignment with the networking stack (e.g., RSS and NUMA nodes).

    Threading Characteristics:

    • Worker Threads: MsQuic typically creates a dedicated worker thread for each processor. These threads handle both the datapath (UDP) and QUIC layers by default.
    • Connection Isolation: Each connection and its derived streams are managed and executed by a single thread at a time. MsQuic never makes upcalls for a single connection or any of its streams in parallel.
    • Listener Scaling: For Listeners, application callbacks are called in parallel for new connections, allowing server applications to scale across multiple processors.
    • Deadlock Prevention: MsQuic is designed to avoid deadlocks when calling MsQuic APIs from within a callback. Calls made from a callback thread occur inline and take precedence over queued calls. By default, MsQuic will never invoke a recursive callback unless the application explicitly opts in using the QUIC_STREAM_SHUTDOWN_FLAG_INLINE flag during a StreamShutdown call.
  6. Understand the MsQuic Object Model

    main

    MsQuic functionality is organized into a hierarchy of objects. Understanding this hierarchy is essential for managing the lifecycle of a QUIC application:

    1. Api: The top-level handle and function table for all calls.
    2. Registration: Manages the execution context (worker threads) for all child objects. An app should ideally open only one.
    3. Configuration: Abstracts security (TLS) and common QUIC settings for a connection.
    4. Listener (Server-only): Provides the interface to accept incoming connections. Once a connection is accepted, it is independent of the listener.
    5. Connection: Represents the QUIC connection state between client and server.
    6. Stream: The layer where application data is exchanged (unidirectional or bidirectional).
  7. Understand the MsQuic Architecture Layers

    main

    MsQuic is organized into two primary high-level layers:

    1. QUIC Layer: Contains platform-independent logic implementing the QUIC protocol.
    2. Platform Abstraction Layer (PAL): Provides abstractions for platform-specific requirements, including TLS, UDP, and OS primitives (threads, locks, etc.).
  8. Understand CIBIR for multi-process port sharing

    main

    CIBIR (Connection ID Based Ingress Routing) allows two or more separate server processes to share a single UDP port on the same machine. When used in conjunction with XDP, packet demultiplexing is performed based on address, port number, and the QUIC connection ID, rather than just address and port.

    Key Requirements and Behaviors:

    • Applications must provide a well-known local port for server sockets when using both CIBIR and XDP.
    • Important: MsQuic will NOT reserve an OS port for server sockets if both CIBIR and XDP are enabled and available.
    • The application is responsible for book-keeping shared ports and ensuring robust protection for them.
  9. Understand MsQuic work item states

    main

    MsQuic manages tasks and issues through several distinct states. Understanding these states helps in identifying whether an issue requires triage, is part of the planned backlog, is currently being worked on, or is available for community contribution.

    StateDescription
    Triage NeededNewly created items that have not yet been evaluated for priority or type.
    Non-prioritized WorkInteresting items labeled help wanted that are not in the main DPT project.
    BacklogPrioritized and sized items in the DPT project waiting for an iteration.
    Current WorkItems currently being addressed (Planned or In Progress) in a specific iteration.
    ClosedCompleted items or items that have been cut (e.g., Cut: NotRepro).
  10. Create a new minor release

    main

    To initiate a new minor release, you must fork the main branch into a dedicated release branch and update the versioning on main to prepare for the next cycle.

    1. Update the release table in Release.md via a PR against main.
    2. Create a release branch named release/X.Y from main.
    3. Increment the minor version on the main branch using the update-version.ps1 script.

    You can automate the branch creation and version bumping using the create-release.ps1 script.

  11. Control data flushing with QUIC_SEND_FLAG_DELAY_SEND

    main

    Use the QUIC_SEND_FLAG_DELAY_SEND flag to hint to MsQuic that it should wait for more data before flushing the connection-wide send queue.

    Warning: Data queued with this flag is not guaranteed to be sent until a subsequent StreamSend call is performed on any stream with the QUIC_SEND_FLAG_DELAY_SEND flag unset.

    To force a flush of all delayed data, call StreamSend on any stream with a null/empty buffer and ensure QUIC_SEND_FLAG_DELAY_SEND is not set.

  12. Publish MsQuic for Alpine

    main

    To publish MsQuic for Alpine Linux, follow these steps:

    1. Generate APKBUILD: Checkout the release tag (e.g., git checkout vX.Y.Z) and run the generation script from the repository root:
      ./scripts/generate-alpine-packaging-file.ps1
    2. Prepare Aports: Fork the https://gitlab.alpinelinux.org/alpine/aports repository and clone it locally.
    3. Update Package: Navigate to aports/community/libmsquic, replace the existing APKBUILD file with the one you generated, and commit the change with the message community/libmsquic: upgrade to <version_number>.
    4. Submit: Create a merge request in the aports repository.