aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMicael Karlberg <[email protected]>2018-10-09 16:46:07 +0200
committerMicael Karlberg <[email protected]>2018-10-09 16:46:07 +0200
commitff3d31f7d102d68a585f8ce636753bf48b9553ab (patch)
tree3c09432251b6b244b32244646ec12fb04afcc993
parent4e3f42da1dae7166faeb9f9e07adc40bc3b22d75 (diff)
parentce28d70c686f342fb04fc05e1d00501e7cfbf213 (diff)
downloadotp-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
-rw-r--r--erts/doc/src/socket.xml49
-rw-r--r--erts/emulator/nifs/common/socket_int.h123
-rw-r--r--erts/emulator/nifs/common/socket_nif.c1743
-rw-r--r--erts/preloaded/ebin/socket.beambin66596 -> 68544 bytes
-rw-r--r--erts/preloaded/src/socket.erl106
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
index 9c7bcf89b5..a0bf156263 100644
--- a/erts/preloaded/ebin/socket.beam
+++ b/erts/preloaded/ebin/socket.beam
Binary files differ
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).