Skip to content
Snippets Groups Projects
Commit dc28e265 authored by Martine Lenders's avatar Martine Lenders Committed by GitHub
Browse files

Merge pull request #6771 from francois-berder-imgtec/rcv-timeout

posix: sockets: Implement SO_RCVTIMEO option in setsockopt
parents cc151522 c7876386
Branches
No related tags found
No related merge requests found
......@@ -491,16 +491,8 @@ static inline int getsockopt(int socket, int level, int option_name, void *optio
return -1;
}
static inline int setsockopt(int socket, int level, int option_name, const void *option_value,
socklen_t option_len)
{
(void)socket;
(void)level;
(void)option_name;
(void)option_value;
(void)option_len;
return -1;
}
int setsockopt(int socket, int level, int option_name, const void *option_value,
socklen_t option_len);
/** @} */
......
......@@ -68,6 +68,9 @@ typedef struct {
int type;
int protocol;
bool bound;
#ifdef POSIX_SETSOCKOPT
uint32_t recv_timeout;
#endif
socket_sock_t *sock;
#ifdef MODULE_SOCK_TCP
sock_tcp_t *queue_array;
......@@ -323,6 +326,9 @@ int socket(int domain, int type, int protocol)
}
s->bound = false;
s->sock = NULL;
#ifdef POSIX_SETSOCKOPT
s->recv_timeout = SOCK_NO_TIMEOUT;
#endif
#ifdef MODULE_SOCK_TCP
if (type == SOCK_STREAM) {
s->queue_array = NULL;
......@@ -363,6 +369,13 @@ int accept(int socket, struct sockaddr *restrict address,
errno = EINVAL;
return -1;
}
#ifdef POSIX_SETSOCKOPT
const uint32_t recv_timeout = s->recv_timeout;
#else
const uint32_t recv_timeout = SOCK_NO_TIMEOUT;
#endif
switch (s->type) {
case SOCK_STREAM:
new_s = _get_free_socket();
......@@ -372,9 +385,8 @@ int accept(int socket, struct sockaddr *restrict address,
res = -1;
break;
}
/* TODO: apply configured timeout */
if ((res = sock_tcp_accept(&s->sock->tcp.queue, &sock,
SOCK_NO_TIMEOUT)) < 0) {
recv_timeout)) < 0) {
errno = -res;
res = -1;
break;
......@@ -789,11 +801,17 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
return res;
}
}
#ifdef POSIX_SETSOCKOPT
const uint32_t recv_timeout = s->recv_timeout;
#else
const uint32_t recv_timeout = SOCK_NO_TIMEOUT;
#endif
switch (s->type) {
#ifdef MODULE_SOCK_IP
case SOCK_RAW:
/* TODO: apply configured timeout */
if ((res = sock_ip_recv(&s->sock->raw, buffer, length, SOCK_NO_TIMEOUT,
if ((res = sock_ip_recv(&s->sock->raw, buffer, length, recv_timeout
(sock_ip_ep_t *)&ep)) < 0) {
errno = -res;
res = -1;
......@@ -802,9 +820,8 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
#endif
#ifdef MODULE_SOCK_TCP
case SOCK_STREAM:
/* TODO: apply configured timeout */
if ((res = sock_tcp_read(&s->sock->tcp.sock, buffer, length,
SOCK_NO_TIMEOUT)) < 0) {
recv_timeout)) < 0) {
errno = -res;
res = -1;
}
......@@ -812,8 +829,7 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
#endif
#ifdef MODULE_SOCK_UDP
case SOCK_DGRAM:
/* TODO: apply configured timeout */
if ((res = sock_udp_recv(&s->sock->udp, buffer, length, SOCK_NO_TIMEOUT,
if ((res = sock_udp_recv(&s->sock->udp, buffer, length, recv_timeout,
&ep)) < 0) {
errno = -res;
res = -1;
......@@ -920,6 +936,62 @@ ssize_t sendto(int socket, const void *buffer, size_t length, int flags,
return res;
}
/*
* This is a partial implementation of setsockopt for changing the receive
* timeout value of a socket.
*/
int setsockopt(int socket, int level, int option_name, const void *option_value,
socklen_t option_len)
{
#ifdef POSIX_SETSOCKOPT
socket_t *s;
struct timeval *tv;
const uint32_t max_timeout_secs = UINT32_MAX / (1000 * 1000);
if (level != SOL_SOCKET
|| option_name != SO_RCVTIMEO) {
errno = ENOTSUP;
return -1;
}
if (option_value == NULL
|| option_len != sizeof(struct timeval)) {
errno = EINVAL;
return -1;
}
mutex_lock(&_socket_pool_mutex);
s = _get_socket(socket);
mutex_unlock(&_socket_pool_mutex);
if (s == NULL) {
errno = ENOTSOCK;
return -1;
}
tv = (struct timeval *) option_value;
if (tv->tv_sec < 0 || tv->tv_usec < 0) {
errno = EINVAL;
return -1;
}
if ((uint32_t)tv->tv_sec > max_timeout_secs
|| ((uint32_t)tv->tv_sec == max_timeout_secs && (uint32_t)tv->tv_usec > UINT32_MAX - max_timeout_secs * 1000 * 1000)) {
errno = EDOM;
return -1;
}
s->recv_timeout = tv->tv_sec * 1000 * 1000 + tv->tv_usec;
return 0;
#else
(void)socket;
(void)level;
(void)option_name;
(void)option_value;
(void)option_len;
return -1;
#endif
}
/**
* @}
*/
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment