Jabber Boot Camp
Ralph Meijer & Peter Saint-Andre
Jabber Software Foundation
Agenda
- Why Are You Here?
- Technology Overview
- How Jabber/XMPP Works
- A Simple Bot Example
- Jabber/XMPP Extensions
- Writing a Component
- Go Forth and Implement
Why Are You Here?
- You've heard that Jabber is a cool technology
- You want to write / improve a Jabber IM client
- You want to write / improve a Jabber server / component
- You want to add presence to an existing application
- You want to add real-time interaction to an existing application
- You want to solve Problem X in your project / company
What is Jabber?
- Real-time messaging technology
- Route XML from Point A to Point B
- Federated (inter-domain communications)
- Like email, but really fast
- Built-in presence
- Strong security
- No spam!
- An open standard (RFCs 3920 + 3921 etc.)
Applications
- Instant messaging
- Content syndication (RSS/Atom)
- Whiteboarding (SVG)
- Workflow processing
- Network management
- Lightweight middleware
- Real-time social networking
- [insert your idea here]
History
- Invented by Jeremie Miller (1998)
- First server + clients + libraries (1999-2000)
- More open source + commercial codebases (2000+)
- Core standardization in IETF as XMPP (2002-2004)
- Development of extensions (2002+)
- Serious adoption by Apple, Google, LiveJournal, etc. (2005+)
Open Source Servers
- jabberd 1.x (C)
- jabberd 2.x (C)
- ejabberd (Erlang)
- Wildfire (Java)
- djabberd (Perl)
- Pretzel (Python)
==> Take control and run your own server!
Open Source Clients
- Adium (C + Java)
- Exodus (Delphi)
- Gaim (C)
- Gajim (Python)
- Gossip (C)
- Kopete (C++)
- Psi (C++)
- Spark (Java)
Open Source Libraries
- gloox (C++)
- Jabber-Net (C#)
- JSO (Java)
- libstrophe (C)
- Loudmouth (C)
- Net::XMPP (Perl)
- Smack (Java)
- Twisted Words (Python)
- xmpppy (Python)
How Does it Work?
- Streaming XML over TCP connections
- Client server architecture (but also "link-local" mode)
- SSL/TLS for channel encryption
- SASL for strong authentication
- Domain-name-based routing
- Full UTF-8 / Unicode support
- Message, presence, request-response, and publish-subscribe semantics
- XML namespaces for payload extensions
Privacy and Security
- Presence subscription "handshake" for authorization
- Pure XML -- no MIME types, attachments, etc.
- Diverse client and server ecosystem
- No server spoofing (reverse DNS lookups)
- IP addresses not revealed
- Channel encryption (SSL/TLS, deploying server certificates)
- Strong authentication (DIGEST-MD5, Kerberos, etc.)
- End-to-end encryption being improved
XML Streams
- Open a TCP connection
- Send a <stream> header
- Incrementally parse XML
- Close the </stream> when done
- Easy, right?
A Simple XML Stream (Part 1)
<stream xmlns='jabber:client' to='capulet.com' ...>
[authentication]
<iq from='juliet@capulet.com/balcony' type='get' id='foo'>
<query xmlns='jabber:iq:roster'/>
</iq>
<iq to='juliet@capulet.com/balcony' type='result' id='foo'>
<query xmlns='jabber:iq:roster'>
<item jid='romeo@montague.net'/>
</query>
</iq>
<presence/>
A Simple XML Stream (Part 2)
<message from='juliet@capulet.com' to='romeo@montague.net'>
<body>Art thou not Romeo, and a Montague?</body>
</message>
<message from='romeo@montague.net' to='juliet@capulet.com'>
<body>Neither, fair saint, if either thee dislike.</body>
</message>
<presence type='unavailable'/>
</stream>
Simple, But There Can Be Challenges
- Incremental parsing can require two parser instances (one to hold <stream> context, one to parse XML "stanzas")
- Actually two streams: one in each direction
- Internationalization via UTF-8 encoding
-
Cutting-edge IETF technologies not widely supported yet...
- Transport Layer Security (TLS) -- IETF improvement to SSL
- Simple Authentication and Security Layer (SASL) -- framework for authentication methods
- Stringprep -- case folding for Unicode characters (e.g., Π to π)
- BUT: Libraries typically abstract all these details
Coding a Simple Stream (xmpppy)
#!/usr/bin/env python
import xmpp
jid = xmpp.JID("juliet@capulet.com")
password = "R0m30"
toJid = "romeo@montague.net"
msgText = "Wherefore art thou?"
cl = xmpp.Client(jid.getDomain())
cl.connect()
cl.auth(jid.getNode(), password)
cl.sendInitPresence(requestRoster=1)
cl.send(xmpp.Message(toJid, msgText))
cl.disconnect()
Extending XMPP
- Core XML routing protocol standardized in IETF (RFC 3920)
- Basic IM extensions also standardized in IETF (RFC 3921)
- XML stanzas contain extensions via XML namespaces
- Extensions typically developed in Jabber Software Foundation's JEP series (open community standards process)
- Can write your own "private" extensions if desired for custom functionality
Chatrooms
-
JEP-0045: Multi-User Chat
- Virtual "rooms" for multiple participants
- Like IRC, but stronger owner/admin model
- In-room presence (doesn't exist in IRC)
- Very popular in organizations (trading desks, incident rooms)
- Messages are extensible (gaming, in-room voting, etc.)
Discovering Capabilities
-
JEP-0030: Service Discovery
- disco#info: entity's identity plus supported protocol namespaces and features
- disco#items: associated entities (server components, chatrooms, devices, etc.)
- Send request, receive response
-
JEP-0115: Entity Capabilities
- Dynamic "profile" of service discovery
- Advertise supported features via presence
- Saves bandwidth if cached (no "disco flood")
User Info / Social Networking
- vCard / Profile (static)
- Geolocation
- Mood
- Activity
- Tune
- Video (movies/TV)
- Chatrooms
- Browsing
- Gaming
How Do We Publish This Information?
- Old approach: overload presence
- Better approach: publish-subscribe (JEP-0060)
- Generic mechanism for multi-casting information
- Subscribe to nodes of interest
- Receive items as soon as they are published (no polling)
- Your user@host address can be a virtual pubsub service, too (JEP-0163)
PubSub Applications
- Social networking (Plazes, last.fm, etc.)
- Real-time RSS readers
- Fat pings for the FeedMesh (Atom over XMPP)
- Data syndication
- Tickers / news feeds
- Update financial models in real time
- Location-based marketing
- Lots of potential mashups!
Alternative Connection Methods
- Client-server TCP is not always realistic or available, so...
-
JEP-0124: HTTP Binding
- Great for constrained devices / intermittent networks
- Pipelining to reduce polling requirements
-
JEP-0174: Link-Local Messaging
- Zero-configuration networking (Rendezvous)
- No need for a server, runs anywhere (LAN, hotspot, etc.)
- Can deliver messages locally for handoff to stable network
Structured Data Exchange
-
JEP-0004: Data Forms
- Similar to HTML forms
- Great for configuration, lightweight workflow processing, automated systems, etc.
-
JEP-0009: Jabber-RPC
- Real-time transport for remote procedure calls
-
JEP-0072: SOAP Over XMPP
- Real-time transport for SOAP payloads
- Official SOAP binding
Collaboration
-
JEP-0096: File Transfer
- Exchange single files between two users
- Not optimized for multiple files
- NAT traversal is less than ideal
- May be replaced with Jingle...
-
Whiteboarding
- Exchange Scalable Vector Graphics (SVG) over XMPP channel
- Several projects in existence (Inkboard, Coccinella, etc.)
- Protocols being harmonized and standardized
-
Collaborative Editing
- Generalize SVG to any XML document format (under development)
Jingle
- Session negotiation over XMPP channel
- Direct or relayed media path
- Transports: RTP (ICE), direct UDP, etc.
- Content: voice, video, etc.
- Support: Google Talk, Asterisk, FreeSWITCH, etc.
- Applications: voice chat, video chat, file sharing, PBX federation, etc.
An Atom over XMPP news ticker
- Push instead of Pull (HTTP)
- Using Publish-Subscribe
- Node per news source
- Access control on publishers
- Items with atom:entry as payload
- MimÃr aggregator
- Universal Feed Parser
Example entry
<entry xmlns='http://www.w3.org/2005/Atom'>
<id>http://ralphm.net/#1</id>
<title type='text'>Example entry</title>
<summary type='text'>This is a sample entry</summary>
<link href="http://mimir.ik.nu/"
rel="alternate"
type="text/html">
<published>2006-08-18T16:37:00+00:00</published>
<updated>2006-08-18T16:37:00+00:00</updated>
</entry>
import sys, feedparser, client
from twisted.internet import reactor
class Client(client.Client):
logTraffic = False
def initialization_failed(self, failure):
print 'Initialization failed: %s' % failure
def authenticated(self):
self.xmlstream.send('<presence/>')
self.xmlstream.addObserver('//message/event/items', self.onItems)
def onItems(self, message):
items = (e for e in message.event.items.elements()
if e.name == 'item' and e.entry)
feed = '<atom xmlns="http://www.w3.org/2005/Atom">'
for item in items:
feed += item.entry.toXml().encode('utf-8')
feed += '</atom>'
parsed_feed = feedparser.parse(feed)
for entry in parsed_feed.entries:
print entry.title
Client(sys.argv[1], sys.argv[2]).connect()
reactor.run()
Further Resources
- http://www.jabber.org/
- mailto:jdev@jabber.org
- xmpp:jdev@conference.jabber.org
- [mailto:|xmpp:]stpeter@jabber.org
- [mailto:|xmpp:]ralphm@ik.nu
Conclusion
- The real-time Internet is coming
- Build competitive advantage using open technologies
- What problems can you solve with Jabber?
- Join the conversation
- Happy Jabbering!