# 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 typically 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. See ["disconnect\_now"](#disconnect_now).
### disconnect\_now
Like ["disconnect"](#disconnect), but attempt to destroy the wheel immediately (without
waiting for a buffer flush).
### 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, IRC
(`irc.cobaltirc.org#perl`), or GitHub
([
http://github.com/avenj/poex-irc-backend](
http://github.com/avenj/poex-irc-backend)).
# 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::HasEndpoint](
https://metacpan.org/pod/POEx::IRC::Backend::Role::HasEndpoint)
[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 <
[email protected]>
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.