XMPP Schema
From Mugshot Developer Wiki
This document is a little bit out of date, but is mostly accurate. Look at the file client/common/hippo/hippo-connection.c for the client-side source code and in wildfire/ for the Jive Wildfire plugin that sends it.
Our XMPP (aka Jabber) server is not usable as a plain chat server; its "identity system" is the Mugshot site instead of normal Jabber IDs, and its chat rooms are attached to Mugshot shares and groups. In other words we're repurposing an XMPP server to implement our own protocol.
We use this protocol to integrate the live social experience of Mugshot into the desktop and applications, when our design efforts suggest said integration makes sense.
Contents |
Common elements
These are some elements that can be embedded in multiple different notifications; all of the notifications they are sent in currently have the namespace xmlns="http://dumbhippo.com/protocol/post" so these can be considered to be in that namespace as well.
user
Identifies a user of the system. If embedded in other tags, this can appear in abbreviated form with only the id attribute.
<user id="ID" name="NAME" smallPhotoUrl="URL"/>
- ID
- GUID of user
- NAME
- Human readable name of user
- URL
- URL to use to display a small thumbnail of the user's identifying picture
resource
Used to refer to a resource such as an email address that identifies a person that is not a user of the system. If embedded in other tags, this can appear in abbreviated form with only the id attribute.
<resource id="ID" name="NAME"/>
- ID
- GUID of the resource
- NAME
- Display form of the resource
group
Identifies a group of the system. If embedded in other tags, this can appear in abbreviated form with only the id attribute.
<group id="ID" name="NAME" smallPhotoUrl=""/>
- ID
- GUID of group
- NAME
- Human readable name of the group
- URL
- URL to use to display a small thumbnail of the group's identifying picture
post
Stores fixed information about a post.
<post id="ID">
<poster>POSTER_ID</poster>
<href>HREF</href>
<title>TITLE</title>
<text>TEXT</text>
<postDate>POSTDATE</postDate>
[ <postInfo>POSTINFO</postInfo ]
</postInfo>
<recipients>
RECIPIENTS = ( <user id="ID"/> | <resource id="ID"/> | <group id="ID"/> ) ...
</recipients>
</post>
- POSTER_ID
- ID of the user posting the post
- HREF
- URL of the link that was shared in this post
- TITLE
- Title of the post
- TEXT
- Descriptive body of the post
- POSTDATE
- Date of the post in Unix format (seconds since January 1, 1970)
- POSTINFO
- Optional chunk of XML information about the post in a form specific to a particular type of post.
- RECIPIENTS
- List of recipients of the post; these are <user/> <resource/> and <group/> elements in abbreviated form.
livepost
Represents information about a post that changes during the life of a post.
<livepost id="ID">
<recentViewers>
RECENTVIEWERS = <viewer id="VIEWERID"/> ...
[...]
</recentViewers>
<chattingUserCount>CHATTING_USER_COUNT></chattingUserCount>
<totalViewers>TOTAL_VIEWERS</totalViewers>
</livepost>
- RECENTVIEWERS
- A small number of people who have recently viewed the post. (It's unclear why this has <viewer/> subelements rather than <user/> subelements.)
- CHATTING_USER_COUNT
- Number of current participants in the chatroom for this post
- TOTAL_VIEWERS
- Total number people who have ever looked at the post
Notifications sent from the server to clients
All of the following are sent inside <message/> element, of type 'headline', except for newPost, which is sent in a <message/> of type 'normal', so that it will be queued inside the XMPP server for later sending.
newPost
<newPost xmlns="http://dumbhippo.com/protocol/post"> <user/> [<user/> | <resource/> | <group/> ... ] <post/> </newpost>
livePostChanged
<livePostChanged xmlns="http://dumbhippo.com/protocol/post"> <livePost/> </livePostChanged>
mySpaceNameChanged
<myspaceNameChanged xmlns="http://dumbhippo.com/protocol/myspace" name="NAME"/>
mySpaceContactComment
<myspaceContactComment xmlns="http://dumbhippo.com/protocol/myspace"/>
hotness
<hotness xmln="http://dumbhippo.com/protocol/hotness" value="HOTNESS"/>
activePostsChanged
<activePostsChanged xmlns="http://dumbhippo.com/protocol/post"> <post/> <livePost/> [... (in pairs) ] </activePostsChanged>
prefs
<prefs xmlns="http://dumbhippo.com/protocol/prefs"> <prop key="KEY">VALUES</prop> [...] </prefs>
IQs
recentPosts
FIXME no docs yet
clientInfo
Request information about the required and available version of the client software for a particular platform.
<iq type="get" id="N">
<clientInfo xmlns="http://dumbhippo.com/protocol/clientinfo" platform="PLATFORM"/>
</iq>
- PLATFORM
- platform for which the client information should be retrieved. Currently, the supported values are 'windows' and 'x11'
<iq type="result" id="N">
<clientInfo xmlns="http://dumbhippo.com/protocol/clientinfo"
minimum="MINIMUM"
current="CURRENT"
download="DOWNLOAD"/>
</iq>
- MINIMUM
- Minimum client version that is required for interoperation with the server. If the version of the client that is currently running is older than this, then the client should prompt the user for an upgrade and do nothing until the upgrade is completed.
- CURRENT
- The current version of the client available on the server. If the version of the client that is currently running is older than this, then the client should prompt the user for an upgrade, but may continue running until the download is complete or if the user does not upgrade immediately.
method
Generic call to perform an operation on the server. This is used only for one method currently, and that method doesn't actually do anything at the moment either. This approach should be considered deprecated.
<iq type="set" id="N">
<method xmlns="http://dumbhippo.com/protocol/servermethod" name="METHOD_NAME">
<arg>VALUE</arg>...
</method>
</iq>
<iq type="result" id="N"></iq>
- METHOD_NAME
- The name of the method to execute. Currently, only 'postClicked' is supported. 'postClicked' takes a single argument, the GUID of the post that the user clicked on.
- VALUE
- A string argument value to pass to the method.
hotness
<iq type="get" id="N">
<hotness xmlns="http://dumbhippo.com/protocol/hotness" type="getValue"/>
</iq>
<iq type="result" id="N">
<hotness xmlns="http://dumbhippo.com/protocol/hotness" value="VALUE"/>
</iq>
music
<iq type="set" id="N">
<music xmlns="http://dumbhippo.com/protocol/musc" type="musicChanged">
<prop key="KEY">VALUE</prop>[...]
</music>
</iq>
<iq type="result" id="N"></iq> KEY=type|format|name|artist|album|url|duration|fileSize|trackNumber|discIdentifier
<iq type="set" id="N">
<music xmlns="http://dumbhippo.com/protocol/music" type="primingTracks">
<track>
<prop key="KEY">VALUE</prop>[..]
</track>[....]
</music>
</iq>
<iq type="result" id="N"></iq>
(This is foul and disgusting to have the schema depend upon attribute values, no clue why separate element names aren't used)
addBlogComment
<iq type="set" id="N">
<addBlogComment xmlns="http://dumbhippo.com/protocol/myspace" type="addBlogComment">
<commentId>COMMENT_ID</commentId>
<posterId>POSTER_ID</posterId>
</addBlogComment>
</iq>
<iq type="result" id="N"></iq>
(I have no clue why the type attribute mirrors the element name)
notifyContactComment =
<iq type="set" id="N">
<notifyContactComment xmlns="http://dumbhippo.com/protocol/myspace" type="notifyContactComment"
name="NAME">
</notifyContactComment>
</iq>
<iq type="result" id="N"></iq>
mySpaceInfo
<iq type="get" id="N">
<myspaceInfo xmlns="http://dumbhippo.com/protocol/myspace" type="getName"/>
</iq>
<iq type="result" id="N">
<myspaceInfo xmlns="http://dumbhippo.com/protocol/myspaceInfo" mySpaceName="NAME">
</iq>
<iq type="get" id="N">
<myspaceInfo xmlns="http://dumbhippo.com/protocol/myspace" type="getBlogComments"/>
</iq>
<iq type="result" id="N">
<myspaceInfo xmlns="http://dumbhippo.com/protocol/myspaceInfo">
<comment>
<commentId>COMMENT_ID</commentId>
<posterId>POSTER_ID</posterId>
</comment>[...]
</myspaceInfo>
</iq>
<iq type="get" id="N">
<myspaceInfo xmlns="http://dumbhippo.com/protocol/myspace" type="getContacts"/>
</iq>
<iq type="result" id="N">
<myspaceInfo xmlns="http://dumbhippo.com/protocol/myspaceInfo">
<contact name="NAME" friendId="FRIEND_ID"/>
</myspaceInfo>
</iq>
prefs
<iq type="get" id="N">
<prefs xmlns="http://dumbhippo.com/protocol/prefs"/>
</iq>
<iq type="result" id="N">
<prefs xmlns="http://dumbhippo.com/protocol/prefs">
<prop key="KEY">VALUES</prop>
[...]
</prefs>
</iq>
Chat Room Protocol
This is an adaption of the JEP-0045 Multi User chat protocol (http://www.jabber.org/jeps/jep-0045.html)
Client Joins Chat Room
Client sends a presence message to the room
<presence type="available" to="POST_ID@rooms.dumbhippo.com"> <x xmlns="http://jabber.org/protocol/muc"> <userInfo xmlns="http://dumbhippo.com/protocol/rooms" role="ROLE"/> </x> </message> ROLE=participant|visitor
If the same user joins a room multiple with different resources, these resources are combined into one "role" - if at least one resource has a role of "participant", then the user has a role of "participant", otherwise the user has a rule of "visitor".
If the client joining the chatroom causes the client to be present (with either role) for the first time, or the role to change, the presence message is echoed to all other room member clients:
<presence type="available" from="POST_ID@rooms.dumbhippo.com/USER_ID"> <x xmlns="http://jabber.org/protocol/muc#user"> <userInfo xmlns="http://dumbhippo.com/protocol/rooms" name="NAME" version="VERSION" role="ROLE"/> </x> </presence>
- USER_ID
- GUID of the use newly joining the chatroom
- NAME
- Human readable name of the user
- VERSION
- User's version number (used when building URLs to headshot photos)
- ROLE
- The role of the user, as above.
In the case of a change in role, the <presence type="available"/> message is simply resent with the new role. No intervening <presence type="unavailable"/> message is sent.
Room also sends <presence/> information for all other room members to the newly joined resource and a complete backlog of all past messages.
Client Leaves Chat Room
Client sends a presence message to the room
<presence type="available" to="POST_ID@rooms.dumbhippo.com"/>
If that causes the user to now be unavailable for the room, the room echos the message to all other room member clients:
<presence type="unavailable" from="POST_ID@rooms.dumbhippo.com/USER_ID"/>
If the user stays available but the users role changes, a <presence type="available/"> message is sent as discussed in the previous section.
Client adds a message to the chat room
Client sends the message to the room
<message to="POST_ID@rooms.dumbhippo.com">
<body>BODY</body>
</message>
- POST_ID
- GUID of the post this mesage is about
- BODY
- Descriptive body of the new message
The room echos the message to all other client members of the room:
<message from="POST_ID@rooms.dumbhippo.com/USER_ID">
<body>BODY</body>
<messageInfo xmlns="http://dumbhippo.com/protocol/rooms"
version="VERSION"
name="NAME"
timestamp="TIMESTAMP"
serial="SERIAL"/>
</message>
- USER_ID
- The GUID of the user sending the message
- NAME
- The human readable name of the sending user
- VERSION
- The version of the sending user (used to build headshot URLs)
- TIMESTAMP
- The timestamp of the message, in milliseconds since the Unix epoch
- SERIAL
- The serial of the message: every message sent to the chatroom is assigned an integer serial in ascending order. This can be used to identify whether a message has been seen before or should be added to the list of messages displayed to the user.

