原因终止:没有匹配jlib的函数子句:iq_to_xml

时间:2016-03-15 06:13:58

标签: erlang ejabberd

我已经为ejabberd编写了一个iq处理程序模块,该模块接受了iq查询,并且应该返回更新相关元素的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">>}]}]}}

希望我已经发布了足够的信息。

此致

威尔

1 个答案:

答案 0 :(得分:1)

你应该直接从该函数返回IQ回复,以便它被ejabberd路由。

相反,您将返回mnesia:transaction/1形式的调用{atomic, Result}的结果。这不是有效的IQ数据包。

因此,您需要打开mnesia事务结果以删除周围的元组{atomic,Result}以返回结果。