Skip to content

kyleburton/intro-to-extending-ejabberd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

68 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A Journey into Extending Jabber

We incorporated XMPP into our product to do multi-user chat.

For this we use eJabberd, an Erlang based XMPP server.

  • eJabberd supports clustering (standard erlang and mnesia clustering)
  • eJabberd supports multi-user-chat (plugin: mod_muc)

We needed to be able to get information out of Jabber from our JVM based
services:

  • see who is currently in a room
    if there is no counterparty for a user, we actively try to find one that is
    on-call and send them into the room
  • peek at the messages in a room: so we could write tests for our system to
    ensure we were mapping sms <→ xmpp
  • post a message to the room on behalf of a user
    this was for integrating SMS send/recv into the room

We thought there were a few approaches:

  • extend the XMPP protocol to support all of these
    PRO: fits into the existing clients (bosh, smack)
    CON: existing client (smack) is flaky/unreliable
    CON: we don’t want normal users to be able to exercise
    the new features.
    CON: eJabberd prevents the same user from logging into a room multiple times:
    this is in conflict with our distributed system
    CON: extending XMPP would be complex and standard clients may no longer be
    able to participate
  • create an alternate interface into jabber

We found mod_restful_admin, so we chose to go with an alternate interface:
HTTP. mod_restful_admin already allowed for registering users (which is
something we need to do, but can via smack), and looked like it could be easily
extended to do what we needed.

Understanding eJabberd through the standard OTP Behaviors:

  • gen_server
  • gen_fsm
  • gen_event
  • supervisor

mod_muc_room’s record structure:

./software/build/ejabberd-2.1.12/src/mod_muc/mod_muc_room.hrl

Understanding Erlang: Language, Semantics of code

  • expression based language
  • single assignment
  • pattern matching and destructuring
  • single funciton, multiple clauses does not exactly map to polymorphisim,
    function overloading or even defmulti but defmulti is closest
  • syntatic: comma, semi-colon; and period.
  • data types: numbers, atoms, tuples, lists and strings
  • records, tuples with a type

Understanding Erlang: Runtime Semantics

  • processes
  • message passing
  • recursion and handling state in a single-assginment world
  • mnesia, data storage and clustering
  • iolists, and Erlang’s sprintf
  • The erlang path, and finding compiled code.

Lessons Learned, some learned the hard way

  • mnesia is tied to the node name(!)
  • erlang cookie
  • data types: JSON challenges: strings are arrays of ints
  • debugging: ?INFO_MSG(),
  • debugging: mod_restful_debug: capture live data (vars) like we do in Clojure
  • debugging: query a gen_fsm for it’s state
  • iterating: shell, interacting with code
  • iterating: remote shell, connect to a running erlang node
  • iterating: using ejabberdctl debug
  • iterating: make sure the build only builds what you changed
  • iterating: using ejabberdctl live

Internals of MUC that we reverse engineered:

  • MUC room is managed by a process
  • that process stores it’s configuration in mnesia
  • list of rooms is persisted in mnesia
  • the list of users and the messages are in the room state only
    only in memory

To R&D:

  • recompile and hot reload code: ‘code replacement’ or ‘release handling’

Authors:

  • Kyle Burton
  • Paul Santa Clara

Running the Code

Requirements

The code in this repository assumes that you have Erlang already installed.
Ruby’s rake utiliity must be installed, is used for automating and building.
The included Rakefile will download and install eJabberd into a self-contained
directory for working through the examples.

Installing eJabberd

rake ejabberd:install

Running eJabberd

eJabberd can be run in the background as a daemon, or in the foreground. If it
is run in the background, you can still interact with it by launching
ejabberdctl debug. To run eJabberd, run ejabberdctl start. After
installation, ejabberdctl will be located in ./software/ejabberd/sbin/ejabberdctl.

Recipies / Cheatsheet:

Interactive REPL/Shell:

erl erl -name test1@localhost erl -sname test1

Find your erlang ROOT:

init:get_argument(root).

Find your erlang node’s cookie:

erlang:get_cookie().

Get current node’s name

node().

The nodes you’re clustered with:

nodes().

Ping another node, must have the same cookie, to cluster with it:

net_adm:ping(test2@localhost).

Tutorials

  • Interact with the Shell: erl
  • Create a module
  • Compile and load
  • Connect 2 Nodes
  • Mnesia: Starting mnesia
  • Mnesia: Creating tables, insertion and querying.
  • Mnesia: Clustering 2 Nodes

Photos

http://www.flickr.com/photos/42336015@N00/5067418822/
“Donkey”: Donkey-5067418822_6fde6e9e64_z.jpg

About

Notes on how we extended Ejabberd

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published