Rewrite multicast code to use XML generator
This commit is contained in:
parent
abb4446b51
commit
bc33a3873d
|
@ -43,9 +43,10 @@
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("jlib.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
-record(route_multicast, {domain, pid}).
|
-record(route_multicast, {domain = <<"">> :: binary(),
|
||||||
|
pid = self() :: pid()}).
|
||||||
-record(state, {}).
|
-record(state, {}).
|
||||||
|
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
|
@ -58,7 +59,7 @@
|
||||||
start_link() ->
|
start_link() ->
|
||||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||||
|
|
||||||
|
-spec route_multicast(jid(), binary(), [jid()], stanza()) -> ok.
|
||||||
route_multicast(From, Domain, Destinations, Packet) ->
|
route_multicast(From, Domain, Destinations, Packet) ->
|
||||||
case catch do_route(From, Domain, Destinations, Packet) of
|
case catch do_route(From, Domain, Destinations, Packet) of
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
|
@ -68,6 +69,7 @@ route_multicast(From, Domain, Destinations, Packet) ->
|
||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec register_route(binary()) -> any().
|
||||||
register_route(Domain) ->
|
register_route(Domain) ->
|
||||||
case jid:nameprep(Domain) of
|
case jid:nameprep(Domain) of
|
||||||
error ->
|
error ->
|
||||||
|
@ -81,6 +83,7 @@ register_route(Domain) ->
|
||||||
mnesia:transaction(F)
|
mnesia:transaction(F)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec unregister_route(binary()) -> any().
|
||||||
unregister_route(Domain) ->
|
unregister_route(Domain) ->
|
||||||
case jid:nameprep(Domain) of
|
case jid:nameprep(Domain) of
|
||||||
error ->
|
error ->
|
||||||
|
@ -206,6 +209,7 @@ code_change(_OldVsn, State, _Extra) ->
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% From = #jid
|
%% From = #jid
|
||||||
%% Destinations = [#jid]
|
%% Destinations = [#jid]
|
||||||
|
-spec do_route(jid(), binary(), [jid()], stanza()) -> any().
|
||||||
do_route(From, Domain, Destinations, Packet) ->
|
do_route(From, Domain, Destinations, Packet) ->
|
||||||
|
|
||||||
?DEBUG("route_multicast~n\tfrom ~s~n\tdomain ~s~n\tdestinations ~p~n\tpacket ~p~n",
|
?DEBUG("route_multicast~n\tfrom ~s~n\tdomain ~s~n\tdestinations ~p~n\tpacket ~p~n",
|
||||||
|
@ -226,6 +230,7 @@ do_route(From, Domain, Destinations, Packet) ->
|
||||||
Pid ! {route_trusted, From, Destinations, Packet}
|
Pid ! {route_trusted, From, Destinations, Packet}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec pick_multicast_pid([#route_multicast{}]) -> pid().
|
||||||
pick_multicast_pid(Rs) ->
|
pick_multicast_pid(Rs) ->
|
||||||
List = case [R || R <- Rs, node(R#route_multicast.pid) == node()] of
|
List = case [R || R <- Rs, node(R#route_multicast.pid) == node()] of
|
||||||
[] -> Rs;
|
[] -> Rs;
|
||||||
|
@ -233,5 +238,6 @@ pick_multicast_pid(Rs) ->
|
||||||
end,
|
end,
|
||||||
(hd(List))#route_multicast.pid.
|
(hd(List))#route_multicast.pid.
|
||||||
|
|
||||||
|
-spec do_route_normal(jid(), [jid()], stanza()) -> any().
|
||||||
do_route_normal(From, Destinations, Packet) ->
|
do_route_normal(From, Destinations, Packet) ->
|
||||||
[ejabberd_router:route(From, To, Packet) || To <- Destinations].
|
[ejabberd_router:route(From, To, Packet) || To <- Destinations].
|
||||||
|
|
|
@ -45,16 +45,20 @@
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
|
||||||
-include("jlib.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
-record(state,
|
-record(state,
|
||||||
{lserver, lservice, access, service_limits}).
|
{lserver, lservice, access, service_limits}).
|
||||||
|
-type state() :: #state{}.
|
||||||
|
|
||||||
-record(multicastc, {rserver, response, ts}).
|
-record(multicastc, {rserver, response, ts}).
|
||||||
|
|
||||||
%% ts: timestamp (in seconds) when the cache item was last updated
|
%% ts: timestamp (in seconds) when the cache item was last updated
|
||||||
|
|
||||||
-record(dest, {jid_string, jid_jid, type, full_xml}).
|
-record(dest, {jid_string = none :: binary(),
|
||||||
|
jid_jid :: jid(),
|
||||||
|
type :: atom(),
|
||||||
|
full_xml :: address()}).
|
||||||
|
|
||||||
%% jid_string = string()
|
%% jid_string = string()
|
||||||
%% jid_jid = jid()
|
%% jid_jid = jid()
|
||||||
|
@ -168,10 +172,8 @@ handle_cast(_Msg, State) -> {noreply, State}.
|
||||||
%% Description: Handling all non call/cast messages
|
%% Description: Handling all non call/cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
handle_info({route, From, To,
|
handle_info({route, From, To, #iq{} = Packet}, State) ->
|
||||||
#xmlel{name = <<"iq">>, attrs = Attrs} = Packet},
|
case catch handle_iq(From, To, Packet, State) of
|
||||||
State) ->
|
|
||||||
case catch handle_iq(From, To, #xmlel{attrs = Attrs} = Packet, State) of
|
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
?ERROR_MSG("Error when processing IQ stanza: ~p",
|
?ERROR_MSG("Error when processing IQ stanza: ~p",
|
||||||
[Reason]);
|
[Reason]);
|
||||||
|
@ -179,13 +181,10 @@ handle_info({route, From, To,
|
||||||
end,
|
end,
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
%% XEP33 allows only 'message' and 'presence' stanza type
|
%% XEP33 allows only 'message' and 'presence' stanza type
|
||||||
handle_info({route, From, To,
|
handle_info({route, From, To, Packet},
|
||||||
#xmlel{name = Stanza_type} = Packet},
|
|
||||||
#state{lservice = LServiceS, lserver = LServerS,
|
#state{lservice = LServiceS, lserver = LServerS,
|
||||||
access = Access, service_limits = SLimits} =
|
access = Access, service_limits = SLimits} =
|
||||||
State)
|
State) when ?is_stanza(Packet) ->
|
||||||
when (Stanza_type == <<"message">>) or
|
|
||||||
(Stanza_type == <<"presence">>) ->
|
|
||||||
route_untrusted(LServiceS, LServerS, Access, SLimits,
|
route_untrusted(LServiceS, LServerS, Access, SLimits,
|
||||||
From, To, Packet),
|
From, To, Packet),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
|
@ -220,91 +219,59 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
|
||||||
%%% IQ Request Processing
|
%%% IQ Request Processing
|
||||||
%%%------------------------
|
%%%------------------------
|
||||||
|
|
||||||
handle_iq(From, To, #xmlel{attrs = Attrs} = Packet, State) ->
|
handle_iq(From, To, Packet, State) ->
|
||||||
IQ = jlib:iq_query_info(Packet),
|
try
|
||||||
case catch process_iq(From, IQ, State) of
|
IQ = xmpp:decode_els(Packet),
|
||||||
Result when is_record(Result, iq) ->
|
case process_iq(From, IQ, State) of
|
||||||
ejabberd_router:route(To, From, jlib:iq_to_xml(Result));
|
{result, SubEl} ->
|
||||||
{'EXIT', Reason} ->
|
ejabberd_router:route(To, From, xmpp:make_iq_result(Packet, SubEl));
|
||||||
?ERROR_MSG("Error when processing IQ stanza: ~p",
|
{error, Error} ->
|
||||||
[Reason]),
|
ejabberd_router:route_error(To, From, Packet, Error);
|
||||||
Err = jlib:make_error_reply(Packet,
|
reply ->
|
||||||
?ERR_INTERNAL_SERVER_ERROR),
|
LServiceS = jid:to_string(To),
|
||||||
ejabberd_router:route(To, From, Err);
|
case Packet#iq.type of
|
||||||
reply ->
|
result ->
|
||||||
LServiceS = jts(To),
|
process_iqreply_result(From, LServiceS, IQ);
|
||||||
case fxml:get_attr_s(<<"type">>, Attrs) of
|
error ->
|
||||||
<<"result">> ->
|
process_iqreply_error(From, LServiceS, IQ)
|
||||||
process_iqreply_result(From, LServiceS, Packet, State);
|
end
|
||||||
<<"error">> ->
|
end
|
||||||
process_iqreply_error(From, LServiceS, Packet)
|
catch _:{xmpp_codec, Why} ->
|
||||||
end;
|
Lang = xmpp:get_lang(Packet),
|
||||||
ok -> ok
|
Err = xmpp:err_bad_request(xmpp:format_error(Why), Lang),
|
||||||
|
ejabberd_router:route_error(To, From, Packet, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
process_iq(From,
|
-spec process_iq(jid(), iq(), state()) -> {result, xmpp_element()} |
|
||||||
#iq{type = get, xmlns = ?NS_DISCO_INFO, lang = Lang} =
|
{error, error()} | reply.
|
||||||
IQ,
|
process_iq(From, #iq{type = get, lang = Lang,
|
||||||
State) ->
|
sub_els = [#disco_info{}]}, State) ->
|
||||||
IQ#iq{type = result,
|
{result, iq_disco_info(From, Lang, State)};
|
||||||
sub_el =
|
process_iq(_, #iq{type = get, sub_els = [#disco_items{}]}, _) ->
|
||||||
[#xmlel{name = <<"query">>,
|
{result, #disco_items{}};
|
||||||
attrs = [{<<"xmlns">>, ?NS_DISCO_INFO}],
|
process_iq(_, #iq{type = get, lang = Lang, sub_els = [#vcard_temp{}]}, _) ->
|
||||||
children = iq_disco_info(From, Lang, State)}]};
|
{result, iq_vcard(Lang)};
|
||||||
%% disco#items request
|
process_iq(_, #iq{type = T}, _) when T == set; T == get ->
|
||||||
process_iq(_,
|
{error, xmpp:err_service_unavailable()};
|
||||||
#iq{type = get, xmlns = ?NS_DISCO_ITEMS} = IQ, _) ->
|
process_iq(_, _, _) ->
|
||||||
IQ#iq{type = result,
|
reply.
|
||||||
sub_el =
|
|
||||||
[#xmlel{name = <<"query">>,
|
|
||||||
attrs = [{<<"xmlns">>, ?NS_DISCO_ITEMS}],
|
|
||||||
children = []}]};
|
|
||||||
%% vCard request
|
|
||||||
process_iq(_,
|
|
||||||
#iq{type = get, xmlns = ?NS_VCARD, lang = Lang} = IQ,
|
|
||||||
_) ->
|
|
||||||
IQ#iq{type = result,
|
|
||||||
sub_el =
|
|
||||||
[#xmlel{name = <<"vCard">>,
|
|
||||||
attrs = [{<<"xmlns">>, ?NS_VCARD}],
|
|
||||||
children = iq_vcard(Lang)}]};
|
|
||||||
%% Unknown "set" or "get" request
|
|
||||||
process_iq(_, #iq{type = Type, sub_el = SubEl} = IQ, _)
|
|
||||||
when Type == get; Type == set ->
|
|
||||||
IQ#iq{type = error,
|
|
||||||
sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]};
|
|
||||||
%% IQ "result" or "error".
|
|
||||||
process_iq(_, reply, _) -> reply;
|
|
||||||
%% IQ "result" or "error".
|
|
||||||
process_iq(_, _, _) -> ok.
|
|
||||||
|
|
||||||
-define(FEATURE(Feat),
|
-define(FEATURE(Feat), Feat).
|
||||||
#xmlel{name = <<"feature">>,
|
|
||||||
attrs = [{<<"var">>, Feat}], children = []}).
|
|
||||||
|
|
||||||
iq_disco_info(From, Lang, State) ->
|
iq_disco_info(From, Lang, State) ->
|
||||||
[#xmlel{name = <<"identity">>,
|
#disco_info{
|
||||||
attrs =
|
identities = [#identity{category = <<"service">>,
|
||||||
[{<<"category">>, <<"service">>},
|
type = <<"multicast">>,
|
||||||
{<<"type">>, <<"multicast">>},
|
name = translate:translate(Lang, <<"Multicast">>)}],
|
||||||
{<<"name">>,
|
features = [?NS_DISCO_INFO, ?NS_DISCO_ITEMS, ?NS_VCARD, ?NS_ADDRESS],
|
||||||
translate:translate(Lang, <<"Multicast">>)}],
|
xdata = iq_disco_info_extras(From, State)}.
|
||||||
children = []},
|
|
||||||
?FEATURE((?NS_DISCO_INFO)), ?FEATURE((?NS_DISCO_ITEMS)),
|
|
||||||
?FEATURE((?NS_VCARD)), ?FEATURE((?NS_ADDRESS))]
|
|
||||||
++ iq_disco_info_extras(From, State).
|
|
||||||
|
|
||||||
iq_vcard(Lang) ->
|
iq_vcard(Lang) ->
|
||||||
[#xmlel{name = <<"FN">>, attrs = [],
|
Desc = translate:translate(Lang, <<"ejabberd Multicast service">>),
|
||||||
children = [{xmlcdata, <<"ejabberd/mod_multicast">>}]},
|
Copyright = <<"Copyright (c) 2002-2016 ProcessOne">>,
|
||||||
#xmlel{name = <<"URL">>, attrs = [],
|
#vcard_temp{fn = <<"ejabberd/mod_multicast">>,
|
||||||
children = [{xmlcdata, ?EJABBERD_URI}]},
|
url = ?EJABBERD_URI,
|
||||||
#xmlel{name = <<"DESC">>, attrs = [],
|
desc = <<Desc/binary, $\n, Copyright/binary>>}.
|
||||||
children =
|
|
||||||
[{xmlcdata,
|
|
||||||
<<(translate:translate(Lang,
|
|
||||||
<<"ejabberd Multicast service">>))/binary,
|
|
||||||
"\nCopyright (c) 2002-2016 ProcessOne">>}]}].
|
|
||||||
|
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
%%% Route
|
%%% Route
|
||||||
|
@ -313,19 +280,14 @@ iq_vcard(Lang) ->
|
||||||
route_trusted(LServiceS, LServerS, FromJID,
|
route_trusted(LServiceS, LServerS, FromJID,
|
||||||
Destinations, Packet) ->
|
Destinations, Packet) ->
|
||||||
Packet_stripped = Packet,
|
Packet_stripped = Packet,
|
||||||
AAttrs = [{<<"xmlns">>, ?NS_ADDRESS}],
|
AAttrs = [],
|
||||||
Delivereds = [],
|
Delivereds = [],
|
||||||
Dests2 = lists:map(fun (D) ->
|
Dests2 = lists:map(
|
||||||
DS = jts(D),
|
fun(D) ->
|
||||||
XML = #xmlel{name = <<"address">>,
|
#dest{jid_string = jid:to_string(D),
|
||||||
attrs =
|
jid_jid = D, type = bcc,
|
||||||
[{<<"type">>, <<"bcc">>},
|
full_xml = #address{type = bcc, jid = D}}
|
||||||
{<<"jid">>, DS}],
|
end, Destinations),
|
||||||
children = []},
|
|
||||||
#dest{jid_string = DS, jid_jid = D,
|
|
||||||
type = <<"bcc">>, full_xml = XML}
|
|
||||||
end,
|
|
||||||
Destinations),
|
|
||||||
Groups = group_dests(Dests2),
|
Groups = group_dests(Dests2),
|
||||||
route_common(LServerS, LServiceS, FromJID, Groups,
|
route_common(LServerS, LServiceS, FromJID, Groups,
|
||||||
Delivereds, Packet_stripped, AAttrs).
|
Delivereds, Packet_stripped, AAttrs).
|
||||||
|
@ -363,20 +325,19 @@ route_untrusted(LServiceS, LServerS, Access, SLimits,
|
||||||
route_untrusted2(LServiceS, LServerS, Access, SLimits,
|
route_untrusted2(LServiceS, LServerS, Access, SLimits,
|
||||||
FromJID, Packet) ->
|
FromJID, Packet) ->
|
||||||
ok = check_access(LServerS, Access, FromJID),
|
ok = check_access(LServerS, Access, FromJID),
|
||||||
{ok, Packet_stripped, AAttrs, Addresses} =
|
{ok, Packet_stripped, Addresses} = strip_addresses_element(Packet),
|
||||||
strip_addresses_element(Packet),
|
{To_deliver, Delivereds} = split_addresses_todeliver(Addresses),
|
||||||
{To_deliver, Delivereds} =
|
|
||||||
split_addresses_todeliver(Addresses),
|
|
||||||
Dests = convert_dest_record(To_deliver),
|
Dests = convert_dest_record(To_deliver),
|
||||||
{Dests2, Not_jids} = split_dests_jid(Dests),
|
{Dests2, Not_jids} = split_dests_jid(Dests),
|
||||||
report_not_jid(FromJID, Packet, Not_jids),
|
report_not_jid(FromJID, Packet, Not_jids),
|
||||||
ok = check_limit_dests(SLimits, FromJID, Packet,
|
ok = check_limit_dests(SLimits, FromJID, Packet, Dests2),
|
||||||
Dests2),
|
|
||||||
Groups = group_dests(Dests2),
|
Groups = group_dests(Dests2),
|
||||||
ok = check_relay(FromJID#jid.server, LServerS, Groups),
|
ok = check_relay(FromJID#jid.server, LServerS, Groups),
|
||||||
route_common(LServerS, LServiceS, FromJID, Groups,
|
route_common(LServerS, LServiceS, FromJID, Groups,
|
||||||
Delivereds, Packet_stripped, AAttrs).
|
Delivereds, Packet_stripped, []).
|
||||||
|
|
||||||
|
-spec route_common(binary(), binary(), jid(), [#group{}],
|
||||||
|
[address()], stanza(), list()) -> any().
|
||||||
route_common(LServerS, LServiceS, FromJID, Groups,
|
route_common(LServerS, LServiceS, FromJID, Groups,
|
||||||
Delivereds, Packet_stripped, AAttrs) ->
|
Delivereds, Packet_stripped, AAttrs) ->
|
||||||
Groups2 = look_cached_servers(LServerS, Groups),
|
Groups2 = look_cached_servers(LServerS, Groups),
|
||||||
|
@ -435,52 +396,39 @@ check_access(LServerS, Access, From) ->
|
||||||
%%% Strip 'addresses' XML element
|
%%% Strip 'addresses' XML element
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
|
-spec strip_addresses_element(stanza()) -> {ok, stanza(), [address()]}.
|
||||||
strip_addresses_element(Packet) ->
|
strip_addresses_element(Packet) ->
|
||||||
case fxml:get_subtag(Packet, <<"addresses">>) of
|
case xmpp:get_subtag(Packet, #addresses{}) of
|
||||||
#xmlel{name = <<"addresses">>, attrs = AAttrs,
|
#addresses{list = Addrs} ->
|
||||||
children = Addresses} ->
|
PacketStripped = xmpp:remove_subtag(Packet, #addresses{}),
|
||||||
case fxml:get_attr_s(<<"xmlns">>, AAttrs) of
|
{ok, PacketStripped, Addrs};
|
||||||
?NS_ADDRESS ->
|
undefined ->
|
||||||
#xmlel{name = Name, attrs = Attrs, children = Els} =
|
throw(eadsele)
|
||||||
Packet,
|
|
||||||
Els_stripped = lists:keydelete(<<"addresses">>, 2, Els),
|
|
||||||
Packet_stripped = #xmlel{name = Name, attrs = Attrs,
|
|
||||||
children = Els_stripped},
|
|
||||||
{ok, Packet_stripped, AAttrs, fxml:remove_cdata(Addresses)};
|
|
||||||
_ -> throw(ewxmlns)
|
|
||||||
end;
|
|
||||||
_ -> throw(eadsele)
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
%%% Split Addresses
|
%%% Split Addresses
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
|
-spec split_addresses_todeliver([address()]) -> {[address()], [address()]}.
|
||||||
split_addresses_todeliver(Addresses) ->
|
split_addresses_todeliver(Addresses) ->
|
||||||
lists:partition(fun (XML) ->
|
lists:partition(
|
||||||
case XML of
|
fun(#address{delivered = true}) ->
|
||||||
#xmlel{name = <<"address">>, attrs = Attrs} ->
|
false;
|
||||||
case fxml:get_attr_s(<<"delivered">>, Attrs) of
|
(#address{type = Type}) ->
|
||||||
<<"true">> -> false;
|
case Type of
|
||||||
_ ->
|
to -> true;
|
||||||
Type = fxml:get_attr_s(<<"type">>,
|
cc -> true;
|
||||||
Attrs),
|
bcc -> true;
|
||||||
case Type of
|
_ -> false
|
||||||
<<"to">> -> true;
|
end
|
||||||
<<"cc">> -> true;
|
end, Addresses).
|
||||||
<<"bcc">> -> true;
|
|
||||||
_ -> false
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
_ -> false
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
Addresses).
|
|
||||||
|
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
%%% Check does not exceed limit of destinations
|
%%% Check does not exceed limit of destinations
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
|
-spec check_limit_dests(_, jid(), stanza(), [address()]) -> ok.
|
||||||
check_limit_dests(SLimits, FromJID, Packet,
|
check_limit_dests(SLimits, FromJID, Packet,
|
||||||
Addresses) ->
|
Addresses) ->
|
||||||
SenderT = sender_type(FromJID),
|
SenderT = sender_type(FromJID),
|
||||||
|
@ -497,24 +445,22 @@ check_limit_dests(SLimits, FromJID, Packet,
|
||||||
%%% Convert Destination XML to record
|
%%% Convert Destination XML to record
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
convert_dest_record(XMLs) ->
|
-spec convert_dest_record([address()]) -> [#dest{}].
|
||||||
lists:map(fun (XML) ->
|
convert_dest_record(Addrs) ->
|
||||||
case fxml:get_tag_attr_s(<<"jid">>, XML) of
|
lists:map(
|
||||||
<<"">> -> #dest{jid_string = none, full_xml = XML};
|
fun(#address{jid = undefined} = Addr) ->
|
||||||
JIDS ->
|
#dest{jid_string = none, full_xml = Addr};
|
||||||
Type = fxml:get_tag_attr_s(<<"type">>, XML),
|
(#address{jid = JID, type = Type} = Addr) ->
|
||||||
JIDJ = stj(JIDS),
|
#dest{jid_string = jid:to_string(JID), jid_jid = JID,
|
||||||
#dest{jid_string = JIDS, jid_jid = JIDJ,
|
type = Type, full_xml = Addr}
|
||||||
type = Type, full_xml = XML}
|
end, Addrs).
|
||||||
end
|
|
||||||
end,
|
|
||||||
XMLs).
|
|
||||||
|
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
%%% Split destinations by existence of JID
|
%%% Split destinations by existence of JID
|
||||||
%%% and send error messages for other dests
|
%%% and send error messages for other dests
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
|
-spec split_dests_jid([#dest{}]) -> {[#dest{}], [#dest{}]}.
|
||||||
split_dests_jid(Dests) ->
|
split_dests_jid(Dests) ->
|
||||||
lists:partition(fun (Dest) ->
|
lists:partition(fun (Dest) ->
|
||||||
case Dest#dest.jid_string of
|
case Dest#dest.jid_string of
|
||||||
|
@ -524,8 +470,9 @@ split_dests_jid(Dests) ->
|
||||||
end,
|
end,
|
||||||
Dests).
|
Dests).
|
||||||
|
|
||||||
|
-spec report_not_jid(jid(), stanza(), #dest{}) -> any().
|
||||||
report_not_jid(From, Packet, Dests) ->
|
report_not_jid(From, Packet, Dests) ->
|
||||||
Dests2 = [fxml:element_to_binary(Dest#dest.full_xml)
|
Dests2 = [fxml:element_to_binary(xmpp:encode(Dest#dest.full_xml))
|
||||||
|| Dest <- Dests],
|
|| Dest <- Dests],
|
||||||
[route_error(From, From, Packet, jid_malformed,
|
[route_error(From, From, Packet, jid_malformed,
|
||||||
<<"This service can not process the address: ",
|
<<"This service can not process the address: ",
|
||||||
|
@ -536,6 +483,7 @@ report_not_jid(From, Packet, Dests) ->
|
||||||
%%% Group destinations by their servers
|
%%% Group destinations by their servers
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
|
-spec group_dests([#dest{}]) -> [#group{}].
|
||||||
group_dests(Dests) ->
|
group_dests(Dests) ->
|
||||||
D = lists:foldl(fun (Dest, Dict) ->
|
D = lists:foldl(fun (Dest, Dict) ->
|
||||||
ServerS = (Dest#dest.jid_jid)#jid.server,
|
ServerS = (Dest#dest.jid_jid)#jid.server,
|
||||||
|
@ -575,18 +523,17 @@ build_other_xml(Dests) ->
|
||||||
lists:foldl(fun (Dest, R) ->
|
lists:foldl(fun (Dest, R) ->
|
||||||
XML = Dest#dest.full_xml,
|
XML = Dest#dest.full_xml,
|
||||||
case Dest#dest.type of
|
case Dest#dest.type of
|
||||||
<<"to">> -> [add_delivered(XML) | R];
|
to -> [add_delivered(XML) | R];
|
||||||
<<"cc">> -> [add_delivered(XML) | R];
|
cc -> [add_delivered(XML) | R];
|
||||||
<<"bcc">> -> R;
|
bcc -> R;
|
||||||
_ -> [XML | R]
|
_ -> [XML | R]
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
[], Dests).
|
[], Dests).
|
||||||
|
|
||||||
add_delivered(#xmlel{name = Name, attrs = Attrs,
|
-spec add_delivered(address()) -> address().
|
||||||
children = Els}) ->
|
add_delivered(Addr) ->
|
||||||
Attrs2 = [{<<"delivered">>, <<"true">>} | Attrs],
|
Addr#address{delivered = true}.
|
||||||
#xmlel{name = Name, attrs = Attrs2, children = Els}.
|
|
||||||
|
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
%%% Add preliminary packets
|
%%% Add preliminary packets
|
||||||
|
@ -636,7 +583,7 @@ decide_action_group(Group) ->
|
||||||
|
|
||||||
route_packet(From, ToDest, Packet, AAttrs, Others, Addresses) ->
|
route_packet(From, ToDest, Packet, AAttrs, Others, Addresses) ->
|
||||||
Dests = case ToDest#dest.type of
|
Dests = case ToDest#dest.type of
|
||||||
<<"bcc">> -> [];
|
bcc -> [];
|
||||||
_ -> [ToDest]
|
_ -> [ToDest]
|
||||||
end,
|
end,
|
||||||
route_packet2(From, ToDest#dest.jid_string, Dests,
|
route_packet2(From, ToDest#dest.jid_string, Dests,
|
||||||
|
@ -652,20 +599,20 @@ route_packet_multicast(From, ToS, Packet, AAttrs, Dests,
|
||||||
Addresses)
|
Addresses)
|
||||||
|| DFragment <- Fragmented_dests].
|
|| DFragment <- Fragmented_dests].
|
||||||
|
|
||||||
route_packet2(From, ToS, Dests, Packet, AAttrs,
|
-spec route_packet2(jid(), binary(), [#dest{}], stanza(), list(), [address()]) -> ok.
|
||||||
|
route_packet2(From, ToS, Dests, Packet, _AAttrs,
|
||||||
Addresses) ->
|
Addresses) ->
|
||||||
#xmlel{name = T, attrs = A, children = C} = Packet,
|
Els = case append_dests(Dests, Addresses) of
|
||||||
C2 = case append_dests(Dests, Addresses) of
|
[] ->
|
||||||
[] -> C;
|
xmpp:get_els(Packet);
|
||||||
ACs ->
|
ACs ->
|
||||||
[#xmlel{name = <<"addresses">>, attrs = AAttrs,
|
[#addresses{list = ACs}|xmpp:get_els(Packet)]
|
||||||
children = ACs}
|
end,
|
||||||
| C]
|
Packet2 = xmpp:set_els(Packet, Els),
|
||||||
end,
|
|
||||||
Packet2 = #xmlel{name = T, attrs = A, children = C2},
|
|
||||||
ToJID = stj(ToS),
|
ToJID = stj(ToS),
|
||||||
ejabberd_router:route(From, ToJID, Packet2).
|
ejabberd_router:route(From, ToJID, Packet2).
|
||||||
|
|
||||||
|
-spec append_dests([#dest{}], {[address()], [address()]} | [address()]) -> [address()].
|
||||||
append_dests(_Dests, {Others, Addresses}) ->
|
append_dests(_Dests, {Others, Addresses}) ->
|
||||||
Addresses++Others;
|
Addresses++Others;
|
||||||
append_dests([], Addresses) -> Addresses;
|
append_dests([], Addresses) -> Addresses;
|
||||||
|
@ -676,12 +623,14 @@ append_dests([Dest | Dests], Addresses) ->
|
||||||
%%% Check relay
|
%%% Check relay
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
|
-spec check_relay(binary(), binary(), [#group{}]) -> ok.
|
||||||
check_relay(RS, LS, Gs) ->
|
check_relay(RS, LS, Gs) ->
|
||||||
case check_relay_required(RS, LS, Gs) of
|
case check_relay_required(RS, LS, Gs) of
|
||||||
false -> ok;
|
false -> ok;
|
||||||
true -> throw(edrelay)
|
true -> throw(edrelay)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec check_relay_required(binary(), binary(), [#group{}]) -> boolean().
|
||||||
check_relay_required(RServer, LServerS, Groups) ->
|
check_relay_required(RServer, LServerS, Groups) ->
|
||||||
case lists:suffix(str:tokens(LServerS, <<".">>),
|
case lists:suffix(str:tokens(LServerS, <<".">>),
|
||||||
str:tokens(RServer, <<".">>)) of
|
str:tokens(RServer, <<".">>)) of
|
||||||
|
@ -689,6 +638,7 @@ check_relay_required(RServer, LServerS, Groups) ->
|
||||||
false -> check_relay_required(LServerS, Groups)
|
false -> check_relay_required(LServerS, Groups)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec check_relay_required(binary(), [#group{}]) -> boolean().
|
||||||
check_relay_required(LServerS, Groups) ->
|
check_relay_required(LServerS, Groups) ->
|
||||||
lists:any(fun (Group) -> Group#group.server /= LServerS
|
lists:any(fun (Group) -> Group#group.server /= LServerS
|
||||||
end,
|
end,
|
||||||
|
@ -701,19 +651,16 @@ check_relay_required(LServerS, Groups) ->
|
||||||
send_query_info(RServerS, LServiceS) ->
|
send_query_info(RServerS, LServiceS) ->
|
||||||
case str:str(RServerS, <<"echo.">>) of
|
case str:str(RServerS, <<"echo.">>) of
|
||||||
1 -> false;
|
1 -> false;
|
||||||
_ -> send_query(RServerS, LServiceS, ?NS_DISCO_INFO)
|
_ -> send_query(RServerS, LServiceS, #disco_info{})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
send_query_items(RServerS, LServiceS) ->
|
send_query_items(RServerS, LServiceS) ->
|
||||||
send_query(RServerS, LServiceS, ?NS_DISCO_ITEMS).
|
send_query(RServerS, LServiceS, #disco_items{}).
|
||||||
|
|
||||||
send_query(RServerS, LServiceS, XMLNS) ->
|
-spec send_query(binary(), binary(), [disco_info()|disco_items()]) -> ok.
|
||||||
Packet = #xmlel{name = <<"iq">>,
|
send_query(RServerS, LServiceS, SubEl) ->
|
||||||
attrs = [{<<"to">>, RServerS}, {<<"type">>, <<"get">>}],
|
Packet = #iq{id = randoms:get_string(),
|
||||||
children =
|
type = get, sub_els = [SubEl]},
|
||||||
[#xmlel{name = <<"query">>,
|
|
||||||
attrs = [{<<"xmlns">>, XMLNS}],
|
|
||||||
children = []}]},
|
|
||||||
ejabberd_router:route(stj(LServiceS), stj(RServerS),
|
ejabberd_router:route(stj(LServiceS), stj(RServerS),
|
||||||
Packet).
|
Packet).
|
||||||
|
|
||||||
|
@ -733,49 +680,40 @@ process_iqreply_error(From, LServiceS, _Packet) ->
|
||||||
%%% Check protocol support: Receive response: Disco
|
%%% Check protocol support: Receive response: Disco
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
process_iqreply_result(From, LServiceS, Packet, State) ->
|
-spec process_iqreply_result(jid(), binary(), iq()) -> any().
|
||||||
#xmlel{name = <<"query">>, attrs = Attrs2,
|
process_iqreply_result(From, LServiceS, #iq{sub_els = [SubEl]}) ->
|
||||||
children = Els2} =
|
case SubEl of
|
||||||
fxml:get_subtag(Packet, <<"query">>),
|
#disco_info{} ->
|
||||||
case fxml:get_attr_s(<<"xmlns">>, Attrs2) of
|
process_discoinfo_result(From, LServiceS, SubEl);
|
||||||
?NS_DISCO_INFO ->
|
#disco_items{} ->
|
||||||
process_discoinfo_result(From, LServiceS, Els2, State);
|
process_discoitems_result(From, LServiceS, SubEl);
|
||||||
?NS_DISCO_ITEMS ->
|
_ ->
|
||||||
process_discoitems_result(From, LServiceS, Els2)
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
%%% Check protocol support: Receive response: Disco Info
|
%%% Check protocol support: Receive response: Disco Info
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
process_discoinfo_result(From, LServiceS, Els,
|
process_discoinfo_result(From, LServiceS, DiscoInfo) ->
|
||||||
_State) ->
|
|
||||||
FromS = jts(From),
|
FromS = jts(From),
|
||||||
case search_waiter(FromS, LServiceS, info) of
|
case search_waiter(FromS, LServiceS, info) of
|
||||||
{found_waiter, Waiter} ->
|
{found_waiter, Waiter} ->
|
||||||
process_discoinfo_result2(From, FromS, LServiceS, Els,
|
process_discoinfo_result2(From, FromS, LServiceS, DiscoInfo,
|
||||||
Waiter);
|
Waiter);
|
||||||
_ -> ok
|
_ -> ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
process_discoinfo_result2(From, FromS, LServiceS, Els,
|
process_discoinfo_result2(From, FromS, LServiceS,
|
||||||
|
#disco_info{features = Feats} = DiscoInfo,
|
||||||
Waiter) ->
|
Waiter) ->
|
||||||
Multicast_support =
|
Multicast_support = lists:member(?NS_ADDRESS, Feats),
|
||||||
lists:any(
|
|
||||||
fun(XML) ->
|
|
||||||
case XML of
|
|
||||||
#xmlel{name = <<"feature">>, attrs = Attrs} ->
|
|
||||||
(?NS_ADDRESS) == fxml:get_attr_s(<<"var">>, Attrs);
|
|
||||||
_ -> false
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
Els),
|
|
||||||
Group = Waiter#waiter.group,
|
Group = Waiter#waiter.group,
|
||||||
RServer = Group#group.server,
|
RServer = Group#group.server,
|
||||||
case Multicast_support of
|
case Multicast_support of
|
||||||
true ->
|
true ->
|
||||||
SenderT = sender_type(From),
|
SenderT = sender_type(From),
|
||||||
RLimits = get_limits_xml(Els, SenderT),
|
RLimits = get_limits_xml(DiscoInfo, SenderT),
|
||||||
add_response(RServer, {multicast_supported, FromS, RLimits}),
|
add_response(RServer, {multicast_supported, FromS, RLimits}),
|
||||||
FromM = Waiter#waiter.sender,
|
FromM = Waiter#waiter.sender,
|
||||||
DestsM = Group#group.dests,
|
DestsM = Group#group.dests,
|
||||||
|
@ -799,90 +737,58 @@ process_discoinfo_result2(From, FromS, LServiceS, Els,
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_limits_xml(Els, SenderT) ->
|
get_limits_xml(DiscoInfo, SenderT) ->
|
||||||
LimitOpts = get_limits_els(Els),
|
LimitOpts = get_limits_els(DiscoInfo),
|
||||||
build_remote_limit_record(LimitOpts, SenderT).
|
build_remote_limit_record(LimitOpts, SenderT).
|
||||||
|
|
||||||
get_limits_els(Els) ->
|
-spec get_limits_els(disco_info()) -> [{atom(), integer()}].
|
||||||
lists:foldl(fun (XML, R) ->
|
get_limits_els(DiscoInfo) ->
|
||||||
case XML of
|
lists:flatmap(
|
||||||
#xmlel{name = <<"x">>, attrs = Attrs,
|
fun(#xdata{type = result} = X) ->
|
||||||
children = SubEls} ->
|
get_limits_fields(X);
|
||||||
case ((?NS_XDATA) ==
|
(_) ->
|
||||||
fxml:get_attr_s(<<"xmlns">>, Attrs))
|
[]
|
||||||
and
|
end, DiscoInfo#disco_info.xdata).
|
||||||
(<<"result">> ==
|
|
||||||
fxml:get_attr_s(<<"type">>, Attrs))
|
|
||||||
of
|
|
||||||
true -> get_limits_fields(SubEls) ++ R;
|
|
||||||
false -> R
|
|
||||||
end;
|
|
||||||
_ -> R
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
[], Els).
|
|
||||||
|
|
||||||
get_limits_fields(Fields) ->
|
-spec get_limits_fields(xdata()) -> [{atom(), integer()}].
|
||||||
{Head, Tail} = lists:partition(fun (Field) ->
|
get_limits_fields(X) ->
|
||||||
case Field of
|
{Head, Tail} = lists:partition(
|
||||||
#xmlel{name = <<"field">>,
|
fun(#xdata_field{var = Var, type = Type}) ->
|
||||||
attrs = Attrs} ->
|
Var == <<"FORM_TYPE">> andalso Type == hidden
|
||||||
(<<"FORM_TYPE">> ==
|
end, X#xdata.fields),
|
||||||
fxml:get_attr_s(<<"var">>,
|
|
||||||
Attrs))
|
|
||||||
and
|
|
||||||
(<<"hidden">> ==
|
|
||||||
fxml:get_attr_s(<<"type">>,
|
|
||||||
Attrs));
|
|
||||||
_ -> false
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
Fields),
|
|
||||||
case Head of
|
case Head of
|
||||||
[] -> [];
|
[] -> [];
|
||||||
_ -> get_limits_values(Tail)
|
_ -> get_limits_values(Tail)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_limits_values(Values) ->
|
-spec get_limits_values([xdata_field()]) -> [{atom(), integer()}].
|
||||||
lists:foldl(fun (Value, R) ->
|
get_limits_values(Fields) ->
|
||||||
case Value of
|
lists:flatmap(
|
||||||
#xmlel{name = <<"field">>, attrs = Attrs,
|
fun(#xdata_field{var = Name, values = [Number]}) ->
|
||||||
children = SubEls} ->
|
try
|
||||||
[#xmlel{name = <<"value">>, children = SubElsV}] =
|
[{binary_to_atom(Name, utf8), binary_to_integer(Number)}]
|
||||||
SubEls,
|
catch _:badarg ->
|
||||||
Number = fxml:get_cdata(SubElsV),
|
[]
|
||||||
Name = fxml:get_attr_s(<<"var">>, Attrs),
|
end;
|
||||||
[{jlib:binary_to_atom(Name),
|
(_) ->
|
||||||
jlib:binary_to_integer(Number)}
|
[]
|
||||||
| R];
|
end, Fields).
|
||||||
_ -> R
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
[], Values).
|
|
||||||
|
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
%%% Check protocol support: Receive response: Disco Items
|
%%% Check protocol support: Receive response: Disco Items
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
process_discoitems_result(From, LServiceS, Els) ->
|
process_discoitems_result(From, LServiceS, #disco_items{items = Items}) ->
|
||||||
FromS = jts(From),
|
FromS = jts(From),
|
||||||
case search_waiter(FromS, LServiceS, items) of
|
case search_waiter(FromS, LServiceS, items) of
|
||||||
{found_waiter, Waiter} ->
|
{found_waiter, Waiter} ->
|
||||||
List = lists:foldl(
|
List = lists:flatmap(
|
||||||
fun(XML, Res) ->
|
fun(#disco_item{jid = #jid{luser = <<"">>,
|
||||||
case XML of
|
lresource = <<"">>} = J}) ->
|
||||||
#xmlel{name = <<"item">>, attrs = Attrs} ->
|
[J];
|
||||||
SJID = fxml:get_attr_s(<<"jid">>, Attrs),
|
(_) ->
|
||||||
case jid:from_string(SJID) of
|
[]
|
||||||
#jid{luser = <<"">>,
|
end, Items),
|
||||||
lresource = <<"">>} ->
|
|
||||||
[SJID | Res];
|
|
||||||
_ -> Res
|
|
||||||
end;
|
|
||||||
_ -> Res
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
[], Els),
|
|
||||||
case List of
|
case List of
|
||||||
[] ->
|
[] ->
|
||||||
received_awaiter(FromS, Waiter, LServiceS);
|
received_awaiter(FromS, Waiter, LServiceS);
|
||||||
|
@ -1109,9 +1015,7 @@ get_limit_value(Name, Default, LimitOpts) ->
|
||||||
false -> {default, Default}
|
false -> {default, Default}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
type_of_stanza(#xmlel{name = <<"message">>}) -> message;
|
type_of_stanza(Stanza) -> element(1, Stanza).
|
||||||
type_of_stanza(#xmlel{name = <<"presence">>}) ->
|
|
||||||
presence.
|
|
||||||
|
|
||||||
get_limit_number(message, Limits) ->
|
get_limit_number(message, Limits) ->
|
||||||
Limits#limits.message;
|
Limits#limits.message;
|
||||||
|
@ -1144,17 +1048,10 @@ fragment_dests(Dests, Limit_number) ->
|
||||||
%% Some parts of code are borrowed from mod_muc_room.erl
|
%% Some parts of code are borrowed from mod_muc_room.erl
|
||||||
|
|
||||||
-define(RFIELDT(Type, Var, Val),
|
-define(RFIELDT(Type, Var, Val),
|
||||||
#xmlel{name = <<"field">>,
|
#xdata_field{type = Type, var = Var, values = [Val]}).
|
||||||
attrs = [{<<"var">>, Var}, {<<"type">>, Type}],
|
|
||||||
children =
|
|
||||||
[#xmlel{name = <<"value">>, attrs = [],
|
|
||||||
children = [{xmlcdata, Val}]}]}).
|
|
||||||
|
|
||||||
-define(RFIELDV(Var, Val),
|
-define(RFIELDV(Var, Val),
|
||||||
#xmlel{name = <<"field">>, attrs = [{<<"var">>, Var}],
|
#xdata_field{var = Var, values = [Val]}).
|
||||||
children =
|
|
||||||
[#xmlel{name = <<"value">>, attrs = [],
|
|
||||||
children = [{xmlcdata, Val}]}]}).
|
|
||||||
|
|
||||||
iq_disco_info_extras(From, State) ->
|
iq_disco_info_extras(From, State) ->
|
||||||
SenderT = sender_type(From),
|
SenderT = sender_type(From),
|
||||||
|
@ -1162,12 +1059,9 @@ iq_disco_info_extras(From, State) ->
|
||||||
case iq_disco_info_extras2(SenderT, Service_limits) of
|
case iq_disco_info_extras2(SenderT, Service_limits) of
|
||||||
[] -> [];
|
[] -> [];
|
||||||
List_limits_xmpp ->
|
List_limits_xmpp ->
|
||||||
[#xmlel{name = <<"x">>,
|
#xdata{type = result,
|
||||||
attrs =
|
fields = [?RFIELDT(hidden, <<"FORM_TYPE">>, ?NS_ADDRESS)
|
||||||
[{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}],
|
| List_limits_xmpp]}
|
||||||
children =
|
|
||||||
[?RFIELDT(<<"hidden">>, <<"FORM_TYPE">>, (?NS_ADDRESS))]
|
|
||||||
++ List_limits_xmpp}]
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
sender_type(From) ->
|
sender_type(From) ->
|
||||||
|
@ -1198,22 +1092,20 @@ to_binary(A) -> list_to_binary(hd(io_lib:format("~p", [A]))).
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
route_error(From, To, Packet, ErrType, ErrText) ->
|
route_error(From, To, Packet, ErrType, ErrText) ->
|
||||||
#xmlel{attrs = Attrs} = Packet,
|
Lang = xmpp:get_lang(Packet),
|
||||||
Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs),
|
Err = make_reply(ErrType, Lang, ErrText),
|
||||||
Reply = make_reply(ErrType, Lang, ErrText),
|
ejabberd_router:route_error(From, To, Packet, Err).
|
||||||
Err = jlib:make_error_reply(Packet, Reply),
|
|
||||||
ejabberd_router:route(From, To, Err).
|
|
||||||
|
|
||||||
make_reply(bad_request, Lang, ErrText) ->
|
make_reply(bad_request, Lang, ErrText) ->
|
||||||
?ERRT_BAD_REQUEST(Lang, ErrText);
|
xmpp:err_bad_request(ErrText, Lang);
|
||||||
make_reply(jid_malformed, Lang, ErrText) ->
|
make_reply(jid_malformed, Lang, ErrText) ->
|
||||||
?ERRT_JID_MALFORMED(Lang, ErrText);
|
xmpp:err_jid_malformed(ErrText, Lang);
|
||||||
make_reply(not_acceptable, Lang, ErrText) ->
|
make_reply(not_acceptable, Lang, ErrText) ->
|
||||||
?ERRT_NOT_ACCEPTABLE(Lang, ErrText);
|
xmpp:err_not_acceptable(ErrText, Lang);
|
||||||
make_reply(internal_server_error, Lang, ErrText) ->
|
make_reply(internal_server_error, Lang, ErrText) ->
|
||||||
?ERRT_INTERNAL_SERVER_ERROR(Lang, ErrText);
|
xmpp:err_internal_server_error(ErrText, Lang);
|
||||||
make_reply(forbidden, Lang, ErrText) ->
|
make_reply(forbidden, Lang, ErrText) ->
|
||||||
?ERRT_FORBIDDEN(Lang, ErrText).
|
xmpp:err_forbidden(ErrText, Lang).
|
||||||
|
|
||||||
stj(String) -> jid:from_string(String).
|
stj(String) -> jid:from_string(String).
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue