aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_sql.erl9
-rw-r--r--src/mod_http_upload.erl50
-rw-r--r--src/mod_mam.erl11
-rw-r--r--src/mod_proxy65_stream.erl25
-rw-r--r--src/mod_stream_mgmt.erl2
-rw-r--r--src/xmpp_stream_out.erl58
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()]} |