NAME
Linux::Event::Listener - accepting socket that constructs Stream instances
SYNOPSIS
use Linux::Event::Listener;
use Linux::Event::Loop;
package EchoStream;
use parent 'Linux::Event::Stream';
sub on_data ($stream, $bytes) {
$stream->write($bytes);
}
package EchoListener;
use parent 'Linux::Event::Listener';
sub on_accept ($listener, $stream) {
say "accepted " . $stream->peer->host;
}
package main;
my $loop = Linux::Event::Loop->new;
my $listener = EchoListener->new(
loop => $loop, # optional: attach immediately
stream_class => 'EchoStream', # required
host => '0.0.0.0', # required for TCP
port => 7000, # required for TCP
backlog => 4096, # default
max_accept_per_tick => 256, # default
edge_triggered => 0, # default
);
$loop->run;
DESCRIPTION
Listener creates or adopts a listening TCP or Unix stream socket, drains accepted connections with native accept4, constructs the configured Stream subclass for every accepted connection, and attaches each Stream to the same Loop. Application code never handles accepted descriptors directly.
Every accepted Stream receives the Listener's data value. Stream-level buffer, deadline, framing, and TLS policy comes from the Stream subclass's cached declarations.
CONSTRUCTION
Construct Listener directly and name the Stream subclass that it should create for accepted connections.
Every Listener can be attached in either form:
my $listener = Linux::Event::Listener->new(
loop => $loop, # optional: attach immediately
stream_class => 'ServerStream', # required
host => '127.0.0.1', # required for TCP
port => 9000, # required for TCP
reuseaddr => 1, # default
);
my $listener = Linux::Event::Listener->new(
stream_class => 'ServerStream', # required
unix => '/run/app.sock', # required for Unix
unlink => 1, # optional; default 0
permissions => 0660, # optional
);
$loop->add($listener);
$loop->add sets loop, starts accepting, and returns the same Listener. A Listener may be attached only once and to only one Loop.
SOCKET SOURCES
Exactly one of these sources is required:
host => $host, port => $portCreates a TCP listener.
$hostmay be an address, hostname, or*for a passive wildcard bind.port => 0asks the kernel to choose a port;port()then returns the assigned value.unix => $pathCreates a filesystem Unix stream listener.
fh => $listening_socketAdopts an existing listening socket. Listener sets nonblocking and close-on-exec flags. It does not close the handle by default; pass
owns_socket => 1to transfer ownership.
OPTIONS
Common options, shown with their actual defaults, are:
my $listener = Linux::Event::Listener->new(
stream_class => 'ServerStream', # required
host => '0.0.0.0', # required for TCP
port => 9000, # required for TCP
loop => $loop, # optional
data => $server_state, # optional
backlog => 4096, # default
max_accept_per_tick => 256, # default
edge_triggered => 0, # default
);
max_accept_per_tick bounds accepts per level-triggered dispatch. Zero drains until EAGAIN. edge_triggered => 1 requires that zero/unbounded setting.
TCP socket options are:
my $listener = Linux::Event::Listener->new(
stream_class => 'ServerStream', # required
host => '::', # required for TCP
port => 9000, # required for TCP
reuseaddr => 1, # default
reuseport => 0, # default
v6only => 1, # optional; kernel default if omitted
bind_device => 'eth0', # optional
);
Unix socket options are:
my $listener = Linux::Event::Listener->new(
stream_class => 'ServerStream', # required
unix => '/run/app.sock', # required for Unix
unlink => 0, # default
unlink_on_close => 1, # default
permissions => 0660, # optional
);
Adopted-socket options are:
my $listener = Linux::Event::Listener->new(
stream_class => 'ServerStream', # required
fh => $socket, # required for adoption
owns_socket => 0, # default
);
Source-specific options are rejected for other source types. bind_device applies Linux SO_BINDTODEVICE before a created TCP socket is bound. It is also accepted for an adopted Internet listener. The process must have the privilege required by the kernel; failure throws a structured socket_configuration Error naming bind_device.
ACCEPTED STREAMS
Listener uses native accept4 with SOCK_NONBLOCK and SOCK_CLOEXEC. For every success it constructs stream_class with fh and a lazy Linux::Event::Address peer, passes it this Listener's data, attaches the Stream to this Listener's Loop, calls the optional Listener on_accept, and then fires on_ready for a plain Stream. on_accept may replace the Stream's data when connection-specific state is needed.
A Stream subclass declares TLS directly:
package SecureStream;
use parent 'Linux::Event::Stream';
use Linux::Event::TLS
cert_file => '/etc/linux-event/server-cert.pem', # required
key_file => '/etc/linux-event/server-key.pem', # required
alpn => ['echo/1'], # optional
handshake_timeout => 10, # default
shutdown_timeout => 5; # default
sub on_data ($stream, $bytes) {
$stream->write($bytes);
}
Naming SecureStream as stream_class makes every accepted connection use server TLS automatically. Listener loads and validates the declared server identity during construction. The TLS handshake begins after attachment and on_ready does not fire until it succeeds.
CALLBACKS
on_accept
A Listener subclass may define this optional callback:
sub on_accept ($listener, $stream) {
$listener->data->{connections}{ $stream->fd } = $stream;
}
It receives the fully constructed Stream after attachment to the Listener's Loop. It runs before a plain Stream's on_ready and before a TLS Stream has completed its handshake. Use it for connection accounting, association with server state, initial policy, or immediate rejection with $stream->close.
An exception closes that accepted Stream, suppresses its pending on_ready, and delivers a nonfatal callback Error with operation on_accept to the Listener's on_error. The listening socket remains active when on_error handles the error.
on_error
Listener subclasses may override on_error($listener, $error) to implement runtime error policy. The base implementation dies. Resource-exhaustion errors pause acceptance before on_error runs; call resume after the application has restored descriptor or memory capacity.
ERROR POLICY
Runtime failures are Linux::Event::Error objects. Resource exhaustion pauses acceptance before notification to prevent an error spin. The base Listener dies after such a failure. Applications that need another policy may subclass Listener and override on_error:
package MyListener;
use parent 'Linux::Event::Listener';
sub on_error ($listener, $error) {
warn "$error\n";
}
Constructor validation errors throw immediately, and socket-setup failures throw a structured Error.
METHODS
pause / resume
Disable or re-enable acceptance without closing the listening socket. Both return the Listener.
close
Stop accepting, remove native registration, close an owned handle, and remove an owned Unix path when configured. A terminal Listener releases its Loop.
detach
Stop accepting and return the still-open listener handle, transferring ownership to the caller. Returns undef after a terminal state.
loop / fh / fd / host / port / path
Return attachment and bound-socket information. loop is undef before attachment and after terminal cleanup. Fields that do not apply to the socket family are undefined.
family / family_number / is_tcp / is_unix
family returns inet, inet6, unix, or unknown. family_number returns the native numeric address-family constant. is_tcp is true for IPv4 and IPv6 listeners; is_unix is true for Unix listeners.
stream_class
Return the configured Stream subclass name.
state
Returns unattached, listening, paused, closed, failed, or detached.
accepted / last_error / data
Return the cumulative accepted connection count, most recent runtime error, and optional application value. data($new_value) replaces the value.
is_paused / is_running / is_terminal
Convenience predicates for the current lifecycle state.
PERFORMANCE
The Listener class caches its resolved native callbacks. XS drains accept4 in batches, while Perl is entered only for Stream construction and application policy. Accepted sockets never receive a temporary public registration before Stream attachment.