JabChapter 2
From WikiContent
(insert content template) |
|||
| (6 intermediate revisions not shown.) | |||
| Line 1: | Line 1: | ||
| + | {{Content Programming Jabber}} | ||
=Inside Jabber= | =Inside Jabber= | ||
<br>Jabber has a number of features that are fundamental to its design philosophy. | <br>Jabber has a number of features that are fundamental to its design philosophy. | ||
| Line 186: | Line 187: | ||
<br> | <br> | ||
| + | <br> | ||
===Message Receipt=== | ===Message Receipt=== | ||
<br>In many cases, it's not much use sending a | <br>In many cases, it's not much use sending a | ||
| Line 196: | Line 198: | ||
namespace—<tt>jabber:x:event</tt>—which is described in Section 6.3.6 in | namespace—<tt>jabber:x:event</tt>—which is described in Section 6.3.6 in | ||
Chapter 6. | Chapter 6. | ||
| - | + | <br> | |
| - | + | ==Messaging== | |
| - | + | <br>We've been using the term "message" in quite a general | |
| - | == Messaging == We've been using the term "message" in quite a general | + | |
sense, to represent data passing from one Jabber entity to another. In | 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 | fact, as we'll see in Chapter 5, there are different sorts of | ||
| Line 285: | Line 286: | ||
* All three of the elements, <tt><message/></tt>, | * All three of the elements, <tt><message/></tt>, | ||
<tt><iq/></tt>, and <tt><presence/></tt>, can carry these | <tt><iq/></tt>, and <tt><presence/></tt>, can carry these | ||
| - | attachments. * These attachments usually serve one of two purposes: | + | attachments. |
| - | To bring primary (or secondary) meaning to the element that contains it. | + | * 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 | element really exists only to carry the attachment. This distinction is | ||
rather subtle, so let's look at a couple of examples. | rather subtle, so let's look at a couple of examples. | ||
| Line 390: | Line 392: | ||
Figure 2-1 shows the element traffic in a typical IQ-based conversation. | Figure 2-1 shows the element traffic in a typical IQ-based conversation. | ||
| + | [[Image:Jab 0201.png|center|350 px|Element traffic in an IQ-based | ||
| + | conversation]] | ||
| - | + | <br>Example 2-5, Example 2-6, | |
| - | + | ||
and Example 2-7 show typical uses of the <tt><iq/></tt> element to | and Example 2-7 show typical uses of the <tt><iq/></tt> element to | ||
effect the IQ request/response model. | effect the IQ request/response model. | ||
| Line 555: | Line 558: | ||
client time queries. | client time queries. | ||
<br> | <br> | ||
| - | |||
==Component/Service Architecture== | ==Component/Service Architecture== | ||
| - | <br>The original problem for Jabber to | + | <br>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 |
| - | 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 | imagination allows. Each of the IM bridges, or ''transports'' as they | ||
are often called, is a pluggable component; the Jabber server | are often called, is a pluggable component; the Jabber server | ||
| Line 605: | Line 605: | ||
other Jabber entities can be addressed: | other Jabber entities can be addressed: | ||
| - | * As a whole, the JID is simply the name of the component, for example, | + | * As a whole, the JID is simply the name of the component, for example, <tt>stocks.company-a.com</tt>. <br> |
| - | <tt>stocks.company-a.com</tt>. <br> | + | * Using individual "users" as if they existed as separate entities within that component, for example, <tt>MEGC@stocks.company-a.com</tt>. A version of this imaginary conversation will become reality in Part II as we learn how to build our own components and attach them to the Jabber server.<br> |
| - | * Using individual "users" as if they | + | |
| - | existed as separate entities within that component, for example, | + | |
| - | <tt>MEGC@stocks.company-a.com</tt>. A version of this imaginary | + | |
| - | conversation will become reality in Part II as we learn how to build our | + | |
| - | own components and attach them to the Jabber server.<br> | + | |
Although components are addressed in the same way that clients are | Although components are addressed in the same way that clients are | ||
| Line 640: | Line 635: | ||
details. To put it another way: | details. To put it another way: | ||
| - | * Send a message to a client that's not connected, and it will get | + | * Send a message to a client that's not connected, and it will get stored until that client connects and becomes available again. <br> |
| - | stored until that client connects and becomes available again. | + | * Send a message to a component that's not connected, and an error will occur. <br> |
| - | * Send a message to a component that's not connected, and an error will occur. | + | |
From a philosophical standpoint, this is fair enough, as you're trying | From a philosophical standpoint, this is fair enough, as you're trying | ||
to address a (temporarily) nonexistent feature of the server. From a | to address a (temporarily) nonexistent feature of the server. From a | ||
| Line 651: | Line 645: | ||
<br> | <br> | ||
| + | |||
==Custom Clients== | ==Custom Clients== | ||
<br>Earlier in this chapter, we discussed features of | <br>Earlier in this chapter, we discussed features of | ||
Current revision
Contents |
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.
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.
Qualifying a fragment extension with a namespace
|<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>
The main part of the fragment is the <message/> element
containing the <thread/> and <body/> tags.
The <message/> element is the "carrier" part of the
fragment:
|<message type='chat' from='jim@company-a.com/home'
to='john@company-b.com/Desk'> <thread>01</thread>
<body>Here's the link</body> </message>
But the fragment has been embellished by an extension that is qualified
by the jabber:x:oob namespace:
|<x xmlns='jabber:x:oob'>
<url>http://www.megacorp.co.uk/earnings3q.html</url>
<desc>Third Quarter Earnings for Megacorp</desc> </x>
The xmlns attribute of the <x/> tag declares that the tag and any children of that tag belong to, or are qualified by, the jabber:x:oob namespace. This namespace is used in Jabber to carry information about out-of-band (OOB) data: data that moves outside of the main client-server-client pathways. When a client sends a file directly to another client without sending that file via the server, this is said to be "out of band." See Section 6.3.8 in Chapter 6 for more details. This namespace is different from the namespace that qualifies the carrier <message/> tag and the other elements, <presence/> and <iq/>, that appear at the same level. The namespace that qualifies these tags is not explicitly specified as an xmlns attribute; rather, it is declared when the XML stream is established. It is over this XML stream that these elements flow. See Chapter 5 for more details on XML streams and namespaces.
The general point is that the jabber:x:oob-qualified extension is recognizable as an extension (by us and, more importantly, by the XML parser) and can be dealt with appropriately—we are likely to want to handle the information contained in the extension separately from the rest of the message.
So Jabber uses the extensible XML format to contain and carry data between endpoints.
"XML between endpoints"? That sounds rather generic to me—not something that's limited to providing an IM experience. Indeed, that's the whole idea.
"XML Router" is a moniker often used to describe Jabber by people who
have made this logical leap. Remove the IM mantle, and underneath we
find a system, an architecture, capable of being deployed to exchange
and distribute all manner of XML-encoded data.
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.
Store and Forward
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).
Queuing
Indeed, in the case of the recipient being offline and
messages being handled by a store-and-forward mechanism, or simply where
the recipient cannot handle the messages as fast as they arrive, the
nature of the XML stream in which these message fragments are
transmitted (see Chapter 5 for details) means that the messages are
naturally queued, to be handled in the order that they arrive.
Message Receipt
In many cases, it's not much use sending a
message to an application and having it queued or stored offline,
without knowing whether the recipient actually did (eventually) receive
and handle it. Jabber supports the concept of message
receipt,whereby the sender can request an acknowledgment of receipt
from the recipient. This request is sent along with the message itself.
Support for message receiptexists in the form of a
namespace—jabber:x:event—which is described in Section 6.3.6 in
Chapter 6.
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/>.
<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.
| Element | Tag | Types | |
|---|---|---|---|
| Message | <message> | normal, chat, groupchat, | headline, error |
| IQ | <iq> | get, set, result, error | |
| Presence | <presence> | available, unavailable, | subscribe, subscribed, unsubscribe, unsubscribed, error |
There's a certain amount of consideration to be given in this respect when designing our messaging solutions and applications; how should we employ the basic message types, and do we need to create our own custom extensions qualified by our own namespaces?
For the most part, the answers to these questions will depend on what sort of solution needs to be developed; however, it is also important to consider what support is already available off the shelf in the form of Jabber clients. This is especially the case if the application is A2P or P2A. These Jabber clients provide varying levels of features supporting the different elements and types. For example, WinJab (for Win32 platforms) and Jarl (cross-platform, written in Perl/Tk) both support the headline type <message/> and can display URL information, which typically comes attached to the message in a jabber:x:oob-qualified extension, in a useful way. If you're writing a news headline alert mechanism, for example, you may want to consider aiming development with a target of WinJab or Jarl in mind; the alternative is to develop your custom news headline viewer client. (Indeed, we do just that, in Section 9.4 in Chapter 9.)
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.
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 <message
type='headline'/> carrier without the payload wouldn't make much
sense.
A jabber:x:oob extension is the heart of a <message/> element
|<message type='headline'
from='jabbercentral@news.company-b.com' to='john@company-b.com'>
<x xmlns='jabber:x:oob'>
<url>http://www.jabbercentral.com/news/view.php?news_id='989358658
</url> <desc> Tomorrow, May 9th, a meeting regarding the
Jabber Foundation will be held. </desc> </x> </message>
The outermost tag of each attachment, by convention, is either <x/> or <query/> although they can be any valid XML tag name. The Jabber namespaces that are used to qualify these <x/> and <query/> attachments follow a convention, beginning with jabber:x: for those qualifying the <x/> attachments, and jabber:iq: for those qualifying the <query/> attachments.
The <x/> tag is used as a generic extension mechanism to add information to any of the Jabber elements, and <query/> is used to extend the <iq/> element.
The standard namespaces used in Jabber to qualify the <x/> and <query/> attachments are listed in Chapter 6. But we're not restricted to just those namespaces; we're free to build attachments qualified by custom namespaces, if we think that what we want to achieve isn't covered by anything out of the box. In this situation, there are two things to note:
- The namespaces cannot begin jabber:. * The receiving
recipient of the extended element must be able to appropriately
interpret the attachments.
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.
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.
Example 2-5, Example 2-6,
and Example 2-7 show typical uses of the <iq/> element to
effect the IQ request/response model.
A simple client version query via the IQ model
|SEND: <iq type='get' from='jim@company-a.com/home'
to='mark@company-a.com/Laptop-7' id='v1'> <query
xmlns='jabber:iq:version'/> </iq>
RECV: <iq type='result' to='jim@company-a.com/home' from='mark@company-a.com/Laptop-7' id='v1'> <query xmlns='jabber:iq:version'> <name>Jabber Instant Messenger</name> <version>1.7.0.14</version> <os>95 4.10</os> </query> </iq>
In Example 2-5 we see that the equivalent of HTTP's GET verb is
the type='get' attribute of the <iq/> element
and that the equivalent of what to get (/home.html) is our
namespace specification in the <query/> tag.
Example 2-6 shows a two-stage request/response model. First, a query is made, using the IQ-get type with an ID of reg1 (the id attribute), to discover which fields are required for user registration. Then, the actual user registration attempt is made with the IQ-set (ID reg2). In this second stage, we can see a link with HTTP's POST verb, whereby data is sent along with the request.[1]
A multiple-phase IQ to register a user
|SEND: <iq type='get' id='reg1'> <query
xmlns='jabber:iq:register'/> </iq>
RECV: <iq type='result' id='reg1'> <query xmlns='jabber:iq:register'> <instructions>Choose a name and pass to register.</instructions> <username/> <password/> </query> </iq>
SEND: <iq type='set' id='reg2'> <query xmlns='jabber:iq:register'> <username>helen</username> <password>tr0y</password> </query> </iq>
RECV: <iq type='result' id='reg2'/>
While HTTP is primarily a client/server protocol (although these words
have less and less meaning in a peer-to-peer environment in which each
participating entity can be both client and server), Example 2-5 shows
that the IQ model can be used in a client-to-client (or
server-to-server, or server-to-client, for that matter) context as well.
Example 2-7 shows how an IQ-based conversation can extend beyond the get ... result or set ... result model. It shows how the IQ model can be used to deliver results of a search request in stages.
Staggered response from IQ-based search request The search request:
|SEND: <iq type='set' to='ldap.company-a.com' id='801'>
<query xmlns='jabber:iq:search'>
<group>Support</group> </query> </iq>
The first part of the response is the first record found:
|RECV: <iq type='set' from='ldap.company-a.com'
to='jim@company-a.com/home' id='801'> <query
xmlns='jabber:iq:search'> <name>John Aston</name>
<phone>4701</phone> <group>Support</group>
</query> </iq>
The second record found:
|RECV: <iq type='set' from='ldap.company-a.com'
to='jim@company-a.com/home' id='801'> <query
xmlns='jabber:iq:search'> <name>Katie Smith</name>
<phone>4711</phone> <group>Support</group>
</query> </iq>
The last record found:
|RECV: <iq type='set' from='ldap.company-a.com'
to='jim@company-a.com/home' id='801'> <query
xmlns='jabber:iq:search'> <name>Jeremy Taylor</name>
<phone>4702</phone> <group>Support</group>
</query> </iq>
No more records have been found, and no more results are sent; instead,
an "end marker," signified by the type='result' attribute, is
sent:
|RECV: <iq type='result' from='ldap.company-a.com'
to='jim@company-a.com/home' id='801'> <query
xmlns='jabber:iq:search'/> </iq>
Because of the inherently asynchronous nature of Jabber, we need some
way of matching the responses received with the original request. After
all, if we were to fire off two requests almost simultaneously to ask
for the local time on our server and on a client in New Zealand:
|SEND: <iq type='get' from='jim@company-a.com/home'
to='piers@company-a.com/emacs'> <query xmlns='jabber:iq:time'/>
<iq/>
SEND: <iq type='get' from='jim@company-a.com/home' to='company-a.com'> <query xmlns='jabber:iq:time'/> <iq/>
we might find that the responses come back out of sequence (in our
view), because of the comparative network distances over which the two
conversations must travel. First this:
|RECV: <iq type='result' to='jim@company-a.com/home'
from='company-a.com'> <query xmlns='jabber:iq:time'/>
<utc>20010611T17:59:13</utc> <tz>CET</tz>
<display>Mon Jun 11 19:59:13 2001</display> </query>
</iq>
and then this:
|RECV: <iq type='result' to='jim@company-a.com/home'
from='piers@company-a.com/emacs'> <query
xmlns='jabber:iq:time'/> <utc>20010611T17:59:14</utc>
<tz>UTC+12</tz> <display>Tue Jun 12 06:59:14
2001</display> </query> </iq>
That's the reason for the id attribute in the examples earlier
in this section. Between a request and a response, any id
attribute value in the <iq/> element is preserved,
allowing the requester to match up <iq/> request/response
pairs. Using the id attribute, we can piece together related
fragments of individual conversations, which in this case were a pair of
client time queries.
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.[2]
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 <route/>, <xdb/>, and <log/>. These message types are explained in Chapter 4.
The <message/>, <iq/>, and <presence/> elements can all flow to and from components—how a component handles or generates these elements reflects the purpose of that component. As we saw in the imaginary conversation in Chapter 1, components can also be addressed in the same way that other Jabber entities can be addressed:
- As a whole, the JID is simply the name of the component, for example, stocks.company-a.com.
- Using individual "users" as if they existed as separate entities within that component, for example, MEGC@stocks.company-a.com. A version of this imaginary conversation will become reality in Part II as we learn how to build our own components and attach them to the Jabber server.
Although components are addressed in the same way that clients are addressed, and the interaction is similar, there is one significant difference between writing or using a client (which could just as well be a stub connector for a service) and writing or using a component.
This difference is rooted in the Jabber server architecture and becomes clear when we consider the nature of how the components provide their services. Messages sent to a client entity that is not connected will be stored and forwarded to that entity the next time it connects and becomes available. This is because the client's connection is inherently hosted, or managed, by the standard component that provides IM services such as availability handling and message queuing. This is the Jabber Session Manager (JSM) component. All clients are handled this way and automatically partake of these features. All entities that connect over a stream with the jabber:client namespace are considered clients, and their XML-based interaction is handled by the JSM.
Because other components connected to the Jabber server are peer components to the JSM component, no availability or message queueing is available, as the JSM is designed to handle only client-connected entities. The components that connect as separate entities (i.e., those that aren't written as shared libraries) do so over a stream that is described by one of two namespaces, each beginning jabber:component:. See Chapter 4 and Chapter 5 for more details. To put it another way:
- Send a message to a client that's not connected, and it will get stored until that client connects and becomes available again.
- Send a message to a component that's not connected, and an error will occur.
From a philosophical standpoint, this is fair enough, as you're trying to address a (temporarily) nonexistent feature of the server. From a practical standpoint, this is not usually a problem unless you're in the habit of restarting your Jabber server to randomly connect or disconnect components.
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.
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.
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
- Browsing follows the MIME model in defining categories and
- subcategories, but rather than content being categorized
- (text/plain, image/png, and so on), the
- categorization in browsing is of entities that can be browsed to.
- Categories are used to describe users, services, agents, conferencing
- mechanisms, applications, and so on. Within these categories, the
- subcategories are used to make finer distinctions
- (service/pager, conference/private,
- user/device, and so on).
- Identification
- Every entity described in browsing is identifiable by a JID; the world
- is homogenized, so to speak. The JID is the key to browsing navigation
- as, when listed in a browse result as identifiation for an entity,
- that JID can be used as the target of the next browse request.
- Hierarchy
- Browsing describes entities in the Jabber world. But the world isn't
- flat—it's hierarchical! Relationships between entities are easily
- established and described by placing browse information in
- hierarchies. These hierarchies, these relationships, are represented
- in XML. A typical browse response might contain descriptions of
- entities on one or two levels. These levels can be navigated simply by
- choosing the JID of the desired node and making a further browse
- request, creating an instant "drill-down" method to access
- information.
- Discovery
- It might be that the only information you have about any particular
- entity is its JID. You've been passed the JID from someone else, or
- you've found it when browsing a hierarchy of relationships. Browsing
- to that entity allows you to find out more—to discover what
- features and services it supports, through a list of namespaces
- returned in response to that browse request. So, Jabber entities can
- be classified, given identities, organized into hierarchies, and
- navigated. What takes place from there is really up to the
- imagination. But what is a Jabber entity? For the sake of
- argument, let's say it's anything that has a JID. Does having a JID
- presume having an IM user account with a Jabber server? Not
- necessarily, as we'll see. So as long as we assign a JID to something
- we wish to include in the Jabber world, most anything goes. In Section
- 10.3 in Chapter 10, we build an LDAP "reflector" service that enables
- us to browse LDAP information from within our Jabber clients.
Browsing is a combination—a culmination even—of many of the Jabber features. Browsing is carried out in the context of the IQ request/response mechanism and uses a namespace-qualified payload to carry the data whose hierarchy is naturally expressed in XML. Browsing bridges, philosophically and technically, the distances between the Jabber and non-Jabber spaces.
