NAME
Linux::Event::IO::Sock::Listener - asynchronous listening SOCK_STREAM socket
SYNOPSIS
use v5.36;
use Linux::Event::Loop;
use Linux::Event::IO::Sock::Listener;
use Linux::Event::IO::Sock::Stream;
my $loop = Linux::Event::Loop->new;
my $listener = Linux::Event::IO::Sock::Listener->new(
loop => $loop,
stream_class => 'Linux::Event::IO::Sock::Stream',
host => '127.0.0.1',
port => 9999,
on_data => sub ($stream, $bytes) {
$stream->write($bytes);
},
);
$loop->run;
DESCRIPTION
Linux::Event::IO::Sock::Listener owns a listening Linux SOCK_STREAM socket and constructs the configured Linux::Event::IO::Sock::Stream subclass for every accepted connection. It is a separate public object because bind/listen/accept lifecycle is different from connected byte-stream I/O.
TCP and Unix-domain listeners share this class. Socket family is selected by constructor options, not by subclass hierarchy.
ACCEPTED STREAM SUBCLASS POLICY AND TUNING
stream_class is a prominent part of the Listener design. The selected Linux::Event::IO::Sock::Stream subclass gives every accepted connection the same native framer, TLS server identity and verification policy, socket policy, and stream_options tuning for fairness, batching, limits, watermarks, and deadlines. Linux::Event validates and caches that policy once per stream class.
Listener constructor callbacks are complementary: on_data, on_message, and the other accepted-Stream callback templates can capture lexical server state, override same-named stream methods, and are shared rather than rebuilt for every accept. This keeps reusable protocol and tuning policy in the Stream subclass while preserving ordinary closure scope for a particular listener.
The Listener's own on_accept and listener-error policy remain named subclass methods because on_error in the constructor belongs to accepted Streams.
Listener acceptance tuning
Listener tuning is constructor policy; it is distinct from the accepted class's stream_options and socket_options:
my $listener = Linux::Event::IO::Sock::Listener->new(
loop => $loop,
stream_class => 'ServerConnection',
host => '0.0.0.0',
port => 9999,
backlog => 8_192,
max_accept_per_tick => 512,
);
These settings are passed directly to new; Listener does not define a class-level tuning method. The complete set is:
backlog(default 4,096)Positive listen backlog requested from the kernel.
max_accept_per_tick(default 256)Non-negative accept fairness limit. Zero drains until
EAGAINand is required whenedge_triggeredis enabled.edge_triggered(default 0)Boolean
0or1selecting edge-triggered accept readiness.reuseaddr(default 1)Boolean
0or1controllingSO_REUSEADDRfor a created listener.reuseport(default 0)Boolean
0or1controllingSO_REUSEPORTfor a created listener.v6only(default unspecified)Optional boolean
0or1controllingIPV6_V6ONLYfor a created IPv6 listener.bind_device(default unspecified)Optional non-empty interface name used with
SO_BINDTODEVICEfor a created Internet listener.
Unix listener ownership controls are unlink (default 0), unlink_on_close (default 1), and optional permissions from 0 through 07777. owns_socket controls ownership of an adopted fh and is not a throughput-tuning option.
CONSTRUCTION
stream_class is required and names the stream-socket subclass created for each accepted connection. Exactly one listener source is selected:
Listener->new(
stream_class => 'ServerConnection',
host => '0.0.0.0',
port => 9999,
);
Listener->new(
stream_class => 'ServerConnection',
unix => '/run/example.sock',
);
Listener->new(
stream_class => 'ServerConnection',
fh => $existing_listener,
);
loop => $loop attaches immediately; otherwise add the detached object with $loop->add($listener). Listener data is supplied to each accepted connection as its initial data value.
The Listener may also receive accepted-Stream callback templates directly:
my $database = ...;
my $listener = Listener->new(
stream_class => 'Linux::Event::IO::Sock::Stream',
host => '0.0.0.0',
port => 9999,
on_data => sub ($stream, $bytes) {
persist($database, $stream, $bytes);
},
);
Supported templates and signatures are on_data($stream, $bytes), on_message($stream, $message), on_messages($stream, $messages), on_ready($stream), on_transport_ready($stream), on_drain($stream), on_eof($stream), on_error($stream, $error), and on_close($stream). These constructor options belong to each accepted Stream; on_error($listener, $error) for the Listener itself remains a Listener subclass method. One template CV is retained by the Listener and passed to every accepted Stream. Linux::Event does not create a new closure per accept.
TCP listener policy includes backlog, reuseaddr, reuseport, optional v6only, and bind_device. Unix listeners support path ownership controls including unlink, unlink_on_close, and permissions. Adopted handles default to caller ownership unless owns_socket is true.
ACCEPTANCE
Native code drains accept4 with nonblocking and close-on-exec flags. max_accept_per_tick bounds level-triggered acceptance for fairness; zero drains until EAGAIN and is required with edge-triggered operation.
For each accepted socket Linux::Event constructs stream_class, attaches it to the same Loop, then invokes optional on_accept($listener, $stream). A plain stream's on_ready follows. For TLS, on_accept still observes the new connection immediately after attachment while on_ready waits for the TLS handshake and verification to complete.
An on_accept exception closes only that accepted connection and is reported as a callback error; it does not silently kill the listener.
TLS
TLS policy belongs to the accepted stream-socket class, not the listener. A server class declares Linux::Event::TLS with cert_file and key_file. Listener validates that server policy during construction and creates fresh TLS state for every accepted connection.
METHODS AND LIFECYCLE
port reports the bound TCP port, including the kernel-selected value after port => 0. family, family_number, is_tcp, and is_unix identify the listening socket family.
pause and resume control acceptance while retaining the listening socket. close ends ownership. detach returns the still-open listening handle and is terminal. state reports listener lifecycle such as unattached, listening, paused, closed, failed, or detached.
Runtime errors are Linux::Event::Error values. Resource exhaustion pauses acceptance before error delivery to prevent a readable-backlog error spin. A subclass may define on_error($listener, $error) to implement application policy.
SEE ALSO
Linux::Event::IO::Sock::Stream, Linux::Event::TLS, docs/LISTENER-DESIGN.md, docs/SOCKET-CONFIGURATION.md, docs/FIRST-CLASS-STREAM-CALLBACKS.md.