Merge pull request #6771 from francois-berder-imgtec/rcv-timeout
posix: sockets: Implement SO_RCVTIMEO option in setsockopt
This commit is contained in:
commit
dc28e265cd
@ -491,16 +491,8 @@ static inline int getsockopt(int socket, int level, int option_name, void *optio
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int setsockopt(int socket, int level, int option_name, const void *option_value,
|
int setsockopt(int socket, int level, int option_name, const void *option_value,
|
||||||
socklen_t option_len)
|
socklen_t option_len);
|
||||||
{
|
|
||||||
(void)socket;
|
|
||||||
(void)level;
|
|
||||||
(void)option_name;
|
|
||||||
(void)option_value;
|
|
||||||
(void)option_len;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|||||||
@ -68,6 +68,9 @@ typedef struct {
|
|||||||
int type;
|
int type;
|
||||||
int protocol;
|
int protocol;
|
||||||
bool bound;
|
bool bound;
|
||||||
|
#ifdef POSIX_SETSOCKOPT
|
||||||
|
uint32_t recv_timeout;
|
||||||
|
#endif
|
||||||
socket_sock_t *sock;
|
socket_sock_t *sock;
|
||||||
#ifdef MODULE_SOCK_TCP
|
#ifdef MODULE_SOCK_TCP
|
||||||
sock_tcp_t *queue_array;
|
sock_tcp_t *queue_array;
|
||||||
@ -323,6 +326,9 @@ int socket(int domain, int type, int protocol)
|
|||||||
}
|
}
|
||||||
s->bound = false;
|
s->bound = false;
|
||||||
s->sock = NULL;
|
s->sock = NULL;
|
||||||
|
#ifdef POSIX_SETSOCKOPT
|
||||||
|
s->recv_timeout = SOCK_NO_TIMEOUT;
|
||||||
|
#endif
|
||||||
#ifdef MODULE_SOCK_TCP
|
#ifdef MODULE_SOCK_TCP
|
||||||
if (type == SOCK_STREAM) {
|
if (type == SOCK_STREAM) {
|
||||||
s->queue_array = NULL;
|
s->queue_array = NULL;
|
||||||
@ -363,6 +369,13 @@ int accept(int socket, struct sockaddr *restrict address,
|
|||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
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) {
|
switch (s->type) {
|
||||||
case SOCK_STREAM:
|
case SOCK_STREAM:
|
||||||
new_s = _get_free_socket();
|
new_s = _get_free_socket();
|
||||||
@ -372,9 +385,8 @@ int accept(int socket, struct sockaddr *restrict address,
|
|||||||
res = -1;
|
res = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* TODO: apply configured timeout */
|
|
||||||
if ((res = sock_tcp_accept(&s->sock->tcp.queue, &sock,
|
if ((res = sock_tcp_accept(&s->sock->tcp.queue, &sock,
|
||||||
SOCK_NO_TIMEOUT)) < 0) {
|
recv_timeout)) < 0) {
|
||||||
errno = -res;
|
errno = -res;
|
||||||
res = -1;
|
res = -1;
|
||||||
break;
|
break;
|
||||||
@ -789,11 +801,17 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
|
|||||||
return res;
|
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) {
|
switch (s->type) {
|
||||||
#ifdef MODULE_SOCK_IP
|
#ifdef MODULE_SOCK_IP
|
||||||
case SOCK_RAW:
|
case SOCK_RAW:
|
||||||
/* TODO: apply configured timeout */
|
if ((res = sock_ip_recv(&s->sock->raw, buffer, length, recv_timeout
|
||||||
if ((res = sock_ip_recv(&s->sock->raw, buffer, length, SOCK_NO_TIMEOUT,
|
|
||||||
(sock_ip_ep_t *)&ep)) < 0) {
|
(sock_ip_ep_t *)&ep)) < 0) {
|
||||||
errno = -res;
|
errno = -res;
|
||||||
res = -1;
|
res = -1;
|
||||||
@ -802,9 +820,8 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef MODULE_SOCK_TCP
|
#ifdef MODULE_SOCK_TCP
|
||||||
case SOCK_STREAM:
|
case SOCK_STREAM:
|
||||||
/* TODO: apply configured timeout */
|
|
||||||
if ((res = sock_tcp_read(&s->sock->tcp.sock, buffer, length,
|
if ((res = sock_tcp_read(&s->sock->tcp.sock, buffer, length,
|
||||||
SOCK_NO_TIMEOUT)) < 0) {
|
recv_timeout)) < 0) {
|
||||||
errno = -res;
|
errno = -res;
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
@ -812,8 +829,7 @@ ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef MODULE_SOCK_UDP
|
#ifdef MODULE_SOCK_UDP
|
||||||
case SOCK_DGRAM:
|
case SOCK_DGRAM:
|
||||||
/* TODO: apply configured timeout */
|
if ((res = sock_udp_recv(&s->sock->udp, buffer, length, recv_timeout,
|
||||||
if ((res = sock_udp_recv(&s->sock->udp, buffer, length, SOCK_NO_TIMEOUT,
|
|
||||||
&ep)) < 0) {
|
&ep)) < 0) {
|
||||||
errno = -res;
|
errno = -res;
|
||||||
res = -1;
|
res = -1;
|
||||||
@ -920,6 +936,62 @@ ssize_t sendto(int socket, const void *buffer, size_t length, int flags,
|
|||||||
return res;
|
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
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user