Tuesday, February 26, 2008

Towards an Open Source XMPP Framework for Cocoa

A long time ago I promised I'd release our XMPP implementation. I'm making good on that promise today. Read on for details.

XMPP ("Extensible Messaging and Presence Protocol" aka Jabber) is a popular protocol which is very useful in a variety of situations and programs. It's a lot more than just instant messaging! For example, the presence notifications alone could be useful to help clients discover remote servers or vice-versa. We use XMPP in Mojo to help clients create direct TCP connections. There's a lot of potential for use outside the narrow scope of IM.

In terms of development, there are a handful of XMPP libraries available:

List on Jabber.org
List on Wikipedia

However, you'll notice neither list includes an Objective-C/Cocoa implementation. This doesn't make it impossible to use one of the listed libraries. One can always use a C or C++ library. Although I won't promise it won't give you headaches or that you won't regret it.

There has been work on XMPP in Cocoa:

JabberFox is an old Jabber client for Mac OS X. Written in Cocoa, but hasn't been updated since early 2002.

Colloquy is a Mac chat client which is still in development. It uses the "acid" library, originally written back in 2003 (I think). Browsing their subversion library online, it looks like the acid library was copied from Fire and has received only minor changes.

XMPPFramework - I got really excited when I first stumbled upon this page. But then my hopes sank when I realized it was never released, and hasn't been touched since early 2007. For all I know, they may have only written the interface and not a single line of implementation. :(

Reading over the XMPP code from Colloquy, I was very impressed. It had a lot of good stuff, although it showed it's age a bit. For example, it uses it's own XMLElement class. This is no longer needed as 10.4 introduced it's own set of XML classes such as NSXMLElement, NSXMLNode, etc. It also uses the expat parser. Certainly not a bad parser (I actually wrote a Cocoa wrapper for it back in the day). But I wonder if it would have been used today as 10.3 introduced NSXMLParser, and 10.4 added XQuery and XPath stuff.

So I got to thinking about what it might take to write the basic code for a Cocoa XMPP framework, and I guessed that it might not be too difficult. It tured out to be a little harder than I thought, but not impossible. What I'm releasing is certainly not a full framework. But it could be used as the basis/beginning of one. It's pretty much just a single class at this point: XMPPStream. It has the basics down:

- Connect to a host
- Registartion
- Authentication
- Support for SSL and STARTTLS

So at this point you can actually use the available code to login to Google Talk, and chat with your friends. All you have to do is instruct the class to connect to the proper server, authenticate, and handle the delegate messages:



- (void)xmppStream:(XMPPStream *)xs didReceiveIQ:(NSXMLElement *)iq;
- (void)xmppStream:(XMPPStream *)xs didReceiveMessage:(NSXMLElement *)message;
- (void)xmppStream:(XMPPStream *)xs didReceivePresence:(NSXMLElement *)presence;


Download the code here from Google Code Project.

Remember: I'm not writing a chat client, and that's not the purpose of this source code. The GUI exists solely as testing for the XMPP library.

What still needs to be done:
Write nice little wrapper classes (that extend NSXMLElement) for IQ, Message and Presence elements. Something like XMPPIQElement, XMPPMessageElement, and XMPPPresenceElement. These would ideally have convenient methods for accessing common information.

Write an XMPPClient, which automatically handles fetching and updating the roster, and offers convenient methods for adding/removing users.

Write XMPPRoster class.

I've more or less implemented much of the above. I just haven't written out a nice API for it.

Perhaps this code will be useful. Perhaps somebody will use it to help make a full framework. Perhaps they'll modify somebody else's code. Perhaps they'll write their own. I really don't care how it gets done, the important thing is that Cocoa programmers get their own open source XMPP library.

16 comments:

chanson said...

Have you thought about putting this in Google Code or on Sourceforge? It's a lot easier to keep up with changes to Open Source projects that way - especially if they have an issue tracker and project page etc.

Robbie Hanson said...

That's an excellent idea. It's now here:
http://code.google.com/p/xmppframework/

simplicidade.org said...

Hi,

nice work.

Another suggestion: add your library to the http://jabber.org/ site, under the Code Libraries section.

This will make it easier to find.

Mark Malone said...

I was able to compile the app just fine but want to make it better. What's the process

Robbie Hanson said...

If you're interested in improving the code, just check out the latest version from here:
http://code.google.com/p/xmppframework/

Make any improvements you want, and then just send me the changes. I'm always looking to add developers to the project.

Abhinav Maheshwari said...

Excellent information. Just for completeness, I would like to mention this jabber client tested on iPhone.

http://code.google.com/p/ichabber/

Warm regards,

Robbie Hanson said...

Hi Abhinav,

Thanks for the info! The only problem I see with ichabber is that it's licensed under the GPL, which makes it worthless to any commercial developer, or anybody who wants to sell their app in the app store.

On a related note, several developers have been helping recently to make the xmpp framework compatible with the iPhone, and I just committed these changes.

Martin said...

In case you're interested I've been working on my own little XMPP library... It's currently unstable and nowhere near complete but it's getting there...

http://www.martinpetrov.com/xmpp

Have a look at XMPPTest.m to get a general idea of what the API looks like, although it will most likey change in the future.

I'm going for a fairly high level of abstraction here, currently it's only been tested with the google servers. The current version should only compile in Leopard, though I've been doing my best to make it somewhat backwars compatible. I've also been trying to keep everything highly threadsafe, but it's still rather sloppy. Note that this is my first large Objective-C project, so don't bash on the quality of my code too much. Hit up my email or gtalk if you have questions or comments: martin [at] martinpetrov.com

Tharindu said...

Hi
I have got the code from google code and try to use it with iPhone, I am new to iPhone application development. When I try to compile after step 2, I get linking dependencies. How to solve this can you help. Please tell it in detail. Because I am really new with xcode and iphone apps.
Thanks
tharindufit@gmail.com

Robbie Hanson said...

KissXML has some dependencies that we forgot to write down in step 2. Go here for a description of how to fix the problem:
KissXML - Getting Started

ikarius said...

How can you integrate SSCrypto on an iPhone without openssl ?

Robbie Hanson said...

The XMPPFramework doesn't use SSCrypto when running on the iPhone. In this case it uses CommonCrypto. (See the file NSDataAdditions.m)

See here for How to use XMPP Framework on the iPhone.

Paul Cunningham said...

Hi Guys,
Has anyone got/or seen code to do the Avatars pub/sub?

David said...

Any chance you have a Jingle layer to go on top of this?

Yepher said...

The xmppStream framework looks nice. I was having a quick read through the code and noticed a potential issue.

In LibIDN.m there is the statement "JID MUST NOT be more than 1023 bytes". Which is true. But with '@' and '/' seperators I believe that buffer can end up needing to be a lot larger. Wouldn't 3072 be a safer buffer size?

I have only started looking through the code so I am not 100% sure this is a problem yet...

yepher said...

Ooops, I see how LibIDN gets used now. the 1024 should be fine.. Sorry about that.