Cover | Table of Contents | Colophon
<presence from='john@company-b.com/Desk'
to='jim@company-a.com/home'>
<status>Online</status>
<priority>2</priority>
</presence>
<presence from='john@company-b.com/Desk'
to='jim@company-a.com/home'>
<status>Online</status>
<priority>2</priority>
</presence>
<message type='chat' from='jim@company-a.com/home'
to='john@company-b.com'>
<thread>01</thread>
<body>Hey John, have you seen the latest story on Megacorp earnings?</body>
</message>
<message type='chat' to='jim@company-a.com/home'
from='john@company-b.com/Desk'>
<thread>01</thread>
<body>No, where is it?</body>
</message>
<message type='chat' from='jim@company-a.com/home'
to='john@company-b.com/Desk'>
<thread>01</thread>
<body>Here's the link</body>
<x xmlns='jabber:x:oob'>
<url>http://www.megacorp.co.uk/earnings3q.html</url>
<desc>Third Quarter Earnings for Megacorp</desc>
</x>
</message>
<message to='john@company-b.com' from='alert@stocks.company-b.com'> <subject>ACMH Fallen below 250p</subject> <body>ACME Holdings price 248p as at 10:20am today</body> </message>
Net::Jabber
library, which provides a high-level API to many Jabber-related functions
such as handling the connection to the server (this is via another
library that Net::Jabber uses—XML::Stream), authentication, events,
and all the mechanisms to parse and create Jabber traffic.
#!/usr/bin/perl
use Net::Jabber qw(Client);
use strict;
# List of addressees for our reminder
our @addressees;
# What we want to send
my $reminder = $ARGV[0] or die "No reminder!";
# Connect to our Jabber server
my $c= Net::Jabber::Client->new();
$c->Connect('hostname' => 'yak',
'port' => 5222);
# Authenticate
$c->AuthSend('username' => 'reminder',
'password' => 'secret',
'resource' => 'reminder');
# Set handler to deal with presence packets
# that might (will) be pushed to us (we're
# not interested in any other type of packet)
$c->SetCallBacks('presence' => \&handle_presence);
# Send out our own presence, and run an
# event loop for up to 5 seconds to
# catch any packets pushed to us
$c->PresenceSend();
$c->Process(5);
# Create a new message with our reminder text
my $m = Net::Jabber::Message->new();
$m->SetBody($reminder);
# Send the message to each of the addressees collected
# in the handle_presence() subroutine
foreach my $jid (@addressees) {
$m->SetTo($jid);
$c->Send($m);
}
# Disconnect from the Jabber server and exit
$c->Disconnect;
exit(0);
# Deal with presence packets
sub handle_presence {
my ($sid, $presence) = @_;
# Get the presence
my $show = $presence->GetShow() || 'online';
# If the user is around, add to addressee list
push @addressees, $presence->GetFrom()
if $show eq 'online' or $show eq 'chat';
}
http://www.w3.org/TR/REC-xml-names for more details.)
Namespaces are used in XML to segregate, or qualify, individual chunks of
data, giving tags a reference to which they belong. What the reference is,
in many ways, is of secondary importance; the point is the delineation that
allows us
to manage content within an XML fragment that is logically divided into
subfragments. Consider Example 2-1,
which shows a section of the imaginary
conversation from Chapter 1.
<message/>,
<iq/>, and
<presence/>.
<route/>,
is only used in the server to route messages between the various
components. More details on
<route/> can be found
in Section 4.1.2.3 in Chapter 4.
<message/> element has five
types—normal, chat,
groupchat, headline, and
error.
The <iq/> and
<presence/> elements also have types
to distinguish and describe their usage and context.
The <iq/> element has the types
get, set,
result, and error, while
the <presence/> element has, among
others, the types
available and unavailable.
Details can be seen in Table 2-1.
jabber:) have been designed with specific scenarios
in mind.
An example of a headline
<message/> element
containing an extension qualified by a predefined namespace is shown in
Example 2-3.
|
Element
|
Tag
|
Types
|
|---|---|---|
|
Message
|
<message>
|
normal, chat, groupchat, headline, error |
jabber:x:oob-qualified <x/>
tag and its child tags:
<x xmlns='jabber:x:oob'> <url>http://www.megacorp.co.uk/earnings3q.html</url> <desc>Third Quarter Earnings for Megacorp</desc> </x>
<message/>,
<iq/>, and <presence/>,
can carry these attachments.
jabber:x:delay
namespace. This works like a timestamp and in this context indicates when
that presence element appeared—in other words, from what time Jim started
on his break.
<presence from='jim@company-a.com/home' to='john@company-b.com'>
<show>chat</show>
<status>having a break from work</status>
<priority>1</priority>
<x xmlns='jabber:x:delay' from='jim@company-a.com/home'
stamp='20010611T13:13:04'/>
</presence>
GET /home.html HTTP/1.0 is the request,
and everything else, starting with HTTP/1.1 200 OK,
is the response.
GET /home.html HTTP/1.0 HTTP/1.1 200 OK Date: Mon, 11 Jun 2001 13:43:13 GMT Server: Apache/1.3.12 (Unix) mod_perl/1.24 Last-Modified: Fri, 09 Jun 2000 13:47:56 GMT ETag: "8a69-6a-3940f58c" Accept-Ranges: bytes Content-Length: 306 Connection: close Content-Type: text/html <html> <head> ...
GET and the specification
of what to retrieve (the /home.html document), and it
shows us what is returned in response.
<iq/>.
<iq/> element to effect the IQ request/response
model.
<message type='headline'/> element. Considering this, in
combination with the features we know Jabber posesses and the
solution potential that these features offer in presenting a wider deployment
vista than IM services, we come to an interesting conclusion:
A Jabber client is a piece of software that implements as much of the Jabber protocol as required to get the job done.
http://mailman.jabber.org/listinfo/jamdev);
an extension to one of the Perl libraries
for Jabber (Jabber::Connection) to carry
XML-RPC-encoded messages also exists
(http://www.pipetree.com/jabber/jrpc/), which is shown in Section 10.2.7 in Chapter 10.
jabber:iq:agents)
was found to be too restrictive and, more importantly, too specific.
A more generic way of describing entities in the Jabber
world was needed.
http://www.gnu.org)
are recommended if you don't already have them installed.
http://www.jabber.org; the
1.4.1 version is available in the downloads area:
http://download.jabber.org/dists/1.4/final/jabber-1.4.1.tar.gz
http://download.jabber.org.
yak:/usr/local# mkdir jabber
yak:/usr/local# groupadd jabber yak:/usr/local# useradd -g jabber -d /usr/local/jabber jabber yak:/usr/local# passwd jabber Changing password for jabber Enter the new password (minimum of 5, maximum of 127 characters) Please use a combination of upper and lower case letters and numbers. New password: ******** Re-enter new password: ******** Password changed. yak:/usr/local# chown jabber:jabber jabber yak:/usr/local#
yak:/usr/local# su - jabber yak:~$ tar xzf jabber-1.4.1.tar.gz yak:~$ cd jabber-1.4.1/ yak:~/jabber-1.4.1$
<host/>
parameter specifies the
Jabber server's hostname. As delivered, the jabber.xml
configuration has this set to localhost:
<host><jabberd:cmdline flag="h">localhost</jabberd:cmdline></host>
yak:~/jabber-1.4.1$ ./jabberd/jabberd
yak:~/jabber-1.4.1$ ./jabberd/jabberd -h yak
<log id='elogger'>
<host/>
<logtype/>
<format>%d: [%t] (%h): %s</format>
<file>error.log</file>
<stderr/>
</log>
<!-- <stderr/> -->Or redirect STDERR to /dev/null:
yak:~/jabber-1.4.1$ ./jabberd/jabberd -h yak 2>/dev/null
yak:~/jabber-1.4.1$ ./jabberd/jabberd -h yak 2>/dev/null &
<log id='elogger'>
<host/>
<logtype/>
<format>%d: [%t] (%h): %s</format>
<file>error.log</file>
<stderr/>
</log>
<log id='rlogger'>
<host/>
<logtype>record</logtype>
<format>%d %h %s</format>
<file>record.log</file>
</log>
c2s.
s2s.
<jabber/>.
The opening tags for each of these chunks are as follows:
<service id="sessions">
<xdb id="xdb">
<service id="c2s">
<log id="elogger">
<log id="rlogger">
<service id="dnsrv">
<service id="jud">
<service id="s2s">
<service id="conf">
<io>
sessions component, described by the configuration
XML shown in Example 4-8 and shown in diagram form
in Figure 4-5, provides Session Management
features for users (the word "users" is employed in the widest possible
sense—a user could be a person or a script) connecting with Jabber
clients, through XML streams identified
with the jabber:client stream namespace.
<service id="sessions">
<host><jabberd:cmdline flag="h">yak</jabberd:cmdline></host>
<jsm xmlns="jabber:config:jsm">
<filter>
<default/>
<max_size>100</max_size>
<allow>
<conditions>
<ns/>
<unavailable/>
<from/>
<resource/>
<subject/>
<body/>
<show/>
<type/>
<roster/>
<group/>
</conditions>
<actions>
<error/>
<offline/>
<forward/>
<reply/>
<continue/>
<settype/>
</actions>
</allow>
</filter>
<vCard>
<FN>Jabber Server on yak</FN>
<DESC>A Jabber Server!</DESC>
<URL>http://yak/</URL>
</vCard>
<register notify="yes">
<instructions>Choose a userid and password to register.</instructions>
<name/>
<email/>
</register>
<welcome>
<subject>Welcome!</subject>
<body>Welcome to the Jabber server on yak</body>
</welcome>
<!--
<admin>
<read>support@yak</read>
<write>admin@yak</write>
<reply>
<subject>Auto Reply</subject>
<body>This is a special administrative address.</body>
</reply>
</admin>
-->
<update><jabberd:cmdline flag="h">yak</jabberd:cmdline></update>
<vcard2jud/>
<browse>
<service type="jud" jid="jud.yak" name="yak User Directory">
<ns>jabber:iq:search</ns>
<ns>jabber:iq:register</ns>
</service>
<conference type="public" jid="conference.yak" name="yak Conferencing"/>
</browse>
</jsm>
<load main="jsm">
<jsm>./jsm/jsm.so</jsm>
<mod_echo>./jsm/jsm.so</mod_echo>
<mod_roster>./jsm/jsm.so</mod_roster>
<mod_time>./jsm/jsm.so</mod_time>
<mod_vcard>./jsm/jsm.so</mod_vcard>
<mod_last>./jsm/jsm.so</mod_last>
<mod_version>./jsm/jsm.so</mod_version>
<mod_announce>./jsm/jsm.so</mod_announce>
<mod_agents>./jsm/jsm.so</mod_agents>
<mod_browse>./jsm/jsm.so</mod_browse>
<mod_admin>./jsm/jsm.so</mod_admin>
<mod_filter>./jsm/jsm.so</mod_filter>
<mod_offline>./jsm/jsm.so</mod_offline>
<mod_presence>./jsm/jsm.so</mod_presence>
<mod_auth_plain>./jsm/jsm.so</mod_auth_plain>
<mod_auth_digest>./jsm/jsm.so</mod_auth_digest>
<mod_auth_0k>./jsm/jsm.so</mod_auth_0k>
<mod_log>./jsm/jsm.so</mod_log>
<mod_register>./jsm/jsm.so</mod_register>
<mod_xml>./jsm/jsm.so</mod_xml>
</load>
</service>
xdb component, described by the configuration
XML shown in Example 4-10 and shown in diagram form
in Figure 4-8, provides data storage for the
server—it is the
XML Database.
xdb component. In normal configurations, there is a
single instance, although it is possible to have more than one, each handling
separate areas of storage, possibly using different storage mechanisms.
<xdb id="xdb">
<host/>
<load>
<xdb_file>./xdb_file/xdb_file.so</xdb_file>
</load>
<xdb_file xmlns="jabber:config:xdb_file">
<spool><jabberd:cmdline flag='s'>./spool</jabberd:cmdline></spool>
</xdb_file>
</xdb>
xdb type component, as follows:
<xdb id="xdb">
xdb, much in the same way that the sessions service
has the name sessions.
<host/>
xdb component instance will answer
data storage and retrieval requests for all hosts. This, in turn, means that
all data to be stored server-side will be stored using the same data
storage mechanism, in this case xdb_file, which is a simple lowest
common denominator storage system based upon directories containing
files with XML content; these files are at a ratio of one per JID, plus
"global" files where storage of data not tied to a JID is required.
An example of this would be JUD's usage of c2s component, described by the configuration
XML shown in Example 4-12 and shown in diagram form
in Figure 4-9, provides the Client
(to Server) Connections service—it manages Jabber client
connections to the Jabber server.
<service id="c2s">
<load>
<pthsock_client>./pthsock/pthsock_client.so</pthsock_client>
</load>
<pthcsock xmlns='jabber:config:pth-csock'>
<authtime/>
<karma>
<init>10</init>
<max>10</max>
<inc>1</inc>
<dec>1</dec>
<penalty>-6</penalty>
<restore>10</restore>
</karma>
<ip port="5222"/>
</pthcsock>
</service>
<service id="c2s">
c2s.
c2s component has no explicit
<host/> tag; the identification
of the service with the id attribute is enough,
and the value of the host filter will be taken as that identification. As long
as the specified ID is unique within the context of the whole configuration