Make fixes and improvements

- Introduce __assert_disable global
- Improve strsignal() thread safety
- Make system call tracing thread safe
- Fix SO_RCVTIMEO / SO_SNDTIMEO on Windows
- Refactor DescribeFoo() functions into one place
- Fix fork() on Windows when TLS and MAP_STACK exist
- Round upwards in setsockopt(SO_RCVTIMEO) on Windows
- Disable futexes on OpenBSD which seem extremely broken
- Implement a better kludge for monotonic time on Windows
This commit is contained in:
Justine Tunney 2022-06-25 18:17:31 -07:00
parent 5d837c4e7c
commit fbc053e018
186 changed files with 1836 additions and 1325 deletions

View file

@ -19,9 +19,9 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/sockdebug.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
@ -51,7 +51,6 @@ int accept4(int fd, void *out_addr, uint32_t *inout_addrsize, int flags) {
rc = ebadf();
}
STRACE("accept4(%d, [%s]) -> %d% lm", fd,
__describe_sockaddr(out_addr, inout_addrsize ? *inout_addrsize : 0),
rc);
DescribeSockaddr(out_addr, inout_addrsize ? *inout_addrsize : 0), rc);
return rc;
}

View file

@ -20,14 +20,18 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/sockdebug.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Assigns local address and port number to socket.
* Assigns local address and port number to socket, e.g.
*
* struct sockaddr_in in = {AF_INET, htons(12345), {htonl(0x7f000001)}};
* int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
* bind(fd, &in, sizeof(in));
*
* @param fd is the file descriptor returned by socket()
* @param addr is usually the binary-encoded ip:port on which to listen
@ -51,6 +55,6 @@ int bind(int fd, const void *addr, uint32_t addrsize) {
} else {
rc = einval();
}
STRACE("bind(%d, %s) -> %d% lm", fd, __describe_sockaddr(addr, addrsize), rc);
STRACE("bind(%d, %s) -> %d% lm", fd, DescribeSockaddr(addr, addrsize), rc);
return rc;
}

View file

@ -25,8 +25,11 @@
textwindows int sys_connect_nt(struct Fd *fd, const void *addr,
uint32_t addrsize) {
struct SockFd *sockfd;
sockfd = (struct SockFd *)fd->extra;
assert(fd->kind == kFdSocket);
return __winsockblock(
fd->handle, FD_CONNECT_BIT,
WSAConnect(fd->handle, addr, addrsize, NULL, NULL, NULL, NULL));
WSAConnect(fd->handle, addr, addrsize, NULL, NULL, NULL, NULL),
sockfd->rcvtimeo);
}

View file

@ -19,10 +19,10 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/sockdebug.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
@ -51,7 +51,6 @@ int connect(int fd, const void *addr, uint32_t addrsize) {
} else {
rc = efault();
}
STRACE("connect(%d, %s) -> %d% lm", fd, __describe_sockaddr(addr, addrsize),
rc);
STRACE("connect(%d, %s) -> %d% lm", fd, DescribeSockaddr(addr, addrsize), rc);
return rc;
}

View file

@ -1,33 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/sysv/consts/sol.h"
/**
* Describes setsockopt() level arguments.
*/
char *DescribeSockLevel(int x) {
static char buf[12];
if (x == SOL_IP) return "SOL_IP";
if (x == SOL_TCP) return "SOL_TCP";
if (x == SOL_UDP) return "SOL_UDP";
if (x == SOL_SOCKET) return "SOL_SOCKET";
FormatInt32(buf, x);
return buf;
}

View file

@ -1,51 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sol.h"
/**
* Describes setsockopt() optname arguments.
*/
char *DescribeSockOptname(int l, int x) {
int i;
char *ps, *s;
const struct MagnumStr *ms = 0;
_Alignas(char) static char buf[32];
if (x) {
if (l == SOL_SOCKET) {
ps = "SO_";
ms = kSockOptnames;
} else if (l == SOL_TCP) {
ps = "TCP_";
ms = kTcpOptnames;
} else if (l == SOL_IP) {
ps = "IP_";
ms = kIpOptnames;
}
}
if (ms && (s = GetMagnumStr(ms, x))) {
stpcpy(stpcpy(buf, ps), s);
return buf;
} else {
FormatInt32(buf, x);
return buf;
}
}

