NAME
Net::QUIC::Driver - simple event-loop integration for Net::QUIC
SYNOPSIS
use Net::QUIC::Driver;
my $driver = Net::QUIC::Driver->client(
local => $packed_local,
peer => $packed_peer,
alpn => 'my-protocol',
server_name => 'example.com',
send => sub {
my ($datagram) = @_;
return send_udp_datagram(
$datagram->data,
$datagram->local,
$datagram->peer,
);
},
set_timeout => sub {
my ($seconds) = @_;
if (defined $seconds) {
replace_quic_timer($seconds);
} else {
cancel_quic_timer();
}
},
);
my $connection = $driver->connection;
# Once the UDP transport is ready to send:
$driver->start;
# From the UDP receive callback:
$driver->receive($bytes, $local, $peer);
# From the one-shot timer callback:
$driver->timeout;
# When UDP output recovers from backpressure:
$driver->writable;
DESCRIPTION
Net::QUIC::Driver is the recommended way to connect Net::QUIC to an event loop.
The event loop owns the UDP socket and one replaceable timer. Driver owns the QUIC servicing rules around those two things.
Net::QUIC::Endpoint remains the lower-level engine underneath Driver. Driver drains Endpoint output, stops when the UDP transport reports backpressure, and replaces the event-loop timeout whenever QUIC's next deadline changes.
An adapter normally reports only four lifecycle events:
start
receive
timeout
writable
start is a one-time readiness notification. It lets an adapter construct the Driver before its UDP transport is ready without causing constructor-time I/O.
After startup, the ordinary event-loop inputs are only:
receive a UDP datagram arrived
timeout the requested QUIC timeout expired
writable UDP output can accept more packets again
The adapter supplies only two operations in the other direction:
send transmit one complete UDP datagram
set_timeout replace or cancel QUIC's one-shot timeout
Application stream operations do not require a separate Driver call. When a Connection is obtained through the Driver, Net::QUIC installs a private output notification so state-changing application operations can cause pending QUIC output and deadline changes to be serviced automatically.
If an adapter can provide UDP receive/send readiness and a one-shot timer, it usually has everything Driver needs.
Driver methods return after the corresponding QUIC work has been serviced. The surrounding event callback can then inspect application state normally. For example, after receive returns a client can check ready, pull peer streams with next_stream, and consume their data.
Driver handles the transport bookkeeping; it does not impose an application dispatcher.
DRIVER OR ENDPOINT?
Use Driver for ordinary event-loop integration.
Use Net::QUIC::Endpoint directly only when the integration deliberately wants to own QUIC output draining and timeout maintenance itself.
Driver is not a second protocol layer. It is a small piece of integration bookkeeping around Endpoint.
CONSTRUCTORS
client
my $driver = Net::QUIC::Driver->client(
local => $local,
peer => $peer,
alpn => $alpn,
server_name => $server_name,
send => sub { ... },
set_timeout => sub { ... },
);
Creates a client Net::QUIC::Endpoint and wraps it in a Driver.
local and peer are packed IPv4 or IPv6 socket addresses for this UDP socket and the remote server.
alpn identifies the application protocol carried over QUIC. The client and server must use a compatible ALPN value.
server_name is the DNS name or IP address expected in the server certificate. It is used for certificate verification and does not have to be the same textual value used to obtain peer.
Endpoint options other than send and set_timeout are passed directly to "client" in Net::QUIC::Endpoint.
server
my $driver = Net::QUIC::Driver->server(
alpn => $alpn,
certificate_file => $certificate_file,
private_key_file => $private_key_file,
send => sub { ... },
set_timeout => sub { ... },
);
Creates a server Net::QUIC::Endpoint and wraps it in a Driver.
New server Connections obtained through next_connection receive the same automatic application-output notification as the client Connection.
new
my $driver = Net::QUIC::Driver->new(
endpoint => $endpoint,
send => sub { ... },
set_timeout => sub { ... },
);
Wraps an existing Endpoint-compatible object. Most adapters can use client or server instead.
ADAPTER CALLBACKS
send
send => sub {
my ($datagram) = @_;
...
return 1;
}
Receives one Net::QUIC::Datagram.
The Datagram contains one complete UDP packet:
$datagram->data payload bytes
$datagram->peer packed destination socket address
$datagram->local packed local socket address chosen by QUIC
The adapter should send data as one UDP datagram to peer. local is the concrete local source address associated with that QUIC path.
For a socket bound to one concrete local address, the socket normally already selects that source address.
For a wildcard-bound socket, the adapter must explicitly preserve the Datagram's local source address when transmitting. The mechanism is platform-specific; for example, Linux IPv4 can use packet information with sendmsg.
Return true when the adapter can immediately accept another datagram.
Return false only after accepting this datagram when output has crossed the adapter's backpressure threshold. Driver then stops asking Net::QUIC for more datagrams until writable is called.
set_timeout
set_timeout => sub {
my ($seconds) = @_;
...
}
Replace the adapter's current one-shot QUIC timeout.
$seconds is a non-negative number of seconds relative to now. undef means QUIC currently needs no timed wakeup and the adapter should cancel its existing QUIC timeout.
The value can change after any QUIC state transition. It is not a recurring interval.
METHODS
start
$driver->start;
Marks the UDP transport ready and performs the initial QUIC service pass.
For a client this normally sends the Initial packet and requests the first QUIC timeout.
start is idempotent.
receive
$driver->receive($bytes, $local, $peer);
Report one received UDP datagram.
$local must be the packed concrete destination address on which this packet was received. 0.0.0.0 and :: are wildcard bind addresses and are not valid QUIC paths.
A socket bound to a wildcard address therefore needs destination-address packet information from the operating system. On Linux IPv4 this can be obtained with IP_PKTINFO and recvmsg. The equivalent mechanism for other address families or operating systems belongs in the UDP adapter.
$peer is the packed address of the remote sender.
Driver gives the packet to the Endpoint, sends any datagrams QUIC produces, and updates the requested timeout.
timeout
$driver->timeout;
Report that the one-shot timeout most recently requested through set_timeout has fired.
Driver lets QUIC process the expiry, sends any resulting datagrams, and updates the next timeout.
writable
$driver->writable;
Report that UDP output has recovered after send returned false.
Driver resumes sending queued QUIC datagrams and updates the timeout.
connection
Returns the client Connection and enables automatic application-output notification for it.
A server Driver follows the Endpoint rule and does not provide one singular Connection through this method.
next_connection
Returns the next new server Connection, or undef when none is waiting.
The returned Connection is automatically connected to the Driver's private application-output notification.
endpoint
Returns the underlying low-level Endpoint.
This escape hatch is intended for integrations that need Endpoint-specific functionality. Code that directly drives the Endpoint is responsible for not bypassing Driver's integration rules.
started
Returns true after start.
LOW-LEVEL ENDPOINT
Driver does not replace Net::QUIC::Endpoint.
Endpoint remains useful for tests, unusual integrations, and code that deliberately wants direct control over:
receive_datagram
next_datagram
timeout_after
handle_timeout
Driver is the simpler recommended API for ordinary event-loop adapters.
EXAMPLES
The distribution includes complete Driver integrations in examples/ for:
Linux::Event
AnyEvent
IO::Async
Mojo::IOLoop
EV
examples/io-select-echo-server.pl provides a small local QUIC echo server that can be used to run the client examples.
See examples/README.md.