[ejabberd] Clustering, data (state) sharing, and hooks firing on the cluster / nodes

CGS cgsmcmlxxv at gmail.com
Fri Nov 18 14:07:42 MSK 2011

Hi, Hisham,

I suppose the hooks you are interested in are:

ejabberd_hooks:add(sm_register_connection_hook, Host, <hook module 
name>, <hook function name>, 90)
ejabberd_hooks:add(sm_remove_connection_hook, Host, <hook module name>, 
<hook function name>, 90)

Here is an example I wrote some time ago (people didn't want my module, 
so, I didn't push further):

--- code snippet ---

-author('CGSMCMLXXV <cgsmcmlxxv at gmail.com>').




start(Host, _Opts) ->
     ?INFO_MSG("mod_filter_presence starting", []),
     ejabberd_hooks:add(sm_register_connection_hook, Host, ?MODULE, 
user_presence, 90),
     ejabberd_hooks:add(sm_remove_connection_hook, Host, ?MODULE, 
user_presence, 90),

stop(Host) ->
     ?INFO_MSG("mod_filter_presence stopping", []),
     ejabberd_hooks:delete(sm_register_connection_hook, Host, ?MODULE, 
user_presence, 90),
     ejabberd_hooks:delete(sm_remove_connection_hook, Host, ?MODULE, 
user_presence, 90),

user_presence(JID) ->
     User = JID#jid.luser,
     Host = JID#jid.lserver,
     Resource = JID#jid.lresource,
     _Data = {},

user_presence(_, JID) ->
     User = JID#jid.luser,
     Host = JID#jid.lserver,
     Resource = JID#jid.lresource,
     _Data = {},

user_presence(_, JID, _Data) ->
     User = JID#jid.luser,
     Host = JID#jid.lserver,
     Resource = JID#jid.lresource,

user_presence(User, Server, Resource, _Packet) ->
    %% Do something with "User" from "Server" who tries to log in
    %% with XMPP-client "Resources" and if it's not enough, I may
    %% get lucky and have the full "Packet"
    %% Here should go your code defining FilterIt (filter it) as boolean:
    %% -> if FilterIt is true then don't allow connection
    %% -> if FilterIt is false then allow connection
    if (FilterIt == true) ->
    %% each user has a registered process which can be caught with
           SID = ejabberd_sm:get_session_pid(User, Server, Resource),
           SID ! system_shutdown; %% a trick to disconnect the user
        (FilterIt /= true) -> ok %% let the user log in

--- end of code snippet ---

I did that module to filter for a certain resource (XMPP-client software 
ID like Pidgin, Psi, Vacuum-IM, Real-time Ignite Spark or whatever), but 
I cut that part for you to use it as you think it's fit for your 
project. You need just to set the value for FilterIt before enters 
if-condition. I hope it will help. Good luck!


On 11/18/2011 09:01 AM, Hisham Mardam Bey wrote:
> Hi Peter,
> Although that is a valid solution it will not work for us. We can not
> rely on our clients having this switched on as our chat service is
> paid and we need to be in control of who can send messages. This is
> why we want to block everything by default (yet allow roster requests
> to travel through) and only let 2 people chat once they have added one
> another to the roster (this will be subject to our business rules via
> a packet filter).
> Now we could try to inspect every message and do the roster check in
> the packet filter inside of ejabberd but we're trying to avoid having
> to do that if possible.
> hisham.
> On Fri, Nov 18, 2011 at 1:27 AM, Peter Viskup<skupko.sk at gmail.com>  wrote:
>> Hi Hisham,
>> this can be done on XMPP client side. For example Gajim has option 'Ignore
>> events from contact not in the roster' in advanced settings.
>> Best regards,
>> --
>> Peter
>> On 11/18/2011 05:42 AM, Hisham Mardam Bey wrote:
>>> A quick update on my findings after doing some more spec reading.
>>> Using rosters and presence I can simulate the exact environment and
>>> online / offline notifications that we need for our business logic.
>>> The only rule I still have to meet is blocking all communication by
>>> default (messages) unless 2 members have successfully subscribed to
>>> each others rosters. Any hints?
>>> hisham.
>>> On Thu, Nov 17, 2011 at 1:06 PM, Hisham Mardam Bey
>>> <hisham.mardambey at gmail.com>    wrote:
>>>> Hi folks,
>>>> I'm fairly new to ejabberd and Erlang (3rd day using it as of writing
>>>> this email) and I am having fantastic results with both so far. We
>>>> want to use ejabberd where I work (dating site, we have up to around
>>>> 8K people online wanting to chat). What we have so far is ejabberd
>>>> 2.1.6-2.1 (via apt) coupled with Strophe JS for the web browsers.
>>>> We've written a couple of Erlang modules that update our system via
>>>> presence notifications when people join and leave. We've also got
>>>> another module that coordinates invitations between users and must
>>>> keep some state about who's said "yes" to who's invitation so that
>>>> subsequent chat messages between the 2 users can go through (other
>>>> wise the module's packet filter will drop it). The goal is to then use
>>>> this by adding a hook on fitler_packet and only let through chats that
>>>> have been approved and "registered" in the system.
>>>> My question is really about the last part, how one would go about
>>>> "sharing" such state across the cluster, and how do hooks work in a
>>>> cluster? I am still reading up on Erlang and ejabberd clustering and
>>>> how it works.
>>>> If I have multiple nodes in my cluster with users connected to
>>>> different nodes what is the recommended way of tracking such
>>>> invitation state? Also, if I use presence to figure out when a user
>>>> has left through a hook, will the presence hook fire only on the node
>>>> the user was connected to and left (presence changed)?
>>>> My plan is to read up some more on how Erlang and ejabberd handles
>>>> clustering then come back here and update this question. In the mean
>>>> time, any helpful information or resources explaining how this stuff
>>>> works are greatly appreciated.
>>>> hisham.
>>>> --
>>>> Hisham Mardam-Bey
>>>> http://hisham.cc/

More information about the ejabberd mailing list