Skip to content

Commit

Permalink
Enable usage of experimental inet_backend option for TCP listeners
Browse files Browse the repository at this point in the history
  • Loading branch information
Maria-12648430 committed Jun 19, 2020
1 parent 9d16b30 commit 018b1bb
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 12 deletions.
7 changes: 1 addition & 6 deletions src/ranch_acceptors_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,7 @@ start_listen_sockets(Ref, NumListenSockets, Transport, TransOpts0, Logger) when
[];
{_, Port} ->
SocketOpts = maps:get(socket_opts, TransOpts0, []),
SocketOpts1 = case lists:keyfind(port, 1, SocketOpts) of
{port, Port} ->
SocketOpts;
_ ->
[{port, Port}|lists:keydelete(port, 1, SocketOpts)]
end,
SocketOpts1 = lists:keystore(port, 1, SocketOpts, {port, Port}),
TransOpts1 = TransOpts0#{socket_opts => SocketOpts1},
[{N, start_listen_socket(Ref, Transport, TransOpts1, Logger)}
|| N <- lists:seq(2, NumListenSockets)]
Expand Down
20 changes: 14 additions & 6 deletions src/ranch_tcp.erl
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,24 @@ messages() -> {tcp, tcp_closed, tcp_error, tcp_passive}.
listen(TransOpts) ->
ok = cleanup(TransOpts),
Logger = maps:get(logger, TransOpts, logger),
SocketOpts0 = maps:get(socket_opts, TransOpts, []),
SocketOpts = maps:get(socket_opts, TransOpts, []),
%% We set the port to 0 because it is given in the Opts directly.
%% The port in the options takes precedence over the one in the
%% first argument.
gen_tcp:listen(0, prepare_socket_opts(SocketOpts, Logger)).

prepare_socket_opts([Backend = {inet_backend, _}|SocketOpts], Logger) ->
%% In OTP/23, the inet_backend option may be used to activate the
%% experimental socket backend for inet/gen_tcp. If present, it must
%% be the first option in the list.
[Backend|prepare_socket_opts(SocketOpts, Logger)];
prepare_socket_opts(SocketOpts0, Logger) ->
SocketOpts1 = ranch:set_option_default(SocketOpts0, backlog, 1024),
SocketOpts2 = ranch:set_option_default(SocketOpts1, nodelay, true),
SocketOpts3 = ranch:set_option_default(SocketOpts2, send_timeout, 30000),
SocketOpts4 = ranch:set_option_default(SocketOpts3, send_timeout_close, true),
%% We set the port to 0 because it is given in the Opts directly.
%% The port in the options takes precedence over the one in the
%% first argument.
gen_tcp:listen(0, ranch:filter_options(SocketOpts4, disallowed_listen_options(),
[binary, {active, false}, {packet, raw}, {reuseaddr, true}], Logger)).
ranch:filter_options(SocketOpts4, disallowed_listen_options(),
[binary, {active, false}, {packet, raw}, {reuseaddr, true}], Logger).

%% 'binary' and 'list' are disallowed but they are handled
%% specifically as they do not have 2-tuple equivalents.
Expand Down
28 changes: 28 additions & 0 deletions test/acceptor_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ groups() ->
tcp_active_n_echo,
tcp_echo,
tcp_local_echo,
tcp_socket_echo,
tcp_graceful,
tcp_inherit_options,
tcp_max_connections,
Expand Down Expand Up @@ -916,6 +917,33 @@ do_tcp_local_echo() ->
file:delete(SockFile)
end.

tcp_socket_echo(_) ->
%% The socket backend for inet/gen_tcp was introduced as an experimental
%% feature in OTP/23. erlang:atom_to_binary/1 first appears in this
%% release.
case erlang:function_exported(erlang, atom_to_binary, 1) of
true ->
do_tcp_socket_echo();
false ->
{skip, "No socket backend support."}
end.

do_tcp_socket_echo() ->
doc("Ensure that using the socket backend works with TCP transport."),
Name = name(),
{ok, _} = ranch:start_listener(Name,
ranch_tcp, #{socket_opts => [{inet_backend, socket}]},
echo_protocol, []),
Port = ranch:get_port(Name),
{ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]),
ok = gen_tcp:send(Socket, <<"TCP Ranch is working!">>),
{ok, <<"TCP Ranch is working!">>} = gen_tcp:recv(Socket, 21, 1000),
ok = ranch:stop_listener(Name),
{error, closed} = gen_tcp:recv(Socket, 0, 1000),
%% Make sure the listener stopped.
{'EXIT', _} = begin catch ranch:get_port(Name) end,
ok.

tcp_graceful(_) ->
doc("Ensure suspending and resuming of listeners does not kill active connections."),
Name = name(),
Expand Down

0 comments on commit 018b1bb

Please sign in to comment.