Commit 45e86ae4 authored by Jan Včelák's avatar Jan Včelák 🚀

net: add net_accept() function

parent aaf4e5c6
......@@ -465,7 +465,7 @@ AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
# Checks for library functions.
AC_CHECK_FUNCS([clock_gettime gettimeofday fgetln getline madvise malloc_trim poll posix_memalign pthread_setaffinity_np regcomp select setgroups strlcat strlcpy initgroups])
AC_CHECK_FUNCS([clock_gettime gettimeofday fgetln getline madvise malloc_trim poll posix_memalign pthread_setaffinity_np regcomp select setgroups strlcat strlcpy initgroups accept4])
# Check for be64toh function
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <endian.h>]], [[return be64toh(0);]])],
......
......@@ -234,6 +234,30 @@ bool net_is_connected(int sock)
return (getpeername(sock, (struct sockaddr *)&ss, &len) == 0);
}
int net_accept(int sock, struct sockaddr_storage *addr)
{
struct sockaddr *sa = (struct sockaddr *)addr;
socklen_t sa_len = sizeof(*addr);
int remote = -1;
#if defined(HAVE_ACCEPT4) && defined(SOCK_NONBLOCK)
remote = accept4(sock, sa, &sa_len, SOCK_NONBLOCK);
if (remote < 0) {
return knot_map_errno();
}
#else
remote = accept(sock, sa, &sa_len);
if (fcntl(remote, F_SETFL, O_NONBLOCK) != 0) {
int error = knot_map_errno();
close(remote);
return error;
}
#endif
return remote;
}
/* -- I/O interface handling partial -------------------------------------- */
static int select_read(int fd, struct timeval *timeout)
......
......@@ -79,6 +79,18 @@ int net_connected_socket(int type, const struct sockaddr_storage *dst_addr,
*/
bool net_is_connected(int sock);
/*!
* \brief Accept a connection on a listening socket.
*
* \brief The socket is set to non-blocking mode.
*
* \param sock Socket
* \param addr Remote address (can be NULL).
*
* \return socket or error code
*/
int net_accept(int sock, struct sockaddr_storage *addr);
/*!
* \brief Send a message on a socket.
*
......
......@@ -573,6 +573,64 @@ static void test_nonblocking_mode(int type)
close(server);
}
static void test_nonblocking_accept(void)
{
int r;
// create server
struct sockaddr_storage addr_server = addr_local();
int server = net_bound_socket(SOCK_STREAM, &addr_server, 0);
ok(server >= 0, "server, create socket");
r = listen(server, LISTEN_BACKLOG);
ok(r == 0, "server, start listening");
addr_server = addr_from_socket(server);
// create client
int client = net_connected_socket(SOCK_STREAM, &addr_server, NULL);
ok(client >= 0, "client, create connected socket");
struct sockaddr_storage addr_client = addr_from_socket(client);
// accept connection
r = select_read(server);
ok(r == 1, "server, pending connection");
struct sockaddr_storage addr_accepted = { 0 };
int accepted = net_accept(server, &addr_accepted);
ok(accepted >= 0, "server, accept connection");
ok(!socket_is_blocking(accepted), "accepted, nonblocking mode");
ok(sockaddr_cmp(&addr_client, &addr_accepted) == 0, "accepted, correct address");
close(client);
// client reconnect
close(client);
client = net_connected_socket(SOCK_STREAM, &addr_server, NULL);
ok(client >= 0, "client, reconnect");
r = select_read(server);
ok(r == 1, "server, pending connection");
accepted = net_accept(server, NULL);
ok(accepted >= 0, "server, accept connection");
ok(!socket_is_blocking(accepted), "accepted, nonblocking mode");
// cleanup
close(client);
close(server);
}
static void test_bind_multiple(void)
{
const struct sockaddr_storage addr = addr_local();
......@@ -616,6 +674,7 @@ int main(int argc, char *argv[])
diag("nonblocking mode");
test_nonblocking_mode(SOCK_DGRAM);
test_nonblocking_mode(SOCK_STREAM);
test_nonblocking_accept();
diag("connected sockets");
test_connected(SOCK_DGRAM);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment