BUY THIS BOOK
Add to Cart

Print Book $39.95


Safari Books Online

What is this?

Add to UK Cart

Print Book £28.50

What is this?

Looking to Reprint this content?


Programming Jabber
Programming Jabber Extending XML Messaging By DJ Adams
January 2002
Pages: 480

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Introducing Jabber
This book is about Jabber: the technology, protocols, ideas, and the philosophy. Jabber is about connecting things (users, applications, and so on) in an all-pervasive message plasma that flows between clients and servers, carrying content, structure, and conversations.
The spirit of Jabber lies in its openness, its extensibility, and its lean but generic nature. That it finds itself in the midst of all that technology that will provide the backdrop to the dawn of the next-generation Internet is no accident. Web services, peer-to-peer, XML encapsulation, presence, identity, distributed computing—these are all phrases that describe key intiatives and developments that lie at the core of the coming transition, and Jabber can and does play a central role.
This book will show you how Jabber works, what makes it tick, and how to bend and shape it into solutions that join applications and users together. This first part is a guide to Jabber's technology and server. Part II is an examination of Jabber's building blocks and a series of scenarios and scripts we call "recipes," to show you how to deploy Jabber in a variety of situations.
To help you better understand what transpires during a Jabber-based conversation, this section presents a conversation between two friends, Jim and John, and two "assistant" applications at their respective places of work.
Jim and John work at two different companies. Both of them invest in the stock market, and they use a Jabber-based service to check and monitor prices, to buy and sell shares, and to manage their portfolios. John's company also has a workflow assistant that monitors incoming email and coordinates work items between colleagues.
Jim is notified that John is available:
<presence from='john@company-b.com/Desk'
    to='jim@company-a.com/home'>
  <status>Online</status>
  <priority>2</priority>
</presence>
Jim sends a quick chat message to John:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Imaginary Jabber Conversation
To help you better understand what transpires during a Jabber-based conversation, this section presents a conversation between two friends, Jim and John, and two "assistant" applications at their respective places of work.
Jim and John work at two different companies. Both of them invest in the stock market, and they use a Jabber-based service to check and monitor prices, to buy and sell shares, and to manage their portfolios. John's company also has a workflow assistant that monitors incoming email and coordinates work items between colleagues.
Jim is notified that John is available:
<presence from='john@company-b.com/Desk'
    to='jim@company-a.com/home'>
  <status>Online</status>
  <priority>2</priority>
