uhlenheuerdotnet
programming, .NET, linux and others

ejabberd: message archive management (XEP-0313)

by Gregor Uhlenheuer on February 23, 2014

Lately programming with erlang fascinates me a lot. Specifically hacking the XMPP server ejabberd draws my interest the most. So I started implementing the message archive management XMPP extension described in the experimental XEP-0313 specification.

ejabberd message archiving

ejabberd already supports some message archiving out-of-the-box by the mod_archive module that is part of the ejabberd community scripts repository. That module implements the XEP-0136 specification and supports storage via mnesia, PostgreSQL, MySQL or sqlite.

For my approach I chose to implement the XEP-0313 standard instead because it is known to be less complicated and therefore easier to implement by clients, as stated by the specification:

“This specification aims to define a much simpler and modular protocol for working with a server-side message store. Through this it is hoped to boost implementation and deployment of archiving in XMPP.”

Moreover I plan to use the MongoDB database as storage engine.

ejabberd-mod-mam

You can find the latest version of mod-mam on github. The module targets the current master branch of ejabberd which is the so called “community edition”.

The latest version of mod-mam supports:

The following points are on my TODO list:

Configuration

In order to use mod-mam you have to add it to the modules section in your ejabberd.cfg. This could look like this:

{modules,
  [
    {mod_mam,
      [
        % use the default localhost:27017
        % or define a specific host
        {mongo, {localhost, 27017}},

        % define a database to use
        % (default: test)
        {mongo_database, test},

        % specify a collection to use
        % (default: ejabberd_mam)
        {mongo_collection, ejabberd_mam}
      ]
    },

    % ...
  ]
}.

MongoDB content

Just to give a short impression on how the content is stored, this is what an archived message looks like inside the MongoDB collection:

{
    "_id" : ObjectId("52f7fc9ecdbb08255f000002"),
    "user" : "test2",
    "server" : "localhost",
    "jid" : {
        "user" : "test",
        "server" : "localhost",
        "resource" : "sendxmpp"
    },
    "body" : "foo",
    "direction" : "to",
    "ts" : ISODate("2014-02-09T22:09:34.282Z"),
    "raw" : "<message xml:lang='en' to='test@localhost' type='chat'><body>foo</body><subject/></message>"
}

Example archive query

An examplary archive query conversion between client and server would look like the following. At first the client queries for its last two messages (limited by a RSM instruction):

<iq type='get'
    id='query1'>
  <query xmlns='urn:xmpp:mam:tmp'
         queryid='x01'>
    <set xmlns='http://jabber.org/protocol/rsm'>
      <max>2</max>
    </set>
  </query>
</iq>

The server responds with the two requested messages:

<message xmlns='jabber:client'
         to='test@localhost/37367024071393189531836643'>
  <result queryid='x01'
          xmlns='urn:xmpp:mam:tmp'
          id='52F7FC8DCDBB08255F000001'>
    <forwarded xmlns='urn:xmpp:forward:0'>
      <delay xmlns='urn:xmpp:delay'
             stamp='2014-02-09T22:09:17Z'/>
      <message from='test2@localhost/sendxmpp'
               to='test@localhost'
               xml:lang='en'
               type='chat'>
        <body>
          foo
        </body>
      </message>
    </forwarded>
  </result>
</message>
<message xmlns='jabber:client'
         to='test@localhost/37367024071393189531836643'>
  <result queryid='x01'
          xmlns='urn:xmpp:mam:tmp'
          id='52F7FC9ECDBB08255F000003'>
    <forwarded xmlns='urn:xmpp:forward:0'>
      <delay xmlns='urn:xmpp:delay'
             stamp='2014-02-09T22:09:34Z'/>
      <message from='test2@localhost/sendxmpp'
               to='test@localhost'
               xml:lang='en'
               type='chat'>
        <body>
          bar
        </body>
      </message>
    </forwarded>
  </result>
</message>

Finally the server finishes the interaction with the closing <id> stanza:

<iq xmlns='jabber:client'
    to='test@localhost/37367024071393189531836643'
    id='query1'
    type='result'/>

Feedback

As mod-mam is still in early beta phase any feedback, bug reports or contributions are very much appreciated. Either contact me or better head over to the issues on github and open a bug report or pull request.

References

This post is tagged with programming, erlang, ejabberd, archive and module