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 ++++--------------------------- erts/emulator/nifs/common/socket_dbg.h | 10 + erts/emulator/nifs/common/socket_int.h | 20 +- erts/emulator/nifs/common/socket_nif.c | 416 +++++------ erts/emulator/nifs/common/socket_util.c | 474 +++++++++++- erts/emulator/nifs/common/socket_util.h | 47 ++ 6 files changed, 858 insertions(+), 1312 deletions(-) (limited to 'erts/emulator/nifs/common') 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; } diff --git a/erts/emulator/nifs/common/socket_dbg.h b/erts/emulator/nifs/common/socket_dbg.h index 36e2be1679..ad0fcdada9 100644 --- a/erts/emulator/nifs/common/socket_dbg.h +++ b/erts/emulator/nifs/common/socket_dbg.h @@ -28,6 +28,16 @@ #define SOCKET_DBG_H__ +/* Used in debug printouts */ +#ifdef __WIN32__ +#define LLU "%I64u" +#else +#define LLU "%llu" +#endif +typedef unsigned long long llu_t; + + + #define ESOCK_DBG_PRINTF( ___COND___ , proto ) \ if ( ___COND___ ) { \ esock_dbg_printf proto; \ diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h index 83794f0b95..d6a612cab6 100644 --- a/erts/emulator/nifs/common/socket_int.h +++ b/erts/emulator/nifs/common/socket_int.h @@ -67,7 +67,7 @@ /* The general purpose sockaddr */ typedef union { /* General sockaddr */ - struct sockaddr in; + struct sockaddr sa; /* IPv4 sockaddr */ struct sockaddr_in in4; @@ -85,44 +85,56 @@ typedef union { } SocketAddress; +/* *** Boolean *type* stuff... *** */ typedef unsigned int BOOLEAN_T; #define TRUE 1 #define FALSE 0 +#define BOOL2ATOM(__B__) ((__B__) ? esock_atom_true : esock_atom_false) + /* Misc error strings */ -#define ESOCK_STR_EINVAL "einval" #define ESOCK_STR_EAFNOSUPPORT "eafnosupport" +#define ESOCK_STR_EAGAIN "eagain" +#define ESOCK_STR_EINVAL "einval" /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * Misc atoms + * "Global" atoms */ extern ERL_NIF_TERM esock_atom_addr; extern ERL_NIF_TERM esock_atom_any; extern ERL_NIF_TERM esock_atom_dgram; extern ERL_NIF_TERM esock_atom_error; +extern ERL_NIF_TERM esock_atom_false; extern ERL_NIF_TERM esock_atom_family; extern ERL_NIF_TERM esock_atom_flowinfo; extern ERL_NIF_TERM esock_atom_inet; extern ERL_NIF_TERM esock_atom_inet6; +extern ERL_NIF_TERM esock_atom_ip; +extern ERL_NIF_TERM esock_atom_ipv6; extern ERL_NIF_TERM esock_atom_local; extern ERL_NIF_TERM esock_atom_loopback; extern ERL_NIF_TERM esock_atom_ok; extern ERL_NIF_TERM esock_atom_path; extern ERL_NIF_TERM esock_atom_port; extern ERL_NIF_TERM esock_atom_raw; +extern ERL_NIF_TERM esock_atom_rdm; extern ERL_NIF_TERM esock_atom_scope_id; +extern ERL_NIF_TERM esock_atom_sctp; extern ERL_NIF_TERM esock_atom_seqpacket; extern ERL_NIF_TERM esock_atom_stream; +extern ERL_NIF_TERM esock_atom_tcp; +extern ERL_NIF_TERM esock_atom_true; +extern ERL_NIF_TERM esock_atom_udp; extern ERL_NIF_TERM esock_atom_undefined; /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * Error value (=reason) atoms */ -extern ERL_NIF_TERM esock_atom_eagain; extern ERL_NIF_TERM esock_atom_eafnosupport; +extern ERL_NIF_TERM esock_atom_eagain; extern ERL_NIF_TERM esock_atom_einval; diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 335d773f89..d2455a7b3a 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -181,22 +181,6 @@ #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 #define SOCKET_DEBUG_DEFAULT TRUE @@ -205,15 +189,6 @@ typedef unsigned int BOOLEAN_T; #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 @@ -301,9 +276,9 @@ typedef unsigned long long llu_t; #define SOCKET_RECV_BUFFER_SIZE_DEFAULT 2048 -#define SOCKET_OPT_VALLUE_TYPE_UNSPEC 0 -#define SOCKET_OPT_VALLUE_TYPE_INT 1 -#define SOCKET_OPT_VALLUE_TYPE_BOOL 2 +#define SOCKET_OPT_VALUE_TYPE_UNSPEC 0 +#define SOCKET_OPT_VALUE_TYPE_INT 1 +#define SOCKET_OPT_VALUE_TYPE_BOOL 2 typedef union { struct { @@ -1248,15 +1223,17 @@ static BOOLEAN_T decode_sock_linger(ErlNifEnv* env, static BOOLEAN_T decode_ip_tos(ErlNifEnv* env, ERL_NIF_TERM eVal, int* val); +/* static BOOLEAN_T decode_bool(ErlNifEnv* env, ERL_NIF_TERM eVal, BOOLEAN_T* val); +*/ static BOOLEAN_T decode_native_get_opt(ErlNifEnv* env, ERL_NIF_TERM eVal, int* opt, uint16_t* valueType, int* valueSz); -static void encode_bool(BOOLEAN_T val, ERL_NIF_TERM* eVal); +// static void encode_bool(BOOLEAN_T val, ERL_NIF_TERM* eVal); static ERL_NIF_TERM encode_ip_tos(ErlNifEnv* env, int val); static void inform_waiting_procs(ErlNifEnv* env, @@ -1330,11 +1307,6 @@ static char* send_msg(ErlNifEnv* env, ERL_NIF_TERM msg, ErlNifPid* pid); -static void xabort(const char* expr, - const char* func, - const char* file, - int line); - static BOOLEAN_T extract_item_on_load(ErlNifEnv* env, ERL_NIF_TERM map, ERL_NIF_TERM key, @@ -1407,9 +1379,6 @@ static char str_reliability[] = "reliability"; static char str_mincost[] = "mincost"; /* (special) error string constants */ -static char str_eagain[] = "eagain"; -static char str_eafnosupport[] = "eafnosupport"; -static char str_einval[] = "einval"; static char str_eisconn[] = "eisconn"; static char str_enotclosing[] = "enotclosing"; static char str_enotconn[] = "enotconn"; @@ -1426,21 +1395,33 @@ ERL_NIF_TERM esock_atom_addr; ERL_NIF_TERM esock_atom_any; ERL_NIF_TERM esock_atom_dgram; ERL_NIF_TERM esock_atom_error; +ERL_NIF_TERM esock_atom_false; ERL_NIF_TERM esock_atom_family; ERL_NIF_TERM esock_atom_flowinfo; ERL_NIF_TERM esock_atom_inet; ERL_NIF_TERM esock_atom_inet6; +ERL_NIF_TERM esock_atom_ip; +ERL_NIF_TERM esock_atom_ipv6; ERL_NIF_TERM esock_atom_local; ERL_NIF_TERM esock_atom_loopback; ERL_NIF_TERM esock_atom_ok; ERL_NIF_TERM esock_atom_path; ERL_NIF_TERM esock_atom_port; ERL_NIF_TERM esock_atom_raw; +ERL_NIF_TERM esock_atom_rdm; ERL_NIF_TERM esock_atom_scope_id; +ERL_NIF_TERM esock_atom_sctp; ERL_NIF_TERM esock_atom_seqpacket; ERL_NIF_TERM esock_atom_stream; +ERL_NIF_TERM esock_atom_tcp; +ERL_NIF_TERM esock_atom_true; +ERL_NIF_TERM esock_atom_udp; ERL_NIF_TERM esock_atom_undefined; +/* *** "Global" error (=reason) atoms *** */ +ERL_NIF_TERM esock_atom_eagain; +ERL_NIF_TERM esock_atom_eafnosupport; +ERL_NIF_TERM esock_atom_einval; /* *** Atoms *** */ static ERL_NIF_TERM atom_close; @@ -1473,9 +1454,6 @@ static ERL_NIF_TERM atom_throughput; static ERL_NIF_TERM atom_reliability; static ERL_NIF_TERM atom_mincost; -static ERL_NIF_TERM atom_eagain; -static ERL_NIF_TERM atom_eafnosupport; -static ERL_NIF_TERM atom_einval; static ERL_NIF_TERM atom_eisconn; static ERL_NIF_TERM atom_enotclosing; static ERL_NIF_TERM atom_enotconn; @@ -1597,7 +1575,7 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, unsigned int numKeys = sizeof(keys) / sizeof(ERL_NIF_TERM); unsigned int numVals = sizeof(keys) / sizeof(ERL_NIF_TERM); - SASSERT( (numKeys == numVals) ); + ESOCK_ASSERT( (numKeys == numVals) ); if (!MKMA(env, keys, vals, numKeys, &info)) return enif_make_badarg(env); @@ -1982,7 +1960,7 @@ ERL_NIF_TERM nbind(ErlNifEnv* env, if (port == 0) { SOCKLEN_T len = sizeof(local); sys_memzero((char *) &local, len); - sock_name(descP->sock, &local.in, &len); + sock_name(descP->sock, &local.sa, &len); port = which_address_port(&local); } else if (port == -1) { port = 0; @@ -2012,7 +1990,7 @@ char* decode_laddress(ErlNifEnv* env, } else if (IS_TUPLE(env, localAddr)) { return decode_in_sockaddr(env, localAddr, localP, addrLenP); } else { - return str_einval; + return ESOCK_STR_EINVAL; } } @@ -2035,10 +2013,10 @@ char* decode_laddress_binary(ErlNifEnv* env, ErlNifBinary bin; if (domain != AF_UNIX) - return str_einval; + return ESOCK_STR_EINVAL; if (!GET_BIN(env, localAddr, &bin)) - return str_einval; + return ESOCK_STR_EINVAL; if ((bin.size + #ifdef __linux__ @@ -2054,7 +2032,7 @@ char* decode_laddress_binary(ErlNifEnv* env, 1 #endif ) > sizeof(localP->un.sun_path)) - return str_einval; + return ESOCK_STR_EINVAL; sys_memzero((char*)localP, sizeof(struct sockaddr_un)); localP->un.sun_family = domain; @@ -2128,7 +2106,7 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, return esock_make_error(env, atom_eisconn); if (IS_CONNECTING(descP)) - return esock_make_error(env, atom_einval); + return esock_make_error(env, esock_atom_einval); code = sock_connect(descP->sock, (struct sockaddr*) &descP->remote, @@ -2364,7 +2342,7 @@ ERL_NIF_TERM naccept(ErlNifEnv* env, break; default: - res = esock_make_error(env, atom_einval); + res = esock_make_error(env, esock_atom_einval); break; } @@ -2437,7 +2415,7 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env, descP->state = SOCKET_STATE_ACCEPTING; - return esock_make_error(env, atom_eagain); + return esock_make_error(env, esock_atom_eagain); } else { return esock_make_error_errno(env, save_errno); @@ -2540,7 +2518,7 @@ ERL_NIF_TERM naccept_accepting(ErlNifEnv* env, (ERL_NIF_SELECT_READ), descP, NULL, ref); - return esock_make_error(env, atom_eagain); + return esock_make_error(env, esock_atom_eagain); } else { return esock_make_error_errno(env, save_errno); } @@ -2742,10 +2720,10 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env, /* THIS TEST IS NOT CORRECT!!! */ if (!IS_OPEN(descP)) - return esock_make_error(env, atom_einval); + return esock_make_error(env, esock_atom_einval); if (!esendflags2sendflags(eflags, &flags)) - return esock_make_error(env, atom_einval); + return esock_make_error(env, esock_atom_einval); if ((xres = decode_in_sockaddr(env, eSockAddr, &remoteAddr, @@ -2778,7 +2756,7 @@ ERL_NIF_TERM nsendto(ErlNifEnv* env, if (toAddrP != NULL) { written = sock_sendto(descP->sock, dataP->data, dataP->size, flags, - &toAddrP->in, toAddrLen); + &toAddrP->sa, toAddrLen); } else { written = sock_sendto(descP->sock, dataP->data, dataP->size, flags, @@ -3069,7 +3047,7 @@ ERL_NIF_TERM nrecvfrom(ErlNifEnv* env, sys_memzero((char*) &fromAddr, addrLen); read = sock_recvfrom(descP->sock, buf.data, buf.size, flags, - &fromAddr.in, &addrLen); + &fromAddr.sa, &addrLen); return recvfrom_check_result(env, descP, read, @@ -3368,11 +3346,10 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env, eIsEncoded = argv[1]; eVal = argv[4]; - if (!decode_bool(env, eIsEncoded, &isEncoded)) - return esock_make_error(env, atom_einval); + isEncoded = esock_decode_bool(eIsEncoded); if (!elevel2level(isEncoded, eLevel, &isOTP, &level)) - return esock_make_error(env, atom_einval); + return esock_make_error(env, esock_atom_einval); return nsetopt(env, descP, isEncoded, isOTP, level, eOpt, eVal); } @@ -3425,7 +3402,7 @@ ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env, break; default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -3440,15 +3417,9 @@ ERL_NIF_TERM nsetopt_otp_debug(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM eVal) { - ERL_NIF_TERM result; + descP->dbg = esock_decode_bool(eVal); - if (decode_bool(env, eVal, &descP->dbg)) { - result = esock_atom_ok; - } else { - result = esock_make_error(env, atom_einval); - } - - return result; + return esock_atom_ok; } @@ -3459,15 +3430,9 @@ ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM eVal) { - ERL_NIF_TERM result; + descP->iow = esock_decode_bool(eVal); - if (decode_bool(env, eVal, &descP->iow)) { - result = esock_atom_ok; - } else { - result = esock_make_error(env, atom_einval); - } - - return result; + return esock_atom_ok; } @@ -3493,7 +3458,7 @@ ERL_NIF_TERM nsetopt_native(ErlNifEnv* env, else result = esock_atom_ok; } else { - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); } return result; @@ -3546,7 +3511,7 @@ ERL_NIF_TERM nsetopt_level(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -3615,7 +3580,7 @@ ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -3674,7 +3639,7 @@ ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env, else result = esock_atom_ok; } else { - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); } return result; @@ -3763,7 +3728,7 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -3834,7 +3799,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env, result = esock_atom_ok; } else { - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); } return result; @@ -3881,7 +3846,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -3934,7 +3899,7 @@ ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -4002,7 +3967,7 @@ ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -4050,7 +4015,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -4113,7 +4078,7 @@ ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env, result = esock_atom_ok; } else { - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); } FREE(val); @@ -4133,19 +4098,17 @@ ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env, { ERL_NIF_TERM result; BOOLEAN_T val; + int ival, res; - if (decode_bool(env, eVal, &val)) { - int ival = (val) ? 1 : 0; - int res = socket_setopt(descP->sock, level, opt, &ival, sizeof(ival)); - - if (res != 0) - result = esock_make_error_errno(env, res); - else - result = esock_atom_ok; + val = esock_decode_bool(eVal); + + ival = (val) ? 1 : 0; + res = socket_setopt(descP->sock, level, opt, &ival, sizeof(ival)); - } else { - result = esock_make_error(env, atom_einval); - } + if (res != 0) + result = esock_make_error_errno(env, res); + else + result = esock_atom_ok; return result; } @@ -4172,7 +4135,7 @@ ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env, result = esock_atom_ok; } else { - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); } return result; @@ -4378,11 +4341,10 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env, } eIsEncoded = argv[1]; - if (!decode_bool(env, eIsEncoded, &isEncoded)) - return esock_make_error(env, atom_einval); + isEncoded = esock_decode_bool(eIsEncoded); if (!elevel2level(isEncoded, eLevel, &isOTP, &level)) - return esock_make_error(env, atom_einval); + return esock_make_error(env, esock_atom_einval); return ngetopt(env, descP, isEncoded, isOTP, level, eOpt); } @@ -4434,7 +4396,7 @@ ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env, break; default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -4448,9 +4410,7 @@ static ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env, SocketDescriptor* descP) { - ERL_NIF_TERM eVal; - - encode_bool(descP->dbg, &eVal); + ERL_NIF_TERM eVal = esock_encode_bool(descP->dbg); return esock_make_ok2(env, eVal); } @@ -4462,9 +4422,7 @@ static ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env, SocketDescriptor* descP) { - ERL_NIF_TERM eVal; - - encode_bool(descP->iow, &eVal); + ERL_NIF_TERM eVal = esock_encode_bool(descP->iow); return esock_make_ok2(env, eVal); } @@ -4494,21 +4452,21 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, if (decode_native_get_opt(env, eOpt, &opt, &valueType, (int*) &valueSz)) { switch (valueType) { - case SOCKET_OPT_VALLUE_TYPE_UNSPEC: + case SOCKET_OPT_VALUE_TYPE_UNSPEC: result = ngetopt_native_unspec(env, descP, level, opt, valueSz); break; - case SOCKET_OPT_VALLUE_TYPE_INT: + case SOCKET_OPT_VALUE_TYPE_INT: result = ngetopt_int_opt(env, descP, level, opt); break; - case SOCKET_OPT_VALLUE_TYPE_BOOL: + case SOCKET_OPT_VALUE_TYPE_BOOL: result = ngetopt_bool_opt(env, descP, level, opt); break; default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } } else { - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); } return result; @@ -4601,7 +4559,7 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -4668,7 +4626,7 @@ ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -4811,7 +4769,7 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -4922,7 +4880,7 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -4973,7 +4931,7 @@ ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -5037,7 +4995,7 @@ ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -5082,7 +5040,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env, #endif default: - result = esock_make_error(env, atom_einval); + result = esock_make_error(env, esock_atom_einval); break; } @@ -5352,7 +5310,7 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env, } else if ((save_errno == ERRNO_BLOCK) || (save_errno == EAGAIN)) { - return esock_make_error(env, atom_eagain); + return esock_make_error(env, esock_atom_eagain); } else { return esock_make_error_errno(env, save_errno); } @@ -5437,7 +5395,7 @@ ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env, } else if ((save_errno == ERRNO_BLOCK) || (save_errno == EAGAIN)) { - return esock_make_error(env, atom_eagain); + return esock_make_error(env, esock_atom_eagain); } else { return esock_make_error_errno(env, save_errno); } @@ -5501,23 +5459,23 @@ char* decode_send_addr(ErlNifEnv* env, if (!(GET_ATOM_LEN(env, addr, &len) && (len > 0) && (len <= (sizeof("null"))))) - return str_einval; + return ESOCK_STR_EINVAL; if (!GET_ATOM(env, addr, a, sizeof(a))) - return str_einval; + return ESOCK_STR_EINVAL; *toAddrP = NULL; if (strncmp(a, "null", len) == 0) return NULL; else - return str_einval; + return ESOCK_STR_EINVAL; } else if (IS_TUPLE(env, addr)) { / * We now know that the we have a proper address. * / return decode_send_addr_tuple(env, domain, addr, port, *toAddrP, toAddrLenP); } else { - return str_einval; + return ESOCK_STR_EINVAL; } } */ @@ -5540,18 +5498,18 @@ char* decode_send_addr_tuple(ErlNifEnv* env, int addrtSz; if (!GET_TUPLE(env, addr, &addrtSz, &addrt)) - return str_einval; // PLACEHOLDER + return ESOCK_STR_EINVAL; // PLACEHOLDER switch (domain) { case AF_INET: if (addrtSz != 4) - return str_einval; + return ESOCK_STR_EINVAL; break; #if defined(HAVE_IN6) && defined(AF_INET6) case AF_INET6: if (addrtSz != 8) - return str_einval; + return ESOCK_STR_EINVAL; break; #endif @@ -5592,7 +5550,7 @@ char* decode_in_sockaddr(ErlNifEnv* env, char* result = NULL; if (!GET_TUPLE(env, eSockAddr, &addrtSz, &addrt)) - return str_einval; + return ESOCK_STR_EINVAL; /* * We use the tuple size to figure out which @@ -5610,7 +5568,7 @@ char* decode_in_sockaddr(ErlNifEnv* env, #endif default: - result = str_eafnosupport; + result = ESOCK_STR_EAFNOSUPPORT; break; } @@ -5634,11 +5592,11 @@ char* decode_in4_sockaddr(ErlNifEnv* env, /* 1: Ensure that the tuple has the correct tag: in4_sockaddr */ if (COMPARE(atom_in4_sockaddr, eIn4SockAddr[0]) != 0) - return str_einval; + return ESOCK_STR_EINVAL; /* 2: Get the port number */ if (!GET_INT(env, eIn4SockAddr[1], &port)) - return str_einval; + return ESOCK_STR_EINVAL; /* 3: Get the address. * It can either be the atoms: any | loopback, @@ -5651,7 +5609,7 @@ char* decode_in4_sockaddr(ErlNifEnv* env, return decode_in4_sockaddr_addr(env, eIn4SockAddr[2], port, sockAddrP, addrLenP); } else { - return str_einval; + return ESOCK_STR_EINVAL; } } @@ -5671,7 +5629,7 @@ char* decode_in4_sockaddr_atomaddr(ErlNifEnv* env, } else if (COMPARE(esock_atom_any, eAddr) == 0) { addr.s_addr = sock_htonl(INADDR_ANY); } else { - return str_einval; + return ESOCK_STR_EINVAL; } sys_memzero((char*) sockAddrP, sizeof(struct sockaddr_in)); @@ -5704,10 +5662,10 @@ char* decode_in4_sockaddr_addr(ErlNifEnv* env, /* This shall be a 4 tuple */ if (!GET_TUPLE(env, eAddr, &ip4AddrTSz, &ip4AddrT)) - return str_einval; + return ESOCK_STR_EINVAL; if (ip4AddrTSz != 4) - return str_einval; + return ESOCK_STR_EINVAL; sys_memzero((char*)sockAddrP, sizeof(struct sockaddr_in)); #ifndef NO_SA_LEN @@ -5717,7 +5675,7 @@ char* decode_in4_sockaddr_addr(ErlNifEnv* env, sockAddrP->in4.sin_port = sock_htons(port); for (a = 0; a < 4; a++) { if (!GET_INT(env, ip4AddrT[a], &v)) - return str_einval; + return ESOCK_STR_EINVAL; addr[a] = v; } sys_memcpy(&sockAddrP->in4.sin_addr, &addr, sizeof(addr)); @@ -5747,19 +5705,19 @@ char* decode_in6_sockaddr(ErlNifEnv* env, /* 1: Ensure that the tuple has the correct tag: in6_sockaddr */ if (COMPARE(atom_in6_sockaddr, eIn6SockAddr[0]) != 0) - return str_einval; + return ESOCK_STR_EINVAL; /* 2: Get the port number */ if (!GET_INT(env, eIn6SockAddr[1], &port)) - return str_einval; + return ESOCK_STR_EINVAL; /* 4: Get the flowinfo */ if (!GET_UINT(env, eIn6SockAddr[3], &flowInfo)) - return str_einval; + return ESOCK_STR_EINVAL; /* 5: Get the scope_id */ if (!GET_UINT(env, eIn6SockAddr[4], &scopeId)) - return str_einval; + return ESOCK_STR_EINVAL; /* 3: Get the address. * It can either be the atoms: any | loopback, @@ -5774,7 +5732,7 @@ char* decode_in6_sockaddr(ErlNifEnv* env, flowInfo, scopeId, sockAddrP, addrLenP); } else { - return str_einval; + return ESOCK_STR_EINVAL; } } #endif @@ -5797,7 +5755,7 @@ char* decode_in6_sockaddr_atomaddr(ErlNifEnv* env, } else if (COMPARE(esock_atom_any, eAddr) == 0) { addr = &in6addr_any; } else { - return str_einval; + return ESOCK_STR_EINVAL; } sys_memzero((char*)sockAddrP, sizeof(struct sockaddr_in6)); @@ -5835,10 +5793,10 @@ char* decode_in6_sockaddr_addr(ErlNifEnv* env, /* This shall be a 8 tuple */ if (!GET_TUPLE(env, eAddr, &ip6AddrTSz, &ip6AddrT)) - return str_einval; + return ESOCK_STR_EINVAL; if (ip6AddrTSz != 8) - return str_einval; + return ESOCK_STR_EINVAL; sys_memzero((char*)sockAddrP, sizeof(struct sockaddr_in6)); #ifndef NO_SA_LEN @@ -5853,7 +5811,7 @@ char* decode_in6_sockaddr_addr(ErlNifEnv* env, */ for (a = 0; a < 8; a++) { if (!GET_INT(env, ip6AddrT[a], &v)) - return str_einval; + return ESOCK_STR_EINVAL; addr[a*2 ] = ((v >> 8) & 0xFF); addr[a*2+1] = (v & 0xFF); } @@ -5896,7 +5854,7 @@ char* decode_address_tuple(ErlNifEnv* env, addrP->sai.sin_port = sock_htons(port); for (a = 0; a < 4; a++) { if (!GET_INT(env, addrt[a], &v)) - return str_einval; + return ESOCK_STR_EINVAL; laddr[a] = v; } sys_memcpy(&addrP->sai.sin_addr, &laddr, sizeof(laddr)); @@ -5923,7 +5881,7 @@ char* decode_address_tuple(ErlNifEnv* env, * / for (a = 0; a < 8; a++) { if (!GET_INT(env, addrt[a], &v)) - return str_einval; + return ESOCK_STR_EINVAL; laddr[a*2 ] = ((v >> 8) & 0xFF); laddr[a*2+1] = (v & 0xFF); } @@ -5936,7 +5894,7 @@ char* decode_address_tuple(ErlNifEnv* env, } / * switch (domain) * / - return str_eafnosupport; + return ESOCK_STR_EAFNOSUPPORT; } */ @@ -5956,14 +5914,14 @@ char* decode_address_tuple(ErlNifEnv* env, */ static void encode_address(ErlNifEnv* env, - SocketAddress* addrP, + SocketAddress* sockAddrP, unsigned int addrLen, ERL_NIF_TERM* domainT, ERL_NIF_TERM* sourceT) { short port; - switch (addrP->in.sa_family) { + switch (sockAddrP->sa.sa_family) { /* +++ inet (IPv4) +++ */ @@ -5972,9 +5930,9 @@ void encode_address(ErlNifEnv* env, ERL_NIF_TERM addrT, portT; unsigned int i; ERL_NIF_TERM at4[4]; - char* a4 = (char*) &addrP->in4.sin_addr; + char* a4 = (char*) &sockAddrP->in4.sin_addr; - port = sock_ntohs(addrP->in4.sin_port); + port = sock_ntohs(sockAddrP->in4.sin_port); for (i = 0; i < 4; i++) { at4[i] = MKI(env, a4[i]); } @@ -5998,9 +5956,9 @@ void encode_address(ErlNifEnv* env, ERL_NIF_TERM addrT, portT; unsigned int i; ERL_NIF_TERM at6[8]; - char* a16 = (char*) &addrP->in6.sin6_addr; + char* a16 = (char*) &sockAddrP->in6.sin6_addr; - port = sock_ntohs(addrP->in6.sin6_port); + port = sock_ntohs(sockAddrP->in6.sin6_port); /* The address tuple is of size 8 * and each element is a two byte integer */ @@ -6037,7 +5995,7 @@ void encode_address(ErlNifEnv* env, if (255 < n) { *sourceT = esock_atom_undefined; } else { - m = my_strnlen(addrP->un.sun_path, n); + m = my_strnlen(sockAddrP->un.sun_path, n); #ifdef __linux__ /* Assume that the address is a zero terminated string, * except when the first byte is \0 i.e the string length is 0, @@ -6050,7 +6008,7 @@ void encode_address(ErlNifEnv* env, } #endif - *sourceT = MKSL(env, addrP->un.sun_path, m); + *sourceT = MKSL(env, sockAddrP->un.sun_path, m); } } } @@ -6087,7 +6045,7 @@ char* decode_address_atom(ErlNifEnv* env, } if (strncmp(addr, "loopback", addrLen) == 0) { any = FALSE; } else { - return str_einval; + return ESOCK_STR_EINVAL; } / * If we get this far, we *know* its either 'any' or 'loopback' * / @@ -6135,7 +6093,7 @@ char* decode_address_atom(ErlNifEnv* env, #endif default: - return str_einval; + return ESOCK_STR_EINVAL; break; } @@ -6143,23 +6101,24 @@ char* decode_address_atom(ErlNifEnv* env, } */ +/* static BOOLEAN_T decode_bool(ErlNifEnv* env, ERL_NIF_TERM eVal, BOOLEAN_T* val) { unsigned int len; char b[16]; // Just in case... - /* Verify that the value is actually an atom */ + / * Verify that the value is actually an atom * / if (!IS_ATOM(env, eVal)) return FALSE; - /* Verify that the value is of acceptable length */ + / * Verify that the value is of acceptable length * / if (!(GET_ATOM_LEN(env, eVal, &len) && (len > 0) && (len <= sizeof("false")))) return FALSE; - /* And finally try to extract the value */ + / * And finally try to extract the value * / if (!GET_ATOM(env, eVal, b, sizeof(b))) return FALSE; @@ -6170,6 +6129,7 @@ BOOLEAN_T decode_bool(ErlNifEnv* env, ERL_NIF_TERM eVal, BOOLEAN_T* val) return TRUE; } +*/ /* +++ decode the linger value +++ @@ -6195,8 +6155,7 @@ BOOLEAN_T decode_sock_linger(ErlNifEnv* env, ERL_NIF_TERM eVal, struct linger* v /* So fas so good - now check the two elements of the tuple. */ - if (!decode_bool(env, lt[0], &onOff)) - return FALSE; + onOff = esock_decode_bool(lt[0]); if (!GET_INT(env, lt[1], &secs)) return FALSE; @@ -6326,10 +6285,10 @@ BOOLEAN_T decode_native_get_opt(ErlNifEnv* env, ERL_NIF_TERM eVal, return FALSE; if (strncmp(t, "bool", len) == 0) { - *valueType = SOCKET_OPT_VALLUE_TYPE_BOOL; + *valueType = SOCKET_OPT_VALUE_TYPE_BOOL; *valueSz = sizeof(int); // Just to be sure } else if (strncmp(t, "int", len) == 0) { - *valueType = SOCKET_OPT_VALLUE_TYPE_INT; + *valueType = SOCKET_OPT_VALUE_TYPE_INT; *valueSz = sizeof(int); // Just to be sure } else { return FALSE; @@ -6337,7 +6296,7 @@ BOOLEAN_T decode_native_get_opt(ErlNifEnv* env, ERL_NIF_TERM eVal, } else if (IS_NUM(env, nativeOptT[1])) { if (GET_INT(env, nativeOptT[1], valueSz)) { - *valueType = SOCKET_OPT_VALLUE_TYPE_UNSPEC; + *valueType = SOCKET_OPT_VALUE_TYPE_UNSPEC; } else { return FALSE; } @@ -6349,14 +6308,16 @@ BOOLEAN_T decode_native_get_opt(ErlNifEnv* env, ERL_NIF_TERM eVal, } +/* static void encode_bool(BOOLEAN_T val, ERL_NIF_TERM* eVal) { if (val) - *eVal = atom_true; + *eVal = esock_atom_true; else - *eVal = atom_false; + *eVal = esock_atom_false; } +*/ /* +++ encode the ip socket option tos +++ @@ -6772,13 +6733,13 @@ char* decode_sockaddr(ErlNifEnv* env, char* res; if (!IS_MAP(env, eSockAddr)) - return str_einval; + return ESOCK_STR_EINVAL; if (!GET_MAP_VAL(env, eSockAddr, esock_atom_family, &efam)) - return str_einval; + return ESOCK_STR_EINVAL; if (!decode_domain(env, efam, &fam)) - return str_einval; + return ESOCK_STR_EINVAL; switch (fam) { case AF_INET: @@ -6798,7 +6759,7 @@ char* decode_sockaddr(ErlNifEnv* env, #endif default: - result = str_eafnosupport; + result = ESOCK_STR_EAFNOSUPPORT; break; } @@ -6841,20 +6802,20 @@ char* decode_sockaddr_in4(ErlNifEnv* env, / * Extract (e) port number from map * / if (!GET_MAP_VAL(env, eSockAddr, atom_port, &eport)) - return str_einval; + return ESOCK_STR_EINVAL; / * Decode port number * / if (!GET_INT(env, eport, &port)) - return str_einval; + return ESOCK_STR_EINVAL; sockAddrP->sin_port = sock_htons(port); / * Extract (e) address from map * / if (!GET_MAP_VAL(env, eSockAddr, atom_addr, &eaddr)) - return str_einval; + return ESOCK_STR_EINVAL; / * Decode address * / if (!decode_ip4_address(env, eaddr, sockAddrP, addrLen)) - return str_einval; + return ESOCK_STR_EINVAL; return NULL; } @@ -6896,41 +6857,41 @@ char* decode_sockaddr_in6(ErlNifEnv* env, / * *** Extract (e) port number from map *** * / if (!GET_MAP_VAL(env, eSockAddr, atom_port, &eport)) - return str_einval; + return ESOCK_STR_EINVAL; / * Decode port number * / if (!GET_INT(env, eport, &port)) - return str_einval; + return ESOCK_STR_EINVAL; sockAddrP->sin6_port = sock_htons(port); / * *** Extract (e) flowinfo from map *** * / if (!GET_MAP_VAL(env, eSockAddr, atom_flowinfo, &eflowInfo)) - return str_einval; + return ESOCK_STR_EINVAL; / * 4: Get the flowinfo * / if (!GET_UINT(env, eflowInfo, &flowInfo)) - return str_einval; + return ESOCK_STR_EINVAL; sockAddrP->sin6_flowinfo = flowInfo; / * *** Extract (e) scope_id from map *** * / if (!GET_MAP_VAL(env, eSockAddr, atom_scope_id, &escopeId)) - return str_einval; + return ESOCK_STR_EINVAL; / * *** Get the scope_id *** * / if (!GET_UINT(env, escopeId, &scopeId)) - return str_einval; + return ESOCK_STR_EINVAL; sockAddrP->sin6_scope_id = scopeId; / * *** Extract (e) address from map *** * / if (!GET_MAP_VAL(env, eSockAddr, atom_addr, &eaddr)) - return str_einval; + return ESOCK_STR_EINVAL; / * Decode address * / if (!decode_ip6_address(env, eaddr, sockAddrP, addrLen)) - return str_einval; + return ESOCK_STR_EINVAL; return NULL; } @@ -6964,11 +6925,11 @@ char* decode_sockaddr_un(ErlNifEnv* env, / * *** Extract (e) path (a binary) from map *** * / if (!GET_MAP_VAL(env, eSockAddr, atom_port, &epath)) - return str_einval; + return ESOCK_STR_EINVAL; / * Get the path * / if (!GET_BIN(env, epath, &bin)) - return str_einval; + return ESOCK_STR_EINVAL; if ((bin.size + #ifdef __linux__ @@ -6984,7 +6945,7 @@ char* decode_sockaddr_un(ErlNifEnv* env, 1 #endif ) > sizeof(sockaAddrP->sun_path)) - return str_einval; + return ESOCK_STR_EINVAL; sys_memzero((char*) sockAddrP, sizeof(struct sockaddr_un)); @@ -7032,7 +6993,7 @@ char* decode_ip4_address(ErlNifEnv* env, } else if (COMPARE(esock_atom_any, eAddr) == 0) { addr.s_addr = sock_htonl(INADDR_ANY); } else { - return str_einval; + return ESOCK_STR_EINVAL; } sockAddrP->sin_addr.s_addr = addr.s_addr; @@ -7047,14 +7008,14 @@ char* decode_ip4_address(ErlNifEnv* env, char addr[4]; if (!GET_TUPLE(env, eAddr, &addrtSz, &addrt)) - return str_einval; + return ESOCK_STR_EINVAL; if (addrtSz != 4) - return str_einval; + return ESOCK_STR_EINVAL; for (a = 0; a < 4; a++) { if (!GET_INT(env, addrt[a], &v)) - return str_einval; + return ESOCK_STR_EINVAL; addr[a] = v; } @@ -7098,7 +7059,7 @@ char* decode_ip6_address(ErlNifEnv* env, } else if (COMPARE(esock_atom_any, eAddr) == 0) { addr = &in6addr_any; } else { - return str_einval; + return ESOCK_STR_EINVAL; } sockAddrP->sin6_addr = *addr; @@ -7113,14 +7074,14 @@ char* decode_ip6_address(ErlNifEnv* env, char addr[16]; if (!GET_TUPLE(env, eAddr, &addrtSz, &addrt)) - return str_einval; + return ESOCK_STR_EINVAL; if (addrtSz != 8) - return str_einval; + return ESOCK_STR_EINVAL; for (a = 0; a < 8; a++) { if (!GET_INT(env, addrt[a], &v)) - return str_einval; + return ESOCK_STR_EINVAL; addr[a*2 ] = ((v >> 8) & 0xFF); addr[a*2+1] = (v & 0xFF); } @@ -7219,20 +7180,6 @@ char* send_msg(ErlNifEnv* env, } -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 @@ -7332,10 +7279,10 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) * writers waiting. */ - SASSERT( (NULL == send_msg_nif_abort(env, - descP->currentWriter.ref, - atom_closed, - &descP->currentWriter.pid)) ); + ESOCK_ASSERT( (NULL == send_msg_nif_abort(env, + descP->currentWriter.ref, + atom_closed, + &descP->currentWriter.pid)) ); /* And also deal with the waiting writers (in the same way) */ inform_waiting_procs(env, descP, &descP->writersQ, TRUE, atom_closed); @@ -7347,10 +7294,10 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) * readers waiting. */ - SASSERT( (NULL == send_msg_nif_abort(env, - descP->currentReader.ref, - atom_closed, - &descP->currentReader.pid)) ); + ESOCK_ASSERT( (NULL == send_msg_nif_abort(env, + descP->currentReader.ref, + atom_closed, + &descP->currentReader.pid)) ); /* And also deal with the waiting readers (in the same way) */ inform_waiting_procs(env, descP, &descP->readersQ, TRUE, atom_closed); @@ -7361,10 +7308,10 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) * acceptors waiting. */ - SASSERT( (NULL == send_msg_nif_abort(env, - descP->currentAcceptor.ref, - atom_closed, - &descP->currentAcceptor.pid)) ); + ESOCK_ASSERT( (NULL == send_msg_nif_abort(env, + descP->currentAcceptor.ref, + atom_closed, + &descP->currentAcceptor.pid)) ); /* And also deal with the waiting acceptors (in the same way) */ inform_waiting_procs(env, descP, &descP->acceptorsQ, TRUE, atom_closed); @@ -7446,10 +7393,10 @@ void inform_waiting_procs(ErlNifEnv* env, * */ - SASSERT( (NULL == send_msg_nif_abort(env, - currentP->data.ref, - reason, - ¤tP->data.pid)) ); + ESOCK_ASSERT( (NULL == send_msg_nif_abort(env, + currentP->data.ref, + reason, + ¤tP->data.pid)) ); DEMONP(env, descP, ¤tP->data.mon); nextP = currentP->nextP; if (free) FREE(currentP); @@ -7656,34 +7603,45 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_timeout = MKA(env, str_timeout); atom_true = MKA(env, str_true); + /* Global atom(s) */ esock_atom_addr = MKA(env, "addr"); esock_atom_any = MKA(env, "any"); esock_atom_dgram = MKA(env, "dgram"); esock_atom_error = MKA(env, "error"); + esock_atom_false = MKA(env, "famlse"); esock_atom_family = MKA(env, "family"); esock_atom_flowinfo = MKA(env, "flowinfo"); esock_atom_inet = MKA(env, "inet"); esock_atom_inet6 = MKA(env, "inet6"); + esock_atom_ip = MKA(env, "ip"); + esock_atom_ipv6 = MKA(env, "ipvp"); esock_atom_local = MKA(env, "local"); esock_atom_loopback = MKA(env, "loopback"); esock_atom_ok = MKA(env, "ok"); esock_atom_path = MKA(env, "path"); esock_atom_port = MKA(env, "port"); esock_atom_raw = MKA(env, "raw"); + esock_atom_rdm = MKA(env, "rdm"); esock_atom_scope_id = MKA(env, "scope_id"); + esock_atom_sctp = MKA(env, "sctp"); esock_atom_seqpacket = MKA(env, "seqpacket"); esock_atom_stream = MKA(env, "stream"); + esock_atom_tcp = MKA(env, "tcp"); + esock_atom_true = MKA(env, "true"); + esock_atom_udp = MKA(env, "udp"); esock_atom_undefined = MKA(env, "undefined"); + /* Global error codes */ + esock_atom_eafnosupport = MKA(env, ESOCK_STR_EAFNOSUPPORT); + esock_atom_eagain = MKA(env, ESOCK_STR_EAGAIN); + esock_atom_einval = MKA(env, ESOCK_STR_EINVAL); + 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_eagain = MKA(env, str_eagain); - atom_eafnosupport = MKA(env, str_eafnosupport); - atom_einval = MKA(env, str_einval); atom_eisconn = MKA(env, str_eisconn); atom_enotclosing = MKA(env, str_enotclosing); atom_enotconn = MKA(env, str_enotconn); diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c index 818e259ae8..37adee682b 100644 --- a/erts/emulator/nifs/common/socket_util.c +++ b/erts/emulator/nifs/common/socket_util.c @@ -29,8 +29,22 @@ #include "sys.h" -/* THIS IS JUST TEMPORARY */ -extern char* erl_errno_id(int error); + +extern char* erl_errno_id(int error); /* THIS IS JUST TEMPORARY??? */ + +static char* make_sockaddr_in4(ErlNifEnv* env, + ERL_NIF_TERM port, + ERL_NIF_TERM addr, + ERL_NIF_TERM* sa); +static char* make_sockaddr_in6(ErlNifEnv* env, + ERL_NIF_TERM port, + ERL_NIF_TERM addr, + ERL_NIF_TERM flowInfo, + ERL_NIF_TERM scopeId, + ERL_NIF_TERM* sa); +static char* make_sockaddr_un(ErlNifEnv* env, + ERL_NIF_TERM path, + ERL_NIF_TERM* sa); /* +++ esock_decode_sockaddr +++ @@ -95,10 +109,59 @@ char* esock_decode_sockaddr(ErlNifEnv* env, +/* +++ esock_encode_sockaddr +++ + * + * Encode a socket address - sockaddr. In erlang its represented as + * a map, which has a specific set of attributes, depending on one + * mandatory attribute; family. So depending on the value of the family + * attribute: + * + * local - sockaddr_un: path + * inet - sockaddr_in4: port, addr + * inet6 - sockaddr_in6: port, addr, flowinfo, scope_id + */ + +extern +char* esock_encode_sockaddr(ErlNifEnv* env, + SocketAddress* sockAddrP, + unsigned int addrLen, + ERL_NIF_TERM* eSockAddr) +{ + char* xres; + + switch (sockAddrP->sa.sa_family) { + case AF_INET: + xres = esock_encode_sockaddr_in4(env, &sockAddrP->in4, addrLen, eSockAddr); + break; + +#if defined(HAVE_IN6) && defined(AF_INET6) + case AF_INET6: + xres = esock_encode_sockaddr_in6(env, &sockAddrP->in6, addrLen, eSockAddr); + break; +#endif + +#ifdef HAVE_SYS_UN_H + case AF_UNIX: + xres = esock_encode_sockaddr_un(env, &sockAddrP->un, addrLen, eSockAddr); + break; +#endif + + default: + xres = ESOCK_STR_EAFNOSUPPORT; + break; + + } + + return xres; +} + + + /* +++ esock_decode_sockaddr_in4 +++ * * Decode a IPv4 socket address - sockaddr_in4. In erlang its represented as - * a map, which has a specific set of attributes: + * a map, which has a specific set of attributes (beside the mandatory family + * attribute, which is "inherited" from the "sockaddr" type): * * port :: port_numbber() * addr :: ip4_address() @@ -147,10 +210,58 @@ char* esock_decode_sockaddr_in4(ErlNifEnv* env, } -/* +++ decode_sockaddr_in6 +++ + +/* +++ esock_encode_sockaddr_in4 +++ + * + * Encode a IPv4 socket address - sockaddr_in4. In erlang its represented as + * a map, which has a specific set of attributes (beside the mandatory family + * attribute, which is "inherited" from the "sockaddr" type): + * + * port :: port_numbber() + * addr :: ip4_address() + * + */ + +extern +char* esock_encode_sockaddr_in4(ErlNifEnv* env, + struct sockaddr_in* sockAddrP, + unsigned int addrLen, + ERL_NIF_TERM* eSockAddr) +{ + ERL_NIF_TERM ePort, eAddr; + int port; + char* xres = NULL; + + if (addrLen >= sizeof(struct sockaddr_in)) { + /* The port */ + port = ntohs(sockAddrP->sin_port); + ePort = MKI(env, port); + + /* The address */ + if ((xres = esock_encode_ip4_address(env, &sockAddrP->sin_addr, + &eAddr)) != NULL) { + /* And finally construct the in4_sockaddr record */ + xres = make_sockaddr_in4(env, ePort, eAddr, eSockAddr); + } else { + *eSockAddr = esock_atom_undefined; + xres = ESOCK_STR_EINVAL; + } + + } else { + *eSockAddr = esock_atom_undefined; + xres = ESOCK_STR_EINVAL; + } + + return xres; +} + + + +/* +++ esock_decode_sockaddr_in6 +++ * * Decode a IPv6 socket address - sockaddr_in6. In erlang its represented as - * a map, which has a specific set of attributes: + * a map, which has a specific set of attributes (beside the mandatory family + * attribute, which is "inherited" from the "sockaddr" type): * * port :: port_numbber() (integer) * addr :: ip6_address() (tuple) @@ -224,10 +335,67 @@ char* esock_decode_sockaddr_in6(ErlNifEnv* env, +/* +++ esock_encode_sockaddr_in6 +++ + * + * Encode a IPv6 socket address - sockaddr_in6. In erlang its represented as + * a map, which has a specific set of attributes (beside the mandatory family + * attribute, which is "inherited" from the "sockaddr" type): + * + * port :: port_numbber() (integer) + * addr :: ip6_address() (tuple) + * flowinfo :: in6_flow_info() (integer) + * scope_id :: in6_scope_id() (integer) + * + */ + +#if defined(HAVE_IN6) && defined(AF_INET6) +extern +char* esock_encode_sockaddr_in6(ErlNifEnv* env, + struct sockaddr_in6* sockAddrP, + unsigned int addrLen, + ERL_NIF_TERM* eSockAddr) +{ + ERL_NIF_TERM ePort, eAddr, eFlowInfo, eScopeId; + char* xres; + + if (addrLen >= sizeof(struct sockaddr_in6)) { + /* The port */ + ePort = MKI(env, ntohs(sockAddrP->sin6_port)); + + /* The flowInfo */ + eFlowInfo = MKI(env, sockAddrP->sin6_flowinfo); + + /* The scopeId */ + eScopeId = MKI(env, sockAddrP->sin6_scope_id); + + /* The address */ + if ((xres = esock_encode_ip6_address(env, &sockAddrP->sin6_addr, + &eAddr)) != NULL) { + /* And finally construct the in6_sockaddr record */ + xres = make_sockaddr_in6(env, + ePort, eAddr, eFlowInfo, eScopeId, eSockAddr); + } else { + *eSockAddr = esock_atom_undefined; + xres = ESOCK_STR_EINVAL; + } + + } else { + *eSockAddr = esock_atom_undefined; + xres = ESOCK_STR_EINVAL; + } + + return xres; +} +#endif + + + /* +++ esock_decode_sockaddr_un +++ * * Decode a Unix Domain socket address - sockaddr_un. In erlang its - * represented as a map, which has a specific set of attributes: + * represented as a map, which has a specific set of attributes + * (beside the mandatory family attribute, which is "inherited" from + * the "sockaddr" type): * * path :: binary() * @@ -256,16 +424,16 @@ char* esock_decode_sockaddr_un(ErlNifEnv* env, if ((bin.size + #ifdef __linux__ - /* Make sure the address gets zero terminated - * except when the first byte is \0 because then it is - * sort of zero terminated although the zero termination - * comes before the address... - * This fix handles Linux's nonportable - * abstract socket address extension. - */ - (bin.data[0] == '\0' ? 0 : 1) + /* Make sure the address gets zero terminated + * except when the first byte is \0 because then it is + * sort of zero terminated although the zero termination + * comes before the address... + * This fix handles Linux's nonportable + * abstract socket address extension. + */ + (bin.data[0] == '\0' ? 0 : 1) #else - 1 + 1 #endif ) > sizeof(sockAddrP->sun_path)) return ESOCK_STR_EINVAL; @@ -288,7 +456,65 @@ char* esock_decode_sockaddr_un(ErlNifEnv* env, -/* +++ decode_ip4_address +++ +/* +++ esock_encode_sockaddr_un +++ + * + * Encode a Unix Domain socket address - sockaddr_un. In erlang its + * represented as a map, which has a specific set of attributes + * (beside the mandatory family attribute, which is "inherited" from + * the "sockaddr" type): + * + * path :: binary() + * + */ + +#ifdef HAVE_SYS_UN_H +extern +char* esock_encode_sockaddr_un(ErlNifEnv* env, + struct sockaddr_un* sockAddrP, + unsigned int addrLen, + ERL_NIF_TERM* eSockAddr) +{ + ERL_NIF_TERM ePath; + size_t n, m; + char* xres; + + if (addrLen >= offsetof(struct sockaddr_un, sun_path)) { + n = addrLen - offsetof(struct sockaddr_un, sun_path); + if (255 < n) { + *eSockAddr = esock_atom_undefined; + xres = ESOCK_STR_EINVAL; + } else { + m = esock_strnlen(sockAddrP->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 + + /* And finally build the 'path' attribute */ + ePath = MKSL(env, sockAddrP->sun_path, m); + + /* And the socket address */ + xres = make_sockaddr_un(env, ePath, eSockAddr); + } + } else { + *eSockAddr = esock_atom_undefined; + xres = ESOCK_STR_EINVAL; + } + + return xres; +} +#endif + + + +/* +++ esock_decode_ip4_address +++ * * Decode a IPv4 address. This can be three things: * @@ -351,7 +577,39 @@ char* esock_decode_ip4_address(ErlNifEnv* env, -/* +++ decode_ip6_address +++ +/* +++ esock_encode_ip4_address +++ + * + * Encode a IPv4 address: + * + * + An ip4_address() (4 tuple) + * + * Note that this *only* decodes the "address" part of a + * (IPv4) socket address. There are several other things (port). + */ + +extern +char* esock_encode_ip4_address(ErlNifEnv* env, + struct in_addr* addrP, + ERL_NIF_TERM* eAddr) +{ + unsigned int i; + ERL_NIF_TERM at[4]; + unsigned int atLen = sizeof(at) / sizeof(ERL_NIF_TERM); + unsigned char* a = (unsigned char*) addrP; + + /* The address */ + for (i = 0; i < atLen; i++) { + at[i] = MKI(env, a[i]); + } + + *eAddr = MKTA(env, at, atLen); + + return NULL; +} + + + +/* +++ esock_decode_ip6_address +++ * * Decode a IPv6 address. This can be three things: * @@ -417,6 +675,42 @@ char* esock_decode_ip6_address(ErlNifEnv* env, #endif + +/* +++ esock_encode_ip6_address +++ + * + * Encode a IPv6 address: + * + * + An ip6_address() (8 tuple) + * + * Note that this *only* encodes the "address" part of a + * (IPv6) socket address. There are several other things + * (port, flowinfo and scope_id) that are handled elsewhere). + */ + +#if defined(HAVE_IN6) && defined(AF_INET6) +extern +char* esock_encode_ip6_address(ErlNifEnv* env, + struct in6_addr* addrP, + ERL_NIF_TERM* eAddr) +{ + unsigned int i; + ERL_NIF_TERM at[8]; + unsigned int atLen = sizeof(at) / sizeof(ERL_NIF_TERM); + unsigned char* a = (unsigned char*) &addrP; + + /* The address */ + for (i = 0; i < atLen; i++) { + at[i] = MKI(env, get_int16(a + i*2)); + } + + *eAddr = MKTA(env, at, atLen); + + return NULL; +} +#endif + + + /* +++ esock_decode_domain +++ * * Decode the Erlang form of the 'domain' type, that is: @@ -584,6 +878,36 @@ char* esock_encode_type(ErlNifEnv* env, +/* *** esock_decode_bool *** + * + * Decode a boolean value. + * + */ +extern +BOOLEAN_T esock_decode_bool(ERL_NIF_TERM val) +{ + if (COMPARE(esock_atom_true, val) == 0) + return TRUE; + else + return FALSE; +} + + +/* *** esock_encode_bool *** + * + * Encode a boolean value. + * + */ +extern +ERL_NIF_TERM esock_encode_bool(BOOLEAN_T val) +{ + if (val) + return esock_atom_true; + else + return esock_atom_false; +} + + /* Create an ok two (2) tuple in the form: * * {ok, Any} @@ -657,3 +981,119 @@ ERL_NIF_TERM esock_make_error_errno(ErlNifEnv* env, int err) } + +/* strnlen doesn't exist everywhere */ +extern +size_t esock_strnlen(const char *s, size_t maxlen) +{ + size_t i = 0; + while (i < maxlen && s[i] != '\0') + i++; + return i; +} + + + +/* *** esock_abort *** + * + * Generate an abort with "extra" info. This should be called + * via the ESOCK_ABORT macro. + * Basically it prints the extra info onto stderr before aborting. + * + */ +extern +void esock_abort(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(); +} + + + + +/* =================================================================== * + * * + * Various utility functions * + * * + * =================================================================== */ + +/* Construct the IPv4 socket address */ +static +char* make_sockaddr_in4(ErlNifEnv* env, + ERL_NIF_TERM port, + ERL_NIF_TERM addr, + ERL_NIF_TERM* sa) +{ + ERL_NIF_TERM keys[] = {esock_atom_family, esock_atom_port, esock_atom_addr}; + ERL_NIF_TERM vals[] = {esock_atom_inet, port, 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, sa)) { + *sa = esock_atom_undefined; + return ESOCK_STR_EINVAL; + } else { + return NULL; + } +} + + +/* Construct the IPv6 socket address */ +static +char* make_sockaddr_in6(ErlNifEnv* env, + ERL_NIF_TERM port, + ERL_NIF_TERM addr, + ERL_NIF_TERM flowInfo, + ERL_NIF_TERM scopeId, + ERL_NIF_TERM* sa) +{ + ERL_NIF_TERM keys[] = {esock_atom_family, + esock_atom_port, + esock_atom_addr, + esock_atom_flowinfo, + esock_atom_scope_id}; + ERL_NIF_TERM vals[] = {esock_atom_inet6, port, addr, flowInfo, scopeId}; + 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, sa)) { + *sa = esock_atom_undefined; + return ESOCK_STR_EINVAL; + } else { + return NULL; + } +} + + +/* Construct the Unix Domain socket address */ +static +char* make_sockaddr_un(ErlNifEnv* env, + ERL_NIF_TERM path, + ERL_NIF_TERM* sa) +{ + ERL_NIF_TERM keys[] = {esock_atom_family, esock_atom_path}; + ERL_NIF_TERM vals[] = {esock_atom_inet, path}; + 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, sa)) { + *sa = esock_atom_undefined; + return ESOCK_STR_EINVAL; + } else { + return NULL; + } +} + + diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h index babfebc17b..f5594c408e 100644 --- a/erts/emulator/nifs/common/socket_util.h +++ b/erts/emulator/nifs/common/socket_util.h @@ -29,17 +29,34 @@ #include #include "socket_int.h" +#define ESOCK_ABORT(E) esock_abort(E, __func__, __FILE__, __LINE__) +#define ESOCK_ASSERT(e) ((void) ((e) ? 1 : (ESOCK_ABORT(#e), 0))) + +/* Two byte integer decoding */ +#define get_int16(s) ((((unsigned char*) (s))[0] << 8) | \ + (((unsigned char*) (s))[1])) + extern char* esock_decode_sockaddr(ErlNifEnv* env, ERL_NIF_TERM eSockAddr, SocketAddress* sockAddrP, unsigned int* addrLen); +extern +char* esock_encode_sockaddr(ErlNifEnv* env, + SocketAddress* sockAddrP, + unsigned int addrLen, + ERL_NIF_TERM* eSockAddr); extern char* esock_decode_sockaddr_in4(ErlNifEnv* env, ERL_NIF_TERM eSockAddr, struct sockaddr_in* sockAddrP, unsigned int* addrLen); +extern +char* esock_encode_sockaddr_in4(ErlNifEnv* env, + struct sockaddr_in* sockAddrP, + unsigned int addrLen, + ERL_NIF_TERM* eSockAddr); #if defined(HAVE_IN6) && defined(AF_INET6) extern @@ -47,6 +64,11 @@ char* esock_decode_sockaddr_in6(ErlNifEnv* env, ERL_NIF_TERM eSockAddr, struct sockaddr_in6* sockAddrP, unsigned int* addrLen); +extern +char* esock_encode_sockaddr_in6(ErlNifEnv* env, + struct sockaddr_in6* sockAddrP, + unsigned int addrLen, + ERL_NIF_TERM* eSockAddr); #endif #ifdef HAVE_SYS_UN_H @@ -55,6 +77,11 @@ char* esock_decode_sockaddr_un(ErlNifEnv* env, ERL_NIF_TERM eSockAddr, struct sockaddr_un* sockAddrP, unsigned int* addrLen); +extern +char* esock_encode_sockaddr_un(ErlNifEnv* env, + struct sockaddr_un* sockAddrP, + unsigned int addrLen, + ERL_NIF_TERM* eSockAddr); #endif extern @@ -62,6 +89,10 @@ char* esock_decode_ip4_address(ErlNifEnv* env, ERL_NIF_TERM eAddr, struct sockaddr_in* sockAddrP, unsigned int* addrLen); +extern +char* esock_encode_ip4_address(ErlNifEnv* env, + struct in_addr* addrP, + ERL_NIF_TERM* eAddr); #if defined(HAVE_IN6) && defined(AF_INET6) extern @@ -69,6 +100,10 @@ char* esock_decode_ip6_address(ErlNifEnv* env, ERL_NIF_TERM eAddr, struct sockaddr_in6* sockAddrP, unsigned int* addrLen); +extern +char* esock_encode_ip6_address(ErlNifEnv* env, + struct in6_addr* addrP, + ERL_NIF_TERM* eAddr); #endif extern @@ -91,6 +126,18 @@ char* esock_encode_type(ErlNifEnv* env, int type, ERL_NIF_TERM* eType); +extern +BOOLEAN_T esock_decode_bool(ERL_NIF_TERM val); +extern +ERL_NIF_TERM esock_encode_bool(BOOLEAN_T val); + +extern +size_t esock_strnlen(const char *s, size_t maxlen); +extern +void esock_abort(const char* expr, + const char* func, + const char* file, + int line); extern ERL_NIF_TERM esock_make_ok2(ErlNifEnv* env, ERL_NIF_TERM any); -- cgit v1.2.3