diff options
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 130 | ||||
-rw-r--r-- | erts/preloaded/ebin/socket.beam | bin | 43472 -> 43604 bytes | |||
-rw-r--r-- | erts/preloaded/src/socket.erl | 24 | ||||
-rw-r--r-- | lib/kernel/test/socket_server.erl | 16 |
4 files changed, 152 insertions, 18 deletions
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index c23f0b021d..70a5de912f 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -347,14 +347,16 @@ typedef union { #define SOCKET_OPT_OTP_CTRL_PROC 2 #define SOCKET_OPT_SOCK_BROADCAST 4 -#define SOCKET_OPT_SOCK_DONTROUTE 7 -#define SOCKET_OPT_SOCK_KEEPALIVE 9 -#define SOCKET_OPT_SOCK_LINGER 10 -#define SOCKET_OPT_SOCK_PRIORITY 16 -#define SOCKET_OPT_SOCK_RCVBUF 17 -#define SOCKET_OPT_SOCK_REUSEADDR 21 -#define SOCKET_OPT_SOCK_SNDBUF 27 -#define SOCKET_OPT_SOCK_TYPE 32 +#define SOCKET_OPT_SOCK_DOMAIN 7 +#define SOCKET_OPT_SOCK_DONTROUTE 8 +#define SOCKET_OPT_SOCK_KEEPALIVE 10 +#define SOCKET_OPT_SOCK_LINGER 11 +#define SOCKET_OPT_SOCK_PRIORITY 17 +#define SOCKET_OPT_SOCK_PROTOCOL 18 +#define SOCKET_OPT_SOCK_RCVBUF 19 +#define SOCKET_OPT_SOCK_REUSEADDR 23 +#define SOCKET_OPT_SOCK_SNDBUF 29 +#define SOCKET_OPT_SOCK_TYPE 34 #define SOCKET_OPT_IP_RECVTOS 25 #define SOCKET_OPT_IP_ROUTER_ALERT 28 @@ -931,6 +933,10 @@ static ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env, static ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env, SocketDescriptor* descP); #endif +#if defined(SO_DOMAIN) +static ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env, + SocketDescriptor* descP); +#endif #if defined(SO_DONTROUTE) static ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env, SocketDescriptor* descP); @@ -947,6 +953,10 @@ static ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env, static ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env, SocketDescriptor* descP); #endif +#if defined(SO_PROTOCOL) +static ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env, + SocketDescriptor* descP); +#endif #if defined(SO_RCVBUF) static ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env, SocketDescriptor* descP); @@ -4715,6 +4725,12 @@ ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env, break; #endif +#if defined(SO_DOMAIN) + case SOCKET_OPT_SOCK_DOMAIN: + result = ngetopt_lvl_sock_domain(env, descP); + break; +#endif + #if defined(SO_DONTROUTE) case SOCKET_OPT_SOCK_DONTROUTE: result = ngetopt_lvl_sock_dontroute(env, descP); @@ -4739,6 +4755,12 @@ ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env, break; #endif +#if defined(SO_PROTOCOL) + case SOCKET_OPT_SOCK_PROTOCOL: + result = ngetopt_lvl_sock_protocol(env, descP); + break; +#endif + #if defined(SO_RCVBUF) case SOCKET_OPT_SOCK_RCVBUF: result = ngetopt_lvl_sock_rcvbuf(env, descP); @@ -4782,6 +4804,51 @@ ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env, #endif +#if defined(SO_DOMAIN) +static +ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env, + SocketDescriptor* descP) +{ + ERL_NIF_TERM result; + int val; + SOCKOPTLEN_T valSz = sizeof(val); + int res; + + res = sock_getopt(descP->sock, SOL_SOCKET, SO_DOMAIN, + &val, &valSz); + + if (res != 0) { + result = esock_make_error_errno(env, res); + } else { + switch (val) { + case AF_INET: + result = esock_make_ok2(env, esock_atom_inet); + break; + +#if defined(HAVE_IN6) && defined(AF_INET6) + case AF_INET6: + result = esock_make_ok2(env, esock_atom_inet6); + break; +#endif + +#ifdef HAVE_SYS_UN_H + case AF_UNIX: + result = esock_make_ok2(env, esock_atom_local); + break; +#endif + + default: + result = esock_make_error(env, + MKT2(env, esock_atom_unknown, MKI(env, val))); + break; + } + } + + return result; +} +#endif + + #if defined(SO_DONTROUTE) static ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env, @@ -4842,6 +4909,53 @@ ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env, #endif +#if defined(SO_PROTOCOL) +static +ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env, + SocketDescriptor* descP) +{ + ERL_NIF_TERM result; + int val; + SOCKOPTLEN_T valSz = sizeof(val); + int res; + + res = sock_getopt(descP->sock, SOL_SOCKET, SO_PROTOCOL, + &val, &valSz); + + if (res != 0) { + result = esock_make_error_errno(env, res); + } else { + switch (val) { + case IPPROTO_IP: + result = esock_make_ok2(env, esock_atom_ip); + break; + + case IPPROTO_TCP: + result = esock_make_ok2(env, esock_atom_tcp); + break; + + case IPPROTO_UDP: + result = esock_make_ok2(env, esock_atom_udp); + break; + +#if defined(HAVE_SCTP) + case IPPROTO_SCTP: + result = esock_make_ok2(env, esock_atom_sctp); + break; +#endif + + default: + result = esock_make_error(env, + MKT2(env, esock_atom_unknown, MKI(env, val))); + break; + } + } + + return result; +} +#endif + + #if defined(SO_RCVBUF) static ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env, diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam Binary files differindex 8a3dab1313..952f869d54 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 a1db295a79..4932e301fb 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -193,6 +193,7 @@ broadcast | busy_poll | debug | + domain | dontroute | error | keepalive | @@ -203,6 +204,7 @@ peek_off | peek_cred | priority | + protocol | rcvbuf | rcvbufforce | rcvlowat | @@ -463,14 +465,16 @@ -define(SOCKET_OPT_OTP_CTRL_PROC, 2). -define(SOCKET_OPT_SOCK_BROADCAST, 4). --define(SOCKET_OPT_SOCK_DONTROUTE, 7). --define(SOCKET_OPT_SOCK_KEEPALIVE, 9). --define(SOCKET_OPT_SOCK_LINGER, 10). --define(SOCKET_OPT_SOCK_PRIORITY, 16). --define(SOCKET_OPT_SOCK_RCVBUF, 17). --define(SOCKET_OPT_SOCK_REUSEADDR, 21). --define(SOCKET_OPT_SOCK_SNDBUF, 27). --define(SOCKET_OPT_SOCK_TYPE, 32). +-define(SOCKET_OPT_SOCK_DOMAIN, 7). +-define(SOCKET_OPT_SOCK_DONTROUTE, 8). +-define(SOCKET_OPT_SOCK_KEEPALIVE, 10). +-define(SOCKET_OPT_SOCK_LINGER, 11). +-define(SOCKET_OPT_SOCK_PRIORITY, 17). +-define(SOCKET_OPT_SOCK_PROTOCOL, 18). +-define(SOCKET_OPT_SOCK_RCVBUF, 19). +-define(SOCKET_OPT_SOCK_REUSEADDR, 23). +-define(SOCKET_OPT_SOCK_SNDBUF, 29). +-define(SOCKET_OPT_SOCK_TYPE, 34). -define(SOCKET_OPT_IP_RECVTOS, 25). -define(SOCKET_OPT_IP_ROUTER_ALERT, 28). @@ -2032,6 +2036,8 @@ enc_sockopt_key(socket = L, busy_poll = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); enc_sockopt_key(socket = L, debug = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); +enc_sockopt_key(socket, domain = _Opt, get = _Dir, _D, _T, _P) -> + ?SOCKET_OPT_SOCK_DOMAIN; enc_sockopt_key(socket, dontroute = _Opt, _Dir, _D, _T, _P) -> ?SOCKET_OPT_SOCK_DONTROUTE; enc_sockopt_key(socket = L, error = Opt, get = _Dir, _D, _T, _P) -> @@ -2055,6 +2061,8 @@ enc_sockopt_key(socket = L, peek_cred = Opt, get = _Dir, _D, _T, _P) -> not_supported({L, Opt}); enc_sockopt_key(socket, priority = _Opt, _Dir, _D, _T, _P) -> ?SOCKET_OPT_SOCK_PRIORITY; +enc_sockopt_key(socket, protocol = _Opt, get = _Dir, _D, _T, _P) -> + ?SOCKET_OPT_SOCK_PROTOCOL; enc_sockopt_key(socket, rcvbuf = _Opt, _Dir, _D, _T, _P) -> ?SOCKET_OPT_SOCK_RCVBUF; enc_sockopt_key(socket = L, rcvbufforce = Opt, _Dir, _D, _T, _P) -> diff --git a/lib/kernel/test/socket_server.erl b/lib/kernel/test/socket_server.erl index 02fc6fc26d..cf7e349a3d 100644 --- a/lib/kernel/test/socket_server.erl +++ b/lib/kernel/test/socket_server.erl @@ -258,7 +258,13 @@ acceptor_do_init(Domain, Type, Proto) -> {error, OReason} -> throw({open, OReason}) end, - i("(socket) open - try find (local) address"), + F = fun(X) -> case socket:getopt(Sock, socket, X) of + {ok, V} -> f("~p", [V]); + {error, _} -> f("~w", [X]) + end + end, + i("(socket) open (~s,~s,~s) - try find (local) address", + [F(domain), F(type), F(protocol)]), Addr = which_addr(Domain), SA = #{family => Domain, addr => Addr}, @@ -392,7 +398,13 @@ handler_init(Manager, ID, Peek, Sock) -> {handler, Pid, Ref, continue} -> i("got continue"), handler_reply(Pid, Ref, ok), - {ok, Type} = socket:getopt(Sock, socket, type), + {ok, Domain} = socket:getopt(Sock, socket, domain), + {ok, Type} = socket:getopt(Sock, socket, type), + {ok, Proto} = socket:getopt(Sock, socket, protocol), + i("got continue when: " + "~n Domain: ~p" + "~n Type: ~p" + "~n Protocol: ~p", [Domain, Type, Proto]), %% socket:setopt(Socket, otp, debug, true), handler_loop(#handler{peek = Peek, manager = Manager, |