diff options
-rw-r--r-- | rebar.config | 2 | ||||
-rw-r--r-- | src/ejabberd_listener.erl | 114 | ||||
-rw-r--r-- | src/ejabberd_piefxis.erl | 49 | ||||
-rw-r--r-- | src/ejabberd_s2s_in.erl | 9 | ||||
-rw-r--r-- | src/ejabberd_web_admin.erl | 3 | ||||
-rw-r--r-- | src/mod_admin_extra.erl | 11 | ||||
-rw-r--r-- | src/mod_http_upload.erl | 2 | ||||
-rw-r--r-- | src/mod_http_upload_quota.erl | 9 | ||||
-rw-r--r-- | test/ejabberd_SUITE.erl | 1 | ||||
-rw-r--r-- | test/privacy_tests.erl | 3 | ||||
-rw-r--r-- | test/pubsub_tests.erl | 4 | ||||
-rw-r--r-- | test/upload_tests.erl | 4 |
12 files changed, 100 insertions, 111 deletions
diff --git a/rebar.config b/rebar.config index 7c77b6561..df49ede73 100644 --- a/rebar.config +++ b/rebar.config @@ -25,7 +25,7 @@ {fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.23"}}}, {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.12"}}}, {fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.32"}}}, - {xmpp, ".*", {git, "https://github.com/processone/xmpp", "64fbddd"}}, + {xmpp, ".*", {git, "https://github.com/processone/xmpp", "c98ee04"}}, {fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.15"}}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.8"}}}, {p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.3"}}}, diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index f5a65183a..54bc877cc 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -92,15 +92,15 @@ start_dependent(Port, Module, Opts) -> proc_lib:start_link(?MODULE, init, [Port, Module, Opts]). init(PortIP, Module, RawOpts) -> - {Port, IPT, IPS, IPV, Proto, OptsClean} = parse_listener_portip(PortIP, RawOpts), + {Port, IPT, IPV, Proto, OptsClean} = parse_listener_portip(PortIP, RawOpts), {Opts, SockOpts} = prepare_opts(IPT, IPV, OptsClean), if Proto == udp -> - init_udp(PortIP, Module, Opts, SockOpts, Port, IPS); + init_udp(PortIP, Module, Opts, SockOpts, Port); true -> - init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) + init_tcp(PortIP, Module, Opts, SockOpts, Port) end. -init_udp(PortIP, Module, Opts, SockOpts, Port, IPS) -> +init_udp(PortIP, Module, Opts, SockOpts, Port) -> case gen_udp:open(Port, [binary, {active, false}, {reuseaddr, true} | @@ -126,34 +126,38 @@ init_udp(PortIP, Module, Opts, SockOpts, Port, IPS) -> udp_recv(Socket, Module, NewOpts) end end; - {error, Reason} -> - socket_error(Reason, PortIP, Module, SockOpts, Port, IPS) + {error, Reason} = Err -> + report_socket_error(Reason, PortIP, Module), + proc_lib:init_ack(Err) end. -init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) -> - ListenSocket = listen_tcp(PortIP, Module, SockOpts, Port, IPS), - %% Inform my parent that this port was opened successfully - proc_lib:init_ack({ok, self()}), - application:ensure_started(ejabberd), - start_module_sup(Port, Module), - ?INFO_MSG("Start accepting TCP connections at ~s for ~p", - [format_portip(PortIP), Module]), - case erlang:function_exported(Module, tcp_init, 2) of - false -> - accept(ListenSocket, Module, Opts); - true -> - case catch Module:tcp_init(ListenSocket, Opts) of - {'EXIT', _} = Err -> - ?ERROR_MSG("failed to process callback function " - "~p:~s(~p, ~p): ~p", - [Module, tcp_init, ListenSocket, Opts, Err]), +init_tcp(PortIP, Module, Opts, SockOpts, Port) -> + case listen_tcp(PortIP, Module, SockOpts, Port) of + {ok, ListenSocket} -> + proc_lib:init_ack({ok, self()}), + application:ensure_started(ejabberd), + start_module_sup(Port, Module), + ?INFO_MSG("Start accepting TCP connections at ~s for ~p", + [format_portip(PortIP), Module]), + case erlang:function_exported(Module, tcp_init, 2) of + false -> accept(ListenSocket, Module, Opts); - NewOpts -> - accept(ListenSocket, Module, NewOpts) - end + true -> + case catch Module:tcp_init(ListenSocket, Opts) of + {'EXIT', _} = Err -> + ?ERROR_MSG("failed to process callback function " + "~p:~s(~p, ~p): ~p", + [Module, tcp_init, ListenSocket, Opts, Err]), + accept(ListenSocket, Module, Opts); + NewOpts -> + accept(ListenSocket, Module, NewOpts) + end + end; + {error, _} = Err -> + proc_lib:init_ack(Err) end. -listen_tcp(PortIP, Module, SockOpts, Port, IPS) -> +listen_tcp(PortIP, Module, SockOpts, Port) -> Res = gen_tcp:listen(Port, [binary, {packet, 0}, {active, false}, @@ -165,52 +169,34 @@ listen_tcp(PortIP, Module, SockOpts, Port, IPS) -> SockOpts]), case Res of {ok, ListenSocket} -> - ListenSocket; - {error, Reason} -> - socket_error(Reason, PortIP, Module, SockOpts, Port, IPS) + {ok, ListenSocket}; + {error, Reason} = Err -> + report_socket_error(Reason, PortIP, Module), + Err end. -%% @spec (PortIP, Opts) -> {Port, IPT, IPS, IPV, OptsClean} -%% where -%% PortIP = Port | {Port, IPT | IPS} -%% Port = integer() -%% IPT = tuple() -%% IPS = string() -%% IPV = inet | inet6 -%% Opts = [IPV | {ip, IPT} | atom() | tuple()] -%% OptsClean = [atom() | tuple()] -%% @doc Parse any kind of ejabberd listener specification. -%% The parsed options are returned in several formats. -%% OptsClean does not include inet/inet6 or ip options. -%% Opts can include the options inet6 and {ip, Tuple}, -%% but they are only used when no IP address was specified in the PortIP. -%% The IP version (either IPv4 or IPv6) is inferred from the IP address type, -%% so the option inet/inet6 is only used when no IP is specified at all. parse_listener_portip(PortIP, Opts) -> {IPOpt, Opts2} = strip_ip_option(Opts), {IPVOpt, OptsClean} = case proplists:get_bool(inet6, Opts2) of true -> {inet6, proplists:delete(inet6, Opts2)}; false -> {inet, Opts2} end, - {Port, IPT, IPS, Proto} = + {Port, IPT, Proto} = case add_proto(PortIP, Opts) of {P, Prot} -> T = get_ip_tuple(IPOpt, IPVOpt), - S = misc:ip_to_list(T), - {P, T, S, Prot}; + {P, T, Prot}; {P, T, Prot} when is_integer(P) and is_tuple(T) -> - S = misc:ip_to_list(T), - {P, T, S, Prot}; + {P, T, Prot}; {P, S, Prot} when is_integer(P) and is_binary(S) -> - [S | _] = str:tokens(S, <<"/">>), {ok, T} = inet_parse:address(binary_to_list(S)), - {P, T, S, Prot} + {P, T, Prot} end, IPV = case tuple_size(IPT) of 4 -> inet; 8 -> inet6 end, - {Port, IPT, IPS, IPV, Proto, OptsClean}. + {Port, IPT, IPV, Proto, OptsClean}. prepare_opts(IPT, IPV, OptsClean) -> %% The first inet|inet6 and the last {ip, _} work, @@ -364,7 +350,7 @@ stop_listener({_, _, Transport} = PortIP, Module) -> end. add_listener(PortIP, Module, Opts) -> - {Port, IPT, _, _, Proto, _} = parse_listener_portip(PortIP, Opts), + {Port, IPT, _, Proto, _} = parse_listener_portip(PortIP, Opts), PortIP1 = {Port, IPT, Proto}, case start_listener(PortIP1, Module, Opts) of {ok, _Pid} -> @@ -387,7 +373,7 @@ delete_listener(PortIP, Module) -> %% Module = atom() %% Opts = [term()] delete_listener(PortIP, Module, Opts) -> - {Port, IPT, _, _, Proto, _} = parse_listener_portip(PortIP, Opts), + {Port, IPT, _, Proto, _} = parse_listener_portip(PortIP, Opts), PortIP1 = {Port, IPT, Proto}, stop_listener(PortIP1, Module). @@ -437,19 +423,9 @@ normalize_proto(UnknownProto) -> [UnknownProto]), tcp. -socket_error(Reason, PortIP, Module, SockOpts, Port, IPS) -> - ReasonT = case Reason of - eaddrnotavail -> - "IP address not available: " ++ binary_to_list(IPS); - eaddrinuse -> - "IP address and port number already used: " - ++binary_to_list(IPS)++" "++integer_to_list(Port); - _ -> - format_error(Reason) - end, - ?ERROR_MSG("Failed to open socket:~n ~p~nReason: ~s", - [{Port, Module, SockOpts}, ReasonT]), - throw({Reason, PortIP}). +report_socket_error(Reason, PortIP, Module) -> + ?ERROR_MSG("Failed to open socket at ~s for ~s: ~s", + [format_portip(PortIP), Module, format_error(Reason)]). format_error(Reason) -> case inet:format_error(Reason) of diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index 32828475d..541fcad8b 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -435,7 +435,7 @@ process_user_el(#xmlel{name = Name, attrs = Attrs, children = Els} = El, {<<"query">>, ?NS_PRIVATE} -> process_private(xmpp:decode(El), State); {<<"vCard">>, ?NS_VCARD} -> - process_vcard(El, State); + process_vcard(xmpp:decode(El), State); {<<"offline-messages">>, NS} -> Msgs = [xmpp:decode(E, NS, [ignore_els]) || E <- Els], process_offline_msgs(Msgs, State); @@ -475,25 +475,42 @@ process_roster(RosterQuery, State = #state{user = U, server = S}) -> -spec process_privacy(privacy_query(), state()) -> {ok, state()} | {error, _}. process_privacy(#privacy_query{lists = Lists, default = Default, - active = Active} = PrivacyQuery, + active = Active}, State = #state{user = U, server = S}) -> JID = jid:make(U, S), - IQ = #iq{type = set, id = p1_rand:get_string(), - from = JID, to = JID, sub_els = [PrivacyQuery]}, - case mod_privacy:process_iq(IQ) of - #iq{type = error} = ResIQ -> - #stanza_error{reason = Reason} = xmpp:get_error(ResIQ), - if Reason == 'item-not-found', Lists == [], - Active == undefined, Default /= undefined -> + if Lists /= undefined -> + process_privacy2(JID, #privacy_query{lists = Lists}); + true -> + ok + end, + if Active /= undefined -> + process_privacy2(JID, #privacy_query{active = Active}); + true -> + ok + end, + if Default /= undefined -> + process_privacy2(JID, #privacy_query{default = Default}); + true -> + ok + end, + {ok, State}. + +process_privacy2(JID, PQ) -> + case mod_privacy:process_iq(#iq{type = set, id = p1_rand:get_string(), + from = JID, to = JID, + sub_els = [PQ]}) of + #iq{type = error} = ResIQ -> + #stanza_error{reason = Reason} = xmpp:get_error(ResIQ), + if Reason /= 'item-not-found' -> %% Failed to set default list because there is no %% list with such name. We shouldn't stop here. - {ok, State}; - true -> - stop("Failed to write privacy: ~p", [Reason]) - end; - _ -> - {ok, State} - end. + stop("Failed to write default privacy: ~p", [Reason]); + true -> + ok + end; + _ -> + ok + end. -spec process_private(private(), state()) -> {ok, state()} | {error, _}. process_private(Private, State = #state{user = U, server = S}) -> diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 20106ab6f..8a681bbbc 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -30,8 +30,7 @@ %% xmpp_stream_in callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). --export([tls_options/1, tls_required/1, tls_enabled/1, - compress_methods/1, sasl_mechanisms/2, +-export([tls_options/1, tls_required/1, tls_enabled/1, compress_methods/1, unauthenticated_stream_features/1, authenticated_stream_features/1, handle_stream_start/2, handle_stream_end/2, handle_stream_established/1, handle_auth_success/4, @@ -147,12 +146,6 @@ tls_required(#{server_host := LServer}) -> tls_enabled(#{server_host := LServer}) -> ejabberd_s2s:tls_enabled(LServer). -sasl_mechanisms(Mechs, #{server_host := LServer}) -> - lists:filter( - fun(<<"EXTERNAL">>) -> ejabberd_s2s:tls_verify(LServer); - (_) -> false - end, Mechs). - compress_methods(#{server_host := LServer}) -> case ejabberd_s2s:zlib_enabled(LServer) of true -> [<<"zlib">>]; diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 7f031dce0..46c957330 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -2242,8 +2242,9 @@ make_netprot_html(NetProt) -> [<<"tcp">>, <<"udp">>]))). get_port_data(PortIP, Opts) -> - {Port, IPT, IPS, _IPV, NetProt, OptsClean} = + {Port, IPT, _IPV, NetProt, OptsClean} = ejabberd_listener:parse_listener_portip(PortIP, Opts), + IPS = misc:ip_to_list(IPT), SPort = integer_to_binary(Port), SSPort = list_to_binary( lists:map(fun (N) -> diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 2deb5525b..bb7fe0bdd 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -1018,7 +1018,7 @@ status_num(Status) -> status_num(<<"all">>, Status). status_list(Host, Status) -> Res = get_status_list(Host, Status), - [{U, S, R, P, St} || {U, S, R, P, St} <- Res]. + [{U, S, R, num_prio(P), St} || {U, S, R, P, St} <- Res]. status_list(Status) -> status_list(<<"all">>, Status). @@ -1046,7 +1046,7 @@ get_status_list(Host, Status_required) -> _ -> fun(A, B) -> A == B end end, - [{User, Server, Resource, Priority, stringize(Status_text)} + [{User, Server, Resource, num_prio(Priority), stringize(Status_text)} || {{User, Resource, Status, Status_text}, Server, Priority} <- Sessions4, apply(Fstatus, [Status, Status_required])]. @@ -1127,7 +1127,7 @@ user_session_info(User, Host, Resource) -> NodeS = atom_to_list(node(Pid)), Uptime = CurrentSec - calendar:datetime_to_gregorian_seconds( calendar:now_to_local_time(Now)), - {atom_to_list(Conn), IPS, Port, Priority, NodeS, Uptime, Status, Resource, StatusText}. + {atom_to_list(Conn), IPS, Port, num_prio(Priority), NodeS, Uptime, Status, Resource, StatusText}. %%% @@ -1736,4 +1736,9 @@ is_glob_match(String, <<"!", Glob/binary>>) -> is_glob_match(String, Glob) -> is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)). +num_prio(Priority) when is_integer(Priority) -> + Priority; +num_prio(_) -> + -1. + mod_options(_) -> []. diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index afba0f09a..f58d4bc78 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -584,7 +584,7 @@ create_slot(#state{service_url = undefined, UserStr = make_user_string(JID, JIDinURL), UserDir = <<DocRoot/binary, $/, UserStr/binary>>, case ejabberd_hooks:run_fold(http_upload_slot_request, ServerHost, allow, - [JID, UserDir, Size, Lang]) of + [ServerHost, JID, UserDir, Size, Lang]) of allow -> RandStr = p1_rand:get_alphanum_string(SecretLength), FileStr = make_file_string(File), diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index 529c79291..f27c0222e 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -49,7 +49,7 @@ code_change/3]). %% ejabberd_hooks callback. --export([handle_slot_request/5]). +-export([handle_slot_request/6]). -include("jid.hrl"). -include("logger.hrl"). @@ -229,14 +229,13 @@ code_change(_OldVsn, #state{server_host = ServerHost} = State, _Extra) -> %%-------------------------------------------------------------------- %% ejabberd_hooks callback. %%-------------------------------------------------------------------- --spec handle_slot_request(allow | deny, jid(), binary(), +-spec handle_slot_request(allow | deny, binary(), jid(), binary(), non_neg_integer(), binary()) -> allow | deny. -handle_slot_request(allow, #jid{lserver = ServerHost} = JID, Path, Size, - _Lang) -> +handle_slot_request(allow, ServerHost, JID, Path, Size, _Lang) -> Proc = mod_http_upload:get_proc_name(ServerHost, ?MODULE), gen_server:cast(Proc, {handle_slot_request, JID, Path, Size}), allow; -handle_slot_request(Acc, _JID, _Path, _Size, _Lang) -> Acc. +handle_slot_request(Acc, _ServerHost, _JID, _Path, _Size, _Lang) -> Acc. %%-------------------------------------------------------------------- %% Internal functions. diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index d3240f3d5..553eae1e4 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -907,7 +907,6 @@ presence_broadcast(Config) -> B64Ver = base64:encode(Ver), Node = <<(?EJABBERD_CT_URI)/binary, $#, B64Ver/binary>>, Server = ?config(server, Config), - ServerJID = server_jid(Config), Info = #disco_info{identities = [#identity{category = <<"client">>, type = <<"bot">>, diff --git a/test/privacy_tests.erl b/test/privacy_tests.erl index 25e5441ee..8cd99f513 100644 --- a/test/privacy_tests.erl +++ b/test/privacy_tests.erl @@ -710,7 +710,7 @@ check_presence_blocked(Config, Reason) -> #stanza_error{reason = Reason} = xmpp:get_error(Err) end, [available, unavailable]). -recv_roster_pushes(Config, 0) -> +recv_roster_pushes(_Config, 0) -> ok; recv_roster_pushes(Config, Count) -> receive @@ -719,7 +719,6 @@ recv_roster_pushes(Config, Count) -> end. recv_err_and_roster_pushes(Config, Count) -> - PeerJID = ?config(master, Config), recv_roster_pushes(Config, Count), recv_presence(Config). diff --git a/test/pubsub_tests.erl b/test/pubsub_tests.erl index 718a5b7b5..ca468f779 100644 --- a/test/pubsub_tests.erl +++ b/test/pubsub_tests.erl @@ -217,7 +217,7 @@ master_slave_cases() -> publish_master(Config) -> Node = create_node(Config, <<>>), put_event(Config, Node), - wait_for_slave(Config), + ready = get_event(Config), #ps_item{id = ID} = publish_item(Config, Node), #ps_item{id = ID} = get_event(Config), delete_node(Config, Node), @@ -226,7 +226,7 @@ publish_master(Config) -> publish_slave(Config) -> Node = get_event(Config), subscribe_node(Config, Node), - wait_for_master(Config), + put_event(Config, ready), #message{ sub_els = [#ps_event{ diff --git a/test/upload_tests.erl b/test/upload_tests.erl index 88d27fc2c..ed1e90845 100644 --- a/test/upload_tests.erl +++ b/test/upload_tests.erl @@ -149,13 +149,13 @@ slot_request(Config, NS) -> {GetURL, PutURL, Filename, Size} end. -put_request(Config, URL0, Data) -> +put_request(_Config, URL0, Data) -> ct:comment("Putting ~B bytes to ~s", [size(Data), URL0]), URL = binary_to_list(URL0), {ok, {{"HTTP/1.1", 201, _}, _, _}} = httpc:request(put, {URL, [], ?CONTENT_TYPE, Data}, [], []). -get_request(Config, URL0, Data) -> +get_request(_Config, URL0, Data) -> ct:comment("Getting ~B bytes from ~s", [size(Data), URL0]), URL = binary_to_list(URL0), {ok, {{"HTTP/1.1", 200, _}, _, Body}} = |