NAME

Linux::Event::IO::Sock::Stream - asynchronous Linux SOCK_STREAM connections

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 $server = Linux::Event::IO::Sock::Listener->new(
    loop         => $loop,
    stream_class => 'Linux::Event::IO::Sock::Stream',
    host         => '127.0.0.1',
    port         => 0,
    on_data      => sub ($stream, $bytes) {
        $stream->write($bytes);
    },
);

my $prefix = 'received';
my $client = Linux::Event::IO::Sock::Stream->connect(
    loop    => $loop,
    host    => '127.0.0.1',
    port    => $server->port,
    on_ready => sub ($stream) {
        $stream->write('hello');
    },
    on_data => sub ($stream, $bytes) {
        say "$prefix: $bytes";
        $stream->close;
        $server->close;
        $loop->stop;
    },
    on_error => sub ($stream, $error) {
        die "connection failed: $error\n";
    },
);

$loop->run;

DESCRIPTION

Linux::Event::IO::Sock::Stream is the public class for connected Linux SOCK_STREAM sockets. TCP over IPv4 or IPv6 and Unix-domain stream sockets use the same class; address family is connection configuration rather than a separate type hierarchy.

The class combines the common ordered-byte engine with socket acquisition, addresses, socket policy, kernel half-close semantics, and optional TLS. A concrete protocol subclass can supply named callbacks and declare class policy; constructor callbacks are an equally supported way to provide application behavior with normal Perl lexical scope.

CALLBACKS, SUBCLASSING, AND TUNING

Constructor callbacks make the public Stream leaf directly useful and preserve ordinary lexical scope. Subclassing remains one of Linux::Event's important distinguishing features because a protocol class can declare, once:

  • a native Linux::Event::Framer and its wire format;

  • Linux::Event::TLS identity, verification, ALPN, and role policy;

  • stream_options tuning for reads, fairness, batching, buffers, watermarks, limits, and established deadlines; and

  • socket policy and named, reusable callbacks.

Class policy and method callbacks are validated and cached once per subclass. A constructor callback overrides a same-named method for one connection and is retained once in that object's effective descriptor. This makes it natural to combine reusable high-performance protocol policy with per-connection lexical state without adding event-time method lookup or callback-style selection.

stream_options

Define stream_options as a class method on the Stream subclass. It returns key/value pairs, or one hash reference:

package TunedConnection;
use parent 'Linux::Event::IO::Sock::Stream';

sub stream_options ($class) {
    return (
        read_size         => 131_072,
        read_budget_bytes => 524_288,
        high_watermark    => 2_097_152,
        low_watermark     => 524_288,
        idle_timeout      => 60,
    );
}

These options also apply to Pipe and TTY subclasses. The complete Stream option set is:

  • read_size (default 65,536)

    Maximum bytes requested by one native read; a positive integer.

  • read_budget_bytes (default 0)

    Maximum bytes read during one readiness drain. Zero drains until the socket would block.

  • read_batch_bytes (default 0)

    For an unframed class, combine successful reads before on_data up to this non-negative byte target. Partial batches flush when the current drain ends; zero preserves normal read callback boundaries. It is invalid with framing.

  • message_batch_size (default 0)

    For a framed class, deliver arrays of at most this many messages to on_messages. Partial batches flush when the current drain ends; zero uses on_message. A positive value requires on_messages and framing.

  • max_buffer (default 8,388,608)

    Positive hard byte bound for retained input, an incomplete frame, and the aggregate payload retained for one message batch.

  • high_watermark (default 1,048,576)

    Non-negative pending-output byte level at which write or send begins returning false while still accepting the data.

  • low_watermark (default 262,144)

    Non-negative pending-output byte level at or below which on_drain fires after high-watermark backpressure. It must not exceed high_watermark.

  • max_pending_bytes (default 0)

    Hard non-negative pending-output byte limit. Zero means unbounded.

  • idle_timeout (default 0 seconds)

    Maximum inactivity interval since successful established input or output progress. Zero disables it.

  • read_timeout (default 0 seconds)

    Maximum interval without inbound progress while reading is active. Pausing input suspends it; zero disables it.

  • write_timeout (default 0 seconds)

    Maximum interval without output progress while data is queued. Zero disables it.

Byte counts are integers. Timeout values are finite non-negative seconds and may be fractional. Constructor timeout values override class defaults for one Stream; the other values are class policy.

socket_options

Define socket_options as another class method on a Stream subclass. It also returns key/value pairs or one hash reference:

sub socket_options ($class) {
    return (
        tcp_nodelay      => 1,
        keepalive        => 1,
        tcp_user_timeout => 15,
    );
}

Unspecified options retain kernel defaults. The complete set is:

  • tcp_nodelay

    Boolean 0 or 1 controlling TCP_NODELAY; TCP only.

  • keepalive

    Boolean 0 or 1 controlling SO_KEEPALIVE; TCP only.

  • keepalive_idle

    Positive integer seconds before the first TCP keepalive probe.

  • keepalive_interval

    Positive integer seconds between TCP keepalive probes.

  • keepalive_count

    Positive integer number of failed TCP keepalive probes allowed.

  • tcp_user_timeout

    Finite non-negative seconds for TCP_USER_TIMEOUT; fractional values are rounded up to milliseconds. TCP only.

  • send_buffer

    Positive integer requested SO_SNDBUF size.

  • receive_buffer

    Positive integer requested SO_RCVBUF size.

