From b8b69255e347eb9001f94236ea21384ea04b6099 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Tue, 18 Apr 2023 19:38:25 +0900 Subject: [PATCH] net: Support ioctl FIONBIO to set non-blocking --- base/usr/include/kernel/net/netif.h | 1 + base/usr/include/sys/ioctl.h | 1 + kernel/net/ipv4.c | 6 ++++++ kernel/net/socket.c | 13 +++++++++++++ 4 files changed, 21 insertions(+) diff --git a/base/usr/include/kernel/net/netif.h b/base/usr/include/kernel/net/netif.h index 9393214a..8ddfc12c 100644 --- a/base/usr/include/kernel/net/netif.h +++ b/base/usr/include/kernel/net/netif.h @@ -35,6 +35,7 @@ typedef struct SockData { size_t unread; char * buf; + int nonblocking; } sock_t; void net_sock_alert(sock_t * sock); diff --git a/base/usr/include/sys/ioctl.h b/base/usr/include/sys/ioctl.h index 65f8b35b..d51ab55e 100644 --- a/base/usr/include/sys/ioctl.h +++ b/base/usr/include/sys/ioctl.h @@ -14,4 +14,5 @@ #define IOCTL_PACKETFS_QUEUED 0x5050 +#define FIONBIO 0x4e424c4b diff --git a/kernel/net/ipv4.c b/kernel/net/ipv4.c index 3721613b..fe4ad8de 100644 --- a/kernel/net/ipv4.c +++ b/kernel/net/ipv4.c @@ -207,6 +207,8 @@ static long sock_icmp_recv(sock_t * sock, struct msghdr * msg, int flags) { } if (msg->msg_iovlen == 0) return 0; + if (!sock->rx_queue->length && sock->nonblocking) return -EAGAIN; + char * packet = net_sock_get(sock); if (!packet) return -EINTR; size_t packet_size = *(size_t*)packet - sizeof(struct ipv4_packet); @@ -536,6 +538,8 @@ static long sock_udp_recv(sock_t * sock, struct msghdr * msg, int flags) { } if (msg->msg_iovlen == 0) return 0; + if (!sock->rx_queue->length && sock->nonblocking) return -EAGAIN; + char * packet = net_sock_get(sock); if (!packet) return -EINTR; struct ipv4_packet * data = (struct ipv4_packet*)(packet + sizeof(size_t)); @@ -698,6 +702,8 @@ static long sock_tcp_recv(sock_t * sock, struct msghdr * msg, int flags) { return 0; /* EOF */ } + if (!sock->rx_queue->length && sock->nonblocking) return -EAGAIN; + while (!sock->rx_queue->length) { process_wait_nodes((process_t *)this_core->current_process, (fs_node_t*[]){(fs_node_t*)sock,NULL}, 200); } diff --git a/kernel/net/socket.c b/kernel/net/socket.c index ff65de69..fe55d3e8 100644 --- a/kernel/net/socket.c +++ b/kernel/net/socket.c @@ -105,6 +105,18 @@ void sock_generic_close(fs_node_t *node) { printf("net: socket closed\n"); } +int sock_generic_ioctl(fs_node_t * node, unsigned long request, void * argp) { + sock_t * sock = (sock_t*)node; + switch (request) { + case FIONBIO: { + if (!mmu_validate_user_pointer(argp, sizeof(int), 0)) return -EFAULT; + sock->nonblocking = (!!*(int*)argp); + return 0; + } + } + return -EINVAL; +} + sock_t * net_sock_create(void) { sock_t * sock = calloc(sizeof(struct SockData),1); sock->_fnode.flags = FS_SOCKET; /* uh, FS_SOCKET? */ @@ -113,6 +125,7 @@ sock_t * net_sock_create(void) { sock->_fnode.selectcheck = sock_generic_check; sock->_fnode.selectwait = sock_generic_wait; sock->_fnode.close = sock_generic_close; + sock->_fnode.ioctl = sock_generic_ioctl; sock->alert_wait = list_create("socket alert wait", sock); sock->rx_wait = list_create("socket rx wait", sock); sock->rx_queue = list_create("socket rx queue", sock);