Reduce IQ handler code copying

This commit is contained in:
Evgeniy Khramtsov 2018-05-09 10:30:00 +03:00
parent 11ff2a1ccf
commit 680384c342
5 changed files with 67 additions and 123 deletions

View File

@ -32,10 +32,8 @@
%% API
-export([start/0, start_link/0]).
-export([route/1, process_iq/1,
-export([route/1,
get_features/1,
register_iq_handler/4,
unregister_iq_handler/2,
bounce_resource_packet/1,
host_up/1, host_down/1]).
@ -54,8 +52,6 @@
-record(state, {}).
-define(IQTABLE, local_iqtable).
%%====================================================================
%% API
%%====================================================================
@ -72,30 +68,6 @@ start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [],
[]).
-spec process_iq(iq()) -> any().
process_iq(#iq{to = To, type = T, lang = Lang, sub_els = [El]} = Packet)
when T == get; T == set ->
XMLNS = xmpp:get_ns(El),
Host = To#jid.lserver,
case ets:lookup(?IQTABLE, {Host, XMLNS}) of
[{_, Module, Function}] ->
gen_iq_handler:handle(Host, Module, Function, Packet);
[] ->
Txt = <<"No module is handling this query">>,
Err = xmpp:err_service_unavailable(Txt, Lang),
ejabberd_router:route_error(Packet, Err)
end;
process_iq(#iq{type = T, lang = Lang, sub_els = SubEls} = Packet)
when T == get; T == set ->
Txt = case SubEls of
[] -> <<"No child elements found">>;
_ -> <<"Too many child elements">>
end,
Err = xmpp:err_bad_request(Txt, Lang),
ejabberd_router:route_error(Packet, Err);
process_iq(#iq{type = T}) when T == result; T == error ->
ok.
-spec route(stanza()) -> any().
route(Packet) ->
try do_route(Packet)
@ -112,15 +84,6 @@ route_iq(IQ, Fun) ->
route_iq(IQ, Fun, Timeout) ->
ejabberd_router:route_iq(IQ, Fun, undefined, Timeout).
-spec register_iq_handler(binary(), binary(), module(), function()) -> ok.
register_iq_handler(Host, XMLNS, Module, Fun) ->
gen_server:cast(?MODULE,
{register_iq_handler, Host, XMLNS, Module, Fun}).
-spec unregister_iq_handler(binary(), binary()) -> ok.
unregister_iq_handler(Host, XMLNS) ->
gen_server:cast(?MODULE, {unregister_iq_handler, Host, XMLNS}).
-spec bounce_resource_packet(stanza()) -> ok | stop.
bounce_resource_packet(#presence{to = #jid{lresource = <<"">>}}) ->
ok;
@ -135,12 +98,7 @@ bounce_resource_packet(Packet) ->
-spec get_features(binary()) -> [binary()].
get_features(Host) ->
get_features(ets:next(?IQTABLE, {Host, <<"">>}), Host, []).
get_features({Host, XMLNS}, Host, XMLNSs) ->
get_features(ets:next(?IQTABLE, {Host, XMLNS}), Host, [XMLNS|XMLNSs]);
get_features(_, _, XMLNSs) ->
XMLNSs.
gen_iq_handler:get_features(?MODULE, Host).
%%====================================================================
%% gen_server callbacks
@ -151,23 +109,13 @@ init([]) ->
lists:foreach(fun host_up/1, ?MYHOSTS),
ejabberd_hooks:add(host_up, ?MODULE, host_up, 10),
ejabberd_hooks:add(host_down, ?MODULE, host_down, 100),
catch ets:new(?IQTABLE, [named_table, public, ordered_set,
{read_concurrency, true}]),
gen_iq_handler:start(?MODULE),
update_table(),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
Reply = ok, {reply, Reply, State}.
handle_cast({register_iq_handler, Host, XMLNS, Module, Function},
State) ->
ets:insert(?IQTABLE,
{{Host, XMLNS}, Module, Function}),
{noreply, State};
handle_cast({unregister_iq_handler, Host, XMLNS},
State) ->
ets:delete(?IQTABLE, {Host, XMLNS}),
{noreply, State};
handle_cast(_Msg, State) -> {noreply, State}.
handle_info({route, Packet}, State) ->
@ -197,7 +145,7 @@ do_route(Packet) ->
if To#jid.luser /= <<"">> ->
ejabberd_sm:route(Packet);
is_record(Packet, iq), To#jid.lresource == <<"">> ->
process_iq(Packet);
gen_iq_handler:handle(?MODULE, Packet);
Type == result; Type == error ->
ok;
true ->

View File

@ -306,12 +306,8 @@ is_my_host(Domain) ->
end.
-spec process_iq(iq()) -> any().
process_iq(#iq{to = To} = IQ) ->
if To#jid.luser == <<"">> ->
ejabberd_local:process_iq(IQ);
true ->
ejabberd_sm:process_iq(IQ)
end.
process_iq(IQ) ->
gen_iq_handler:handle(IQ).
-spec config_reloaded() -> ok.
config_reloaded() ->

View File

@ -39,7 +39,6 @@
stop/0,
route/1,
route/2,
process_iq/1,
open_session/5,
open_session/6,
close_session/4,
@ -58,8 +57,6 @@
get_vh_session_list/1,
get_vh_session_number/1,
get_vh_by_backend/1,
register_iq_handler/4,
unregister_iq_handler/2,
force_update_presence/1,
connected_users/0,
connected_users_number/0,
@ -397,17 +394,6 @@ get_vh_session_number(Server) ->
Mod = get_sm_backend(LServer),
length(online(get_sessions(Mod, LServer))).
-spec register_iq_handler(binary(), binary(), atom(), atom()) -> ok.
register_iq_handler(Host, XMLNS, Module, Fun) ->
?GEN_SERVER:cast(?MODULE,
{register_iq_handler, Host, XMLNS, Module, Fun}).
-spec unregister_iq_handler(binary(), binary()) -> ok.
unregister_iq_handler(Host, XMLNS) ->
?GEN_SERVER:cast(?MODULE, {unregister_iq_handler, Host, XMLNS}).
%% Why the hell do we have so many similar kicks?
c2s_handle_info(#{lang := Lang} = State, replaced) ->
State1 = State#{replaced => true},
@ -437,7 +423,7 @@ init([]) ->
init_cache(),
lists:foreach(fun(Mod) -> Mod:init() end, get_sm_backends()),
clean_cache(),
ets:new(sm_iqtable, [named_table, public, {read_concurrency, true}]),
gen_iq_handler:start(?MODULE),
ejabberd_hooks:add(host_up, ?MODULE, host_up, 50),
ejabberd_hooks:add(host_down, ?MODULE, host_down, 60),
ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 50),
@ -448,15 +434,6 @@ init([]) ->
handle_call(_Request, _From, State) ->
Reply = ok, {reply, Reply, State}.
handle_cast({register_iq_handler, Host, XMLNS, Module, Function},
State) ->
ets:insert(sm_iqtable,
{{Host, XMLNS}, Module, Function}),
{noreply, State};
handle_cast({unregister_iq_handler, Host, XMLNS},
State) ->
ets:delete(sm_iqtable, {Host, XMLNS}),
{noreply, State};
handle_cast(_Msg, State) -> {noreply, State}.
handle_info({route, Packet}, State) ->
@ -664,7 +641,7 @@ do_route(#message{to = #jid{lresource = <<"">>}, type = T} = Packet) ->
end;
do_route(#iq{to = #jid{lresource = <<"">>}} = Packet) ->
?DEBUG("processing IQ to bare JID:~n~s", [xmpp:pp(Packet)]),
process_iq(Packet);
gen_iq_handler:handle(?MODULE, Packet);
do_route(Packet) ->
?DEBUG("processing packet to full JID:~n~s", [xmpp:pp(Packet)]),
To = xmpp:get_to(Packet),
@ -849,31 +826,6 @@ get_max_user_sessions(LUser, Host) ->
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec process_iq(iq()) -> any().
process_iq(#iq{to = To, type = T, lang = Lang, sub_els = [El]} = Packet)
when T == get; T == set ->
XMLNS = xmpp:get_ns(El),
Host = To#jid.lserver,
case ets:lookup(sm_iqtable, {Host, XMLNS}) of
[{_, Module, Function}] ->
gen_iq_handler:handle(Host, Module, Function, Packet);
[] ->
Txt = <<"No module is handling this query">>,
Err = xmpp:err_service_unavailable(Txt, Lang),
ejabberd_router:route_error(Packet, Err)
end;
process_iq(#iq{type = T, lang = Lang, sub_els = SubEls} = Packet)
when T == get; T == set ->
Txt = case SubEls of
[] -> <<"No child elements found">>;
_ -> <<"Too many child elements">>
end,
Err = xmpp:err_bad_request(Txt, Lang),
ejabberd_router:route_error(Packet, Err);
process_iq(#iq{}) ->
ok.
-spec force_update_presence({binary(), binary()}) -> ok.
force_update_presence({LUser, LServer}) ->

View File

@ -30,9 +30,9 @@
-behaviour(ejabberd_config).
%% API
-export([add_iq_handler/5, remove_iq_handler/3, handle/4,
process_iq/4, check_type/1, transform_module_options/1,
opt_type/1]).
-export([add_iq_handler/5, remove_iq_handler/3, handle/1, handle/2,
check_type/1, transform_module_options/1,
opt_type/1, start/1, get_features/2]).
%% Deprecated functions
-export([add_iq_handler/6, handle/5, iqdisc/1]).
-deprecated([{add_iq_handler, 6}, {handle, 5}, {iqdisc, 1}]).
@ -46,17 +46,65 @@
%%====================================================================
%% API
%%====================================================================
-spec add_iq_handler(module(), binary(), binary(), module(), atom()) -> ok.
-spec start(component()) -> ok.
start(Component) ->
catch ets:new(Component, [named_table, public, ordered_set,
{read_concurrency, true},
{heir, erlang:group_leader(), none}]),
ok.
-spec add_iq_handler(component(), binary(), binary(), module(), atom()) -> ok.
add_iq_handler(Component, Host, NS, Module, Function) ->
Component:register_iq_handler(Host, NS, Module, Function).
ets:insert(Component, {{Host, NS}, Module, Function}),
ok.
-spec remove_iq_handler(component(), binary(), binary()) -> ok.
remove_iq_handler(Component, Host, NS) ->
Component:unregister_iq_handler(Host, NS).
ets:delete(Component, {Host, NS}),
ok.
-spec handle(binary(), atom(), atom(), iq()) -> any().
handle(Host, Module, Function, IQ) ->
process_iq(Host, Module, Function, IQ).
-spec handle(iq()) -> ok.
handle(#iq{to = To} = IQ) ->
Component = case To#jid.luser of
<<"">> -> ejabberd_local;
_ -> ejabberd_sm
end,
handle(Component, IQ).
-spec handle(component(), iq()) -> ok.
handle(Component,
#iq{to = To, type = T, lang = Lang, sub_els = [El]} = Packet)
when T == get; T == set ->
XMLNS = xmpp:get_ns(El),
Host = To#jid.lserver,
case ets:lookup(Component, {Host, XMLNS}) of
[{_, Module, Function}] ->
process_iq(Host, Module, Function, Packet);
[] ->
Txt = <<"No module is handling this query">>,
Err = xmpp:err_service_unavailable(Txt, Lang),
ejabberd_router:route_error(Packet, Err)
end;
handle(_, #iq{type = T, lang = Lang, sub_els = SubEls} = Packet)
when T == get; T == set ->
Txt = case SubEls of
[] -> <<"No child elements found">>;
_ -> <<"Too many child elements">>
end,
Err = xmpp:err_bad_request(Txt, Lang),
ejabberd_router:route_error(Packet, Err);
handle(_, #iq{type = T}) when T == result; T == error ->
ok.
-spec get_features(component(), binary()) -> [binary()].
get_features(Component, Host) ->
get_features(Component, ets:next(Component, {Host, <<"">>}), Host, []).
get_features(Component, {Host, XMLNS}, Host, XMLNSs) ->
get_features(Component,
ets:next(Component, {Host, XMLNS}), Host, [XMLNS|XMLNSs]);
get_features(_, _, _, XMLNSs) ->
XMLNSs.
-spec process_iq(binary(), atom(), atom(), iq()) -> any().
process_iq(_Host, Module, Function, IQ) ->
@ -139,4 +187,4 @@ add_iq_handler(Component, Host, NS, Module, Function, _Type) ->
-spec handle(binary(), atom(), atom(), any(), iq()) -> any().
handle(Host, Module, Function, _Opts, IQ) ->
handle(Host, Module, Function, IQ).
process_iq(Host, Module, Function, IQ).

View File

@ -399,7 +399,7 @@ do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
do_route1(_Host, _ServerHost, _Access, _HistorySize, _RoomShaper,
_From, #jid{luser = <<"">>, lresource = <<"">>} = _To,
#iq{} = IQ, _DefRoomOpts, _QueueType) ->
ejabberd_local:process_iq(IQ);
ejabberd_router:process_iq(IQ);
do_route1(Host, ServerHost, Access, _HistorySize, _RoomShaper,
From, #jid{luser = <<"">>, lresource = <<"">>} = _To,
#message{lang = Lang, body = Body, type = Type} = Packet, _, _) ->