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

CGS cgsmcmlxxv at gmail.com
Sun Nov 20 16:05:41 MSK 2011


You have two options: pull or push.

Pull: Every module is part of the same Erlang session, so, in 
mod_filter_presence you should be able to call directly 
mod_roster:get_user_roster([],{User,Server}) - take care to transform 
them in binary if they aren't (list_to_binary(List)) - from user_presence/4.

Push: You can define a listener (listener(Vars) -> receive Message -> 
proc_lib:spawn(?MODULE,process_message,[Message]), NewVars = 
modify(Vars), listener(NewVars) end.) in mod_roster (or another module 
of your choice linked to mod_roster), register listener with a name 
(register(my_listener,pid_for_listener)) and you send messages from 
mod_filter_presence:send_presence/4 to that registered process 
(my_listener ! {User,Server}).

I hope these ideas will help you. I am still searching for my former 
project implementation (lots of search through the versions :D).

CGS



On 11/20/2011 06:03 AM, Hisham Mardam Bey wrote:
> At this point I am trying to either use mod_roster:get_user_roster/3
> or call into mnesia myself. get_user_roster seems perfect but I do not
> know how to get from filter_packet/1's input to the {User,Server}
> tuple that is expected on both techniques I mentioned.
>
> hisham.
>
> On Sat, Nov 19, 2011 at 5:33 AM, CGS<cgsmcmlxxv at gmail.com>  wrote:
>> One way is using ejabberdctl command. Another is to to put Ejabberd in the
>> standard Erlang path and to access directly its modules. I used both and I
>> had good results. I never entered Mnesia to manipulate the roster. Check
>> also mod_roster (if I remember well the name) for details.
>>
>> If you need more help, let me know, I will check my previous work and I can
>> give you some examples of code.
>>
>> CGS
>>
>>
>>
>> On 11/19/2011 06:44 AM, Hisham Mardam Bey wrote:
>>> Should I directly query and modify the rosters via mnesia queries or
>>> is there an API?
>>>
>>> On Sat, Nov 19, 2011 at 12:26 AM, Hisham Mardam Bey
>>> <hisham.mardambey at gmail.com>    wrote:
>>>> Thanks for your example. Between that and using the roster I have
>>>> everything we need except being able to filter basic roster
>>>> (subscription) and presence stanzas. I can identify them in the filter
>>>> module but haven't found ejabberd's API for manipulating users'
>>>> rosters. Once I have that we'll be able to toss out what we currently
>>>> have (Red5) and replace it with ejabberd! (=
>>>>
>>>> hmb.
>>>>
>>>> On Fri, Nov 18, 2011 at 6:07 AM, CGS<cgsmcmlxxv at gmail.com>    wrote:
>>>>> 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 ---
>>>>>
>>>>> -module(mod_filter_presence).
>>>>> -author('CGSMCMLXXV<cgsmcmlxxv at gmail.com>').
>>>>>
>>>>> -behavior(gen_mod).
>>>>>
>>>>> -include("ejabberd.hrl").
>>>>> -include("jlib.hrl").
>>>>>
>>>>> -export([start/2,
>>>>>          stop/1,
>>>>>          user_presence/1,
>>>>>          user_presence/2,
>>>>>          user_presence/3,
>>>>>          user_presence/4,
>>>>>          send_message/1]).
>>>>>
>>>>> 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),
>>>>>     ok.
>>>>>
>>>>> 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),
>>>>>     ok.
>>>>>
>>>>> user_presence(JID) ->
>>>>>     User = JID#jid.luser,
>>>>>     Host = JID#jid.lserver,
>>>>>     Resource = JID#jid.lresource,
>>>>>     _Data = {},
>>>>>     user_presence(User,Host,Resource,_Data).
>>>>>
>>>>> user_presence(_, JID) ->
>>>>>     User = JID#jid.luser,
>>>>>     Host = JID#jid.lserver,
>>>>>     Resource = JID#jid.lresource,
>>>>>     _Data = {},
>>>>>     user_presence(User,Host,Resource,_Data).
>>>>>
>>>>> user_presence(_, JID, _Data) ->
>>>>>     User = JID#jid.luser,
>>>>>     Host = JID#jid.lserver,
>>>>>     Resource = JID#jid.lresource,
>>>>>     user_presence(User,Host,Resource,_Data).
>>>>>
>>>>> 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,
>>>>>     none.
>>>>>
>>>>> --- 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!
>>>>>
>>>>> Cheers,
>>>>> CGS
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> 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/
>>>>>>>>>
>>>>> _______________________________________________
>>>>> ejabberd mailing list
>>>>> ejabberd at jabber.ru
>>>>> http://lists.jabber.ru/mailman/listinfo/ejabberd
>>>>>
>>>>
>>>> --
>>>> Hisham Mardam-Bey
>>>> http://hisham.cc/
>>>>
>>>
>> _______________________________________________
>> ejabberd mailing list
>> ejabberd at jabber.ru
>> http://lists.jabber.ru/mailman/listinfo/ejabberd
>>
>
>



More information about the ejabberd mailing list