Log in

No account? Create an account
Modular Jabber Server: DJabberd - brad's life [entries|archive|friends|userinfo]
Brad Fitzpatrick

[ website | bradfitz.com ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Modular Jabber Server: DJabberd [Mar. 2nd, 2006|11:42 pm]
Brad Fitzpatrick
[Tags|, , , ]

UPDATE 2006-04-12: This ancient post is still the top Google hit, so go here for new information DJabberd website.
I've been hacking on a Jabber server lately and getting other people at the company also hacking on it with me. Tonight Artur and I did SSL support and fixed a ton of bugs and missing features. Started to work on s2s/dialback, now that we have SSL, but got tired, and I have jury duty in the morning.

The idea of the server is that it's a dummy shell / base class that you either subclass and/or instantiate a bunch of hook handlers for. (in the spirit of mod_perl, qpsmtpd, etc...)

It'll be usable for:
-- my personal jabber server, on "fitzpat.com" (maybe), but for other dorks
-- our company-internal jabber server, using LDAP auth (an auth plugin)
-- LiveJournal (lots of machines in one logical domain)

The main pluggable phases now are auth and roster management, and you can subclass to handle new stanzas, or to change message routing behavior, etc.

So far we have plugins for:
-- DJabberd::Roster::LiveJournal
-- DJabberd::Auth::StaticPassword
-- DJabberd::Auth::AllowedUsers
-- DJabberd::Auth::LiveJournal

So it's flexible.

Here's the main executable:

my $server = DJabberd->new(
           daemonize => $daemonize,
           s2s       => 1,
           auth_hooks => [
                DJabberd::Auth::AllowedUsers->new(policy => "deny",
         allowed => [qw(brad crucially bradfitz bob test)]),
                DJabberd::Auth::StaticPassword->new(password => "password"),
               #DJabberd::Auth::LiveJournal->new(server => "livejournal.com"),
            roster_hooks => [ DJabberd::Roster::LiveJournal->new(
                       server => "livejournal.com")

Also, all the hook chains are processed async, so you have as much time in your handlers as you want, and you can call the callbacks with your response whenever, without stalling the event loop. Or you can be lazy and synchronous for small sites.

Before I started working on it, Artur and I looked into ejabberd, jabberd2, and some other things. They're just not extensible enough. We started to add pluggable roster management to them, but it was getting painful.

One day Artur comes in and says, "Dude, why don't we write our own?" I started to reply that it'd be hard, but I stopped myself and was like, "oh, right... just an event loop that feeds incoming data to a SAX parser..."

Turns out CPAN is full of bad XML code, bad Jabber code, and really bad SSL code. So it wasn't quite as easy as it should've been, but it wasn't that bad. To be fair, a lot of CPAN is good, but crap always outnumbers quality.

Don't go looking at the code yet. It's horrid at the moment, while we rearrange/tinker/etc. But I'll be posting more about it as it mature.

[User Picture]From: mart
2006-03-03 08:07 am (UTC)

For ages now I've had on my to-do list “make XML stuff on CPAN not suck”, but unfortunately other projects that are more fun keep beating it. What I really want to do is make all of the XML modules operate on a common DOM so that you can chuck documents/nodes from one to another freely. Currently each library seems to implement its own DOM-like datastructures that aren't interchangable.

My canonical example is that you can parse a document with LibXML and get back a DOM, then give the DOM to the XPath library to extract a bunch of Atom entry elements and then give those element nodes to the Atom parser library and have it parse them. The Atom library would then return an Entry object which is a subclass of a DOM Element so you can still do XPath/DOM on it to extract funny extension elements that the Atom library doesn't know about.

If only there were more hours in a day…

(Reply) (Thread)