Log in

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: brad
2006-03-03 04:07 pm (UTC)
At least it's well-formed. If not, you disconnect the client with a stream error.

Great thing is often you have to send clients just the right XML, or they barf. If you send semantically identical XML but not how other clients produce ... boom. Makes me question if they're actually using XML parsers or being lazy and using sscanf.

Also, most server code out there ignores XML namespaces.... so sad.

But once I did a bunch of XML helper stuff, it's been easy.
(Reply) (Parent) (Thread)
[User Picture]From: mart
2006-03-04 12:40 am (UTC)

It upsets me that people manage to get XML so wrong. However, it doesn't surprise me in the least.

(Reply) (Parent) (Thread)