aboutsummaryrefslogtreecommitdiffstats
path: root/erts/preloaded
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2018-07-04 15:18:18 +0200
committerMicael Karlberg <[email protected]>2018-09-18 14:50:18 +0200
commite39e25d84405e13ca0ce476e3ba473510e5548de (patch)
tree217ac95a480968372496b2b3b5d978826860f076 /erts/preloaded
parentdce68cf27f2dd1721bd316594a29ff99a0de7bb9 (diff)
downloadotp-e39e25d84405e13ca0ce476e3ba473510e5548de.tar.gz
otp-e39e25d84405e13ca0ce476e3ba473510e5548de.tar.bz2
otp-e39e25d84405e13ca0ce476e3ba473510e5548de.zip
[socket-nif] Fixed (dgram) recv
Fixed handling of recvfrom (used by dgram sockets). Had forgot to do select(read) when we got block from the call to recvfrom. Argh! Also updated the (simple) test server and client to to be able to use udp (dgram+udp). OTP-14831
Diffstat (limited to 'erts/preloaded')
-rw-r--r--erts/preloaded/ebin/socket.beambin42488 -> 42660 bytes
-rw-r--r--erts/preloaded/src/socket.erl122
2 files changed, 79 insertions, 43 deletions
diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam
index 4924c43a5c..99a9f0f749 100644
--- a/erts/preloaded/ebin/socket.beam
+++ b/erts/preloaded/ebin/socket.beam
Binary files differ
diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl
index bf94271073..79b8471e08 100644
--- a/erts/preloaded/src/socket.erl
+++ b/erts/preloaded/src/socket.erl
@@ -37,7 +37,7 @@
accept/1, accept/2,
send/2, send/3, send/4,
- sendto/4, sendto/5,
+ sendto/3, sendto/4, sendto/5,
%% sendmsg/4,
%% writev/4, OR SENDV? It will be strange for recv then: recvv (instead of readv)
@@ -50,7 +50,10 @@
shutdown/2,
setopt/4,
- getopt/3
+ getopt/3,
+
+ sockname/1,
+ peername/1
]).
-export_type([
@@ -204,11 +207,11 @@
reuseaddr |
reuseport |
rxq_ovfl |
- sndlowat |
- sndtimeo |
setfib |
sndbuf |
sndbufforce |
+ sndlowat |
+ sndtimeo |
timestamp |
type.
@@ -431,6 +434,7 @@
-define(SOCKET_SEND_FLAGS_DEFAULT, []).
-define(SOCKET_SEND_TIMEOUT_DEFAULT, infinity).
+-define(SOCKET_SENDTO_FLAGS_DEFAULT, []).
-define(SOCKET_SENDTO_TIMEOUT_DEFAULT, ?SOCKET_SEND_TIMEOUT_DEFAULT).
-define(SOCKET_RECV_FLAG_CMSG_CLOEXEC, 0).
@@ -462,6 +466,7 @@
-define(SOCKET_OPT_SOCK_RCVBUF, 17).
-define(SOCKET_OPT_SOCK_REUSEADDR, 21).
-define(SOCKET_OPT_SOCK_SNDBUF, 27).
+-define(SOCKET_OPT_SOCK_TYPE, 32).
-define(SOCKET_OPT_IP_RECVTOS, 25).
-define(SOCKET_OPT_IP_ROUTER_ALERT, 28).
@@ -927,40 +932,43 @@ do_send(SockRef, Data, EFlags, Timeout) ->
%% ---------------------------------------------------------------------------
%%
-sendto(Socket, Data, Flags, Dest) ->
- sendto(Socket, Data, Flags, Dest, ?SOCKET_SENDTO_TIMEOUT_DEFAULT).
+sendto(Socket, Data, Dest) ->
+ sendto(Socket, Data, Dest, ?SOCKET_SENDTO_FLAGS_DEFAULT).
+
+sendto(Socket, Data, Dest, Flags) ->
+ sendto(Socket, Data, Dest, Flags, ?SOCKET_SENDTO_TIMEOUT_DEFAULT).
--spec sendto(Socket, Data, Flags, Dest, Timeout) ->
+-spec sendto(Socket, Data, Dest, Flags, Timeout) ->
ok | {error, Reason} when
Socket :: socket(),
Data :: binary(),
- Flags :: send_flags(),
Dest :: null | sockaddr(),
+ Flags :: send_flags(),
Timeout :: timeout(),
Reason :: term().
-sendto(Socket, Data, Flags, Dest, Timeout) when is_list(Data) ->
+sendto(Socket, Data, Dest, Flags, Timeout) when is_list(Data) ->
Bin = erlang:list_to_binary(Data),
- sendto(Socket, Bin, Flags, Dest, Timeout);
-sendto(#socket{ref = SockRef}, Data, Flags, Dest, Timeout)
+ sendto(Socket, Bin, Dest, Flags, Timeout);
+sendto(#socket{ref = SockRef}, Data, Dest, Flags, Timeout)
when is_binary(Data) andalso
- is_list(Flags) andalso
(Dest =:= null) andalso
+ is_list(Flags) andalso
(is_integer(Timeout) orelse (Timeout =:= infinity)) ->
EFlags = enc_send_flags(Flags),
- do_sendto(SockRef, Data, EFlags, Dest, Timeout);
-sendto(#socket{ref = SockRef}, Data, Flags, #{family := Fam} = Dest, Timeout)
+ do_sendto(SockRef, Data, Dest, EFlags, Timeout);
+sendto(#socket{ref = SockRef}, Data, #{family := Fam} = Dest, Flags, Timeout)
when is_binary(Data) andalso
- is_list(Flags) andalso
((Fam =:= inet) orelse (Fam =:= inet6) orelse (Fam =:= local)) andalso
+ is_list(Flags) andalso
(is_integer(Timeout) orelse (Timeout =:= infinity)) ->
EFlags = enc_send_flags(Flags),
- do_sendto(SockRef, Data, EFlags, Dest, Timeout).
+ do_sendto(SockRef, Data, Dest, EFlags, Timeout).
-do_sendto(SockRef, Data, EFlags, Dest, Timeout) ->
+do_sendto(SockRef, Data, Dest, EFlags, Timeout) ->
TS = timestamp(Timeout),
SendRef = make_ref(),
- case nif_sendto(SockRef, SendRef, Data, EFlags, Dest) of
+ case nif_sendto(SockRef, SendRef, Data, Dest, EFlags) of
ok ->
%% We are done
ok;
@@ -970,10 +978,10 @@ do_sendto(SockRef, Data, EFlags, Dest, Timeout) ->
receive
{select, SockRef, SendRef, ready_output} when (Written > 0) ->
<<_:Written/binary, Rest/binary>> = Data,
- do_sendto(SockRef, Rest, EFlags, Dest,
+ do_sendto(SockRef, Rest, Dest, EFlags,
next_timeout(TS, Timeout));
{select, SockRef, SendRef, ready_output} ->
- do_sendto(SockRef, Data, EFlags, Dest,
+ do_sendto(SockRef, Data, Dest, EFlags,
next_timeout(TS, Timeout));
{nif_abort, SendRef, Reason} ->
@@ -988,7 +996,7 @@ do_sendto(SockRef, Data, EFlags, Dest, Timeout) ->
{error, eagain} ->
receive
{select, SockRef, SendRef, ready_output} ->
- do_sendto(SockRef, Data, EFlags, Dest,
+ do_sendto(SockRef, Data, Dest, EFlags,
next_timeout(TS, Timeout))
after Timeout ->
nif_cancel(SockRef, sendto, SendRef),
@@ -1135,21 +1143,10 @@ do_recv(SockRef, _OldRef, Length, EFlags, Acc, Timeout)
(is_integer(Timeout) andalso (Timeout > 0)) ->
TS = timestamp(Timeout),
RecvRef = make_ref(),
- p("do_recv -> try read with"
- "~n SockRef: ~p"
- "~n RecvRef: ~p"
- "~n Length: ~p"
- "~n EFlags: ~p"
- "~nwhen"
- "~n Timeout: ~p (~p)", [SockRef, RecvRef, Length, EFlags, Timeout, TS]),
case nif_recv(SockRef, RecvRef, Length, EFlags) of
{ok, true = _Complete, Bin} when (size(Acc) =:= 0) ->
- p("do_recv -> ok: complete (size(Acc) =:= 0)"
- "~n size(Bin): ~p", [size(Bin)]),
{ok, Bin};
{ok, true = _Complete, Bin} ->
- p("do_recv -> ok: complete"
- "~n size(Bin): ~p", [size(Bin)]),
{ok, <<Acc/binary, Bin/binary>>};
%% It depends on the amount of bytes we tried to read:
@@ -1158,16 +1155,12 @@ do_recv(SockRef, _OldRef, Length, EFlags, Acc, Timeout)
%% > 0 - We got a part of the message and we will be notified
%% when there is more to read (a select message)
{ok, false = _Complete, Bin} when (Length =:= 0) ->
- p("do_recv -> ok: not-complete (Length =:= 0)"
- "~n size(Bin): ~p", [size(Bin)]),
do_recv(SockRef, RecvRef,
Length, EFlags,
<<Acc/binary, Bin/binary>>,
next_timeout(TS, Timeout));
{ok, false = _Completed, Bin} when (size(Acc) =:= 0) ->
- p("do_recv -> ok: not-complete (size(Acc) =:= 0)"
- "~n size(Bin): ~p", [size(Bin)]),
%% We got the first chunk of it.
%% We will be notified (select message) when there
%% is more to read.
@@ -1190,8 +1183,6 @@ do_recv(SockRef, _OldRef, Length, EFlags, Acc, Timeout)
end;
{ok, false = _Completed, Bin} ->
- p("do_recv -> ok: not-complete"
- "~n size(Bin): ~p", [size(Bin)]),
%% We got a chunk of it!
NewTimeout = next_timeout(TS, Timeout),
receive
@@ -1213,17 +1204,14 @@ do_recv(SockRef, _OldRef, Length, EFlags, Acc, Timeout)
%% We return with the accumulated binary (if its non-empty)
{error, eagain} when (Length =:= 0) andalso (size(Acc) > 0) ->
- p("do_recv -> eagain (Length =:= 0)", []),
{ok, Acc};
{error, eagain} ->
- p("do_recv -> eagain", []),
%% There is nothing just now, but we will be notified when there
%% is something to read (a select message).
NewTimeout = next_timeout(TS, Timeout),
receive
{select, SockRef, RecvRef, ready_input} ->
- p("do_recv -> received select ready-input message", []),
do_recv(SockRef, RecvRef,
Length, EFlags,
Acc,
@@ -1317,16 +1305,21 @@ recvfrom(#socket{ref = SockRef}, BufSz, Flags, Timeout)
do_recvfrom(SockRef, BufSz, EFlags, Timeout) ->
TS = timestamp(Timeout),
RecvRef = make_ref(),
+ p("recvfrom -> try recvfrom"),
case nif_recvfrom(SockRef, RecvRef, BufSz, EFlags) of
{ok, {_Source, _NewData}} = OK ->
+ p("recvfrom -> ok: "
+ "~n Source: ~p", [_Source]),
OK;
{error, eagain} ->
+ p("recvfrom -> eagain - wait for select ready-input"),
%% There is nothing just now, but we will be notified when there
%% is something to read (a select message).
NewTimeout = next_timeout(TS, Timeout),
receive
{select, SockRef, RecvRef, ready_input} ->
+ p("recvfrom -> eagain - got select ready-input"),
do_recvfrom(SockRef, BufSz, EFlags,
next_timeout(TS, Timeout));
@@ -1339,7 +1332,8 @@ do_recvfrom(SockRef, BufSz, EFlags, Timeout) ->
{error, timeout}
end;
- {error, _} = ERROR ->
+ {error, _Reason} = ERROR ->
+ p("recvfrom -> error: ~p", [_Reason]),
ERROR
end.
@@ -1572,6 +1566,37 @@ getopt(#socket{info = Info, ref = SockRef}, Level, Key) ->
+%% ===========================================================================
+%%
+%% sockname - return the current address of the socket.
+%%
+%%
+
+-spec sockname(Socket) -> {ok, SockAddr} | {error, Reason} when
+ Socket :: socket(),
+ SockAddr :: sockaddr(),
+ Reason :: term().
+
+sockname(#socket{ref = SockRef}) ->
+ nif_sockname(SockRef).
+
+
+
+%% ===========================================================================
+%%
+%% peername - return the address of the peer *connected* to the socket.
+%%
+%%
+
+-spec peername(Socket) -> {ok, SockAddr} | {error, Reason} when
+ Socket :: socket(),
+ SockAddr :: sockaddr(),
+ Reason :: term().
+
+peername(#socket{ref = SockRef}) ->
+ nif_peername(SockRef).
+
+
%% ===========================================================================
%%
@@ -1970,6 +1995,8 @@ enc_sockopt_key(socket = L, sndtimeo = Opt, _Dir, _D, _T, _P) ->
not_supported({L, Opt});
enc_sockopt_key(socket = L, timestamp = Opt, _Dir, _D, _T, _P) ->
not_supported({L, Opt});
+enc_sockopt_key(socket = _L, type = _Opt, _Dir, _D, _T, _P) ->
+ ?SOCKET_OPT_SOCK_TYPE;
enc_sockopt_key(socket = L, UnknownOpt, _Dir, _D, _T, _P) ->
unknown({L, UnknownOpt});
@@ -2200,6 +2227,9 @@ tdiff(T1, T2) ->
+p(F) ->
+ p(F, []).
+
p(F, A) ->
p(get(sname), F, A).
@@ -2261,7 +2291,7 @@ nif_accept(_SRef, _Ref) ->
nif_send(_SockRef, _SendRef, _Data, _Flags) ->
erlang:error(badarg).
-nif_sendto(_SRef, _SendRef, _Data, _Flags, _DestSockAddr) ->
+nif_sendto(_SRef, _SendRef, _Data, _Dest, _Flags) ->
erlang:error(badarg).
nif_recv(_SRef, _RecvRef, _Length, _Flags) ->
@@ -2288,3 +2318,9 @@ nif_setopt(_Ref, _IsEnc, _Lev, _Key, _Val) ->
nif_getopt(_Ref, _IsEnc, _Lev, _Key) ->
erlang:error(badarg).
+nif_sockname(_Ref) ->
+ erlang:error(badarg).
+
+nif_peername(_Ref) ->
+ erlang:error(badarg).
+