终止原因:没有函数子句匹配 jlib:iq_to_xml
terminated with reason: no function clause matching jlib:iq_to_xml
我已经为 ejabberd 编写了一个 iq 处理程序模块,它接受一个 iq 查询并且应该 return iq 记录与相关元素更新。我已经在这个问题上待了 2 天没有解决,所以我把它贴在这里寻求帮助。
process_local_iq(_From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
?INFO_MSG("PROCESS LOCAL IQ Type=~p ~n SubEl =~p ~n IQ=~p~n", [Type, SubEl, IQ]),
%%Check that the server name is the TO by testing the emptiness of the user id part of the JID
if To#jid.luser == <<"">> ->
%%Get the ID for the iq request
%%Id=IQ#iq.id,
%%Take out the subTypes from the sub_el and Place in variable SubType
SubType = proplists:get_value(<<"type">>, IQ#iq.sub_el#xmlel.attrs),
?INFO_MSG("PROCESS LOCAL IQ GET - SubType = ~p~n", [SubType]),
case Type of
set ->
%%Add the NEW user to the jid_user table OR UPDATE the current one
if SubType== <<"UPDATE">> ->
%% Use the Userid and update the jid_user table
?INFO_MSG("PROCESS LOCAL IQ SET - UPDATE", []),
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
end,
if SubType == <<"NEW">> ->
%% Write the new record to the database - table jid_user
?INFO_MSG("PROCESS LOCAL IQ SET - NEW", []),
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
end,
%%Get the type from the #iq body and test it
?INFO_MSG("PROCESS LOCAL IQ SET", []),
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
get ->
%%Either CHECK the availability of a userid OR RETRIEVE a known user information
%% Get the user id from the xml packet
Childrenrec = IQ#iq.sub_el#xmlel.children,
Attrib = IQ#iq.sub_el#xmlel.attrs,
[Childrenrec]),
SubRec = proplists:lookup(xmlel, Childrenrec),
KList = SubRec#xmlel.children,
UserId = proplists:get_value(xmlcdata, KList),
case SubType of
<<"RETRIEVE">> ->
%% Use the Userid and retrieve the record from the jid_user table
?INFO_MSG("PROCESS LOCAL IQ GET RETRIEVE - UserId = ~p~n", [UserId]),
FR = fun() ->
case Rec = mnesia:read({jid_users, UserId}) =:= [] of
true -> %% User id is available for use so update the iq record with the status
IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = Attrib, children = [{xmlcdata, "RECORD NOT FOUND"}]}]};
false -> %% Record found so use the data populate the xml structure
%%Rec1 = lists:last(Rec),
XmlStruct = item_to_xml(Rec#jid_users{}), %%Convert the record to XML
IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [], children = [XmlStruct]}]}
end
end,
mnesia:transaction(FR);
<<"CHECK">> ->
%% Check if the requested user id is available
?INFO_MSG("PROCESS LOCAL IQ GET CHECK - UserId = ~p~n", [UserId]),
%%User the id and check the mnesia table jib_user
FC = fun() ->
case mnesia:read({jid_users, UserId}) =:= [] of
true -> %% User id is available for use so update the iq record with the status
**Test =IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = Attrib, children = [#xmlel{name = <<"userid">>, attrs = [], children=[{xmlcdata, <<"available">>}]}]}]},**
?INFO_MSG("PROCESS LOCAL IQ GET CHECK - Test= ~p~n", [Test]),
Test;
false -> %% User Id already being used
IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, children = [{#xmlel{name = <<"userid">>, attrs = [], children=[{xmlcdata, "NOT AVAILABLE"}]}}]}]}
%% IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [], children = [{xmlcdata, "NOT AVAILABLE"}]}]}
end
end,
mnesia:transaction(FC)
end
end;
true ->
%%Return and empty record with body set to some value
?INFO_MSG("PROCESS LOCAL IQ SET - FULL JID SUPPLIED", []),
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
end.
这行代码失败了:
Test =IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = Attrib, children = [#xmlel{name = <<"userid">>, attrs = [], children=[{xmlcdata, <<"available">>}]}]}]},
出现此错误(在日志中):
2016-03-13 23:51:44.923 [error] <0.421.0> gen_server <0.421.0> terminated with reason: no function clause matching jlib:iq_to_xml({atomic,{iq,<<>>,result,<<>>,<<>>,{xmlel,<<"query">>,[{<<"xmlns">>,<<"user:profile">>},{<<"type">>,...}],...}}}) line 463
2016-03-13 23:51:44.923 [error] <0.421.0> CRASH REPORT Process <0.421.0> with 0 neighbours exited with reason: no function clause matching jlib:iq_to_xml({atomic,{iq,<<>>,result,<<>>,<<>>,{xmlel,<<"query">>,[{<<"xmlns">>,<<"user:profile">>},{<<"type">>,...}],...}}}) line 463 in gen_server:terminate/7 line 804
2016-03-13 23:51:44.923 [error] <0.349.0> Supervisor ejabberd_iq_sup had child undefined started with {gen_iq_handler,start_link,undefined} at <0.421.0> exit with reason no function clause matching jlib:iq_to_xml({atomic,{iq,<<>>,result,<<>>,<<>>,{xmlel,<<"query">>,[{<<"xmlns">>,<<"user:profile">>},{<<"type">>,...}],...}}}) line 463 in context child_terminated
这是客户端发送并由 iq 处理程序接收的输入 iq:
IQ={iq,<<"MX_4">>,get,<<"user:profile">>,<<>>,{xmlel,<<"query">>,[{<<"xmlns">>,<<"user:profile">>},{<<"type">>,<<"CHECK">>}],[{xmlel,<<"userId">>,[],[{xmlcdata,<<"wilford">>}]}]}}
希望我已经发布了足够的信息。
此致,
会
您应该 return 直接从该函数获取 IQ 回复,以便它被 ejabberd 路由。
相反,您正在 return 调用 mnesia:transaction/1
的结果,格式为 {atomic, Result}
。这不是有效的 IQ 数据包。
因此您需要解包 mnesia 事务结果以将周围的元组 {atomic, Result} 移除为 return 结果。
我已经为 ejabberd 编写了一个 iq 处理程序模块,它接受一个 iq 查询并且应该 return iq 记录与相关元素更新。我已经在这个问题上待了 2 天没有解决,所以我把它贴在这里寻求帮助。
process_local_iq(_From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
?INFO_MSG("PROCESS LOCAL IQ Type=~p ~n SubEl =~p ~n IQ=~p~n", [Type, SubEl, IQ]),
%%Check that the server name is the TO by testing the emptiness of the user id part of the JID
if To#jid.luser == <<"">> ->
%%Get the ID for the iq request
%%Id=IQ#iq.id,
%%Take out the subTypes from the sub_el and Place in variable SubType
SubType = proplists:get_value(<<"type">>, IQ#iq.sub_el#xmlel.attrs),
?INFO_MSG("PROCESS LOCAL IQ GET - SubType = ~p~n", [SubType]),
case Type of
set ->
%%Add the NEW user to the jid_user table OR UPDATE the current one
if SubType== <<"UPDATE">> ->
%% Use the Userid and update the jid_user table
?INFO_MSG("PROCESS LOCAL IQ SET - UPDATE", []),
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
end,
if SubType == <<"NEW">> ->
%% Write the new record to the database - table jid_user
?INFO_MSG("PROCESS LOCAL IQ SET - NEW", []),
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
end,
%%Get the type from the #iq body and test it
?INFO_MSG("PROCESS LOCAL IQ SET", []),
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]};
get ->
%%Either CHECK the availability of a userid OR RETRIEVE a known user information
%% Get the user id from the xml packet
Childrenrec = IQ#iq.sub_el#xmlel.children,
Attrib = IQ#iq.sub_el#xmlel.attrs,
[Childrenrec]),
SubRec = proplists:lookup(xmlel, Childrenrec),
KList = SubRec#xmlel.children,
UserId = proplists:get_value(xmlcdata, KList),
case SubType of
<<"RETRIEVE">> ->
%% Use the Userid and retrieve the record from the jid_user table
?INFO_MSG("PROCESS LOCAL IQ GET RETRIEVE - UserId = ~p~n", [UserId]),
FR = fun() ->
case Rec = mnesia:read({jid_users, UserId}) =:= [] of
true -> %% User id is available for use so update the iq record with the status
IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = Attrib, children = [{xmlcdata, "RECORD NOT FOUND"}]}]};
false -> %% Record found so use the data populate the xml structure
%%Rec1 = lists:last(Rec),
XmlStruct = item_to_xml(Rec#jid_users{}), %%Convert the record to XML
IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [], children = [XmlStruct]}]}
end
end,
mnesia:transaction(FR);
<<"CHECK">> ->
%% Check if the requested user id is available
?INFO_MSG("PROCESS LOCAL IQ GET CHECK - UserId = ~p~n", [UserId]),
%%User the id and check the mnesia table jib_user
FC = fun() ->
case mnesia:read({jid_users, UserId}) =:= [] of
true -> %% User id is available for use so update the iq record with the status
**Test =IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = Attrib, children = [#xmlel{name = <<"userid">>, attrs = [], children=[{xmlcdata, <<"available">>}]}]}]},**
?INFO_MSG("PROCESS LOCAL IQ GET CHECK - Test= ~p~n", [Test]),
Test;
false -> %% User Id already being used
IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, children = [{#xmlel{name = <<"userid">>, attrs = [], children=[{xmlcdata, "NOT AVAILABLE"}]}}]}]}
%% IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [], children = [{xmlcdata, "NOT AVAILABLE"}]}]}
end
end,
mnesia:transaction(FC)
end
end;
true ->
%%Return and empty record with body set to some value
?INFO_MSG("PROCESS LOCAL IQ SET - FULL JID SUPPLIED", []),
IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
end.
这行代码失败了:
Test =IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = Attrib, children = [#xmlel{name = <<"userid">>, attrs = [], children=[{xmlcdata, <<"available">>}]}]}]},
出现此错误(在日志中):
2016-03-13 23:51:44.923 [error] <0.421.0> gen_server <0.421.0> terminated with reason: no function clause matching jlib:iq_to_xml({atomic,{iq,<<>>,result,<<>>,<<>>,{xmlel,<<"query">>,[{<<"xmlns">>,<<"user:profile">>},{<<"type">>,...}],...}}}) line 463
2016-03-13 23:51:44.923 [error] <0.421.0> CRASH REPORT Process <0.421.0> with 0 neighbours exited with reason: no function clause matching jlib:iq_to_xml({atomic,{iq,<<>>,result,<<>>,<<>>,{xmlel,<<"query">>,[{<<"xmlns">>,<<"user:profile">>},{<<"type">>,...}],...}}}) line 463 in gen_server:terminate/7 line 804
2016-03-13 23:51:44.923 [error] <0.349.0> Supervisor ejabberd_iq_sup had child undefined started with {gen_iq_handler,start_link,undefined} at <0.421.0> exit with reason no function clause matching jlib:iq_to_xml({atomic,{iq,<<>>,result,<<>>,<<>>,{xmlel,<<"query">>,[{<<"xmlns">>,<<"user:profile">>},{<<"type">>,...}],...}}}) line 463 in context child_terminated
这是客户端发送并由 iq 处理程序接收的输入 iq:
IQ={iq,<<"MX_4">>,get,<<"user:profile">>,<<>>,{xmlel,<<"query">>,[{<<"xmlns">>,<<"user:profile">>},{<<"type">>,<<"CHECK">>}],[{xmlel,<<"userId">>,[],[{xmlcdata,<<"wilford">>}]}]}}
希望我已经发布了足够的信息。
此致,
会
您应该 return 直接从该函数获取 IQ 回复,以便它被 ejabberd 路由。
相反,您正在 return 调用 mnesia:transaction/1
的结果,格式为 {atomic, Result}
。这不是有效的 IQ 数据包。
因此您需要解包 mnesia 事务结果以将周围的元组 {atomic, Result} 移除为 return 结果。