diff options
author | Micael Karlberg <[email protected]> | 2018-10-09 16:46:07 +0200 |
---|---|---|
committer | Micael Karlberg <[email protected]> | 2018-10-09 16:46:07 +0200 |
commit | ff3d31f7d102d68a585f8ce636753bf48b9553ab (patch) | |
tree | 3c09432251b6b244b32244646ec12fb04afcc993 /erts | |
parent | 4e3f42da1dae7166faeb9f9e07adc40bc3b22d75 (diff) | |
parent | ce28d70c686f342fb04fc05e1d00501e7cfbf213 (diff) | |
download | otp-ff3d31f7d102d68a585f8ce636753bf48b9553ab.tar.gz otp-ff3d31f7d102d68a585f8ce636753bf48b9553ab.tar.bz2 otp-ff3d31f7d102d68a585f8ce636753bf48b9553ab.zip |
Merge branch 'bmk/20181005/nififying_inet_supported_options/OTP-14831' into bmk/20180918/nififying_inet/OTP-14831
Diffstat (limited to 'erts')
-rw-r--r-- | erts/doc/src/socket.xml | 49 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_int.h | 123 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 1743 | ||||
-rw-r--r-- | erts/preloaded/ebin/socket.beam | bin | 66596 -> 68544 bytes | |||
-rw-r--r-- | erts/preloaded/src/socket.erl | 106 |
5 files changed, 1935 insertions, 86 deletions
diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml index af7e0ca9c1..49c14869bf 100644 --- a/erts/doc/src/socket.xml +++ b/erts/doc/src/socket.xml @@ -205,6 +205,27 @@ <datatype> <name name="int32"/> </datatype> + <datatype> + <name name="supports_options_socket"/> + </datatype> + <datatype> + <name name="supports_options_ip"/> + </datatype> + <datatype> + <name name="supports_options_ipv6"/> + </datatype> + <datatype> + <name name="supports_options_tcp"/> + </datatype> + <datatype> + <name name="supports_options_udp"/> + </datatype> + <datatype> + <name name="supports_options_sctp"/> + </datatype> + <datatype> + <name name="supports_options"/> + </datatype> </datatypes> <funcs> @@ -511,6 +532,34 @@ </desc> </func> + <func> + <name name="supports" arity="0"/> + <name name="supports" arity="1" clause_i="1"/> + <name name="supports" arity="1" clause_i="2"/> + <name name="supports" arity="1" clause_i="3"/> + <name name="supports" arity="1" clause_i="4"/> + <name name="supports" arity="2" clause_i="1"/> + <name name="supports" arity="2" clause_i="2"/> + <name name="supports" arity="2" clause_i="3"/> + <name name="supports" arity="2" clause_i="4"/> + <name name="supports" arity="2" clause_i="5"/> + <name name="supports" arity="2" clause_i="6"/> + <name name="supports" arity="2" clause_i="7"/> + <name name="supports" arity="3" clause_i="1"/> + <name name="supports" arity="3" clause_i="2"/> + <name name="supports" arity="3" clause_i="3"/> + <name name="supports" arity="3" clause_i="4"/> + <name name="supports" arity="3" clause_i="5"/> + <name name="supports" arity="3" clause_i="6"/> + <name name="supports" arity="3" clause_i="7"/> + <fsummary>Report info about what the platform supports.</fsummary> + <desc> + <p>This function intends to retreive information about what the + platform supports. Such as if SCTP is supported. Or which socket + options are supported. </p> + </desc> + </func> + </funcs> <section> <title>Examples</title> diff --git a/erts/emulator/nifs/common/socket_int.h b/erts/emulator/nifs/common/socket_int.h index f9246856fa..06f677482c 100644 --- a/erts/emulator/nifs/common/socket_int.h +++ b/erts/emulator/nifs/common/socket_int.h @@ -104,72 +104,195 @@ typedef unsigned int BOOLEAN_T; * "Global" atoms */ 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_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_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_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; /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 0ef88162bc..4544604f28 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -314,6 +314,10 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL; #include "socket_int.h" #include "socket_util.h" +#if defined(SOL_IPV6) || defined(IPPROTO_IPV6) +#define HAVE_IPV6 +#endif + /* All platforms fail on malloc errors. */ #define FATAL_MALLOC @@ -603,6 +607,11 @@ typedef union { #define ESOCK_RECVMSG_IOVEC_SZ 1 +#define SOCKET_SUPPORTS_OPTIONS 0x0001 +#define SOCKET_SUPPORTS_SCTP 0x0002 +#define SOCKET_SUPPORTS_IPV6 0x0003 + + /* =================================================================== * * * @@ -860,6 +869,9 @@ typedef struct { 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. @@ -928,6 +940,16 @@ static ERL_NIF_TERM nif_cancel(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +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); +static ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env); +static ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env); +static ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env); +static ERL_NIF_TERM nsupports_options_udp(ErlNifEnv* env); +static ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env); +static ERL_NIF_TERM nsupports_sctp(ErlNifEnv* env); +static ERL_NIF_TERM nsupports_ipv6(ErlNifEnv* env); static ERL_NIF_TERM nopen(ErlNifEnv* env, int domain, @@ -1308,7 +1330,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env, /* *** Handling set of socket options for level = ipv6 *** */ -#if defined(SOL_IPV6) +#if defined(HAVE_IPV6) static ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, SocketDescriptor* descP, int eOpt, @@ -1416,7 +1438,7 @@ static ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, int opt); #endif -#endif // defined(SOL_IPV6) +#endif // defined(HAVE_IPV6) static ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env, SocketDescriptor* descP, int eOpt, @@ -1722,7 +1744,7 @@ static ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env, static ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env, SocketDescriptor* descP); #endif -#if defined(SOL_IPV6) +#if defined(HAVE_IPV6) static ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, SocketDescriptor* descP, int eOpt); @@ -1791,7 +1813,7 @@ static ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env, SocketDescriptor* descP); #endif -#endif // defined(SOL_IPV6) +#endif // defined(HAVE_IPV6) static ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env, SocketDescriptor* descP, @@ -2046,7 +2068,7 @@ static char* encode_cmsghdr_data_ip(ErlNifEnv* env, size_t dataPos, size_t dataLen, ERL_NIF_TERM* eCMsgHdrData); -#if defined(SOL_IPV6) +#if defined(HAVE_IPV6) static char* encode_cmsghdr_data_ipv6(ErlNifEnv* env, ERL_NIF_TERM ctrlBuf, int type, @@ -2372,72 +2394,195 @@ static char str_exsend[] = "exsend"; // failed send /* *** "Global" Atoms *** */ 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_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_dgram; 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_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_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; @@ -2536,6 +2681,7 @@ static SocketData data; * Utility and admin functions: * ---------------------------- * nif_info/0 + * nif_supports/1 * (nif_debug/1) * * The "proper" socket functions: @@ -2619,6 +2765,1278 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, } + +/* ---------------------------------------------------------------------- + * nif_supports + * + * Description: + * This function is intended to answer the question: "Is X supported?" + * Currently only one key is "supported": options + * That results in a list of all *known options* (known by us) and if + * the platform supports (OS) it or not. + * + * Key + * --- + * options [{socket, [{Opt, boolean()}]}, + * {ip, [{Opt, boolean()}]}, + * {ipv6, [{Opt, boolean()}]}, + * {tcp, [{Opt, boolean()}]}, + * {udp, [{Opt, boolean()}]}, + * {sctp, [{Opt, boolean()}]}] + */ + +static +ERL_NIF_TERM nif_supports(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + int key; + + SGDBG( ("SOCKET", "nif_supports -> entry with %d args\r\n", argc) ); + + /* Extract arguments and perform preliminary validation */ + + if ((argc != 1) || + !GET_INT(env, argv[0], &key)) { + return enif_make_badarg(env); + } + + return nsupports(env, key); +} + + + +/* nopen - create an endpoint for communication + * + * Assumes the input has been validated. + * + * Normally we want debugging on (individual) sockets to be controlled + * by the sockets own debug flag. But since we don't even have a socket + * yet, we must use the global debug flag. + */ +static +ERL_NIF_TERM nsupports(ErlNifEnv* env, int key) +{ + ERL_NIF_TERM result; + + SGDBG( ("SOCKET", "nsupports -> entry with 0x%lX\r\n", key) ); + + switch (key) { + case SOCKET_SUPPORTS_OPTIONS: + result = nsupports_options(env); + break; + + case SOCKET_SUPPORTS_SCTP: + result = nsupports_sctp(env); + break; + + case SOCKET_SUPPORTS_IPV6: + result = nsupports_ipv6(env); + break; + + default: + result = esock_atom_false; + break; + } + + return result; +} + + +static +ERL_NIF_TERM nsupports_options(ErlNifEnv* env) +{ + ERL_NIF_TERM sockOpts = nsupports_options_socket(env); + ERL_NIF_TERM sockOptsT = MKT2(env, esock_atom_socket, sockOpts); + ERL_NIF_TERM ipOpts = nsupports_options_ip(env); + ERL_NIF_TERM ipOptsT = MKT2(env, esock_atom_ip, ipOpts); + ERL_NIF_TERM ipv6Opts = nsupports_options_ipv6(env); + ERL_NIF_TERM ipv6OptsT = MKT2(env, esock_atom_ipv6, ipv6Opts); + ERL_NIF_TERM tcpOpts = nsupports_options_tcp(env); + ERL_NIF_TERM tcpOptsT = MKT2(env, esock_atom_tcp, tcpOpts); + ERL_NIF_TERM udpOpts = nsupports_options_udp(env); + ERL_NIF_TERM udpOptsT = MKT2(env, esock_atom_udp, udpOpts); + ERL_NIF_TERM sctpOpts = nsupports_options_sctp(env); + ERL_NIF_TERM sctpOptsT = MKT2(env, esock_atom_sctp, sctpOpts); + ERL_NIF_TERM optsA[] = {sockOptsT, + ipOptsT, ipv6OptsT, + tcpOptsT, udpOptsT, sctpOptsT}; + unsigned int lenOptsA = sizeof(optsA) / sizeof(ERL_NIF_TERM); + ERL_NIF_TERM optsL = MKLA(env, optsA, lenOptsA); + + return optsL; +} + + + +static +ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) +{ + SocketTArray opts = TARRAY_CREATE(128); + ERL_NIF_TERM tmp, optsL; + + + /* *** SOCKET_OPT_SOCK_ACCEPTCONN => SO_ACCEPTCONN *** */ +#if defined(SO_ACCEPTCONN) + tmp = MKT2(env, esock_atom_acceptconn, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_acceptconn, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_ACCEPTFILTER => SO_ACCEPTFILTER *** */ + tmp = MKT2(env, esock_atom_acceptfilter, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_BINDTODEVICE => SO_BINDTODEVICE *** */ +#if defined(SO_BINDTODEVICE) + tmp = MKT2(env, esock_atom_bindtodevice, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_bindtodevice, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_BROADCAST => SO_BROADCAST *** */ +#if defined(SO_BROADCAST) + tmp = MKT2(env, esock_atom_broadcast, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_broadcast, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_BUSY_POLL => SO_BUSY_POLL *** */ + tmp = MKT2(env, esock_atom_busy_poll, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_DEBUG => SO_DEBUG *** */ +#if defined(SO_DEBUG) + tmp = MKT2(env, esock_atom_debug, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_debug, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_DOMAIN => SO_DOMAIN *** */ +#if defined(SO_DOMAIN) + tmp = MKT2(env, esock_atom_domain, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_domain, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_DONTROUTE => SO_DONTROUTE *** */ +#if defined(SO_DONTROUTE) + tmp = MKT2(env, esock_atom_dontroute, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_dontroute, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_ERROR => SO_ERROR *** */ + tmp = MKT2(env, esock_atom_error, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_KEEPALIVE => SO_KEEPALIVE *** */ +#if defined(SO_KEEPALIVE) + tmp = MKT2(env, esock_atom_keepalive, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_keepalive, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_LINGER => SO_LINGER *** */ +#if defined(SO_LINGER) + tmp = MKT2(env, esock_atom_linger, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_linger, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_MARK => SO_MARK *** */ + tmp = MKT2(env, esock_atom_mark, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_OOBINLINE => SO_OOBINLINE *** */ +#if defined(SO_OOBINLINE) + tmp = MKT2(env, esock_atom_oobinline, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_oobinline, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_PASSCRED => SO_PASSCRED *** */ + tmp = MKT2(env, esock_atom_passcred, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_PEEK_OFF => SO_PEEK_OFF *** */ +#if defined(SO_PEEK_OFF) + tmp = MKT2(env, esock_atom_peek_off, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_peek_off, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_PEEKCRED => SO_PEEKCRED *** */ + tmp = MKT2(env, esock_atom_peekcred, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_PRIORITY => SO_PRIORITY *** */ +#if defined(SO_PRIORITY) + tmp = MKT2(env, esock_atom_priority, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_priority, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_PROTOCOL => SO_PROTOCOL *** */ +#if defined(SO_PROTOCOL) + tmp = MKT2(env, esock_atom_protocol, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_protocol, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_RCVBUF => SO_RCVBUF *** */ +#if defined(SO_RCVBUF) + tmp = MKT2(env, esock_atom_rcvbuf, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_rcvbuf, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_RCVBUFFORCE => SO_RCVBUFFORCE *** */ + tmp = MKT2(env, esock_atom_rcvbufforce, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_RCVLOWAT => SO_RCVLOWAT *** */ +#if defined(SO_RCVLOWAT) + tmp = MKT2(env, esock_atom_rcvlowat, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_rcvlowat, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_RCVTIMEO => SO_RCVTIMEO *** */ +#if defined(SO_RCVTIMEO) + tmp = MKT2(env, esock_atom_rcvtimeo, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_rcvtimeo, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_REUSEADDR => SO_REUSEADDR *** */ +#if defined(SO_REUSEADDR) + tmp = MKT2(env, esock_atom_reuseaddr, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_reuseaddr, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_REUSEPORT => SO_REUSEPORT *** */ +#if defined(SO_REUSEPORT) + tmp = MKT2(env, esock_atom_reuseport, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_reuseport, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_RXQ_OVFL => SO_RXQ_OVFL *** */ + tmp = MKT2(env, esock_atom_rxq_ovfl, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_SETFIB => SO_SETFIB *** */ + tmp = MKT2(env, esock_atom_setfib, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_SNDBUF => SO_SNDBUF *** */ +#if defined(SO_SNDBUF) + tmp = MKT2(env, esock_atom_sndbuf, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_sndbuf, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_SNDBUFFORCE => SO_SNDBUFFORCE *** */ + tmp = MKT2(env, esock_atom_sndbufforce, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_SNDLOWAT => SO_SNDLOWAT *** */ +#if defined(SO_SNDLOWAT) + tmp = MKT2(env, esock_atom_sndlowat, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_sndlowat, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_SNDTIMEO => SO_SNDTIMEO *** */ +#if defined(SO_SNDTIMEO) + tmp = MKT2(env, esock_atom_sndtimeo, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_sndtimeo, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_TIMESTAMP => SO_TIMESTAMP *** */ +#if defined(SO_TIMESTAMP) + tmp = MKT2(env, esock_atom_timestamp, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_timestamp, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SOCK_TYPE => SO_TYPE *** */ +#if defined(SO_TYPE) + tmp = MKT2(env, esock_atom_type, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_type, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + TARRAY_TOLIST(opts, env, &optsL); + + return optsL; +} + + + +static +ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) +{ + SocketTArray opts = TARRAY_CREATE(128); + ERL_NIF_TERM tmp, optsL; + + + /* *** SOCKET_OPT_IP_ADD_MEMBERSHIP => IP_ADD_MEMBERSHIP *** */ +#if defined(IP_ADD_MEMBERSHIP) + tmp = MKT2(env, esock_atom_add_membership, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_add_membership, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_ADD_SOURCE_MEMBERSHIP => IP_ADD_SOURCE_MEMBERSHIP *** */ +#if defined(IP_ADD_SOURCE_MEMBERSHIP) + tmp = MKT2(env, esock_atom_add_source_membership, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_add_source_membership, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_BLOCK_SOURCE => IP_BLOCK_SOURCE *** */ +#if defined(IP_BLOCK_SOURCE) + tmp = MKT2(env, esock_atom_block_source, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_block_source, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_DONTFRAG => IP_DONTFRAG *** */ + tmp = MKT2(env, esock_atom_dontfrag, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_DROP_MEMBERSHIP => IP_DROP_MEMBERSHIP *** */ +#if defined(IP_DROP_MEMBERSHIP) + tmp = MKT2(env, esock_atom_drop_membership, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_drop_membership, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_DROP_SOURCE_MEMBERSHIP => IP_DROP_SOURCE_MEMBERSHIP *** */ +#if defined(IP_DROP_SOURCE_MEMBERSHIP) + tmp = MKT2(env, esock_atom_drop_source_membership, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_drop_source_membership, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_FREEBIND => IP_FREEBIND *** */ +#if defined(IP_FREEBIND) + tmp = MKT2(env, esock_atom_freebind, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_freebind, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_HDRINCL => IP_HDRINCL *** */ +#if defined(IP_HDRINCL) + tmp = MKT2(env, esock_atom_hdrincl, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_hdrincl, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_MINTTL => IP_MINTTL *** */ +#if defined(IP_MINTTL) + tmp = MKT2(env, esock_atom_minttl, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_minttl, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_MSFILTER => IP_MSFILTER / IP_MSFILTER_SIZE *** */ +#if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE) + tmp = MKT2(env, esock_atom_msfilter, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_msfilter, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_MTU => IP_MTU *** */ + tmp = MKT2(env, esock_atom_mtu, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_MTU_DISCOVER => IP_MTU_DISCOVER *** */ +#if defined(IP_MTU_DISCOVER) + tmp = MKT2(env, esock_atom_mtu_discover, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_mtu_discover, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_MULTICAST_ALL => IP_MULTICAST_ALL *** */ +#if defined(IP_MULTICAST_ALL) + tmp = MKT2(env, esock_atom_multicast_all, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_multicast_all, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_MULTICAST_IF => IP_MULTICAST_IF *** */ +#if defined(IP_MULTICAST_IF) + tmp = MKT2(env, esock_atom_multicast_if, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_multicast_if, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_MULTICAST_LOOP => IP_MULTICAST_LOOP *** */ +#if defined(IP_MULTICAST_LOOP) + tmp = MKT2(env, esock_atom_multicast_loop, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_multicast_loop, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_MULTICAST_TTL => IP_MULTICAST_TTL *** */ +#if defined(IP_MULTICAST_TTL) + tmp = MKT2(env, esock_atom_multicast_ttl, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_multicast_ttl, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_NODEFRAG => IP_NODEFRAG *** */ +#if defined(IP_NODEFRAG) + tmp = MKT2(env, esock_atom_nodefrag, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_nodefrag, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_OPTIONS => IP_OPTIONS *** */ + tmp = MKT2(env, esock_atom_options, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_PKTINFO => IP_PKTINFO *** */ +#if defined(IP_PKTINFO) + tmp = MKT2(env, esock_atom_pktinfo, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_pktinfo, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_RECVDSTADDR => IP_RECVDSTADDR *** */ +#if defined(IP_RECVDSTADDR) + tmp = MKT2(env, esock_atom_recvdstaddr, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_recvdstaddr, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_RECVERR => IP_RECVERR *** */ +#if defined(IP_RECVERR) + tmp = MKT2(env, esock_atom_recverr, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_recverr, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_RECVIF => IP_RECVIF *** */ +#if defined(IP_RECVIF) + tmp = MKT2(env, esock_atom_recvif, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_recvif, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_RECVOPTS => IP_RECVOPTS *** */ +#if defined(IP_RECVOPTS) + tmp = MKT2(env, esock_atom_recvopts, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_recvopts, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_RECVORIGDSTADDR => IP_RECVORIGDSTADDR *** */ +#if defined(IP_RECVORIGDSTADDR) + tmp = MKT2(env, esock_atom_recvorigdstaddr, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_recvorigdstaddr, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_RECVTOS => IP_RECVTOS *** */ +#if defined(IP_RECVTOS) + tmp = MKT2(env, esock_atom_recvtos, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_recvtos, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_RECVTTL => IP_RECVTTL *** */ +#if defined(IP_RECVTTL) + tmp = MKT2(env, esock_atom_recvttl, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_recvttl, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_RETOPTS => IP_RETOPTS *** */ +#if defined(IP_RETOPTS) + tmp = MKT2(env, esock_atom_retopts, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_retopts, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_ROUTER_ALERT => IP_ROUTER_ALERT *** */ +#if defined(IP_ROUTER_ALERT) + tmp = MKT2(env, esock_atom_router_alert, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_router_alert, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_SENDSRCADDR => IP_SENDSRCADDR *** */ +#if defined(IP_SENDSRCADDR) + tmp = MKT2(env, esock_atom_sendsrcaddr, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_sendsrcaddr, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_TOS => IP_TOS *** */ +#if defined(IP_TOS) + tmp = MKT2(env, esock_atom_tos, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_tos, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_TRANSPARENT => IP_TRANSPARENT *** */ +#if defined(IP_TRANSPARENT) + tmp = MKT2(env, esock_atom_transparent, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_transparent, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_TTL => IP_TTL *** */ +#if defined(IP_TTL) + tmp = MKT2(env, esock_atom_ttl, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_ttl, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IP_UNBLOCK_SOURCE => IP_UNBLOCK_SOURCE *** */ +#if defined(IP_UNBLOCK_SOURCE) + tmp = MKT2(env, esock_atom_unblock_source, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_unblock_source, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + TARRAY_TOLIST(opts, env, &optsL); + + return optsL; +} + + + +static +ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) +{ + SocketTArray opts = TARRAY_CREATE(128); + ERL_NIF_TERM tmp, optsL; + + + /* *** SOCKET_OPT_IPV6_ADDRFORM => IPV6_ADDRFORM *** */ +#if defined(IPV6_ADDRFORM) + tmp = MKT2(env, esock_atom_addrform, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_addrform, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_ADD_MEMBERSHIP => IPV6_ADD_MEMBERSHIP *** */ +#if defined(IPV6_ADD_MEMBERSHIP) + tmp = MKT2(env, esock_atom_add_membership, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_add_membership, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_AUTHHDR => IPV6_AUTHHDR *** */ +#if defined(IPV6_AUTHHDR) + tmp = MKT2(env, esock_atom_authhdr, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_authhdr, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_AUTH_LEVEL => IPV6_AUTH_LEVEL *** */ + tmp = MKT2(env, esock_atom_auth_level, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_CHECKSUM => IPV6_CHECKSUM *** */ + tmp = MKT2(env, esock_atom_checksum, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_DROP_MEMBERSHIP => IPV6_DROP_MEMBERSHIP *** */ +#if defined(IPV6_DROP_MEMBERSHIP) + tmp = MKT2(env, esock_atom_drop_membership, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_drop_membership, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_DSTOPTS => IPV6_DSTOPTS *** */ +#if defined(IPV6_DSTOPTS) + tmp = MKT2(env, esock_atom_dstopts, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_dstopts, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_ESP_NETWORK_LEVEL => IPV6_ESP_NETWORK_LEVEL *** */ + tmp = MKT2(env, esock_atom_esp_network_level, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_ESP_TRANS_LEVEL => IPV6_ESP_TRANS_LEVEL *** */ + tmp = MKT2(env, esock_atom_esp_trans_level, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_FAITH => IPV6_FAITH *** */ + tmp = MKT2(env, esock_atom_faith, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_FLOWINFO => IPV6_FLOWINFO *** */ +#if defined(IPV6_FLOWINFO) + tmp = MKT2(env, esock_atom_flowinfo, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_flowinfo, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_HOPLIMIT => IPV6_HOPLIMIT *** */ +#if defined(IPV6_HOPLIMIT) + tmp = MKT2(env, esock_atom_hoplimit, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_hoplimit, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_HOPOPTS => IPV6_HOPOPTS *** */ +#if defined(IPV6_HOPOPTS) + tmp = MKT2(env, esock_atom_hopopts, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_hopopts, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_IPCOMP_LEVEL => IPV6_IPCOMP_LEVEL *** */ + tmp = MKT2(env, esock_atom_ipcomp_level, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_JOIN_GROUP => IPV6_JOIN_GROUP *** */ + tmp = MKT2(env, esock_atom_join_group, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_LEAVE_GROUP => IPV6_LEAVE_GROUP *** */ + tmp = MKT2(env, esock_atom_leave_group, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_MTU => IPV6_MTU *** */ +#if defined(IPV6_MTU) + tmp = MKT2(env, esock_atom_mtu, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_mtu, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_MTU_DISCOVER => IPV6_MTU_DISCOVER *** */ +#if defined(IPV6_MTU_DISCOVER) + tmp = MKT2(env, esock_atom_mtu_discover, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_mtu_discover, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_MULTICAST_HOPS => IPV6_MULTICAST_HOPS *** */ +#if defined(IPV6_MULTICAST_HOPS) + tmp = MKT2(env, esock_atom_multicast_hops, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_multicast_hops, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_MULTICAST_IF => IPV6_MULTICAST_IF *** */ +#if defined(IPV6_MULTICAST_IF) + tmp = MKT2(env, esock_atom_multicast_if, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_multicast_if, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_MULTICAST_LOOP => IPV6_MULTICAST_LOOP *** */ +#if defined(IPV6_MULTICAST_LOOP) + tmp = MKT2(env, esock_atom_multicast_loop, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_multicast_loop, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_PORTRANGE => IPV6_PORTRANGE *** */ + tmp = MKT2(env, esock_atom_portrange, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_PKTOPTIONS => IPV6_PKTOPTIONS *** */ + tmp = MKT2(env, esock_atom_pktoptions, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_RECVERR => IPV6_RECVERR *** */ +#if defined(IPV6_RECVERR) + tmp = MKT2(env, esock_atom_recverr, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_recverr, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_RECVPKTINFO => IPV6_RECVPKTINFO *** */ +#if defined(IPV6_RECVPKTINFO) + tmp = MKT2(env, esock_atom_recvpktinfo, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_recvpktinfo, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_RECVTCLASS => IPV6_RECVTCLASS *** */ + tmp = MKT2(env, esock_atom_recvtclass, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_ROUTER_ALERT => IPV6_ROUTER_ALERT *** */ +#if defined(IPV6_ROUTER_ALERT) + tmp = MKT2(env, esock_atom_router_alert, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_router_alert, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_RTHDR => IPV6_RTHDR *** */ +#if defined(IPV6_RTHDR) + tmp = MKT2(env, esock_atom_rthdr, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_rthdr, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_TCLASS => IPV6_TCLASS *** */ + tmp = MKT2(env, esock_atom_tclass, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_UNICAST_HOPS => IPV6_UNICAST_HOPS *** */ +#if defined(IPV6_UNICAST_HOPS) + tmp = MKT2(env, esock_atom_unicast_hops, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_unicast_hops, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_USE_MIN_MTU => IPV6_USE_MIN_MTU *** */ + tmp = MKT2(env, esock_atom_use_min_mtu, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_IPV6_V6ONLY => IPV6_V6ONLY *** */ +#if defined(IPV6_V6ONLY) + tmp = MKT2(env, esock_atom_v6only, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_v6only, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + TARRAY_TOLIST(opts, env, &optsL); + + return optsL; +} + + + +static +ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env) +{ + SocketTArray opts = TARRAY_CREATE(32); + ERL_NIF_TERM tmp, optsL; + + + /* *** SOCKET_OPT_TCP_CONGESTION => TCP_CONGESTION *** */ +#if defined(TCP_CONGESTION) + tmp = MKT2(env, esock_atom_congestion, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_congestion, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_CORK => TCP_CORK *** */ +#if defined(TCP_CORK) + tmp = MKT2(env, esock_atom_cork, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_cork, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_INFO => TCP_INFO *** */ + tmp = MKT2(env, esock_atom_info, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_KEEPCNT => TCP_KEEPCNT *** */ + tmp = MKT2(env, esock_atom_keepcnt, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_KEEPIDLE => TCP_KEEPIDLE *** */ + tmp = MKT2(env, esock_atom_keepidle, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_KEEPINTVL => TCP_KEEPINTVL *** */ + tmp = MKT2(env, esock_atom_keepintvl, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_MAXSEG => TCP_MAXSEG *** */ +#if defined(TCP_) + tmp = MKT2(env, esock_atom_maxseg, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_maxseg, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_MD5SIG => TCP_MD5SIG *** */ + tmp = MKT2(env, esock_atom_md5sig, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_NODELAY => TCP_NODELAY *** */ +#if defined(TCP_) + tmp = MKT2(env, esock_atom_nodelay, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_nodelay, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_NOOPT => TCP_NOOPT *** */ + tmp = MKT2(env, esock_atom_noopt, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_NOPUSH => TCP_NOPUSH *** */ + tmp = MKT2(env, esock_atom_nopush, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_SYNCNT => TCP_SYNCNT *** */ + tmp = MKT2(env, esock_atom_syncnt, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_TCP_USER_TIMEOUT => TCP_USER_TIMEOUT *** */ + tmp = MKT2(env, esock_atom_user_timeout, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + TARRAY_TOLIST(opts, env, &optsL); + + return optsL; +} + + + +static +ERL_NIF_TERM nsupports_options_udp(ErlNifEnv* env) +{ + SocketTArray opts = TARRAY_CREATE(8); + ERL_NIF_TERM tmp, optsL; + + + /* *** SOCKET_OPT_UDP_CORK => UDP_CORK *** */ +#if defined(UDP_CORK) + tmp = MKT2(env, esock_atom_cork, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_cork, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + TARRAY_TOLIST(opts, env, &optsL); + + return optsL; +} + + + +static +ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) +{ + SocketTArray opts = TARRAY_CREATE(64); + ERL_NIF_TERM tmp, optsL; + + + /* *** SOCKET_OPT_SCTP_ADAPTION_LAYER => SCTP_ADAPTION_LAYER *** */ + tmp = MKT2(env, esock_atom_adaption_layer, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_ASSOCINFO => SCTP_ASSOCINFO *** */ +#if defined(SCTP_ASSOCINFO) + tmp = MKT2(env, esock_atom_associnfo, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_associnfo, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_AUTH_ACTIVE_KEY => SCTP_AUTH_ACTIVE_KEY *** */ + tmp = MKT2(env, esock_atom_auth_active_key, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_AUTH_ASCONF => SCTP_AUTH_ASCONF *** */ + tmp = MKT2(env, esock_atom_auth_asconf, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_AUTH_CHUNK => SCTP_AUTH_CHUNK *** */ + tmp = MKT2(env, esock_atom_auth_chunk, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_AUTH_DELETE_KEY => SCTP_AUTH_DELETE_KEY *** */ + tmp = MKT2(env, esock_atom_auth_delete_key, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_AUTH_KEY => SCTP_AUTH_KEY *** */ + tmp = MKT2(env, esock_atom_auth_key, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_AUTOCLOSE => SCTP_AUTOCLOSE *** */ +#if defined(SCTP_AUTOCLOSE) + tmp = MKT2(env, esock_atom_autoclose, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_autoclose, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_CONTEXT => SCTP_CONTEXT *** */ + tmp = MKT2(env, esock_atom_context, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_DEFAULT_SEND_PARAMS => SCTP_DEFAULT_SEND_PARAMS *** */ + tmp = MKT2(env, esock_atom_default_send_params, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_DELAYED_ACK_TIME => SCTP_DELAYED_ACK_TIME *** */ + tmp = MKT2(env, esock_atom_delayed_ack_time, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_DISABLE_FRAGMENTS => SCTP_DISABLE_FRAGMENTS *** */ +#if defined(SCTP_DISABLE_FRAGMENTS) + tmp = MKT2(env, esock_atom_disable_fragments, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_disable_fragments, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_HMAC_IDENT => SCTP_HMAC_IDENT *** */ + tmp = MKT2(env, esock_atom_hmac_ident, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_EVENTS => SCTP_EVENTS *** */ +#if defined(SCTP_EVENTS) + tmp = MKT2(env, esock_atom_events, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_events, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_EXPLICIT_EOR => SCTP_EXPLICIT_EOR *** */ + tmp = MKT2(env, esock_atom_explicit_eor, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_FRAGMENT_INTERLEAVE => SCTP_FRAGMENT_INTERLEAVE *** */ + tmp = MKT2(env, esock_atom_fragment_interleave, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_GET_PEER_ADDR_INFO => SCTP_GET_PEER_ADDR_INFO *** */ + tmp = MKT2(env, esock_atom_get_peer_addr_info, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_INITMSG => SCTP_INITMSG *** */ +#if defined(SCTP_INITMSG) + tmp = MKT2(env, esock_atom_initmsg, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_initmsg, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_I_WANT_MAPPED_V4_ADDR => SCTP_I_WANT_MAPPED_V4_ADDR *** */ + tmp = MKT2(env, esock_atom_i_want_mapped_v4_addr, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_LOCAL_AUTH_CHUNKS => SCTP_LOCAL_AUTH_CHUNKS *** */ + tmp = MKT2(env, esock_atom_local_auth_chunks, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_MAXSEG => SCTP_MAXSEG *** */ +#if defined(SCTP_MAXSEG) + tmp = MKT2(env, esock_atom_maxseg, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_maxseg, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_MAXBURST => SCTP_MAXBURST *** */ + tmp = MKT2(env, esock_atom_maxburst, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_NODELAY => SCTP_NODELAY *** */ +#if defined(SCTP_NODELAY) + tmp = MKT2(env, esock_atom_nodelay, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_nodelay, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_PARTIAL_DELIVERY_POINT => SCTP_PARTIAL_DELIVERY_POINT *** */ + tmp = MKT2(env, esock_atom_partial_delivery_point, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_PEER_ADDR_PARAMS => SCTP_PEER_ADDR_PARAMS *** */ + tmp = MKT2(env, esock_atom_peer_addr_params, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_PEER_AUTH_CHUNKS => SCTP_PEER_AUTH_CHUNKS *** */ + tmp = MKT2(env, esock_atom_peer_auth_chunks, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_PRIMARY_ADDR => SCTP_PRIMARY_ADDR *** */ + tmp = MKT2(env, esock_atom_primary_addr, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_RESET_STREAMS => SCTP_RESET_STREAMS *** */ + tmp = MKT2(env, esock_atom_reset_streams, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_RTOINFO => SCTP_RTOINFO *** */ +#if defined(SCTP_RTOINFO) + tmp = MKT2(env, esock_atom_rtoinfo, esock_atom_true); +#else + tmp = MKT2(env, esock_atom_rtoinfo, esock_atom_false); +#endif + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_SET_PEER_PRIMARY_ADDR => SCTP_SET_PEER_PRIMARY_ADDR *** */ + tmp = MKT2(env, esock_atom_set_peer_primary_addr, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_STATUS => SCTP_STATUS *** */ + tmp = MKT2(env, esock_atom_status, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + /* *** SOCKET_OPT_SCTP_USE_EXT_RECVINFO => SCTP_USE_EXT_RECVINFO *** */ + tmp = MKT2(env, esock_atom_use_ext_recvinfo, esock_atom_false); + TARRAY_ADD(opts, tmp); + + + TARRAY_TOLIST(opts, env, &optsL); + + return optsL; +} + + + +static +ERL_NIF_TERM nsupports_sctp(ErlNifEnv* env) +{ + ERL_NIF_TERM supports; + +#if defined(HAVE_SCTP) + supports = esock_atom_true; +#else + supports = esock_atom_false; +#endif + + return supports; +} + + + +static +ERL_NIF_TERM nsupports_ipv6(ErlNifEnv* env) +{ + ERL_NIF_TERM supports; + + /* Is this (test) really sufficient for testing if we support IPv6? */ +#if defined(HAVE_IPV6) + supports = esock_atom_true; +#else + supports = esock_atom_false; +#endif + + return supports; +} + + + /* ---------------------------------------------------------------------- * nif_open * @@ -5285,8 +6703,12 @@ ERL_NIF_TERM nsetopt_level(ErlNifEnv* env, result = nsetopt_lvl_ip(env, descP, eOpt, eVal); break; +#if defined(HAVE_IPV6) #if defined(SOL_IPV6) case SOL_IPV6: +#else + case IPPROTO_IPV6: +#endif result = nsetopt_lvl_ipv6(env, descP, eOpt, eVal); break; #endif @@ -6772,7 +8194,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env, /* nsetopt_lvl_ipv6 - Level *IPv6* option(s) */ -#if defined(SOL_IPV6) +#if defined(HAVE_IPV6) static ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, SocketDescriptor* descP, @@ -7243,7 +8665,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, -#endif // defined(SOL_IPV6) +#endif // defined(HAVE_IPV6) @@ -8045,10 +9467,14 @@ BOOLEAN_T elevel2level(BOOLEAN_T isEncoded, result = TRUE; break; -#if defined(SOL_IPV6) +#if defined(HAVE_IPV6) case SOCKET_OPT_LEVEL_IPV6: *isOTP = FALSE; +#if defined(SOL_IPV6) *level = SOL_IPV6; +#else + *level = IPPROTO_IPV6; +#endif result = TRUE; break; #endif @@ -8694,8 +10120,12 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env, result = ngetopt_lvl_ip(env, descP, eOpt); break; +#if defined(HAVE_IPV6) #if defined(SOL_IPV6) case SOL_IPV6: +#else + case IPPROTO_IPV6: +#endif result = ngetopt_lvl_ipv6(env, descP, eOpt); break; #endif @@ -9898,7 +11328,7 @@ ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env, /* ngetopt_lvl_ipv6 - Level *IPv6* option(s) */ -#if defined(SOL_IPV6) +#if defined(HAVE_IPV6) static ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, SocketDescriptor* descP, @@ -10207,7 +11637,7 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env, #endif -#endif // defined(SOL_IPV6) +#endif // defined(HAVE_IPV6) @@ -12811,8 +14241,12 @@ char* encode_cmsghdr_level(ErlNifEnv* env, xres = NULL; break; +#if defined(HAVE_IPV6) #if defined(SOL_IPV6) case SOL_IPV6: +#else + case IPPROTO_IPV6: +#endif *eLevel = esock_atom_ip; xres = NULL; break; @@ -12859,9 +14293,13 @@ char* decode_cmsghdr_level(ErlNifEnv* env, *level = IPPROTO_IP; #endif xres = NULL; -#if defined(SOL_IPV6) +#if defined(HAVE_IPV6) } else if (COMPARE(eLevel, esock_atom_ipv6) == 0) { +#if defined(SOL_IPV6) *level = SOL_IPV6; +#else + *level = IPPROTO_IPV6; +#endif xres = NULL; #endif } else if (COMPARE(eLevel, esock_atom_udp) == 0) { @@ -12961,8 +14399,12 @@ char* encode_cmsghdr_type(ErlNifEnv* env, } break; +#if defined(HAVE_IPV6) #if defined(SOL_IPV6) - case SOL_IPV6: + case SOL_IPV6: +#else + case IPPROTO_IPV6: +#endif switch (type) { #if defined(IPV6_PKTINFO) case IPV6_PKTINFO: @@ -13073,8 +14515,12 @@ char* decode_cmsghdr_type(ErlNifEnv* env, } break; +#if defined(HAVE_IPV6) #if defined(SOL_IPV6) case SOL_IPV6: +#else + case IPPROTO_IPV6: +#endif if (IS_NUM(env, eType)) { if (!GET_INT(env, eType, type)) { *type = -1; @@ -13147,8 +14593,12 @@ char* encode_cmsghdr_data(ErlNifEnv* env, eCMsgHdrData); break; +#if defined(HAVE_IPV6) #if defined(SOL_IPV6) case SOL_IPV6: +#else + case IPPROTO_IPV6: +#endif xres = encode_cmsghdr_data_ipv6(env, ctrlBuf, type, dataP, dataPos, dataLen, eCMsgHdrData); @@ -13345,7 +14795,7 @@ char* encode_cmsghdr_data_ip(ErlNifEnv* env, * Encode the data part when protocol = IPv6 of the cmsghdr(). * */ -#if defined(SOL_IPV6) +#if defined(HAVE_IPV6) static char* encode_cmsghdr_data_ipv6(ErlNifEnv* env, ERL_NIF_TERM ctrlBuf, @@ -15412,9 +16862,11 @@ void socket_down_reader(ErlNifEnv* env, static ErlNifFunc socket_funcs[] = { - // Some utility functions - {"nif_info", 0, nif_info, 0}, - // {"nif_debug", 1, nif_debug_, 0}, + // Some utility and support functions + {"nif_info", 0, nif_info, 0}, + {"nif_supports", 1, nif_supports, 0}, + // {"nif_debug", 1, nif_debug, 0}, + // {"nif_command", 1, nif_command, 0}, // The proper "socket" interface // nif_open/1 is used when we already have a file descriptor @@ -15564,73 +17016,196 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) atom_want = MKA(env, str_want); /* Global atom(s) */ - esock_atom_accept = MKA(env, "accept"); - esock_atom_addr = MKA(env, "addr"); - esock_atom_any = MKA(env, "any"); - esock_atom_connect = MKA(env, "connect"); - 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_dgram = MKA(env, "dgram"); - esock_atom_eor = MKA(env, "eor"); - esock_atom_error = MKA(env, "error"); - esock_atom_errqueue = MKA(env, "errqueue"); - 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_ifindex = MKA(env, "ifindex"); - esock_atom_inet = MKA(env, "inet"); - esock_atom_inet6 = MKA(env, "inet6"); - esock_atom_iov = MKA(env, "iov"); - esock_atom_ip = MKA(env, "ip"); - esock_atom_ipv6 = MKA(env, "ipv6"); - esock_atom_level = MKA(env, "level"); - esock_atom_local = MKA(env, "local"); - esock_atom_loopback = MKA(env, "loopback"); - esock_atom_lowdelay = MKA(env, "lowdelay"); - esock_atom_mincost = MKA(env, "mincost"); - 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_origdstaddr = MKA(env, "origdstaddr"); - esock_atom_path = MKA(env, "path"); - esock_atom_pktinfo = MKA(env, "pktinfo"); - esock_atom_port = MKA(env, "port"); - esock_atom_protocol = MKA(env, "protocol"); - esock_atom_raw = MKA(env, "raw"); - esock_atom_rdm = MKA(env, "rdm"); - esock_atom_recv = MKA(env, "recv"); - esock_atom_recvfrom = MKA(env, "recvfrom"); - esock_atom_recvmsg = MKA(env, "recvmsg"); - esock_atom_reliability = MKA(env, "reliability"); - esock_atom_rights = MKA(env, "rights"); - esock_atom_scope_id = MKA(env, "scope_id"); - esock_atom_sctp = MKA(env, "sctp"); - esock_atom_sec = MKA(env, "sec"); - esock_atom_select_sent = MKA(env, "select_sent"); - esock_atom_send = MKA(env, "send"); - esock_atom_sendmsg = MKA(env, "sendmsg"); - esock_atom_sendto = MKA(env, "sendto"); - esock_atom_seqpacket = MKA(env, "seqpacket"); - esock_atom_socket = MKA(env, "socket"); - esock_atom_spec_dst = MKA(env, "spec_dst"); - esock_atom_stream = MKA(env, "stream"); - 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_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_undefined = MKA(env, "undefined"); - esock_atom_unknown = MKA(env, "unknown"); - esock_atom_usec = MKA(env, "usec"); + 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_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_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_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); diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam Binary files differindex 9c7bcf89b5..a0bf156263 100644 --- a/erts/preloaded/ebin/socket.beam +++ b/erts/preloaded/ebin/socket.beam diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index c388fc2849..acf5e18cec 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -27,6 +27,7 @@ -export([ on_load/0, on_load/1, info/0, + supports/0, supports/1, supports/2, supports/3, ensure_sockaddr/1 ]). @@ -733,8 +734,8 @@ %% -define(SOCKET_OPT_IPV6_CHECKSUM, 5). % FreeBSD -define(SOCKET_OPT_IPV6_DROP_MEMBERSHIP, 6). -define(SOCKET_OPT_IPV6_DSTOPTS, 7). -%% -define(SOCKET_OPT_IPV6_ESP_TRANS_LEVEL, 8). % FreeBSD -%% -define(SOCKET_OPT_IPV6_ESP_NETWORK_LEVEL, 9). % FreeBSD +%% -define(SOCKET_OPT_IPV6_ESP_NETWORK_LEVEL, 8). % FreeBSD +%% -define(SOCKET_OPT_IPV6_ESP_TRANS_LEVEL, 9). % FreeBSD %% -define(SOCKET_OPT_IPV6_FAITH, 10). % FreeBSD -define(SOCKET_OPT_IPV6_FLOWINFO, 11). -define(SOCKET_OPT_IPV6_HOPLIMIT, 12). @@ -816,6 +817,10 @@ -define(SOCKET_SHUTDOWN_HOW_READ_WRITE, 2). +-define(SOCKET_SUPPORTS_OPTIONS, 16#0001). +-define(SOCKET_SUPPORTS_SCTP, 16#0002). +-define(SOCKET_SUPPORTS_IPV6, 16#0003). + %% =========================================================================== %% @@ -846,6 +851,100 @@ info() -> %% =========================================================================== %% +%% supports - get information about what the platform "supports". +%% +%% Generates a list of various info about what the plaform can support. +%% The most obvious case is 'options'. +%% +%% Each item in a 'supports'-list will appear only *one* time. +%% +%% =========================================================================== + +-type supports_options_socket() :: [{socket_option(), boolean()}]. +-type supports_options_ip() :: [{ip_socket_option(), boolean()}]. +-type supports_options_ipv6() :: [{ipv6_socket_option(), boolean()}]. +-type supports_options_tcp() :: [{tcp_socket_option(), boolean()}]. +-type supports_options_udp() :: [{udp_socket_option(), boolean()}]. +-type supports_options_sctp() :: [{sctp_socket_option(), boolean()}]. +-type supports_options() :: [{socket, supports_options_socket()} | + {ip, supports_options_ip()} | + {ipv6, supports_options_ipv6()} | + {tcp, supports_options_tcp()} | + {udp, supports_options_udp()} | + {sctp, supports_options_sctp()}]. + +-spec supports() -> [{options, supports_options()} | + {sctp, boolean()} | + {ipv6, boolean()}]. + +supports() -> + [{options, supports(options)}, + {sctp, supports(sctp)}, + {ipv6, supports(ipv6)}]. + + +-spec supports(options) -> supports_options(); + (sctp) -> boolean(); + (ipv6) -> boolean(); + (Key1) -> false when + Key1 :: term(). + +supports(options) -> + nif_supports(?SOCKET_SUPPORTS_OPTIONS); +supports(sctp) -> + nif_supports(?SOCKET_SUPPORTS_SCTP); +supports(ipv6) -> + nif_supports(?SOCKET_SUPPORTS_IPV6); +supports(_Key1) -> + false. + +-spec supports(options, socket) -> supports_options_socket(); + (options, ip) -> supports_options_ip(); + (options, ipv6) -> supports_options_ipv6(); + (options, tcp) -> supports_options_tcp(); + (options, udp) -> supports_options_udp(); + (options, sctp) -> supports_options_sctp(); + (Key1, Key2) -> false when + Key1 :: term(), + Key2 :: term(). + +supports(options, Level) -> + proplists:get_value(Level, supports(options), false); +supports(_Key1, _Level) -> + false. + + +-spec supports(options, socket, Opt) -> boolean() when + Opt :: socket_option(); + (options, ip, Opt) -> boolean() when + Opt :: ip_socket_option(); + (options, ipv6, Opt) -> boolean() when + Opt :: ipv6_socket_option(); + (options, tcp, Opt) -> boolean() when + Opt :: tcp_socket_option(); + (options, udp, Opt) -> boolean() when + Opt :: udp_socket_option(); + (options, sctp, Opt) -> boolean() when + Opt :: sctp_socket_option(); + (Key1, Key2, Key3) -> false when + Key1 :: term(), + Key2 :: term(), + Key3 :: term(). + +supports(options, Level, Opt) -> + case supports(options, Level) of + S when is_list(S) -> + proplists:get_value(Opt, S, false); + _ -> + false + end; +supports(_Key1, _Key2, _Key3) -> + false. + + + +%% =========================================================================== +%% %% The proper socket API %% %% =========================================================================== @@ -3417,6 +3516,9 @@ error(Reason) -> nif_info() -> erlang:nif_error(undef). +nif_supports(_Key) -> + erlang:nif_error(undef). + nif_open(_Domain, _Type, _Protocol, _Extra) -> erlang:nif_error(undef). |