ejabberd:跟踪花名册和状态导致错误
ejabberd: Tracking Roster and Presence cause error
在 ejabberd 的论坛上发布了这个问题,但没有得到回应,所以我将其发布在这里 (https://www.ejabberd.im/forum/25371/tracking-roster-and-presence-cause-error)。我创建了一个简单的 ejabberd 模块来记录名册和状态的所有事件。我试图了解事件的顺序和每个事件的参数。一切似乎都正常,除了我在 ejabberd 日志文件中看到 2 个错误,我不确定如何修复它们,因为我所做的只是写入日志文件。
模块代码(mod_monitor_roster):
start(Host, Opt) ->
?INFO_MSG("Monitor Roster Started for Host (~p) and Opt(~p)...~n", [Host, Opt]),
%%Add the roster hooks here...
ejabberd_hooks:add(roster_process_item, Host, ?MODULE, process_item, 10),
ejabberd_hooks:add(roster_get, Host, ?MODULE, rosterget, 10),
ejabberd_hooks:add(roster_get_jid_info, Host, ?MODULE, rostergetjidinfo, 10),
ejabberd_hooks:add(roster_get_subscription_lists, Host, ?MODULE, rostergetsubscriptionlists, 10),
ejabberd_hooks:add(roster_get_versioning_feature, Host, ?MODULE, rostergetversioningfeature, 10),
ejabberd_hooks:add(roster_groups, Host, ?MODULE, rostergroup, 10),
ejabberd_hooks:add(roster_in_subscription, Host, ?MODULE, rosterinsubscription, 10),
ejabberd_hooks:add(roster_out_subscription, Host, ?MODULE, rosteroutsubscription, 10),
ejabberd_hooks:add(set_presence_hook, Host, ?MODULE, setpresencehook, 1),
%%ejabberd_hooks:add(resend_subscription_requests_hook, Host, ?MODULE, resendsubscriptionrequestshook, 50),
ok.
process_item(Acc, Server) ->
?INFO_MSG("Roster process Item... Acc= ~p~n Server= ~p~n", [Acc, Server]).
rosterget(Acc, {User,Server}) ->
?INFO_MSG("Roster Get.... Acc= ~p~n User/Server= ~p~n", [Acc, {User,Server}]).
rostergetjidinfo(Acc, User, Server, From) ->
?INFO_MSG("Roster Get Jid Info.... Acc= ~p~n User= ~p.~n Server= ~p~n From= ~p~n", [Acc, User,Server, From]).
rostergetsubscriptionlists(Acc, User, Server) ->
?INFO_MSG("Roster Get Subscription List.... Acc= ~p~n User= ~p~n Server= ~p~n", [Acc, User,Server]).
rostergetversioningfeature(Acc, User, Server) ->
?INFO_MSG("Roster Get Versioning Feature.... Acc= ~p~n User= ~p~n Server= ~p~n", [Acc, User,Server]),
[].
rostergroup(Acc, ServerHost) ->
?INFO_MSG("Roster Group.... Acc= ~p~n ServerHost= ~p~n", [Acc, ServerHost]).
rosterinsubscription(Acc, User, Server, From, SubscriptionInType, Reason) ->
?INFO_MSG("Roster In Subscription.... Acc= ~p~n User= ~p.~n Server= ~p~n From= ~p~n SubscriptionType= ~p~n Reason= ~p~n", [Acc, User,Server, From, SubscriptionInType, Reason]).
rosteroutsubscription(Acc, Server, To, SubscriptionOutType) ->
?INFO_MSG("Roster Out Subscription.... Acc= ~p~n Server= ~p~n To= ~p~n SubscriptionType= ~p~n", [Acc, Server, To, SubscriptionOutType]).
setpresencehook(User, Server, Resource, Presence) ->
?INFO_MSG("Set Presence Hook.... User= ~p~n Server= ~p~n Resource= ~p~n Presence= ~p~n", [User, Server, Resource, Presence]),
ok.
resendsubscriptionrequestshook(Acc, User, Server) ->
?INFO_MSG("Resend Subscription Request Hook.... Acc= ~p~n User= ~p~n Server= ~p~n", [Acc, User,Server]).
ejabberd 日志条目(显示错误):
2016-02-10 22:10:07.975 [error] <0.5735.0>@ejabberd_hooks:run_fold1:368 {undef,[{mod_monitor_roster,rostergetversioningfeature,[[],<<"adminpc">>],[]},{ejabberd_hooks,safe_apply,3,[{file,"src/ejabberd_hooks.erl"},{line,382}]},{ejabberd_hooks,run_fold1,4,[{file,"src/ejabberd_hooks.erl"},{line,365}]},{ejabberd_c2s,wait_for_stream,2,[{file,"src/ejabberd_c2s.erl"},{line,463}]},{p1_fsm,handle_msg,10,[{file,"src/p1_fsm.erl"},{line,582}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,237}]}]} running hook: {roster_get_versioning_feature,[<<"adminpc">>]}
2016-02-10 22:10:08.178 [info] <0.5735.0>@ejabberd_c2s:wait_for_session:1117 ({socket_state,p1_tls,{tlssock,#Port<0.6781>,#Port<0.6784>},<0.5734.0>}) Opened session for karen@adminpc/adminPC
2016-02-10 22:10:08.178 [info] <0.5735.0>@mod_monitor_roster:rostergetsubscriptionlists:93 Roster Get Subscription List.... Acc= {[],[]} User= <<"karen">> Server= <<"adminpc">>
2016-02-10 22:10:08.255 [info] <0.451.0>@mod_monitor_roster:rosterget:87 Roster Get.... Acc= [] User/Server= {<<"karen">>,<<"adminpc">>}
2016-02-10 22:10:08.256 [error] <0.451.0>@ejabberd_hooks:run_fold1:368 {function_clause,[{lists,mapfoldl,[#Fun<mod_shared_roster.1.107782361>,{dict,0,16,16,8,80,48,{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},{{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}}},ok],[{file,"lists.erl"},{line,1351}]},{lists,mapfoldl,3,[{file,"lists.erl"},{line,1353}]},{lists,mapfoldl,3,[{file,"lists.erl"},{line,1353}]},{mod_shared_roster,get_user_roster,2,[{file,"src/mod_shared_roster.erl"},{line,148}]},{ejabberd_hooks,safe_apply,3,[{file,"src/ejabberd_hooks.erl"},{line,382}]},{ejabberd_hooks,run_fold1,4,[{file,"src/ejabberd_hooks.erl"},{line,365}]},{mod_roster,process_iq_get,3,[{file,"src/mod_roster.erl"},{line,316}]},{gen_iq_handler,process_iq,6,[{file,"src/gen_iq_handler.erl"},{line,127}]}]} running hook: {roster_get,[{<<"karen">>,<<"adminpc">>}]}
2016-02-10 22:10:08.272 [info] <0.5735.0>@mod_monitor_roster:setpresencehook:109 Set Presence Hook.... User=<<"karen">> Server= <<"adminpc">> Resource= <<"adminPC">> Presence= {xmlel,<<"presence">>,[{<<"xml:lang">>,<<"en">>}],[{xmlcdata,<<"\n">>},{xmlel,<<"priority">>,[],[{xmlcdata,<<"5">>}]},{xmlcdata,<<"\n">>},{xmlel,<<"c">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/caps">>},{<<"node">>,<<"http://psi-im.org/caps">>},{<<"ver">>,<<"caps-b75d8d2b25">>},{<<"ext">>,<<"ca cs ep-notify-2 html">>}],[]},{xmlcdata,<<"\n">>}]}
2016-02-10 22:12:41.994 [info] <0.475.0>@ejabberd_listener:accept:299 (#Port<0.6792>) Accepted connection 127.0.0.1:23595 -> 127.0.0.1:5280
希望我提供了所有信息
此致,
会
第一个错误表明 ejabberd_hooks
模块无法为 roster_get_versioning_feature
挂钩找到 运行 所需的函数。这个钩子需要一个带有两个个参数(arity)的函数,但是你实现的有三个个参数,所以ejabberd_hooks
找不到它。您必须使用以下描述的函数规范 here.
roster_get_versioning_feature(Acc, Server) -> []
第二个错误抱怨传递给 lists:mapfoldl/3
函数的参数。其规格如下:
mapfoldl(Fun, Acc0, List1) -> {List2, Acc1}
具有以下类型:
Fun = fun((A, AccIn) -> {B, AccOut})
Acc0 = Acc1 = AccIn = AccOut = term()
List1 = [A]
List2 = [B]
A = B = term()
日志说第一个参数是一个函数,第二个参数是一个字典,它们似乎是正确的。但是必须是列表的第三个参数只是一个 ok
项,所以 mapfoldl
会抛出错误。
对于 mapfoldl
function_clause
错误,问题出在您的 roster_get
挂钩函数上。添加到此挂钩的函数获取用户列表,并且应该将它们自己的条目添加到此列表并将其传递。这是通过 ejabberd_hook:run_fold
完成的。但是,由于您的 rosterget
函数只打印一条调试消息,因此它 returns ok
而不是要传递的列表,这稍后会导致 mod_shared_roster
,因为它将 认为 是列表传递给 lists:mapfoldl
,但它实际上是原子 ok
。
要解决此问题,return 来自 rosterget
函数的 Acc
值,如下所示:
rosterget(Acc, {User,Server}) ->
?INFO_MSG("Roster Get.... Acc= ~p~n User/Server= ~p~n", [Acc, {User,Server}]),
Acc.
我怀疑您需要对所有获得 Acc
参数的函数执行相同的操作。
在 ejabberd 的论坛上发布了这个问题,但没有得到回应,所以我将其发布在这里 (https://www.ejabberd.im/forum/25371/tracking-roster-and-presence-cause-error)。我创建了一个简单的 ejabberd 模块来记录名册和状态的所有事件。我试图了解事件的顺序和每个事件的参数。一切似乎都正常,除了我在 ejabberd 日志文件中看到 2 个错误,我不确定如何修复它们,因为我所做的只是写入日志文件。
模块代码(mod_monitor_roster):
start(Host, Opt) ->
?INFO_MSG("Monitor Roster Started for Host (~p) and Opt(~p)...~n", [Host, Opt]),
%%Add the roster hooks here...
ejabberd_hooks:add(roster_process_item, Host, ?MODULE, process_item, 10),
ejabberd_hooks:add(roster_get, Host, ?MODULE, rosterget, 10),
ejabberd_hooks:add(roster_get_jid_info, Host, ?MODULE, rostergetjidinfo, 10),
ejabberd_hooks:add(roster_get_subscription_lists, Host, ?MODULE, rostergetsubscriptionlists, 10),
ejabberd_hooks:add(roster_get_versioning_feature, Host, ?MODULE, rostergetversioningfeature, 10),
ejabberd_hooks:add(roster_groups, Host, ?MODULE, rostergroup, 10),
ejabberd_hooks:add(roster_in_subscription, Host, ?MODULE, rosterinsubscription, 10),
ejabberd_hooks:add(roster_out_subscription, Host, ?MODULE, rosteroutsubscription, 10),
ejabberd_hooks:add(set_presence_hook, Host, ?MODULE, setpresencehook, 1),
%%ejabberd_hooks:add(resend_subscription_requests_hook, Host, ?MODULE, resendsubscriptionrequestshook, 50),
ok.
process_item(Acc, Server) ->
?INFO_MSG("Roster process Item... Acc= ~p~n Server= ~p~n", [Acc, Server]).
rosterget(Acc, {User,Server}) ->
?INFO_MSG("Roster Get.... Acc= ~p~n User/Server= ~p~n", [Acc, {User,Server}]).
rostergetjidinfo(Acc, User, Server, From) ->
?INFO_MSG("Roster Get Jid Info.... Acc= ~p~n User= ~p.~n Server= ~p~n From= ~p~n", [Acc, User,Server, From]).
rostergetsubscriptionlists(Acc, User, Server) ->
?INFO_MSG("Roster Get Subscription List.... Acc= ~p~n User= ~p~n Server= ~p~n", [Acc, User,Server]).
rostergetversioningfeature(Acc, User, Server) ->
?INFO_MSG("Roster Get Versioning Feature.... Acc= ~p~n User= ~p~n Server= ~p~n", [Acc, User,Server]),
[].
rostergroup(Acc, ServerHost) ->
?INFO_MSG("Roster Group.... Acc= ~p~n ServerHost= ~p~n", [Acc, ServerHost]).
rosterinsubscription(Acc, User, Server, From, SubscriptionInType, Reason) ->
?INFO_MSG("Roster In Subscription.... Acc= ~p~n User= ~p.~n Server= ~p~n From= ~p~n SubscriptionType= ~p~n Reason= ~p~n", [Acc, User,Server, From, SubscriptionInType, Reason]).
rosteroutsubscription(Acc, Server, To, SubscriptionOutType) ->
?INFO_MSG("Roster Out Subscription.... Acc= ~p~n Server= ~p~n To= ~p~n SubscriptionType= ~p~n", [Acc, Server, To, SubscriptionOutType]).
setpresencehook(User, Server, Resource, Presence) ->
?INFO_MSG("Set Presence Hook.... User= ~p~n Server= ~p~n Resource= ~p~n Presence= ~p~n", [User, Server, Resource, Presence]),
ok.
resendsubscriptionrequestshook(Acc, User, Server) ->
?INFO_MSG("Resend Subscription Request Hook.... Acc= ~p~n User= ~p~n Server= ~p~n", [Acc, User,Server]).
ejabberd 日志条目(显示错误):
2016-02-10 22:10:07.975 [error] <0.5735.0>@ejabberd_hooks:run_fold1:368 {undef,[{mod_monitor_roster,rostergetversioningfeature,[[],<<"adminpc">>],[]},{ejabberd_hooks,safe_apply,3,[{file,"src/ejabberd_hooks.erl"},{line,382}]},{ejabberd_hooks,run_fold1,4,[{file,"src/ejabberd_hooks.erl"},{line,365}]},{ejabberd_c2s,wait_for_stream,2,[{file,"src/ejabberd_c2s.erl"},{line,463}]},{p1_fsm,handle_msg,10,[{file,"src/p1_fsm.erl"},{line,582}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,237}]}]} running hook: {roster_get_versioning_feature,[<<"adminpc">>]}
2016-02-10 22:10:08.178 [info] <0.5735.0>@ejabberd_c2s:wait_for_session:1117 ({socket_state,p1_tls,{tlssock,#Port<0.6781>,#Port<0.6784>},<0.5734.0>}) Opened session for karen@adminpc/adminPC
2016-02-10 22:10:08.178 [info] <0.5735.0>@mod_monitor_roster:rostergetsubscriptionlists:93 Roster Get Subscription List.... Acc= {[],[]} User= <<"karen">> Server= <<"adminpc">>
2016-02-10 22:10:08.255 [info] <0.451.0>@mod_monitor_roster:rosterget:87 Roster Get.... Acc= [] User/Server= {<<"karen">>,<<"adminpc">>}
2016-02-10 22:10:08.256 [error] <0.451.0>@ejabberd_hooks:run_fold1:368 {function_clause,[{lists,mapfoldl,[#Fun<mod_shared_roster.1.107782361>,{dict,0,16,16,8,80,48,{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},{{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}}},ok],[{file,"lists.erl"},{line,1351}]},{lists,mapfoldl,3,[{file,"lists.erl"},{line,1353}]},{lists,mapfoldl,3,[{file,"lists.erl"},{line,1353}]},{mod_shared_roster,get_user_roster,2,[{file,"src/mod_shared_roster.erl"},{line,148}]},{ejabberd_hooks,safe_apply,3,[{file,"src/ejabberd_hooks.erl"},{line,382}]},{ejabberd_hooks,run_fold1,4,[{file,"src/ejabberd_hooks.erl"},{line,365}]},{mod_roster,process_iq_get,3,[{file,"src/mod_roster.erl"},{line,316}]},{gen_iq_handler,process_iq,6,[{file,"src/gen_iq_handler.erl"},{line,127}]}]} running hook: {roster_get,[{<<"karen">>,<<"adminpc">>}]}
2016-02-10 22:10:08.272 [info] <0.5735.0>@mod_monitor_roster:setpresencehook:109 Set Presence Hook.... User=<<"karen">> Server= <<"adminpc">> Resource= <<"adminPC">> Presence= {xmlel,<<"presence">>,[{<<"xml:lang">>,<<"en">>}],[{xmlcdata,<<"\n">>},{xmlel,<<"priority">>,[],[{xmlcdata,<<"5">>}]},{xmlcdata,<<"\n">>},{xmlel,<<"c">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/caps">>},{<<"node">>,<<"http://psi-im.org/caps">>},{<<"ver">>,<<"caps-b75d8d2b25">>},{<<"ext">>,<<"ca cs ep-notify-2 html">>}],[]},{xmlcdata,<<"\n">>}]}
2016-02-10 22:12:41.994 [info] <0.475.0>@ejabberd_listener:accept:299 (#Port<0.6792>) Accepted connection 127.0.0.1:23595 -> 127.0.0.1:5280
希望我提供了所有信息
此致,
会
第一个错误表明 ejabberd_hooks
模块无法为 roster_get_versioning_feature
挂钩找到 运行 所需的函数。这个钩子需要一个带有两个个参数(arity)的函数,但是你实现的有三个个参数,所以ejabberd_hooks
找不到它。您必须使用以下描述的函数规范 here.
roster_get_versioning_feature(Acc, Server) -> []
第二个错误抱怨传递给 lists:mapfoldl/3
函数的参数。其规格如下:
mapfoldl(Fun, Acc0, List1) -> {List2, Acc1}
具有以下类型:
Fun = fun((A, AccIn) -> {B, AccOut})
Acc0 = Acc1 = AccIn = AccOut = term()
List1 = [A]
List2 = [B]
A = B = term()
日志说第一个参数是一个函数,第二个参数是一个字典,它们似乎是正确的。但是必须是列表的第三个参数只是一个 ok
项,所以 mapfoldl
会抛出错误。
对于 mapfoldl
function_clause
错误,问题出在您的 roster_get
挂钩函数上。添加到此挂钩的函数获取用户列表,并且应该将它们自己的条目添加到此列表并将其传递。这是通过 ejabberd_hook:run_fold
完成的。但是,由于您的 rosterget
函数只打印一条调试消息,因此它 returns ok
而不是要传递的列表,这稍后会导致 mod_shared_roster
,因为它将 认为 是列表传递给 lists:mapfoldl
,但它实际上是原子 ok
。
要解决此问题,return 来自 rosterget
函数的 Acc
值,如下所示:
rosterget(Acc, {User,Server}) ->
?INFO_MSG("Roster Get.... Acc= ~p~n User/Server= ~p~n", [Acc, {User,Server}]),
Acc.
我怀疑您需要对所有获得 Acc
参数的函数执行相同的操作。