# NAME POEx::IRC::Backend - IRC client or server backend # SYNOPSIS use POE; use POEx::IRC::Backend; POE::Session->create( package_states => [ main => [ qw/ _start ircsock_registered ircsock_input / ], ], ); sub _start { # Spawn a Backend and register as the controlling session: my $backend = POEx::IRC::Backend->spawn; $_[HEAP]->{backend} = $backend; $_[KERNEL]->post( $backend->session_id, 'register' ); } sub ircsock_registered { my $backend = $_[HEAP]->{backend}; # Listen for incoming IRC traffic: $backend->create_listener( bindaddr => $addr, port => $port, ); # Connect to a remote endpoint: $backend->create_connector( remoteaddr => $remote, remoteport => $remoteport, # Optional: bindaddr => $bindaddr, ipv6 => 1, ssl => 1, ); } # Handle and dispatch incoming IRC events: sub ircsock_input { # POEx::IRC::Backend::Connect obj: my $this_conn = $_[ARG0]; # IRC::Message::Object obj: my $input_obj = $_[ARG1]; my $cmd = $input_obj->command; # ... dispatch, etc ... } # DESCRIPTION A [POE](https://metacpan.org/pod/POE) IRC socket handler that can be used (by client or server implementations) to speak the IRC protocol to endpoints via [IRC::Message::Object](https://metacpan.org/pod/IRC::Message::Object) objects. Inspired by [POE::Component::Server::IRC::Backend](https://metacpan.org/pod/POE::Component::Server::IRC::Backend) & [POE::Component::IRC](https://metacpan.org/pod/POE::Component::IRC). This is a very low-level interface to IRC sockets; the goal is to provide all the necessary scaffolding to develop stateless or stateful IRC clients and daemons. See [POEx::IRC::Client::Lite](https://metacpan.org/pod/POEx::IRC::Client::Lite) for an experimental IRC client library using this backend (and the ["SEE ALSO"](#see-also) section of this documentation for related tools). ## Attributes ### controller Retrieve the [POE::Session](https://metacpan.org/pod/POE::Session) ID for the backend's registered controller. Predicate: **has\_controller** ### connectors A HASH of active Connector objects, keyed on their wheel ID. ### filter A [POE::Filter::Stackable](https://metacpan.org/pod/POE::Filter::Stackable) instance consisting of the current ["filter\_irc"](#filter_irc) stacked with ["filter\_line"](#filter_line) (at the time the attribute is built). ### filter\_irc A [POE::Filter::IRCv3](https://metacpan.org/pod/POE::Filter::IRCv3) instance with **colonify** disabled, by default (this behavior changed in v0.27.2). A server-side Backend may want a colonifying filter: my $backend = POEx::IRC::Backend->new( filter_irc => POE::Filter::IRCv3->new(colonify => 1), ... ); ### filter\_line A [POE::Filter::Line](https://metacpan.org/pod/POE::Filter::Line) instance. ### listeners HASH of active Listener objects, keyed on their wheel ID. ### session\_id Returns the backend's session ID. ### ssl\_context Returns the [Net::SSLeay](https://metacpan.org/pod/Net::SSLeay) Context object, if we have one (or `undef` if not); the context is set up by ["spawn"](#spawn) if `ssl_opts` are specified. ### wheels HASH of actively connected wheels, keyed on their wheel ID. ## Methods ### spawn my $backend = POEx::IRC::Backend->spawn( ## Optional, needed for SSL-ified server-side sockets ssl_opts => [ 'server.key', 'server.cert', ], ); Creates the backend's [POE::Session](https://metacpan.org/pod/POE::Session). The `ssl_opts` ARRAY is passed directly to ["SSLify\_ContextCreate" in POE::Component::SSLify](https://metacpan.org/pod/POE::Component::SSLify#SSLify_ContextCreate), if present. As of `v0.28.x`, each Backend gets its own [Net::SSLeay](https://metacpan.org/pod/Net::SSLeay) context object (rather than sharing the global context). See [POE::Component::SSLify](https://metacpan.org/pod/POE::Component::SSLify) & [Net::SSLeay](https://metacpan.org/pod/Net::SSLeay). ### create\_connector $backend->create_connector( remoteaddr => $addr, remoteport => $addr, ## Optional: bindaddr => $local_addr, ipv6 => 1, ssl => 1, ## Unrecognized opts are stored in the Connector's 'args' hash: tag => 'foo', ); Attempts to create a [POEx::IRC::Backend::Connector](https://metacpan.org/pod/POEx::IRC::Backend::Connector) that holds a [POE::Wheel::SocketFactory](https://metacpan.org/pod/POE::Wheel::SocketFactory) connector wheel; connectors will attempt to establish an outgoing connection immediately. Unrecognized options are stored in the [POEx::IRC::Backend::Connector](https://metacpan.org/pod/POEx::IRC::Backend::Connector)'s `args` HASH-type attribute; this is passed to successfully created [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) instances (as of `v0.26.x`). Note that the reference is shared, not copied. ### create\_listener $backend->create_listener( bindaddr => $addr, port => $port, ## Optional: ipv6 => 1, ssl => 1, idle => $seconds, ); Attempts to create a [POEx::IRC::Backend::Listener](https://metacpan.org/pod/POEx::IRC::Backend::Listener) that holds a [POE::Wheel::SocketFactory](https://metacpan.org/pod/POE::Wheel::SocketFactory) listener wheel. Unrecognized arguments will be added to the Listener object's `args` attribute, which is then passed on to [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) objects created by incoming connections to that listener, similar to the behavior described in ["create\_connector"](#create_connector) (as of `v0.28.x`). ### remove\_listener $backend->remove_listener( listener => $listener_id, ); ## or via addr, port, or combination thereof: $backend->remove_listener( addr => '127.0.0.1', port => 6667, ); Removes a listener and clears its **wheel** attribute; the socket shuts down when the [POE::Wheel::SocketFactory](https://metacpan.org/pod/POE::Wheel::SocketFactory) wheel goes out of scope. ### disconnect $backend->disconnect($wheel_id, $disconnect_string); Given a [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) or its `wheel_id`, mark the specified wheel for disconnection. This method will warn if the given `wheel_id` cannot be found, which may be due to the connection disappearing prior to calling `disconnect`. You can avoid spurious warnings by checking if the [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) still has an active wheel attached: if ($this_conn->has_wheel) { $backend->disconnect( $this_conn ) } Note that disconnection happens after a buffer flush; if your software does not perform entirely like a traditional platform (server implementations will typically send `ERROR: Closing Link` or similar to clients marked for disconnection, which will trigger a buffer flush) you may currently experience "late" disconnects. This behavior may be subject to change in future versions. ### send $backend->send( { prefix => $prefix, params => [ @params ], command => $cmd, }, @connect_ids ); use IRC::Message::Object 'ircmsg'; my $msg = ircmsg( command => 'PRIVMSG', params => [ $chan, $string ], ); $backend->send( $msg, $connect_obj ); Feeds [POE::Filter::IRCv3](https://metacpan.org/pod/POE::Filter::IRCv3) and sends the resultant raw IRC line to the specified connection wheel ID(s) or [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) object(s). Accepts either an [IRC::Message::Object](https://metacpan.org/pod/IRC::Message::Object) or a HASH compatible with [POE::Filter::IRCv3](https://metacpan.org/pod/POE::Filter::IRCv3) -- look there for details. Note that unroutable (target connection IDs with no matching live wheel) messages are silently dropped. You can check ["wheels"](#wheels) yourself before sending if this behavior is unwanted: for my $target (@connect_ids) { unless (exists $backend->wheels->{$target}) { warn "Cannot send to nonexistant target '$target'"; next } $backend->send( { prefix => $prefix, params => [ @params ], command => $cmd }, $target ); } ### has\_ssl\_support Returns true if [POE::Component::SSLify](https://metacpan.org/pod/POE::Component::SSLify) was successfully loaded. ### has\_zlib\_support Returns true if [POE::Filter::Zlib::Stream](https://metacpan.org/pod/POE::Filter::Zlib::Stream) was successfully loaded. ### set\_compressed\_link $backend->set_compressed_link( $conn_id ); Mark a specified connection wheel ID as pending compression; [POE::Filter::Zlib::Stream](https://metacpan.org/pod/POE::Filter::Zlib::Stream) will be added to the filter stack when the next flush event arrives. This method will die unless ["has\_zlib\_support"](#has_zlib_support) is true. ### set\_compressed\_link\_now $backend->set_compressed_link_now( $conn_id ); Add a [POE::Filter::Zlib::Stream](https://metacpan.org/pod/POE::Filter::Zlib::Stream) to the connection's filter stack immediately, rather than upon next flush event. This method will die unless ["has\_zlib\_support"](#has_zlib_support) is true. ### unset\_compressed\_link $backend->unset_compressed_link( $conn_id ); Remove [POE::Filter::Zlib::Stream](https://metacpan.org/pod/POE::Filter::Zlib::Stream) from the connection's filter stack. ## Received events ### register $poe_kernel->post( $backend->session_id, 'register' ); Register the sender session as the backend's controller session. The last session to send 'register' is the session that receives notification events from the backend component. ### create\_connector Event interface to _create\_connector_ -- see ["Methods"](#methods) ### create\_listener Event interface to _create\_listener_ -- see ["Methods"](#methods) ### remove\_listener Event interface to _remove\_listener_ -- see ["Methods"](#methods) ### send Event interface to _/send_ -- see ["Methods"](#methods) ### shutdown Disconnect all wheels and clean up. ## Dispatched events These events are dispatched to the controller session; see ["register"](#register). ### ircsock\_compressed Dispatched when a connection wheel has had a compression filter added. `$_[ARG0]` is the connection's [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) ### ircsock\_connection\_idle Dispatched when a connection wheel has had no input for longer than specified idle time (see ["create\_listener"](#create_listener) regarding idle times). Currently these events are only issued for incoming Connects accepted on a Listener, not outgoing Connects created by a Connector. `$_[ARG0]` is the connection's [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) See also: ["ping\_pending" in POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect#ping_pending) ### ircsock\_connector\_failure Dispatched when a Connector has failed due to some sort of socket error. `$_[ARG0]` is the connection's [POEx::IRC::Backend::Connector](https://metacpan.org/pod/POEx::IRC::Backend::Connector) with wheel() cleared. `@_[ARG1 .. ARG3]` contain the socket error details reported by [POE::Wheel::SocketFactory](https://metacpan.org/pod/POE::Wheel::SocketFactory); operation, errno, and errstr, respectively. ### ircsock\_connector\_open Dispatched when a Connector has established a connection to a peer. `$_[ARG0]` is the [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) for the connection. ### ircsock\_disconnect Dispatched when a connection wheel has been cleared. `$_[ARG0]` is the connection's [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) with wheel() cleared. ### ircsock\_input Dispatched when there is some IRC input from a connection wheel. `$_[ARG0]` is the connection's [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect). `$_[ARG1]` is an [IRC::Message::Object](https://metacpan.org/pod/IRC::Message::Object). ### ircsock\_listener\_created Dispatched when a [POEx::IRC::Backend::Listener](https://metacpan.org/pod/POEx::IRC::Backend::Listener) has been created. `$_[ARG0]` is the [POEx::IRC::Backend::Listener](https://metacpan.org/pod/POEx::IRC::Backend::Listener) instance; the instance's port() is altered based on getsockname() details after socket creation and before dispatching this event. ### ircsock\_listener\_failure Dispatched when a Listener has failed due to some sort of socket error. `$_[ARG0]` is the [POEx::IRC::Backend::Listener](https://metacpan.org/pod/POEx::IRC::Backend::Listener) object. `@_[ARG1 .. ARG3]` contain the socket error details reported by [POE::Wheel::SocketFactory](https://metacpan.org/pod/POE::Wheel::SocketFactory); operation, errno, and errstr, respectively. ### ircsock\_listener\_open Dispatched when a listener accepts a connection. `$_[ARG0]` is the connection's [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) `$_[ARG1]` is the connection's [POEx::IRC::Backend::Listener](https://metacpan.org/pod/POEx::IRC::Backend::Listener) ### ircsock\_listener\_removed Dispatched when a Listener has been removed. `$_[ARG0]` is the [POEx::IRC::Backend::Listener](https://metacpan.org/pod/POEx::IRC::Backend::Listener) object. ### ircsock\_registered Dispatched when a ["register"](#register) event has been successfully received, as a means of acknowledging the controlling session. `$_[ARG0]` is the Backend's `$self` object. # BUGS Probably lots. Please report them via RT, e-mail, or GitHub ([http://github.com/avenj/poex-irc-backend](http://github.com/avenj/poex-irc-backend)). Tests are a bit incomplete, as of this writing. Zlib and SSL are mostly untested. # SEE ALSO [POEx::IRC::Backend::Connect](https://metacpan.org/pod/POEx::IRC::Backend::Connect) [POEx::IRC::Backend::Connector](https://metacpan.org/pod/POEx::IRC::Backend::Connector) [POEx::IRC::Backend::Listener](https://metacpan.org/pod/POEx::IRC::Backend::Listener) [POEx::IRC::Backend::Role::Socket](https://metacpan.org/pod/POEx::IRC::Backend::Role::Socket) [POEx::IRC::Backend::Role::HasWheel](https://metacpan.org/pod/POEx::IRC::Backend::Role::HasWheel) [POEx::IRC::Client::Lite](https://metacpan.org/pod/POEx::IRC::Client::Lite) for an experimental IRC client library using this backend. [https://github.com/miniCruzer/irssi-bouncer](https://github.com/miniCruzer/irssi-bouncer) for an irssi-based bouncer/proxy system using this backend. [POE::Filter::IRCv3](https://metacpan.org/pod/POE::Filter::IRCv3) and [IRC::Message::Object](https://metacpan.org/pod/IRC::Message::Object) for documentation regarding IRC message parsing. [IRC::Toolkit](https://metacpan.org/pod/IRC::Toolkit) for an extensive set of IRC-related utilities. [POE::Component::IRC](https://metacpan.org/pod/POE::Component::IRC) if you're looking for a mature, fully-featured IRC client library. # AUTHOR Jon Portnoy Inspiration derived from [POE::Component::Server::IRC::Backend](https://metacpan.org/pod/POE::Component::Server::IRC::Backend) and [POE::Component::IRC](https://metacpan.org/pod/POE::Component::IRC) by BINGOS, HINRIK et al.