View file

@ -19,9 +19,9 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/sockdebug.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
@ -44,6 +44,6 @@ int getpeername(int fd, void *out_addr, uint32_t *out_addrsize) {
rc = ebadf();
}
STRACE("getpeername(%d, [%s]) -> %d% lm", fd,
__describe_sockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
DescribeSockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
return rc;
}

View file

@ -19,9 +19,9 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/sockdebug.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/errfuns.h"
@ -44,6 +44,6 @@ int getsockname(int fd, void *out_addr, uint32_t *out_addrsize) {
rc = ebadf();
}
STRACE("getsockname(%d, [%s]) -> %d% lm", fd,
__describe_sockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
DescribeSockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
return rc;
}

View file

@ -26,14 +26,17 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sol.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
void *out_opt_optval,
uint32_t *inout_optlen) {
uint64_t ms;
uint32_t in_optlen;
struct SockFd *sockfd;
struct linger_nt linger;
assert(fd->kind == kFdSocket);
sockfd = (struct SockFd *)fd->extra;
if (out_opt_optval && inout_optlen) {
in_optlen = *inout_optlen;
@ -41,6 +44,23 @@ textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
in_optlen = 0;
}
if (level == SOL_SOCKET &&
(optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
if (in_optlen >= sizeof(struct timeval)) {
if (optname == SO_RCVTIMEO) {
ms = sockfd->rcvtimeo;
} else {
ms = sockfd->sndtimeo;
}
((struct timeval *)out_opt_optval)->tv_sec = ms / 1000;
((struct timeval *)out_opt_optval)->tv_usec = ms % 1000 * 1000;
*inout_optlen = sizeof(struct timeval);
return 0;
} else {
return einval();
}
}
// TODO(jart): Use WSAIoctl?
if (__sys_getsockopt_nt(fd->handle, level, optname, out_opt_optval,
inout_optlen) == -1) {
@ -48,14 +68,7 @@ textwindows int sys_getsockopt_nt(struct Fd *fd, int level, int optname,
}
if (level == SOL_SOCKET) {
if ((optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) &&
in_optlen == sizeof(struct timeval) &&
*inout_optlen == sizeof(uint32_t)) {
ms = *(uint32_t *)out_opt_optval;
((struct timeval *)out_opt_optval)->tv_sec = ms / 1000;
((struct timeval *)out_opt_optval)->tv_usec = ms % 1000 * 1000;
*inout_optlen = sizeof(struct timeval);
} else if (optname == SO_LINGER && in_optlen == sizeof(struct linger)) {
if (optname == SO_LINGER && in_optlen == sizeof(struct linger)) {
linger = *(struct linger_nt *)out_opt_optval;
((struct linger *)out_opt_optval)->l_onoff = !!linger.l_onoff;
((struct linger *)out_opt_optval)->l_linger = linger.l_linger;

View file

@ -18,8 +18,8 @@
*/
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/syscall_fd.internal.h"

View file

@ -72,6 +72,8 @@ struct SockFd {
int family;
int type;
int protocol;
uint32_t rcvtimeo;
uint32_t sndtimeo;
bool32 (*__msabi ConnectEx)(int64_t s, const struct sockaddr *name,
int namelen, const void *opt_lpSendBuffer,
uint32_t dwSendDataLength,
@ -144,8 +146,9 @@ ssize_t sys_sendto_nt(int, const struct iovec *, size_t, uint32_t, void *,
void WinSockInit(void) hidden;
int64_t __winsockerr(void) nocallback hidden;
int __fixupnewsockfd(int, int) hidden;
int __wsablock(int64_t, struct NtOverlapped *, uint32_t *, bool) hidden;
int64_t __winsockblock(int64_t, unsigned, int64_t) hidden;
int __wsablock(int64_t, struct NtOverlapped *, uint32_t *, bool,
uint32_t) hidden;
int64_t __winsockblock(int64_t, unsigned, int64_t, uint32_t) hidden;
struct SockFd *_dupsockfd(struct SockFd *) hidden;
int64_t GetNtBaseSocket(int64_t) hidden;
int sys_close_epoll(int) hidden;

View file

@ -1,40 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/macros.internal.h"
.macro .e e s
.long \e - kIpOptnames
.long 1f - kIpOptnames
.rodata.str1.1
1: .string "\s"
.previous
.endm
.section .rodata
.align 4
.underrun
kIpOptnames:
.e IP_TOS,"TOS" # int
.e IP_MTU,"MTU" # int
.e IP_TTL,"TTL" # int
.e IP_HDRINCL,"HDRINCL" # bool32
.long MAGNUM_TERMINATOR
.endobj kIpOptnames,globl,hidden
.overrun

View file

@ -1,52 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/macros.internal.h"
.macro .e e s
.long \e - kSockOptnames
.long 1f - kSockOptnames
.rodata.str1.1
1: .string "\s"
.previous
.endm
.section .rodata
.align 4
.underrun
kSockOptnames:
.e SO_DEBUG,"DEBUG" # bool32
.e SO_ACCEPTCONN,"ACCEPTCONN" # bool32
.e SO_BROADCAST,"BROADCAST" # bool32
.e SO_REUSEADDR,"REUSEADDR" # bool32
.e SO_REUSEPORT,"REUSEPORT" # bool32
.e SO_KEEPALIVE,"KEEPALIVE" # bool32
.e SO_DONTROUTE,"DONTROUTE" # bool32
.e SO_RCVTIMEO,"RCVTIMEO" # timeval
.e SO_SNDTIMEO,"SNDTIMEO" # timeval
.e SO_LINGER,"LINGER" # linger
.e SO_TYPE,"TYPE" # int
.e SO_SNDBUF,"SNDBUF" # int
.e SO_RCVBUF,"RCVBUF" # int
.e SO_RCVLOWAT,"RCVLOWAT" # int
.e SO_SNDLOWAT,"SNDLOWAT" # int
.e SO_ERROR,"ERROR" # int
.long MAGNUM_TERMINATOR
.endobj kSockOptnames,globl,hidden
.overrun

View file

@ -1,49 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/macros.internal.h"
.macro .e e s
.long \e - kTcpOptnames
.long 1f - kTcpOptnames
.rodata.str1.1
1: .string "\s"
.previous
.endm
.section .rodata
.align 4
.underrun
kTcpOptnames:
.e TCP_NODELAY,"NODELAY" # bool32
.e TCP_CORK,"CORK" # bool32
.e TCP_QUICKACK,"QUICKACK" # bool32
.e TCP_FASTOPEN_CONNECT,"FASTOPEN_CONNECT" # bool32
.e TCP_DEFER_ACCEPT,"DEFER_ACCEPT" # bool32
.e TCP_KEEPIDLE,"KEEPIDLE" # int (seconds)
.e TCP_KEEPINTVL,"KEEPINTVL" # int (seconds)
.e TCP_FASTOPEN,"FASTOPEN" # int
.e TCP_KEEPCNT,"KEEPCNT" # int
.e TCP_MAXSEG,"MAXSEG" # int
.e TCP_SYNCNT,"SYNCNT" # int
.e TCP_NOTSENT_LOWAT,"NOTSENT_LOWAT" # int
.e TCP_WINDOW_CLAMP,"WINDOW_CLAMP" # int
.long MAGNUM_TERMINATOR
.endobj kTcpOptnames,globl,hidden
.overrun

View file

@ -16,7 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/likely.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
@ -31,16 +35,21 @@
*/
textwindows ssize_t sys_recv_nt(struct Fd *fd, const struct iovec *iov,
size_t iovlen, uint32_t flags) {
int err;
ssize_t rc;
uint32_t got = 0;
struct SockFd *sockfd;
struct NtIovec iovnt[16];
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
if (_check_interrupts(true, g_fds.p)) return eintr();
err = errno;
if (!WSARecv(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), &got, &flags,
&overlapped, NULL)) {
rc = got;
} else {
rc = __wsablock(fd->handle, &overlapped, &flags, true);
errno = err;
sockfd = (struct SockFd *)fd->extra;
rc = __wsablock(fd->handle, &overlapped, &flags, true, sockfd->rcvtimeo);
}
WSACloseEvent(overlapped.hEvent);
return rc;

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/struct/iovec.h"
#include "libc/errno.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
@ -33,17 +34,22 @@ textwindows ssize_t sys_recvfrom_nt(struct Fd *fd, const struct iovec *iov,
size_t iovlen, uint32_t flags,
void *opt_out_srcaddr,
uint32_t *opt_inout_srcaddrsize) {
int err;
ssize_t rc;
uint32_t got = 0;
struct SockFd *sockfd;
struct NtIovec iovnt[16];
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
if (_check_interrupts(true, g_fds.p)) return eintr();
err = errno;
if (!WSARecvFrom(fd->handle, iovnt, __iovec2nt(iovnt, iov, iovlen), &got,
&flags, opt_out_srcaddr, opt_inout_srcaddrsize, &overlapped,
NULL)) {
rc = got;
} else {
rc = __wsablock(fd->handle, &overlapped, &flags, true);
errno = err;
sockfd = (struct SockFd *)fd->extra;
rc = __wsablock(fd->handle, &overlapped, &flags, true, sockfd->rcvtimeo);
}
WSACloseEvent(overlapped.hEvent);
return rc;

View file

@ -33,6 +33,7 @@ textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,
uint32_t flags) {
ssize_t rc;
uint32_t sent = 0;
struct SockFd *sockfd;
struct NtIovec iovnt[16];
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
if (_check_interrupts(true, g_fds.p)) return eintr();
@ -40,7 +41,9 @@ textwindows ssize_t sys_send_nt(int fd, const struct iovec *iov, size_t iovlen,
flags, &overlapped, NULL)) {
rc = sent;
} else {
rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true);
sockfd = (struct SockFd *)g_fds.p[fd].extra;
rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true,
sockfd->sndtimeo);
}
WSACloseEvent(overlapped.hEvent);
return rc;

View file

@ -38,7 +38,8 @@
static textwindows int SendfileBlock(int64_t handle,
struct NtOverlapped *overlapped) {
uint32_t i, got, flags = 0;
if (WSAGetLastError() != kNtErrorIoPending) {
if (WSAGetLastError() != kNtErrorIoPending &&
WSAGetLastError() != WSAEINPROGRESS) {
NTTRACE("TransmitFile failed %lm");
return __winsockerr();
}

View file

@ -34,6 +34,7 @@ textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
void *opt_in_addr, uint32_t in_addrsize) {
ssize_t rc;
uint32_t sent = 0;
struct SockFd *sockfd;
struct NtIovec iovnt[16];
struct NtOverlapped overlapped = {.hEvent = WSACreateEvent()};
if (_check_interrupts(true, g_fds.p)) return eintr();
@ -41,7 +42,9 @@ textwindows ssize_t sys_sendto_nt(int fd, const struct iovec *iov,
&sent, flags, opt_in_addr, in_addrsize, &overlapped, NULL)) {
rc = sent;
} else {
rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true);
sockfd = (struct SockFd *)g_fds.p[fd].extra;
rc = __wsablock(g_fds.p[fd].handle, &overlapped, &flags, true,
sockfd->sndtimeo);
}
WSACloseEvent(overlapped.hEvent);
return rc;

View file

@ -28,9 +28,10 @@
textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
const void *optval, uint32_t optlen) {
int64_t ms;
int64_t ms, micros;
struct timeval *tv;
struct linger *linger;
struct SockFd *sockfd;
union {
uint32_t millis;
struct linger_nt linger;
@ -47,7 +48,8 @@ textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
optlen == sizeof(struct timeval)) {
tv = optval;
if (__builtin_mul_overflow(tv->tv_sec, 1000, &ms) ||
__builtin_add_overflow(ms, tv->tv_usec / 1000, &ms) ||
__builtin_add_overflow(tv->tv_usec, 999, &micros) ||
__builtin_add_overflow(ms, micros / 1000, &ms) ||
(ms < 0 || ms > 0xffffffff)) {
u.millis = 0xffffffff;
} else {
@ -55,6 +57,14 @@ textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
}
optval = &u.millis;
optlen = sizeof(u.millis);
sockfd = (struct SockFd *)fd->extra;
if (optname == SO_RCVTIMEO) {
sockfd->rcvtimeo = u.millis;
}
if (optname == SO_SNDTIMEO) {
sockfd->sndtimeo = u.millis;
}
return 0;
}
}

View file

@ -20,8 +20,8 @@
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"

View file

@ -3,6 +3,10 @@
#include "libc/bits/bswap.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/timespec.h"
#include "libc/sock/struct/linger.h"
#include "libc/sock/struct/msghdr.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/sockaddr.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/*───────────────────────────────────────────────────────────────────────────│─╗
@ -25,62 +29,11 @@ COSMOPOLITAN_C_START_
#define htonl(u32) bswap_32(u32)
#define ntohl(u32) bswap_32(u32)
struct in_addr { /* ARPA ABI */
/* e.g. 127|0<<8|0<<16|1<<24 or inet_pton(AF_INET, "127.0.0.1", &s_addr) */
uint32_t s_addr;
};
struct sockaddr { /* Linux+NT ABI */
uint16_t sa_family; /* AF_XXX */
char sa_data[14];
};
struct sockaddr_in { /* Linux+NT ABI */
uint16_t sin_family; /* AF_XXX */
uint16_t sin_port; /* htons(XXX) i.e. big endian */
struct in_addr sin_addr;
uint8_t sin_zero[8];
};
struct sockaddr_un {
uint16_t sun_family; /* AF_UNIX */
char sun_path[108]; /* path */
};
struct sockaddr_storage {
union {
uint16_t ss_family;
intptr_t __ss_align;
char __ss_storage[128];
};
};
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
struct linger { /* Linux+XNU+BSD ABI */
int32_t l_onoff; /* on/off */
int32_t l_linger; /* seconds */
};
struct pollfd {
int32_t fd;
int16_t events;
int16_t revents;
};
struct msghdr { /* Linux+NT ABI */
void *msg_name; /* optional address */
uint32_t msg_namelen; /* size of msg_name */
struct iovec *msg_iov; /* scatter/gather array */
uint64_t msg_iovlen; /* iovec count */
void *msg_control; /* credentials and stuff */
uint64_t msg_controllen; /* size of msg_control */
uint32_t msg_flags; /* MSG_XXX */
};
/*
* Structure used in SIOCGIFCONF request.
* Used to retrieve interface configuration

View file

@ -6,7 +6,7 @@ PKGS += LIBC_SOCK
LIBC_SOCK_ARTIFACTS += LIBC_SOCK_A
LIBC_SOCK = $(LIBC_SOCK_A_DEPS) $(LIBC_SOCK_A)
LIBC_SOCK_A = o/$(MODE)/libc/sock/sock.a
LIBC_SOCK_A_FILES := $(wildcard libc/sock/*)
LIBC_SOCK_A_FILES := $(wildcard libc/sock/*) $(wildcard libc/sock/struct/*)
LIBC_SOCK_A_HDRS = $(filter %.h,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_INCS = $(filter %.inc,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_SRCS_C = $(filter %.c,$(LIBC_SOCK_A_FILES))

View file

@ -19,69 +19,24 @@
#include "libc/calls/struct/sockaddr6.h"
#include "libc/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/macros.internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/sockdebug.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/sock.h"
const char *__describe_socket_family(int family) {
static char buf[12];
if (family == AF_UNIX) return "AF_UNIX";
if (family == AF_INET) return "AF_INET";
if (family == AF_INET6) return "AF_INET6";
FormatInt32(buf, family);
return buf;
}
const char *__describe_socket_type(int type) {
int x;
char *p;
static char buf[12 + 1 + 12 + 1 + 13 + 1];
p = buf;
x = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
if (x == SOCK_STREAM) {
p = stpcpy(p, "SOCK_STREAM");
} else if (x == SOCK_DGRAM) {
p = stpcpy(p, "SOCK_DGRAM");
} else if (x == SOCK_RAW) {
p = stpcpy(p, "SOCK_RAW");
} else if (x == SOCK_RDM) {
p = stpcpy(p, "SOCK_RDM");
} else if (x == SOCK_SEQPACKET) {
p = stpcpy(p, "SOCK_SEQPACKET");
} else {
p = FormatInt32(p, x);
}
if (type & SOCK_CLOEXEC) p = stpcpy(p, "|SOCK_CLOEXEC");
if (type & SOCK_NONBLOCK) p = stpcpy(p, "|SOCK_NONBLOCK");
return buf;
}
const char *__describe_socket_protocol(int family) {
static char buf[12];
if (family == IPPROTO_IP) return "IPPROTO_IP";
if (family == IPPROTO_ICMP) return "IPPROTO_ICMP";
if (family == IPPROTO_TCP) return "IPPROTO_TCP";
if (family == IPPROTO_UDP) return "IPPROTO_UDP";
if (family == IPPROTO_RAW) return "IPPROTO_RAW";
if (family == IPPROTO_IPV6) return "IPPROTO_IPv6";
FormatInt32(buf, family);
return buf;
}
const char *__describe_sockaddr(const struct sockaddr *sa, size_t sasize) {
const char *(DescribeSockaddr)(char buf[128], const struct sockaddr *sa,
size_t sasize) {
int e;
size_t n;
uint16_t port;
char *p, ip[72];
static char buf[128];
e = errno;
stpcpy(buf, "NULL");
if (sa && sasize >= sizeof(sa->sa_family)) {
stpcpy(buf, __describe_socket_family(sa->sa_family));
stpcpy(buf, DescribeSocketFamily(sa->sa_family));
if (sa->sa_family == AF_INET && sasize >= sizeof(struct sockaddr_in)) {
const struct sockaddr_in *in;
in = (const struct sockaddr_in *)sa;
@ -108,7 +63,7 @@ const char *__describe_sockaddr(const struct sockaddr *sa, size_t sasize) {
const struct sockaddr_un *unix;
unix = (const struct sockaddr_un *)sa;
n = strnlen(unix->sun_path, sizeof(unix->sun_path));
n = MIN(n, sizeof(buf) - 1);
n = MIN(n, 128 - 1);
memcpy(buf, unix->sun_path, n);
buf[n] = 0;
}

View file

@ -1,14 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_SOCK_SOCKDEBUG_H_
#define COSMOPOLITAN_LIBC_SOCK_SOCKDEBUG_H_
#include "libc/sock/sock.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
const char *__describe_sockaddr(const struct sockaddr *, size_t);
const char *__describe_socket_family(int);
const char *__describe_socket_type(int);
const char *__describe_socket_protocol(int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SOCK_SOCKDEBUG_H_ */

View file

@ -18,9 +18,9 @@
*/
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/sockdebug.h"
#include "libc/sysv/consts/af.h"
/**
@ -46,8 +46,7 @@ int socket(int family, int type, int protocol) {
} else {
rc = sys_socket_nt(family, type, protocol);
}
STRACE("socket(%s, %s, %s) → %d% lm", __describe_socket_family(family),
__describe_socket_type(type), __describe_socket_protocol(protocol),
rc);
STRACE("socket(%s, %s, %s) → %d% lm", DescribeSocketFamily(family),
DescribeSocketType(type), DescribeSocketProtocol(protocol), rc);
return rc;
}

13
libc/sock/struct/linger.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_LINGER_H_
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_LINGER_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct linger { /* Linux+XNU+BSD ABI */
int32_t l_onoff; /* on/off */
int32_t l_linger; /* seconds */
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_LINGER_H_ */

19
libc/sock/struct/msghdr.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_MSGHDR_H_
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_MSGHDR_H_
#include "libc/calls/struct/iovec.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct msghdr { /* Linux+NT ABI */
void *msg_name; /* optional address */
uint32_t msg_namelen; /* size of msg_name */
struct iovec *msg_iov; /* scatter/gather array */
uint64_t msg_iovlen; /* iovec count */
void *msg_control; /* credentials and stuff */
uint64_t msg_controllen; /* size of msg_control */
uint32_t msg_flags; /* MSG_XXX */
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_MSGHDR_H_ */

14
libc/sock/struct/pollfd.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_H_
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct pollfd {
int32_t fd;
int16_t events;
int16_t revents;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_POLLFD_H_ */

View file

@ -0,0 +1,38 @@
#ifndef COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR_H_
#define COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct sockaddr { /* Linux+NT ABI */
uint16_t sa_family; /* AF_XXX */
char sa_data[14];
};
struct in_addr { /* ARPA ABI */
/* e.g. 127|0<<8|0<<16|1<<24 or inet_pton(AF_INET, "127.0.0.1", &s_addr) */
uint32_t s_addr;
};
struct sockaddr_in { /* Linux+NT ABI */
uint16_t sin_family; /* AF_XXX */
uint16_t sin_port; /* htons(XXX) i.e. big endian */
struct in_addr sin_addr;
uint8_t sin_zero[8];
};
struct sockaddr_un {
uint16_t sun_family; /* AF_UNIX */
char sun_path[108]; /* path */
};
struct sockaddr_storage {
union {
uint16_t ss_family;
intptr_t __ss_align;
char __ss_storage[128];
};
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_SOCKADDR_H_ */

View file

@ -23,7 +23,8 @@
#include "libc/sock/sock.h"
#include "libc/str/str.h"
textwindows int64_t __winsockblock(int64_t fh, unsigned eventbit, int64_t rc) {
textwindows int64_t __winsockblock(int64_t fh, unsigned eventbit, int64_t rc,
uint32_t timeout) {
int64_t eh;
struct NtWsaNetworkEvents ev;
if (rc != -1) return rc;

View file

@ -26,10 +26,11 @@
#include "libc/sysv/errfuns.h"
textwindows int __wsablock(int64_t handle, struct NtOverlapped *overlapped,
uint32_t *flags, bool restartable) {
uint32_t *flags, bool restartable,
uint32_t timeout) {
uint32_t i, got;
if (WSAGetLastError() != kNtErrorIoPending) {
NTTRACE("WSARecv failed %lm");
NTTRACE("sock i/o failed %lm");
return __winsockerr();
}
for (;;) {
@ -39,10 +40,15 @@ textwindows int __wsablock(int64_t handle, struct NtOverlapped *overlapped,
NTTRACE("WSAWaitForMultipleEvents failed %lm");
return __winsockerr();
} else if (i == kNtWaitTimeout || i == kNtWaitIoCompletion) {
if (_check_interrupts(restartable, g_fds.p)) return eintr();
#if _NTTRACE
POLLTRACE("WSAWaitForMultipleEvents...");
#endif
if (_check_interrupts(restartable, g_fds.p)) {
return eintr();
}
if (timeout) {
if (timeout <= __SIG_POLLING_INTERVAL_MS) {
return eagain();
}
timeout -= __SIG_POLLING_INTERVAL_MS;
}
} else {
break;
}