syscalls: shutdown

This commit is contained in:
Matheus
2025-02-08 20:24:43 -03:00
parent 73929bfd57
commit b1e87c57e9
7 changed files with 183 additions and 13 deletions
+44 -2
View File
@@ -13,7 +13,7 @@
struct localpair_t;
struct binding_t;
typedef struct {
socket_t socket;
socket_t socket; // shutdown state is shared with pair
ringbuffer_t ringbuffer; // shared with pair
// client/connected server
struct localpair_t *pair;
@@ -1003,6 +1003,47 @@ static int localsock_getpeername(socket_t *socket, sockaddr_t *addr) {
return 0;
}
static int localsock_shutdown(socket_t *socket, int how) {
localsocket_t *localsocket = (localsocket_t *)socket;
MUTEX_ACQUIRE(&socket->mutex);
int error;
localpair_t *pair = localsocket->pair;
// socket not connected
if (pair == NULL) {
error = ENOTCONN;
goto leave;
}
MUTEX_ACQUIRE(&pair->mutex);
localsocket_t *peer = localsocket->pair->client == localsocket ? localsocket->pair->server : localsocket->pair->client;
socket->shutdown |= how;
int poll_events = 0;
// XXX is this the correct behaviour?
if (how & SOCKET_SHUTDOWN_READ)
poll_events |= POLLHUP;
if (how & SOCKET_SHUTDOWN_WRITE)
poll_events |= POLLIN;
if (peer)
poll_event(&peer->socket.pollheader, poll_events);
error = 0;
leave:
if (pair)
MUTEX_RELEASE(&pair->mutex);
MUTEX_RELEASE(&socket->mutex);
return error;
}
static socketops_t socketops = {
.bind = localsock_bind,
.listen = localsock_listen,
@@ -1014,7 +1055,8 @@ static socketops_t socketops = {
.poll = localsock_poll,
.datacount = localsocket_datacount,
.getname = localsock_getname,
.getpeername = localsock_getpeername
.getpeername = localsock_getpeername,
.shutdown = localsock_shutdown
};
socket_t *localsock_createsocket() {
+7 -1
View File
@@ -1832,6 +1832,11 @@ static int tcp_setopt(socket_t *socket, int optname, void *buffer, size_t len, c
return 0;
}
static int tcp_shutdown(socket_t *socket, int how) {
printf("tcp: shutdown is not implemented\n");
return ENOSYS;
}
static socketops_t socketops = {
.bind = tcp_bind,
.send = tcp_send,
@@ -1844,7 +1849,8 @@ static socketops_t socketops = {
.destroy = tcp_destroy,
.getname = tcp_getname,
.getpeername = tcp_getpeername,
.setopt = tcp_setopt
.setopt = tcp_setopt,
.shutdown = tcp_shutdown
};
socket_t *tcp_createsocket() {
+23 -3
View File
@@ -109,7 +109,7 @@ void udp_process(netdev_t *netdev, void *buffer, uint32_t peer) {
spinlock_release(&portlock);
if (socket == NULL) // drop packet if no socket listening on port
if (socket == NULL || (socket->socket.shutdown & SOCKET_SHUTDOWN_READ)) // drop packet if no socket listening on port or its not accepting incoming data
return;
dataheader_t header = {
@@ -185,7 +185,14 @@ static int udp_send(socket_t *socket, sockdesc_t *sockdesc) {
int e;
MUTEX_ACQUIRE(&socket->mutex);
if (sockdesc->addr == NULL && socket->state != SOCKET_STATE_CONNECTED) {
if (socket->shutdown & SOCKET_SHUTDOWN_WRITE) {
// XXX should SIGPIPE be sent in this case?
e = 0;
sockdesc->donecount = 0;
return 0;
}
if (sockdesc->addr == NULL) {
e = ENOTCONN;
goto cleanup;
}
@@ -337,6 +344,18 @@ static int udp_poll(socket_t *socket, polldata_t *data, int events) {
return revents;
}
static int udp_shutdown(socket_t *socket, int how) {
if (how > SOCKET_SHUTDOWN_RW)
return EINVAL;
MUTEX_ACQUIRE(&socket->mutex);
socket->shutdown |= how;
MUTEX_RELEASE(&socket->mutex);
return 0;
}
static socketops_t socketops = {
.bind = udp_bind,
.send = udp_send,
@@ -344,7 +363,8 @@ static socketops_t socketops = {
.destroy = udp_destroy,
.poll = udp_poll,
.getname = udp_getname,
.getpeername = udp_getpeername
.getpeername = udp_getpeername,
.shutdown = udp_shutdown
};
socket_t *udp_createsocket() {