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.

SEE ALSO

Net::QUIC

Net::QUIC::Connection

Net::QUIC::Stream

Net::QUIC::Endpoint

Net::QUIC::Datagram