The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Volity::Jabber - a base class for Jabber-speaking Volity objects

SYNOPSIS

 package My::Volity::Object;
 use base qw(Volity::Jabber);
 use fields qw(wubba_wubba);

 # Override the parent's initialize method to set values on construction.
 sub initialize {
   my $self = shift;
   $self->SUPER::initialize(@_);   # Don't forget to call the parent's init!
   # Initialization goes here
   $self->wubba_wubba('grink gronk');
 }

 # An example chat handler, defined by the base class
 sub handle_groupchat_message {
   my $self = shift;
   my ($message) = @_;  # A hashref with info about the incoming message.
   # Send a debug message.
   $self->logger->debug(sprintf("%s says, '%s'\n", $$message{from}, $$message{body}));
   # More use message-handling code goes here.
 }

DESCRIPTION

This package provides a base class for Volity objects that speak Jabber. These objects will automatically connect to (and authenticate with ) a Jabber server on construction, and then provide some methods for doing some common jabbery things, as well as access the POE kernel.

USAGE

For game authors

You don't need to know much of anything at this level. Here be dragons.

Stick to the modules listed in "Modules of interest to game developers" in Volity, especially Volity::Game.

For deep-voodoo wizards

To use this module, write an object class that subclasses Volity::Jabber, then override any event-handling methods which should perform some action other than the default (which is usually a no-op). See "CALLBACK METHODS" for a list of these handlers.

Commonly, you'll want to respond to incoming Jabber stanzas by firing off some stanzas of your own, and the methods listed under "JABBER ACTION METHODS" can help you here.

Keep in mind that every instance of your class will represent a separate connection to a Jabber server. So, a single object can represent a game server, a client connection, or a "bot", among other things.

Object construction and initialization

The module inherits from Class::Accessor::Fields, so using it means using the base and fields pragmas, respectively. If you don't like this behavior, you can just overload the new() method. Otherwise, you don't need to define new() at all.

If you want to initialize your object, override the initialize method. however, you must call SUPER::initilialize, otherwise the connection won't open.

Localization

This module supports language localization compliant with the core Jabber protocol. All stanzas automatically get an xml:lang attribute set on their top-level element (such as <message> or <presence>) whose value is the object's current default_language value (en being the default's default, and you can change this through the default_language accessor method).

Some methods, such as send_message (described under "JABBER ACTION METHODS"), allow you to specify either plain text strings in the default language, or localized text strings in several languages. To provide localized strings, pass the method a hash reference where'd you'd normally pass in a plain string. The hash's keys should be ISO 639-compliant two-letter language codes, with their corresponding localized text as values. For example:

 { 
   'en' => "This is some localized text.",
   'es' => "Éste es un poco de texto localizado.",
   'fr' => "C'est un certain texte localisé.",
   'ru' => "Это будет некоторый локализованный текст.",
 }

Do make sure that you "use utf8" and enter UTF-8 only text if you're using anything other then ASCII. Remember, Latin-1 is NOT compatible with UTF-8.

If you aren't concerned at all with localization, you can simply ignore all these methods and techniques, and nothing will break. So, in the same place as you'd use the above hashref, you could instead simply use a string like this:

 "This string is available in English only. C'est la vie."

METHODS

Accessors

All these accessor methods take the same form, as defined by Class::Accessor: all return a scalar value (or undef) representing a current value set on the object, and will set this value first if called with an argument (which can be a scalar or a list, if appropriate).

Also in Class::Accessor style, you can set any of these values during construction by passing them in a hashref to the new method.

kernel

The current POE kernel. You shouldn't need to access this much, but it's there if you need it.

alias

The 'nickname' under which this object's own POE session will be known to the kernel. You should set this to something meaningful, and unique to the application.

host

The Jabber server's hostname (or IP address).

jid_host

The connection's concept of the hostname part of its Jabber ID. This is almost always identical to the value of the host key, but if there's some proxy-connection magic afoot, these may be different.

port

The Jabber server's TCP port.

user

The username to use when connecting to the Jabber server.

password

The password to use when connecting to the Jabber server.

resource

The resource identifier to use when connecting to the Jabber server. (This is the part that gets stuck on the end of the JID, after the slash. So, setting this to "foo" will result in a JID like "bob@somejabberserver.com/foo")

default_language

The two-letter language code that the object will attach to all outgoing Jabber stanzas to identify their default language. Defaults to en. (See "Localization" more more information about how this module handles different langauges.)

jid (read-only)

After connection, this will return the connection's JID.

basic_jid (read-only)

Like jid, except it returns the non-resource part of the JID. (e.g. foo@bar.com versus foo@bar.com/bazzle.)

CALLBACK METHODS

Element-handling methods

All these object methods are called with a single argument: the XML node that triggered them. See POE::Filter::XML::Node for more about this node object's API.

jabber_presence

Called when a presence element is received.

jabber_iq

Called when a an IQ element is received.

If you override this, you should call SUPER::jabber_iq within the method, since the base class already does a lot of work with incoming IQ elements, such as handling RPC requests and responses.

The following related methods handle specific applications of the <<iq>> element. As with jabber_iq, the single argument in every case is a POE::Filter::XML::Node object representing the triggering XMPP <<iq>> element.

handle_disco_items
handle_disco_info
handle_disco_items_request
handle_disco_info_request

Define these methods in your subclass to let it respond to Jabber service discovery (JEP-0030) requests and responses. The first two methods handle other entities' response to requests that this one sent; the latter two handle entities seeking disco information on this object.

RPC handler methods

These methods are called by RPC events.

handle_rpc_response({id=>$id, response=>$response, from=>$from, rpc_object=>$obj})

Called upon receipt of an RPC response. The argument is a hashref containing the response's ID attribute and response value, as well as an RPC::XML object representing the response.

handle_rpc_request({id=>$id, method=>$method, args=>[@args], from=>$from, rpc_object=>$obj})

Called upon receipt of an RPC request. The argument is a hashref containing the request's ID attribute, method, argument list (as an arrayref), and originating JID, as well as an RPC::XML object representing the request.

handle_rpc_fault({id=>$id, rpc_object=>$obj, from=>$from, fault_code=>$code, fault_string=>$string})

Called upon receipt of an RPC fault response.

handle_rpc_transmission_error($iq_node, $error_code, $error_message);

Called upon receipt of a Jabber IQ packet that's of type error, but that seems to contain a Jabber-RPC element. This usually means that the RPC message failed to reach its destination for some reason. If this reason is known, it will show up as a code and (maybe) a text message in the callback's arguments.

Note that this is distinct from an RPC fault, which is something returned from a network entity after successfully receiving an RPC request.

Message handler methods

All of the following methods are called with a single hashref as an argument, containing message information under the following keys: from, to, subject, body, thread

  • handle_normal_message

  • handle_groupchat_message

  • handle_chat_message

  • handle_headline_message

  • handle_error_message

JABBER ACTION METHODS

These methods will send messages and other data to the Jabber server.

send_rpc_request($args_hashref)

Send an RPC request. The single argument is a hashref with the following keys:

to

The JID to which this request should be sent.

id

The ID of this request. (The RPC result will have the same ID.)

methodname

The name of the remote method to call.

args

The method's arguments, as a list reference. If there's only one argument, and it's not itself an array reference, you can optionally pass it in by itself. If there are no arguments, you can pass undef or just skip this key.

Each argument must be either a simple scalar, a hashref, or an arrayref. In the latter cases, the argument will turn into an RPC struct or array, respectively. All the datatyping magic is handled by the RPC::XML module (q.v.).

handler

This is the response handler. It's executed when we get an answer back. If it isn't passed then the default handler is used (which does nothing unless overridden). It can either be a CODE ref or the name of a premade response handler. CODE refs are passed only the response. Premade response handler are not provided here but may be available in subclasses. The method name of the handler is in the form "rpc_response_$handler". So if $handler was "start_game" then the method containing the response handler would be "rpc_response_start_game". Premade response handlers are called as methods with the response as their argument.

send_rpc_response ($receiver_jid, $response_id, $response_value)

Send an RPC response. The value can be any scalar.

send_rpc_fault ($receiver_jid, $response_id, $fault_code, $fault_string)

Send an RPC fault.

send_message($args_hashref)

Send a Jabber message. The single argument is a hashref with the following keys:

to

The JID to which this message is to be sent.

type

The type of Jabber message this is. Should be one of: chat, groupchat, normal, headline or error. (See the Jabber protocol for explanation on what these mean.)

