From 6b2c750c53a288d999c0f63dc6fe26a22d63ed00 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 29 May 2018 10:54:55 +0200 Subject: [net-nif] Added preliminary net nif file OTP-14831 --- erts/emulator/nifs/common/net_nif.c | 1788 +++++++++++++++++++++++++++++++++++ 1 file changed, 1788 insertions(+) create mode 100644 erts/emulator/nifs/common/net_nif.c (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c new file mode 100644 index 0000000000..b8fa6628a7 --- /dev/null +++ b/erts/emulator/nifs/common/net_nif.c @@ -0,0 +1,1788 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2018-2018. 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. + * + * %CopyrightEnd% + * + * ---------------------------------------------------------------------- + * Purpose : The NIF (C) part of the net interface + * This is a module of miscellaneous functions. + * ---------------------------------------------------------------------- + * + */ + +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ +/* #include */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* If we HAVE_SCTP_H and Solaris, we need to define the following in + * order to get SCTP working: + */ +#if (defined(HAVE_SCTP_H) && defined(__sun) && defined(__SVR4)) +#define SOLARIS10 1 +/* WARNING: This is not quite correct, it may also be Solaris 11! */ +#define _XPG4_2 +#define __EXTENSIONS__ +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#ifdef HAVE_NET_IF_DL_H +#include +#endif + +#ifdef HAVE_IFADDRS_H +#include +#endif + +#ifdef HAVE_NETPACKET_PACKET_H +#include +#endif + +#ifdef HAVE_SYS_UN_H +#include +#endif + +/* SENDFILE STUFF HERE IF WE NEED IT... */ + +#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__) +#define __DARWIN__ 1 +#endif + + +#ifdef __WIN32__ +#define STRNCASECMP strncasecmp +#define INCL_WINSOCK_API_TYPEDEFS 1 + +#ifndef WINDOWS_H_INCLUDES_WINSOCK2_H +#include +#endif +#include +#include /* NEED VC 6.0 or higher */ + +/* Visual studio 2008+: NTDDI_VERSION needs to be set for iphlpapi.h + * to define the right structures. It needs to be set to WINXP (or LONGHORN) + * for IPV6 to work and it's set lower by default, so we need to change it. + */ +#ifdef HAVE_SDKDDKVER_H +# include +# ifdef NTDDI_VERSION +# undef NTDDI_VERSION +# endif +# define NTDDI_VERSION NTDDI_WINXP +#endif +#include + +#undef WANT_NONBLOCKING +#include "sys.h" + +#else /* !__WIN32__ */ + +#include +#ifdef NETDB_H_NEEDS_IN_H +#include +#endif +#include + +#include +#include + +#ifdef DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H +#include +#endif + +#include +#include +#include + +#include +#ifdef HAVE_ARPA_NAMESER_H +#include +#endif + +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#include + +#ifdef HAVE_SCHED_H +#include +#endif + +#ifdef HAVE_SETNS_H +#include +#endif + +#define HAVE_UDP + +#ifndef WANT_NONBLOCKING +#define WANT_NONBLOCKING +#endif +#include "sys.h" + +#endif + +#include + + +/* All platforms fail on malloc errors. */ +#define FATAL_MALLOC + + + +/* *** Boolean *type* stuff... *** */ +typedef unsigned int BOOLEAN_T; +#define TRUE 1 +#define FALSE 0 +#define BOOL2STR(__B__) ((__B__) ? "true" : "false") +#define BOOL2ATOM(__B__) ((__B__) ? atom_true : atom_false) + +/* Two byte integer decoding */ +#define get_int16(s) ((((unsigned char*) (s))[0] << 8) | \ + (((unsigned char*) (s))[1])) + +#define SASSERT(e) \ + ((void) ((e) ? 1 : (xabort(#e, __func__, __FILE__, __LINE__), 0))) + + +/* Debug stuff... */ +#define SOCKET_NIF_DEBUG_DEFAULT TRUE + +/* Various defaults... */ +#define SOCKET_DEBUG_DEFAULT TRUE +#define SOCKET_IOW_DEFAULT FALSE + +/* Counters and stuff (Don't know where to sent this stuff anyway) */ +#define SOCKET_NIF_IOW_DEFAULT FALSE + + +/* Used in debug printouts */ +#ifdef __WIN32__ +#define LLU "%I64u" +#else +#define LLU "%llu" +#endif +typedef unsigned long long llu_t; + + + +/* Socket stuff */ +// #define INVALID_SOCKET -1 +// #define INVALID_EVENT -1 +// #define SOCKET_ERROR -1 + +// #define SOCKET int +// #define HANDLE long int + + +/* *** Misc macros and defines *** */ + +#ifdef __WIN32__ +#define get_errno() WSAGetLastError() +#else +#define get_errno() errno +#endif + +// #if defined(TCP_CA_NAME_MAX) +// #define SOCKET_OPT_TCP_CONGESTION_NAME_MAX TCP_CA_NAME_MAX +// #else +/* This is really excessive, but just in case... */ +// #define SOCKET_OPT_TCP_CONGESTION_NAME_MAX 256 +// #endif + +#define HOSTNAME_LEN 256 +#define SERVICE_LEN 256 + + +/* =================================================================== * + * * + * Various enif macros * + * * + * =================================================================== */ + +#define MALLOC(SZ) enif_alloc((SZ)) +#define FREE(P) enif_free((P)) + +#define MKA(E,S) enif_make_atom((E), (S)) +#define MKBIN(E,B) enif_make_binary((E), (B)) +#define MKI(E,I) enif_make_int((E), (I)) +#define MKLA(E,A,L) enif_make_list_from_array((E), (A), (L)) +#define MKEL(E) enif_make_list((E), 0) +#define MKREF(E) enif_make_ref((E)) +#define MKS(E,S) enif_make_string((E), (S), ERL_NIF_LATIN1) +#define MKSL(E,S,L) enif_make_string_len((E), (S), (L), ERL_NIF_LATIN1) +#define MKSBIN(E,B,ST,SZ) enif_make_sub_binary((E), (B), (ST), (SZ)) +#define MKT2(E,E1,E2) enif_make_tuple2((E), (E1), (E2)) +#define MKT3(E,E1,E2,E3) enif_make_tuple3((E), (E1), (E2), (E3)) +#define MKT4(E,E1,E2,E3,E4) enif_make_tuple4((E), (E1), (E2), (E3), (E4)) +#define MKT8(E,E1,E2,E3,E4,E5,E6,E7,E8) \ + enif_make_tuple8((E), (E1), (E2), (E3), (E4), (E5), (E6), (E7), (E8)) + +#define MCREATE(N) enif_mutex_create((N)) +#define MDESTROY(M) enif_mutex_destroy((M)) +#define MLOCK(M) enif_mutex_lock((M)) +#define MUNLOCK(M) enif_mutex_unlock((M)) + +#define MONP(E,D,P,M) enif_monitor_process((E), (D), (P), (M)) +#define DEMONP(E,D,M) enif_demonitor_process((E), (D), (M)) + +#define SELECT(E,FD,M,O,P,R) \ + enif_select((E), (FD), (M), (O), (P), (R)) +#define SELECT_READ(E, DP, P, R) \ + SELECT((E), (DP)->sock, (ERL_NIF_SELECT_READ), (DP), (P), (R)) +#define SELECT_WRITE(E, DP, P, R) \ + SELECT((E), (DP)->sock, (ERL_NIF_SELECT_WRITE), (DP), (P), (R)) +#define SELECT_STOP(E, DP) \ + enif_select((E), (DP)->sock, (ERL_NIF_SELECT_STOP), (DP), NULL, atom_undefined) + +#define IS_ATOM(E, TE) enif_is_atom((E), (TE)) +#define IS_BIN(E, TE) enif_is_binary((E), (TE)) +#define IS_NUM(E, TE) enif_is_number((E), (TE)) +#define IS_TUPLE(E, TE) enif_is_tuple((E), (TE)) +#define IS_LIST(E, TE) enif_is_list((E), (TE)) + +#define COMPARE(L, R) enif_compare((L), (R)) + +#define GET_ATOM_LEN(E, TE, LP) \ + enif_get_atom_length((E), (TE), (LP), ERL_NIF_LATIN1) +#define GET_ATOM(E, TE, BP, MAX) \ + enif_get_atom((E), (TE), (BP), (MAX), ERL_NIF_LATIN1) +#define GET_BIN(E, TE, BP) enif_inspect_iolist_as_binary((E), (TE), (BP)) +#define GET_INT(E, TE, IP) enif_get_int((E), (TE), (IP)) +#define GET_LIST_ELEM(E, L, HP, TP) enif_get_list_cell((E), (L), (HP), (TP)) +#define GET_LIST_LEN(E, L, LP) enif_get_list_length((E), (L), (LP)) +#define GET_STR(E, L, B, SZ) \ + enif_get_string((E), (L), (B), (SZ), ERL_NIF_LATIN1) +#define GET_UINT(E, TE, IP) enif_get_uint((E), (TE), (IP)) +#define GET_TUPLE(E, TE, TSZ, TA) enif_get_tuple((E), (TE), (TSZ), (TA)) + +#define ALLOC_BIN(SZ, BP) enif_alloc_binary((SZ), (BP)) +#define REALLOC_BIN(SZ, BP) enif_realloc_binary((SZ), (BP)) + + +#ifdef HAVE_SOCKLEN_T +# define SOCKLEN_T socklen_t +#else +# define SOCKLEN_T size_t +#endif + + +/* The general purpose socket address */ +typedef union { + struct sockaddr sa; + + struct sockaddr_in in; + +#ifdef HAVE_IN6 + struct sockaddr_in6 in6; +#endif + +} SockAddress; + + + +/* ---------------------------------------------------------------------- + * F o r w a r d s + * ---------------------------------------------------------------------- + */ + +/* THIS IS JUST TEMPORARY */ +extern char* erl_errno_id(int error); + + +static ERL_NIF_TERM nif_is_loaded(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM nif_info(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]); + +static ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]); + +static ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]); + +static ERL_NIF_TERM nif_if_name2index(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM nif_if_index2name(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM nif_if_names(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]); + +static ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, + const SockAddress* saP, + socklen_t saLen, + int flags); +static ERL_NIF_TERM nif_name2index(ErlNifEnv* env, + char* ifn); +static ERL_NIF_TERM nif_index2name(ErlNifEnv* env, + unsigned int id); +static ERL_NIF_TERM nif_names(ErlNifEnv* env); +static unsigned int nif_names_length(struct if_nameindex* p); + +/* +static void net_dtor(ErlNifEnv* env, void* obj); +static void net_stop(ErlNifEnv* env, + void* obj, + int fd, + int is_direct_call); +static void net_down(ErlNifEnv* env, + void* obj, + const ErlNifPid* pid, + const ErlNifMonitor* mon); +*/ +static BOOLEAN_T decode_in_sockaddr(ErlNifEnv* env, + const ERL_NIF_TERM eAddr, + SockAddress* saP, + socklen_t* saLen); +static BOOLEAN_T decode_in4_sockaddr(ErlNifEnv* env, + const ERL_NIF_TERM* addrt, + SockAddress* saP, + socklen_t* saLen); +#if defined(HAVE_IN6) && defined(AF_INET6) +static BOOLEAN_T decode_in6_sockaddr(ErlNifEnv* env, + const ERL_NIF_TERM* addrt, + SockAddress* saP, + socklen_t* saLen); +#endif +static BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env, + const ERL_NIF_TERM eflags, + int* flags); +static BOOLEAN_T decode_nameinfo_flags_list(ErlNifEnv* env, + const ERL_NIF_TERM eflags, + int* flags); +static ERL_NIF_TERM encode_address_info(ErlNifEnv* env, + struct addrinfo* addrInfo); +static unsigned int address_info_length(struct addrinfo* addrInfoP); + +static ERL_NIF_TERM make_ok2(ErlNifEnv* env, ERL_NIF_TERM val); +// static ERL_NIF_TERM make_ok3(ErlNifEnv* env, ERL_NIF_TERM val1, ERL_NIF_TERM val2); +static ERL_NIF_TERM make_error(ErlNifEnv* env, ERL_NIF_TERM reason); +static ERL_NIF_TERM make_error1(ErlNifEnv* env, char* reason); +static ERL_NIF_TERM make_error2(ErlNifEnv* env, int err); + +/* +static void xabort(const char* expr, + const char* func, + const char* file, + int line); +*/ + +static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); + + +#if HAVE_IN6 +# if ! defined(HAVE_IN6ADDR_ANY) || ! HAVE_IN6ADDR_ANY +# if HAVE_DECL_IN6ADDR_ANY_INIT +static const struct in6_addr in6addr_any = { { IN6ADDR_ANY_INIT } }; +# else +static const struct in6_addr in6addr_any = + { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }; +# endif /* HAVE_IN6ADDR_ANY_INIT */ +# endif /* ! HAVE_DECL_IN6ADDR_ANY */ + +# if ! defined(HAVE_IN6ADDR_LOOPBACK) || ! HAVE_IN6ADDR_LOOPBACK +# if HAVE_DECL_IN6ADDR_LOOPBACK_INIT +static const struct in6_addr in6addr_loopback = + { { IN6ADDR_LOOPBACK_INIT } }; +# else +static const struct in6_addr in6addr_loopback = + { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }; +# endif /* HAVE_IN6ADDR_LOOPBACk_INIT */ +# endif /* ! HAVE_DECL_IN6ADDR_LOOPBACK */ +#endif /* HAVE_IN6 */ + + + +/* *** String constants *** */ +static char str_dgram[] = "dgram"; +static char str_error[] = "error"; +static char str_idn[] = "idn"; +static char str_idna_allow_unassigned[] = "idna_allow_unassigned"; +static char str_idna_use_std3_ascii_rules[] = "idna_use_std3_ascii_rules"; +static char str_namereqd[] = "namereqd"; +static char str_name_info[] = "name_info"; +static char str_nofqdn[] = "nofqdn"; +static char str_numerichost[] = "numerichost"; +static char str_numericserv[] = "numericserv"; +static char str_ok[] = "ok"; +static char str_true[] = "true"; +static char str_undefined[] = "undefined"; + +// static char str_lowdelay[] = "lowdelay"; +// static char str_throughput[] = "throughput"; +// static char str_reliability[] = "reliability"; +// static char str_mincost[] = "mincost"; + +/* (special) error string constants */ +// static char str_eafnosupport[] = "eafnosupport"; +static char str_eagain[] = "eagain"; +static char str_ebadflags[] = "ebadflags"; +static char str_efail[] = "efail"; +static char str_efamily[] = "efamily"; +static char str_einval[] = "einval"; +// static char str_eisconn[] = "eisconn"; +static char str_emem[] = "emem"; +static char str_enoname[] = "enoname"; +// static char str_enotclosing[] = "enotclosing"; +// static char str_enotconn[] = "enotconn"; +static char str_eoverflow[] = "eoverflow"; +// static char str_exalloc[] = "exalloc"; +// static char str_exbadstate[] = "exbadstate"; +// static char str_exbusy[] = "exbusy"; +// static char str_exmon[] = "exmonitor"; // failed monitor +// static char str_exself[] = "exself"; // failed self +// static char str_exsend[] = "exsend"; // failed send + + +/* *** Atoms *** */ + +static ERL_NIF_TERM atom_error; +static ERL_NIF_TERM atom_dgram; +static ERL_NIF_TERM atom_idn; +static ERL_NIF_TERM atom_idna_allow_unassigned; +static ERL_NIF_TERM atom_idna_use_std3_ascii_rules; +static ERL_NIF_TERM atom_namereqd; +static ERL_NIF_TERM atom_name_info; +static ERL_NIF_TERM atom_nofqdn; +static ERL_NIF_TERM atom_numerichost; +static ERL_NIF_TERM atom_numericserv; +static ERL_NIF_TERM atom_ok; +// static ERL_NIF_TERM atom_select; +// static ERL_NIF_TERM atom_timeout; +static ERL_NIF_TERM atom_true; +static ERL_NIF_TERM atom_undefined; + +// static ERL_NIF_TERM atom_lowdelay; +// static ERL_NIF_TERM atom_throughput; +// static ERL_NIF_TERM atom_reliability; +// static ERL_NIF_TERM atom_mincost; + +// static ERL_NIF_TERM atom_eafnosupport; +static ERL_NIF_TERM atom_eagain; +static ERL_NIF_TERM atom_ebadflags; +static ERL_NIF_TERM atom_efail; +static ERL_NIF_TERM atom_efamily; +static ERL_NIF_TERM atom_einval; +// static ERL_NIF_TERM atom_eisconn; +static ERL_NIF_TERM atom_emem; +static ERL_NIF_TERM atom_enoname; +// static ERL_NIF_TERM atom_enotclosing; +// static ERL_NIF_TERM atom_enotconn; +static ERL_NIF_TERM atom_eoverflow; +// static ERL_NIF_TERM atom_exalloc; +// static ERL_NIF_TERM atom_exbadstate; +// static ERL_NIF_TERM atom_exbusy; +// static ERL_NIF_TERM atom_exmon; +// static ERL_NIF_TERM atom_exself; +// static ERL_NIF_TERM atom_exsend; + +/* *** net *** */ +static ErlNifResourceType* net; +/* Maybe all of these whould be NULL? */ +static ErlNifResourceTypeInit netInit = { + NULL, // net_dtor, + NULL, // net_stop, + NULL // (ErlNifResourceDown*) net_down +}; + + + +/* ---------------------------------------------------------------------- + * N I F F u n c t i o n s + * ---------------------------------------------------------------------- + * + * Utility and admin functions: + * ---------------------------- + * nif_is_loaded/0 + * nif_info/0 + * + * The "proper" net functions: + * ------------------------------ + * nif_getnameinfo/2 + * nif_getaddrinfo/3 + * nif_if_name2index/1 + * nif_if_index2name/1 + * nif_if_names/0 + * + */ + + +/* ---------------------------------------------------------------------- + * nif_is_loaded + * + * Description: + * This functions only purpose is to return the atom 'true'. + * This will happen *if* the (socket) nif library is loaded. + * If its not, the erlang (nif_is_loaded) will instead return + * 'false'. + */ +static +ERL_NIF_TERM nif_is_loaded(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + if (argc != 0) + return enif_make_badarg(env); + + return atom_true; +} + + +/* ---------------------------------------------------------------------- + * nif_info + * + * Description: + * This is currently just a placeholder... + */ +static +ERL_NIF_TERM nif_info(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM info = enif_make_new_map(env); + return info; +} + + + +/* ---------------------------------------------------------------------- + * nif_getnameinfo + * + * Description: + * Address-to-name translation in protocol-independent manner. + * + * Arguments: + * SockAddr - Socket Address (address and port) + * Flags - The flags argument modifies the behavior of getnameinfo(). + * Not used! + */ + +static +ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM eSockAddr; + unsigned int eFlags; + int flags = 0; // Just in case... + SockAddress sa; + socklen_t saLen = 0; // Just in case... + + if ((argc != 2) || + !GET_UINT(env, argv[1], &eFlags)) { + return enif_make_badarg(env); + } + eSockAddr = argv[0]; + + if (!decode_nameinfo_flags(env, eFlags, &flags)) + return enif_make_badarg(env); + + if (decode_in_sockaddr(env, eSockAddr, &sa, &saLen)) + return enif_make_badarg(env); + + return ngetnameinfo(env, &sa, saLen, flags); +} + + + +/* Given the provided sock(et) address (and honts), retreive the host and + * service info. + */ +static +ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, + const SockAddress* saP, + socklen_t saLen, + int flags) +{ + ERL_NIF_TERM result; + char host[HOSTNAME_LEN]; + socklen_t hostLen = sizeof(host); + char serv[SERVICE_LEN]; + socklen_t servLen = sizeof(serv); + + int res = getnameinfo((struct sockaddr*) saP, saLen, + host, hostLen, + serv, servLen, + flags); + + switch (res) { + case 0: + { + ERL_NIF_TERM info = MKT3(env, + atom_name_info, + MKS(env, host), + MKS(env, serv)); + result = make_ok2(env, info); + } + break; + + case EAI_AGAIN: + result = make_error(env, atom_eagain); + break; + + case EAI_BADFLAGS: + result = make_error(env, atom_ebadflags); + break; + + case EAI_FAIL: + result = make_error(env, atom_efail); + break; + + case EAI_FAMILY: + result = make_error(env, atom_efamily); + break; + + case EAI_MEMORY: + result = make_error(env, atom_emem); + break; + + case EAI_NONAME: + result = make_error(env, atom_enoname); + break; + + case EAI_OVERFLOW: + result = make_error(env, atom_eoverflow); + break; + + case EAI_SYSTEM: + result = make_error2(env, get_errno()); + break; + + default: + result = make_error(env, atom_einval); + break; + } + + return result; +} + + + +/* ---------------------------------------------------------------------- + * nif_getaddrinfo + * + * Description: + * Network address and service translation. + * + * Arguments: + * Host - Host name (either a string or the atom undefined) + * Service - Service name (either a string or the atom undefined) + * Hints - Hints for the lookup (address info record) (currently *ignored*) + */ + +static +ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM result; + char* hostName; + char* servName; + // struct addrinfo* hints; + + if (argc != 3) { + return enif_make_badarg(env); + } + eHostName = argv[0]; + eServName = argv[1]; + eHints = argv[2]; + + if (!decode_addrinfo_string(env, eHostName, &hostName)) + return enif_make_badarg(env); + + if (!decode_addrinfo_string(env, eServName, &servName)) + return enif_make_badarg(env); + + /* + if (decode_addrinfo_hints(env, eHints, &hints)) + return enif_make_badarg(env); + */ + + if ((hostName == NULL) && (servName == NULL)) + return enif_make_badarg(env); + + result = ngetaddrinfo(env, hostName, servName); + + if (hostName != NULL) + FREE(hostName); + + if (servName != NULL) + FREE(servName); + + /* + if (hints != NULL) + FREE(hints); + */ + + return result; +} + + +static +ERL_NIF_TERM nifgetaddrinfo(ErlNifEnv* env, + char* host, + char* serv) +{ + struct addrinfo* addrInfoP; + int res; + + res = getaddrinfo(host, serv, NULL, &addrInfoP); + + switch (res) { + case 0: + { + ERL_NIF_TERM addrInfo = encode_address_info(env, addrInfoP); + freeaddrinfo(addrInfoP); + result = make_ok2(env, addrInfo); + } + break; + + case EAI_ADDRFAMILY: + result = make_error(env, atom_eaddrfamily); + break; + + case EAI_AGAIN: + result = make_error(env, atom_eagain); + break; + + case EAI_BADFLAGS: + result = make_error(env, atom_ebadflags); + break; + + case EAI_FAIL: + result = make_error(env, atom_efail); + break; + + case EAI_FAMILY: + result = make_error(env, atom_efamily); + break; + + case EAI_MEMORY: + result = make_error(env, atom_emem); + break; + + case EAI_NODATA: + result = make_error(env, atom_enodata); + break; + + case EAI_NONAME: + result = make_error(env, atom_enoname); + break; + + case EAI_SERCVICE: + result = make_error(env, atom_eservice); + break; + + case EAI_SOCKTYPE: + result = make_error(env, atom_esocktype); + break; + + case EAI_SYSTEM: + result = make_error(env, atom_esystem); + break; + + default: + result = make_error(env, atom_einval); + break; + } + + return result; +} + + +/* ---------------------------------------------------------------------- + * nif_if_name2index + * + * Description: + * Perform a Interface Name to Interface Index translation. + * + * Arguments: + * Ifn - Interface name to be translated. + */ + +static +ERL_NIF_TERM nif_if_name2index(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM eifn; + char ifn[IF_NAMESIZE+1]; + + if (argc != 1) { + return enif_make_badarg(env); + } + eifn = argv[0]; + + if (0 >= GET_STR(env, eifn, ifn, sizeof(ifn))) + return make_error2(env, atom_einval); + + return nif_name2index(env, ifn); +} + + + +static +ERL_NIF_TERM nif_name2index(ErlNifEnv* env, + char* ifn) +{ + unsigned int idx = if_nametoindex(ifn); + + if (idx == 0) + return make_error2(env, get_errno()); + else + return make_ok2(env, idx); + +} + + + +/* ---------------------------------------------------------------------- + * nif_if_index2name + * + * Description: + * Perform a Interface Index to Interface Name translation. + * + * Arguments: + * Idx - Interface index to be translated. + */ + +static +ERL_NIF_TERM nif_if_index2name(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + unsigned int idx; + + if ((argc != 1) || + !GET_UINT(env, argv[0], &idx)) { + return enif_make_badarg(env); + } + + return nif_index2name(env, idx); +} + + + +static +ERL_NIF_TERM nif_index2name(ErlNifEnv* env, + unsigned int idx) +{ + ERL_NIF_TERM result; + char* ifn = MALLOC(IF_NAMESIZE+1); + + if (ifn == NULL) + return enif_make_badarg(env); // PLACEHOLDER + + if (NULL == if_indextoname(idx, ifn)) { + result = make_ok2(env, MKS(env, ifn)); + } else { + result = make_error2(env, get_errno()); + } + + FREE(ifn); + + return result; +} + + + +/* ---------------------------------------------------------------------- + * nif_if_names + * + * Description: + * Get network interface names and indexes. + * + */ + +static +ERL_NIF_TERM nif_if_names(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + if (argc != 0) { + return enif_make_badarg(env); + } + + return nif_names(env); +} + + + +static +ERL_NIF_TERM nif_names(ErlNifEnv* env) +{ + ERL_NIF_TERM result; + struct if_nameindex* ifs = if_nameindex(); + + if (ifs == NULL) { + result = make_error2(env, get_errno()); + } else { + /* + * We got some interfaces: + * 1) Calculate how many - the only way is to iterate through the list + * until its end (which is indicated by an entry with index = zero + * and if_name = NULL). + * 2) Allocate an ERL_NIF_TERM array of the calculated length. + * 3) Iterate through the array of interfaces and for each create + * a two tuple: {Idx, If} + * + * Or shall we instead build a list in reverse order and then when + * its done, reverse that? Check + */ + unsigned int len = nif_names_length(ifs); + + if (len > 0) { + ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM)); + unsigned int i; + + for (i = 0; i < len; i++) { + array[i] = MKT2(env, + MKI(env, ifs[i].if_index), + MKS(env, ifs[i].if_name)); + } + + result = make_ok2(env, MKLA(env, array, len)); + FREE(array); + } else { + result = make_ok2(env, enif_make_list(env, 0)); + } + } + + if (ifs != NULL) + if_freenameindex(ifs); + + return result; +} + + +static +unsigned int nif_names_length(struct if_nameindex* p) +{ + unsigned int len = 0; + + while ((p[len].if_index == 0) && (p[len].if_name == NULL)) { + len++; + } + + return len; +} + + + +/* ---------------------------------------------------------------------- + * U t i l i t y F u n c t i o n s + * ---------------------------------------------------------------------- + */ + +/* Decode an in_sockaddr (the socket address). + * This is the (erlang) type: in_sockaddr(), which is either + * a in4_sockaddr() (tuple of size 3) or a in6_sockaddr() + * (tuple of size 5). See the net erlang module for details. + * + * We first detect which which of the tuples it is: + * - Size 3: maybe in4_sockaddr + * - Size 5: maybe in6_sockaddr + */ +static +BOOLEAN_T decode_in_sockaddr(ErlNifEnv* env, + const ERL_NIF_TERM eAddr, + SockAddress* saP, + socklen_t* saLen) +{ + const ERL_NIF_TERM* addrt; + int addrtSz; + + if (!GET_TUPLE(env, eAddr, &addrtSz, &addrt)) + return FALSE; + + switch (addrtSz) { + case 3: + return decode_in4_sockaddr(env, addrt, saP, saLen); + break; + +#ifdef HAVE_IN6 + case 5: + return decode_in6_sockaddr(env, addrt, saP, saLen); + break; +#endif + + default: + return FALSE; + break; + } + +} + + +/* Decode an in4_sockaddr record. This is a tuple of size 3. + * The size has already been verified, but not its content. + * So, the first element should be the atom 'in4_sockaddr'. + * The second the port number, an integer. And the third, + * the actual ip address, a 4-tuple. + */ +static +BOOLEAN_T decode_in4_sockaddr(ErlNifEnv* env, + const ERL_NIF_TERM* addrt, + SockAddress* saP, + socklen_t* saLen) +{ + unsigned int len; + char tag[16]; // Just in case... + int port; + int ipAddrSz; + const ERL_NIF_TERM* ipAddrT; + int a, v; + char addr[4]; + + /* The first element: Verify record tag (atom()): in4_sockaddr */ + + if (!(GET_ATOM_LEN(env, addrt[0], &len) && + (len > 0) && + (len <= (sizeof(tag))))) + return FALSE; + + if (!GET_ATOM(env, addrt[0], tag, sizeof(tag))) + return FALSE; + + if (strncmp(tag, "in4_sockaddr", len) != 0) + return FALSE; + + + /* Get second element: port number (integer) */ + + if (!GET_INT(env, addrt[1], &port)) + return FALSE; + + + /* And finally, get the third element, the ip address (a 4 tuple) */ + + if (!GET_TUPLE(env, addrt[2], &ipAddrSz, &ipAddrT)) + return FALSE; + + if (ipAddrSz != 4) + return FALSE; + + + /* And finally initialize the sockaddr structure (and size) */ + sys_memzero((char*)saP, sizeof(struct sockaddr_in)); + saP->in.sin_family = AF_INET; + saP->in.sin_port = htons(port); + for (a = 0; a < 4; a++) { + if (!GET_INT(env, ipAddrT[a], &v)) + return FALSE; + addr[a] = v; + } + sys_memcpy(&saP->in.sin_addr, &addr, sizeof(addr)); + *saLen = sizeof(struct sockaddr_in); + return TRUE; +} + + + +#if defined(HAVE_IN6) && defined(AF_INET6) +/* Decode an in6_sockaddr record. This is a tuple of size 5. + * The size has already been verified, but not its content. + * So, the first element should be the atom 'in6_sockaddr'. + * The second the port number, an integer. The third, the + * actual ip address, a 8-tuple. The forth, the flowinfo, + * an integer. And finally, the fifth element, the scope_id, + * also an integer. *Not used here*. + */ +static +BOOLEAN_T decode_in6_sockaddr(ErlNifEnv* env, + const ERL_NIF_TERM* addrt, + SockAddress* saP, + socklen_t* saLen) +{ + unsigned int len; + char tag[16]; // Just in case... + int port; + int ipAddrSz; + const ERL_NIF_TERM* ipAddrT; + int flowInfo; + int a, v; + char addr[16]; + + + /* The first element: Verify record tag (atom()): in6_sockaddr */ + + if (!(GET_ATOM_LEN(env, addrt[0], &len) && + (len > 0) && + (len <= (sizeof(tag))))) + return FALSE; + + if (!GET_ATOM(env, addrt[0], tag, sizeof(tag))) + return FALSE; + + if (strncmp(tag, "in6_sockaddr", len) != 0) + return FALSE; + + + /* Get second element: port number (integer) */ + + if (!GET_INT(env, addrt[1], &port)) + return FALSE; + + + /* Get the third element, the ip address (a 8 tuple) */ + + if (!GET_TUPLE(env, addrt[2], &ipAddrSz, &ipAddrT)) + return FALSE; + + if (ipAddrSz != 8) + return FALSE; + + + /* And finally, get the forth element, the flowinfo (integer) */ + + if (!GET_INT(env, addrt[3], &flowInfo)) + return FALSE; + + + /* And finally initialize the sockaddr structure (and size) */ + + sys_memzero((char*)saP, sizeof(struct sockaddr_in6)); + saP->in6.sin6_family = AF_INET6; + saP->in6.sin6_port = htons(port); + saP->in6.sin6_flowinfo = flowInfo; + /* 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 FALSE; + addr[a*2 ] = ((v >> 8) & 0xFF); + addr[a*2+1] = (v & 0xFF); + } + sys_memcpy(&saP->in6.sin6_addr, &addr, sizeof(addr)); + *saLen = sizeof(struct sockaddr_in6); + + return TRUE; +} +#endif + + + +/* The erlang format for a set of flags is a list of atoms. + * A special case is when there is no flags, which is + * represented by the atom undefined. + */ +static +BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env, + const ERL_NIF_TERM eflags, + int* flags) +{ + BOOLEAN_T result; + + if (IS_ATOM(env, eflags)) { + if (COMPARE(eflags, atom_undefined) == 0) { + *flags = 0; + result = TRUE; + } else { + result = FALSE; + } + } else if (IS_LIST(env, eflags)) { + result = decode_nameinfo_flags_list(env, eflags, flags); + } else { + result = FALSE; + } + + return result; +} + + + +static +BOOLEAN_T decode_nameinfo_flags_list(ErlNifEnv* env, + const ERL_NIF_TERM eflags, + int* flags) +{ + ERL_NIF_TERM elem, tail, list = eflags; + int tmp = 0; + BOOLEAN_T done = FALSE; + + while (!done) { + if (GET_LIST_ELEM(env, list, &elem, &tail)) { + if (COMPARE(elem, atom_namereqd) == 0) { + tmp |= NI_NAMEREQD; + } else if (COMPARE(elem, atom_dgram) == 0) { + tmp |= NI_DGRAM; + } else if (COMPARE(elem, atom_nofqdn) == 0) { + tmp |= NI_NOFQDN; + } else if (COMPARE(elem, atom_numerichost) == 0) { + tmp |= NI_NUMERICHOST; + } else if (COMPARE(elem, atom_numericserv) == 0) { + tmp |= NI_NUMERICSERV; + + /* Starting with glibc 2.3.4: */ + +#if defined(NI_IDN) + } else if (COMPARE(elem, atom_idn) == 0) { + tmp |= NI_IDN; +#endif + +#if defined(NI_IDN_ALLOW_UNASSIGNED) + } else if (COMPARE(elem, atom_idna_allow_unassigned) == 0) { + tmp |= NI_IDN_ALLOW_UNASSIGNED; +#endif + +#if defined(NI_IDN_USE_STD3_ASCII_RULES) + } else if (COMPARE(elem, atom_idna_use_std3_ascii_rules) == 0) { + tmp |= NI_IDN_USE_STD3_ASCII_RULES; +#endif + + } else { + return FALSE; + } + + list = tail; + + } else { + done = TRUE; + } + } + + *flags = tmp; + + return TRUE; +} + + + +/* Decode the address info string (hostname or service name) + * The string is either the atom undefined or an actual string. + */ +static +BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, + const ERL_NIF_TERM eString, + char** stringP) +{ + BOOLEAN_T result; + + if (IS_ATOM(env, eString)) { + if (COMPARE(eString, atom_undefined) == 0) { + *stringP = NULL; + result = TRUE; + } else { + *stringP = NULL; + result = FALSE; + } + } else { + unsigned int len; + char* bufP; + + if (!GET_LIST_LEN(env, eString, &len) && (len != 0)) { + *stringP = NULL; + result = FALSE; + } + + bufP = ALLOC(len); + + if (GET_STR(env, eString, bufP, len)) { + *stringP = bufP; + result = TRUE; + } else { + *stringP = NULL; + result = FALSE; + } + } + + return result; + +} + + + +/* Encode the address info + * The address info is a linked list och address info, which + * will result in the result being a list of zero or more length. + */ +static +ERL_NIF_TERM encode_address_info(ErlNifEnv* env, + struct addrinfo* addrInfo) +{ + ERL_NIF_TERM result; + unsigned int len = address_info_length(addrInfo); + + if (len > 0) { + ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM)); + unsigned int i; + + for (i = 0; i < len; i++) { + array[i] = make_address_info(env, &addrInfo[i]); + } + + result = mkake_ok2(env, MKLA(env, array, len)); + } else { + result = MKEL(env); + } + + return result; +} + + + +/* Calculate the length of the adress info linked list + * The list is NULL-terminated, so the only way is to + * iterate through the list until we find next = NULL. + */ +static +unsigned int address_info_length(struct addrinfo* addrInfoP) +{ + unsigned int len; + struct addrinfo* tmp = addrInfoP; + + if (tmp != NULL) { + len = 1; + while (tmp->ai_next != NULL) { + tmp = tmp->ai_next; + len++; + } + } else { + len = 0; + } + + return len; +} + + + +/* Create one (erlang) instance of the address info record + * Should we have address info as a record or as a map? + * + * {address_info, Fam, Type, Proto, Addr} + */ +static +ERL_NIF_TERM make_adress_info(ErlNifEnv* env, + struct addrinfo* addrInfoP) +{ + ERL_NIF_TERM Fam = make_addrinfo_family(env, addrInfoP->ai_family); + ERL_NIF_TERM Type = make_addrinfo_type(env, addrInfoP->ai_socktype); + ERL_NIF_TERM Proto = make_addrinfo_proto(env, addrInfoP->ai_protocol); + ERL_NIF_TERM Addr = make_addrinfo_addr(env, + addrInfoP->ai_addr, + addrInfoP->ai_addrlen); + + return MKT5(env, atom_address_info, Fam, Type, Proto, Addr); + +} + + +/* Convert an "native" family to an erlang family + * Note that this is not currently exhaustive, but only supports + * inet and inet6. Other values will be returned as is, that is + * in the form of an integer. + */ +static +ERL_NIF_TERM make_addrinfo_family(ErlNifEnv* env, + int family) +{ + ERL_NIF_TERM efam; + + switch (family) { + case AF_INET: + efam = atom_inet; + break; + +#if defined(HAVE_IN6) && defined(AF_INET6) + case AF_INET6: + efam = atom_inet6; + break; +#endif + + default: + efam = MKI(env, family); + break; + } + + return efam; +} + + + +/* Convert an "native" socket type to an erlang socket type + * Note that this is not currently exhaustive, but only supports + * stream and dgram. Other values will be returned as is, that is + * in the form of an integer. + */ +static +ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env, + int socktype) +{ + ERL_NIF_TERM etype; + + switch (socktype) { + case SOCK_STREAM: + etype = atom_stream; + break; + + case SOCK_DGRAM: + etype = atom_dgram; + break; + + default: + etype = MKI(env, socktype); + break; + } + + return etype; +} + + + +/* Convert an "native" protocol to an erlang protocol + * Note that this is not currently exhaustive, but only supports + * tcp and udp. Other values will be returned as is, that is + * in the form of an integer. + */ +static +ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env, + int proto) +{ + ERL_NIF_TERM eproto; + + switch (proto) { +#if defined(SOL_IP) + case SOL_IP: +#else + case IPPROTO_IP: +#endif + eproto = atom_ip; + break; + + case IPPROTO_TCP: + eproto = atom_tcp; + break; + + case IPPROTO_UDP: + eproto = atom_udp; + break; + + default: + eproto = MKI(env, proto); + break; + } + + return eproto; +} + + + +/* Convert an "native" address to an erlang address + * Note that this is not currently exhaustive, but only supports + * IPv4 and IPv6 addresses. Values of other families will be + * returned as an undefined. + */ +static +ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, + struct sockaddr* addrP, + socklen_t addrLen) +{ + ERL_NIF_TERM port, addr, eaddr; + SockAddress* p = (SockAddress*) addrP; + + switch (addrP->sa_family) { + case AF_INET: + port = ntohs(p->in.sin_port); + addr = MKT4(env, + MKI(env, p->in.sin_addr[0]), + MKI(env, p->in.sin_addr[1]), + MKI(env, p->in.sin_addr[2]), + MKI(env, p->in.sin_addr[3])); + eaddr = MKT2(env, port, addr); + break; + +#if defined(HAVE_IN6) && defined(AF_INET6) + case AF_INET6: + port = ntohs(p->in6.sin6_port); + addr = MKT8(env, + MKI(env, p->in6.sin_addr[0]), + MKI(env, p->in6.sin_addr[1]), + MKI(env, p->in6.sin_addr[2]), + MKI(env, p->in6.sin_addr[3]), + MKI(env, p->in6.sin_addr[3]), + MKI(env, p->in6.sin_addr[3]), + MKI(env, p->in6.sin_addr[3]), + MKI(env, p->in6.sin_addr[3])); + eaddr = MKT2(env, port, addr); + break; +#endif + + default: + eaddr = atom_undefined; + break; + } + + return eaddr; +} + + + +/* Create an ok two (2) tuple in the form: {ok, Any}. + * The second element (Any) is already in the form of an + * ERL_NIF_TERM so all we have to do is create the tuple. + */ +static +ERL_NIF_TERM make_ok2(ErlNifEnv* env, ERL_NIF_TERM any) +{ + return MKT2(env, atom_ok, any); +} + + +/* Create an ok three (3) tuple in the form: {ok, Val1, Val2}. + * The second (Val1) and third (Val2) elements are already in + * the form of an ERL_NIF_TERM so all we have to do is create + * the tuple. + */ +/* +static +ERL_NIF_TERM make_ok3(ErlNifEnv* env, ERL_NIF_TERM val1, ERL_NIF_TERM val2) +{ + return MKT3(env, atom_ok, val1, val2); +} +*/ + + +/* Create an error two (2) tuple in the form: {error, Reason}. + * The second element (Reason) is already in the form of an + * ERL_NIF_TERM so all we have to do is create the tuple. + */ +static +ERL_NIF_TERM make_error(ErlNifEnv* env, ERL_NIF_TERM reason) +{ + return MKT2(env, atom_error, reason); +} + + +/* Create an error two (2) tuple in the form: {error, Reason}. + * The second element, Reason, is a string to be converted into + * an atom. + */ +static +ERL_NIF_TERM make_error1(ErlNifEnv* env, char* reason) +{ + return make_error(env, MKA(env, reason)); +} + + +/* Create an error two (2) tuple in the form: {error, Reason}. + * The second element, Reason, is the errno value in its + * basic form (integer) which will (eventually) be converted + * into an atom. + */ +static +ERL_NIF_TERM make_error2(ErlNifEnv* env, int err) +{ + return make_error1(env, erl_errno_id(err)); +} + + +/* +static +void xabort(const char* expr, + const char* func, + const char* file, + int line) +{ + fflush(stdout); + fprintf(stderr, "%s:%d:%s() Assertion failed: %s\n", + file, line, func, expr); + fflush(stderr); + abort(); +} +*/ + + +/* ---------------------------------------------------------------------- + * C o u n t e r F u n c t i o n s + * ---------------------------------------------------------------------- + */ + +/* ---------------------------------------------------------------------- + * C a l l b a c k F u n c t i o n s + * ---------------------------------------------------------------------- + */ + +/* ========================================================================= + * net_dtor - Callback function for resource destructor + * + */ +/* +static +void net_dtor(ErlNifEnv* env, void* obj) +{ +} +*/ + + +/* ========================================================================= + * net_stop - Callback function for resource stop + * + */ +/* +static +void net_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) +{ +} +*/ + + + + +/* ========================================================================= + * net_down - Callback function for resource down (monitored processes) + * + */ +/* +static +void net_down(ErlNifEnv* env, + void* obj, + const ErlNifPid* pid, + const ErlNifMonitor* mon) +{ +} +*/ + + + +/* ---------------------------------------------------------------------- + * L o a d / u n l o a d / u p g r a d e F u n c t i o n s + * ---------------------------------------------------------------------- + */ + +static +ErlNifFunc net_funcs[] = +{ + // Some utility functions + {"nif_is_loaded", 0, nif_is_loaded, 0}, + {"nif_info", 0, nif_info, 0}, + + /* address and name translation in protocol-independent manner */ + {"nif_getnameinfo", 2, nif_getnameinfo, 0}, + + /* Network interface (name and/or index) functions */ + {"nif_if_name2index", 1, nif_if_name2index, 0}, + {"nif_if_index2name", 1, nif_if_index2name, 0}, + {"nif_if_names", 0, nif_if_names, 0} +}; + + + +/* ======================================================================= + * load_info - A map of misc info (e.g global debug) + */ + +static +int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + /* +++ Misc atoms +++ */ + atom_dgram = MKA(env, str_dgram); + atom_error = MKA(env, str_error); + atom_idn = MKA(env, str_idn); + atom_idna_allow_unassigned = MKA(env, str_idna_allow_unassigned); + atom_idna_use_std3_ascii_rules = MKA(env, str_idna_use_std3_ascii_rules); + atom_namereqd = MKA(env, str_namereqd); + atom_name_info = MKA(env, str_name_info); + atom_nofqdn = MKA(env, str_nofqdn); + atom_numerichost = MKA(env, str_numerichost); + atom_numericserv = MKA(env, str_numericserv); + atom_ok = MKA(env, str_ok); + atom_true = MKA(env, str_true); + atom_undefined = MKA(env, str_undefined); + // atom_version = MKA(env, str_version); + + // atom_lowdelay = MKA(env, str_lowdelay); + // atom_throughput = MKA(env, str_throughput); + // atom_reliability = MKA(env, str_reliability); + // atom_mincost = MKA(env, str_mincost); + + /* Error codes */ + // atom_eafnosupport = MKA(env, str_eafnosupport); + atom_eagain = MKA(env, str_eagain); + atom_ebadflags = MKA(env, str_ebadflags); + atom_efail = MKA(env, str_efail); + atom_efamily = MKA(env, str_efamily); + atom_einval = MKA(env, str_einval); + // atom_eisconn = MKA(env, str_eisconn); + atom_emem = MKA(env, str_emem); + atom_enoname = MKA(env, str_enoname); + // atom_enotclosing = MKA(env, str_enotclosing); + // atom_enotconn = MKA(env, str_enotconn); + atom_eoverflow = MKA(env, str_eoverflow); + // atom_exalloc = MKA(env, str_exalloc); + // atom_exbadstate = MKA(env, str_exbadstate); + // atom_exbusy = MKA(env, str_exbusy); + // atom_exnotopen = MKA(env, str_exnotopen); + // atom_exmon = MKA(env, str_exmon); + // atom_exself = MKA(env, str_exself); + // atom_exsend = MKA(env, str_exsend); + + // For storing "global" things... + // socketData.env = enif_alloc_env(); // We should really check + // socketData.version = MKA(env, ERTS_VERSION); + // socketData.buildDate = MKA(env, ERTS_BUILD_DATE); + + net = enif_open_resource_type_x(env, + "net", + &netInit, + ERL_NIF_RT_CREATE, + NULL); + + return !net; +} + +ERL_NIF_INIT(net, net_funcs, on_load, NULL, NULL, NULL) -- cgit v1.2.3 From 5b7ac9423f07171e4cd682a216cc86b1d32c660a Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 8 Jun 2018 15:25:51 +0200 Subject: [net-nif] The net-module now actually loads The net (nif) module now actually loads (automatically) when the VM is started (*on linux*). Now we must make sure it *actually* works, and implement the rest of the stuff... --- erts/emulator/nifs/common/net_nif.c | 149 ++++++++++++++++++++++++++---------- 1 file changed, 108 insertions(+), 41 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index b8fa6628a7..edcf944c66 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -24,6 +24,8 @@ * */ +#define STATIC_ERLANG_NIF 1 + /* #include */ /* #include */ /* #include */ @@ -262,6 +264,8 @@ typedef unsigned long long llu_t; #define MKT2(E,E1,E2) enif_make_tuple2((E), (E1), (E2)) #define MKT3(E,E1,E2,E3) enif_make_tuple3((E), (E1), (E2), (E3)) #define MKT4(E,E1,E2,E3,E4) enif_make_tuple4((E), (E1), (E2), (E3), (E4)) +#define MKT5(E,E1,E2,E3,E4,E5) \ + enif_make_tuple5((E), (E1), (E2), (E3), (E4), (E5)) #define MKT8(E,E1,E2,E3,E4,E5,E6,E7,E8) \ enif_make_tuple8((E), (E1), (E2), (E3), (E4), (E5), (E6), (E7), (E8)) @@ -364,8 +368,11 @@ static ERL_NIF_TERM nif_if_names(ErlNifEnv* env, static ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, const SockAddress* saP, - socklen_t saLen, + SOCKLEN_T saLen, int flags); +static ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env, + char* host, + char* serv); static ERL_NIF_TERM nif_name2index(ErlNifEnv* env, char* ifn); static ERL_NIF_TERM nif_index2name(ErlNifEnv* env, @@ -387,16 +394,16 @@ static void net_down(ErlNifEnv* env, static BOOLEAN_T decode_in_sockaddr(ErlNifEnv* env, const ERL_NIF_TERM eAddr, SockAddress* saP, - socklen_t* saLen); + SOCKLEN_T* saLen); static BOOLEAN_T decode_in4_sockaddr(ErlNifEnv* env, const ERL_NIF_TERM* addrt, SockAddress* saP, - socklen_t* saLen); + SOCKLEN_T* saLen); #if defined(HAVE_IN6) && defined(AF_INET6) static BOOLEAN_T decode_in6_sockaddr(ErlNifEnv* env, const ERL_NIF_TERM* addrt, SockAddress* saP, - socklen_t* saLen); + SOCKLEN_T* saLen); #endif static BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env, const ERL_NIF_TERM eflags, @@ -404,10 +411,26 @@ static BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env, static BOOLEAN_T decode_nameinfo_flags_list(ErlNifEnv* env, const ERL_NIF_TERM eflags, int* flags); +static +BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, + const ERL_NIF_TERM eString, + char** stringP); static ERL_NIF_TERM encode_address_info(ErlNifEnv* env, struct addrinfo* addrInfo); static unsigned int address_info_length(struct addrinfo* addrInfoP); +static ERL_NIF_TERM make_address_info(ErlNifEnv* env, + struct addrinfo* addrInfoP); +static ERL_NIF_TERM make_addrinfo_family(ErlNifEnv* env, + int family); +static ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env, + int socktype); +static ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env, + int proto); +static ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, + struct sockaddr* addrP, + SOCKLEN_T addrLen); + static ERL_NIF_TERM make_ok2(ErlNifEnv* env, ERL_NIF_TERM val); // static ERL_NIF_TERM make_ok3(ErlNifEnv* env, ERL_NIF_TERM val1, ERL_NIF_TERM val2); static ERL_NIF_TERM make_error(ErlNifEnv* env, ERL_NIF_TERM reason); @@ -448,18 +471,25 @@ static const struct in6_addr in6addr_loopback = /* *** String constants *** */ +static char str_address_info[] = "address_info"; static char str_dgram[] = "dgram"; static char str_error[] = "error"; static char str_idn[] = "idn"; static char str_idna_allow_unassigned[] = "idna_allow_unassigned"; static char str_idna_use_std3_ascii_rules[] = "idna_use_std3_ascii_rules"; +static char str_inet[] = "inet"; +static char str_inet6[] = "inet6"; +static char str_ip[] = "ip"; static char str_namereqd[] = "namereqd"; static char str_name_info[] = "name_info"; static char str_nofqdn[] = "nofqdn"; static char str_numerichost[] = "numerichost"; static char str_numericserv[] = "numericserv"; static char str_ok[] = "ok"; +static char str_stream[] = "stream"; +static char str_tcp[] = "tcp"; static char str_true[] = "true"; +static char str_udp[] = "udp"; static char str_undefined[] = "undefined"; // static char str_lowdelay[] = "lowdelay"; @@ -469,6 +499,7 @@ static char str_undefined[] = "undefined"; /* (special) error string constants */ // static char str_eafnosupport[] = "eafnosupport"; +static char str_eaddrfamily[] = "eaddrfamily"; static char str_eagain[] = "eagain"; static char str_ebadflags[] = "ebadflags"; static char str_efail[] = "efail"; @@ -476,10 +507,14 @@ static char str_efamily[] = "efamily"; static char str_einval[] = "einval"; // static char str_eisconn[] = "eisconn"; static char str_emem[] = "emem"; +static char str_enodata[] = "enodata"; static char str_enoname[] = "enoname"; // static char str_enotclosing[] = "enotclosing"; // static char str_enotconn[] = "enotconn"; static char str_eoverflow[] = "eoverflow"; +static char str_eservice[] = "eservice"; +static char str_esocktype[] = "esocktype"; +static char str_esystem[] = "esystem"; // static char str_exalloc[] = "exalloc"; // static char str_exbadstate[] = "exbadstate"; // static char str_exbusy[] = "exbusy"; @@ -490,11 +525,15 @@ static char str_eoverflow[] = "eoverflow"; /* *** Atoms *** */ -static ERL_NIF_TERM atom_error; +static ERL_NIF_TERM atom_address_info; static ERL_NIF_TERM atom_dgram; +static ERL_NIF_TERM atom_error; static ERL_NIF_TERM atom_idn; static ERL_NIF_TERM atom_idna_allow_unassigned; static ERL_NIF_TERM atom_idna_use_std3_ascii_rules; +static ERL_NIF_TERM atom_inet; +static ERL_NIF_TERM atom_inet6; +static ERL_NIF_TERM atom_ip; static ERL_NIF_TERM atom_namereqd; static ERL_NIF_TERM atom_name_info; static ERL_NIF_TERM atom_nofqdn; @@ -502,8 +541,11 @@ static ERL_NIF_TERM atom_numerichost; static ERL_NIF_TERM atom_numericserv; static ERL_NIF_TERM atom_ok; // static ERL_NIF_TERM atom_select; +static ERL_NIF_TERM atom_stream; // static ERL_NIF_TERM atom_timeout; +static ERL_NIF_TERM atom_tcp; static ERL_NIF_TERM atom_true; +static ERL_NIF_TERM atom_udp; static ERL_NIF_TERM atom_undefined; // static ERL_NIF_TERM atom_lowdelay; @@ -512,6 +554,7 @@ static ERL_NIF_TERM atom_undefined; // static ERL_NIF_TERM atom_mincost; // static ERL_NIF_TERM atom_eafnosupport; +static ERL_NIF_TERM atom_eaddrfamily; static ERL_NIF_TERM atom_eagain; static ERL_NIF_TERM atom_ebadflags; static ERL_NIF_TERM atom_efail; @@ -519,10 +562,14 @@ static ERL_NIF_TERM atom_efamily; static ERL_NIF_TERM atom_einval; // static ERL_NIF_TERM atom_eisconn; static ERL_NIF_TERM atom_emem; +static ERL_NIF_TERM atom_enodata; static ERL_NIF_TERM atom_enoname; // static ERL_NIF_TERM atom_enotclosing; // static ERL_NIF_TERM atom_enotconn; static ERL_NIF_TERM atom_eoverflow; +static ERL_NIF_TERM atom_eservice; +static ERL_NIF_TERM atom_esocktype; +static ERL_NIF_TERM atom_esystem; // static ERL_NIF_TERM atom_exalloc; // static ERL_NIF_TERM atom_exbadstate; // static ERL_NIF_TERM atom_exbusy; @@ -620,7 +667,7 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, unsigned int eFlags; int flags = 0; // Just in case... SockAddress sa; - socklen_t saLen = 0; // Just in case... + SOCKLEN_T saLen = 0; // Just in case... if ((argc != 2) || !GET_UINT(env, argv[1], &eFlags)) { @@ -645,14 +692,14 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, static ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, const SockAddress* saP, - socklen_t saLen, + SOCKLEN_T saLen, int flags) { ERL_NIF_TERM result; char host[HOSTNAME_LEN]; - socklen_t hostLen = sizeof(host); + SOCKLEN_T hostLen = sizeof(host); char serv[SERVICE_LEN]; - socklen_t servLen = sizeof(serv); + SOCKLEN_T servLen = sizeof(serv); int res = getnameinfo((struct sockaddr*) saP, saLen, host, hostLen, @@ -729,7 +776,7 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ERL_NIF_TERM result; + ERL_NIF_TERM result, eHostName, eServName; //, eHints; char* hostName; char* servName; // struct addrinfo* hints; @@ -739,7 +786,7 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, } eHostName = argv[0]; eServName = argv[1]; - eHints = argv[2]; + // eHints = argv[2]; if (!decode_addrinfo_string(env, eHostName, &hostName)) return enif_make_badarg(env); @@ -773,10 +820,11 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, static -ERL_NIF_TERM nifgetaddrinfo(ErlNifEnv* env, - char* host, - char* serv) +ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env, + char* host, + char* serv) { + ERL_NIF_TERM result; struct addrinfo* addrInfoP; int res; @@ -823,7 +871,7 @@ ERL_NIF_TERM nifgetaddrinfo(ErlNifEnv* env, result = make_error(env, atom_enoname); break; - case EAI_SERCVICE: + case EAI_SERVICE: result = make_error(env, atom_eservice); break; @@ -1041,7 +1089,7 @@ static BOOLEAN_T decode_in_sockaddr(ErlNifEnv* env, const ERL_NIF_TERM eAddr, SockAddress* saP, - socklen_t* saLen) + SOCKLEN_T* saLen) { const ERL_NIF_TERM* addrt; int addrtSz; @@ -1078,7 +1126,7 @@ static BOOLEAN_T decode_in4_sockaddr(ErlNifEnv* env, const ERL_NIF_TERM* addrt, SockAddress* saP, - socklen_t* saLen) + SOCKLEN_T* saLen) { unsigned int len; char tag[16]; // Just in case... @@ -1146,7 +1194,7 @@ static BOOLEAN_T decode_in6_sockaddr(ErlNifEnv* env, const ERL_NIF_TERM* addrt, SockAddress* saP, - socklen_t* saLen) + SOCKLEN_T* saLen) { unsigned int len; char tag[16]; // Just in case... @@ -1330,7 +1378,7 @@ BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, result = FALSE; } - bufP = ALLOC(len); + bufP = MALLOC(len); if (GET_STR(env, eString, bufP, len)) { *stringP = bufP; @@ -1366,7 +1414,7 @@ ERL_NIF_TERM encode_address_info(ErlNifEnv* env, array[i] = make_address_info(env, &addrInfo[i]); } - result = mkake_ok2(env, MKLA(env, array, len)); + result = make_ok2(env, MKLA(env, array, len)); } else { result = MKEL(env); } @@ -1407,8 +1455,8 @@ unsigned int address_info_length(struct addrinfo* addrInfoP) * {address_info, Fam, Type, Proto, Addr} */ static -ERL_NIF_TERM make_adress_info(ErlNifEnv* env, - struct addrinfo* addrInfoP) +ERL_NIF_TERM make_address_info(ErlNifEnv* env, + struct addrinfo* addrInfoP) { ERL_NIF_TERM Fam = make_addrinfo_family(env, addrInfoP->ai_family); ERL_NIF_TERM Type = make_addrinfo_type(env, addrInfoP->ai_socktype); @@ -1530,35 +1578,41 @@ ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env, static ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, struct sockaddr* addrP, - socklen_t addrLen) + SOCKLEN_T addrLen) { ERL_NIF_TERM port, addr, eaddr; SockAddress* p = (SockAddress*) addrP; switch (addrP->sa_family) { case AF_INET: - port = ntohs(p->in.sin_port); - addr = MKT4(env, - MKI(env, p->in.sin_addr[0]), - MKI(env, p->in.sin_addr[1]), - MKI(env, p->in.sin_addr[2]), - MKI(env, p->in.sin_addr[3])); - eaddr = MKT2(env, port, addr); + { + unsigned char* a = (unsigned char*) &p->in.sin_addr; + port = ntohs(p->in.sin_port); + addr = MKT4(env, + MKI(env, a[0]), + MKI(env, a[1]), + MKI(env, a[2]), + MKI(env, a[3])); + eaddr = MKT2(env, port, addr); + } break; #if defined(HAVE_IN6) && defined(AF_INET6) case AF_INET6: - port = ntohs(p->in6.sin6_port); - addr = MKT8(env, - MKI(env, p->in6.sin_addr[0]), - MKI(env, p->in6.sin_addr[1]), - MKI(env, p->in6.sin_addr[2]), - MKI(env, p->in6.sin_addr[3]), - MKI(env, p->in6.sin_addr[3]), - MKI(env, p->in6.sin_addr[3]), - MKI(env, p->in6.sin_addr[3]), - MKI(env, p->in6.sin_addr[3])); - eaddr = MKT2(env, port, addr); + { + unsigned char* a = (unsigned char*) &p->in6.sin6_addr; + port = ntohs(p->in6.sin6_port); + addr = MKT8(env, + MKI(env, get_int16(a)), + MKI(env, get_int16(&a[ 2])), + MKI(env, get_int16(&a[ 4])), + MKI(env, get_int16(&a[ 6])), + MKI(env, get_int16(&a[ 8])), + MKI(env, get_int16(&a[10])), + MKI(env, get_int16(&a[12])), + MKI(env, get_int16(&a[14]))); + eaddr = MKT2(env, port, addr); + } break; #endif @@ -1713,6 +1767,7 @@ ErlNifFunc net_funcs[] = /* address and name translation in protocol-independent manner */ {"nif_getnameinfo", 2, nif_getnameinfo, 0}, + {"nif_getaddrinfo", 3, nif_getaddrinfo, 0}, /* Network interface (name and/or index) functions */ {"nif_if_name2index", 1, nif_if_name2index, 0}, @@ -1730,18 +1785,25 @@ static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { /* +++ Misc atoms +++ */ + atom_address_info = MKA(env, str_address_info); atom_dgram = MKA(env, str_dgram); atom_error = MKA(env, str_error); atom_idn = MKA(env, str_idn); atom_idna_allow_unassigned = MKA(env, str_idna_allow_unassigned); atom_idna_use_std3_ascii_rules = MKA(env, str_idna_use_std3_ascii_rules); + atom_inet = MKA(env, str_inet); + atom_inet6 = MKA(env, str_inet6); + atom_ip = MKA(env, str_ip); atom_namereqd = MKA(env, str_namereqd); atom_name_info = MKA(env, str_name_info); atom_nofqdn = MKA(env, str_nofqdn); atom_numerichost = MKA(env, str_numerichost); atom_numericserv = MKA(env, str_numericserv); atom_ok = MKA(env, str_ok); + atom_stream = MKA(env, str_stream); + atom_tcp = MKA(env, str_tcp); atom_true = MKA(env, str_true); + atom_udp = MKA(env, str_udp); atom_undefined = MKA(env, str_undefined); // atom_version = MKA(env, str_version); @@ -1752,6 +1814,7 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) /* Error codes */ // atom_eafnosupport = MKA(env, str_eafnosupport); + atom_eaddrfamily = MKA(env, str_eaddrfamily); atom_eagain = MKA(env, str_eagain); atom_ebadflags = MKA(env, str_ebadflags); atom_efail = MKA(env, str_efail); @@ -1759,10 +1822,14 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_einval = MKA(env, str_einval); // atom_eisconn = MKA(env, str_eisconn); atom_emem = MKA(env, str_emem); + atom_enodata = MKA(env, str_enodata); atom_enoname = MKA(env, str_enoname); // atom_enotclosing = MKA(env, str_enotclosing); // atom_enotconn = MKA(env, str_enotconn); atom_eoverflow = MKA(env, str_eoverflow); + atom_eservice = MKA(env, str_eservice); + atom_esocktype = MKA(env, str_esocktype); + atom_esystem = MKA(env, str_esystem); // atom_exalloc = MKA(env, str_exalloc); // atom_exbadstate = MKA(env, str_exbadstate); // atom_exbusy = MKA(env, str_exbusy); -- cgit v1.2.3 From cc08971508f3515f9f3b6c406ff0f6a186b24f6b Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 11 Jun 2018 12:34:23 +0200 Subject: [net-nif] Added debugging Added a command function, which is currently only used to enable and disable debug, which is also added. --- erts/emulator/nifs/common/net_nif.c | 285 +++++++++++++++++++++++++++++++++++- 1 file changed, 278 insertions(+), 7 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index edcf944c66..134b02d178 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -63,6 +63,7 @@ #include #include #include +#include #ifdef HAVE_UNISTD_H #include @@ -317,6 +318,12 @@ typedef unsigned long long llu_t; # define SOCKLEN_T size_t #endif +#define NDEBUG( ___COND___ , proto ) \ + if ( ___COND___ ) { \ + dbg_printf proto; \ + fflush(stdout); \ + } +#define NDBG( proto ) NDEBUG( data.debug , proto ) /* The general purpose socket address */ typedef union { @@ -330,6 +337,12 @@ typedef union { } SockAddress; +typedef struct { + BOOLEAN_T debug; +} NetData; + + +static NetData data; /* ---------------------------------------------------------------------- @@ -347,6 +360,9 @@ static ERL_NIF_TERM nif_is_loaded(ErlNifEnv* env, static ERL_NIF_TERM nif_info(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM nif_command(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]); static ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, int argc, @@ -366,6 +382,8 @@ static ERL_NIF_TERM nif_if_names(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ncommand(ErlNifEnv* env, + ERL_NIF_TERM cmd); static ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, const SockAddress* saP, SOCKLEN_T saLen, @@ -415,6 +433,9 @@ static BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, const ERL_NIF_TERM eString, char** stringP); +static ERL_NIF_TERM decode_bool(ErlNifEnv* env, + ERL_NIF_TERM eBool, + BOOLEAN_T* bool); static ERL_NIF_TERM encode_address_info(ErlNifEnv* env, struct addrinfo* addrInfo); static unsigned int address_info_length(struct addrinfo* addrInfoP); @@ -437,6 +458,10 @@ static ERL_NIF_TERM make_error(ErlNifEnv* env, ERL_NIF_TERM reason); static ERL_NIF_TERM make_error1(ErlNifEnv* env, char* reason); static ERL_NIF_TERM make_error2(ErlNifEnv* env, int err); +static void dbg_printf( const char* format, ... ); +static int dbg_realtime(struct timespec* tsP); +static int dbg_timespec2str(char *buf, unsigned int len, struct timespec *ts); + /* static void xabort(const char* expr, const char* func, @@ -472,8 +497,10 @@ static const struct in6_addr in6addr_loopback = /* *** String constants *** */ static char str_address_info[] = "address_info"; +static char str_debug[] = "debug"; static char str_dgram[] = "dgram"; static char str_error[] = "error"; +static char str_false[] = "false"; static char str_idn[] = "idn"; static char str_idna_allow_unassigned[] = "idna_allow_unassigned"; static char str_idna_use_std3_ascii_rules[] = "idna_use_std3_ascii_rules"; @@ -526,8 +553,10 @@ static char str_esystem[] = "esystem"; /* *** Atoms *** */ static ERL_NIF_TERM atom_address_info; +static ERL_NIF_TERM atom_debug; static ERL_NIF_TERM atom_dgram; static ERL_NIF_TERM atom_error; +static ERL_NIF_TERM atom_false; static ERL_NIF_TERM atom_idn; static ERL_NIF_TERM atom_idna_allow_unassigned; static ERL_NIF_TERM atom_idna_use_std3_ascii_rules; @@ -640,12 +669,90 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ERL_NIF_TERM info = enif_make_new_map(env); + ERL_NIF_TERM info; + + NDBG( ("info -> entry\r\n") ); + + info = enif_make_new_map(env); + + NDBG( ("info -> done\r\n") ); + return info; } +/* ---------------------------------------------------------------------- + * nif_command + * + * Description: + * This is a general purpose utility function. + * + * Arguments: + * Command - This is a general purpose command, of any type. + * Currently, the only supported command is: + * + * {debug, boolean()} + */ +static +ERL_NIF_TERM nif_command(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM ecmd, result; + + NDBG( ("command -> entry (%d)\r\n", argc) ); + + if (argc != 1) + return enif_make_badarg(env); + + ecmd = argv[0]; + + NDBG( ("command -> ecmd: %T\r\n", ecmd) ); + + result = ncommand(env, ecmd); + + NDBG( ("command -> result: %T\r\n", result) ); + + return result; +} + + + +/* + * The command can, in principle, be anything, though currently we only + * support a debug command. + */ +static +ERL_NIF_TERM ncommand(ErlNifEnv* env, + ERL_NIF_TERM cmd) +{ + const ERL_NIF_TERM* t; + int tsz; + + if (IS_TUPLE(env, cmd)) { + /* Could be the debug tuple */ + if (!GET_TUPLE(env, cmd, &tsz, &t)) + return make_error(env, atom_einval); + + if (tsz != 2) + return make_error(env, atom_einval); + + /* First element should be the atom 'debug' */ + if (COMPARE(t[0], atom_debug) != 0) + return make_error(env, atom_einval); + + return decode_bool(env, t[1], &data.debug); + + } else { + return make_error(env, atom_einval); + } + +} + + + + /* ---------------------------------------------------------------------- * nif_getnameinfo * @@ -663,25 +770,36 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ERL_NIF_TERM eSockAddr; + ERL_NIF_TERM result, eSockAddr; unsigned int eFlags; int flags = 0; // Just in case... SockAddress sa; SOCKLEN_T saLen = 0; // Just in case... + NDBG( ("nif_getnameinfo -> entry (%d)\r\n", argc) ); + if ((argc != 2) || !GET_UINT(env, argv[1], &eFlags)) { return enif_make_badarg(env); } eSockAddr = argv[0]; + NDBG( ("nif_getnameinfo -> " + "\r\n SockAddr: %T" + "\r\n Flags: %T" + "\r\n", argv[0], argv[1]) ); + if (!decode_nameinfo_flags(env, eFlags, &flags)) return enif_make_badarg(env); if (decode_in_sockaddr(env, eSockAddr, &sa, &saLen)) return enif_make_badarg(env); - return ngetnameinfo(env, &sa, saLen, flags); + result = ngetnameinfo(env, &sa, saLen, flags); + + NDBG( ("nif_getnameinfo -> done when result: %T\r\n", result) ); + + return result; } @@ -781,6 +899,8 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, char* servName; // struct addrinfo* hints; + NDBG( ("nif_getaddrinfo -> entry (%d)\r\n", argc) ); + if (argc != 3) { return enif_make_badarg(env); } @@ -788,6 +908,12 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, eServName = argv[1]; // eHints = argv[2]; + NDBG( ("nif_getaddrinfo -> " + "\r\n Host: %T" + "\r\n Service: %T" + "\r\n Hints: %T" + "\r\n", argv[0], argv[1], argv[2]) ); + if (!decode_addrinfo_string(env, eHostName, &hostName)) return enif_make_badarg(env); @@ -815,6 +941,8 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, FREE(hints); */ + NDBG( ("nif_getaddrinfo -> done when result: %T\r\n", result) ); + return result; } @@ -907,18 +1035,28 @@ ERL_NIF_TERM nif_if_name2index(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ERL_NIF_TERM eifn; + ERL_NIF_TERM eifn, result; char ifn[IF_NAMESIZE+1]; + NDBG( ("nif_if_name2index -> entry (%d)\r\n", argc) ); + if (argc != 1) { return enif_make_badarg(env); } eifn = argv[0]; + NDBG( ("nif_name2index -> " + "\r\n Ifn: %T" + "\r\n", argv[0]) ); + if (0 >= GET_STR(env, eifn, ifn, sizeof(ifn))) return make_error2(env, atom_einval); - return nif_name2index(env, ifn); + result = nif_name2index(env, ifn); + + NDBG( ("nif_if_name2index -> done when result: %T\r\n", result) ); + + return result; } @@ -953,14 +1091,25 @@ ERL_NIF_TERM nif_if_index2name(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { + ERL_NIF_TERM result; unsigned int idx; + NDBG( ("nif_if_index2name -> entry (%d)\r\n", argc) ); + if ((argc != 1) || !GET_UINT(env, argv[0], &idx)) { return enif_make_badarg(env); } - return nif_index2name(env, idx); + NDBG( ("nif_index2name -> " + "\r\n Idx: %T" + "\r\n", argv[0]) ); + + result = nif_index2name(env, idx); + + NDBG( ("nif_if_index2name -> done when result: %T\r\n", result) ); + + return result; } @@ -1001,11 +1150,19 @@ ERL_NIF_TERM nif_if_names(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { + ERL_NIF_TERM result; + + NDBG( ("nif_if_names -> entry (%d)\r\n", argc) ); + if (argc != 0) { return enif_make_badarg(env); } - return nif_names(env); + result = nif_names(env); + + NDBG( ("nif_if_names -> done when result: %T\r\n", result) ); + + return result; } @@ -1016,6 +1173,8 @@ ERL_NIF_TERM nif_names(ErlNifEnv* env) ERL_NIF_TERM result; struct if_nameindex* ifs = if_nameindex(); + NDBG( ("nif_names -> ifs: 0x%lX\r\n", ifs) ); + if (ifs == NULL) { result = make_error2(env, get_errno()); } else { @@ -1033,6 +1192,8 @@ ERL_NIF_TERM nif_names(ErlNifEnv* env) */ unsigned int len = nif_names_length(ifs); + NDBG( ("nif_names -> len: %d\r\n", len) ); + if (len > 0) { ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM)); unsigned int i; @@ -1395,6 +1556,24 @@ BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, +static +ERL_NIF_TERM decode_bool(ErlNifEnv* env, + ERL_NIF_TERM eBool, + BOOLEAN_T* bool) +{ + if (COMPARE(eBool, atom_true) == 0) { + *bool = TRUE; + return atom_ok; + } else if (COMPARE(eBool, atom_false) == 0) { + *bool = FALSE; + return atom_ok; + } else { + return make_error(env, atom_einval); + } +} + + + /* Encode the address info * The address info is a linked list och address info, which * will result in the result being a list of zero or more length. @@ -1753,6 +1932,88 @@ void net_down(ErlNifEnv* env, +/* ---------------------------------------------------------------------- + * D e b u g F u n c t i o n s + * ---------------------------------------------------------------------- + */ + +/* + * Print a debug format string *with* both a timestamp and the + * the name of the *current* thread. + */ +static +void dbg_printf( const char* format, ... ) +{ + va_list args; + char f[512 + sizeof(format)]; // This has to suffice... + char stamp[30]; + struct timespec ts; + int res; + + /* + * We should really include self in the printout, so we can se which process + * are executing the code. But then I must change the API.... + * ....something for later. + */ + + if (!dbg_realtime(&ts)) { + if (dbg_timespec2str(stamp, sizeof(stamp), &ts) != 0) { + // res = enif_snprintf(f, sizeof(f), "NET [%s] %s", TSNAME(), format); + res = enif_snprintf(f, sizeof(f), "NET [%s]", format); + } else { + // res = enif_snprintf(f, sizeof(f), "NET[%s] [%s] %s", stamp, TSNAME(), format); + res = enif_snprintf(f, sizeof(f), "NET [%s] %s", stamp, format); + } + + if (res > 0) { + va_start (args, format); + erts_vfprintf (stdout, f, args); // TMP: use enif_vfprintf + va_end (args); + fflush(stdout); + } + } + + return; +} + + +static +int dbg_realtime(struct timespec* tsP) +{ + return clock_gettime(CLOCK_REALTIME, tsP); +} + + + + +/* + * Convert a timespec struct into a readable/printable string + */ +static +int dbg_timespec2str(char *buf, unsigned int len, struct timespec *ts) +{ + int ret, buflen; + struct tm t; + + tzset(); + if (localtime_r(&(ts->tv_sec), &t) == NULL) + return 1; + + ret = strftime(buf, len, "%F %T", &t); + if (ret == 0) + return 2; + len -= ret - 1; + buflen = strlen(buf); + + ret = snprintf(&buf[buflen], len, ".%06ld", ts->tv_nsec/1000); + if (ret >= len) + return 3; + + return 0; +} + + + /* ---------------------------------------------------------------------- * L o a d / u n l o a d / u p g r a d e F u n c t i o n s * ---------------------------------------------------------------------- @@ -1764,6 +2025,7 @@ ErlNifFunc net_funcs[] = // Some utility functions {"nif_is_loaded", 0, nif_is_loaded, 0}, {"nif_info", 0, nif_info, 0}, + {"nif_command", 1, nif_command, 0}, // Shall we let this be dirty? /* address and name translation in protocol-independent manner */ {"nif_getnameinfo", 2, nif_getnameinfo, 0}, @@ -1784,10 +2046,17 @@ ErlNifFunc net_funcs[] = static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { + // We should make it possible to use load_info to get default values + data.debug = FALSE; + + // NDBG( ("on_load -> entry\r\n") ); + /* +++ Misc atoms +++ */ atom_address_info = MKA(env, str_address_info); + atom_debug = MKA(env, str_debug); atom_dgram = MKA(env, str_dgram); atom_error = MKA(env, str_error); + atom_false = MKA(env, str_false); atom_idn = MKA(env, str_idn); atom_idna_allow_unassigned = MKA(env, str_idna_allow_unassigned); atom_idna_use_std3_ascii_rules = MKA(env, str_idna_use_std3_ascii_rules); @@ -1849,6 +2118,8 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) ERL_NIF_RT_CREATE, NULL); + // NDBG( ("on_load -> done\r\n") ); + return !net; } -- cgit v1.2.3 From f2a28200a826af65596bb554b014d2c93b6314a7 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 11 Jun 2018 14:40:58 +0200 Subject: [net-nif] Removed the old net module The old net module (in kernel) (deprecated) was removed and its function(s) has been moved into the new module. Also a minor updated to the info function. OTP-14831 --- erts/emulator/nifs/common/net_nif.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index 134b02d178..328fb52ac3 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -669,13 +669,15 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ERL_NIF_TERM info; + ERL_NIF_TERM info, tmp; NDBG( ("info -> entry\r\n") ); - info = enif_make_new_map(env); + tmp = enif_make_new_map(env); + if (!enif_make_map_put(env, tmp, atom_debug, BOOL2ATOM(data.debug), &info)) + info = tmp; - NDBG( ("info -> done\r\n") ); + NDBG( ("info -> done: %T\r\n", info) ); return info; } -- cgit v1.2.3 From 8c6d495f54207d019e645e5ff726418677f92ab9 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 11 Jun 2018 18:14:42 +0200 Subject: [net-nif] Implemented gethostname --- erts/emulator/nifs/common/net_nif.c | 93 ++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index 328fb52ac3..d623c6f246 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -215,6 +215,13 @@ typedef unsigned int BOOLEAN_T; typedef unsigned long long llu_t; +#ifdef __WIN32__ +#define net_gethostname(__buf__, __bufSz__) gethostname((__buf__), (__bufSz__)) +#else +#define net_gethostname(__buf__, __bufSz__) gethostname((__buf__), (__bufSz__)) +#endif // __WIN32__ + + /* Socket stuff */ // #define INVALID_SOCKET -1 @@ -244,6 +251,12 @@ typedef unsigned long long llu_t; #define SERVICE_LEN 256 +/* MAXHOSTNAMELEN could be 64 or 255 depending + * on the platform. Instead, use INET_MAXHOSTNAMELEN + * which is always 255 across all platforms + */ +#define NET_MAXHOSTNAMELEN 255 + /* =================================================================== * * * * Various enif macros * @@ -364,10 +377,13 @@ static ERL_NIF_TERM nif_command(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, +static ERL_NIF_TERM nif_gethostname(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]); static ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -384,6 +400,7 @@ static ERL_NIF_TERM nif_if_names(ErlNifEnv* env, static ERL_NIF_TERM ncommand(ErlNifEnv* env, ERL_NIF_TERM cmd); +static ERL_NIF_TERM ngethostname(ErlNifEnv* env); static ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, const SockAddress* saP, SOCKLEN_T saLen, @@ -531,9 +548,11 @@ static char str_eagain[] = "eagain"; static char str_ebadflags[] = "ebadflags"; static char str_efail[] = "efail"; static char str_efamily[] = "efamily"; +static char str_efault[] = "efault"; static char str_einval[] = "einval"; // static char str_eisconn[] = "eisconn"; static char str_emem[] = "emem"; +static char str_enametoolong[] = "enametoolong"; static char str_enodata[] = "enodata"; static char str_enoname[] = "enoname"; // static char str_enotclosing[] = "enotclosing"; @@ -588,9 +607,11 @@ static ERL_NIF_TERM atom_eagain; static ERL_NIF_TERM atom_ebadflags; static ERL_NIF_TERM atom_efail; static ERL_NIF_TERM atom_efamily; +static ERL_NIF_TERM atom_efault; static ERL_NIF_TERM atom_einval; // static ERL_NIF_TERM atom_eisconn; static ERL_NIF_TERM atom_emem; +static ERL_NIF_TERM atom_enametoolong; static ERL_NIF_TERM atom_enodata; static ERL_NIF_TERM atom_enoname; // static ERL_NIF_TERM atom_enotclosing; @@ -754,6 +775,71 @@ ERL_NIF_TERM ncommand(ErlNifEnv* env, +/* ---------------------------------------------------------------------- + * nif_gethostname + * + * Description: + * Access the hostname of the current processor. + * + */ +static +ERL_NIF_TERM nif_gethostname(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM result; + + NDBG( ("nif_gethostname -> entry (%d)\r\n", argc) ); + + if (argc != 0) + return enif_make_badarg(env); + + result = ngethostname(env); + + NDBG( ("nif_gethostname -> done when result: %T\r\n", result) ); + + return result; +} + + +static +ERL_NIF_TERM ngethostname(ErlNifEnv* env) +{ + ERL_NIF_TERM result; + char buf[NET_MAXHOSTNAMELEN + 1]; + int res; + + res = net_gethostname(buf, sizeof(buf)); + + NDBG( ("ngethostname -> gethostname res: %d\r\n", res) ); + + switch (res) { + case 0: + result = make_ok2(env, MKS(env, buf)); + break; + + case EFAULT: + result = make_error(env, atom_efault); + break; + + case EINVAL: + result = make_error(env, atom_einval); + break; + + case ENAMETOOLONG: + result = make_error(env, atom_enametoolong); + break; + + default: + result = make_error(env, MKI(env, res)); + break; + } + + return result; +} + + + /* ---------------------------------------------------------------------- * nif_getnameinfo @@ -2029,6 +2115,9 @@ ErlNifFunc net_funcs[] = {"nif_info", 0, nif_info, 0}, {"nif_command", 1, nif_command, 0}, // Shall we let this be dirty? + /* get/set hostname */ + {"nif_gethostname", 0, nif_gethostname, 0}, + /* address and name translation in protocol-independent manner */ {"nif_getnameinfo", 2, nif_getnameinfo, 0}, {"nif_getaddrinfo", 3, nif_getaddrinfo, 0}, @@ -2090,9 +2179,11 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_ebadflags = MKA(env, str_ebadflags); atom_efail = MKA(env, str_efail); atom_efamily = MKA(env, str_efamily); + atom_efault = MKA(env, str_efault); atom_einval = MKA(env, str_einval); // atom_eisconn = MKA(env, str_eisconn); atom_emem = MKA(env, str_emem); + atom_enametoolong = MKA(env, str_enametoolong); atom_enodata = MKA(env, str_enodata); atom_enoname = MKA(env, str_enoname); // atom_enotclosing = MKA(env, str_enotclosing); -- cgit v1.2.3 From d892681a4554b08442db219c3ac161027e9a4c4f Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 12 Jun 2018 15:06:03 +0200 Subject: [net-nif] Fixed things... Fixed functions getaddrinfo, if_index2name, if_name2index and if_names. OTP-14831 --- erts/emulator/nifs/common/net_nif.c | 162 +++++++++++++++++++++++++++++------- 1 file changed, 130 insertions(+), 32 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index d623c6f246..900828c7b2 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -514,6 +514,7 @@ static const struct in6_addr in6addr_loopback = /* *** String constants *** */ static char str_address_info[] = "address_info"; +static char str_dccp[] = "dccp"; static char str_debug[] = "debug"; static char str_dgram[] = "dgram"; static char str_error[] = "error"; @@ -530,6 +531,9 @@ static char str_nofqdn[] = "nofqdn"; static char str_numerichost[] = "numerichost"; static char str_numericserv[] = "numericserv"; static char str_ok[] = "ok"; +static char str_raw[] = "raw"; +static char str_rdm[] = "rdm"; +static char str_seqpacket[] = "seqpacket"; static char str_stream[] = "stream"; static char str_tcp[] = "tcp"; static char str_true[] = "true"; @@ -557,6 +561,7 @@ static char str_enodata[] = "enodata"; static char str_enoname[] = "enoname"; // static char str_enotclosing[] = "enotclosing"; // static char str_enotconn[] = "enotconn"; +static char str_enxio[] = "enxio"; static char str_eoverflow[] = "eoverflow"; static char str_eservice[] = "eservice"; static char str_esocktype[] = "esocktype"; @@ -572,6 +577,7 @@ static char str_esystem[] = "esystem"; /* *** Atoms *** */ static ERL_NIF_TERM atom_address_info; +static ERL_NIF_TERM atom_dccp; static ERL_NIF_TERM atom_debug; static ERL_NIF_TERM atom_dgram; static ERL_NIF_TERM atom_error; @@ -588,8 +594,11 @@ static ERL_NIF_TERM atom_nofqdn; static ERL_NIF_TERM atom_numerichost; static ERL_NIF_TERM atom_numericserv; static ERL_NIF_TERM atom_ok; +static ERL_NIF_TERM atom_raw; +static ERL_NIF_TERM atom_rdm; // static ERL_NIF_TERM atom_select; static ERL_NIF_TERM atom_stream; +static ERL_NIF_TERM atom_seqpacket; // static ERL_NIF_TERM atom_timeout; static ERL_NIF_TERM atom_tcp; static ERL_NIF_TERM atom_true; @@ -616,6 +625,7 @@ static ERL_NIF_TERM atom_enodata; static ERL_NIF_TERM atom_enoname; // static ERL_NIF_TERM atom_enotclosing; // static ERL_NIF_TERM atom_enotconn; +static ERL_NIF_TERM atom_enxio; static ERL_NIF_TERM atom_eoverflow; static ERL_NIF_TERM atom_eservice; static ERL_NIF_TERM atom_esocktype; @@ -1029,7 +1039,8 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, FREE(hints); */ - NDBG( ("nif_getaddrinfo -> done when result: %T\r\n", result) ); + NDBG( ("nif_getaddrinfo -> done when result: " + "\r\n %T\r\n", result) ); return result; } @@ -1044,8 +1055,17 @@ ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env, struct addrinfo* addrInfoP; int res; + NDBG( ("ngetaddrinfo -> entry with" + "\r\n host: %s" + "\r\n serv: %s" + "\r\n", + ((host == NULL) ? "NULL" : host), + ((serv == NULL) ? "NULL" : serv)) ); + res = getaddrinfo(host, serv, NULL, &addrInfoP); + NDBG( ("ngetaddrinfo -> res: %d\r\n", res) ); + switch (res) { case 0: { @@ -1133,7 +1153,7 @@ ERL_NIF_TERM nif_if_name2index(ErlNifEnv* env, } eifn = argv[0]; - NDBG( ("nif_name2index -> " + NDBG( ("nif_if_name2index -> " "\r\n Ifn: %T" "\r\n", argv[0]) ); @@ -1153,12 +1173,18 @@ static ERL_NIF_TERM nif_name2index(ErlNifEnv* env, char* ifn) { - unsigned int idx = if_nametoindex(ifn); + unsigned int idx; + + NDBG( ("nif_name2index -> entry with ifn: %s\r\n", ifn) ); + + idx = if_nametoindex(ifn); - if (idx == 0) + NDBG( ("nif_name2index -> idx: %d\r\n", idx) ); + + if (idx == 0) return make_error2(env, get_errno()); else - return make_ok2(env, idx); + return make_ok2(env, MKI(env, idx)); } @@ -1212,10 +1238,10 @@ ERL_NIF_TERM nif_index2name(ErlNifEnv* env, if (ifn == NULL) return enif_make_badarg(env); // PLACEHOLDER - if (NULL == if_indextoname(idx, ifn)) { + if (NULL != if_indextoname(idx, ifn)) { result = make_ok2(env, MKS(env, ifn)); } else { - result = make_error2(env, get_errno()); + result = make_error(env, atom_enxio); } FREE(ifn); @@ -1310,9 +1336,19 @@ static unsigned int nif_names_length(struct if_nameindex* p) { unsigned int len = 0; + BOOLEAN_T done = FALSE; + + while (!done) { + + NDBG( ("nif_names_length -> %d: " + "\r\n if_index: %d" + "\r\n if_name: 0x%lX" + "\r\n", len, p[len].if_index, p[len].if_name) ); - while ((p[len].if_index == 0) && (p[len].if_name == NULL)) { - len++; + if ((p[len].if_index == 0) && (p[len].if_name == NULL)) + done = TRUE; + else + len++; } return len; @@ -1627,9 +1663,13 @@ BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, result = FALSE; } - bufP = MALLOC(len); + NDBG( ("decode_addrinfo_string -> len: %d\r\n", len) ); + + bufP = MALLOC(len + 1); // We shall NULL-terminate - if (GET_STR(env, eString, bufP, len)) { + if (GET_STR(env, eString, bufP, len+1)) { + NDBG( ("decode_addrinfo_string -> buf: %s\r\n", bufP) ); + // bufP[len] = '\0'; *stringP = bufP; result = TRUE; } else { @@ -1673,19 +1713,32 @@ ERL_NIF_TERM encode_address_info(ErlNifEnv* env, ERL_NIF_TERM result; unsigned int len = address_info_length(addrInfo); - if (len > 0) { - ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM)); - unsigned int i; + NDBG( ("encode_address_info -> len: %d\r\n", len) ); + if (len > 0) { + ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM)); + unsigned int i = 0; + struct addrinfo* p = addrInfo; + + while (i < len) { + array[i] = make_address_info(env, p); + p = p->ai_next; + i++; + } + /* for (i = 0; i < len; i++) { array[i] = make_address_info(env, &addrInfo[i]); } + */ - result = make_ok2(env, MKLA(env, array, len)); + result = MKLA(env, array, len); } else { result = MKEL(env); } + NDBG( ("encode_address_info -> result: " + "\r\n %T\r\n", result) ); + return result; } @@ -1698,17 +1751,19 @@ ERL_NIF_TERM encode_address_info(ErlNifEnv* env, static unsigned int address_info_length(struct addrinfo* addrInfoP) { - unsigned int len; - struct addrinfo* tmp = addrInfoP; + unsigned int len = 1; + struct addrinfo* tmp; + BOOLEAN_T done = FALSE; - if (tmp != NULL) { - len = 1; - while (tmp->ai_next != NULL) { - tmp = tmp->ai_next; + tmp = addrInfoP; + + while (!done) { + if (tmp->ai_next != NULL) { len++; + tmp = tmp->ai_next; + } else { + done = TRUE; } - } else { - len = 0; } return len; @@ -1725,14 +1780,27 @@ static ERL_NIF_TERM make_address_info(ErlNifEnv* env, struct addrinfo* addrInfoP) { - ERL_NIF_TERM Fam = make_addrinfo_family(env, addrInfoP->ai_family); - ERL_NIF_TERM Type = make_addrinfo_type(env, addrInfoP->ai_socktype); - ERL_NIF_TERM Proto = make_addrinfo_proto(env, addrInfoP->ai_protocol); - ERL_NIF_TERM Addr = make_addrinfo_addr(env, - addrInfoP->ai_addr, - addrInfoP->ai_addrlen); + ERL_NIF_TERM result, fam, type, proto, addr; + + fam = make_addrinfo_family(env, addrInfoP->ai_family); + // NDBG( ("make_address_info -> fam: %T\r\n", fam) ); + type = make_addrinfo_type(env, addrInfoP->ai_socktype); + // NDBG( ("make_address_info -> type: %T\r\n", type) ); + proto = make_addrinfo_proto(env, addrInfoP->ai_protocol); + // NDBG( ("make_address_info -> proto: %T\r\n", proto) ); + addr = make_addrinfo_addr(env, + addrInfoP->ai_addr, + addrInfoP->ai_addrlen); + // NDBG( ("make_address_info -> addr: %T\r\n", addr) ); + + result = MKT5(env, atom_address_info, fam, type, proto, addr); - return MKT5(env, atom_address_info, Fam, Type, Proto, Addr); + /* + NDBG( ("make_address_info -> result: " + "\r\n %T\r\n", result) ); + */ + + return result; } @@ -1789,6 +1857,22 @@ ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env, etype = atom_dgram; break; + case SOCK_RAW: + etype = atom_raw; + break; + + case SOCK_RDM: + etype = atom_rdm; + break; + + case SOCK_SEQPACKET: + etype = atom_seqpacket; + break; + + case SOCK_DCCP: + etype = atom_dccp; + break; + default: etype = MKI(env, socktype); break; @@ -1850,11 +1934,16 @@ ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, ERL_NIF_TERM port, addr, eaddr; SockAddress* p = (SockAddress*) addrP; + NDBG( ("make_addrinfo_addr -> entry with" + "\r\n family: %d" + "\r\n addrLen: %d" + "\r\n", addrP->sa_family, addrLen) ); + switch (addrP->sa_family) { case AF_INET: { unsigned char* a = (unsigned char*) &p->in.sin_addr; - port = ntohs(p->in.sin_port); + port = MKI(env, ntohs(p->in.sin_port)); addr = MKT4(env, MKI(env, a[0]), MKI(env, a[1]), @@ -1868,7 +1957,7 @@ ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, case AF_INET6: { unsigned char* a = (unsigned char*) &p->in6.sin6_addr; - port = ntohs(p->in6.sin6_port); + port = MKI(env, ntohs(p->in6.sin6_port)); addr = MKT8(env, MKI(env, get_int16(a)), MKI(env, get_int16(&a[ 2])), @@ -1888,6 +1977,9 @@ ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, break; } + NDBG( ("make_addrinfo_addr -> eaddr: " + "\r\n %T\r\n", eaddr) ); + return eaddr; } @@ -1948,6 +2040,7 @@ ERL_NIF_TERM make_error1(ErlNifEnv* env, char* reason) static ERL_NIF_TERM make_error2(ErlNifEnv* env, int err) { + NDBG( ("make_error2 -> err: %d\r\n", err) ); return make_error1(env, erl_errno_id(err)); } @@ -2144,6 +2237,7 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) /* +++ Misc atoms +++ */ atom_address_info = MKA(env, str_address_info); + atom_dccp = MKA(env, str_dccp); atom_debug = MKA(env, str_debug); atom_dgram = MKA(env, str_dgram); atom_error = MKA(env, str_error); @@ -2160,6 +2254,9 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_numerichost = MKA(env, str_numerichost); atom_numericserv = MKA(env, str_numericserv); atom_ok = MKA(env, str_ok); + atom_raw = MKA(env, str_raw); + atom_rdm = MKA(env, str_rdm); + atom_seqpacket = MKA(env, str_seqpacket); atom_stream = MKA(env, str_stream); atom_tcp = MKA(env, str_tcp); atom_true = MKA(env, str_true); @@ -2188,6 +2285,7 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_enoname = MKA(env, str_enoname); // atom_enotclosing = MKA(env, str_enotclosing); // atom_enotconn = MKA(env, str_enotconn); + atom_enxio = MKA(env, str_enxio); atom_eoverflow = MKA(env, str_eoverflow); atom_eservice = MKA(env, str_eservice); atom_esocktype = MKA(env, str_esocktype); -- cgit v1.2.3 From ef34944c970f842a7406f59c827243c8be77fdc2 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 12 Jun 2018 15:47:29 +0200 Subject: [net-nif] Fixed getnameinfo And now fixed the getnameinfo function. OTP-14831 --- erts/emulator/nifs/common/net_nif.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index 900828c7b2..e0129aec69 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -659,6 +659,7 @@ static ErlNifResourceTypeInit netInit = { * * The "proper" net functions: * ------------------------------ + * nif_gethostname/0 * nif_getnameinfo/2 * nif_getaddrinfo/3 * nif_if_name2index/1 @@ -860,7 +861,6 @@ ERL_NIF_TERM ngethostname(ErlNifEnv* env) * Arguments: * SockAddr - Socket Address (address and port) * Flags - The flags argument modifies the behavior of getnameinfo(). - * Not used! */ static @@ -869,33 +869,33 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM result, eSockAddr; - unsigned int eFlags; + ERL_NIF_TERM eFlags; int flags = 0; // Just in case... SockAddress sa; SOCKLEN_T saLen = 0; // Just in case... NDBG( ("nif_getnameinfo -> entry (%d)\r\n", argc) ); - if ((argc != 2) || - !GET_UINT(env, argv[1], &eFlags)) { + if (argc != 2) return enif_make_badarg(env); - } eSockAddr = argv[0]; + eFlags = argv[1]; NDBG( ("nif_getnameinfo -> " "\r\n SockAddr: %T" "\r\n Flags: %T" - "\r\n", argv[0], argv[1]) ); + "\r\n", eSockAddr, eFlags) ); if (!decode_nameinfo_flags(env, eFlags, &flags)) return enif_make_badarg(env); - if (decode_in_sockaddr(env, eSockAddr, &sa, &saLen)) + if (!decode_in_sockaddr(env, eSockAddr, &sa, &saLen)) return enif_make_badarg(env); result = ngetnameinfo(env, &sa, saLen, flags); - NDBG( ("nif_getnameinfo -> done when result: %T\r\n", result) ); + NDBG( ("nif_getnameinfo -> done when result: " + "\r\n %T\r\n", result) ); return result; } @@ -922,6 +922,8 @@ ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, serv, servLen, flags); + NDBG( ("ngetnameinfo -> res: %d\r\n", res) ); + switch (res) { case 0: { @@ -1569,6 +1571,7 @@ BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env, result = FALSE; } } else if (IS_LIST(env, eflags)) { + NDBG( ("decode_nameinfo_flags -> is atom\r\n") ); result = decode_nameinfo_flags_list(env, eflags, flags); } else { result = FALSE; -- cgit v1.2.3 From 1b31432a2c60364dc3e7b2a18fa8494475344271 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 15 Jun 2018 18:51:48 +0200 Subject: [socket+net-nif] Introduced a couple of common files Started to move the common stuff, such as common utility functions, debug and encode / decode of basic types. OTP-14831 --- erts/emulator/nifs/common/net_nif.c | 511 +++++++++++++++++++++++++++--------- 1 file changed, 389 insertions(+), 122 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index e0129aec69..90263d11c2 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -174,6 +174,9 @@ #include +#include "socket_dbg.h" +#include "socket_int.h" + /* All platforms fail on malloc errors. */ #define FATAL_MALLOC @@ -263,66 +266,67 @@ typedef unsigned long long llu_t; * * * =================================================================== */ -#define MALLOC(SZ) enif_alloc((SZ)) -#define FREE(P) enif_free((P)) - -#define MKA(E,S) enif_make_atom((E), (S)) -#define MKBIN(E,B) enif_make_binary((E), (B)) -#define MKI(E,I) enif_make_int((E), (I)) -#define MKLA(E,A,L) enif_make_list_from_array((E), (A), (L)) -#define MKEL(E) enif_make_list((E), 0) -#define MKREF(E) enif_make_ref((E)) -#define MKS(E,S) enif_make_string((E), (S), ERL_NIF_LATIN1) -#define MKSL(E,S,L) enif_make_string_len((E), (S), (L), ERL_NIF_LATIN1) -#define MKSBIN(E,B,ST,SZ) enif_make_sub_binary((E), (B), (ST), (SZ)) -#define MKT2(E,E1,E2) enif_make_tuple2((E), (E1), (E2)) -#define MKT3(E,E1,E2,E3) enif_make_tuple3((E), (E1), (E2), (E3)) -#define MKT4(E,E1,E2,E3,E4) enif_make_tuple4((E), (E1), (E2), (E3), (E4)) -#define MKT5(E,E1,E2,E3,E4,E5) \ - enif_make_tuple5((E), (E1), (E2), (E3), (E4), (E5)) -#define MKT8(E,E1,E2,E3,E4,E5,E6,E7,E8) \ - enif_make_tuple8((E), (E1), (E2), (E3), (E4), (E5), (E6), (E7), (E8)) - -#define MCREATE(N) enif_mutex_create((N)) -#define MDESTROY(M) enif_mutex_destroy((M)) -#define MLOCK(M) enif_mutex_lock((M)) -#define MUNLOCK(M) enif_mutex_unlock((M)) - -#define MONP(E,D,P,M) enif_monitor_process((E), (D), (P), (M)) -#define DEMONP(E,D,M) enif_demonitor_process((E), (D), (M)) - -#define SELECT(E,FD,M,O,P,R) \ - enif_select((E), (FD), (M), (O), (P), (R)) -#define SELECT_READ(E, DP, P, R) \ - SELECT((E), (DP)->sock, (ERL_NIF_SELECT_READ), (DP), (P), (R)) -#define SELECT_WRITE(E, DP, P, R) \ - SELECT((E), (DP)->sock, (ERL_NIF_SELECT_WRITE), (DP), (P), (R)) -#define SELECT_STOP(E, DP) \ - enif_select((E), (DP)->sock, (ERL_NIF_SELECT_STOP), (DP), NULL, atom_undefined) - -#define IS_ATOM(E, TE) enif_is_atom((E), (TE)) -#define IS_BIN(E, TE) enif_is_binary((E), (TE)) -#define IS_NUM(E, TE) enif_is_number((E), (TE)) -#define IS_TUPLE(E, TE) enif_is_tuple((E), (TE)) -#define IS_LIST(E, TE) enif_is_list((E), (TE)) - -#define COMPARE(L, R) enif_compare((L), (R)) - -#define GET_ATOM_LEN(E, TE, LP) \ - enif_get_atom_length((E), (TE), (LP), ERL_NIF_LATIN1) -#define GET_ATOM(E, TE, BP, MAX) \ - enif_get_atom((E), (TE), (BP), (MAX), ERL_NIF_LATIN1) -#define GET_BIN(E, TE, BP) enif_inspect_iolist_as_binary((E), (TE), (BP)) -#define GET_INT(E, TE, IP) enif_get_int((E), (TE), (IP)) -#define GET_LIST_ELEM(E, L, HP, TP) enif_get_list_cell((E), (L), (HP), (TP)) -#define GET_LIST_LEN(E, L, LP) enif_get_list_length((E), (L), (LP)) -#define GET_STR(E, L, B, SZ) \ - enif_get_string((E), (L), (B), (SZ), ERL_NIF_LATIN1) -#define GET_UINT(E, TE, IP) enif_get_uint((E), (TE), (IP)) -#define GET_TUPLE(E, TE, TSZ, TA) enif_get_tuple((E), (TE), (TSZ), (TA)) - -#define ALLOC_BIN(SZ, BP) enif_alloc_binary((SZ), (BP)) -#define REALLOC_BIN(SZ, BP) enif_realloc_binary((SZ), (BP)) +/* #define MALLOC(SZ) enif_alloc((SZ)) */ +/* #define FREE(P) enif_free((P)) */ + +/* #define MKA(E,S) enif_make_atom((E), (S)) */ +/* #define MKBIN(E,B) enif_make_binary((E), (B)) */ +/* #define MKI(E,I) enif_make_int((E), (I)) */ +/* #define MKLA(E,A,L) enif_make_list_from_array((E), (A), (L)) */ +/* #define MKEL(E) enif_make_list((E), 0) */ +/* #define MKREF(E) enif_make_ref((E)) */ +/* #define MKS(E,S) enif_make_string((E), (S), ERL_NIF_LATIN1) */ +/* #define MKSL(E,S,L) enif_make_string_len((E), (S), (L), ERL_NIF_LATIN1) */ +/* #define MKSBIN(E,B,ST,SZ) enif_make_sub_binary((E), (B), (ST), (SZ)) */ +/* #define MKT2(E,E1,E2) enif_make_tuple2((E), (E1), (E2)) */ +/* #define MKT3(E,E1,E2,E3) enif_make_tuple3((E), (E1), (E2), (E3)) */ +/* #define MKT4(E,E1,E2,E3,E4) enif_make_tuple4((E), (E1), (E2), (E3), (E4)) */ +/* #define MKT5(E,E1,E2,E3,E4,E5) \ */ +/* enif_make_tuple5((E), (E1), (E2), (E3), (E4), (E5)) */ +/* #define MKT8(E,E1,E2,E3,E4,E5,E6,E7,E8) \ */ +/* enif_make_tuple8((E), (E1), (E2), (E3), (E4), (E5), (E6), (E7), (E8)) */ +/* #define MKTA(E, A, AL) enif_make_tuple_from_array((E), (A), (AL)) */ + +/* #define MCREATE(N) enif_mutex_create((N)) */ +/* #define MDESTROY(M) enif_mutex_destroy((M)) */ +/* #define MLOCK(M) enif_mutex_lock((M)) */ +/* #define MUNLOCK(M) enif_mutex_unlock((M)) */ + +/* #define MONP(E,D,P,M) enif_monitor_process((E), (D), (P), (M)) */ +/* #define DEMONP(E,D,M) enif_demonitor_process((E), (D), (M)) */ + +/* #define SELECT(E,FD,M,O,P,R) \ */ +/* enif_select((E), (FD), (M), (O), (P), (R)) */ +/* #define SELECT_READ(E, DP, P, R) \ */ +/* SELECT((E), (DP)->sock, (ERL_NIF_SELECT_READ), (DP), (P), (R)) */ +/* #define SELECT_WRITE(E, DP, P, R) \ */ +/* SELECT((E), (DP)->sock, (ERL_NIF_SELECT_WRITE), (DP), (P), (R)) */ +/* #define SELECT_STOP(E, DP) \ */ +/* enif_select((E), (DP)->sock, (ERL_NIF_SELECT_STOP), (DP), NULL, atom_undefined) */ + +/* #define IS_ATOM(E, TE) enif_is_atom((E), (TE)) */ +/* #define IS_BIN(E, TE) enif_is_binary((E), (TE)) */ +/* #define IS_NUM(E, TE) enif_is_number((E), (TE)) */ +/* #define IS_TUPLE(E, TE) enif_is_tuple((E), (TE)) */ +/* #define IS_LIST(E, TE) enif_is_list((E), (TE)) */ + +/* #define COMPARE(L, R) enif_compare((L), (R)) */ + +/* #define GET_ATOM_LEN(E, TE, LP) \ */ +/* enif_get_atom_length((E), (TE), (LP), ERL_NIF_LATIN1) */ +/* #define GET_ATOM(E, TE, BP, MAX) \ */ +/* enif_get_atom((E), (TE), (BP), (MAX), ERL_NIF_LATIN1) */ +/* #define GET_BIN(E, TE, BP) enif_inspect_iolist_as_binary((E), (TE), (BP)) */ +/* #define GET_INT(E, TE, IP) enif_get_int((E), (TE), (IP)) */ +/* #define GET_LIST_ELEM(E, L, HP, TP) enif_get_list_cell((E), (L), (HP), (TP)) */ +/* #define GET_LIST_LEN(E, L, LP) enif_get_list_length((E), (L), (LP)) */ +/* #define GET_STR(E, L, B, SZ) \ */ +/* enif_get_string((E), (L), (B), (SZ), ERL_NIF_LATIN1) */ +/* #define GET_UINT(E, TE, IP) enif_get_uint((E), (TE), (IP)) */ +/* #define GET_TUPLE(E, TE, TSZ, TA) enif_get_tuple((E), (TE), (TSZ), (TA)) */ + +/* #define ALLOC_BIN(SZ, BP) enif_alloc_binary((SZ), (BP)) */ +/* #define REALLOC_BIN(SZ, BP) enif_realloc_binary((SZ), (BP)) */ #ifdef HAVE_SOCKLEN_T @@ -342,12 +346,16 @@ typedef unsigned long long llu_t; typedef union { struct sockaddr sa; - struct sockaddr_in in; + struct sockaddr_in in4; #ifdef HAVE_IN6 struct sockaddr_in6 in6; #endif +#ifdef HAVE_SYS_UN_H + struct sockaddr_un un; +#endif + } SockAddress; typedef struct { @@ -440,6 +448,22 @@ static BOOLEAN_T decode_in6_sockaddr(ErlNifEnv* env, SockAddress* saP, SOCKLEN_T* saLen); #endif +static ERL_NIF_TERM encode_in_sockaddr(ErlNifEnv* env, + struct sockaddr* addrP, + SOCKLEN_T addrLen); +static ERL_NIF_TERM encode_in4_sockaddr(ErlNifEnv* env, + struct sockaddr_in* addrP, + SOCKLEN_T addrLen); +#if defined(HAVE_IN6) && defined(AF_INET6) +static ERL_NIF_TERM encode_in6_sockaddr(ErlNifEnv* env, + struct sockaddr_in6* addrP, + SOCKLEN_T addrLen); +#endif +#ifdef HAVE_SYS_UN_H +static ERL_NIF_TERM encode_un_sockaddr(ErlNifEnv* env, + struct sockaddr_un* addrP, + SOCKLEN_T addrLen); +#endif static BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env, const ERL_NIF_TERM eflags, int* flags); @@ -453,28 +477,50 @@ BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, static ERL_NIF_TERM decode_bool(ErlNifEnv* env, ERL_NIF_TERM eBool, BOOLEAN_T* bool); +static ERL_NIF_TERM encode_address_infos(ErlNifEnv* env, + struct addrinfo* addrInfo); static ERL_NIF_TERM encode_address_info(ErlNifEnv* env, - struct addrinfo* addrInfo); + struct addrinfo* addrInfoP); static unsigned int address_info_length(struct addrinfo* addrInfoP); -static ERL_NIF_TERM make_address_info(ErlNifEnv* env, - struct addrinfo* addrInfoP); -static ERL_NIF_TERM make_addrinfo_family(ErlNifEnv* env, +static ERL_NIF_TERM encode_address_info_family(ErlNifEnv* env, int family); -static ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env, +static ERL_NIF_TERM encode_address_info_type(ErlNifEnv* env, int socktype); -static ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env, +static ERL_NIF_TERM encode_address_info_proto(ErlNifEnv* env, int proto); -static ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, - struct sockaddr* addrP, - SOCKLEN_T addrLen); +/* static ERL_NIF_TERM make_address_info(ErlNifEnv* env, */ +/* struct addrinfo* addrInfoP); */ +/* static ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, */ +/* struct sockaddr* addrP, */ +/* SOCKLEN_T addrLen); */ + +static ERL_NIF_TERM make_in4_sockaddr(ErlNifEnv* env, + ERL_NIF_TERM port, + ERL_NIF_TERM addr); +#if defined(HAVE_IN6) && defined(AF_INET6) +static ERL_NIF_TERM make_in6_sockaddr(ErlNifEnv* env, + ERL_NIF_TERM port, + ERL_NIF_TERM addr, + ERL_NIF_TERM flowInfo, + ERL_NIF_TERM scopeId); +#endif +static ERL_NIF_TERM make_address_info(ErlNifEnv* env, + ERL_NIF_TERM fam, + ERL_NIF_TERM sockType, + ERL_NIF_TERM proto, + ERL_NIF_TERM addr); static ERL_NIF_TERM make_ok2(ErlNifEnv* env, ERL_NIF_TERM val); // static ERL_NIF_TERM make_ok3(ErlNifEnv* env, ERL_NIF_TERM val1, ERL_NIF_TERM val2); static ERL_NIF_TERM make_error(ErlNifEnv* env, ERL_NIF_TERM reason); static ERL_NIF_TERM make_error1(ErlNifEnv* env, char* reason); static ERL_NIF_TERM make_error2(ErlNifEnv* env, int err); +#if defined(HAVE_SYS_UN_H) || defined(SO_BINDTODEVICE) +static size_t my_strnlen(const char *s, size_t maxlen); +#endif + static void dbg_printf( const char* format, ... ); static int dbg_realtime(struct timespec* tsP); static int dbg_timespec2str(char *buf, unsigned int len, struct timespec *ts); @@ -522,9 +568,12 @@ static char str_false[] = "false"; static char str_idn[] = "idn"; static char str_idna_allow_unassigned[] = "idna_allow_unassigned"; static char str_idna_use_std3_ascii_rules[] = "idna_use_std3_ascii_rules"; +static char str_in4_sockaddr[] = "in4_sockaddr"; +static char str_in6_sockaddr[] = "in6_sockaddr"; static char str_inet[] = "inet"; static char str_inet6[] = "inet6"; static char str_ip[] = "ip"; +static char str_ipv6[] = "ipv6"; static char str_namereqd[] = "namereqd"; static char str_name_info[] = "name_info"; static char str_nofqdn[] = "nofqdn"; @@ -585,9 +634,12 @@ static ERL_NIF_TERM atom_false; static ERL_NIF_TERM atom_idn; static ERL_NIF_TERM atom_idna_allow_unassigned; static ERL_NIF_TERM atom_idna_use_std3_ascii_rules; +static ERL_NIF_TERM atom_in4_sockaddr; +static ERL_NIF_TERM atom_in6_sockaddr; static ERL_NIF_TERM atom_inet; static ERL_NIF_TERM atom_inet6; static ERL_NIF_TERM atom_ip; +static ERL_NIF_TERM atom_ipv6; static ERL_NIF_TERM atom_namereqd; static ERL_NIF_TERM atom_name_info; static ERL_NIF_TERM atom_nofqdn; @@ -1009,9 +1061,9 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, // eHints = argv[2]; NDBG( ("nif_getaddrinfo -> " - "\r\n Host: %T" - "\r\n Service: %T" - "\r\n Hints: %T" + "\r\n ehost: %T" + "\r\n eservice: %T" + "\r\n ehints: %T" "\r\n", argv[0], argv[1], argv[2]) ); if (!decode_addrinfo_string(env, eHostName, &hostName)) @@ -1071,7 +1123,7 @@ ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env, switch (res) { case 0: { - ERL_NIF_TERM addrInfo = encode_address_info(env, addrInfoP); + ERL_NIF_TERM addrInfo = encode_address_infos(env, addrInfoP); freeaddrinfo(addrInfoP); result = make_ok2(env, addrInfo); } @@ -1454,14 +1506,14 @@ BOOLEAN_T decode_in4_sockaddr(ErlNifEnv* env, /* And finally initialize the sockaddr structure (and size) */ sys_memzero((char*)saP, sizeof(struct sockaddr_in)); - saP->in.sin_family = AF_INET; - saP->in.sin_port = htons(port); + saP->in4.sin_family = AF_INET; + saP->in4.sin_port = htons(port); for (a = 0; a < 4; a++) { if (!GET_INT(env, ipAddrT[a], &v)) return FALSE; addr[a] = v; } - sys_memcpy(&saP->in.sin_addr, &addr, sizeof(addr)); + sys_memcpy(&saP->in4.sin_addr, &addr, sizeof(addr)); *saLen = sizeof(struct sockaddr_in); return TRUE; } @@ -1552,6 +1604,168 @@ BOOLEAN_T decode_in6_sockaddr(ErlNifEnv* env, +static +ERL_NIF_TERM encode_in_sockaddr(ErlNifEnv* env, + struct sockaddr* addrP, + SOCKLEN_T addrLen) +{ + SockAddress* sockAddrP = (SockAddress*) addrP; + ERL_NIF_TERM sockAddr; + + switch (sockAddrP->sa.sa_family) { + case AF_INET: + sockAddr = encode_in4_sockaddr(env, &sockAddrP->in4, addrLen); + break; + +#if defined(HAVE_IN6) && defined(AF_INET6) + case AF_INET6: + sockAddr = encode_in6_sockaddr(env, &sockAddrP->in6, addrLen); + break; +#endif + +#ifdef HAVE_SYS_UN_H + case AF_UNIX: + sockAddr = encode_un_sockaddr(env, &sockAddrP->un, addrLen); + break; +#endif + + default: + sockAddr = atom_undefined; + break; + } + + return sockAddr; +} + + + +/* Encode an IPv4 socket address; in4_sockaddr */ +static +ERL_NIF_TERM encode_in4_sockaddr(ErlNifEnv* env, + struct sockaddr_in* addrP, + SOCKLEN_T addrLen) +{ + ERL_NIF_TERM sockAddr; + short port; + ERL_NIF_TERM ePort, eAddr; + + + if (addrLen >= sizeof(struct sockaddr_in)) { + unsigned int i; + ERL_NIF_TERM at[4]; + unsigned int atLen = sizeof(at) / sizeof(ERL_NIF_TERM); + unsigned char* a = (unsigned char*) &addrP->sin_addr; + + /* The port */ + port = ntohs(addrP->sin_port); + ePort = MKI(env, port); + + /* The address */ + for (i = 0; i < atLen; i++) { + at[i] = MKI(env, a[i]); + } + eAddr = MKTA(env, at, atLen); + // eAddr = MKT4(env, at[0], at[1], at[2], at[3]); + + /* And finally construct the in4_sockaddr record */ + sockAddr = make_in4_sockaddr(env, ePort, eAddr); + + } else { + sockAddr = atom_undefined; + } + + return sockAddr; +} + + + +/* Encode an IPv6 socket address; in6_sockaddr */ +#if defined(HAVE_IN6) && defined(AF_INET6) +static +ERL_NIF_TERM encode_in6_sockaddr(ErlNifEnv* env, + struct sockaddr_in6* addrP, + SOCKLEN_T addrLen) +{ + ERL_NIF_TERM sockAddr; + short port; + ERL_NIF_TERM ePort, eAddr, eFlowInfo, eScopeId; + + + if (addrLen >= sizeof(struct sockaddr_in6)) { + unsigned int i; + ERL_NIF_TERM at[8]; + unsigned int atLen = sizeof(at) / sizeof(ERL_NIF_TERM); + unsigned char* a = (unsigned char*) &addrP->sin6_addr; + + /* The port */ + port = ntohs(addrP->sin6_port); + ePort = MKI(env, port); + + /* The address */ + for (i = 0; i < atLen; i++) { + at[i] = MKI(env, get_int16(a + i*2)); + } + eAddr = MKTA(env, at, atLen); + + /* The flowInfo */ + eFlowInfo = MKI(env, addrP->sin6_flowinfo); + + /* The scopeId */ + eScopeId = MKI(env, addrP->sin6_scope_id); + + /* And finally construct the in6_sockaddr record */ + sockAddr = make_in6_sockaddr(env, ePort, eAddr, eFlowInfo, eScopeId); + + } else { + sockAddr = atom_undefined; + } + + return sockAddr; +} +#endif + + + +/* Encode an Unix Domain socket address: string() */ +#ifdef HAVE_SYS_UN_H +static +ERL_NIF_TERM encode_un_sockaddr(ErlNifEnv* env, + struct sockaddr_un* addrP, + SOCKLEN_T addrLen) +{ + ERL_NIF_TERM sockAddr; + size_t n, m; + + if (addrLen >= offsetof(struct sockaddr_un, sun_path)) { + n = addrLen - offsetof(struct sockaddr_un, sun_path); + if (255 < n) { + sockAddr = atom_undefined; + } else { + m = my_strnlen(addrP->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 + + sockAddr = MKSL(env, addrP->sun_path, m); + } + } else { + sockAddr = atom_undefined; + } + + return sockAddr; +} +#endif + + + /* The erlang format for a set of flags is a list of atoms. * A special case is when there is no flags, which is * represented by the atom undefined. @@ -1710,13 +1924,13 @@ ERL_NIF_TERM decode_bool(ErlNifEnv* env, * will result in the result being a list of zero or more length. */ static -ERL_NIF_TERM encode_address_info(ErlNifEnv* env, - struct addrinfo* addrInfo) +ERL_NIF_TERM encode_address_infos(ErlNifEnv* env, + struct addrinfo* addrInfo) { ERL_NIF_TERM result; unsigned int len = address_info_length(addrInfo); - NDBG( ("encode_address_info -> len: %d\r\n", len) ); + NDBG( ("encode_address_infos -> len: %d\r\n", len) ); if (len > 0) { ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM)); @@ -1724,22 +1938,17 @@ ERL_NIF_TERM encode_address_info(ErlNifEnv* env, struct addrinfo* p = addrInfo; while (i < len) { - array[i] = make_address_info(env, p); + array[i] = encode_address_info(env, p); p = p->ai_next; i++; } - /* - for (i = 0; i < len; i++) { - array[i] = make_address_info(env, &addrInfo[i]); - } - */ result = MKLA(env, array, len); } else { result = MKEL(env); } - NDBG( ("encode_address_info -> result: " + NDBG( ("encode_address_infos -> result: " "\r\n %T\r\n", result) ); return result; @@ -1780,28 +1989,17 @@ unsigned int address_info_length(struct addrinfo* addrInfoP) * {address_info, Fam, Type, Proto, Addr} */ static -ERL_NIF_TERM make_address_info(ErlNifEnv* env, - struct addrinfo* addrInfoP) +ERL_NIF_TERM encode_address_info(ErlNifEnv* env, + struct addrinfo* addrInfoP) { ERL_NIF_TERM result, fam, type, proto, addr; - fam = make_addrinfo_family(env, addrInfoP->ai_family); - // NDBG( ("make_address_info -> fam: %T\r\n", fam) ); - type = make_addrinfo_type(env, addrInfoP->ai_socktype); - // NDBG( ("make_address_info -> type: %T\r\n", type) ); - proto = make_addrinfo_proto(env, addrInfoP->ai_protocol); - // NDBG( ("make_address_info -> proto: %T\r\n", proto) ); - addr = make_addrinfo_addr(env, - addrInfoP->ai_addr, - addrInfoP->ai_addrlen); - // NDBG( ("make_address_info -> addr: %T\r\n", addr) ); + fam = encode_address_info_family(env, addrInfoP->ai_family); + type = encode_address_info_type(env, addrInfoP->ai_socktype); + proto = encode_address_info_proto(env, addrInfoP->ai_protocol); + addr = encode_in_sockaddr(env, addrInfoP->ai_addr, addrInfoP->ai_addrlen); - result = MKT5(env, atom_address_info, fam, type, proto, addr); - - /* - NDBG( ("make_address_info -> result: " - "\r\n %T\r\n", result) ); - */ + result = make_address_info(env, fam, type, proto, addr); return result; @@ -1814,23 +2012,29 @@ ERL_NIF_TERM make_address_info(ErlNifEnv* env, * in the form of an integer. */ static -ERL_NIF_TERM make_addrinfo_family(ErlNifEnv* env, - int family) +ERL_NIF_TERM encode_address_info_family(ErlNifEnv* env, + int family) { ERL_NIF_TERM efam; switch (family) { case AF_INET: - efam = atom_inet; + efam = esock_atom_inet; break; #if defined(HAVE_IN6) && defined(AF_INET6) case AF_INET6: - efam = atom_inet6; + efam = esock_atom_inet6; break; #endif - default: + #ifdef HAVE_SYS_UN_H + case AF_UNIX: + efam = esock_atom_local; + break; +#endif + + default: efam = MKI(env, family); break; } @@ -1846,8 +2050,8 @@ ERL_NIF_TERM make_addrinfo_family(ErlNifEnv* env, * in the form of an integer. */ static -ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env, - int socktype) +ERL_NIF_TERM encode_address_info_type(ErlNifEnv* env, + int socktype) { ERL_NIF_TERM etype; @@ -1872,10 +2076,6 @@ ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env, etype = atom_seqpacket; break; - case SOCK_DCCP: - etype = atom_dccp; - break; - default: etype = MKI(env, socktype); break; @@ -1892,8 +2092,8 @@ ERL_NIF_TERM make_addrinfo_type(ErlNifEnv* env, * in the form of an integer. */ static -ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env, - int proto) +ERL_NIF_TERM encode_address_info_proto(ErlNifEnv* env, + int proto) { ERL_NIF_TERM eproto; @@ -1906,6 +2106,12 @@ ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env, eproto = atom_ip; break; +#if defined(SOL_IPV6) + case SOL_IPV6: + eproto = atom_ipv6; + break; +#endif + case IPPROTO_TCP: eproto = atom_tcp; break; @@ -1914,6 +2120,12 @@ ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env, eproto = atom_udp; break; +#if defined(HAVE_SCTP) + case IPPROTO_SCTP: + eproto = atom_sctp; + break; +#endif + default: eproto = MKI(env, proto); break; @@ -1929,15 +2141,16 @@ ERL_NIF_TERM make_addrinfo_proto(ErlNifEnv* env, * IPv4 and IPv6 addresses. Values of other families will be * returned as an undefined. */ +/* static -ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, - struct sockaddr* addrP, - SOCKLEN_T addrLen) +ERL_NIF_TERM encode_address_info_addr(ErlNifEnv* env, + struct sockaddr* addrP, + SOCKLEN_T addrLen) { ERL_NIF_TERM port, addr, eaddr; SockAddress* p = (SockAddress*) addrP; - NDBG( ("make_addrinfo_addr -> entry with" + NDBG( ("encode_address_info_addr -> entry with" "\r\n family: %d" "\r\n addrLen: %d" "\r\n", addrP->sa_family, addrLen) ); @@ -1985,6 +2198,57 @@ ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, return eaddr; } +*/ + + + +#if defined(HAVE_SYS_UN_H) || defined(SO_BINDTODEVICE) +/* strnlen doesn't exist everywhere */ +static +size_t my_strnlen(const char *s, size_t maxlen) +{ + size_t i = 0; + while (i < maxlen && s[i] != '\0') + i++; + return i; +} +#endif + + + +/* Construct the IPv4 socket address record: in4_sockaddr */ +static +ERL_NIF_TERM make_in4_sockaddr(ErlNifEnv* env, + ERL_NIF_TERM port, + ERL_NIF_TERM addr) +{ + return MKT3(env, atom_in4_sockaddr, port, addr); +} + + + +/* Construct the IPv6 socket address record: in6_sockaddr */ +static +ERL_NIF_TERM make_in6_sockaddr(ErlNifEnv* env, + ERL_NIF_TERM port, + ERL_NIF_TERM addr, + ERL_NIF_TERM flowInfo, + ERL_NIF_TERM scopeId) +{ + return MKT5(env, atom_in6_sockaddr, port, addr, flowInfo, scopeId); +} + + + +static +ERL_NIF_TERM make_address_info(ErlNifEnv* env, + ERL_NIF_TERM fam, + ERL_NIF_TERM sockType, + ERL_NIF_TERM proto, + ERL_NIF_TERM addr) +{ + return MKT5(env, atom_address_info, fam, sockType, proto, addr); +} @@ -2248,9 +2512,12 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_idn = MKA(env, str_idn); atom_idna_allow_unassigned = MKA(env, str_idna_allow_unassigned); atom_idna_use_std3_ascii_rules = MKA(env, str_idna_use_std3_ascii_rules); + atom_in4_sockaddr = MKA(env, str_in4_sockaddr); + atom_in6_sockaddr = MKA(env, str_in6_sockaddr); atom_inet = MKA(env, str_inet); atom_inet6 = MKA(env, str_inet6); atom_ip = MKA(env, str_ip); + atom_ipv6 = MKA(env, str_ipv6); atom_namereqd = MKA(env, str_namereqd); atom_name_info = MKA(env, str_name_info); atom_nofqdn = MKA(env, str_nofqdn); -- cgit v1.2.3 From 978a8a855c57bdfb20d3bcd8a6055968f3be3887 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 18 Jun 2018 15:29:53 +0200 Subject: [socket+net-nif] Backup --- erts/emulator/nifs/common/net_nif.c | 1203 ++++------------------------------- 1 file changed, 141 insertions(+), 1062 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index 90263d11c2..9a96eff654 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -26,21 +26,6 @@ #define STATIC_ERLANG_NIF 1 -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ -/* #include */ - #ifdef HAVE_CONFIG_H #include "config.h" @@ -176,48 +161,13 @@ #include "socket_dbg.h" #include "socket_int.h" +#include "socket_util.h" /* All platforms fail on malloc errors. */ #define FATAL_MALLOC - -/* *** Boolean *type* stuff... *** */ -typedef unsigned int BOOLEAN_T; -#define TRUE 1 -#define FALSE 0 -#define BOOL2STR(__B__) ((__B__) ? "true" : "false") -#define BOOL2ATOM(__B__) ((__B__) ? atom_true : atom_false) - -/* Two byte integer decoding */ -#define get_int16(s) ((((unsigned char*) (s))[0] << 8) | \ - (((unsigned char*) (s))[1])) - -#define SASSERT(e) \ - ((void) ((e) ? 1 : (xabort(#e, __func__, __FILE__, __LINE__), 0))) - - -/* Debug stuff... */ -#define SOCKET_NIF_DEBUG_DEFAULT TRUE - -/* Various defaults... */ -#define SOCKET_DEBUG_DEFAULT TRUE -#define SOCKET_IOW_DEFAULT FALSE - -/* Counters and stuff (Don't know where to sent this stuff anyway) */ -#define SOCKET_NIF_IOW_DEFAULT FALSE - - -/* Used in debug printouts */ -#ifdef __WIN32__ -#define LLU "%I64u" -#else -#define LLU "%llu" -#endif -typedef unsigned long long llu_t; - - #ifdef __WIN32__ #define net_gethostname(__buf__, __bufSz__) gethostname((__buf__), (__bufSz__)) #else @@ -226,15 +176,6 @@ typedef unsigned long long llu_t; -/* Socket stuff */ -// #define INVALID_SOCKET -1 -// #define INVALID_EVENT -1 -// #define SOCKET_ERROR -1 - -// #define SOCKET int -// #define HANDLE long int - - /* *** Misc macros and defines *** */ #ifdef __WIN32__ @@ -243,12 +184,6 @@ typedef unsigned long long llu_t; #define get_errno() errno #endif -// #if defined(TCP_CA_NAME_MAX) -// #define SOCKET_OPT_TCP_CONGESTION_NAME_MAX TCP_CA_NAME_MAX -// #else -/* This is really excessive, but just in case... */ -// #define SOCKET_OPT_TCP_CONGESTION_NAME_MAX 256 -// #endif #define HOSTNAME_LEN 256 #define SERVICE_LEN 256 @@ -260,74 +195,13 @@ typedef unsigned long long llu_t; */ #define NET_MAXHOSTNAMELEN 255 + /* =================================================================== * * * * Various enif macros * * * * =================================================================== */ -/* #define MALLOC(SZ) enif_alloc((SZ)) */ -/* #define FREE(P) enif_free((P)) */ - -/* #define MKA(E,S) enif_make_atom((E), (S)) */ -/* #define MKBIN(E,B) enif_make_binary((E), (B)) */ -/* #define MKI(E,I) enif_make_int((E), (I)) */ -/* #define MKLA(E,A,L) enif_make_list_from_array((E), (A), (L)) */ -/* #define MKEL(E) enif_make_list((E), 0) */ -/* #define MKREF(E) enif_make_ref((E)) */ -/* #define MKS(E,S) enif_make_string((E), (S), ERL_NIF_LATIN1) */ -/* #define MKSL(E,S,L) enif_make_string_len((E), (S), (L), ERL_NIF_LATIN1) */ -/* #define MKSBIN(E,B,ST,SZ) enif_make_sub_binary((E), (B), (ST), (SZ)) */ -/* #define MKT2(E,E1,E2) enif_make_tuple2((E), (E1), (E2)) */ -/* #define MKT3(E,E1,E2,E3) enif_make_tuple3((E), (E1), (E2), (E3)) */ -/* #define MKT4(E,E1,E2,E3,E4) enif_make_tuple4((E), (E1), (E2), (E3), (E4)) */ -/* #define MKT5(E,E1,E2,E3,E4,E5) \ */ -/* enif_make_tuple5((E), (E1), (E2), (E3), (E4), (E5)) */ -/* #define MKT8(E,E1,E2,E3,E4,E5,E6,E7,E8) \ */ -/* enif_make_tuple8((E), (E1), (E2), (E3), (E4), (E5), (E6), (E7), (E8)) */ -/* #define MKTA(E, A, AL) enif_make_tuple_from_array((E), (A), (AL)) */ - -/* #define MCREATE(N) enif_mutex_create((N)) */ -/* #define MDESTROY(M) enif_mutex_destroy((M)) */ -/* #define MLOCK(M) enif_mutex_lock((M)) */ -/* #define MUNLOCK(M) enif_mutex_unlock((M)) */ - -/* #define MONP(E,D,P,M) enif_monitor_process((E), (D), (P), (M)) */ -/* #define DEMONP(E,D,M) enif_demonitor_process((E), (D), (M)) */ - -/* #define SELECT(E,FD,M,O,P,R) \ */ -/* enif_select((E), (FD), (M), (O), (P), (R)) */ -/* #define SELECT_READ(E, DP, P, R) \ */ -/* SELECT((E), (DP)->sock, (ERL_NIF_SELECT_READ), (DP), (P), (R)) */ -/* #define SELECT_WRITE(E, DP, P, R) \ */ -/* SELECT((E), (DP)->sock, (ERL_NIF_SELECT_WRITE), (DP), (P), (R)) */ -/* #define SELECT_STOP(E, DP) \ */ -/* enif_select((E), (DP)->sock, (ERL_NIF_SELECT_STOP), (DP), NULL, atom_undefined) */ - -/* #define IS_ATOM(E, TE) enif_is_atom((E), (TE)) */ -/* #define IS_BIN(E, TE) enif_is_binary((E), (TE)) */ -/* #define IS_NUM(E, TE) enif_is_number((E), (TE)) */ -/* #define IS_TUPLE(E, TE) enif_is_tuple((E), (TE)) */ -/* #define IS_LIST(E, TE) enif_is_list((E), (TE)) */ - -/* #define COMPARE(L, R) enif_compare((L), (R)) */ - -/* #define GET_ATOM_LEN(E, TE, LP) \ */ -/* enif_get_atom_length((E), (TE), (LP), ERL_NIF_LATIN1) */ -/* #define GET_ATOM(E, TE, BP, MAX) \ */ -/* enif_get_atom((E), (TE), (BP), (MAX), ERL_NIF_LATIN1) */ -/* #define GET_BIN(E, TE, BP) enif_inspect_iolist_as_binary((E), (TE), (BP)) */ -/* #define GET_INT(E, TE, IP) enif_get_int((E), (TE), (IP)) */ -/* #define GET_LIST_ELEM(E, L, HP, TP) enif_get_list_cell((E), (L), (HP), (TP)) */ -/* #define GET_LIST_LEN(E, L, LP) enif_get_list_length((E), (L), (LP)) */ -/* #define GET_STR(E, L, B, SZ) \ */ -/* enif_get_string((E), (L), (B), (SZ), ERL_NIF_LATIN1) */ -/* #define GET_UINT(E, TE, IP) enif_get_uint((E), (TE), (IP)) */ -/* #define GET_TUPLE(E, TE, TSZ, TA) enif_get_tuple((E), (TE), (TSZ), (TA)) */ - -/* #define ALLOC_BIN(SZ, BP) enif_alloc_binary((SZ), (BP)) */ -/* #define REALLOC_BIN(SZ, BP) enif_realloc_binary((SZ), (BP)) */ - #ifdef HAVE_SOCKLEN_T # define SOCKLEN_T socklen_t @@ -335,37 +209,26 @@ typedef unsigned long long llu_t; # define SOCKLEN_T size_t #endif -#define NDEBUG( ___COND___ , proto ) \ - if ( ___COND___ ) { \ - dbg_printf proto; \ - fflush(stdout); \ - } -#define NDBG( proto ) NDEBUG( data.debug , proto ) - -/* The general purpose socket address */ -typedef union { - struct sockaddr sa; - - struct sockaddr_in in4; - -#ifdef HAVE_IN6 - struct sockaddr_in6 in6; -#endif - -#ifdef HAVE_SYS_UN_H - struct sockaddr_un un; -#endif +#define NDBG( proto ) ESOCK_DBG_PRINTF( data.debug , proto ) -} SockAddress; typedef struct { BOOLEAN_T debug; } NetData; + +/* =================================================================== * + * * + * Static data * + * * + * =================================================================== */ + + static NetData data; + /* ---------------------------------------------------------------------- * F o r w a r d s * ---------------------------------------------------------------------- @@ -409,10 +272,10 @@ static ERL_NIF_TERM nif_if_names(ErlNifEnv* env, static ERL_NIF_TERM ncommand(ErlNifEnv* env, ERL_NIF_TERM cmd); static ERL_NIF_TERM ngethostname(ErlNifEnv* env); -static ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, - const SockAddress* saP, - SOCKLEN_T saLen, - int flags); +static ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, + const SocketAddress* saP, + SOCKLEN_T saLen, + int flags); static ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env, char* host, char* serv); @@ -434,36 +297,7 @@ static void net_down(ErlNifEnv* env, const ErlNifPid* pid, const ErlNifMonitor* mon); */ -static BOOLEAN_T decode_in_sockaddr(ErlNifEnv* env, - const ERL_NIF_TERM eAddr, - SockAddress* saP, - SOCKLEN_T* saLen); -static BOOLEAN_T decode_in4_sockaddr(ErlNifEnv* env, - const ERL_NIF_TERM* addrt, - SockAddress* saP, - SOCKLEN_T* saLen); -#if defined(HAVE_IN6) && defined(AF_INET6) -static BOOLEAN_T decode_in6_sockaddr(ErlNifEnv* env, - const ERL_NIF_TERM* addrt, - SockAddress* saP, - SOCKLEN_T* saLen); -#endif -static ERL_NIF_TERM encode_in_sockaddr(ErlNifEnv* env, - struct sockaddr* addrP, - SOCKLEN_T addrLen); -static ERL_NIF_TERM encode_in4_sockaddr(ErlNifEnv* env, - struct sockaddr_in* addrP, - SOCKLEN_T addrLen); -#if defined(HAVE_IN6) && defined(AF_INET6) -static ERL_NIF_TERM encode_in6_sockaddr(ErlNifEnv* env, - struct sockaddr_in6* addrP, - SOCKLEN_T addrLen); -#endif -#ifdef HAVE_SYS_UN_H -static ERL_NIF_TERM encode_un_sockaddr(ErlNifEnv* env, - struct sockaddr_un* addrP, - SOCKLEN_T addrLen); -#endif + static BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env, const ERL_NIF_TERM eflags, int* flags); @@ -490,47 +324,11 @@ static ERL_NIF_TERM encode_address_info_type(ErlNifEnv* env, static ERL_NIF_TERM encode_address_info_proto(ErlNifEnv* env, int proto); -/* static ERL_NIF_TERM make_address_info(ErlNifEnv* env, */ -/* struct addrinfo* addrInfoP); */ -/* static ERL_NIF_TERM make_addrinfo_addr(ErlNifEnv* env, */ -/* struct sockaddr* addrP, */ -/* SOCKLEN_T addrLen); */ - -static ERL_NIF_TERM make_in4_sockaddr(ErlNifEnv* env, - ERL_NIF_TERM port, - ERL_NIF_TERM addr); -#if defined(HAVE_IN6) && defined(AF_INET6) -static ERL_NIF_TERM make_in6_sockaddr(ErlNifEnv* env, - ERL_NIF_TERM port, - ERL_NIF_TERM addr, - ERL_NIF_TERM flowInfo, - ERL_NIF_TERM scopeId); -#endif static ERL_NIF_TERM make_address_info(ErlNifEnv* env, ERL_NIF_TERM fam, ERL_NIF_TERM sockType, ERL_NIF_TERM proto, ERL_NIF_TERM addr); -static ERL_NIF_TERM make_ok2(ErlNifEnv* env, ERL_NIF_TERM val); -// static ERL_NIF_TERM make_ok3(ErlNifEnv* env, ERL_NIF_TERM val1, ERL_NIF_TERM val2); -static ERL_NIF_TERM make_error(ErlNifEnv* env, ERL_NIF_TERM reason); -static ERL_NIF_TERM make_error1(ErlNifEnv* env, char* reason); -static ERL_NIF_TERM make_error2(ErlNifEnv* env, int err); - -#if defined(HAVE_SYS_UN_H) || defined(SO_BINDTODEVICE) -static size_t my_strnlen(const char *s, size_t maxlen); -#endif - -static void dbg_printf( const char* format, ... ); -static int dbg_realtime(struct timespec* tsP); -static int dbg_timespec2str(char *buf, unsigned int len, struct timespec *ts); - -/* -static void xabort(const char* expr, - const char* func, - const char* file, - int line); -*/ static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); @@ -560,134 +358,63 @@ static const struct in6_addr in6addr_loopback = /* *** String constants *** */ static char str_address_info[] = "address_info"; -static char str_dccp[] = "dccp"; static char str_debug[] = "debug"; -static char str_dgram[] = "dgram"; -static char str_error[] = "error"; -static char str_false[] = "false"; static char str_idn[] = "idn"; static char str_idna_allow_unassigned[] = "idna_allow_unassigned"; static char str_idna_use_std3_ascii_rules[] = "idna_use_std3_ascii_rules"; -static char str_in4_sockaddr[] = "in4_sockaddr"; -static char str_in6_sockaddr[] = "in6_sockaddr"; -static char str_inet[] = "inet"; -static char str_inet6[] = "inet6"; -static char str_ip[] = "ip"; -static char str_ipv6[] = "ipv6"; static char str_namereqd[] = "namereqd"; static char str_name_info[] = "name_info"; static char str_nofqdn[] = "nofqdn"; static char str_numerichost[] = "numerichost"; static char str_numericserv[] = "numericserv"; -static char str_ok[] = "ok"; -static char str_raw[] = "raw"; -static char str_rdm[] = "rdm"; -static char str_seqpacket[] = "seqpacket"; -static char str_stream[] = "stream"; -static char str_tcp[] = "tcp"; -static char str_true[] = "true"; -static char str_udp[] = "udp"; -static char str_undefined[] = "undefined"; - -// static char str_lowdelay[] = "lowdelay"; -// static char str_throughput[] = "throughput"; -// static char str_reliability[] = "reliability"; -// static char str_mincost[] = "mincost"; /* (special) error string constants */ -// static char str_eafnosupport[] = "eafnosupport"; static char str_eaddrfamily[] = "eaddrfamily"; -static char str_eagain[] = "eagain"; static char str_ebadflags[] = "ebadflags"; static char str_efail[] = "efail"; static char str_efamily[] = "efamily"; static char str_efault[] = "efault"; -static char str_einval[] = "einval"; -// static char str_eisconn[] = "eisconn"; static char str_emem[] = "emem"; static char str_enametoolong[] = "enametoolong"; static char str_enodata[] = "enodata"; static char str_enoname[] = "enoname"; -// static char str_enotclosing[] = "enotclosing"; -// static char str_enotconn[] = "enotconn"; static char str_enxio[] = "enxio"; static char str_eoverflow[] = "eoverflow"; static char str_eservice[] = "eservice"; static char str_esocktype[] = "esocktype"; static char str_esystem[] = "esystem"; -// static char str_exalloc[] = "exalloc"; -// static char str_exbadstate[] = "exbadstate"; -// static char str_exbusy[] = "exbusy"; -// static char str_exmon[] = "exmonitor"; // failed monitor -// static char str_exself[] = "exself"; // failed self -// static char str_exsend[] = "exsend"; // failed send /* *** Atoms *** */ static ERL_NIF_TERM atom_address_info; -static ERL_NIF_TERM atom_dccp; static ERL_NIF_TERM atom_debug; -static ERL_NIF_TERM atom_dgram; -static ERL_NIF_TERM atom_error; -static ERL_NIF_TERM atom_false; static ERL_NIF_TERM atom_idn; static ERL_NIF_TERM atom_idna_allow_unassigned; static ERL_NIF_TERM atom_idna_use_std3_ascii_rules; -static ERL_NIF_TERM atom_in4_sockaddr; -static ERL_NIF_TERM atom_in6_sockaddr; -static ERL_NIF_TERM atom_inet; -static ERL_NIF_TERM atom_inet6; -static ERL_NIF_TERM atom_ip; -static ERL_NIF_TERM atom_ipv6; static ERL_NIF_TERM atom_namereqd; static ERL_NIF_TERM atom_name_info; static ERL_NIF_TERM atom_nofqdn; static ERL_NIF_TERM atom_numerichost; static ERL_NIF_TERM atom_numericserv; -static ERL_NIF_TERM atom_ok; -static ERL_NIF_TERM atom_raw; -static ERL_NIF_TERM atom_rdm; -// static ERL_NIF_TERM atom_select; -static ERL_NIF_TERM atom_stream; -static ERL_NIF_TERM atom_seqpacket; -// static ERL_NIF_TERM atom_timeout; -static ERL_NIF_TERM atom_tcp; -static ERL_NIF_TERM atom_true; -static ERL_NIF_TERM atom_udp; -static ERL_NIF_TERM atom_undefined; - -// static ERL_NIF_TERM atom_lowdelay; -// static ERL_NIF_TERM atom_throughput; -// static ERL_NIF_TERM atom_reliability; -// static ERL_NIF_TERM atom_mincost; - -// static ERL_NIF_TERM atom_eafnosupport; + + static ERL_NIF_TERM atom_eaddrfamily; -static ERL_NIF_TERM atom_eagain; +// static ERL_NIF_TERM atom_eagain; static ERL_NIF_TERM atom_ebadflags; static ERL_NIF_TERM atom_efail; static ERL_NIF_TERM atom_efamily; static ERL_NIF_TERM atom_efault; -static ERL_NIF_TERM atom_einval; -// static ERL_NIF_TERM atom_eisconn; static ERL_NIF_TERM atom_emem; static ERL_NIF_TERM atom_enametoolong; static ERL_NIF_TERM atom_enodata; static ERL_NIF_TERM atom_enoname; -// static ERL_NIF_TERM atom_enotclosing; -// static ERL_NIF_TERM atom_enotconn; static ERL_NIF_TERM atom_enxio; static ERL_NIF_TERM atom_eoverflow; static ERL_NIF_TERM atom_eservice; static ERL_NIF_TERM atom_esocktype; static ERL_NIF_TERM atom_esystem; -// static ERL_NIF_TERM atom_exalloc; -// static ERL_NIF_TERM atom_exbadstate; -// static ERL_NIF_TERM atom_exbusy; -// static ERL_NIF_TERM atom_exmon; -// static ERL_NIF_TERM atom_exself; -// static ERL_NIF_TERM atom_exsend; + /* *** net *** */ static ErlNifResourceType* net; @@ -738,7 +465,7 @@ ERL_NIF_TERM nif_is_loaded(ErlNifEnv* env, if (argc != 0) return enif_make_badarg(env); - return atom_true; + return esock_atom_true; } @@ -755,13 +482,13 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, { ERL_NIF_TERM info, tmp; - NDBG( ("info -> entry\r\n") ); + NDBG( ("NET", "info -> entry\r\n") ); tmp = enif_make_new_map(env); if (!enif_make_map_put(env, tmp, atom_debug, BOOL2ATOM(data.debug), &info)) info = tmp; - NDBG( ("info -> done: %T\r\n", info) ); + NDBG( ("NET", "info -> done: %T\r\n", info) ); return info; } @@ -787,18 +514,18 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env, { ERL_NIF_TERM ecmd, result; - NDBG( ("command -> entry (%d)\r\n", argc) ); + NDBG( ("NET", "command -> entry (%d)\r\n", argc) ); if (argc != 1) return enif_make_badarg(env); ecmd = argv[0]; - NDBG( ("command -> ecmd: %T\r\n", ecmd) ); + NDBG( ("NET", "command -> ecmd: %T\r\n", ecmd) ); result = ncommand(env, ecmd); - NDBG( ("command -> result: %T\r\n", result) ); + NDBG( ("NET", "command -> result: %T\r\n", result) ); return result; } @@ -819,19 +546,19 @@ ERL_NIF_TERM ncommand(ErlNifEnv* env, if (IS_TUPLE(env, cmd)) { /* Could be the debug tuple */ if (!GET_TUPLE(env, cmd, &tsz, &t)) - return make_error(env, atom_einval); + return esock_make_error(env, esock_atom_einval); if (tsz != 2) - return make_error(env, atom_einval); + return esock_make_error(env, esock_atom_einval); /* First element should be the atom 'debug' */ if (COMPARE(t[0], atom_debug) != 0) - return make_error(env, atom_einval); + return esock_make_error(env, esock_atom_einval); return decode_bool(env, t[1], &data.debug); } else { - return make_error(env, atom_einval); + return esock_make_error(env, esock_atom_einval); } } @@ -852,14 +579,14 @@ ERL_NIF_TERM nif_gethostname(ErlNifEnv* env, { ERL_NIF_TERM result; - NDBG( ("nif_gethostname -> entry (%d)\r\n", argc) ); + NDBG( ("NET", "nif_gethostname -> entry (%d)\r\n", argc) ); if (argc != 0) return enif_make_badarg(env); result = ngethostname(env); - NDBG( ("nif_gethostname -> done when result: %T\r\n", result) ); + NDBG( ("NET", "nif_gethostname -> done when result: %T\r\n", result) ); return result; } @@ -874,27 +601,27 @@ ERL_NIF_TERM ngethostname(ErlNifEnv* env) res = net_gethostname(buf, sizeof(buf)); - NDBG( ("ngethostname -> gethostname res: %d\r\n", res) ); + NDBG( ("NET", "ngethostname -> gethostname res: %d\r\n", res) ); switch (res) { case 0: - result = make_ok2(env, MKS(env, buf)); + result = esock_make_ok2(env, MKS(env, buf)); break; case EFAULT: - result = make_error(env, atom_efault); + result = esock_make_error(env, atom_efault); break; case EINVAL: - result = make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; case ENAMETOOLONG: - result = make_error(env, atom_enametoolong); + result = esock_make_error(env, atom_enametoolong); break; default: - result = make_error(env, MKI(env, res)); + result = esock_make_error(env, MKI(env, res)); break; } @@ -920,33 +647,35 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - ERL_NIF_TERM result, eSockAddr; - ERL_NIF_TERM eFlags; - int flags = 0; // Just in case... - SockAddress sa; - SOCKLEN_T saLen = 0; // Just in case... + ERL_NIF_TERM result; + ERL_NIF_TERM eSockAddr, eFlags; + int flags = 0; // Just in case... + SocketAddress sa; + SOCKLEN_T saLen = 0; // Just in case... - NDBG( ("nif_getnameinfo -> entry (%d)\r\n", argc) ); + NDBG( ("NET", "nif_getnameinfo -> entry (%d)\r\n", argc) ); if (argc != 2) return enif_make_badarg(env); eSockAddr = argv[0]; eFlags = argv[1]; - NDBG( ("nif_getnameinfo -> " + NDBG( ("NET", + "nif_getnameinfo -> " "\r\n SockAddr: %T" "\r\n Flags: %T" "\r\n", eSockAddr, eFlags) ); - if (!decode_nameinfo_flags(env, eFlags, &flags)) + if (!esock_decode_sockaddr(env, eSockAddr, &sa, &saLen)) return enif_make_badarg(env); - if (!decode_in_sockaddr(env, eSockAddr, &sa, &saLen)) + if (!decode_nameinfo_flags(env, eFlags, &flags)) return enif_make_badarg(env); result = ngetnameinfo(env, &sa, saLen, flags); - NDBG( ("nif_getnameinfo -> done when result: " + NDBG( ("NET", + "nif_getnameinfo -> done when result: " "\r\n %T\r\n", result) ); return result; @@ -958,10 +687,10 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, * service info. */ static -ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, - const SockAddress* saP, - SOCKLEN_T saLen, - int flags) +ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, + const SocketAddress* saP, + SOCKLEN_T saLen, + int flags) { ERL_NIF_TERM result; char host[HOSTNAME_LEN]; @@ -974,7 +703,7 @@ ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, serv, servLen, flags); - NDBG( ("ngetnameinfo -> res: %d\r\n", res) ); + NDBG( ("NET", "ngetnameinfo -> res: %d\r\n", res) ); switch (res) { case 0: @@ -983,44 +712,44 @@ ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, atom_name_info, MKS(env, host), MKS(env, serv)); - result = make_ok2(env, info); + result = esock_make_ok2(env, info); } break; case EAI_AGAIN: - result = make_error(env, atom_eagain); + result = esock_make_error(env, esock_atom_eagain); break; case EAI_BADFLAGS: - result = make_error(env, atom_ebadflags); + result = esock_make_error(env, atom_ebadflags); break; case EAI_FAIL: - result = make_error(env, atom_efail); + result = esock_make_error(env, atom_efail); break; case EAI_FAMILY: - result = make_error(env, atom_efamily); + result = esock_make_error(env, atom_efamily); break; case EAI_MEMORY: - result = make_error(env, atom_emem); + result = esock_make_error(env, atom_emem); break; case EAI_NONAME: - result = make_error(env, atom_enoname); + result = esock_make_error(env, atom_enoname); break; case EAI_OVERFLOW: - result = make_error(env, atom_eoverflow); + result = esock_make_error(env, atom_eoverflow); break; case EAI_SYSTEM: - result = make_error2(env, get_errno()); + result = esock_make_error_errno(env, get_errno()); break; default: - result = make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -1051,7 +780,7 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, char* servName; // struct addrinfo* hints; - NDBG( ("nif_getaddrinfo -> entry (%d)\r\n", argc) ); + NDBG( ("NET", "nif_getaddrinfo -> entry (%d)\r\n", argc) ); if (argc != 3) { return enif_make_badarg(env); @@ -1060,7 +789,8 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, eServName = argv[1]; // eHints = argv[2]; - NDBG( ("nif_getaddrinfo -> " + NDBG( ("NET", + "nif_getaddrinfo -> " "\r\n ehost: %T" "\r\n eservice: %T" "\r\n ehints: %T" @@ -1093,7 +823,8 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, FREE(hints); */ - NDBG( ("nif_getaddrinfo -> done when result: " + NDBG( ("NET", + "nif_getaddrinfo -> done when result: " "\r\n %T\r\n", result) ); return result; @@ -1109,7 +840,7 @@ ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env, struct addrinfo* addrInfoP; int res; - NDBG( ("ngetaddrinfo -> entry with" + NDBG( ("NET", "ngetaddrinfo -> entry with" "\r\n host: %s" "\r\n serv: %s" "\r\n", @@ -1118,63 +849,63 @@ ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env, res = getaddrinfo(host, serv, NULL, &addrInfoP); - NDBG( ("ngetaddrinfo -> res: %d\r\n", res) ); + NDBG( ("NET", "ngetaddrinfo -> res: %d\r\n", res) ); switch (res) { case 0: { ERL_NIF_TERM addrInfo = encode_address_infos(env, addrInfoP); freeaddrinfo(addrInfoP); - result = make_ok2(env, addrInfo); + result = esock_make_ok2(env, addrInfo); } break; case EAI_ADDRFAMILY: - result = make_error(env, atom_eaddrfamily); + result = esock_make_error(env, atom_eaddrfamily); break; case EAI_AGAIN: - result = make_error(env, atom_eagain); + result = esock_make_error(env, esock_atom_eagain); break; case EAI_BADFLAGS: - result = make_error(env, atom_ebadflags); + result = esock_make_error(env, atom_ebadflags); break; case EAI_FAIL: - result = make_error(env, atom_efail); + result = esock_make_error(env, atom_efail); break; case EAI_FAMILY: - result = make_error(env, atom_efamily); + result = esock_make_error(env, atom_efamily); break; case EAI_MEMORY: - result = make_error(env, atom_emem); + result = esock_make_error(env, atom_emem); break; case EAI_NODATA: - result = make_error(env, atom_enodata); + result = esock_make_error(env, atom_enodata); break; case EAI_NONAME: - result = make_error(env, atom_enoname); + result = esock_make_error(env, atom_enoname); break; case EAI_SERVICE: - result = make_error(env, atom_eservice); + result = esock_make_error(env, atom_eservice); break; case EAI_SOCKTYPE: - result = make_error(env, atom_esocktype); + result = esock_make_error(env, atom_esocktype); break; case EAI_SYSTEM: - result = make_error(env, atom_esystem); + result = esock_make_error(env, atom_esystem); break; default: - result = make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -1200,23 +931,24 @@ ERL_NIF_TERM nif_if_name2index(ErlNifEnv* env, ERL_NIF_TERM eifn, result; char ifn[IF_NAMESIZE+1]; - NDBG( ("nif_if_name2index -> entry (%d)\r\n", argc) ); + NDBG( ("NET", "nif_if_name2index -> entry (%d)\r\n", argc) ); if (argc != 1) { return enif_make_badarg(env); } eifn = argv[0]; - NDBG( ("nif_if_name2index -> " + NDBG( ("NET", + "nif_if_name2index -> " "\r\n Ifn: %T" "\r\n", argv[0]) ); if (0 >= GET_STR(env, eifn, ifn, sizeof(ifn))) - return make_error2(env, atom_einval); + return esock_make_error(env, esock_atom_einval); result = nif_name2index(env, ifn); - NDBG( ("nif_if_name2index -> done when result: %T\r\n", result) ); + NDBG( ("NET", "nif_if_name2index -> done when result: %T\r\n", result) ); return result; } @@ -1229,16 +961,16 @@ ERL_NIF_TERM nif_name2index(ErlNifEnv* env, { unsigned int idx; - NDBG( ("nif_name2index -> entry with ifn: %s\r\n", ifn) ); + NDBG( ("NET", "nif_name2index -> entry with ifn: %s\r\n", ifn) ); idx = if_nametoindex(ifn); - NDBG( ("nif_name2index -> idx: %d\r\n", idx) ); + NDBG( ("NET", "nif_name2index -> idx: %d\r\n", idx) ); if (idx == 0) - return make_error2(env, get_errno()); + return esock_make_error_errno(env, get_errno()); else - return make_ok2(env, MKI(env, idx)); + return esock_make_ok2(env, MKI(env, idx)); } @@ -1262,20 +994,20 @@ ERL_NIF_TERM nif_if_index2name(ErlNifEnv* env, ERL_NIF_TERM result; unsigned int idx; - NDBG( ("nif_if_index2name -> entry (%d)\r\n", argc) ); + NDBG( ("NET", "nif_if_index2name -> entry (%d)\r\n", argc) ); if ((argc != 1) || !GET_UINT(env, argv[0], &idx)) { return enif_make_badarg(env); } - NDBG( ("nif_index2name -> " + NDBG( ("NET", "nif_index2name -> " "\r\n Idx: %T" "\r\n", argv[0]) ); result = nif_index2name(env, idx); - NDBG( ("nif_if_index2name -> done when result: %T\r\n", result) ); + NDBG( ("NET", "nif_if_index2name -> done when result: %T\r\n", result) ); return result; } @@ -1293,9 +1025,9 @@ ERL_NIF_TERM nif_index2name(ErlNifEnv* env, return enif_make_badarg(env); // PLACEHOLDER if (NULL != if_indextoname(idx, ifn)) { - result = make_ok2(env, MKS(env, ifn)); + result = esock_make_ok2(env, MKS(env, ifn)); } else { - result = make_error(env, atom_enxio); + result = esock_make_error(env, atom_enxio); } FREE(ifn); @@ -1320,7 +1052,7 @@ ERL_NIF_TERM nif_if_names(ErlNifEnv* env, { ERL_NIF_TERM result; - NDBG( ("nif_if_names -> entry (%d)\r\n", argc) ); + NDBG( ("NET", "nif_if_names -> entry (%d)\r\n", argc) ); if (argc != 0) { return enif_make_badarg(env); @@ -1328,7 +1060,7 @@ ERL_NIF_TERM nif_if_names(ErlNifEnv* env, result = nif_names(env); - NDBG( ("nif_if_names -> done when result: %T\r\n", result) ); + NDBG( ("NET", "nif_if_names -> done when result: %T\r\n", result) ); return result; } @@ -1341,10 +1073,10 @@ ERL_NIF_TERM nif_names(ErlNifEnv* env) ERL_NIF_TERM result; struct if_nameindex* ifs = if_nameindex(); - NDBG( ("nif_names -> ifs: 0x%lX\r\n", ifs) ); + NDBG( ("NET", "nif_names -> ifs: 0x%lX\r\n", ifs) ); if (ifs == NULL) { - result = make_error2(env, get_errno()); + result = esock_make_error_errno(env, get_errno()); } else { /* * We got some interfaces: @@ -1360,7 +1092,7 @@ ERL_NIF_TERM nif_names(ErlNifEnv* env) */ unsigned int len = nif_names_length(ifs); - NDBG( ("nif_names -> len: %d\r\n", len) ); + NDBG( ("NET", "nif_names -> len: %d\r\n", len) ); if (len > 0) { ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM)); @@ -1372,10 +1104,10 @@ ERL_NIF_TERM nif_names(ErlNifEnv* env) MKS(env, ifs[i].if_name)); } - result = make_ok2(env, MKLA(env, array, len)); + result = esock_make_ok2(env, MKLA(env, array, len)); FREE(array); } else { - result = make_ok2(env, enif_make_list(env, 0)); + result = esock_make_ok2(env, enif_make_list(env, 0)); } } @@ -1394,7 +1126,7 @@ unsigned int nif_names_length(struct if_nameindex* p) while (!done) { - NDBG( ("nif_names_length -> %d: " + NDBG( ("NET", "nif_names_length -> %d: " "\r\n if_index: %d" "\r\n if_name: 0x%lX" "\r\n", len, p[len].if_index, p[len].if_name) ); @@ -1415,357 +1147,6 @@ unsigned int nif_names_length(struct if_nameindex* p) * ---------------------------------------------------------------------- */ -/* Decode an in_sockaddr (the socket address). - * This is the (erlang) type: in_sockaddr(), which is either - * a in4_sockaddr() (tuple of size 3) or a in6_sockaddr() - * (tuple of size 5). See the net erlang module for details. - * - * We first detect which which of the tuples it is: - * - Size 3: maybe in4_sockaddr - * - Size 5: maybe in6_sockaddr - */ -static -BOOLEAN_T decode_in_sockaddr(ErlNifEnv* env, - const ERL_NIF_TERM eAddr, - SockAddress* saP, - SOCKLEN_T* saLen) -{ - const ERL_NIF_TERM* addrt; - int addrtSz; - - if (!GET_TUPLE(env, eAddr, &addrtSz, &addrt)) - return FALSE; - - switch (addrtSz) { - case 3: - return decode_in4_sockaddr(env, addrt, saP, saLen); - break; - -#ifdef HAVE_IN6 - case 5: - return decode_in6_sockaddr(env, addrt, saP, saLen); - break; -#endif - - default: - return FALSE; - break; - } - -} - - -/* Decode an in4_sockaddr record. This is a tuple of size 3. - * The size has already been verified, but not its content. - * So, the first element should be the atom 'in4_sockaddr'. - * The second the port number, an integer. And the third, - * the actual ip address, a 4-tuple. - */ -static -BOOLEAN_T decode_in4_sockaddr(ErlNifEnv* env, - const ERL_NIF_TERM* addrt, - SockAddress* saP, - SOCKLEN_T* saLen) -{ - unsigned int len; - char tag[16]; // Just in case... - int port; - int ipAddrSz; - const ERL_NIF_TERM* ipAddrT; - int a, v; - char addr[4]; - - /* The first element: Verify record tag (atom()): in4_sockaddr */ - - if (!(GET_ATOM_LEN(env, addrt[0], &len) && - (len > 0) && - (len <= (sizeof(tag))))) - return FALSE; - - if (!GET_ATOM(env, addrt[0], tag, sizeof(tag))) - return FALSE; - - if (strncmp(tag, "in4_sockaddr", len) != 0) - return FALSE; - - - /* Get second element: port number (integer) */ - - if (!GET_INT(env, addrt[1], &port)) - return FALSE; - - - /* And finally, get the third element, the ip address (a 4 tuple) */ - - if (!GET_TUPLE(env, addrt[2], &ipAddrSz, &ipAddrT)) - return FALSE; - - if (ipAddrSz != 4) - return FALSE; - - - /* And finally initialize the sockaddr structure (and size) */ - sys_memzero((char*)saP, sizeof(struct sockaddr_in)); - saP->in4.sin_family = AF_INET; - saP->in4.sin_port = htons(port); - for (a = 0; a < 4; a++) { - if (!GET_INT(env, ipAddrT[a], &v)) - return FALSE; - addr[a] = v; - } - sys_memcpy(&saP->in4.sin_addr, &addr, sizeof(addr)); - *saLen = sizeof(struct sockaddr_in); - return TRUE; -} - - - -#if defined(HAVE_IN6) && defined(AF_INET6) -/* Decode an in6_sockaddr record. This is a tuple of size 5. - * The size has already been verified, but not its content. - * So, the first element should be the atom 'in6_sockaddr'. - * The second the port number, an integer. The third, the - * actual ip address, a 8-tuple. The forth, the flowinfo, - * an integer. And finally, the fifth element, the scope_id, - * also an integer. *Not used here*. - */ -static -BOOLEAN_T decode_in6_sockaddr(ErlNifEnv* env, - const ERL_NIF_TERM* addrt, - SockAddress* saP, - SOCKLEN_T* saLen) -{ - unsigned int len; - char tag[16]; // Just in case... - int port; - int ipAddrSz; - const ERL_NIF_TERM* ipAddrT; - int flowInfo; - int a, v; - char addr[16]; - - - /* The first element: Verify record tag (atom()): in6_sockaddr */ - - if (!(GET_ATOM_LEN(env, addrt[0], &len) && - (len > 0) && - (len <= (sizeof(tag))))) - return FALSE; - - if (!GET_ATOM(env, addrt[0], tag, sizeof(tag))) - return FALSE; - - if (strncmp(tag, "in6_sockaddr", len) != 0) - return FALSE; - - - /* Get second element: port number (integer) */ - - if (!GET_INT(env, addrt[1], &port)) - return FALSE; - - - /* Get the third element, the ip address (a 8 tuple) */ - - if (!GET_TUPLE(env, addrt[2], &ipAddrSz, &ipAddrT)) - return FALSE; - - if (ipAddrSz != 8) - return FALSE; - - - /* And finally, get the forth element, the flowinfo (integer) */ - - if (!GET_INT(env, addrt[3], &flowInfo)) - return FALSE; - - - /* And finally initialize the sockaddr structure (and size) */ - - sys_memzero((char*)saP, sizeof(struct sockaddr_in6)); - saP->in6.sin6_family = AF_INET6; - saP->in6.sin6_port = htons(port); - saP->in6.sin6_flowinfo = flowInfo; - /* 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 FALSE; - addr[a*2 ] = ((v >> 8) & 0xFF); - addr[a*2+1] = (v & 0xFF); - } - sys_memcpy(&saP->in6.sin6_addr, &addr, sizeof(addr)); - *saLen = sizeof(struct sockaddr_in6); - - return TRUE; -} -#endif - - - -static -ERL_NIF_TERM encode_in_sockaddr(ErlNifEnv* env, - struct sockaddr* addrP, - SOCKLEN_T addrLen) -{ - SockAddress* sockAddrP = (SockAddress*) addrP; - ERL_NIF_TERM sockAddr; - - switch (sockAddrP->sa.sa_family) { - case AF_INET: - sockAddr = encode_in4_sockaddr(env, &sockAddrP->in4, addrLen); - break; - -#if defined(HAVE_IN6) && defined(AF_INET6) - case AF_INET6: - sockAddr = encode_in6_sockaddr(env, &sockAddrP->in6, addrLen); - break; -#endif - -#ifdef HAVE_SYS_UN_H - case AF_UNIX: - sockAddr = encode_un_sockaddr(env, &sockAddrP->un, addrLen); - break; -#endif - - default: - sockAddr = atom_undefined; - break; - } - - return sockAddr; -} - - - -/* Encode an IPv4 socket address; in4_sockaddr */ -static -ERL_NIF_TERM encode_in4_sockaddr(ErlNifEnv* env, - struct sockaddr_in* addrP, - SOCKLEN_T addrLen) -{ - ERL_NIF_TERM sockAddr; - short port; - ERL_NIF_TERM ePort, eAddr; - - - if (addrLen >= sizeof(struct sockaddr_in)) { - unsigned int i; - ERL_NIF_TERM at[4]; - unsigned int atLen = sizeof(at) / sizeof(ERL_NIF_TERM); - unsigned char* a = (unsigned char*) &addrP->sin_addr; - - /* The port */ - port = ntohs(addrP->sin_port); - ePort = MKI(env, port); - - /* The address */ - for (i = 0; i < atLen; i++) { - at[i] = MKI(env, a[i]); - } - eAddr = MKTA(env, at, atLen); - // eAddr = MKT4(env, at[0], at[1], at[2], at[3]); - - /* And finally construct the in4_sockaddr record */ - sockAddr = make_in4_sockaddr(env, ePort, eAddr); - - } else { - sockAddr = atom_undefined; - } - - return sockAddr; -} - - - -/* Encode an IPv6 socket address; in6_sockaddr */ -#if defined(HAVE_IN6) && defined(AF_INET6) -static -ERL_NIF_TERM encode_in6_sockaddr(ErlNifEnv* env, - struct sockaddr_in6* addrP, - SOCKLEN_T addrLen) -{ - ERL_NIF_TERM sockAddr; - short port; - ERL_NIF_TERM ePort, eAddr, eFlowInfo, eScopeId; - - - if (addrLen >= sizeof(struct sockaddr_in6)) { - unsigned int i; - ERL_NIF_TERM at[8]; - unsigned int atLen = sizeof(at) / sizeof(ERL_NIF_TERM); - unsigned char* a = (unsigned char*) &addrP->sin6_addr; - - /* The port */ - port = ntohs(addrP->sin6_port); - ePort = MKI(env, port); - - /* The address */ - for (i = 0; i < atLen; i++) { - at[i] = MKI(env, get_int16(a + i*2)); - } - eAddr = MKTA(env, at, atLen); - - /* The flowInfo */ - eFlowInfo = MKI(env, addrP->sin6_flowinfo); - - /* The scopeId */ - eScopeId = MKI(env, addrP->sin6_scope_id); - - /* And finally construct the in6_sockaddr record */ - sockAddr = make_in6_sockaddr(env, ePort, eAddr, eFlowInfo, eScopeId); - - } else { - sockAddr = atom_undefined; - } - - return sockAddr; -} -#endif - - - -/* Encode an Unix Domain socket address: string() */ -#ifdef HAVE_SYS_UN_H -static -ERL_NIF_TERM encode_un_sockaddr(ErlNifEnv* env, - struct sockaddr_un* addrP, - SOCKLEN_T addrLen) -{ - ERL_NIF_TERM sockAddr; - size_t n, m; - - if (addrLen >= offsetof(struct sockaddr_un, sun_path)) { - n = addrLen - offsetof(struct sockaddr_un, sun_path); - if (255 < n) { - sockAddr = atom_undefined; - } else { - m = my_strnlen(addrP->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 - - sockAddr = MKSL(env, addrP->sun_path, m); - } - } else { - sockAddr = atom_undefined; - } - - return sockAddr; -} -#endif - - - /* The erlang format for a set of flags is a list of atoms. * A special case is when there is no flags, which is * represented by the atom undefined. @@ -1778,14 +1159,14 @@ BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env, BOOLEAN_T result; if (IS_ATOM(env, eflags)) { - if (COMPARE(eflags, atom_undefined) == 0) { + if (COMPARE(eflags, esock_atom_undefined) == 0) { *flags = 0; result = TRUE; } else { result = FALSE; } } else if (IS_LIST(env, eflags)) { - NDBG( ("decode_nameinfo_flags -> is atom\r\n") ); + NDBG( ("NET", "decode_nameinfo_flags -> is atom\r\n") ); result = decode_nameinfo_flags_list(env, eflags, flags); } else { result = FALSE; @@ -1809,7 +1190,7 @@ BOOLEAN_T decode_nameinfo_flags_list(ErlNifEnv* env, if (GET_LIST_ELEM(env, list, &elem, &tail)) { if (COMPARE(elem, atom_namereqd) == 0) { tmp |= NI_NAMEREQD; - } else if (COMPARE(elem, atom_dgram) == 0) { + } else if (COMPARE(elem, esock_atom_dgram) == 0) { tmp |= NI_DGRAM; } else if (COMPARE(elem, atom_nofqdn) == 0) { tmp |= NI_NOFQDN; @@ -1864,7 +1245,7 @@ BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, BOOLEAN_T result; if (IS_ATOM(env, eString)) { - if (COMPARE(eString, atom_undefined) == 0) { + if (COMPARE(eString, esock_atom_undefined) == 0) { *stringP = NULL; result = TRUE; } else { @@ -1880,12 +1261,12 @@ BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, result = FALSE; } - NDBG( ("decode_addrinfo_string -> len: %d\r\n", len) ); + NDBG( ("NET", "decode_addrinfo_string -> len: %d\r\n", len) ); bufP = MALLOC(len + 1); // We shall NULL-terminate if (GET_STR(env, eString, bufP, len+1)) { - NDBG( ("decode_addrinfo_string -> buf: %s\r\n", bufP) ); + NDBG( ("NET", "decode_addrinfo_string -> buf: %s\r\n", bufP) ); // bufP[len] = '\0'; *stringP = bufP; result = TRUE; @@ -1906,14 +1287,14 @@ ERL_NIF_TERM decode_bool(ErlNifEnv* env, ERL_NIF_TERM eBool, BOOLEAN_T* bool) { - if (COMPARE(eBool, atom_true) == 0) { + if (COMPARE(eBool, esock_atom_true) == 0) { *bool = TRUE; - return atom_ok; - } else if (COMPARE(eBool, atom_false) == 0) { + return esock_atom_ok; + } else if (COMPARE(eBool, esock_atom_false) == 0) { *bool = FALSE; - return atom_ok; + return esock_atom_ok; } else { - return make_error(env, atom_einval); + return esock_make_error(env, esock_atom_einval); } } @@ -1930,10 +1311,10 @@ ERL_NIF_TERM encode_address_infos(ErlNifEnv* env, ERL_NIF_TERM result; unsigned int len = address_info_length(addrInfo); - NDBG( ("encode_address_infos -> len: %d\r\n", len) ); + NDBG( ("NET", "encode_address_infos -> len: %d\r\n", len) ); if (len > 0) { - ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM)); + ERL_NIF_TERM* array = MALLOC(len * sizeof(ERL_NIF_TERM)); // LEAK? unsigned int i = 0; struct addrinfo* p = addrInfo; @@ -1948,7 +1329,7 @@ ERL_NIF_TERM encode_address_infos(ErlNifEnv* env, result = MKEL(env); } - NDBG( ("encode_address_infos -> result: " + NDBG( ("NET", "encode_address_infos -> result: " "\r\n %T\r\n", result) ); return result; @@ -1997,7 +1378,10 @@ ERL_NIF_TERM encode_address_info(ErlNifEnv* env, fam = encode_address_info_family(env, addrInfoP->ai_family); type = encode_address_info_type(env, addrInfoP->ai_socktype); proto = encode_address_info_proto(env, addrInfoP->ai_protocol); - addr = encode_in_sockaddr(env, addrInfoP->ai_addr, addrInfoP->ai_addrlen); + esock_encode_sockaddr(env, + (SocketAddress*) addrInfoP->ai_addr, + addrInfoP->ai_addrlen, + &addr); result = make_address_info(env, fam, type, proto, addr); @@ -2057,23 +1441,23 @@ ERL_NIF_TERM encode_address_info_type(ErlNifEnv* env, switch (socktype) { case SOCK_STREAM: - etype = atom_stream; + etype = esock_atom_stream; break; case SOCK_DGRAM: - etype = atom_dgram; + etype = esock_atom_dgram; break; case SOCK_RAW: - etype = atom_raw; + etype = esock_atom_raw; break; case SOCK_RDM: - etype = atom_rdm; + etype = esock_atom_rdm; break; case SOCK_SEQPACKET: - etype = atom_seqpacket; + etype = esock_atom_seqpacket; break; default: @@ -2103,26 +1487,26 @@ ERL_NIF_TERM encode_address_info_proto(ErlNifEnv* env, #else case IPPROTO_IP: #endif - eproto = atom_ip; + eproto = esock_atom_ip; break; #if defined(SOL_IPV6) case SOL_IPV6: - eproto = atom_ipv6; + eproto = esock_atom_ipv6; break; #endif case IPPROTO_TCP: - eproto = atom_tcp; + eproto = esock_atom_tcp; break; case IPPROTO_UDP: - eproto = atom_udp; + eproto = esock_atom_udp; break; #if defined(HAVE_SCTP) case IPPROTO_SCTP: - eproto = atom_sctp; + eproto = esock_atom_sctp; break; #endif @@ -2136,110 +1520,6 @@ ERL_NIF_TERM encode_address_info_proto(ErlNifEnv* env, -/* Convert an "native" address to an erlang address - * Note that this is not currently exhaustive, but only supports - * IPv4 and IPv6 addresses. Values of other families will be - * returned as an undefined. - */ -/* -static -ERL_NIF_TERM encode_address_info_addr(ErlNifEnv* env, - struct sockaddr* addrP, - SOCKLEN_T addrLen) -{ - ERL_NIF_TERM port, addr, eaddr; - SockAddress* p = (SockAddress*) addrP; - - NDBG( ("encode_address_info_addr -> entry with" - "\r\n family: %d" - "\r\n addrLen: %d" - "\r\n", addrP->sa_family, addrLen) ); - - switch (addrP->sa_family) { - case AF_INET: - { - unsigned char* a = (unsigned char*) &p->in.sin_addr; - port = MKI(env, ntohs(p->in.sin_port)); - addr = MKT4(env, - MKI(env, a[0]), - MKI(env, a[1]), - MKI(env, a[2]), - MKI(env, a[3])); - eaddr = MKT2(env, port, addr); - } - break; - -#if defined(HAVE_IN6) && defined(AF_INET6) - case AF_INET6: - { - unsigned char* a = (unsigned char*) &p->in6.sin6_addr; - port = MKI(env, ntohs(p->in6.sin6_port)); - addr = MKT8(env, - MKI(env, get_int16(a)), - MKI(env, get_int16(&a[ 2])), - MKI(env, get_int16(&a[ 4])), - MKI(env, get_int16(&a[ 6])), - MKI(env, get_int16(&a[ 8])), - MKI(env, get_int16(&a[10])), - MKI(env, get_int16(&a[12])), - MKI(env, get_int16(&a[14]))); - eaddr = MKT2(env, port, addr); - } - break; -#endif - - default: - eaddr = atom_undefined; - break; - } - - NDBG( ("make_addrinfo_addr -> eaddr: " - "\r\n %T\r\n", eaddr) ); - - return eaddr; -} -*/ - - - -#if defined(HAVE_SYS_UN_H) || defined(SO_BINDTODEVICE) -/* strnlen doesn't exist everywhere */ -static -size_t my_strnlen(const char *s, size_t maxlen) -{ - size_t i = 0; - while (i < maxlen && s[i] != '\0') - i++; - return i; -} -#endif - - - -/* Construct the IPv4 socket address record: in4_sockaddr */ -static -ERL_NIF_TERM make_in4_sockaddr(ErlNifEnv* env, - ERL_NIF_TERM port, - ERL_NIF_TERM addr) -{ - return MKT3(env, atom_in4_sockaddr, port, addr); -} - - - -/* Construct the IPv6 socket address record: in6_sockaddr */ -static -ERL_NIF_TERM make_in6_sockaddr(ErlNifEnv* env, - ERL_NIF_TERM port, - ERL_NIF_TERM addr, - ERL_NIF_TERM flowInfo, - ERL_NIF_TERM scopeId) -{ - return MKT5(env, atom_in6_sockaddr, port, addr, flowInfo, scopeId); -} - - - static ERL_NIF_TERM make_address_info(ErlNifEnv* env, ERL_NIF_TERM fam, @@ -2252,87 +1532,6 @@ ERL_NIF_TERM make_address_info(ErlNifEnv* env, -/* Create an ok two (2) tuple in the form: {ok, Any}. - * The second element (Any) is already in the form of an - * ERL_NIF_TERM so all we have to do is create the tuple. - */ -static -ERL_NIF_TERM make_ok2(ErlNifEnv* env, ERL_NIF_TERM any) -{ - return MKT2(env, atom_ok, any); -} - - -/* Create an ok three (3) tuple in the form: {ok, Val1, Val2}. - * The second (Val1) and third (Val2) elements are already in - * the form of an ERL_NIF_TERM so all we have to do is create - * the tuple. - */ -/* -static -ERL_NIF_TERM make_ok3(ErlNifEnv* env, ERL_NIF_TERM val1, ERL_NIF_TERM val2) -{ - return MKT3(env, atom_ok, val1, val2); -} -*/ - - -/* Create an error two (2) tuple in the form: {error, Reason}. - * The second element (Reason) is already in the form of an - * ERL_NIF_TERM so all we have to do is create the tuple. - */ -static -ERL_NIF_TERM make_error(ErlNifEnv* env, ERL_NIF_TERM reason) -{ - return MKT2(env, atom_error, reason); -} - - -/* Create an error two (2) tuple in the form: {error, Reason}. - * The second element, Reason, is a string to be converted into - * an atom. - */ -static -ERL_NIF_TERM make_error1(ErlNifEnv* env, char* reason) -{ - return make_error(env, MKA(env, reason)); -} - - -/* Create an error two (2) tuple in the form: {error, Reason}. - * The second element, Reason, is the errno value in its - * basic form (integer) which will (eventually) be converted - * into an atom. - */ -static -ERL_NIF_TERM make_error2(ErlNifEnv* env, int err) -{ - NDBG( ("make_error2 -> err: %d\r\n", err) ); - return make_error1(env, erl_errno_id(err)); -} - - -/* -static -void xabort(const char* expr, - const char* func, - const char* file, - int line) -{ - fflush(stdout); - fprintf(stderr, "%s:%d:%s() Assertion failed: %s\n", - file, line, func, expr); - fflush(stderr); - abort(); -} -*/ - - -/* ---------------------------------------------------------------------- - * C o u n t e r F u n c t i o n s - * ---------------------------------------------------------------------- - */ - /* ---------------------------------------------------------------------- * C a l l b a c k F u n c t i o n s * ---------------------------------------------------------------------- @@ -2380,88 +1579,6 @@ void net_down(ErlNifEnv* env, -/* ---------------------------------------------------------------------- - * D e b u g F u n c t i o n s - * ---------------------------------------------------------------------- - */ - -/* - * Print a debug format string *with* both a timestamp and the - * the name of the *current* thread. - */ -static -void dbg_printf( const char* format, ... ) -{ - va_list args; - char f[512 + sizeof(format)]; // This has to suffice... - char stamp[30]; - struct timespec ts; - int res; - - /* - * We should really include self in the printout, so we can se which process - * are executing the code. But then I must change the API.... - * ....something for later. - */ - - if (!dbg_realtime(&ts)) { - if (dbg_timespec2str(stamp, sizeof(stamp), &ts) != 0) { - // res = enif_snprintf(f, sizeof(f), "NET [%s] %s", TSNAME(), format); - res = enif_snprintf(f, sizeof(f), "NET [%s]", format); - } else { - // res = enif_snprintf(f, sizeof(f), "NET[%s] [%s] %s", stamp, TSNAME(), format); - res = enif_snprintf(f, sizeof(f), "NET [%s] %s", stamp, format); - } - - if (res > 0) { - va_start (args, format); - erts_vfprintf (stdout, f, args); // TMP: use enif_vfprintf - va_end (args); - fflush(stdout); - } - } - - return; -} - - -static -int dbg_realtime(struct timespec* tsP) -{ - return clock_gettime(CLOCK_REALTIME, tsP); -} - - - - -/* - * Convert a timespec struct into a readable/printable string - */ -static -int dbg_timespec2str(char *buf, unsigned int len, struct timespec *ts) -{ - int ret, buflen; - struct tm t; - - tzset(); - if (localtime_r(&(ts->tv_sec), &t) == NULL) - return 1; - - ret = strftime(buf, len, "%F %T", &t); - if (ret == 0) - return 2; - len -= ret - 1; - buflen = strlen(buf); - - ret = snprintf(&buf[buflen], len, ".%06ld", ts->tv_nsec/1000); - if (ret >= len) - return 3; - - return 0; -} - - - /* ---------------------------------------------------------------------- * L o a d / u n l o a d / u p g r a d e F u n c t i o n s * ---------------------------------------------------------------------- @@ -2500,78 +1617,40 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) // We should make it possible to use load_info to get default values data.debug = FALSE; - // NDBG( ("on_load -> entry\r\n") ); + NDBG( ("NET", "on_load -> entry\r\n") ); /* +++ Misc atoms +++ */ atom_address_info = MKA(env, str_address_info); - atom_dccp = MKA(env, str_dccp); atom_debug = MKA(env, str_debug); - atom_dgram = MKA(env, str_dgram); - atom_error = MKA(env, str_error); - atom_false = MKA(env, str_false); atom_idn = MKA(env, str_idn); atom_idna_allow_unassigned = MKA(env, str_idna_allow_unassigned); atom_idna_use_std3_ascii_rules = MKA(env, str_idna_use_std3_ascii_rules); - atom_in4_sockaddr = MKA(env, str_in4_sockaddr); - atom_in6_sockaddr = MKA(env, str_in6_sockaddr); - atom_inet = MKA(env, str_inet); - atom_inet6 = MKA(env, str_inet6); - atom_ip = MKA(env, str_ip); - atom_ipv6 = MKA(env, str_ipv6); atom_namereqd = MKA(env, str_namereqd); atom_name_info = MKA(env, str_name_info); atom_nofqdn = MKA(env, str_nofqdn); atom_numerichost = MKA(env, str_numerichost); atom_numericserv = MKA(env, str_numericserv); - atom_ok = MKA(env, str_ok); - atom_raw = MKA(env, str_raw); - atom_rdm = MKA(env, str_rdm); - atom_seqpacket = MKA(env, str_seqpacket); - atom_stream = MKA(env, str_stream); - atom_tcp = MKA(env, str_tcp); - atom_true = MKA(env, str_true); - atom_udp = MKA(env, str_udp); - atom_undefined = MKA(env, str_undefined); - // atom_version = MKA(env, str_version); - - // atom_lowdelay = MKA(env, str_lowdelay); - // atom_throughput = MKA(env, str_throughput); - // atom_reliability = MKA(env, str_reliability); - // atom_mincost = MKA(env, str_mincost); /* Error codes */ - // atom_eafnosupport = MKA(env, str_eafnosupport); atom_eaddrfamily = MKA(env, str_eaddrfamily); - atom_eagain = MKA(env, str_eagain); atom_ebadflags = MKA(env, str_ebadflags); atom_efail = MKA(env, str_efail); atom_efamily = MKA(env, str_efamily); atom_efault = MKA(env, str_efault); - atom_einval = MKA(env, str_einval); - // atom_eisconn = MKA(env, str_eisconn); atom_emem = MKA(env, str_emem); atom_enametoolong = MKA(env, str_enametoolong); atom_enodata = MKA(env, str_enodata); atom_enoname = MKA(env, str_enoname); - // atom_enotclosing = MKA(env, str_enotclosing); - // atom_enotconn = MKA(env, str_enotconn); atom_enxio = MKA(env, str_enxio); atom_eoverflow = MKA(env, str_eoverflow); atom_eservice = MKA(env, str_eservice); atom_esocktype = MKA(env, str_esocktype); atom_esystem = MKA(env, str_esystem); - // atom_exalloc = MKA(env, str_exalloc); - // atom_exbadstate = MKA(env, str_exbadstate); - // atom_exbusy = MKA(env, str_exbusy); - // atom_exnotopen = MKA(env, str_exnotopen); - // atom_exmon = MKA(env, str_exmon); - // atom_exself = MKA(env, str_exself); - // atom_exsend = MKA(env, str_exsend); // For storing "global" things... - // socketData.env = enif_alloc_env(); // We should really check - // socketData.version = MKA(env, ERTS_VERSION); - // socketData.buildDate = MKA(env, ERTS_BUILD_DATE); + // data.env = enif_alloc_env(); // We should really check + // data.version = MKA(env, ERTS_VERSION); + // data.buildDate = MKA(env, ERTS_BUILD_DATE); net = enif_open_resource_type_x(env, "net", @@ -2579,7 +1658,7 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) ERL_NIF_RT_CREATE, NULL); - // NDBG( ("on_load -> done\r\n") ); + NDBG( ("NET", "on_load -> done\r\n") ); return !net; } -- cgit v1.2.3 From b63a16d0958bd748644d22f13f35f8956a903d6c Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 18 Jun 2018 18:19:39 +0200 Subject: [socket+net-nif] Moved common functions into util files The common stuff, like decode and encode of common types (soch as socket address), has been moved into a util file (socket_util). The debug stuff has also been moved into its own file. Also introduced a common include file for common macros and types. OTP-14831 --- erts/emulator/nifs/common/net_nif.c | 87 +++---------------------------------- 1 file changed, 7 insertions(+), 80 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index 9a96eff654..572813ac62 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -1390,7 +1390,7 @@ ERL_NIF_TERM encode_address_info(ErlNifEnv* env, } -/* Convert an "native" family to an erlang family +/* Convert an "native" family to an erlang family (=domain). * Note that this is not currently exhaustive, but only supports * inet and inet6. Other values will be returned as is, that is * in the form of an integer. @@ -1401,34 +1401,15 @@ ERL_NIF_TERM encode_address_info_family(ErlNifEnv* env, { ERL_NIF_TERM efam; - switch (family) { - case AF_INET: - efam = esock_atom_inet; - break; - -#if defined(HAVE_IN6) && defined(AF_INET6) - case AF_INET6: - efam = esock_atom_inet6; - break; -#endif - - #ifdef HAVE_SYS_UN_H - case AF_UNIX: - efam = esock_atom_local; - break; -#endif - - default: + if (NULL != esock_encode_type(env, family, &efam)) efam = MKI(env, family); - break; - } return efam; } -/* Convert an "native" socket type to an erlang socket type +/* Convert an "native" socket type to an erlang socket type. * Note that this is not currently exhaustive, but only supports * stream and dgram. Other values will be returned as is, that is * in the form of an integer. @@ -1439,38 +1420,15 @@ ERL_NIF_TERM encode_address_info_type(ErlNifEnv* env, { ERL_NIF_TERM etype; - switch (socktype) { - case SOCK_STREAM: - etype = esock_atom_stream; - break; - - case SOCK_DGRAM: - etype = esock_atom_dgram; - break; - - case SOCK_RAW: - etype = esock_atom_raw; - break; - - case SOCK_RDM: - etype = esock_atom_rdm; - break; - - case SOCK_SEQPACKET: - etype = esock_atom_seqpacket; - break; - - default: + if (NULL != esock_encode_type(env, socktype, &etype)) etype = MKI(env, socktype); - break; - } return etype; } -/* Convert an "native" protocol to an erlang protocol +/* Convert an "native" protocol to an erlang protocol. * Note that this is not currently exhaustive, but only supports * tcp and udp. Other values will be returned as is, that is * in the form of an integer. @@ -1481,39 +1439,8 @@ ERL_NIF_TERM encode_address_info_proto(ErlNifEnv* env, { ERL_NIF_TERM eproto; - switch (proto) { -#if defined(SOL_IP) - case SOL_IP: -#else - case IPPROTO_IP: -#endif - eproto = esock_atom_ip; - break; - -#if defined(SOL_IPV6) - case SOL_IPV6: - eproto = esock_atom_ipv6; - break; -#endif - - case IPPROTO_TCP: - eproto = esock_atom_tcp; - break; - - case IPPROTO_UDP: - eproto = esock_atom_udp; - break; - -#if defined(HAVE_SCTP) - case IPPROTO_SCTP: - eproto = esock_atom_sctp; - break; -#endif - - default: + if (NULL != esock_encode_protocol(env, proto, &eproto)) eproto = MKI(env, proto); - break; - } return eproto; } @@ -1615,7 +1542,7 @@ static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { // We should make it possible to use load_info to get default values - data.debug = FALSE; + data.debug = TRUE; NDBG( ("NET", "on_load -> entry\r\n") ); -- cgit v1.2.3 From 6632cb103336786f3ca12f9d1f1d3338fc76c237 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 20 Jun 2018 12:33:18 +0200 Subject: [net-nif] Changed return type of getaddrinfo The returned address info was supposed to be a map, by was instead (still) a record. OTP-14831 --- erts/emulator/nifs/common/net_nif.c | 72 +++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 35 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index 572813ac62..6829de509b 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -324,11 +324,12 @@ static ERL_NIF_TERM encode_address_info_type(ErlNifEnv* env, static ERL_NIF_TERM encode_address_info_proto(ErlNifEnv* env, int proto); -static ERL_NIF_TERM make_address_info(ErlNifEnv* env, - ERL_NIF_TERM fam, - ERL_NIF_TERM sockType, - ERL_NIF_TERM proto, - ERL_NIF_TERM addr); +static char* make_address_info(ErlNifEnv* env, + ERL_NIF_TERM fam, + ERL_NIF_TERM sockType, + ERL_NIF_TERM proto, + ERL_NIF_TERM addr, + ERL_NIF_TERM* ai); static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); @@ -1245,6 +1246,7 @@ BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, BOOLEAN_T result; if (IS_ATOM(env, eString)) { + if (COMPARE(eString, esock_atom_undefined) == 0) { *stringP = NULL; result = TRUE; @@ -1252,28 +1254,11 @@ BOOLEAN_T decode_addrinfo_string(ErlNifEnv* env, *stringP = NULL; result = FALSE; } - } else { - unsigned int len; - char* bufP; - if (!GET_LIST_LEN(env, eString, &len) && (len != 0)) { - *stringP = NULL; - result = FALSE; - } + } else { - NDBG( ("NET", "decode_addrinfo_string -> len: %d\r\n", len) ); - - bufP = MALLOC(len + 1); // We shall NULL-terminate + result = esock_decode_string(env, eString, stringP); - if (GET_STR(env, eString, bufP, len+1)) { - NDBG( ("NET", "decode_addrinfo_string -> buf: %s\r\n", bufP) ); - // bufP[len] = '\0'; - *stringP = bufP; - result = TRUE; - } else { - *stringP = NULL; - result = FALSE; - } } return result; @@ -1373,7 +1358,7 @@ static ERL_NIF_TERM encode_address_info(ErlNifEnv* env, struct addrinfo* addrInfoP) { - ERL_NIF_TERM result, fam, type, proto, addr; + ERL_NIF_TERM fam, type, proto, addr, addrInfo; fam = encode_address_info_family(env, addrInfoP->ai_family); type = encode_address_info_type(env, addrInfoP->ai_socktype); @@ -1383,9 +1368,10 @@ ERL_NIF_TERM encode_address_info(ErlNifEnv* env, addrInfoP->ai_addrlen, &addr); - result = make_address_info(env, fam, type, proto, addr); - - return result; + if (make_address_info(env, fam, type, proto, addr, &addrInfo) == NULL) + return addrInfo; + else + return esock_atom_undefined; // We should to better... } @@ -1401,7 +1387,7 @@ ERL_NIF_TERM encode_address_info_family(ErlNifEnv* env, { ERL_NIF_TERM efam; - if (NULL != esock_encode_type(env, family, &efam)) + if (NULL != esock_encode_domain(env, family, &efam)) efam = MKI(env, family); return efam; @@ -1448,13 +1434,29 @@ ERL_NIF_TERM encode_address_info_proto(ErlNifEnv* env, static -ERL_NIF_TERM make_address_info(ErlNifEnv* env, - ERL_NIF_TERM fam, - ERL_NIF_TERM sockType, - ERL_NIF_TERM proto, - ERL_NIF_TERM addr) +char* make_address_info(ErlNifEnv* env, + ERL_NIF_TERM fam, + ERL_NIF_TERM sockType, + ERL_NIF_TERM proto, + ERL_NIF_TERM addr, + ERL_NIF_TERM* ai) { - return MKT5(env, atom_address_info, fam, sockType, proto, addr); + ERL_NIF_TERM keys[] = {esock_atom_family, + esock_atom_type, + esock_atom_protocol, + esock_atom_addr}; + ERL_NIF_TERM vals[] = {fam, sockType, proto, addr}; + unsigned int numKeys = sizeof(keys) / sizeof(ERL_NIF_TERM); + unsigned int numVals = sizeof(vals) / sizeof(ERL_NIF_TERM); + + ESOCK_ASSERT( (numKeys == numVals) ); + + if (!MKMA(env, keys, vals, numKeys, ai)) { + *ai = esock_atom_undefined; + return ESOCK_STR_EINVAL; + } else { + return NULL; + } } -- cgit v1.2.3 From 416644989e26ac76038523511d81ebf9e0b8fc4f Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 13 Jul 2018 12:34:06 +0200 Subject: [net+socket-nif] Updated on_load stuff The net nif-module had debug on by default. Fixed this and also made it an option, just as for the socket nif-module. OTP-14831 --- erts/emulator/nifs/common/net_nif.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index 6829de509b..309ad05a36 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -209,6 +209,9 @@ # define SOCKLEN_T size_t #endif +/* Debug stuff... */ +#define NET_NIF_DEBUG_DEFAULT FALSE + #define NDBG( proto ) ESOCK_DBG_PRINTF( data.debug , proto ) @@ -331,6 +334,8 @@ static char* make_address_info(ErlNifEnv* env, ERL_NIF_TERM addr, ERL_NIF_TERM* ai); +static BOOLEAN_T extract_debug(ErlNifEnv* env, + ERL_NIF_TERM map); static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); @@ -1535,6 +1540,19 @@ ErlNifFunc net_funcs[] = }; +static +BOOLEAN_T extract_debug(ErlNifEnv* env, + ERL_NIF_TERM map) +{ + /* + * We need to do this here since the "proper" atom has not been + * created when this function is called. + */ + ERL_NIF_TERM debug = MKA(env, "debug"); + + return esock_extract_bool_from_map(env, map, debug, NET_NIF_DEBUG_DEFAULT); +} + /* ======================================================================= * load_info - A map of misc info (e.g global debug) @@ -1544,7 +1562,7 @@ static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { // We should make it possible to use load_info to get default values - data.debug = TRUE; + data.debug = extract_debug(env, load_info); NDBG( ("NET", "on_load -> entry\r\n") ); -- 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/emulator/nifs/common/net_nif.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index 309ad05a36..9905d99a04 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -241,9 +241,6 @@ static NetData data; extern char* erl_errno_id(int error); -static ERL_NIF_TERM nif_is_loaded(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); static ERL_NIF_TERM nif_info(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -439,8 +436,8 @@ static ErlNifResourceTypeInit netInit = { * * Utility and admin functions: * ---------------------------- - * nif_is_loaded/0 * nif_info/0 + * nif_command/1 * * The "proper" net functions: * ------------------------------ @@ -454,27 +451,6 @@ static ErlNifResourceTypeInit netInit = { */ -/* ---------------------------------------------------------------------- - * nif_is_loaded - * - * Description: - * This functions only purpose is to return the atom 'true'. - * This will happen *if* the (socket) nif library is loaded. - * If its not, the erlang (nif_is_loaded) will instead return - * 'false'. - */ -static -ERL_NIF_TERM nif_is_loaded(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]) -{ - if (argc != 0) - return enif_make_badarg(env); - - return esock_atom_true; -} - - /* ---------------------------------------------------------------------- * nif_info * @@ -1522,7 +1498,6 @@ static ErlNifFunc net_funcs[] = { // Some utility functions - {"nif_is_loaded", 0, nif_is_loaded, 0}, {"nif_info", 0, nif_info, 0}, {"nif_command", 1, nif_command, 0}, // Shall we let this be dirty? -- cgit v1.2.3 From 37704e1eccc60e2077be13ec0a4c3344d9c04b30 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 21 Sep 2018 12:00:05 +0200 Subject: [socket-nif] More constant if-def and header include moving --- erts/emulator/nifs/common/net_nif.c | 40 ++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index 9905d99a04..f7eeee45ac 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #ifdef HAVE_UNISTD_H @@ -121,6 +120,7 @@ #include #endif +#include #include #include #include @@ -698,37 +698,53 @@ ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, } break; +#if defined(EAI_AGAIN) case EAI_AGAIN: result = esock_make_error(env, esock_atom_eagain); break; +#endif +#if defined(EAI_BADFLAGS) case EAI_BADFLAGS: result = esock_make_error(env, atom_ebadflags); break; +#endif +#if defined(EAI_FAIL) case EAI_FAIL: result = esock_make_error(env, atom_efail); break; +#endif +#if defined(EAI_FAMILY) case EAI_FAMILY: result = esock_make_error(env, atom_efamily); break; +#endif +#if defined(EAI_MEMORY) case EAI_MEMORY: result = esock_make_error(env, atom_emem); break; +#endif +#if defined(EAI_NONAME) case EAI_NONAME: result = esock_make_error(env, atom_enoname); break; +#endif +#if defined(EAI_OVERFLOW) case EAI_OVERFLOW: result = esock_make_error(env, atom_eoverflow); break; +#endif +#if defined(EAI_SYSTEM) case EAI_SYSTEM: result = esock_make_error_errno(env, get_errno()); break; +#endif default: result = esock_make_error(env, esock_atom_einval); @@ -842,49 +858,71 @@ ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env, } break; +#if defined(EAI_ADDRFAMILY) case EAI_ADDRFAMILY: result = esock_make_error(env, atom_eaddrfamily); break; +#endif +#if defined(EAI_AGAIN) case EAI_AGAIN: result = esock_make_error(env, esock_atom_eagain); break; +#endif +#if defined(EAI_BADFLAGS) case EAI_BADFLAGS: result = esock_make_error(env, atom_ebadflags); break; +#endif +#if defined(EAI_FAIL) case EAI_FAIL: result = esock_make_error(env, atom_efail); break; +#endif +#if defined(EAI_FAMILY) case EAI_FAMILY: result = esock_make_error(env, atom_efamily); break; +#endif +#if defined(EAI_MEMORY) case EAI_MEMORY: result = esock_make_error(env, atom_emem); break; +#endif +#if defined(EAI_NODATA) case EAI_NODATA: result = esock_make_error(env, atom_enodata); break; +#endif +#if defined(EAI_NONAME) case EAI_NONAME: result = esock_make_error(env, atom_enoname); break; +#endif +#if defined(EAI_SERVICE) case EAI_SERVICE: result = esock_make_error(env, atom_eservice); break; +#endif +#if defined(EAI_SOCKTYPE) case EAI_SOCKTYPE: result = esock_make_error(env, atom_esocktype); break; +#endif +#if defined(EAI_SYSTEM) case EAI_SYSTEM: result = esock_make_error(env, atom_esystem); break; +#endif default: result = esock_make_error(env, esock_atom_einval); -- cgit v1.2.3 From 060338c0a6904cc4aaf5226dc7fb321ad3d23862 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 30 Jan 2019 14:17:52 +0100 Subject: [socket-nif] Preliminary windows adaptions Added preliminary, and temporary, windows adaptions. Basically they amount to letting all nif-callback functions returning badarg for all calls if on windows (this has been accomplished by if-defing the nif-code; if win32 then badarg else do-something). OTP-15526 --- erts/emulator/nifs/common/net_nif.c | 63 ++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index f7eeee45ac..f51975b564 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -421,7 +421,6 @@ static ERL_NIF_TERM atom_esystem; /* *** net *** */ static ErlNifResourceType* net; -/* Maybe all of these whould be NULL? */ static ErlNifResourceTypeInit netInit = { NULL, // net_dtor, NULL, // net_stop, @@ -462,6 +461,9 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { +#if defined(__WIN32__) + return enif_make_badarg(env); +#else ERL_NIF_TERM info, tmp; NDBG( ("NET", "info -> entry\r\n") ); @@ -473,6 +475,7 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, NDBG( ("NET", "info -> done: %T\r\n", info) ); return info; +#endif } @@ -494,6 +497,9 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { +#if defined(__WIN32__) + return enif_make_badarg(env); +#else ERL_NIF_TERM ecmd, result; NDBG( ("NET", "command -> entry (%d)\r\n", argc) ); @@ -510,6 +516,7 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env, NDBG( ("NET", "command -> result: %T\r\n", result) ); return result; +#endif } @@ -518,6 +525,7 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env, * The command can, in principle, be anything, though currently we only * support a debug command. */ +#if !defined(__WIN32__) static ERL_NIF_TERM ncommand(ErlNifEnv* env, ERL_NIF_TERM cmd) @@ -544,6 +552,7 @@ ERL_NIF_TERM ncommand(ErlNifEnv* env, } } +#endif @@ -559,6 +568,9 @@ ERL_NIF_TERM nif_gethostname(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { +#if defined(__WIN32__) + return enif_make_badarg(env); +#else ERL_NIF_TERM result; NDBG( ("NET", "nif_gethostname -> entry (%d)\r\n", argc) ); @@ -571,9 +583,11 @@ ERL_NIF_TERM nif_gethostname(ErlNifEnv* env, NDBG( ("NET", "nif_gethostname -> done when result: %T\r\n", result) ); return result; +#endif } +#if !defined(__WIN32__) static ERL_NIF_TERM ngethostname(ErlNifEnv* env) { @@ -609,6 +623,7 @@ ERL_NIF_TERM ngethostname(ErlNifEnv* env) return result; } +#endif @@ -629,6 +644,9 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { +#if defined(__WIN32__) + return enif_make_badarg(env); +#else ERL_NIF_TERM result; ERL_NIF_TERM eSockAddr, eFlags; int flags = 0; // Just in case... @@ -661,6 +679,7 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, "\r\n %T\r\n", result) ); return result; +#endif } @@ -668,6 +687,7 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, /* Given the provided sock(et) address (and honts), retreive the host and * service info. */ +#if !defined(__WIN32__) static ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, const SocketAddress* saP, @@ -753,6 +773,7 @@ ERL_NIF_TERM ngetnameinfo(ErlNifEnv* env, return result; } +#endif @@ -773,6 +794,9 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { +#if defined(__WIN32__) + return enif_make_badarg(env); +#else ERL_NIF_TERM result, eHostName, eServName; //, eHints; char* hostName; char* servName; @@ -826,9 +850,11 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, "\r\n %T\r\n", result) ); return result; +#endif } +#if !defined(__WIN32__) static ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env, char* host, @@ -931,6 +957,8 @@ ERL_NIF_TERM ngetaddrinfo(ErlNifEnv* env, return result; } +#endif + /* ---------------------------------------------------------------------- @@ -948,6 +976,9 @@ ERL_NIF_TERM nif_if_name2index(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { +#if defined(__WIN32__) + return enif_make_badarg(env); +#else ERL_NIF_TERM eifn, result; char ifn[IF_NAMESIZE+1]; @@ -971,10 +1002,12 @@ ERL_NIF_TERM nif_if_name2index(ErlNifEnv* env, NDBG( ("NET", "nif_if_name2index -> done when result: %T\r\n", result) ); return result; +#endif } +#if !defined(__WIN32__) static ERL_NIF_TERM nif_name2index(ErlNifEnv* env, char* ifn) @@ -987,12 +1020,16 @@ ERL_NIF_TERM nif_name2index(ErlNifEnv* env, NDBG( ("NET", "nif_name2index -> idx: %d\r\n", idx) ); - if (idx == 0) - return esock_make_error_errno(env, get_errno()); - else + if (idx == 0) { + int save_errno = get_errno(); + NDBG( ("NET", "nif_name2index -> failed: %d\r\n", save_errno) ); + return esock_make_error_errno(env, save_errno); + } else { return esock_make_ok2(env, MKI(env, idx)); + } } +#endif @@ -1011,6 +1048,9 @@ ERL_NIF_TERM nif_if_index2name(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { +#if defined(__WIN32__) + return enif_make_badarg(env); +#else ERL_NIF_TERM result; unsigned int idx; @@ -1030,10 +1070,12 @@ ERL_NIF_TERM nif_if_index2name(ErlNifEnv* env, NDBG( ("NET", "nif_if_index2name -> done when result: %T\r\n", result) ); return result; +#endif } +#if !defined(__WIN32__) static ERL_NIF_TERM nif_index2name(ErlNifEnv* env, unsigned int idx) @@ -1054,6 +1096,7 @@ ERL_NIF_TERM nif_index2name(ErlNifEnv* env, return result; } +#endif @@ -1070,6 +1113,9 @@ ERL_NIF_TERM nif_if_names(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { +#if defined(__WIN32__) + return enif_make_badarg(env); +#else ERL_NIF_TERM result; NDBG( ("NET", "nif_if_names -> entry (%d)\r\n", argc) ); @@ -1083,10 +1129,12 @@ ERL_NIF_TERM nif_if_names(ErlNifEnv* env, NDBG( ("NET", "nif_if_names -> done when result: %T\r\n", result) ); return result; +#endif } +#if !defined(__WIN32__) static ERL_NIF_TERM nif_names(ErlNifEnv* env) { @@ -1159,6 +1207,7 @@ unsigned int nif_names_length(struct if_nameindex* p) return len; } +#endif // if !defined(__WIN32__) @@ -1171,6 +1220,7 @@ unsigned int nif_names_length(struct if_nameindex* p) * A special case is when there is no flags, which is * represented by the atom undefined. */ +#if !defined(__WIN32__) static BOOLEAN_T decode_nameinfo_flags(ErlNifEnv* env, const ERL_NIF_TERM eflags, @@ -1477,6 +1527,7 @@ char* make_address_info(ErlNifEnv* env, return NULL; } } +#endif // if !defined(__WIN32__) @@ -1553,6 +1604,7 @@ ErlNifFunc net_funcs[] = }; +#if !defined(__WIN32__) static BOOLEAN_T extract_debug(ErlNifEnv* env, ERL_NIF_TERM map) @@ -1565,6 +1617,7 @@ BOOLEAN_T extract_debug(ErlNifEnv* env, return esock_extract_bool_from_map(env, map, debug, NET_NIF_DEBUG_DEFAULT); } +#endif /* ======================================================================= @@ -1574,10 +1627,12 @@ BOOLEAN_T extract_debug(ErlNifEnv* env, static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { +#if !defined(__WIN32__) // We should make it possible to use load_info to get default values data.debug = extract_debug(env, load_info); NDBG( ("NET", "on_load -> entry\r\n") ); +#endif /* +++ Misc atoms +++ */ atom_address_info = MKA(env, str_address_info); -- cgit v1.2.3 From 875825874d4a8d52ec5cc593f5024afc696c29df Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 31 Jan 2019 11:34:03 +0100 Subject: [socket-nif] nosup expection of win32 and type(s) replacements The nif callback functions (nif_open) now instead cause an 'nosup' exception if called (instead of badarg). The basic type uint16_t, uint32_t and int32_t (C99) replaced "own" (that is, defined by "us") types Uint16, Uint32 and Sint32. The point of this is that our Windows build system seems to be a bit lacking when it comes to types... Removed "some stuff" that was if-defed. Different solution when win32 support for sockets has been improved. Make sure the socket_*.c util modules are not included in the building for windows. OTP-15526 --- erts/emulator/nifs/common/net_nif.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'erts/emulator/nifs/common/net_nif.c') diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index f51975b564..d48112133f 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -462,7 +462,7 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, const ERL_NIF_TERM argv[]) { #if defined(__WIN32__) - return enif_make_badarg(env); + return enif_raise_exception(env, MKA(env, "nosup")); #else ERL_NIF_TERM info, tmp; @@ -498,7 +498,7 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env, const ERL_NIF_TERM argv[]) { #if defined(__WIN32__) - return enif_make_badarg(env); + return enif_raise_exception(env, MKA(env, "nosup")); #else ERL_NIF_TERM ecmd, result; @@ -569,7 +569,7 @@ ERL_NIF_TERM nif_gethostname(ErlNifEnv* env, const ERL_NIF_TERM argv[]) { #if defined(__WIN32__) - return enif_make_badarg(env); + return enif_raise_exception(env, MKA(env, "nosup")); #else ERL_NIF_TERM result; @@ -645,7 +645,7 @@ ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, const ERL_NIF_TERM argv[]) { #if defined(__WIN32__) - return enif_make_badarg(env); + return enif_raise_exception(env, MKA(env, "nosup")); #else ERL_NIF_TERM result; ERL_NIF_TERM eSockAddr, eFlags; @@ -795,7 +795,7 @@ ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, const ERL_NIF_TERM argv[]) { #if defined(__WIN32__) - return enif_make_badarg(env); + return enif_raise_exception(env, MKA(env, "nosup")); #else ERL_NIF_TERM result, eHostName, eServName; //, eHints; char* hostName; @@ -977,7 +977,7 @@ ERL_NIF_TERM nif_if_name2index(ErlNifEnv* env, const ERL_NIF_TERM argv[]) { #if defined(__WIN32__) - return enif_make_badarg(env); + return enif_raise_exception(env, MKA(env, "nosup")); #else ERL_NIF_TERM eifn, result; char ifn[IF_NAMESIZE+1]; @@ -1049,7 +1049,7 @@ ERL_NIF_TERM nif_if_index2name(ErlNifEnv* env, const ERL_NIF_TERM argv[]) { #if defined(__WIN32__) - return enif_make_badarg(env); + return enif_raise_exception(env, MKA(env, "nosup")); #else ERL_NIF_TERM result; unsigned int idx; @@ -1114,7 +1114,7 @@ ERL_NIF_TERM nif_if_names(ErlNifEnv* env, const ERL_NIF_TERM argv[]) { #if defined(__WIN32__) - return enif_make_badarg(env); + return enif_raise_exception(env, MKA(env, "nosup")); #else ERL_NIF_TERM result; @@ -1673,7 +1673,9 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) ERL_NIF_RT_CREATE, NULL); +#if !defined(__WIN32__) NDBG( ("NET", "on_load -> done\r\n") ); +#endif return !net; } -- cgit v1.2.3