Skip to content

Commit

Permalink
Properly handle IQ requests in mod_matrix_gw
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeyshch committed Feb 21, 2025
1 parent 80423d7 commit 41232cc
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
49 changes: 48 additions & 1 deletion src/mod_matrix_gw.erl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
prune_event/2, get_event_id/2, content_hash/1,
sign_event/3, sign_pruned_event/2, sign_json/2,
send_request/8, s2s_out_bounce_packet/2, user_receive_packet/1,
process_disco_info/1,
process_disco_items/1,
route/1]).

-include_lib("xmpp/include/xmpp.hrl").
Expand Down Expand Up @@ -516,6 +518,10 @@ init([Host]) ->
Opts = gen_mod:get_module_opts(Host, ?MODULE),
MyHost = gen_mod:get_opt(host, Opts),
register_routes(Host, [MyHost]),
gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO,
?MODULE, process_disco_info),
gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS,
?MODULE, process_disco_items),
{ok, #state{server_host = Host, host = MyHost}}.

-spec handle_call(term(), {pid(), term()}, state()) ->
Expand All @@ -536,7 +542,11 @@ handle_info(Info, State) ->

-spec terminate(term(), state()) -> any().
terminate(_Reason, #state{host = Host}) ->
unregister_routes([Host]).
unregister_routes([Host]),
gen_iq_handler:del_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
?MODULE, process_disco_info),
gen_iq_handler:del_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS,
?MODULE, process_disco_items).

-spec code_change(term(), state(), term()) -> {ok, state()}.
code_change(_OldVsn, State, _Extra) -> {ok, State}.
Expand Down Expand Up @@ -873,9 +883,46 @@ user_receive_packet({Pkt, C2SState} = Acc) ->
end
end.

-spec route(stanza()) -> ok.
route(#iq{to = #jid{luser = <<"">>, lresource = <<"">>}} = IQ) ->
ejabberd_router:process_iq(IQ);
route(Pkt) ->
mod_matrix_gw_room:route(Pkt).

-spec process_disco_info(iq()) -> iq().
process_disco_info(#iq{type = set, lang = Lang} = IQ) ->
Txt = ?T("Value 'set' of 'type' attribute is not allowed"),
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
process_disco_info(#iq{type = get,
sub_els = [#disco_info{node = <<"">>}]} = IQ) ->
Features = [?NS_DISCO_INFO, ?NS_DISCO_ITEMS, ?NS_MUC],
Identity = #identity{category = <<"gateway">>,
type = <<"matrix">>},
xmpp:make_iq_result(
IQ, #disco_info{features = Features,
identities = [Identity]});
process_disco_info(#iq{type = get, lang = Lang,
sub_els = [#disco_info{}]} = IQ) ->
xmpp:make_error(IQ, xmpp:err_item_not_found(?T("Node not found"), Lang));
process_disco_info(#iq{lang = Lang} = IQ) ->
Txt = ?T("No module is handling this query"),
xmpp:make_error(IQ, xmpp:err_service_unavailable(Txt, Lang)).

-spec process_disco_items(iq()) -> iq().
process_disco_items(#iq{type = set, lang = Lang} = IQ) ->
Txt = ?T("Value 'set' of 'type' attribute is not allowed"),
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang));
process_disco_items(#iq{type = get,
sub_els = [#disco_items{node = <<>>}]} = IQ) ->
xmpp:make_iq_result(IQ, #disco_items{});
process_disco_items(#iq{type = get, lang = Lang,
sub_els = [#disco_items{}]} = IQ) ->
xmpp:make_error(IQ, xmpp:err_item_not_found(?T("Node not found"), Lang));
process_disco_items(#iq{lang = Lang} = IQ) ->
Txt = ?T("No module is handling this query"),
xmpp:make_error(IQ, xmpp:err_service_unavailable(Txt, Lang)).


depends(_Host, _Opts) ->
[].

Expand Down
36 changes: 36 additions & 0 deletions src/mod_matrix_gw_room.erl
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,42 @@ route(#message{from = From, to = To, body = Body} = _Pkt) ->
error ->
ok
end;
route(#iq{type = Type}) when Type == error; Type == result ->
ok;
route(#iq{type = Type, lang = Lang, sub_els = [_]} = IQ0) ->
try xmpp:decode_els(IQ0) of
#iq{sub_els = [SubEl]} = IQ ->
Result =
case {Type, SubEl} of
{set, _} ->
{error, xmpp:err_not_allowed()};
{get, #disco_info{node = <<>>}} ->
{result,
#disco_info{identities =
[#identity{category = <<"conference">>,
type = <<"text">>}],
features = [?NS_MUC, ?NS_DISCO_INFO, ?NS_DISCO_ITEMS]}};
{get, #disco_info{node = _}} ->
{error, xmpp:err_item_not_found()};
{get, #disco_items{node = <<>>}} ->
{result, #disco_items{}};
{get, #disco_items{node = _}} ->
{error, xmpp:err_item_not_found()};
_ ->
{error, xmpp:err_service_unavailable()}
end,
case Result of
{result, Res} ->
ejabberd_router:route(xmpp:make_iq_result(IQ, Res));
{error, Error} ->
ejabberd_router:route(xmpp:make_error(IQ, Error))
end
catch _:{xmpp_codec, Why} ->
ErrTxt = xmpp:io_format_error(Why),
Err = xmpp:err_bad_request(ErrTxt, Lang),
ejabberd_router:route_error(IQ0, Err),
ok
end;
route(_) ->
ok.

Expand Down

0 comments on commit 41232cc

Please sign in to comment.