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:
localPacked local UDP address.
peerPacked server UDP address.
alpnApplication protocol name.
server_nameName 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,
max_datagram_frame_size => 0,
}
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.
max_datagram_frame_size advertises this endpoint's RFC 9221 QUIC DATAGRAM receive limit. Zero disables QUIC DATAGRAM receive support. A value such as 65535 enables it while the actual sendable payload is still limited by the peer and the current network path.
See "QUIC DATAGRAM" in Net::QUIC::Connection.
The Stream values 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.