Current File : //usr/local/share/man/man3/POE::Wheel::SocketFactory.3pm
.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings.  \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
.    ds -- \(*W-
.    ds PI pi
.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
.    ds L" ""
.    ds R" ""
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds -- \|\(em\|
.    ds PI \(*p
.    ds L" ``
.    ds R" ''
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
.    if \nF \{\
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{\
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\" ========================================================================
.\"
.IX Title "POE::Wheel::SocketFactory 3"
.TH POE::Wheel::SocketFactory 3 "2022-03-23" "perl v5.26.3" "User Contributed Perl Documentation"
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
POE::Wheel::SocketFactory \- non\-blocking socket creation
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
See \*(L"\s-1SYNOPSIS\*(R"\s0 in POE::Component::Server::TCP for a much simpler version
of this program.
.PP
.Vb 1
\&  #!perl
\&
\&  use warnings;
\&  use strict;
\&
\&  use IO::Socket;
\&  use POE qw(Wheel::SocketFactory Wheel::ReadWrite);
\&
\&  POE::Session\->create(
\&    inline_states => {
\&      _start => sub {
\&        # Start the server.
\&        $_[HEAP]{server} = POE::Wheel::SocketFactory\->new(
\&          BindPort => 12345,
\&          SuccessEvent => "on_client_accept",
\&          FailureEvent => "on_server_error",
\&        );
\&      },
\&      on_client_accept => sub {
\&        # Begin interacting with the client.
\&        my $client_socket = $_[ARG0];
\&        my $io_wheel = POE::Wheel::ReadWrite\->new(
\&          Handle => $client_socket,
\&          InputEvent => "on_client_input",
\&          ErrorEvent => "on_client_error",
\&        );
\&        $_[HEAP]{client}{ $io_wheel\->ID() } = $io_wheel;
\&      },
\&      on_server_error => sub {
\&        # Shut down server.
\&        my ($operation, $errnum, $errstr) = @_[ARG0, ARG1, ARG2];
\&        warn "Server $operation error $errnum: $errstr\en";
\&        delete $_[HEAP]{server};
\&      },
\&      on_client_input => sub {
\&        # Handle client input.
\&        my ($input, $wheel_id) = @_[ARG0, ARG1];
\&        $input =~ tr[a\-zA\-Z][n\-za\-mN\-ZA\-M]; # ASCII rot13
\&        $_[HEAP]{client}{$wheel_id}\->put($input);
\&      },
\&      on_client_error => sub {
\&        # Handle client error, including disconnect.
\&        my $wheel_id = $_[ARG3];
\&        delete $_[HEAP]{client}{$wheel_id};
\&      },
\&    }
\&  );
\&
\&  POE::Kernel\->run();
\&  exit;
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
POE::Wheel::SocketFactory creates sockets upon demand.  It can create
connectionless \s-1UDP\s0 sockets, but it really shines for client/server
work where establishing connections normally would block.
.SH "PUBLIC METHODS"
.IX Header "PUBLIC METHODS"
.SS "new"
.IX Subsection "new"
\&\fBnew()\fR creates a new POE::Wheel::SocketFactory object.  For sockets
which \fBlisten()\fR for and \fBaccept()\fR connections, the wheel will generate
new sockets for each accepted client.  Socket factories for one-shot
sockets, such as \s-1UDP\s0 peers or clients established by \fBconnect()\fR only
emit a single socket and can be destroyed afterwards without ill
effects.
.PP
\&\fBnew()\fR always returns a POE::Wheel::SocketFactory object even if it
fails to establish the socket.  This allows the object to be queried
after it has sent its session a \f(CW\*(C`FailureEvent\*(C'\fR.
.PP
\&\fBnew()\fR accepts a healthy number of named parameters, each governing
some aspect of socket creation.
.PP
\fICreating the Socket\fR
.IX Subsection "Creating the Socket"
.PP
Socket creation is done with Perl's built-in \fBsocket()\fR function.  The
\&\fBnew()\fR parameters beginning with \f(CW\*(C`Socket\*(C'\fR determine how \fBsocket()\fR will
be called.
.PP
SocketDomain
.IX Subsection "SocketDomain"
.PP
\&\f(CW\*(C`SocketDomain\*(C'\fR instructs the wheel to create a socket within a
particular domain.  Supported domains are \f(CW\*(C`AF_UNIX\*(C'\fR, \f(CW\*(C`AF_INET\*(C'\fR,
\&\f(CW\*(C`AF_INET6\*(C'\fR, \f(CW\*(C`PF_UNIX\*(C'\fR, \f(CW\*(C`PF_INET\*(C'\fR, and \f(CW\*(C`PF_INET6\*(C'\fR.  If omitted, the
socket will be created in the \f(CW\*(C`AF_INET\*(C'\fR domain.
.PP
POE::Wheel::SocketFactory contains a table of supported domains and
the instructions needed to create them.  Please send patches to
support additional domains, as needed.
.PP
Note: \f(CW\*(C`AF_INET6\*(C'\fR and \f(CW\*(C`PF_INET6\*(C'\fR are supplied by the Socket
module included in Perl 5.8.0 or later.  Perl versions before 5.8.0
should not attempt to use IPv6 until someone contributes a workaround.
.PP
IPv6 support requires a Socket module that implements \fBgetaddrinfo()\fR
and \fBunpack_sockaddr_in6()\fR.  There may be other modules that perform
these functions, but most if not all of them have been deprecated with
the advent of proper core Socket support for IPv6.
.PP
SocketType
.IX Subsection "SocketType"
.PP
\&\f(CW\*(C`SocketType\*(C'\fR supplies the \fBsocket()\fR call with a particular socket
type, which may be \f(CW\*(C`SOCK_STREAM\*(C'\fR or \f(CW\*(C`SOCK_DGRAM\*(C'\fR.  \f(CW\*(C`SOCK_STREAM\*(C'\fR is
the default if \f(CW\*(C`SocketType\*(C'\fR is not supplied.
.PP
SocketProtocol
.IX Subsection "SocketProtocol"
.PP
\&\f(CW\*(C`SocketProtocol\*(C'\fR sets the \fBsocket()\fR call's protocol.  Protocols may be
specified by number or name.  \f(CW\*(C`SocketProtocol\*(C'\fR is ignored for \s-1UNIX\s0
domain sockets.
.PP
The protocol defaults to \*(L"tcp\*(R" for \s-1INET\s0 domain sockets.  There is no
default for other socket domains.
.PP
\fISetting Socket Options\fR
.IX Subsection "Setting Socket Options"
.PP
POE::Wheel::SocketFactory uses \fBioctl()\fR, \fBfcntl()\fR and \fBsetsockopt()\fR to
set socket options after the socket is created.  All sockets are set
non-blocking, and bound sockets may be made reusable.
.PP
Reuse
.IX Subsection "Reuse"
.PP
When set, the \f(CW\*(C`Reuse\*(C'\fR parameter allows a bound port to be reused
immediately.  \f(CW\*(C`Reuse\*(C'\fR is considered enabled if it contains \*(L"yes\*(R",
\&\*(L"on\*(R", or a true numeric value.  All other values disable port reuse,
as does omitting \f(CW\*(C`Reuse\*(C'\fR entirely.
.PP
For security purposes, a port cannot be reused for a minute or more
after a server has released it.  This gives clients time to realize
the port has been abandoned.  Otherwise a malicious service may snatch
up the port and spoof the legitimate service.
.PP
It's also terribly annoying to wait a minute or more between server
invocations, especially during development.
.PP
\fIBind the Socket to an Address and Port\fR
.IX Subsection "Bind the Socket to an Address and Port"
.PP
A socket may optionally be bound to a specific interface and port.
The \f(CW\*(C`INADDR_ANY\*(C'\fR address may be used to bind to a specific port
across all interfaces.
.PP
Sockets are bound using \fBbind()\fR.  POE::Wheel::SocketFactory parameters
beginning with \f(CW\*(C`Bind\*(C'\fR control how \fBbind()\fR is called.
.PP
BindAddress
.IX Subsection "BindAddress"
.PP
\&\f(CW\*(C`BindAddress\*(C'\fR sets an address to bind the socket's local endpoint to.
\&\f(CW\*(C`INADDR_ANY\*(C'\fR will be used if \f(CW\*(C`BindAddress\*(C'\fR is not specified.
.PP
\&\f(CW\*(C`BindAddress\*(C'\fR may contain either a string or a packed Internet
address (for \*(L"\s-1INET\*(R"\s0 domain sockets).  The string parameter should be a
dotted numeric address or a resolvable host name.  Note that the host
name will be resolved with a blocking call.  If this is not desired,
use POE::Component::Client::DNS to perform a non-blocking name
resolution.
.PP
When used to bind a \*(L"\s-1UNIX\*(R"\s0 domain socket, \f(CW\*(C`BindAddress\*(C'\fR should
contain a path describing the socket's filename.  This is required for
server sockets and datagram client sockets.  \f(CW\*(C`BindAddress\*(C'\fR has no
default value for \s-1UNIX\s0 sockets.
.PP
BindPort
.IX Subsection "BindPort"
.PP
\&\f(CW\*(C`BindPort\*(C'\fR is only meaningful for \*(L"\s-1INET\*(R"\s0 domain sockets.  It contains
a port on the \f(CW\*(C`BindAddress\*(C'\fR interface where the socket will be bound.
It defaults to 0 if omitted, which will cause the \fBbind()\fR call to
choose an indeterminate unallocated port.
.PP
\&\f(CW\*(C`BindPort\*(C'\fR may be a port number or a name that can be looked up in
the system's services (or equivalent) database.
.PP
\fIConnectionless Sockets\fR
.IX Subsection "Connectionless Sockets"
.PP
Connectionless sockets may interact with remote endpoints without
needing to \fBlisten()\fR for connections or \fBconnect()\fR to remote addresses.
.PP
This class of sockets is complete after the \fBbind()\fR call.
.PP
\fIConnecting the Socket to a Remote Endpoint\fR
.IX Subsection "Connecting the Socket to a Remote Endpoint"
.PP
A socket may either listen for connections to arrive, initiate
connections to a remote endpoint, or be connectionless (such as in the
case of \s-1UDP\s0 sockets).
.PP
POE::Wheel::SocketFactory will initiate a client connection when \fBnew()\fR
is capped with parameters that describe a remote endpoint.  In all
other cases, the socket will either listen for connections or be
connectionless depending on the socket type.
.PP
The following parameters describe a socket's remote endpoint.  They
determine how POE::Wheel::SocketFactory will call Perl's built-in
\&\fBconnect()\fR function.
.PP
RemoteAddress
.IX Subsection "RemoteAddress"
.PP
\&\f(CW\*(C`RemoteAddress\*(C'\fR specifies the remote address to which a socket should
connect.  If present, POE::Wheel::SocketFactory will create a client
socket that attempts to collect to the \f(CW\*(C`RemoteAddress\*(C'\fR.  Otherwise,
if the protocol warrants it, the wheel will create a listening socket
and attempt to accept connections.
.PP
As with the bind address, \f(CW\*(C`RemoteAddress\*(C'\fR may be a string containing
a dotted quad or a resolvable host name.  It may also be a packed
Internet address, or a \s-1UNIX\s0 socket path.  It will be packed, with or
without an accompanying \f(CW\*(C`RemotePort\*(C'\fR, as necessary for the socket
domain.
.PP
RemotePort
.IX Subsection "RemotePort"
.PP
\&\f(CW\*(C`RemotePort\*(C'\fR is the port to which the socket should connect.  It is
required for \*(L"\s-1INET\*(R"\s0 client sockets, since the remote endpoint must
contain both an address and a port.
.PP
The remote port may be numeric, or it may be a symbolic name found in
/etc/services or the equivalent for your operating system.
.PP
\fIListening for Connections\fR
.IX Subsection "Listening for Connections"
.PP
Streaming sockets that have no remote endpoint are considered to be
server sockets.  POE::Wheel::SocketFactory will \fBlisten()\fR for
connections to these sockets, \fBaccept()\fR the new clients, and send the
application events with the new client sockets.
.PP
POE::Wheel::SocketFactory constructor parameters beginning with
\&\f(CW\*(C`Listen\*(C'\fR control how the \fBlisten()\fR function is called.
.PP
ListenQueue
.IX Subsection "ListenQueue"
.PP
\&\f(CW\*(C`ListenQueue\*(C'\fR specifies the length of the socket's \fBlisten()\fR queue.
It defaults to \f(CW\*(C`SOMAXCONN\*(C'\fR if omitted.  \f(CW\*(C`ListenQueue\*(C'\fR values greater
than \f(CW\*(C`SOMAXCONN\*(C'\fR will be clipped to \f(CW\*(C`SOMAXCONN\*(C'\fR.  Excessively large
\&\f(CW\*(C`ListenQueue\*(C'\fR values are not necessarily portable, and may cause
errors in some rare cases.
.PP
\fIEmitting Events\fR
.IX Subsection "Emitting Events"
.PP
POE::Wheel::SocketFactory emits a small number of events depending on
what happens during socket setup or while listening for new
connections.
.PP
See \*(L"\s-1PUBLIC EVENTS\*(R"\s0 for more details.
.PP
SuccessEvent
.IX Subsection "SuccessEvent"
.PP
\&\f(CW\*(C`SuccessEvent\*(C'\fR names the event that will be emitted whenever
POE::Wheel::SocketFactory succeeds in creating a new socket.
.PP
For connectionless sockets, \f(CW\*(C`SuccessEvent\*(C'\fR happens just after the
socket is created.
.PP
For client connections, \f(CW\*(C`SuccessEvent\*(C'\fR is fired when the connection
has successfully been established with the remote endpoint.
.PP
Server sockets emit a \f(CW\*(C`SuccessEvent\*(C'\fR for every successfully accepted
client.
.PP
FailureEvent
.IX Subsection "FailureEvent"
.PP
\&\f(CW\*(C`FailureEvent\*(C'\fR names the event POE::Wheel::SocketFactory will emit
whenever something goes wrong.  It usually represents some kind of
built-in function call error.  See \*(L"\s-1PUBLIC EVENTS\*(R"\s0 for details, as
some errors are handled internally by this wheel.
.SS "event"
.IX Subsection "event"
\&\fBevent()\fR allows a session to change the events emitted by a wheel
without destroying and re-creating the wheel.  It accepts one or more
of the events listed in \*(L"\s-1PUBLIC EVENTS\*(R"\s0.  Undefined event names
disable those events.
.PP
\&\fBevent()\fR is described in more depth in POE::Wheel.
.SS "getsockname"
.IX Subsection "getsockname"
\&\fBgetsockname()\fR behaves like the built-in function of the same name.  It
returns the local endpoint information for POE::Wheel::SocketFactory's
encapsulated listening socket.
.PP
\&\fBgetsockname()\fR allows applications to determine the address and port
to which POE::Wheel::SocketFactory has bound its listening socket.
.PP
Test applications may use \fBgetsockname()\fR to find the server socket
after POE::Wheel::SocketFactory has bound to \s-1INADDR_ANY\s0 port 0.
.PP
Since there is no event fired immediately after a successful creation of a
listening socket, applications can use \fBgetsockname()\fR to verify this.
.PP
.Vb 1
\& use Socket \*(Aqunpack_sockaddr_in\*(Aq;
\&
\& my $listener = POE::Wheel::SocketFactory\->new(
\&     BindPort     => 123,
\&     SuccessEvent => \*(Aqgot_client\*(Aq,
\&     FailureEvent => \*(Aqlistener_failed\*(Aq,
\&     Reuse        => \*(Aqon\*(Aq,
\& );
\&
\& my ($port, $addr) = unpack_sockaddr_in($listener\->getsockname);
\& print "Socket successfully bound\en" if $port;
.Ve
.SS "\s-1ID\s0"
.IX Subsection "ID"
\&\s-1\fBID\s0()\fR returns the wheel's unique \s-1ID.\s0  The \s-1ID\s0 will also be included in
every event the wheel generates.  Applications can match events back
to the objects that generated them.
.SS "pause_accept"
.IX Subsection "pause_accept"
Applications may occasionally need to block incoming connections.
\&\fBpause_accept()\fR pauses the event watcher that triggers \fBaccept()\fR.  New
inbound connections will stack up in the socket's \fBlisten()\fR queue until
the queue overflows or the application calls \fBresume_accept()\fR.
.PP
Pausing \fBaccept()\fR can limit the amount of load a server generates.
It's also useful in pre-forking servers when the master process
shouldn't accept connections at all.
.PP
\&\fBpause_accept()\fR and \fBresume_accept()\fR is quicker and more reliable than
dynamically destroying and re-creating a POE::Wheel::SocketFactory
object.
.SS "resume_accept"
.IX Subsection "resume_accept"
\&\fBresume_accept()\fR resumes the watcher that triggers \fBaccept()\fR.  See
\&\*(L"pause_accept\*(R" for a more detailed discussion.
.SH "PUBLIC EVENTS"
.IX Header "PUBLIC EVENTS"
POE::Wheel::SocketFactory emits two public events.
.SS "SuccessEvent"
.IX Subsection "SuccessEvent"
\&\f(CW\*(C`SuccessEvent\*(C'\fR names an event that will be sent to the creating
session whenever a POE::Wheel::SocketFactory has created a new socket.
For connectionless sockets, it's when the socket is created.  For
connecting clients, it's after the connection has been established.
And for listening servers, \f(CW\*(C`SuccessEvent\*(C'\fR is fired after each new
client is accepted.
.PP
\fICommon SuccessEvent Parameters\fR
.IX Subsection "Common SuccessEvent Parameters"
.PP
In all cases, \f(CW$_[ARG0]\fR holds the new socket's filehandle, and
\&\f(CW$_[ARG3]\fR contains the POE::Wheel::SocketFactory's \s-1ID.\s0  Other
parameters vary depending on the socket's domain and whether it's
listening or connecting.  See below for the differences.
.PP
\fI\s-1INET\s0 SuccessEvent Parameters\fR
.IX Subsection "INET SuccessEvent Parameters"
.PP
For \s-1INET\s0 sockets, \f(CW$_[ARG1]\fR and \f(CW$_[ARG2]\fR hold the socket's remote
address and port, respectively.  The address is packed; see
\&\*(L"inet_ntop\*(R" in Socket if a human-readable address is needed.
.PP
.Vb 2
\&  sub handle_new_client {
\&    my $accepted_socket = $_[ARG0];
\&
\&    my $peer_host = inet_ntop(
\&      ((length($_[ARG1]) == 4) ? AF_INET : AF_INET6),
\&      $_[ARG1]
\&    );
\&
\&    print(
\&      "Wheel $_[ARG3] accepted a connection from ",
\&      "$peer_host port $peer_port\en"
\&    );
\&
\&    spawn_connection_session($accepted_handle);
\&  }
.Ve
.PP
\fI\s-1UNIX\s0 Client SuccessEvent Parameters\fR
.IX Subsection "UNIX Client SuccessEvent Parameters"
.PP
For \s-1UNIX\s0 client sockets, \f(CW$_[ARG1]\fR often (but not always) holds the
server address.  Some systems cannot retrieve a \s-1UNIX\s0 socket's remote
address.  \f(CW$_[ARG2]\fR is always undef for \s-1UNIX\s0 client sockets.
.PP
\fI\s-1UNIX\s0 Server SuccessEvent Parameters\fR
.IX Subsection "UNIX Server SuccessEvent Parameters"
.PP
According to \fIPerl Cookbook\fR, the remote address returned by \fBaccept()\fR
on \s-1UNIX\s0 sockets is undefined, so \f(CW$_[ARG1]\fR and \f(CW$_[ARG2]\fR are also
undefined in this case.
.SS "FailureEvent"
.IX Subsection "FailureEvent"
\&\f(CW\*(C`FailureEvent\*(C'\fR names the event that will be emitted when a socket
error occurs.  POE::Wheel::SocketFactory handles \f(CW\*(C`EAGAIN\*(C'\fR internally,
so it doesn't count as an error.
.PP
\&\f(CW\*(C`FailureEvent\*(C'\fR events include the standard error event parameters:
.PP
\&\f(CW$_[ARG0]\fR describes which part of socket creation failed.  It often
holds a Perl built-in function name.
.PP
\&\f(CW$_[ARG1]\fR and \f(CW$_[ARG2]\fR describe how the operation failed.  They
contain the numeric and stringified versions of \f(CW$!\fR, respectively.
An application cannot merely check the global \f(CW$!\fR variable since it
may change during event dispatch.
.PP
Finally, \f(CW$_[ARG3]\fR contains the \s-1ID\s0 for the POE::Wheel::SocketFactory
instance that generated the event.  See \*(L"\s-1ID\*(R"\s0 and \*(L"\s-1ID\*(R"\s0 in POE::Wheel
for uses for wheel IDs.
.PP
A sample FailureEvent handler:
.PP
.Vb 5
\&  sub handle_failure {
\&    my ($operation, $errnum, $errstr, $wheel_id) = @_[ARG0..ARG3];
\&    warn "Wheel $wheel_id generated $operation error $errnum: $errstr\en";
\&    delete $_[HEAP]{wheels}{$wheel_id}; # shut down that wheel
\&  }
.Ve
.SH "SEE ALSO"
.IX Header "SEE ALSO"
POE::Wheel describes the basic operations of all wheels in more
depth.  You need to know this.
.PP
Socket::GetAddrInfo is required for IPv6 work.
POE::Wheel::SocketFactory will load it automatically if it's
installed.  SocketDomain => \s-1AF_INET6\s0 is required to trigger IPv6
behaviors.  \s-1AF_INET6\s0 is exported by the Socket module on all but the
oldest versions of Perl 5.  If your Socket doesn't provide \s-1AF_INET6,\s0
try installing Socket6 instead.
.PP
The \s-1SEE ALSO\s0 section in \s-1POE\s0 contains a table of contents covering
the entire \s-1POE\s0 distribution.
.SH "BUGS"
.IX Header "BUGS"
Many (if not all) of the croak/carp/warn/die statements should fire
back \f(CW\*(C`FailureEvent\*(C'\fR instead.
.PP
SocketFactory is only tested with \s-1UNIX\s0 streams and \s-1INET\s0 sockets using
the \s-1UDP\s0 and \s-1TCP\s0 protocols.  Others should work after the module's
internal configuration tables are updated.  Please send patches.
.SH "AUTHORS & COPYRIGHTS"
.IX Header "AUTHORS & COPYRIGHTS"
Please see \s-1POE\s0 for more information about authors and contributors.