在ejabberd 中,hooks 是很重要的一个模块,作为系统hook(钩子),通过调用ejabberd_hooks:add函数,注册一系列方法在ets表hook中,为某些特定事件(event)钩挂相应的行为(action),使在事件(event)发生时,触发对应的所有行为(actions)
1 ejabberd_hooks启动
查看ejabberd_app.erl文件,启动过程语句
%%%启动一个supervisor,并启动和监控定义子进程
Sup = ejabberd_sup:start_link()
ejabberd_sup:
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([]) ->
Hooks =
{ejabberd_hooks,
{ejabberd_hooks, start_link, []},
permanent,
brutal_kill,
worker,
[ejabberd_hooks]},
...
{ok, {
{
one_for_one, 10, 1},
[Hooks,
NodeGroups,
SystemMonitor,
Router,
Router_multicast,
S2S,
Local,
Captcha,
S2SInSupervisor,
S2SOutSupervisor,
ServiceSupervisor,
IQSupervisor,
FrontendSocketSupervisor,
Listener]}}.
启动详细参数可以参照supervisor行为规范
ejabberd_hooks:
start_link() ->
gen_server:start_link({local, ejabberd_hooks}, ejabberd_hooks, [], []).
由上述代码可知ejabberd_hooks启动的是一个gen_sever进程,作为ejabberd_sup子进程存在
init([]) ->
ets:new(hooks, [named_table]),
{ok, #state{}}.
gen_server:start_link/4执行后,调用init/1函数新建ets表hooks,用于存储绑定事件行为,存储格式以disco_info为例:
{
{
disco_info,<<"localhost">>},
[{50,mod_offline,get_info},
{75,mod_caps,disco_info},
{100,mod_disco,get_info}]}
2 add hooks
add hooks是需要绑定事件行为(event-action)的模块,通过调用ejabberd_hooks:add和ejabberd_hooks:add_dist函数绑定
add在ejabberd_hooks中定义如下
%%%以下针对不同情况是否包含主机模块等参数匹配不同处理,最终都会调用gen_server:call/2
%%%然后在handle_call回调模块中实现添加
%%% @doc See add/4.
add(Hook, Function, Seq) when is_function(Function) -&g