aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Lebedeff <[email protected]>2016-04-22 17:33:34 +0300
committerLoïc Hoguin <[email protected]>2016-11-15 15:46:54 +0200
commitf33ff7cbacb204adae9d53ad15829f44c4140525 (patch)
treeeb4b031b5e887e4fdc2391cecb3acb6511de735c
parentdff4ea04dc0e286e8cb43fea0177d3efc249aec5 (diff)
downloadranch-f33ff7cbacb204adae9d53ad15829f44c4140525.tar.gz
ranch-f33ff7cbacb204adae9d53ad15829f44c4140525.tar.bz2
ranch-f33ff7cbacb204adae9d53ad15829f44c4140525.zip
Improve error reporting
Simplify some return values, improve error messages for eaddrinuse and no_cert. Amended to add tests and simpler code. Also hides the contents of cert and key transport options, if any.
-rw-r--r--src/ranch.erl13
-rw-r--r--src/ranch_acceptors_sup.erl13
-rw-r--r--src/ranch_ssl.erl15
-rw-r--r--test/acceptor_SUITE.erl37
4 files changed, 68 insertions, 10 deletions
diff --git a/src/ranch.erl b/src/ranch.erl
index 7f751cf..9eb9a47 100644
--- a/src/ranch.erl
+++ b/src/ranch.erl
@@ -74,9 +74,20 @@ start_listener(Ref, NumAcceptors, Transport, TransOpts, Protocol, ProtoOpts)
_ ->
ok
end,
- Res
+ maybe_started(Res)
end.
+maybe_started({error, {{shutdown,
+ {failed_to_start_child, ranch_acceptors_sup,
+ {listen_error, _, Reason}}}, _}} = Error) ->
+ start_error(Reason, Error);
+maybe_started(Res) ->
+ Res.
+
+start_error(E=eaddrinuse, _) -> {error, E};
+start_error(E=no_cert, _) -> {error, E};
+start_error(_, Error) -> Error.
+
-spec stop_listener(ref()) -> ok | {error, not_found}.
stop_listener(Ref) ->
case supervisor:terminate_child(ranch_sup, {ranch_listener_sup, Ref}) of
diff --git a/src/ranch_acceptors_sup.erl b/src/ranch_acceptors_sup.erl
index 67854d5..d716a33 100644
--- a/src/ranch_acceptors_sup.erl
+++ b/src/ranch_acceptors_sup.erl
@@ -49,8 +49,15 @@ init([Ref, NumAcceptors, Transport, TransOpts]) ->
{ok, {{one_for_one, 1, 5}, Procs}}.
-spec listen_error(any(), module(), any(), atom()) -> no_return().
-listen_error(Ref, Transport, TransOpts2, Reason) ->
+listen_error(Ref, Transport, TransOpts0, Reason) ->
+ TransOpts1 = lists:keyreplace(cert, 1, TransOpts0, {cert, '...'}),
+ TransOpts = lists:keyreplace(key, 1, TransOpts1, {key, '...'}),
error_logger:error_msg(
- "Failed to start Ranch listener ~p in ~p:listen(~p) for reason ~p (~s)~n",
- [Ref, Transport, TransOpts2, Reason, inet:format_error(Reason)]),
+ "Failed to start Ranch listener ~p in ~p:listen(~999999p) for reason ~p (~s)~n",
+ [Ref, Transport, TransOpts, Reason, format_error(Reason)]),
exit({listen_error, Ref, Reason}).
+
+format_error(no_cert) ->
+ "no certificate provided; see cert, certfile, sni_fun or sni_hosts options";
+format_error(Reason) ->
+ inet:format_error(Reason).
diff --git a/src/ranch_ssl.erl b/src/ranch_ssl.erl
index b3fab51..0385065 100644
--- a/src/ranch_ssl.erl
+++ b/src/ranch_ssl.erl
@@ -89,10 +89,17 @@ messages() -> {ssl, ssl_closed, ssl_error}.
-spec listen(opts()) -> {ok, ssl:sslsocket()} | {error, atom()}.
listen(Opts) ->
- true = lists:keymember(cert, 1, Opts)
- orelse lists:keymember(certfile, 1, Opts)
- orelse lists:keymember(sni_fun, 1, Opts)
- orelse lists:keymember(sni_hosts, 1, Opts),
+ case lists:keymember(cert, 1, Opts)
+ orelse lists:keymember(certfile, 1, Opts)
+ orelse lists:keymember(sni_fun, 1, Opts)
+ orelse lists:keymember(sni_hosts, 1, Opts) of
+ true ->
+ do_listen(Opts);
+ false ->
+ {error, no_cert}
+ end.
+
+do_listen(Opts) ->
Opts2 = ranch:set_option_default(Opts, backlog, 1024),
Opts3 = ranch:set_option_default(Opts2, ciphers, unbroken_cipher_suites()),
Opts4 = ranch:set_option_default(Opts3, nodelay, true),
diff --git a/test/acceptor_SUITE.erl b/test/acceptor_SUITE.erl
index 547d1c0..7235420 100644
--- a/test/acceptor_SUITE.erl
+++ b/test/acceptor_SUITE.erl
@@ -34,14 +34,17 @@ groups() ->
tcp_max_connections_infinity,
tcp_set_max_connections,
tcp_set_max_connections_clean,
- tcp_upgrade
+ tcp_upgrade,
+ tcp_error_eaddrinuse
]}, {ssl, [
ssl_accept_error,
ssl_accept_socket,
ssl_active_echo,
ssl_echo,
ssl_sni_echo,
- ssl_sni_fail
+ ssl_sni_fail,
+ ssl_error_eaddrinuse,
+ ssl_error_no_cert
]}, {misc, [
misc_bad_transport,
misc_bad_transport_options
@@ -177,6 +180,24 @@ do_ssl_sni_fail() ->
{'EXIT', _} = begin catch ranch:get_port(Name) end,
ok.
+ssl_error_eaddrinuse(_) ->
+ doc("Check that eaddrinuse returns a simplified error."),
+ Name = name(),
+ Opts = ct_helper:get_certs_from_ets(),
+ {ok, _} = ranch:start_listener(Name, 1, ranch_ssl, Opts, active_echo_protocol, []),
+ Port = ranch:get_port(Name),
+ {error, eaddrinuse} = ranch:start_listener({Name, fails}, 1,
+ ranch_ssl, [{port, Port}|Opts], active_echo_protocol, []),
+ ok = ranch:stop_listener(Name),
+ %% Make sure the listener stopped.
+ {'EXIT', _} = begin catch ranch:get_port(Name) end,
+ ok.
+
+ssl_error_no_cert(_) ->
+ doc("Check that missing certificate returns a simplified error."),
+ {error, no_cert} = ranch:start_listener(name(), 1, ranch_ssl, [], active_echo_protocol, []),
+ ok.
+
%% tcp.
tcp_accept_socket(_) ->
@@ -350,6 +371,18 @@ tcp_upgrade(_) ->
receive upgraded -> ok after 1000 -> error(timeout) end,
ok = ranch:stop_listener(Name).
+tcp_error_eaddrinuse(_) ->
+ doc("Check that eaddrinuse returns a simplified error."),
+ Name = name(),
+ {ok, _} = ranch:start_listener(Name, 1, ranch_tcp, [], active_echo_protocol, []),
+ Port = ranch:get_port(Name),
+ {error, eaddrinuse} = ranch:start_listener({Name, fails}, 1,
+ ranch_tcp, [{port, Port}], active_echo_protocol, []),
+ ok = ranch:stop_listener(Name),
+ %% Make sure the listener stopped.
+ {'EXIT', _} = begin catch ranch:get_port(Name) end,
+ ok.
+
%% Supervisor tests
connection_type_supervisor(_) ->