diff options
author | Micael Karlberg <[email protected]> | 2018-06-19 12:20:21 +0200 |
---|---|---|
committer | Micael Karlberg <[email protected]> | 2018-09-18 14:50:18 +0200 |
commit | 44cfb3d222ba4d20607af7cc654746f84ece3989 (patch) | |
tree | 8613e0736320ce8ea8a015b88d06194ffb91f1fe | |
parent | 1952754950f371f43ed4dd675a42c60b3d166bd7 (diff) | |
download | otp-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
-rw-r--r-- | erts/doc/src/Makefile | 6 | ||||
-rw-r--r-- | erts/doc/src/net.xml | 126 | ||||
-rw-r--r-- | erts/doc/src/ref_man.xml | 1 | ||||
-rw-r--r-- | erts/doc/src/specs.xml | 1 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_int.h | 1 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 870 | ||||
-rw-r--r-- | erts/preloaded/ebin/net.beam | bin | 5928 -> 6036 bytes | |||
-rw-r--r-- | erts/preloaded/src/net.erl | 26 |
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 Binary files differindex c3d043edfa..b52fa01b07 100644 --- a/erts/preloaded/ebin/net.beam +++ b/erts/preloaded/ebin/net.beam 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() -> |