NAME
Net::QUIC::Endpoint - low-level QUIC transport boundary
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) {
$udp->send($datagram->data, $datagram->peer);
}
my $after = $endpoint->timeout_after;
DESCRIPTION
Net::QUIC::Endpoint is the low-level boundary between QUIC and an event loop.
Most integrations should use Net::QUIC::Driver, which owns Endpoint output draining, backpressure pause/resume, and timeout replacement.
Direct Endpoint users own those rules themselves.
The event-loop integration owns the UDP socket and its timer. Endpoint owns the transport-facing side of QUIC and gives the integration datagrams to send and a timeout to schedule.
A QUIC connection is represented separately by Net::QUIC::Connection. A client endpoint owns one connection. A server endpoint can manage several connections behind one UDP socket and routes incoming packets by QUIC destination connection ID.
For a client integration, the basic cycle is:
UDP readable
-> receive_datagram
-> send each next_datagram
-> arm a timer for timeout_after
timer fires
-> handle_timeout
-> send each next_datagram
-> arm the timer again
The local and peer addresses are packed socket addresses such as those returned by Perl's Socket functions or by the networking framework in use. They must be IPv4 or IPv6 addresses.
local must identify the concrete local endpoint for the packet. Wildcard bind addresses 0.0.0.0 and :: are rejected because they do not identify a QUIC network path.
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 first Net::QUIC::Connection.
local, peer, alpn, and server_name are required.
Server certificates are verified by default. Net::QUIC uses Picotls' OpenSSL certificate verifier, including certificate-chain validation and DNS-name or IP-address verification against server_name. The verifier uses OpenSSL's default trust locations.
For a private or test certificate authority, ca_file adds certificates from a PEM file to the default trust store:
my $endpoint = Net::QUIC::Endpoint->client(
local => $packed_local_address,
peer => $packed_peer_address,
alpn => 'my-protocol',
server_name => 'internal.example',
ca_file => '/path/to/private-ca.pem',
);
Net::QUIC does not provide an insecure skip-verification switch.
Both client and server accept an optional transport hash:
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 Net::QUIC defaults.
handshake_timeout and idle_timeout are in seconds. Fractional seconds are accepted to millisecond precision. handshake_timeout must be greater than zero. idle_timeout => 0 disables the advertised idle timeout.
connection_window is the initial connection-level receive flow-control credit in bytes. stream_window is the initial per-stream receive credit and is used for bidirectional and unidirectional streams. Net::QUIC returns receive credit as the application consumes data, so these are starting windows rather than lifetime byte limits.
max_bidi_streams and max_uni_streams are the initial numbers of concurrent peer-initiated streams allowed. Closed peer streams return stream credit, so the values do not limit how many streams may exist over the life of a connection.
Net::QUIC currently advertises active migration as disabled. Migration is not exposed as a tuning option until the library implements and tests migration semantics.
ACK timing, congestion control, packet sizing, PMTU behavior, and connection ID management remain ngtcp2/Net::QUIC policy rather than public knobs at this stage.
server
my $endpoint = Net::QUIC::Endpoint->server(
alpn => 'my-protocol',
certificate_file => 'server-cert.pem',
private_key_file => 'server-key.pem',
validate_address => 1,
);
Creates a server endpoint. The UDP socket still belongs to the integration layer. One server endpoint can route packets for multiple QUIC connections.
Unsupported QUIC versions are answered statelessly with Version Negotiation before a Connection object is created.
validate_address is optional and defaults to false. When true, the first acceptable Initial from a new peer receives Retry instead of creating a Connection. The Retry token is authenticated, bound to the peer socket address, and valid for 10 seconds. Net::QUIC creates the Connection only after the peer returns a valid token. A token replayed from a different peer address is rejected without creating connection state.
Finished Connections are retired automatically after QUIC's closing or draining period, and all of their CID routes are removed from the Endpoint at the same time.
Server certificate and private-key files are loaded once when the Endpoint is constructed. Accepted Connections create their own Picotls sessions from that shared server TLS context instead of reopening or reparsing the credential files. Connections retain the shared context for as long as they need it.
Unknown short-header packets that cannot be routed to a live Connection can receive a Stateless Reset when they are large enough to do so safely. The Endpoint derives reset tokens from its private server secret and the destination connection ID, so it does not recreate Connection state just to send the reset. Unknown long-header packets and packets that are too small are dropped.
connection
my $connection = $endpoint->connection;
Returns the client connection owned by a client endpoint.
A server endpoint manages multiple connections, so calling connection on a server endpoint is an error. Use next_connection instead.
next_connection
while (my $connection = $endpoint->next_connection) {
...
}
Server only. Returns the next newly created connection, or undef when there is none waiting.
A connection can be returned before its TLS handshake is complete. Use $connection->ready when the application needs handshake readiness.
receive_datagram
$endpoint->receive_datagram($bytes, $local, $peer);
Feeds one received UDP datagram into QUIC.
$local must be the packed concrete destination address on which the packet arrived. It must not be 0.0.0.0 or ::.
If the UDP socket is bound to a wildcard address, the integration must use the platform's packet-info or destination-address mechanism to recover this value. The Endpoint intentionally does not own or inspect the UDP socket.
$peer is the packed address of the remote sender.
next_datagram
while (my $datagram = $endpoint->next_datagram) {
...
}
Returns the next UDP datagram QUIC wants sent, or undef if none is ready.
timeout_after
my $seconds = $endpoint->timeout_after;
Returns the number of seconds until QUIC next needs timer service. It may return zero when the timeout is already due, or undef when no timeout is currently needed.
For a server endpoint this is the earliest timeout among all managed connections, so the integration still needs only one endpoint timer.
handle_timeout
$endpoint->handle_timeout;
Tells QUIC that its event-loop timer fired. After this call, drain next_datagram again and arrange the new timeout_after value.