NAME
Net::QUIC::Driver - connect Net::QUIC to an event loop
DESCRIPTION
Driver is the recommended integration API.
Net::QUIC needs two things from an event loop:
UDP I/O
one replaceable one-shot timer
Driver turns those two things into a working QUIC transport.
Your application normally does not call a separate QUIC pump. Driver handles the routine transport work after UDP reads, timer expirations, writable notifications, and application Stream operations.
If you are writing an event-loop adapter, start here.
QUICK MODEL
The adapter gives Driver two callbacks:
send
set_timeout
The adapter reports four events to Driver:
start
receive
timeout
writable
In plain language:
UDP transport is ready
-> start
one UDP packet arrived
-> receive
the requested timer fired
-> timeout
UDP output was blocked and can send again
-> writable
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) = @_;
send_one_udp_packet(
$datagram->data,
$datagram->local,
$datagram->peer,
);
return 1;
},
set_timeout => sub {
my ($seconds) = @_;
if (defined $seconds) {
replace_quic_timer($seconds);
} else {
cancel_quic_timer();
}
},
);
my $connection = $driver->connection;
$driver->start;
From the UDP read callback:
$driver->receive($bytes, $local, $peer);
From the timer callback:
$driver->timeout;
If UDP sending had become blocked and later recovers:
$driver->writable;
DRIVER OR ENDPOINT?
Use Driver unless you have a specific reason not to.
Net::QUIC::Endpoint is the lower-level engine underneath Driver. Endpoint makes the caller manually drain output and maintain the QUIC timer.
Driver does that bookkeeping for you.
CONSTRUCTORS
client
my $driver = Net::QUIC::Driver->client(
local => $local,
peer => $peer,
alpn => 'my-protocol',
server_name => 'example.com',
send => sub { ... },
set_timeout => sub { ... },
);
Creates a client Driver.
local is the packed local UDP socket address.
peer is the packed server UDP address.
alpn is the application protocol name that client and server agree to use.
server_name is the DNS name or IP address expected in the server certificate.
Other client options are passed to "client" in Net::QUIC::Endpoint. This includes session resumption, 0-RTT, address-token reuse, QUIC version selection, and transport limits.
server
my $driver = Net::QUIC::Driver->server(
alpn => 'my-protocol',
certificate_file => 'server-cert.pem',
private_key_file => 'server-key.pem',
send => sub { ... },
set_timeout => sub { ... },
);
Creates a server Driver.
One server Driver can manage many QUIC Connections on one UDP socket.
Pull newly created Connections with "next_connection".
Other server options are passed to "server" in Net::QUIC::Endpoint.
new
my $driver = Net::QUIC::Driver->new(
endpoint => $endpoint,
send => sub { ... },
set_timeout => sub { ... },
);
Wraps an existing Endpoint-compatible object.
Most code should use client or server instead.
ADAPTER CALLBACKS
send
send => sub {
my ($datagram) = @_;
...
return 1;
}
Receives one complete Net::QUIC::Datagram.
Useful values are:
$datagram->data
$datagram->local
$datagram->peer
$datagram->ecn
data is one complete UDP payload. Do not split it.
peer is the destination address.
local is the local source address QUIC expects for that packet.
For a socket bound to one concrete local address, the socket normally already uses the right source address.
For a wildcard-bound socket or a migrating connection, the adapter may need a platform-specific source-address mechanism such as sendmsg packet information.
The callback return value controls output flow:
true
The adapter can accept another UDP datagram immediately.
false
This datagram was accepted, but the adapter cannot accept another one yet.
That temporary inability to accept more output is often called backpressure.
When output becomes available again, call "writable".
set_timeout
set_timeout => sub {
my ($seconds) = @_;
...
}
Replace the current one-shot QUIC timer.
$seconds is relative to now and can be fractional.
undef means cancel the current QUIC timer.
This is not a repeating interval. Driver can request a different value after any QUIC state change.
METHODS
start
$driver->start;
Tells Driver that the UDP transport is ready.
For a client this normally causes the first QUIC packet to be produced.
start is idempotent.
receive
$driver->receive($bytes, $local, $peer);
Reports one received UDP datagram.
$local is the concrete local address on which the packet arrived.
$peer is the sender's address.
Both are packed IPv4 or IPv6 socket addresses.
0.0.0.0 and :: are wildcard bind addresses and are not valid packet paths. A wildcard-bound server therefore needs the operating system's destination-address information for each received packet.
An ECN-aware adapter can pass one optional fourth argument:
$driver->receive($bytes, $local, $peer, $ecn);
where $ecn is the two-bit IP-header value from 0 through 3.
Adapters that do not support ECN can omit it.
Driver processes the packet, sends any resulting output, and updates the timer before returning.
timeout
$driver->timeout;
Reports that the currently requested one-shot QUIC timer fired.
Driver processes the timeout, sends any resulting packets, and requests the next timer value.
writable
$driver->writable;
Reports that UDP output can accept packets again after send returned false.
Driver resumes output and updates the timer.
connection
my $connection = $driver->connection;
Client only.
Returns the client's Net::QUIC::Connection.
next_connection
while (my $connection = $driver->next_connection) {
...
}
Server only.
Returns the next newly created Connection, or undef when none is waiting.
A new server Connection can be returned before its handshake is complete. Check:
$connection->ready
before ordinary application work.
endpoint
Returns the underlying Net::QUIC::Endpoint.
This is an escape hatch for integrations that need Endpoint-specific functionality.
started
Returns true after start.
APPLICATION OPERATIONS
Connections and Streams obtained through Driver automatically notify it when application operations create transport work.
For example:
$stream->send(...);
$stream->finish;
$stream->reset(...);
$connection->close;
do not require a separate Driver service call.
EXAMPLES
Complete Driver integrations are included in examples/ for:
Linux::Event
AnyEvent
IO::Async
Mojo::IOLoop
EV
There is also a small IO::Select echo server.
See examples/README.md.