Positive socket integers are at most 2,147,483,647. Constructor values override class policy for one connection. bind_device is a constructor option, not a socket_options key. configure_socket is the cached cold-path hook for Linux options not covered above.

OUTBOUND CONNECTIONS

connect constructs one connection object whose identity is retained through resolution, connection, optional TLS handshake, established I/O, and close:

my $stream = Client->connect(
    loop    => $loop,          # optional immediate attachment
    host    => 'example.com',  # TCP remote host
    port    => 443,            # TCP remote port
    timeout => 10,             # connection deadline; default 10
    data    => $state,         # optional application state
);

Use unix => $path for a filesystem Unix-domain stream socket. Advanced callers may supply a packed sockaddr with its numeric family.

loop is optional. Without it, connect returns a detached object that may later be passed to $loop->add($stream). Writes submitted before readiness use the normal bounded output queue and are delivered in order after the transport becomes usable.

Optional source-side controls include numeric local_host, local_port, and bind_device. Hostname resolution is asynchronous and uses the Loop's private native resolver service.

ADOPTED CONNECTED SOCKETS

new(fh => $socket) adopts an already connected SOCK_STREAM handle. The handle is validated, made nonblocking and close-on-exec, and uses the same established I/O path as an accepted or outbound connection. A TLS-declared class must also specify tls_role for an adopted handle because acquisition cannot infer client versus server role.

CALLBACKS

Callbacks may be methods, constructor coderefs, or a mixture:

my $database = ...;
my $stream = RawConnection->new(
    fh      => $socket,
    on_data => sub ($stream, $bytes) {
        process_bytes($database, $stream, $bytes);
    },
);

A constructor callback overrides the corresponding class method for that object. Supported names 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). connect accepts the same callback options as new.

on_ready($stream) runs once when an outbound or accepted connection becomes application-ready. For TLS that means after handshake and verification, not merely after TCP connect. new(fh => ...) adopts a connection that is already ready and does not emit a later readiness callback.

on_transport_ready($stream) is the lower transport notification used by TLS or another native transport and runs immediately before on_ready. Plain connections have no separate transport phase.

A raw object requires on_data($stream, $bytes) as a method or constructor callback. The public Stream leaf can therefore be constructed directly for raw I/O. A framed class uses Linux::Event::Framer and requires on_message or, with explicit batching, on_messages; either may be supplied by the class or constructor.

Optional lifecycle callbacks include on_drain, on_eof, on_error, on_close, and on_transport_ready for transport-specific observation. Method defaults are resolved into an immutable class descriptor. Constructor input callbacks are retained once in native Stream state, producing one effective cached CV with no event-time lookup or method-versus-coderef branch. Lifecycle callbacks are likewise resolved once during construction. Closing or detaching the Stream releases its retained constructor callbacks.

FRAMING AND OUTPUT

write($bytes) sends raw ordered bytes. send($payload) applies the subclass's native framer. The native write engine attempts immediate output, queues only unsent bytes, enables writable readiness only while necessary, and uses high/low watermarks plus optional max_pending_bytes protection.

pause_read and resume_read control application reads. transition_to changes protocol callback/framing descriptors in place while retaining the live socket, transport, output queue, and unread native input according to the transition rules in docs/FRAMING.md.

SOCKET POLICY

A subclass may define socket_options for acquisition-time socket policy. The method shape and complete option contract appear near the top of this document. See docs/SOCKET-CONFIGURATION.md for application order and failure behavior.

ORDERED-BYTE POLICY AND DEADLINES

stream_options has the complete option contract listed near the top of this document. One explicit operation deadline may also be set or changed at runtime. Established timeout policy begins when the application transport is usable; DNS, connect, TLS handshake, and TLS shutdown retain separate lifecycle deadlines.

TLS

A stream-socket subclass opts into TLS declaratively:

package SecureClient;
use parent 'Linux::Event::IO::Sock::Stream';
use Linux::Event::TLS
    verify => 1,
    alpn   => ['http/1.1'];

Outbound connect selects client mode and derives the default server name from host. A listener that accepts a TLS-declared class selects server mode; that class must declare cert_file and key_file. Framing and callbacks receive plaintext. See Linux::Event::TLS.

ADDRESSES AND LIFECYCLE

local and peer return lazy Linux::Event::Address values when available. fd, fh, state, pending_bytes, and last_error expose connection state without changing ownership.

end drains accepted output then performs the transport's writable half-close. close is immediate and terminal. detach transfers a plain connected socket only when no output is pending; encrypted transports cannot be detached safely.

SEE ALSO

Linux::Event::IO::Sock::Listener, Linux::Event::IO::Sock::Dgram, Linux::Event::Framer, Linux::Event::TLS, docs/SOCKET-CONNECTIONS.md, docs/ORDERED-BYTE-IO-DESIGN.md, docs/FIRST-CLASS-STREAM-CALLBACKS.md.