MongooseIM 简单模块事件未得到处理
MongooseIM simple module event not getting handled
我是 erlang 和 ejabbered/mongooseIM 的新手。我正在尝试编写一个非常简单的 mongoose 模块,它将在发送之前向数据包添加一个额外的子元素。下面是我的代码:
-module(mod_test).
-behavior(gen_mod).
-export([start/2, stop/1]).
-export([add_child/1]).
-include("ejabberd.hrl").
start(Host, Opts) ->
ejabberd_hooks:add(filter_packet, Host, ?MODULE, add_child, 0),
?DEBUG(" MOD_TEST Started",[]),
ok.
stop(Host) ->
ejabberd_hooks:delete(filter_packet, Host, ?MODULE, add_child, 0),
ok.
add_child({From, To, XML} = Packet) ->
Tag = {"a","b"},
NewPacket = xml:append_subtags(Packet, [Tag]),
?INFO_MSG(" To party: ~p~n",[To]),
NewPacket.
我可以在几乎没有警告的情况下编译代码
mod_test.erl:3: Warning: behaviour gen_mod undefined
mod_test.erl:11: Warning: variable 'Opts' is unused
mod_test.erl:20: Warning: variable 'From' is unused
mod_test.erl:20: Warning: variable 'XML' is unused
然后,当我添加模块并 运行 它开始时,它不会对数据包进行任何更改,也不会生成任何日志。
另一个问题是,如果我在我的启动函数中添加一个日志,它会被编译但我在启动模块时看到错误
2015-03-03 16:36:34.772 [critical] <0.200.0>@gen_mod:start_module:94 Problem starting the module mod_test for host <<"localhost">>
options: []
error: undef
[{lager,info,[" mod_test starting ...",[[]]],[]},
{mod_test,start,2,[{file,"mod_test.erl"},{line,13}]},
{gen_mod,start_module,3,[{file,"src/gen_mod.erl"},{line,83}]},
{lists,foreach,2,[{file,"lists.erl"},{line,1336}]},
{ejabberd_app,start,2,[{file,"src/ejabberd_app.erl"},{line,69}]},
{application_master,start_it_old,4,
[{file,"application_master.erl"},{line,272}]}]
2015-03-03 16:36:34.773 [critical] <0.200.0>@gen_mod:start_module:99 ejabberd initialization was aborted because a module start failed.
The trace is [{lager,info,[" mod_test starting ...",[[]]],[]},{mod_test,start,2,[{file,"mod_test.erl"},{line,13}]},{gen_mod,start_module,3,[{file,"src/gen_mod.erl"},{line,83}]},{lists,foreach,2,[{file,"lists.erl"},{line,1336}]},{ejabberd_app,start,2,[{file,"src/ejabberd_app.erl"},{line,69}]},{application_master,start_it_old,4,[{file,"application_master.erl"},{line,272}]}].
Crash dump was written to: erl_crash.dump
Problem starting the module mod_test for host <<"localhost">>
options: []
error: undef
[{lager,info,[" mod_xyz starting ...",[[]]],[]},
{mod_test,start,2,[{file,"mod_timetagg
我做错了什么?
错误为 undef
,这意味着调用的函数不是 defined/exported。堆栈跟踪显示有问题的函数是 lager:info/2
.
Lager(处理您的 ?INFO_MSG
的日志记录库)有一个特殊的怪癖,即您的代码会调用不存在的函数,但代码在编译之前会通过解析转换进行转换。看来你没有遇到过这种情况。
MongooseIM 树中 apps/ejabberd
中的 rebar.config
文件包含 erl_opts
中的 {parse_transform, lager_transform}
,它要求编译器应用解析转换。我建议将 mod_test.erl
放入 apps/ejabberd/src
并构建整个 MongooseIM 树;这将确保您的文件使用正确的选项构建。
所以您的示例实际上有点棘手,因为 filter_packet
挂钩的工作原理。您在第一次尝试时选择了最差的钩子进行注册 ;)
如果你查看 ejabberd_router:do_route
,你会发现 filter_packet
是 运行,没有 Host
参数——它是一个全局钩子,所以当你为特定 Host
注册您的 add_child
函数,它基本上会被忽略。
尝试以下操作:
-module(mod_test).
-behavior(gen_mod).
-export([start/2, stop/1]).
-export([add_child/1]).
-include_lib("ejabberd/include/ejabberd.hrl").
-include_lib("exml/include/exml.hrl").
start(Host, Opts) ->
ejabberd_loglevel:set_custom(?MODULE, 5),
ejabberd_hooks:add(filter_local_packet, Host, ?MODULE, add_child, 1),
?DEBUG(" MOD_TEST Started",[]),
ok.
stop(Host) ->
ejabberd_hooks:delete(filter_local_packet, Host, ?MODULE, add_child, 1),
ok.
add_child({From, To, Element} = HookData) ->
?DEBUG("Filtering ~p~n", [HookData]),
case Element#xmlel.name of
<<"message">> ->
Tag = #xmlel{name = <<"added-tag">>, attrs = [], children = []},
NewElement = xml:append_subtags(Element, [Tag]),
?DEBUG("will return new el: ~p", [NewElement]),
{From, To, NewElement};
_ ->
?DEBUG("will pass old el: ~p", [Element]),
HookData
end.
在给定的 Host
上注册 filter_local_packet
现在可以使用,所有传入的节都将传递给您的函数。重要的是要记住,向所有节添加虚假标签可能会破坏事情,因此上面的代码只会向 <message>
节添加一个 <added-tag>
元素。
使用上面的示例并从那里开始工作。
祝你好运!
我是 erlang 和 ejabbered/mongooseIM 的新手。我正在尝试编写一个非常简单的 mongoose 模块,它将在发送之前向数据包添加一个额外的子元素。下面是我的代码:
-module(mod_test).
-behavior(gen_mod).
-export([start/2, stop/1]).
-export([add_child/1]).
-include("ejabberd.hrl").
start(Host, Opts) ->
ejabberd_hooks:add(filter_packet, Host, ?MODULE, add_child, 0),
?DEBUG(" MOD_TEST Started",[]),
ok.
stop(Host) ->
ejabberd_hooks:delete(filter_packet, Host, ?MODULE, add_child, 0),
ok.
add_child({From, To, XML} = Packet) ->
Tag = {"a","b"},
NewPacket = xml:append_subtags(Packet, [Tag]),
?INFO_MSG(" To party: ~p~n",[To]),
NewPacket.
我可以在几乎没有警告的情况下编译代码
mod_test.erl:3: Warning: behaviour gen_mod undefined
mod_test.erl:11: Warning: variable 'Opts' is unused
mod_test.erl:20: Warning: variable 'From' is unused
mod_test.erl:20: Warning: variable 'XML' is unused
然后,当我添加模块并 运行 它开始时,它不会对数据包进行任何更改,也不会生成任何日志。
另一个问题是,如果我在我的启动函数中添加一个日志,它会被编译但我在启动模块时看到错误
2015-03-03 16:36:34.772 [critical] <0.200.0>@gen_mod:start_module:94 Problem starting the module mod_test for host <<"localhost">>
options: []
error: undef
[{lager,info,[" mod_test starting ...",[[]]],[]},
{mod_test,start,2,[{file,"mod_test.erl"},{line,13}]},
{gen_mod,start_module,3,[{file,"src/gen_mod.erl"},{line,83}]},
{lists,foreach,2,[{file,"lists.erl"},{line,1336}]},
{ejabberd_app,start,2,[{file,"src/ejabberd_app.erl"},{line,69}]},
{application_master,start_it_old,4,
[{file,"application_master.erl"},{line,272}]}]
2015-03-03 16:36:34.773 [critical] <0.200.0>@gen_mod:start_module:99 ejabberd initialization was aborted because a module start failed.
The trace is [{lager,info,[" mod_test starting ...",[[]]],[]},{mod_test,start,2,[{file,"mod_test.erl"},{line,13}]},{gen_mod,start_module,3,[{file,"src/gen_mod.erl"},{line,83}]},{lists,foreach,2,[{file,"lists.erl"},{line,1336}]},{ejabberd_app,start,2,[{file,"src/ejabberd_app.erl"},{line,69}]},{application_master,start_it_old,4,[{file,"application_master.erl"},{line,272}]}].
Crash dump was written to: erl_crash.dump
Problem starting the module mod_test for host <<"localhost">>
options: []
error: undef
[{lager,info,[" mod_xyz starting ...",[[]]],[]},
{mod_test,start,2,[{file,"mod_timetagg
我做错了什么?
错误为 undef
,这意味着调用的函数不是 defined/exported。堆栈跟踪显示有问题的函数是 lager:info/2
.
Lager(处理您的 ?INFO_MSG
的日志记录库)有一个特殊的怪癖,即您的代码会调用不存在的函数,但代码在编译之前会通过解析转换进行转换。看来你没有遇到过这种情况。
MongooseIM 树中 apps/ejabberd
中的 rebar.config
文件包含 erl_opts
中的 {parse_transform, lager_transform}
,它要求编译器应用解析转换。我建议将 mod_test.erl
放入 apps/ejabberd/src
并构建整个 MongooseIM 树;这将确保您的文件使用正确的选项构建。
所以您的示例实际上有点棘手,因为 filter_packet
挂钩的工作原理。您在第一次尝试时选择了最差的钩子进行注册 ;)
如果你查看 ejabberd_router:do_route
,你会发现 filter_packet
是 运行,没有 Host
参数——它是一个全局钩子,所以当你为特定 Host
注册您的 add_child
函数,它基本上会被忽略。
尝试以下操作:
-module(mod_test).
-behavior(gen_mod).
-export([start/2, stop/1]).
-export([add_child/1]).
-include_lib("ejabberd/include/ejabberd.hrl").
-include_lib("exml/include/exml.hrl").
start(Host, Opts) ->
ejabberd_loglevel:set_custom(?MODULE, 5),
ejabberd_hooks:add(filter_local_packet, Host, ?MODULE, add_child, 1),
?DEBUG(" MOD_TEST Started",[]),
ok.
stop(Host) ->
ejabberd_hooks:delete(filter_local_packet, Host, ?MODULE, add_child, 1),
ok.
add_child({From, To, Element} = HookData) ->
?DEBUG("Filtering ~p~n", [HookData]),
case Element#xmlel.name of
<<"message">> ->
Tag = #xmlel{name = <<"added-tag">>, attrs = [], children = []},
NewElement = xml:append_subtags(Element, [Tag]),
?DEBUG("will return new el: ~p", [NewElement]),
{From, To, NewElement};
_ ->
?DEBUG("will pass old el: ~p", [Element]),
HookData
end.
在给定的 Host
上注册 filter_local_packet
现在可以使用,所有传入的节都将传递给您的函数。重要的是要记住,向所有节添加虚假标签可能会破坏事情,因此上面的代码只会向 <message>
节添加一个 <added-tag>
元素。
使用上面的示例并从那里开始工作。
祝你好运!