diff options
Diffstat (limited to 'erts')
50 files changed, 3466 insertions, 897 deletions
diff --git a/erts/configure.in b/erts/configure.in index 506ce0d0fb..3a043c940d 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -676,7 +676,7 @@ elif test "X$PROFILE_INSTR_GENERATE" = "Xtrue" -a "X$PROFILE_INSTR_USE" = "Xtrue PROFILE_COMPILER=clang AC_MSG_RESULT([yes, using -fprofile-instr-generate]) else - if $enable_pgo = yes; then + if test $enable_pgo = yes; then AC_MSG_ERROR(cannot use PGO with this compiler) else AC_MSG_RESULT([no]) @@ -1362,6 +1362,13 @@ else USE_ESOCK=no fi fi + +if test "x$USE_ESOCK" = "xyes"; then + if test "x$USE_ESOCK" = "xyes"; then + AC_CHECK_FUNCS([localtime_r strftime]) + fi +fi + AC_SUBST(USE_ESOCK) diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index f88d255296..d74ae23a93 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -1495,6 +1495,9 @@ enif_free_iovec(iovec);]]></code> <c>term</c>.</p> <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is not a handle to a resource object of type <c>type</c>.</p> + <p><c>enif_get_resource</c> does not add a reference to the resource + object. However, the pointer received in <c>*objp</c> is guaranteed to + be valid at least as long as the resource handle <c>term</c> is valid.</p> </desc> </func> @@ -2947,6 +2950,10 @@ enif_map_iterator_destroy(env, &iter);</code> References made by <seealso marker="#enif_make_resource"> <c>enif_make_resource</c></seealso> can only be removed by the garbage collector.</p> + <p>There are no guarantees exactly when the destructor of an + unreferenced resource is called. It could be called directly by + <c>enif_release_resource</c> but it could also be scheduled to be + called at a later time possibly by another thread.</p> </desc> </func> diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index a879cce840..f41ed87048 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -3105,6 +3105,7 @@ false</code> Map = #{42 => value_two,1337 => "value one","a" => 1}, map_get(Key,Map). "value one"</code> + <p>Allowed in guard tests.</p> </desc> </func> @@ -9412,6 +9413,18 @@ Metadata = #{ pid => pid(), <p>Returns the previous system monitor settings just like <seealso marker="#system_monitor/0"> <c>erlang:system_monitor/0</c></seealso>.</p> + <p>The arguments to <c>system_monitor/2</c> specifies how all + system monitoring on the node should be done, not how it should be + changed. This means only one process at a time + (<c><anno>MonitorPid</anno></c>) can be the receiver of system monitor + messages. Also, the way to clear a specific monitor option + is to not include it in the list <c><anno>Options</anno></c>. All + system monitoring will, however, be cleared if the process identified by + <c><anno>MonitorPid</anno></c> terminates.</p> + <p>There are no special option values (like zero) to clear an option. + Some of the options have a unspecified minimum value. Lower values + will be adjusted to the minimum value. For example, it is currently not + possible to monitor all garbage collections with <c>{long_gc, 0}</c>.</p> <note> <p>If a monitoring process gets so large that it itself starts to cause system monitor messages when garbage diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index ddf17097bd..79cb37a341 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -531,6 +531,58 @@ </section> +<section><title>Erts 10.3.5.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>In nested use of <c>try</c>/<c>catch</c>, rethrowing + an exception using <c>erlang:raise/3</c> with a different + class would not always be able to change the class of the + exception.</p> + <p> + Own Id: OTP-15834 Aux Id: ERIERL-367 </p> + </item> + <item> + <p> + Fixed bug in <c>seq_trace:set_token(label,Term)</c> which + could cause VM crash if <c>Term</c> was heap allocated + (not an atom, small integer, local pid or port). Bug + exists since OTP 21.0 when terms other than small + integers were first allowed as labels.</p> + <p> + Own Id: OTP-15849 Aux Id: ERL-700 </p> + </item> + <item> + <p> + Fix <c>seq_trace:print/2</c> not to raise <c>badarg</c> + exception if label is not a small integer. Bug exists + since OTP 21.0.</p> + <p> + Own Id: OTP-15859 Aux Id: ERL-700 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.3.5.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a buffer overflow when + <c>binary_to_existing_atom/2</c> and + <c>list_to_existing_atom/2</c> was used with the + <c>latin1</c> encoding.</p> + <p> + Own Id: OTP-15819 Aux Id: ERL-944 </p> + </item> + </list> + </section> + +</section> + <section><title>Erts 10.3.5</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index 343b61d4aa..9b34bf1df1 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -373,19 +373,24 @@ <name name="open" arity="4" since="OTP 22.0"/> <fsummary>Create an endpoint for communication.</fsummary> <desc> - <p>Creates an endpoint (socket) for communication.</p> - <p>For some <c>types</c> there is a default protocol, which will - be used if no protocol is specified: </p> + <p>Creates an endpoint (socket) for communication.</p> - <list> - <item><p><c>stream</c>: <c>tcp</c></p></item> - <item><p><c>dgram</c>: <c>udp</c></p></item> - <item><p><c>seqpacket</c>: <c>sctp</c></p></item> - </list> + <p>For some <c>types</c> there is a default protocol, + indicated by <c>default</c>, which it <em>may</em> be + possible to specify. + And for <c>Domain = local</c>, if a protocol <em>is</em> pecified, + it <em>must</em> be <c>default</c>. </p> <p>The <c>Extra</c> argument is intended for "obscure" options. Currently the only supported option is <c>netns</c>, which is only supported on the linux platform.</p> + + <note> + <p>It may not be possible to specify the default protocol (except + when <c>Domain = local</c>). We need to be able to retreive + the resulting protocol, which is <em>not</em> possble on all + platforms. </p> + </note> </desc> </func> diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml index e0f006e618..4b3872d7e3 100644 --- a/erts/doc/src/socket_usage.xml +++ b/erts/doc/src/socket_usage.xml @@ -205,7 +205,7 @@ <cell>protocol()</cell> <cell>no</cell> <cell>yes</cell> - <cell>none</cell> + <cell><em>Not</em> on (some) Darwin (for instance)</cell> </row> <row> <cell>rcvbuf</cell> diff --git a/erts/emulator/beam/atom.c b/erts/emulator/beam/atom.c index 59b51fd15e..5a70509ffd 100644 --- a/erts/emulator/beam/atom.c +++ b/erts/emulator/beam/atom.c @@ -200,11 +200,15 @@ atom_free(Atom* obj) ASSERT(obj->slot.index == atom_val(am_ErtsSecretAtom)); } -static void latin1_to_utf8(byte* conv_buf, const byte** srcp, int* lenp) +static void latin1_to_utf8(byte* conv_buf, Uint buf_sz, + const byte** srcp, Uint* lenp) { byte* dst; const byte* src = *srcp; - int i, len = *lenp; + Uint i, len = *lenp; + + ASSERT(len <= MAX_ATOM_CHARACTERS); + ASSERT(buf_sz >= MAX_ATOM_SZ_FROM_LATIN1); for (i=0 ; i < len; ++i) { if (src[i] & 0x80) { @@ -234,11 +238,11 @@ need_convertion: * erts_atom_put_index() may fail. Returns negative indexes for errors. */ int -erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc) +erts_atom_put_index(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc) { byte utf8_copy[MAX_ATOM_SZ_FROM_LATIN1]; const byte *text = name; - int tlen = len; + Uint tlen; Sint no_latin1_chars; Atom a; int aix; @@ -247,13 +251,16 @@ erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc) erts_atomic_inc_nob(&atom_put_ops); #endif - if (tlen < 0) { - if (trunc) - tlen = 0; - else - return ATOM_MAX_CHARS_ERROR; + if (len < 0) { + if (trunc) { + len = 0; + } else { + return ATOM_MAX_CHARS_ERROR; + } } + tlen = len; + switch (enc) { case ERTS_ATOM_ENC_7BIT_ASCII: if (tlen > MAX_ATOM_CHARACTERS) { @@ -277,7 +284,7 @@ erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc) return ATOM_MAX_CHARS_ERROR; } no_latin1_chars = tlen; - latin1_to_utf8(utf8_copy, &text, &tlen); + latin1_to_utf8(utf8_copy, sizeof(utf8_copy), &text, &tlen); break; case ERTS_ATOM_ENC_UTF8: /* First sanity check; need to verify later */ @@ -338,7 +345,7 @@ erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc) * erts_atom_put() may fail. If it fails THE_NON_VALUE is returned! */ Eterm -erts_atom_put(const byte *name, int len, ErtsAtomEncoding enc, int trunc) +erts_atom_put(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc) { int aix = erts_atom_put_index(name, len, enc, trunc); if (aix >= 0) @@ -348,7 +355,7 @@ erts_atom_put(const byte *name, int len, ErtsAtomEncoding enc, int trunc) } Eterm -am_atom_put(const char* name, int len) +am_atom_put(const char* name, Sint len) { /* Assumes 7-bit ascii; use erts_atom_put() for other encodings... */ return erts_atom_put((byte *) name, len, ERTS_ATOM_ENC_7BIT_ASCII, 1); @@ -379,23 +386,57 @@ int atom_table_sz(void) } int -erts_atom_get(const char *name, int len, Eterm* ap, ErtsAtomEncoding enc) +erts_atom_get(const char *name, Uint len, Eterm* ap, ErtsAtomEncoding enc) { byte utf8_copy[MAX_ATOM_SZ_FROM_LATIN1]; Atom a; int i; int res; - a.len = (Sint16) len; - a.name = (byte *)name; - if (enc == ERTS_ATOM_ENC_LATIN1) { - latin1_to_utf8(utf8_copy, (const byte**)&a.name, &len); - a.len = (Sint16) len; + switch (enc) { + case ERTS_ATOM_ENC_LATIN1: + if (len > MAX_ATOM_CHARACTERS) { + return 0; + } + + latin1_to_utf8(utf8_copy, sizeof(utf8_copy), (const byte**)&name, &len); + + a.name = (byte*)name; + a.len = (Sint16)len; + break; + case ERTS_ATOM_ENC_7BIT_ASCII: + if (len > MAX_ATOM_CHARACTERS) { + return 0; + } + + for (i = 0; i < len; i++) { + if (name[i] & 0x80) { + return 0; + } + } + + a.len = (Sint16)len; + a.name = (byte*)name; + break; + case ERTS_ATOM_ENC_UTF8: + if (len > MAX_ATOM_SZ_LIMIT) { + return 0; + } + + /* We don't need to check whether the encoding is legal as all atom + * names are stored as UTF-8 and we know a lookup with a badly encoded + * name will fail. */ + + a.len = (Sint16)len; + a.name = (byte*)name; + break; } + atom_read_lock(); i = index_get(&erts_atom_table, (void*) &a); res = i < 0 ? 0 : (*ap = make_atom(i), 1); atom_read_unlock(); + return res; } diff --git a/erts/emulator/beam/atom.h b/erts/emulator/beam/atom.h index ca920679c6..f51c5a8c62 100644 --- a/erts/emulator/beam/atom.h +++ b/erts/emulator/beam/atom.h @@ -133,14 +133,14 @@ typedef enum { int atom_table_size(void); /* number of elements */ int atom_table_sz(void); /* table size in bytes, excluding stored objects */ -Eterm am_atom_put(const char*, int); /* ONLY 7-bit ascii! */ -Eterm erts_atom_put(const byte *name, int len, ErtsAtomEncoding enc, int trunc); -int erts_atom_put_index(const byte *name, int len, ErtsAtomEncoding enc, int trunc); +Eterm am_atom_put(const char*, Sint); /* ONLY 7-bit ascii! */ +Eterm erts_atom_put(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc); +int erts_atom_put_index(const byte *name, Sint len, ErtsAtomEncoding enc, int trunc); void init_atom_table(void); void atom_info(fmtfn_t, void *); void dump_atoms(fmtfn_t, void *); Uint erts_get_atom_limit(void); -int erts_atom_get(const char* name, int len, Eterm* ap, ErtsAtomEncoding enc); +int erts_atom_get(const char* name, Uint len, Eterm* ap, ErtsAtomEncoding enc); void erts_atom_get_text_space_sizes(Uint *reserved, Uint *used); #endif diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c index 711e62c795..b31d5b86cb 100644 --- a/erts/emulator/beam/erl_bif_trace.c +++ b/erts/emulator/beam/erl_bif_trace.c @@ -74,7 +74,7 @@ static void smp_bp_finisher(void* arg); static BIF_RETTYPE system_monitor(Process *p, Eterm monitor_pid, Eterm list); -static void new_seq_trace_token(Process* p); /* help func for seq_trace_2*/ +static void new_seq_trace_token(Process* p, int); /* help func for seq_trace_2*/ static Eterm trace_info_pid(Process* p, Eterm pid_spec, Eterm key); static Eterm trace_info_func(Process* p, Eterm pid_spec, Eterm key); static Eterm trace_info_on_load(Process* p, Eterm key); @@ -1874,7 +1874,7 @@ Eterm erts_seq_trace(Process *p, Eterm arg1, Eterm arg2, if (current_flag && ( (arg2 == am_true) || (arg2 == am_false)) ) { /* Flags */ - new_seq_trace_token(p); + new_seq_trace_token(p, 0); flags = unsigned_val(SEQ_TRACE_TOKEN_FLAGS(p)); if (build_result) { old_value = flags & current_flag ? am_true : am_false; @@ -1889,11 +1889,11 @@ Eterm erts_seq_trace(Process *p, Eterm arg1, Eterm arg2, return old_value; } else if (arg1 == am_label) { - new_seq_trace_token(p); + new_seq_trace_token(p, is_not_immed(arg2)); if (build_result) { old_value = SEQ_TRACE_TOKEN_LABEL(p); } - SEQ_TRACE_TOKEN_LABEL(p) = arg2; + SEQ_TRACE_TOKEN_LABEL(p) = arg2; return old_value; } else if (arg1 == am_serial) { @@ -1905,7 +1905,7 @@ Eterm erts_seq_trace(Process *p, Eterm arg1, Eterm arg2, if ((*tp != make_arityval(2)) || is_not_small(*(tp+1)) || is_not_small(*(tp+2))) { return THE_NON_VALUE; } - new_seq_trace_token(p); + new_seq_trace_token(p, 0); if (build_result) { hp = HAlloc(p,3); old_value = TUPLE2(hp, SEQ_TRACE_TOKEN_LASTCNT(p), @@ -1940,8 +1940,8 @@ Eterm erts_seq_trace(Process *p, Eterm arg1, Eterm arg2, } } -void -new_seq_trace_token(Process* p) +static void +new_seq_trace_token(Process* p, int ensure_new_heap) { Eterm* hp; @@ -1953,6 +1953,16 @@ new_seq_trace_token(Process* p) p->common.id, /* Internal pid */ /* From */ make_small(p->seq_trace_lastcnt)); } + else if (ensure_new_heap) { + Eterm* tpl = tuple_val(SEQ_TRACE_TOKEN(p)); + ASSERT(arityval(tpl[0]) == 5); + if (ErtsInArea(tpl, OLD_HEAP(p), + (OLD_HEND(p) - OLD_HEAP(p))*sizeof(Eterm))) { + hp = HAlloc(p, 6); + sys_memcpy(hp, tpl, 6*sizeof(Eterm)); + SEQ_TRACE_TOKEN(p) = make_tuple(hp); + } + } } BIF_RETTYPE erl_seq_trace_info(Process *p, Eterm item) @@ -2050,10 +2060,7 @@ BIF_RETTYPE seq_trace_print_2(BIF_ALIST_2) if (have_no_seqtrace(SEQ_TRACE_TOKEN(BIF_P))) { BIF_RET(am_false); } - if (!(is_atom(BIF_ARG_1) || is_small(BIF_ARG_1))) { - BIF_ERROR(BIF_P, BADARG); - } - if (SEQ_TRACE_TOKEN_LABEL(BIF_P) != BIF_ARG_1) + if (!EQ(BIF_ARG_1, SEQ_TRACE_TOKEN_LABEL(BIF_P))) BIF_RET(am_false); seq_trace_update_send(BIF_P); seq_trace_output(SEQ_TRACE_TOKEN(BIF_P), BIF_ARG_2, diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 6118c671ee..bbf50b4189 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -1230,9 +1230,10 @@ void erts_check_for_holes(Process* p); /* The sequential tracing token is a tuple of size 5: * - * {Flags, Label, Serial, Sender} + * {Flags, Label, Serial, Sender, LastCnt} + * + * WARNING: The top 5-tuple is *MUTABLE* and thus INTERNAL ONLY. */ - #define SEQ_TRACE_TOKEN_ARITY(p) (arityval(*(tuple_val(SEQ_TRACE_TOKEN(p))))) #define SEQ_TRACE_TOKEN_FLAGS(p) (*(tuple_val(SEQ_TRACE_TOKEN(p)) + 1)) #define SEQ_TRACE_TOKEN_LABEL(p) (*(tuple_val(SEQ_TRACE_TOKEN(p)) + 2)) diff --git a/erts/emulator/beam/erl_sched_spec_pre_alloc.h b/erts/emulator/beam/erl_sched_spec_pre_alloc.h index 74cc966cbe..6f715ae80d 100644 --- a/erts/emulator/beam/erl_sched_spec_pre_alloc.h +++ b/erts/emulator/beam/erl_sched_spec_pre_alloc.h @@ -49,7 +49,7 @@ do { \ #endif #ifdef DEBUG -extern Uint erts_no_schedulers; +extern Uint ERTS_WRITE_UNLIKELY(erts_no_schedulers); #endif #define ERTS_SSPA_FORCE_THR_CHECK_PROGRESS 10 diff --git a/erts/emulator/nifs/common/socket_dbg.c b/erts/emulator/nifs/common/socket_dbg.c index 96f75a328f..7dfc4b77bc 100644 --- a/erts/emulator/nifs/common/socket_dbg.c +++ b/erts/emulator/nifs/common/socket_dbg.c @@ -30,6 +30,7 @@ #include <time.h> #include <erl_nif.h> +#include "socket_util.h" #include "socket_dbg.h" #define TSELF() enif_thread_self() @@ -38,12 +39,6 @@ static FILE* dbgout = NULL; -#if defined(CLOCK_REALTIME) -static int realtime(struct timespec* tsP); -static int timespec2str(char *buf, unsigned int len, struct timespec *ts); -#endif - - extern void esock_dbg_init(char* filename) { @@ -73,10 +68,7 @@ void esock_dbg_printf( const char* prefix, const char* format, ... ) { va_list args; char f[512 + sizeof(format)]; // This has to suffice... -#if defined(CLOCK_REALTIME) char stamp[30]; - struct timespec ts; -#endif int res; /* @@ -85,64 +77,21 @@ void esock_dbg_printf( const char* prefix, const char* format, ... ) * But then I must change the API....something for later. */ -#if defined(CLOCK_REALTIME) - if (!realtime(&ts) && - (timespec2str(stamp, sizeof(stamp), &ts) == 0)) { + if (esock_timestamp(stamp, sizeof(stamp))) { res = enif_snprintf(f, sizeof(f), "%s [%s] [%s] %s", prefix, stamp, TSNAME(), format); } else { res = enif_snprintf(f, sizeof(f), "%s [%s] %s", prefix, TSNAME(), format); } -#else - res = enif_snprintf(f, sizeof(f), "%s [%s] %s", - prefix, TSNAME(), format); -#endif if (res > 0) { va_start (args, format); enif_vfprintf (dbgout, f, args); va_end (args); - fflush(stdout); + fflush(dbgout); } return; } - -#if defined(CLOCK_REALTIME) -static -int realtime(struct timespec* tsP) -{ - return clock_gettime(CLOCK_REALTIME, tsP); -} - - - - -/* - * Convert a timespec struct into a readable/printable string - */ -static -int 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; -} -#endif diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h index 38c28a6de5..d6977be5aa 100644 --- a/erts/emulator/nifs/common/socket_int.h +++ b/erts/emulator/nifs/common/socket_int.h @@ -139,6 +139,7 @@ typedef unsigned int BOOLEAN_T; GLOBAL_ATOM_DEF(ctrunc); \ GLOBAL_ATOM_DEF(data); \ GLOBAL_ATOM_DEF(debug); \ + GLOBAL_ATOM_DEF(default); \ GLOBAL_ATOM_DEF(default_send_params); \ GLOBAL_ATOM_DEF(delayed_ack_time); \ GLOBAL_ATOM_DEF(dgram); \ diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index ee3b9f2a98..25bc712949 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -528,6 +528,7 @@ typedef union { #define SOCKET_TYPE_SEQPACKET 5 /* protocol */ +#define SOCKET_PROTOCOL_DEFAULT 0 #define SOCKET_PROTOCOL_IP 1 #define SOCKET_PROTOCOL_TCP 2 #define SOCKET_PROTOCOL_UDP 3 @@ -658,6 +659,10 @@ typedef union { #define SOCKET_SUPPORTS_OPTIONS 0x0001 #define SOCKET_SUPPORTS_SCTP 0x0002 #define SOCKET_SUPPORTS_IPV6 0x0003 +#define SOCKET_SUPPORTS_LOCAL 0x0004 + +#define ESOCK_WHICH_PROTO_ERROR -1 +#define ESOCK_WHICH_PROTO_UNSUP -2 @@ -994,12 +999,15 @@ static ERL_NIF_TERM nsupports_options_udp(ErlNifEnv* env); static ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env); static ERL_NIF_TERM nsupports_sctp(ErlNifEnv* env); static ERL_NIF_TERM nsupports_ipv6(ErlNifEnv* env); +static ERL_NIF_TERM nsupports_local(ErlNifEnv* env); static ERL_NIF_TERM nopen(ErlNifEnv* env, int domain, int type, int protocol, char* netns); +static BOOLEAN_T nopen_which_protocol(SOCKET sock, int* proto); + static ERL_NIF_TERM nbind(ErlNifEnv* env, ESockDescriptor* descP, ESockAddress* sockAddrP, @@ -2644,6 +2652,7 @@ static char str_exsend[] = "exsend"; // failed send GLOBAL_ATOM_DECL(ctrunc); \ GLOBAL_ATOM_DECL(data); \ GLOBAL_ATOM_DECL(debug); \ + GLOBAL_ATOM_DECL(default); \ GLOBAL_ATOM_DECL(default_send_params); \ GLOBAL_ATOM_DECL(delayed_ack_time); \ GLOBAL_ATOM_DECL(dgram); \ @@ -3046,6 +3055,9 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, * {tcp, [{Opt, boolean()}]}, * {udp, [{Opt, boolean()}]}, * {sctp, [{Opt, boolean()}]}] + * sctp boolean() + * ipv6 boolean() + * local boolean() */ static @@ -3073,13 +3085,10 @@ ERL_NIF_TERM nif_supports(ErlNifEnv* env, -/* nopen - create an endpoint for communication +/* nsupports - what features do we support * - * Assumes the input has been validated. - * - * Normally we want debugging on (individual) sockets to be controlled - * by the sockets own debug flag. But since we don't even have a socket - * yet, we must use the global debug flag. + * This is to prove information about what features actually + * work on the current platform. */ #if !defined(__WIN32__) static @@ -3102,6 +3111,10 @@ ERL_NIF_TERM nsupports(ErlNifEnv* env, int key) result = nsupports_ipv6(env); break; + case SOCKET_SUPPORTS_LOCAL: + result = nsupports_local(env); + break; + default: result = esock_atom_false; break; @@ -4004,7 +4017,7 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env) /* *** SOCKET_OPT_TCP_MAXSEG => TCP_MAXSEG *** */ -#if defined(TCP_) +#if defined(TCP_MAXSEG) tmp = MKT2(env, esock_atom_maxseg, esock_atom_true); #else tmp = MKT2(env, esock_atom_maxseg, esock_atom_false); @@ -4018,7 +4031,7 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env) /* *** SOCKET_OPT_TCP_NODELAY => TCP_NODELAY *** */ -#if defined(TCP_) +#if defined(TCP_NODELAY) tmp = MKT2(env, esock_atom_nodelay, esock_atom_true); #else tmp = MKT2(env, esock_atom_nodelay, esock_atom_false); @@ -4324,6 +4337,24 @@ ERL_NIF_TERM nsupports_ipv6(ErlNifEnv* env) +#if !defined(__WIN32__) +static +ERL_NIF_TERM nsupports_local(ErlNifEnv* env) +{ + ERL_NIF_TERM supports; + +#if defined(AF_LOCAL) + supports = esock_atom_true; +#else + supports = esock_atom_false; +#endif + + return supports; +} +#endif + + + /* ---------------------------------------------------------------------- * nif_open * @@ -4421,6 +4452,7 @@ ERL_NIF_TERM nif_open(ErlNifEnv* env, * yet, we must use the global debug flag. */ #if !defined(__WIN32__) + static ERL_NIF_TERM nopen(ErlNifEnv* env, int domain, int type, int protocol, @@ -4428,7 +4460,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, { ESockDescriptor* descP; ERL_NIF_TERM res; - int save_errno = 0; + int proto = protocol, save_errno = 0; SOCKET sock; HANDLE event; #ifdef HAVE_SETNS @@ -4448,11 +4480,35 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, return esock_make_error_errno(env, save_errno); #endif - if ((sock = sock_open(domain, type, protocol)) == INVALID_SOCKET) + if ((sock = sock_open(domain, type, proto)) == INVALID_SOCKET) return esock_make_error_errno(env, sock_errno()); SGDBG( ("SOCKET", "nopen -> open success: %d\r\n", sock) ); + + /* NOTE that if the protocol = 0 (default) and the domain is not + * local (AF_LOCAL) we need to explicitly get the protocol here! + */ + + if ((proto == 0) +#if defined(AF_LOCAL) + && (domain != AF_LOCAL) +#endif + ) + if (!nopen_which_protocol(sock, &proto)) { + if (proto == ESOCK_WHICH_PROTO_ERROR) { + save_errno = sock_errno(); + while ((sock_close(sock) == INVALID_SOCKET) && + (sock_errno() == EINTR)); + return esock_make_error_errno(env, save_errno); + } else { + while ((sock_close(sock) == INVALID_SOCKET) && + (sock_errno() == EINTR)); + return esock_make_error(env, esock_atom_eafnosupport); + } + } + + #ifdef HAVE_SETNS if ((netns != NULL) && !restore_network_namespace(current_ns, sock, &save_errno)) @@ -4484,7 +4540,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, descP->state = SOCKET_STATE_OPEN; descP->domain = domain; descP->type = type; - descP->protocol = protocol; + descP->protocol = proto; /* Does this apply to other types? Such as RAW? * Also, is this really correct? Should we not wait for bind? @@ -4521,6 +4577,32 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, return esock_make_ok2(env, res); } + + +static +BOOLEAN_T nopen_which_protocol(SOCKET sock, int* proto) +{ +#if defined(SO_PROTOCOL) + int val; + SOCKOPTLEN_T valSz = sizeof(val); + int res; + + res = sock_getopt(sock, SOL_SOCKET, SO_PROTOCOL, &val, &valSz); + + if (res != 0) { + *proto = ESOCK_WHICH_PROTO_ERROR; + return FALSE; + } else { + *proto = val; + return TRUE; + } +#else + *proto = ESOCK_WHICH_PROTO_UNSUP; + return FALSE; +#endif +} + + #endif // if !defined(__WIN32__) @@ -5253,6 +5335,7 @@ ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env, enif_set_pid_undefined(&descP->currentAcceptor.pid); res = esock_make_error(env, atom_exmon); } else { + ESOCK_ASSERT(!descP->currentAcceptor.env); descP->currentAcceptor.env = esock_alloc_env("current acceptor"); descP->currentAcceptor.ref = CP_TERM(descP->currentAcceptor.env, accRef); @@ -5411,6 +5494,7 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env, esock_free_env("naccept_accepting_current_accept - " "current-accept-env", descP->currentAcceptor.env); + descP->currentAcceptor.env = NULL; if (!activate_next_acceptor(env, descP, sockRef)) { @@ -5422,6 +5506,7 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env, descP->state = SOCKET_STATE_LISTENING; descP->currentAcceptorP = NULL; + ESOCK_ASSERT(!descP->currentAcceptor.env); descP->currentAcceptor.env = NULL; MON_INIT(&descP->currentAcceptor.mon); } @@ -5448,6 +5533,7 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env, ESockRequestor req; ERL_NIF_TERM res, reason; + req.env = NULL; if (save_errno == ERRNO_BLOCK) { /* @@ -5475,6 +5561,7 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env, req.pid) ); esock_send_abort_msg(env, sockRef, req.ref, req.env, reason, &req.pid); + req.env = NULL; DEMONP("naccept_accepting_current_error -> pop'ed writer", env, descP, &req.mon); } @@ -10890,7 +10977,15 @@ ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env, switch (val) { case IPPROTO_IP: +#if defined(AF_LOCAL) + if (descP->domain == AF_LOCAL) { + result = esock_make_ok2(env, esock_atom_default); + } else { + result = esock_make_ok2(env, esock_atom_ip); + } +#else result = esock_make_ok2(env, esock_atom_ip); +#endif break; case IPPROTO_TCP: @@ -11462,7 +11557,14 @@ ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env, } else { switch (val) { case IPPROTO_IP: +#if defined(AF_LOCAL) + if (descP->domain == AF_LOCAL) + result = esock_make_ok2(env, esock_atom_default); + else + result = esock_make_ok2(env, esock_atom_ip); +#else result = esock_make_ok2(env, esock_atom_ip); +#endif break; case IPPROTO_TCP: @@ -14037,6 +14139,7 @@ ERL_NIF_TERM send_check_ok(ErlNifEnv* env, DEMONP("send_check_ok -> current writer", env, descP, &descP->currentWriter.mon); esock_free_env("send_check_ok", descP->currentWriter.env); + descP->currentWriter.env = NULL; } SSDBG( descP, @@ -14049,6 +14152,7 @@ ERL_NIF_TERM send_check_ok(ErlNifEnv* env, if (!activate_next_writer(env, descP, sockRef)) { descP->currentWriterP = NULL; + ESOCK_ASSERT(!descP->currentWriter.env); descP->currentWriter.env = NULL; descP->currentWriter.ref = esock_atom_undefined; enif_set_pid_undefined(&descP->currentWriter.pid); @@ -14074,6 +14178,7 @@ ERL_NIF_TERM send_check_fail(ErlNifEnv* env, ESockRequestor req; ERL_NIF_TERM reason; + req.env = NULL; cnt_inc(&descP->writeFails, 1); SSDBG( descP, ("SOCKET", "send_check_fail -> error: %d\r\n", saveErrno) ); @@ -14090,6 +14195,7 @@ ERL_NIF_TERM send_check_fail(ErlNifEnv* env, ("SOCKET", "send_check_fail -> abort %T\r\n", req.pid) ); esock_send_abort_msg(env, sockRef, req.ref, req.env, reason, &req.pid); + req.env = NULL; DEMONP("send_check_fail -> pop'ed writer", env, descP, &req.mon); } } @@ -14131,6 +14237,7 @@ ERL_NIF_TERM send_check_retry(ErlNifEnv* env, enif_set_pid_undefined(&descP->currentWriter.pid); return esock_make_error(env, atom_exmon); } else { + ESOCK_ASSERT(!descP->currentWriter.env); descP->currentWriter.env = esock_alloc_env("current-writer"); descP->currentWriter.ref = CP_TERM(descP->currentWriter.env, sendRef); descP->currentWriterP = &descP->currentWriter; @@ -14260,7 +14367,7 @@ char* recv_init_current_reader(ErlNifEnv* env, enif_set_pid_undefined(&descP->currentReader.pid); return str_exmon; } else { - + ESOCK_ASSERT(!descP->currentReader.env); descP->currentReader.env = esock_alloc_env("current-reader"); descP->currentReader.ref = CP_TERM(descP->currentReader.env, recvRef); @@ -14341,6 +14448,7 @@ void recv_error_current_reader(ErlNifEnv* env, { ESockRequestor req; + req.env = NULL; if (descP->currentReaderP != NULL) { DEMONP("recv_error_current_reader -> current reader", @@ -14352,6 +14460,7 @@ void recv_error_current_reader(ErlNifEnv* env, req.pid) ); esock_send_abort_msg(env, sockRef, req.ref, req.env, reason, &req.pid); + req.env = NULL; DEMONP("recv_error_current_reader -> pop'ed reader", env, descP, &req.mon); } @@ -15123,8 +15232,8 @@ char* encode_msghdr(ErlNifEnv* env, "\r\n read: %d" "\r\n", read) ); - /* The address is not used if we are connected, - * so check (length = 0) before we try to encodel + /* The address is not used if we are connected (unless, maybe, + * family is 'local'), so check (length = 0) before we try to encodel */ if (msgHdrP->msg_namelen != 0) { if ((xres = esock_encode_sockaddr(env, @@ -16246,8 +16355,6 @@ char* encode_cmsghdr_data_ipv6(ErlNifEnv* env, size_t dataLen, ERL_NIF_TERM* eCMsgHdrData) { - char* xres; - switch (type) { #if defined(IPV6_PKTINFO) case IPV6_PKTINFO: @@ -16255,6 +16362,7 @@ char* encode_cmsghdr_data_ipv6(ErlNifEnv* env, struct in6_pktinfo* pktInfoP = (struct in6_pktinfo*) dataP; ERL_NIF_TERM ifIndex = MKI(env, pktInfoP->ipi6_ifindex); ERL_NIF_TERM addr; + char* xres; if ((xres = esock_encode_ip6_address(env, &pktInfoP->ipi6_addr, @@ -17027,6 +17135,10 @@ BOOLEAN_T eproto2proto(ErlNifEnv* env, } switch (ep) { + case SOCKET_PROTOCOL_DEFAULT: + *proto = 0; // default - note that _IP also has the value 0... + break; + case SOCKET_PROTOCOL_IP: *proto = IPPROTO_IP; break; @@ -17647,6 +17759,7 @@ int esock_select_cancel(ErlNifEnv* env, esock_send_abort_msg(env, sockRef, \ reqP->ref, reqP->env, \ reason, &reqP->pid); \ + reqP->env = NULL; \ \ } else { \ \ @@ -17745,7 +17858,7 @@ REQ_SEARCH4PID_FUNCS reqP->pid = pid; \ if (MONP("reader_push -> " #F " request", \ env, descP, &pid, &reqP->mon) != 0) { \ - FREE(reqP); \ + FREE(e); \ return esock_make_error(env, atom_exmon); \ } \ reqP->env = esock_alloc_env(#F "_push"); \ @@ -17822,6 +17935,9 @@ BOOLEAN_T requestor_pop(ESockRequestQueue* q, { ESockRequestQueueElement* e = qpop(q); + if (reqP->env) + esock_free_env("requestor_pop", reqP->env); + if (e != NULL) { reqP->pid = e->data.pid; reqP->mon = e->data.mon; @@ -17933,6 +18049,8 @@ BOOLEAN_T qunqueue(ErlNifEnv* env, } } + if (e->data.env) + esock_free_env("qunqueue", e->data.env); FREE(e); return TRUE; @@ -18074,6 +18192,18 @@ ERL_NIF_TERM esock_make_monitor_term(ErlNifEnv* env, const ESockMonitor* monP) * ---------------------------------------------------------------------- */ + +static void free_request_queue(ESockRequestQueue* q) +{ + while (q->first) { + ESockRequestQueueElement* free_me = q->first; + q->first = free_me->nextP; + if (free_me->data.env) + esock_free_env("dtor", free_me->data.env); + FREE(free_me); + } +} + /* ========================================================================= * socket_dtor - Callback function for resource destructor * @@ -18089,6 +18219,16 @@ void socket_dtor(ErlNifEnv* env, void* obj) MDESTROY(descP->accMtx); MDESTROY(descP->closeMtx); MDESTROY(descP->cfgMtx); + + if (descP->currentReader.env) + esock_free_env("dtor reader", descP->currentReader.env); + if (descP->currentWriter.env) + esock_free_env("dtor writer", descP->currentWriter.env); + if (descP->currentAcceptor.env) + esock_free_env("dtor acceptor", descP->currentAcceptor.env); + free_request_queue(&descP->readersQ); + free_request_queue(&descP->writersQ); + free_request_queue(&descP->acceptorsQ); #endif } @@ -18321,6 +18461,7 @@ void socket_stop_handle_current(ErlNifEnv* env, "current %s %T\r\n", reqP->ref, role, reqP->pid); } + reqP->env = NULL; } } @@ -18376,6 +18517,7 @@ void inform_waiting_procs(ErlNifEnv* env, currentP->data.pid); } + currentP->data.env = NULL, DEMONP("inform_waiting_procs -> current 'request'", env, descP, ¤tP->data.mon); diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c index 8ad95cb6b7..2740cb51ef 100644 --- a/erts/emulator/nifs/common/socket_util.c +++ b/erts/emulator/nifs/common/socket_util.c @@ -35,6 +35,10 @@ #include "socket_util.h" #include "socket_dbg.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* We don't have a "debug flag" to check here, so we * should use the compile debug flag, whatever that is... */ @@ -51,12 +55,10 @@ extern char* erl_errno_id(int error); /* THIS IS JUST TEMPORARY??? */ -#if defined(CLOCK_REALTIME) -static int realtime(struct timespec* tsP); -static int timespec2str(char *buf, - unsigned int len, - struct timespec *ts); +#if (defined(HAVE_LOCALTIME_R) && defined(HAVE_STRFTIME)) +#define ESOCK_USE_PRETTY_TIMESTAMP 1 #endif + static char* make_sockaddr_in4(ErlNifEnv* env, ERL_NIF_TERM port, @@ -984,9 +986,27 @@ char* esock_decode_timeval(ErlNifEnv* env, if (!GET_LONG(env, eSec, &timeP->tv_sec)) return ESOCK_STR_EINVAL; +#if (SIZEOF_INT == 4) + { + int usec; + if (!GET_INT(env, eUSec, &usec)) + return ESOCK_STR_EINVAL; + timeP->tv_usec = (typeof(timeP->tv_usec)) usec; + } +#elif (SIZEOF_LONG == 4) + { + long usec; + if (!GET_LONG(env, eUSec, &usec)) + return ESOCK_STR_EINVAL; + timeP->tv_usec = (typeof(timeP->tv_usec)) usec; + } +#else + /* Ok, we give up... */ if (!GET_LONG(env, eUSec, &timeP->tv_usec)) return ESOCK_STR_EINVAL; +#endif + return NULL; } @@ -1510,10 +1530,7 @@ void esock_warning_msg( const char* format, ... ) { va_list args; char f[512 + sizeof(format)]; // This has to suffice... -#if defined(CLOCK_REALTIME) char stamp[64]; // Just in case... - struct timespec ts; -#endif int res; /* @@ -1525,18 +1542,13 @@ void esock_warning_msg( const char* format, ... ) // 2018-06-29 12:13:21.232089 // 29-Jun-2018::13:47:25.097097 -#if defined(CLOCK_REALTIME) - if (!realtime(&ts) && - (timespec2str(stamp, sizeof(stamp), &ts) == 0)) { + if (esock_timestamp(stamp, sizeof(stamp))) { res = enif_snprintf(f, sizeof(f), "=WARNING MSG==== %s ===\r\n%s", stamp, format); } else { res = enif_snprintf(f, sizeof(f), "=WARNING MSG==== %s", format); } -#else - res = enif_snprintf(f, sizeof(f), "=WARNING MSG==== %s", format); -#endif if (res > 0) { va_start (args, format); @@ -1549,43 +1561,52 @@ void esock_warning_msg( const char* format, ... ) } -#if defined(CLOCK_REALTIME) -static -int realtime(struct timespec* tsP) -{ - return clock_gettime(CLOCK_REALTIME, tsP); -} - - -/* - * Convert a timespec struct into a readable/printable string. +/* *** esock_timestamp *** * - * "%F::%T" => 2018-06-29 12:13:21[.232089] - * "%d-%b-%Y::%T" => 29-Jun-2018::13:47:25.097097 + * Create a timestamp string. + * If awailable, we use the localtime_r and strftime function(s) + * to produces a nice readable timestamp. But if not (awailable), + * it produces a timestamp in the form of an "Epoch" (A real epoch + * is the number of seconds since 1/1 1970, but our timestamp is + * the number micro seconds since 1/1 1970). */ -static -int 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; +extern +BOOLEAN_T esock_timestamp(char *buf, unsigned int len) +{ + int ret; + ErlNifTime monTime = enif_monotonic_time(ERL_NIF_USEC); + ErlNifTime offTime = enif_time_offset(ERL_NIF_USEC); + ErlNifTime time = monTime + offTime; +#if defined(ESOCK_USE_PRETTY_TIMESTAMP) + time_t sec = time / 1000000; // (if _MSEC) sec = time / 1000; + time_t usec = time % 1000000; // (if _MSEC) msec = time % 1000; + int buflen; + struct tm t; + + if (localtime_r(&sec, &t) == NULL) + return FALSE; - ret = strftime(buf, len, "%d-%B-%Y::%T", &t); - if (ret == 0) - return 2; - len -= ret - 1; - buflen = strlen(buf); + ret = strftime(buf, len, "%d-%B-%Y::%T", &t); + if (ret == 0) + return FALSE; + len -= ret - 1; + buflen = strlen(buf); - ret = snprintf(&buf[buflen], len, ".%06ld", ts->tv_nsec/1000); - if (ret >= len) - return 3; + ret = enif_snprintf(&buf[buflen], len, ".%06b64d", usec); + if (ret >= len) + return FALSE; - return 0; -} + return TRUE; +#else + ret = enif_snprintf(buf, len, "%b64d", time); + if (ret == 0) + return FALSE; + else + return TRUE; #endif +} + /* =================================================================== * @@ -1653,7 +1674,7 @@ char* make_sockaddr_un(ErlNifEnv* env, ERL_NIF_TERM* sa) { ERL_NIF_TERM keys[] = {esock_atom_family, esock_atom_path}; - ERL_NIF_TERM vals[] = {esock_atom_inet, path}; + ERL_NIF_TERM vals[] = {esock_atom_local, path}; unsigned int numKeys = sizeof(keys) / sizeof(ERL_NIF_TERM); unsigned int numVals = sizeof(vals) / sizeof(ERL_NIF_TERM); diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h index 84b1c8085f..2688a920c4 100644 --- a/erts/emulator/nifs/common/socket_util.h +++ b/erts/emulator/nifs/common/socket_util.h @@ -199,6 +199,9 @@ extern ERL_NIF_TERM esock_make_error_errno(ErlNifEnv* env, int err); extern +BOOLEAN_T esock_timestamp(char *buf, unsigned int len); + +extern void esock_warning_msg(const char* format, ... ); diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl index 43975d1800..c5abd04e07 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -612,6 +612,16 @@ binary_to_existing_atom(Config) when is_list(Config) -> UnlikelyAtom = binary_to_atom(id(UnlikelyBin), latin1), UnlikelyAtom = binary_to_existing_atom(UnlikelyBin, latin1), + + %% ERL-944; a binary that was too large would overflow the latin1-to-utf8 + %% conversion buffer. + OverflowAtom = <<0:511/unit:8, + 196, 133, 196, 133, 196, 133, 196, 133, 196, 133, + 196, 133, 196, 133, 196, 133, 196, 133, 196, 133, + 196, 133, 196, 133, 196, 133, 196, 133, 196, 133, + 196, 133, 196, 133, 196, 133, 196, 133, 196, 133>>, + {'EXIT', _} = (catch binary_to_existing_atom(OverflowAtom, latin1)), + ok. diff --git a/erts/emulator/test/esock_ttest/esock-ttest b/erts/emulator/test/esock_ttest/esock-ttest index f0d363ab30..cf1d9cd9ab 100755 --- a/erts/emulator/test/esock_ttest/esock-ttest +++ b/erts/emulator/test/esock_ttest/esock-ttest @@ -50,43 +50,47 @@ usage() -> "~n units (server or client)." "~n" "~n options: " - "~n --help Display this info and exit. " - "~n --server [server-options] Start a server. " - "~n There are no mandatory server options." - "~n --client client-options Start a client" - "~n Some client options are mandatory and" - "~n others optional." - "~n --active <active> boolean() | once." - "~n Valid for both client and server." - "~n Defaults to: false" - "~n --transport <transport> Which transport to use: gen|sock[:plain|msg]" - "~n gen: gen_tcp" - "~n sock: socket" - "~n plain: recv/send (default)" - "~n msg: recvmsg/sendmsg" - "~n Defaults to: sock:plain" - "~n --scon <addr>:<port> Address and port of the server." - "~n The address part is in the standard form:" - "~n \"a.b.c.d\"." - "~n Only valid for client." - "~n Mandatory." - "~n --msg-id <1|2|3> Choose which message to use during the test." - "~n Basically: " - "~n 1: small" - "~n 2: medium" - "~n 3: large" - "~n Defaults to: 1" - "~n --max-outstanding <Num> How many messages to send before waiting for" - "~n a reply." - "~n Valid only for client." - "~n Defaults to: " - "~n MsgID 1: 100" - "~n MsgID 2: 10" - "~n MsgID 3: 1" - "~n --runtime <Time> Time of the test in seconds." - "~n Only valid for client." - "~n Mandatory." - "~n Defaults to: 60 (seconds)" + "~n --help Display this info and exit. " + "~n --server [server-options] Start a server. " + "~n There are no mandatory server options." + "~n --client client-options Start a client" + "~n Some client options are mandatory and" + "~n others optional." + "~n --domain <domain> local | inet | inet6" + "~n Which domain to use." + "~n Only valid for server." + "~n Defaults to: inet" + "~n --active <active> boolean() | once." + "~n Valid for both client and server." + "~n Defaults to: false" + "~n --transport <transport> Which transport to use: gen|sock[:plain|msg]" + "~n gen: gen_tcp" + "~n sock: socket" + "~n plain: recv/send (default)" + "~n msg: recvmsg/sendmsg" + "~n Defaults to: sock:plain" + "~n --scon <addr>:<port>|<path> Server info." + "~n The address part is in the standard form:" + "~n \"a.b.c.d\"." + "~n <path> is used for Unix Domain sockets (local)." + "~n Only valid, and mandatory, for client." + "~n --msg-id <1|2|3> Choose which message to use during the test." + "~n Basically: " + "~n 1: small" + "~n 2: medium" + "~n 3: large" + "~n Defaults to: 1" + "~n --max-outstanding <Num> How many messages to send before waiting for" + "~n a reply." + "~n Valid only for client." + "~n Defaults to: " + "~n MsgID 1: 100" + "~n MsgID 2: 10" + "~n MsgID 3: 1" + "~n --runtime <Time> Time of the test in seconds." + "~n Only valid for client." + "~n Mandatory." + "~n Defaults to: 60 (seconds)" "~n" "~n" "~n", @@ -106,6 +110,7 @@ process_args(Args) -> process_server_args(Args) -> Defaults = #{role => server, + domain => inet, active => false, transport => {sock, plain}}, process_server_args(Args, Defaults). @@ -113,6 +118,12 @@ process_server_args(Args) -> process_server_args([], State) -> State; +process_server_args(["--domain", Domain|Args], State) + when ((Domain =:= "local") orelse + (Domain =:= "inet") orelse + (Domain =:= "inet6")) -> + process_server_args(Args, State#{domain => list_to_atom(Domain)}); + process_server_args(["--active", Active|Args], State) when ((Active =:= "false") orelse (Active =:= "once") orelse @@ -137,7 +148,7 @@ process_client_args(Args) -> active => false, transport => {sock, plain}, %% Will cause error if not provided - %% Should be "addr:port" + %% Should be "addr:port or string() server => undefined, msg_id => 1, %% Will be filled in based on msg_id if not provided @@ -199,6 +210,8 @@ process_client_args(["--scon", Server|Args], State) -> usage(f("Invalid Server Port: ~s", [PortStr])) end, process_client_args(Args, State#{server => {Addr, Port}}); + [Path] -> + process_client_args(Args, State#{server => Path}); _ -> usage(f("Invalid Server: ~s", [Server])) end; @@ -249,9 +262,11 @@ process_client_args_ensure_max_outstanding( %% ========================================================================== exec(#{role := server, + domain := Domain, active := Active, - transport := gen}) -> - case socket_test_ttest_tcp_server_gen:start(Active) of + transport := gen}) + when (Domain =:= inet) orelse (Domain =:= inet6) -> + case socket_test_ttest_tcp_server_gen:start(Domain, Active) of {ok, {Pid, _}} -> MRef = erlang:monitor(process, Pid), receive @@ -264,9 +279,10 @@ exec(#{role := server, error end; exec(#{role := server, + domain := Domain, active := Active, transport := {sock, Method}}) -> - case socket_test_ttest_tcp_server_socket:start(Method, Active) of + case socket_test_ttest_tcp_server_socket:start(Method, Domain, Active) of {ok, {Pid, _}} -> MRef = erlang:monitor(process, Pid), receive @@ -283,15 +299,15 @@ exec(#{role := client, server := undefined}) -> usage("Mandatory option 'server' not provided"); exec(#{role := client, - server := {Addr, Port}, + server := {_Addr, _Port} = ServerInfo, active := Active, transport := gen, msg_id := MsgID, max_outstanding := MaxOutstanding, runtime := RunTime}) -> case socket_test_ttest_tcp_client_gen:start(true, + ServerInfo, Active, - Addr, Port, MsgID, MaxOutstanding, RunTime) of {ok, Pid} -> @@ -306,7 +322,7 @@ exec(#{role := client, error end; exec(#{role := client, - server := {Addr, Port}, + server := ServerInfo, active := Active, transport := {sock, Method}, msg_id := MsgID, @@ -314,8 +330,8 @@ exec(#{role := client, runtime := RunTime}) -> case socket_test_ttest_tcp_client_socket:start(true, Method, + ServerInfo, Active, - Addr, Port, MsgID, MaxOutstanding, RunTime) of {ok, Pid} -> diff --git a/erts/emulator/test/esock_ttest/esock-ttest-client b/erts/emulator/test/esock_ttest/esock-ttest-client index 1ab56f2d44..7c90ae6391 100755 --- a/erts/emulator/test/esock_ttest/esock-ttest-client +++ b/erts/emulator/test/esock_ttest/esock-ttest-client @@ -26,33 +26,46 @@ ESOCK_TTEST=$EMU_TEST/esock_ttest RUNTIME=30 -MSGID=$1 -SERVER_ADDR=$2 -SERVER_PORT=$3 +if [ $# = 3 ]; then + MSGID=$1 + SERVER_INFO=$2:$3 + + ITERATIONS="\ + gen false $MSGID + gen true $MSGID + gen once $MSGID + sock false $MSGID + sock true $MSGID + sock once $MSGID" + +else + if [ $# = 2 ]; then + MSGID=$1 + SERVER_INFO=$2 + + ITERATIONS="\ + sock false $MSGID + sock true $MSGID + sock once $MSGID" + + else + echo "Invalid number of args" + exit 1; + fi +fi + # --------------------------------------------------------------------------- -ITERATIONS="\ - gen false $MSGID - gen true $MSGID - gen once $MSGID - sock false $MSGID - sock true $MSGID - sock once $MSGID" - -# gen false 2 -# gen true 2 -# gen once 2 -# sock false 2 -# sock true 2 -# sock once 2 -# gen false 3 -# gen true 3 -# gen once 3 -# sock false 3 -# sock true 3 -# sock once 3 -# +# For when we have figured out how to configure local for gen_tcp... + +#ITERATIONS="\ +# gen false $MSGID +# gen true $MSGID +# gen once $MSGID +# sock false $MSGID +# sock true $MSGID +# sock once $MSGID" # --------------------------------------------------------------------------- @@ -64,7 +77,7 @@ echo "$ITERATIONS" | # The /dev/null at the end is necessary because erlang "does things" with stdin # and this case would cause the 'while read' to "fail" so that we only would # loop one time - $ESOCK_TTEST/esock-ttest --client --transport $TRANSPORT --active $ACTIVE --msg-id $MSG_ID --scon $SERVER_ADDR:$SERVER_PORT --runtime $RUNTIME </dev/null + $ESOCK_TTEST/esock-ttest --client --transport $TRANSPORT --active $ACTIVE --msg-id $MSG_ID --scon $SERVER_INFO --runtime $RUNTIME </dev/null echo "" done diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index e3545ccbf9..49b0fcccc2 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -70,10 +70,16 @@ %% *** API Basic *** api_b_open_and_close_udp4/1, api_b_open_and_close_tcp4/1, + api_b_open_and_close_udpL/1, + api_b_open_and_close_tcpL/1, api_b_sendto_and_recvfrom_udp4/1, + api_b_sendto_and_recvfrom_udpL/1, api_b_sendmsg_and_recvmsg_udp4/1, + api_b_sendmsg_and_recvmsg_udpL/1, api_b_send_and_recv_tcp4/1, + api_b_send_and_recv_tcpL/1, api_b_sendmsg_and_recvmsg_tcp4/1, + api_b_sendmsg_and_recvmsg_tcpL/1, %% *** API Options *** api_opt_simple_otp_options/1, @@ -107,57 +113,79 @@ %% *** Socket Closure *** sc_cpe_socket_cleanup_tcp4/1, sc_cpe_socket_cleanup_tcp6/1, + sc_cpe_socket_cleanup_tcpL/1, sc_cpe_socket_cleanup_udp4/1, sc_cpe_socket_cleanup_udp6/1, + sc_cpe_socket_cleanup_udpL/1, sc_lc_recv_response_tcp4/1, sc_lc_recv_response_tcp6/1, + sc_lc_recv_response_tcpL/1, sc_lc_recvfrom_response_udp4/1, sc_lc_recvfrom_response_udp6/1, + sc_lc_recvfrom_response_udpL/1, sc_lc_recvmsg_response_tcp4/1, sc_lc_recvmsg_response_tcp6/1, + sc_lc_recvmsg_response_tcpL/1, sc_lc_recvmsg_response_udp4/1, sc_lc_recvmsg_response_udp6/1, + sc_lc_recvmsg_response_udpL/1, sc_lc_acceptor_response_tcp4/1, sc_lc_acceptor_response_tcp6/1, + sc_lc_acceptor_response_tcpL/1, sc_rc_recv_response_tcp4/1, sc_rc_recv_response_tcp6/1, + sc_rc_recv_response_tcpL/1, sc_rc_recvmsg_response_tcp4/1, sc_rc_recvmsg_response_tcp6/1, + sc_rc_recvmsg_response_tcpL/1, sc_rs_recv_send_shutdown_receive_tcp4/1, sc_rs_recv_send_shutdown_receive_tcp6/1, + sc_rs_recv_send_shutdown_receive_tcpL/1, sc_rs_recvmsg_send_shutdown_receive_tcp4/1, sc_rs_recvmsg_send_shutdown_receive_tcp6/1, + sc_rs_recvmsg_send_shutdown_receive_tcpL/1, %% *** Traffic *** traffic_send_and_recv_chunks_tcp4/1, traffic_send_and_recv_chunks_tcp6/1, + traffic_send_and_recv_chunks_tcpL/1, traffic_ping_pong_small_send_and_recv_tcp4/1, traffic_ping_pong_small_send_and_recv_tcp6/1, + traffic_ping_pong_small_send_and_recv_tcpL/1, traffic_ping_pong_medium_send_and_recv_tcp4/1, traffic_ping_pong_medium_send_and_recv_tcp6/1, + traffic_ping_pong_medium_send_and_recv_tcpL/1, traffic_ping_pong_large_send_and_recv_tcp4/1, traffic_ping_pong_large_send_and_recv_tcp6/1, + traffic_ping_pong_large_send_and_recv_tcpL/1, traffic_ping_pong_small_sendto_and_recvfrom_udp4/1, traffic_ping_pong_small_sendto_and_recvfrom_udp6/1, + traffic_ping_pong_small_sendto_and_recvfrom_udpL/1, traffic_ping_pong_medium_sendto_and_recvfrom_udp4/1, traffic_ping_pong_medium_sendto_and_recvfrom_udp6/1, + traffic_ping_pong_medium_sendto_and_recvfrom_udpL/1, traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4/1, traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6/1, + traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6/1, + traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL/1, traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4/1, traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6/1, + traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL/1, traffic_ping_pong_small_sendmsg_and_recvmsg_udp4/1, traffic_ping_pong_small_sendmsg_and_recvmsg_udp6/1, + traffic_ping_pong_small_sendmsg_and_recvmsg_udpL/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4/1, traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6/1, + traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL/1, %% *** Time Test *** %% Server: transport = gen_tcp, active = false @@ -325,24 +353,33 @@ %% Client: transport = socket(tcp) ttest_ssockf_csockf_small_tcp4/1, ttest_ssockf_csockf_small_tcp6/1, + ttest_ssockf_csockf_small_tcpL/1, ttest_ssockf_csockf_medium_tcp4/1, ttest_ssockf_csockf_medium_tcp6/1, + ttest_ssockf_csockf_medium_tcpL/1, ttest_ssockf_csockf_large_tcp4/1, ttest_ssockf_csockf_large_tcp6/1, + ttest_ssockf_csockf_large_tcpL/1, ttest_ssockf_csocko_small_tcp4/1, ttest_ssockf_csocko_small_tcp6/1, + ttest_ssockf_csocko_small_tcpL/1, ttest_ssockf_csocko_medium_tcp4/1, ttest_ssockf_csocko_medium_tcp6/1, + ttest_ssockf_csocko_medium_tcpL/1, ttest_ssockf_csocko_large_tcp4/1, ttest_ssockf_csocko_large_tcp6/1, + ttest_ssockf_csocko_large_tcpL/1, ttest_ssockf_csockt_small_tcp4/1, ttest_ssockf_csockt_small_tcp6/1, + ttest_ssockf_csockt_small_tcpL/1, ttest_ssockf_csockt_medium_tcp4/1, ttest_ssockf_csockt_medium_tcp6/1, + ttest_ssockf_csockt_medium_tcpL/1, ttest_ssockf_csockt_large_tcp4/1, ttest_ssockf_csockt_large_tcp6/1, + ttest_ssockf_csockt_large_tcpL/1, %% Server: transport = socket(tcp), active = once %% Client: transport = gen_tcp @@ -371,24 +408,33 @@ %% Client: transport = socket(tcp) ttest_ssocko_csockf_small_tcp4/1, ttest_ssocko_csockf_small_tcp6/1, + ttest_ssocko_csockf_small_tcpL/1, ttest_ssocko_csockf_medium_tcp4/1, + ttest_ssocko_csockf_medium_tcpL/1, ttest_ssocko_csockf_medium_tcp6/1, ttest_ssocko_csockf_large_tcp4/1, ttest_ssocko_csockf_large_tcp6/1, + ttest_ssocko_csockf_large_tcpL/1, ttest_ssocko_csocko_small_tcp4/1, ttest_ssocko_csocko_small_tcp6/1, + ttest_ssocko_csocko_small_tcpL/1, ttest_ssocko_csocko_medium_tcp4/1, ttest_ssocko_csocko_medium_tcp6/1, + ttest_ssocko_csocko_medium_tcpL/1, ttest_ssocko_csocko_large_tcp4/1, ttest_ssocko_csocko_large_tcp6/1, + ttest_ssocko_csocko_large_tcpL/1, ttest_ssocko_csockt_small_tcp4/1, ttest_ssocko_csockt_small_tcp6/1, + ttest_ssocko_csockt_small_tcpL/1, ttest_ssocko_csockt_medium_tcp4/1, ttest_ssocko_csockt_medium_tcp6/1, + ttest_ssocko_csockt_medium_tcpL/1, ttest_ssocko_csockt_large_tcp4/1, ttest_ssocko_csockt_large_tcp6/1, + ttest_ssocko_csockt_large_tcpL/1, %% Server: transport = socket(tcp), active = true %% Client: transport = gen_tcp @@ -417,24 +463,33 @@ %% Client: transport = socket(tcp) ttest_ssockt_csockf_small_tcp4/1, ttest_ssockt_csockf_small_tcp6/1, + ttest_ssockt_csockf_small_tcpL/1, ttest_ssockt_csockf_medium_tcp4/1, ttest_ssockt_csockf_medium_tcp6/1, + ttest_ssockt_csockf_medium_tcpL/1, ttest_ssockt_csockf_large_tcp4/1, ttest_ssockt_csockf_large_tcp6/1, + ttest_ssockt_csockf_large_tcpL/1, ttest_ssockt_csocko_small_tcp4/1, ttest_ssockt_csocko_small_tcp6/1, + ttest_ssockt_csocko_small_tcpL/1, ttest_ssockt_csocko_medium_tcp4/1, ttest_ssockt_csocko_medium_tcp6/1, + ttest_ssockt_csocko_medium_tcpL/1, ttest_ssockt_csocko_large_tcp4/1, ttest_ssockt_csocko_large_tcp6/1, + ttest_ssockt_csocko_large_tcpL/1, ttest_ssockt_csockt_small_tcp4/1, ttest_ssockt_csockt_small_tcp6/1, + ttest_ssockt_csockt_small_tcpL/1, ttest_ssockt_csockt_medium_tcp4/1, ttest_ssockt_csockt_medium_tcp6/1, + ttest_ssockt_csockt_medium_tcpL/1, ttest_ssockt_csockt_large_tcp4/1, - ttest_ssockt_csockt_large_tcp6/1 + ttest_ssockt_csockt_large_tcp6/1, + ttest_ssockt_csockt_large_tcpL/1 %% Tickets ]). @@ -508,71 +563,75 @@ use_group(Group, Env, Default) -> groups() -> - [{api, [], api_cases()}, - {api_basic, [], api_basic_cases()}, - {api_options, [], api_options_cases()}, - {api_op_with_timeout, [], api_op_with_timeout_cases()}, - {socket_closure, [], socket_closure_cases()}, - {sc_ctrl_proc_exit, [], sc_cp_exit_cases()}, - {sc_local_close, [], sc_lc_cases()}, - {sc_remote_close, [], sc_rc_cases()}, - {sc_remote_shutdown, [], sc_rs_cases()}, - {traffic, [], traffic_cases()}, - {ttest, [], ttest_cases()}, - {ttest_sgenf, [], ttest_sgenf_cases()}, - {ttest_sgenf_cgen, [], ttest_sgenf_cgen_cases()}, - {ttest_sgenf_cgenf, [], ttest_sgenf_cgenf_cases()}, - {ttest_sgenf_cgeno, [], ttest_sgenf_cgeno_cases()}, - {ttest_sgenf_cgent, [], ttest_sgenf_cgent_cases()}, - {ttest_sgenf_csock, [], ttest_sgenf_csock_cases()}, - {ttest_sgenf_csockf, [], ttest_sgenf_csockf_cases()}, - {ttest_sgenf_csocko, [], ttest_sgenf_csocko_cases()}, - {ttest_sgenf_csockt, [], ttest_sgenf_csockt_cases()}, - {ttest_sgeno, [], ttest_sgeno_cases()}, - {ttest_sgeno_cgen, [], ttest_sgeno_cgen_cases()}, - {ttest_sgeno_cgenf, [], ttest_sgeno_cgenf_cases()}, - {ttest_sgeno_cgeno, [], ttest_sgeno_cgeno_cases()}, - {ttest_sgeno_cgent, [], ttest_sgeno_cgent_cases()}, - {ttest_sgeno_csock, [], ttest_sgeno_csock_cases()}, - {ttest_sgeno_csockf, [], ttest_sgeno_csockf_cases()}, - {ttest_sgeno_csocko, [], ttest_sgeno_csocko_cases()}, - {ttest_sgeno_csockt, [], ttest_sgeno_csockt_cases()}, - {ttest_sgent, [], ttest_sgent_cases()}, - {ttest_sgent_cgen, [], ttest_sgent_cgen_cases()}, - {ttest_sgent_cgenf, [], ttest_sgent_cgenf_cases()}, - {ttest_sgent_cgeno, [], ttest_sgent_cgeno_cases()}, - {ttest_sgent_cgent, [], ttest_sgent_cgent_cases()}, - {ttest_sgent_csock, [], ttest_sgent_csock_cases()}, - {ttest_sgent_csockf, [], ttest_sgent_csockf_cases()}, - {ttest_sgent_csocko, [], ttest_sgent_csocko_cases()}, - {ttest_sgent_csockt, [], ttest_sgent_csockt_cases()}, - {ttest_ssockf, [], ttest_ssockf_cases()}, - {ttest_ssockf_cgen, [], ttest_ssockf_cgen_cases()}, - {ttest_ssockf_cgenf, [], ttest_ssockf_cgenf_cases()}, - {ttest_ssockf_cgeno, [], ttest_ssockf_cgeno_cases()}, - {ttest_ssockf_cgent, [], ttest_ssockf_cgent_cases()}, - {ttest_ssockf_csock, [], ttest_ssockf_csock_cases()}, - {ttest_ssockf_csockf, [], ttest_ssockf_csockf_cases()}, - {ttest_ssockf_csocko, [], ttest_ssockf_csocko_cases()}, - {ttest_ssockf_csockt, [], ttest_ssockf_csockt_cases()}, - {ttest_ssocko, [], ttest_ssocko_cases()}, - {ttest_ssocko_cgen, [], ttest_ssocko_cgen_cases()}, - {ttest_ssocko_cgenf, [], ttest_ssocko_cgenf_cases()}, - {ttest_ssocko_cgeno, [], ttest_ssocko_cgeno_cases()}, - {ttest_ssocko_cgent, [], ttest_ssocko_cgent_cases()}, - {ttest_ssocko_csock, [], ttest_ssocko_csock_cases()}, - {ttest_ssocko_csockf, [], ttest_ssocko_csockf_cases()}, - {ttest_ssocko_csocko, [], ttest_ssocko_csocko_cases()}, - {ttest_ssocko_csockt, [], ttest_ssocko_csockt_cases()}, - {ttest_ssockt, [], ttest_ssockt_cases()}, - {ttest_ssockt_cgen, [], ttest_ssockt_cgen_cases()}, - {ttest_ssockt_cgenf, [], ttest_ssockt_cgenf_cases()}, - {ttest_ssockt_cgeno, [], ttest_ssockt_cgeno_cases()}, - {ttest_ssockt_cgent, [], ttest_ssockt_cgent_cases()}, - {ttest_ssockt_csock, [], ttest_ssockt_csock_cases()}, - {ttest_ssockt_csockf, [], ttest_ssockt_csockf_cases()}, - {ttest_ssockt_csocko, [], ttest_ssockt_csocko_cases()}, - {ttest_ssockt_csockt, [], ttest_ssockt_csockt_cases()} + [{api, [], api_cases()}, + {api_basic, [], api_basic_cases()}, + {api_options, [], api_options_cases()}, + {api_op_with_timeout, [], api_op_with_timeout_cases()}, + {socket_closure, [], socket_closure_cases()}, + {sc_ctrl_proc_exit, [], sc_cp_exit_cases()}, + {sc_local_close, [], sc_lc_cases()}, + {sc_remote_close, [], sc_rc_cases()}, + {sc_remote_shutdown, [], sc_rs_cases()}, + {traffic, [], traffic_cases()}, + {traffic_chunks, [], traffic_chunks_cases()}, + {traffic_pp_send_recv, [], traffic_pp_send_recv_cases()}, + {traffic_pp_sendto_recvfrom, [], traffic_pp_sendto_recvfrom_cases()}, + {traffic_pp_sendmsg_recvmsg, [], traffic_pp_sendmsg_recvmsg_cases()}, + {ttest, [], ttest_cases()}, + {ttest_sgenf, [], ttest_sgenf_cases()}, + {ttest_sgenf_cgen, [], ttest_sgenf_cgen_cases()}, + {ttest_sgenf_cgenf, [], ttest_sgenf_cgenf_cases()}, + {ttest_sgenf_cgeno, [], ttest_sgenf_cgeno_cases()}, + {ttest_sgenf_cgent, [], ttest_sgenf_cgent_cases()}, + {ttest_sgenf_csock, [], ttest_sgenf_csock_cases()}, + {ttest_sgenf_csockf, [], ttest_sgenf_csockf_cases()}, + {ttest_sgenf_csocko, [], ttest_sgenf_csocko_cases()}, + {ttest_sgenf_csockt, [], ttest_sgenf_csockt_cases()}, + {ttest_sgeno, [], ttest_sgeno_cases()}, + {ttest_sgeno_cgen, [], ttest_sgeno_cgen_cases()}, + {ttest_sgeno_cgenf, [], ttest_sgeno_cgenf_cases()}, + {ttest_sgeno_cgeno, [], ttest_sgeno_cgeno_cases()}, + {ttest_sgeno_cgent, [], ttest_sgeno_cgent_cases()}, + {ttest_sgeno_csock, [], ttest_sgeno_csock_cases()}, + {ttest_sgeno_csockf, [], ttest_sgeno_csockf_cases()}, + {ttest_sgeno_csocko, [], ttest_sgeno_csocko_cases()}, + {ttest_sgeno_csockt, [], ttest_sgeno_csockt_cases()}, + {ttest_sgent, [], ttest_sgent_cases()}, + {ttest_sgent_cgen, [], ttest_sgent_cgen_cases()}, + {ttest_sgent_cgenf, [], ttest_sgent_cgenf_cases()}, + {ttest_sgent_cgeno, [], ttest_sgent_cgeno_cases()}, + {ttest_sgent_cgent, [], ttest_sgent_cgent_cases()}, + {ttest_sgent_csock, [], ttest_sgent_csock_cases()}, + {ttest_sgent_csockf, [], ttest_sgent_csockf_cases()}, + {ttest_sgent_csocko, [], ttest_sgent_csocko_cases()}, + {ttest_sgent_csockt, [], ttest_sgent_csockt_cases()}, + {ttest_ssockf, [], ttest_ssockf_cases()}, + {ttest_ssockf_cgen, [], ttest_ssockf_cgen_cases()}, + {ttest_ssockf_cgenf, [], ttest_ssockf_cgenf_cases()}, + {ttest_ssockf_cgeno, [], ttest_ssockf_cgeno_cases()}, + {ttest_ssockf_cgent, [], ttest_ssockf_cgent_cases()}, + {ttest_ssockf_csock, [], ttest_ssockf_csock_cases()}, + {ttest_ssockf_csockf, [], ttest_ssockf_csockf_cases()}, + {ttest_ssockf_csocko, [], ttest_ssockf_csocko_cases()}, + {ttest_ssockf_csockt, [], ttest_ssockf_csockt_cases()}, + {ttest_ssocko, [], ttest_ssocko_cases()}, + {ttest_ssocko_cgen, [], ttest_ssocko_cgen_cases()}, + {ttest_ssocko_cgenf, [], ttest_ssocko_cgenf_cases()}, + {ttest_ssocko_cgeno, [], ttest_ssocko_cgeno_cases()}, + {ttest_ssocko_cgent, [], ttest_ssocko_cgent_cases()}, + {ttest_ssocko_csock, [], ttest_ssocko_csock_cases()}, + {ttest_ssocko_csockf, [], ttest_ssocko_csockf_cases()}, + {ttest_ssocko_csocko, [], ttest_ssocko_csocko_cases()}, + {ttest_ssocko_csockt, [], ttest_ssocko_csockt_cases()}, + {ttest_ssockt, [], ttest_ssockt_cases()}, + {ttest_ssockt_cgen, [], ttest_ssockt_cgen_cases()}, + {ttest_ssockt_cgenf, [], ttest_ssockt_cgenf_cases()}, + {ttest_ssockt_cgeno, [], ttest_ssockt_cgeno_cases()}, + {ttest_ssockt_cgent, [], ttest_ssockt_cgent_cases()}, + {ttest_ssockt_csock, [], ttest_ssockt_csock_cases()}, + {ttest_ssockt_csockf, [], ttest_ssockt_csockf_cases()}, + {ttest_ssockt_csocko, [], ttest_ssockt_csocko_cases()}, + {ttest_ssockt_csockt, [], ttest_ssockt_csockt_cases()} %% {tickets, [], ticket_cases()} ]. @@ -588,10 +647,16 @@ api_basic_cases() -> [ api_b_open_and_close_udp4, api_b_open_and_close_tcp4, + api_b_open_and_close_udpL, + api_b_open_and_close_tcpL, api_b_sendto_and_recvfrom_udp4, + api_b_sendto_and_recvfrom_udpL, api_b_sendmsg_and_recvmsg_udp4, + api_b_sendmsg_and_recvmsg_udpL, api_b_send_and_recv_tcp4, - api_b_sendmsg_and_recvmsg_tcp4 + api_b_send_and_recv_tcpL, + api_b_sendmsg_and_recvmsg_tcp4, + api_b_sendmsg_and_recvmsg_tcpL ]. api_options_cases() -> @@ -638,13 +703,15 @@ socket_closure_cases() -> ]. %% These cases are all about socket cleanup after the controlling process -%% exits *without* calling socket:close/1. +%% exits *without* explicitly calling socket:close/1. sc_cp_exit_cases() -> [ sc_cpe_socket_cleanup_tcp4, sc_cpe_socket_cleanup_tcp6, + sc_cpe_socket_cleanup_tcpL, sc_cpe_socket_cleanup_udp4, - sc_cpe_socket_cleanup_udp6 + sc_cpe_socket_cleanup_udp6, + sc_cpe_socket_cleanup_udpL ]. %% These cases tests what happens when the socket is closed locally. @@ -652,17 +719,22 @@ sc_lc_cases() -> [ sc_lc_recv_response_tcp4, sc_lc_recv_response_tcp6, + sc_lc_recv_response_tcpL, sc_lc_recvfrom_response_udp4, sc_lc_recvfrom_response_udp6, + sc_lc_recvfrom_response_udpL, sc_lc_recvmsg_response_tcp4, sc_lc_recvmsg_response_tcp6, + sc_lc_recvmsg_response_tcpL, sc_lc_recvmsg_response_udp4, sc_lc_recvmsg_response_udp6, + sc_lc_recvmsg_response_udpL, sc_lc_acceptor_response_tcp4, - sc_lc_acceptor_response_tcp6 + sc_lc_acceptor_response_tcp6, + sc_lc_acceptor_response_tcpL ]. %% These cases tests what happens when the socket is closed remotely. @@ -670,9 +742,11 @@ sc_rc_cases() -> [ sc_rc_recv_response_tcp4, sc_rc_recv_response_tcp6, + sc_rc_recv_response_tcpL, sc_rc_recvmsg_response_tcp4, - sc_rc_recvmsg_response_tcp6 + sc_rc_recvmsg_response_tcp6, + sc_rc_recvmsg_response_tcpL ]. %% These cases tests what happens when the socket is shutdown/closed remotely @@ -681,43 +755,72 @@ sc_rs_cases() -> [ sc_rs_recv_send_shutdown_receive_tcp4, sc_rs_recv_send_shutdown_receive_tcp6, + sc_rs_recv_send_shutdown_receive_tcpL, sc_rs_recvmsg_send_shutdown_receive_tcp4, - sc_rs_recvmsg_send_shutdown_receive_tcp6 + sc_rs_recvmsg_send_shutdown_receive_tcp6, + sc_rs_recvmsg_send_shutdown_receive_tcpL ]. traffic_cases() -> [ + {group, traffic_chunks}, + {group, traffic_pp_send_recv}, + {group, traffic_pp_sendto_recvfrom}, + {group, traffic_pp_sendmsg_recvmsg} + ]. + +traffic_chunks_cases() -> + [ traffic_send_and_recv_chunks_tcp4, traffic_send_and_recv_chunks_tcp6, + traffic_send_and_recv_chunks_tcpL + ]. +traffic_pp_send_recv_cases() -> + [ traffic_ping_pong_small_send_and_recv_tcp4, traffic_ping_pong_small_send_and_recv_tcp6, + traffic_ping_pong_small_send_and_recv_tcpL, traffic_ping_pong_medium_send_and_recv_tcp4, traffic_ping_pong_medium_send_and_recv_tcp6, + traffic_ping_pong_medium_send_and_recv_tcpL, traffic_ping_pong_large_send_and_recv_tcp4, traffic_ping_pong_large_send_and_recv_tcp6, + traffic_ping_pong_large_send_and_recv_tcpL + ]. +traffic_pp_sendto_recvfrom_cases() -> + [ traffic_ping_pong_small_sendto_and_recvfrom_udp4, traffic_ping_pong_small_sendto_and_recvfrom_udp6, + traffic_ping_pong_small_sendto_and_recvfrom_udpL, traffic_ping_pong_medium_sendto_and_recvfrom_udp4, traffic_ping_pong_medium_sendto_and_recvfrom_udp6, + traffic_ping_pong_medium_sendto_and_recvfrom_udpL + ]. +traffic_pp_sendmsg_recvmsg_cases() -> + [ traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4, traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6, + traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL, traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4, traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6, + traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL, traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4, traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6, + traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL, traffic_ping_pong_small_sendmsg_and_recvmsg_udp4, traffic_ping_pong_small_sendmsg_and_recvmsg_udp6, + traffic_ping_pong_small_sendmsg_and_recvmsg_udpL, traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4, - traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6 + traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6, + traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL ]. - - + ttest_cases() -> [ %% Server: transport = gen_tcp, active = false @@ -1123,12 +1226,15 @@ ttest_ssockf_csockf_cases() -> [ ttest_ssockf_csockf_small_tcp4, ttest_ssockf_csockf_small_tcp6, + ttest_ssockf_csockf_small_tcpL, ttest_ssockf_csockf_medium_tcp4, ttest_ssockf_csockf_medium_tcp6, + ttest_ssockf_csockf_medium_tcpL, ttest_ssockf_csockf_large_tcp4, - ttest_ssockf_csockf_large_tcp6 + ttest_ssockf_csockf_large_tcp6, + ttest_ssockf_csockf_large_tcpL ]. %% Server: transport = socket(tcp), active = false @@ -1137,12 +1243,15 @@ ttest_ssockf_csocko_cases() -> [ ttest_ssockf_csocko_small_tcp4, ttest_ssockf_csocko_small_tcp6, + ttest_ssockf_csocko_small_tcpL, ttest_ssockf_csocko_medium_tcp4, ttest_ssockf_csocko_medium_tcp6, + ttest_ssockf_csocko_medium_tcpL, ttest_ssockf_csocko_large_tcp4, - ttest_ssockf_csocko_large_tcp6 + ttest_ssockf_csocko_large_tcp6, + ttest_ssockf_csocko_large_tcpL ]. %% Server: transport = socket(tcp), active = false @@ -1151,12 +1260,15 @@ ttest_ssockf_csockt_cases() -> [ ttest_ssockf_csockt_small_tcp4, ttest_ssockf_csockt_small_tcp6, + ttest_ssockf_csockt_small_tcpL, ttest_ssockf_csockt_medium_tcp4, ttest_ssockf_csockt_medium_tcp6, + ttest_ssockf_csockt_medium_tcpL, ttest_ssockf_csockt_large_tcp4, - ttest_ssockf_csockt_large_tcp6 + ttest_ssockf_csockt_large_tcp6, + ttest_ssockf_csockt_large_tcpL ]. %% Server: transport = socket(tcp), active = once @@ -1232,12 +1344,15 @@ ttest_ssocko_csockf_cases() -> [ ttest_ssocko_csockf_small_tcp4, ttest_ssocko_csockf_small_tcp6, + ttest_ssocko_csockf_small_tcpL, ttest_ssocko_csockf_medium_tcp4, ttest_ssocko_csockf_medium_tcp6, + ttest_ssocko_csockf_medium_tcpL, ttest_ssocko_csockf_large_tcp4, - ttest_ssocko_csockf_large_tcp6 + ttest_ssocko_csockf_large_tcp6, + ttest_ssocko_csockf_large_tcpL ]. %% Server: transport = socket(tcp), active = once @@ -1246,12 +1361,15 @@ ttest_ssocko_csocko_cases() -> [ ttest_ssocko_csocko_small_tcp4, ttest_ssocko_csocko_small_tcp6, + ttest_ssocko_csocko_small_tcpL, ttest_ssocko_csocko_medium_tcp4, ttest_ssocko_csocko_medium_tcp6, + ttest_ssocko_csocko_medium_tcpL, ttest_ssocko_csocko_large_tcp4, - ttest_ssocko_csocko_large_tcp6 + ttest_ssocko_csocko_large_tcp6, + ttest_ssocko_csocko_large_tcpL ]. %% Server: transport = socket(tcp), active = once @@ -1260,12 +1378,15 @@ ttest_ssocko_csockt_cases() -> [ ttest_ssocko_csockt_small_tcp4, ttest_ssocko_csockt_small_tcp6, + ttest_ssocko_csockt_small_tcpL, ttest_ssocko_csockt_medium_tcp4, ttest_ssocko_csockt_medium_tcp6, + ttest_ssocko_csockt_medium_tcpL, ttest_ssocko_csockt_large_tcp4, - ttest_ssocko_csockt_large_tcp6 + ttest_ssocko_csockt_large_tcp6, + ttest_ssocko_csockt_large_tcpL ]. %% Server: transport = socket(tcp), active = true @@ -1341,12 +1462,15 @@ ttest_ssockt_csockf_cases() -> [ ttest_ssockt_csockf_small_tcp4, ttest_ssockt_csockf_small_tcp6, + ttest_ssockt_csockf_small_tcpL, ttest_ssockt_csockf_medium_tcp4, ttest_ssockt_csockf_medium_tcp6, + ttest_ssockt_csockf_medium_tcpL, ttest_ssockt_csockf_large_tcp4, - ttest_ssockt_csockf_large_tcp6 + ttest_ssockt_csockf_large_tcp6, + ttest_ssockt_csockf_large_tcpL ]. %% Server: transport = socket(tcp), active = true @@ -1355,12 +1479,15 @@ ttest_ssockt_csocko_cases() -> [ ttest_ssockt_csocko_small_tcp4, ttest_ssockt_csocko_small_tcp6, + ttest_ssockt_csocko_small_tcpL, ttest_ssockt_csocko_medium_tcp4, ttest_ssockt_csocko_medium_tcp6, + ttest_ssockt_csocko_medium_tcpL, ttest_ssockt_csocko_large_tcp4, - ttest_ssockt_csocko_large_tcp6 + ttest_ssockt_csocko_large_tcp6, + ttest_ssockt_csocko_large_tcpL ]. %% Server: transport = socket(tcp), active = true @@ -1369,12 +1496,15 @@ ttest_ssockt_csockt_cases() -> [ ttest_ssockt_csockt_small_tcp4, ttest_ssockt_csockt_small_tcp6, + ttest_ssockt_csockt_small_tcpL, ttest_ssockt_csockt_medium_tcp4, ttest_ssockt_csockt_medium_tcp6, + ttest_ssockt_csockt_medium_tcpL, ttest_ssockt_csockt_large_tcp4, - ttest_ssockt_csockt_large_tcp6 + ttest_ssockt_csockt_large_tcp6, + ttest_ssockt_csockt_large_tcpL ]. %% ticket_cases() -> @@ -1510,6 +1640,46 @@ api_b_open_and_close_tcp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically open (create) and close an Unix Domain dgram (UDP) socket. +%% With some extra checks... +api_b_open_and_close_udpL(suite) -> + []; +api_b_open_and_close_udpL(doc) -> + []; +api_b_open_and_close_udpL(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), + tc_try(api_b_open_and_close_udpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + InitState = #{domain => local, + type => dgram, + protocol => default}, + ok = api_b_open_and_close(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Basically open (create) and close an Unix Domain stream (TCP) socket. +%% With some extra checks... +api_b_open_and_close_tcpL(suite) -> + []; +api_b_open_and_close_tcpL(doc) -> + []; +api_b_open_and_close_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), + tc_try(api_b_open_and_close_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + InitState = #{domain => local, + type => stream, + protocol => default}, + ok = api_b_open_and_close(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + api_b_open_and_close(InitState) -> Seq = [ @@ -1633,6 +1803,37 @@ api_b_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) -> socket:recvfrom(Sock) end, InitState = #{domain => inet, + proto => udp, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_udp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Basically send and receive on an IPv4 UDP (dgram) socket using +%% sendto and recvfrom. +api_b_sendto_and_recvfrom_udpL(suite) -> + []; +api_b_sendto_and_recvfrom_udpL(doc) -> + []; +api_b_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), + tc_try(api_b_sendto_and_recvfrom_udpL, + fun() -> + has_support_unix_domain_socket(), + unix_domain_socket_host_cond() + end, + fun() -> + Send = fun(Sock, Data, Dest) -> + socket:sendto(Sock, Data, Dest) + end, + Recv = fun(Sock) -> + socket:recvfrom(Sock) + end, + InitState = #{domain => local, + proto => default, send => Send, recv => Recv}, ok = api_b_send_and_recv_udp(InitState) @@ -1665,17 +1866,66 @@ api_b_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) -> end, Recv = fun(Sock) -> %% We have some issues on old darwing... - socket:setopt(Sock, otp, debug, true), + %% socket:setopt(Sock, otp, debug, true), case socket:recvmsg(Sock) of {ok, #{addr := Source, iov := [Data]}} -> - socket:setopt(Sock, otp, debug, false), + %% socket:setopt(Sock, otp, debug, false), {ok, {Source, Data}}; {error, _} = ERROR -> ERROR end end, InitState = #{domain => inet, + proto => udp, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_udp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Basically send and receive on an IPv4 UDP (dgram) socket +%% using sendmsg and recvmsg. +api_b_sendmsg_and_recvmsg_udpL(suite) -> + []; +api_b_sendmsg_and_recvmsg_udpL(doc) -> + []; +api_b_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), + tc_try(api_b_sendmsg_and_recvmsg_udpL, + fun() -> + has_support_unix_domain_socket(), + unix_domain_socket_host_cond() + end, + fun() -> + Send = fun(Sock, Data, Dest) -> + %% We need tests for this, + %% but this is not the place it. + %% CMsgHdr = #{level => ip, + %% type => tos, + %% data => reliability}, + %% CMsgHdrs = [CMsgHdr], + MsgHdr = #{addr => Dest, + %% ctrl => CMsgHdrs, + iov => [Data]}, + socket:sendmsg(Sock, MsgHdr) + end, + Recv = fun(Sock) -> + %% We have some issues on old darwing... + %% socket:setopt(Sock, otp, debug, true), + case socket:recvmsg(Sock) of + {ok, #{addr := Source, + iov := [Data]}} -> + %% socket:setopt(Sock, otp, debug, false), + {ok, {Source, Data}}; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => local, + proto => default, send => Send, recv => Recv}, ok = api_b_send_and_recv_udp(InitState) @@ -1688,42 +1938,64 @@ api_b_send_and_recv_udp(InitState) -> Seq = [ #{desc => "local address", - cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, - {ok, State#{lsa => LSA}} + cmd => fun(#{domain := local = Domain} = State) -> + LSASrc = which_local_socket_addr(Domain), + LSADst = which_local_socket_addr(Domain), + {ok, State#{lsa_src => LSASrc, + lsa_dst => LSADst}}; + (#{domain := Domain} = State) -> + LSA = which_local_socket_addr(Domain), + {ok, State#{lsa_src => LSA, + lsa_dst => LSA}} end}, + #{desc => "open src socket", - cmd => fun(#{domain := Domain} = State) -> - Sock = sock_open(Domain, dgram, udp), - SASrc = sock_sockname(Sock), - {ok, State#{sock_src => Sock, sa_src => SASrc}} + cmd => fun(#{domain := Domain, + proto := Proto} = State) -> + Sock = sock_open(Domain, dgram, Proto), + {ok, State#{sock_src => Sock}} end}, #{desc => "bind src", - cmd => fun(#{sock_src := Sock, lsa := LSA}) -> - sock_bind(Sock, LSA), - ok + cmd => fun(#{sock_src := Sock, lsa_src := LSA}) -> + case socket:bind(Sock, LSA) of + {ok, _Port} -> + ?SEV_IPRINT("src bound"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("src bind failed: ~p", [Reason]), + ERROR + end end}, #{desc => "sockname src socket", cmd => fun(#{sock_src := Sock} = State) -> SASrc = sock_sockname(Sock), - %% ei("src sockaddr: ~p", [SASrc]), + ?SEV_IPRINT("src sockaddr: " + "~n ~p", [SASrc]), {ok, State#{sa_src => SASrc}} end}, + #{desc => "open dst socket", - cmd => fun(#{domain := Domain} = State) -> - Sock = sock_open(Domain, dgram, udp), + cmd => fun(#{domain := Domain, + proto := Proto} = State) -> + Sock = sock_open(Domain, dgram, Proto), {ok, State#{sock_dst => Sock}} end}, #{desc => "bind dst", - cmd => fun(#{sock_dst := Sock, lsa := LSA}) -> - sock_bind(Sock, LSA), - ok + cmd => fun(#{sock_dst := Sock, lsa_dst := LSA}) -> + case socket:bind(Sock, LSA) of + {ok, _Port} -> + ?SEV_IPRINT("src bound"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("src bind failed: ~p", [Reason]), + ERROR + end end}, #{desc => "sockname dst socket", cmd => fun(#{sock_dst := Sock} = State) -> SADst = sock_sockname(Sock), - %% ei("dst sockaddr: ~p", [SADst]), + ?SEV_IPRINT("dst sockaddr: " + "~n ~p", [SADst]), {ok, State#{sa_dst => SADst}} end}, #{desc => "send req (to dst)", @@ -1761,12 +2033,32 @@ api_b_send_and_recv_udp(InitState) -> end end}, #{desc => "close src socket", - cmd => fun(#{sock_src := Sock}) -> - ok = socket:close(Sock) + cmd => fun(#{domain := local, + sock_src := Sock, + lsa_src := #{path := Path}} = State) -> + ok = socket:close(Sock), + State1 = + unlink_path(Path, + fun() -> maps:remove(lsa_src, State) end, + fun() -> State end), + {ok, maps:remove(sock_src, State1)}; + (#{sock_src := Sock} = State) -> + ok = socket:close(Sock), + {ok, maps:remove(sock_src, State)} end}, #{desc => "close dst socket", - cmd => fun(#{sock_dst := Sock}) -> - ok = socket:close(Sock) + cmd => fun(#{domain := local, + sock_dst := Sock, + lsa_dst := #{path := Path}} = State) -> + ok = socket:close(Sock), + State1 = + unlink_path(Path, + fun() -> maps:remove(lsa_dst, State) end, + fun() -> State end), + {ok, maps:remove(sock_dst, State1)}; + (#{sock_dst := Sock} = State) -> + ok = socket:close(Sock), + {ok, maps:remove(sock_dst, State)} end}, %% *** We are done *** @@ -1796,6 +2088,34 @@ api_b_send_and_recv_tcp4(_Config) when is_list(_Config) -> socket:recv(Sock) end, InitState = #{domain => inet, + proto => tcp, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Basically send and receive using the "common" functions (send and recv) +%% on an Unix Domain (stream) socket (TCP). +api_b_send_and_recv_tcpL(suite) -> + []; +api_b_send_and_recv_tcpL(doc) -> + []; +api_b_send_and_recv_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_b_send_and_recv_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + Send = fun(Sock, Data) -> + socket:send(Sock, Data) + end, + Recv = fun(Sock) -> + socket:recv(Sock) + end, + InitState = #{domain => local, + proto => default, send => Send, recv => Recv}, ok = api_b_send_and_recv_tcp(InitState) @@ -1828,6 +2148,56 @@ api_b_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) -> end end, InitState = #{domain => inet, + proto => tcp, + send => Send, + recv => Recv}, + ok = api_b_send_and_recv_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Basically send and receive using the msg functions (sendmsg and recvmsg) +%% on an Unix Domain (stream) socket (TCP). +api_b_sendmsg_and_recvmsg_tcpL(suite) -> + []; +api_b_sendmsg_and_recvmsg_tcpL(doc) -> + []; +api_b_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_b_sendmsg_and_recvmsg_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + Send = fun(Sock, Data) -> + MsgHdr = #{iov => [Data]}, + socket:sendmsg(Sock, MsgHdr) + end, + Recv = fun(Sock) -> + case socket:recvmsg(Sock) of + %% On some platforms, the address + %% is *not* provided (e.g. FreeBSD) + {ok, #{addr := undefined, + iov := [Data]}} -> + {ok, Data}; + %% On some platforms, the address + %% *is* provided (e.g. linux) + {ok, #{addr := #{family := local}, + iov := [Data]}} -> + socket:setopt(Sock, + otp, + debug, + false), + {ok, Data}; + {error, _} = ERROR -> + socket:setopt(Sock, + otp, + debug, + false), + ERROR + end + end, + InitState = #{domain => local, + proto => default, send => Send, recv => Recv}, ok = api_b_send_and_recv_tcp(InitState) @@ -1855,13 +2225,13 @@ api_b_send_and_recv_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create listen socket", - cmd => fun(#{domain := Domain} = State) -> - case socket:open(Domain, stream, tcp) of + cmd => fun(#{domain := Domain, + proto := Proto} = State) -> + case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> @@ -1869,9 +2239,19 @@ api_b_send_and_recv_tcp(InitState) -> end end}, #{desc => "bind to local address", - cmd => fun(#{lsock := LSock, lsa := LSA} = State) -> + cmd => fun(#{domain := local, + lsock := LSock, + lsa := LSA} = _State) -> + case socket:bind(LSock, LSA) of + {ok, _Port} -> + ok; % We do not care about the port for local + {error, _} = ERROR -> + ERROR + end; + (#{lsock := LSock, lsa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> + ?SEV_IPRINT("bound to port: ~w", [Port]), {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR @@ -1882,7 +2262,12 @@ api_b_send_and_recv_tcp(InitState) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", - cmd => fun(#{tester := Tester, lport := Port}) -> + cmd => fun(#{domain := local, + tester := Tester, lsa := #{path := Path}}) -> + ?SEV_ANNOUNCE_READY(Tester, init, Path), + ok; + (#{tester := Tester, lport := Port}) -> + %% This is actually not used for unix domain socket ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, @@ -1946,12 +2331,29 @@ api_b_send_and_recv_tcp(InitState) -> end end}, #{desc => "close connection socket", - cmd => fun(#{csock := Sock}) -> - socket:close(Sock) + cmd => fun(#{csock := Sock} = State) -> + ok = socket:close(Sock), + {ok, maps:remove(csock, State)} end}, #{desc => "close listen socket", - cmd => fun(#{lsock := Sock}) -> - socket:close(Sock) + cmd => fun(#{domain := local, + lsock := Sock, + local_sa := #{path := Path}} = State) -> + ok = socket:close(Sock), + State1 = + unlink_path(Path, + fun() -> + maps:remove(local_sa, State) + end, + fun() -> State end), + {ok, maps:remove(lsock, State1)}; + (#{lsock := LSock} = State) -> + case socket:close(LSock) of + ok -> + {ok, maps:remove(lsock, State)}; + {error, _} = ERROR -> + ERROR + end end}, %% *** We are done *** @@ -1962,7 +2364,10 @@ api_b_send_and_recv_tcp(InitState) -> [ %% *** Wait for start order *** #{desc => "await start (from tester)", - cmd => fun(State) -> + cmd => fun(#{domain := local} = State) -> + {Tester, Path} = ?SEV_AWAIT_START(), + {ok, State#{tester => Tester, server_path => Path}}; + (State) -> {Tester, Port} = ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_port => Port}} end}, @@ -1974,16 +2379,20 @@ api_b_send_and_recv_tcp(InitState) -> %% *** The init part *** #{desc => "which server (local) address", - cmd => fun(#{domain := Domain, server_port := Port} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, - addr => LAddr}, - SSA = LSA#{port => Port}, + cmd => fun(#{domain := local = Domain, + server_path := Path} = State) -> + LSA = which_local_socket_addr(Domain), + SSA = #{family => Domain, path => Path}, + {ok, State#{local_sa => LSA, server_sa => SSA}}; + (#{domain := Domain, server_port := Port} = State) -> + LSA = which_local_socket_addr(Domain), + SSA = LSA#{port => Port}, {ok, State#{local_sa => LSA, server_sa => SSA}} end}, #{desc => "create socket", - cmd => fun(#{domain := Domain} = State) -> - case socket:open(Domain, stream, tcp) of + cmd => fun(#{domain := Domain, + proto := Proto} = State) -> + case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> @@ -2054,8 +2463,20 @@ api_b_send_and_recv_tcp(InitState) -> end end}, #{desc => "close socket", - cmd => fun(#{sock := Sock}) -> - socket:close(Sock) + cmd => fun(#{domain := local, + sock := Sock, + local_sa := #{path := Path}} = State) -> + ok = socket:close(Sock), + State1 = + unlink_path(Path, + fun() -> + maps:remove(local_sa, State) + end, + fun() -> State end), + {ok, maps:remove(sock, State1)}; + (#{sock := Sock} = State) -> + ok = socket:close(Sock), + {ok, maps:remove(sock, State)} end}, %% *** We are done *** @@ -2530,8 +2951,7 @@ api_opt_simple_otp_rcvbuf_option() -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", @@ -2776,8 +3196,7 @@ api_opt_simple_otp_rcvbuf_option() -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", @@ -3434,11 +3853,11 @@ api_to_connect_tcp4(suite) -> api_to_connect_tcp4(doc) -> []; api_to_connect_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), Cond = fun() -> api_to_connect_cond() end, tc_try(api_to_connect_tcp4, Cond, fun() -> - ?TT(?SECS(10)), InitState = #{domain => inet, backlog => 1, timeout => 5000, @@ -3454,7 +3873,9 @@ api_to_connect_cond() -> %% So, just to simplify, we require atleast 4.15 api_to_connect_cond({unix, linux}, {Maj, Min, _Rev}) -> if - ((Maj >= 4) andalso (Min >= 15)) -> + (Maj > 4) -> + ok; + ((Maj =:= 4) andalso (Min >= 15)) -> ok; true -> skip("TC does not work") @@ -3491,10 +3912,10 @@ api_to_connect_tcp6(suite) -> api_to_connect_tcp6(doc) -> []; api_to_connect_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_connect_tcp6, fun() -> has_support_ipv6(), api_to_connect_cond() end, fun() -> - ?TT(?SECS(10)), InitState = #{domain => inet6, backlog => 1, timeout => 5000, @@ -3531,8 +3952,7 @@ api_to_connect_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", @@ -3603,8 +4023,7 @@ api_to_connect_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create node", @@ -3754,8 +4173,7 @@ api_to_connect_tcp(InitState) -> end}, #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "order server start", @@ -3906,9 +4324,7 @@ api_toc_tcp_client_await_terminate(Parent) -> end. api_to_connect_tcp_await_timeout(To, ServerSA, Domain, ConLimit) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, - addr => LAddr}, + LSA = which_local_socket_addr(Domain), NewSock = fun() -> S = case socket:open(Domain, stream, tcp) of {ok, Sock} -> @@ -3986,9 +4402,9 @@ api_to_accept_tcp4(suite) -> api_to_accept_tcp4(doc) -> []; api_to_accept_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_accept_tcp4, fun() -> - ?TT(?SECS(10)), InitState = #{domain => inet, timeout => 5000}, ok = api_to_accept_tcp(InitState) end). @@ -4003,10 +4419,10 @@ api_to_accept_tcp6(suite) -> api_to_accept_tcp6(doc) -> []; api_to_accept_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_accept_tcp4, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(10)), InitState = #{domain => inet6, timeout => 5000}, ok = api_to_accept_tcp(InitState) end). @@ -4020,8 +4436,7 @@ api_to_accept_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create (listen) socket", @@ -4145,8 +4560,7 @@ api_to_maccept_tcp(InitState) -> end}, #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create (listen) socket", @@ -4602,9 +5016,9 @@ api_to_recv_tcp4(suite) -> api_to_recv_tcp4(doc) -> []; api_to_recv_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_recv_tcp4, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recv(Sock, 0, To) end, InitState = #{domain => inet, recv => Recv, @@ -4622,12 +5036,12 @@ api_to_recv_tcp6(suite) -> api_to_recv_tcp6(doc) -> []; api_to_recv_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_recv_tcp6, fun() -> has_support_ipv6() end, fun() -> case socket:supports(ipv6) of true -> - ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recv(Sock, 0, To) end, @@ -4663,8 +5077,7 @@ api_to_receive_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", @@ -4782,10 +5195,8 @@ api_to_receive_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain, server_port := Port} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, - addr => LAddr}, - SSA = LSA#{port => Port}, + LSA = which_local_socket_addr(Domain), + SSA = LSA#{port => Port}, {ok, State#{local_sa => LSA, server_sa => SSA}} end}, #{desc => "create socket", @@ -4961,9 +5372,9 @@ api_to_recvfrom_udp4(suite) -> api_to_recvfrom_udp4(doc) -> []; api_to_recvfrom_udp4(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_recvfrom_udp4, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recvfrom(Sock, 0, To) end, InitState = #{domain => inet, recv => Recv, @@ -4981,10 +5392,10 @@ api_to_recvfrom_udp6(suite) -> api_to_recvfrom_udp6(doc) -> []; api_to_recvfrom_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_recvfrom_udp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recvfrom(Sock, 0, To) end, InitState = #{domain => inet6, recv => Recv, @@ -5001,8 +5412,7 @@ api_to_receive_udp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create socket", @@ -5078,9 +5488,9 @@ api_to_recvmsg_udp4(suite) -> api_to_recvmsg_udp4(doc) -> []; api_to_recvmsg_udp4(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_recvmsg_udp4, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => inet, recv => Recv, @@ -5098,10 +5508,10 @@ api_to_recvmsg_udp6(suite) -> api_to_recvmsg_udp6(doc) -> []; api_to_recvmsg_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_recvmsg_udp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => inet6, recv => Recv, @@ -5119,9 +5529,9 @@ api_to_recvmsg_tcp4(suite) -> api_to_recvmsg_tcp4(doc) -> []; api_to_recvmsg_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_recvmsg_tcp4, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => inet, recv => Recv, @@ -5139,10 +5549,10 @@ api_to_recvmsg_tcp6(suite) -> api_to_recvmsg_tcp6(doc) -> []; api_to_recvmsg_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(api_to_recvmsg_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, InitState = #{domain => inet6, recv => Recv, @@ -5170,9 +5580,9 @@ sc_cpe_socket_cleanup_tcp4(suite) -> sc_cpe_socket_cleanup_tcp4(doc) -> []; sc_cpe_socket_cleanup_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), tc_try(sc_cpe_socket_cleanup_tcp4, fun() -> - ?TT(?SECS(5)), InitState = #{domain => inet, type => stream, protocol => tcp}, @@ -5190,10 +5600,10 @@ sc_cpe_socket_cleanup_tcp6(suite) -> sc_cpe_socket_cleanup_tcp6(doc) -> []; sc_cpe_socket_cleanup_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), tc_try(sc_cpe_socket_cleanup_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(5)), InitState = #{domain => inet6, type => stream, protocol => tcp}, @@ -5204,6 +5614,27 @@ sc_cpe_socket_cleanup_tcp6(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sockets are cleaned up %% ("removed") when the controlling process terminates (without explicitly +%% calling the close function). For a Unix Domain (stream) socket (TCP). + +sc_cpe_socket_cleanup_tcpL(suite) -> + []; +sc_cpe_socket_cleanup_tcpL(doc) -> + []; +sc_cpe_socket_cleanup_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), + tc_try(sc_cpe_socket_cleanup_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + InitState = #{domain => local, + type => stream, + protocol => default}, + ok = sc_cpe_socket_cleanup(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sockets are cleaned up +%% ("removed") when the controlling process terminates (without explicitly %% calling the close function). For a IPv4 UDP (dgram) socket. sc_cpe_socket_cleanup_udp4(suite) -> @@ -5211,9 +5642,9 @@ sc_cpe_socket_cleanup_udp4(suite) -> sc_cpe_socket_cleanup_udp4(doc) -> []; sc_cpe_socket_cleanup_udp4(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), tc_try(sc_cpe_socket_cleanup_udp4, fun() -> - ?TT(?SECS(5)), InitState = #{domain => inet, type => dgram, protocol => udp}, @@ -5232,10 +5663,10 @@ sc_cpe_socket_cleanup_udp6(suite) -> sc_cpe_socket_cleanup_udp6(doc) -> []; sc_cpe_socket_cleanup_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), tc_try(sc_cpe_socket_cleanup_udp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(5)), InitState = #{domain => inet6, type => dgram, protocol => udp}, @@ -5244,6 +5675,28 @@ sc_cpe_socket_cleanup_udp6(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sockets are cleaned up +%% ("removed") when the controlling process terminates (without explicitly +%% calling the close function). For a Unix Domain (dgram) socket (UDP). + +sc_cpe_socket_cleanup_udpL(suite) -> + []; +sc_cpe_socket_cleanup_udpL(doc) -> + []; +sc_cpe_socket_cleanup_udpL(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), + tc_try(sc_cpe_socket_cleanup_udpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + InitState = #{domain => local, + type => dgram, + protocol => default}, + ok = sc_cpe_socket_cleanup(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sc_cpe_socket_cleanup(InitState) -> OwnerSeq = @@ -5386,12 +5839,11 @@ sc_lc_recv_response_tcp4(suite) -> sc_lc_recv_response_tcp4(doc) -> []; sc_lc_recv_response_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(sc_lc_recv_response_tcp4, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => inet, - type => stream, protocol => tcp, recv => Recv}, ok = sc_lc_receive_response_tcp(InitState) @@ -5408,13 +5860,12 @@ sc_lc_recv_response_tcp6(suite) -> sc_lc_recv_response_tcp6(doc) -> []; sc_lc_recv_response_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(sc_lc_recv_response_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => inet6, - type => stream, protocol => tcp, recv => Recv}, ok = sc_lc_receive_response_tcp(InitState) @@ -5422,6 +5873,28 @@ sc_lc_recv_response_tcp6(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the recv function. +%% Socket is Unix Domain (stream) socket. + +sc_lc_recv_response_tcpL(suite) -> + []; +sc_lc_recv_response_tcpL(doc) -> + []; +sc_lc_recv_response_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(sc_lc_recv_response_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + Recv = fun(Sock) -> socket:recv(Sock) end, + InitState = #{domain => local, + protocol => default, + recv => Recv}, + ok = sc_lc_receive_response_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sc_lc_receive_response_tcp(InitState) -> %% This (acceptor) is the server that accepts connections. @@ -5444,15 +5917,13 @@ sc_lc_receive_response_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, - {ok, State#{local_sa => LSA}} + LSA = which_local_socket_addr(Domain), + {ok, State#{lsa => LSA}} end}, #{desc => "create (listen) socket", cmd => fun(#{domain := Domain, - type := Type, protocol := Proto} = State) -> - case socket:open(Domain, Type, Proto) of + case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> @@ -5460,9 +5931,22 @@ sc_lc_receive_response_tcp(InitState) -> end end}, #{desc => "bind to local address", - cmd => fun(#{lsock := LSock, local_sa := LSA} = State) -> + cmd => fun(#{domain := local, + lsock := LSock, + lsa := LSA} = _State) -> + ?SEV_IPRINT("bind to LSA: " + "~n ~p", [LSA]), + case socket:bind(LSock, LSA) of + {ok, _Port} -> + ok; % We do not care about the port for local + {error, _} = ERROR -> + ERROR + end; + (#{lsock := LSock, + lsa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> + ?SEV_IPRINT("bound to port: ~w", [Port]), {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR @@ -5473,7 +5957,12 @@ sc_lc_receive_response_tcp(InitState) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", - cmd => fun(#{tester := Tester, lport := Port}) -> + cmd => fun(#{domain := local, + tester := Tester, + lsa := #{path := Path}}) -> + ?SEV_ANNOUNCE_READY(Tester, init, Path), + ok; + (#{tester := Tester, lport := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, Port), ok end}, @@ -5494,7 +5983,8 @@ sc_lc_receive_response_tcp(InitState) -> cmd => fun(#{lsock := LSock} = State) -> case socket:accept(LSock) of {ok, Sock} -> - ?SEV_IPRINT("connection accepted"), + ?SEV_IPRINT("connection accepted: " + "~n ~p", [socket:sockname(Sock)]), {ok, State#{csock => Sock}}; {error, _} = ERROR -> ERROR @@ -5525,9 +6015,8 @@ sc_lc_receive_response_tcp(InitState) -> ?SEV_AWAIT_CONTINUE(Tester, tester, close), ok end}, - #{desc => "close the connection socket", + #{desc => "close connection socket", cmd => fun(#{csock := Sock} = State) -> - %% ok = socket:setopt(Sock, otp, debug, true), case socket:close(Sock) of ok -> {ok, maps:remove(csock, State)}; @@ -5551,8 +6040,19 @@ sc_lc_receive_response_tcp(InitState) -> ERROR end end}, - #{desc => "close socket", - cmd => fun(#{lsock := Sock} = State) -> + #{desc => "close listen socket", + cmd => fun(#{domain := local, + lsock := Sock, + lsa := #{path := Path}} = State) -> + ok = socket:close(Sock), + State1 = + unlink_path(Path, + fun() ->maps:remove(lsa, State) end, + fun() -> State end), + State2 = maps:remove(lsock, State1), + State3 = maps:remove(lport, State2), + {ok, State3}; + (#{lsock := Sock} = State) -> case socket:close(Sock) of ok -> State1 = maps:remove(lsock, State), @@ -5667,15 +6167,13 @@ sc_lc_receive_response_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create socket", cmd => fun(#{domain := Domain, - type := Type, protocol := Proto} = State) -> - case socket:open(Domain, Type, Proto) of + case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> @@ -5684,6 +6182,8 @@ sc_lc_receive_response_tcp(InitState) -> end}, #{desc => "bind socket to local address", cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> + ?SEV_IPRINT("bind to LSA: " + "~n ~p", [LSA]), case socket:bind(Sock, LSA) of {ok, _} -> ok; @@ -5699,7 +6199,19 @@ sc_lc_receive_response_tcp(InitState) -> %% The actual test #{desc => "await continue (connect)", - cmd => fun(#{tester := Tester, local_sa := LSA} = State) -> + cmd => fun(#{domain := local = Domain, + tester := Tester} = State) -> + case ?SEV_AWAIT_CONTINUE(Tester, tester, connect) of + {ok, ServerPath} -> + ?SEV_IPRINT("Server Path: " + "~n ~s", [ServerPath]), + ServerSA = #{family => Domain, + path => ServerPath}, + {ok, State#{server_sa => ServerSA}}; + {error, _} = ERROR -> + ERROR + end; + (#{tester := Tester, local_sa := LSA} = State) -> case ?SEV_AWAIT_CONTINUE(Tester, tester, connect) of {ok, Port} -> ServerSA = LSA#{port => Port}, @@ -5729,7 +6241,18 @@ sc_lc_receive_response_tcp(InitState) -> end end}, #{desc => "close socket", - cmd => fun(#{sock := Sock} = State) -> + cmd => fun(#{domain := local, + sock := Sock, + local_sa := #{path := Path}} = State) -> + sock_close(Sock), + State1 = + unlink_path(Path, + fun() -> + maps:remove(local_sa, State) + end, + fun() -> State end), + {ok, maps:remove(sock, State1)}; + (#{sock := Sock} = State) -> sock_close(Sock), {ok, maps:remove(sock, State)} end}, @@ -5776,8 +6299,8 @@ sc_lc_receive_response_tcp(InitState) -> #{desc => "await acceptor ready (init)", cmd => fun(#{acceptor := Pid} = State) -> case ?SEV_AWAIT_READY(Pid, acceptor, init) of - {ok, Port} -> - {ok, State#{lport => Port}}; + {ok, PortOrPath} -> + {ok, State#{server_info => PortOrPath}}; {error, _} = ERROR -> ERROR end @@ -5834,8 +6357,8 @@ sc_lc_receive_response_tcp(InitState) -> end}, ?SEV_SLEEP(?SECS(1)), #{desc => "order client to continue (connect)", - cmd => fun(#{client := Pid, lport := Port} = _State) -> - ?SEV_ANNOUNCE_CONTINUE(Pid, connect, Port), + cmd => fun(#{client := Pid, server_info := Info} = _State) -> + ?SEV_ANNOUNCE_CONTINUE(Pid, connect, Info), ok end}, #{desc => "await acceptor ready (accept)", @@ -6002,12 +6525,11 @@ sc_lc_recvfrom_response_udp4(suite) -> sc_lc_recvfrom_response_udp4(doc) -> []; sc_lc_recvfrom_response_udp4(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), tc_try(sc_lc_recvfrom_response_udp4, fun() -> - ?TT(?SECS(30)), Recv = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end, InitState = #{domain => inet, - type => dgram, protocol => udp, recv => Recv}, ok = sc_lc_receive_response_udp(InitState) @@ -6024,13 +6546,36 @@ sc_lc_recvfrom_response_udp6(suite) -> sc_lc_recvfrom_response_udp6(doc) -> []; sc_lc_recvfrom_response_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), tc_try(sc_lc_recvfrom_response_udp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(30)), Recv = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end, - InitState = #{domain => inet6, - recv => Recv}, + InitState = #{domain => inet6, + protocol => udp, + recv => Recv}, + ok = sc_lc_receive_response_udp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the recv function. +%% Socket is Unix Domainm (dgram) socket. + +sc_lc_recvfrom_response_udpL(suite) -> + []; +sc_lc_recvfrom_response_udpL(doc) -> + []; +sc_lc_recvfrom_response_udpL(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(sc_lc_recvfrom_response_udpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + Recv = fun(Sock, To) -> socket:recvfrom(Sock, [], To) end, + InitState = #{domain => local, + protocol => default, + recv => Recv}, ok = sc_lc_receive_response_udp(InitState) end). @@ -6055,20 +6600,25 @@ sc_lc_receive_response_udp(InitState) -> %% *** Init part *** #{desc => "local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "open socket", - cmd => fun(#{domain := Domain} = State) -> - Sock = sock_open(Domain, dgram, udp), + cmd => fun(#{domain := Domain, protocol := Proto} = State) -> + Sock = sock_open(Domain, dgram, Proto), SA = sock_sockname(Sock), {ok, State#{sock => Sock, sa => SA}} end}, #{desc => "bind socket", cmd => fun(#{sock := Sock, local_sa := LSA}) -> - sock_bind(Sock, LSA), - ok + case socket:bind(Sock, LSA) of + {ok, _Port} -> + ?SEV_IPRINT("src bound"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("src bind failed: ~p", [Reason]), + ERROR + end end}, #{desc => "announce ready (init)", cmd => fun(#{tester := Tester, sock := Sock}) -> @@ -6107,7 +6657,18 @@ sc_lc_receive_response_udp(InitState) -> ok = ?SEV_AWAIT_CONTINUE(Tester, tester, close) end}, #{desc => "close socket", - cmd => fun(#{sock := Sock} = State) -> + cmd => fun(#{domain := local, + sock := Sock, + local_sa := #{path := Path}} = State) -> + ok = socket:close(Sock), + State1 = + unlink_path(Path, + fun() -> + maps:remove(local_sa, State) + end, + fun() -> State end), + {ok, maps:remove(sock, State1)}; + (#{sock := Sock} = State) -> case socket:close(Sock) of ok -> {ok, maps:remove(sock, State)}; @@ -6400,9 +6961,9 @@ sc_lc_receive_response_udp(InitState) -> i("start 'tester' evaluator"), TesterInitState = #{prim_server => PrimServer#ev.pid, - sec_server1 => SecServer1#ev.pid, - sec_server2 => SecServer2#ev.pid, - sec_server3 => SecServer3#ev.pid}, + sec_server1 => SecServer1#ev.pid, + sec_server2 => SecServer2#ev.pid, + sec_server3 => SecServer3#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator"), @@ -6422,12 +6983,11 @@ sc_lc_recvmsg_response_tcp4(suite) -> sc_lc_recvmsg_response_tcp4(doc) -> []; sc_lc_recvmsg_response_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(sc_lc_recvmsg_response_tcp4, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => inet, - type => stream, protocol => tcp, recv => Recv}, ok = sc_lc_receive_response_tcp(InitState) @@ -6444,13 +7004,12 @@ sc_lc_recvmsg_response_tcp6(suite) -> sc_lc_recvmsg_response_tcp6(doc) -> []; sc_lc_recvmsg_response_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(sc_recvmsg_response_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => inet6, - type => stream, protocol => tcp, recv => Recv}, ok = sc_lc_receive_response_tcp(InitState) @@ -6460,6 +7019,28 @@ sc_lc_recvmsg_response_tcp6(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% locally closed while the process is calling the recvmsg function. +%% Socket is Unix Domain (stream) socket. + +sc_lc_recvmsg_response_tcpL(suite) -> + []; +sc_lc_recvmsg_response_tcpL(doc) -> + []; +sc_lc_recvmsg_response_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(sc_recvmsg_response_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + Recv = fun(Sock) -> socket:recvmsg(Sock) end, + InitState = #{domain => local, + protocol => default, + recv => Recv}, + ok = sc_lc_receive_response_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the recvmsg function. %% Socket is IPv4. sc_lc_recvmsg_response_udp4(suite) -> @@ -6471,8 +7052,9 @@ sc_lc_recvmsg_response_udp4(_Config) when is_list(_Config) -> fun() -> ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, - InitState = #{domain => inet, - recv => Recv}, + InitState = #{domain => inet, + protocol => udp, + recv => Recv}, ok = sc_lc_receive_response_udp(InitState) end). @@ -6492,8 +7074,32 @@ sc_lc_recvmsg_response_udp6(_Config) when is_list(_Config) -> fun() -> ?TT(?SECS(10)), Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, - InitState = #{domain => inet6, - recv => Recv}, + InitState = #{domain => inet6, + protocol => udp, + recv => Recv}, + ok = sc_lc_receive_response_udp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the recvmsg function. +%% Socket is Unix Domain (dgram) socket. + +sc_lc_recvmsg_response_udpL(suite) -> + []; +sc_lc_recvmsg_response_udpL(doc) -> + []; +sc_lc_recvmsg_response_udpL(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(sc_recvmsg_response_udpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + Recv = fun(Sock, To) -> socket:recvmsg(Sock, To) end, + InitState = #{domain => local, + protocol => default, + recv => Recv}, ok = sc_lc_receive_response_udp(InitState) end). @@ -6511,11 +7117,10 @@ sc_lc_acceptor_response_tcp4(suite) -> sc_lc_acceptor_response_tcp4(doc) -> []; sc_lc_acceptor_response_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(sc_lc_acceptor_response_tcp4, fun() -> - ?TT(?SECS(10)), InitState = #{domain => inet, - type => stream, protocol => tcp}, ok = sc_lc_acceptor_response_tcp(InitState) end). @@ -6533,18 +7138,39 @@ sc_lc_acceptor_response_tcp6(suite) -> sc_lc_acceptor_response_tcp6(doc) -> []; sc_lc_acceptor_response_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), tc_try(sc_lc_acceptor_response_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(10)), - InitState = #{domain => inet, - type => stream, + InitState = #{domain => inet6, protocol => tcp}, ok = sc_lc_acceptor_response_tcp(InitState) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% locally closed while the process is calling the accept function. +%% We test what happens with a non-controlling_process also, since we +%% git the setup anyway. +%% Socket is Unix Domain (stream) socket. + +sc_lc_acceptor_response_tcpL(suite) -> + []; +sc_lc_acceptor_response_tcpL(doc) -> + []; +sc_lc_acceptor_response_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(sc_lc_acceptor_response_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + InitState = #{domain => local, + protocol => default}, + ok = sc_lc_acceptor_response_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sc_lc_acceptor_response_tcp(InitState) -> PrimAcceptorSeq = @@ -6564,15 +7190,13 @@ sc_lc_acceptor_response_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{lsa => LSA}} end}, #{desc => "create (listen) socket", cmd => fun(#{domain := Domain, - type := Type, protocol := Proto} = State) -> - case socket:open(Domain, Type, Proto) of + case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> @@ -6609,8 +7233,8 @@ sc_lc_acceptor_response_tcp(InitState) -> end end}, #{desc => "await connection", - cmd => fun(#{sock := Sock, timeout := Timeout} = _State) -> - case socket:accept(Sock, Timeout) of + cmd => fun(#{sock := LSock, timeout := Timeout} = _State) -> + case socket:accept(LSock, Timeout) of {error, timeout} -> ok; {ok, Sock} -> @@ -6631,7 +7255,25 @@ sc_lc_acceptor_response_tcp(InitState) -> ok = ?SEV_AWAIT_CONTINUE(Tester, tester, close) end}, #{desc => "close socket", - cmd => fun(#{sock := Sock} = State) -> + cmd => fun(#{domain := local, + sock := Sock, + lsa := #{path := Path}} = State) -> + case socket:close(Sock) of + ok -> + State1 = + unlink_path(Path, + fun() -> + maps:remove(lsa, State) + end, + fun() -> + State + end), + {ok, maps:remove(sock, State1)}; + {error, _} = ERROR -> + unlink_path(Path), + ERROR + end; + (#{sock := Sock} = State) -> case socket:close(Sock) of ok -> {ok, maps:remove(sock, State)}; @@ -6946,12 +7588,11 @@ sc_rc_recv_response_tcp4(suite) -> sc_rc_recv_response_tcp4(doc) -> []; sc_rc_recv_response_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), tc_try(sc_rc_recv_response_tcp4, fun() -> - ?TT(?SECS(30)), Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => inet, - type => stream, protocol => tcp, recv => Recv}, ok = sc_rc_receive_response_tcp(InitState) @@ -6968,13 +7609,12 @@ sc_rc_recv_response_tcp6(suite) -> sc_rc_recv_response_tcp6(doc) -> []; sc_rc_recv_response_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), tc_try(sc_rc_recv_response_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock) -> socket:recv(Sock) end, InitState = #{domain => inet6, - type => stream, protocol => tcp, recv => Recv}, ok = sc_rc_receive_response_tcp(InitState) @@ -6982,6 +7622,28 @@ sc_rc_recv_response_tcp6(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% remotely closed while the process is calling the recv function. +%% Socket is Unix Domain (stream) socket. + +sc_rc_recv_response_tcpL(suite) -> + []; +sc_rc_recv_response_tcpL(doc) -> + []; +sc_rc_recv_response_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(sc_rc_recv_response_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + Recv = fun(Sock) -> socket:recv(Sock) end, + InitState = #{domain => local, + protocol => default, + recv => Recv}, + ok = sc_rc_receive_response_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sc_rc_receive_response_tcp(InitState) -> %% Each connection are handled by handler processes. @@ -7004,13 +7666,12 @@ sc_rc_receive_response_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", - cmd => fun(#{domain := Domain} = State) -> - case socket:open(Domain, stream, tcp) of + cmd => fun(#{domain := Domain, protocol := Proto} = State) -> + case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> @@ -7018,7 +7679,17 @@ sc_rc_receive_response_tcp(InitState) -> end end}, #{desc => "bind to local address", - cmd => fun(#{lsock := LSock, local_sa := LSA} = State) -> + cmd => fun(#{domain := local, + lsock := LSock, + lsa := LSA} = _State) -> + case socket:bind(LSock, LSA) of + {ok, _Port} -> + ok; % We do not care about the port for local + {error, _} = ERROR -> + ERROR + end; + (#{lsock := LSock, + local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; @@ -7031,7 +7702,15 @@ sc_rc_receive_response_tcp(InitState) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", - cmd => fun(#{tester := Tester, local_sa := LSA, lport := Port}) -> + cmd => fun(#{domain := local, + tester := Tester, + local_sa := LSA}) -> + %% Actually we only need to send the path, + %% but to keep it simple, we send the "same" + %% as for non-local. + ?SEV_ANNOUNCE_READY(Tester, init, LSA), + ok; + (#{tester := Tester, local_sa := LSA, lport := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok @@ -7213,7 +7892,25 @@ sc_rc_receive_response_tcp(InitState) -> {ok, State2} end}, #{desc => "close listen socket", - cmd => fun(#{lsock := LSock} = State) -> + cmd => fun(#{domain := local, + lsock := LSock, + lsa := #{path := Path}} = State) -> + case socket:close(LSock) of + ok -> + State1 = + unlink_path(Path, + fun() -> + maps:remove(lsa, State) + end, + fun() -> + State + end), + {ok, maps:remove(lsock, State1)}; + {error, _} = ERROR -> + unlink_path(Path), + ERROR + end; + (#{lsock := LSock} = State) -> case socket:close(LSock) of ok -> {ok, maps:remove(lsock, State)}; @@ -7270,8 +7967,10 @@ sc_rc_receive_response_tcp(InitState) -> ok end}, #{desc => "order remote client to start", - cmd => fun(#{rclient := Client, server_sa := ServerSA}) -> - ?SEV_ANNOUNCE_START(Client, ServerSA), + cmd => fun(#{rclient := Client, + server_sa := ServerSA, + protocol := Proto}) -> + ?SEV_ANNOUNCE_START(Client, {ServerSA, Proto}), ok end}, #{desc => "await remote client ready", @@ -7672,16 +8371,16 @@ sc_rc_tcp_client_start(Node) -> sc_rc_tcp_client(Parent) -> sc_rc_tcp_client_init(Parent), - ServerSA = sc_rc_tcp_client_await_start(Parent), + {ServerSA, Proto} = sc_rc_tcp_client_await_start(Parent), Domain = maps:get(family, ServerSA), - Sock = sc_rc_tcp_client_create(Domain), - sc_rc_tcp_client_bind(Sock, Domain), + Sock = sc_rc_tcp_client_create(Domain, Proto), + Path = sc_rc_tcp_client_bind(Sock, Domain), sc_rc_tcp_client_announce_ready(Parent, init), sc_rc_tcp_client_await_continue(Parent, connect), sc_rc_tcp_client_connect(Sock, ServerSA), sc_rc_tcp_client_announce_ready(Parent, connect), sc_rc_tcp_client_await_continue(Parent, close), - sc_rc_tcp_client_close(Sock), + sc_rc_tcp_client_close(Sock, Path), sc_rc_tcp_client_announce_ready(Parent, close), Reason = sc_rc_tcp_client_await_terminate(Parent), ?SEV_IPRINT("terminate"), @@ -7697,9 +8396,9 @@ sc_rc_tcp_client_await_start(Parent) -> i("sc_rc_tcp_client_await_start -> entry"), ?SEV_AWAIT_START(Parent). -sc_rc_tcp_client_create(Domain) -> +sc_rc_tcp_client_create(Domain, Proto) -> i("sc_rc_tcp_client_create -> entry"), - case socket:open(Domain, stream, tcp) of + case socket:open(Domain, stream, Proto) of {ok, Sock} -> case socket:getopt(Sock, otp, fd) of {ok, FD} -> @@ -7714,12 +8413,17 @@ sc_rc_tcp_client_create(Domain) -> sc_rc_tcp_client_bind(Sock, Domain) -> i("sc_rc_tcp_client_bind -> entry"), - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, - addr => LAddr}, + LSA = which_local_socket_addr(Domain), case socket:bind(Sock, LSA) of {ok, _} -> - ok; + case socket:sockname(Sock) of + {ok, #{family := local, path := Path}} -> + Path; + {ok, _} -> + undefined; + {error, Reason1} -> + exit({sockname, Reason1}) + end; {error, Reason} -> exit({bind, Reason}) end. @@ -7741,13 +8445,17 @@ sc_rc_tcp_client_connect(Sock, ServerSA) -> exit({connect, Reason}) end. -sc_rc_tcp_client_close(Sock) -> +sc_rc_tcp_client_close(Sock, Path) -> i("sc_rc_tcp_client_close -> entry"), case socket:close(Sock) of ok -> + unlink_path(Path), ok; {error, Reason} -> - exit({close, Reason}) + ?SEV_EPRINT("failed closing: " + "~n Reason: ~p", [Reason]), + unlink_path(Path), + {error, {close, Reason}} end. sc_rc_tcp_client_await_terminate(Parent) -> @@ -7827,12 +8535,11 @@ sc_rc_recvmsg_response_tcp4(suite) -> sc_rc_recvmsg_response_tcp4(doc) -> []; sc_rc_recvmsg_response_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), tc_try(sc_rc_recvmsg_response_tcp4, fun() -> - ?TT(?SECS(30)), Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => inet, - type => stream, protocol => tcp, recv => Recv}, ok = sc_rc_receive_response_tcp(InitState) @@ -7849,13 +8556,12 @@ sc_rc_recvmsg_response_tcp6(suite) -> sc_rc_recvmsg_response_tcp6(doc) -> []; sc_rc_recvmsg_response_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), tc_try(sc_rc_recvmsg_response_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(10)), Recv = fun(Sock) -> socket:recvmsg(Sock) end, InitState = #{domain => inet6, - type => stream, protocol => tcp, recv => Recv}, ok = sc_rc_receive_response_tcp(InitState) @@ -7863,6 +8569,28 @@ sc_rc_recvmsg_response_tcp6(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% remotely closed while the process is calling the recvmsg function. +%% Socket is Unix Domain (stream) socket. + +sc_rc_recvmsg_response_tcpL(suite) -> + []; +sc_rc_recvmsg_response_tcpL(doc) -> + []; +sc_rc_recvmsg_response_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(sc_rc_recvmsg_response_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + Recv = fun(Sock) -> socket:recvmsg(Sock) end, + InitState = #{domain => local, + protocol => default, + recv => Recv}, + ok = sc_rc_receive_response_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test what happens when a socket is %% remotely closed while the process is calling the recv function. %% The remote client sends data, then shutdown(write) and then the @@ -7872,6 +8600,7 @@ sc_rc_recvmsg_response_tcp6(_Config) when is_list(_Config) -> %% To minimize the chance of "weirdness", we should really have test cases %% where the two sides of the connection is on different machines. But for %% now, we will make do with different VMs on the same host. +%% This would of course not work for Unix Domain sockets. %% sc_rs_recv_send_shutdown_receive_tcp4(suite) -> @@ -7879,9 +8608,9 @@ sc_rs_recv_send_shutdown_receive_tcp4(suite) -> sc_rs_recv_send_shutdown_receive_tcp4(doc) -> []; sc_rs_recv_send_shutdown_receive_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), tc_try(sc_rs_recv_send_shutdown_receive_tcp4, fun() -> - ?TT(?SECS(30)), MsgData = ?DATA, Recv = fun(Sock) -> socket:recv(Sock) @@ -7890,6 +8619,7 @@ sc_rs_recv_send_shutdown_receive_tcp4(_Config) when is_list(_Config) -> socket:send(Sock, Data) end, InitState = #{domain => inet, + proto => tcp, recv => Recv, send => Send, data => MsgData}, @@ -7921,6 +8651,39 @@ sc_rs_recv_send_shutdown_receive_tcp6(_Config) when is_list(_Config) -> socket:send(Sock, Data) end, InitState = #{domain => inet6, + proto => tcp, + recv => Recv, + send => Send, + data => MsgData}, + ok = sc_rs_send_shutdown_receive_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% remotely closed while the process is calling the recv function. +%% The remote client sends data, then shutdown(write) and then the +%% reader attempts a recv. +%% Socket is Unix Domain (stream) socket. + +sc_rs_recv_send_shutdown_receive_tcpL(suite) -> + []; +sc_rs_recv_send_shutdown_receive_tcpL(doc) -> + []; +sc_rs_recv_send_shutdown_receive_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(sc_rs_recv_send_shutdown_receive_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + MsgData = ?DATA, + Recv = fun(Sock) -> + socket:recv(Sock) + end, + Send = fun(Sock, Data) -> + socket:send(Sock, Data) + end, + InitState = #{domain => local, + proto => default, recv => Recv, send => Send, data => MsgData}, @@ -7952,13 +8715,12 @@ sc_rs_send_shutdown_receive_tcp(InitState) -> #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> i("get local address for ~p", [Domain]), - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", - cmd => fun(#{domain := Domain} = State) -> - case socket:open(Domain, stream, tcp) of + cmd => fun(#{domain := Domain, proto := Proto} = State) -> + case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> @@ -7966,9 +8728,19 @@ sc_rs_send_shutdown_receive_tcp(InitState) -> end end}, #{desc => "bind to local address", - cmd => fun(#{lsock := LSock, local_sa := LSA} = State) -> + cmd => fun(#{domain := local, + lsock := LSock, + local_sa := LSA} = _State) -> + case socket:bind(LSock, LSA) of + {ok, _Port} -> + ok; % We do not care about the port for local + {error, _} = ERROR -> + ERROR + end; + (#{lsock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> + ?SEV_IPRINT("bound to port: ~w", [Port]), {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR @@ -7979,7 +8751,11 @@ sc_rs_send_shutdown_receive_tcp(InitState) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", - cmd => fun(#{tester := Tester, local_sa := LSA, lport := Port}) -> + cmd => fun(#{domain := local, + tester := Tester, local_sa := LSA}) -> + ?SEV_ANNOUNCE_READY(Tester, init, LSA), + ok; + (#{tester := Tester, local_sa := LSA, lport := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok @@ -8090,7 +8866,18 @@ sc_rs_send_shutdown_receive_tcp(InitState) -> {ok, State2} end}, #{desc => "close listen socket", - cmd => fun(#{lsock := LSock} = State) -> + cmd => fun(#{domain := local, + lsock := Sock, + local_sa := #{path := Path}} = State) -> + socket:close(Sock), + State1 = + unlink_path(Path, + fun() -> + maps:remove(local_sa, State) + end, + fun() -> State end), + {ok, maps:remove(lsock, State1)}; + (#{lsock := LSock} = State) -> case socket:close(LSock) of ok -> {ok, maps:remove(lsock, State)}; @@ -8148,8 +8935,10 @@ sc_rs_send_shutdown_receive_tcp(InitState) -> ok end}, #{desc => "order remote client to start", - cmd => fun(#{rclient := Client, server_sa := ServerSA}) -> - ?SEV_ANNOUNCE_START(Client, ServerSA), + cmd => fun(#{rclient := Client, + proto := Proto, + server_sa := ServerSA}) -> + ?SEV_ANNOUNCE_START(Client, {ServerSA, Proto}), ok end}, #{desc => "await remote client ready", @@ -8479,12 +9268,14 @@ sc_rs_send_shutdown_receive_tcp(InitState) -> i("start server evaluator"), ServerInitState = #{domain => maps:get(domain, InitState), + proto => maps:get(proto, InitState), recv => maps:get(recv, InitState)}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator"), ClientInitState = #{host => local_host(), domain => maps:get(domain, InitState), + proto => maps:get(proto, InitState), send => maps:get(send, InitState)}, Client = ?SEV_START("client", ClientSeq, ClientInitState), @@ -8506,10 +9297,10 @@ sc_rs_tcp_client_start(Node, Send) -> sc_rs_tcp_client(Parent, Send) -> sc_rs_tcp_client_init(Parent), - ServerSA = sc_rs_tcp_client_await_start(Parent), + {ServerSA, Proto} = sc_rs_tcp_client_await_start(Parent), Domain = maps:get(family, ServerSA), - Sock = sc_rs_tcp_client_create(Domain), - sc_rs_tcp_client_bind(Sock, Domain), + Sock = sc_rs_tcp_client_create(Domain, Proto), + Path = sc_rs_tcp_client_bind(Sock, Domain), sc_rs_tcp_client_announce_ready(Parent, init), sc_rs_tcp_client_await_continue(Parent, connect), sc_rs_tcp_client_connect(Sock, ServerSA), @@ -8521,7 +9312,7 @@ sc_rs_tcp_client(Parent, Send) -> sc_rs_tcp_client_shutdown(Sock), sc_rs_tcp_client_announce_ready(Parent, shutdown), sc_rs_tcp_client_await_continue(Parent, close), - sc_rs_tcp_client_close(Sock), + sc_rs_tcp_client_close(Sock, Path), sc_rs_tcp_client_announce_ready(Parent, close), Reason = sc_rs_tcp_client_await_terminate(Parent), ?SEV_IPRINT("terminate"), @@ -8537,9 +9328,9 @@ sc_rs_tcp_client_await_start(Parent) -> i("sc_rs_tcp_client_await_start -> entry"), ?SEV_AWAIT_START(Parent). -sc_rs_tcp_client_create(Domain) -> +sc_rs_tcp_client_create(Domain, Proto) -> i("sc_rs_tcp_client_create -> entry"), - case socket:open(Domain, stream, tcp) of + case socket:open(Domain, stream, Proto) of {ok, Sock} -> Sock; {error, Reason} -> @@ -8548,12 +9339,17 @@ sc_rs_tcp_client_create(Domain) -> sc_rs_tcp_client_bind(Sock, Domain) -> i("sc_rs_tcp_client_bind -> entry"), - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, - addr => LAddr}, + LSA = which_local_socket_addr(Domain), case socket:bind(Sock, LSA) of {ok, _} -> - ok; + case socket:sockname(Sock) of + {ok, #{family := local, path := Path}} -> + Path; + {ok, _} -> + undefined; + {error, Reason1} -> + exit({sockname, Reason1}) + end; {error, Reason} -> exit({bind, Reason}) end. @@ -8600,13 +9396,17 @@ sc_rs_tcp_client_shutdown(Sock) -> exit({shutdown, Reason}) end. -sc_rs_tcp_client_close(Sock) -> +sc_rs_tcp_client_close(Sock, Path) -> i("sc_rs_tcp_client_close -> entry"), case socket:close(Sock) of ok -> + unlink_path(Path), ok; {error, Reason} -> - exit({close, Reason}) + ?SEV_EPRINT("failed closing: " + "~n Reason: ~p", [Reason]), + unlink_path(Path), + {error, {close, Reason}} end. sc_rs_tcp_client_await_terminate(Parent) -> @@ -8711,12 +9511,11 @@ sc_rs_recvmsg_send_shutdown_receive_tcp4(_Config) when is_list(_Config) -> MsgHdr = #{iov => [Data]}, socket:sendmsg(Sock, MsgHdr) end, - InitState = #{domain => inet, - type => stream, - protocol => tcp, - recv => Recv, - send => Send, - data => MsgData}, + InitState = #{domain => inet, + proto => tcp, + recv => Recv, + send => Send, + data => MsgData}, ok = sc_rs_send_shutdown_receive_tcp(InitState) end). @@ -8748,15 +9547,62 @@ sc_rs_recvmsg_send_shutdown_receive_tcp6(_Config) when is_list(_Config) -> end end, Send = fun(Sock, Data) when is_binary(Data) -> - MsgHdr = #{iov => [Data]}, - socket:sendmsg(Sock, MsgHdr) + MsgHdr = #{iov => [Data]}, + socket:sendmsg(Sock, MsgHdr) end, - InitState = #{domain => inet6, - type => stream, - protocol => tcp, - recv => Recv, - send => Send, - data => MsgData}, + InitState = #{domain => inet6, + proto => tcp, + recv => Recv, + send => Send, + data => MsgData}, + ok = sc_rs_send_shutdown_receive_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test what happens when a socket is +%% remotely closed while the process is calling the recvmsg function. +%% The remote client sends data, then shutdown(write) and then the +%% reader attempts a recv. +%% Socket is UNix Domain (stream) socket. + +sc_rs_recvmsg_send_shutdown_receive_tcpL(suite) -> + []; +sc_rs_recvmsg_send_shutdown_receive_tcpL(doc) -> + []; +sc_rs_recvmsg_send_shutdown_receive_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(sc_rs_recvmsg_send_shutdown_receive_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + {ok, CWD} = file:get_cwd(), + ?SEV_IPRINT("CWD: ~s", [CWD]), + MsgData = ?DATA, + Recv = fun(Sock) -> + case socket:recvmsg(Sock) of + %% On some platforms, the address + %% is *not* provided (e.g. FreeBSD) + {ok, #{addr := undefined, + iov := [Data]}} -> + {ok, Data}; + %% On some platforms, the address + %% *is* provided (e.g. linux) + {ok, #{addr := #{family := local}, + iov := [Data]}} -> + {ok, Data}; + {error, _} = ERROR -> + ERROR + end + end, + Send = fun(Sock, Data) when is_binary(Data) -> + MsgHdr = #{iov => [Data]}, + socket:sendmsg(Sock, MsgHdr) + end, + InitState = #{domain => local, + proto => default, + recv => Recv, + send => Send, + data => MsgData}, ok = sc_rs_send_shutdown_receive_tcp(InitState) end). @@ -8773,10 +9619,11 @@ traffic_send_and_recv_chunks_tcp4(suite) -> traffic_send_and_recv_chunks_tcp4(doc) -> []; traffic_send_and_recv_chunks_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), tc_try(traffic_send_and_recv_chunks_tcp4, fun() -> - ?TT(?SECS(30)), - InitState = #{domain => inet}, + InitState = #{domain => inet, + proto => tcp}, ok = traffic_send_and_recv_chunks_tcp(InitState) end). @@ -8794,11 +9641,34 @@ traffic_send_and_recv_chunks_tcp6(suite) -> traffic_send_and_recv_chunks_tcp6(doc) -> []; traffic_send_and_recv_chunks_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), tc_try(traffic_send_and_recv_chunks_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(30)), - InitState = #{domain => inet6}, + InitState = #{domain => inet6, + proto => tcp}, + ok = traffic_send_and_recv_chunks_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the send and recv functions +%% behave as expected when sending and/or reading chunks. +%% First send data in one "big" chunk, and read it in "small" chunks. +%% Second, send in a bunch of "small" chunks, and read in one "big" chunk. +%% Socket is UNix Domain (Stream) socket. + +traffic_send_and_recv_chunks_tcpL(suite) -> + []; +traffic_send_and_recv_chunks_tcpL(doc) -> + []; +traffic_send_and_recv_chunks_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(traffic_send_and_recv_chunks_tcp6, + fun() -> has_support_unix_domain_socket() end, + fun() -> + InitState = #{domain => local, + proto => default}, ok = traffic_send_and_recv_chunks_tcp(InitState) end). @@ -8823,13 +9693,12 @@ traffic_send_and_recv_chunks_tcp(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", - cmd => fun(#{domain := Domain} = State) -> - case socket:open(Domain, stream, tcp) of + cmd => fun(#{domain := Domain, proto := Proto} = State) -> + case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> @@ -8837,7 +9706,17 @@ traffic_send_and_recv_chunks_tcp(InitState) -> end end}, #{desc => "bind to local address", - cmd => fun(#{lsock := LSock, local_sa := LSA} = State) -> + cmd => fun(#{domain := local, + lsock := LSock, + local_sa := LSA} = _State) -> + case socket:bind(LSock, LSA) of + {ok, _Port} -> + ok; % We do not care about the port for local + {error, _} = ERROR -> + ERROR + end; + (#{lsock := LSock, + local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> {ok, State#{lport => Port}}; @@ -8850,7 +9729,14 @@ traffic_send_and_recv_chunks_tcp(InitState) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", - cmd => fun(#{tester := Tester, local_sa := LSA, lport := Port}) -> + cmd => fun(#{domain := local, + tester := Tester, + local_sa := LSA}) -> + ?SEV_ANNOUNCE_READY(Tester, init, LSA), + ok; + (#{tester := Tester, + local_sa := LSA, + lport := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok @@ -9045,9 +9931,20 @@ traffic_send_and_recv_chunks_tcp(InitState) -> {ok, maps:remove(csock, State)} end}, #{desc => "close listen socket", - cmd => fun(#{lsock := Sock} = State) -> + cmd => fun(#{domain := local, + lsock := Sock, + local_sa := #{path := Path}} = State) -> + ok = socket:close(Sock), + State1 = + unlink_path(Path, + fun() -> + maps:remove(local_sa, State) + end, + fun() -> State end), + {ok, maps:remove(lsock, State1)}; + (#{lsock := Sock} = State) -> (catch socket:close(Sock)), - {ok, maps:remove(lsock, State)} + {ok, maps:remove(lsock, State)} end}, %% *** We are done *** @@ -9098,8 +9995,10 @@ traffic_send_and_recv_chunks_tcp(InitState) -> ok end}, #{desc => "order remote client to start", - cmd => fun(#{rclient := Client, server_sa := ServerSA}) -> - ?SEV_ANNOUNCE_START(Client, ServerSA), + cmd => fun(#{rclient := Client, + server_sa := ServerSA, + proto := Proto}) -> + ?SEV_ANNOUNCE_START(Client, {ServerSA, Proto}), ok end}, #{desc => "await remote client ready", @@ -9654,14 +10553,14 @@ traffic_snr_tcp_client_start(Node) -> erlang:spawn(Node, Fun). traffic_snr_tcp_client(Parent) -> - {Sock, ServerSA} = traffic_snr_tcp_client_init(Parent), + {Sock, ServerSA, Path} = traffic_snr_tcp_client_init(Parent), traffic_snr_tcp_client_announce_ready(Parent, init), traffic_snr_tcp_client_await_continue(Parent, connect), traffic_snr_tcp_client_connect(Sock, ServerSA), traffic_snr_tcp_client_announce_ready(Parent, connect), traffic_snr_tcp_client_send_loop(Parent, Sock), Reason = traffic_snr_tcp_client_await_terminate(Parent), - traffic_snr_tcp_client_close(Sock), + traffic_snr_tcp_client_close(Sock, Path), exit(Reason). @@ -9687,19 +10586,19 @@ traffic_snr_tcp_client_init(Parent) -> put(sname, "rclient"), ?SEV_IPRINT("init"), _MRef = erlang:monitor(process, Parent), - ServerSA = traffic_snr_tcp_client_await_start(Parent), + {ServerSA, Proto} = traffic_snr_tcp_client_await_start(Parent), Domain = maps:get(family, ServerSA), - Sock = traffic_snr_tcp_client_create(Domain), - traffic_snr_tcp_client_bind(Sock, Domain), - {Sock, ServerSA}. + Sock = traffic_snr_tcp_client_create(Domain, Proto), + Path = traffic_snr_tcp_client_bind(Sock, Domain), + {Sock, ServerSA, Path}. traffic_snr_tcp_client_await_start(Parent) -> i("traffic_snr_tcp_client_await_start -> entry"), ?SEV_AWAIT_START(Parent). -traffic_snr_tcp_client_create(Domain) -> +traffic_snr_tcp_client_create(Domain, Proto) -> i("traffic_snr_tcp_client_create -> entry"), - case socket:open(Domain, stream, tcp) of + case socket:open(Domain, stream, Proto) of {ok, Sock} -> Sock; {error, Reason} -> @@ -9708,12 +10607,17 @@ traffic_snr_tcp_client_create(Domain) -> traffic_snr_tcp_client_bind(Sock, Domain) -> i("traffic_snr_tcp_client_bind -> entry"), - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, - addr => LAddr}, + LSA = which_local_socket_addr(Domain), case socket:bind(Sock, LSA) of {ok, _} -> - ok; + case socket:sockname(Sock) of + {ok, #{family := local, path := Path}} -> + Path; + {ok, _} -> + undefined; + {error, Reason1} -> + exit({sockname, Reason1}) + end; {error, Reason} -> exit({bind, Reason}) end. @@ -9734,13 +10638,17 @@ traffic_snr_tcp_client_connect(Sock, ServerSA) -> exit({connect, Reason}) end. -traffic_snr_tcp_client_close(Sock) -> +traffic_snr_tcp_client_close(Sock, Path) -> i("traffic_snr_tcp_client_close -> entry"), case socket:close(Sock) of ok -> + unlink_path(Path), ok; {error, Reason} -> - exit({close, Reason}) + ?SEV_EPRINT("failed closing: " + "~n Reason: ~p", [Reason]), + unlink_path(Path), + {error, {close, Reason}} end. traffic_snr_tcp_client_await_terminate(Parent) -> @@ -9768,12 +10676,13 @@ traffic_ping_pong_small_send_and_recv_tcp4(suite) -> traffic_ping_pong_small_send_and_recv_tcp4(doc) -> []; traffic_ping_pong_small_send_and_recv_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(15)), Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_send_and_recv_tcp4, fun() -> - ?TT(?SECS(15)), InitState = #{domain => inet, + proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) @@ -9795,13 +10704,42 @@ traffic_ping_pong_small_send_and_recv_tcp6(suite) -> traffic_ping_pong_small_send_and_recv_tcp6(doc) -> []; traffic_ping_pong_small_send_and_recv_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(15)), Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_send_and_recv_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(15)), InitState = #{domain => inet6, + proto => tcp, + msg => Msg, + num => Num}, + ok = traffic_ping_pong_send_and_recv_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the send and recv functions +%% by repeatedly sending a meassage between two entities. +%% The same basic test case is used for three different message sizes; +%% small (8 bytes), medium (8K) and large (8M). +%% The message is sent from A to B and then back again. This is +%% repeated a set number of times (more times the small the message). +%% This is the 'small' message test case, for Unix Domain (stream) socket. + +traffic_ping_pong_small_send_and_recv_tcpL(suite) -> + []; +traffic_ping_pong_small_send_and_recv_tcpL(doc) -> + []; +traffic_ping_pong_small_send_and_recv_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(15)), + Msg = l2b(?TPP_SMALL), + Num = ?TPP_SMALL_NUM, + tc_try(traffic_ping_pong_small_send_and_recv_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + InitState = #{domain => local, + proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) @@ -9828,6 +10766,7 @@ traffic_ping_pong_medium_send_and_recv_tcp4(_Config) when is_list(_Config) -> fun() -> ?TT(?SECS(30)), InitState = #{domain => inet, + proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) @@ -9855,6 +10794,36 @@ traffic_ping_pong_medium_send_and_recv_tcp6(_Config) when is_list(_Config) -> fun() -> ?TT(?SECS(30)), InitState = #{domain => inet6, + proto => tcp, + msg => Msg, + num => Num}, + ok = traffic_ping_pong_send_and_recv_tcp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the send and recv functions +%% by repeatedly sending a meassage between two entities. +%% The same basic test case is used for three different message sizes; +%% small (8 bytes), medium (8K) and large (8M). +%% The message is sent from A to B and then back again. This is +%% repeated a set number of times (more times the small the message). +%% This is the 'medium' message test case, for Unix Domain (stream) socket. + +traffic_ping_pong_medium_send_and_recv_tcpL(suite) -> + []; +traffic_ping_pong_medium_send_and_recv_tcpL(doc) -> + []; +traffic_ping_pong_medium_send_and_recv_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + Msg = l2b(?TPP_MEDIUM), + Num = ?TPP_MEDIUM_NUM, + tc_try(traffic_ping_pong_medium_send_and_recv_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + InitState = #{domain => local, + proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) @@ -9876,12 +10845,13 @@ traffic_ping_pong_large_send_and_recv_tcp4(suite) -> traffic_ping_pong_large_send_and_recv_tcp4(doc) -> []; traffic_ping_pong_large_send_and_recv_tcp4(_Config) when is_list(_Config) -> + ?TT(?SECS(45)), Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_send_and_recv_tcp4, fun() -> - ?TT(?SECS(45)), InitState = #{domain => inet, + proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) @@ -9909,11 +10879,53 @@ traffic_ping_pong_large_send_and_recv_tcp6(_Config) when is_list(_Config) -> fun() -> ?TT(?SECS(45)), InitState = #{domain => inet6, + proto => tcp, + msg => Msg, + num => Num}, + ok = traffic_ping_pong_send_and_recv_tcp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the send and recv functions +%% by repeatedly sending a meassage between two entities. +%% The same basic test case is used for three different message sizes; +%% small (8 bytes), medium (8K) and large (8M). +%% The message is sent from A to B and then back again. This is +%% repeated a set number of times (more times the small the message). +%% This is the 'large' message test case, for UNix Domain (stream) socket. + +traffic_ping_pong_large_send_and_recv_tcpL(suite) -> + []; +traffic_ping_pong_large_send_and_recv_tcpL(doc) -> + []; +traffic_ping_pong_large_send_and_recv_tcpL(_Config) when is_list(_Config) -> + ?TT(?SECS(45)), + Msg = l2b(?TPP_LARGE), + Num = ?TPP_LARGE_NUM, + tc_try(traffic_ping_pong_large_send_and_recv_tcpL, + fun() -> + has_support_unix_domain_socket(), + traffic_ping_pong_large_host_cond() + end, + fun() -> + InitState = #{domain => local, + proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_send_and_recv_tcp(InitState) end). +%% This test case is a bit extreme and fails on some hosts +%% (e.g. OpenIndiana Hipster), so exclude them. +traffic_ping_pong_large_host_cond() -> + traffic_ping_pong_large_host_cond(os:type(), os:version()). + +traffic_ping_pong_large_host_cond({unix, sunos}, _) -> + skip("TC does not work on platform"); +traffic_ping_pong_large_host_cond(_, _) -> + ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -9936,6 +10948,7 @@ traffic_ping_pong_small_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) fun() -> ?TT(?SECS(45)), InitState = #{domain => inet, + proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) @@ -9956,12 +10969,43 @@ traffic_ping_pong_small_sendto_and_recvfrom_udp6(suite) -> traffic_ping_pong_small_sendto_and_recvfrom_udp6(doc) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(45)), Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udp6, + fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(45)), - InitState = #{domain => inet, + InitState = #{domain => inet6, + proto => udp, + msg => Msg, + num => Num}, + ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sendto and recvfrom +%% functions by repeatedly sending a meassage between two entities. +%% The same basic test case is used for two different message sizes; +%% small (8 bytes) and medium (8K). +%% The message is sent from A to B and then back again. This is +%% repeated a set number of times (more times the small the message). +%% This is the 'small' message test case, for Unix Domain (dgram) socket. + +traffic_ping_pong_small_sendto_and_recvfrom_udpL(suite) -> + []; +traffic_ping_pong_small_sendto_and_recvfrom_udpL(doc) -> + []; +traffic_ping_pong_small_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) -> + ?TT(?SECS(45)), + Msg = l2b(?TPP_SMALL), + Num = ?TPP_SMALL_NUM, + tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + InitState = #{domain => local, + proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) @@ -9989,6 +11033,7 @@ traffic_ping_pong_medium_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) fun() -> ?TT(?SECS(45)), InitState = #{domain => inet, + proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) @@ -10016,6 +11061,36 @@ traffic_ping_pong_medium_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) fun() -> ?TT(?SECS(45)), InitState = #{domain => inet6, + proto => udp, + msg => Msg, + num => Num}, + ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sendto and recvfrom +%% functions by repeatedly sending a meassage between two entities. +%% The same basic test case is used for two different message sizes; +%% small (8 bytes) and medium (8K). +%% The message is sent from A to B and then back again. This is +%% repeated a set number of times (more times the small the message). +%% This is the 'medium' message test case, for Unix Domain (dgram) socket. + +traffic_ping_pong_medium_sendto_and_recvfrom_udpL(suite) -> + []; +traffic_ping_pong_medium_sendto_and_recvfrom_udpL(doc) -> + []; +traffic_ping_pong_medium_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) -> + Msg = l2b(?TPP_MEDIUM), + Num = ?TPP_MEDIUM_NUM, + tc_try(traffic_ping_pong_medium_sendto_and_recvfrom_udpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + ?TT(?SECS(45)), + InitState = #{domain => local, + proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendto_and_recvfrom_udp(InitState) @@ -10043,6 +11118,7 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) fun() -> ?TT(?SECS(20)), InitState = #{domain => inet, + proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) @@ -10070,6 +11146,35 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) fun() -> ?TT(?SECS(20)), InitState = #{domain => inet6, + proto => tcp, + msg => Msg, + num => Num}, + ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sendmsg and recvmsg functions +%% by repeatedly sending a meassage between two entities. +%% The same basic test case is used for three different message sizes; +%% small (8 bytes), medium (8K) and large (8M). +%% The message is sent from A to B and then back again. This is +%% repeated a set number of times (more times the small the message). +%% This is the 'small' message test case, for Unix Domain (stream) socket. + +traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(suite) -> + []; +traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(doc) -> + []; +traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) -> + Msg = l2b(?TPP_SMALL), + Num = ?TPP_SMALL_NUM, + tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + ?TT(?SECS(20)), + InitState = #{domain => local, + proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) @@ -10096,6 +11201,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) fun() -> ?TT(?SECS(30)), InitState = #{domain => inet, + proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) @@ -10122,7 +11228,36 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(20)), - InitState = #{domain => ine6, + InitState = #{domain => inet6, + proto => tcp, + msg => Msg, + num => Num}, + ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sendmsg and recvmsg functions +%% by repeatedly sending a meassage between two entities. +%% The same basic test case is used for three different message sizes; +%% small (8 bytes), medium (8K) and large (8M). +%% The message is sent from A to B and then back again. This is +%% repeated a set number of times (more times the small the message). +%% This is the 'medium' message test case, for Unix Domain (stream) socket. + +traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(suite) -> + []; +traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(doc) -> + []; +traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) -> + Msg = l2b(?TPP_MEDIUM), + Num = ?TPP_MEDIUM_NUM, + tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + ?TT(?SECS(20)), + InitState = #{domain => local, + proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) @@ -10146,15 +11281,27 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4, + fun() -> traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end, fun() -> ?TT(?SECS(30)), InitState = #{domain => inet, + proto => tcp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) end). +traffic_ping_pong_large_sendmsg_and_recvmsg_cond() -> + traffic_ping_pong_large_sendmsg_and_recvmsg_cond(os:type(), os:version()). + +traffic_ping_pong_large_sendmsg_and_recvmsg_cond({unix, linux}, {M, _, _}) + when (M < 3) -> + skip("TC may not work on this version"); +traffic_ping_pong_large_sendmsg_and_recvmsg_cond(_, _) -> + ok. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendmsg and recvmsg functions %% by repeatedly sending a meassage between two entities. @@ -10172,10 +11319,43 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6, - fun() -> has_support_ipv6() end, + fun() -> + has_support_ipv6(), + traffic_ping_pong_large_sendmsg_and_recvmsg_cond() + end, fun() -> ?TT(?SECS(30)), InitState = #{domain => inet6, + proto => tcp, + msg => Msg, + num => Num}, + ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sendmsg and recvmsg functions +%% by repeatedly sending a meassage between two entities. +%% The same basic test case is used for three different message sizes; +%% small (8 bytes), medium (8K) and large (8M). +%% The message is sent from A to B and then back again. This is +%% repeated a set number of times (more times the small the message). +%% This is the 'large' message test case, for Unix Domain (stream) socket. + +traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(suite) -> + []; +traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(doc) -> + []; +traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) -> + Msg = l2b(?TPP_LARGE), + Num = ?TPP_LARGE_NUM, + tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + ?TT(?SECS(30)), + InitState = #{domain => local, + proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) @@ -10203,6 +11383,7 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) fun() -> ?TT(?SECS(60)), InitState = #{domain => inet, + proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) @@ -10229,7 +11410,36 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(30)), - InitState = #{domain => inet, + InitState = #{domain => inet6, + proto => udp, + msg => Msg, + num => Num}, + ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sendmsg and recvmsg functions +%% by repeatedly sending a meassage between two entities. +%% The same basic test case is used for three different message sizes; +%% small (8 bytes) and medium (8K). +%% The message is sent from A to B and then back again. This is +%% repeated a set number of times (more times the small the message). +%% This is the 'small' message test case, for Unix Domain (dgram) socket. + +traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(suite) -> + []; +traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(doc) -> + []; +traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) -> + Msg = l2b(?TPP_SMALL), + Num = ?TPP_SMALL_NUM, + tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + ?TT(?SECS(30)), + InitState = #{domain => local, + proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) @@ -10256,6 +11466,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) fun() -> ?TT(?SECS(30)), InitState = #{domain => inet, + proto => udp, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) @@ -10282,7 +11493,37 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) fun() -> has_support_ipv6() end, fun() -> ?TT(?SECS(20)), - InitState = #{domain => ine6, + InitState = #{domain => inet6, + proto => udp, + msg => Msg, + num => Num}, + ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to test that the sendmsg and recvmsg +%% functions by repeatedly sending a meassage between two entities. +%% The same basic test case is used for three different message sizes; +%% small (8 bytes) and medium (8K). +%% The message is sent from A to B and then back again. This is +%% repeated a set number of times (more times the small the message). +%% This is the 'medium' message test case, for Unix Domain (dgram) socket. + +traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(suite) -> + []; +traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(doc) -> + []; +traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) -> + Msg = l2b(?TPP_MEDIUM), + Num = ?TPP_MEDIUM_NUM, + tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL, + fun() -> has_support_unix_domain_socket() end, + fun() -> + ?TT(?SECS(20)), + InitState = #{domain => local, + proto => default, msg => Msg, num => Num}, ok = traffic_ping_pong_sendmsg_and_recvmsg_udp(InitState) @@ -10302,14 +11543,26 @@ traffic_ping_pong_send_and_recv_tcp(InitState) -> }, traffic_ping_pong_send_and_receive_tcp(InitState2). -traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) -> - Send = fun(Sock, Data) when is_binary(Data) -> - MsgHdr = #{iov => [Data]}, - socket:sendmsg(Sock, MsgHdr); - (Sock, Data) when is_list(Data) -> %% We assume iovec... - MsgHdr = #{iov => Data}, - socket:sendmsg(Sock, MsgHdr) +traffic_ping_pong_sendmsg_and_recvmsg_tcp(#{domain := local} = InitState) -> + Recv = fun(Sock, Sz) -> + case socket:recvmsg(Sock, Sz, 0) of + %% On some platforms, the address + %% is *not* provided (e.g. FreeBSD) + {ok, #{addr := undefined, + iov := [Data]}} -> + {ok, Data}; + %% On some platforms, the address + %% *is* provided (e.g. linux) + {ok, #{addr := #{family := local}, + iov := [Data]}} -> + {ok, Data}; + {error, _} = ERROR -> + ERROR + end end, + InitState2 = InitState#{recv => Recv}, % Receive function + traffic_ping_pong_sendmsg_and_recvmsg_tcp2(InitState2); +traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) -> Recv = fun(Sock, Sz) -> case socket:recvmsg(Sock, Sz, 0) of {ok, #{addr := undefined, @@ -10319,9 +11572,18 @@ traffic_ping_pong_sendmsg_and_recvmsg_tcp(InitState) -> ERROR end end, - InitState2 = InitState#{send => Send, % Send function - recv => Recv % Receive function - }, + InitState2 = InitState#{recv => Recv}, % Receive function + traffic_ping_pong_sendmsg_and_recvmsg_tcp2(InitState2). + +traffic_ping_pong_sendmsg_and_recvmsg_tcp2(InitState) -> + Send = fun(Sock, Data) when is_binary(Data) -> + MsgHdr = #{iov => [Data]}, + socket:sendmsg(Sock, MsgHdr); + (Sock, Data) when is_list(Data) -> %% We assume iovec... + MsgHdr = #{iov => Data}, + socket:sendmsg(Sock, MsgHdr) + end, + InitState2 = InitState#{send => Send}, % Send function traffic_ping_pong_send_and_receive_tcp(InitState2). @@ -10381,13 +11643,12 @@ traffic_ping_pong_send_and_receive_tcp2(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", - cmd => fun(#{domain := Domain} = State) -> - case socket:open(Domain, stream, tcp) of + cmd => fun(#{domain := Domain, proto := Proto} = State) -> + case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; {error, _} = ERROR -> @@ -10395,9 +11656,19 @@ traffic_ping_pong_send_and_receive_tcp2(InitState) -> end end}, #{desc => "bind to local address", - cmd => fun(#{lsock := LSock, local_sa := LSA} = State) -> + cmd => fun(#{domain := local, + lsock := LSock, + lsa := LSA} = _State) -> + case socket:bind(LSock, LSA) of + {ok, _Port} -> + ok; % We do not care about the port for local + {error, _} = ERROR -> + ERROR + end; + (#{lsock := LSock, local_sa := LSA} = State) -> case socket:bind(LSock, LSA) of {ok, Port} -> + ?SEV_IPRINT("bound to port: ~w", [Port]), {ok, State#{lport => Port}}; {error, _} = ERROR -> ERROR @@ -10412,7 +11683,11 @@ traffic_ping_pong_send_and_receive_tcp2(InitState) -> socket:listen(LSock) end}, #{desc => "announce ready (init)", - cmd => fun(#{tester := Tester, local_sa := LSA, lport := Port}) -> + cmd => fun(#{domain := local, + tester := Tester, local_sa := LSA}) -> + ?SEV_ANNOUNCE_READY(Tester, init, LSA), + ok; + (#{tester := Tester, local_sa := LSA, lport := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok @@ -10523,9 +11798,20 @@ traffic_ping_pong_send_and_receive_tcp2(InitState) -> {ok, State1} end}, #{desc => "close listen socket", - cmd => fun(#{lsock := Sock} = State) -> + cmd => fun(#{domain := local, + lsock := Sock, + local_sa := #{path := Path}} = State) -> + (catch socket:close(Sock)), + State1 = + unlink_path(Path, + fun() -> + maps:remove(local_sa, State) + end, + fun() -> State end), + {ok, maps:remove(lsock, State1)}; + (#{lsock := Sock} = State) -> (catch socket:close(Sock)), - {ok, maps:remove(lsock, State)} + {ok, maps:remove(lsock, State)} end}, %% *** We are done *** @@ -10577,12 +11863,14 @@ traffic_ping_pong_send_and_receive_tcp2(InitState) -> end}, #{desc => "order remote client to start", cmd => fun(#{rclient := RClient, + proto := Proto, server_sa := ServerSA, buf_init := BufInit, send := Send, recv := Recv}) -> ?SEV_ANNOUNCE_START(RClient, - {ServerSA, BufInit, Send, Recv}), + {ServerSA, Proto, BufInit, + Send, Recv}), ok end}, #{desc => "await remote client ready", @@ -10883,6 +12171,7 @@ traffic_ping_pong_send_and_receive_tcp2(InitState) -> i("start server evaluator"), ServerInitState = #{domain => maps:get(domain, InitState), + proto => maps:get(proto, InitState), recv => maps:get(recv, InitState), send => maps:get(send, InitState), buf_init => maps:get(buf_init, InitState)}, @@ -10976,14 +12265,6 @@ tpp_tcp_handler_msg_exchange_loop(Sock, Send, Recv, N, Sent, Received, Start) -> ?SEV_EPRINT("send (~w): ~p", [N, SReason]), exit({send, SReason, N}) end; - %% {error, timeout} -> - %% ?SEV_IPRINT("timeout(~w) - try again", [N]), - %% case Send(Sock, list_to_binary("ping")) of - %% ok -> - %% exit({'ping-send', ok, N}); - %% {error, Reason} -> - %% exit({'ping-send', Reason, N}) - %% end; {error, closed} -> ?SEV_IPRINT("closed - we are done: ~w, ~w, ~w", [N, Sent, Received]), Stop = ?LIB:timestamp(), @@ -11002,10 +12283,10 @@ tpp_tcp_client_create(Node) -> tpp_tcp_client(Parent) -> tpp_tcp_client_init(Parent), - {ServerSA, BufInit, Send, Recv} = tpp_tcp_client_await_start(Parent), + {ServerSA, Proto, BufInit, Send, Recv} = tpp_tcp_client_await_start(Parent), Domain = maps:get(family, ServerSA), - Sock = tpp_tcp_client_sock_open(Domain, BufInit), - tpp_tcp_client_sock_bind(Sock, Domain), + Sock = tpp_tcp_client_sock_open(Domain, Proto, BufInit), + Path = tpp_tcp_client_sock_bind(Sock, Domain), tpp_tcp_client_announce_ready(Parent, init), tpp_tcp_client_await_continue(Parent, connect), tpp_tcp_client_sock_connect(Sock, ServerSA), @@ -11014,7 +12295,7 @@ tpp_tcp_client(Parent) -> Result = tpp_tcp_client_msg_exchange(Sock, Send, Recv, InitMsg, Num), tpp_tcp_client_announce_ready(Parent, send, Result), Reason = tpp_tcp_client_await_terminate(Parent), - tpp_tcp_client_sock_close(Sock), + tpp_tcp_client_sock_close(Sock, Path), ?SEV_IPRINT("terminating"), exit(Reason). @@ -11054,8 +12335,10 @@ tpp_tcp_client_await_terminate(Parent) -> ?SEV_IPRINT("await terminate"), case ?SEV_AWAIT_TERMINATE(Parent, parent) of ok -> - ok; + ?SEV_IPRINT("termination received: normal"), + normal; {error, Reason} -> + ?SEV_IPRINT("termination received: ~w", [Reason]), Reason end. @@ -11099,8 +12382,8 @@ tpp_tcp_client_msg_exchange_loop(Sock, Send, Recv, Data, exit({send, SReason, N}) end. -tpp_tcp_client_sock_open(Domain, BufInit) -> - case socket:open(Domain, stream, tcp) of +tpp_tcp_client_sock_open(Domain, Proto, BufInit) -> + case socket:open(Domain, stream, Proto) of {ok, Sock} -> ok = BufInit(Sock), Sock; @@ -11109,14 +12392,19 @@ tpp_tcp_client_sock_open(Domain, BufInit) -> end. tpp_tcp_client_sock_bind(Sock, Domain) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, - addr => LAddr}, + LSA = which_local_socket_addr(Domain), case socket:bind(Sock, LSA) of {ok, _} -> - ok; - {error, Reason} -> - exit({bind, Reason}) + case socket:sockname(Sock) of + {ok, #{family := local, path := Path}} -> + Path; + {ok, _} -> + undefined; + {error, Reason1} -> + exit({sockname, Reason1}) + end; + {error, Reason2} -> + exit({bind, Reason2}) end. tpp_tcp_client_sock_connect(Sock, ServerSA) -> @@ -11127,14 +12415,20 @@ tpp_tcp_client_sock_connect(Sock, ServerSA) -> exit({connect, Reason}) end. -tpp_tcp_client_sock_close(Sock) -> +tpp_tcp_client_sock_close(Sock, Path) -> case socket:close(Sock) of ok -> + unlink_path(Path), ok; {error, Reason} -> - exit({close, Reason}) + ?SEV_EPRINT("failed closing: " + "~n Reason: ~p", [Reason]), + unlink_path(Path), + {error, {close, Reason}} end. + + -define(TPP_REQUEST, 1). -define(TPP_REPLY, 2). @@ -11300,13 +12594,12 @@ traffic_ping_pong_send_and_receive_udp2(InitState) -> %% *** Init part *** #{desc => "which local address", cmd => fun(#{domain := Domain} = State) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, addr => LAddr}, + LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, #{desc => "create listen socket", - cmd => fun(#{domain := Domain} = State) -> - case socket:open(Domain, dgram, udp) of + cmd => fun(#{domain := Domain, proto := Proto} = State) -> + case socket:open(Domain, dgram, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; {error, _} = ERROR -> @@ -11314,7 +12607,15 @@ traffic_ping_pong_send_and_receive_udp2(InitState) -> end end}, #{desc => "bind to local address", - cmd => fun(#{sock := Sock, local_sa := LSA} = State) -> + cmd => fun(#{domain := local, + sock := Sock, local_sa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _} -> + ok; + {error, _} = ERROR -> + ERROR + end; + (#{sock := Sock, local_sa := LSA} = State) -> case socket:bind(Sock, LSA) of {ok, Port} -> {ok, State#{port => Port}}; @@ -11357,7 +12658,11 @@ traffic_ping_pong_send_and_receive_udp2(InitState) -> end end}, #{desc => "announce ready (init)", - cmd => fun(#{tester := Tester, local_sa := LSA, port := Port}) -> + cmd => fun(#{domain := local, + tester := Tester, local_sa := LSA}) -> + ?SEV_ANNOUNCE_READY(Tester, init, LSA), + ok; + (#{tester := Tester, local_sa := LSA, port := Port}) -> ServerSA = LSA#{port => Port}, ?SEV_ANNOUNCE_READY(Tester, init, ServerSA), ok @@ -11396,6 +12701,19 @@ traffic_ping_pong_send_and_receive_udp2(InitState) -> ERROR end end}, + #{desc => "(maybe) unlink socket", + cmd => fun(#{domain := local, + local_sa := #{path := Path}} = State) -> + unlink_path(Path, + fun() -> + {ok, maps:remove(local_sa, State)} + end, + fun() -> + ok + end); + (_) -> + ok + end}, #{desc => "announce ready (close)", cmd => fun(#{tester := Tester} = _State) -> ?SEV_ANNOUNCE_READY(Tester, close), @@ -11492,11 +12810,13 @@ traffic_ping_pong_send_and_receive_udp2(InitState) -> #{desc => "order remote handler to start", cmd => fun(#{handler := Handler, server_sa := ServerSA, + proto := Proto, buf_init := BufInit, send := Send, recv := Recv}) -> ?SEV_ANNOUNCE_START(Handler, - {ServerSA, BufInit, Send, Recv}), + {ServerSA, Proto, BufInit, + Send, Recv}), ok end}, #{desc => "await (remote) handler ready", @@ -11741,6 +13061,7 @@ traffic_ping_pong_send_and_receive_udp2(InitState) -> i("start server evaluator"), ServerInitState = #{domain => maps:get(domain, InitState), + proto => maps:get(proto, InitState), recv => maps:get(recv, InitState), send => maps:get(send, InitState), buf_init => maps:get(buf_init, InitState)}, @@ -11841,12 +13162,12 @@ tpp_udp_client_handler_create(Node) -> tpp_udp_client_handler(Parent) -> tpp_udp_client_handler_init(Parent), ?SEV_IPRINT("await start command"), - {ServerSA, BufInit, Send, Recv} = tpp_udp_handler_await_start(Parent), + {ServerSA, Proto, BufInit, Send, Recv} = tpp_udp_handler_await_start(Parent), ?SEV_IPRINT("start command with" "~n ServerSA: ~p", [ServerSA]), Domain = maps:get(family, ServerSA), - Sock = tpp_udp_sock_open(Domain, BufInit), - tpp_udp_sock_bind(Sock, Domain), + Sock = tpp_udp_sock_open(Domain, Proto, BufInit), + Path = tpp_udp_sock_bind(Sock, Domain), ?SEV_IPRINT("announce ready", []), tpp_udp_handler_announce_ready(Parent, init), {InitMsg, Num} = tpp_udp_handler_await_continue(Parent, send), @@ -11859,7 +13180,7 @@ tpp_udp_client_handler(Parent) -> ?SEV_IPRINT("await terminate"), Reason = tpp_udp_handler_await_terminate(Parent), ?SEV_IPRINT("terminate with ~p", [Reason]), - tpp_udp_sock_close(Sock), + tpp_udp_sock_close(Sock, Path), ?SEV_IPRINT("terminating"), exit(Reason). @@ -11997,8 +13318,8 @@ tpp_udp_handler_await_terminate(Parent) -> end. -tpp_udp_sock_open(Domain, BufInit) -> - case socket:open(Domain, dgram, udp) of +tpp_udp_sock_open(Domain, Proto, BufInit) -> + case socket:open(Domain, dgram, Proto) of {ok, Sock} -> ok = BufInit(Sock), Sock; @@ -12007,9 +13328,7 @@ tpp_udp_sock_open(Domain, BufInit) -> end. tpp_udp_sock_bind(Sock, Domain) -> - LAddr = which_local_addr(Domain), - LSA = #{family => Domain, - addr => LAddr}, + LSA = which_local_socket_addr(Domain), case socket:bind(Sock, LSA) of {ok, _} -> ok; @@ -12017,12 +13336,16 @@ tpp_udp_sock_bind(Sock, Domain) -> exit({bind, Reason}) end. -tpp_udp_sock_close(Sock) -> +tpp_udp_sock_close(Sock, Path) -> case socket:close(Sock) of ok -> + unlink_path(Path), ok; {error, Reason} -> - exit({close, Reason}) + ?SEV_EPRINT("Failed closing socket: " + "~n ~p", [Reason]), + unlink_path(Path), + {error, {close, Reason}} end. @@ -15104,6 +16427,30 @@ ttest_ssockf_csockf_small_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false +%% Message Size: small (=1) +%% Domain: local +%% + +ttest_ssockf_csockf_small_tcpL(suite) -> + []; +ttest_ssockf_csockf_small_tcpL(doc) -> + []; +ttest_ssockf_csockf_small_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockf_csockf_small_tcpL, + Runtime, + local, + sock, false, + sock, false, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = false +%% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet %% @@ -15152,6 +16499,30 @@ ttest_ssockf_csockf_medium_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = false +%% Message Size: medium (=2) +%% Domain: local +%% + +ttest_ssockf_csockf_medium_tcpL(suite) -> + []; +ttest_ssockf_csockf_medium_tcpL(doc) -> + []; +ttest_ssockf_csockf_medium_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockf_csockf_medium_tcpL, + Runtime, + local, + sock, false, + sock, false, + 2, 20). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = false +%% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet %% @@ -15199,6 +16570,30 @@ ttest_ssockf_csockf_large_tcp6(Config) when is_list(Config) -> %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false +%% Client: Transport = socket(tcp), Active = false +%% Message Size: large (=3) +%% Domain: local +%% + +ttest_ssockf_csockf_large_tcpL(suite) -> + []; +ttest_ssockf_csockf_large_tcpL(doc) -> + []; +ttest_ssockf_csockf_large_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockf_csockf_large_tcpL, + Runtime, + local, + sock, false, + sock, false, + 3, 2). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet @@ -15248,6 +16643,30 @@ ttest_ssockf_csocko_small_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once +%% Message Size: small (=1) +%% Domain: local +%% + +ttest_ssockf_csocko_small_tcpL(suite) -> + []; +ttest_ssockf_csocko_small_tcpL(doc) -> + []; +ttest_ssockf_csocko_small_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockf_csocko_small_tcpL, + Runtime, + local, + sock, false, + sock, once, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = false +%% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet %% @@ -15296,6 +16715,30 @@ ttest_ssockf_csocko_medium_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = once +%% Message Size: medium (=2) +%% Domain: local +%% + +ttest_ssockf_csocko_medium_tcpL(suite) -> + []; +ttest_ssockf_csocko_medium_tcpL(doc) -> + []; +ttest_ssockf_csocko_medium_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockf_csocko_medium_tcpL, + Runtime, + local, + sock, false, + sock, once, + 2, 20). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = false +%% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet %% @@ -15343,6 +16786,30 @@ ttest_ssockf_csocko_large_tcp6(Config) when is_list(Config) -> %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false +%% Client: Transport = socket(tcp), Active = once +%% Message Size: large (=3) +%% Domain: local +%% + +ttest_ssockf_csocko_large_tcpL(suite) -> + []; +ttest_ssockf_csocko_large_tcpL(doc) -> + []; +ttest_ssockf_csocko_large_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockf_csocko_large_tcpL, + Runtime, + local, + sock, false, + sock, once, + 3, 2). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet @@ -15390,6 +16857,30 @@ ttest_ssockf_csockt_small_tcp6(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = false +%% Client: Transport = socket(tcp), Active = true +%% Message Size: small (=1) +%% Domain: local +%% + +ttest_ssockf_csockt_small_tcpL(suite) -> + []; +ttest_ssockf_csockt_small_tcpL(doc) -> + []; +ttest_ssockf_csockt_small_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockf_csocko_small_tcpL, + Runtime, + local, + sock, false, + sock, true, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) @@ -15440,6 +16931,30 @@ ttest_ssockf_csockt_medium_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = false %% Client: Transport = socket(tcp), Active = true +%% Message Size: medium (=2) +%% Domain: local +%% + +ttest_ssockf_csockt_medium_tcpL(suite) -> + []; +ttest_ssockf_csockt_medium_tcpL(doc) -> + []; +ttest_ssockf_csockt_medium_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockf_csockt_medium_tcpL, + Runtime, + local, + sock, false, + sock, true, + 2, 20). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = false +%% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet %% @@ -15486,6 +17001,30 @@ ttest_ssockf_csockt_large_tcp6(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = false +%% Client: Transport = socket(tcp), Active = true +%% Message Size: large (=3) +%% Domain: local +%% + +ttest_ssockf_csockt_large_tcpL(suite) -> + []; +ttest_ssockf_csockt_large_tcpL(doc) -> + []; +ttest_ssockf_csockt_large_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockf_csockt_large_tcpL, + Runtime, + local, + sock, false, + sock, true, + 3, 2). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) @@ -15968,6 +17507,30 @@ ttest_ssocko_csockf_small_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false +%% Message Size: small (=1) +%% Domain: local +%% + +ttest_ssocko_csockf_small_tcpL(suite) -> + []; +ttest_ssocko_csockf_small_tcpL(doc) -> + []; +ttest_ssocko_csockf_small_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssocko_csockf_small_tcpL, + Runtime, + local, + sock, once, + sock, false, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = once +%% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet %% @@ -16016,6 +17579,30 @@ ttest_ssocko_csockf_medium_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = false +%% Message Size: medium (=2) +%% Domain: local +%% + +ttest_ssocko_csockf_medium_tcpL(suite) -> + []; +ttest_ssocko_csockf_medium_tcpL(doc) -> + []; +ttest_ssocko_csockf_medium_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssocko_csockf_medium_tcpL, + Runtime, + local, + sock, once, + sock, false, + 2, 20). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = once +%% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet %% @@ -16063,6 +17650,30 @@ ttest_ssocko_csockf_large_tcp6(Config) when is_list(Config) -> %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once +%% Client: Transport = socket(tcp), Active = false +%% Message Size: large (=3) +%% Domain: local +%% + +ttest_ssocko_csockf_large_tcpL(suite) -> + []; +ttest_ssocko_csockf_large_tcpL(doc) -> + []; +ttest_ssocko_csockf_large_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssocko_csockf_large_tcpL, + Runtime, + local, + sock, once, + sock, false, + 3, 2). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet @@ -16112,6 +17723,30 @@ ttest_ssocko_csocko_small_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once +%% Message Size: small (=1) +%% Domain: local +%% + +ttest_ssocko_csocko_small_tcpL(suite) -> + []; +ttest_ssocko_csocko_small_tcpL(doc) -> + []; +ttest_ssocko_csocko_small_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssocko_csocko_small_tcpL, + Runtime, + local, + sock, once, + sock, once, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = once +%% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet %% @@ -16160,6 +17795,30 @@ ttest_ssocko_csocko_medium_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = once +%% Message Size: medium (=2) +%% Domain: local +%% + +ttest_ssocko_csocko_medium_tcpL(suite) -> + []; +ttest_ssocko_csocko_medium_tcpL(doc) -> + []; +ttest_ssocko_csocko_medium_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssocko_csocko_medium_tcpL, + Runtime, + local, + sock, once, + sock, once, + 2, 20). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = once +%% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet %% @@ -16207,6 +17866,30 @@ ttest_ssocko_csocko_large_tcp6(Config) when is_list(Config) -> %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once +%% Client: Transport = socket(tcp), Active = once +%% Message Size: large (=3) +%% Domain: local +%% + +ttest_ssocko_csocko_large_tcpL(suite) -> + []; +ttest_ssocko_csocko_large_tcpL(doc) -> + []; +ttest_ssocko_csocko_large_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssocko_csocko_large_tcpL, + Runtime, + local, + sock, once, + sock, once, + 3, 2). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet @@ -16254,6 +17937,30 @@ ttest_ssocko_csockt_small_tcp6(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = once +%% Client: Transport = socket(tcp), Active = true +%% Message Size: small (=1) +%% Domain: local +%% + +ttest_ssocko_csockt_small_tcpL(suite) -> + []; +ttest_ssocko_csockt_small_tcpL(doc) -> + []; +ttest_ssocko_csockt_small_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssocko_csocko_small_tcpL, + Runtime, + local, + sock, once, + sock, true, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) @@ -16304,6 +18011,30 @@ ttest_ssocko_csockt_medium_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = once %% Client: Transport = socket(tcp), Active = true +%% Message Size: medium (=2) +%% Domain: local +%% + +ttest_ssocko_csockt_medium_tcpL(suite) -> + []; +ttest_ssocko_csockt_medium_tcpL(doc) -> + []; +ttest_ssocko_csockt_medium_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssocko_csockt_medium_tcpL, + Runtime, + local, + sock, once, + sock, true, + 2, 20). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = once +%% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet %% @@ -16350,6 +18081,30 @@ ttest_ssocko_csockt_large_tcp6(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = once +%% Client: Transport = socket(tcp), Active = true +%% Message Size: large (=3) +%% Domain: local +%% + +ttest_ssocko_csockt_large_tcpL(suite) -> + []; +ttest_ssocko_csockt_large_tcpL(doc) -> + []; +ttest_ssocko_csockt_large_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssocko_csockt_large_tcpL, + Runtime, + local, + sock, once, + sock, true, + 3, 2). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = gen_tcp, Active = false %% Message Size: small (=1) @@ -16832,6 +18587,30 @@ ttest_ssockt_csockf_small_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false +%% Message Size: small (=1) +%% Domain: local +%% + +ttest_ssockt_csockf_small_tcpL(suite) -> + []; +ttest_ssockt_csockf_small_tcpL(doc) -> + []; +ttest_ssockt_csockf_small_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockt_csockf_small_tcpL, + Runtime, + local, + sock, true, + sock, false, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = true +%% Client: Transport = socket(tcp), Active = false %% Message Size: medium (=2) %% Domain: inet %% @@ -16880,6 +18659,30 @@ ttest_ssockt_csockf_medium_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = false +%% Message Size: medium (=2) +%% Domain: local +%% + +ttest_ssockt_csockf_medium_tcpL(suite) -> + []; +ttest_ssockt_csockf_medium_tcpL(doc) -> + []; +ttest_ssockt_csockf_medium_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockt_csockf_medium_tcpL, + Runtime, + local, + sock, true, + sock, false, + 2, 20). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = true +%% Client: Transport = socket(tcp), Active = false %% Message Size: large (=3) %% Domain: inet %% @@ -16927,6 +18730,30 @@ ttest_ssockt_csockf_large_tcp6(Config) when is_list(Config) -> %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true +%% Client: Transport = socket(tcp), Active = false +%% Message Size: large (=3) +%% Domain: local +%% + +ttest_ssockt_csockf_large_tcpL(suite) -> + []; +ttest_ssockt_csockf_large_tcpL(doc) -> + []; +ttest_ssockt_csockf_large_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockt_csockf_large_tcpL, + Runtime, + local, + sock, true, + sock, false, + 3, 2). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once %% Message Size: small (=1) %% Domain: inet @@ -16976,6 +18803,30 @@ ttest_ssockt_csocko_small_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once +%% Message Size: small (=1) +%% Domain: local +%% + +ttest_ssockt_csocko_small_tcpL(suite) -> + []; +ttest_ssockt_csocko_small_tcpL(doc) -> + []; +ttest_ssockt_csocko_small_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockt_csocko_small_tcpL, + Runtime, + local, + sock, true, + sock, once, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = true +%% Client: Transport = socket(tcp), Active = once %% Message Size: medium (=2) %% Domain: inet %% @@ -17024,6 +18875,30 @@ ttest_ssockt_csocko_medium_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = once +%% Message Size: medium (=2) +%% Domain: local +%% + +ttest_ssockt_csocko_medium_tcpL(suite) -> + []; +ttest_ssockt_csocko_medium_tcpL(doc) -> + []; +ttest_ssockt_csocko_medium_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockt_csocko_medium_tcpL, + Runtime, + local, + sock, true, + sock, once, + 2, 20). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = true +%% Client: Transport = socket(tcp), Active = once %% Message Size: large (=3) %% Domain: inet %% @@ -17071,6 +18946,30 @@ ttest_ssockt_csocko_large_tcp6(Config) when is_list(Config) -> %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true +%% Client: Transport = socket(tcp), Active = once +%% Message Size: large (=3) +%% Domain: local +%% + +ttest_ssockt_csocko_large_tcpL(suite) -> + []; +ttest_ssockt_csocko_large_tcpL(doc) -> + []; +ttest_ssockt_csocko_large_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockt_csocko_large_tcpL, + Runtime, + local, + sock, true, + sock, once, + 3, 2). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: small (=1) %% Domain: inet @@ -17118,6 +19017,30 @@ ttest_ssockt_csockt_small_tcp6(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case uses the time test (ttest) utility to implement a %% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = true +%% Client: Transport = socket(tcp), Active = true +%% Message Size: small (=1) +%% Domain: local +%% + +ttest_ssockt_csockt_small_tcpL(suite) -> + []; +ttest_ssockt_csockt_small_tcpL(doc) -> + []; +ttest_ssockt_csockt_small_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockt_csocko_small_tcpL, + Runtime, + local, + sock, true, + sock, true, + 1, 200). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true %% Message Size: medium (=2) @@ -17168,6 +19091,30 @@ ttest_ssockt_csockt_medium_tcp6(Config) when is_list(Config) -> %% ping-pong like test case. %% Server: Transport = socket(tcp), Active = true %% Client: Transport = socket(tcp), Active = true +%% Message Size: medium (=2) +%% Domain: local +%% + +ttest_ssockt_csockt_medium_tcpL(suite) -> + []; +ttest_ssockt_csockt_medium_tcpL(doc) -> + []; +ttest_ssockt_csockt_medium_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockt_csockt_medium_tcpL, + Runtime, + local, + sock, true, + sock, true, + 2, 20). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = true +%% Client: Transport = socket(tcp), Active = true %% Message Size: large (=3) %% Domain: inet %% @@ -17212,6 +19159,30 @@ ttest_ssockt_csockt_large_tcp6(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case uses the time test (ttest) utility to implement a +%% ping-pong like test case. +%% Server: Transport = socket(tcp), Active = true +%% Client: Transport = socket(tcp), Active = true +%% Message Size: large (=3) +%% Domain: local +%% + +ttest_ssockt_csockt_large_tcpL(suite) -> + []; +ttest_ssockt_csockt_large_tcpL(doc) -> + []; +ttest_ssockt_csockt_large_tcpL(Config) when is_list(Config) -> + Runtime = which_ttest_runtime(Config), + ttest_tcp(ttest_ssockt_csockt_large_tcpL, + Runtime, + local, + sock, true, + sock, true, + 3, 2). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% which_ttest_runtime(Config) when is_list(Config) -> case lists:keysearch(esock_test_ttest_runtime, 1, Config) of @@ -17272,7 +19243,8 @@ ttest_tcp(TC, tc_try(TC, fun() -> if - (Domain =/= inet) -> has_support_ipv6(); + (Domain =:= local) -> has_support_unix_domain_socket(); + (Domain =:= inet6) -> has_support_ipv6(); true -> ok end end, @@ -17326,11 +19298,25 @@ ttest_tcp(InitState) -> ok end}, #{desc => "start ttest (remote) server", - cmd => fun(#{mod := Mod, + cmd => fun(#{domain := local = Domain, + mod := Mod, active := Active, node := Node} = State) -> - case ttest_tcp_server_start(Node, Mod, Active) of - {ok, {{Pid, _MRef}, {Addr, Port}}} -> + case ttest_tcp_server_start(Node, + Domain, Mod, Active) of + {ok, {{Pid, _}, Path}} -> + {ok, State#{rserver => Pid, + path => Path}}; + {error, _} = ERROR -> + ERROR + end; + (#{domain := Domain, + mod := Mod, + active := Active, + node := Node} = State) -> + case ttest_tcp_server_start(Node, + Domain, Mod, Active) of + {ok, {{Pid, _}, {Addr, Port}}} -> {ok, State#{rserver => Pid, addr => Addr, port => Port}}; @@ -17339,7 +19325,12 @@ ttest_tcp(InitState) -> end end}, #{desc => "announce ready (init)", - cmd => fun(#{tester := Tester, + cmd => fun(#{domain := local, + tester := Tester, + path := Path}) -> + ?SEV_ANNOUNCE_READY(Tester, init, Path), + ok; + (#{tester := Tester, addr := Addr, port := Port}) -> ?SEV_ANNOUNCE_READY(Tester, init, {Addr, Port}), @@ -17394,8 +19385,14 @@ ttest_tcp(InitState) -> [ %% *** Wait for start order part *** #{desc => "await start", - cmd => fun(State) -> - {Tester, {ServerAddr, ServerPort}} = ?SEV_AWAIT_START(), + cmd => fun(#{domain := local} = State) -> + {Tester, ServerPath} = + ?SEV_AWAIT_START(), + {ok, State#{tester => Tester, + server_path => ServerPath}}; + (State) -> + {Tester, {ServerAddr, ServerPort}} = + ?SEV_AWAIT_START(), {ok, State#{tester => Tester, server_addr => ServerAddr, server_port => ServerPort}} @@ -17436,7 +19433,32 @@ ttest_tcp(InitState) -> ok end}, #{desc => "start ttest (remote) client", - cmd => fun(#{node := Node, + cmd => fun(#{domain := local = Domain, + node := Node, + mod := Mod, + active := Active, + msg_id := MsgID, + max_outstanding := MaxOutstanding, + runtime := RunTime, + server_path := Path} = State) -> + Self = self(), + Notify = + fun(Result) -> + ?SEV_ANNOUNCE_READY(Self, ttest, Result) + end, + case ttest_tcp_client_start(Node, Notify, + Domain, Mod, + Path, + Active, + MsgID, MaxOutstanding, + RunTime) of + {ok, {Pid, _MRef}} -> + {ok, State#{rclient => Pid}}; + {error, _} = ERROR -> + ERROR + end; + (#{domain := Domain, + node := Node, mod := Mod, active := Active, msg_id := MsgID, @@ -17450,8 +19472,9 @@ ttest_tcp(InitState) -> ?SEV_ANNOUNCE_READY(Self, ttest, Result) end, case ttest_tcp_client_start(Node, Notify, - Mod, Active, - Addr, Port, + Domain, Mod, + {Addr, Port}, + Active, MsgID, MaxOutstanding, RunTime) of {ok, {Pid, _MRef}} -> @@ -17463,8 +19486,6 @@ ttest_tcp(InitState) -> #{desc => "await ttest ready", cmd => fun(#{tester := Tester, rclient := RClient} = State) -> - %% TTestResult = ?SEV_AWAIT_READY(RClient, rclient, ttest, - %% [{tester, Tester}]), case ?SEV_AWAIT_READY(RClient, rclient, ttest, [{tester, Tester}]) of {ok, Result} -> @@ -17535,8 +19556,13 @@ ttest_tcp(InitState) -> ok end}, #{desc => "await server ready (init)", - cmd => fun(#{server := Pid} = State) -> - {ok, {Addr, Port}} = ?SEV_AWAIT_READY(Pid, server, init), + cmd => fun(#{domain := local, + server := Pid} = State) -> + {ok, Path} = ?SEV_AWAIT_READY(Pid, server, init), + {ok, State#{server_path => Path}}; + (#{server := Pid} = State) -> + {ok, {Addr, Port}} = + ?SEV_AWAIT_READY(Pid, server, init), {ok, State#{server_addr => Addr, server_port => Port}} end}, @@ -17544,7 +19570,12 @@ ttest_tcp(InitState) -> %% Start the client #{desc => "order client start", - cmd => fun(#{client := Pid, + cmd => fun(#{domain := local, + client := Pid, + server_path := Path} = _State) -> + ?SEV_ANNOUNCE_START(Pid, Path), + ok; + (#{client := Pid, server_addr := Addr, server_port := Port} = _State) -> ?SEV_ANNOUNCE_START(Pid, {Addr, Port}), @@ -17683,7 +19714,8 @@ ttest_tcp(InitState) -> Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start 'tester' evaluator"), - TesterInitState = #{server => Server#ev.pid, + TesterInitState = #{domain => maps:get(domain, InitState), + server => Server#ev.pid, client => Client#ev.pid}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), @@ -17692,12 +19724,12 @@ ttest_tcp(InitState) -> -ttest_tcp_server_start(Node, gen, Active) -> +ttest_tcp_server_start(Node, _Domain, gen, Active) -> Transport = socket_test_ttest_tcp_gen, socket_test_ttest_tcp_server:start_monitor(Node, Transport, Active); -ttest_tcp_server_start(Node, sock, Active) -> +ttest_tcp_server_start(Node, Domain, sock, Active) -> TransportMod = socket_test_ttest_tcp_socket, - Transport = {TransportMod, #{method => plain}}, + Transport = {TransportMod, #{domain => Domain, method => plain}}, socket_test_ttest_tcp_server:start_monitor(Node, Transport, Active). ttest_tcp_server_stop(Pid) -> @@ -17705,26 +19737,26 @@ ttest_tcp_server_stop(Pid) -> ttest_tcp_client_start(Node, Notify, - gen, - Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> + _Domain, gen, + ServerInfo, Active, MsgID, MaxOutstanding, RunTime) -> Transport = socket_test_ttest_tcp_gen, socket_test_ttest_tcp_client:start_monitor(Node, Notify, Transport, + ServerInfo, Active, - Addr, Port, MsgID, MaxOutstanding, RunTime); ttest_tcp_client_start(Node, Notify, - sock, - Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> + Domain, sock, + ServerInfo, Active, MsgID, MaxOutstanding, RunTime) -> TransportMod = socket_test_ttest_tcp_socket, - Transport = {TransportMod, #{method => plain}}, + Transport = {TransportMod, #{domain => Domain, method => plain}}, socket_test_ttest_tcp_client:start_monitor(Node, Notify, Transport, + ServerInfo, Active, - Addr, Port, MsgID, MaxOutstanding, RunTime). @@ -17801,19 +19833,6 @@ sock_open(Domain, Type, Proto) -> end. -sock_bind(Sock, SockAddr) -> - try socket:bind(Sock, SockAddr) of - {ok, Port} -> - Port; - {error, Reason} -> - i("sock_bind -> error: ~p", [Reason]), - ?FAIL({bind, Reason}) - catch - C:E:S -> - i("sock_bind -> failed: ~p, ~p, ~p", [C, E, S]), - ?FAIL({bind, C, E, S}) - end. - sock_connect(Sock, SockAddr) -> try socket:connect(Sock, SockAddr) of ok -> @@ -17899,13 +19918,50 @@ local_host() -> end. +%% The point of this is to "ensure" that paths from different test runs +%% don't clash. +mk_unique_path() -> + [NodeName | _] = string:tokens(atom_to_list(node()), [$@]), + Path = ?LIB:f("/tmp/esock_~s_~w", [NodeName, erlang:system_time(nanosecond)]), + ensure_unique_path(Path). + +ensure_unique_path(Path) -> + case file:read_file_info(Path) of + {ok, _} -> % Ouch, append a unique ID and try again + ensure_unique_path(Path, 1); + {error, _} -> + %% We assume this means it does not exist yet... + %% If we have several process in paralell trying to create + %% (unique) path's, then we are in trouble. To *really* be + %% on the safe side we should have a (central) path registry... + Path + end. + +ensure_unique_path(Path, ID) when (ID < 100) -> % If this is not enough... + NewPath = ?LIB:f("~s_~w", [Path, ID]), + case file:read_file_info(NewPath) of + {ok, _} -> % Ouch, this also existed, increment and try again + ensure_unique_path(Path, ID + 1); + {error, _} -> % We assume this means it does not exist yet... + NewPath + end; +ensure_unique_path(_, _) -> + skip("Could not create unique path"). + + +which_local_socket_addr(local = Domain) -> + #{family => Domain, + path => mk_unique_path()}; + %% This gets the local address (not 127.0...) %% We should really implement this using the (new) net module, %% but until that gets the necessary functionality... -which_local_addr(Domain) -> +which_local_socket_addr(Domain) -> case inet:getifaddrs() of {ok, IFL} -> - which_addr(Domain, IFL); + Addr = which_addr(Domain, IFL), + #{family => Domain, + addr => Addr}; {error, Reason} -> ?FAIL({inet, getifaddrs, Reason}) end. @@ -17935,12 +19991,55 @@ which_addr2(Domain, [_|IFO]) -> +unlink_path(Path) -> + unlink_path(Path, fun() -> ok end, fun() -> ok end). + +unlink_path(Path, Success, Failure) when is_list(Path) andalso + is_function(Success, 0) andalso + is_function(Failure, 0) -> + ?SEV_IPRINT("try unlink path: " + "~n ~s", [Path]), + case os:cmd("unlink " ++ Path) of + "" -> + ?SEV_IPRINT("path unlinked: " + "~n Path: ~s", [Path]), + Success(); + Result -> + ?SEV_EPRINT("unlink maybe failed: " + "~n Path: ~s" + "~n Res: ~s", [Path, Result]), + Failure() + end; +unlink_path(_, _, _) -> + ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Here are all the *general* test vase condition functions. +unix_domain_socket_host_cond() -> + unix_domain_socket_host_cond(os:type(), os:version()). + +unix_domain_socket_host_cond({unix, linux}, {M, _, _}) when (M < 3) -> + skip("TC may not work on this version"); +unix_domain_socket_host_cond(_, _) -> + ok. + +has_support_unix_domain_socket() -> + case os:type() of + {win32, _} -> + skip("Not supported"); + _ -> + case socket:supports(local) of + true -> + ok; + false -> + skip("Not supported") + end + end. + + %% The idea is that this function shall test if the test host has %% support for IPv6. If not, there is no point in running IPv6 tests. %% Currently we just skip. diff --git a/erts/emulator/test/socket_test_ttest_tcp_client.erl b/erts/emulator/test/socket_test_ttest_tcp_client.erl index 5efa3fe491..b5c5300fd0 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_client.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_client.erl @@ -42,16 +42,16 @@ -export([ %% These are for the test suite - start_monitor/6, start_monitor/7, start_monitor/9, + start_monitor/5, start_monitor/6, start_monitor/8, %% These are for starting in a shell when run "manually" - start/4, start/5, start/7, start/8, + start/3, start/4, start/6, start/7, stop/1 ]). %% Internal exports -export([ - do_start/10 + do_start/9 ]). -include_lib("kernel/include/inet.hrl"). @@ -80,25 +80,25 @@ %% ========================================================================== -start_monitor(Node, Notify, Transport, Active, Addr, Port) -> - start_monitor(Node, Notify, Transport, Active, Addr, Port, ?MSG_ID_DEFAULT). +start_monitor(Node, Notify, Transport, ServerInfo, Active) -> + start_monitor(Node, Notify, Transport, ServerInfo, Active, ?MSG_ID_DEFAULT). -start_monitor(Node, Notify, Transport, Active, Addr, Port, 1 = MsgID) -> - start_monitor(Node, Notify, Transport, Active, Addr, Port, MsgID, +start_monitor(Node, Notify, Transport, ServerInfo, Active, 1 = MsgID) -> + start_monitor(Node, Notify, Transport, ServerInfo, Active, MsgID, ?MAX_OUTSTANDING_DEFAULT_1, ?RUNTIME_DEFAULT); -start_monitor(Node, Notify, Transport, Active, Addr, Port, 2 = MsgID) -> - start_monitor(Node, Notify, Transport, Active, Addr, Port, MsgID, +start_monitor(Node, Notify, Transport, ServerInfo, Active, 2 = MsgID) -> + start_monitor(Node, Notify, Transport, ServerInfo, Active, MsgID, ?MAX_OUTSTANDING_DEFAULT_2, ?RUNTIME_DEFAULT); -start_monitor(Node, Notify, Transport, Active, Addr, Port, 3 = MsgID) -> - start_monitor(Node, Notify, Transport, Active, Addr, Port, MsgID, +start_monitor(Node, Notify, Transport, ServerInfo, Active, 3 = MsgID) -> + start_monitor(Node, Notify, Transport, ServerInfo, Active, MsgID, ?MAX_OUTSTANDING_DEFAULT_3, ?RUNTIME_DEFAULT). -start_monitor(Node, Notify, Transport, Active, Addr, Port, +start_monitor(Node, Notify, Transport, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) when (Node =/= node()) -> Args = [false, self(), Notify, - Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime], + Transport, ServerInfo, Active, MsgID, MaxOutstanding, RunTime], case rpc:call(Node, ?MODULE, do_start, Args) of {badrpc, _} = Reason -> {error, Reason}; @@ -108,11 +108,11 @@ start_monitor(Node, Notify, Transport, Active, Addr, Port, {error, _} = ERROR -> ERROR end; -start_monitor(_, Notify, Transport, Active, Addr, Port, +start_monitor(_, Notify, Transport, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) -> case do_start(false, self(), Notify, - Transport, Active, Addr, Port, + Transport, Active, ServerInfo, MsgID, MaxOutstanding, RunTime) of {ok, Pid} -> MRef = erlang:monitor(process, Pid), @@ -122,50 +122,48 @@ start_monitor(_, Notify, Transport, Active, Addr, Port, end. -start(Transport, Active, Addr, Port) -> - start(Transport, Active, Addr, Port, ?MSG_ID_DEFAULT). +start(Transport, ServerInfo, Active) -> + start(Transport, ServerInfo, Active, ?MSG_ID_DEFAULT). -start(Transport, Active, Addr, Port, 1 = MsgID) -> +start(Transport, ServerInfo, Active, 1 = MsgID) -> start(false, - Transport, Active, Addr, Port, MsgID, + Transport, ServerInfo, Active, MsgID, ?MAX_OUTSTANDING_DEFAULT_1, ?RUNTIME_DEFAULT); -start(Transport, Active, Addr, Port, 2 = MsgID) -> +start(Transport, ServerInfo, Active, 2 = MsgID) -> start(false, - Transport, Active, Addr, Port, MsgID, + Transport, ServerInfo, Active, MsgID, ?MAX_OUTSTANDING_DEFAULT_2, ?RUNTIME_DEFAULT); -start(Transport, Active, Addr, Port, 3 = MsgID) -> +start(Transport, ServerInfo, Active, 3 = MsgID) -> start(false, - Transport, Active, Addr, Port, MsgID, + Transport, ServerInfo, Active, MsgID, ?MAX_OUTSTANDING_DEFAULT_3, ?RUNTIME_DEFAULT). -start(Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> +start(Transport, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) -> start(false, - Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime). + Transport, ServerInfo, Active, MsgID, MaxOutstanding, RunTime). -start(Quiet, Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> +start(Quiet, Transport, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) -> Notify = fun(R) -> present_results(R) end, do_start(Quiet, self(), Notify, - Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime). + Transport, ServerInfo, Active, MsgID, MaxOutstanding, RunTime). -spec do_start(Quiet, Parent, Notify, Transport, + ServerInfo, Active, - Addr, - Port, MsgID, MaxOutstanding, RunTime) -> {ok, Pid} | {error, Reason} when - Quiet :: pid(), + Quiet :: boolean(), Parent :: pid(), Notify :: function(), Transport :: atom() | tuple(), + ServerInfo :: {inet:ip_address(), inet:port_number()} | string(), Active :: active(), - Addr :: inet:ip_address(), - Port :: inet:port_number(), MsgID :: msg_id(), MaxOutstanding :: max_outstanding(), RunTime :: runtime(), @@ -174,14 +172,13 @@ start(Quiet, Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> do_start(Quiet, Parent, Notify, - Transport, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) + Transport, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) when is_boolean(Quiet) andalso is_pid(Parent) andalso is_function(Notify) andalso (is_atom(Transport) orelse is_tuple(Transport)) andalso (is_boolean(Active) orelse (Active =:= once)) andalso - is_tuple(Addr) andalso - (is_integer(Port) andalso (Port > 0)) andalso + (is_tuple(ServerInfo) orelse is_list(ServerInfo)) andalso (is_integer(MsgID) andalso (MsgID >= 1) andalso (MsgID =< 3)) andalso (is_integer(MaxOutstanding) andalso (MaxOutstanding > 0)) andalso (is_integer(RunTime) andalso (RunTime > 0)) -> @@ -191,7 +188,7 @@ do_start(Quiet, Starter, Parent, Notify, - Transport, Active, Addr, Port, + Transport, Active, ServerInfo, MsgID, MaxOutstanding, RunTime) end, {Pid, MRef} = spawn_monitor(Init), @@ -217,25 +214,30 @@ stop(Pid) when is_pid(Pid) -> init(Quiet, Starter, Parent, Notify, - Transport, Active, Addr, Port, + Transport, Active, ServerInfo, MsgID, MaxOutstanding, RunTime) -> if not Quiet -> ?I("init with" "~n Transport: ~p" "~n Active: ~p" - "~n Addr: ~s" - "~n Port: ~p" + "~n ServerInfo: ~s" "~n Msg ID: ~p (=> 16 + ~w bytes)" "~n Max Outstanding: ~p" "~n (Suggested) Run Time: ~p ms", - [Transport, Active, inet:ntoa(Addr), Port, + [Transport, Active, + case ServerInfo of + {Addr, Port} -> + ?F("Addr: ~s, Port: ~w", [inet:ntoa(Addr), Port]); + Path -> + Path + end, MsgID, size(which_msg_data(MsgID)), MaxOutstanding, RunTime]); true -> ok end, {Mod, Connect} = process_transport(Transport), - case Connect(Addr, Port) of + case Connect(ServerInfo) of {ok, Sock} -> if not Quiet -> ?I("connected"); true -> ok @@ -269,9 +271,15 @@ init(Quiet, end. process_transport(Mod) when is_atom(Mod) -> - {Mod, fun(A, P) -> Mod:connect(A, P) end}; -process_transport({Mod, Opts}) -> - {Mod, fun(A, P) -> Mod:connect(A, P, Opts) end}. + %% In this case we assume it to be a plain tcp socket + {Mod, fun({A, P}) -> Mod:connect(A, P) end}; +process_transport({Mod, #{domain := Domain} = Opts}) -> + Connect = + case Domain of + local -> fun(Path) -> Mod:connect(Path, Opts) end; + _ -> fun({A, P}) -> Mod:connect(A, P, Opts) end + end, + {Mod, Connect}. which_msg_data(1) -> ?MSG_DATA1; diff --git a/erts/emulator/test/socket_test_ttest_tcp_client_gen.erl b/erts/emulator/test/socket_test_ttest_tcp_client_gen.erl index 0ec2e908d7..65a3a94d38 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_client_gen.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_client_gen.erl @@ -21,28 +21,28 @@ -module(socket_test_ttest_tcp_client_gen). -export([ - start/3, start/4, start/6, start/7, + start/2, start/3, start/5, start/6, stop/1 ]). -define(TRANSPORT_MOD, socket_test_ttest_tcp_gen). -start(Active, Addr, Port) -> - socket_test_ttest_tcp_client:start(?TRANSPORT_MOD, Active, Addr, Port). +start(ServerInfo, Active) -> + socket_test_ttest_tcp_client:start(?TRANSPORT_MOD, ServerInfo, Active). -start(Active, Addr, Port, MsgID) -> - socket_test_ttest_tcp_client:start(?TRANSPORT_MOD, Active, Addr, Port, MsgID). +start(ServerInfo, Active, MsgID) -> + socket_test_ttest_tcp_client:start(?TRANSPORT_MOD, ServerInfo, Active, MsgID). -start(Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> +start(ServerInfo, Active, MsgID, MaxOutstanding, RunTime) -> socket_test_ttest_tcp_client:start(false, ?TRANSPORT_MOD, - Active, Addr, Port, + ServerInfo, Active, MsgID, MaxOutstanding, RunTime). -start(Quiet, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> +start(Quiet, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) -> socket_test_ttest_tcp_client:start(Quiet, ?TRANSPORT_MOD, - Active, Addr, Port, + ServerInfo, Active, MsgID, MaxOutstanding, RunTime). stop(Pid) -> diff --git a/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl b/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl index acf2556793..ccace2a560 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl @@ -21,30 +21,89 @@ -module(socket_test_ttest_tcp_client_socket). -export([ - start/4, start/5, start/7, start/8, + start/3, start/4, start/6, start/7, stop/1 ]). -define(TRANSPORT_MOD, socket_test_ttest_tcp_socket). --define(MOD(M), {?TRANSPORT_MOD, #{method => Method}}). +-define(MOD(D, M), {?TRANSPORT_MOD, #{domain => D, method => M}}). -start(Method, Active, Addr, Port) -> - socket_test_ttest_tcp_client:start_monitor(?MOD(Method), Active, Addr, Port). +start(Method, ServerInfo, Active) + when is_list(ServerInfo) -> + Domain = local, + socket_test_ttest_tcp_client:start_monitor(?MOD(Domain, Method), + ServerInfo, Active); +start(Method, ServerInfo = {Addr, _}, Active) + when is_tuple(Addr) andalso (size(Addr) =:= 4) -> + Domain = inet, + socket_test_ttest_tcp_client:start_monitor(?MOD(Domain, Method), + ServerInfo, Active); +start(Method, ServerInfo = {Addr, _}, Active) + when is_tuple(Addr) andalso (size(Addr) =:= 8) -> + Domain = inet6, + socket_test_ttest_tcp_client:start_monitor(?MOD(Domain, Method), + ServerInfo, Active). -start(Method, Active, Addr, Port, MsgID) -> - socket_test_ttest_tcp_client:start(?MOD(Method), - Active, Addr, Port, MsgID). +start(Method, ServerInfo, Active, MsgID) + when is_list(ServerInfo) -> + %% This is just a simplification + Domain = local, + socket_test_ttest_tcp_client:start(?MOD(Domain, Method), + ServerInfo, Active, MsgID); +start(Method, ServerInfo = {Addr, _}, Active, MsgID) + when is_tuple(Addr) andalso (size(Addr) =:= 4) -> + %% This is just a simplification + Domain = inet, + socket_test_ttest_tcp_client:start(?MOD(Domain, Method), + ServerInfo, Active, MsgID); +start(Method, ServerInfo = {Addr, _}, Active, MsgID) + when is_tuple(Addr) andalso (size(Addr) =:= 8) -> + Domain = inet6, + socket_test_ttest_tcp_client:start(?MOD(Domain, Method), + ServerInfo, Active, MsgID). -start(Method, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> +start(Method, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) + when is_list(ServerInfo) -> + Domain = local, socket_test_ttest_tcp_client:start(false, - ?MOD(Method), - Active, Addr, Port, + ?MOD(Domain, Method), + ServerInfo, Active, + MsgID, MaxOutstanding, RunTime); +start(Method, ServerInfo = {Addr, _}, Active, MsgID, MaxOutstanding, RunTime) + when is_tuple(Addr) andalso (size(Addr) =:= 4) -> + Domain = inet, + socket_test_ttest_tcp_client:start(false, + ?MOD(Domain, Method), + ServerInfo, Active, + MsgID, MaxOutstanding, RunTime); +start(Method, ServerInfo = {Addr, _}, Active, MsgID, MaxOutstanding, RunTime) + when is_tuple(Addr) andalso (size(Addr) =:= 8) -> + Domain = inet6, + socket_test_ttest_tcp_client:start(false, + ?MOD(Domain, Method), + ServerInfo, Active, MsgID, MaxOutstanding, RunTime). -start(Quiet, Method, Active, Addr, Port, MsgID, MaxOutstanding, RunTime) -> +start(Quiet, Method, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) + when is_list(ServerInfo) -> + Domain = local, + socket_test_ttest_tcp_client:start(Quiet, + ?MOD(Domain, Method), + ServerInfo, Active, + MsgID, MaxOutstanding, RunTime); +start(Quiet, Method, ServerInfo = {Addr, _}, Active, MsgID, MaxOutstanding, RunTime) + when is_tuple(Addr) andalso (size(Addr) =:= 4) -> + Domain = inet, + socket_test_ttest_tcp_client:start(Quiet, + ?MOD(Domain, Method), + ServerInfo, Active, + MsgID, MaxOutstanding, RunTime); +start(Quiet, Method, ServerInfo = {Addr, _}, Active, MsgID, MaxOutstanding, RunTime) + when is_tuple(Addr) andalso (size(Addr) =:= 8) -> + Domain = inet6, socket_test_ttest_tcp_client:start(Quiet, - ?MOD(Method), - Active, Addr, Port, + ?MOD(Domain, Method), + ServerInfo, Active, MsgID, MaxOutstanding, RunTime). stop(Pid) -> diff --git a/erts/emulator/test/socket_test_ttest_tcp_gen.erl b/erts/emulator/test/socket_test_ttest_tcp_gen.erl index 604408c489..05b250e3d9 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_gen.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_gen.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2018-2018. All Rights Reserved. +%% Copyright Ericsson AB 2018-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -24,9 +24,9 @@ accept/1, accept/2, active/2, close/1, - connect/2, + connect/2, connect/3, controlling_process/2, - listen/0, listen/1, + listen/0, listen/1, listen/2, peername/1, port/1, recv/2, recv/3, @@ -80,6 +80,13 @@ close(Sock) -> connect(Addr, Port) -> Opts = [binary, {packet, raw}, {active, false}, {buffer, 32*1024}], + do_connect(Addr, Port, Opts). + +connect(Addr, Port, #{domain := Domain}) -> + Opts = [Domain, binary, {packet, raw}, {active, false}, {buffer, 32*1024}], + do_connect(Addr, Port, Opts). + +do_connect(Addr, Port, Opts) -> case gen_tcp:connect(Addr, Port, Opts) of {ok, Sock} -> {ok, Sock}; @@ -95,8 +102,12 @@ controlling_process(Sock, NewPid) -> listen() -> listen(0). -listen(Port) when is_integer(Port) andalso (Port >= 0) -> - Opts = [binary, {ip, {0,0,0,0}}, {packet, raw}, {active, false}, +listen(Port) -> + listen(Port, #{domain => inet}). + +listen(Port, #{domain := Domain}) when is_integer(Port) andalso (Port >= 0) -> + Opts = [Domain, + binary, {ip, {0,0,0,0}}, {packet, raw}, {active, false}, {buffer, 32*1024}], case gen_tcp:listen(Port, Opts) of {ok, Sock} -> diff --git a/erts/emulator/test/socket_test_ttest_tcp_server.erl b/erts/emulator/test/socket_test_ttest_tcp_server.erl index e8d626e3d8..e916fcb93e 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_server.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2018-2018. All Rights Reserved. +%% Copyright Ericsson AB 2018-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -96,8 +96,9 @@ do_start(Parent, Transport, Active) (is_atom(Transport) orelse is_tuple(Transport)) andalso (is_boolean(Active) orelse (Active =:= once)) -> Starter = self(), - ServerInit = fun() -> put(sname, "server"), - server_init(Starter, Parent, Transport, Active) + ServerInit = fun() -> + put(sname, "server"), + server_init(Starter, Parent, Transport, Active) end, {Pid, MRef} = spawn_monitor(ServerInit), receive @@ -126,17 +127,29 @@ server_init(Starter, Parent, Transport, Active) -> case Listen(0) of {ok, LSock} -> case Mod:port(LSock) of - {ok, Port} -> - Addr = which_addr(), % This is just for convenience - ?I("listening on:" - "~n Addr: ~p (~s)" - "~n Port: ~w" - "~n", [Addr, inet:ntoa(Addr), Port]), - Starter ! {?MODULE, self(), {ok, {Addr, Port}}}, + {ok, PortOrPath} -> + Result = + if + is_integer(PortOrPath) -> + %% This is just for convenience + Addr = which_addr(), + ?I("listening on:" + "~n Addr: ~p (~s)" + "~n Port: ~w" + "~n", [Addr, inet:ntoa(Addr), PortOrPath]), + {Addr, PortOrPath}; + is_list(PortOrPath) -> + ?I("listening on:" + "~n Path: ~s" + "~n", [PortOrPath]), + PortOrPath + end, + Starter ! {?MODULE, self(), {ok, Result}}, server_loop(#{parent => Parent, mod => Mod, active => Active, lsock => LSock, + port_or_path => PortOrPath, handlers => [], stats_interval => StatsInterval, %% Accumulation @@ -208,7 +221,9 @@ format_peername({Addr, Port}) -> ?F("~s (~s:~w)", [N, inet:ntoa(Addr), Port]); {error, _} -> ?F("~p, ~p", [Addr, Port]) - end. + end; +format_peername(Path) when is_list(Path) -> + Path. maybe_start_stats_timer(#{active := Active, stats_interval := Time}, Handler) when (Active =/= false) andalso (is_integer(Time) andalso (Time > 0)) -> @@ -219,7 +234,10 @@ maybe_start_stats_timer(_, _) -> start_stats_timer(Time, ProcStr, Pid) -> erlang:start_timer(Time, self(), {stats, Time, ProcStr, Pid}). -server_handle_message(#{parent := Parent, handlers := H} = State) -> +server_handle_message(#{mod := Mod, + lsock := LSock, + parent := Parent, + handlers := H} = State) -> receive {timeout, _TRef, {stats, Interval, ProcStr, Pid}} -> case server_handle_stats(ProcStr, Pid) of @@ -233,6 +251,7 @@ server_handle_message(#{parent := Parent, handlers := H} = State) -> {?MODULE, Ref, Parent, stop} -> reply(Parent, Ref, ok), lists:foreach(fun(P) -> handler_stop(P) end, H), + (catch Mod:close(LSock)), exit(normal); {'DOWN', _MRef, process, Pid, Reason} -> @@ -272,28 +291,26 @@ server_handle_handler_down(Pid, AccMCnt2 = AccMCnt + MCnt, AccBCnt2 = AccBCnt + BCnt, AccHCnt2 = AccHCnt + 1, - ?I("handler ~p (~w) done => accumulated results: " - "~n Run Time: ~s ms" + MsgCount2Str = + fun(RT, ART, MC, AMC) when (RT > 0) -> + ?F("~w => ~w (~w) msgs / ms", [MC, MC div RT, AMC div ART]); + (_, _, MC, AMC) -> + ?F("~w (~w)", [MC, AMC]) + end, + ByteCount2Str = + fun(RT, ART, BC, ABC) when (RT > 0) -> + ?F("~w => ~w (~w) bytes / ms", [BC, BC div RT, ABC div ART]); + (_, _, BC, ABC) -> + ?F("~w", [BC, ABC]) + end, + ?I("handler ~p (~w) done: " + "~n Run Time: ~s" "~n Message Count: ~s" "~n Byte Count: ~s", [Pid, AccHCnt2, - ?FORMAT_TIME(AccRunTime2), - if (AccRunTime2 > 0) -> - ?F("~w => ~w (~w) msgs / ms", - [AccMCnt2, - AccMCnt2 div AccRunTime2, - (AccMCnt2 div AccHCnt2) div AccRunTime2]); - true -> - ?F("~w", [AccMCnt2]) - end, - if (AccRunTime2 > 0) -> - ?F("~w => ~w (~w) bytes / ms", - [AccBCnt2, - AccBCnt2 div AccRunTime2, - (AccBCnt2 div AccHCnt2) div AccRunTime2]); - true -> - ?F("~w", [AccBCnt2]) - end]), + ?FORMAT_TIME(RunTime), + MsgCount2Str(RunTime, AccRunTime2, MCnt, AccMCnt2), + ByteCount2Str(RunTime, AccRunTime2, BCnt, AccBCnt2)]), State#{runtime => AccRunTime2, mcnt => AccMCnt2, bcnt => AccBCnt2, diff --git a/erts/emulator/test/socket_test_ttest_tcp_server_gen.erl b/erts/emulator/test/socket_test_ttest_tcp_server_gen.erl index b1b31f5158..fdf40f1369 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_server_gen.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_server_gen.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2018-2018. All Rights Reserved. +%% Copyright Ericsson AB 2018-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -21,20 +21,18 @@ -module(socket_test_ttest_tcp_server_gen). -export([ - start/1, + start/1, start/2, stop/1 ]). -define(TRANSPORT_MOD, socket_test_ttest_tcp_gen). +-define(MOD(D), {?TRANSPORT_MOD, #{domain => D}}). start(Active) -> - socket_test_ttest_tcp_server:start(?TRANSPORT_MOD, Active). - %% {ok, {Pid, AddrPort}} -> - %% MRef = erlang:monitor(process, Pid), - %% {ok, {Pid, MRef, AddrPort}}; - %% {error, _} = ERROR -> - %% ERROR - %% end. + start(inet, Active). + +start(Domain, Active) -> + socket_test_ttest_tcp_server:start(?MOD(Domain), Active). stop(Pid) -> diff --git a/erts/emulator/test/socket_test_ttest_tcp_server_socket.erl b/erts/emulator/test/socket_test_ttest_tcp_server_socket.erl index b7ea1e8e93..d1de230637 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_server_socket.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_server_socket.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2018-2018. All Rights Reserved. +%% Copyright Ericsson AB 2018-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -21,23 +21,18 @@ -module(socket_test_ttest_tcp_server_socket). -export([ - start/2, + start/3, stop/1 ]). -define(TRANSPORT_MOD, socket_test_ttest_tcp_socket). -%% -define(MOD(M), {?TRANSPORT_MOD, #{method => M, +%% -define(MOD(D, M), {?TRANSPORT_MOD, #{domain => D, +%% method => M, %% stats_interval => 10000}}). --define(MOD(M), {?TRANSPORT_MOD, #{method => M}}). +-define(MOD(D, M), {?TRANSPORT_MOD, #{domain => D, method => M}}). -start(Method, Active) -> - socket_test_ttest_tcp_server:start(?MOD(Method), Active). - %% {ok, {Pid, AddrPort}} -> - %% MRef = erlang:monitor(process, Pid), - %% {ok, {Pid, MRef, AddrPort}}; - %% {error, _} = ERROR -> - %% ERROR - %% end. +start(Method, Domain, Active) -> + socket_test_ttest_tcp_server:start(?MOD(Domain, Method), Active). stop(Pid) -> socket_test_ttest_tcp_server:stop(Pid). diff --git a/erts/emulator/test/socket_test_ttest_tcp_socket.erl b/erts/emulator/test/socket_test_ttest_tcp_socket.erl index 0ae2412e4c..cf68bfe591 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_socket.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_socket.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2018-2018. All Rights Reserved. +%% Copyright Ericsson AB 2018-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ accept/1, accept/2, active/2, close/1, - connect/2, connect/3, + connect/1, connect/2, connect/3, controlling_process/2, listen/0, listen/1, listen/2, port/1, @@ -36,6 +36,8 @@ ]). +-define(LIB, socket_test_lib). + -define(READER_RECV_TIMEOUT, 1000). -define(DATA_MSG(Sock, Method, Data), @@ -97,37 +99,85 @@ active(#{reader := Pid}, NewActive) close(#{sock := Sock, reader := Pid}) -> Pid ! {?MODULE, stop}, - socket:close(Sock). + Unlink = case socket:sockname(Sock) of + {ok, #{family := local, path := Path}} -> + fun() -> os:cmd("unlink " ++ Path), ok end; + _ -> + fun() -> ok end + end, + Res = socket:close(Sock), + Unlink(), + Res. %% Create a socket and connect it to a peer -connect(Addr, Port) -> - connect(Addr, Port, #{method => plain}). - -connect(Addr, Port, #{method := Method} = Opts) -> +connect(ServerPath) when is_list(ServerPath) -> + Domain = local, + ClientPath = mk_unique_path(), + LocalSA = #{family => Domain, + path => ClientPath}, + ServerSA = #{family => Domain, path => ServerPath}, + Opts = #{domain => Domain, + proto => default, + method => plain}, + Cleanup = fun() -> os:cmd("unlink " ++ ClientPath), ok end, + do_connect(LocalSA, ServerSA, Cleanup, Opts). + +connect(Addr, Port) when is_tuple(Addr) andalso is_integer(Port) -> + Domain = inet, + LocalSA = any, + ServerSA = #{family => Domain, + addr => Addr, + port => Port}, + Opts = #{domain => Domain, + proto => tcp, + method => plain}, + Cleanup = fun() -> ok end, + do_connect(LocalSA, ServerSA, Cleanup, Opts); +connect(ServerPath, + #{domain := local = Domain} = Opts) + when is_list(ServerPath) -> + ClientPath = mk_unique_path(), + LocalSA = #{family => Domain, + path => ClientPath}, + ServerSA = #{family => Domain, + path => ServerPath}, + Cleanup = fun() -> os:cmd("unlink " ++ ClientPath), ok end, + do_connect(LocalSA, ServerSA, Cleanup, Opts#{proto => default}). + +connect(Addr, Port, #{domain := Domain} = Opts) -> + LocalSA = any, + ServerSA = #{family => Domain, + addr => Addr, + port => Port}, + Cleanup = fun() -> ok end, + do_connect(LocalSA, ServerSA, Cleanup, Opts#{proto => tcp}). + +do_connect(LocalSA, ServerSA, Cleanup, #{domain := Domain, + proto := Proto, + method := Method} = Opts) -> try begin Sock = - case socket:open(inet, stream, tcp) of + case socket:open(Domain, stream, Proto) of {ok, S} -> S; {error, OReason} -> throw({error, {open, OReason}}) end, - case socket:bind(Sock, any) of + case socket:bind(Sock, LocalSA) of {ok, _} -> ok; {error, BReason} -> (catch socket:close(Sock)), + Cleanup(), throw({error, {bind, BReason}}) end, - SA = #{family => inet, - addr => Addr, - port => Port}, - case socket:connect(Sock, SA) of + case socket:connect(Sock, ServerSA) of ok -> ok; {error, CReason} -> (catch socket:close(Sock)), + Cleanup(), throw({error, {connect, CReason}}) end, Self = self(), @@ -140,6 +190,9 @@ connect(Addr, Port, #{method := Method} = Opts) -> ERROR end. +mk_unique_path() -> + [NodeName | _] = string:tokens(atom_to_list(node()), [$@]), + ?LIB:f("/tmp/esock_~s_~w", [NodeName, erlang:system_time(nanosecond)]). maybe_start_stats_timer(#{stats_to := Pid, stats_interval := T}, @@ -163,37 +216,57 @@ controlling_process(#{sock := Sock, reader := Pid}, NewPid) -> %% Create a listen socket listen() -> - listen(0, #{method => plain}). - -listen(Port) -> - listen(Port, #{method => plain}). -listen(Port, #{method := Method} = Opts) - when (is_integer(Port) andalso (Port >= 0)) andalso - ((Method =:= plain) orelse (Method =:= msg)) -> + listen(0). + +listen(Port) when is_integer(Port) -> + listen(Port, #{domain => inet, method => plain}); +listen(Path) when is_list(Path) -> + listen(Path, #{domain => local, method => plain}). + +listen(0, #{domain := local} = Opts) -> + listen(mk_unique_path(), Opts); +listen(Path, #{domain := local = Domain} = Opts) + when is_list(Path) andalso (Path =/= []) -> + SA = #{family => Domain, + path => Path}, + Cleanup = fun() -> os:cmd("unlink " ++ Path), ok end, + do_listen(SA, Cleanup, Opts#{proto => default}); +listen(Port, #{domain := Domain} = Opts) + when is_integer(Port) andalso (Port >= 0) -> + %% Bind fills in the rest + SA = #{family => Domain, + port => Port}, + Cleanup = fun() -> ok end, + do_listen(SA, Cleanup, Opts#{proto => tcp}). + +do_listen(SA, + Cleanup, + #{domain := Domain, proto := Proto, method := Method} = Opts) + when (Method =:= plain) orelse (Method =:= msg) -> try begin - Sock = case socket:open(inet, stream, tcp) of + Sock = case socket:open(Domain, stream, Proto) of {ok, S} -> S; {error, OReason} -> throw({error, {open, OReason}}) end, - SA = #{family => inet, - port => Port}, case socket:bind(Sock, SA) of {ok, _} -> ok; {error, BReason} -> (catch socket:close(Sock)), + Cleanup(), throw({error, {bind, BReason}}) end, case socket:listen(Sock) of ok -> - ok; - {error, LReason} -> + ok; + {error, LReason} -> (catch socket:close(Sock)), - throw({error, {listen, LReason}}) - end, + Cleanup(), + throw({error, {listen, LReason}}) + end, {ok, #{sock => Sock, opts => Opts}} end catch @@ -204,6 +277,8 @@ listen(Port, #{method := Method} = Opts) port(#{sock := Sock}) -> case socket:sockname(Sock) of + {ok, #{family := local, path := Path}} -> + {ok, Path}; {ok, #{port := Port}} -> {ok, Port}; {error, _} = ERROR -> @@ -213,6 +288,8 @@ port(#{sock := Sock}) -> peername(#{sock := Sock}) -> case socket:peername(Sock) of + {ok, #{family := local, path := Path}} -> + {ok, Path}; {ok, #{addr := Addr, port := Port}} -> {ok, {Addr, Port}}; {error, _} = ERROR -> diff --git a/erts/etc/unix/etp-commands.in b/erts/etc/unix/etp-commands.in index 66d6d20c4e..730f0a0c64 100644 --- a/erts/etc/unix/etp-commands.in +++ b/erts/etc/unix/etp-commands.in @@ -132,14 +132,14 @@ define etp-1 if (($arg0) & 0x3) == 1 # Cons pointer if $etp_flat - printf "<etpf-cons %#x>", ($arg0) + printf "<etpf-cons %p>", (($arg0)-1) else etp-list-1 ($arg0) ($arg1) end else if (($arg0) & 0x3) == 2 if $etp_flat - printf "<etpf-boxed %#x>", ($arg0) + printf "<etpf-boxed %p>", (($arg0)-2) else etp-boxed-1 ($arg0) ($arg1) end @@ -187,7 +187,7 @@ define etp-list-1 # Reentrant # if (($arg0) & 0x3) != 0x1 - printf "#NotCons<%#x>", ($arg0) + printf "#NotCons<%p>", ($arg0) else # Cons pointer if $etp_chart @@ -210,7 +210,7 @@ define etp-list-printable-1 # Returns: $etp_list_printable # if (($arg0) & 0x3) != 0x1 - printf "#NotCons<%#x>", ($arg0) + printf "#NotCons<%p>", ($arg0) else # Loop to check if it is a printable string set $etp_list_p = ($arg0) @@ -272,7 +272,7 @@ define etp-list-2 # Reentrant # if (($arg0) & 0x3) != 0x1 - printf "#NotCons<%#x>", ($arg0) + printf "#NotCons<%p>", ($arg0) else # Cons pointer if ($arg1) >= $etp_max_depth @@ -307,7 +307,7 @@ define etpf-cons # Reentrant capable # if ((Eterm)($arg0) & 0x3) != 0x1 - printf "#NotCons<%#x>", ($arg0) + printf "#NotCons<%p>", ($arg0) else # Cons pointer set $etp_flat = 1 @@ -336,13 +336,13 @@ define etp-boxed-1 # Reentrant # if (($arg0) & 0x3) != 0x2 - printf "#NotBoxed<%#x>", ($arg0) + printf "#NotBoxed<%p>", ($arg0) else if (((Eterm*)(($arg0) & ~0x3))[0] & 0x3) != 0x0 if $etp_chart etp-chart-entry-1 (($arg0)&~0x3) ($arg1) 1 end - printf "#BoxedError<%#x>", ($arg0) + printf "#BoxedError<%p>", ($arg0) else if $etp_chart etp-chart-entry-1 (($arg0)&~0x3) ($arg1) \ @@ -390,10 +390,10 @@ define etp-boxed-immediate-1 # Non-reentrant # if (($arg0) & 0x3) != 0x2 - printf "#NotBoxed<%#x>", ($arg0) + printf "#NotBoxed<%p>", ($arg0) else if (((Eterm*)(($arg0) & ~0x3))[0] & 0x3) != 0x0 - printf "#BoxedError<%#x>", ($arg0) + printf "#BoxedError<%p>", ($arg0) else set $etp_boxed_immediate_p = (Eterm*)(($arg0) & ~0x3) set $etp_boxed_immediate_h = ($etp_boxed_immediate_p[0] >> 2) & 0xF @@ -438,12 +438,12 @@ define etp-boxed-immediate-1 while $etp_boxed_immediate_arity > 0 set $etp_boxed_immediate_p++ if $etp_boxed_immediate_arity > 1 - printf "%#x,", *$etp_boxed_immediate_p + printf "%p,", *$etp_boxed_immediate_p else - printf "%#x", *$etp_boxed_immediate_p + printf "%p", *$etp_boxed_immediate_p if ($etp_boxed_immediate_h == 0xA) set $etp_boxed_immediate_p++ - printf ":%#x", *$etp_boxed_immediate_p + printf ":%p", *$etp_boxed_immediate_p end printf ">" end @@ -558,7 +558,7 @@ define etp-immediate-1 # Reentrant capable # if (($arg0) & 0x3) != 0x3 - printf "#NotImmediate<%#x>", ($arg0) + printf "#NotImmediate<%p>", ($arg0) else if (($arg0) & 0xF) == 0x3 etp-pid-1 ($arg0) @@ -580,7 +580,7 @@ define etp-immediate-1 if (($arg0) == $etp_nil) printf "[]" else - printf "#UnknownImmediate<%#x>", ($arg0) + printf "#UnknownImmediate<%p>", ($arg0) end end end @@ -598,7 +598,7 @@ define etp-atom-1 # Non-reentrant # if ((Eterm)($arg0) & 0x3f) != 0xb - printf "#NotAtom<%#x>", ($arg0) + printf "#NotAtom<%p>", ($arg0) else set $etp_atom_1_ap = (Atom*)erts_atom_table.seg_table[(Eterm)($arg0)>>16][((Eterm)($arg0)>>6)&0x3FF] set $etp_atom_1_i = ($etp_atom_1_ap)->len @@ -652,7 +652,7 @@ define etp-char-1 # Non-reentrant # if (($arg0) < 0) || (0377 < ($arg0)) - printf "#NotChar<%#x>", ($arg0) + printf "#NotChar<%p>", ($arg0) else if ($arg0) == ($arg1) printf "\\%c", ($arg0) @@ -787,7 +787,7 @@ define etp-pid-1 # Internal pid printf "<0.%u.%u>", $etp_pid_data & 0x7fff, ($etp_pid_data >> 15) & 0x1fff else - printf "#NotPid<%#x>", ($arg0) + printf "#NotPid<%p>", ($arg0) end end @@ -797,11 +797,11 @@ define etp-extpid-1 # Non-reentrant # if ((Eterm)($arg0) & 0x3) != 0x2 - printf "#NotBoxed<%#x>", (Eterm)($arg0) + printf "#NotBoxed<%p>", (Eterm)($arg0) else set $etp_extpid_1_p = (ExternalThing*)((Eterm)($arg0) & ~0x3) if ($etp_extpid_1_p->header & 0x3f) != 0x30 - printf "#NotExternalPid<%#x>", $etp_extpid_1_p->header + printf "#NotExternalPid<%p>", $etp_extpid_1_p->header else ## External pid set $etp_extpid_1_number = $etp_extpid_1_p->data.ui[0]&0x7fff @@ -812,7 +812,7 @@ define etp-extpid-1 set $etp_extpid_1_node = $etp_extpid_1_np->sysname if ($etp_extpid_1_node & 0x3f) != 0xb # Should be an atom - printf "#ExternalPidError<%#x>", ($arg0) + printf "#ExternalPidError<%p>", ($arg0) else if $etp_extpid_1_dep == erts_this_dist_entry printf "<0:" @@ -847,7 +847,7 @@ define etp-port-1 # Internal port printf "#Port<0.%u>", $etp_port_data else - printf "#NotPort<%#x>", ($arg0) + printf "#NotPort<%p>", ($arg0) end end @@ -857,11 +857,11 @@ define etp-extport-1 # Non-reentrant # if ((Eterm)($arg0) & 0x3) != 0x2 - printf "#NotBoxed<%#x>", (Eterm)($arg0) + printf "#NotBoxed<%p>", (Eterm)($arg0) else set $etp_extport_1_p = (ExternalThing*)((Eterm)($arg0) & ~0x3) if ($etp_extport_1_p->header & 0x3F) != 0x34 - printf "#NotExternalPort<%#x>", $etp_extport_1->header + printf "#NotExternalPort<%p>", $etp_extport_1->header else ## External port set $etp_extport_1_number = $etp_extport_1_p->data.ui[0]&0x3ffff @@ -871,7 +871,7 @@ define etp-extport-1 set $etp_extport_1_node = $etp_extport_1_np->sysname if ($etp_extport_1_node & 0x3f) != 0xb # Should be an atom - printf "#ExternalPortError<%#x>", ($arg0) + printf "#ExternalPortError<%p>", ($arg0) else if $etp_extport_1_dep == erts_this_dist_entry printf "#Port<0:" @@ -893,15 +893,15 @@ define etp-bignum-1 # Non-reentrant # if ((Eterm)($arg0) & 0x3) != 0x2 - printf "#NotBoxed<%#x>", (Eterm)($arg0) + printf "#NotBoxed<%p>", (Eterm)($arg0) else set $etp_bignum_1_p = (Eterm*)((Eterm)($arg0) & ~0x3) if ($etp_bignum_1_p[0] & 0x3b) != 0x08 - printf "#NotBignum<%#x>", $etp_bignum_1_p[0] + printf "#NotBignum<%p>", $etp_bignum_1_p[0] else set $etp_bignum_1_i = ($etp_bignum_1_p[0] >> 6) if $etp_bignum_1_i < 1 - printf "#BignumError<%#x>", (Eterm)($arg0) + printf "#BignumError<%p>", (Eterm)($arg0) else if $etp_bignum_1_p[0] & 0x04 printf "-" @@ -932,11 +932,11 @@ define etp-float-1 # Non-reentrant # if ((Eterm)($arg0) & 0x3) != 0x2 - printf "#NotBoxed<%#x>", (Eterm)($arg0) + printf "#NotBoxed<%p>", (Eterm)($arg0) else set $etp_float_1_p = (Eterm*)((Eterm)($arg0) & ~0x3) if ($etp_float_1_p[0] & 0x3f) != 0x18 - printf "#NotFloat<%#x>", $etp_float_1_p[0] + printf "#NotFloat<%p>", $etp_float_1_p[0] else printf "%f", *(double*)($etp_float_1_p+1) end @@ -951,14 +951,14 @@ define etp-ref-1 # Non-reentrant # if ((Eterm)($arg0) & 0x3) != 0x2 - printf "#NotBoxed<%#x>", (Eterm)($arg0) + printf "#NotBoxed<%p>", (Eterm)($arg0) else set $etp_ref_1_p = (ErtsORefThing *)((Eterm)($arg0) & ~0x3) if ($etp_ref_1_p->header & 0x3b) != 0x10 - printf "#NotRef<%#x>", $etp_ref_1_p->header + printf "#NotRef<%p>", $etp_ref_1_p->header else if $etp_ref_1_p->header != etp_ref_header && $etp_ref_1_p->header != etp_magic_ref_header - printf "#InternalRefError<%#x>", ($arg0) + printf "#InternalRefError<%p>", ($arg0) else set $etp_magic_ref = 0 set $etp_ref_1_i = 3 @@ -998,11 +998,11 @@ define etp-extref-1 # Non-reentrant # if ((Eterm)($arg0) & 0x3) != 0x2 - printf "#NotBoxed<%#x>", (Eterm)($arg0) + printf "#NotBoxed<%p>", (Eterm)($arg0) else set $etp_extref_1_p = (ExternalThing*)((Eterm)($arg0) & ~0x3) if ($etp_extref_1_p->header & 0x3F) != 0x38 - printf "#NotExternalRef<%#x>", $etp_extref_1->header + printf "#NotExternalRef<%p>", $etp_extref_1->header else ## External ref set $etp_extref_1_nump = (Uint32 *) 0 @@ -1041,7 +1041,7 @@ define etp-extref-1 end end if $etp_extref_1_error - printf "#ExternalRefError<%#x>", ($arg0) + printf "#ExternalRefError<%p>", ($arg0) else set $etp_extref_1_i-- while $etp_extref_1_i >= 0 @@ -1166,7 +1166,7 @@ define etp-cp-1 if *(Eterm*)($etp_cp) == beam_return_to_trace[0] printf "#Cp<return to trace>" else - printf "#Cp<%#x>", $etp_cp + printf "#Cp<%p>", $etp_cp end end end @@ -1743,7 +1743,7 @@ define etp-term-dump-pid # Internal pid printf "| <0.%04u.%03u> ", $etp_pid_data & 0x7fff, ($etp_pid_data >> 15) & 0x1fff else - printf "| #NotPid<%#x> ", ($arg0) + printf "| #NotPid<%p> ", ($arg0) end end @@ -3324,7 +3324,7 @@ define etp-offheapdump set $etp_offheapdump_p = $etp_offheapdump_p->next set $etp_offheapdump_i++ else - printf "#TaggedPtr<%#x>", $etp_offheapdump_p + printf "#TaggedPtr<%p>", $etp_offheapdump_p set $etp_offheapdump_p = 0 end end @@ -3363,12 +3363,12 @@ define etp-search-heaps # # Non-reentrant # - printf "%% Search all (<%u) process heaps for ", erts_max_processes + printf "%% Search all (<%u) process heaps for ", erts_proc.r.o.max set $etp_flat = 1 etp-1 ($arg0) 0 set $etp_flat = 0 printf ":...\n" - etp-search-heaps-1 ((Eterm*)((Eterm)($arg0)&~3)) + etp-search-heaps-1 ((Eterm*)((Eterm)($arg0)&~(Eterm)3)) end define etp-search-heaps-1 @@ -3376,8 +3376,8 @@ define etp-search-heaps-1 # # Non-reentrant # - set $etp_search_heaps_q = erts_max_processes / 10 - set $etp_search_heaps_r = erts_max_processes % 10 + set $etp_search_heaps_q = erts_proc.r.o.max / 10 + set $etp_search_heaps_r = erts_proc.r.o.max % 10 set $etp_search_heaps_t = 10 set $etp_search_heaps_m = $etp_search_heaps_q if $etp_search_heaps_r > 0 @@ -3387,7 +3387,7 @@ define etp-search-heaps-1 set $etp_search_heaps_i = 0 set $etp_search_heaps_found = 0 while $etp_search_heaps_i < erts_proc.r.o.max - set $proc = (Process *) *((UWord *) &erts_proc.r.o.tab[$proc_ix]) + set $proc = (Process *) *((UWord *) &erts_proc.r.o.tab[$etp_search_heaps_i]) if $proc if ($proc->heap <= ($arg0)) && \ (($arg0) < $proc->hend) @@ -3404,7 +3404,7 @@ define etp-search-heaps-1 while $etp_search_heaps_p && ($etp_search_heaps_cnt < $etp_max_depth) set $etp_search_heaps_cnt++ if (&($etp_search_heaps_p->mem) <= ($arg0)) && \ - (($arg0) < &($etp_search_heaps_p->mem)+$etp_search_heaps_p->size) + (($arg0) < &($etp_search_heaps_p->mem)+$etp_search_heaps_p->used_size) printf "process_tab[%d]->mbuf(%d)+%d\n", \ $etp_search_heaps_i, $etp_search_heaps_cnt, \ ($arg0)-&($etp_search_heaps_p->mem) @@ -3700,8 +3700,8 @@ define etp-overlapped-heaps # Non-reentrant # printf "%% Dumping heap addresses to \"etp-commands.bin\"\n" - set $etp_overlapped_heaps_q = erts_max_processes / 10 - set $etp_overlapped_heaps_r = erts_max_processes % 10 + set $etp_overlapped_heaps_q = erts_proc.r.o.max / 10 + set $etp_overlapped_heaps_r = erts_proc.r.o.max % 10 set $etp_overlapped_heaps_t = 10 set $etp_overlapped_heaps_m = $etp_overlapped_heaps_q if $etp_overlapped_heaps_r > 0 @@ -3727,7 +3727,7 @@ define etp-overlapped-heaps append binary value etp-commands.bin 'p' append binary value etp-commands.bin 's' append binary value etp-commands.bin '\0' - while $etp_overlapped_heaps_i < erts_max_processes + while $etp_overlapped_heaps_i < erts_proc.r.o.max if process_tab[$etp_overlapped_heaps_i] append binary value etp-commands.bin \ (Eterm)$etp_overlapped_heaps_i @@ -3868,7 +3868,7 @@ define etp-chart-entry-1 append binary value etp-commands.bin (Eterm)(($arg2)*sizeof(Eterm)) append binary value etp-commands.bin (Eterm)$etp_chart_id append binary value etp-commands.bin (Eterm)($arg1) -# printf "<dumped %#x %lu %lu %lu>", ($arg0)&~0x3, \ +# printf "<dumped %p %lu %lu %lu>", ($arg0)&~0x3, \ # (Eterm)(($arg2)*sizeof(Eterm)), (Eterm)$etp_chart_id, (Eterm)($arg1) end diff --git a/erts/preloaded/ebin/atomics.beam b/erts/preloaded/ebin/atomics.beam Binary files differindex ef402b5fee..c74ce3ce2d 100644 --- a/erts/preloaded/ebin/atomics.beam +++ b/erts/preloaded/ebin/atomics.beam diff --git a/erts/preloaded/ebin/counters.beam b/erts/preloaded/ebin/counters.beam Binary files differindex 674d0d27fa..2aec433bcb 100644 --- a/erts/preloaded/ebin/counters.beam +++ b/erts/preloaded/ebin/counters.beam diff --git a/erts/preloaded/ebin/erl_init.beam b/erts/preloaded/ebin/erl_init.beam Binary files differindex 0313988e3e..0c032e8e91 100644 --- a/erts/preloaded/ebin/erl_init.beam +++ b/erts/preloaded/ebin/erl_init.beam diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex 661bcd8413..13fdd7908b 100644 --- a/erts/preloaded/ebin/erl_prim_loader.beam +++ b/erts/preloaded/ebin/erl_prim_loader.beam diff --git a/erts/preloaded/ebin/erl_tracer.beam b/erts/preloaded/ebin/erl_tracer.beam Binary files differindex ec4d6153d1..16e17b870b 100644 --- a/erts/preloaded/ebin/erl_tracer.beam +++ b/erts/preloaded/ebin/erl_tracer.beam diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex 62dc8702e7..866f9df79f 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/erts_code_purger.beam b/erts/preloaded/ebin/erts_code_purger.beam Binary files differindex 669149df82..d81bc08282 100644 --- a/erts/preloaded/ebin/erts_code_purger.beam +++ b/erts/preloaded/ebin/erts_code_purger.beam diff --git a/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam b/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam Binary files differindex 6d3528c2dc..a8d492dfa5 100644 --- a/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam +++ b/erts/preloaded/ebin/erts_dirty_process_signal_handler.beam diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam Binary files differindex b3af713809..dd08111aad 100644 --- a/erts/preloaded/ebin/erts_internal.beam +++ b/erts/preloaded/ebin/erts_internal.beam diff --git a/erts/preloaded/ebin/erts_literal_area_collector.beam b/erts/preloaded/ebin/erts_literal_area_collector.beam Binary files differindex fc2bf6f6bd..0f7dd6efbe 100644 --- a/erts/preloaded/ebin/erts_literal_area_collector.beam +++ b/erts/preloaded/ebin/erts_literal_area_collector.beam diff --git a/erts/preloaded/ebin/init.beam b/erts/preloaded/ebin/init.beam Binary files differindex 1d89174b25..942f29a11c 100644 --- a/erts/preloaded/ebin/init.beam +++ b/erts/preloaded/ebin/init.beam diff --git a/erts/preloaded/ebin/net.beam b/erts/preloaded/ebin/net.beam Binary files differindex f61b2b4a69..88d546a3af 100644 --- a/erts/preloaded/ebin/net.beam +++ b/erts/preloaded/ebin/net.beam diff --git a/erts/preloaded/ebin/persistent_term.beam b/erts/preloaded/ebin/persistent_term.beam Binary files differindex c882e4fad4..7871b64991 100644 --- a/erts/preloaded/ebin/persistent_term.beam +++ b/erts/preloaded/ebin/persistent_term.beam diff --git a/erts/preloaded/ebin/prim_buffer.beam b/erts/preloaded/ebin/prim_buffer.beam Binary files differindex cf671bf8f4..90d9596fe6 100644 --- a/erts/preloaded/ebin/prim_buffer.beam +++ b/erts/preloaded/ebin/prim_buffer.beam diff --git a/erts/preloaded/ebin/prim_eval.beam b/erts/preloaded/ebin/prim_eval.beam Binary files differindex 24911123f9..19935eeee3 100644 --- a/erts/preloaded/ebin/prim_eval.beam +++ b/erts/preloaded/ebin/prim_eval.beam diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam Binary files differindex 0efd954e50..a2c5f2f336 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex ff9268ad38..b7c4cbe0a8 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/ebin/prim_zip.beam b/erts/preloaded/ebin/prim_zip.beam Binary files differindex d319d7a343..bd51c3b271 100644 --- a/erts/preloaded/ebin/prim_zip.beam +++ b/erts/preloaded/ebin/prim_zip.beam diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam Binary files differindex 558a886565..e37aa81b7c 100644 --- a/erts/preloaded/ebin/socket.beam +++ b/erts/preloaded/ebin/socket.beam diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex 9610c94ac2..8b7c5fe2ef 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index 126db66cdd..0f0d8f7a02 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -602,12 +602,13 @@ %% -define(SOCKET_TYPE_RDM, 4). -define(SOCKET_TYPE_SEQPACKET, 5). --define(SOCKET_PROTOCOL_IP, 1). --define(SOCKET_PROTOCOL_TCP, 2). --define(SOCKET_PROTOCOL_UDP, 3). --define(SOCKET_PROTOCOL_SCTP, 4). --define(SOCKET_PROTOCOL_ICMP, 5). --define(SOCKET_PROTOCOL_IGMP, 6). +-define(SOCKET_PROTOCOL_DEFAULT, 0). +-define(SOCKET_PROTOCOL_IP, 1). +-define(SOCKET_PROTOCOL_TCP, 2). +-define(SOCKET_PROTOCOL_UDP, 3). +-define(SOCKET_PROTOCOL_SCTP, 4). +-define(SOCKET_PROTOCOL_ICMP, 5). +-define(SOCKET_PROTOCOL_IGMP, 6). -define(SOCKET_LISTEN_BACKLOG_DEFAULT, 5). @@ -820,6 +821,7 @@ -define(SOCKET_SUPPORTS_OPTIONS, 16#0001). -define(SOCKET_SUPPORTS_SCTP, 16#0002). -define(SOCKET_SUPPORTS_IPV6, 16#0003). +-define(SOCKET_SUPPORTS_LOCAL, 16#0004). %% =========================================================================== @@ -875,18 +877,21 @@ info() -> -spec supports() -> [{options, supports_options()} | {sctp, boolean()} | - {ipv6, boolean()}]. + {ipv6, boolean()} | + {local, boolean()}]. supports() -> [{options, supports(options)}, {sctp, supports(sctp)}, - {ipv6, supports(ipv6)}]. + {ipv6, supports(ipv6)}, + {local, supports(local)}]. -dialyzer({nowarn_function, supports/1}). -spec supports(options) -> supports_options(); (sctp) -> boolean(); (ipv6) -> boolean(); + (local) -> boolean(); (Key1) -> false when Key1 :: term(). @@ -896,6 +901,8 @@ supports(sctp) -> nif_supports(?SOCKET_SUPPORTS_SCTP); supports(ipv6) -> nif_supports(?SOCKET_SUPPORTS_IPV6); +supports(local) -> + nif_supports(?SOCKET_SUPPORTS_LOCAL); supports(_Key1) -> false. @@ -1006,12 +1013,12 @@ supports(_Key1, _Key2, _Key3) -> Reason :: term(). open(Domain, Type) -> - open(Domain, Type, null). + open(Domain, Type, default). -spec open(Domain, Type, Protocol) -> {ok, Socket} | {error, Reason} when Domain :: domain(), Type :: type(), - Protocol :: null | protocol(), + Protocol :: default | protocol(), Socket :: socket(), Reason :: term(). @@ -1021,15 +1028,14 @@ open(Domain, Type, Protocol) -> -spec open(Domain, Type, Protocol, Extra) -> {ok, Socket} | {error, Reason} when Domain :: domain(), Type :: type(), - Protocol :: null | protocol(), + Protocol :: default | protocol(), Extra :: map(), Socket :: socket(), Reason :: term(). -open(Domain, Type, Protocol0, Extra) when is_map(Extra) -> +open(Domain, Type, Protocol, Extra) when is_map(Extra) -> try begin - Protocol = default_protocol(Protocol0, Type), EDomain = enc_domain(Domain), EType = enc_type(Domain, Type), EProtocol = enc_protocol(Type, Protocol), @@ -1052,15 +1058,6 @@ open(Domain, Type, Protocol0, Extra) when is_map(Extra) -> {error, Reason} end. -%% Note that this is just a convenience function for when the protocol was -%% not specified. If its actually specified, then that will be selected. -%% Also, this only works for the some of the type's (stream, dgram and -%% seqpacket). -default_protocol(null, stream) -> tcp; -default_protocol(null, dgram) -> udp; -default_protocol(null, seqpacket) -> sctp; -default_protocol(null, Type) -> throw({error, {no_default_protocol, Type}}); -default_protocol(Protocol, _) -> Protocol. %% =========================================================================== @@ -2355,7 +2352,7 @@ peername(#socket{ref = SockRef}) -> enc_domain(local) -> ?SOCKET_DOMAIN_LOCAL; enc_domain(inet) -> ?SOCKET_DOMAIN_INET; enc_domain(inet6) -> ?SOCKET_DOMAIN_INET6; -enc_domain(Domain) -> throw({error, {invalid_domain, Domain}}). +enc_domain(Domain) -> invalid_domain(Domain). -spec enc_type(Domain, Type) -> non_neg_integer() when Domain :: domain(), @@ -2366,22 +2363,23 @@ enc_type(_, stream) -> ?SOCKET_TYPE_STREAM; enc_type(_, dgram) -> ?SOCKET_TYPE_DGRAM; enc_type(_, raw) -> ?SOCKET_TYPE_RAW; enc_type(_, seqpacket) -> ?SOCKET_TYPE_SEQPACKET; -enc_type(_, Type) -> throw({error, {invalid_type, Type}}). +enc_type(_, Type) -> invalid_type(Type). -spec enc_protocol(Type, Protocol) -> non_neg_integer() | {raw, non_neg_integer()} when Type :: type(), Protocol :: protocol(). -enc_protocol(dgram, ip) -> ?SOCKET_PROTOCOL_IP; -enc_protocol(stream, tcp) -> ?SOCKET_PROTOCOL_TCP; -enc_protocol(dgram, udp) -> ?SOCKET_PROTOCOL_UDP; -enc_protocol(seqpacket, sctp) -> ?SOCKET_PROTOCOL_SCTP; -enc_protocol(raw, icmp) -> ?SOCKET_PROTOCOL_ICMP; -enc_protocol(raw, igmp) -> ?SOCKET_PROTOCOL_IGMP; +enc_protocol(_, default) -> ?SOCKET_PROTOCOL_DEFAULT; +enc_protocol(dgram, ip) -> ?SOCKET_PROTOCOL_IP; +enc_protocol(stream, tcp) -> ?SOCKET_PROTOCOL_TCP; +enc_protocol(dgram, udp) -> ?SOCKET_PROTOCOL_UDP; +enc_protocol(seqpacket, sctp) -> ?SOCKET_PROTOCOL_SCTP; +enc_protocol(raw, icmp) -> ?SOCKET_PROTOCOL_ICMP; +enc_protocol(raw, igmp) -> ?SOCKET_PROTOCOL_IGMP; enc_protocol(raw, {raw, P} = RAW) when is_integer(P) -> RAW; enc_protocol(Type, Proto) -> - throw({error, {invalid_protocol, {Type, Proto}}}). + invalid_protocol(Type, Proto). -spec enc_send_flags(Flags) -> non_neg_integer() when @@ -2532,7 +2530,7 @@ enc_setopt_value(otp, rcvbuf, V, _, _, _) when is_integer(V) andalso (V > 0) -> V; %% N: Number of reads (when specifying length = 0) %% V: Size of the "read" buffer -enc_setopt_value(otp, rcvbuf, {N, BufSz} = V, _, stream = _T, tcp = _P) +enc_setopt_value(otp, rcvbuf, {N, BufSz} = V, _, stream = _T, _P) when (is_integer(N) andalso (N > 0)) andalso (is_integer(BufSz) andalso (BufSz > 0)) -> V; @@ -3510,6 +3508,25 @@ tdiff(T1, T2) -> %% %% =========================================================================== +-spec invalid_domain(Domain) -> no_return() when + Domain :: term(). + +invalid_domain(Domain) -> + error({invalid_domain, Domain}). + +-spec invalid_type(Type) -> no_return() when + Type :: term(). + +invalid_type(Type) -> + error({invalid_type, Type}). + +-spec invalid_protocol(Type, Proto) -> no_return() when + Type :: term(), + Proto :: term(). + +invalid_protocol(Type, Proto) -> + error({invalid_protocol, {Type, Proto}}). + -spec not_supported(What) -> no_return() when What :: term(). |