Jon Portnoy

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 IRC socket handler that can be used (by client or server implementations) to speak the IRC protocol to endpoints via IRC::Message::Object objects.

Inspired by POE::Component::Server::IRC::Backend & 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 for an experimental IRC client library using this backend (and the "SEE ALSO" section of this documentation for related tools).

Attributes

controller

Retrieve the 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 instance consisting of the current "filter_irc" stacked with "filter_line" (at the time the attribute is built).

filter_irc

A 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 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 Context object, if we have one (or undef if not); the context is set up by "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.

The ssl_opts ARRAY is passed directly to "SSLify_ContextCreate" in POE::Component::SSLify, if present. As of v0.28.x, each Backend gets its own Net::SSLeay context object (rather than sharing the global context). See POE::Component::SSLify & 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 that holds a POE::Wheel::SocketFactory connector wheel; connectors will attempt to establish an outgoing connection immediately.

Unrecognized options are stored in the POEx::IRC::Backend::Connector's args HASH-type attribute; this is passed to successfully created 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 that holds a 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 objects created by incoming connections to that listener, similar to the behavior described in "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 wheel goes out of scope.

disconnect

  $backend->disconnect($wheel_id, $disconnect_string);

Given a 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 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

Like "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 and sends the resultant raw IRC line to the specified connection wheel ID(s) or POEx::IRC::Backend::Connect object(s).

Accepts either an IRC::Message::Object or a HASH compatible with 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" 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 was successfully loaded.

has_zlib_support

Returns true if POE::Filter::Zlib::Stream was successfully loaded.

  $backend->set_compressed_link( $conn_id );

Mark a specified connection wheel ID as pending compression; 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" is true.

  $backend->set_compressed_link_now( $conn_id );

Add a 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" is true.

  $backend->unset_compressed_link( $conn_id );

Remove 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"

create_listener

Event interface to create_listener -- see "Methods"

remove_listener

Event interface to remove_listener -- see "Methods"

send

Event interface to /send -- see "Methods"

shutdown

Disconnect all wheels and clean up.

Dispatched events

These events are dispatched to the controller session; see "register".

ircsock_compressed

Dispatched when a connection wheel has had a compression filter added.

$_[ARG0] is the connection's 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" regarding idle times).

Currently these events are only issued for incoming Connects accepted on a Listener, not outgoing Connects created by a Connector; if you need to do ping/pong-style heartbeating on an outgoing Connector-spawned socket, you will need to run your own timer.

$_[ARG0] is the connection's POEx::IRC::Backend::Connect.

See also: "ping_pending" in POEx::IRC::Backend::Connect

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 with wheel() cleared.

@_[ARG1 .. ARG3] contain the socket error details reported by 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 for the connection.

ircsock_disconnect

Dispatched when a connection wheel has been cleared.

$_[ARG0] is the connection's 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.

$_[ARG1] is an IRC::Message::Object.

ircsock_listener_created

Dispatched when a POEx::IRC::Backend::Listener has been created.

$_[ARG0] is the 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 object.

@_[ARG1 .. ARG3] contain the socket error details reported by 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

$_[ARG1] is the connection's POEx::IRC::Backend::Listener

ircsock_listener_removed

Dispatched when a Listener has been removed.

$_[ARG0] is the POEx::IRC::Backend::Listener object.

ircsock_registered

Dispatched when a "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).

SEE ALSO

POEx::IRC::Backend::Connect

POEx::IRC::Backend::Connector

POEx::IRC::Backend::Listener

POEx::IRC::Backend::Role::Socket

POEx::IRC::Backend::Role::HasEndpoint

POEx::IRC::Backend::Role::HasWheel

POEx::IRC::Client::Lite for an experimental IRC client library using this backend.

https://github.com/miniCruzer/irssi-bouncer for an irssi-based bouncer/proxy system using this backend.

POE::Filter::IRCv3 and IRC::Message::Object for documentation regarding IRC message parsing.

IRC::Toolkit for an extensive set of IRC-related utilities.

POE::Component::IRC if you're looking for a mature, fully-featured IRC client library.

AUTHOR

Jon Portnoy <avenj@cobaltirc.org>

Inspiration derived from POE::Component::Server::IRC::Backend and POE::Component::IRC by BINGOS, HINRIK et al.