aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2018-06-19 12:20:21 +0200
committerMicael Karlberg <[email protected]>2018-09-18 14:50:18 +0200
commit44cfb3d222ba4d20607af7cc654746f84ece3989 (patch)
tree8613e0736320ce8ea8a015b88d06194ffb91f1fe /erts
parent1952754950f371f43ed4dd675a42c60b3d166bd7 (diff)
downloadotp-44cfb3d222ba4d20607af7cc654746f84ece3989.tar.gz
otp-44cfb3d222ba4d20607af7cc654746f84ece3989.tar.bz2
otp-44cfb3d222ba4d20607af7cc654746f84ece3989.zip
[socket-nif] Add doc for net module and some cleanup
Added doc for the net module. Also some socket-nif cleanup. OTP-14831
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/Makefile6
-rw-r--r--erts/doc/src/net.xml126
-rw-r--r--erts/doc/src/ref_man.xml1
-rw-r--r--erts/doc/src/specs.xml1
-rw-r--r--erts/emulator/nifs/common/socket_int.h1
-rw-r--r--erts/emulator/nifs/common/socket_nif.c870
-rw-r--r--erts/preloaded/ebin/net.beambin5928 -> 6036 bytes
-rw-r--r--erts/preloaded/src/net.erl26
8 files changed, 198 insertions, 833 deletions
diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile
index 1540344fde..9a2750b751 100644
--- a/erts/doc/src/Makefile
+++ b/erts/doc/src/Makefile
@@ -53,7 +53,8 @@ XML_REF3_EFILES = \
erl_tracer.xml \
init.xml \
zlib.xml \
- socket.xml
+ socket.xml \
+ net.xml
XML_REF3_FILES = \
driver_entry.xml \
@@ -65,7 +66,8 @@ XML_REF3_FILES = \
erts_alloc.xml \
init.xml \
zlib.xml \
- socket.xml
+ socket.xml \
+ net.xml
XML_PART_FILES = \
part.xml
diff --git a/erts/doc/src/net.xml b/erts/doc/src/net.xml
new file mode 100644
index 0000000000..c022fee4f7
--- /dev/null
+++ b/erts/doc/src/net.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2018</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ 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.
+
+ </legalnotice>
+
+ <title>net</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>net.xml</file>
+ </header>
+ <module>net</module>
+ <modulesummary>Network interface.</modulesummary>
+ <description>
+ <p>This module provides an API for the network interface.</p>
+ </description>
+
+ <datatypes>
+ <datatype>
+ <name name="address_info"/>
+ </datatype>
+ <datatype>
+ <name name="name_info"/>
+ </datatype>
+ <datatype>
+ <name name="name_info_flags"/>
+ </datatype>
+ <datatype>
+ <name name="name_info_flag"/>
+ </datatype>
+ <datatype>
+ <name name="name_info_flag_ext"/>
+ </datatype>
+ <datatype>
+ <name name="network_interface_name"/>
+ </datatype>
+ <datatype>
+ <name name="network_interface_index"/>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+ <func>
+ <name name="gethostname" arity="0"/>
+ <fsummary>Get hostname.</fsummary>
+ <desc>
+ <p>Returns the name of the current host.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="getnameinfo" arity="1"/>
+ <name name="getnameinfo" arity="2"/>
+ <fsummary>Address-to-name transaltion.</fsummary>
+ <desc>
+ <p>Address-to-name translation in a protocol-independant manner.</p>
+ <p>This function is the inverse of
+ <seealso marker="#getaddrinfo"><c>getaddrinfo</c></seealso>.
+ It converts a socket address to a corresponding host and service.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="getaddrinfo" arity="1"/>
+ <name name="getaddrinfo" arity="2" clause_i="1"/>
+ <name name="getaddrinfo" arity="2" clause_i="2"/>
+ <name name="getaddrinfo" arity="2" clause_i="3"/>
+ <fsummary>Network address and service transation.</fsummary>
+ <desc>
+ <p>Network address and service translation.</p>
+ <p>This function is the inverse of
+ <seealso marker="#getnameinfo"><c>getnameinfo</c></seealso>.
+ It converts host and service to a corresponding socket address.</p>
+ <p>One of the <c>Host</c> and <c>Service</c> may be <c>undefined</c>
+ but <em>not</em> both.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="if_name2index" arity="1"/>
+ <fsummary>Mappings between network interface names and indexes.</fsummary>
+ <desc>
+ <p>Mappings between network interface names and indexes.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="if_index2name" arity="1"/>
+ <fsummary>Mappings between network interface index and names.</fsummary>
+ <desc>
+ <p>Mappings between network interface index and names.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="if_names" arity="0"/>
+ <fsummary>Get network interface names and indexes.</fsummary>
+ <desc>
+ <p>Get network interface names and indexes.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
+
diff --git a/erts/doc/src/ref_man.xml b/erts/doc/src/ref_man.xml
index da099dd5bb..ccbafb1530 100644
--- a/erts/doc/src/ref_man.xml
+++ b/erts/doc/src/ref_man.xml
@@ -36,6 +36,7 @@
<xi:include href="init.xml"/>
<xi:include href="zlib.xml"/>
<xi:include href="socket.xml"/>
+ <xi:include href="net.xml"/>
<xi:include href="epmd.xml"/>
<xi:include href="erl.xml"/>
<xi:include href="erlc.xml"/>
diff --git a/erts/doc/src/specs.xml b/erts/doc/src/specs.xml
index 4f6951a44b..6c12f619b1 100644
--- a/erts/doc/src/specs.xml
+++ b/erts/doc/src/specs.xml
@@ -5,5 +5,6 @@
<xi:include href="../specs/specs_erl_tracer.xml"/>
<xi:include href="../specs/specs_init.xml"/>
<xi:include href="../specs/specs_socket.xml"/>
+ <xi:include href="../specs/specs_net.xml"/>
<xi:include href="../specs/specs_zlib.xml"/>
</specs>
diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h
index a3e54360fe..878ed513c8 100644
--- a/erts/emulator/nifs/common/socket_int.h
+++ b/erts/emulator/nifs/common/socket_int.h
@@ -104,6 +104,7 @@ typedef unsigned int BOOLEAN_T;
*/
extern ERL_NIF_TERM esock_atom_addr;
extern ERL_NIF_TERM esock_atom_any;
+extern ERL_NIF_TERM esock_atom_debug;
extern ERL_NIF_TERM esock_atom_dgram;
extern ERL_NIF_TERM esock_atom_error;
extern ERL_NIF_TERM esock_atom_false;
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c
index 4efca1c72d..1534bd0766 100644
--- a/erts/emulator/nifs/common/socket_nif.c
+++ b/erts/emulator/nifs/common/socket_nif.c
@@ -397,29 +397,29 @@ typedef union {
#define sock_accept(s, addr, len) \
make_noninheritable_handle(accept((s), (addr), (len)))
-#define sock_bind(s, addr, len) bind((s), (addr), (len))
-#define sock_close(s) closesocket((s))
-#define sock_close_event(e) WSACloseEvent(e)
-#define sock_connect(s, addr, len) connect((s), (addr), (len))
-#define sock_create_event(s) WSACreateEvent()
-#define sock_errno() WSAGetLastError()
-#define sock_getopt(s,l,o,v,ln) getsockopt((s),(l),(o),(v),(ln))
-#define sock_htons(x) htons((x))
-#define sock_htonl(x) htonl((x))
-#define sock_listen(s, b) listen((s), (b))
-#define sock_name(s, addr, len) getsockname((s), (addr), (len))
-#define sock_ntohs(x) ntohs((x))
+#define sock_bind(s, addr, len) bind((s), (addr), (len))
+#define sock_close(s) closesocket((s))
+#define sock_close_event(e) WSACloseEvent(e)
+#define sock_connect(s, addr, len) connect((s), (addr), (len))
+#define sock_create_event(s) WSACreateEvent()
+#define sock_errno() WSAGetLastError()
+#define sock_getopt(s,l,o,v,ln) getsockopt((s),(l),(o),(v),(ln))
+#define sock_htons(x) htons((x))
+#define sock_htonl(x) htonl((x))
+#define sock_listen(s, b) listen((s), (b))
+#define sock_name(s, addr, len) getsockname((s), (addr), (len))
+#define sock_ntohs(x) ntohs((x))
#define sock_open(domain, type, proto) \
make_noninheritable_handle(socket((domain), (type), (proto)))
#define sock_peer(s, addr, len) getpeername((s), (addr), (len))
#define sock_recv(s,buf,len,flag) recv((s),(buf),(len),(flag))
#define sock_recvfrom(s,buf,blen,flag,addr,alen) \
recvfrom((s),(buf),(blen),(flag),(addr),(alen))
-#define sock_send(s,buf,len,flag) send((s),(buf),(len),(flag))
+#define sock_send(s,buf,len,flag) send((s),(buf),(len),(flag))
#define sock_sendto(s,buf,blen,flag,addr,alen) \
sendto((s),(buf),(blen),(flag),(addr),(alen))
-#define sock_setopt(s,l,o,v,ln) setsockopt((s),(l),(o),(v),(ln))
-#define sock_shutdown(s, how) shutdown((s), (how))
+#define sock_setopt(s,l,o,v,ln) setsockopt((s),(l),(o),(v),(ln))
+#define sock_shutdown(s, how) shutdown((s), (how))
#define SET_BLOCKING(s) ioctlsocket(s, FIONBIO, &zero_value)
@@ -1277,17 +1277,14 @@ static char* send_msg(ErlNifEnv* env,
ERL_NIF_TERM msg,
ErlNifPid* pid);
-static BOOLEAN_T extract_item_on_load(ErlNifEnv* env,
- ERL_NIF_TERM map,
- ERL_NIF_TERM key,
- ERL_NIF_TERM* val);
-
static BOOLEAN_T extract_debug_on_load(ErlNifEnv* env,
- ERL_NIF_TERM map,
- BOOLEAN_T def);
+ ERL_NIF_TERM map);
static BOOLEAN_T extract_iow_on_load(ErlNifEnv* env,
- ERL_NIF_TERM map,
- BOOLEAN_T def);
+ ERL_NIF_TERM map);
+static BOOLEAN_T extract_bool(ErlNifEnv* env,
+ ERL_NIF_TERM map,
+ ERL_NIF_TERM ekey,
+ BOOLEAN_T def);
static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
@@ -1320,7 +1317,6 @@ static const struct in6_addr in6addr_loopback =
static char str_close[] = "close";
static char str_closed[] = "closed";
static char str_closing[] = "closing";
-static char str_debug[] = "debug";
static char str_false[] = "false";
static char str_global_counters[] = "global_counters";
static char str_in4_sockaddr[] = "in4_sockaddr";
@@ -1364,6 +1360,7 @@ static char str_exsend[] = "exsend"; // failed send
ERL_NIF_TERM esock_atom_addr;
ERL_NIF_TERM esock_atom_any;
ERL_NIF_TERM esock_atom_dgram;
+ERL_NIF_TERM esock_atom_debug;
ERL_NIF_TERM esock_atom_error;
ERL_NIF_TERM esock_atom_false;
ERL_NIF_TERM esock_atom_family;
@@ -1398,7 +1395,6 @@ ERL_NIF_TERM esock_atom_einval;
static ERL_NIF_TERM atom_close;
static ERL_NIF_TERM atom_closed;
static ERL_NIF_TERM atom_closing;
-static ERL_NIF_TERM atom_debug;
static ERL_NIF_TERM atom_false;
static ERL_NIF_TERM atom_global_counters;
static ERL_NIF_TERM atom_in4_sockaddr;
@@ -1471,6 +1467,8 @@ static SocketData data;
* nif_recvfrom(Sock, Flags)
* nif_close(Sock)
* nif_shutdown(Sock, How)
+ * nif_sockname(Sock)
+ * nif_peername(Sock)
*
* And some functions to manipulate and retrieve socket options:
* -------------------------------------------------------------
@@ -1540,7 +1538,7 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env,
numProtoIP, numProtoTCP, numProtoUDP, numProtoSCTP};
unsigned int lenGCnt = sizeof(gcnt) / sizeof(ERL_NIF_TERM);
ERL_NIF_TERM lgcnt = MKLA(env, gcnt, lenGCnt);
- ERL_NIF_TERM keys[] = {atom_debug, atom_iow, atom_global_counters};
+ ERL_NIF_TERM keys[] = {esock_atom_debug, atom_iow, atom_global_counters};
ERL_NIF_TERM vals[] = {BOOL2ATOM(data.dbg), BOOL2ATOM(data.iow), lgcnt};
ERL_NIF_TERM info;
unsigned int numKeys = sizeof(keys) / sizeof(ERL_NIF_TERM);
@@ -1647,7 +1645,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
SOCKET sock;
HANDLE event;
#ifdef HAVE_SETNS
- int current_ns;
+ int current_ns = 0;
#endif
SGDBG( ("SOCKET", "nopen -> entry with"
@@ -1666,6 +1664,8 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
if ((sock = sock_open(domain, type, protocol)) == INVALID_SOCKET)
return esock_make_error_errno(env, sock_errno());
+ SGDBG( ("SOCKET", "nopen -> open success: %d\r\n", sock) );
+
#ifdef HAVE_SETNS
if ((netns != NULL) &&
!restore_network_namespace(current_ns, sock, &save_errno))
@@ -1682,6 +1682,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env,
return esock_make_error_errno(env, save_errno);
}
+ SGDBG( ("SOCKET", "nopen -> event success: %d\r\n", event) );
SET_NONBLOCKING(sock);
@@ -1872,10 +1873,10 @@ ERL_NIF_TERM nif_bind(ErlNifEnv* env,
eSockAddr = argv[1];
SSDBG( descP,
- ("SOCKET", "nif_bind -> args:"
+ ("SOCKET", "nif_bind -> args when sock = %d:"
"\r\n Socket: %T"
"\r\n SockAddr: %T"
- "\r\n", argv[0], eSockAddr) );
+ "\r\n", descP->sock, argv[0], eSockAddr) );
/* Make sure we are ready
* Not sure how this would even happen, but...
@@ -3298,8 +3299,8 @@ ERL_NIF_TERM nfinalize_close(ErlNifEnv* env,
* Disable sends and/or receives on a socket.
*
* Arguments:
- * Socket (ref) - Points to the socket descriptor.
- * How - What will be shutdown.
+ * [0] Socket (ref) - Points to the socket descriptor.
+ * [1] How - What will be shutdown.
*/
static
@@ -5846,721 +5847,6 @@ ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env,
}
-/* *** decode_send_addr ***
- *
- * The rather odd thing about the 'toAddrP' (the **) is
- * because we need to be able to return a NULL pointer,
- * in the case of the dest address is the atom 'null'.
- * Its possible to call the sendto function with the
- * args NULL (address) and 0 (port number).
- *
- * This function whouls really have a char* return value
- * type!!
- */
-/*
-static
-char* decode_send_addr(ErlNifEnv* env,
- int domain,
- ERL_NIF_TERM addr,
- int port,
- SocketAddress** toAddrP,
- unsigned int* toAddrLenP)
-{
- if (IS_ATOM(env, addr)) {
- unsigned int len;
- char a[16]; // Just in case...
-
- / * The only acceptable value is the atom 'null' * /
-
- if (!(GET_ATOM_LEN(env, addr, &len) &&
- (len > 0) &&
- (len <= (sizeof("null")))))
- return ESOCK_STR_EINVAL;
-
- if (!GET_ATOM(env, addr, a, sizeof(a)))
- return ESOCK_STR_EINVAL;
-
- *toAddrP = NULL;
- if (strncmp(a, "null", len) == 0)
- return NULL;
- else
- return ESOCK_STR_EINVAL;
-
- } else if (IS_TUPLE(env, addr)) {
- / * We now know that the we have a proper address. * /
- return decode_send_addr_tuple(env, domain, addr, port,
- *toAddrP, toAddrLenP);
- } else {
- return ESOCK_STR_EINVAL;
- }
-}
-*/
-
-/*
-static
-char* decode_send_addr_tuple(ErlNifEnv* env,
- int domain,
- ERL_NIF_TERM addr,
- int port,
- SocketAddress* toAddrP,
- unsigned int* toAddrLenP)
-{
- / * We handle two different tuples:
- * - size 4 (INET)
- * - size 8 (INET6)
- * /
-
- const ERL_NIF_TERM* addrt;
- int addrtSz;
-
- if (!GET_TUPLE(env, addr, &addrtSz, &addrt))
- return ESOCK_STR_EINVAL; // PLACEHOLDER
-
- switch (domain) {
- case AF_INET:
- if (addrtSz != 4)
- return ESOCK_STR_EINVAL;
- break;
-
-#if defined(HAVE_IN6) && defined(AF_INET6)
- case AF_INET6:
- if (addrtSz != 8)
- return ESOCK_STR_EINVAL;
- break;
-#endif
-
- default:
- return str_eafnosupport;
- break;
- }
-
- return decode_address_tuple(env, domain,
- addrt, port,
- toAddrP, toAddrLenP);
-
-}
-*/
-
-
-/* Decode an in_sockaddr(). This is either a:
- * in4_sockaddr: #in4_sockaddr{} = 3 tuple =>
- * 1: The tag in4_sockaddr
- * 2: Port number (an integer())
- * 3: The address: any | loopback | ip4_address()
- * in6_sockaddr: #in6_sockaddr{} = 5 tuple =>
- * 1: The tag in6_sockaddr
- * 2: Port number: integer()
- * 3: The address: any | loopback | ip6_address()
- * 4: Flow info: integer()
- * 5: Scope Id: integer()
- *
- */
-/*
-static
-char* decode_in_sockaddr(ErlNifEnv* env,
- ERL_NIF_TERM eSockAddr,
- SocketAddress* sockAddrP,
- unsigned int* addrLenP)
-{
- const ERL_NIF_TERM* addrt;
- int addrtSz;
- char* result = NULL;
-
- if (!GET_TUPLE(env, eSockAddr, &addrtSz, &addrt))
- return ESOCK_STR_EINVAL;
-
- / *
- * We use the tuple size to figure out which
- * of the records this is.
- * /
- switch (addrtSz) {
- case 3:
- result = decode_in4_sockaddr(env, addrt, sockAddrP, addrLenP);
- break;
-
-#if defined(HAVE_IN6) && defined(AF_INET6)
- case 5:
- result = decode_in6_sockaddr(env, addrt, sockAddrP, addrLenP);
- break;
-#endif
-
- default:
- result = ESOCK_STR_EAFNOSUPPORT;
- break;
- }
-
- return result;
-}
-*/
-
-
-/* Decode an in4_sockaddr().
- * The first element should be the atom in4_sockaddr
- * The second, the port number integer .
- * The third and final, the ip4_address tuple.
- */
-/*
-static
-char* decode_in4_sockaddr(ErlNifEnv* env,
- const ERL_NIF_TERM* eIn4SockAddr,
- SocketAddress* sockAddrP,
- unsigned int* addrLenP)
-{
- int port;
-
- / * 1: Ensure that the tuple has the correct tag: in4_sockaddr * /
- if (COMPARE(atom_in4_sockaddr, eIn4SockAddr[0]) != 0)
- return ESOCK_STR_EINVAL;
-
- / * 2: Get the port number * /
- if (!GET_INT(env, eIn4SockAddr[1], &port))
- return ESOCK_STR_EINVAL;
-
- / * 3: Get the address.
- * It can either be the atoms: any | loopback,
- * or the IPv4 address tuple (size 4).
- * /
- if (IS_ATOM(env, eIn4SockAddr[2])) {
- return decode_in4_sockaddr_atomaddr(env, eIn4SockAddr[2], port,
- sockAddrP, addrLenP);
- } else if (IS_TUPLE(env, eIn4SockAddr[2])) {
- return decode_in4_sockaddr_addr(env, eIn4SockAddr[2], port,
- sockAddrP, addrLenP);
- } else {
- return ESOCK_STR_EINVAL;
- }
-}
-*/
-
-
-/*
-static
-char* decode_in4_sockaddr_atomaddr(ErlNifEnv* env,
- ERL_NIF_TERM eAddr,
- int port,
- SocketAddress* sockAddrP,
- unsigned int* addrLenP)
-{
- struct in_addr addr;
-
- if (COMPARE(esock_atom_loopback, eAddr) == 0) {
- addr.s_addr = sock_htonl(INADDR_LOOPBACK);
- } else if (COMPARE(esock_atom_any, eAddr) == 0) {
- addr.s_addr = sock_htonl(INADDR_ANY);
- } else {
- return ESOCK_STR_EINVAL;
- }
-
- sys_memzero((char*) sockAddrP, sizeof(struct sockaddr_in));
-#ifndef NO_SA_LEN
- sockAddrP->sai.sin_len = sizeof(struct sockaddr_in);
-#endif
- sockAddrP->in4.sin_family = AF_INET;
- sockAddrP->in4.sin_port = sock_htons(port);
- sockAddrP->in4.sin_addr.s_addr = addr.s_addr;
- *addrLenP = sizeof(struct sockaddr_in);
-
- return NULL;
-}
-*/
-
-
-/* Decode an in4_sockaddr where the address field is a tuple.
- * Its *supposed* to be an ip4_address (tuple).
- */
-/*
-static
-char* decode_in4_sockaddr_addr(ErlNifEnv* env,
- ERL_NIF_TERM eAddr,
- int port,
- SocketAddress* sockAddrP,
- unsigned int* addrLenP)
-{
- const ERL_NIF_TERM* ip4AddrT;
- int ip4AddrTSz;
- int a, v;
- char addr[4];
-
- / * This shall be a 4 tuple * /
- if (!GET_TUPLE(env, eAddr, &ip4AddrTSz, &ip4AddrT))
- return ESOCK_STR_EINVAL;
-
- if (ip4AddrTSz != 4)
- return ESOCK_STR_EINVAL;
-
- sys_memzero((char*)sockAddrP, sizeof(struct sockaddr_in));
-#ifndef NO_SA_LEN
- sockAddrP->in4.sin_len = sizeof(struct sockaddr_in);
-#endif
- sockAddrP->in4.sin_family = AF_INET;
- sockAddrP->in4.sin_port = sock_htons(port);
- for (a = 0; a < 4; a++) {
- if (!GET_INT(env, ip4AddrT[a], &v))
- return ESOCK_STR_EINVAL;
- addr[a] = v;
- }
- sys_memcpy(&sockAddrP->in4.sin_addr, &addr, sizeof(addr));
- *addrLenP = sizeof(struct sockaddr_in);
-
- return NULL;
-}
-*/
-
-
-
-/* Decode an in6_sockaddr().
- * The first element should be the atom in4_sockaddr
- * The second, the port number integer .
- * The third, the ip4_address tuple.
- * The forth, the flowinfo integer.
- * The fifth and final, the scope_id integer.
- */
-/*
-#if defined(HAVE_IN6) && defined(AF_INET6)
-static
-char* decode_in6_sockaddr(ErlNifEnv* env,
- const ERL_NIF_TERM* eIn6SockAddr,
- SocketAddress* sockAddrP,
- unsigned int* addrLenP)
-{
- int port;
- unsigned int flowInfo, scopeId;
-
- / * 1: Ensure that the tuple has the correct tag: in6_sockaddr * /
- if (COMPARE(atom_in6_sockaddr, eIn6SockAddr[0]) != 0)
- return ESOCK_STR_EINVAL;
-
- / * 2: Get the port number * /
- if (!GET_INT(env, eIn6SockAddr[1], &port))
- return ESOCK_STR_EINVAL;
-
- / * 4: Get the flowinfo * /
- if (!GET_UINT(env, eIn6SockAddr[3], &flowInfo))
- return ESOCK_STR_EINVAL;
-
- / * 5: Get the scope_id * /
- if (!GET_UINT(env, eIn6SockAddr[4], &scopeId))
- return ESOCK_STR_EINVAL;
-
- / * 3: Get the address.
- * It can either be the atoms: any | loopback,
- * or the IPv6 address tuple (size 8).
- * /
- if (IS_ATOM(env, eIn6SockAddr[2])) {
- return decode_in6_sockaddr_atomaddr(env, eIn6SockAddr[2], port,
- flowInfo, scopeId,
- sockAddrP, addrLenP);
- } else if (IS_TUPLE(env, eIn6SockAddr[2])) {
- return decode_in6_sockaddr_addr(env, eIn6SockAddr[2], port,
- flowInfo, scopeId,
- sockAddrP, addrLenP);
- } else {
- return ESOCK_STR_EINVAL;
- }
-}
-#endif
-*/
-
-
-/*
-#if defined(HAVE_IN6) && defined(AF_INET6)
-static
-char* decode_in6_sockaddr_atomaddr(ErlNifEnv* env,
- ERL_NIF_TERM eAddr,
- int port,
- unsigned int flowInfo,
- unsigned int scopeId,
- SocketAddress* sockAddrP,
- unsigned int* addrLenP)
-{
- const struct in6_addr* addr;
-
- if (COMPARE(esock_atom_loopback, eAddr) == 0) {
- addr = &in6addr_loopback;
- } else if (COMPARE(esock_atom_any, eAddr) == 0) {
- addr = &in6addr_any;
- } else {
- return ESOCK_STR_EINVAL;
- }
-
- sys_memzero((char*)sockAddrP, sizeof(struct sockaddr_in6));
-#ifndef NO_SA_LEN
- sockAddrP->in6.sin6_len = sizeof(struct sockaddr_in6);
-#endif
- sockAddrP->in6.sin6_family = AF_INET6;
- sockAddrP->in6.sin6_port = sock_htons(port);
- sockAddrP->in6.sin6_flowinfo = flowInfo;
- sockAddrP->in6.sin6_scope_id = scopeId;
- sockAddrP->in6.sin6_addr = *addr;
- *addrLenP = sizeof(struct sockaddr_in6);
-
- return NULL;
-}
-#endif
-*/
-
-
-
-#if defined(HAVE_IN6) && defined(AF_INET6)
-/* Decode an in6_sockaddr where the address field is a tuple */
-/*
-static
-char* decode_in6_sockaddr_addr(ErlNifEnv* env,
- ERL_NIF_TERM eAddr,
- int port,
- unsigned int flowInfo,
- unsigned int scopeId,
- SocketAddress* sockAddrP,
- unsigned int* addrLenP)
-{
- const ERL_NIF_TERM* ip6AddrT;
- int ip6AddrTSz;
- int a, v;
- char addr[16];
-
- / * This shall be a 8 tuple * /
- if (!GET_TUPLE(env, eAddr, &ip6AddrTSz, &ip6AddrT))
- return ESOCK_STR_EINVAL;
-
- if (ip6AddrTSz != 8)
- return ESOCK_STR_EINVAL;
-
- sys_memzero((char*)sockAddrP, sizeof(struct sockaddr_in6));
-#ifndef NO_SA_LEN
- sockAddrP->in6.sin6_len = sizeof(struct sockaddr_in6);
-#endif
- sockAddrP->in6.sin6_family = AF_INET6;
- sockAddrP->in6.sin6_port = sock_htons(port);
- sockAddrP->in6.sin6_flowinfo = flowInfo;
- sockAddrP->in6.sin6_scope_id = scopeId;
- / * The address tuple is of size 8
- * and each element is a two byte integer
- * /
- for (a = 0; a < 8; a++) {
- if (!GET_INT(env, ip6AddrT[a], &v))
- return ESOCK_STR_EINVAL;
- addr[a*2 ] = ((v >> 8) & 0xFF);
- addr[a*2+1] = (v & 0xFF);
- }
- sys_memcpy(&sockAddrP->in6.sin6_addr, &addr, sizeof(addr));
- *addrLenP = sizeof(struct sockaddr_in6);
-
- return NULL;
-}
-*/
-#endif
-
-
-/* Decode the 4- or 8-element address tuple
- * and initiate the socket address structure.
- */
-/*
-static
-char* decode_address_tuple(ErlNifEnv* env,
- int domain,
- const ERL_NIF_TERM* addrt,
- int port,
- SocketAddress* addrP,
- unsigned int* addrLenP)
-{
-
- / * We now *know* that the size of the tuple is correct,
- * so we don't need to check anything here, just unpack.
- * /
-
- switch (domain) {
- case AF_INET:
- {
- int a, v;
- char laddr[4];
-
- sys_memzero((char*)addrP, sizeof(struct sockaddr_in));
-#ifndef NO_SA_LEN
- addrP->sai.sin_len = sizeof(struct sockaddr_in);
-#endif
- addrP->sai.sin_family = domain;
- addrP->sai.sin_port = sock_htons(port);
- for (a = 0; a < 4; a++) {
- if (!GET_INT(env, addrt[a], &v))
- return ESOCK_STR_EINVAL;
- laddr[a] = v;
- }
- sys_memcpy(&addrP->sai.sin_addr, &laddr, sizeof(laddr));
- *addrLenP = sizeof(struct sockaddr_in);
- return NULL;
- }
- break;
-
-#if defined(HAVE_IN6) && defined(AF_INET6)
- case AF_INET6:
- {
- int a, v;
- char laddr[16];
-
- sys_memzero((char*)addrP, sizeof(struct sockaddr_in6));
-#ifndef NO_SA_LEN
- addrP->sai6.sin6_len = sizeof(struct sockaddr_in6);
-#endif
- addrP->sai6.sin6_family = domain;
- addrP->sai6.sin6_port = sock_htons(port);
- addrP->sai6.sin6_flowinfo = 0;
- / * The address tuple is of size 8
- * and each element is a two byte integer
- * /
- for (a = 0; a < 8; a++) {
- if (!GET_INT(env, addrt[a], &v))
- return ESOCK_STR_EINVAL;
- laddr[a*2 ] = ((v >> 8) & 0xFF);
- laddr[a*2+1] = (v & 0xFF);
- }
- sys_memcpy(&addrP->sai6.sin6_addr, &laddr, sizeof(laddr));
- *addrLenP = sizeof(struct sockaddr_in6);
- return NULL;
- }
- break;
-#endif
-
- } / * switch (domain) * /
-
- return ESOCK_STR_EAFNOSUPPORT;
-
-}
-*/
-
-/* Encode the 4- or 8-element address tuple from the socket address structure.
- *
- * This function is called when we have received a message. So, if we for some
- * reason fail to decode the address or parts of it, it makes more sense to
- * return with "undefined" for the values rather then fail completely (and not
- * deliver the received message).
- *
- * Returns two things (assuming the encode works):
- *
- * Domain: inet | inet6 | local
- * Source: {Address, Port} | string()
- *
- */
-/*
-static
-void encode_address(ErlNifEnv* env,
- SocketAddress* sockAddrP,
- unsigned int addrLen,
- ERL_NIF_TERM* domainT,
- ERL_NIF_TERM* sourceT)
-{
- short port;
-
- switch (sockAddrP->sa.sa_family) {
-
- / * +++ inet (IPv4) +++ * /
-
- case AF_INET:
- if (addrLen >= sizeof(struct sockaddr_in)) {
- ERL_NIF_TERM addrT, portT;
- unsigned int i;
- ERL_NIF_TERM at4[4];
- char* a4 = (char*) &sockAddrP->in4.sin_addr;
-
- port = sock_ntohs(sockAddrP->in4.sin_port);
- for (i = 0; i < 4; i++) {
- at4[i] = MKI(env, a4[i]);
- }
-
- *domainT = MKA(env, "inet"); // Shall we encode these? See decode
- addrT = MKT4(env, at4[0], at4[1], at4[2], at4[3]);
- portT = MKI(env, port);
- *sourceT = MKT2(env, addrT, portT);
- } else {
- *domainT = esock_atom_undefined;
- *sourceT = esock_atom_undefined;
- }
- break;
-
-
- / * +++ inet6 (IPv6) +++ * /
-
-#if defined(HAVE_IN6) && defined(AF_INET6)
- case AF_INET6:
- if (addrLen >= sizeof(struct sockaddr_in6)) {
- ERL_NIF_TERM addrT, portT;
- unsigned int i;
- ERL_NIF_TERM at6[8];
- char* a16 = (char*) &sockAddrP->in6.sin6_addr;
-
- port = sock_ntohs(sockAddrP->in6.sin6_port);
- / * The address tuple is of size 8
- * and each element is a two byte integer
- * /
- for (i = 0; i < 8; i++) {
- // at6[i] = MKI(env, get_int16(a16[i*2]));
- at6[i] = MKI(env, get_int16(a16 + i*2));
- }
-
- *domainT = MKA(env, "inet6"); // Shall we encode these? See decode
- addrT = MKT8(env,
- at6[0], at6[1], at6[2], at6[3],
- at6[4], at6[5], at6[6], at6[7]);
- portT = MKI(env, port);
- *sourceT = MKT2(env, addrT, portT);
- } else {
- *domainT = esock_atom_undefined;
- *sourceT = esock_atom_undefined;
- }
- break;
-#endif
-
- / * +++ local (Unix Domain Sockets) +++ * /
-
-#ifdef HAVE_SYS_UN_H
- case AF_UNIX:
- {
- size_t n, m;
-
- *domainT = MKA(env, "local");
- if (addrLen < offsetof(struct sockaddr_un, sun_path)) {
- *sourceT = esock_atom_undefined;
- } else {
- n = addrLen - offsetof(struct sockaddr_un, sun_path);
- if (255 < n) {
- *sourceT = esock_atom_undefined;
- } else {
- m = my_strnlen(sockAddrP->un.sun_path, n);
-#ifdef __linux__
- / * Assume that the address is a zero terminated string,
- * except when the first byte is \0 i.e the string length is 0,
- * then use the reported length instead.
- * This fix handles Linux's nonportable
- * abstract socket address extension.
- * /
- if (m == 0) {
- m = n;
- }
-#endif
-
- *sourceT = MKSL(env, sockAddrP->un.sun_path, m);
- }
- }
- }
- break;
-#endif
-
- default:
- *domainT = esock_atom_undefined;
- *sourceT = esock_atom_undefined;
- break;
-
- } / * switch (addrP->sa.sa_family) * /
-
-}
-*/
-
-
-/* Decode the address when its an atom.
- * Currently we only accept two atoms: 'any' and 'loopback'
- */
-/*
-static
-char* decode_address_atom(ErlNifEnv* env,
- int domain,
- char* addr,
- int addrLen,
- int port,
- SocketAddress* addrP,
- unsigned int* addrLenP)
-{
- BOOLEAN_T any;
-
- if (strncmp(addr, "any", addrLen) == 0) {
- any = TRUE;
- } if (strncmp(addr, "loopback", addrLen) == 0) {
- any = FALSE;
- } else {
- return ESOCK_STR_EINVAL;
- }
-
- / * If we get this far, we *know* its either 'any' or 'loopback' * /
-
- switch (domain) {
- case AF_INET:
- {
- struct in_addr addr;
- if (any) {
- addr.s_addr = sock_htonl(INADDR_ANY);
- } else {
- addr.s_addr = sock_htonl(INADDR_LOOPBACK);
- }
- sys_memzero((char*) addrP, sizeof(struct sockaddr_in));
-#ifndef NO_SA_LEN
- addrP->sai.sin_len = sizeof(struct sockaddr_in6);
-#endif
- addrP->sai.sin_family = domain;
- addrP->sai.sin_port = sock_htons(port);
- addrP->sai.sin_addr.s_addr = addr.s_addr;
- *addrLenP = sizeof(struct sockaddr_in);
- }
- break;
-
-#if defined(HAVE_IN6) && defined(AF_INET6)
- case AF_INET6:
- {
- const struct in6_addr* paddr;
- if (any) {
- paddr = &in6addr_any;
- } else {
- paddr = &in6addr_loopback;
- }
- sys_memzero((char*)addrP, sizeof(struct sockaddr_in6));
-#ifndef NO_SA_LEN
- addrP->sai6.sin6_len = sizeof(struct sockaddr_in6);
-#endif
- addrP->sai6.sin6_family = domain;
- addrP->sai6.sin6_port = sock_htons(port);
- addrP->sai6.sin6_flowinfo = 0;
- addrP->sai6.sin6_addr = *paddr;
- *addrLenP = sizeof(struct sockaddr_in6);
- }
- break;
-#endif
-
- default:
- return ESOCK_STR_EINVAL;
- break;
- }
-
- return NULL;
-}
-*/
-
-/*
-static
-BOOLEAN_T decode_bool(ErlNifEnv* env, ERL_NIF_TERM eVal, BOOLEAN_T* val)
-{
- unsigned int len;
- char b[16]; // Just in case...
-
- / * Verify that the value is actually an atom * /
- if (!IS_ATOM(env, eVal))
- return FALSE;
-
- / * Verify that the value is of acceptable length * /
- if (!(GET_ATOM_LEN(env, eVal, &len) &&
- (len > 0) &&
- (len <= sizeof("false"))))
- return FALSE;
-
- / * And finally try to extract the value * /
- if (!GET_ATOM(env, eVal, b, sizeof(b)))
- return FALSE;
-
- if (strncmp(b, "true", len) == 0)
- *val = TRUE;
- else
- *val = FALSE;
-
- return TRUE;
-}
-*/
-
/* +++ decode the linger value +++
* The (socket) linger option is provided as a two tuple:
@@ -8055,88 +7341,40 @@ ErlNifFunc socket_funcs[] =
static
-BOOLEAN_T extract_item_on_load(ErlNifEnv* env,
- ERL_NIF_TERM map,
- ERL_NIF_TERM key,
- ERL_NIF_TERM* val)
+BOOLEAN_T extract_debug_on_load(ErlNifEnv* env,
+ ERL_NIF_TERM map)
{
- if (!enif_is_map(env, map))
- return FALSE;
-
- if (!GET_MAP_VAL(env, map, key, val))
- return FALSE;
-
- return TRUE;
+ return extract_bool(env, map, esock_atom_debug, SOCKET_NIF_DEBUG_DEFAULT);
}
static
-BOOLEAN_T extract_debug_on_load(ErlNifEnv* env, ERL_NIF_TERM map, BOOLEAN_T def)
+BOOLEAN_T extract_iow_on_load(ErlNifEnv* env,
+ ERL_NIF_TERM map)
{
- ERL_NIF_TERM dbgKey = enif_make_atom(env, "debug");
- ERL_NIF_TERM dbgVal;
- unsigned int len;
- char d[16]; // Just in case...
-
- /* Extra the value of the debug property */
- if (!extract_item_on_load(env, map, dbgKey, &dbgVal))
- return def;
+ return extract_bool(env, map, atom_iow, SOCKET_NIF_IOW_DEFAULT);
+}
- /* Verify that the value is actually an atom */
- if (!enif_is_atom(env, dbgVal))
- return def;
+static
+BOOLEAN_T extract_bool(ErlNifEnv* env,
+ ERL_NIF_TERM map,
+ ERL_NIF_TERM ekey,
+ BOOLEAN_T def)
+{
+ ERL_NIF_TERM eval;
- /* Verify that the value is of acceptable length */
- if (!(GET_ATOM_LEN(env, dbgVal, &len) &&
- (len > 0) &&
- (len <= sizeof("false"))))
+ if (!GET_MAP_VAL(env, map, ekey, &eval))
return def;
- /* And finally try to extract the value */
- if (!GET_ATOM(env, dbgVal, d, sizeof(d)))
+ if (!IS_ATOM(env, eval))
return def;
- if (strncmp(d, "true", len) == 0)
+ if (COMPARE(eval, esock_atom_true) == 0)
return TRUE;
else
return FALSE;
-
}
-static
-BOOLEAN_T extract_iow_on_load(ErlNifEnv* env, ERL_NIF_TERM map, BOOLEAN_T def)
-{
- ERL_NIF_TERM iowKey = enif_make_atom(env, "iow");
- ERL_NIF_TERM iowVal;
- unsigned int len;
- char b[16]; // Just in case...
-
- /* Extra the value of the debug property */
- if (!extract_item_on_load(env, map, iowKey, &iowVal))
- return def;
-
- /* Verify that the value is actually an atom */
- if (!enif_is_atom(env, iowVal))
- return def;
-
- /* Verify that the value is of acceptable length */
- if (!(GET_ATOM_LEN(env, iowVal, &len) &&
- (len > 0) &&
- (len <= sizeof("false"))))
- return def;
-
- /* And finally try to extract the value */
- if (!GET_ATOM(env, iowVal, b, sizeof(b)))
- return def;
-
- if (strncmp(b, "true", len) == 0)
- return TRUE;
- else
- return FALSE;
-
- }
-
-
/* =======================================================================
* load_info - A map of misc info (e.g global debug)
@@ -8145,10 +7383,8 @@ BOOLEAN_T extract_iow_on_load(ErlNifEnv* env, ERL_NIF_TERM map, BOOLEAN_T def)
static
int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
- data.dbg = extract_debug_on_load(env, load_info,
- SOCKET_NIF_DEBUG_DEFAULT);
- data.iow = extract_iow_on_load(env, load_info,
- SOCKET_NIF_IOW_DEFAULT);
+ data.dbg = extract_debug_on_load(env, load_info);
+ data.iow = extract_iow_on_load(env, load_info);
/* +++ Global Counters +++ */
data.cntMtx = MCREATE("socket[gcnt]");
@@ -8168,7 +7404,6 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
atom_close = MKA(env, str_close);
atom_closed = MKA(env, str_closed);
atom_closing = MKA(env, str_closing);
- atom_debug = MKA(env, str_debug);
atom_false = MKA(env, str_false);
atom_global_counters = MKA(env, str_global_counters);
atom_in4_sockaddr = MKA(env, str_in4_sockaddr);
@@ -8193,6 +7428,7 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
/* Global atom(s) */
esock_atom_addr = MKA(env, "addr");
esock_atom_any = MKA(env, "any");
+ esock_atom_debug = MKA(env, "debug");
esock_atom_dgram = MKA(env, "dgram");
esock_atom_error = MKA(env, "error");
esock_atom_false = MKA(env, "false");
diff --git a/erts/preloaded/ebin/net.beam b/erts/preloaded/ebin/net.beam
index c3d043edfa..b52fa01b07 100644
--- a/erts/preloaded/ebin/net.beam
+++ b/erts/preloaded/ebin/net.beam
Binary files differ
diff --git a/erts/preloaded/src/net.erl b/erts/preloaded/src/net.erl
index 6abfc22d3f..01b12696e9 100644
--- a/erts/preloaded/src/net.erl
+++ b/erts/preloaded/src/net.erl
@@ -69,17 +69,10 @@
idna_use_std3_ascii_rules.
-type name_info() :: #{host := string(),
service := string()}.
-%% -record(name_info, {host, service}).
-%% -type name_info() :: #name_info{}.
-type address_info() :: #{family := socket:domain(),
socktype := socket:type(),
protocol := socket:protocol(),
address := socket:sockaddr()}.
-%% -record(address_info, {family :: socket:domain(),
-%% socktype :: socket:type(),
-%% protocol :: socket:protocol(),
-%% addr :: undefined | socket:in_sockaddr() | string()}).
-%% -type address_info() :: #address_info{}.
-type network_interface_name() :: string().
-type network_interface_index() :: non_neg_integer().
@@ -218,6 +211,11 @@ getaddrinfo(Host) when is_list(Host) ->
; (undefined, Service) -> {ok, Info} | {error, Reason} when
Service :: string(),
Info :: [address_info()],
+ Reason :: term()
+ ; (Host, Service) -> {ok, Info} | {error, Reason} when
+ Host :: string(),
+ Service :: string(),
+ Info :: [address_info()],
Reason :: term().
getaddrinfo(Host, Service)
@@ -236,8 +234,8 @@ getaddrinfo(Host, Service)
%%
-spec if_name2index(Name) -> {ok, Idx} | {error, Reason} when
- Name :: string(),
- Idx :: non_neg_integer(),
+ Name :: network_interface_name(),
+ Idx :: network_interface_index(),
Reason :: term().
if_name2index(If) when is_list(If) ->
@@ -247,14 +245,14 @@ if_name2index(If) when is_list(If) ->
%% ===========================================================================
%%
-%% if_index2name - Mappings between network interface names and indexes:
+%% if_index2name - Mappings between network interface index and names:
%% idx -> name
%%
%%
-spec if_index2name(Idx) -> {ok, Name} | {error, Reason} when
- Idx :: non_neg_integer(),
- Name :: string(),
+ Idx :: network_interface_index(),
+ Name :: network_interface_name(),
Reason :: term().
if_index2name(Idx) when is_integer(Idx) ->
@@ -270,8 +268,8 @@ if_index2name(Idx) when is_integer(Idx) ->
-spec if_names() -> Names | {error, Reason} when
Names :: [{Idx, If}],
- Idx :: non_neg_integer(),
- If :: string(),
+ Idx :: network_interface_index(),
+ If :: network_interface_name(),
Reason :: term().
if_names() ->