{
    "content": [
        {
            "type": "text",
            "text": "# POE::Wheel::SocketFactory (perldoc)\n\n## NAME\n\nPOE::Wheel::SocketFactory - non-blocking socket creation\n\n## SYNOPSIS\n\nSee \"SYNOPSIS\" in POE::Component::Server::TCP for a much simpler version of this program.\n#!perl\nuse warnings;\nuse strict;\nuse IO::Socket;\nuse POE qw(Wheel::SocketFactory Wheel::ReadWrite);\nPOE::Session->create(\ninlinestates => {\nstart => sub {\n# Start the server.\n$[HEAP]{server} = POE::Wheel::SocketFactory->new(\nBindPort => 12345,\nSuccessEvent => \"onclientaccept\",\nFailureEvent => \"onservererror\",\n);\n},\nonclientaccept => sub {\n# Begin interacting with the client.\nmy $clientsocket = $[ARG0];\nmy $iowheel = POE::Wheel::ReadWrite->new(\nHandle => $clientsocket,\nInputEvent => \"onclientinput\",\nErrorEvent => \"onclienterror\",\n);\n$[HEAP]{client}{ $iowheel->ID() } = $iowheel;\n},\nonservererror => sub {\n# Shut down server.\nmy ($operation, $errnum, $errstr) = @[ARG0, ARG1, ARG2];\nwarn \"Server $operation error $errnum: $errstr\\n\";\ndelete $[HEAP]{server};\n},\nonclientinput => sub {\n# Handle client input.\nmy ($input, $wheelid) = @[ARG0, ARG1];\n$input =~ tr[a-zA-Z][n-za-mN-ZA-M]; # ASCII rot13\n$[HEAP]{client}{$wheelid}->put($input);\n},\nonclienterror => sub {\n# Handle client error, including disconnect.\nmy $wheelid = $[ARG3];\ndelete $[HEAP]{client}{$wheelid};\n},\n}\n);\nPOE::Kernel->run();\nexit;\n\n## DESCRIPTION\n\nPOE::Wheel::SocketFactory creates sockets upon demand. It can create connectionless UDP sockets,\nbut it really shines for client/server work where establishing connections normally would block.\n\n## Sections\n\n- **NAME**\n- **SYNOPSIS**\n- **DESCRIPTION**\n- **PUBLIC METHODS** (13 subsections)\n- **PUBLIC EVENTS** (2 subsections)\n- **SEE ALSO**\n- **BUGS**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "POE::Wheel::SocketFactory",
        "section": "",
        "mode": "perldoc",
        "summary": "POE::Wheel::SocketFactory - non-blocking socket creation",
        "synopsis": "See \"SYNOPSIS\" in POE::Component::Server::TCP for a much simpler version of this program.\n#!perl\nuse warnings;\nuse strict;\nuse IO::Socket;\nuse POE qw(Wheel::SocketFactory Wheel::ReadWrite);\nPOE::Session->create(\ninlinestates => {\nstart => sub {\n# Start the server.\n$[HEAP]{server} = POE::Wheel::SocketFactory->new(\nBindPort => 12345,\nSuccessEvent => \"onclientaccept\",\nFailureEvent => \"onservererror\",\n);\n},\nonclientaccept => sub {\n# Begin interacting with the client.\nmy $clientsocket = $[ARG0];\nmy $iowheel = POE::Wheel::ReadWrite->new(\nHandle => $clientsocket,\nInputEvent => \"onclientinput\",\nErrorEvent => \"onclienterror\",\n);\n$[HEAP]{client}{ $iowheel->ID() } = $iowheel;\n},\nonservererror => sub {\n# Shut down server.\nmy ($operation, $errnum, $errstr) = @[ARG0, ARG1, ARG2];\nwarn \"Server $operation error $errnum: $errstr\\n\";\ndelete $[HEAP]{server};\n},\nonclientinput => sub {\n# Handle client input.\nmy ($input, $wheelid) = @[ARG0, ARG1];\n$input =~ tr[a-zA-Z][n-za-mN-ZA-M]; # ASCII rot13\n$[HEAP]{client}{$wheelid}->put($input);\n},\nonclienterror => sub {\n# Handle client error, including disconnect.\nmy $wheelid = $[ARG3];\ndelete $[HEAP]{client}{$wheelid};\n},\n}\n);\nPOE::Kernel->run();\nexit;",
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [],
        "see_also": [],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "SYNOPSIS",
                "lines": 53,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "PUBLIC METHODS",
                "lines": 1,
                "subsections": [
                    {
                        "name": "new",
                        "lines": 1
                    },
                    {
                        "name": "accept",
                        "lines": 3
                    },
                    {
                        "name": "new",
                        "lines": 2
                    },
                    {
                        "name": "new",
                        "lines": 72
                    },
                    {
                        "name": "bind",
                        "lines": 43
                    },
                    {
                        "name": "listen",
                        "lines": 29
                    },
                    {
                        "name": "event",
                        "lines": 3
                    },
                    {
                        "name": "event",
                        "lines": 1
                    },
                    {
                        "name": "getsockname",
                        "lines": 2
                    },
                    {
                        "name": "getsockname",
                        "lines": 27
                    },
                    {
                        "name": "listen",
                        "lines": 3
                    },
                    {
                        "name": "pause_accept",
                        "lines": 3
                    },
                    {
                        "name": "resume_accept",
                        "lines": 2
                    }
                ]
            },
            {
                "name": "PUBLIC EVENTS",
                "lines": 2,
                "subsections": [
                    {
                        "name": "SuccessEvent",
                        "lines": 39
                    },
                    {
                        "name": "FailureEvent",
                        "lines": 23
                    }
                ]
            },
            {
                "name": "SEE ALSO",
                "lines": 9,
                "subsections": []
            },
            {
                "name": "BUGS",
                "lines": 9,
                "subsections": []
            }
        ],
        "sections": {
            "NAME": {
                "content": "POE::Wheel::SocketFactory - non-blocking socket creation\n",
                "subsections": []
            },
            "SYNOPSIS": {
                "content": "See \"SYNOPSIS\" in POE::Component::Server::TCP for a much simpler version of this program.\n\n#!perl\n\nuse warnings;\nuse strict;\n\nuse IO::Socket;\nuse POE qw(Wheel::SocketFactory Wheel::ReadWrite);\n\nPOE::Session->create(\ninlinestates => {\nstart => sub {\n# Start the server.\n$[HEAP]{server} = POE::Wheel::SocketFactory->new(\nBindPort => 12345,\nSuccessEvent => \"onclientaccept\",\nFailureEvent => \"onservererror\",\n);\n},\nonclientaccept => sub {\n# Begin interacting with the client.\nmy $clientsocket = $[ARG0];\nmy $iowheel = POE::Wheel::ReadWrite->new(\nHandle => $clientsocket,\nInputEvent => \"onclientinput\",\nErrorEvent => \"onclienterror\",\n);\n$[HEAP]{client}{ $iowheel->ID() } = $iowheel;\n},\nonservererror => sub {\n# Shut down server.\nmy ($operation, $errnum, $errstr) = @[ARG0, ARG1, ARG2];\nwarn \"Server $operation error $errnum: $errstr\\n\";\ndelete $[HEAP]{server};\n},\nonclientinput => sub {\n# Handle client input.\nmy ($input, $wheelid) = @[ARG0, ARG1];\n$input =~ tr[a-zA-Z][n-za-mN-ZA-M]; # ASCII rot13\n$[HEAP]{client}{$wheelid}->put($input);\n},\nonclienterror => sub {\n# Handle client error, including disconnect.\nmy $wheelid = $[ARG3];\ndelete $[HEAP]{client}{$wheelid};\n},\n}\n);\n\nPOE::Kernel->run();\nexit;\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "POE::Wheel::SocketFactory creates sockets upon demand. It can create connectionless UDP sockets,\nbut it really shines for client/server work where establishing connections normally would block.\n",
                "subsections": []
            },
            "PUBLIC METHODS": {
                "content": "new",
                "subsections": [
                    {
                        "name": "new",
                        "content": ""
                    },
                    {
                        "name": "accept",
                        "content": "factories for one-shot sockets, such as UDP peers or clients established by connect() only emit\na single socket and can be destroyed afterwards without ill effects.\n"
                    },
                    {
                        "name": "new",
                        "content": "socket. This allows the object to be queried after it has sent its session a \"FailureEvent\".\n"
                    },
                    {
                        "name": "new",
                        "content": "creation.\n\nCreating the Socket\nSocket creation is done with Perl's built-in socket() function. The new() parameters beginning\nwith \"Socket\" determine how socket() will be called.\n\nSocketDomain\n\"SocketDomain\" instructs the wheel to create a socket within a particular domain. Supported\ndomains are \"AFUNIX\", \"AFINET\", \"AFINET6\", \"PFUNIX\", \"PFINET\", and \"PFINET6\". If omitted,\nthe socket will be created in the \"AFINET\" domain.\n\nPOE::Wheel::SocketFactory contains a table of supported domains and the instructions needed to\ncreate them. Please send patches to support additional domains, as needed.\n\nNote: \"AFINET6\" and \"PFINET6\" are supplied by the Socket module included in Perl 5.8.0 or\nlater. Perl versions before 5.8.0 should not attempt to use IPv6 until someone contributes a\nworkaround.\n\nIPv6 support requires a Socket module that implements getaddrinfo() and unpacksockaddrin6().\nThere may be other modules that perform these functions, but most if not all of them have been\ndeprecated with the advent of proper core Socket support for IPv6.\n\nSocketType\n\"SocketType\" supplies the socket() call with a particular socket type, which may be\n\"SOCKSTREAM\" or \"SOCKDGRAM\". \"SOCKSTREAM\" is the default if \"SocketType\" is not supplied.\n\nSocketProtocol\n\"SocketProtocol\" sets the socket() call's protocol. Protocols may be specified by number or\nname. \"SocketProtocol\" is ignored for UNIX domain sockets.\n\nThe protocol defaults to \"tcp\" for INET domain sockets. There is no default for other socket\ndomains.\n\nSetting Socket Options\nPOE::Wheel::SocketFactory uses ioctl(), fcntl() and setsockopt() to set socket options after the\nsocket is created. All sockets are set non-blocking, and bound sockets may be made reusable.\n\nReuse\nWhen set, the \"Reuse\" parameter allows a bound port to be reused immediately. \"Reuse\" is\nconsidered enabled if it contains \"yes\", \"on\", or a true numeric value. All other values disable\nport reuse, as does omitting \"Reuse\" entirely.\n\nFor security purposes, a port cannot be reused for a minute or more after a server has released\nit. This gives clients time to realize the port has been abandoned. Otherwise a malicious\nservice may snatch up the port and spoof the legitimate service.\n\nIt's also terribly annoying to wait a minute or more between server invocations, especially\nduring development.\n\nBind the Socket to an Address and Port\nA socket may optionally be bound to a specific interface and port. The \"INADDRANY\" address may\nbe used to bind to a specific port across all interfaces.\n\nSockets are bound using bind(). POE::Wheel::SocketFactory parameters beginning with \"Bind\"\ncontrol how bind() is called.\n\nBindAddress\n\"BindAddress\" sets an address to bind the socket's local endpoint to. \"INADDRANY\" will be used\nif \"BindAddress\" is not specified.\n\n\"BindAddress\" may contain either a string or a packed Internet address (for \"INET\" domain\nsockets). The string parameter should be a dotted numeric address or a resolvable host name.\nNote that the host name will be resolved with a blocking call. If this is not desired, use\nPOE::Component::Client::DNS to perform a non-blocking name resolution.\n\nWhen used to bind a \"UNIX\" domain socket, \"BindAddress\" should contain a path describing the\nsocket's filename. This is required for server sockets and datagram client sockets.\n\"BindAddress\" has no default value for UNIX sockets.\n\nBindPort\n\"BindPort\" is only meaningful for \"INET\" domain sockets. It contains a port on the \"BindAddress\"\ninterface where the socket will be bound. It defaults to 0 if omitted, which will cause the"
                    },
                    {
                        "name": "bind",
                        "content": "\"BindPort\" may be a port number or a name that can be looked up in the system's services (or\nequivalent) database.\n\nConnectionless Sockets\nConnectionless sockets may interact with remote endpoints without needing to listen() for\nconnections or connect() to remote addresses.\n\nThis class of sockets is complete after the bind() call.\n\nConnecting the Socket to a Remote Endpoint\nA socket may either listen for connections to arrive, initiate connections to a remote endpoint,\nor be connectionless (such as in the case of UDP sockets).\n\nPOE::Wheel::SocketFactory will initiate a client connection when new() is capped with parameters\nthat describe a remote endpoint. In all other cases, the socket will either listen for\nconnections or be connectionless depending on the socket type.\n\nThe following parameters describe a socket's remote endpoint. They determine how\nPOE::Wheel::SocketFactory will call Perl's built-in connect() function.\n\nRemoteAddress\n\"RemoteAddress\" specifies the remote address to which a socket should connect. If present,\nPOE::Wheel::SocketFactory will create a client socket that attempts to collect to the\n\"RemoteAddress\". Otherwise, if the protocol warrants it, the wheel will create a listening\nsocket and attempt to accept connections.\n\nAs with the bind address, \"RemoteAddress\" may be a string containing a dotted quad or a\nresolvable host name. It may also be a packed Internet address, or a UNIX socket path. It will\nbe packed, with or without an accompanying \"RemotePort\", as necessary for the socket domain.\n\nRemotePort\n\"RemotePort\" is the port to which the socket should connect. It is required for \"INET\" client\nsockets, since the remote endpoint must contain both an address and a port.\n\nThe remote port may be numeric, or it may be a symbolic name found in /etc/services or the\nequivalent for your operating system.\n\nListening for Connections\nStreaming sockets that have no remote endpoint are considered to be server sockets.\nPOE::Wheel::SocketFactory will listen() for connections to these sockets, accept() the new\nclients, and send the application events with the new client sockets.\n\nPOE::Wheel::SocketFactory constructor parameters beginning with \"Listen\" control how the"
                    },
                    {
                        "name": "listen",
                        "content": "ListenQueue\n\"ListenQueue\" specifies the length of the socket's listen() queue. It defaults to \"SOMAXCONN\" if\nomitted. \"ListenQueue\" values greater than \"SOMAXCONN\" will be clipped to \"SOMAXCONN\".\nExcessively large \"ListenQueue\" values are not necessarily portable, and may cause errors in\nsome rare cases.\n\nEmitting Events\nPOE::Wheel::SocketFactory emits a small number of events depending on what happens during socket\nsetup or while listening for new connections.\n\nSee \"PUBLIC EVENTS\" for more details.\n\nSuccessEvent\n\"SuccessEvent\" names the event that will be emitted whenever POE::Wheel::SocketFactory succeeds\nin creating a new socket.\n\nFor connectionless sockets, \"SuccessEvent\" happens just after the socket is created.\n\nFor client connections, \"SuccessEvent\" is fired when the connection has successfully been\nestablished with the remote endpoint.\n\nServer sockets emit a \"SuccessEvent\" for every successfully accepted client.\n\nFailureEvent\n\"FailureEvent\" names the event POE::Wheel::SocketFactory will emit whenever something goes\nwrong. It usually represents some kind of built-in function call error. See \"PUBLIC EVENTS\" for\ndetails, as some errors are handled internally by this wheel.\n\nevent"
                    },
                    {
                        "name": "event",
                        "content": "re-creating the wheel. It accepts one or more of the events listed in \"PUBLIC EVENTS\". Undefined\nevent names disable those events.\n"
                    },
                    {
                        "name": "event",
                        "content": "getsockname"
                    },
                    {
                        "name": "getsockname",
                        "content": "information for POE::Wheel::SocketFactory's encapsulated listening socket.\n"
                    },
                    {
                        "name": "getsockname",
                        "content": "POE::Wheel::SocketFactory has bound its listening socket.\n\nTest applications may use getsockname() to find the server socket after\nPOE::Wheel::SocketFactory has bound to INADDRANY port 0.\n\nSince there is no event fired immediately after a successful creation of a listening socket,\napplications can use getsockname() to verify this.\n\nuse Socket 'unpacksockaddrin';\n\nmy $listener = POE::Wheel::SocketFactory->new(\nBindPort     => 123,\nSuccessEvent => 'gotclient',\nFailureEvent => 'listenerfailed',\nReuse        => 'on',\n);\n\nmy ($port, $addr) = unpacksockaddrin($listener->getsockname);\nprint \"Socket successfully bound\\n\" if $port;\n\nID\nID() returns the wheel's unique ID. The ID will also be included in every event the wheel\ngenerates. Applications can match events back to the objects that generated them.\n\npauseaccept\nApplications may occasionally need to block incoming connections. pauseaccept() pauses the\nevent watcher that triggers accept(). New inbound connections will stack up in the socket's"
                    },
                    {
                        "name": "listen",
                        "content": "Pausing accept() can limit the amount of load a server generates. It's also useful in\npre-forking servers when the master process shouldn't accept connections at all.\n"
                    },
                    {
                        "name": "pause_accept",
                        "content": "re-creating a POE::Wheel::SocketFactory object.\n\nresumeaccept"
                    },
                    {
                        "name": "resume_accept",
                        "content": "detailed discussion.\n"
                    }
                ]
            },
            "PUBLIC EVENTS": {
                "content": "POE::Wheel::SocketFactory emits two public events.\n",
                "subsections": [
                    {
                        "name": "SuccessEvent",
                        "content": "\"SuccessEvent\" names an event that will be sent to the creating session whenever a\nPOE::Wheel::SocketFactory has created a new socket. For connectionless sockets, it's when the\nsocket is created. For connecting clients, it's after the connection has been established. And\nfor listening servers, \"SuccessEvent\" is fired after each new client is accepted.\n\nCommon SuccessEvent Parameters\nIn all cases, $[ARG0] holds the new socket's filehandle, and $[ARG3] contains the\nPOE::Wheel::SocketFactory's ID. Other parameters vary depending on the socket's domain and\nwhether it's listening or connecting. See below for the differences.\n\nINET SuccessEvent Parameters\nFor INET sockets, $[ARG1] and $[ARG2] hold the socket's remote address and port, respectively.\nThe address is packed; see \"inetntop\" in Socket if a human-readable address is needed.\n\nsub handlenewclient {\nmy $acceptedsocket = $[ARG0];\n\nmy $peerhost = inetntop(\n((length($[ARG1]) == 4) ? AFINET : AFINET6),\n$[ARG1]\n);\n\nprint(\n\"Wheel $[ARG3] accepted a connection from \",\n\"$peerhost port $peerport\\n\"\n);\n\nspawnconnectionsession($acceptedhandle);\n}\n\nUNIX Client SuccessEvent Parameters\nFor UNIX client sockets, $[ARG1] often (but not always) holds the server address. Some systems\ncannot retrieve a UNIX socket's remote address. $[ARG2] is always undef for UNIX client\nsockets.\n\nUNIX Server SuccessEvent Parameters\nAccording to *Perl Cookbook*, the remote address returned by accept() on UNIX sockets is\nundefined, so $[ARG1] and $[ARG2] are also undefined in this case.\n"
                    },
                    {
                        "name": "FailureEvent",
                        "content": "\"FailureEvent\" names the event that will be emitted when a socket error occurs.\nPOE::Wheel::SocketFactory handles \"EAGAIN\" internally, so it doesn't count as an error.\n\n\"FailureEvent\" events include the standard error event parameters:\n\n$[ARG0] describes which part of socket creation failed. It often holds a Perl built-in function\nname.\n\n$[ARG1] and $[ARG2] describe how the operation failed. They contain the numeric and\nstringified versions of $!, respectively. An application cannot merely check the global $!\nvariable since it may change during event dispatch.\n\nFinally, $[ARG3] contains the ID for the POE::Wheel::SocketFactory instance that generated the\nevent. See \"ID\" and \"ID\" in POE::Wheel for uses for wheel IDs.\n\nA sample FailureEvent handler:\n\nsub handlefailure {\nmy ($operation, $errnum, $errstr, $wheelid) = @[ARG0..ARG3];\nwarn \"Wheel $wheelid generated $operation error $errnum: $errstr\\n\";\ndelete $[HEAP]{wheels}{$wheelid}; # shut down that wheel\n}\n"
                    }
                ]
            },
            "SEE ALSO": {
                "content": "POE::Wheel describes the basic operations of all wheels in more depth. You need to know this.\n\nSocket::GetAddrInfo is required for IPv6 work. POE::Wheel::SocketFactory will load it\nautomatically if it's installed. SocketDomain => AFINET6 is required to trigger IPv6 behaviors.\nAFINET6 is exported by the Socket module on all but the oldest versions of Perl 5. If your\nSocket doesn't provide AFINET6, try installing Socket6 instead.\n\nThe SEE ALSO section in POE contains a table of contents covering the entire POE distribution.\n",
                "subsections": []
            },
            "BUGS": {
                "content": "Many (if not all) of the croak/carp/warn/die statements should fire back \"FailureEvent\" instead.\n\nSocketFactory is only tested with UNIX streams and INET sockets using the UDP and TCP protocols.\nOthers should work after the module's internal configuration tables are updated. Please send\npatches.\n\nAUTHORS & COPYRIGHTS\nPlease see POE for more information about authors and contributors.\n",
                "subsections": []
            }
        }
    }
}