.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) .\" .\" 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 turned on, 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 .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "POE::Wheel::SocketFactory 3pm" .TH POE::Wheel::SocketFactory 3pm "2014-10-01" "perl v5.20.1" "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" \&\fInew()\fR creates a new POE::Wheel::SocketFactory object. For sockets which \fIlisten()\fR for and \fIaccept()\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 \fIconnect()\fR only emit a single socket and can be destroyed afterwards without ill effects. .PP \&\fInew()\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 \&\fInew()\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 \fIsocket()\fR function. The \&\fInew()\fR parameters beginning with \f(CW\*(C`Socket\*(C'\fR determine how \fIsocket()\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 \fIgetaddrinfo()\fR and \fIunpack_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 \fIsocket()\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 \fIsocket()\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 \fIioctl()\fR, \fIfcntl()\fR and \fIsetsockopt()\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 \fIbind()\fR. POE::Wheel::SocketFactory parameters beginning with \f(CW\*(C`Bind\*(C'\fR control how \fIbind()\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 \fIbind()\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 \fIlisten()\fR for connections or \fIconnect()\fR to remote addresses. .PP This class of sockets is complete after the \fIbind()\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 \fInew()\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 \&\fIconnect()\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 \fIlisten()\fR for connections to these sockets, \fIaccept()\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 \fIlisten()\fR function is called. .PP ListenQueue .IX Subsection "ListenQueue" .PP \&\f(CW\*(C`ListenQueue\*(C'\fR specifies the length of the socket's \fIlisten()\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" \&\fIevent()\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 \&\fIevent()\fR is described in more depth in POE::Wheel. .SS "getsockname" .IX Subsection "getsockname" \&\fIgetsockname()\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 \&\fIgetsockname()\fR allows applications to determine the address and port to which POE::Wheel::SocketFactory has bound its listening socket. .PP Test applications may use \fIgetsockname()\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 \fIgetsockname()\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\fIID\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. \&\fIpause_accept()\fR pauses the event watcher that triggers \fIaccept()\fR. New inbound connections will stack up in the socket's \fIlisten()\fR queue until the queue overflows or the application calls \fIresume_accept()\fR. .PP Pausing \fIaccept()\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 \&\fIpause_accept()\fR and \fIresume_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" \&\fIresume_accept()\fR resumes the watcher that triggers \fIaccept()\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_ntoa\*(R" in Socket if a human-readable IPv4 address is needed. \&\*(L"getnameinfo\*(R" in Socket::GetAddrInfo provides numeric addresses for IPv4 and IPv6 addresses. .PP .Vb 2 \& sub handle_new_client { \& my $accepted_socket = $_[ARG0]; \& \& my $peer_host = inet_ntoa($_[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 \fIaccept()\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.