[ejabberd] Communicate with other code from hooks

Shaun Kruger shaun.kruger at gmail.com
Mon Aug 1 18:06:45 MSD 2011


There are a few ways of doing this that I like to use.  It all depends
on if you have a gen_server per vhost or if you want a global
gen_server.  Also, I'm going to make my suggestions based on what I
have seen in the ejabberd 2 series.  Things a a little different (and
nicer) in ejabberd3.

The best way of talking to a gen server when you can't just pass a PID
around is by naming your gen server.  There are two options for this.
You can create a global (to your node) gen server, or you can start
one for each vhost.

The global gen_server option assuming you are making use of the
gen_mod behaviour.
======================================
start("localhost",Opts) ->
    supervisor:start_child(ejabberd_sup,{?MODULE,{?MODULE,start_link,[Opts]},permanent,2000,worker,[?MODULE]}),
    ok;
start(Host,Opts) ->
    %% Do per vhost startup.
    ok.

start_link(Opts) ->
    gen_server:start_link({local,?MODULE},?MODULE,Opts,[]).

init(Opts) ->
    %% This assumes you simply want opts to be your state variable.  I
usually create a local record definition and put opts into it.
    {ok,Opts}.

on_register(SID,#jid{lname=Name},Info) ->
    gen_server:call(?MODULE,{on_register,Name,SID,Info}),
    ok.

In the event you wish to start a gen_server per vhost you can do this:
=======================================
start(Host,Opts) ->
    PName = gen_mod:get_module_proc(Host,?MODULE),
    supervisor:start_child(ejabberd_sup,{PName,{?MODULE,start_link,[Host,Opts]},permanent,2000,worker,[?MODULE]}),
    ok.

start_link(Host,Opts) ->
    PName = gen_mod:get_module_proc(Host,?MODULE),
    gen_server:start_link({local,PName},?MODULE,{Host,Opts},[]).

init({Host,Opts}) ->
    {ok,{Host,Opts}}.

on_register(SID,#jid,{lname=Name,lserver=Host},Info) ->
    PName = gen_mod:get_module_proc(Host,?MODULE),
    gen_server:call(PName,{on_register,Name,SID,Info}),
    ok.


In essence, you must give your gen_server a name that you either can
assume globally (first example), or infer based on the arguments that
come in (second example).  Take note that these are only partial
examples.  I didn't implement the stop(_Host) function where I stop
the gen_servers and remove them from the supervisor.  I have seen some
modules merely start a gen_server or spawn a process without
supervisor support, but I don't recommend it.  It's always sad when
your module stops running properly because of a small bug that should
have been automatically corrected.

Shaun

On Mon, Aug 1, 2011 at 12:40 AM, Alexander Kuleshov
<kuleshovmail at gmail.com> wrote:
> Hello,
>
> I have hook handler in my code:
>
>    ejabberd_hooks:add(sm_register_connection_hook,
> BotState#state.host, ?MODULE, on_register, 80),
>
> on_register(SID, JID, INFO) ->
>    {_, _, _, _, Name, _, _} = JID,
>    ok.
>
> How can i send message to gen_server for example from this hook with Name?
>
> How can i make know gen_server pid to hook?
>
> Thank you.
> _______________________________________________
> ejabberd mailing list
> ejabberd at jabber.ru
> http://lists.jabber.ru/mailman/listinfo/ejabberd
>


More information about the ejabberd mailing list