diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ejabberd_sql.erl | 9 | ||||
-rw-r--r-- | src/mod_http_upload.erl | 50 | ||||
-rw-r--r-- | src/mod_mam.erl | 11 | ||||
-rw-r--r-- | src/mod_proxy65_stream.erl | 25 | ||||
-rw-r--r-- | src/mod_stream_mgmt.erl | 2 | ||||
-rw-r--r-- | src/xmpp_stream_out.erl | 58 |
6 files changed, 98 insertions, 57 deletions
diff --git a/src/ejabberd_sql.erl b/src/ejabberd_sql.erl index 28103430a..970dece3f 100644 --- a/src/ejabberd_sql.erl +++ b/src/ejabberd_sql.erl @@ -580,8 +580,13 @@ sql_query_internal(#sql_query{} = Query) -> sqlite -> sqlite_sql_query(Query) end - catch - Class:Reason -> + catch exit:{timeout, _} -> + {error, <<"timed out">>}; + exit:{killed, _} -> + {error, <<"killed">>}; + exit:{normal, _} -> + {error, <<"terminated unexpectedly">>}; + Class:Reason -> ST = erlang:get_stacktrace(), ?ERROR_MSG("Internal error while processing SQL query: ~p", [{Class, Reason, ST}]), diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 65251e056..55a51af86 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -110,7 +110,8 @@ service_url :: binary() | undefined, thumbnail :: boolean(), custom_headers :: [{binary(), binary()}], - slots = #{} :: map()}). + slots = #{} :: map(), + external_secret :: binary()}). -record(media_info, {type :: atom(), @@ -208,7 +209,9 @@ mod_opt_type(thumbnail) -> end; (false) -> false - end. + end; +mod_opt_type(external_secret) -> + fun iolist_to_binary/1. -spec mod_options(binary()) -> [{atom(), any()}]. mod_options(_Host) -> @@ -225,6 +228,7 @@ mod_options(_Host) -> {put_url, <<"http://@HOST@:5444">>}, {get_url, undefined}, {service_url, undefined}, + {external_secret, <<"">>}, {custom_headers, []}, {rm_on_unregister, true}, {thumbnail, false}]. @@ -255,6 +259,7 @@ init([ServerHost, Opts]) -> end, ServiceURL = gen_mod:get_opt(service_url, Opts), Thumbnail = gen_mod:get_opt(thumbnail, Opts), + ExternalSecret = gen_mod:get_opt(external_secret, Opts), CustomHeaders = gen_mod:get_opt(custom_headers, Opts), DocRoot1 = expand_home(str:strip(DocRoot, right, $/)), DocRoot2 = expand_host(DocRoot1, ServerHost), @@ -277,6 +282,7 @@ init([ServerHost, Opts]) -> put_url = expand_host(str:strip(PutURL, right, $/), ServerHost), get_url = expand_host(str:strip(GetURL, right, $/), ServerHost), service_url = ServiceURL, + external_secret = ExternalSecret, custom_headers = CustomHeaders}}. -spec handle_call(_, {pid(), _}, state()) @@ -532,11 +538,12 @@ process_slot_request(#iq{lang = Lang, from = From} = IQ, {ok, Timer} = timer:send_after(?SLOT_TIMEOUT, {slot_timed_out, Slot}), + Query = make_query_string(Slot, Size, State), NewState = add_slot(Slot, Size, Timer, State), - NewSlot = mk_slot(Slot, State, XMLNS), + NewSlot = mk_slot(Slot, State, XMLNS, Query), {xmpp:make_iq_result(IQ, NewSlot), NewState}; {ok, PutURL, GetURL} -> - Slot = mk_slot(PutURL, GetURL, XMLNS), + Slot = mk_slot(PutURL, GetURL, XMLNS, <<"">>), xmpp:make_iq_result(IQ, Slot); {error, Error} -> xmpp:make_error(IQ, Error) @@ -646,20 +653,21 @@ del_slot(Slot, #state{slots = Slots} = State) -> NewSlots = maps:remove(Slot, Slots), State#state{slots = NewSlots}. --spec mk_slot(slot(), state(), binary()) -> upload_slot(); - (binary(), binary(), binary()) -> upload_slot(). -mk_slot(Slot, #state{put_url = PutPrefix, get_url = GetPrefix}, XMLNS) -> +-spec mk_slot(slot(), state(), binary(), binary()) -> upload_slot(); + (binary(), binary(), binary(), binary()) -> upload_slot(). +mk_slot(Slot, #state{put_url = PutPrefix, get_url = GetPrefix}, XMLNS, Query) -> PutURL = str:join([PutPrefix | Slot], <<$/>>), GetURL = str:join([GetPrefix | Slot], <<$/>>), - mk_slot(PutURL, GetURL, XMLNS); -mk_slot(PutURL, GetURL, ?NS_HTTP_UPLOAD_0) -> - #upload_slot_0{get = misc:url_encode(GetURL), - put = misc:url_encode(PutURL), - xmlns = ?NS_HTTP_UPLOAD_0}; -mk_slot(PutURL, GetURL, XMLNS) -> - #upload_slot{get = misc:url_encode(GetURL), - put = misc:url_encode(PutURL), - xmlns = XMLNS}. + mk_slot(PutURL, GetURL, XMLNS, Query); +mk_slot(PutURL, GetURL, XMLNS, Query) -> + PutURL1 = <<(misc:url_encode(PutURL))/binary, Query/binary>>, + GetURL1 = misc:url_encode(GetURL), + case XMLNS of + ?NS_HTTP_UPLOAD_0 -> + #upload_slot_0{get = GetURL1, put = PutURL1, xmlns = XMLNS}; + _ -> + #upload_slot{get = GetURL1, put = PutURL1, xmlns = XMLNS} + end. -spec make_user_string(jid(), sha1 | node) -> binary(). make_user_string(#jid{luser = U, lserver = S}, sha1) -> @@ -671,6 +679,16 @@ make_user_string(#jid{luser = U}, node) -> make_file_string(File) -> replace_special_chars(File). +-spec make_query_string(slot(), non_neg_integer(), state()) -> binary(). +make_query_string(Slot, Size, #state{external_secret = Key}) when Key /= <<>> -> + UrlPath = str:join(Slot, <<$/>>), + SizeStr = integer_to_binary(Size), + Data = <<UrlPath/binary, " ", SizeStr/binary>>, + HMAC = str:to_hexlist(crypto:hmac(sha256, Data, Key)), + <<"?v=", HMAC/binary>>; +make_query_string(_Slot, _Size, _State) -> + <<>>. + -spec replace_special_chars(binary()) -> binary(). replace_special_chars(S) -> re:replace(S, <<"[^\\p{Xan}_.-]">>, <<$_>>, diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 9595be99f..a643fe51c 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -77,6 +77,17 @@ %%% API %%%=================================================================== start(Host, Opts) -> + case gen_mod:get_opt(db_type, Opts) of + mnesia -> + ?WARNING_MSG("Mnesia backend for ~s is not recommended: " + "it's limited to 2GB and often gets corrupted " + "when reaching this limit. SQL backend is " + "recommended. Namely, for small servers SQLite " + "is a preferred choice because it's very easy " + "to configure.", [?MODULE]); + _ -> + ok + end, Mod = gen_mod:db_mod(Host, Opts, ?MODULE), Mod:init(Host, Opts), init_cache(Mod, Host, Opts), diff --git a/src/mod_proxy65_stream.erl b/src/mod_proxy65_stream.erl index df6bc4776..418e4588f 100644 --- a/src/mod_proxy65_stream.erl +++ b/src/mod_proxy65_stream.erl @@ -245,14 +245,19 @@ handle_sync_event(_Event, _From, StateName, %%%------------------------------------------------- relay(MySocket, PeerSocket, Shaper) -> case gen_tcp:recv(MySocket, 0) of - {ok, Data} -> - gen_tcp:send(PeerSocket, Data), - {NewShaper, Pause} = shaper:update(Shaper, byte_size(Data)), - if Pause > 0 -> timer:sleep(Pause); - true -> pass - end, - relay(MySocket, PeerSocket, NewShaper); - _ -> stopped + {ok, Data} -> + case gen_tcp:send(PeerSocket, Data) of + ok -> + {NewShaper, Pause} = shaper:update(Shaper, byte_size(Data)), + if Pause > 0 -> timer:sleep(Pause); + true -> pass + end, + relay(MySocket, PeerSocket, NewShaper); + {error, _} = Err -> + Err + end; + {error, _} = Err -> + Err end. %%%------------------------ @@ -299,7 +304,7 @@ listen_opt_type(accept_interval) -> listen_options() -> [{auth_type, anonymous}, - {recbuf, 8192}, - {sndbuf, 8192}, + {recbuf, 65536}, + {sndbuf, 65536}, {accept_interval, 0}, {shaper, none}]. diff --git a/src/mod_stream_mgmt.erl b/src/mod_stream_mgmt.erl index 62124b22e..6fb601817 100644 --- a/src/mod_stream_mgmt.erl +++ b/src/mod_stream_mgmt.erl @@ -682,6 +682,8 @@ inherit_session_state(#{user := U, server := S, {error, <<"Previous session PID is dead">>}; exit:{normal, _} -> {error, <<"Previous session PID has exited">>}; + exit:{killed, _} -> + {error, <<"Previous session PID has been killed">>}; exit:{timeout, _} -> ejabberd_sm:close_session(OldSID, U, S, R), ejabberd_c2s:stop(OldPID), diff --git a/src/xmpp_stream_out.erl b/src/xmpp_stream_out.erl index 6bdd16213..f11aaf743 100644 --- a/src/xmpp_stream_out.erl +++ b/src/xmpp_stream_out.erl @@ -49,7 +49,7 @@ -type state() :: map(). -type noreply() :: {noreply, state(), timeout()}. --type host_port() :: {inet:hostname(), inet:port_number(), boolean()}. +-type host_port() :: {inet:hostname(), inet:port_number(), boolean()} | ip_port(). -type ip_port() :: {inet:ip_address(), inet:port_number(), boolean()}. -type h_addr_list() :: {{integer(), integer(), inet:port_number(), string()}, boolean()}. -type network_error() :: {error, inet:posix() | inet_res:res_error()}. @@ -1115,8 +1115,19 @@ a_lookup(HostPorts, State) -> Family <- get_address_families(State)], a_lookup(HostPortFamilies, State, [], {error, nxdomain}). --spec a_lookup([{inet:hostname(), inet:port_number(), boolean(), inet:address_family()}], +-spec a_lookup([{inet:hostname() | inet:ip_address(), inet:port_number(), + boolean(), inet:address_family()}], state(), [ip_port()], network_error()) -> {ok, [ip_port()]} | network_error(). +a_lookup([{Addr, Port, TLS, Family}|HostPortFamilies], State, Acc, Err) + when is_tuple(Addr) -> + Acc1 = if tuple_size(Addr) == 4 andalso Family == inet -> + [{Addr, Port, TLS}|Acc]; + tuple_size(Addr) == 8 andalso Family == inet6 -> + [{Addr, Port, TLS}|Acc]; + true -> + Acc + end, + a_lookup(HostPortFamilies, State, Acc1, Err); a_lookup([{Host, Port, TLS, Family}|HostPortFamilies], State, Acc, Err) -> Timeout = get_dns_timeout(State), Retries = get_dns_retries(State), @@ -1136,35 +1147,24 @@ a_lookup([], _State, Acc, _) -> a_lookup(_Host, _Port, _TLS, _Family, _Timeout, Retries) when Retries < 1 -> {error, timeout}; a_lookup(Host, Port, TLS, Family, Timeout, Retries) -> - case inet:parse_address(Host) of - {ok, Addr} -> - if tuple_size(Addr) == 4 andalso Family == inet -> - {ok, [{Addr, Port, TLS}]}; - tuple_size(Addr) == 8 andalso Family == inet6 -> - {ok, [{Addr, Port, TLS}]}; + Start = p1_time_compat:monotonic_time(milli_seconds), + case inet:gethostbyname(Host, Family, Timeout) of + {error, nxdomain} = Err -> + %% inet:gethostbyname/3 doesn't return {error, timeout}, + %% so we should check if 'nxdomain' is in fact a result + %% of a timeout. + %% We also cannot use inet_res:gethostbyname/3 because + %% it ignores DNS configuration settings (/etc/hosts, etc) + End = p1_time_compat:monotonic_time(milli_seconds), + if (End - Start) >= Timeout -> + a_lookup(Host, Port, TLS, Family, Timeout, Retries - 1); true -> - {error, nxdomain} + Err end; - {error, _} -> - Start = p1_time_compat:monotonic_time(milli_seconds), - case inet:gethostbyname(Host, Family, Timeout) of - {error, nxdomain} = Err -> - %% inet:gethostbyname/3 doesn't return {error, timeout}, - %% so we should check if 'nxdomain' is in fact a result - %% of a timeout. - %% We also cannot use inet_res:gethostbyname/3 because - %% it ignores DNS configuration settings (/etc/hosts, etc) - End = p1_time_compat:monotonic_time(milli_seconds), - if (End - Start) >= Timeout -> - a_lookup(Host, Port, TLS, Family, Timeout, Retries - 1); - true -> - Err - end; - {error, _} = Err -> - Err; - {ok, HostEntry} -> - host_entry_to_addr_ports(HostEntry, Port, TLS) - end + {error, _} = Err -> + Err; + {ok, HostEntry} -> + host_entry_to_addr_ports(HostEntry, Port, TLS) end. -spec h_addr_list_to_host_ports(h_addr_list()) -> {ok, [host_port()]} | |