</presence>
Jim sends a quick chat message to John:
<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>
John responds:
<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>
Jim sends John the URL:
<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>
John receives an alert about the price of ACME Holdings (ACMH) falling below a threshold he previously set:
<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>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
A Simple Script
Before moving on, let's have a look at how simple it is to interact with Jabber. Example 1-1 shows a simple Perl script that connects to a Jabber server, authenticates, checks who's online, and sends those people a reminder message. It uses the 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.
Example 1-1. A simple Jabber script
#!/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';

}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Inside Jabber
Jabber has a number of features that are fundamental to its design philosophy. This design philosophy outlines Jabber as a much more flexible and generic solution to the original problem of connecting to disparate IM systems. These features give Jabber the potential to exist and act in the P2P (peer-to-peer, or person-to-person), A2P (application-to-person), A2A (application-to-application)—or in fact, any of the three-letter acronyms (TLAs) that have a 2 in the middle—spaces that have conversation at their core.
Understanding Jabber's features is fundamental to seeing how it fits into the bigger picture. In this chapter, we explore these features and discover in what ways Jabber is not simply a cross-IM mechanism. In this exploration, you'll get a feel for how capable Jabber is of being integrated into "conversational solutions."
In Part II of the book, we'll revisit each of these features and see how they can be used in many different programming scenarios.
Arguments abound for and against XML in the arena of data representation. XML is suited extremely well to Jabber, which is suited extremely well to XML. There are many reasons for this.
The alternatives for representing data in Jabber are binary and ASCII text. Binary? Well, perhaps binary data is more space efficient, but where is that advantage in the general scheme of things these days? Near the bottom of my list, anyway, especially as it's always at the cost of readability. ASCII? Well, yes, of course, ASCII is human readable, but since Jabber data flow consists of a series of conversationalchunks—independent constructions in their own right—we need some sort of boundary mechanism to separate these chunks. XML affords us a very nice way of packaging individual chunks of data and giving their content meaning and context. These individual chunks of information have structure too, and this structure doesn't require any fixed-length madness either; XML allows the chunks, or fragments, to bend and stretch as required, while still retaining their meaning.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
XML-Based
Arguments abound for and against XML in the arena of data representation. XML is suited extremely well to Jabber, which is suited extremely well to XML. There are many reasons for this.
The alternatives for representing data in Jabber are binary and ASCII text. Binary? Well, perhaps binary data is more space efficient, but where is that advantage in the general scheme of things these days? Near the bottom of my list, anyway, especially as it's always at the cost of readability. ASCII? Well, yes, of course, ASCII is human readable, but since Jabber data flow consists of a series of conversationalchunks—independent constructions in their own right—we need some sort of boundary mechanism to separate these chunks. XML affords us a very nice way of packaging individual chunks of data and giving their content meaning and context. These individual chunks of information have structure too, and this structure doesn't require any fixed-length madness either; XML allows the chunks, or fragments, to bend and stretch as required, while still retaining their meaning.
This flexibility also comes in the form of extensibility. It's straightforward to add distinct "extensions" to a fragment in a way that does not compromise the integrity of that fragment and provides a structure to the extension added.
So why reinvent the wheel when there are tools that can be taken off the shelf to parse the data? There are many tried and tested XML libraries out there, and to be able to receive (from the parser) the Jabber data in a native format of your choice is a definite advantage.
Some of these arguments, concerning XML fragments and extensibility, will become clearer in Chapter 5. Until then, consider that Jabber makes good use of an XML feature called namespaces. (See 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.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Asynchronous Nature
The exchange and distribution of information in real-world scenarios requires more than a synchronous (sequenced) request/response framework. In IM, people originate chat messages in a spontaneous and unpredictable manner (especially if there's beer involved). In a loose network of independent applications, messages originate on a similar "random" event basis. This asynchronous activity requires a design equally asynchronous in nature—and that is what Jabber has.
To allow for the generation, and more importantly the receipt, of messages in an asynchronous fashion, Jabber's programming model for client and server alike is an event-based one. An event-based programming model is nothing to be afraid of. In simple terms, it's just a loop that iterates either doing nothing in particular or doing something regularly (like checking for user input and acting upon it if required) while waiting for something (an event) to happen. In Jabber's case, it will be the receipt of an XML fragment. Depending on what type of fragment it is, a handler will be called to deal with that fragment. We saw a simple example of this in the Perl script in Chapter 1.
In all but the simplest deployment examples of Jabber, the event model pervades. We will see the model in action in Part II. And while we've reduced the receipt of chat messages to a rather dry and generic event idea, let's also look at some concepts that often go hand in hand with event-based messaging systems.
Depending on circumstances, if you send a message to someone who's not currently connected, that message will be held and passed to the recipient when he does connect.
Likewise, in the wider context of application-to-application (A2A) or application-to-person (A2P) messaging, this store-and-forward concept is often useful in non-time-critical situations, such as a centralized logging mechanism in which the log-writing component might be temporarily unavailable or a workflow scenario in which an application passes a message to a supervisor for approval (in this case, the message would be similar to an email).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Messaging
We've been using the term "message" in quite a general sense, to represent data passing from one Jabber entity to another. In fact, as we'll see in Chapter 5, there are different sorts of messages—and each one has a certain role within the whole context of the Jabber protocol. They are sometimes referred to as elements, and there are three of them: <message/>, <iq/>, and <presence/>.
Actually, there are four, but the fourth, <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.
The <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.
Furthermore, we already know that these elements can be extended using namespaces. Each element and type, and each of the pre-defined namespaces (those that begin 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.
Table 2-1: Jabber elements and types
Element
Tag
Types
Message
<message>
normal, chat, groupchat, headline, error
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Payload Carrier
Earlier in this chapter we saw how a basic message was embellished with a structured and parseable "attachment" in the form of a 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>
How does this actually work in practice? Well, partly by requirement, partly by convention:
  • All three of the elements, <message/>, <iq/>, and <presence/>, can carry these attachments.
  • These attachments usually serve one of two purposes:
  • To bring primary (or secondary) meaning to the element that contains it.
  • To act as the driving force behind the element, such as that the element really exists only to carry the attachment.
This distinction is rather subtle, so let's look at a couple of examples.
Example 2-2 shows an attachment in the 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.
Example 2-2. A jabber:x:delay extension adds meaning to a <presence/> element
<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>
Example 2-3 shows us a message element containing a URL attachment. In this case, the element serves to carry the URL attachment; there is not really any other purpose to it. Delivering the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Request/Response
The HyperText Transfer Protocol (HTTP) is a great example of a simple, effective request/response model used on the Web to request and respond to requests for HTML and other content. Example 2-4 shows a typical HTTP request/response pairing, where GET /home.html HTTP/1.0 is the request, and everything else, starting with HTTP/1.1 200 OK, is the response.
Example 2-4. A typical HTTP request/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>
...
It shows us the request verb GET and the specification of what to retrieve (the /home.html document), and it shows us what is returned in response.
While we've already seen that the Jabber protocol is asynchronous in nature, there is a similar request/response model available, too, which tends to the synchronous (i.e., first request, then response), although, unlike HTTP, the response is not guaranteed to immediately follow the request. Other unrelated Jabber fragments may be received in the stream in the time between request and response. This request/response model is called Info/Query, or IQ for short; the Jabber element employed in the implementation of this model is <iq/>.
This IQ model has many uses in providing Jabber's basic IM features. Figure 2-1 shows the element traffic in a typical IQ-based conversation.
Figure 2-1: Element traffic in an IQ-based conversation
Example 2-5, Example 2-6, and Example 2-7 show typical uses of the <iq/> element to effect the IQ request/response model.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Component/Service Architecture
The original problem for Jabber to solve was to provide bridges to different IM systems; the upshot of the solution was a server design that is ultimately as flexible as the imagination allows. Each of the IM bridges, or transports as they are often called, is a pluggable component; the Jabber server architecture, examined in detail in Chapter 4, is a component-based architecture. The standard Jabber server distribution comes with the components required to provide IM services, data storage, and server-to-server communication, for example. Each component is separately configurable and is made known to the server through the inclusion of that configuration into the main configuration structure.
Components, also known as services, can be, to a large extent, platform agnostic. There are different methods by which components can connect to and interact with the Jabber server. One of these methods uses low-level Jabber library functions (in C) to bind the component (built in the form of a shared library) to the server. The other methods use either standard I/O (STDIO) in a process-spawning mechanism or TCP sockets.
Both the former library load method and the STDIO method require that the component runs on the same host as the Jabber server itself; this isn't in fact as restrictive as it sounds. As you'll find out in Chapter 4, it is possible to run multiple "instances" of a Jabber server across different hosts, each instance containing one or more components, in much the same way as, say, an SAP R/3 system can exist as multiple instances, each instance running on a separate host and providing different services (dialog, update, enqueue, message, background, gateway, spool) according to configuration.
Would it surprise you to learn that the binding fluid that flows between the Jabber server and components (and ultimately, of course, between Jabber clients and components) is XML? Of course not. In fact, it's the same XML that flows between Jabber clients and servers. There are extra message types that flow inside the server and between the components, including
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Custom Clients
Earlier in this chapter, we discussed features of off-the-shelf clients such as WinJab and Jarl, clients that natively support the <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.
What does this mean? WinJab supports a Jabber feature called browsing (see later in this chapter); Jarl supports connections to the server via an HTTP proxy. Some clients merely support a limited subset of Jabber as we know it; for example, the sjabber client supports only the conferencing features of Jabber. (As a somewhat biased observer, I would, of course, call this "extremely focused.")
Our definition of a Jabber client deliberately omits any mention of a user interface (let alone a GUI!). Indeed, human interaction in a Jabber solution is only an assumption formed from the hangover of the IM idea. Various efforts are underway to use Jabber as a transport for A2A messaging—the Jabber As Middleware (JAM) project is one such effort (at 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.
So, a Jabber client doesn't need to follow any particularly conventional model, except if you're developing an IM client, of course, and even then, flexibility and fitness for purpose are key. We will see this philosophy in action in Part II of the book, where we develop just enough Jabber client code to be able to connect to a server, authenticate, and deal with one-way alert-style messages. This is a key idea: you use as much, or as little, of what Jabber has to offer to build your solutions. This doesn't refer to the Jabber building blocks, but also to the existing software, in particular the clients. For example, if you wanted to develop a Jabber IM-based approval cycle workflow process, you could carry the approval data in a custom namespace-qualified message extension. In this case, you're going to have to build a custom client to interpret that extension. However, if you carry the approval data inside the body of a normal message, then you can more or less take your pick of ready-made clients. Furthermore, if you include URLs in the message body—which many graphical clients can render into an active link—you can easily bind in the power of existing web-based interactivity to complete the solution. We see an example of this in Section 10.4 in Chapter 10.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
XML-RPC and SOAP
Realizing that if Jabber is an XML router that can carry XML-based custom payloads in synchronous and asynchronous modes, we can immediately start to imagine scenarios in which Jabber fits as a transport glue in other already established application domains.
The XML Remote Procedure Call (XML-RPC) specification and the Simple Object Access Protocol (SOAP) both formalize method calls and responses in XML. The XML-RPC specification describes the use of HTTP to carry those encoded calls and responses between endpoints, and SOAP can use HTTP too. What if we carry XML-RPC or SOAP payloads in Jabber? We immediately see the step-change increase in contextual richness; XML-RPC interactivity becomes part of a wider, all-encompassing conversation between applications and humans. Indeed, the breadth of that interactivity increases too; Jabber affords a network transparency across traditional firewalls and Network Address Translation (NAT) mechanisms that often defeat HTTP-based calls.
Traditional IM-based clients, applications using client stub libraries, and components can all make use of the power these technologies have to offer, without having to leave the comfort of their Jabber environment, which can serve as a messaging plasma between all sorts of entities and services.
We will look at embedding XML-RPC-encoded calls in Jabber messages in Section 10.2 in Chapter 10.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Browsing
The more pervasive Jabber becomes and the more it is used, the larger the world of entities grows. And therein lies the challenge. How can we identify, organize, and navigate these entities in any useful way? Within the relatively narrow world of IM, the entities that exist (the IM users) and the hierarchies and relationships that are formed between them (where the only hierarchies are in the form of user rosters) don't really present much of a problem; as all the entities are users, there's no classification problem, and there's no hierarchical navigation problem. But within a system that regards users, applications, and services as equals (the unifying concept of a JID is an especially powerful device here), we need to have some way of searching, traversing, discovering, and querying these entities that is consistent regardless of what those entities are. Enter Jabber Browsing.
Browsing was introduced in Version 1.4 of the Jabber server to solve some specific problems with service discovery: how clients found out about what services (say, what IM transports) were available from the Jabber server that they were connected to. The namespace that supported the original discovery mechanism (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.
Browsing has since grown from that single problem space and can now be found in Jabber software everywhere. Want to find out what a user's client is capable of (so you can interact with it) or what it otherwise offers? Just browse to it. Want to find out what conference rooms currently exist on a particular conference service? Browse that service. Want to take a peek to see who's in one of the rooms? Navigate down one level to browse to the room (if this is permitted by that room).
There are four key elements that make browsing so flexible and so powerful:
Categorization
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Installing the Jabber Server
This chapter explains what you have to do to obtain, install, configure, and start up a Jabber server of your own with the minimum of fuss.
It's certainly possible to learn about the Jabber protocols and technology and develop solutions using someone else's Jabber server, but for real understanding and control, it's definitely worth setting up one of your own. By installing and configuring a Jabber server, you will gain a valuable insight into how it and its components work together. Understanding how components are controlled and configured allows us to build Jabber solutions in the context of the "big picture."
Installations of earlier versions (1.0, 1.2) of the Jabber server were often complex affairs, and while the installation process has become much more straightforward, some people still shrink back from installing and configuring their own. This chapter shows how straightforward it is.
If you already have a server set up, you might want to skip this chapter and go on to Chapter 4, where the configuration and system architecture are explained in more detail.
Although the Jabber development platform is Linux, the Jabber server will compile and run on many flavors of Unix, including FreeBSD, Solaris, AIX, and IRIX. Versions of the C compiler and make utility from the GNU project (at http://www.gnu.org) are recommended if you don't already have them installed.
The examples shown in this and other chapters are taken from Linux platforms (various Slackware and Red Hat distributions with 2.2 and 2.4 kernel versions); consult your local documentation for equivalent commands on your Unix OS.
The incarnation of the Jabber server at the time of writing is Version 1.4, more specifically 1.4.1. Version 1.4 represents a major advance in the server code and brings increases in performance and reliability over earlier versions. Jabber server Version 1.4.1 is the one we will obtain and install here, and this will be used as the server for the recipes in the rest of this book.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Downloading the Jabber Server
The Jabber server package can be obtained from the Jabber project site, 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
The tarball jabber-1.4.1.tar.gz contains everything that you need to get a Jabber server up and running. Previous versions of the Jabber server came in multiple packages; it was necessary to separately obtain and install GNU's portable threads library (pth) and the asynchronous DNS package (ADNS), as well as obtaining and installing various Jabber-specific libraries such as libxode, libjabber, and libetherx. Now some of these libraries and packages have become obsolete as far as the Jabber server is concerned (ADNS and libetherx) and others have been combined into the main Jabber server tarball.
If you don't want to compile the server yourself, you can also download prebuilt binaries for some of the platforms already mentioned, from http://download.jabber.org.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Installing the Server
Once you have downloaded the Jabber server tarball, you need to unpack it, configure the build environment, and compile the server. The general idea is that the Jabber server will be compiled and run from wherever you decide to unpack it; that is, there is no separate "install" step.
For this reason, and because it's also often useful to be able to install and start up a different version of the Jabber server for testing and comparisons, create a generic jabber directory somewhere central but local, for example in /usr/local/:
yak:/usr/local# mkdir jabber
               
The Jabber server does not need to be and should not be run as root; so create a new user jabber (group jabber) to be used as the Jabber server administrator and make that user the owner of the generic Jabber server directory:
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#
Once you've created the generic Jabber server directory, switch to the new Jabber server administration user jabber, unpack the tarball you downloaded, and enter the resulting directory:
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$
Examining the contents of the jabber-1.4.1 directory, we see the following files:
  • configure (the configuration script)
  • jabber.xml
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Configuring the Jabber Server
The nature and behavior of a Jabber server is controlled by the contents of a configuration file (with a default name of jabber.xml), which you will find in the jabber-1.4.1 directory. As you can probably guess from the filename's extension, the configuration is formatted in XML, which offers a very powerful way of expressing the nature and features of your Jabber server and associated services and components.
Details on how to navigate, interpret, and edit this configuration file are given in Chapter 4; here we will just look at the basic settings that can be modified before you start up the Jabber server.
For an experimental Jabber server (such as for the purposes of this book), there isn't actually anything you need to change in the configuration. The out-of-the-box configuration settings are pretty much what we need in order to experiment with our recipes later in the book; nevertheless, let's look at some of the settings you may wish to change right now:
Server hostname
The <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>
You can change this to the name of your server hostname; in the case of our examples, this would be yak.
The localhost setting occurs elsewhere in the configuration too—as a literal in the welcome message that is sent to users after a successful registration with the server. You may wish to replace this occurrence of localhost; furthermore, you will find other occurrences, but they are within sections of the configuration that are commented out in the standard delivered version of jabber.xml (specifically, administration JIDs and definitions for various add-on agents and transports; we will cover these in the next chapter).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Starting and Stopping the Jabber Server
At this stage, we have a Jabber server with enough basic configuration to be able to start it up and have it do something useful (like accept client connections). If you're curious about the rest of the configuration you encountered while editing the jabber.xml file, you can jump to Chapter 4. Otherwise, let's start it up!
The basic invocation looks like this:
yak:~/jabber-1.4.1$ ./jabberd/jabberd
                  
but if you haven't bothered to change localhost anywhere in the configuration (as described earlier), you can use the -h switch to specify the hostname:
yak:~/jabber-1.4.1$ ./jabberd/jabberd -h yak
                  
As it stands, there's a directive in the standard jabber.xml configuration file that specifies that any server error messages are to be written out to STDERR:
<log id='elogger'>
  <host/>
  <logtype/>
  <format>%d: [%t] (%h): %s</format>
  <file>error.log</file>
  <stderr/>
</log>
So either comment the directive out:
<!--
  <stderr/>
-->
Or redirect STDERR to /dev/null:
yak:~/jabber-1.4.1$ ./jabberd/jabberd -h yak 2>/dev/null
                  
You won't lose the error messages—as you can see they're also written to the error.log file.
Assuming you wish to free up the terminal session after starting the server, you can send it to the background:
yak:~/jabber-1.4.1$ ./jabberd/jabberd -h yak 2>/dev/null &
                  
Once the server is started, you're ready to start up a client and make a connection. The thing to remember at this point, when specifying which server to connect to, is to use the same hostname as you specified in the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Monitoring and Troubleshooting the Server
We've already seen a glimpse of the configuration relating to logging of messages in the previous section. As standard, the Jabber server configuration describes two types of logging record and a recipient file for each type:
Error logging
Error log records are written to error.log in the current directory, as determined thus:
<log id='elogger'>
  <host/>
  <logtype/>
  <format>%d: [%t] (%h): %s</format>
  <file>error.log</file>
  <stderr/>
</log>
Statistical logging
Statistical log records used for tracking purposes are written to record.log in the current directory, as determined thus:
<log id='rlogger'>
  <host/>
  <logtype>record</logtype>
  <format>%d %h %s</format>
  <file>record.log</file>
</log>
Log records of this type are written when a client connects to the server and when a client disconnects.
Furthermore, we can use the debugging switch (-D) when we start the server and have debugging and trace output written to STDERR.
A number of likely candidates might have prevented your server from starting.
Bad XML configuration
It is not difficult to make errors (typographical or otherwise) in the server configuration. The first line of defense is to be careful when editing your jabber.xml file. After that, the Jabber server isn't going to be too forthcoming with information if you have broken the well-formedness of the XML:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: Server Architecture and Configuration
If you followed Chapter 3 through, you should now have a Jabber server of your own up and running. If you also made the configuration changes described there, you may be curious to find out about the other 99 percent of the configuration file contents—what it does, what sort of structure (if any) exists, and how you might modify the configuration to suit your own requirements.
On the other hand, if you want to press on with learning about the the protocol and looking at the recipes, you can safely skip this chapter right now and jump to Chapter 5. Whenever you want detail on specific server configuration, you can come back here at any time. Indeed, we'll be referring to parts of this chapter throughout the rest of the book.
Despite the initially daunting and seemingly random nature of the jabber.xml file contents, there is a structure to the configuration. This chapter will take you through that structure, explaining how all the pieces fit together and describing what those pieces do. In order to understand the configuration structure, we examine the nature of the server architecture itself. This architecture is reflected in that structure, and if we are to understand the latter, it helps to understand the former.
Indeed, in order to take the best advantage of what Jabber has to offer in terms of being a basis for many a messaging solution, it's important to understand how the server works and how you as a programmer fit in. Jabber programming solutions can exist at different levels within the Jabber architecture; understanding this architecture can help you make better decisions about what needs to be done to build a solution.
So in this chapter, we'll take a look at the Jabber server architecture and follow that by an in-depth tour of the server configuration in jabber.xml. Finally, we'll have a look at some of the server "constellation" possibilities—how you can organize parts of the server to run over different hosts and how you can make the server host multiple virtual server identities.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
An Overview of the Server Architecture
In order to understand the configuration directives and how they work, it is necessary to take a step back and look at what the Jabber server really is.
The Jabber server is a daemon, jabberd, that manages the flow of data between various components that collectively make up the Jabber service. There are different components, each of which performs different kinds of tasks, and there is a basic set of components that is required for a simple Jabber server such as the one we configured and installed in Chapter 3.
The following list shows what the basic Jabber components are and what services they provide. It's worth considering the original and most well-known application of Jabber—instant messaging—and a Jabber design feature (distributed server architecture) to put this list into context and make better sense of it.
Session Management
We need to be able to manage users' sessions while they're connected to the server. The component that does this is called the Jabber Session Manager (JSM), and it provides IM features such as message store and forward and roster management, as well as session management.
Client (to Server) Connections
This is the component that manages the connections between clients and the server. It is known internally as c2s.
Server (to Server) Connections
If there's a requirement to send a message from a user on one Jabber server to a user on another Jabber server, we need a way for the servers to connect to each other. This component establishes and manages server-to-server connections and is known internally as s2s.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Server Configuration
At this stage, we should be fairly comfortable with the notion of a jabberd backbone and a set of components that combine to provide the features needed for a complete messaging system. We've looked at fragments of configuration in the previous section; now we'll examine the configuration directives in more detail.
It's not uncommon for people installing a Jabber server for the first time to be daunted (I was terrified!) by the contents of the jabber.xml configuration file. But really, for the most part, it's just a collection of component descriptions—what those components are, how they're connected, what packets they are to process, and what their individual configurations are.
There's a concept that encompasses Jabber's configuration approach that is taken from the object-oriented (OO) world—the concept of objects (and classes) and instances thereof. In Jabber server configuration, specifically the description of the components that are to make up a particular Jabber server, we talk about instances of components, not components directly.
In other words, a component is something generic that is written to provide a specific service or set of services; when we put that component to use in a Jabber server, we customize the characteristics of that component by specifying detailed configuration pertaining to how that component will actually work. We're creating an instance of that component.
Each component instance description follows the same approximate pattern:
  • Declaration of the component type
  • Identification (name) of the component
  • Specification of the host filter for packet reception
  • Definition of how the component is connected
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
A Tour of jabber.xml
Now that we know what patterns to look out for, we're well prepared to dive into a jabber.xml configuration file. As an example, we'll take one that's very similar to the default jabber.xml installed with Version 1.4.1 of Jabber, but we'll plug in some extra components: the conferencing component and a local JUD component.
The entire configuration content, with comment lines dividing up each section, can be found in Appendix A. It's definitely worth turning briefly to have a look at the XML before continuing, to get a feel for how the configuration is laid out.
In order to deal with it without going crazy, let's break down the XML into manageable chunks. We'll build configuration diagrams for each of the top-level tags that are children of the root tag <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>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Component Instance: sessions
The 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.
Figure 4-5: Diagram view of sessions component instance
The component also provides the services that give Jabber its IM capabilities— services such as roster management, message filtering, store-and-forward ("offline") message handling, and so on. These IM services are loaded individually as part of the component connection phase.
Example 4-8. jabber.xml configuration for the sessions component instance
<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>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Component Instance: xdb
The 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.
Figure 4-8: Diagram view of xdb component instance
All storage requirements by components connected to the Jabber backbone can be fulfilled by an 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.
Example 4-10. jabber.xml configuration for the xdb component instance
<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>
The opening tag identifies this component instance to the backbone as an xdb type component, as follows:
<xdb id="xdb">
This gives it a name, xdb, much in the same way that the sessions service has the name sessions.
For the host filter, we have an empty tag:
<host/>
specified, which signifies that this 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
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Component Instance: c2s
The 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.
Figure 4-9: Diagram view of c2s component instance
Example 4-12. jabber.xml configuration for the c2s component instance
<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>
The opening tag:
<service id="c2s">
identifies this component instance to the backbone as a service type component and gives it the name c2s.
The 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