quic_socket (quic v0.11.0)

View Source

UDP socket abstraction with packet batching support.

This module provides a unified socket interface that: - Uses the OTP 27+ socket module with GSO/GRO on Linux - Falls back to gen_udp on macOS/Windows/other platforms - Batches outgoing packets for improved throughput - Handles coalesced packets on receive (GRO)

Architecture

   quic_connection/quic_listener
           |
      quic_socket (this module)
           |
     socket module (OTP 27+) with GSO/GRO on Linux
           or
     gen_udp fallback on macOS/Windows

Configuration

   quic:start_server(Name, Port, #{
       batching => #{
           enabled => true,
           max_packets => 64
       }
   }).

Summary

Functions

Close the socket and flush any pending packets. Only closes the socket if owns_socket is true (i.e., socket was created by us).

Set the controlling process.

Detect platform capabilities for GSO/GRO.

Flush all buffered packets.

Get the underlying file descriptor.

Get the underlying socket from a socket_state.

Check if GSO is supported for this socket_state.

Open a UDP socket with batching support. Options: - All standard gen_udp options - batching => #{enabled => true, max_packets => 64, flush_timeout_ms => 1}

Open a UDP socket optimized for sending (client connections). Detects platform capabilities and enables GSO if available. Unlike open/2, this is optimized for a single destination.

Open a server send socket bound to a local address with reuseport. Uses OTP socket backend with GSO support on Linux for high throughput. This is for server connections that need to send from a specific local port.

Receive packets from the socket. On Linux with GRO, may return multiple coalesced packets.

Send a packet, buffering for batch send if enabled. Packet can be: - binary() - already flat packet - {iov, [binary()]} - packet parts for scatter/gather (avoids copy)

Set socket options.

Get the local address and port.

Wrap an existing gen_udp socket with batching support. This allows adding batching to connections that already have a socket. Note: GSO/GRO are not available when wrapping existing gen_udp sockets. The wrapped socket is NOT owned by this state - close/1 will not close it.

Types

packet_view/0

-type packet_view() :: binary() | {iov, [binary()]} | iodata().

socket_state/0

-opaque socket_state()

Functions

close(Socket_state)

-spec close(socket_state()) -> ok.

Close the socket and flush any pending packets. Only closes the socket if owns_socket is true (i.e., socket was created by us).

controlling_process(Socket_state, Pid)

-spec controlling_process(socket_state(), pid()) -> ok | {error, term()}.

Set the controlling process.

detect_capabilities()

-spec detect_capabilities() -> map().

Detect platform capabilities for GSO/GRO.

flush(Socket_state)

-spec flush(socket_state()) -> {ok, socket_state()} | {error, term()}.

Flush all buffered packets.

get_fd(Socket_state)

-spec get_fd(socket_state()) -> {ok, integer()} | {error, term()}.

Get the underlying file descriptor.

get_socket(Socket_state)

-spec get_socket(socket_state()) -> socket:socket() | gen_udp:socket().

Get the underlying socket from a socket_state.

gso_supported(Socket_state)

-spec gso_supported(socket_state()) -> boolean().

Check if GSO is supported for this socket_state.

open(Port, Opts)

-spec open(inet:port_number(), map()) -> {ok, socket_state()} | {error, term()}.

Open a UDP socket with batching support. Options: - All standard gen_udp options - batching => #{enabled => true, max_packets => 64, flush_timeout_ms => 1}

open_for_send(RemoteIP, Opts)

-spec open_for_send(inet:ip_address(), map()) -> {ok, socket_state()} | {error, term()}.

Open a UDP socket optimized for sending (client connections). Detects platform capabilities and enables GSO if available. Unlike open/2, this is optimized for a single destination.

open_server_send(_, Opts)

-spec open_server_send({inet:ip_address(), inet:port_number()}, map()) ->
                          {ok, socket_state()} | {error, term()}.

Open a server send socket bound to a local address with reuseport. Uses OTP socket backend with GSO support on Linux for high throughput. This is for server connections that need to send from a specific local port.

recv(Socket_state, Timeout)

-spec recv(socket_state(), timeout()) ->
              {ok, {inet:ip_address(), inet:port_number()}, [binary()]} | {error, term()}.

Receive packets from the socket. On Linux with GRO, may return multiple coalesced packets.

send(Socket_state, IP, Port, Packet)

-spec send(socket_state(), inet:ip_address(), inet:port_number(), packet_view()) ->
              {ok, socket_state()} | {error, term()}.

Send a packet, buffering for batch send if enabled. Packet can be: - binary() - already flat packet - {iov, [binary()]} - packet parts for scatter/gather (avoids copy)

Returns updated state. Auto-flushes when: - Batch is full (max_batch_packets reached) - Destination address changes

setopts(Socket_state, Opts)

-spec setopts(socket_state(), list()) -> ok | {error, term()}.

Set socket options.

sockname(Socket_state)

-spec sockname(socket_state()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, term()}.

Get the local address and port.

wrap(Socket, Opts)

-spec wrap(gen_udp:socket(), map()) -> {ok, socket_state()}.

Wrap an existing gen_udp socket with batching support. This allows adding batching to connections that already have a socket. Note: GSO/GRO are not available when wrapping existing gen_udp sockets. The wrapped socket is NOT owned by this state - close/1 will not close it.