From b3695e08787679dfd7dbccbfd5cc407a6751dc2a Mon Sep 17 00:00:00 2001 From: juhlig Date: Mon, 17 Jun 2019 16:45:00 +0200 Subject: Validate transport options --- src/ranch.erl | 59 ++++++++++++++++++++++++++++++++++++++++++++----- test/acceptor_SUITE.erl | 6 ++--- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/ranch.erl b/src/ranch.erl index 0580d5b..b26f3a6 100644 --- a/src/ranch.erl +++ b/src/ranch.erl @@ -71,12 +71,14 @@ start_listener(Ref, Transport, TransOpts0, Protocol, ProtoOpts) when is_atom(Transport), is_atom(Protocol) -> TransOpts = normalize_opts(TransOpts0), _ = code:ensure_loaded(Transport), - case erlang:function_exported(Transport, name, 0) of - false -> - {error, badarg}; - true -> + case {erlang:function_exported(Transport, name, 0), validate_transport_opts(TransOpts)} of + {true, ok} -> maybe_started(supervisor:start_child(ranch_sup, child_spec(Ref, - Transport, TransOpts, Protocol, ProtoOpts))) + Transport, TransOpts, Protocol, ProtoOpts))); + {false, _} -> + {error, {bad_transport, Transport}}; + {_, TransOptsError} -> + TransOptsError end. -spec normalize_opts(opts()) -> transport_opts(any()). @@ -85,6 +87,53 @@ normalize_opts(Map) when is_map(Map) -> normalize_opts(Any) -> #{socket_opts => Any}. +-spec validate_transport_opts(transport_opts(any())) -> ok | {error, any()}. +validate_transport_opts(Opts) -> + maps:fold(fun + (Key, Value, ok) -> + case validate_transport_opt(Key, Value, Opts) of + true -> + ok; + false -> + {error, {bad_option, Key}} + end; + (_, _, Acc) -> + Acc + end, ok, Opts). + +-spec validate_transport_opt(any(), any(), transport_opts(any())) -> boolean(). +validate_transport_opt(connection_type, worker, _) -> + true; +validate_transport_opt(connection_type, supervisor, _) -> + true; +validate_transport_opt(handshake_timeout, infinity, _) -> + true; +validate_transport_opt(handshake_timeout, Value, _) -> + is_integer(Value) andalso Value >= 0; +validate_transport_opt(max_connections, infinity, _) -> + true; +validate_transport_opt(max_connections, Value, _) -> + is_integer(Value) andalso Value >= 0; +validate_transport_opt(logger, Value, _) -> + is_atom(Value); +validate_transport_opt(num_acceptors, Value, _) -> + is_integer(Value) andalso Value > 0; +validate_transport_opt(num_conns_sups, Value, _) -> + is_integer(Value) andalso Value > 0; +validate_transport_opt(num_listen_sockets, Value, Opts) -> + is_integer(Value) andalso Value > 0 + andalso Value =< maps:get(num_acceptors, Opts, 10); +validate_transport_opt(shutdown, brutal_kill, _) -> + true; +validate_transport_opt(shutdown, infinity, _) -> + true; +validate_transport_opt(shutdown, Value, _) -> + is_integer(Value) andalso Value >= 0; +validate_transport_opt(socket_opts, _, _) -> + true; +validate_transport_opt(_, _, _) -> + false. + maybe_started({error, {{shutdown, {failed_to_start_child, ranch_acceptors_sup, {listen_error, _, Reason}}}, _}} = Error) -> diff --git a/test/acceptor_SUITE.erl b/test/acceptor_SUITE.erl index b6ddea4..294b07e 100644 --- a/test/acceptor_SUITE.erl +++ b/test/acceptor_SUITE.erl @@ -94,8 +94,8 @@ groups() -> misc_bad_transport(_) -> doc("Reject invalid transport modules."), - {error, badarg} = ranch:start_listener(misc_bad_transport, - bad_transport, #{}, + {error, {bad_transport, invalid_transport}} = ranch:start_listener(misc_bad_transport, + invalid_transport, #{}, echo_protocol, []), ok. @@ -1202,7 +1202,7 @@ supervisor_changed_options_restart(_) -> {ok, [{send_timeout, 300001}]} = inet:getopts(do_get_listener_socket(ListenerSupPid1), [send_timeout]), %% Crash the listener_sup process, allow a short time for restart to succeed. - %% We silence the excepted log events coming from the relevant supervisors. + %% We silence the expected log events coming from the relevant supervisors. ListenerChilds = [ChildPid || {_, ChildPid, _, _} <- supervisor:which_children(ListenerSupPid1)], FilterFun = fun (#{meta := #{pid := EventPid}}, _) -> case lists:member(EventPid, ListenerChilds) of -- cgit v1.2.3