summaryrefslogtreecommitdiff
path: root/lib/kernel/src/gen_tcp_socket.erl
diff options
context:
space:
mode:
authorRaimo Niskanen <raimo@erlang.org>2021-05-27 14:30:51 +0200
committerRaimo Niskanen <raimo@erlang.org>2021-05-27 14:30:51 +0200
commite5d56f3579fe72c7c82051816f7726e8ae020795 (patch)
tree2f66f3acf243ff57b4edee05068b45452a87c74d /lib/kernel/src/gen_tcp_socket.erl
parentfc27b8f2ef5fee417636e34c44a2327df0e0b553 (diff)
downloaderlang-e5d56f3579fe72c7c82051816f7726e8ae020795.tar.gz
Implement undocumented functions
Diffstat (limited to 'lib/kernel/src/gen_tcp_socket.erl')
-rw-r--r--lib/kernel/src/gen_tcp_socket.erl103
1 files changed, 89 insertions, 14 deletions
diff --git a/lib/kernel/src/gen_tcp_socket.erl b/lib/kernel/src/gen_tcp_socket.erl
index cde37ebe24..83e897326d 100644
--- a/lib/kernel/src/gen_tcp_socket.erl
+++ b/lib/kernel/src/gen_tcp_socket.erl
@@ -39,10 +39,10 @@
%% Utility
-export([info/1, which_sockets/0, which_packet_type/1, socket_to_list/1]).
--ifdef(undefined).
+%% Undocumented or unsupported
-export([unrecv/2]).
-export([fdopen/2]).
--endif.
+
%% gen_statem callbacks
-export([init/1, callback_mode/0, terminate/3]).
@@ -150,14 +150,17 @@ connect_open(Addrs, Domain, ConnectOpts, Opts, ExtraOpts, Timer, BindAddr) ->
ExtraOpts)
of
{ok, Server} ->
- {Setopts, _} =
+ {Setopts_1, _} =
setopts_split(
#{socket => [], server_read => [], server_write => []},
ConnectOpts),
+ Setopts =
+ default_active_true(
+ [{start_opts, StartOpts}] ++ SocketOpts ++ Setopts_1),
ErrRef = make_ref(),
try
- ok(ErrRef, call(Server, {setopts, SocketOpts ++ Setopts})),
ok(ErrRef, call_bind(Server, BindAddr)),
+ ok(ErrRef, call(Server, {setopts, Setopts})),
DefaultError = {error, einval},
Socket =
val(ErrRef,
@@ -200,6 +203,19 @@ extra_opts(OpenOpts) when is_list(OpenOpts) ->
maps:from_list(OpenOpts).
+default_any(Domain, undefined = Undefined) ->
+ if
+ Domain =:= inet;
+ Domain =:= inet6 ->
+ #{family => Domain,
+ addr => any,
+ port => 0};
+ true ->
+ Undefined
+ end;
+default_any(_Domain, BindAddr) ->
+ BindAddr.
+
bind_addr(_Domain, BindIP, BindPort) when BindIP =:= undefined ->
0 = BindPort, % Assert
%% Do not bind!
@@ -221,6 +237,15 @@ call_bind(_Server, undefined) ->
call_bind(Server, BindAddr) ->
call(Server, {bind, BindAddr}).
+
+default_active_true(Opts) ->
+ case lists:keyfind(active, 1, Opts) of
+ {active,_} ->
+ Opts;
+ _ ->
+ [{active,true} | Opts]
+ end.
+
%% -------------------------------------------------------------------------
listen(Port, Opts) ->
@@ -275,19 +300,18 @@ listen_open(Domain, ListenOpts, Opts, ExtraOpts, Backlog, BindAddr) ->
case start_server(Domain, StartOpts, ExtraOpts) of
{ok, Server} ->
%% ?DBG([{server_started, Server}]),
- {Setopts, _} =
+ {Setopts_1, _} =
setopts_split(
#{socket => [], server_read => [], server_write => []},
ListenOpts),
- %% ?DBG([{setopts, Setopts}]),
+ %% ?DBG([{setopts, Setopts_1}]),
+ Setopts =
+ default_active_true(
+ [{start_opts, StartOpts}] ++ SocketOpts ++ Setopts_1),
ErrRef = make_ref(),
try
- ok(ErrRef,
- call(
- Server,
- {setopts,
- [{start_opts, StartOpts}] ++ SocketOpts ++ Setopts})),
- ok(ErrRef, call_bind(Server, BindAddr)),
+ ok(ErrRef, call_bind(Server, default_any(Domain, BindAddr))),
+ ok(ErrRef, call(Server, {setopts, Setopts})),
Socket = val(ErrRef, call(Server, {listen, Backlog})),
{ok, ?MODULE_socket(Server, Socket)}
catch
@@ -593,7 +617,51 @@ which_packet_type(?MODULE_socket(_Server, Socket)) ->
error
end.
-
+
+%% -------------------------------------------------------------------------
+%% Undocumented or unsupported
+%% -------------------------------------------------------------------------
+
+unrecv(?MODULE_socket(_Server, _Socket), _Data) ->
+ {error, enotsup}.
+
+fdopen(Fd, Opts) when is_integer(Fd), 0 =< Fd, is_list(Opts) ->
+ %% ?DBG({Fd, Opts}),
+ {EinvalOpts, Opts_1} = setopts_split(einval, Opts),
+ EinvalOpts =:= [] orelse exit(badarg),
+ {Mod, Opts_2} = inet:tcp_module(Opts_1),
+ Domain = domain(Mod),
+ {StartOpts_1, Opts_3} = setopts_split(start, Opts_2),
+ {SocketOpts, StartOpts} = setopts_split(socket, StartOpts_1),
+ ExtraOpts = extra_opts(Fd),
+ case
+ start_server(
+ Domain,
+ [{timeout, infinity} | start_opts(StartOpts)],
+ ExtraOpts)
+ of
+ {ok, Server} ->
+ {Setopts_1, _} =
+ setopts_split(
+ #{socket => [], server_read => [], server_write => []},
+ Opts_3),
+ Setopts = [{start_opts, StartOpts}] ++ SocketOpts ++ Setopts_1,
+ ErrRef = make_ref(),
+ try
+ ok(ErrRef, call(Server, {setopts, Setopts})),
+ Socket = val(ErrRef, call(Server, fdopen)),
+ {ok, ?MODULE_socket(Server, Socket)}
+ catch
+ throw : {ErrRef, Reason} ->
+ close_server(Server),
+ ?badarg_exit({error, Reason})
+ end;
+ {error, {shutdown, Reason}} ->
+ ?badarg_exit({error, Reason});
+ {error, _} = Error ->
+ ?badarg_exit(Error)
+ end.
+
%%% ========================================================================
%%% Socket glue code
%%%
@@ -1020,7 +1088,7 @@ server_read_write_opts() ->
server_read_opts() ->
%% Read side only opts
maps:merge(
- #{active => true,
+ #{active => false, % inet_drv also has this default
mode => list,
header => 0,
deliver => term,
@@ -1535,6 +1603,13 @@ handle_event(
{call, From}, {recv, _Length, _Timeout}, 'connect' = _State, _P_D) ->
{keep_state_and_data,
[{reply, From, {error, enotconn}}]};
+%% Call: fdopen/2
+handle_event(
+ {call, From}, fdopen, 'connect' = _State,
+ {#params{socket = Socket} = P, D}) ->
+ handle_connected(
+ P, D#{type => fdopen},
+ [{reply, From, {ok, Socket}}]);
handle_event(Type, Content, 'connect' = State, P_D) ->
handle_unexpected(Type, Content, State, P_D);
%%