thread

Optional A string identifying the thread that this message belongs to.

subject

Optional The message's subject. Can be either a string, or a hashref of the sort described in "Localization".

body

Optional The message's body. Can be either a string, or a hashref of the sort described in "Localization".

invitation

Optional A hashref describing a Volity message-based invitation. Keys include referee, name, player, parlor, ruleset and table.

send_query($args_hashref)

Send a Jabber <<query>> element, wrapped in an <<iq>> packet. The single argument is a hashref describing the query to send, and can take the following keys:

to

The JID that this query will be sent to.

id

The ID attribute attached to the enfolding <<iq>> envelope.

type

The sort of <<iq>> this will be, e.g. set or result.

query_ns

The XML namespace to attach to the query. It's usually important to set this to some value, since it lets the receiver know which Jabber application the query applies to. For instance, a MUC configuration form query would set this to "http://jabber.org/protocol/muc#owner", as per JEP-0045.

content

An anonymous array containing POE::Filter::XML::Node objects (or objects made from a subclass thereof), to be added as children to the outgoing query.

join_muc($args_hashref)

Join a multi-user conference (MUC). The single argument is a hashref with the following keys:

jid

The JID of the conference to join. You can specify the MUC either through this key, or the room and server keys.

nick

The nickname to use in the conference. If you don't specify this, the nick used will default to the object's username.

server

The server on which this MUC is located.

room

The name of the MUC.

The return value is the JID of the MUC that presence was sent to.

leave_muc ($muc_jid)

Leave the multi-user conference whose JID matches the provided argument.

send_presence ($info_hashref)

Send a presence packet. Its optional argument is a hashref containing any of the following keys:

to

The destination of this presence packet (if it's a directed packet and not just a 'ping' to one's Jabber server).

type

Sets the type attribute. See the XMPP-IM protocol for more information as to their use and legal values.

show
status
priority

These all set sub-elements on the outgoing presence element. See the XMPP-IM protocol for more information as to their use. You may set these to localized values by setting their values to hashrefs instead of strings, as described in "Localization".

caps

This optional key has a value of another hashref containing entity capabilities (JEP-0115) information. Its keys are node, ver and ext.

namespace

If you define this optional key, then the presence packet will include an empty <<x/>> element with the given xmlns attribute value.

You can leave out the hashref entirely to send a blank <<presence/>> element.

request_roster

Requests the user's roster from its Jabber server. Takes no arguments.

This will result in a new roster object becoming available under the roster accessor method. See "Volity::Jabber::Roster" for this object's API.

request_disco_info ($args_hashref)

Request service-discovery info from a JID/node combination. The server's answer will trigger your module's receive_disco_info callback method (see "CALLBACK METHODS").

The argument hashref can contain the following keys:

to

A JID that the request will be sent to.

node

An optional string, specifying the node of the given JID.

id

The ID of this request.

request_disco_items ($args_hashref)

Request service-discovery items from a JID/node combination. The server's answer will trigger your module's receive_disco_items callback method (see "CALLBACK METHODS").

The argument hashref can contain the following keys:

to

A JID that the request will be sent to.

node

An optional string, specifying the node of the given JID.

id

The ID of this request.

disconnect

Disconnects this entity from the Jabber server.

It sends out an 'unavailable' presence packet before doing so, just to be nice.

post_node($node)

Post the given XML node object to the POE kernel, which will then send it off to the Jabber server.

This is the method that is ultimately called by all the other action methods. You can use it too, if you find yourself knitting up raw nodes for some reason.

SUPPLEMENTARY PACKAGES

This module also include a handful of supplementary packages which define some helper objects. You'll usually use them in conjunction with the methods described above.

Volity::Jabber::Roster

Objects of this class represent a Jabber roster, and its creation is usually the result of a call to the request_roster method of a Volity::Jabber object. Roster objects have methods appropriate for storing and grouping Jabber IDs (JIDs), as follows:

add_item ($item_hash)

Adds to the roster the JID described by the given hash reference. The hash must include a jid key, whose value is the JID to add to the roster. It can optionally contain a name, whose value is a nickname to associate with this roster JID, and a group key, whose value is an anonymous list of all the roster group names that this JID should be filed under.

