mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 07:18:30 +00:00
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:
parent
ac92f25296
commit
0ba3199915
49 changed files with 347 additions and 352 deletions
|
@ -17,9 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sock/struct/sockaddr.h"
|
||||
|
@ -27,25 +30,63 @@
|
|||
#include "libc/sock/syscall_fd.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static int __getsockpeername(int fd, struct sockaddr *out_addr,
|
||||
uint32_t *inout_addrsize, const char *name,
|
||||
int impl_sysv(int, void *, uint32_t *),
|
||||
int impl_win32(uint64_t, void *, uint32_t *)) {
|
||||
int rc;
|
||||
struct sockaddr_storage ss = {0};
|
||||
uint32_t size = sizeof(ss);
|
||||
|
||||
if (IsWindows()) {
|
||||
if (__isfdkind(fd, kFdSocket)) {
|
||||
if ((rc = impl_win32(g_fds.p[fd].handle, &ss, &size))) {
|
||||
if (impl_win32 == __sys_getsockname_nt &&
|
||||
WSAGetLastError() == WSAEINVAL) {
|
||||
// The socket has not been bound to an address with bind, or
|
||||
// ADDR_ANY is specified in bind but connection has not yet
|
||||
// occurred. -MSDN
|
||||
ss.ss_family = ((struct SockFd *)g_fds.p[fd].extra)->family;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = __winsockerr();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
} else {
|
||||
rc = impl_sysv(fd, &ss, &size);
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
if (IsBsd()) {
|
||||
__convert_bsd_to_sockaddr(&ss);
|
||||
}
|
||||
__write_sockaddr(&ss, out_addr, inout_addrsize);
|
||||
}
|
||||
|
||||
STRACE("%s(%d, [%s]) -> %d% lm", name, fd,
|
||||
DescribeSockaddr(out_addr, inout_addrsize ? *inout_addrsize : 0), rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns details about network interface kernel granted socket.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @see getpeername()
|
||||
*/
|
||||
int getsockname(int fd, struct sockaddr *out_addr, uint32_t *out_addrsize) {
|
||||
int rc;
|
||||
if (!out_addrsize || !out_addrsize ||
|
||||
(IsAsan() && (!__asan_is_valid(out_addrsize, 4) ||
|
||||
!__asan_is_valid(out_addr, *out_addrsize)))) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_getsockname(fd, out_addr, out_addrsize);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
rc = sys_getsockname_nt(&g_fds.p[fd], out_addr, out_addrsize);
|
||||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
STRACE("getsockname(%d, [%s]) -> %d% lm", fd,
|
||||
DescribeSockaddr(out_addr, out_addrsize ? *out_addrsize : 0), rc);
|
||||
return rc;
|
||||
int getsockname(int fd, struct sockaddr *out_addr, uint32_t *inout_addrsize) {
|
||||
return __getsockpeername(fd, out_addr, inout_addrsize, "getsockname",
|
||||
__sys_getsockname, __sys_getsockname_nt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns details about remote end of connected socket.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @see getsockname()
|
||||
*/
|
||||
int getpeername(int fd, struct sockaddr *out_addr, uint32_t *inout_addrsize) {
|
||||
return __getsockpeername(fd, out_addr, inout_addrsize, "getpeername",
|
||||
__sys_getpeername, __sys_getpeername_nt);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue