diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/doc/src/socket_usage.xml | 21 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 146 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_util.c | 29 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_util.h | 6 | ||||
-rw-r--r-- | erts/preloaded/ebin/socket.beam | bin | 66040 -> 66584 bytes | |||
-rw-r--r-- | erts/preloaded/src/socket.erl | 33 |
6 files changed, 231 insertions, 4 deletions
diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml index 9785830637..23d0f319f1 100644 --- a/erts/doc/src/socket_usage.xml +++ b/erts/doc/src/socket_usage.xml @@ -81,6 +81,27 @@ <cell>yes</cell> <cell>none</cell> </row> + <row> + <cell>rcvbuf</cell> + <cell>default | pos_integer()</cell> + <cell>yes</cell> + <cell>yes</cell> + <cell>default only valid for set</cell> + </row> + <row> + <cell>rcvctrlbuf</cell> + <cell>default | pos_integer()</cell> + <cell>yes</cell> + <cell>yes</cell> + <cell>default only valid for set</cell> + </row> + <row> + <cell>sndctrlbuf</cell> + <cell>default | pos_integer()</cell> + <cell>yes</cell> + <cell>yes</cell> + <cell>default only valid for set</cell> + </row> </table> <p>Options for level <c>socket</c>: </p> diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index ccbcf63ece..876bed3135 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -501,6 +501,9 @@ typedef union { #define SOCKET_OPT_OTP_DEBUG 1 #define SOCKET_OPT_OTP_IOW 2 #define SOCKET_OPT_OTP_CTRL_PROC 3 +#define SOCKET_OPT_OTP_RCVBUF 4 +#define SOCKET_OPT_OTP_RCVCTRLBUF 6 +#define SOCKET_OPT_OTP_SNDCTRLBUF 7 #define SOCKET_OPT_SOCK_ACCEPTCONN 1 #define SOCKET_OPT_SOCK_BINDTODEVICE 3 @@ -1004,6 +1007,15 @@ static ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env, static ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM eVal); +static ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal); +static ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal); +static ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal); static ERL_NIF_TERM nsetopt_native(ErlNifEnv* env, SocketDescriptor* descP, int level, @@ -1492,6 +1504,12 @@ static ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env, SocketDescriptor* descP); static ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env, SocketDescriptor* descP); +static ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env, + SocketDescriptor* descP); +static ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env, + SocketDescriptor* descP); +static ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env, + SocketDescriptor* descP); static ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, SocketDescriptor* descP, int level, @@ -5001,6 +5019,18 @@ ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env, result = nsetopt_otp_ctrl_proc(env, descP, eVal); break; + case SOCKET_OPT_OTP_RCVBUF: + result = nsetopt_otp_rcvbuf(env, descP, eVal); + break; + + case SOCKET_OPT_OTP_RCVCTRLBUF: + result = nsetopt_otp_rcvctrlbuf(env, descP, eVal); + break; + + case SOCKET_OPT_OTP_SNDCTRLBUF: + result = nsetopt_otp_sndctrlbuf(env, descP, eVal); + break; + default: result = esock_make_error(env, esock_atom_einval); break; @@ -5079,6 +5109,74 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env, +/* nsetopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option + */ +static +ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal) +{ + size_t val; + char* xres; + + if ((xres = esock_decode_bufsz(env, + eVal, + SOCKET_RECV_BUFFER_SIZE_DEFAULT, &val)) != NULL) + return esock_make_error_str(env, xres); + + descP->rBufSz = val; + + return esock_atom_ok; +} + + + +/* nsetopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option + */ +static +ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal) +{ + size_t val; + char* xres; + + if ((xres = esock_decode_bufsz(env, + eVal, + SOCKET_RECV_CTRL_BUFFER_SIZE_DEFAULT, + &val)) != NULL) + return esock_make_error_str(env, xres); + + descP->rCtrlSz = val; + + return esock_atom_ok; +} + + + +/* nsetopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option + */ +static +ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal) +{ + size_t val; + char* xres; + + if ((xres = esock_decode_bufsz(env, + eVal, + SOCKET_SEND_CTRL_BUFFER_SIZE_DEFAULT, + &val)) != NULL) + return esock_make_error_str(env, xres); + + descP->wCtrlSz = val; + + return esock_atom_ok; +} + + + /* The option has *not* been encoded. Instead it has been provided * in "native mode" (option is provided as is and value as a binary). */ @@ -8169,6 +8267,18 @@ ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env, result = ngetopt_otp_ctrl_proc(env, descP); break; + case SOCKET_OPT_OTP_RCVBUF: + result = ngetopt_otp_rcvbuf(env, descP); + break; + + case SOCKET_OPT_OTP_RCVCTRLBUF: + result = ngetopt_otp_rcvctrlbuf(env, descP); + break; + + case SOCKET_OPT_OTP_SNDCTRLBUF: + result = ngetopt_otp_sndctrlbuf(env, descP); + break; + default: result = esock_make_error(env, esock_atom_einval); break; @@ -8220,6 +8330,42 @@ ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env, +/* ngetopt_otp_rcvbuf - Handle the OTP (level) rcvbuf options + */ +static +ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env, + SocketDescriptor* descP) +{ + ERL_NIF_TERM eVal = MKI(env, descP->rBufSz); + + return esock_make_ok2(env, eVal); +} + + +/* ngetopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf options + */ +static +ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env, + SocketDescriptor* descP) +{ + ERL_NIF_TERM eVal = MKI(env, descP->rCtrlSz); + + return esock_make_ok2(env, eVal); +} + + +/* ngetopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf options + */ +static +ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env, + SocketDescriptor* descP) +{ + ERL_NIF_TERM eVal = MKI(env, descP->wCtrlSz); + + return esock_make_ok2(env, eVal); +} + + /* The option has *not* been encoded. Instead it has been provided * in "native mode" (option is provided as is). In this case it will have the * format: {NativeOpt :: integer(), ValueSize :: non_neg_integer()} diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c index 8bb725fb5b..ff50fd2384 100644 --- a/erts/emulator/nifs/common/socket_util.c +++ b/erts/emulator/nifs/common/socket_util.c @@ -1261,6 +1261,35 @@ char* esock_decode_protocol(ErlNifEnv* env, +/* +++ esock_decode_bufsz +++ + * + * Decode an buffer size. The size of a buffer is: + * + * Sz > 0 => Use provided value + * Sz => Use provided default + * + */ +extern +char* esock_decode_bufsz(ErlNifEnv* env, + ERL_NIF_TERM eVal, + size_t defSz, + size_t* sz) +{ + int val; + + if (!GET_INT(env, eVal, &val)) + return ESOCK_STR_EINVAL; + + if (val > 0) + *sz = (size_t) val; + else + *sz = defSz; + + return NULL; +} + + + /* *** esock_decode_string *** * * Decode a string value. A successful decode results in an diff --git a/erts/emulator/nifs/common/socket_util.h b/erts/emulator/nifs/common/socket_util.h index a38453e238..1b5d003155 100644 --- a/erts/emulator/nifs/common/socket_util.h +++ b/erts/emulator/nifs/common/socket_util.h @@ -158,6 +158,12 @@ char* esock_encode_protocol(ErlNifEnv* env, ERL_NIF_TERM* eProtocol); extern +char* esock_decode_bufsz(ErlNifEnv* env, + ERL_NIF_TERM eVal, + size_t defSz, + size_t* sz); + +extern BOOLEAN_T esock_decode_string(ErlNifEnv* env, const ERL_NIF_TERM eString, char** stringP); diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam Binary files differindex 9e6d9f4709..a0550990e3 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 652054457f..8093bad885 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -320,12 +320,15 @@ %% Should we just document it and leave it to the user? %% Or catch it in the encode functions? %% A setopt for a readonly option leads to einval? +%% Do we really need a sndbuf? -type otp_socket_option() :: debug | iow | controlling_process | rcvbuf | - sndbuf. + sndbuf | + rcvctrlbuf | + sndctrlbuf. %% Shall we have special treatment of linger?? %% read-only options: %% domain | protocol | type. @@ -645,6 +648,10 @@ -define(SOCKET_OPT_OTP_DEBUG, 1). -define(SOCKET_OPT_OTP_IOW, 2). -define(SOCKET_OPT_OTP_CTRL_PROC, 3). +-define(SOCKET_OPT_OTP_RCVBUF, 4). +%%-define(SOCKET_OPT_OTP_SNDBUF, 5). +-define(SOCKET_OPT_OTP_RCVCTRLBUF, 6). +-define(SOCKET_OPT_OTP_SNDCTRLBUF, 7). %% *** SOCKET (socket) options -define(SOCKET_OPT_SOCK_ACCEPTCONN, 1). @@ -2136,9 +2143,9 @@ getopt(#socket{ref = SockRef}, Level, Key) -> end end catch - throw:T -> - T; - error:Reason -> + throw:E:_S -> + E; + error:Reason:_Stack -> {error, Reason} % Process more? end. @@ -2401,6 +2408,18 @@ enc_setopt_value(otp, iow, V, _, _, _) when is_boolean(V) -> V; enc_setopt_value(otp, controlling_process, V, _, _, _) when is_pid(V) -> V; +enc_setopt_value(otp, rcvbuf, V, _, _, _) when (V =:= default) -> + 0; +enc_setopt_value(otp, rcvbuf, V, _, _, _) when is_integer(V) andalso (V > 0) -> + V; +enc_setopt_value(otp, rcvctrlbuf, V, _, _, _) when (V =:= default) -> + 0; +enc_setopt_value(otp, rcvctrlbuf, V, _, _, _) when is_integer(V) andalso (V > 0) -> + V; +enc_setopt_value(otp, sndctrlbuf, V, _, _, _) when (V =:= default) -> + 0; +enc_setopt_value(otp, sndctrlbuf, V, _, _, _) when is_integer(V) andalso (V > 0) -> + V; enc_setopt_value(otp = L, Opt, V, _D, _T, _P) -> not_supported({L, Opt, V}); @@ -2871,6 +2890,12 @@ enc_sockopt_key(otp, iow, _, _, _, _) -> ?SOCKET_OPT_OTP_IOW; enc_sockopt_key(otp, controlling_process, _, _, _, _) -> ?SOCKET_OPT_OTP_CTRL_PROC; +enc_sockopt_key(otp, rcvbuf, _, _, _, _) -> + ?SOCKET_OPT_OTP_RCVBUF; +enc_sockopt_key(otp, rcvctrlbuf, _, _, _, _) -> + ?SOCKET_OPT_OTP_RCVCTRLBUF; +enc_sockopt_key(otp, sndctrlbuf, _, _, _, _) -> + ?SOCKET_OPT_OTP_SNDCTRLBUF; enc_sockopt_key(otp = L, Opt, _, _, _, _) -> not_supported({L, Opt}); |