diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 58 | ||||
-rw-r--r-- | erts/preloaded/src/socket.erl | 32 |
2 files changed, 77 insertions, 13 deletions
diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index a702e35a0d..88fb2206e4 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -322,6 +322,7 @@ typedef unsigned long long llu_t; #define sock_getopt(s,t,n,v,l) getsockopt((s),(t),(n),(v),(l)) #define sock_htons(x) htons((x)) #define sock_htonl(x) htonl((x)) +#define sock_listen(s, b) listen((s), (b)) #define sock_name(s, addr, len) getsockname((s), (addr), (len)) #define sock_open(domain, type, proto) \ make_noninheritable_handle(socket((domain), (type), (proto))) @@ -341,6 +342,7 @@ static unsigned long one_value = 1; #define sock_getopt(s,t,n,v,l) getsockopt((s),(t),(n),(v),(l)) #define sock_htons(x) htons((x)) #define sock_htonl(x) htonl((x)) +#define sock_listen(s, b) listen((s), (b)) #define sock_name(s, addr, len) getsockname((s), (addr), (len)) #define sock_open(domain, type, proto) socket((domain), (type), (proto)) @@ -551,6 +553,9 @@ static ERL_NIF_TERM nconnect(ErlNifEnv* env, SocketDescriptor* descP, const ERL_NIF_TERM* addr, int port); +static ERL_NIF_TERM nlisten(ErlNifEnv* env, + SocketDescriptor* descP, + int backlog); static ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env, SocketDescriptor* descP); @@ -1611,6 +1616,59 @@ BOOLEAN_T verify_is_connected(SocketDescriptor* descP, int* err) /* ---------------------------------------------------------------------- + * nif_listen + * + * Description: + * Listen for connections on a socket. + * + * Arguments: + * Socket (ref) - Points to the socket descriptor. + * Backlog - The maximum length to which the queue of pending + * connections for socket may grow. + */ +static +ERL_NIF_TERM nif_listen(ErlNifEnv* env, + int argc, + const ERL_NIF_TERM argv[]) +{ + SocketDescriptor* descP; + int backlog; + + /* Extract arguments and perform preliminary validation */ + + if ((argc != 2) || + !enif_get_resource(env, argv[0], sockets, (void**) &descP) || + !GET_INT(env, argv[1], &backlog)) { + return enif_make_badarg(env); + } + + return nlisten(env, descP, backlog); +} + + + +static +ERL_NIF_TERM nlisten(ErlNifEnv* env, + SocketDescriptor* descP, + int backlog) +{ + if (descP->state == SOCKET_STATE_CLOSED) + return make_error(env, atom_exbadstate); + + if (!IS_OPEN(descP)) + return make_error(env, atom_exbadstate); + + if (IS_SOCKET_ERROR(sock_listen(descP->sock, backlog))) + return make_error2(env, sock_errno()); + + descP->state = SOCKET_STATE_LISTENING; + + return atom_ok; +} + + + +/* ---------------------------------------------------------------------- * U t i l i t y F u n c t i o n s * ---------------------------------------------------------------------- */ diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index f8e3d0419a..0886c0d211 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -213,7 +213,10 @@ info() -> %% %% =========================================================================== +%% =========================================================================== +%% %% open - create an endpoint for communication +%% open(Domain, Type) -> open(Domain, Type, null). @@ -272,7 +275,10 @@ default_protocol(null, Type) -> throw({error, {no_default_protocol, Type}}) default_protocol(Protocol, _) -> Protocol. +%% =========================================================================== +%% %% bind - bind a name to a socket +%% -spec bind(Socket, FileOrAddr) -> ok | {error, Reason} when Socket :: socket(), @@ -318,7 +324,11 @@ bind({socket, _, SockRef}, Addr, Port) nif_bind(SockRef, {Addr, Port}). + +%% =========================================================================== +%% %% connect - initiate a connection on a socket +%% -spec connect(Socket, Addr, Port) -> ok | {error, Reason} when Socket :: socket(), @@ -364,7 +374,11 @@ connect({socket, _, SockRef}, Addr, Port, Timeout) end. + +%% =========================================================================== +%% %% listen - listen for connections on a socket +%% -spec listen(Socket, Backlog) -> ok | {error, Reason} when Socket :: socket(), @@ -375,13 +389,15 @@ listen(Socket) -> listen(Socket, ?SOCKET_LISTEN_BACKLOG_DEFAULT). listen({socket, _, SockRef}, Backlog) - when (is_integer(Backlog) andalso (Backlog >= 0)) orelse is_boolean(Backlog) -> - EBacklog = enc_backlog(Backlog), - nif_listen(SockRef, EBacklog). + when (is_integer(Backlog) andalso (Backlog >= 0)) -> + nif_listen(SockRef, Backlog). +%% =========================================================================== +%% %% accept, accept4 - accept a connection on a socket +%% -spec accept(LSocket, Timeout) -> {ok, Socket} | {error, Reason} when LSocket :: socket(), @@ -682,16 +698,6 @@ enc_protocol(seqpacket, sctp) -> ?SOCKET_PROTOCOL_SCTP; enc_protocol(Type, Proto) -> throw({error, {invalid_protocol, {Type, Proto}}}). --spec enc_backlog(Backlog) -> non_neg_integer() when - Backlog :: non_neg_integer() | boolean(). - -enc_backlog(true) -> - ?SOCKET_LISTEN_BACKLOG_DEFAULT; -enc_backlog(false) -> - 0; -enc_backlog(Backlog) when is_integer(Backlog) andalso (Backlog >= 0) -> - Backlog. - -spec enc_accept_flags(Flags) -> non_neg_integer() when Flags :: accept_flags(). |