mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 00:02:28 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
53
libc/sock/accept-nt.c
Normal file
53
libc/sock/accept-nt.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int accept$nt(struct Fd *fd, void *addr, uint32_t *addrsize,
|
||||
int flags) {
|
||||
int client;
|
||||
uint32_t yes;
|
||||
assert(fd->kind == kFdSocket);
|
||||
if ((client = createfd()) == -1) return -1;
|
||||
if ((g_fds.p[client].handle = WSAAccept(fd->handle, addr, (int32_t *)addrsize,
|
||||
NULL, NULL)) != -1) {
|
||||
if (flags & SOCK_CLOEXEC) {
|
||||
SetHandleInformation(g_fds.p[client].handle, kNtHandleFlagInherit, 0);
|
||||
}
|
||||
if (flags & SOCK_NONBLOCK) {
|
||||
yes = 1;
|
||||
if (__ioctlsocket$nt(g_fds.p[client].handle, FIONBIO, &yes) == -1) {
|
||||
__closesocket$nt(g_fds.p[client].handle);
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
||||
g_fds.p[client].kind = kFdSocket;
|
||||
g_fds.p[client].flags = flags;
|
||||
return client;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
29
libc/sock/accept-sysv.c
Normal file
29
libc/sock/accept-sysv.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
int accept$sysv(int server, void *addr, uint32_t *addrsize) {
|
||||
int client;
|
||||
if ((client = __accept$sysv(server, addr, addrsize)) != -1 && IsBsd()) {
|
||||
sockaddr2linux(addr);
|
||||
}
|
||||
return client;
|
||||
}
|
43
libc/sock/accept.c
Normal file
43
libc/sock/accept.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Creates client socket file descriptor for incoming connection.
|
||||
*
|
||||
* @param fd is the server socket file descriptor
|
||||
* @param out_addr will receive the remote address
|
||||
* @param inout_addrsize provides and receives addr's byte length
|
||||
* @return client fd which needs close(), or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int accept(int fd, void *out_addr, uint32_t *inout_addrsize) {
|
||||
if (!IsWindows()) {
|
||||
return accept$sysv(fd, out_addr, inout_addrsize);
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return accept$nt(&g_fds.p[fd], out_addr, inout_addrsize, 0);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
48
libc/sock/accept4-sysv.c
Normal file
48
libc/sock/accept4-sysv.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
#define __NR_accept4_linux 0x0120 /* rhel5:enosysevil */
|
||||
|
||||
int accept4$sysv(int server, void *addr, uint32_t *addrsize, int flags) {
|
||||
static bool once, demodernize;
|
||||
int olderr, client;
|
||||
if (!flags || demodernize) goto TriedAndTrue;
|
||||
olderr = errno;
|
||||
client = __accept4$sysv(server, addr, addrsize, flags);
|
||||
if (client == -1 && errno == ENOSYS) {
|
||||
errno = olderr;
|
||||
TriedAndTrue:
|
||||
client = fixupnewsockfd$sysv(__accept$sysv(server, addr, addrsize), flags);
|
||||
} else if (SupportsLinux() && !once) {
|
||||
once = true;
|
||||
if (client == __NR_accept4_linux) {
|
||||
demodernize = true;
|
||||
goto TriedAndTrue;
|
||||
}
|
||||
}
|
||||
if (client != -1 && IsBsd()) {
|
||||
sockaddr2linux(addr);
|
||||
}
|
||||
return client;
|
||||
}
|
44
libc/sock/accept4.c
Normal file
44
libc/sock/accept4.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Creates client socket file descriptor for incoming connection.
|
||||
*
|
||||
* @param fd is the server socket file descriptor
|
||||
* @param out_addr will receive the remote address
|
||||
* @param inout_addrsize provides and receives out_addr's byte length
|
||||
* @param flags can have SOCK_{CLOEXEC,NONBLOCK}, which may apply to
|
||||
* both the newly created socket and the server one
|
||||
* @return client fd which needs close(), or -1 w/ errno
|
||||
*/
|
||||
int accept4(int fd, void *out_addr, uint32_t *inout_addrsize, int flags) {
|
||||
if (!IsWindows()) {
|
||||
return accept4$sysv(fd, out_addr, inout_addrsize, flags);
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return accept$nt(&g_fds.p[fd], out_addr, inout_addrsize, flags);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
43
libc/sock/bind-nt.c
Normal file
43
libc/sock/bind-nt.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Assigns local address and port number to socket.
|
||||
*
|
||||
* @param fd is the file descriptor returned by socket()
|
||||
* @param addr is usually the binary-encoded ip:port on which to listen
|
||||
* @param addrsize is the byte-length of addr's true polymorphic form
|
||||
* @return socket file descriptor or -1 w/ errno
|
||||
* @error ENETDOWN, EPFNOSUPPORT, etc.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
textwindows int bind$nt(struct Fd *fd, const void *addr, uint32_t addrsize) {
|
||||
assert(fd->kind == kFdSocket);
|
||||
if (__bind$nt(fd->handle, addr, addrsize) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
58
libc/sock/bind.c
Normal file
58
libc/sock/bind.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Assigns local address and port number to socket.
|
||||
*
|
||||
* @param fd is the file descriptor returned by socket()
|
||||
* @param addr is usually the binary-encoded ip:port on which to listen
|
||||
* @param addrsize is the byte-length of addr's true polymorphic form
|
||||
* @return socket file descriptor or -1 w/ errno
|
||||
* @error ENETDOWN, EPFNOSUPPORT, etc.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int bind(int fd, const void *addr, uint32_t addrsize) {
|
||||
if (addrsize == sizeof(struct sockaddr_in)) {
|
||||
if (!IsWindows()) {
|
||||
if (!IsBsd()) {
|
||||
return bind$sysv(fd, addr, addrsize);
|
||||
} else {
|
||||
struct sockaddr_in$bsd addr2;
|
||||
static_assert(sizeof(struct sockaddr_in) ==
|
||||
sizeof(struct sockaddr_in$bsd));
|
||||
memcpy(&addr2, addr, sizeof(struct sockaddr_in));
|
||||
sockaddr2bsd(&addr2);
|
||||
return bind$sysv(fd, &addr2, addrsize);
|
||||
}
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return bind$nt(&g_fds.p[fd], addr, addrsize);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
32
libc/sock/closesocket-nt.c
Normal file
32
libc/sock/closesocket-nt.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int closesocket$nt(int fd) {
|
||||
int rc;
|
||||
if (!isfdkind(fd, kFdSocket)) return ebadf();
|
||||
rc = __closesocket$nt(g_fds.p[fd].handle) ? 0 : winsockerr();
|
||||
removefd(fd);
|
||||
return rc;
|
||||
}
|
31
libc/sock/connect-nt.c
Normal file
31
libc/sock/connect-nt.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int connect$nt(struct Fd *fd, const void *addr, uint32_t addrsize) {
|
||||
assert(fd->kind == kFdSocket);
|
||||
return winsockblock(
|
||||
fd->handle, FD_CONNECT_BIT,
|
||||
WSAConnect(fd->handle, addr, addrsize, NULL, NULL, NULL, NULL));
|
||||
}
|
36
libc/sock/connect-sysv.c
Normal file
36
libc/sock/connect-sysv.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int connect$sysv(int fd, const void *addr, uint32_t addrsize) {
|
||||
if (addrsize != sizeof(struct sockaddr_in)) return einval();
|
||||
if (!IsBsd()) {
|
||||
return __connect$sysv(fd, addr, addrsize);
|
||||
} else {
|
||||
struct sockaddr_in$bsd addr2;
|
||||
static_assert(sizeof(struct sockaddr_in) == sizeof(struct sockaddr_in$bsd));
|
||||
memcpy(&addr2, addr, sizeof(struct sockaddr_in));
|
||||
sockaddr2bsd(&addr2);
|
||||
return connect$sysv(fd, &addr2, addrsize);
|
||||
}
|
||||
}
|
44
libc/sock/connect.c
Normal file
44
libc/sock/connect.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Connects socket to remote end.
|
||||
*
|
||||
* ProTip: Connectionless sockets, e.g. UDP, can be connected too. The
|
||||
* benefit is not needing to specify the remote address on each send. It
|
||||
* also means getsockname() can be called to retrieve routing details.
|
||||
*
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int connect(int fd, const void *addr, uint32_t addrsize) {
|
||||
if (!IsWindows()) {
|
||||
return connect$sysv(fd, addr, addrsize);
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return connect$nt(&g_fds.p[fd], addr, addrsize);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
35
libc/sock/fixupnewsockfd.c
Normal file
35
libc/sock/fixupnewsockfd.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
|
||||
/**
|
||||
* Applies non-atomic file descriptor fixups on XNU or ancient Linux.
|
||||
*
|
||||
* @param fd of -1 means no-op
|
||||
*/
|
||||
int fixupnewsockfd$sysv(int fd, int flags) {
|
||||
return fixupnewfd$sysv(fd, (((flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0) |
|
||||
((flags & SOCK_NONBLOCK) ? O_NONBLOCK : 0)));
|
||||
}
|
35
libc/sock/getpeername-nt.c
Normal file
35
libc/sock/getpeername-nt.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int getpeername$nt(struct Fd *fd, void *out_addr,
|
||||
uint32_t *out_addrsize) {
|
||||
assert(fd->kind == kFdSocket);
|
||||
if (__getpeername$nt(fd->handle, out_addr, out_addrsize) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
29
libc/sock/getpeername-sysv.c
Normal file
29
libc/sock/getpeername-sysv.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
int getpeername$sysv(int fd, void *out_addr, uint32_t *out_addrsize) {
|
||||
int rc = __getpeername$sysv(fd, out_addr, out_addrsize);
|
||||
if (rc != -1 && IsBsd()) {
|
||||
sockaddr2linux(out_addr);
|
||||
}
|
||||
return rc;
|
||||
}
|
39
libc/sock/getpeername.c
Normal file
39
libc/sock/getpeername.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Returns details about remote end of connected socket.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @see getsockname()
|
||||
*/
|
||||
int getpeername(int fd, void *out_addr, uint32_t *out_addrsize) {
|
||||
if (!IsWindows()) {
|
||||
return getpeername$sysv(fd, out_addr, out_addrsize);
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return getpeername$nt(&g_fds.p[fd], out_addr, out_addrsize);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
35
libc/sock/getsockname-nt.c
Normal file
35
libc/sock/getsockname-nt.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int getsockname$nt(struct Fd *fd, void *out_addr,
|
||||
uint32_t *out_addrsize) {
|
||||
assert(fd->kind == kFdSocket);
|
||||
if (__getsockname$nt(fd->handle, out_addr, out_addrsize) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
29
libc/sock/getsockname-sysv.c
Normal file
29
libc/sock/getsockname-sysv.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
int getsockname$sysv(int fd, void *out_addr, uint32_t *out_addrsize) {
|
||||
int rc = __getsockname$sysv(fd, out_addr, out_addrsize);
|
||||
if (rc != -1 && IsBsd()) {
|
||||
sockaddr2linux(out_addr);
|
||||
}
|
||||
return rc;
|
||||
}
|
39
libc/sock/getsockname.c
Normal file
39
libc/sock/getsockname.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Returns details about network interface kernel granted socket.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @see getpeername()
|
||||
*/
|
||||
int getsockname(int fd, void *out_addr, uint32_t *out_addrsize) {
|
||||
if (!IsWindows()) {
|
||||
return getsockname$sysv(fd, out_addr, out_addrsize);
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return getsockname$nt(&g_fds.p[fd], out_addr, out_addrsize);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
36
libc/sock/getsockopt-nt.c
Normal file
36
libc/sock/getsockopt-nt.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int getsockopt$nt(struct Fd *fd, int level, int optname,
|
||||
void *out_opt_optval, uint32_t *out_optlen) {
|
||||
/* TODO(jart): Use WSAIoctl? */
|
||||
assert(fd->kind == kFdSocket);
|
||||
if (__getsockopt$nt(fd->handle, level, optname, out_opt_optval, out_optlen) !=
|
||||
-1) {
|
||||
return 0;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
48
libc/sock/getsockopt.c
Normal file
48
libc/sock/getsockopt.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Retrieves socket setting.
|
||||
*
|
||||
* @param level can be SOL_SOCKET, IPPROTO_TCP, etc.
|
||||
* @param optname can be SO_{REUSE{PORT,ADDR},KEEPALIVE,etc.} etc.
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @error ENOPROTOOPT for unknown (level,optname)
|
||||
* @see libc/sysv/consts.sh for tuning catalogue
|
||||
* @see setsockopt()
|
||||
*/
|
||||
int getsockopt(int fd, int level, int optname, void *out_opt_optval,
|
||||
uint32_t *out_optlen) {
|
||||
if (!level || !optname) return enoprotoopt(); /* our sysvconsts definition */
|
||||
if (optname == -1) return 0; /* our sysvconsts definition */
|
||||
if (!IsWindows()) {
|
||||
return getsockopt$sysv(fd, level, optname, out_opt_optval, out_optlen);
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return getsockopt$nt(&g_fds.p[fd], level, optname, out_opt_optval,
|
||||
out_optlen);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
53
libc/sock/inet_ntop.c
Normal file
53
libc/sock/inet_ntop.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
|
||||
/**
|
||||
* Formats internet address to string.
|
||||
*
|
||||
* @param af can be AF_INET
|
||||
* @param src is the binary-encoded address, e.g. &addr->sin_addr
|
||||
* @param dst is the output string buffer
|
||||
* @param size is bytes in dst, which needs 16+ for IPv4
|
||||
* @return dst on success or NULL w/ errno
|
||||
*/
|
||||
const char *inet_ntop(int af, const void *src, char *dst, uint32_t size) {
|
||||
if (src) {
|
||||
if (af == AF_INET) {
|
||||
unsigned char *p = (unsigned char *)src;
|
||||
if (snprintf(dst, size, "%hhu.%hhu.%hhu.%hhu", p[0], p[1], p[2], p[3]) <
|
||||
size) {
|
||||
return dst;
|
||||
} else {
|
||||
enospc();
|
||||
}
|
||||
} else {
|
||||
eafnosupport();
|
||||
}
|
||||
} else {
|
||||
einval();
|
||||
}
|
||||
if (size) dst[0] = '\0';
|
||||
return NULL;
|
||||
}
|
48
libc/sock/inet_pton.c
Normal file
48
libc/sock/inet_pton.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/inaddr.h"
|
||||
|
||||
/**
|
||||
* Converts internet address string to binary.
|
||||
*
|
||||
* @param af can be AF_INET
|
||||
* @param src is the ASCII-encoded address
|
||||
* @param dst is where the binary-encoded net-order address goes
|
||||
* @return 1 on success, 0 on src malformed, or -1 w/ errno
|
||||
*/
|
||||
int inet_pton(int af, const char *src, void *dst) {
|
||||
if (af == AF_INET) {
|
||||
unsigned char *p = (unsigned char *)dst;
|
||||
if (sscanf(src, "%hhu.%hhu.%hhu.%hhu", &p[0], &p[1], &p[2], &p[3]) == 4) {
|
||||
return 1;
|
||||
} else {
|
||||
*(uint32_t *)dst = htonl(INADDR_TESTNET3);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
*(uint32_t *)dst = htonl(INADDR_TESTNET3);
|
||||
return eafnosupport();
|
||||
}
|
||||
}
|
148
libc/sock/internal.h
Normal file
148
libc/sock/internal.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_SOCK_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_SOCK_INTERNAL_H_
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define FD_READ (1 << FD_READ_BIT)
|
||||
#define FD_READ_BIT 0
|
||||
#define FD_WRITE (1 << FD_WRITE_BIT)
|
||||
#define FD_WRITE_BIT 1
|
||||
#define FD_OOB (1 << FD_OOB_BIT)
|
||||
#define FD_OOB_BIT 2
|
||||
#define FD_ACCEPT (1 << FD_ACCEPT_BIT)
|
||||
#define FD_ACCEPT_BIT 3
|
||||
#define FD_CONNECT (1 << FD_CONNECT_BIT)
|
||||
#define FD_CONNECT_BIT 4
|
||||
#define FD_CLOSE (1 << FD_CLOSE_BIT)
|
||||
#define FD_CLOSE_BIT 5
|
||||
|
||||
struct Fd;
|
||||
struct iovec;
|
||||
struct timeval;
|
||||
|
||||
struct sockaddr$bsd {
|
||||
uint8_t sa_len; /* « different type */
|
||||
uint8_t sa_family; /* « different type */
|
||||
char sa_data[14];
|
||||
};
|
||||
|
||||
struct sockaddr_in$bsd {
|
||||
uint8_t sin_len; /* « different type */
|
||||
uint8_t sin_family; /* « different type */
|
||||
uint16_t sin_port;
|
||||
struct in_addr sin_addr;
|
||||
uint8_t sin_zero[8];
|
||||
};
|
||||
|
||||
struct msghdr$bsd {
|
||||
void *msg_name;
|
||||
uint32_t msg_namelen;
|
||||
struct iovec *msg_iov;
|
||||
uint32_t msg_iovlen; /* « different type */
|
||||
void *msg_control;
|
||||
uint64_t msg_controllen;
|
||||
uint32_t msg_flags; /* « different type */
|
||||
};
|
||||
|
||||
int32_t __accept$sysv(int32_t, void *, uint32_t *) nodiscard hidden;
|
||||
int32_t __accept4$sysv(int32_t, void *, uint32_t *, int) nodiscard hidden;
|
||||
int32_t __connect$sysv(int32_t, const void *, uint32_t) hidden;
|
||||
int32_t __socket$sysv(int32_t, int32_t, int32_t) hidden;
|
||||
int32_t __getsockname$sysv(int32_t, void *, uint32_t *) hidden;
|
||||
int32_t __getpeername$sysv(int32_t, void *, uint32_t *) hidden;
|
||||
|
||||
int32_t select$sysv(int32_t, fd_set *, fd_set *, fd_set *, struct timeval *);
|
||||
int32_t setsockopt$sysv(int32_t, int32_t, int32_t, const void *,
|
||||
uint32_t) hidden;
|
||||
int32_t accept4$sysv(int32_t, void *, uint32_t *, int) nodiscard hidden;
|
||||
int32_t accept$sysv(int32_t, void *, uint32_t *) hidden;
|
||||
int32_t bind$sysv(int32_t, const void *, uint32_t) hidden;
|
||||
int32_t connect$sysv(int32_t, const void *, uint32_t) hidden;
|
||||
int32_t getsockopt$sysv(int32_t, int32_t, int32_t, void *, uint32_t *) hidden;
|
||||
int32_t listen$sysv(int32_t, int32_t) hidden;
|
||||
int32_t getsockname$sysv(int32_t, void *, uint32_t *) hidden;
|
||||
int32_t getpeername$sysv(int32_t, void *, uint32_t *) hidden;
|
||||
int32_t poll$sysv(struct pollfd *, uint64_t, signed) hidden;
|
||||
int32_t shutdown$sysv(int32_t, int32_t) hidden;
|
||||
int32_t socket$sysv(int32_t, int32_t, int32_t) hidden;
|
||||
int64_t readv$sysv(int32_t, const struct iovec *, int32_t) hidden;
|
||||
int64_t writev$sysv(int32_t, const struct iovec *, int32_t) hidden;
|
||||
ssize_t recvfrom$sysv(int, void *, size_t, int, void *, uint32_t *) hidden;
|
||||
ssize_t sendto$sysv(int, const void *, size_t, int, const void *,
|
||||
uint32_t) hidden;
|
||||
|
||||
int poll$nt(struct pollfd *, uint64_t, int32_t) hidden;
|
||||
int getsockopt$nt(struct Fd *, int, int, void *, uint32_t *) hidden;
|
||||
int getsockname$nt(struct Fd *, void *, uint32_t *) hidden;
|
||||
int getpeername$nt(struct Fd *, void *, uint32_t *) hidden;
|
||||
int listen$nt(struct Fd *, int) hidden;
|
||||
int connect$nt(struct Fd *, const void *, uint32_t) hidden;
|
||||
int bind$nt(struct Fd *, const void *, uint32_t);
|
||||
int accept$nt(struct Fd *, void *, uint32_t *, int) hidden;
|
||||
int closesocket$nt(int) hidden;
|
||||
int socket$nt(int, int, int) hidden;
|
||||
|
||||
size_t iovec2nt(struct iovec$nt[hasatleast 16], const struct iovec *,
|
||||
size_t) hidden;
|
||||
ssize_t sendto$nt(struct Fd *, const struct iovec *, size_t, uint32_t, void *,
|
||||
uint32_t *) hidden;
|
||||
ssize_t recvfrom$nt(struct Fd *, const struct iovec *, size_t, uint32_t, void *,
|
||||
uint32_t *) hidden;
|
||||
|
||||
int64_t winsockerr(void) nocallback hidden;
|
||||
int fixupnewsockfd$sysv(int, int) hidden;
|
||||
ssize_t WinSendRecv(int64_t, void *, size_t, uint32_t, struct sockaddr *,
|
||||
uint32_t *, bool) hidden;
|
||||
int64_t winsockblock(int64_t, unsigned, int64_t) hidden;
|
||||
|
||||
/**
|
||||
* Converts sockaddr (Linux/Windows) → sockaddr$bsd (XNU/BSD).
|
||||
*/
|
||||
forceinline void sockaddr2bsd(void *saddr) {
|
||||
uint8_t *p;
|
||||
uint16_t fam;
|
||||
if (saddr) {
|
||||
p = saddr;
|
||||
fam = read16le(p);
|
||||
p[0] = sizeof(struct sockaddr_in$bsd);
|
||||
p[1] = fam;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts sockaddr_in$bsd (XNU/BSD) → sockaddr (Linux/Windows).
|
||||
*/
|
||||
forceinline void sockaddr2linux(void *saddr) {
|
||||
uint8_t *p, fam;
|
||||
if (saddr) {
|
||||
p = saddr;
|
||||
fam = p[1];
|
||||
WRITE16LE(p, fam);
|
||||
}
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SOCK_INTERNAL_H_ */
|
45
libc/sock/iovec2nt.c
Normal file
45
libc/sock/iovec2nt.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/iov.h"
|
||||
|
||||
/**
|
||||
* Converts I/O vector from System Five to WIN32 ABI.
|
||||
*
|
||||
* @return effective iovlen
|
||||
* @see IOV_MAX
|
||||
*/
|
||||
textwindows size_t iovec2nt(struct iovec$nt iovnt[hasatleast 16],
|
||||
const struct iovec *iov, size_t iovlen) {
|
||||
size_t i, limit;
|
||||
for (limit = 0x7ffff000, i = 0; i < MIN(16, iovlen); ++i) {
|
||||
iovnt[i].buf = iov[i].iov_base;
|
||||
if (iov[i].iov_len < limit) {
|
||||
limit -= (iovnt[i].len = iov[i].iov_len);
|
||||
} else {
|
||||
iovnt[i].len = limit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
68
libc/sock/ipclassify.h
Normal file
68
libc/sock/ipclassify.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SOCK_IPCLASSIFY_H_
|
||||
#define COSMOPOLITAN_LIBC_SOCK_IPCLASSIFY_H_
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/inaddr.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* Returns true if address is part of standardized test-only subnet.
|
||||
*/
|
||||
forceinline bool istestip(int sin_family, void *sin_addr) {
|
||||
if (sin_family == AF_INET) {
|
||||
uint32_t ip4net24 = ntohl(*(const uint32_t *)sin_addr) & 0xffffff00u;
|
||||
if (ip4net24 == INADDR_TESTNET1 || ip4net24 == INADDR_TESTNET2 ||
|
||||
ip4net24 == INADDR_TESTNET3) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
eafnosupport();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if address is part of a local-only subnet.
|
||||
*/
|
||||
forceinline bool islocalip(int sin_family, void *sin_addr) {
|
||||
if (sin_family == AF_INET) {
|
||||
uint32_t ip4net8 = ntohl(*(const uint32_t *)sin_addr) & 0xff000000u;
|
||||
if (ip4net8 == 0x7f000000u) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
eafnosupport();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if address is part of a well-known private subnet.
|
||||
*/
|
||||
forceinline bool isprivateip(int sin_family, void *sin_addr) {
|
||||
if (sin_family == AF_INET) {
|
||||
uint32_t ip4 = ntohl(*(const uint32_t *)sin_addr);
|
||||
if ((0x0a000000u <= ip4 && ip4 <= 0x0affffffu) /* 10.0.0.0/8 */ ||
|
||||
(0xac100000u <= ip4 && ip4 <= 0xac1fffffu) /* 172.16.0.0/12 */ ||
|
||||
(0xc0a80000u <= ip4 && ip4 <= 0xc0a8ffffu) /* 192.168.0.0/16 */) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
eafnosupport();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if address is most likely part of the public Internet.
|
||||
*/
|
||||
forceinline bool ispublicip(int sin_family, void *sin_addr) {
|
||||
return !islocalip(sin_family, sin_addr) &&
|
||||
!isprivateip(sin_family, sin_addr) && !istestip(sin_family, sin_addr);
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SOCK_IPCLASSIFY_H_ */
|
47
libc/sock/kntwsadata.c
Normal file
47
libc/sock/kntwsadata.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
#define VERSION 0x0202 /* Windows Vista+ */
|
||||
|
||||
/**
|
||||
* Information about underyling Windows Sockets implemmentation.
|
||||
*
|
||||
* Cosmopolitan automatically calls YOINK() on this symbol when its
|
||||
* Berkeley Socket wrappers are linked. The latest version of Winsock
|
||||
* was introduced alongside x64, so this should never fail.
|
||||
*/
|
||||
struct NtWsaData kNtWsaData;
|
||||
|
||||
textwindows static void winsockfini(void) { WSACleanup(); }
|
||||
textstartup static void winsockinit(void) {
|
||||
if (!IsWindows()) return;
|
||||
atexit(winsockfini);
|
||||
int rc;
|
||||
if ((rc = WSAStartup(VERSION, &kNtWsaData)) != 0 ||
|
||||
kNtWsaData.wVersion != VERSION) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
const void *const winsockctor[] initarray = {winsockinit};
|
33
libc/sock/listen-nt.c
Normal file
33
libc/sock/listen-nt.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int listen$nt(struct Fd *fd, int backlog) {
|
||||
assert(fd->kind == kFdSocket);
|
||||
if (__listen$nt(fd->handle, backlog) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
45
libc/sock/listen.c
Normal file
45
libc/sock/listen.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Asks system to accept incoming connections on socket.
|
||||
*
|
||||
* The socket() and bind() functions need to be called beforehand. Once
|
||||
* this function is called, accept() is used to wait for connections.
|
||||
* Using this on connectionless sockets will allow it to receive packets
|
||||
* on a designated address.
|
||||
*
|
||||
* @param backlog <= SOMAXCONN
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int listen(int fd, int backlog) {
|
||||
if (!IsWindows()) {
|
||||
return listen$sysv(fd, backlog);
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return listen$nt(&g_fds.p[fd], backlog);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
27
libc/sock/parseport.c
Normal file
27
libc/sock/parseport.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int parseport(const char *service) {
|
||||
int port = atoi(service);
|
||||
return (0 <= port && port <= 65535) ? port : einval();
|
||||
}
|
45
libc/sock/poll-nt.c
Normal file
45
libc/sock/poll-nt.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/struct/pollfd.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int poll$nt(struct pollfd *fds, uint64_t nfds, int32_t timeout_ms) {
|
||||
int got;
|
||||
size_t i;
|
||||
struct pollfd$nt ntfds[64];
|
||||
if (nfds > 64) return einval();
|
||||
for (i = 0; i < nfds; ++i) {
|
||||
if (!isfdkind(fds[i].fd, kFdSocket)) return ebadf();
|
||||
ntfds[i].handle = g_fds.p[fds[i].fd].handle;
|
||||
ntfds[i].events = fds[i].events & (POLLPRI | POLLIN | POLLOUT);
|
||||
}
|
||||
if ((got = WSAPoll(ntfds, nfds, timeout_ms)) != -1) {
|
||||
for (i = 0; i < nfds; ++i) {
|
||||
fds[i].revents = ntfds[i].revents;
|
||||
}
|
||||
return got;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
46
libc/sock/poll.c
Normal file
46
libc/sock/poll.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
/**
|
||||
* Waits for something to happen on multiple file descriptors at once.
|
||||
*
|
||||
* @param fds[𝑖].fd should have been created with SOCK_NONBLOCK passed
|
||||
* to socket() or accept4()
|
||||
* @param fds[𝑖].events flags can have POLL{IN,OUT,PRI}
|
||||
* @param timeout_ms if 0 means don't wait and -1 means wait forever
|
||||
* @return number of items fds whose revents field has been set to
|
||||
* nonzero to describe its events, or -1 w/ errno
|
||||
* @return fds[𝑖].revents flags can have:
|
||||
* (fds[𝑖].events & POLL{IN,OUT,PRI,HUP,ERR,NVAL})
|
||||
* @asyncsignalsafe
|
||||
* @see ppoll()
|
||||
*/
|
||||
int poll(struct pollfd *fds, uint64_t nfds, int32_t timeout_ms) {
|
||||
if (!IsWindows()) {
|
||||
return poll$sysv(fds, nfds, timeout_ms);
|
||||
} else {
|
||||
return poll$nt(fds, nfds, timeout_ms);
|
||||
}
|
||||
}
|
36
libc/sock/recv.c
Normal file
36
libc/sock/recv.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
/**
|
||||
* Receives data from network socket.
|
||||
*
|
||||
* @param fd is the file descriptor returned by socket()
|
||||
* @param buf is where received network data gets copied
|
||||
* @param size is the byte capacity of buf
|
||||
* @param flags can have MSG_{WAITALL,PEEK,OOB}, etc.
|
||||
* @return number of bytes received, 0 on remote close, or -1 w/ errno
|
||||
* @error EINTR, EHOSTUNREACH, ECONNRESET (UDP ICMP Port Unreachable),
|
||||
* EPIPE (if MSG_NOSIGNAL), EMSGSIZE, ENOTSOCK, EFAULT, etc.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
ssize_t recv(int fd, void *buf, size_t size, int flags) {
|
||||
return recvfrom(fd, buf, size, flags, NULL, 0);
|
||||
}
|
43
libc/sock/recvfrom-nt.c
Normal file
43
libc/sock/recvfrom-nt.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
/**
|
||||
* Performs recv(), recvfrom(), or readv() on Windows NT.
|
||||
*
|
||||
* @param fd must be a socket
|
||||
* @return number of bytes received, or -1 w/ errno
|
||||
*/
|
||||
textwindows ssize_t recvfrom$nt(struct Fd *fd, const struct iovec *iov,
|
||||
size_t iovlen, uint32_t flags,
|
||||
void *opt_out_srcaddr,
|
||||
uint32_t *opt_inout_srcaddrsize) {
|
||||
uint32_t got;
|
||||
struct iovec$nt iovnt[16];
|
||||
got = 0;
|
||||
if (WSARecvFrom(fd->handle, iovnt, iovec2nt(iovnt, iov, iovlen), &got, &flags,
|
||||
opt_out_srcaddr, opt_inout_srcaddrsize, NULL, NULL) != -1) {
|
||||
return got;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
60
libc/sock/recvfrom.c
Normal file
60
libc/sock/recvfrom.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Receives data from network.
|
||||
*
|
||||
* This function blocks unless MSG_DONTWAIT is passed.
|
||||
*
|
||||
* @param fd is the file descriptor returned by socket()
|
||||
* @param buf is where received network data gets copied
|
||||
* @param size is the byte capacity of buf
|
||||
* @param flags can have MSG_{WAITALL,DONTROUTE,PEEK,OOB}, etc.
|
||||
* @param opt_out_srcaddr receives the binary ip:port of the data's origin
|
||||
* @param opt_inout_srcaddrsize is srcaddr capacity which gets updated
|
||||
* @return number of bytes received, 0 on remote close, or -1 w/ errno
|
||||
* @error EINTR, EHOSTUNREACH, ECONNRESET (UDP ICMP Port Unreachable),
|
||||
* EPIPE (if MSG_NOSIGNAL), EMSGSIZE, ENOTSOCK, EFAULT, etc.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
ssize_t recvfrom(int fd, void *buf, size_t size, uint32_t flags,
|
||||
void *opt_out_srcaddr, uint32_t *opt_inout_srcaddrsize) {
|
||||
ssize_t got;
|
||||
if (!IsWindows()) {
|
||||
got = recvfrom$sysv(fd, buf, size, flags, opt_out_srcaddr,
|
||||
opt_inout_srcaddrsize);
|
||||
if (opt_out_srcaddr && IsBsd() && got != -1) {
|
||||
sockaddr2linux(opt_out_srcaddr);
|
||||
}
|
||||
return got;
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return recvfrom$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, flags,
|
||||
opt_out_srcaddr, opt_inout_srcaddrsize);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
28
libc/sock/select.c
Normal file
28
libc/sock/select.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
struct timeval *timeout) {
|
||||
/* TODO(jart): Windows */
|
||||
return select$sysv(nfds, readfds, writefds, exceptfds, timeout);
|
||||
}
|
36
libc/sock/send.c
Normal file
36
libc/sock/send.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
/**
|
||||
* Sends data to network socket.
|
||||
*
|
||||
* @param fd is the file descriptor returned by socket()
|
||||
* @param buf is the data to send, which we'll copy if necessary
|
||||
* @param size is the byte-length of buf
|
||||
* @param flags MSG_OOB, MSG_DONTROUTE, MSG_PARTIAL, MSG_NOSIGNAL, etc.
|
||||
* @return number of bytes transmitted, or -1 w/ errno
|
||||
* @error EINTR, EHOSTUNREACH, ECONNRESET (UDP ICMP Port Unreachable),
|
||||
* EPIPE (if MSG_NOSIGNAL), EMSGSIZE, ENOTSOCK, EFAULT, etc.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
ssize_t send(int fd, const void *buf, size_t size, int flags) {
|
||||
return sendto(fd, buf, size, flags, NULL, 0);
|
||||
}
|
101
libc/sock/sendfile.c
Normal file
101
libc/sock/sendfile.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows ssize_t sendfile$linux2nt(int outfd, int infd,
|
||||
int64_t *inout_opt_inoffset,
|
||||
size_t uptobytes) {
|
||||
struct NtOverlapped Overlapped;
|
||||
struct NtOverlapped *lpOverlapped;
|
||||
if (!isfdkind(outfd, kFdSocket) || !isfdkind(outfd, kFdFile)) return ebadf();
|
||||
if (inout_opt_inoffset) {
|
||||
memset(&Overlapped, 0, sizeof(Overlapped));
|
||||
Overlapped.Pointer = (void *)(intptr_t)(*inout_opt_inoffset);
|
||||
lpOverlapped = &Overlapped;
|
||||
} else {
|
||||
lpOverlapped = NULL;
|
||||
}
|
||||
/* TODO(jart): Fetch this on a per-socket basis via GUID. */
|
||||
if (TransmitFile(g_fds.p[outfd].handle, g_fds.p[infd].handle, uptobytes, 0,
|
||||
lpOverlapped, NULL, 0)) {
|
||||
return uptobytes;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t sendfile$linux2netflix(int outfd, int infd,
|
||||
int64_t *inout_opt_inoffset,
|
||||
size_t uptobytes) {
|
||||
int sendfile$netflix(int32_t infd, int32_t outfd, int64_t offset,
|
||||
size_t nbytes, const void *opt_hdtr,
|
||||
int64_t *out_opt_sbytes,
|
||||
int32_t flags) asm("sendfile$sysv") hidden;
|
||||
int rc;
|
||||
int64_t offset, sbytes;
|
||||
if (inout_opt_inoffset) {
|
||||
offset = *inout_opt_inoffset;
|
||||
} else if ((offset = lseek$sysv(infd, 0, SEEK_CUR)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
if ((rc = sendfile$netflix(infd, outfd, offset, uptobytes, NULL, &sbytes,
|
||||
0)) != -1) {
|
||||
if (inout_opt_inoffset) *inout_opt_inoffset += sbytes;
|
||||
return sbytes;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers data from file to network.
|
||||
*
|
||||
* @param outfd needs to be a socket
|
||||
* @param infd needs to be a file
|
||||
* @param inout_opt_inoffset may be specified for pread()-like behavior
|
||||
* @param uptobytes is usually the number of bytes remaining in file; it
|
||||
* can't exceed INT_MAX-1; some platforms block until everything's
|
||||
* sent, whereas others won't; zero isn't allowed
|
||||
* @return number of bytes transmitted which may be fewer than requested
|
||||
* @see copy_file_range() for file ↔ file
|
||||
* @see splice() for fd ↔ pipe
|
||||
*/
|
||||
ssize_t sendfile(int outfd, int infd, int64_t *inout_opt_inoffset,
|
||||
size_t uptobytes) {
|
||||
if (!uptobytes) return einval();
|
||||
if (uptobytes > 0x7ffffffe /* Microsoft's off-by-one */) return eoverflow();
|
||||
if (IsModeDbg() && uptobytes > 1) uptobytes >>= 1;
|
||||
if (IsLinux()) {
|
||||
return sendfile$sysv(outfd, infd, inout_opt_inoffset, uptobytes);
|
||||
} else if (IsFreebsd() || IsXnu()) {
|
||||
return sendfile$linux2netflix(outfd, infd, inout_opt_inoffset, uptobytes);
|
||||
} else if (IsWindows()) {
|
||||
return sendfile$linux2nt(outfd, infd, inout_opt_inoffset, uptobytes);
|
||||
} else {
|
||||
return copyfd(infd, inout_opt_inoffset, outfd, NULL, uptobytes, 0);
|
||||
}
|
||||
}
|
41
libc/sock/sendto-nt.c
Normal file
41
libc/sock/sendto-nt.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
/**
|
||||
* Performs send(), sendto(), or writev() on Windows NT.
|
||||
*
|
||||
* @param fd must be a socket
|
||||
* @return number of bytes handed off, or -1 w/ errno
|
||||
*/
|
||||
textwindows ssize_t sendto$nt(struct Fd *fd, const struct iovec *iov,
|
||||
size_t iovlen, uint32_t flags, void *opt_in_addr,
|
||||
uint32_t *in_addrsize) {
|
||||
uint32_t sent;
|
||||
struct iovec$nt iovnt[16];
|
||||
if (WSASendTo(fd->handle, iovnt, iovec2nt(iovnt, iov, iovlen), &sent, flags,
|
||||
opt_in_addr, *in_addrsize, NULL, NULL) != -1) {
|
||||
return sent;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
67
libc/sock/sendto.c
Normal file
67
libc/sock/sendto.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sends data over network.
|
||||
*
|
||||
* This function blocks unless MSG_DONTWAIT is passed. In that case, the
|
||||
* non-error EWOULDBLOCK might be returned. It basically means we didn't
|
||||
* wait around to learn an amount of bytes were written that we know in
|
||||
* advance are guaranteed to be atomic.
|
||||
*
|
||||
* @param fd is the file descriptor returned by socket()
|
||||
* @param buf is the data to send, which we'll copy if necessary
|
||||
* @param size is the byte-length of buf
|
||||
* @param flags MSG_OOB, MSG_DONTROUTE, MSG_PARTIAL, MSG_NOSIGNAL, etc.
|
||||
* @param opt_addr is a binary ip:port destination override, which is
|
||||
* mandatory for UDP if connect() wasn't called
|
||||
* @param addrsize is the byte-length of addr's true polymorphic form
|
||||
* @return number of bytes transmitted, or -1 w/ errno
|
||||
* @error EINTR, EHOSTUNREACH, ECONNRESET (UDP ICMP Port Unreachable),
|
||||
* EPIPE (if MSG_NOSIGNAL), EMSGSIZE, ENOTSOCK, EFAULT, etc.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
ssize_t sendto(int fd, const void *buf, size_t size, uint32_t flags,
|
||||
const void *opt_addr, uint32_t addrsize) {
|
||||
static_assert(sizeof(struct sockaddr_in) == sizeof(struct sockaddr_in$bsd));
|
||||
if (!IsWindows()) {
|
||||
if (!IsBsd() || !opt_addr) {
|
||||
return sendto$sysv(fd, buf, size, flags, opt_addr, addrsize);
|
||||
} else {
|
||||
struct sockaddr_in$bsd addr2;
|
||||
if (addrsize != sizeof(addr2)) return einval();
|
||||
memcpy(&addr2, opt_addr, sizeof(struct sockaddr_in));
|
||||
sockaddr2bsd(&addr2);
|
||||
return sendto$sysv(fd, buf, size, flags, &addr2, addrsize);
|
||||
}
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return sendto$nt(&g_fds.p[fd], (struct iovec[]){{buf, size}}, 1, flags,
|
||||
opt_addr, &addrsize);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
77
libc/sock/setsockopt.c
Normal file
77
libc/sock/setsockopt.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static bool setsockopt_polyfill(int *optname) {
|
||||
if (errno == ENOPROTOOPT && *optname == SO_REUSEPORT /* RHEL5 */) {
|
||||
*optname = SO_REUSEADDR; /* close enough */
|
||||
return true; /* fudges errno */
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static textwindows int setsockopt$nt(struct Fd *fd, int level, int optname,
|
||||
const void *optval, uint32_t optlen) {
|
||||
if (__setsockopt$nt(fd->handle, level, optname, optval, optlen) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies socket settings.
|
||||
*
|
||||
* This function is the ultimate rabbit hole. Basic usage:
|
||||
*
|
||||
* int yes = 1;
|
||||
* setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
|
||||
*
|
||||
* @param level can be SOL_SOCKET, IPPROTO_TCP, etc.
|
||||
* @param optname can be SO_{REUSE{PORT,ADDR},KEEPALIVE,etc.} etc.
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @error ENOPROTOOPT for unknown (level,optname)
|
||||
* @see libc/sysv/consts.sh for tuning catalogue
|
||||
* @see getsockopt()
|
||||
*/
|
||||
int setsockopt(int fd, int level, int optname, const void *optval,
|
||||
uint32_t optlen) {
|
||||
if (!level || !optname) return enoprotoopt(); /* our sysvconsts definition */
|
||||
if (optname == -1) return 0; /* our sysvconsts definition */
|
||||
if (!IsWindows()) {
|
||||
do {
|
||||
if (setsockopt$sysv(fd, level, optname, optval, optlen) != -1) {
|
||||
return 0;
|
||||
}
|
||||
} while (setsockopt_polyfill(&optname));
|
||||
return -1;
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return setsockopt$nt(&g_fds.p[fd], level, optname, optval, optlen);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
56
libc/sock/shutdown.c
Normal file
56
libc/sock/shutdown.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static int shutdown$nt(struct Fd *fd, int how) {
|
||||
if (__shutdown$nt(fd->handle, how) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables sends or receives on a socket, without closing.
|
||||
*
|
||||
* @param fd is the open file descriptor for the socket
|
||||
* @param how can be SHUT_RD, SHUT_WR, or SHUT_RDWR
|
||||
* @return 0 on success or -1 on error
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int shutdown(int fd, int how) {
|
||||
if (!IsWindows()) {
|
||||
if (!IsXnu()) {
|
||||
return shutdown$sysv(fd, how);
|
||||
} else {
|
||||
/* TODO(jart): What's wrong with XNU shutdown()? */
|
||||
return 0;
|
||||
}
|
||||
} else if (isfdkind(fd, kFdSocket)) {
|
||||
return shutdown$nt(&g_fds.p[fd], how);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
99
libc/sock/sock.h
Normal file
99
libc/sock/sock.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SOCK_SOCK_H_
|
||||
#define COSMOPOLITAN_LIBC_SOCK_SOCK_H_
|
||||
#include "libc/bits/bits.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § system api » berkeley sockets ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define INET_ADDRSTRLEN 22
|
||||
|
||||
#define NI_DGRAM 0x10
|
||||
#define NI_MAXSERV 0x20
|
||||
|
||||
#define htons(u16) bswap_16(u16)
|
||||
#define ntohs(u16) bswap_16(u16)
|
||||
#define htonl(u32) bswap_32(u32)
|
||||
#define ntohl(u32) bswap_32(u32)
|
||||
|
||||
struct iovec;
|
||||
struct sigset;
|
||||
struct timespec;
|
||||
struct timeval;
|
||||
struct addrinfo;
|
||||
|
||||
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 pollfd {
|
||||
int32_t fd;
|
||||
int16_t events;
|
||||
int16_t revents;
|
||||
};
|
||||
|
||||
struct msghdr { /* Linux+NT ABI */
|
||||
void *msg_name; /* optional address */
|
||||
int32_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 */
|
||||
};
|
||||
|
||||
const char *inet_ntop(int, const void *, char *, uint32_t);
|
||||
int inet_pton(int af, const char *, void *);
|
||||
int parseport(const char *);
|
||||
|
||||
int socket(int, int, int) nodiscard;
|
||||
int accept(int, void *, uint32_t *) paramsnonnull() nodiscard;
|
||||
int accept4(int, void *, uint32_t *, int) paramsnonnull() nodiscard;
|
||||
int bind(int, const void *, uint32_t) paramsnonnull();
|
||||
int connect(int, const void *, uint32_t) paramsnonnull();
|
||||
int socketconnect(const struct addrinfo *, int);
|
||||
int listen(int, int);
|
||||
int shutdown(int, int);
|
||||
int getsockname(int, void *, uint32_t *) paramsnonnull();
|
||||
int getpeername(int, void *, uint32_t *) paramsnonnull();
|
||||
ssize_t send(int, const void *, size_t, int) paramsnonnull();
|
||||
ssize_t recv(int, void *, size_t, int);
|
||||
ssize_t recvmsg(int, struct msghdr *, uint32_t) paramsnonnull();
|
||||
ssize_t recvfrom(int, void *, size_t, uint32_t, void *, uint32_t *);
|
||||
ssize_t sendmsg(int, const struct msghdr *, int) paramsnonnull();
|
||||
ssize_t readv(int, const struct iovec *, int);
|
||||
ssize_t writev(int, const struct iovec *, int);
|
||||
ssize_t sendfile(int, int, int64_t *, size_t);
|
||||
int getsockopt(int, int, int, void *, uint32_t *) paramsnonnull((5));
|
||||
int setsockopt(int, int, int, const void *, uint32_t) paramsnonnull();
|
||||
int socketpair(int, int, int, int64_t[2]) paramsnonnull();
|
||||
int poll(struct pollfd *, uint64_t, int32_t) paramsnonnull();
|
||||
int ppoll(struct pollfd *, uint64_t, const struct timespec *,
|
||||
const struct sigset *) paramsnonnull((1, 4));
|
||||
ssize_t sendto(int, const void *, size_t, uint32_t, const void *, uint32_t)
|
||||
paramsnonnull((2));
|
||||
|
||||
typedef int64_t fd_set;
|
||||
#define FD_CLR(FD, SET) btr(SET, FD)
|
||||
#define FD_ISSET(FD, SET) bt(SET, FD)
|
||||
#define FD_SET(FD, SET) bts(SET, FD)
|
||||
#define FD_ZERO(SET) *(SET) = 0
|
||||
int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SOCK_SOCK_H_ */
|
55
libc/sock/sock.mk
Normal file
55
libc/sock/sock.mk
Normal file
|
@ -0,0 +1,55 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
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_HDRS = $(filter %.h,$(LIBC_SOCK_A_FILES))
|
||||
LIBC_SOCK_A_SRCS = $(filter %.c,$(LIBC_SOCK_A_FILES))
|
||||
|
||||
LIBC_SOCK_A_OBJS = \
|
||||
$(LIBC_SOCK_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(LIBC_SOCK_A_SRCS:%.c=o/$(MODE)/%.o)
|
||||
|
||||
LIBC_SOCK_A_CHECKS = \
|
||||
$(LIBC_SOCK_A).pkg \
|
||||
$(LIBC_SOCK_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
LIBC_SOCK_A_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_CONV \
|
||||
LIBC_FMT \
|
||||
LIBC_MEM \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STUBS \
|
||||
LIBC_NT_KERNELBASE \
|
||||
LIBC_NT_WS2_32 \
|
||||
LIBC_NT_MSWSOCK \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_SYSV
|
||||
|
||||
LIBC_SOCK_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_SOCK_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_SOCK_A): libc/sock/ \
|
||||
$(LIBC_SOCK_A).pkg \
|
||||
$(LIBC_SOCK_A_OBJS)
|
||||
|
||||
$(LIBC_SOCK_A).pkg: \
|
||||
$(LIBC_SOCK_A_OBJS) \
|
||||
$(foreach x,$(LIBC_SOCK_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
LIBC_SOCK_LIBS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)))
|
||||
LIBC_SOCK_SRCS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_SOCK_HDRS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_SOCK_CHECKS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_SOCK_OBJS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_OBJS))
|
||||
$(LIBC_SOCK_OBJS): $(BUILD_FILES) libc/sock/sock.mk
|
||||
|
||||
.PHONY: o/$(MODE)/libc/sock
|
||||
o/$(MODE)/libc/sock: $(LIBC_SOCK_CHECKS)
|
50
libc/sock/socket-nt.c
Normal file
50
libc/sock/socket-nt.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
|
||||
STATIC_YOINK("closesocket$nt");
|
||||
STATIC_YOINK("kNtWsaData");
|
||||
STATIC_YOINK("recvfrom$nt");
|
||||
STATIC_YOINK("sendto$nt");
|
||||
|
||||
textwindows int socket$nt(int family, int type, int protocol) {
|
||||
int fd;
|
||||
if ((fd = createfd()) == -1) return -1;
|
||||
if ((g_fds.p[fd].handle =
|
||||
WSASocket(family, type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK), protocol,
|
||||
NULL, 0, (type & SOCK_CLOEXEC))) != -1) {
|
||||
if (type & SOCK_NONBLOCK) {
|
||||
uint32_t yes = 1;
|
||||
if (__ioctlsocket$nt(g_fds.p[fd].handle, FIONBIO, &yes) == -1) {
|
||||
__closesocket$nt(g_fds.p[fd].handle);
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
||||
g_fds.p[fd].kind = kFdSocket;
|
||||
g_fds.p[fd].flags = type;
|
||||
return fd;
|
||||
} else {
|
||||
return winsockerr();
|
||||
}
|
||||
}
|
37
libc/sock/socket-sysv.c
Normal file
37
libc/sock/socket-sysv.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
|
||||
int socket$sysv(int family, int type, int protocol) {
|
||||
int rc, olderr, modernflags;
|
||||
olderr = errno;
|
||||
rc = __socket$sysv(family, type, protocol);
|
||||
if ((SupportsLinux() || SupportsXnu()) &&
|
||||
(rc == -1 && errno == EINVAL /* rhel5 behavior */) &&
|
||||
(modernflags = (type & (SOCK_CLOEXEC | SOCK_NONBLOCK)))) {
|
||||
errno = olderr;
|
||||
rc = fixupnewsockfd$sysv(
|
||||
__socket$sysv(family, type & ~modernflags, protocol), modernflags);
|
||||
}
|
||||
return rc;
|
||||
}
|
53
libc/sock/socket.c
Normal file
53
libc/sock/socket.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Creates new system resource for network communication.
|
||||
*
|
||||
* @param family can be AF_UNIX, AF_INET, etc.
|
||||
* @param type can be SOCK_STREAM (for TCP), SOCK_DGRAM (e.g. UDP), or
|
||||
* SOCK_RAW (IP) so long as IP_HDRINCL was passed to setsockopt();
|
||||
* and additionally, may be or'd with SOCK_NONBLOCK, SOCK_CLOEXEC
|
||||
* @param protocol can be IPPROTO_TCP, IPPROTO_UDP, or IPPROTO_ICMP
|
||||
* @return socket file descriptor or -1 w/ errno
|
||||
* @error ENETDOWN, EPFNOSUPPORT, etc.
|
||||
* @see libc/sysv/consts.sh
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int socket(int family, int type, int protocol) {
|
||||
if (family == AF_UNSPEC) {
|
||||
family = AF_INET;
|
||||
} else if (family == AF_INET6) {
|
||||
/* Recommend IPv6 on frontend serving infrastructure only. That's
|
||||
what Google Cloud does. It's more secure. It also means poll()
|
||||
will work on Windows, which doesn't allow mixing third layers. */
|
||||
return epfnosupport();
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return socket$sysv(family, type, protocol);
|
||||
} else {
|
||||
return socket$nt(family, type, protocol);
|
||||
}
|
||||
}
|
42
libc/sock/socketconnect.c
Normal file
42
libc/sock/socketconnect.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dns/dns.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
/**
|
||||
* Opens socket client connection.
|
||||
*
|
||||
* @param ai can be obtained via getaddrinfo()
|
||||
* @return socket file descriptor, or -1 w/ errno
|
||||
*/
|
||||
int socketconnect(const struct addrinfo *ai, int flags) {
|
||||
int fd;
|
||||
fd = socket(ai->ai_family, ai->ai_socktype | flags, ai->ai_protocol);
|
||||
if (fd != -1) {
|
||||
if (connect(fd, ai->ai_addr, ai->ai_addrlen) != -1 ||
|
||||
errno == EINPROGRESS) {
|
||||
return fd;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
return -1;
|
||||
}
|
46
libc/sock/winsockblock.c
Normal file
46
libc/sock/winsockblock.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
textwindows int64_t winsockblock(int64_t fh, unsigned eventbit, int64_t rc) {
|
||||
int64_t eh;
|
||||
struct NtWsaNetworkEvents ev;
|
||||
if (rc != -1) return rc;
|
||||
if (WSAGetLastError() != EWOULDBLOCK) return winsockerr();
|
||||
eh = WSACreateEvent();
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
if (WSAEventSelect(fh, eh, 1u << eventbit) != -1 &&
|
||||
WSAEnumNetworkEvents(fh, eh, &ev) != -1) {
|
||||
if (!ev.iErrorCode[eventbit]) {
|
||||
rc = 0;
|
||||
} else {
|
||||
errno = ev.iErrorCode[eventbit];
|
||||
}
|
||||
} else {
|
||||
winsockerr();
|
||||
}
|
||||
WSACloseEvent(eh);
|
||||
return rc;
|
||||
}
|
30
libc/sock/winsockerr.c
Normal file
30
libc/sock/winsockerr.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
||||
/**
|
||||
* Error return path for winsock wrappers.
|
||||
*/
|
||||
textwindows int64_t winsockerr(void) {
|
||||
errno = WSAGetLastError();
|
||||
return -1;
|
||||
}
|
41
libc/sock/xinet_ntop.c
Normal file
41
libc/sock/xinet_ntop.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
/**
|
||||
* Formats internet address to string, or dies.
|
||||
*
|
||||
* @param af can be AF_INET, e.g. addr->sin_family
|
||||
* @param src is the binary-encoded address, e.g. &addr->sin_addr
|
||||
* @return allocated IP address string, which must be free()'d
|
||||
*/
|
||||
char *xinet_ntop(int af, const void *src) {
|
||||
char *res, ip[16];
|
||||
if (inet_ntop(af, src, ip, sizeof(ip)) && (res = strdup(ip))) {
|
||||
return res;
|
||||
} else {
|
||||
if (weaken(die)) weaken(die)();
|
||||
abort();
|
||||
unreachable;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue