Fix some more socket bugs

- The functions that return a sockaddr now do so the same way the Linux
  Kernel does across platforms, e.g. getpeername(), accept4()

- Socket system calls on Windows will now only check for interrupts when
  a blocking operation needs to be performed.

- Write tests for recvfrom() system call
This commit is contained in:
Justine Tunney 2023-07-23 16:31:10 -07:00
parent ac92f25296
commit 0ba3199915
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
49 changed files with 347 additions and 352 deletions

View file

@ -18,13 +18,12 @@
*/
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/errno.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/struct/sockaddr.h"
#include "libc/sock/struct/sockaddr.internal.h"
#include "libc/sock/struct/sockaddr6.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
@ -32,7 +31,7 @@
#include "libc/sysv/consts/sock.h"
union AcceptExAddr {
union sockaddr_storage_linux addr;
struct sockaddr_storage addr;
char buf[sizeof(struct sockaddr_storage) + 16];
};
@ -41,30 +40,8 @@ struct AcceptExBuffer {
union AcceptExAddr remote;
};
static void CopyLinuxSockAddr(const union sockaddr_storage_linux *addr,
void *out_addr, uint32_t *inout_addrsize) {
uint32_t insize, outsize;
if (out_addr && inout_addrsize) {
if (addr->sa.sa_family == AF_INET) {
outsize = sizeof(struct sockaddr_in);
} else if (addr->sa.sa_family == AF_INET6) {
outsize = sizeof(struct sockaddr_in6);
} else if (addr->sa.sa_family == AF_UNIX) {
outsize = sizeof(addr->sun.sun_family) +
strnlen(addr->sun.sun_path, sizeof(addr->sun.sun_path)) + 1;
} else {
outsize = sizeof(union sockaddr_storage_linux);
}
insize = *inout_addrsize;
if (insize) bzero(out_addr, insize);
outsize = MIN(insize, outsize);
if (outsize) memcpy(out_addr, addr, outsize);
*inout_addrsize = outsize;
}
}
textwindows int sys_accept_nt(struct Fd *fd, void *out_addr,
uint32_t *inout_addrsize, int accept4_flags) {
textwindows int sys_accept_nt(struct Fd *fd, struct sockaddr_storage *addr,
int accept4_flags) {
int64_t handle;
int rc, client, oflags;
uint32_t bytes_received;
@ -72,11 +49,6 @@ textwindows int sys_accept_nt(struct Fd *fd, void *out_addr,
struct AcceptExBuffer buffer;
struct SockFd *sockfd, *sockfd2;
// deliver interrupt instead if any are pending
if (_check_interrupts(true, g_fds.p)) {
return -1;
}
// creates resources for child socket
// inherit the listener configuration
sockfd = (struct SockFd *)fd->extra;
@ -120,6 +92,6 @@ textwindows int sys_accept_nt(struct Fd *fd, void *out_addr,
__fds_unlock();
// handoff information to caller;
CopyLinuxSockAddr(&buffer.remote.addr, out_addr, inout_addrsize);
memcpy(addr, &buffer.remote.addr, sizeof(*addr));
return client;
}