From 63338250778d2caad08aa3180b372e5260f22aa7 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 31 May 2018 10:58:19 +0200 Subject: [socket-nif-doc] Add preliminary doc for socket The doc now builds. Had to update the code (spec and types) to match. Though, te result is less then stellar. OTP-14831 --- erts/doc/src/socket.xml | 308 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 erts/doc/src/socket.xml (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml new file mode 100644 index 0000000000..9b487172c5 --- /dev/null +++ b/erts/doc/src/socket.xml @@ -0,0 +1,308 @@ + + + + +
+ + 20182018 + Ericsson AB. All Rights Reserved. + + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + + socket + + + + + socket.xml +
+ socket + Socket interface. + +

This module provides an API for the socket interface. + It is used to create, delete and manipulate sockets.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Accept a connection on a socket. + +

Accept a connection on a socket.

+

This call is used with connection-based socket types + (stream or seqpacket). It extracs the first pending connection + request for the listen socket and returns the (newly) connected + socket.

+
+
+ + + + Bind a name to a socket. + +

Bind a name to a socket.

+

When a socket is created + (with open), + it has no address assigned to it. bind assigns the + address specified by the Addr argument.

+

The rules used for name binding vary between domains.

+
+
+ + + + Close a socket. + +

Closes the socket.

+
+
+ + + + + Initiate a connection on a socket. + +

This function connects the socket to the address + specied by the Addr argument.

+
+
+ + + + + + + + + + + Get an option on a socket. + +

Get an option on a socket.

+

What properties are valid depend on what kind of socket + it is (domain, type and protocol).

+

When specifying Level as an integer, and therefor + using "native mode", it is *currently* up to the caller to + know how to interpret the result.

+ +

Not all options are valid on all platforms. That is, + even if "we" support an option, that does not mean that the + underlying OS does.

+
+
+ + + + + Listen for connections on a socket. + +

Listen for connections on a socket.

+
+
+ + + + + + Create an endpoint for communication. + +

Creates an endpoint (socket) for communication.

+

For some types there is a default protocol, which will + be used if no protocol is specified:

+ + stream + +

tcp

+
+ dgram + +

udp

+
+ seqpacket + +

sctp

+
+
+
+
+ + + + + + Receive a message from a socket. + +

Receive a message from a socket.

+

There is a special case for the argument Length. + If it is set to zero (0), it means "give me everything you + currently have".

+
+
+ + + + + + + Receive a message from a socket. + +

Receive a message from a socket.

+

This function reads "messages", which means that regardless of + how much we want to read, it returns when we get a message.

+

The MaxSize argument basically defines the size of the + receive buffer. By setting the value to zero (0), the configured + size (setopt) is used.

+

It may be impossible to know what (buffer) size is appropriate + "in advance", and in those cases it may be convenient to use the + (recv) 'peek' flag. When this flag is provided the message is *not* + "consumed" from the underlying buffers, so another recvfrom call + is needed, possibly with a then adjusted buffer size.

+
+
+ + + + + + Send a message on a socket. + +

Send a message on a connected socket.

+
+
+ + + + + Send a message on a socket. + +

Send a message on a socket, to the specified destination.

+
+
+ + + + + + + + + + Set options on a socket. + +

Set options on a socket.

+

What properties are valid depend on what kind of socket + it is (domain, type and protocol).

+ +

Not all options are valid on all platforms. That is, + even if "we" support an option, that does not mean that the + underlying OS does.

+ +

Sockets are set 'non-blocking' when created, so this option + is *not* available (as it would adversely effect the Erlang VM + to set a socket 'blocking').

+
+
+ + + + Shut down part of a full-duplex connection. + +

Shut down all or part of a full-duplex connection.

+
+
+ +
+
+ -- cgit v1.2.3 From 9e0acc8f442549f1f5ee4271816cbfbeb25d8719 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 7 Jun 2018 11:03:27 +0200 Subject: [socket-nif-doc] Fixed socket type and function open The doc for type socket was missing (as it is opaque), so instead its replaced with a simple text referring to the functions open and accept. The open function missed a spec (for open/2), the text for default protocol needed some omrpvement and finally the Extra argument needed explaining. --- erts/doc/src/socket.xml | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 9b487172c5..d0a316c4de 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -47,7 +47,11 @@ - + socket() +

As returned by + open/2,3,4 and + accept/1,2.

+
@@ -134,7 +138,7 @@

Bind a name to a socket.

When a socket is created - (with open), + (with open), it has no address assigned to it. bind assigns the address specified by the Addr argument.

The rules used for name binding vary between domains.

@@ -199,22 +203,18 @@ Create an endpoint for communication.

Creates an endpoint (socket) for communication.

-

For some types there is a default protocol, which will +

For some types there is a default protocol, which will be used if no protocol is specified:

- - stream - -

tcp

-
- dgram - -

udp

-
- seqpacket - -

sctp

-
-
+ + +

stream: tcp

+

dgram: udp

+

seqpacket: sctp

+
+ +

The Extra argument is intended for "obscure" options. + Currently the only supported option is netns, which + is only supported on the linux platform.

@@ -282,8 +282,9 @@ Set options on a socket.

Set options on a socket.

-

What properties are valid depend on what kind of socket - it is (domain, type and protocol).

+

What properties are valid depend both on Level and on + what kind of socket it is (domain, type and + protocol).

Not all options are valid on all platforms. That is, even if "we" support an option, that does not mean that the -- cgit v1.2.3 From 70b74f57a360c2b2a1edfe46c61d2ea170d73f91 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 7 Jun 2018 17:50:38 +0200 Subject: [socket-nif-doc] More polishing Also added (a very) temporary example. OTP-14831 --- erts/doc/src/socket.xml | 250 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 243 insertions(+), 7 deletions(-) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index d0a316c4de..3efa412b8a 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -149,7 +149,17 @@ Close a socket. -

Closes the socket.

+

Closes the socket.

+ + +

Note that for e.g. protocol = tcp, most implementations + doing a close does not guarantee that any data sent is delivered to + the recipient before the close is detected at the remote side.

+

One way to handle this is to use the + shutdown function + (socket:shutdown(Socket, write)) to signal that no more data is + to be sent and then wait for the read side of the socket to be closed.

+
@@ -159,7 +169,7 @@ Initiate a connection on a socket.

This function connects the socket to the address - specied by the Addr argument.

+ specied by the SockAddr argument.

@@ -171,12 +181,27 @@ + Get an option on a socket. + +

Get an option on a socket.

+

What properties are valid depend both on Level and + on what kind of socket it is (domain, type and + protocol).

+ +

Not all options are valid on all platforms. That is, + even if "we" support an option, that does not mean that the + underlying OS does.

+
+ + + Get an option on a socket.

Get an option on a socket.

-

What properties are valid depend on what kind of socket - it is (domain, type and protocol).

+

What properties are valid depend both on Level and + on what kind of socket it is (domain, type and + protocol).

When specifying Level as an integer, and therefor using "native mode", it is *currently* up to the caller to know how to interpret the result.

@@ -241,12 +266,12 @@

Receive a message from a socket.

This function reads "messages", which means that regardless of how much we want to read, it returns when we get a message.

-

The MaxSize argument basically defines the size of the +

The BufSz argument basically defines the size of the receive buffer. By setting the value to zero (0), the configured - size (setopt) is used.

+ size (setopt with Level = otp) is used.

It may be impossible to know what (buffer) size is appropriate "in advance", and in those cases it may be convenient to use the - (recv) 'peek' flag. When this flag is provided the message is *not* + (recv) 'peek' flag. When this flag is provided, the message is *not* "consumed" from the underlying buffers, so another recvfrom call is needed, possibly with a then adjusted buffer size.

@@ -305,5 +330,216 @@
+
+ Examples + +

TBD: Need to implement a receiver process in order to be able to + implement active!

+

x_tcp.erl:

+ +listen(Addr, Port) -> + try + begin + Socket = case socket:open(inet, stream, tcp) of + {ok, Socket} -> + Socket; + {error, _} = OERROR -> + throw(OERROR) + end, + SockAddr = #in4_sockaddr{port = Port, + addr = Addr}, + ok = case socket:bind(Socket, SockAddr) of + ok -> + ok; + {error, _} = BERROR -> + throw(BERROR) + end, + case socket:listen(Socket, 10) of + ok -> + {ok, Socket}; + {error, _} = LERROR -> + throw(LERROR) + end + end + catch + throw:ERROR -> + ERROR +end. + + + +connect(Addr, Port) -> + try + begin + Socket = case socket:open(inet, stream, tcp) of + {ok, Socket} -> + Socket; + {error, _} = OERROR -> + throw(OERROR) + end, + BSockAddr = #in4_sockaddr{port = 0, + addr = any}, + ok = case socket:bind(Socket, BSockAddr) of + ok -> + ok; + {error, _} = BERROR -> + throw(BERROR) + end, + CSockAddr = #in4_sockaddr{port = Port, + addr = Addr}, + Socket = case socket:connect(Socket, CSockAddr) of + {ok, Sock} -> + Sock; + {error, _} = CERROR -> + throw(CERROR) + end, + case start_receiver(Socket) of + {ok, Pid} -> + ok = socket:ts_add(Socket, receiver, Pid), + {ok, Socket}; + {error, _} = RERROR -> + socket:close(Socket), + throw(RERROR) + end + end + catch + throw:ERROR -> + ERROR +end. + + + +accept(LSocket) -> + case socket:accept(LSocket) of + {ok, Socket} -> + case start_receiver(Socket) of + {ok, Pid} -> + ok = socket:ts_add(Socket, receiver, Pid), + {ok, Socket}; + {error, _} = RERROR -> + socket:close(Socket), + throw(RERROR) + end, + {error, _} = AERROR -> + AERROR + end. + + + +send(Socket, Data) -> + socket:send(Socket, Data). + + + +setopt(Socket, controlling_process = Item, Pid) when is_pid(Pid) -> + case socket:setopt(Socket, otp, Item, Pid) of + ok -> + {ok, Receiver} = socket:ts_get(Socket, receiver), + update_receiver(Receiver, {controlling_process, Pid), + ok; + {error, _} = ERROR -> + ERROR + end; +setopt(Socket, active, Active) -> + {ok, Receiver} = socket:ts_get(Socket, receiver), + receiver_active(Receiver, Active), + ok; +%% This is just to indicate that there will be more options +%% that needs to be handled +setopt(Socket, Item, Pid) when is_pid(Pid) -> + socket:setopt(Socket, which_level(Item), Item, Pid). + + +

The receiver process:

+ +start_receiver(Socket) -> + CtrlProc = self(), + Ref = make_ref(), + Receiver = proc_lib:spawn_link(fun() -> receiver_init(CtrlProc, Ref) end), + receive + {?MODULE, started, Ref} -> + Receiver ! {?MODULE, receiver, Ref, Sock, true}, + unlink(Receiver), + {ok, Receiver}; + {'EXIT', Receiver, Reason} -> + {error, Reason} + end. + +receiver_active(Receiver, Active) + when (Active =:= false) orelse + (Active =:= true) orelse + (Active =:= once) orelse + is_integer(Active) -> + Receiver ! {?MODULE, active, What}. + +receiver_update(Receiver, What) -> + Ref = make_ref(), + Receiver ! {?MODULE, receiver_update, Ref, What}, + receive + {?MODULE, receiver_upadate, Ref, Result} -> + Result + end. + +-record(receiver, {sock :: socket:socket(), + ctrl :: pid(), + num_packages :: infinity | non_neg_ineteger()}). + +receiver_init(Pid, Ref) -> + receive + {?MODULE, receiver, Ref, stop} -> + i("received stop"), + exit(normal); + + {?MODULE, receiver, Ref, Sock, InitialMode} -> + i("received socket: ~p", [Sock]), + NumPackages = mode2pkgcount(InitialMode), + receiver(#receiver{sock = Sock, ctrl = Pid}) + end. + +mode2pkgcount(true) -> + infinity; +mode2pkgcount(false) -> + 0; +mode2pkgcount(N) when is_integer(N) andalso (N >= 0) -> + N. + +receiver(#receiver{num_packages = 0} = State) -> + receive + {?MODULE, active, false} -> + receiver(State); + {?MODULE, active, true} -> + receiver(State#receiver{num_packages = infinity}); + {?MODULE, active, once} -> + receiver(State#receiver{num_packages = 1}); + {?MODULE, active, N} when (N > 0) -> + receiver(State#receiver{num_packages = N}) + end; +receiver(#receiver{num_packages = N, sock = Sock, ctrl = Pid} = State) -> + case socket:recv(Sock, 0) of + {ok, Package} when size(Package) > 0 -> + Pid ! {tcp, Sock, Packege}, + case next_active(N) of + 0 -> + Pid ! {tcp_passive, Sock}, + receiver(State#{num_packages = 0}); + NextN -> + receiver(State#{num_packages = NextN}) + end; + {ok, Package} when size(Package) =:= 0 -> + receiver(State); + + {error, closed} -> + i("closed"), + Pid ! {tcp_closed, Sock}, + exit(normal); + + {error, Reason} -> + i("error: ~p", [Reason]), + Pid ! {tcp_error, Sock, Reason}, + exit(normal) + end. + + +
-- cgit v1.2.3 From eacb95d88db1e1123d17288e71835b457bcf4016 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 4 Jul 2018 18:37:32 +0200 Subject: [socket-doc-nif] Updated documentation Updated the documentation of recv, recvfrom, send and sendto. Also added doc for functions peername and sockname. OTP-14831 --- erts/doc/src/socket.xml | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 3efa412b8a..6f116abca9 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -63,13 +63,16 @@
- + - + - + + + + @@ -244,8 +247,18 @@ + + Get name of connected socket peer. + +

Returns the address of the peer connected to the socket.

+
+
+ + + - + + Receive a message from a socket. @@ -259,7 +272,9 @@ - + + + Receive a message from a socket. @@ -279,7 +294,8 @@ - + + Send a message on a socket. @@ -288,6 +304,7 @@ + Send a message on a socket. @@ -329,6 +346,14 @@ + + + Get socket name. + +

Returns the current address to which the socket is bound.

+
+
+
Examples -- cgit v1.2.3 From 9b5560dbe50c377c8fc9b6a0c0c7b6c2dcf9f0de Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 11 Jul 2018 11:49:58 +0200 Subject: [socket-doc-nif] Preliminary socket option table Added a commented out (preliminary) table in the getopt function for the socket level. The table is not included (atleast) in the man page, so there is no point in including it yet. But since its table(s) of all socket options (one for each level) we need comprehensive tables "somewhere", but where... OTP-14831 --- erts/doc/src/socket.xml | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 6f116abca9..2681910a72 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -119,6 +119,9 @@ + + + @@ -194,6 +197,50 @@

Not all options are valid on all platforms. That is, even if "we" support an option, that does not mean that the underlying OS does.

+ + -- cgit v1.2.3 From d28129b7098bce154264937862fcdafb21541433 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 19 Jul 2018 14:00:42 +0200 Subject: [socket-nif] Add support for socket (level sctp) option events Added support for the SCTP option EVENTS. OTP-14831 --- erts/doc/src/socket.xml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 2681910a72..4ecf35b8ed 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -122,6 +122,21 @@ + + + + + + + + + + + + + + + @@ -132,9 +147,9 @@

Accept a connection on a socket.

This call is used with connection-based socket types - (stream or seqpacket). It extracs the first pending connection - request for the listen socket and returns the (newly) connected - socket.

+ (stream or seqpacket). It extracs the first pending + connection request for the listen socket and returns the (newly) + connected socket.

-- cgit v1.2.3 From 7a5b320b5bb5ec45b21839005e8538172908fb57 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 19 Jul 2018 16:39:13 +0200 Subject: [socket-nif] Add (partial) support for socket (level sctp) option associnfo Added support for the SCTP option ASSOCINFO. This option is a bit tricky. As the underlying structure (sctp_assocparams) contains the assoc_id, it begs the question what happens if this option is fetched for: * The own assoc (which means that we might have the assoc id in the descriptor and can initiate that part of the struct accordningly). * Another assoc: From assoc A asks for info with assoc_id set to that of assoc B. * The "owning" endpoint. * Another endpoint (an endpoint to which the assoc does not belong). So, if the user calls socket:[getopt|setopt] for an association socket, shall we require that the assoc_id field is set to -1? Or not set at all and therefor filled in automatically by the nif-code? And, if the user calls socket:[getopt|setopt] for an endpoint socket, shall we require that the assoc_id field is set to a valid id? Or shall it not be allowed? Questions, questions... OTP-14831 --- erts/doc/src/socket.xml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 4ecf35b8ed..3e8e7af5c6 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -137,6 +137,9 @@ + + + -- cgit v1.2.3 From 6bb60f1fecef368991806e25a0022c63b8650f39 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 19 Jul 2018 17:34:15 +0200 Subject: [socket-nif] Add (partial) support for socket (level sctp) option rtoinfo Added support for the SCTP option RTOINFO. We have the same questions for this option as for ASSOCINFO. Maybe the assoc field shall be made 'out' only (that is, it will be ignored for setopt). The assoc id used will be that which is stored in the descriptor (how do we get it to begin with?). Questions, questions... OTP-14831 --- erts/doc/src/socket.xml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 3e8e7af5c6..f6b25c8563 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -140,6 +140,9 @@ + + + -- cgit v1.2.3 From bd36af21717b138c91724128e592b3fc587bb07a Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 20 Jul 2018 10:10:28 +0200 Subject: [socket-nif] Add support for socket (level sctp) option initmsg Added support for the SCTP option INITMSG. OTP-14831 --- erts/doc/src/socket.xml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index f6b25c8563..fe23eaa138 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -140,6 +140,9 @@ + + + -- cgit v1.2.3 From 3f1d17f3031b71ca6ff1f8e051859ad55e55822b Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 20 Jul 2018 12:28:19 +0200 Subject: [socket-nif] Add support for socket (level socket) option(s) [rcv|snd]timeo Added support for socket level socket option RCVTIMEO and SNDTIMEO. These are both a little strange, at least on linux. See the man pages for more info. OTP-14831 --- erts/doc/src/socket.xml | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index fe23eaa138..14a21823b8 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -116,6 +116,9 @@ + + + @@ -146,6 +149,12 @@ + + + + + + -- cgit v1.2.3 From 5d9de1cdc46c75117f15f1ab17f017cdb700eb4c Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 25 Jul 2018 11:28:49 +0200 Subject: [socket-nif] Add support for socket (level ip) option msfilter Added support for ip level socket option MSFILTER. This option has not been tested *in any way*... OTP-14831 --- erts/doc/src/socket.xml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 14a21823b8..53d1516f1e 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -131,6 +131,12 @@ + + + + + + -- cgit v1.2.3 From 90a150771faa3cf01e82919b0c17854de9987783 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 1 Aug 2018 19:42:32 +0200 Subject: [socket-nif] Processing of more cmsg headers Added processing or more cmsg headers (for more options). Now (also) supports: socket:timestamp. Also various fixes and cleanups. For some reason calling getopt(Sock, 0, {13, int}) (or similar) fails with badarg even though the nif-function (nif_getopt) actually returns a valid value (for instance: {ok, 0}). OTP-14831 --- erts/doc/src/socket.xml | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 53d1516f1e..2fb922408b 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -120,7 +120,7 @@ - + @@ -137,6 +137,9 @@ + + + @@ -155,6 +158,27 @@ + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From d8b1eace1cfe3184497752f345e5f6bc5def9769 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 3 Aug 2018 12:33:22 +0200 Subject: [socket-nif] Add preliminary support for sendmsg Added function sendmsg/2,3,4. Actually worked on the first try. Something must be wrong... Still no supported cmsghdr's (only support headers where the data part is already a binary, which therefor does not require any processing). So if the cmsghdrs actually work is unclear. OTP-14831 --- erts/doc/src/socket.xml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 2fb922408b..93a3a8172e 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -402,6 +402,40 @@ + + + + + + + Receive a message from a socket. + +

Receive a message from a socket.

+

This function reads "messages", which means that regardless of + how much we want to read, it returns when we get a message.

+

The message will be delivered in the form of a msghdr(), + which may contain the source address (if socket not connected), + a list of cmsghdr() (depends on what socket options have + been set and what the protocol and platform supports) and + also a set of flags, providing further info about the read .

+ +

The BufSz argument basically defines the size of the + receive buffer. By setting the value to zero (0), the configured + size (setopt with Level = otp) is used.

+ +

The CtrlSz argument basically defines the size of the + receive buffer for the control messages. + By setting the value to zero (0), the configured size (setopt + with Level = otp) is used.

+ +

It may be impossible to know what (buffer) size is appropriate + "in advance", and in those cases it may be convenient to use the + (recv) 'peek' flag. When this flag is provided, the message is *not* + "consumed" from the underlying buffers, so another recvmsg call + is needed, possibly with a then adjusted buffer size.

+
+
+ @@ -413,6 +447,21 @@ + + + + + + Send a message on a socket. + +

Send a message on a socket. The destination, if needed (socket not + connected) is provided in the MsgHdr, which also + contains the message to send, The MsgHdr may also contain + an list of optional cmsghdr() (depends on what the protocol and + platform supports).

+
+
+ -- cgit v1.2.3 From 01601a4db44b3adccfbcc07129a4584649252736 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 3 Aug 2018 15:08:30 +0200 Subject: [socket-nif] Add more data types (with doc) and (C) debug Add more debug printouts for the new sendmsg. Also added new (erlang) types with doc. OTP-14831 --- erts/doc/src/socket.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 93a3a8172e..b11b68cba5 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -146,6 +146,9 @@ + + + @@ -179,12 +182,21 @@ + + + + + + + + + -- cgit v1.2.3 From 929ae46220f402d6f36072c46fe27ba39ad48d1b Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 13 Sep 2018 15:44:21 +0200 Subject: [socket-nif] CMsgHdr and various doc related changes Updated the (send) cmsghdr type and the handling of it (in the nif code). Still not tested! Removed the is_loaded nif function. Tried to get fix the doc build problem (socket.erl *i think*), which causes socket.html generation to fail with: "cannot find module exporting type" To solve this I tried to run dialyzer on preloaded, and ran into problems with enc_setopt_value. Update various specs and types to "solve" this (which did not work). Updated the nif-stub functions to make dialyzer happy. --- erts/doc/src/socket.xml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index b11b68cba5..35f7e8502d 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -176,11 +176,16 @@ + - + + + + @@ -427,7 +432,7 @@ how much we want to read, it returns when we get a message.

The message will be delivered in the form of a msghdr(), which may contain the source address (if socket not connected), - a list of cmsghdr() (depends on what socket options have + a list of cmsghdr_recv() (depends on what socket options have been set and what the protocol and platform supports) and also a set of flags, providing further info about the read .

@@ -466,11 +471,11 @@ Send a message on a socket. -

Send a message on a socket. The destination, if needed (socket not - connected) is provided in the MsgHdr, which also - contains the message to send, The MsgHdr may also contain - an list of optional cmsghdr() (depends on what the protocol and - platform supports).

+

Send a message on a socket. The destination, if needed + (socket not connected) is provided in the MsgHdr, + which also contains the message to send, + The MsgHdr may also contain an list of optional cmsghdr_send() + (depends on what the protocol and platform supports).

@@ -492,6 +497,7 @@ + Set options on a socket.

Set options on a socket.

-- cgit v1.2.3 From 4341dcd7ab14ae8af3d12a30563b5229015e320c Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 27 Sep 2018 12:40:35 +0200 Subject: [socket-nif|doc] SCTP type and sendto Added missing SCTP type (for assoc id) and updated sento doc (missing clauses). OTP-14831 --- erts/doc/src/socket.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 35f7e8502d..e2fd0adc8f 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -146,6 +146,9 @@ + + + @@ -481,7 +484,8 @@ - + + Send a message on a socket. -- cgit v1.2.3 From 0b56a98366fc152c0fa5d5398220ac31866114d5 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 28 Sep 2018 18:34:45 +0200 Subject: [socket-nif|doc] Cleanup and fixed setopt doc Removed some cruft. Also tried, without success, to fix the build issue ("Error file: cannot find module exporting type"). It may be because of a spec-file issue. Finally fixed the setopt doc. It did not have a seperate clause for clause 8 (the fallback clause that takes level and key as integer). --- erts/doc/src/socket.xml | 272 ++++-------------------------------------------- 1 file changed, 21 insertions(+), 251 deletions(-) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index e2fd0adc8f..af7e0ca9c1 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -245,7 +245,8 @@ doing a close does not guarantee that any data sent is delivered to the recipient before the close is detected at the remote side.

One way to handle this is to use the - shutdown function + shutdown + function (socket:shutdown(Socket, write)) to signal that no more data is to be sent and then wait for the read side of the socket to be closed.

@@ -281,49 +282,6 @@ even if "we" support an option, that does not mean that the underlying OS does.

-
@@ -501,6 +459,24 @@ + Set options on a socket. + +

Set options on a socket.

+

What properties are valid depend both on Level and on + what kind of socket it is (domain, type and + protocol).

+ +

Not all options are valid on all platforms. That is, + even if "we" support an option, that does not mean that the + underlying OS does.

+ +

Sockets are set 'non-blocking' when created, so this option + is *not* available (as it would adversely effect the Erlang VM + to set a socket 'blocking').

+
+ + + Set options on a socket. @@ -539,213 +515,7 @@
Examples -

TBD: Need to implement a receiver process in order to be able to - implement active!

-

x_tcp.erl:

- -listen(Addr, Port) -> - try - begin - Socket = case socket:open(inet, stream, tcp) of - {ok, Socket} -> - Socket; - {error, _} = OERROR -> - throw(OERROR) - end, - SockAddr = #in4_sockaddr{port = Port, - addr = Addr}, - ok = case socket:bind(Socket, SockAddr) of - ok -> - ok; - {error, _} = BERROR -> - throw(BERROR) - end, - case socket:listen(Socket, 10) of - ok -> - {ok, Socket}; - {error, _} = LERROR -> - throw(LERROR) - end - end - catch - throw:ERROR -> - ERROR -end. - - - -connect(Addr, Port) -> - try - begin - Socket = case socket:open(inet, stream, tcp) of - {ok, Socket} -> - Socket; - {error, _} = OERROR -> - throw(OERROR) - end, - BSockAddr = #in4_sockaddr{port = 0, - addr = any}, - ok = case socket:bind(Socket, BSockAddr) of - ok -> - ok; - {error, _} = BERROR -> - throw(BERROR) - end, - CSockAddr = #in4_sockaddr{port = Port, - addr = Addr}, - Socket = case socket:connect(Socket, CSockAddr) of - {ok, Sock} -> - Sock; - {error, _} = CERROR -> - throw(CERROR) - end, - case start_receiver(Socket) of - {ok, Pid} -> - ok = socket:ts_add(Socket, receiver, Pid), - {ok, Socket}; - {error, _} = RERROR -> - socket:close(Socket), - throw(RERROR) - end - end - catch - throw:ERROR -> - ERROR -end. - - - -accept(LSocket) -> - case socket:accept(LSocket) of - {ok, Socket} -> - case start_receiver(Socket) of - {ok, Pid} -> - ok = socket:ts_add(Socket, receiver, Pid), - {ok, Socket}; - {error, _} = RERROR -> - socket:close(Socket), - throw(RERROR) - end, - {error, _} = AERROR -> - AERROR - end. - - - -send(Socket, Data) -> - socket:send(Socket, Data). - - - -setopt(Socket, controlling_process = Item, Pid) when is_pid(Pid) -> - case socket:setopt(Socket, otp, Item, Pid) of - ok -> - {ok, Receiver} = socket:ts_get(Socket, receiver), - update_receiver(Receiver, {controlling_process, Pid), - ok; - {error, _} = ERROR -> - ERROR - end; -setopt(Socket, active, Active) -> - {ok, Receiver} = socket:ts_get(Socket, receiver), - receiver_active(Receiver, Active), - ok; -%% This is just to indicate that there will be more options -%% that needs to be handled -setopt(Socket, Item, Pid) when is_pid(Pid) -> - socket:setopt(Socket, which_level(Item), Item, Pid). - - -

The receiver process:

- -start_receiver(Socket) -> - CtrlProc = self(), - Ref = make_ref(), - Receiver = proc_lib:spawn_link(fun() -> receiver_init(CtrlProc, Ref) end), - receive - {?MODULE, started, Ref} -> - Receiver ! {?MODULE, receiver, Ref, Sock, true}, - unlink(Receiver), - {ok, Receiver}; - {'EXIT', Receiver, Reason} -> - {error, Reason} - end. - -receiver_active(Receiver, Active) - when (Active =:= false) orelse - (Active =:= true) orelse - (Active =:= once) orelse - is_integer(Active) -> - Receiver ! {?MODULE, active, What}. - -receiver_update(Receiver, What) -> - Ref = make_ref(), - Receiver ! {?MODULE, receiver_update, Ref, What}, - receive - {?MODULE, receiver_upadate, Ref, Result} -> - Result - end. - --record(receiver, {sock :: socket:socket(), - ctrl :: pid(), - num_packages :: infinity | non_neg_ineteger()}). - -receiver_init(Pid, Ref) -> - receive - {?MODULE, receiver, Ref, stop} -> - i("received stop"), - exit(normal); - - {?MODULE, receiver, Ref, Sock, InitialMode} -> - i("received socket: ~p", [Sock]), - NumPackages = mode2pkgcount(InitialMode), - receiver(#receiver{sock = Sock, ctrl = Pid}) - end. - -mode2pkgcount(true) -> - infinity; -mode2pkgcount(false) -> - 0; -mode2pkgcount(N) when is_integer(N) andalso (N >= 0) -> - N. - -receiver(#receiver{num_packages = 0} = State) -> - receive - {?MODULE, active, false} -> - receiver(State); - {?MODULE, active, true} -> - receiver(State#receiver{num_packages = infinity}); - {?MODULE, active, once} -> - receiver(State#receiver{num_packages = 1}); - {?MODULE, active, N} when (N > 0) -> - receiver(State#receiver{num_packages = N}) - end; -receiver(#receiver{num_packages = N, sock = Sock, ctrl = Pid} = State) -> - case socket:recv(Sock, 0) of - {ok, Package} when size(Package) > 0 -> - Pid ! {tcp, Sock, Packege}, - case next_active(N) of - 0 -> - Pid ! {tcp_passive, Sock}, - receiver(State#{num_packages = 0}); - NextN -> - receiver(State#{num_packages = NextN}) - end; - {ok, Package} when size(Package) =:= 0 -> - receiver(State); - - {error, closed} -> - i("closed"), - Pid ! {tcp_closed, Sock}, - exit(normal); - - {error, Reason} -> - i("error: ~p", [Reason]), - Pid ! {tcp_error, Sock, Reason}, - exit(normal) - end. - - +

TBD

-- cgit v1.2.3 From ce28d70c686f342fb04fc05e1d00501e7cfbf213 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 9 Oct 2018 16:32:31 +0200 Subject: [socket-nif|doc] Add preliminary doc for the function supports Added preliminary documentation for the function socket:supports/0,1,2,3. It still does not generate proper doc for supports/3 (the last arg, Opt, don't get a type). OTP-14831 --- erts/doc/src/socket.xml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index af7e0ca9c1..49c14869bf 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -205,6 +205,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -511,6 +532,34 @@
+ + + + + + + + + + + + + + + + + + + + + Report info about what the platform supports. + +

This function intends to retreive information about what the + platform supports. Such as if SCTP is supported. Or which socket + options are supported.

+
+
+
Examples -- cgit v1.2.3 From 741eb8d2d8ba606d81990ef50b2d8b261d47ec81 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 5 Nov 2018 14:47:03 +0100 Subject: [socket-nif|doc] Improved doc for recvmsg and update for sendmsg The API for the sendmsg function has been updated to describe the possible "partial success" of {ok, Remaining}. OTP-14831 --- erts/doc/src/socket.xml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'erts/doc/src/socket.xml') diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 49c14869bf..ea2fde7dee 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -405,7 +405,8 @@ - + + Receive a message from a socket. @@ -416,7 +417,7 @@ which may contain the source address (if socket not connected), a list of cmsghdr_recv() (depends on what socket options have been set and what the protocol and platform supports) and - also a set of flags, providing further info about the read .

+ also a set of flags, providing further info about the read.

The BufSz argument basically defines the size of the receive buffer. By setting the value to zero (0), the configured @@ -458,6 +459,15 @@ which also contains the message to send, The MsgHdr may also contain an list of optional cmsghdr_send() (depends on what the protocol and platform supports).

+ +

Unlike the send function, + this one sends one message. + This means that if, for whatever reason, its not possible to send the + message in one go, the function will instead return with the + remaining data ({ok, Remaining}). Thereby leaving it + up to the caller to decide what to do (retry with the remaining data + of give up).

+
-- cgit v1.2.3