Browse Source

Validate transport options

juhlig 6 years ago
parent
commit
b3695e0878
2 changed files with 57 additions and 8 deletions
  1. 54 5
      src/ranch.erl
  2. 3 3
      test/acceptor_SUITE.erl

+ 54 - 5
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) ->

+ 3 - 3
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