UPDATE: Official documentation is now available, including several details not mentioned here

Some notes on the protocol used by atlassian's hipchat, a slight variation of XMPP. Despite my initial impressions of it being weird and ugly, it's surprisingly decent and close to the standards. Still a bit weird, though

These notes assume proper support of standard XMPP already, only document the differences with it.

The official knowledgebase has a page for XMPP support details with a few high level support details.

Summary of differences

  • New auth packet
  • Different username
  • No concept of session bind, but the <success> packet has a similar effect.
  • A few additional supported <iq>
  • mention_name attributes
  • MUCs require using a specific nickname
  • File transfer is done through http

Debugging

Getting protocol debug is super trivial. So much that this page may not even be very useful.

The linux client can be started with the following commandline:

hipchat --debug --verbose --dont-strip-messages

This will print all traffic and other useful debug information to stderr.

Additionally, this may be done through the GUI. The official docs mention how to do this

Authentication

Using starttls is required. After that:

RX: <stream:features><auth xmlns='http://jabber.org/features/iq-auth'/><auth xmlns='http://hipchat.com'/><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>PLAIN</mechanism></mechanisms></stream:features>
TX: <auth xmlns='http://hipchat.com'>...base64 encoded data...</auth>

The advertised server auth methods include iq-auth (XEP-0078, obsolete), hipchat's own auth (<auth xmlns='http://hipchat.com'/>), and SASL plain.

Hipchat's own auth is a slight variation on SASL PLAIN, compare:

TX: <auth xmlns='http://hipchat.com'>...base64 encoded data...</auth>
username = "your.username@example.com"
data = base64("\x00" + username + "\x00" + password + "\x00" + resource)

vs:

TX: <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">...base64 encoded data...</auth>
username = "11111_22222@chat.hipchat.com"
data = base64("\x00" + username + "\x00" + password)

First difference is that hipchat's auth uses the real email address of the user instead of the actual JID, which is left for internal use.

Auth packet response

Using hipchat's auth also changes the authentication flow considerably.

RX: <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl' jid='11111_22222@chat.hipchat.com/resource' api_host='api.hipchat.com' chat_host='chat.hipchat.com' muc_host='conf.hipchat.com' web_host='www.hipchat.com'/>

vs normal success:

RX: <success xmlns='urn:ietf:params:xml:ns:xmpp-sasl' />

At this point, if you restart the stream and bind the session the usual way, the server will just ignore you. (Using SASL plain will let you do this, however.)

The additional attributes

Post-login IQ requests done by the client

TX: <iq id="qxmpp2" from="11111_22222@chat.hipchat.com/linux" type="get"><query xmlns="jabber:iq:roster"/></iq>"
TX: <iq id="qxmpp3" to="conf.hipchat.com" type="get"><query xmlns="http://jabber.org/protocol/disco#items" node="Rooms"/></iq>"
TX: <iq id="qxmpp4" type="get"><query xmlns="http://hipchat.com/protocol/startup"/></iq>"
TX: <iq id="qxmpp5" type="get"><query xmlns="http://hipchat.com/protocol/emoticons"/></iq>"
TX: <iq id="qxmpp6" to="11111_22222@chat.hipchat.com" type="get"><query xmlns="http://hipchat.com/protocol/profile"/></iq>"

qxmpp2 and qxmpp3 are standard requests, nothing interesting here. The replies have a few extra fields which might interest you. For example, each item of the roster has a mention_name attribute.

qxmpp4, qxmpp5 and qxmpp6 are hipchat specific.

The "startup" request returns several potentially useful fields, user preferences, autojoins, and your own mention name. Can be skipped.

The "emoticons" request returns a XML description of "funny internet memes". Can be skipped.

The responses of these are self-explanatory, if you happen to care about implementing those.

qxmpp6 is a profile request done to yourself. Can be skipped, but either this or the "startup" request should be done to get your own mention_name.

Joining MUCs

All standard stuff here - you just need to set your mention_name as the MUC nickname to be able to join.

XEP-0203: Delayed delivery

This is used to specify the timestamp of backlog msesages.

<delay xmlns='urn:xmpp:delay' stamp='2013-09-09T01:50:52Z' from_jid='11111_22222@chat.hipchat.com'/>

There's one slight difference with the standard, the "from" field is called "from_jid". This is not guaranteed to be a valid JID from the roster, however. Sometimes it is just the MUC JID.

Infinite scroll

This is done with a http://hipchat.com/protocol/history iq. The target can be either a user or a groupchat.

<iq id="qxmpp26" to="11111_name@conf.hipchat.com" type="get"><query xmlns="http://hipchat.com/protocol/history" type="groupchat" before="2013-09-08T23:01:02Z"/></iq>

<iq id="qxmpp11" to="11111_22222@chat.hipchat.com" type="get"><query xmlns="http://hipchat.com/protocol/history" type="chat" maxstanzas="50"/></iq>

File transfer

This is nothing like the standard p2p mess of jabber - you get 5gb of storage in amazon s3, and most of it is managed through xmp.

Receiving files falls back nicely - you just get a message with an http link to the file.

Uploading files is done through http and you just send a reference to it through XMPP.

TODO: details.