diff options
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/beam/beam_load.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/bif.c | 6 | ||||
-rw-r--r-- | erts/emulator/beam/bif_instrs.tab | 114 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 41 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.h | 23 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif_api_funcs.h | 3 | ||||
-rw-r--r-- | erts/emulator/beam/ops.tab | 30 | ||||
-rw-r--r-- | erts/emulator/nifs/common/net_nif.c | 181 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_int.h | 412 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 2459 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_util.c | 2 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE.erl | 43 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 33 | ||||
-rw-r--r-- | erts/emulator/test/socket_SUITE.erl | 1 | ||||
-rw-r--r-- | erts/emulator/test/socket_test_evaluator.erl | 2 | ||||
-rw-r--r-- | erts/emulator/test/trace_local_SUITE.erl | 4 |
16 files changed, 1598 insertions, 1758 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 43adf7a5e0..0ad5329b2f 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -1425,7 +1425,7 @@ load_atom_table(LoaderState* stp, ErtsAtomEncoding enc) ap = atom_tab(atom_val(stp->atom[1])); sys_memcpy(sbuf, ap->name, ap->len); sbuf[ap->len] = '\0'; - LoadError1(stp, "module name in object code is %s", sbuf); + LoadError1(stp, "BEAM file exists but it defines a module named %s", sbuf); } return 1; diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 7faba35e1c..c102ddbee6 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -5165,6 +5165,12 @@ erts_schedule_bif(Process *proc, pc = i; mfa = &exp->info.mfa; } + else if (BeamIsOpCode(*i, op_call_bif_only_e)) { + /* Pointer to bif export in i+1 */ + exp = (Export *) i[1]; + pc = i; + mfa = &exp->info.mfa; + } else if (BeamIsOpCode(*i, op_apply_bif)) { /* Pointer to bif in i+1, and mfa in i-3 */ pc = c_p->cp; diff --git a/erts/emulator/beam/bif_instrs.tab b/erts/emulator/beam/bif_instrs.tab index 8499f61114..8e0caa38a3 100644 --- a/erts/emulator/beam/bif_instrs.tab +++ b/erts/emulator/beam/bif_instrs.tab @@ -209,8 +209,8 @@ i_length.execute(Fail, Live, Dst) { } // -// The most general BIF call. The BIF may build any amount of data -// on the heap. The result is always returned in r(0). +// Call a BIF, store the result in x(0) and transfer control to the +// next instruction. // call_bif(Exp) { ErtsBifFunc bf; @@ -219,8 +219,10 @@ call_bif(Exp) { Export *export = (Export*) $Exp; if (!((FCALLS - 1) > 0 || (FCALLS-1) > neg_o_reds)) { - /* If we have run out of reductions, we do a context - switch before calling the bif */ + /* + * If we have run out of reductions, do a context + * switch before calling the BIF. + */ c_p->arity = GET_BIF_ARITY(export); c_p->current = &export->info.mfa; goto context_switch3; @@ -257,9 +259,12 @@ call_bif(Exp) { HTOP = HEAP_TOP(c_p); FCALLS = c_p->fcalls; ERTS_DBG_CHK_REDS(c_p, FCALLS); - /* We have to update the cache if we are enabled in order - to make sure no book keeping is done after we disabled - msacc. We don't always do this as it is quite expensive. */ + + /* + * We have to update the cache if we are enabled in order + * to make sure no bookkeeping is done after we disabled + * msacc. We don't always do this as it is quite expensive. + */ if (ERTS_MSACC_IS_ENABLED_CACHED_X()) { ERTS_MSACC_UPDATE_CACHE_X(); } @@ -269,6 +274,12 @@ call_bif(Exp) { CHECK_TERM(r(0)); $NEXT0(); } else if (c_p->freason == TRAP) { + /* + * Set the continuation pointer to return to next + * instruction after the trap (either by a return from + * erlang code or by nif_bif.epilogue() when the BIF + * is done). + */ SET_CP(c_p, $NEXT_INSTRUCTION); SET_I(c_p->i); SWAPIN; @@ -281,6 +292,95 @@ call_bif(Exp) { ASSERT(c_p->stop == E); I = handle_error(c_p, I, reg, &export->info.mfa); goto post_error_handling; + //| -no_next +} + +// +// Call a BIF tail-recursively, storing the result in x(0) and doing +// a return to the continuation poiner (c_p->cp). +// + +call_bif_only(Exp) { + ErtsBifFunc bf; + Eterm result; + ErlHeapFragment *live_hf_end; + Export *export = (Export*) $Exp; + + if (!((FCALLS - 1) > 0 || (FCALLS-1) > neg_o_reds)) { + /* + * If we have run out of reductions, do a context + * switch before calling the BIF. + */ + c_p->arity = GET_BIF_ARITY(export); + c_p->current = &export->info.mfa; + goto context_switch3; + } + + ERTS_MSACC_SET_BIF_STATE_CACHED_X(GET_BIF_MODULE(export), + GET_BIF_ADDRESS(export)); + + bf = GET_BIF_ADDRESS(export); + + PRE_BIF_SWAPOUT(c_p); + ERTS_DBG_CHK_REDS(c_p, FCALLS); + c_p->fcalls = FCALLS - 1; + if (FCALLS <= 0) { + save_calls(c_p, export); + } + ASSERT(!ERTS_PROC_IS_EXITING(c_p)); + ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); + live_hf_end = c_p->mbuf; + ERTS_CHK_MBUF_SZ(c_p); + result = (*bf)(c_p, reg, I); + ERTS_CHK_MBUF_SZ(c_p); + ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result)); + ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); + ERTS_HOLE_CHECK(c_p); + ERTS_REQ_PROC_MAIN_LOCK(c_p); + if (ERTS_IS_GC_DESIRED(c_p)) { + Uint arity = GET_BIF_ARITY(export); + result = erts_gc_after_bif_call_lhf(c_p, live_hf_end, result, + reg, arity); + E = c_p->stop; + } + PROCESS_MAIN_CHK_LOCKS(c_p); + HTOP = HEAP_TOP(c_p); + FCALLS = c_p->fcalls; + ERTS_DBG_CHK_REDS(c_p, FCALLS); + + /* + * We have to update the cache if we are enabled in order + * to make sure no bookkeeping is done after we disabled + * msacc. We don't always do this as it is quite expensive. + */ + if (ERTS_MSACC_IS_ENABLED_CACHED_X()) { + ERTS_MSACC_UPDATE_CACHE_X(); + } + ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_EMULATOR); + if (ERTS_LIKELY(is_value(result))) { + /* + * Success. Store the result and return to the caller. + */ + r(0) = result; + CHECK_TERM(r(0)); + $return(); + } else if (c_p->freason == TRAP) { + /* + * Dispatch to a trap. When the trap is done, a jump + * to the continuation pointer (c_p->cp) will be done. + */ + SET_I(c_p->i); + SWAPIN; + Dispatch(); + } + + /* + * Error handling. SWAPOUT is not needed because it was done above. + */ + ASSERT(c_p->stop == E); + I = handle_error(c_p, I, reg, &export->info.mfa); + goto post_error_handling; + //| -no_next } // diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 5a3cdf980d..af1acbfc90 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -1175,6 +1175,47 @@ int enif_is_number(ErlNifEnv* env, ERL_NIF_TERM term) return is_number(term); } +ErlNifTermType enif_term_type(ErlNifEnv* env, ERL_NIF_TERM term) { + (void)env; + + switch (tag_val_def(term)) { + case ATOM_DEF: + return ERL_NIF_TERM_TYPE_ATOM; + case BINARY_DEF: + return ERL_NIF_TERM_TYPE_BITSTRING; + case FLOAT_DEF: + return ERL_NIF_TERM_TYPE_FLOAT; + case EXPORT_DEF: + case FUN_DEF: + return ERL_NIF_TERM_TYPE_FUN; + case BIG_DEF: + case SMALL_DEF: + return ERL_NIF_TERM_TYPE_INTEGER; + case LIST_DEF: + case NIL_DEF: + return ERL_NIF_TERM_TYPE_LIST; + case MAP_DEF: + return ERL_NIF_TERM_TYPE_MAP; + case EXTERNAL_PID_DEF: + case PID_DEF: + return ERL_NIF_TERM_TYPE_PID; + case EXTERNAL_PORT_DEF: + case PORT_DEF: + return ERL_NIF_TERM_TYPE_PORT; + case EXTERNAL_REF_DEF: + case REF_DEF: + return ERL_NIF_TERM_TYPE_REFERENCE; + case TUPLE_DEF: + return ERL_NIF_TERM_TYPE_TUPLE; + default: + /* tag_val_def() aborts on its own when passed complete garbage, but + * it's possible that the user has given us garbage that just happens + * to match something that tag_val_def() accepts but we don't, like + * binary match contexts. */ + ERTS_INTERNAL_ERROR("Invalid term passed to enif_term_type"); + } +} + static void aligned_binary_dtor(struct enif_tmp_obj_t* obj) { erts_free_aligned_binary_bytes_extra((byte*)obj, obj->allocator); diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index 3fd1a8fd4c..a599511c78 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -55,6 +55,7 @@ ** 2.14: 21.0 add enif_ioq_peek_head, enif_(mutex|cond|rwlock|thread)_name ** enif_vfprintf, enif_vsnprintf, enif_make_map_from_arrays ** 2.15: 22.0 ERL_NIF_SELECT_CANCEL, enif_select_(read|write) +** enif_term_type */ #define ERL_NIF_MAJOR_VERSION 2 #define ERL_NIF_MINOR_VERSION 15 @@ -63,7 +64,7 @@ * with ticket syntax like "erts-@OTP-12345@", or a temporary placeholder * between two @ like "erts-@MyName@", if you don't know what a ticket is. */ -#define ERL_NIF_MIN_ERTS_VERSION "erts-@OTP-15095@ (OTP-22)" +#define ERL_NIF_MIN_ERTS_VERSION "erts-@OTP-15095 OTP-15640@ (OTP-22)" /* * The emulator will refuse to load a nif-lib with a major version @@ -282,6 +283,26 @@ typedef enum { ERL_NIF_IOQ_NORMAL = 1 } ErlNifIOQueueOpts; +typedef enum { + ERL_NIF_TERM_TYPE_ATOM = 1, + ERL_NIF_TERM_TYPE_BITSTRING = 2, + ERL_NIF_TERM_TYPE_FLOAT = 3, + ERL_NIF_TERM_TYPE_FUN = 4, + ERL_NIF_TERM_TYPE_INTEGER = 5, + ERL_NIF_TERM_TYPE_LIST = 6, + ERL_NIF_TERM_TYPE_MAP = 7, + ERL_NIF_TERM_TYPE_PID = 8, + ERL_NIF_TERM_TYPE_PORT = 9, + ERL_NIF_TERM_TYPE_REFERENCE = 10, + ERL_NIF_TERM_TYPE_TUPLE = 11, + + /* This is a dummy value intended to coax the compiler into warning about + * unhandled values in a switch even if all the above values have been + * handled. We can add new entries at any time so the user must always + * have a default case. */ + ERL_NIF_TERM_TYPE__MISSING_DEFAULT_CASE__READ_THE_MANUAL = -1 +} ErlNifTermType; + /* * Return values from enif_thread_type(). Negative values * reserved for specific types of non-scheduler threads. diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h index 8ab454c8dd..d57f6ec97c 100644 --- a/erts/emulator/beam/erl_nif_api_funcs.h +++ b/erts/emulator/beam/erl_nif_api_funcs.h @@ -215,6 +215,8 @@ ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_monitor_term,(ErlNifEnv* env, const ERL_NIF_API_FUNC_DECL(void,enif_set_pid_undefined,(ErlNifPid* pid)); ERL_NIF_API_FUNC_DECL(int,enif_is_pid_undefined,(const ErlNifPid* pid)); +ERL_NIF_API_FUNC_DECL(ErlNifTermType,enif_term_type,(ErlNifEnv* env, ERL_NIF_TERM term)); + /* ** ADD NEW ENTRIES HERE (before this comment) !!! */ @@ -401,6 +403,7 @@ ERL_NIF_API_FUNC_DECL(int,enif_is_pid_undefined,(const ErlNifPid* pid)); # define enif_make_monitor_term ERL_NIF_API_FUNC_MACRO(enif_make_monitor_term) # define enif_set_pid_undefined ERL_NIF_API_FUNC_MACRO(enif_set_pid_undefined) # define enif_is_pid_undefined ERL_NIF_API_FUNC_MACRO(enif_is_pid_undefined) +# define enif_term_type ERL_NIF_API_FUNC_MACRO(enif_term_type) /* ** ADD NEW ENTRIES HERE (before this comment) diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab index e688c6996b..da5364183c 100644 --- a/erts/emulator/beam/ops.tab +++ b/erts/emulator/beam/ops.tab @@ -74,23 +74,19 @@ trace_jump W return +# To ensure that a "move Src x(0)" instruction can be combined with +# the following call instruction, we need to make sure that there is +# no line/1 instruction between the move and the call. # -# To ensure that a "move Src x(0)" instruction can be combined -# with the following call instruction, we need to make sure that -# there is no line/1 instruction between the move and the call. -# -# A tail-recursive call to an external function (non-BIF) will -# never be saved on the stack, so there is no reason to keep -# the line instruction. (The compiler did not remove the line -# instruction because it cannot tell the difference between -# BIFs and ordinary Erlang functions.) -# +# A tail-recursive call to an external function (BIF or non-BIF) will +# never be saved on the stack, so there is no reason to keep the line +# instruction. move S X0=x==0 | line Loc | call_ext Ar Func => \ line Loc | move S X0 | call_ext Ar Func -move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_not_bif D => \ +move S X0=x==0 | line Loc | call_ext_last Ar Func D => \ move S X0 | call_ext_last Ar Func D -move S X0=x==0 | line Loc | call_ext_only Ar Func=u$is_not_bif => \ +move S X0=x==0 | line Loc | call_ext_only Ar Func => \ move S X0 | call_ext_only Ar Func move S X0=x==0 | line Loc | call Ar Func => \ line Loc | move S X0 | call Ar Func @@ -102,9 +98,9 @@ line I allocate t t? allocate_heap t I t? -%cold +# This instruction when a BIF is called tail-recursively when +# ther is stack frame. deallocate Q -%hot init y allocate_zero t t? @@ -985,10 +981,9 @@ call_ext_only u==0 u$func:os:perf_counter/0 => \ call_ext u Bif=u$is_bif => call_bif Bif -call_ext_last u Bif=u$is_bif D => call_bif Bif | deallocate_return D +call_ext_last u Bif=u$is_bif D => deallocate D | call_bif_only Bif -call_ext_only Ar=u Bif=u$is_bif => \ - allocate u Ar | call_bif Bif | deallocate_return u +call_ext_only Ar=u Bif=u$is_bif => call_bif_only Bif # # Any remaining calls are calls to Erlang functions, not BIFs. @@ -1020,6 +1015,7 @@ i_perf_counter %hot call_bif e +call_bif_only e # # Calls to non-building and guard BIFs. diff --git a/erts/emulator/nifs/common/net_nif.c b/erts/emulator/nifs/common/net_nif.c index 9a18ed3b15..6c91bd74bd 100644 --- a/erts/emulator/nifs/common/net_nif.c +++ b/erts/emulator/nifs/common/net_nif.c @@ -240,35 +240,37 @@ static NetData data; /* THIS IS JUST TEMPORARY */ extern char* erl_errno_id(int error); +/* All the nif "callback" functions for the net API has + * the exact same API: + * + * nif_<funcname>(ErlNifEnv* env, + * int argc, + * const ERL_NIF_TERM argv[]); + * + * So, to simplify, use some macro magic to define those. + * + * These are the functions making up the "official" API. + */ -static ERL_NIF_TERM nif_info(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_command(ErlNifEnv* env, - int argc, +#define ENET_NIF_FUNCS \ + ENET_NIF_FUNC_DEF(info); \ + ENET_NIF_FUNC_DEF(command); \ + ENET_NIF_FUNC_DEF(gethostname); \ + ENET_NIF_FUNC_DEF(getnameinfo); \ + ENET_NIF_FUNC_DEF(getaddrinfo); \ + ENET_NIF_FUNC_DEF(if_name2index); \ + ENET_NIF_FUNC_DEF(if_index2name); \ + ENET_NIF_FUNC_DEF(if_names); + +#define ENET_NIF_FUNC_DEF(F) \ + static ERL_NIF_TERM nif_##F(ErlNifEnv* env, \ + int argc, \ const ERL_NIF_TERM argv[]); +ENET_NIF_FUNCS +#undef ENET_NIF_FUNC_DEF -static ERL_NIF_TERM nif_gethostname(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); - -static ERL_NIF_TERM nif_getnameinfo(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_getaddrinfo(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); - -static ERL_NIF_TERM nif_if_name2index(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_if_index2name(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_if_names(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); +/* And here comes the functions that does the actual work (for the most part) */ static ERL_NIF_TERM ncommand(ErlNifEnv* env, ERL_NIF_TERM cmd); static ERL_NIF_TERM ngethostname(ErlNifEnv* env); @@ -359,66 +361,42 @@ static const struct in6_addr in6addr_loopback = -/* *** String constants *** */ -static char str_address_info[] = "address_info"; -static char str_debug[] = "debug"; -static char str_idn[] = "idn"; -static char str_idna_allow_unassigned[] = "idna_allow_unassigned"; -static char str_idna_use_std3_ascii_rules[] = "idna_use_std3_ascii_rules"; -static char str_namereqd[] = "namereqd"; -static char str_name_info[] = "name_info"; -static char str_nofqdn[] = "nofqdn"; -static char str_numerichost[] = "numerichost"; -static char str_numericserv[] = "numericserv"; - -/* (special) error string constants */ -static char str_eaddrfamily[] = "eaddrfamily"; -static char str_ebadflags[] = "ebadflags"; -static char str_efail[] = "efail"; -static char str_efamily[] = "efamily"; -static char str_efault[] = "efault"; -static char str_emem[] = "emem"; -static char str_enametoolong[] = "enametoolong"; -static char str_enodata[] = "enodata"; -static char str_enoname[] = "enoname"; -static char str_enxio[] = "enxio"; -static char str_eoverflow[] = "eoverflow"; -static char str_eservice[] = "eservice"; -static char str_esocktype[] = "esocktype"; -static char str_esystem[] = "esystem"; - - -/* *** Atoms *** */ - -static ERL_NIF_TERM atom_address_info; -static ERL_NIF_TERM atom_debug; -static ERL_NIF_TERM atom_host; -static ERL_NIF_TERM atom_idn; -static ERL_NIF_TERM atom_idna_allow_unassigned; -static ERL_NIF_TERM atom_idna_use_std3_ascii_rules; -static ERL_NIF_TERM atom_namereqd; -static ERL_NIF_TERM atom_name_info; -static ERL_NIF_TERM atom_nofqdn; -static ERL_NIF_TERM atom_numerichost; -static ERL_NIF_TERM atom_numericserv; -static ERL_NIF_TERM atom_service; - - -static ERL_NIF_TERM atom_eaddrfamily; -// static ERL_NIF_TERM atom_eagain; -static ERL_NIF_TERM atom_ebadflags; -static ERL_NIF_TERM atom_efail; -static ERL_NIF_TERM atom_efamily; -static ERL_NIF_TERM atom_efault; -static ERL_NIF_TERM atom_emem; -static ERL_NIF_TERM atom_enametoolong; -static ERL_NIF_TERM atom_enodata; -static ERL_NIF_TERM atom_enoname; -static ERL_NIF_TERM atom_enxio; -static ERL_NIF_TERM atom_eoverflow; -static ERL_NIF_TERM atom_eservice; -static ERL_NIF_TERM atom_esocktype; -static ERL_NIF_TERM atom_esystem; +/* *** Local atoms *** */ + +#define LOCAL_ATOMS \ + LOCAL_ATOM_DECL(address_info); \ + LOCAL_ATOM_DECL(debug); \ + LOCAL_ATOM_DECL(host); \ + LOCAL_ATOM_DECL(idn); \ + LOCAL_ATOM_DECL(idna_allow_unassigned); \ + LOCAL_ATOM_DECL(idna_use_std3_ascii_rules); \ + LOCAL_ATOM_DECL(namereqd); \ + LOCAL_ATOM_DECL(name_info); \ + LOCAL_ATOM_DECL(nofqdn); \ + LOCAL_ATOM_DECL(numerichost); \ + LOCAL_ATOM_DECL(numericserv); \ + LOCAL_ATOM_DECL(service); + +#define LOCAL_ERROR_REASON_ATOMS \ + LOCAL_ATOM_DECL(eaddrfamily); \ + LOCAL_ATOM_DECL(ebadflags); \ + LOCAL_ATOM_DECL(efail); \ + LOCAL_ATOM_DECL(efamily); \ + LOCAL_ATOM_DECL(efault); \ + LOCAL_ATOM_DECL(emem); \ + LOCAL_ATOM_DECL(enametoolong); \ + LOCAL_ATOM_DECL(enodata); \ + LOCAL_ATOM_DECL(enoname); \ + LOCAL_ATOM_DECL(enxio); \ + LOCAL_ATOM_DECL(eoverflow); \ + LOCAL_ATOM_DECL(eservice); \ + LOCAL_ATOM_DECL(esocktype); \ + LOCAL_ATOM_DECL(esystem); + +#define LOCAL_ATOM_DECL(A) static ERL_NIF_TERM atom_##A +LOCAL_ATOMS +LOCAL_ERROR_REASON_ATOMS +#undef LOCAL_ATOM_DECL /* *** net *** */ @@ -1651,35 +1629,10 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) NDBG( ("NET", "on_load -> entry\r\n") ); #endif - /* +++ Misc atoms +++ */ - atom_address_info = MKA(env, str_address_info); - atom_debug = MKA(env, str_debug); - atom_host = MKA(env, "host"); - atom_idn = MKA(env, str_idn); - atom_idna_allow_unassigned = MKA(env, str_idna_allow_unassigned); - atom_idna_use_std3_ascii_rules = MKA(env, str_idna_use_std3_ascii_rules); - atom_namereqd = MKA(env, str_namereqd); - atom_name_info = MKA(env, str_name_info); - atom_nofqdn = MKA(env, str_nofqdn); - atom_numerichost = MKA(env, str_numerichost); - atom_numericserv = MKA(env, str_numericserv); - atom_service = MKA(env, "service"); - - /* Error codes */ - atom_eaddrfamily = MKA(env, str_eaddrfamily); - atom_ebadflags = MKA(env, str_ebadflags); - atom_efail = MKA(env, str_efail); - atom_efamily = MKA(env, str_efamily); - atom_efault = MKA(env, str_efault); - atom_emem = MKA(env, str_emem); - atom_enametoolong = MKA(env, str_enametoolong); - atom_enodata = MKA(env, str_enodata); - atom_enoname = MKA(env, str_enoname); - atom_enxio = MKA(env, str_enxio); - atom_eoverflow = MKA(env, str_eoverflow); - atom_eservice = MKA(env, str_eservice); - atom_esocktype = MKA(env, str_esocktype); - atom_esystem = MKA(env, str_esystem); +#define LOCAL_ATOM_DECL(A) atom_##A = MKA(env, #A) +LOCAL_ATOMS +LOCAL_ERROR_REASON_ATOMS +#undef LOCAL_ATOM_DECL // For storing "global" things... // data.env = enif_alloc_env(); // We should really check diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h index a9e83adc21..043303a60d 100644 --- a/erts/emulator/nifs/common/socket_int.h +++ b/erts/emulator/nifs/common/socket_int.h @@ -103,209 +103,218 @@ typedef unsigned int BOOLEAN_T; /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * "Global" atoms */ -extern ERL_NIF_TERM esock_atom_abort; -extern ERL_NIF_TERM esock_atom_accept; -extern ERL_NIF_TERM esock_atom_acceptconn; -extern ERL_NIF_TERM esock_atom_acceptfilter; -extern ERL_NIF_TERM esock_atom_adaption_layer; -extern ERL_NIF_TERM esock_atom_addr; -extern ERL_NIF_TERM esock_atom_addrform; -extern ERL_NIF_TERM esock_atom_add_membership; -extern ERL_NIF_TERM esock_atom_add_source_membership; -extern ERL_NIF_TERM esock_atom_any; -extern ERL_NIF_TERM esock_atom_associnfo; -extern ERL_NIF_TERM esock_atom_authhdr; -extern ERL_NIF_TERM esock_atom_auth_active_key; -extern ERL_NIF_TERM esock_atom_auth_asconf; -extern ERL_NIF_TERM esock_atom_auth_chunk; -extern ERL_NIF_TERM esock_atom_auth_delete_key; -extern ERL_NIF_TERM esock_atom_auth_key; -extern ERL_NIF_TERM esock_atom_auth_level; -extern ERL_NIF_TERM esock_atom_autoclose; -extern ERL_NIF_TERM esock_atom_bindtodevice; -extern ERL_NIF_TERM esock_atom_block_source; -extern ERL_NIF_TERM esock_atom_broadcast; -extern ERL_NIF_TERM esock_atom_busy_poll; -extern ERL_NIF_TERM esock_atom_checksum; -extern ERL_NIF_TERM esock_atom_close; -extern ERL_NIF_TERM esock_atom_connect; -extern ERL_NIF_TERM esock_atom_congestion; -extern ERL_NIF_TERM esock_atom_context; -extern ERL_NIF_TERM esock_atom_cork; -extern ERL_NIF_TERM esock_atom_credentials; -extern ERL_NIF_TERM esock_atom_ctrl; -extern ERL_NIF_TERM esock_atom_ctrunc; -extern ERL_NIF_TERM esock_atom_data; -extern ERL_NIF_TERM esock_atom_debug; -extern ERL_NIF_TERM esock_atom_default_send_params; -extern ERL_NIF_TERM esock_atom_delayed_ack_time; -extern ERL_NIF_TERM esock_atom_dgram; -extern ERL_NIF_TERM esock_atom_disable_fragments; -extern ERL_NIF_TERM esock_atom_domain; -extern ERL_NIF_TERM esock_atom_dontfrag; -extern ERL_NIF_TERM esock_atom_dontroute; -extern ERL_NIF_TERM esock_atom_drop_membership; -extern ERL_NIF_TERM esock_atom_drop_source_membership; -extern ERL_NIF_TERM esock_atom_dstopts; -extern ERL_NIF_TERM esock_atom_eor; -extern ERL_NIF_TERM esock_atom_error; -extern ERL_NIF_TERM esock_atom_errqueue; -extern ERL_NIF_TERM esock_atom_esp_network_level; -extern ERL_NIF_TERM esock_atom_esp_trans_level; -extern ERL_NIF_TERM esock_atom_events; -extern ERL_NIF_TERM esock_atom_explicit_eor; -extern ERL_NIF_TERM esock_atom_faith; -extern ERL_NIF_TERM esock_atom_false; -extern ERL_NIF_TERM esock_atom_family; -extern ERL_NIF_TERM esock_atom_flags; -extern ERL_NIF_TERM esock_atom_flowinfo; -extern ERL_NIF_TERM esock_atom_fragment_interleave; -extern ERL_NIF_TERM esock_atom_freebind; -extern ERL_NIF_TERM esock_atom_get_peer_addr_info; -extern ERL_NIF_TERM esock_atom_hdrincl; -extern ERL_NIF_TERM esock_atom_hmac_ident; -extern ERL_NIF_TERM esock_atom_hoplimit; -extern ERL_NIF_TERM esock_atom_hopopts; -extern ERL_NIF_TERM esock_atom_ifindex; -extern ERL_NIF_TERM esock_atom_inet; -extern ERL_NIF_TERM esock_atom_inet6; -extern ERL_NIF_TERM esock_atom_info; -extern ERL_NIF_TERM esock_atom_initmsg; -extern ERL_NIF_TERM esock_atom_iov; -extern ERL_NIF_TERM esock_atom_ip; -extern ERL_NIF_TERM esock_atom_ipcomp_level; -extern ERL_NIF_TERM esock_atom_ipv6; -extern ERL_NIF_TERM esock_atom_i_want_mapped_v4_addr; -extern ERL_NIF_TERM esock_atom_join_group; -extern ERL_NIF_TERM esock_atom_keepalive; -extern ERL_NIF_TERM esock_atom_keepcnt; -extern ERL_NIF_TERM esock_atom_keepidle; -extern ERL_NIF_TERM esock_atom_keepintvl; -extern ERL_NIF_TERM esock_atom_leave_group; -extern ERL_NIF_TERM esock_atom_level; -extern ERL_NIF_TERM esock_atom_linger; -extern ERL_NIF_TERM esock_atom_local; -extern ERL_NIF_TERM esock_atom_local_auth_chunks; -extern ERL_NIF_TERM esock_atom_loopback; -extern ERL_NIF_TERM esock_atom_lowdelay; -extern ERL_NIF_TERM esock_atom_mark; -extern ERL_NIF_TERM esock_atom_maxburst; -extern ERL_NIF_TERM esock_atom_maxseg; -extern ERL_NIF_TERM esock_atom_md5sig; -extern ERL_NIF_TERM esock_atom_mincost; -extern ERL_NIF_TERM esock_atom_minttl; -extern ERL_NIF_TERM esock_atom_msfilter; -extern ERL_NIF_TERM esock_atom_mtu; -extern ERL_NIF_TERM esock_atom_mtu_discover; -extern ERL_NIF_TERM esock_atom_multicast_all; -extern ERL_NIF_TERM esock_atom_multicast_hops; -extern ERL_NIF_TERM esock_atom_multicast_if; -extern ERL_NIF_TERM esock_atom_multicast_loop; -extern ERL_NIF_TERM esock_atom_multicast_ttl; -extern ERL_NIF_TERM esock_atom_nodelay; -extern ERL_NIF_TERM esock_atom_nodefrag; -extern ERL_NIF_TERM esock_atom_noopt; -extern ERL_NIF_TERM esock_atom_nopush; -extern ERL_NIF_TERM esock_atom_not_found; -extern ERL_NIF_TERM esock_atom_not_owner; -extern ERL_NIF_TERM esock_atom_ok; -extern ERL_NIF_TERM esock_atom_oob; -extern ERL_NIF_TERM esock_atom_oobinline; -extern ERL_NIF_TERM esock_atom_options; -extern ERL_NIF_TERM esock_atom_origdstaddr; -extern ERL_NIF_TERM esock_atom_partial_delivery_point; -extern ERL_NIF_TERM esock_atom_passcred; -extern ERL_NIF_TERM esock_atom_path; -extern ERL_NIF_TERM esock_atom_peekcred; -extern ERL_NIF_TERM esock_atom_peek_off; -extern ERL_NIF_TERM esock_atom_peer_addr_params; -extern ERL_NIF_TERM esock_atom_peer_auth_chunks; -extern ERL_NIF_TERM esock_atom_pktinfo; -extern ERL_NIF_TERM esock_atom_pktoptions; -extern ERL_NIF_TERM esock_atom_port; -extern ERL_NIF_TERM esock_atom_portrange; -extern ERL_NIF_TERM esock_atom_primary_addr; -extern ERL_NIF_TERM esock_atom_priority; -extern ERL_NIF_TERM esock_atom_protocol; -extern ERL_NIF_TERM esock_atom_raw; -extern ERL_NIF_TERM esock_atom_rcvbuf; -extern ERL_NIF_TERM esock_atom_rcvbufforce; -extern ERL_NIF_TERM esock_atom_rcvlowat; -extern ERL_NIF_TERM esock_atom_rcvtimeo; -extern ERL_NIF_TERM esock_atom_rdm; -extern ERL_NIF_TERM esock_atom_recv; -extern ERL_NIF_TERM esock_atom_recvdstaddr; -extern ERL_NIF_TERM esock_atom_recverr; -extern ERL_NIF_TERM esock_atom_recvfrom; -extern ERL_NIF_TERM esock_atom_recvif; -extern ERL_NIF_TERM esock_atom_recvmsg; -extern ERL_NIF_TERM esock_atom_recvopts; -extern ERL_NIF_TERM esock_atom_recvorigdstaddr; -extern ERL_NIF_TERM esock_atom_recvpktinfo; -extern ERL_NIF_TERM esock_atom_recvtclass; -extern ERL_NIF_TERM esock_atom_recvtos; -extern ERL_NIF_TERM esock_atom_recvttl; -extern ERL_NIF_TERM esock_atom_reliability; -extern ERL_NIF_TERM esock_atom_reset_streams; -extern ERL_NIF_TERM esock_atom_retopts; -extern ERL_NIF_TERM esock_atom_reuseaddr; -extern ERL_NIF_TERM esock_atom_reuseport; -extern ERL_NIF_TERM esock_atom_rights; -extern ERL_NIF_TERM esock_atom_router_alert; -extern ERL_NIF_TERM esock_atom_rthdr; -extern ERL_NIF_TERM esock_atom_rtoinfo; -extern ERL_NIF_TERM esock_atom_rxq_ovfl; -extern ERL_NIF_TERM esock_atom_scope_id; -extern ERL_NIF_TERM esock_atom_sctp; -extern ERL_NIF_TERM esock_atom_sec; -extern ERL_NIF_TERM esock_atom_select_failed; -extern ERL_NIF_TERM esock_atom_select_sent; -extern ERL_NIF_TERM esock_atom_send; -extern ERL_NIF_TERM esock_atom_sendmsg; -extern ERL_NIF_TERM esock_atom_sendsrcaddr; -extern ERL_NIF_TERM esock_atom_sendto; -extern ERL_NIF_TERM esock_atom_seqpacket; -extern ERL_NIF_TERM esock_atom_setfib; -extern ERL_NIF_TERM esock_atom_set_peer_primary_addr; -extern ERL_NIF_TERM esock_atom_sndbuf; -extern ERL_NIF_TERM esock_atom_sndbufforce; -extern ERL_NIF_TERM esock_atom_sndlowat; -extern ERL_NIF_TERM esock_atom_sndtimeo; -extern ERL_NIF_TERM esock_atom_socket; -extern ERL_NIF_TERM esock_atom_socket_tag; -extern ERL_NIF_TERM esock_atom_spec_dst; -extern ERL_NIF_TERM esock_atom_status; -extern ERL_NIF_TERM esock_atom_stream; -extern ERL_NIF_TERM esock_atom_syncnt; -extern ERL_NIF_TERM esock_atom_tclass; -extern ERL_NIF_TERM esock_atom_tcp; -extern ERL_NIF_TERM esock_atom_throughput; -extern ERL_NIF_TERM esock_atom_timestamp; -extern ERL_NIF_TERM esock_atom_tos; -extern ERL_NIF_TERM esock_atom_transparent; -extern ERL_NIF_TERM esock_atom_true; -extern ERL_NIF_TERM esock_atom_trunc; -extern ERL_NIF_TERM esock_atom_ttl; -extern ERL_NIF_TERM esock_atom_type; -extern ERL_NIF_TERM esock_atom_udp; -extern ERL_NIF_TERM esock_atom_unblock_source; -extern ERL_NIF_TERM esock_atom_undefined; -extern ERL_NIF_TERM esock_atom_unicast_hops; -extern ERL_NIF_TERM esock_atom_unknown; -extern ERL_NIF_TERM esock_atom_usec; -extern ERL_NIF_TERM esock_atom_user_timeout; -extern ERL_NIF_TERM esock_atom_use_ext_recvinfo; -extern ERL_NIF_TERM esock_atom_use_min_mtu; -extern ERL_NIF_TERM esock_atom_v6only; + +#define GLOBAL_ATOM_DEFS \ + GLOBAL_ATOM_DEF(abort); \ + GLOBAL_ATOM_DEF(accept); \ + GLOBAL_ATOM_DEF(acceptconn); \ + GLOBAL_ATOM_DEF(acceptfilter); \ + GLOBAL_ATOM_DEF(adaption_layer); \ + GLOBAL_ATOM_DEF(addr); \ + GLOBAL_ATOM_DEF(addrform); \ + GLOBAL_ATOM_DEF(add_membership); \ + GLOBAL_ATOM_DEF(add_source_membership); \ + GLOBAL_ATOM_DEF(any); \ + GLOBAL_ATOM_DEF(associnfo); \ + GLOBAL_ATOM_DEF(authhdr); \ + GLOBAL_ATOM_DEF(auth_active_key); \ + GLOBAL_ATOM_DEF(auth_asconf); \ + GLOBAL_ATOM_DEF(auth_chunk); \ + GLOBAL_ATOM_DEF(auth_delete_key); \ + GLOBAL_ATOM_DEF(auth_key); \ + GLOBAL_ATOM_DEF(auth_level); \ + GLOBAL_ATOM_DEF(autoclose); \ + GLOBAL_ATOM_DEF(bindtodevice); \ + GLOBAL_ATOM_DEF(block_source); \ + GLOBAL_ATOM_DEF(broadcast); \ + GLOBAL_ATOM_DEF(busy_poll); \ + GLOBAL_ATOM_DEF(checksum); \ + GLOBAL_ATOM_DEF(close); \ + GLOBAL_ATOM_DEF(connect); \ + GLOBAL_ATOM_DEF(congestion); \ + GLOBAL_ATOM_DEF(context); \ + GLOBAL_ATOM_DEF(cork); \ + GLOBAL_ATOM_DEF(credentials); \ + GLOBAL_ATOM_DEF(ctrl); \ + GLOBAL_ATOM_DEF(ctrunc); \ + GLOBAL_ATOM_DEF(data); \ + GLOBAL_ATOM_DEF(debug); \ + GLOBAL_ATOM_DEF(default_send_params); \ + GLOBAL_ATOM_DEF(delayed_ack_time); \ + GLOBAL_ATOM_DEF(dgram); \ + GLOBAL_ATOM_DEF(disable_fragments); \ + GLOBAL_ATOM_DEF(domain); \ + GLOBAL_ATOM_DEF(dontfrag); \ + GLOBAL_ATOM_DEF(dontroute); \ + GLOBAL_ATOM_DEF(drop_membership); \ + GLOBAL_ATOM_DEF(drop_source_membership); \ + GLOBAL_ATOM_DEF(dstopts); \ + GLOBAL_ATOM_DEF(eor); \ + GLOBAL_ATOM_DEF(error); \ + GLOBAL_ATOM_DEF(errqueue); \ + GLOBAL_ATOM_DEF(esp_network_level); \ + GLOBAL_ATOM_DEF(esp_trans_level); \ + GLOBAL_ATOM_DEF(events); \ + GLOBAL_ATOM_DEF(explicit_eor); \ + GLOBAL_ATOM_DEF(faith); \ + GLOBAL_ATOM_DEF(false); \ + GLOBAL_ATOM_DEF(family); \ + GLOBAL_ATOM_DEF(flags); \ + GLOBAL_ATOM_DEF(flowinfo); \ + GLOBAL_ATOM_DEF(fragment_interleave); \ + GLOBAL_ATOM_DEF(freebind); \ + GLOBAL_ATOM_DEF(get_peer_addr_info); \ + GLOBAL_ATOM_DEF(hdrincl); \ + GLOBAL_ATOM_DEF(hmac_ident); \ + GLOBAL_ATOM_DEF(hoplimit); \ + GLOBAL_ATOM_DEF(hopopts); \ + GLOBAL_ATOM_DEF(ifindex); \ + GLOBAL_ATOM_DEF(inet); \ + GLOBAL_ATOM_DEF(inet6); \ + GLOBAL_ATOM_DEF(info); \ + GLOBAL_ATOM_DEF(initmsg); \ + GLOBAL_ATOM_DEF(iov); \ + GLOBAL_ATOM_DEF(ip); \ + GLOBAL_ATOM_DEF(ipcomp_level); \ + GLOBAL_ATOM_DEF(ipv6); \ + GLOBAL_ATOM_DEF(i_want_mapped_v4_addr); \ + GLOBAL_ATOM_DEF(join_group); \ + GLOBAL_ATOM_DEF(keepalive); \ + GLOBAL_ATOM_DEF(keepcnt); \ + GLOBAL_ATOM_DEF(keepidle); \ + GLOBAL_ATOM_DEF(keepintvl); \ + GLOBAL_ATOM_DEF(leave_group); \ + GLOBAL_ATOM_DEF(level); \ + GLOBAL_ATOM_DEF(linger); \ + GLOBAL_ATOM_DEF(local); \ + GLOBAL_ATOM_DEF(local_auth_chunks); \ + GLOBAL_ATOM_DEF(loopback); \ + GLOBAL_ATOM_DEF(lowdelay); \ + GLOBAL_ATOM_DEF(mark); \ + GLOBAL_ATOM_DEF(maxburst); \ + GLOBAL_ATOM_DEF(maxseg); \ + GLOBAL_ATOM_DEF(md5sig); \ + GLOBAL_ATOM_DEF(mincost); \ + GLOBAL_ATOM_DEF(minttl); \ + GLOBAL_ATOM_DEF(msfilter); \ + GLOBAL_ATOM_DEF(mtu); \ + GLOBAL_ATOM_DEF(mtu_discover); \ + GLOBAL_ATOM_DEF(multicast_all); \ + GLOBAL_ATOM_DEF(multicast_hops); \ + GLOBAL_ATOM_DEF(multicast_if); \ + GLOBAL_ATOM_DEF(multicast_loop); \ + GLOBAL_ATOM_DEF(multicast_ttl); \ + GLOBAL_ATOM_DEF(nodelay); \ + GLOBAL_ATOM_DEF(nodefrag); \ + GLOBAL_ATOM_DEF(noopt); \ + GLOBAL_ATOM_DEF(nopush); \ + GLOBAL_ATOM_DEF(not_found); \ + GLOBAL_ATOM_DEF(not_owner); \ + GLOBAL_ATOM_DEF(ok); \ + GLOBAL_ATOM_DEF(oob); \ + GLOBAL_ATOM_DEF(oobinline); \ + GLOBAL_ATOM_DEF(options); \ + GLOBAL_ATOM_DEF(origdstaddr); \ + GLOBAL_ATOM_DEF(partial_delivery_point); \ + GLOBAL_ATOM_DEF(passcred); \ + GLOBAL_ATOM_DEF(path); \ + GLOBAL_ATOM_DEF(peekcred); \ + GLOBAL_ATOM_DEF(peek_off); \ + GLOBAL_ATOM_DEF(peer_addr_params); \ + GLOBAL_ATOM_DEF(peer_auth_chunks); \ + GLOBAL_ATOM_DEF(pktinfo); \ + GLOBAL_ATOM_DEF(pktoptions); \ + GLOBAL_ATOM_DEF(port); \ + GLOBAL_ATOM_DEF(portrange); \ + GLOBAL_ATOM_DEF(primary_addr); \ + GLOBAL_ATOM_DEF(priority); \ + GLOBAL_ATOM_DEF(protocol); \ + GLOBAL_ATOM_DEF(raw); \ + GLOBAL_ATOM_DEF(rcvbuf); \ + GLOBAL_ATOM_DEF(rcvbufforce); \ + GLOBAL_ATOM_DEF(rcvlowat); \ + GLOBAL_ATOM_DEF(rcvtimeo); \ + GLOBAL_ATOM_DEF(rdm); \ + GLOBAL_ATOM_DEF(recv); \ + GLOBAL_ATOM_DEF(recvdstaddr); \ + GLOBAL_ATOM_DEF(recverr); \ + GLOBAL_ATOM_DEF(recvfrom); \ + GLOBAL_ATOM_DEF(recvif); \ + GLOBAL_ATOM_DEF(recvmsg); \ + GLOBAL_ATOM_DEF(recvopts); \ + GLOBAL_ATOM_DEF(recvorigdstaddr); \ + GLOBAL_ATOM_DEF(recvpktinfo); \ + GLOBAL_ATOM_DEF(recvtclass); \ + GLOBAL_ATOM_DEF(recvtos); \ + GLOBAL_ATOM_DEF(recvttl); \ + GLOBAL_ATOM_DEF(reliability); \ + GLOBAL_ATOM_DEF(reset_streams); \ + GLOBAL_ATOM_DEF(retopts); \ + GLOBAL_ATOM_DEF(reuseaddr); \ + GLOBAL_ATOM_DEF(reuseport); \ + GLOBAL_ATOM_DEF(rights); \ + GLOBAL_ATOM_DEF(router_alert); \ + GLOBAL_ATOM_DEF(rthdr); \ + GLOBAL_ATOM_DEF(rtoinfo); \ + GLOBAL_ATOM_DEF(rxq_ovfl); \ + GLOBAL_ATOM_DEF(scope_id); \ + GLOBAL_ATOM_DEF(sctp); \ + GLOBAL_ATOM_DEF(sec); \ + GLOBAL_ATOM_DEF(select_failed); \ + GLOBAL_ATOM_DEF(select_sent); \ + GLOBAL_ATOM_DEF(send); \ + GLOBAL_ATOM_DEF(sendmsg); \ + GLOBAL_ATOM_DEF(sendsrcaddr); \ + GLOBAL_ATOM_DEF(sendto); \ + GLOBAL_ATOM_DEF(seqpacket); \ + GLOBAL_ATOM_DEF(setfib); \ + GLOBAL_ATOM_DEF(set_peer_primary_addr); \ + GLOBAL_ATOM_DEF(sndbuf); \ + GLOBAL_ATOM_DEF(sndbufforce); \ + GLOBAL_ATOM_DEF(sndlowat); \ + GLOBAL_ATOM_DEF(sndtimeo); \ + GLOBAL_ATOM_DEF(socket); \ + GLOBAL_ATOM_DEF(socket_tag); \ + GLOBAL_ATOM_DEF(spec_dst); \ + GLOBAL_ATOM_DEF(status); \ + GLOBAL_ATOM_DEF(stream); \ + GLOBAL_ATOM_DEF(syncnt); \ + GLOBAL_ATOM_DEF(tclass); \ + GLOBAL_ATOM_DEF(tcp); \ + GLOBAL_ATOM_DEF(throughput); \ + GLOBAL_ATOM_DEF(timestamp); \ + GLOBAL_ATOM_DEF(tos); \ + GLOBAL_ATOM_DEF(transparent); \ + GLOBAL_ATOM_DEF(true); \ + GLOBAL_ATOM_DEF(trunc); \ + GLOBAL_ATOM_DEF(ttl); \ + GLOBAL_ATOM_DEF(type); \ + GLOBAL_ATOM_DEF(udp); \ + GLOBAL_ATOM_DEF(unblock_source); \ + GLOBAL_ATOM_DEF(undefined); \ + GLOBAL_ATOM_DEF(unicast_hops); \ + GLOBAL_ATOM_DEF(unknown); \ + GLOBAL_ATOM_DEF(usec); \ + GLOBAL_ATOM_DEF(user_timeout); \ + GLOBAL_ATOM_DEF(use_ext_recvinfo); \ + GLOBAL_ATOM_DEF(use_min_mtu); \ + GLOBAL_ATOM_DEF(v6only); /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * Error value (=reason) atoms + * Error reason atoms */ -extern ERL_NIF_TERM esock_atom_eafnosupport; -extern ERL_NIF_TERM esock_atom_eagain; -extern ERL_NIF_TERM esock_atom_einval; +#define GLOBAL_ERROR_REASON_ATOM_DEFS \ + GLOBAL_ATOM_DEF(eafnosupport); \ + GLOBAL_ATOM_DEF(eagain); \ + GLOBAL_ATOM_DEF(einval); + + +#define GLOBAL_ATOM_DEF(A) extern ERL_NIF_TERM esock_atom_##A +GLOBAL_ATOM_DEFS +GLOBAL_ERROR_REASON_ATOM_DEFS +#undef GLOBAL_ATOM_DEF /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -343,14 +352,13 @@ extern ERL_NIF_TERM esock_atom_einval; #define MLOCK(M) enif_mutex_lock((M)) #define MUNLOCK(M) enif_mutex_unlock((M)) -// #define MONP(S,E,D,P,M) enif_monitor_process((E), (D), (P), (M)) -// #define DEMONP(S,E,D,M) enif_demonitor_process((E), (D), (M)) #define MONP(S,E,D,P,M) esock_monitor((S), (E), (D), (P), (M)) #define DEMONP(S,E,D,M) esock_demonitor((S), (E), (D), (M)) #define MON_INIT(M) esock_monitor_init((M)) -// #define MON_COMP(M1, M2) esock_monitor_compare((M1), (M2)) +#define MON2T(E, M) enif_make_monitor_term((E), (M)) -#define COMPARE(A, B) enif_compare((A), (B)) +#define COMPARE(A, B) enif_compare((A), (B)) +#define COMPARE_PIDS(P1, P2) enif_compare_pids((P1), (P2)) #define IS_ATOM(E, TE) enif_is_atom((E), (TE)) #define IS_BIN(E, TE) enif_is_binary((E), (TE)) diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index d56b70e3fd..bb3df85ea4 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -32,7 +32,7 @@ * * esock_dbg_printf("DEMONP", "[%d] %s: %T\r\n", * descP->sock, slogan, - * my_make_monitor_term(env, &monP->mon)); + * MON2T(env, &monP->mon)); * */ @@ -392,6 +392,13 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL; #endif +#if defined(TCP_CONGESTION) || defined(SO_BINDTODEVICE) +#define USE_GETOPT_STR_OPT +#define USE_SETOPT_STR_OPT +#endif + + + /* *** Socket state defs *** */ #define SOCKET_FLAG_OPEN 0x0001 @@ -882,81 +889,81 @@ typedef struct { */ +extern char* erl_errno_id(int error); /* THIS IS JUST TEMPORARY??? */ -static ERL_NIF_TERM nif_info(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_supports(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -/* -This is a *global* debug function (enable or disable for all -operations and all sockets. -static ERL_NIF_TERM nif_debug(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -*/ -static ERL_NIF_TERM nif_open(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_bind(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_connect(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_listen(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_accept(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_send(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_sendto(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_recv(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env, - int argc, + +/* All the nif "callback" functions for the socket API has + * the exact same API: + * + * nif_<funcname>(ErlNifEnv* env, + * int argc, + * const ERL_NIF_TERM argv[]); + * + * So, to simplify, use some macro magic to define those. + * + * These are the functions making up the "official" API. + * Basically, these functions does some preliminary checks and argument + * extractions and then call the functions called 'n<funcname>', which + * does the actual work. Except for the info function. + * + * nif_info + * nif_supports + * nif_open + * nif_bind + * nif_connect + * nif_listen + * nif_accept + * nif_send + * nif_sendto + * nif_sendmsg + * nif_recv + * nif_recvfrom + * nif_recvmsg + * nif_close + * nif_shutdown + * nif_setopt + * nif_getopt + * nif_sockname + * nif_peername + * nif_finalize_connection + * nif_finalize_close + * nif_cancel + */ + +#define ESOCK_NIF_FUNCS \ + ESOCK_NIF_FUNC_DEF(info); \ + ESOCK_NIF_FUNC_DEF(supports); \ + ESOCK_NIF_FUNC_DEF(open); \ + ESOCK_NIF_FUNC_DEF(bind); \ + ESOCK_NIF_FUNC_DEF(connect); \ + ESOCK_NIF_FUNC_DEF(listen); \ + ESOCK_NIF_FUNC_DEF(accept); \ + ESOCK_NIF_FUNC_DEF(send); \ + ESOCK_NIF_FUNC_DEF(sendto); \ + ESOCK_NIF_FUNC_DEF(sendmsg); \ + ESOCK_NIF_FUNC_DEF(recv); \ + ESOCK_NIF_FUNC_DEF(recvfrom); \ + ESOCK_NIF_FUNC_DEF(recvmsg); \ + ESOCK_NIF_FUNC_DEF(close); \ + ESOCK_NIF_FUNC_DEF(shutdown); \ + ESOCK_NIF_FUNC_DEF(setopt); \ + ESOCK_NIF_FUNC_DEF(getopt); \ + ESOCK_NIF_FUNC_DEF(sockname); \ + ESOCK_NIF_FUNC_DEF(peername); \ + ESOCK_NIF_FUNC_DEF(finalize_connection); \ + ESOCK_NIF_FUNC_DEF(finalize_close); \ + ESOCK_NIF_FUNC_DEF(cancel); + +#define ESOCK_NIF_FUNC_DEF(F) \ + static ERL_NIF_TERM nif_##F(ErlNifEnv* env, \ + int argc, \ const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_close(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_shutdown(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_setopt(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_getopt(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_sockname(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_peername(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_finalize_connection(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_finalize_close(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM nif_cancel(ErlNifEnv* env, - int argc, - const ERL_NIF_TERM argv[]); +ESOCK_NIF_FUNCS +#undef ESOCK_NIF_FUNC_DEF + +#if !defined(__WIN32__) +/* And here comes the functions that does the actual work (for the most part) */ static ERL_NIF_TERM nsupports(ErlNifEnv* env, int key); static ERL_NIF_TERM nsupports_options(ErlNifEnv* env); static ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env); @@ -984,6 +991,7 @@ static ERL_NIF_TERM nlisten(ErlNifEnv* env, int backlog); static ERL_NIF_TERM naccept(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM ref); static ERL_NIF_TERM naccept_listening(ErlNifEnv* env, SocketDescriptor* descP, @@ -1000,17 +1008,21 @@ static ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env, SocketAddress* remote); static ERL_NIF_TERM naccept_accepting(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM ref); static ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM ref); static ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, SOCKET accSock, SocketAddress* remote); static ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env, SocketDescriptor* descP, - ERL_NIF_TERM ref, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM opRef, int save_errno); static ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env, SocketDescriptor* descP, @@ -1078,28 +1090,34 @@ static ERL_NIF_TERM nsetopt(ErlNifEnv* env, int level, int eOpt, ERL_NIF_TERM eVal); + +/* Set OTP level options */ static ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env, SocketDescriptor* descP, int eOpt, ERL_NIF_TERM eVal); -static ERL_NIF_TERM nsetopt_otp_debug(ErlNifEnv* env, - SocketDescriptor* descP, - ERL_NIF_TERM eVal); -static ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env, - SocketDescriptor* descP, - ERL_NIF_TERM eVal); -static ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env, - SocketDescriptor* descP, - ERL_NIF_TERM eVal); -static ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env, - SocketDescriptor* descP, - ERL_NIF_TERM eVal); -static ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env, - SocketDescriptor* descP, - ERL_NIF_TERM eVal); -static ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env, - SocketDescriptor* descP, - ERL_NIF_TERM eVal); +/* *** nsetopt_otp_debug *** + * *** nsetopt_otp_iow *** + * *** nsetopt_otp_ctrl_proc *** + * *** nsetopt_otp_rcvbuf *** + * *** nsetopt_otp_rcvctrlbuf *** + * *** nsetopt_otp_sndctrlbuf *** + */ +#define NSETOPT_OTP_FUNCS \ + NSETOPT_OTP_FUNC_DEF(debug); \ + NSETOPT_OTP_FUNC_DEF(iow); \ + NSETOPT_OTP_FUNC_DEF(ctrl_proc); \ + NSETOPT_OTP_FUNC_DEF(rcvbuf); \ + NSETOPT_OTP_FUNC_DEF(rcvctrlbuf); \ + NSETOPT_OTP_FUNC_DEF(sndctrlbuf); +#define NSETOPT_OTP_FUNC_DEF(F) \ + static ERL_NIF_TERM nsetopt_otp_##F(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + ERL_NIF_TERM eVal) +NSETOPT_OTP_FUNCS +#undef NSETOPT_OTP_FUNC_DEF + +/* Set native options */ static ERL_NIF_TERM nsetopt_native(ErlNifEnv* env, SocketDescriptor* descP, int level, @@ -1579,29 +1597,38 @@ static ERL_NIF_TERM ngetopt(ErlNifEnv* env, BOOLEAN_T isOTP, int level, ERL_NIF_TERM eOpt); + static ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env, SocketDescriptor* descP, int eOpt); -static ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env, - SocketDescriptor* descP); -static ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env, - SocketDescriptor* descP); -static ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env, - SocketDescriptor* descP); -static ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env, - SocketDescriptor* descP); -static ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env, - SocketDescriptor* descP); -static ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env, - SocketDescriptor* descP); -static ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env, - SocketDescriptor* descP); -static ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env, - SocketDescriptor* descP); -static ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env, - SocketDescriptor* descP); -static ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env, - SocketDescriptor* descP); +/* *** ngetopt_otp_debug *** + * *** ngetopt_otp_iow *** + * *** ngetopt_otp_ctrl_proc *** + * *** ngetopt_otp_rcvbuf *** + * *** ngetopt_otp_rcvctrlbuf *** + * *** ngetopt_otp_sndctrlbuf *** + * *** ngetopt_otp_fd *** + * *** ngetopt_otp_domain *** + * *** ngetopt_otp_type *** + * *** ngetopt_otp_protocol *** + */ +#define NGETOPT_OTP_FUNCS \ + NGETOPT_OTP_FUNC_DEF(debug); \ + NGETOPT_OTP_FUNC_DEF(iow); \ + NGETOPT_OTP_FUNC_DEF(ctrl_proc); \ + NGETOPT_OTP_FUNC_DEF(rcvbuf); \ + NGETOPT_OTP_FUNC_DEF(rcvctrlbuf); \ + NGETOPT_OTP_FUNC_DEF(sndctrlbuf); \ + NGETOPT_OTP_FUNC_DEF(fd); \ + NGETOPT_OTP_FUNC_DEF(domain); \ + NGETOPT_OTP_FUNC_DEF(type); \ + NGETOPT_OTP_FUNC_DEF(protocol); +#define NGETOPT_OTP_FUNC_DEF(F) \ + static ERL_NIF_TERM ngetopt_otp_##F(ErlNifEnv* env, \ + SocketDescriptor* descP) +NGETOPT_OTP_FUNCS +#undef NGETOPT_OTP_FUNC_DEF + static ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, SocketDescriptor* descP, int level, @@ -1938,31 +1965,38 @@ static ERL_NIF_TERM npeername(ErlNifEnv* env, static ERL_NIF_TERM ncancel(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM op, + ERL_NIF_TERM sockRef, ERL_NIF_TERM opRef); static ERL_NIF_TERM ncancel_connect(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM opRef); static ERL_NIF_TERM ncancel_accept(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM opRef); static ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env, - SocketDescriptor* descP); + SocketDescriptor* descP, + ERL_NIF_TERM sockRef); static ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM opRef); static ERL_NIF_TERM ncancel_send(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM opRef); static ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env, - SocketDescriptor* descP); + SocketDescriptor* descP, + ERL_NIF_TERM sockRef); static ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM opRef); static ERL_NIF_TERM ncancel_recv(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM opRef); static ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env, - SocketDescriptor* descP); + SocketDescriptor* descP, + ERL_NIF_TERM sockRef); static ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM opRef); @@ -1978,12 +2012,14 @@ static ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env, int smode, int rmode); +#if defined(USE_SETOPT_STR_OPT) static ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env, SocketDescriptor* descP, int level, int opt, int max, ERL_NIF_TERM eVal); +#endif static ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env, SocketDescriptor* descP, int level, @@ -2000,11 +2036,13 @@ static ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env, int opt, ERL_NIF_TERM eVal); +#if defined(USE_GETOPT_STR_OPT) static ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env, SocketDescriptor* descP, int level, int opt, int max); +#endif static ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env, SocketDescriptor* descP, int level, @@ -2037,7 +2075,8 @@ static char* recv_init_current_reader(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM ref); static ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env, - SocketDescriptor* descP); + SocketDescriptor* descP, + ERL_NIF_TERM sockRef); static void recv_error_current_reader(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM sockRef, @@ -2206,6 +2245,7 @@ static BOOLEAN_T decode_native_get_opt(ErlNifEnv* env, static ERL_NIF_TERM encode_ip_tos(ErlNifEnv* env, int val); static void inform_waiting_procs(ErlNifEnv* env, + char* role, SocketDescriptor* descP, SocketRequestQueue* q, BOOLEAN_T free, @@ -2221,11 +2261,6 @@ static BOOLEAN_T verify_is_connected(SocketDescriptor* descP, int* err); static SocketDescriptor* alloc_descriptor(SOCKET sock, HANDLE event); -static int compare_pids(ErlNifEnv* env, - const ErlNifPid* pid1, - const ErlNifPid* pid2); - - static BOOLEAN_T edomain2domain(int edomain, int* domain); static BOOLEAN_T etype2type(int etype, int* type); @@ -2252,56 +2287,69 @@ static void inc_socket(int domain, int type, int protocol); static void dec_socket(int domain, int type, int protocol); -static BOOLEAN_T acceptor_search4pid(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid); -static ERL_NIF_TERM acceptor_push(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid pid, - ERL_NIF_TERM ref); -static BOOLEAN_T acceptor_pop(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid, - // ErlNifMonitor* mon, - ESockMonitor* mon, - ERL_NIF_TERM* ref); -static BOOLEAN_T acceptor_unqueue(ErlNifEnv* env, - SocketDescriptor* descP, - const ErlNifPid* pid); -static BOOLEAN_T writer_search4pid(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid); -static ERL_NIF_TERM writer_push(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid pid, - ERL_NIF_TERM ref); -static BOOLEAN_T writer_pop(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid, - // ErlNifMonitor* mon, - ESockMonitor* mon, - ERL_NIF_TERM* ref); -static BOOLEAN_T writer_unqueue(ErlNifEnv* env, - SocketDescriptor* descP, - const ErlNifPid* pid); +/* *** activate_next_acceptor *** + * *** activate_next_writer *** + * *** activate_next_reader *** + * + * All the activate-next functions for acceptor, writer and reader + * have exactly the same API, so we apply some macro magic to simplify. + * They simply operates on dufferent data structures. + * + */ -static BOOLEAN_T reader_search4pid(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid); -static ERL_NIF_TERM reader_push(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid pid, - ERL_NIF_TERM ref); -static BOOLEAN_T reader_pop(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid, - // ErlNifMonitor* mon, - ESockMonitor* mon, - ERL_NIF_TERM* ref); -static BOOLEAN_T reader_unqueue(ErlNifEnv* env, - SocketDescriptor* descP, - const ErlNifPid* pid); +#define ACTIVATE_NEXT_FUNCS_DEFS \ + ACTIVATE_NEXT_FUNC_DEF(acceptor) \ + ACTIVATE_NEXT_FUNC_DEF(writer) \ + ACTIVATE_NEXT_FUNC_DEF(reader) + +#define ACTIVATE_NEXT_FUNC_DEF(F) \ + static BOOLEAN_T activate_next_##F(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + ERL_NIF_TERM sockRef); +ACTIVATE_NEXT_FUNCS_DEFS +#undef ACTIVATE_NEXT_FUNC_DEF + +static BOOLEAN_T activate_next(ErlNifEnv* env, + SocketDescriptor* descP, + SocketRequestor* reqP, + SocketRequestQueue* q, + ERL_NIF_TERM sockRef); + +/* *** acceptor_search4pid | writer_search4pid | reader_search4pid *** + * *** acceptor_push | writer_push | reader_push *** + * *** acceptor_pop | writer_pop | reader_pop *** + * *** acceptor_unqueue | writer_unqueue | reader_unqueue *** + * + * All the queue operator functions (search4pid, push, pop + * and unqueue) for acceptor, writer and reader has exactly + * the same API, so we apply some macro magic to simplify. + */ + +#define ESOCK_OPERATOR_FUNCS_DEFS \ + ESOCK_OPERATOR_FUNCS_DEF(acceptor) \ + ESOCK_OPERATOR_FUNCS_DEF(writer) \ + ESOCK_OPERATOR_FUNCS_DEF(reader) + +#define ESOCK_OPERATOR_FUNCS_DEF(O) \ + static BOOLEAN_T O##_search4pid(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + ErlNifPid* pid); \ + static ERL_NIF_TERM O##_push(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + ErlNifPid pid, \ + ERL_NIF_TERM ref); \ + static BOOLEAN_T O##_pop(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + SocketRequestor* reqP); \ + static BOOLEAN_T O##_unqueue(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + const ErlNifPid* pid); +ESOCK_OPERATOR_FUNCS_DEFS +#undef ESOCK_OPERATOR_FUNCS_DEF + +static BOOLEAN_T requestor_pop(SocketRequestQueue* q, + SocketRequestor* reqP); static BOOLEAN_T qsearch4pid(ErlNifEnv* env, SocketRequestQueue* q, @@ -2325,11 +2373,8 @@ static int esock_demonitor(const char* slogan, SocketDescriptor* descP, ESockMonitor* monP); static void esock_monitor_init(ESockMonitor* mon); -/* -static int esock_monitor_compare(const ErlNifMonitor* mon1, - const ESockMonitor* mon2); -*/ +#endif // if defined(__WIN32__) /* #if defined(HAVE_SYS_UN_H) || defined(SO_BINDTODEVICE) @@ -2346,14 +2391,20 @@ static void socket_down(ErlNifEnv* env, void* obj, const ErlNifPid* pid, const ErlNifMonitor* mon); + +#if !defined(__WIN32__) + static void socket_down_acceptor(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, const ErlNifPid* pid); static void socket_down_writer(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, const ErlNifPid* pid); static void socket_down_reader(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, const ErlNifPid* pid); static char* esock_send_close_msg(ErlNifEnv* env, @@ -2397,6 +2448,8 @@ static BOOLEAN_T extract_debug(ErlNifEnv* env, static BOOLEAN_T extract_iow(ErlNifEnv* env, ERL_NIF_TERM map); +#endif // if defined(__WIN32__) + static int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); @@ -2424,354 +2477,301 @@ static const struct in6_addr in6addr_loopback = -/* *** String constants *** */ -static char str_adaptation_layer[] = "adaptation_layer"; -static char str_address[] = "address"; -static char str_association[] = "association"; -static char str_assoc_id[] = "assoc_id"; -static char str_authentication[] = "authentication"; -// static char str_any[] = "any"; -static char str_bool[] = "bool"; -static char str_close[] = "close"; -static char str_closed[] = "closed"; -static char str_closing[] = "closing"; -static char str_cookie_life[] = "cookie_life"; -static char str_data_in[] = "data_in"; -static char str_do[] = "do"; -static char str_dont[] = "dont"; -static char str_exclude[] = "exclude"; -static char str_false[] = "false"; -static char str_global_counters[] = "global_counters"; -static char str_in4_sockaddr[] = "in4_sockaddr"; -static char str_in6_sockaddr[] = "in6_sockaddr"; -static char str_include[] = "include"; -static char str_initial[] = "initial"; -static char str_int[] = "int"; -static char str_interface[] = "interface"; -static char str_iow[] = "iow"; -static char str_local_rwnd[] = "local_rwnd"; -// static char str_loopback[] = "loopback"; -static char str_max[] = "max"; -static char str_max_attempts[] = "max_attempts"; -static char str_max_init_timeo[] = "max_init_timeo"; -static char str_max_instreams[] = "max_instreams"; -static char str_max_rxt[] = "max_rxt"; -static char str_min[] = "min"; -static char str_mode[] = "mode"; -static char str_multiaddr[] = "multiaddr"; -// static char str_nif_abort[] = "nif_abort"; -static char str_null[] = "null"; -static char str_num_dlocal[] = "num_domain_local"; -static char str_num_dinet[] = "num_domain_inet"; -static char str_num_dinet6[] = "num_domain_inet6"; -static char str_num_outstreams[] = "num_outstreams"; -static char str_num_peer_dests[] = "num_peer_dests"; -static char str_num_pip[] = "num_proto_ip"; -static char str_num_psctp[] = "num_proto_sctp"; -static char str_num_ptcp[] = "num_proto_tcp"; -static char str_num_pudp[] = "num_proto_udp"; -static char str_num_sockets[] = "num_sockets"; -static char str_num_tdgrams[] = "num_type_dgram"; -static char str_num_tseqpkgs[] = "num_type_seqpacket"; -static char str_num_tstreams[] = "num_type_stream"; -static char str_partial_delivery[] = "partial_delivery"; -static char str_peer_error[] = "peer_error"; -static char str_peer_rwnd[] = "peer_rwnd"; -static char str_probe[] = "probe"; -static char str_select[] = "select"; -static char str_sender_dry[] = "sender_dry"; -static char str_send_failure[] = "send_failure"; -static char str_shutdown[] = "shutdown"; -static char str_slist[] = "slist"; -static char str_sourceaddr[] = "sourceaddr"; -static char str_timeout[] = "timeout"; -static char str_true[] = "true"; -static char str_want[] = "want"; - /* (special) error string constants */ -static char str_eisconn[] = "eisconn"; -static char str_enotclosing[] = "enotclosing"; -static char str_enotconn[] = "enotconn"; -static char str_exalloc[] = "exalloc"; -static char str_exbadstate[] = "exbadstate"; -static char str_exbusy[] = "exbusy"; static char str_exmon[] = "exmonitor"; // failed monitor static char str_exself[] = "exself"; // failed self static char str_exsend[] = "exsend"; // failed send -/* *** "Global" Atoms *** */ -ERL_NIF_TERM esock_atom_abort; -ERL_NIF_TERM esock_atom_accept; -ERL_NIF_TERM esock_atom_acceptconn; -ERL_NIF_TERM esock_atom_acceptfilter; -ERL_NIF_TERM esock_atom_adaption_layer; -ERL_NIF_TERM esock_atom_addr; -ERL_NIF_TERM esock_atom_addrform; -ERL_NIF_TERM esock_atom_add_membership; -ERL_NIF_TERM esock_atom_add_source_membership; -ERL_NIF_TERM esock_atom_any; -ERL_NIF_TERM esock_atom_associnfo; -ERL_NIF_TERM esock_atom_authhdr; -ERL_NIF_TERM esock_atom_auth_active_key; -ERL_NIF_TERM esock_atom_auth_asconf; -ERL_NIF_TERM esock_atom_auth_chunk; -ERL_NIF_TERM esock_atom_auth_delete_key; -ERL_NIF_TERM esock_atom_auth_key; -ERL_NIF_TERM esock_atom_auth_level; -ERL_NIF_TERM esock_atom_autoclose; -ERL_NIF_TERM esock_atom_bindtodevice; -ERL_NIF_TERM esock_atom_block_source; -ERL_NIF_TERM esock_atom_broadcast; -ERL_NIF_TERM esock_atom_busy_poll; -ERL_NIF_TERM esock_atom_checksum; -ERL_NIF_TERM esock_atom_close; -ERL_NIF_TERM esock_atom_connect; -ERL_NIF_TERM esock_atom_congestion; -ERL_NIF_TERM esock_atom_context; -ERL_NIF_TERM esock_atom_cork; -ERL_NIF_TERM esock_atom_credentials; -ERL_NIF_TERM esock_atom_ctrl; -ERL_NIF_TERM esock_atom_ctrunc; -ERL_NIF_TERM esock_atom_data; -ERL_NIF_TERM esock_atom_debug; -ERL_NIF_TERM esock_atom_default_send_params; -ERL_NIF_TERM esock_atom_delayed_ack_time; -ERL_NIF_TERM esock_atom_dgram; -ERL_NIF_TERM esock_atom_disable_fragments; -ERL_NIF_TERM esock_atom_domain; -ERL_NIF_TERM esock_atom_dontfrag; -ERL_NIF_TERM esock_atom_dontroute; -ERL_NIF_TERM esock_atom_drop_membership; -ERL_NIF_TERM esock_atom_drop_source_membership; -ERL_NIF_TERM esock_atom_dstopts; -ERL_NIF_TERM esock_atom_eor; -ERL_NIF_TERM esock_atom_error; -ERL_NIF_TERM esock_atom_errqueue; -ERL_NIF_TERM esock_atom_esp_network_level; -ERL_NIF_TERM esock_atom_esp_trans_level; -ERL_NIF_TERM esock_atom_events; -ERL_NIF_TERM esock_atom_explicit_eor; -ERL_NIF_TERM esock_atom_faith; -ERL_NIF_TERM esock_atom_false; -ERL_NIF_TERM esock_atom_family; -ERL_NIF_TERM esock_atom_flags; -ERL_NIF_TERM esock_atom_flowinfo; -ERL_NIF_TERM esock_atom_fragment_interleave; -ERL_NIF_TERM esock_atom_freebind; -ERL_NIF_TERM esock_atom_get_peer_addr_info; -ERL_NIF_TERM esock_atom_hdrincl; -ERL_NIF_TERM esock_atom_hmac_ident; -ERL_NIF_TERM esock_atom_hoplimit; -ERL_NIF_TERM esock_atom_hopopts; -ERL_NIF_TERM esock_atom_ifindex; -ERL_NIF_TERM esock_atom_inet; -ERL_NIF_TERM esock_atom_inet6; -ERL_NIF_TERM esock_atom_info; -ERL_NIF_TERM esock_atom_initmsg; -ERL_NIF_TERM esock_atom_iov; -ERL_NIF_TERM esock_atom_ip; -ERL_NIF_TERM esock_atom_ipcomp_level; -ERL_NIF_TERM esock_atom_ipv6; -ERL_NIF_TERM esock_atom_i_want_mapped_v4_addr; -ERL_NIF_TERM esock_atom_join_group; -ERL_NIF_TERM esock_atom_keepalive; -ERL_NIF_TERM esock_atom_keepcnt; -ERL_NIF_TERM esock_atom_keepidle; -ERL_NIF_TERM esock_atom_keepintvl; -ERL_NIF_TERM esock_atom_leave_group; -ERL_NIF_TERM esock_atom_level; -ERL_NIF_TERM esock_atom_linger; -ERL_NIF_TERM esock_atom_local; -ERL_NIF_TERM esock_atom_local_auth_chunks; -ERL_NIF_TERM esock_atom_loopback; -ERL_NIF_TERM esock_atom_lowdelay; -ERL_NIF_TERM esock_atom_mark; -ERL_NIF_TERM esock_atom_maxburst; -ERL_NIF_TERM esock_atom_maxseg; -ERL_NIF_TERM esock_atom_md5sig; -ERL_NIF_TERM esock_atom_mincost; -ERL_NIF_TERM esock_atom_minttl; -ERL_NIF_TERM esock_atom_msfilter; -ERL_NIF_TERM esock_atom_mtu; -ERL_NIF_TERM esock_atom_mtu_discover; -ERL_NIF_TERM esock_atom_multicast_all; -ERL_NIF_TERM esock_atom_multicast_hops; -ERL_NIF_TERM esock_atom_multicast_if; -ERL_NIF_TERM esock_atom_multicast_loop; -ERL_NIF_TERM esock_atom_multicast_ttl; -ERL_NIF_TERM esock_atom_nodelay; -ERL_NIF_TERM esock_atom_nodefrag; -ERL_NIF_TERM esock_atom_noopt; -ERL_NIF_TERM esock_atom_nopush; -ERL_NIF_TERM esock_atom_not_found; -ERL_NIF_TERM esock_atom_not_owner; -ERL_NIF_TERM esock_atom_ok; -ERL_NIF_TERM esock_atom_oob; -ERL_NIF_TERM esock_atom_oobinline; -ERL_NIF_TERM esock_atom_options; -ERL_NIF_TERM esock_atom_origdstaddr; -ERL_NIF_TERM esock_atom_partial_delivery_point; -ERL_NIF_TERM esock_atom_passcred; -ERL_NIF_TERM esock_atom_path; -ERL_NIF_TERM esock_atom_peekcred; -ERL_NIF_TERM esock_atom_peek_off; -ERL_NIF_TERM esock_atom_peer_addr_params; -ERL_NIF_TERM esock_atom_peer_auth_chunks; -ERL_NIF_TERM esock_atom_pktinfo; -ERL_NIF_TERM esock_atom_pktoptions; -ERL_NIF_TERM esock_atom_port; -ERL_NIF_TERM esock_atom_portrange; -ERL_NIF_TERM esock_atom_primary_addr; -ERL_NIF_TERM esock_atom_priority; -ERL_NIF_TERM esock_atom_protocol; -ERL_NIF_TERM esock_atom_raw; -ERL_NIF_TERM esock_atom_rcvbuf; -ERL_NIF_TERM esock_atom_rcvbufforce; -ERL_NIF_TERM esock_atom_rcvlowat; -ERL_NIF_TERM esock_atom_rcvtimeo; -ERL_NIF_TERM esock_atom_rdm; -ERL_NIF_TERM esock_atom_recv; -ERL_NIF_TERM esock_atom_recvdstaddr; -ERL_NIF_TERM esock_atom_recverr; -ERL_NIF_TERM esock_atom_recvfrom; -ERL_NIF_TERM esock_atom_recvif; -ERL_NIF_TERM esock_atom_recvmsg; -ERL_NIF_TERM esock_atom_recvopts; -ERL_NIF_TERM esock_atom_recvorigdstaddr; -ERL_NIF_TERM esock_atom_recvpktinfo; -ERL_NIF_TERM esock_atom_recvtclass; -ERL_NIF_TERM esock_atom_recvtos; -ERL_NIF_TERM esock_atom_recvttl; -ERL_NIF_TERM esock_atom_reliability; -ERL_NIF_TERM esock_atom_reset_streams; -ERL_NIF_TERM esock_atom_retopts; -ERL_NIF_TERM esock_atom_reuseaddr; -ERL_NIF_TERM esock_atom_reuseport; -ERL_NIF_TERM esock_atom_rights; -ERL_NIF_TERM esock_atom_router_alert; -ERL_NIF_TERM esock_atom_rthdr; -ERL_NIF_TERM esock_atom_rtoinfo; -ERL_NIF_TERM esock_atom_rxq_ovfl; -ERL_NIF_TERM esock_atom_scope_id; -ERL_NIF_TERM esock_atom_sctp; -ERL_NIF_TERM esock_atom_sec; -ERL_NIF_TERM esock_atom_select_failed; -ERL_NIF_TERM esock_atom_select_sent; -ERL_NIF_TERM esock_atom_send; -ERL_NIF_TERM esock_atom_sendmsg; -ERL_NIF_TERM esock_atom_sendsrcaddr; -ERL_NIF_TERM esock_atom_sendto; -ERL_NIF_TERM esock_atom_seqpacket; -ERL_NIF_TERM esock_atom_setfib; -ERL_NIF_TERM esock_atom_set_peer_primary_addr; -ERL_NIF_TERM esock_atom_socket; -ERL_NIF_TERM esock_atom_socket_tag; -ERL_NIF_TERM esock_atom_sndbuf; -ERL_NIF_TERM esock_atom_sndbufforce; -ERL_NIF_TERM esock_atom_sndlowat; -ERL_NIF_TERM esock_atom_sndtimeo; -ERL_NIF_TERM esock_atom_spec_dst; -ERL_NIF_TERM esock_atom_status; -ERL_NIF_TERM esock_atom_stream; -ERL_NIF_TERM esock_atom_syncnt; -ERL_NIF_TERM esock_atom_tclass; -ERL_NIF_TERM esock_atom_tcp; -ERL_NIF_TERM esock_atom_throughput; -ERL_NIF_TERM esock_atom_timestamp; -ERL_NIF_TERM esock_atom_tos; -ERL_NIF_TERM esock_atom_transparent; -ERL_NIF_TERM esock_atom_true; -ERL_NIF_TERM esock_atom_trunc; -ERL_NIF_TERM esock_atom_ttl; -ERL_NIF_TERM esock_atom_type; -ERL_NIF_TERM esock_atom_udp; -ERL_NIF_TERM esock_atom_unblock_source; -ERL_NIF_TERM esock_atom_undefined; -ERL_NIF_TERM esock_atom_unicast_hops; -ERL_NIF_TERM esock_atom_unknown; -ERL_NIF_TERM esock_atom_usec; -ERL_NIF_TERM esock_atom_user_timeout; -ERL_NIF_TERM esock_atom_use_ext_recvinfo; -ERL_NIF_TERM esock_atom_use_min_mtu; -ERL_NIF_TERM esock_atom_v6only; - -/* *** "Global" error (=reason) atoms *** */ -ERL_NIF_TERM esock_atom_eagain; -ERL_NIF_TERM esock_atom_eafnosupport; -ERL_NIF_TERM esock_atom_einval; - -/* *** Atoms *** */ -static ERL_NIF_TERM atom_adaptation_layer; -static ERL_NIF_TERM atom_address; -static ERL_NIF_TERM atom_association; -static ERL_NIF_TERM atom_assoc_id; -static ERL_NIF_TERM atom_authentication; -static ERL_NIF_TERM atom_bool; -static ERL_NIF_TERM atom_close; -static ERL_NIF_TERM atom_closed; -static ERL_NIF_TERM atom_closing; -static ERL_NIF_TERM atom_cookie_life; -static ERL_NIF_TERM atom_data_in; -static ERL_NIF_TERM atom_do; -static ERL_NIF_TERM atom_dont; -static ERL_NIF_TERM atom_exclude; -static ERL_NIF_TERM atom_false; -static ERL_NIF_TERM atom_global_counters; -static ERL_NIF_TERM atom_in4_sockaddr; -static ERL_NIF_TERM atom_in6_sockaddr; -static ERL_NIF_TERM atom_include; -static ERL_NIF_TERM atom_initial; -static ERL_NIF_TERM atom_int; -static ERL_NIF_TERM atom_interface; -static ERL_NIF_TERM atom_iow; -static ERL_NIF_TERM atom_local_rwnd; -static ERL_NIF_TERM atom_max; -static ERL_NIF_TERM atom_max_attempts; -static ERL_NIF_TERM atom_max_init_timeo; -static ERL_NIF_TERM atom_max_instreams; -static ERL_NIF_TERM atom_max_rxt; -static ERL_NIF_TERM atom_min; -static ERL_NIF_TERM atom_mode; -static ERL_NIF_TERM atom_multiaddr; -// static ERL_NIF_TERM atom_nif_abort; -static ERL_NIF_TERM atom_null; -static ERL_NIF_TERM atom_num_dinet; -static ERL_NIF_TERM atom_num_dinet6; -static ERL_NIF_TERM atom_num_dlocal; -static ERL_NIF_TERM atom_num_outstreams; -static ERL_NIF_TERM atom_num_peer_dests; -static ERL_NIF_TERM atom_num_pip; -static ERL_NIF_TERM atom_num_psctp; -static ERL_NIF_TERM atom_num_ptcp; -static ERL_NIF_TERM atom_num_pudp; -static ERL_NIF_TERM atom_num_sockets; -static ERL_NIF_TERM atom_num_tdgrams; -static ERL_NIF_TERM atom_num_tseqpkgs; -static ERL_NIF_TERM atom_num_tstreams; -static ERL_NIF_TERM atom_partial_delivery; -static ERL_NIF_TERM atom_peer_error; -static ERL_NIF_TERM atom_peer_rwnd; -static ERL_NIF_TERM atom_probe; -static ERL_NIF_TERM atom_select; -static ERL_NIF_TERM atom_sender_dry; -static ERL_NIF_TERM atom_send_failure; -static ERL_NIF_TERM atom_shutdown; -static ERL_NIF_TERM atom_slist; -static ERL_NIF_TERM atom_sourceaddr; -static ERL_NIF_TERM atom_timeout; -static ERL_NIF_TERM atom_true; -static ERL_NIF_TERM atom_want; - -static ERL_NIF_TERM atom_eisconn; -static ERL_NIF_TERM atom_enotclosing; -static ERL_NIF_TERM atom_enotconn; -static ERL_NIF_TERM atom_exalloc; -static ERL_NIF_TERM atom_exbadstate; -static ERL_NIF_TERM atom_exbusy; -static ERL_NIF_TERM atom_exmon; -static ERL_NIF_TERM atom_exself; -static ERL_NIF_TERM atom_exsend; + +/* *** Global atoms *** */ +#define GLOBAL_ATOMS \ + GLOBAL_ATOM_DECL(abort); \ + GLOBAL_ATOM_DECL(accept); \ + GLOBAL_ATOM_DECL(acceptconn); \ + GLOBAL_ATOM_DECL(acceptfilter); \ + GLOBAL_ATOM_DECL(adaption_layer); \ + GLOBAL_ATOM_DECL(addr); \ + GLOBAL_ATOM_DECL(addrform); \ + GLOBAL_ATOM_DECL(add_membership); \ + GLOBAL_ATOM_DECL(add_source_membership); \ + GLOBAL_ATOM_DECL(any); \ + GLOBAL_ATOM_DECL(associnfo); \ + GLOBAL_ATOM_DECL(authhdr); \ + GLOBAL_ATOM_DECL(auth_active_key); \ + GLOBAL_ATOM_DECL(auth_asconf); \ + GLOBAL_ATOM_DECL(auth_chunk); \ + GLOBAL_ATOM_DECL(auth_delete_key); \ + GLOBAL_ATOM_DECL(auth_key); \ + GLOBAL_ATOM_DECL(auth_level); \ + GLOBAL_ATOM_DECL(autoclose); \ + GLOBAL_ATOM_DECL(bindtodevice); \ + GLOBAL_ATOM_DECL(block_source); \ + GLOBAL_ATOM_DECL(broadcast); \ + GLOBAL_ATOM_DECL(busy_poll); \ + GLOBAL_ATOM_DECL(checksum); \ + GLOBAL_ATOM_DECL(close); \ + GLOBAL_ATOM_DECL(connect); \ + GLOBAL_ATOM_DECL(congestion); \ + GLOBAL_ATOM_DECL(context); \ + GLOBAL_ATOM_DECL(cork); \ + GLOBAL_ATOM_DECL(credentials); \ + GLOBAL_ATOM_DECL(ctrl); \ + GLOBAL_ATOM_DECL(ctrunc); \ + GLOBAL_ATOM_DECL(data); \ + GLOBAL_ATOM_DECL(debug); \ + GLOBAL_ATOM_DECL(default_send_params); \ + GLOBAL_ATOM_DECL(delayed_ack_time); \ + GLOBAL_ATOM_DECL(dgram); \ + GLOBAL_ATOM_DECL(disable_fragments); \ + GLOBAL_ATOM_DECL(domain); \ + GLOBAL_ATOM_DECL(dontfrag); \ + GLOBAL_ATOM_DECL(dontroute); \ + GLOBAL_ATOM_DECL(drop_membership); \ + GLOBAL_ATOM_DECL(drop_source_membership); \ + GLOBAL_ATOM_DECL(dstopts); \ + GLOBAL_ATOM_DECL(eor); \ + GLOBAL_ATOM_DECL(error); \ + GLOBAL_ATOM_DECL(errqueue); \ + GLOBAL_ATOM_DECL(esp_network_level); \ + GLOBAL_ATOM_DECL(esp_trans_level); \ + GLOBAL_ATOM_DECL(events); \ + GLOBAL_ATOM_DECL(explicit_eor); \ + GLOBAL_ATOM_DECL(faith); \ + GLOBAL_ATOM_DECL(false); \ + GLOBAL_ATOM_DECL(family); \ + GLOBAL_ATOM_DECL(flags); \ + GLOBAL_ATOM_DECL(flowinfo); \ + GLOBAL_ATOM_DECL(fragment_interleave); \ + GLOBAL_ATOM_DECL(freebind); \ + GLOBAL_ATOM_DECL(get_peer_addr_info); \ + GLOBAL_ATOM_DECL(hdrincl); \ + GLOBAL_ATOM_DECL(hmac_ident); \ + GLOBAL_ATOM_DECL(hoplimit); \ + GLOBAL_ATOM_DECL(hopopts); \ + GLOBAL_ATOM_DECL(ifindex); \ + GLOBAL_ATOM_DECL(inet); \ + GLOBAL_ATOM_DECL(inet6); \ + GLOBAL_ATOM_DECL(info); \ + GLOBAL_ATOM_DECL(initmsg); \ + GLOBAL_ATOM_DECL(iov); \ + GLOBAL_ATOM_DECL(ip); \ + GLOBAL_ATOM_DECL(ipcomp_level); \ + GLOBAL_ATOM_DECL(ipv6); \ + GLOBAL_ATOM_DECL(i_want_mapped_v4_addr); \ + GLOBAL_ATOM_DECL(join_group); \ + GLOBAL_ATOM_DECL(keepalive); \ + GLOBAL_ATOM_DECL(keepcnt); \ + GLOBAL_ATOM_DECL(keepidle); \ + GLOBAL_ATOM_DECL(keepintvl); \ + GLOBAL_ATOM_DECL(leave_group); \ + GLOBAL_ATOM_DECL(level); \ + GLOBAL_ATOM_DECL(linger); \ + GLOBAL_ATOM_DECL(local); \ + GLOBAL_ATOM_DECL(local_auth_chunks); \ + GLOBAL_ATOM_DECL(loopback); \ + GLOBAL_ATOM_DECL(lowdelay); \ + GLOBAL_ATOM_DECL(mark); \ + GLOBAL_ATOM_DECL(maxburst); \ + GLOBAL_ATOM_DECL(maxseg); \ + GLOBAL_ATOM_DECL(md5sig); \ + GLOBAL_ATOM_DECL(mincost); \ + GLOBAL_ATOM_DECL(minttl); \ + GLOBAL_ATOM_DECL(msfilter); \ + GLOBAL_ATOM_DECL(mtu); \ + GLOBAL_ATOM_DECL(mtu_discover); \ + GLOBAL_ATOM_DECL(multicast_all); \ + GLOBAL_ATOM_DECL(multicast_hops); \ + GLOBAL_ATOM_DECL(multicast_if); \ + GLOBAL_ATOM_DECL(multicast_loop); \ + GLOBAL_ATOM_DECL(multicast_ttl); \ + GLOBAL_ATOM_DECL(nodelay); \ + GLOBAL_ATOM_DECL(nodefrag); \ + GLOBAL_ATOM_DECL(noopt); \ + GLOBAL_ATOM_DECL(nopush); \ + GLOBAL_ATOM_DECL(not_found); \ + GLOBAL_ATOM_DECL(not_owner); \ + GLOBAL_ATOM_DECL(ok); \ + GLOBAL_ATOM_DECL(oob); \ + GLOBAL_ATOM_DECL(oobinline); \ + GLOBAL_ATOM_DECL(options); \ + GLOBAL_ATOM_DECL(origdstaddr); \ + GLOBAL_ATOM_DECL(partial_delivery_point); \ + GLOBAL_ATOM_DECL(passcred); \ + GLOBAL_ATOM_DECL(path); \ + GLOBAL_ATOM_DECL(peekcred); \ + GLOBAL_ATOM_DECL(peek_off); \ + GLOBAL_ATOM_DECL(peer_addr_params); \ + GLOBAL_ATOM_DECL(peer_auth_chunks); \ + GLOBAL_ATOM_DECL(pktinfo); \ + GLOBAL_ATOM_DECL(pktoptions); \ + GLOBAL_ATOM_DECL(port); \ + GLOBAL_ATOM_DECL(portrange); \ + GLOBAL_ATOM_DECL(primary_addr); \ + GLOBAL_ATOM_DECL(priority); \ + GLOBAL_ATOM_DECL(protocol); \ + GLOBAL_ATOM_DECL(raw); \ + GLOBAL_ATOM_DECL(rcvbuf); \ + GLOBAL_ATOM_DECL(rcvbufforce); \ + GLOBAL_ATOM_DECL(rcvlowat); \ + GLOBAL_ATOM_DECL(rcvtimeo); \ + GLOBAL_ATOM_DECL(rdm); \ + GLOBAL_ATOM_DECL(recv); \ + GLOBAL_ATOM_DECL(recvdstaddr); \ + GLOBAL_ATOM_DECL(recverr); \ + GLOBAL_ATOM_DECL(recvfrom); \ + GLOBAL_ATOM_DECL(recvif); \ + GLOBAL_ATOM_DECL(recvmsg); \ + GLOBAL_ATOM_DECL(recvopts); \ + GLOBAL_ATOM_DECL(recvorigdstaddr); \ + GLOBAL_ATOM_DECL(recvpktinfo); \ + GLOBAL_ATOM_DECL(recvtclass); \ + GLOBAL_ATOM_DECL(recvtos); \ + GLOBAL_ATOM_DECL(recvttl); \ + GLOBAL_ATOM_DECL(reliability); \ + GLOBAL_ATOM_DECL(reset_streams); \ + GLOBAL_ATOM_DECL(retopts); \ + GLOBAL_ATOM_DECL(reuseaddr); \ + GLOBAL_ATOM_DECL(reuseport); \ + GLOBAL_ATOM_DECL(rights); \ + GLOBAL_ATOM_DECL(router_alert); \ + GLOBAL_ATOM_DECL(rthdr); \ + GLOBAL_ATOM_DECL(rtoinfo); \ + GLOBAL_ATOM_DECL(rxq_ovfl); \ + GLOBAL_ATOM_DECL(scope_id); \ + GLOBAL_ATOM_DECL(sctp); \ + GLOBAL_ATOM_DECL(sec); \ + GLOBAL_ATOM_DECL(select_failed); \ + GLOBAL_ATOM_DECL(select_sent); \ + GLOBAL_ATOM_DECL(send); \ + GLOBAL_ATOM_DECL(sendmsg); \ + GLOBAL_ATOM_DECL(sendsrcaddr); \ + GLOBAL_ATOM_DECL(sendto); \ + GLOBAL_ATOM_DECL(seqpacket); \ + GLOBAL_ATOM_DECL(setfib); \ + GLOBAL_ATOM_DECL(set_peer_primary_addr); \ + GLOBAL_ATOM_DECL(socket); \ + GLOBAL_ATOM_DECL(sndbuf); \ + GLOBAL_ATOM_DECL(sndbufforce); \ + GLOBAL_ATOM_DECL(sndlowat); \ + GLOBAL_ATOM_DECL(sndtimeo); \ + GLOBAL_ATOM_DECL(spec_dst); \ + GLOBAL_ATOM_DECL(status); \ + GLOBAL_ATOM_DECL(stream); \ + GLOBAL_ATOM_DECL(syncnt); \ + GLOBAL_ATOM_DECL(tclass); \ + GLOBAL_ATOM_DECL(tcp); \ + GLOBAL_ATOM_DECL(throughput); \ + GLOBAL_ATOM_DECL(timestamp); \ + GLOBAL_ATOM_DECL(tos); \ + GLOBAL_ATOM_DECL(transparent); \ + GLOBAL_ATOM_DECL(true); \ + GLOBAL_ATOM_DECL(trunc); \ + GLOBAL_ATOM_DECL(ttl); \ + GLOBAL_ATOM_DECL(type); \ + GLOBAL_ATOM_DECL(udp); \ + GLOBAL_ATOM_DECL(unblock_source); \ + GLOBAL_ATOM_DECL(undefined); \ + GLOBAL_ATOM_DECL(unicast_hops); \ + GLOBAL_ATOM_DECL(unknown); \ + GLOBAL_ATOM_DECL(usec); \ + GLOBAL_ATOM_DECL(user_timeout); \ + GLOBAL_ATOM_DECL(use_ext_recvinfo); \ + GLOBAL_ATOM_DECL(use_min_mtu); \ + GLOBAL_ATOM_DECL(v6only); + + +/* *** Global error reason atoms *** */ +#define GLOBAL_ERROR_REASON_ATOMS \ + GLOBAL_ATOM_DECL(eagain); \ + GLOBAL_ATOM_DECL(eafnosupport); \ + GLOBAL_ATOM_DECL(einval); + + +#define GLOBAL_ATOM_DECL(A) ERL_NIF_TERM esock_atom_##A +GLOBAL_ATOMS +GLOBAL_ERROR_REASON_ATOMS +#undef GLOBAL_ATOM_DECL +ERL_NIF_TERM esock_atom_socket_tag; // This has a "special" name ('$socket') + +/* *** Local atoms *** */ +#define LOCAL_ATOMS \ + LOCAL_ATOM_DECL(adaptation_layer); \ + LOCAL_ATOM_DECL(address); \ + LOCAL_ATOM_DECL(association); \ + LOCAL_ATOM_DECL(assoc_id); \ + LOCAL_ATOM_DECL(authentication); \ + LOCAL_ATOM_DECL(bool); \ + LOCAL_ATOM_DECL(close); \ + LOCAL_ATOM_DECL(closed); \ + LOCAL_ATOM_DECL(closing); \ + LOCAL_ATOM_DECL(cookie_life); \ + LOCAL_ATOM_DECL(data_in); \ + LOCAL_ATOM_DECL(do); \ + LOCAL_ATOM_DECL(dont); \ + LOCAL_ATOM_DECL(exclude); \ + LOCAL_ATOM_DECL(false); \ + LOCAL_ATOM_DECL(global_counters); \ + LOCAL_ATOM_DECL(in4_sockaddr); \ + LOCAL_ATOM_DECL(in6_sockaddr); \ + LOCAL_ATOM_DECL(include); \ + LOCAL_ATOM_DECL(initial); \ + LOCAL_ATOM_DECL(int); \ + LOCAL_ATOM_DECL(interface); \ + LOCAL_ATOM_DECL(iow); \ + LOCAL_ATOM_DECL(local_rwnd); \ + LOCAL_ATOM_DECL(max); \ + LOCAL_ATOM_DECL(max_attempts); \ + LOCAL_ATOM_DECL(max_init_timeo); \ + LOCAL_ATOM_DECL(max_instreams); \ + LOCAL_ATOM_DECL(max_rxt); \ + LOCAL_ATOM_DECL(min); \ + LOCAL_ATOM_DECL(mode); \ + LOCAL_ATOM_DECL(multiaddr); \ + LOCAL_ATOM_DECL(null); \ + LOCAL_ATOM_DECL(num_dinet); \ + LOCAL_ATOM_DECL(num_dinet6); \ + LOCAL_ATOM_DECL(num_dlocal); \ + LOCAL_ATOM_DECL(num_outstreams); \ + LOCAL_ATOM_DECL(num_peer_dests); \ + LOCAL_ATOM_DECL(num_pip); \ + LOCAL_ATOM_DECL(num_psctp); \ + LOCAL_ATOM_DECL(num_ptcp); \ + LOCAL_ATOM_DECL(num_pudp); \ + LOCAL_ATOM_DECL(num_sockets); \ + LOCAL_ATOM_DECL(num_tdgrams); \ + LOCAL_ATOM_DECL(num_tseqpkgs); \ + LOCAL_ATOM_DECL(num_tstreams); \ + LOCAL_ATOM_DECL(partial_delivery); \ + LOCAL_ATOM_DECL(peer_error); \ + LOCAL_ATOM_DECL(peer_rwnd); \ + LOCAL_ATOM_DECL(probe); \ + LOCAL_ATOM_DECL(select); \ + LOCAL_ATOM_DECL(sender_dry); \ + LOCAL_ATOM_DECL(send_failure); \ + LOCAL_ATOM_DECL(shutdown); \ + LOCAL_ATOM_DECL(slist); \ + LOCAL_ATOM_DECL(sourceaddr); \ + LOCAL_ATOM_DECL(timeout); \ + LOCAL_ATOM_DECL(true); \ + LOCAL_ATOM_DECL(want); + +/* Local error reason atoms */ +#define LOCAL_ERROR_REASON_ATOMS \ + LOCAL_ATOM_DECL(eisconn); \ + LOCAL_ATOM_DECL(enotclosing); \ + LOCAL_ATOM_DECL(enotconn); \ + LOCAL_ATOM_DECL(exalloc); \ + LOCAL_ATOM_DECL(exbadstate); \ + LOCAL_ATOM_DECL(exbusy); \ + LOCAL_ATOM_DECL(exmon); \ + LOCAL_ATOM_DECL(exself); \ + LOCAL_ATOM_DECL(exsend); + +#define LOCAL_ATOM_DECL(LA) static ERL_NIF_TERM atom_##LA +LOCAL_ATOMS +LOCAL_ERROR_REASON_ATOMS +#undef LOCAL_ATOM_DECL /* *** Sockets *** */ @@ -2887,7 +2887,7 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, * * Description: * This function is intended to answer the question: "Is X supported?" - * Currently only one key is "supported": options + * Currently three keys are "supported": options | sctp | ipv6 * That results in a list of all *known options* (known by us) and if * the platform supports (OS) it or not. * @@ -4928,14 +4928,15 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env, return enif_raise_exception(env, MKA(env, "notsup")); #else SocketDescriptor* descP; - ERL_NIF_TERM ref, res; + ERL_NIF_TERM sockRef, ref, res; SGDBG( ("SOCKET", "nif_accept -> entry with argc: %d\r\n", argc) ); /* Extract arguments and perform preliminary validation */ + sockRef = argv[0]; if ((argc != 2) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP)) { + !enif_get_resource(env, sockRef, sockets, (void**) &descP)) { return enif_make_badarg(env); } ref = argv[1]; @@ -4948,7 +4949,7 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env, MLOCK(descP->accMtx); - res = naccept(env, descP, ref); + res = naccept(env, descP, sockRef, ref); MUNLOCK(descP->accMtx); @@ -4962,6 +4963,7 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env, static ERL_NIF_TERM naccept(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM ref) { ERL_NIF_TERM res; @@ -4975,7 +4977,7 @@ ERL_NIF_TERM naccept(ErlNifEnv* env, break; case SOCKET_STATE_ACCEPTING: - res = naccept_accepting(env, descP, ref); + res = naccept_accepting(env, descP, sockRef, ref); break; default: @@ -5112,6 +5114,7 @@ ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env, static ERL_NIF_TERM naccept_accepting(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM ref) { ErlNifPid caller; @@ -5128,15 +5131,12 @@ ERL_NIF_TERM naccept_accepting(ErlNifEnv* env, "\r\n Current: %T" "\r\n", caller, descP->currentAcceptor.pid) ); - - - - if (compare_pids(env, &descP->currentAcceptor.pid, &caller)) { + if (COMPARE_PIDS(&descP->currentAcceptor.pid, &caller) == 0) { SSDBG( descP, ("SOCKET", "naccept_accepting -> current acceptor\r\n") ); - res = naccept_accepting_current(env, descP, ref); + res = naccept_accepting_current(env, descP, sockRef, ref); } else { @@ -5161,7 +5161,8 @@ ERL_NIF_TERM naccept_accepting(ErlNifEnv* env, static ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env, SocketDescriptor* descP, - ERL_NIF_TERM ref) + ERL_NIF_TERM sockRef, + ERL_NIF_TERM accRef) { SocketAddress remote; unsigned int n; @@ -5182,13 +5183,15 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env, "naccept_accepting_current -> accept failed: %d\r\n", save_errno) ); - res = naccept_accepting_current_error(env, descP, ref, save_errno); + res = naccept_accepting_current_error(env, descP, sockRef, + accRef, save_errno); } else { SSDBG( descP, ("SOCKET", "naccept_accepting_current -> accepted\r\n") ); - res = naccept_accepting_current_accept(env, descP, accSock, &remote); + res = naccept_accepting_current_accept(env, descP, sockRef, + accSock, &remote); } @@ -5203,10 +5206,10 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env, static ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, SOCKET accSock, SocketAddress* remote) { - int sres; ERL_NIF_TERM res; if (naccept_accepted(env, descP, accSock, @@ -5220,33 +5223,21 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env, * */ - if (acceptor_pop(env, descP, - &descP->currentAcceptor.pid, - &descP->currentAcceptor.mon, - &descP->currentAcceptor.ref)) { - - /* There was another one */ + if (!activate_next_acceptor(env, descP, sockRef)) { SSDBG( descP, ("SOCKET", - "naccept_accepting_current_accept -> new (active) acceptor: " - "\r\n pid: %T" - "\r\n ref: %T" - "\r\n", - descP->currentAcceptor.pid, - descP->currentAcceptor.ref) ); + "naccept_accepting_current_accept -> " + "no more writers\r\n") ); - if ((sres = esock_select_read(env, descP->sock, descP, - &descP->currentAcceptor.pid, - descP->currentAcceptor.ref)) < 0) { - esock_warning_msg("Failed select (%d) for new acceptor " - "after current (%T) died\r\n", - sres, descP->currentAcceptor.pid); - } - } else { - descP->currentAcceptorP = NULL; - descP->state = SOCKET_STATE_LISTENING; + descP->state = SOCKET_STATE_LISTENING; + + descP->currentAcceptorP = NULL; + descP->currentAcceptor.ref = esock_atom_undefined; + enif_set_pid_undefined(&descP->currentAcceptor.pid); + esock_monitor_init(&descP->currentAcceptor.mon); } + } return res; @@ -5262,10 +5253,12 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env, static ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env, SocketDescriptor* descP, - ERL_NIF_TERM ref, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM opRef, int save_errno) { - ERL_NIF_TERM res; + SocketRequestor req; + ERL_NIF_TERM res, reason; if (save_errno == ERRNO_BLOCK) { @@ -5275,14 +5268,27 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env, SSDBG( descP, ("SOCKET", - "naccept_accepting_current_error -> would block: try again\r\n") ); + "naccept_accepting_current_error -> " + "would block: try again\r\n") ); - res = naccept_busy_retry(env, descP, ref, &descP->currentAcceptor.pid, + res = naccept_busy_retry(env, descP, opRef, &descP->currentAcceptor.pid, /* No state change */ descP->state); } else { - res = esock_make_error_errno(env, save_errno); + + reason = MKA(env, erl_errno_id(save_errno)); + res = esock_make_error(env, reason); + + while (acceptor_pop(env, descP, &req)) { + SSDBG( descP, + ("SOCKET", "naccept_accepting_current_error -> abort %T\r\n", + req.pid) ); + esock_send_abort_msg(env, sockRef, req.ref, reason, &req.pid); + DEMONP("naccept_accepting_current_error -> pop'ed writer", + env, descP, &req.mon); + } + } return res; @@ -7002,7 +7008,7 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env, if (enif_self(env, &caller) == NULL) return esock_make_error(env, atom_exself); - if (!compare_pids(env, &descP->ctrlPid, &caller)) { + if (COMPARE_PIDS(&descP->ctrlPid, &caller) != 0) { SSDBG( descP, ("SOCKET", "nsetopt_otp_ctrl_proc -> not owner (%T)\r\n", descP->ctrlPid) ); return esock_make_error(env, esock_atom_not_owner); @@ -9491,7 +9497,6 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env, int res; size_t sz; unsigned int tmp; - Sint32 tmpAssocId; SSDBG( descP, ("SOCKET", "nsetopt_lvl_sctp_associnfo -> entry with" @@ -9532,10 +9537,29 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env, /* On some platforms the assoc id is typed as an unsigned integer (uint32) * So, to avoid warnings there, we always make an explicit cast... + * Also, size of types matter, so adjust for that... */ - if (!GET_INT(env, eAssocId, &tmpAssocId)) - return esock_make_error(env, esock_atom_einval); - assocParams.sasoc_assoc_id = (typeof(assocParams.sasoc_assoc_id)) tmpAssocId; + +#if (SIZEOF_INT == 4) + { + int tmpAssocId; + if (!GET_INT(env, eAssocId, &tmpAssocId)) + return esock_make_error(env, esock_atom_einval); + assocParams.sasoc_assoc_id = + (typeof(assocParams.sasoc_assoc_id)) tmpAssocId; + } +#elif (SIZEOF_LONG == 4) + { + long tmpAssocId; + if (!GET_LONG(env, eAssocId, &tmpAssocId)) + return esock_make_error(env, esock_atom_einval); + assocParams.sasoc_assoc_id = + (typeof(assocParams.sasoc_assoc_id)) tmpAssocId; + } +#else + SIZE CHECK FOR ASSOC ID FAILED +#endif + /* * We should really make sure this is ok in erlang (to ensure that @@ -9620,7 +9644,10 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env, ERL_NIF_TERM result; ERL_NIF_TERM eDataIn, eAssoc, eAddr, eSndFailure; ERL_NIF_TERM ePeerError, eShutdown, ePartialDelivery; - ERL_NIF_TERM eAdaptLayer, eAuth; + ERL_NIF_TERM eAdaptLayer; +#if defined(HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_AUTHENTICATION_EVENT) + ERL_NIF_TERM eAuth; +#endif #if defined(HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_SENDER_DRY_EVENT) ERL_NIF_TERM eSndDry; #endif @@ -9841,7 +9868,6 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, struct sctp_rtoinfo rtoInfo; int res; size_t sz; - Sint32 tmpAssocId; SSDBG( descP, ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> entry with" @@ -9876,10 +9902,31 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, /* On some platforms the assoc id is typed as an unsigned integer (uint32) * So, to avoid warnings there, we always make an explicit cast... + * Also, size of types matter, so adjust for that... */ + +#if (SIZEOF_INT == 4) + { + int tmpAssocId; + if (!GET_INT(env, eAssocId, &tmpAssocId)) + return esock_make_error(env, esock_atom_einval); + rtoInfo.srto_assoc_id = (typeof(rtoInfo.srto_assoc_id)) tmpAssocId; + } +#elif (SIZEOF_LONG == 4) + { + long tmpAssocId; + if (!GET_LONG(env, eAssocId, &tmpAssocId)) + return esock_make_error(env, esock_atom_einval); + rtoInfo.srto_assoc_id = (typeof(rtoInfo.srto_assoc_id)) tmpAssocId; + } +#else + SIZE CHECK FOR ASSOC ID FAILED +#endif + /* if (!GET_INT(env, eAssocId, &tmpAssocId)) return esock_make_error(env, esock_atom_einval); rtoInfo.srto_assoc_id = (typeof(rtoInfo.srto_assoc_id)) tmpAssocId; + */ if (!GET_UINT(env, eInitial, &rtoInfo.srto_initial)) return esock_make_error(env, esock_atom_einval); @@ -9985,6 +10032,7 @@ ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env, /* nsetopt_str_opt - set an option that has an string value */ +#if defined(USE_SETOPT_STR_OPT) static ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env, SocketDescriptor* descP, @@ -10013,6 +10061,7 @@ ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env, return result; } +#endif /* nsetopt_timeval_opt - set an option that has an (timeval) bool value @@ -10503,7 +10552,7 @@ static ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env, SocketDescriptor* descP) { - ERL_NIF_TERM result; + ERL_NIF_TERM result, reason; int val = descP->domain; switch (val) { @@ -10524,10 +10573,8 @@ ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env, #endif default: - result = esock_make_error(env, - MKT2(env, - esock_atom_unknown, - MKI(env, val))); + reason = MKT2(env, esock_atom_unknown, MKI(env, val)); + result = esock_make_error(env, reason); break; } @@ -10541,7 +10588,7 @@ static ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env, SocketDescriptor* descP) { - ERL_NIF_TERM result; + ERL_NIF_TERM result, reason; int val = descP->type; switch (val) { @@ -10567,8 +10614,8 @@ ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env, break; default: - result = esock_make_error(env, - MKT2(env, esock_atom_unknown, MKI(env, val))); + reason = MKT2(env, esock_atom_unknown, MKI(env, val)); + result = esock_make_error(env, reason); break; } @@ -10582,7 +10629,7 @@ static ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env, SocketDescriptor* descP) { - ERL_NIF_TERM result; + ERL_NIF_TERM result, reason; int val = descP->protocol; switch (val) { @@ -10605,8 +10652,8 @@ ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env, #endif default: - result = esock_make_error(env, - MKT2(env, esock_atom_unknown, MKI(env, val))); + reason = MKT2(env, esock_atom_unknown, MKI(env, val)); + result = esock_make_error(env, reason); break; } @@ -11021,7 +11068,7 @@ static ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env, SocketDescriptor* descP) { - ERL_NIF_TERM result; + ERL_NIF_TERM result, reason; int val; SOCKOPTLEN_T valSz = sizeof(val); int res; @@ -11050,10 +11097,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env, #endif default: - result = esock_make_error(env, - MKT2(env, - esock_atom_unknown, - MKI(env, val))); + reason = MKT2(env, esock_atom_unknown, MKI(env, val)); + result = esock_make_error(env, reason); break; } } @@ -11148,7 +11193,7 @@ static ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env, SocketDescriptor* descP) { - ERL_NIF_TERM result; + ERL_NIF_TERM result, reason; int val; SOCKOPTLEN_T valSz = sizeof(val); int res; @@ -11179,8 +11224,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env, #endif default: - result = esock_make_error(env, - MKT2(env, esock_atom_unknown, MKI(env, val))); + reason = MKT2(env, esock_atom_unknown, MKI(env, val)); + result = esock_make_error(env, reason); break; } } @@ -11285,7 +11330,7 @@ static ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env, SocketDescriptor* descP) { - ERL_NIF_TERM result; + ERL_NIF_TERM result, reason; int val; SOCKOPTLEN_T valSz = sizeof(val); int res; @@ -11314,8 +11359,8 @@ ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env, result = esock_make_ok2(env, esock_atom_rdm); break; default: - result = esock_make_error(env, - MKT2(env, esock_atom_unknown, MKI(env, val))); + reason = MKT2(env, esock_atom_unknown, MKI(env, val)); + result = esock_make_error(env, reason); break; } } @@ -11485,7 +11530,8 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env, #endif default: - SSDBG( descP, ("SOCKET", "ngetopt_lvl_ip -> unknown opt %d\r\n", eOpt) ); + SSDBG( descP, + ("SOCKET", "ngetopt_lvl_ip -> unknown opt %d\r\n", eOpt) ); result = esock_make_error(env, esock_atom_einval); break; } @@ -12910,6 +12956,7 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env, * The actual size of the (read) value will be communicated * in the optSz variable. */ +#if defined(USE_GETOPT_STR_OPT) static ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env, SocketDescriptor* descP, @@ -12948,6 +12995,7 @@ ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env, return result; } +#endif // if defined(USE_GETOPT_STR_OPT) #endif // if !defined(__WIN32__) @@ -13120,14 +13168,15 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env, return enif_raise_exception(env, MKA(env, "notsup")); #else SocketDescriptor* descP; - ERL_NIF_TERM op, opRef, result; + ERL_NIF_TERM op, sockRef, opRef, result; SGDBG( ("SOCKET", "nif_cancel -> entry with argc: %d\r\n", argc) ); /* Extract arguments and perform preliminary validation */ + sockRef = argv[0]; if ((argc != 3) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP)) { + !enif_get_resource(env, sockRef, sockets, (void**) &descP)) { return enif_make_badarg(env); } op = argv[1]; @@ -13142,7 +13191,7 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env, "\r\n opRef: %T" "\r\n", descP->sock, op, opRef) ); - result = ncancel(env, descP, op, opRef); + result = ncancel(env, descP, op, sockRef, opRef); SSDBG( descP, ("SOCKET", "nif_cancel -> done with result: " @@ -13159,6 +13208,7 @@ static ERL_NIF_TERM ncancel(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM op, + ERL_NIF_TERM sockRef, ERL_NIF_TERM opRef) { /* <KOLLA> @@ -13172,19 +13222,19 @@ ERL_NIF_TERM ncancel(ErlNifEnv* env, if (COMPARE(op, esock_atom_connect) == 0) { return ncancel_connect(env, descP, opRef); } else if (COMPARE(op, esock_atom_accept) == 0) { - return ncancel_accept(env, descP, opRef); + return ncancel_accept(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_send) == 0) { - return ncancel_send(env, descP, opRef); + return ncancel_send(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_sendto) == 0) { - return ncancel_send(env, descP, opRef); + return ncancel_send(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_sendmsg) == 0) { - return ncancel_send(env, descP, opRef); + return ncancel_send(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_recv) == 0) { - return ncancel_recv(env, descP, opRef); + return ncancel_recv(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_recvfrom) == 0) { - return ncancel_recv(env, descP, opRef); + return ncancel_recv(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_recvmsg) == 0) { - return ncancel_recv(env, descP, opRef); + return ncancel_recv(env, descP, sockRef, opRef); } else { return esock_make_error(env, esock_atom_einval); } @@ -13218,6 +13268,7 @@ ERL_NIF_TERM ncancel_connect(ErlNifEnv* env, static ERL_NIF_TERM ncancel_accept(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM opRef) { ERL_NIF_TERM res; @@ -13233,7 +13284,7 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env, if (descP->currentAcceptorP != NULL) { if (COMPARE(opRef, descP->currentAcceptor.ref) == 0) { - res = ncancel_accept_current(env, descP); + res = ncancel_accept_current(env, descP, sockRef); } else { res = ncancel_accept_waiting(env, descP, opRef); } @@ -13259,9 +13310,9 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env, */ static ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env, - SocketDescriptor* descP) + SocketDescriptor* descP, + ERL_NIF_TERM sockRef) { - int sres; ERL_NIF_TERM res; SSDBG( descP, ("SOCKET", "ncancel_accept_current -> entry\r\n") ); @@ -13270,36 +13321,22 @@ ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env, env, descP, &descP->currentAcceptor.mon); res = ncancel_read_select(env, descP, descP->currentAcceptor.ref); - SSDBG( descP, ("SOCKET", "ncancel_accept_current -> cancel res: %T\r\n", res) ); + SSDBG( descP, ("SOCKET", + "ncancel_accept_current -> cancel res: %T\r\n", res) ); - if (acceptor_pop(env, descP, - &descP->currentAcceptor.pid, - &descP->currentAcceptor.mon, - &descP->currentAcceptor.ref)) { - - /* There was another one */ - - SSDBG( descP, ("SOCKET", "ncancel_accept_current -> new (active) acceptor: " - "\r\n pid: %T" - "\r\n ref: %T" - "\r\n", - descP->currentAcceptor.pid, - descP->currentAcceptor.ref) ); - - if ((sres = esock_select_read(env, descP->sock, descP, - &descP->currentAcceptor.pid, - descP->currentAcceptor.ref)) < 0) { - return esock_make_error(env, - MKT2(env, - esock_atom_select_failed, - MKI(env, sres))); - } - } else { - SSDBG( descP, ("SOCKET", "ncancel_accept_current -> no more acceptors\r\n") ); - descP->currentAcceptorP = NULL; - descP->state = SOCKET_STATE_LISTENING; + if (!activate_next_acceptor(env, descP, sockRef)) { + + SSDBG( descP, + ("SOCKET", "ncancel_accept_current -> no more writers\r\n") ); + + descP->state = SOCKET_STATE_LISTENING; + + descP->currentAcceptorP = NULL; + descP->currentAcceptor.ref = esock_atom_undefined; + enif_set_pid_undefined(&descP->currentAcceptor.pid); + esock_monitor_init(&descP->currentAcceptor.mon); } - + SSDBG( descP, ("SOCKET", "ncancel_accept_current -> done with result:" "\r\n %T" "\r\n", res) ); @@ -13341,6 +13378,7 @@ ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env, static ERL_NIF_TERM ncancel_send(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM opRef) { ERL_NIF_TERM res; @@ -13356,7 +13394,7 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env, if (descP->currentWriterP != NULL) { if (COMPARE(opRef, descP->currentWriter.ref) == 0) { - res = ncancel_send_current(env, descP); + res = ncancel_send_current(env, descP, sockRef); } else { res = ncancel_send_waiting(env, descP, opRef); } @@ -13383,46 +13421,29 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env, */ static ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env, - SocketDescriptor* descP) + SocketDescriptor* descP, + ERL_NIF_TERM sockRef) { - int sres; ERL_NIF_TERM res; SSDBG( descP, ("SOCKET", "ncancel_send_current -> entry\r\n") ); - DEMONP("ncancel_recv_current -> current writer", + DEMONP("ncancel_send_current -> current writer", env, descP, &descP->currentWriter.mon); res = ncancel_write_select(env, descP, descP->currentWriter.ref); - SSDBG( descP, ("SOCKET", "ncancel_send_current -> cancel res: %T\r\n", res) ); + SSDBG( descP, + ("SOCKET", "ncancel_send_current -> cancel res: %T\r\n", res) ); - if (writer_pop(env, descP, - &descP->currentWriter.pid, - &descP->currentWriter.mon, - &descP->currentWriter.ref)) { - - /* There was another one */ - - SSDBG( descP, ("SOCKET", "ncancel_send_current -> new (active) writer: " - "\r\n pid: %T" - "\r\n ref: %T" - "\r\n", - descP->currentWriter.pid, - descP->currentWriter.ref) ); - - if ((sres = esock_select_write(env, descP->sock, descP, - &descP->currentWriter.pid, - descP->currentWriter.ref)) < 0) { - return esock_make_error(env, - MKT2(env, - esock_atom_select_failed, - MKI(env, sres))); - } - } else { - SSDBG( descP, ("SOCKET", "ncancel_send_current -> no more writers\r\n") ); - descP->currentWriterP = NULL; + if (!activate_next_writer(env, descP, sockRef)) { + SSDBG( descP, + ("SOCKET", "ncancel_send_current -> no more writers\r\n") ); + descP->currentWriterP = NULL; + descP->currentWriter.ref = esock_atom_undefined; + enif_set_pid_undefined(&descP->currentWriter.pid); + esock_monitor_init(&descP->currentWriter.mon); } - + SSDBG( descP, ("SOCKET", "ncancel_send_current -> done with result:" "\r\n %T" "\r\n", res) ); @@ -13464,6 +13485,7 @@ ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env, static ERL_NIF_TERM ncancel_recv(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM opRef) { ERL_NIF_TERM res; @@ -13479,7 +13501,7 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env, if (descP->currentReaderP != NULL) { if (COMPARE(opRef, descP->currentReader.ref) == 0) { - res = ncancel_recv_current(env, descP); + res = ncancel_recv_current(env, descP, sockRef); } else { res = ncancel_recv_waiting(env, descP, opRef); } @@ -13505,9 +13527,9 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env, */ static ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env, - SocketDescriptor* descP) + SocketDescriptor* descP, + ERL_NIF_TERM sockRef) { - int sres; ERL_NIF_TERM res; SSDBG( descP, ("SOCKET", "ncancel_recv_current -> entry\r\n") ); @@ -13516,35 +13538,18 @@ ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env, env, descP, &descP->currentReader.mon); res = ncancel_read_select(env, descP, descP->currentReader.ref); - SSDBG( descP, ("SOCKET", "ncancel_recv_current -> cancel res: %T\r\n", res) ); + SSDBG( descP, + ("SOCKET", "ncancel_recv_current -> cancel res: %T\r\n", res) ); - if (reader_pop(env, descP, - &descP->currentReader.pid, - &descP->currentReader.mon, - &descP->currentReader.ref)) { - - /* There was another one */ - - SSDBG( descP, ("SOCKET", "ncancel_recv_current -> new (active) reader: " - "\r\n pid: %T" - "\r\n ref: %T" - "\r\n", - descP->currentReader.pid, - descP->currentReader.ref) ); - - if ((sres = esock_select_read(env, descP->sock, descP, - &descP->currentReader.pid, - descP->currentReader.ref)) < 0) { - return esock_make_error(env, - MKT2(env, - esock_atom_select_failed, - MKI(env, sres))); - } - } else { - SSDBG( descP, ("SOCKET", "ncancel_recv_current -> no more readers\r\n") ); - descP->currentReaderP = NULL; + if (!activate_next_reader(env, descP, sockRef)) { + SSDBG( descP, + ("SOCKET", "ncancel_recv_current -> no more readers\r\n") ); + descP->currentReaderP = NULL; + descP->currentReader.ref = esock_atom_undefined; + enif_set_pid_undefined(&descP->currentReader.pid); + esock_monitor_init(&descP->currentReader.mon); } - + SSDBG( descP, ("SOCKET", "ncancel_recv_current -> done with result:" "\r\n %T" "\r\n", res) ); @@ -13653,7 +13658,7 @@ BOOLEAN_T send_check_writer(ErlNifEnv* env, return FALSE; } - if (!compare_pids(env, &descP->currentWriter.pid, &caller)) { + if (COMPARE_PIDS(&descP->currentWriter.pid, &caller) != 0) { /* Not the "current writer", so (maybe) push onto queue */ SSDBG( descP, @@ -13727,30 +13732,11 @@ ERL_NIF_TERM send_check_result(ErlNifEnv* env, /* Ok, this write is done maybe activate the next (if any) */ - if (writer_pop(env, descP, - &descP->currentWriter.pid, - &descP->currentWriter.mon, - &descP->currentWriter.ref)) { - - /* There was another one */ - - SSDBG( descP, ("SOCKET", "send_check_result -> new (active) writer: " - "\r\n pid: %T" - "\r\n ref: %T" - "\r\n", - descP->currentWriter.pid, - descP->currentWriter.ref) ); - - if ((sres = esock_select_write(env, descP->sock, descP, - &descP->currentWriter.pid, - descP->currentWriter.ref)) < 0) { - return esock_make_error(env, - MKT2(env, - esock_atom_select_failed, - MKI(env, sres))); - } - } else { - descP->currentWriterP = NULL; + if (!activate_next_writer(env, descP, sockRef)) { + descP->currentWriterP = NULL; + descP->currentWriter.ref = esock_atom_undefined; + enif_set_pid_undefined(&descP->currentWriter.pid); + esock_monitor_init(&descP->currentWriter.mon); } return esock_atom_ok; @@ -13760,10 +13746,8 @@ ERL_NIF_TERM send_check_result(ErlNifEnv* env, /* Some kind of send failure - check what kind */ if ((saveErrno != EAGAIN) && (saveErrno != EINTR)) { - ErlNifPid pid; - // ErlNifMonitor mon; - ESockMonitor mon; - ERL_NIF_TERM ref, res; + SocketRequestor req; + ERL_NIF_TERM res, reason; /* * An actual failure - we (and everyone waiting) give up @@ -13772,20 +13756,25 @@ ERL_NIF_TERM send_check_result(ErlNifEnv* env, cnt_inc(&descP->writeFails, 1); SSDBG( descP, - ("SOCKET", "send_check_result -> error: %d\r\n", saveErrno) ); + ("SOCKET", + "send_check_result -> error: %d\r\n", saveErrno) ); - res = esock_make_error_errno(env, saveErrno); + reason = MKA(env, erl_errno_id(saveErrno)); + res = esock_make_error(env, reason); if (descP->currentWriterP != NULL) { + DEMONP("send_check_result -> current writer", env, descP, &descP->currentWriter.mon); - while (writer_pop(env, descP, &pid, &mon, &ref)) { + while (writer_pop(env, descP, &req)) { SSDBG( descP, - ("SOCKET", "send_check_result -> abort %T\r\n", pid) ); - esock_send_abort_msg(env, sockRef, ref, res, &pid); + ("SOCKET", "send_check_result -> abort %T\r\n", + req.pid) ); + esock_send_abort_msg(env, sockRef, req.ref, + reason, &req.pid); DEMONP("send_check_result -> pop'ed writer", - env, descP, &mon); + env, descP, &req.mon); } } @@ -13877,7 +13866,7 @@ BOOLEAN_T recv_check_reader(ErlNifEnv* env, return FALSE; } - if (!compare_pids(env, &descP->currentReader.pid, &caller)) { + if (COMPARE_PIDS(&descP->currentReader.pid, &caller) != 0) { ERL_NIF_TERM tmp; /* Not the "current reader", so (maybe) push onto queue */ @@ -13950,9 +13939,9 @@ char* recv_init_current_reader(ErlNifEnv* env, static ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env, - SocketDescriptor* descP) + SocketDescriptor* descP, + ERL_NIF_TERM sockRef) { - int sres; ERL_NIF_TERM res = esock_atom_ok; if (descP->currentReaderP != NULL) { @@ -13960,32 +13949,18 @@ ERL_NIF_TERM recv_update_current_reader(ErlNifEnv* env, DEMONP("recv_update_current_reader -> current reader", env, descP, &descP->currentReader.mon); - if (reader_pop(env, descP, - &descP->currentReader.pid, - &descP->currentReader.mon, - &descP->currentReader.ref)) { - - /* There was another one */ - + if (!activate_next_reader(env, descP, sockRef)) { + SSDBG( descP, - ("SOCKET", "recv_update_current_reader -> new (active) reader: " - "\r\n pid: %T" - "\r\n ref: %T" - "\r\n", - descP->currentReader.pid, - descP->currentReader.ref) ); - - if ((sres = esock_select_read(env, descP->sock, descP, - &descP->currentReader.pid, - descP->currentReader.ref)) < 0) { - res = esock_make_error(env, - MKT2(env, - esock_atom_select_failed, - MKI(env, sres))); - } - } else { - descP->currentReaderP = NULL; + ("SOCKET", + "recv_update_current_reader -> no more readers\r\n") ); + + descP->currentReaderP = NULL; + descP->currentReader.ref = esock_atom_undefined; + enif_set_pid_undefined(&descP->currentReader.pid); + esock_monitor_init(&descP->currentReader.mon); } + } return res; @@ -14006,21 +13981,20 @@ void recv_error_current_reader(ErlNifEnv* env, ERL_NIF_TERM sockRef, ERL_NIF_TERM reason) { + SocketRequestor req; + if (descP->currentReaderP != NULL) { - ErlNifPid pid; - // ErlNifMonitor mon; - ESockMonitor mon; - ERL_NIF_TERM ref; DEMONP("recv_error_current_reader -> current reader", env, descP, &descP->currentReader.mon); - while (reader_pop(env, descP, &pid, &mon, &ref)) { + while (reader_pop(env, descP, &req)) { SSDBG( descP, - ("SOCKET", "recv_error_current_reader -> abort %T\r\n", pid) ); - esock_send_abort_msg(env, sockRef, ref, reason, &pid); + ("SOCKET", "recv_error_current_reader -> abort %T\r\n", + req.pid) ); + esock_send_abort_msg(env, sockRef, req.ref, reason, &req.pid); DEMONP("recv_error_current_reader -> pop'ed reader", - env, descP, &mon); + env, descP, &req.mon); } } } @@ -14137,7 +14111,7 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env, cnt_inc(&descP->readPkgCnt, 1); - recv_update_current_reader(env, descP); + recv_update_current_reader(env, descP, sockRef); /* This transfers "ownership" of the *allocated* binary to an * erlang term (no need for an explicit free). @@ -14182,7 +14156,7 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env, "recv_check_result -> [%d] " "we got exactly what we could fit\r\n", toRead) ); - recv_update_current_reader(env, descP); + recv_update_current_reader(env, descP, sockRef); /* This transfers "ownership" of the *allocated* binary to an * erlang term (no need for an explicit free). @@ -14294,7 +14268,7 @@ ERL_NIF_TERM recv_check_result(ErlNifEnv* env, cnt_inc(&descP->readPkgCnt, 1); cnt_inc(&descP->readByteCnt, read); - recv_update_current_reader(env, descP); + recv_update_current_reader(env, descP, sockRef); /* This transfers "ownership" of the *allocated* binary to an * erlang term (no need for an explicit free). @@ -14479,7 +14453,7 @@ ERL_NIF_TERM recvfrom_check_result(ErlNifEnv* env, data = MKSBIN(env, data, 0, read); } - recv_update_current_reader(env, descP); + recv_update_current_reader(env, descP, sockRef); return esock_make_ok2(env, MKT2(env, eSockAddr, data)); @@ -14644,7 +14618,7 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env, "recvmsg_check_result -> " "(msghdr) encode failed: %s\r\n", xres) ); - recv_update_current_reader(env, descP); + recv_update_current_reader(env, descP, sockRef); FREE_BIN(dataBufP); FREE_BIN(ctrlBufP); @@ -14656,7 +14630,7 @@ ERL_NIF_TERM recvmsg_check_result(ErlNifEnv* env, "recvmsg_check_result -> " "(msghdr) encode ok: %T\r\n", eMsgHdr) ); - recv_update_current_reader(env, descP); + recv_update_current_reader(env, descP, sockRef); return esock_make_ok2(env, eMsgHdr); } @@ -16299,6 +16273,7 @@ ERL_NIF_TERM encode_ip_tos(ErlNifEnv* env, int val) /* *** alloc_descriptor *** + * * Allocate and perform basic initialization of a socket descriptor. * */ @@ -16370,14 +16345,16 @@ SocketDescriptor* alloc_descriptor(SOCKET sock, HANDLE event) -/* decrement counters for when a socket is closed */ +/* Decrement counters for when a socket is closed + */ static void dec_socket(int domain, int type, int protocol) { MLOCK(data.cntMtx); cnt_dec(&data.numSockets, 1); - + + /* *** Domain counter *** */ if (domain == AF_INET) cnt_dec(&data.numDomainInet, 1); #if defined(HAVE_IN6) && defined(AF_INET6) @@ -16389,6 +16366,7 @@ void dec_socket(int domain, int type, int protocol) cnt_dec(&data.numDomainInet6, 1); #endif + /* *** Type counter *** */ if (type == SOCK_STREAM) cnt_dec(&data.numTypeStreams, 1); else if (type == SOCK_DGRAM) @@ -16398,6 +16376,7 @@ void dec_socket(int domain, int type, int protocol) cnt_dec(&data.numTypeSeqPkgs, 1); #endif + /* *** Protocol counter *** */ if (protocol == IPPROTO_IP) cnt_dec(&data.numProtoIP, 1); else if (protocol == IPPROTO_TCP) @@ -16413,7 +16392,8 @@ void dec_socket(int domain, int type, int protocol) } -/* increment counters for when a socket is opened */ +/* Increment counters for when a socket is opened + */ static void inc_socket(int domain, int type, int protocol) { @@ -16421,6 +16401,7 @@ void inc_socket(int domain, int type, int protocol) cnt_inc(&data.numSockets, 1); + /* *** Domain counter *** */ if (domain == AF_INET) cnt_inc(&data.numDomainInet, 1); #if defined(HAVE_IN6) && defined(AF_INET6) @@ -16432,6 +16413,7 @@ void inc_socket(int domain, int type, int protocol) cnt_inc(&data.numDomainInet6, 1); #endif + /* *** Type counter *** */ if (type == SOCK_STREAM) cnt_inc(&data.numTypeStreams, 1); else if (type == SOCK_DGRAM) @@ -16441,6 +16423,7 @@ void inc_socket(int domain, int type, int protocol) cnt_inc(&data.numTypeSeqPkgs, 1); #endif + /* *** Protocol counter *** */ if (protocol == IPPROTO_IP) cnt_inc(&data.numProtoIP, 1); else if (protocol == IPPROTO_TCP) @@ -16456,20 +16439,6 @@ void inc_socket(int domain, int type, int protocol) } - -/* compare_pids - Test if two pids are equal - * - */ -static -int compare_pids(ErlNifEnv* env, - const ErlNifPid* pid1, - const ErlNifPid* pid2) -{ - ERL_NIF_TERM p1 = enif_make_pid(env, pid1); - ERL_NIF_TERM p2 = enif_make_pid(env, pid2); - - return enif_is_identical(p1, p2); -} #endif // if !defined(__WIN32__) @@ -17070,280 +17039,261 @@ int esock_select_cancel(ErlNifEnv* env, /* ---------------------------------------------------------------------- - * R e q u e s t Q u e u e F u n c t i o n s + * A c t i v a t e N e x t ( o p e r a t o r ) F u n c t i o n s * ---------------------------------------------------------------------- */ -/* *** acceptor search for pid *** +/* *** activate_next_acceptor *** + * *** activate_next_writer *** + * *** activate_next_reader *** * - * Search for a pid in the acceptor queue. - */ -#if !defined(__WIN32__) -static -BOOLEAN_T acceptor_search4pid(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid) -{ - return qsearch4pid(env, &descP->acceptorsQ, pid); -} + * This functions pops the writer queue and then selects until it + * manages to successfully activate a writer or the queue is empty. + */ + +#define ACTIVATE_NEXT_FUNCS \ + ACTIVATE_NEXT_FUNC_DECL(acceptor, currentAcceptor, acceptorsQ) \ + ACTIVATE_NEXT_FUNC_DECL(writer, currentWriter, writersQ) \ + ACTIVATE_NEXT_FUNC_DECL(reader, currentReader, readersQ) + +#define ACTIVATE_NEXT_FUNC_DECL(F, R, Q) \ + static \ + BOOLEAN_T activate_next_##F(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + ERL_NIF_TERM sockRef) \ + { \ + return activate_next(env, descP, \ + &descP->R, &descP->Q, \ + sockRef); \ + } +ACTIVATE_NEXT_FUNCS +#undef ACTIVATE_NEXT_FUNC_DECL -/* *** acceptor push *** +/* *** activate_next *** * - * Push an acceptor onto the acceptor queue. - * This happens when we already have atleast one current acceptor. + * This functions pops the requestor queue and then selects until it + * manages to successfully activate a new requestor or the queue is empty. + * Return value indicates if a new requestor was activated or not. */ + static -ERL_NIF_TERM acceptor_push(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid pid, - ERL_NIF_TERM ref) +BOOLEAN_T activate_next(ErlNifEnv* env, + SocketDescriptor* descP, + SocketRequestor* reqP, + SocketRequestQueue* q, + ERL_NIF_TERM sockRef) { - SocketRequestQueueElement* e = MALLOC(sizeof(SocketRequestQueueElement)); - SocketRequestor* reqP = &e->data; + BOOLEAN_T popped, activated; + int sres; - reqP->pid = pid; - reqP->ref = enif_make_copy(descP->env, ref); - - if (MONP("acceptor_push -> acceptor request", - env, descP, &pid, &reqP->mon) != 0) { - FREE(reqP); - return esock_make_error(env, atom_exmon); - } - - qpush(&descP->acceptorsQ, e); - - // THIS IS OK => MAKES THE CALLER WAIT FOR ITS TURN - return esock_make_error(env, esock_atom_eagain); -} + popped = FALSE; + do { + if (requestor_pop(q, reqP)) { -/* *** acceptor pop *** - * - * Pop an acceptor from the acceptor queue. - */ -static -BOOLEAN_T acceptor_pop(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid, - // ErlNifMonitor* mon, - ESockMonitor* mon, - ERL_NIF_TERM* ref) -{ - SocketRequestQueueElement* e = qpop(&descP->acceptorsQ); + /* There was another one */ + + SSDBG( descP, + ("SOCKET", "activate_next -> new (active) requestor: " + "\r\n pid: %T" + "\r\n ref: %T" + "\r\n", reqP->pid, reqP->ref) ); + + if ((sres = esock_select_read(env, descP->sock, descP, + &reqP->pid, reqP->ref)) < 0) { + /* We need to inform this process, reqP->pid, that we + * failed to select, so we don't leave it hanging. + * => send abort + */ - if (e != NULL) { - *pid = e->data.pid; - *mon = e->data.mon; - *ref = e->data.ref; - FREE(e); - return TRUE; - } else { - /* (acceptors) Queue was empty */ - // *pid = NULL; we have no null value for pids - // *mon = NULL; we have no null value for monitors - *ref = esock_atom_undefined; // Just in case - return FALSE; - } - -} + esock_send_abort_msg(env, sockRef, reqP->ref, sres, &reqP->pid); + + } else { + /* Success: New requestor selected */ + popped = TRUE; + activated = FALSE; -/* *** acceptor unqueue *** - * - * Remove an acceptor from the acceptor queue. - */ -static -BOOLEAN_T acceptor_unqueue(ErlNifEnv* env, - SocketDescriptor* descP, - const ErlNifPid* pid) -{ - return qunqueue(env, descP, "qunqueue -> waiting acceptor", - &descP->acceptorsQ, pid); -} + } + } else { + SSDBG( descP, + ("SOCKET", "send_activate_next -> no more requestors\r\n") ); -/* *** writer search for pid *** - * - * Search for a pid in the writer queue. - */ -static -BOOLEAN_T writer_search4pid(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid) -{ - return qsearch4pid(env, &descP->writersQ, pid); + popped = TRUE; + activated = FALSE; + } + + } while (!popped); + + SSDBG( descP, + ("SOCKET", "activate_next -> " + "done with %s\r\n", B2S(activated)) ); + + return activated; } -/* *** writer push *** +/* ---------------------------------------------------------------------- + * R e q u e s t o r Q u e u e F u n c t i o n s + * ---------------------------------------------------------------------- * - * Push an writer onto the writer queue. - * This happens when we already have atleast one current writer. + * Since each of these functions (search4pid, push, pop and unqueue + * are virtually identical for acceptors, writers and readers, + * we make use of set of declaration macros. */ -static -ERL_NIF_TERM writer_push(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid pid, - ERL_NIF_TERM ref) -{ - SocketRequestQueueElement* e = MALLOC(sizeof(SocketRequestQueueElement)); - SocketRequestor* reqP = &e->data; - - reqP->pid = pid; - reqP->ref = enif_make_copy(descP->env, ref); - - if (MONP("writer_push -> writer request", - env, descP, &pid, &reqP->mon) != 0) { - FREE(reqP); - return esock_make_error(env, atom_exmon); - } - - qpush(&descP->writersQ, e); - - // THIS IS OK => MAKES THE CALLER WAIT FOR ITS TURN - return esock_make_error(env, esock_atom_eagain); -} +#if !defined(__WIN32__) -/* *** writer pop *** +/* *** acceptor_search4pid *** + * *** writer_search4pid *** + * *** reader_search4pid *** + * + * Search for a pid in the requestor (acceptor, writer, or reader) queue. * - * Pop an writer from the writer queue. */ -static -BOOLEAN_T writer_pop(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid, - // ErlNifMonitor* mon, - ESockMonitor* mon, - ERL_NIF_TERM* ref) -{ - SocketRequestQueueElement* e = qpop(&descP->writersQ); - if (e != NULL) { - *pid = e->data.pid; - *mon = e->data.mon; - *ref = e->data.ref; // At this point the ref has already been copied (env) - FREE(e); - return TRUE; - } else { - /* (writers) Queue was empty */ - // *pid = NULL; we have no null value for pids - // *mon = NULL; we have no null value for monitors - *ref = esock_atom_undefined; // Just in case - return FALSE; +#define REQ_SEARCH4PID_FUNCS \ + REQ_SEARCH4PID_FUNC_DECL(acceptor, acceptorsQ) \ + REQ_SEARCH4PID_FUNC_DECL(writer, writersQ) \ + REQ_SEARCH4PID_FUNC_DECL(reader, readersQ) + +#define REQ_SEARCH4PID_FUNC_DECL(F, Q) \ + static \ + BOOLEAN_T F##_search4pid(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + ErlNifPid* pid) \ + { \ + return qsearch4pid(env, &descP->Q, pid); \ } - -} +REQ_SEARCH4PID_FUNCS +#undef REQ_SEARCH4PID_FUNC_DECL + -/* *** writer unqueue *** +/* *** acceptor_push *** + * *** writer_push *** + * *** reader_push *** + * + * Push a requestor (acceptor, writer, or reader) onto its queue. + * This happens when we already have a current request (of its type). * - * Remove an writer from the writer queue. */ -static -BOOLEAN_T writer_unqueue(ErlNifEnv* env, - SocketDescriptor* descP, - const ErlNifPid* pid) -{ - return qunqueue(env, descP, "qunqueue -> waiting writer", - &descP->writersQ, pid); -} + +#define REQ_PUSH_FUNCS \ + REQ_PUSH_FUNC_DECL(acceptor, acceptorsQ) \ + REQ_PUSH_FUNC_DECL(writer, writersQ) \ + REQ_PUSH_FUNC_DECL(reader, readersQ) + +#define REQ_PUSH_FUNC_DECL(F, Q) \ + static \ + ERL_NIF_TERM F##_push(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + ErlNifPid pid, \ + ERL_NIF_TERM ref) \ + { \ + SocketRequestQueueElement* e = MALLOC(sizeof(SocketRequestQueueElement)); \ + SocketRequestor* reqP = &e->data; \ + \ + reqP->pid = pid; \ + reqP->ref = enif_make_copy(descP->env, ref); \ + \ + if (MONP("reader_push -> " #F " request", \ + env, descP, &pid, &reqP->mon) != 0) { \ + FREE(reqP); \ + return esock_make_error(env, atom_exmon); \ + } \ + \ + qpush(&descP->Q, e); \ + \ + return esock_make_error(env, esock_atom_eagain); \ + } +REQ_PUSH_FUNCS +#undef REQ_PUSH_FUNC_DECL -/* *** reader search for pid *** +/* *** acceptor_pop *** + * *** writer_pop *** + * *** reader_pop *** + * + * Pop a requestor (acceptor, writer, or reader) from its queue. * - * Search for a pid in the reader queue. */ -static -BOOLEAN_T reader_search4pid(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid) -{ - return qsearch4pid(env, &descP->readersQ, pid); -} +#define REQ_POP_FUNCS \ + REQ_POP_FUNC_DECL(acceptor, acceptorsQ) \ + REQ_POP_FUNC_DECL(writer, writersQ) \ + REQ_POP_FUNC_DECL(reader, readersQ) + +#define REQ_POP_FUNC_DECL(F, Q) \ + static \ + BOOLEAN_T F##_pop(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + SocketRequestor* reqP) \ + { \ + return requestor_pop(&descP->Q, reqP); \ + } +REQ_POP_FUNCS +#undef REQ_POP_FUNC_DECL -/* *** reader push *** + +/* *** acceptor_unqueue *** + * *** writer_unqueue *** + * *** reader_unqueue *** + * + * Remove a requestor (acceptor, writer, or reader) from its queue. * - * Push an reader onto the raeder queue. - * This happens when we already have atleast one current reader. */ -static -ERL_NIF_TERM reader_push(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid pid, - ERL_NIF_TERM ref) -{ - SocketRequestQueueElement* e = MALLOC(sizeof(SocketRequestQueueElement)); - SocketRequestor* reqP = &e->data; - - reqP->pid = pid; - reqP->ref = enif_make_copy(descP->env, ref); - - if (MONP("reader_push -> reader request", - env, descP, &pid, &reqP->mon) != 0) { - FREE(reqP); - return esock_make_error(env, atom_exmon); + +#define REQ_UNQUEUE_FUNCS \ + REQ_UNQUEUE_FUNC_DECL(acceptor, acceptorsQ) \ + REQ_UNQUEUE_FUNC_DECL(writer, writersQ) \ + REQ_UNQUEUE_FUNC_DECL(reader, readersQ) + +#define REQ_UNQUEUE_FUNC_DECL(F, Q) \ + static \ + BOOLEAN_T F##_unqueue(ErlNifEnv* env, \ + SocketDescriptor* descP, \ + const ErlNifPid* pid) \ + { \ + return qunqueue(env, descP, "qunqueue -> waiting " #F, \ + &descP->Q, pid); \ } - - qpush(&descP->readersQ, e); - - // THIS IS OK => MAKES THE CALLER WAIT FOR ITS TURN - return esock_make_error(env, esock_atom_eagain); -} +REQ_UNQUEUE_FUNCS +#undef REQ_UNQUEUE_FUNC_DECL + -/* *** reader pop *** +/* *** requestor pop *** * - * Pop an writer from the reader queue. + * Pop an requestor from its queue. */ static -BOOLEAN_T reader_pop(ErlNifEnv* env, - SocketDescriptor* descP, - ErlNifPid* pid, - // ErlNifMonitor* mon, - ESockMonitor* mon, - ERL_NIF_TERM* ref) +BOOLEAN_T requestor_pop(SocketRequestQueue* q, + SocketRequestor* reqP) { - SocketRequestQueueElement* e = qpop(&descP->readersQ); + SocketRequestQueueElement* e = qpop(q); if (e != NULL) { - *pid = e->data.pid; - *mon = e->data.mon; - *ref = e->data.ref; // At this point the ref has already been copied (env) + reqP->pid = e->data.pid; + reqP->mon = e->data.mon; + reqP->ref = e->data.ref; FREE(e); return TRUE; } else { - /* (readers) Queue was empty */ - // *pid = NULL; we have no null value for pids - // *mon = NULL; we have no null value for monitors - *ref = esock_atom_undefined; // Just in case + /* (writers) Queue was empty */ + enif_set_pid_undefined(&reqP->pid); + // *reqP->mon = NULL; we have no null value for monitors + reqP->ref = esock_atom_undefined; // Just in case return FALSE; } } -/* *** reader unqueue *** - * - * Remove an reader from the reader queue. - */ -static -BOOLEAN_T reader_unqueue(ErlNifEnv* env, - SocketDescriptor* descP, - const ErlNifPid* pid) -{ - return qunqueue(env, descP, "qunqueue -> waiting reader", - &descP->readersQ, pid); -} - - - - - static BOOLEAN_T qsearch4pid(ErlNifEnv* env, SocketRequestQueue* q, @@ -17352,7 +17302,7 @@ BOOLEAN_T qsearch4pid(ErlNifEnv* env, SocketRequestQueueElement* tmp = q->first; while (tmp != NULL) { - if (compare_pids(env, &tmp->data.pid, pid)) + if (COMPARE_PIDS(&tmp->data.pid, pid) == 0) return TRUE; else tmp = tmp->nextP; @@ -17411,7 +17361,7 @@ BOOLEAN_T qunqueue(ErlNifEnv* env, /* Check if it was one of the waiting acceptor processes */ while (e != NULL) { - if (compare_pids(env, &e->data.pid, pid)) { + if (COMPARE_PIDS(&e->data.pid, pid) == 0) { /* We have a match */ @@ -17502,12 +17452,6 @@ void cnt_dec(Uint32* cnt, Uint32 dec) #if !defined(__WIN32__) static -ERL_NIF_TERM my_make_monitor_term(ErlNifEnv* env, const ErlNifMonitor* mon) -{ - return ((ERL_NIF_TERM)&mon->data) + 2; -} - -static int esock_monitor(const char* slogan, ErlNifEnv* env, SocketDescriptor* descP, @@ -17660,7 +17604,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) descP->readTries, descP->readWaits) ); - sockRef = enif_make_resource(env, descP), + sockRef = enif_make_resource(env, descP); descP->state = SOCKET_STATE_CLOSING; // Just in case...??? descP->isReadable = FALSE; descP->isWritable = FALSE; @@ -17692,9 +17636,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) env, descP, &descP->currentWriter.mon); SSDBG( descP, ("SOCKET", "socket_stop -> handle current writer\r\n") ); - if (!compare_pids(env, - &descP->closerPid, - &descP->currentWriter.pid)) { + if (COMPARE_PIDS(&descP->closerPid, &descP->currentWriter.pid) != 0) { SSDBG( descP, ("SOCKET", "socket_stop -> " "send abort message to current writer %T\r\n", descP->currentWriter.pid) ); @@ -17715,7 +17657,8 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) /* And also deal with the waiting writers (in the same way) */ SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting writer(s)\r\n") ); - inform_waiting_procs(env, descP, &descP->writersQ, TRUE, atom_closed); + inform_waiting_procs(env, "writer", + descP, &descP->writersQ, TRUE, atom_closed); } @@ -17736,12 +17679,15 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) env, descP, &descP->currentReader.mon); SSDBG( descP, ("SOCKET", "socket_stop -> handle current reader\r\n") ); - if (!compare_pids(env, - &descP->closerPid, - &descP->currentReader.pid)) { + if (COMPARE_PIDS(&descP->closerPid, &descP->currentReader.pid) != 0) { SSDBG( descP, ("SOCKET", "socket_stop -> " "send abort message to current reader %T\r\n", descP->currentReader.pid) ); + /* + esock_dbg_printf("SOCKET", "socket_stop -> " + "send abort message to current reader %T\r\n", + descP->currentReader.pid); + */ if (esock_send_abort_msg(env, sockRef, descP->currentReader.ref, @@ -17759,7 +17705,8 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) /* And also deal with the waiting readers (in the same way) */ SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting reader(s)\r\n") ); - inform_waiting_procs(env, descP, &descP->readersQ, TRUE, atom_closed); + inform_waiting_procs(env, "reader", + descP, &descP->readersQ, TRUE, atom_closed); } @@ -17780,9 +17727,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) env, descP, &descP->currentAcceptor.mon); SSDBG( descP, ("SOCKET", "socket_stop -> handle current acceptor\r\n") ); - if (!compare_pids(env, - &descP->closerPid, - &descP->currentAcceptor.pid)) { + if (COMPARE_PIDS(&descP->closerPid, &descP->currentAcceptor.pid) != 0) { SSDBG( descP, ("SOCKET", "socket_stop -> " "send abort message to current acceptor %T\r\n", descP->currentWriter.pid) ); @@ -17803,7 +17748,8 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) /* And also deal with the waiting acceptors (in the same way) */ SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting acceptor(s)\r\n") ); - inform_waiting_procs(env, descP, &descP->acceptorsQ, TRUE, atom_closed); + inform_waiting_procs(env, "acceptor", + descP, &descP->acceptorsQ, TRUE, atom_closed); } @@ -17859,15 +17805,24 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) * and if the 'free' argument is TRUE, the queue will be emptied. */ #if !defined(__WIN32__) -static -void inform_waiting_procs(ErlNifEnv* env, - SocketDescriptor* descP, - SocketRequestQueue* q, - BOOLEAN_T free, - ERL_NIF_TERM reason) +static void inform_waiting_procs(ErlNifEnv* env, + char* role, + SocketDescriptor* descP, + SocketRequestQueue* q, + BOOLEAN_T free, + ERL_NIF_TERM reason) { SocketRequestQueueElement* currentP = q->first; SocketRequestQueueElement* nextP; + ERL_NIF_TERM sockRef = enif_make_resource(env, descP); + + /* + esock_dbg_printf("SOCKET", "inform_waiting_procs -> entry with: " + "\r\n role: %s" + "\r\n free: %s" + "\r\n reason: %T" + "\r\n", role, B2S(free), reason); + */ while (currentP != NULL) { @@ -17884,11 +17839,25 @@ void inform_waiting_procs(ErlNifEnv* env, ("SOCKET", "inform_waiting_procs -> abort request %T (from %T)\r\n", currentP->data.ref, currentP->data.pid) ); - ESOCK_ASSERT( (NULL == esock_send_abort_msg(env, - esock_atom_undefined, - currentP->data.ref, - reason, - ¤tP->data.pid)) ); + /* + esock_dbg_printf("SOCKET", "inform_waiting_procs -> " + "try sending abort to %s %T " + "\r\n", role, currentP->data.pid); + */ + + if (esock_send_abort_msg(env, + sockRef, + currentP->data.ref, + reason, + ¤tP->data.pid) != NULL) { + + esock_warning_msg("Failed sending abort (%T) message to " + "current %s %T\r\n", + currentP->data.ref, + role, + currentP->data.pid); + + } DEMONP("inform_waiting_procs -> current 'request'", env, descP, ¤tP->data.mon); @@ -17918,6 +17887,7 @@ void socket_down(ErlNifEnv* env, #if !defined(__WIN32__) SocketDescriptor* descP = (SocketDescriptor*) obj; int sres; + ERL_NIF_TERM sockRef; SSDBG( descP, ("SOCKET", "socket_down -> entry with" "\r\n sock: %d" @@ -17930,7 +17900,7 @@ void socket_down(ErlNifEnv* env, if (!IS_CLOSED(descP)) { - if (compare_pids(env, &descP->ctrlPid, pid)) { + if (COMPARE_PIDS(&descP->ctrlPid, pid) == 0) { /* We don't bother with the queue cleanup here - * we leave it to the stop callback function. @@ -18019,7 +17989,7 @@ void socket_down(ErlNifEnv* env, "\r\n Descriptor: %d" "\r\n Monitor: %T" "\r\n", sres, pid, descP->sock, - my_make_monitor_term(env, mon)); + MON2T(env, mon)); } } else { @@ -18032,19 +18002,21 @@ void socket_down(ErlNifEnv* env, SSDBG( descP, ("SOCKET", "socket_down -> other process term\r\n") ); + sockRef = enif_make_resource(env, descP); + MLOCK(descP->accMtx); if (descP->currentAcceptorP != NULL) - socket_down_acceptor(env, descP, pid); + socket_down_acceptor(env, descP, sockRef, pid); MUNLOCK(descP->accMtx); MLOCK(descP->writeMtx); if (descP->currentWriterP != NULL) - socket_down_writer(env, descP, pid); + socket_down_writer(env, descP, sockRef, pid); MUNLOCK(descP->writeMtx); MLOCK(descP->readMtx); if (descP->currentReaderP != NULL) - socket_down_reader(env, descP, pid); + socket_down_reader(env, descP, sockRef, pid); MUNLOCK(descP->readMtx); } @@ -18066,49 +18038,28 @@ void socket_down(ErlNifEnv* env, static void socket_down_acceptor(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, const ErlNifPid* pid) { - if (compare_pids(env, &descP->currentAcceptor.pid, pid)) { + if (COMPARE_PIDS(&descP->currentAcceptor.pid, pid) == 0) { SSDBG( descP, ("SOCKET", "socket_down_acceptor -> " - "current acceptor - try pop the queue\r\n") ); + "current acceptor - try activate next\r\n") ); - if (acceptor_pop(env, descP, - &descP->currentAcceptor.pid, - &descP->currentAcceptor.mon, - &descP->currentAcceptor.ref)) { - int res; - - /* There was another one, so we will still be in accepting state */ - - SSDBG( descP, ("SOCKET", - "socket_down_acceptor -> new (active) acceptor: " - "\r\n pid: %T" - "\r\n ref: %T" - "\r\n", - descP->currentAcceptor.pid, - descP->currentAcceptor.ref) ); - - if ((res = esock_select_read(env, descP->sock, descP, - &descP->currentAcceptor.pid, - descP->currentAcceptor.ref) < 0)) { - - esock_warning_msg("Failed select (%d) for new acceptor " - "after current (%T) died\r\n", - res, *pid); - - } - - } else { - - SSDBG( descP, ("SOCKET", - "socket_down_acceptor -> no active acceptor\r\n") ); - - descP->currentAcceptorP = NULL; - descP->state = SOCKET_STATE_LISTENING; + if (!activate_next_acceptor(env, descP, sockRef)) { + + SSDBG( descP, + ("SOCKET", "socket_down_acceptor -> no more writers\r\n") ); + + descP->state = SOCKET_STATE_LISTENING; + + descP->currentAcceptorP = NULL; + descP->currentAcceptor.ref = esock_atom_undefined; + enif_set_pid_undefined(&descP->currentAcceptor.pid); + esock_monitor_init(&descP->currentAcceptor.mon); } - + } else { /* Maybe unqueue one of the waiting acceptors */ @@ -18132,45 +18083,22 @@ void socket_down_acceptor(ErlNifEnv* env, static void socket_down_writer(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, const ErlNifPid* pid) { - if (compare_pids(env, &descP->currentWriter.pid, pid)) { + if (COMPARE_PIDS(&descP->currentWriter.pid, pid) == 0) { SSDBG( descP, ("SOCKET", "socket_down_writer -> " - "current writer - try pop the queue\r\n") ); + "current writer - try activate next\r\n") ); - if (writer_pop(env, descP, - &descP->currentWriter.pid, - &descP->currentWriter.mon, - &descP->currentWriter.ref)) { - int res; - - /* There was another one */ - - SSDBG( descP, ("SOCKET", "socket_down_writer -> new (current) writer: " - "\r\n pid: %T" - "\r\n ref: %T" - "\r\n", - descP->currentWriter.pid, - descP->currentWriter.ref) ); - - if ((res = esock_select_write(env, descP->sock, descP, - &descP->currentWriter.pid, - descP->currentWriter.ref) < 0)) { - - esock_warning_msg("Failed select (%d) for new writer " - "after current (%T) died\r\n", - res, *pid); - - } - - } else { - + if (!activate_next_writer(env, descP, sockRef)) { SSDBG( descP, ("SOCKET", "socket_down_writer -> no active writer\r\n") ); - - descP->currentWriterP = NULL; + descP->currentWriterP = NULL; + descP->currentWriter.ref = esock_atom_undefined; + enif_set_pid_undefined(&descP->currentWriter.pid); + esock_monitor_init(&descP->currentWriter.mon); } } else { @@ -18196,47 +18124,24 @@ void socket_down_writer(ErlNifEnv* env, static void socket_down_reader(ErlNifEnv* env, SocketDescriptor* descP, + ERL_NIF_TERM sockRef, const ErlNifPid* pid) { - if (compare_pids(env, &descP->currentReader.pid, pid)) { + if (COMPARE_PIDS(&descP->currentReader.pid, pid) == 0) { SSDBG( descP, ("SOCKET", "socket_down_reader -> " - "current reader - try pop the queue\r\n") ); + "current reader - try activate next\r\n") ); - if (reader_pop(env, descP, - &descP->currentReader.pid, - &descP->currentReader.mon, - &descP->currentReader.ref)) { - int res; - - /* There was another one */ - - SSDBG( descP, ("SOCKET", "socket_down_reader -> new (current) reader: " - "\r\n pid: %T" - "\r\n ref: %T" - "\r\n", - descP->currentReader.pid, - descP->currentReader.ref) ); - - if ((res = esock_select_read(env, descP->sock, descP, - &descP->currentReader.pid, - descP->currentReader.ref) < 0)) { - - esock_warning_msg("Failed select (%d) for new reader " - "after current (%T) died\r\n", - res, *pid); - - } - - } else { - - SSDBG( descP, ("SOCKET", - "socket_down_reader -> no active reader\r\n") ); - - descP->currentReaderP = NULL; + if (!activate_next_reader(env, descP, sockRef)) { + SSDBG( descP, + ("SOCKET", "ncancel_recv_current -> no more readers\r\n") ); + descP->currentReaderP = NULL; + descP->currentReader.ref = esock_atom_undefined; + enif_set_pid_undefined(&descP->currentReader.pid); + esock_monitor_init(&descP->currentReader.mon); } - + } else { /* Maybe unqueue one of the waiting reader(s) */ @@ -18358,284 +18263,18 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) data.numProtoSCTP = 0; #endif - /* +++ Misc atoms +++ */ - atom_adaptation_layer = MKA(env, str_adaptation_layer); - atom_address = MKA(env, str_address); - atom_association = MKA(env, str_association); - atom_assoc_id = MKA(env, str_assoc_id); - atom_authentication = MKA(env, str_authentication); - atom_bool = MKA(env, str_bool); - atom_close = MKA(env, str_close); - atom_closed = MKA(env, str_closed); - atom_closing = MKA(env, str_closing); - atom_cookie_life = MKA(env, str_cookie_life); - atom_data_in = MKA(env, str_data_in); - atom_do = MKA(env, str_do); - atom_dont = MKA(env, str_dont); - atom_exclude = MKA(env, str_exclude); - atom_false = MKA(env, str_false); - atom_global_counters = MKA(env, str_global_counters); - atom_in4_sockaddr = MKA(env, str_in4_sockaddr); - atom_in6_sockaddr = MKA(env, str_in6_sockaddr); - atom_include = MKA(env, str_include); - atom_initial = MKA(env, str_initial); - atom_int = MKA(env, str_int); - atom_interface = MKA(env, str_interface); - atom_iow = MKA(env, str_iow); - atom_local_rwnd = MKA(env, str_local_rwnd); - atom_max = MKA(env, str_max); - atom_max_attempts = MKA(env, str_max_attempts); - atom_max_init_timeo = MKA(env, str_max_init_timeo); - atom_max_instreams = MKA(env, str_max_instreams); - atom_max_rxt = MKA(env, str_max_rxt); - atom_min = MKA(env, str_min); - atom_mode = MKA(env, str_mode); - atom_multiaddr = MKA(env, str_multiaddr); - // atom_nif_abort = MKA(env, str_nif_abort); - atom_null = MKA(env, str_null); - atom_num_dinet = MKA(env, str_num_dinet); - atom_num_dinet6 = MKA(env, str_num_dinet6); - atom_num_dlocal = MKA(env, str_num_dlocal); - atom_num_outstreams = MKA(env, str_num_outstreams); - atom_num_peer_dests = MKA(env, str_num_peer_dests); - atom_num_pip = MKA(env, str_num_pip); - atom_num_psctp = MKA(env, str_num_psctp); - atom_num_ptcp = MKA(env, str_num_ptcp); - atom_num_pudp = MKA(env, str_num_pudp); - atom_num_sockets = MKA(env, str_num_sockets); - atom_num_tdgrams = MKA(env, str_num_tdgrams); - atom_num_tseqpkgs = MKA(env, str_num_tseqpkgs); - atom_num_tstreams = MKA(env, str_num_tstreams); - atom_partial_delivery = MKA(env, str_partial_delivery); - atom_peer_rwnd = MKA(env, str_peer_rwnd); - atom_peer_error = MKA(env, str_peer_error); - atom_probe = MKA(env, str_probe); - atom_select = MKA(env, str_select); - atom_sender_dry = MKA(env, str_sender_dry); - atom_send_failure = MKA(env, str_send_failure); - atom_shutdown = MKA(env, str_shutdown); - atom_slist = MKA(env, str_slist); - atom_sourceaddr = MKA(env, str_sourceaddr); - atom_timeout = MKA(env, str_timeout); - atom_true = MKA(env, str_true); - atom_want = MKA(env, str_want); - - /* Global atom(s) */ - esock_atom_abort = MKA(env, "abort"); - esock_atom_accept = MKA(env, "accept"); - esock_atom_acceptconn = MKA(env, "acceptconn"); - esock_atom_acceptfilter = MKA(env, "acceptfilter"); - esock_atom_adaption_layer = MKA(env, "adaption_layer"); - esock_atom_addr = MKA(env, "addr"); - esock_atom_addrform = MKA(env, "addrform"); - esock_atom_add_membership = MKA(env, "add_membership"); - esock_atom_add_source_membership = MKA(env, "add_source_membership"); - esock_atom_any = MKA(env, "any"); - esock_atom_associnfo = MKA(env, "associnfo"); - esock_atom_authhdr = MKA(env, "authhdr"); - esock_atom_auth_active_key = MKA(env, "auth_active_key"); - esock_atom_auth_asconf = MKA(env, "auth_asconf"); - esock_atom_auth_chunk = MKA(env, "auth_chunk"); - esock_atom_auth_delete_key = MKA(env, "auth_delete_key"); - esock_atom_auth_key = MKA(env, "auth_key"); - esock_atom_auth_level = MKA(env, "auth_level"); - esock_atom_autoclose = MKA(env, "autoclose"); - esock_atom_bindtodevice = MKA(env, "bindtodevice"); - esock_atom_block_source = MKA(env, "block_source"); - esock_atom_broadcast = MKA(env, "broadcast"); - esock_atom_busy_poll = MKA(env, "busy_poll"); - esock_atom_checksum = MKA(env, "checksum"); - esock_atom_close = MKA(env, "close"); - esock_atom_connect = MKA(env, "connect"); - esock_atom_congestion = MKA(env, "congestion"); - esock_atom_context = MKA(env, "context"); - esock_atom_cork = MKA(env, "cork"); - esock_atom_credentials = MKA(env, "credentials"); - esock_atom_ctrl = MKA(env, "ctrl"); - esock_atom_ctrunc = MKA(env, "ctrunc"); - esock_atom_data = MKA(env, "data"); - esock_atom_debug = MKA(env, "debug"); - esock_atom_default_send_params = MKA(env, "default_send_params"); - esock_atom_delayed_ack_time = MKA(env, "delayed_ack_time"); - esock_atom_dgram = MKA(env, "dgram"); - esock_atom_disable_fragments = MKA(env, "disable_fragments"); - esock_atom_domain = MKA(env, "domain"); - esock_atom_dontfrag = MKA(env, "dontfrag"); - esock_atom_dontroute = MKA(env, "dontroute"); - esock_atom_drop_membership = MKA(env, "drop_membership"); - esock_atom_drop_source_membership = MKA(env, "drop_source_membership"); - esock_atom_dstopts = MKA(env, "dstpopts"); - esock_atom_eor = MKA(env, "eor"); - esock_atom_error = MKA(env, "error"); - esock_atom_errqueue = MKA(env, "errqueue"); - esock_atom_esp_network_level = MKA(env, "esp_network_level"); - esock_atom_esp_trans_level = MKA(env, "esp_trans_level"); - esock_atom_events = MKA(env, "events"); - esock_atom_explicit_eor = MKA(env, "explicit_eor"); - esock_atom_faith = MKA(env, "faith"); - esock_atom_false = MKA(env, "false"); - esock_atom_family = MKA(env, "family"); - esock_atom_flags = MKA(env, "flags"); - esock_atom_flowinfo = MKA(env, "flowinfo"); - esock_atom_fragment_interleave = MKA(env, "fragment_interleave"); - esock_atom_freebind = MKA(env, "freebind"); - esock_atom_get_peer_addr_info = MKA(env, "get_peer_addr_info"); - esock_atom_hdrincl = MKA(env, "hdrincl"); - esock_atom_hmac_ident = MKA(env, "hmac_ident"); - esock_atom_hoplimit = MKA(env, "hoplimit"); - esock_atom_hopopts = MKA(env, "hopopts"); - esock_atom_ifindex = MKA(env, "ifindex"); - esock_atom_inet = MKA(env, "inet"); - esock_atom_inet6 = MKA(env, "inet6"); - esock_atom_info = MKA(env, "info"); - esock_atom_initmsg = MKA(env, "initmsg"); - esock_atom_iov = MKA(env, "iov"); - esock_atom_ip = MKA(env, "ip"); - esock_atom_ipcomp_level = MKA(env, "ipcomp_level"); - esock_atom_ipv6 = MKA(env, "ipv6"); - esock_atom_i_want_mapped_v4_addr = MKA(env, "i_want_mapped_v4_addr"); - esock_atom_join_group = MKA(env, "join_group"); - esock_atom_keepalive = MKA(env, "keepalive"); - esock_atom_keepcnt = MKA(env, "keepcnt"); - esock_atom_keepidle = MKA(env, "keepidle"); - esock_atom_keepintvl = MKA(env, "keepintvl"); - esock_atom_leave_group = MKA(env, "leave_group"); - esock_atom_level = MKA(env, "level"); - esock_atom_linger = MKA(env, "linger"); - esock_atom_local = MKA(env, "local"); - esock_atom_local_auth_chunks = MKA(env, "local_auth_chunks"); - esock_atom_loopback = MKA(env, "loopback"); - esock_atom_lowdelay = MKA(env, "lowdelay"); - esock_atom_mark = MKA(env, "mark"); - esock_atom_maxburst = MKA(env, "maxburst"); - esock_atom_maxseg = MKA(env, "maxseg"); - esock_atom_md5sig = MKA(env, "md5sig"); - esock_atom_mincost = MKA(env, "mincost"); - esock_atom_minttl = MKA(env, "minttl"); - esock_atom_msfilter = MKA(env, "msfilter"); - esock_atom_mtu = MKA(env, "mtu"); - esock_atom_mtu_discover = MKA(env, "mtu_discover"); - esock_atom_multicast_all = MKA(env, "multicast_all"); - esock_atom_multicast_hops = MKA(env, "multicast_hops"); - esock_atom_multicast_if = MKA(env, "multicast_if"); - esock_atom_multicast_loop = MKA(env, "multicast_loop"); - esock_atom_multicast_ttl = MKA(env, "multicast_ttl"); - esock_atom_nodefrag = MKA(env, "nodefrag"); - esock_atom_nodelay = MKA(env, "nodelay"); - esock_atom_noopt = MKA(env, "noopt"); - esock_atom_nopush = MKA(env, "nopush"); - esock_atom_not_found = MKA(env, "not_found"); - esock_atom_not_owner = MKA(env, "not_owner"); - esock_atom_ok = MKA(env, "ok"); - esock_atom_oob = MKA(env, "oob"); - esock_atom_oobinline = MKA(env, "oobinline"); - esock_atom_options = MKA(env, "options"); - esock_atom_origdstaddr = MKA(env, "origdstaddr"); - esock_atom_partial_delivery_point = MKA(env, "partial_delivery_point"); - esock_atom_passcred = MKA(env, "passcred"); - esock_atom_path = MKA(env, "path"); - esock_atom_peekcred = MKA(env, "peekcred"); - esock_atom_peek_off = MKA(env, "peek_off"); - esock_atom_peer_addr_params = MKA(env, "peer_addr_params"); - esock_atom_peer_auth_chunks = MKA(env, "peer_auth_chunks"); - esock_atom_pktinfo = MKA(env, "pktinfo"); - esock_atom_pktoptions = MKA(env, "pktoptions"); - esock_atom_port = MKA(env, "port"); - esock_atom_portrange = MKA(env, "portrange"); - esock_atom_primary_addr = MKA(env, "primary_addr"); - esock_atom_priority = MKA(env, "priority"); - esock_atom_protocol = MKA(env, "protocol"); - esock_atom_raw = MKA(env, "raw"); - esock_atom_rcvbuf = MKA(env, "rcvbuf"); - esock_atom_rcvbufforce = MKA(env, "rcvbufforce"); - esock_atom_rcvlowat = MKA(env, "rcvlowat"); - esock_atom_rcvtimeo = MKA(env, "rcvtimeo"); - esock_atom_rdm = MKA(env, "rdm"); - esock_atom_recv = MKA(env, "recv"); - esock_atom_recvdstaddr = MKA(env, "recvdstaddr"); - esock_atom_recverr = MKA(env, "recverr"); - esock_atom_recvfrom = MKA(env, "recvfrom"); - esock_atom_recvif = MKA(env, "recvif"); - esock_atom_recvmsg = MKA(env, "recvmsg"); - esock_atom_recvopts = MKA(env, "recvopts"); - esock_atom_recvorigdstaddr = MKA(env, "recvorigdstaddr"); - esock_atom_recvpktinfo = MKA(env, "recvpktinfo"); - esock_atom_recvtclass = MKA(env, "recvtclass"); - esock_atom_recvtos = MKA(env, "recvtos"); - esock_atom_recvttl = MKA(env, "recvttl"); - esock_atom_reliability = MKA(env, "reliability"); - esock_atom_reset_streams = MKA(env, "reset_streams"); - esock_atom_retopts = MKA(env, "retopts"); - esock_atom_reuseaddr = MKA(env, "reuseaddr"); - esock_atom_reuseport = MKA(env, "reuseport"); - esock_atom_rights = MKA(env, "rights"); - esock_atom_router_alert = MKA(env, "router_alert"); - esock_atom_rthdr = MKA(env, "rthdr"); - esock_atom_rtoinfo = MKA(env, "rtoinfo"); - esock_atom_rxq_ovfl = MKA(env, "rxq_ovfl"); - esock_atom_scope_id = MKA(env, "scope_id"); - esock_atom_sctp = MKA(env, "sctp"); - esock_atom_sec = MKA(env, "sec"); - esock_atom_select_failed = MKA(env, "select_failed"); - esock_atom_select_sent = MKA(env, "select_sent"); - esock_atom_send = MKA(env, "send"); - esock_atom_sendmsg = MKA(env, "sendmsg"); - esock_atom_sendsrcaddr = MKA(env, "sendsrcaddr"); - esock_atom_sendto = MKA(env, "sendto"); - esock_atom_seqpacket = MKA(env, "seqpacket"); - esock_atom_setfib = MKA(env, "setfib"); - esock_atom_set_peer_primary_addr = MKA(env, "set_peer_primary_addr"); - esock_atom_sndbuf = MKA(env, "sndbuf"); - esock_atom_sndbufforce = MKA(env, "sndbufforce"); - esock_atom_sndlowat = MKA(env, "sndlowat"); - esock_atom_sndtimeo = MKA(env, "sndtimeo"); - esock_atom_socket = MKA(env, "socket"); - esock_atom_socket_tag = MKA(env, "$socket"); - esock_atom_spec_dst = MKA(env, "spec_dst"); - esock_atom_status = MKA(env, "status"); - esock_atom_stream = MKA(env, "stream"); - esock_atom_syncnt = MKA(env, "syncnt"); - esock_atom_tclass = MKA(env, "tclass"); - esock_atom_tcp = MKA(env, "tcp"); - esock_atom_throughput = MKA(env, "throughput"); - esock_atom_timestamp = MKA(env, "timestamp"); - esock_atom_tos = MKA(env, "tos"); - esock_atom_transparent = MKA(env, "transparent"); - esock_atom_true = MKA(env, "true"); - esock_atom_trunc = MKA(env, "trunc"); - esock_atom_ttl = MKA(env, "ttl"); - esock_atom_type = MKA(env, "type"); - esock_atom_udp = MKA(env, "udp"); - esock_atom_unblock_source = MKA(env, "unblock_source"); - esock_atom_undefined = MKA(env, "undefined"); - esock_atom_unicast_hops = MKA(env, "unicast_hops"); - esock_atom_unknown = MKA(env, "unknown"); - esock_atom_usec = MKA(env, "usec"); - esock_atom_user_timeout = MKA(env, "user_timeout"); - esock_atom_use_ext_recvinfo = MKA(env, "use_ext_recvinfo"); - esock_atom_use_min_mtu = MKA(env, "use_min_mtu"); - esock_atom_v6only = MKA(env, "v6only"); - - /* Global error codes */ - esock_atom_eafnosupport = MKA(env, ESOCK_STR_EAFNOSUPPORT); - esock_atom_eagain = MKA(env, ESOCK_STR_EAGAIN); - esock_atom_einval = MKA(env, ESOCK_STR_EINVAL); - - /* Error codes */ - atom_eisconn = MKA(env, str_eisconn); - atom_enotclosing = MKA(env, str_enotclosing); - atom_enotconn = MKA(env, str_enotconn); - atom_exalloc = MKA(env, str_exalloc); - atom_exbadstate = MKA(env, str_exbadstate); - atom_exbusy = MKA(env, str_exbusy); - atom_exmon = MKA(env, str_exmon); - atom_exself = MKA(env, str_exself); - atom_exsend = MKA(env, str_exsend); - - // For storing "global" things... - // data.env = enif_alloc_env(); // We should really check - // data.version = MKA(env, ERTS_VERSION); - // data.buildDate = MKA(env, ERTS_BUILD_DATE); + /* +++ Local atoms and error reason atoms +++ */ +#define LOCAL_ATOM_DECL(A) atom_##A = MKA(env, #A) +LOCAL_ATOMS +LOCAL_ERROR_REASON_ATOMS +#undef LOCAL_ATOM_DECL + + /* Global atom(s) and error reason atom(s) */ +#define GLOBAL_ATOM_DECL(A) esock_atom_##A = MKA(env, #A) +GLOBAL_ATOMS +GLOBAL_ERROR_REASON_ATOMS +#undef GLOBAL_ATOM_DECL + esock_atom_socket_tag = MKA(env, "$socket"); sockets = enif_open_resource_type_x(env, "sockets", diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c index f6e4781977..b817ae7636 100644 --- a/erts/emulator/nifs/common/socket_util.c +++ b/erts/emulator/nifs/common/socket_util.c @@ -177,7 +177,7 @@ char* esock_decode_iov(ErlNifEnv* env, return ESOCK_STR_EINVAL; if (IS_BIN(env, elem) && GET_BIN(env, elem, &bufs[i])) { - iov[i].iov_base = bufs[i].data; + iov[i].iov_base = (caddr_t) bufs[i].data; iov[i].iov_len = bufs[i].size; sz += bufs[i].size; } else { diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 4a0ad9c1d5..2309f844b9 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -65,7 +65,8 @@ nif_whereis/1, nif_whereis_parallel/1, nif_whereis_threaded/1, nif_whereis_proxy/1, nif_ioq/1, - pid/1 + pid/1, + nif_term_type/1 ]). -export([many_args_100/100]). @@ -105,7 +106,8 @@ all() -> nif_phash2, nif_whereis, nif_whereis_parallel, nif_whereis_threaded, nif_ioq, - pid]. + pid, + nif_term_type]. groups() -> [{G, [], api_repeaters()} || G <- api_groups()] @@ -3392,6 +3394,41 @@ pid(Config) -> {false, _} = get_local_pid_nif(undefined), ok. +nif_term_type(Config) -> + ensure_lib_loaded(Config), + + atom = term_type_nif(atom), + + bitstring = term_type_nif(<<1:1>>), + bitstring = term_type_nif(<<1:8>>), + + float = term_type_nif(0.0), + + 'fun' = term_type_nif(fun external:function/1), + 'fun' = term_type_nif(fun(A) -> A end), + 'fun' = term_type_nif(fun id/1), + + integer = term_type_nif(1 bsl 1024), %Bignum. + integer = term_type_nif(1), + + list = term_type_nif([list]), + list = term_type_nif([]), + + LargeMap = maps:from_list([{N, N} || N <- lists:seq(1, 256)]), + map = term_type_nif(LargeMap), + map = term_type_nif(#{ small => map }), + + pid = term_type_nif(self()), + + Port = open_port({spawn,echo_drv},[eof]), + port = term_type_nif(Port), + port_close(Port), + + reference = term_type_nif(make_ref()), + + tuple = term_type_nif({}), + + ok. id(I) -> I. @@ -3507,5 +3544,7 @@ set_pid_undefined_nif() -> ?nif_stub. is_pid_undefined_nif(_) -> ?nif_stub. compare_pids_nif(_, _) -> ?nif_stub. +term_type_nif(_) -> ?nif_stub. + nif_stub_error(Line) -> exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 0d5d900d31..1906384af4 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -3583,6 +3583,36 @@ static ERL_NIF_TERM compare_pids_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER return enif_make_int(env, enif_compare_pids(&a, &b)); } +static ERL_NIF_TERM term_type_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + switch (enif_term_type(env, argv[0])) { + case ERL_NIF_TERM_TYPE_ATOM: + return enif_make_atom(env, "atom"); + case ERL_NIF_TERM_TYPE_BITSTRING: + return enif_make_atom(env, "bitstring"); + case ERL_NIF_TERM_TYPE_FLOAT: + return enif_make_atom(env, "float"); + case ERL_NIF_TERM_TYPE_FUN: + return enif_make_atom(env, "fun"); + case ERL_NIF_TERM_TYPE_INTEGER: + return enif_make_atom(env, "integer"); + case ERL_NIF_TERM_TYPE_LIST: + return enif_make_atom(env, "list"); + case ERL_NIF_TERM_TYPE_MAP: + return enif_make_atom(env, "map"); + case ERL_NIF_TERM_TYPE_PID: + return enif_make_atom(env, "pid"); + case ERL_NIF_TERM_TYPE_PORT: + return enif_make_atom(env, "port"); + case ERL_NIF_TERM_TYPE_REFERENCE: + return enif_make_atom(env, "reference"); + case ERL_NIF_TERM_TYPE_TUPLE: + return enif_make_atom(env, "tuple"); + default: + return enif_make_badarg(env); + } +} + static ErlNifFunc nif_funcs[] = { {"lib_version", 0, lib_version}, @@ -3690,7 +3720,8 @@ static ErlNifFunc nif_funcs[] = {"make_pid_nif", 1, make_pid_nif}, {"set_pid_undefined_nif", 0, set_pid_undefined_nif}, {"is_pid_undefined_nif", 1, is_pid_undefined_nif}, - {"compare_pids_nif", 2, compare_pids_nif} + {"compare_pids_nif", 2, compare_pids_nif}, + {"term_type_nif", 1, term_type_nif} }; ERL_NIF_INIT(nif_SUITE,nif_funcs,load,NULL,upgrade,unload) diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index 52d002c9b8..aec280485c 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -5543,6 +5543,7 @@ sc_lc_receive_response_tcp(InitState) -> end}, #{desc => "attempt recv (=> closed)", cmd => fun(#{sock := Sock, recv := Recv} = State) -> + %% ok = socket:setopt(Sock, otp, debug, true), case Recv(Sock) of {ok, _Data} -> ?SEV_EPRINT("Unexpected data received"), diff --git a/erts/emulator/test/socket_test_evaluator.erl b/erts/emulator/test/socket_test_evaluator.erl index fe6a6ff70a..bd86b3b92e 100644 --- a/erts/emulator/test/socket_test_evaluator.erl +++ b/erts/emulator/test/socket_test_evaluator.erl @@ -471,7 +471,7 @@ await(ExpPid, Name, Announcement, Slogan, OtherPids) "~n Announcement: ~p" "~n Slogan: ~p" "~nwhen" - "~n Messages: ~p", + "~n Messages: ~p", [ExpPid, Name, Announcement, Slogan, pi(messages)]), await(ExpPid, Name, Announcement, Slogan, OtherPids) end. diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl index 253d5fed23..ad802352b9 100644 --- a/erts/emulator/test/trace_local_SUITE.erl +++ b/erts/emulator/test/trace_local_SUITE.erl @@ -1181,7 +1181,9 @@ undef(X) -> ?MODULE:undef(X, X). % undef lists_reverse(A, B) -> - lists:reverse(A, B). + Res = lists:reverse(A, B), + _ = (catch abs(A)), + Res. |