NAME

Net::QUIC::Endpoint - lower-level QUIC engine

DESCRIPTION

Endpoint is the low-level transport API underneath Net::QUIC::Driver.

Most applications should use Driver.

Use Endpoint directly only when you want to manage the QUIC service cycle yourself.

The caller owns:

the UDP socket
sending every outgoing datagram
draining all pending output
scheduling the next QUIC timeout
calling handle_timeout when that timer fires

Endpoint owns the QUIC protocol state.

A client Endpoint has one Net::QUIC::Connection.

A server Endpoint can manage many Connections behind one UDP socket.

BASIC CYCLE

A direct client integration looks like this:

receive one UDP packet
    -> receive_datagram

send all pending output
    -> next_datagram until undef

ask when QUIC next needs a timer
    -> timeout_after

timer fires
    -> handle_timeout

Then drain next_datagram again and schedule the new timeout_after.

Driver exists so most event-loop adapters do not have to repeat this logic.

SYNOPSIS

use Net::QUIC::Endpoint;

my $endpoint = Net::QUIC::Endpoint->client(
    local       => $packed_local_address,
    peer        => $packed_peer_address,
    alpn        => 'my-protocol',
    server_name => 'example.com',
);

my $connection = $endpoint->connection;

while (my $datagram = $endpoint->next_datagram) {
    send_udp($datagram);
}

my $seconds = $endpoint->timeout_after;

ADDRESSES

local and peer are packed IPv4 or IPv6 socket addresses.

local must be the actual local address used by the packet.

Wildcard bind addresses such as:

0.0.0.0
::

are not concrete QUIC paths.

If a server UDP socket is bound to a wildcard address, the integration must recover the real destination address of each received packet.

METHODS

client

my $endpoint = Net::QUIC::Endpoint->client(
    local       => $packed_local_address,
    peer        => $packed_peer_address,
    alpn        => 'my-protocol',
    server_name => 'example.com',
);

Creates a client Endpoint and its Connection.

Required options are:

  • local

    Packed local UDP address.

  • peer

    Packed server UDP address.

  • alpn

    Application protocol name.

  • server_name

    Name expected in the server certificate.

Server certificates are verified by default.

For a private or test CA:

ca_file => '/path/to/private-ca.pem'

adds that PEM file to the normal trust store.

Net::QUIC does not provide an insecure skip-verification option.

Optional client features

Choose the first QUIC version:

version => 2

Supported values are 1 and 2. The default is 1.

Resume a previous TLS session:

session_ticket => $saved_ticket

Reuse a previous address-validation token:

address_token => $saved_address_token

Attempt 0-RTT early data:

early_data => $saved_early_data_state

early_data already contains its matching session ticket, so it cannot be combined with session_ticket.

Saved session, address-token, and early-data values are opaque. Net::QUIC remembers the QUIC version inside them and automatically uses the correct version.

0-RTT data can be replayed. Only send operations that are safe to repeat.

Transport limits

Client and server both accept:

transport => {
    handshake_timeout => 10,
    idle_timeout      => 30,
    connection_window => 1024 * 1024,
    stream_window     => 256 * 1024,
    max_bidi_streams  => 100,
    max_uni_streams   => 100,
}

These are the defaults.

handshake_timeout is how long the initial connection setup may take.

idle_timeout is how long an otherwise established connection may stay idle. A value of zero disables the advertised idle timeout.

connection_window is the starting receive allowance for the whole connection.

stream_window is the starting receive allowance for each Stream.

max_bidi_streams and max_uni_streams are the initial numbers of peer-created streams that may exist at once.

These are flow-control starting values, not lifetime byte or stream limits.

server

my $endpoint = Net::QUIC::Endpoint->server(
    alpn             => 'my-protocol',
    certificate_file => 'server-cert.pem',
    private_key_file => 'server-key.pem',
);

Creates a server Endpoint.

One server Endpoint can manage many QUIC Connections.

Required options are:

alpn
certificate_file
private_key_file

Address validation

To require a new client to prove that it can receive packets at its source address:

validate_address => 1

A new client may receive QUIC Retry before a full Connection is created.

After a validated handshake, Net::QUIC can issue NEW_TOKEN so a returning client can prove the same address without another Retry round trip.

The client exposes that opaque value through "address_token" in Net::QUIC::Connection.

0-RTT

To allow replayable early data:

accept_early_data => 1

Only enable this when the application knows how to handle operations that may be repeated.

QUIC version preference

A server accepts QUIC v1 and v2.

To prefer v2 when a compatible client starts with v1:

preferred_version => 2

If this option is omitted, the server keeps the client's chosen supported version.

Preferred server address

A server can advertise another address for the same Connection:

preferred_address => $packed_server_address

The client validates that path before switching to it.

The UDP integration must actually be able to send and receive on the advertised address.

connection

my $connection = $endpoint->connection;

Client only.

Returns the client's Connection.

A server manages many Connections, so server code uses "next_connection" instead.

next_connection

while (my $connection = $endpoint->next_connection) {
    ...
}

Server only.

Returns the next newly created Connection, or undef when none is waiting.

A new Connection can be returned before its TLS handshake is complete. Check:

$connection->ready

before ordinary application work.

receive_datagram

$endpoint->receive_datagram($bytes, $local, $peer);

Feeds one received UDP datagram into QUIC.

$local must be the concrete local destination address for this packet.

$peer is the remote sender address.

An ECN-aware integration can pass the packet's two-bit IP-header ECN value as a fourth argument:

$endpoint->receive_datagram($bytes, $local, $peer, $ecn);

The values are:

0   Not-ECT
1   ECT(1)
2   ECT(0)
3   CE

Omitting $ecn is equivalent to zero.

next_datagram

while (my $datagram = $endpoint->next_datagram) {
    ...
}

Returns the next complete UDP datagram QUIC wants sent.

Returns undef when no output is waiting.

The returned Net::QUIC::Datagram contains the payload, local address, peer address, and ECN mark for the packet.

timeout_after

my $seconds = $endpoint->timeout_after;

Returns the number of seconds until QUIC next needs timer service.

It can return:

  • a positive number

    Schedule a one-shot timer for that many seconds.

  • zero

    The timeout is already due.

  • undef

    No timer is currently needed.

For a server this is the earliest deadline among all managed Connections, so the integration still needs only one Endpoint timer.

handle_timeout

$endpoint->handle_timeout;

Reports that the Endpoint timer fired.

After calling it:

drain next_datagram
ask timeout_after again

WHEN TO USE ENDPOINT DIRECTLY

Endpoint is useful for:

tests
unusual event-loop integrations
integrations that already have their own QUIC service loop

For ordinary event-loop code, Net::QUIC::Driver is simpler.

SEE ALSO

Net::QUIC

Net::QUIC::Driver

Net::QUIC::Connection

Net::QUIC::Datagram