net: Support ioctl FIONBIO to set non-blocking

This commit is contained in:
K. Lange 2023-04-18 19:38:25 +09:00
parent df25724fcc
commit b8b69255e3
4 changed files with 21 additions and 0 deletions

View File

@ -35,6 +35,7 @@ typedef struct SockData {
size_t unread; size_t unread;
char * buf; char * buf;
int nonblocking;
} sock_t; } sock_t;
void net_sock_alert(sock_t * sock); void net_sock_alert(sock_t * sock);

View File

@ -14,4 +14,5 @@
#define IOCTL_PACKETFS_QUEUED 0x5050 #define IOCTL_PACKETFS_QUEUED 0x5050
#define FIONBIO 0x4e424c4b

View File

@ -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 (msg->msg_iovlen == 0) return 0;
if (!sock->rx_queue->length && sock->nonblocking) return -EAGAIN;
char * packet = net_sock_get(sock); char * packet = net_sock_get(sock);
if (!packet) return -EINTR; if (!packet) return -EINTR;
size_t packet_size = *(size_t*)packet - sizeof(struct ipv4_packet); 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 (msg->msg_iovlen == 0) return 0;
if (!sock->rx_queue->length && sock->nonblocking) return -EAGAIN;
char * packet = net_sock_get(sock); char * packet = net_sock_get(sock);
if (!packet) return -EINTR; if (!packet) return -EINTR;
struct ipv4_packet * data = (struct ipv4_packet*)(packet + sizeof(size_t)); 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 */ return 0; /* EOF */
} }
if (!sock->rx_queue->length && sock->nonblocking) return -EAGAIN;
while (!sock->rx_queue->length) { while (!sock->rx_queue->length) {
process_wait_nodes((process_t *)this_core->current_process, (fs_node_t*[]){(fs_node_t*)sock,NULL}, 200); process_wait_nodes((process_t *)this_core->current_process, (fs_node_t*[]){(fs_node_t*)sock,NULL}, 200);
} }

View File

@ -105,6 +105,18 @@ void sock_generic_close(fs_node_t *node) {
printf("net: socket closed\n"); 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 * net_sock_create(void) {
sock_t * sock = calloc(sizeof(struct SockData),1); sock_t * sock = calloc(sizeof(struct SockData),1);
sock->_fnode.flags = FS_SOCKET; /* uh, FS_SOCKET? */ 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.selectcheck = sock_generic_check;
sock->_fnode.selectwait = sock_generic_wait; sock->_fnode.selectwait = sock_generic_wait;
sock->_fnode.close = sock_generic_close; sock->_fnode.close = sock_generic_close;
sock->_fnode.ioctl = sock_generic_ioctl;
sock->alert_wait = list_create("socket alert wait", sock); sock->alert_wait = list_create("socket alert wait", sock);
sock->rx_wait = list_create("socket rx wait", sock); sock->rx_wait = list_create("socket rx wait", sock);
sock->rx_queue = list_create("socket rx queue", sock); sock->rx_queue = list_create("socket rx queue", sock);