remove_item ($jid)

Removes the given JID from the roster.

jids

Returns a list of all the JIDs on the roster.

ungrouped_jids

Returns a list of all the JIDs which do not belong to any group.

jids_in_group ($group)

Returns a list of all the JIDs which belong to the given group.

jid_for_name ($name)

Returns the JID corresponding to the given nickname, if any.

name_for_jid ($jid)

Returns the nickname associated with the given JID, if any.

groups_for_jid ($jid)

Returns a list of the groups that the given JID belongs to, if any.

has_jid ($jid)

Returns 1 if the given jid is on the roster, and 0 if it isn't.

presence ($jid, {type=>$presence_type)

Gets or sets a hash of information about the given JID's presence. Note that the roster object doesn't listen to presence and do this all by itself; this method has to be called from outside.

The JID in the required first argument may include a resource string. If so, the method will set and return presence information only for that one JID / resource combination.

At this time, only a single key, type, is supported in the optional second argument. If present, it sets the presence of the given JID (and resource, if provided) to that key's value, e.g. "unavailable".

The return value is a list of anonymous hashes describing all known presence information about this JID. Each hash has two keys, resource and type.

Volity::Jabber::Disco::Item

This object represents a Jabber Service Discovery item. A subclass of POE::XML::Node, it may be inserted directly into disco responses you are building, just as <<item>> elements in disco responses you receive may be re-blessed into this class.

It contains the following simple accessor methods, whose ultimate function is described in JEP-0030:

jid
node
name

Volity::Jabber::Disco::Identity

Just like Volity::Jabber::Disco::Item, except for disco <<identity>> elements.

It contains the following simple accessor methods:

category
type
name

Volity::Jabber::Disco::Feature

Just like Volity::Jabber::Disco::Item, except for disco <<feature>> elements.

It contains the following simple accessor methods (er, method):

var

Volity::Jabber::Form

Caution: incomplete implementation.

A class for Jabber data forms, as defined by JEP-0004. An object of this class is useful to stick under the content key of of the send_query argument (see "ACTION METHODS".

Simple accessors:

type
title
instructions

Other accessors:

fields

Returns, as a list of Volity::Jabber::Form::Field objects, the form's fields, with any values they may contain.

Optionally call with an array of Volity::Jabber::Form::Field objects to first set the form's fields.

clear_fields

Erases all the form's fields.

Other methods:

invalid_fields

Returns a list of Volity::Jabber::Form::Field objects set as required but which have no values set.

Volity::Jabber::Form::Field

Just like Volity::Jabber::Disco::Item, except for JEP-0004 form-field elements.

It contains the following simple accessor methods:

label
var
type
desc
required

And the slightly less-simple accessors:

values (@values)

If a list of arguments is provided, it becomes the values for this form field.

Returns a list of this field's current values.

clear_values

Clears this field's list of values.

options (@options)

If a list of arguments is provided, it becomes the options for this form field. Each argument should be an anonymous hash, with a values key set to an anonymous list of the values this option allows, and an optional label key.

Returns a list of this field's current options, using the anonymous hash format described above.

clear_options

Clears the options from this form element.

Other methods:

is_required ($is_required)

Set to a true value to define this field as required. Call with a false (but defined) value to set the field to not-required (which is the initial state of all new objects of this class).

Returns the current required-state of this object, expressed as 0 or 1.

is_valid

Returns 0 if this field is set required and contains no values; 1 otherwise.

NOTES

This class was originally written with the Volity internet game system in mind, but it doesn't really have much Volity-specific code in it. It might end up leaving the Volity namespace, if it stays as such for a long time.

BUGS AND SUCH

JEP-0004 (data forms) is not yet fully implemented, especially where handling incoming forms is concerned.

The module is only patchily object-oriented. Some things that really ought to have object classes lack them, such as Jabber iq/message/presence packets. Future versions of this module. Backwards compatibility will be attempted but is not guaranteed. (Therefore, modules which subclass from Volity::Jabber should really be specific about which version they require.)

SEE ALSO

  • Jabber Protocol information: http://www.jabber.org/protocol/

  • RPC::XML

  • Volity

AUTHOR

Jason McIntosh <jmac@jmac.org>

COPYRIGHT

Copyright (c) 2003-2006 by Jason McIntosh.