Commit 1f94b48f authored by Jan Včelák's avatar Jan Včelák 🚀

net: change API to accept timeout in miliseconds

We now internally use poll(), which uses this timeout format.
parent 674ef1db
......@@ -305,16 +305,14 @@ int net_accept(int sock, struct sockaddr_storage *addr)
/*!
* \brief Perform \a poll() on one socket.
*/
static int poll_one(int fd, int events, const struct timeval *tv_timeout)
static int poll_one(int fd, int events, int timeout_ms)
{
struct pollfd pfd = {
.fd = fd,
.events = events
};
int timeout = tv_timeout ? (tv_timeout->tv_sec * 1000) : -1;
return poll(&pfd, 1, timeout);
return poll(&pfd, 1, timeout_ms);
}
/*!
......@@ -344,7 +342,7 @@ static bool io_should_wait(int error)
*/
struct io {
ssize_t (*process)(int sockfd, struct msghdr *msg);
int (*wait)(int sockfd, struct timeval *timeout);
int (*wait)(int sockfd, int timeout_ms);
};
/*!
......@@ -391,7 +389,7 @@ static void msg_iov_shift(struct msghdr *msg, size_t done)
*
*/
static ssize_t io_exec(const struct io *io, int fd, struct msghdr *msg,
bool oneshot, struct timeval *timeout)
bool oneshot, int timeout_ms)
{
size_t done = 0;
size_t total = msg_iov_len(msg);
......@@ -413,7 +411,7 @@ static ssize_t io_exec(const struct io *io, int fd, struct msghdr *msg,
/* Wait for data readiness. */
if (ret > 0 || (ret == -1 && io_should_wait(errno))) {
do {
ret = io->wait(fd, timeout);
ret = io->wait(fd, timeout_ms);
} while (ret == -1 && errno == EINTR);
if (ret == 1) {
continue;
......@@ -434,19 +432,19 @@ static ssize_t recv_process(int fd, struct msghdr *msg)
return recvmsg(fd, msg, MSG_DONTWAIT | MSG_NOSIGNAL);
}
static int recv_wait(int fd, struct timeval *timeout)
static int recv_wait(int fd, int timeout_ms)
{
return poll_one(fd, POLLIN, timeout);
return poll_one(fd, POLLIN, timeout_ms);
}
static ssize_t recv_data(int sock, struct msghdr *msg, bool oneshot, struct timeval *timeout)
static ssize_t recv_data(int sock, struct msghdr *msg, bool oneshot, int timeout_ms)
{
static const struct io RECV_IO = {
.process = recv_process,
.wait = recv_wait
};
return io_exec(&RECV_IO, sock, msg, oneshot, timeout);
return io_exec(&RECV_IO, sock, msg, oneshot, timeout_ms);
}
static ssize_t send_process(int fd, struct msghdr *msg)
......@@ -454,25 +452,25 @@ static ssize_t send_process(int fd, struct msghdr *msg)
return sendmsg(fd, msg, MSG_NOSIGNAL);
}
static int send_wait(int fd, struct timeval *timeout)
static int send_wait(int fd, int timeout_ms)
{
return poll_one(fd, POLLOUT, timeout);
return poll_one(fd, POLLOUT, timeout_ms);
}
static ssize_t send_data(int sock, struct msghdr *msg, struct timeval *timeout)
static ssize_t send_data(int sock, struct msghdr *msg, int timeout_ms)
{
static const struct io SEND_IO = {
.process = send_process,
.wait = send_wait
};
return io_exec(&SEND_IO, sock, msg, false, timeout);
return io_exec(&SEND_IO, sock, msg, false, timeout_ms);
}
/* -- generic stream and datagram I/O -------------------------------------- */
ssize_t net_send(int sock, const uint8_t *buffer, size_t size,
const struct sockaddr_storage *addr, struct timeval *timeout)
const struct sockaddr_storage *addr, int timeout_ms)
{
if (sock < 0 || buffer == NULL) {
return KNOT_EINVAL;
......@@ -488,7 +486,7 @@ ssize_t net_send(int sock, const uint8_t *buffer, size_t size,
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
int ret = send_data(sock, &msg, timeout);
int ret = send_data(sock, &msg, timeout_ms);
if (ret < 0) {
return ret;
} else if (ret != size) {
......@@ -499,7 +497,7 @@ ssize_t net_send(int sock, const uint8_t *buffer, size_t size,
}
ssize_t net_recv(int sock, uint8_t *buffer, size_t size,
struct sockaddr_storage *addr, struct timeval *timeout)
struct sockaddr_storage *addr, int timeout_ms)
{
if (sock < 0 || buffer == NULL) {
return KNOT_EINVAL;
......@@ -515,33 +513,33 @@ ssize_t net_recv(int sock, uint8_t *buffer, size_t size,
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
return recv_data(sock, &msg, true, timeout);
return recv_data(sock, &msg, true, timeout_ms);
}
ssize_t net_dgram_send(int sock, const uint8_t *buffer, size_t size,
const struct sockaddr_storage *addr)
{
return net_send(sock, buffer, size, addr, NULL);
return net_send(sock, buffer, size, addr, 0);
}
ssize_t net_dgram_recv(int sock, uint8_t *buffer, size_t size, struct timeval *timeout)
ssize_t net_dgram_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms)
{
return net_recv(sock, buffer, size, NULL, timeout);
return net_recv(sock, buffer, size, NULL, timeout_ms);
}
ssize_t net_stream_send(int sock, const uint8_t *buffer, size_t size, struct timeval *timeout)
ssize_t net_stream_send(int sock, const uint8_t *buffer, size_t size, int timeout_ms)
{
return net_send(sock, buffer, size, NULL, timeout);
return net_send(sock, buffer, size, NULL, timeout_ms);
}
ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size, struct timeval *timeout)
ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms)
{
return net_recv(sock, buffer, size, NULL, timeout);
return net_recv(sock, buffer, size, NULL, timeout_ms);
}
/* -- DNS specific I/O ----------------------------------------------------- */
ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, struct timeval *timeout)
ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, int timeout_ms)
{
if (sock < 0 || buffer == NULL || size > UINT16_MAX) {
return KNOT_EINVAL;
......@@ -558,7 +556,7 @@ ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, struct ti
msg.msg_iov = iov;
msg.msg_iovlen = 2;
ssize_t ret = send_data(sock, &msg, timeout);
ssize_t ret = send_data(sock, &msg, timeout_ms);
if (ret < 0) {
return ret;
}
......@@ -566,7 +564,7 @@ ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, struct ti
return size; /* Do not count the size prefix. */
}
ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, struct timeval *timeout)
ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms)
{
if (sock < 0 || buffer == NULL) {
return KNOT_EINVAL;
......@@ -581,7 +579,7 @@ ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, struct timeval
uint16_t pktsize = 0;
iov.iov_base = &pktsize;
iov.iov_len = sizeof(pktsize);
int ret = recv_data(sock, &msg, false, timeout);
int ret = recv_data(sock, &msg, false, timeout_ms);
if (ret != sizeof(pktsize)) {
return ret;
}
......@@ -598,5 +596,5 @@ ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, struct timeval
msg.msg_iovlen = 1;
iov.iov_base = buffer;
iov.iov_len = pktsize;
return recv_data(sock, &msg, false, timeout);
return recv_data(sock, &msg, false, timeout_ms);
}
......@@ -19,7 +19,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/time.h>
/*!
* \brief Network interface flags.
......@@ -109,30 +108,31 @@ int net_accept(int sock, struct sockaddr_storage *addr);
*
* The implementation handles partial-writes automatically.
*
* \param[in] sock Socket.
* \param[in] buffer Message buffer.
* \param[in] size Size of the message.
* \param[in] addr Remote address (ignored for SOCK_STREAM).
* \param[in,out] timeout Write timeout (ignored for SOCK_DGRAM).
* \param[in] sock Socket.
* \param[in] buffer Message buffer.
* \param[in] size Size of the message.
* \param[in] addr Remote address (ignored for SOCK_STREAM).
* \param[in] timeout_ms Write timeout in miliseconds (-1 for infinity,
* not valid for SOCK_DGRAM).
*
* \return Number of bytes sent or negative error code.
*/
ssize_t net_send(int sock, const uint8_t *buffer, size_t size,
const struct sockaddr_storage *addr, struct timeval *timeout);
const struct sockaddr_storage *addr, int timeout_ms);
/*!
* \brief Receive a message from a socket.
*
* \param[in] sock Socket.
* \param[out] buffer Receiving buffer.
* \param[in] size Capacity of the receiving buffer.
* \param[out] addr Remote address (can be NULL).
* \param[in,out] timeout Read timeout.
* \param[in] sock Socket.
* \param[out] buffer Receiving buffer.
* \param[in] size Capacity of the receiving buffer.
* \param[out] addr Remote address (can be NULL).
* \param[in] timeout_ms Read timeout in miliseconds (-1 for infinity).
*
* \return Number of bytes read or negative error code.
*/
ssize_t net_recv(int sock, uint8_t *buffer, size_t size,
struct sockaddr_storage *addr, struct timeval *timeout);
struct sockaddr_storage *addr, int timeout_ms);
/*!
* \brief Send a message on a SOCK_DGRAM socket.
......@@ -147,24 +147,21 @@ ssize_t net_dgram_send(int sock, const uint8_t *buffer, size_t size,
*
* \see net_recv
*/
ssize_t net_dgram_recv(int sock, uint8_t *buffer, size_t size,
struct timeval *timeout);
ssize_t net_dgram_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms);
/*!
* \brief Send a message on a SOCK_STREAM socket.
*
* \see net_send
*/
ssize_t net_stream_send(int sock, const uint8_t *buffer, size_t size,
struct timeval *timeout);
ssize_t net_stream_send(int sock, const uint8_t *buffer, size_t size, int timeout_ms);
/*!
* \brief Receive a message from a SOCK_STREAM socket.
*
* \see net_recv
*/
ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size,
struct timeval *timeout);
ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms);
/*!
* \brief Send a DNS message on a TCP socket.
......@@ -175,8 +172,7 @@ ssize_t net_stream_recv(int sock, uint8_t *buffer, size_t size,
*
* \see net_send
*/
ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size,
struct timeval *timeout);
ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size, int timeout_ms);
/*!
* \brief Receive a DNS message from a TCP socket.
......@@ -187,5 +183,4 @@ ssize_t net_dns_tcp_send(int sock, const uint8_t *buffer, size_t size,
*
* \see net_recv
*/
ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size,
struct timeval *timeout);
ssize_t net_dns_tcp_recv(int sock, uint8_t *buffer, size_t size, int timeout_ms);
......@@ -18,11 +18,11 @@
#include <assert.h>
#include <fcntl.h>
#include <poll.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include "libknot/errcode.h"
#include "contrib/net.h"
......@@ -31,8 +31,8 @@
#undef ENABLE_NET_UNREACHABLE_TEST
//#define ENABLE_NET_UNREACHABLE_TEST
const struct timeval TIMEOUT = { 5, 0 };
const struct timeval TIMEOUT_SHORT = { 0, 500000 };
const int TIMEOUT = 5000;
const int TIMEOUT_SHORT = 500;
/*!
* \brief Get loopback socket address with unset port.
......@@ -112,14 +112,10 @@ struct server_ctx {
pthread_mutex_t mx;
};
static int select_read(int sock)
static int poll_read(int sock)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(sock, &fds);
struct timeval tv = TIMEOUT;
return select(sock + 1, &fds, NULL, NULL, &tv);
struct pollfd pfd = { .fd = sock, .events = POLLIN };
return poll(&pfd, 1, TIMEOUT);
}
static void server_handle(server_ctx_t *ctx)
......@@ -162,7 +158,7 @@ static void *server_main(void *_ctx)
break;
}
int r = select_read(ctx->sock);
int r = poll_read(ctx->sock);
if (r == -1) {
if (errno == EINTR) {
continue;
......@@ -219,14 +215,12 @@ static void handler_echo(int sock, void *_server)
addr = &remote;
}
struct timeval tv = TIMEOUT;
int in = net_recv(sock, buffer, sizeof(buffer), addr, &tv);
int in = net_recv(sock, buffer, sizeof(buffer), addr, TIMEOUT);
if (in <= 0) {
return;
}
tv = TIMEOUT;
net_send(sock, buffer, in, addr, &tv);
net_send(sock, buffer, in, addr, TIMEOUT);
}
static void test_connected_one(const struct sockaddr_storage *server_addr,
......@@ -234,7 +228,6 @@ static void test_connected_one(const struct sockaddr_storage *server_addr,
int type, const char *name, const char *addr_name)
{
int r;
struct timeval tv;
int client = net_connected_socket(type, server_addr, NULL);
ok(client >= 0, "%s, %s: client, create connected socket", name, addr_name);
......@@ -242,8 +235,7 @@ static void test_connected_one(const struct sockaddr_storage *server_addr,
const uint8_t out[] = "test message";
const size_t out_len = sizeof(out);
if (socktype_is_stream(type)) {
tv = TIMEOUT;
r = net_stream_send(client, out, out_len, &tv);
r = net_stream_send(client, out, out_len, TIMEOUT);
} else {
r = net_dgram_send(client, out, out_len, NULL);
}
......@@ -253,11 +245,10 @@ static void test_connected_one(const struct sockaddr_storage *server_addr,
ok(r, "%s, %s: client, is connected", name, addr_name);
uint8_t in[128] = { 0 };
tv = TIMEOUT;
if (socktype_is_stream(type)) {
r = net_stream_recv(client, in, sizeof(in), &tv);
r = net_stream_recv(client, in, sizeof(in), TIMEOUT);
} else {
r = net_dgram_recv(client, in, sizeof(in), &tv);
r = net_dgram_recv(client, in, sizeof(in), TIMEOUT);
}
ok(r == out_len && memcmp(out, in, out_len) == 0,
"%s, %s: client, receive message", name, addr_name);
......@@ -310,7 +301,6 @@ static void test_unconnected(void)
int r = 0;
int sock = -1;
const struct sockaddr_storage local = addr_local();
struct timeval tv = { 0 };
uint8_t buffer[] = { 'k', 'n', 'o', 't' };
ssize_t buffer_len = sizeof(buffer);
......@@ -334,8 +324,7 @@ static void test_unconnected(void)
r = net_dgram_send(sock, buffer, buffer_len, NULL);
ok(r == KNOT_ECONN, "UDP, send failure on unconnected socket");
tv = TIMEOUT_SHORT;
r = net_dgram_recv(sock, buffer, buffer_len, &tv);
r = net_dgram_recv(sock, buffer, buffer_len, TIMEOUT_SHORT);
ok(r == KNOT_ETIMEOUT, "UDP, receive timeout on unconnected socket");
struct sockaddr_storage server_addr = addr_from_socket(server);
......@@ -354,19 +343,17 @@ static void test_unconnected(void)
#ifdef __linux__
const int expected = KNOT_ECONN;
const char *expected_msg = "failure";
const struct timeval expected_tv = TIMEOUT;
const int expected_timeout = TIMEOUT;
#else
const int expected = KNOT_ETIMEOUT;
const char *expected_msg = "timeout";
const struct timeval expected_tv = TIMEOUT_SHORT;
const int expected_timeout = TIMEOUT_SHORT;
#endif
tv = expected_tv;
r = net_stream_send(sock, buffer, buffer_len, &tv);
r = net_stream_send(sock, buffer, buffer_len, expected_timeout);
ok(r == expected, "TCP, send %s on unconnected socket", expected_msg);
tv = expected_tv;
r = net_stream_recv(sock, buffer, sizeof(buffer), &tv);
r = net_stream_recv(sock, buffer, sizeof(buffer), expected_timeout);
ok(r == expected, "TCP, receive %s on unconnected socket", expected_msg);
close(sock);
......@@ -382,7 +369,6 @@ static void test_refused(void)
int r = -1;
struct sockaddr_storage addr = { 0 };
struct timeval tv = { 0 };
uint8_t buffer[1] = { 0 };
int server, client;
......@@ -423,12 +409,10 @@ static void test_refused(void)
client = net_connected_socket(SOCK_STREAM, &addr, NULL);
ok(client >= 0, "client, connect");
tv = TIMEOUT;
r = net_stream_send(client, (uint8_t *)"", 1, &tv);
r = net_stream_send(client, (uint8_t *)"", 1, TIMEOUT);
ok(r == 1, "client, successful write");
tv = TIMEOUT_SHORT;
r = net_stream_recv(client, buffer, sizeof(buffer), &tv);
r = net_stream_recv(client, buffer, sizeof(buffer), TIMEOUT_SHORT);
ok(r == KNOT_ETIMEOUT, "client, timeout on read");
close(client);
......@@ -441,8 +425,7 @@ static void test_refused(void)
r = close(server);
ok(r == 0, "server, close socket");
tv = TIMEOUT;
r = net_stream_send(client, (uint8_t *)"", 1, &tv);
r = net_stream_send(client, (uint8_t *)"", 1, TIMEOUT);
ok(r == KNOT_ECONN, "client, refused on write");
close(client);
......@@ -458,12 +441,11 @@ struct dns_handler_ctx {
static void _sync(int remote, int send)
{
uint8_t buf[1] = { 0 };
struct timeval tv = TIMEOUT;
int r;
if (send) {
r = net_stream_send(remote, buf, sizeof(buf), &tv);
r = net_stream_send(remote, buf, sizeof(buf), TIMEOUT);
} else {
r = net_stream_recv(remote, buf, sizeof(buf), &tv);
r = net_stream_recv(remote, buf, sizeof(buf), TIMEOUT);
}
assert(r == sizeof(buf));
......@@ -483,16 +465,15 @@ static void handler_dns(int sock, void *_ctx)
{
struct dns_handler_ctx *ctx = _ctx;
struct timeval tv = TIMEOUT;
uint8_t in[16] = { 0 };
int in_len = 0;
sync_signal(sock);
if (ctx->raw) {
in_len = net_stream_recv(sock, in, sizeof(in), &tv);
in_len = net_stream_recv(sock, in, sizeof(in), TIMEOUT);
} else {
in_len = net_dns_tcp_recv(sock, in, sizeof(in), &tv);
in_len = net_dns_tcp_recv(sock, in, sizeof(in), TIMEOUT);
}
ctx->success = in_len == ctx->len &&
......@@ -501,8 +482,7 @@ static void handler_dns(int sock, void *_ctx)
static void dns_send_hello(int sock)
{
struct timeval tv = TIMEOUT;
net_dns_tcp_send(sock, (uint8_t *)"wimbgunts", 9, &tv);
net_dns_tcp_send(sock, (uint8_t *)"wimbgunts", 9, TIMEOUT);
}
static void dns_send_fragmented(int sock)
......@@ -517,21 +497,18 @@ static void dns_send_fragmented(int sock)
};
for (const struct fragment *f = fragments; f->len > 0; f++) {
struct timeval tv = TIMEOUT;
net_stream_send(sock, f->data, f->len, &tv);
net_stream_send(sock, f->data, f->len, TIMEOUT);
}
}
static void dns_send_incomplete(int sock)
{
struct timeval tv = TIMEOUT;
net_stream_send(sock, (uint8_t *)"\x00\x08""korm", 6, &tv);
net_stream_send(sock, (uint8_t *)"\x00\x08""korm", 6, TIMEOUT);
}
static void dns_send_trailing(int sock)
{
struct timeval tv = TIMEOUT;
net_stream_send(sock, (uint8_t *)"\x00\x05""bloitxx", 9, &tv);
net_stream_send(sock, (uint8_t *)"\x00\x05""bloitxx", 9, TIMEOUT);
}
static void test_dns_tcp(void)
......@@ -645,7 +622,7 @@ static void test_nonblocking_accept(void)
// accept connection
r = select_read(server);
r = poll_read(server);
ok(r == 1, "server, pending connection");
struct sockaddr_storage addr_accepted = { 0 };
......@@ -664,7 +641,7 @@ static void test_nonblocking_accept(void)
client = net_connected_socket(SOCK_STREAM, &addr_server, NULL);
ok(client >= 0, "client, reconnect");
r = select_read(server);
r = poll_read(server);
ok(r == 1, "server, pending connection");
accepted = net_accept(server, NULL);
......
......@@ -20,6 +20,7 @@
#include <stdint.h>
#include <string.h>
#include <pthread.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/socket.h>
......@@ -29,7 +30,7 @@
#include "contrib/net.h"
#include "contrib/sockaddr.h"
const struct timeval TIMEOUT = { .tv_sec = 2 };
const int TIMEOUT = 2000;
static struct sockaddr_storage localhost(void)
{
......@@ -55,14 +56,8 @@ static void *thr_receive(void *data)
{
struct data *d = data;
struct timeval timeout = { 0 };
fd_set fds;
FD_ZERO(&fds);
FD_SET(d->server_fd, &fds);
timeout = TIMEOUT;
int r = select(d->server_fd + 1, &fds, NULL, NULL, &timeout);
struct pollfd pfd = { .fd = d->server_fd, .events = POLLIN };
int r = poll(&pfd, 1, TIMEOUT);
if (r != 1) {
d->result = KNOT_ETIMEOUT;
return NULL;
......@@ -74,8 +69,7 @@ static void *thr_receive(void *data)
return NULL;
}
timeout = TIMEOUT;
d->result = net_dns_tcp_recv(client, d->buffer, d->size, &timeout);
d->result = net_dns_tcp_recv(client, d->buffer, d->size, TIMEOUT);
close(client);
......@@ -131,8 +125,7 @@ int main(int argc, char *argv[])
for (size_t i = 0; i < sizeof(sndbuf); i++) {
sndbuf[i] = i;
}
struct timeval timeout = TIMEOUT;
r = net_dns_tcp_send(client, sndbuf, sizeof(sndbuf), &timeout);
r = net_dns_tcp_send(client, sndbuf, sizeof(sndbuf), TIMEOUT);
ok(r == sizeof(sndbuf), "client: net_dns_tcp_send() with short-write");
// receive message
......
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