mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-02 07:28:21 +00:00
localsocket: implement SO_RCVTIMEO and SO_SNDTIMEO
This commit is contained in:
@@ -120,6 +120,8 @@ typedef struct {
|
|||||||
#define SO_PEERCRED 17
|
#define SO_PEERCRED 17
|
||||||
#define SO_RCVLOWAT 18
|
#define SO_RCVLOWAT 18
|
||||||
#define SO_SNDLOWAT 19
|
#define SO_SNDLOWAT 19
|
||||||
|
#define SO_RCVTIMEO 20
|
||||||
|
#define SO_SNDTIMEO 21
|
||||||
#define SO_BINDTODEVICE 25
|
#define SO_BINDTODEVICE 25
|
||||||
#define SO_ACCEPTCONN 30
|
#define SO_ACCEPTCONN 30
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
typedef long time_t;
|
typedef long time_t;
|
||||||
typedef long suseconds_t;
|
typedef long suseconds_t;
|
||||||
@@ -65,4 +66,19 @@ static inline timeval_t timespec_to_timeval(timespec_t ts) {
|
|||||||
return tv;
|
return tv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int timeval_to_us(timeval_t *tv, time_t *timeout_us) {
|
||||||
|
if (tv->s < 0 || tv->us < 0 || tv->us >= 1000000)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
*timeout_us = tv->s * 1000000 + tv->us;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline timeval_t timeval_from_us(time_t timeout_us) {
|
||||||
|
return (timeval_t) {
|
||||||
|
.s = timeout_us / 1000000,
|
||||||
|
.us = timeout_us % 1000000
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <ringbuffer.h>
|
#include <ringbuffer.h>
|
||||||
#include <kernel/vfs.h>
|
#include <kernel/vfs.h>
|
||||||
#include <kernel/file.h>
|
#include <kernel/file.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#define SOCKET_BUFFER (256 * 1024)
|
#define SOCKET_BUFFER (256 * 1024)
|
||||||
#define FILE_COUNT 256
|
#define FILE_COUNT 256
|
||||||
@@ -35,6 +36,8 @@ typedef struct {
|
|||||||
uintmax_t barrierwrite; // shared with pair
|
uintmax_t barrierwrite; // shared with pair
|
||||||
int filesremaining[BARRIER_SIZE]; // shared with pair
|
int filesremaining[BARRIER_SIZE]; // shared with pair
|
||||||
int bytesremaining[BARRIER_SIZE]; // shared with pair
|
int bytesremaining[BARRIER_SIZE]; // shared with pair
|
||||||
|
time_t rcv_timeout_us;
|
||||||
|
time_t snd_timeout_us;
|
||||||
bool seqpacket;
|
bool seqpacket;
|
||||||
localsock_cred_t cred;
|
localsock_cred_t cred;
|
||||||
} localsocket_t;
|
} localsocket_t;
|
||||||
@@ -464,7 +467,9 @@ static int localsock_send(socket_t *socket, sockdesc_t *sockdesc) {
|
|||||||
MUTEX_RELEASE(&pair->mutex);
|
MUTEX_RELEASE(&pair->mutex);
|
||||||
MUTEX_RELEASE(&socket->mutex);
|
MUTEX_RELEASE(&socket->mutex);
|
||||||
|
|
||||||
error = poll_dowait(&desc, 0);
|
error = poll_dowait(&desc, localsocket->snd_timeout_us);
|
||||||
|
if (error == ETIMEDOUT)
|
||||||
|
error = EAGAIN;
|
||||||
|
|
||||||
poll_leave(&desc);
|
poll_leave(&desc);
|
||||||
poll_destroydesc(&desc);
|
poll_destroydesc(&desc);
|
||||||
@@ -562,7 +567,9 @@ static int localsock_recv(socket_t *socket, sockdesc_t *sockdesc) {
|
|||||||
MUTEX_RELEASE(&pair->mutex);
|
MUTEX_RELEASE(&pair->mutex);
|
||||||
MUTEX_RELEASE(&socket->mutex);
|
MUTEX_RELEASE(&socket->mutex);
|
||||||
|
|
||||||
error = poll_dowait(&desc, 0);
|
error = poll_dowait(&desc, localsocket->rcv_timeout_us);
|
||||||
|
if (error == ETIMEDOUT)
|
||||||
|
error = EAGAIN;
|
||||||
|
|
||||||
poll_leave(&desc);
|
poll_leave(&desc);
|
||||||
poll_destroydesc(&desc);
|
poll_destroydesc(&desc);
|
||||||
@@ -687,7 +694,9 @@ static int localsock_accept(socket_t *_server, socket_t *_clientconnection, sock
|
|||||||
MUTEX_RELEASE(&binding->mutex);
|
MUTEX_RELEASE(&binding->mutex);
|
||||||
MUTEX_RELEASE(&server->socket.mutex);
|
MUTEX_RELEASE(&server->socket.mutex);
|
||||||
|
|
||||||
error = poll_dowait(&desc, 0);
|
error = poll_dowait(&desc, server->rcv_timeout_us);
|
||||||
|
if (error == ETIMEDOUT)
|
||||||
|
error = EAGAIN;
|
||||||
|
|
||||||
poll_leave(&desc);
|
poll_leave(&desc);
|
||||||
poll_destroydesc(&desc);
|
poll_destroydesc(&desc);
|
||||||
@@ -827,7 +836,9 @@ static int localsock_connect(socket_t *socket, sockaddr_t *addr, uintmax_t flags
|
|||||||
VOP_HOLD(vn);
|
VOP_HOLD(vn);
|
||||||
MUTEX_RELEASE(&binding->mutex);
|
MUTEX_RELEASE(&binding->mutex);
|
||||||
|
|
||||||
error = poll_dowait(&desc, 0);
|
error = poll_dowait(&desc, localsocket->snd_timeout_us);
|
||||||
|
if (error == ETIMEDOUT)
|
||||||
|
error = EAGAIN;
|
||||||
|
|
||||||
poll_leave(&desc);
|
poll_leave(&desc);
|
||||||
poll_destroydesc(&desc);
|
poll_destroydesc(&desc);
|
||||||
@@ -905,7 +916,9 @@ static int localsock_connect(socket_t *socket, sockaddr_t *addr, uintmax_t flags
|
|||||||
// release and wait. once we return, we will be connected.
|
// release and wait. once we return, we will be connected.
|
||||||
MUTEX_RELEASE(&pair->mutex);
|
MUTEX_RELEASE(&pair->mutex);
|
||||||
|
|
||||||
error = poll_dowait(&desc, 0);
|
error = poll_dowait(&desc, localsocket->snd_timeout_us);
|
||||||
|
if (error == ETIMEDOUT)
|
||||||
|
error = EAGAIN;
|
||||||
|
|
||||||
poll_leave(&desc);
|
poll_leave(&desc);
|
||||||
poll_destroydesc(&desc);
|
poll_destroydesc(&desc);
|
||||||
@@ -1264,10 +1277,32 @@ static int localsock_shutdown(socket_t *socket, int how) {
|
|||||||
|
|
||||||
// called with socket locked
|
// called with socket locked
|
||||||
static int localsock_setopt(socket_t *socket, int layer, int optname, void *buffer, socklen_t len, cred_t *cred) {
|
static int localsock_setopt(socket_t *socket, int layer, int optname, void *buffer, socklen_t len, cred_t *cred) {
|
||||||
|
localsocket_t *localsocket = (localsocket_t *)socket;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (layer == SOL_SOCKET) {
|
if (layer == SOL_SOCKET) {
|
||||||
switch (optname) {
|
switch (optname) {
|
||||||
|
case SO_RCVTIMEO:
|
||||||
|
case SO_SNDTIMEO: {
|
||||||
|
if (len != sizeof(timeval_t))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
timeval_t tv;
|
||||||
|
error = USERCOPY_POSSIBLY_FROM_USER(&tv, buffer, sizeof(tv));
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
time_t timeout_us;
|
||||||
|
error = timeval_to_us(&tv, &timeout_us);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (optname == SO_RCVTIMEO)
|
||||||
|
localsocket->rcv_timeout_us = timeout_us;
|
||||||
|
else
|
||||||
|
localsocket->snd_timeout_us = timeout_us;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SO_SNDLOWAT:
|
case SO_SNDLOWAT:
|
||||||
case SO_OOBINLINE:
|
case SO_OOBINLINE:
|
||||||
case SO_KEEPALIVE:
|
case SO_KEEPALIVE:
|
||||||
@@ -1344,6 +1379,14 @@ static int localsock_getopt(socket_t *socket, int layer, int optname, void *unsa
|
|||||||
int value = SOCKET_BUFFER;
|
int value = SOCKET_BUFFER;
|
||||||
return USERCOPY_POSSIBLY_TO_USER(unsafe_buffer, &value, 4);
|
return USERCOPY_POSSIBLY_TO_USER(unsafe_buffer, &value, 4);
|
||||||
}
|
}
|
||||||
|
case SO_RCVTIMEO:
|
||||||
|
case SO_SNDTIMEO: {
|
||||||
|
if (len != sizeof(timeval_t))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
timeval_t tv = timeval_from_us(optname == SO_RCVTIMEO ? localsocket->rcv_timeout_us : localsocket->snd_timeout_us);
|
||||||
|
return USERCOPY_POSSIBLY_TO_USER(unsafe_buffer, &tv, sizeof(tv));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user