mirror of
https://github.com/wassname/ray.git
synced 2026-07-10 09:24:33 +08:00
Platform shims for Windows (#6548)
* Platform shims for Windows * Satisfy linter
This commit is contained in:
@@ -186,6 +186,9 @@ cc_library(
|
||||
],
|
||||
strip_include_prefix = "cpp/src",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@com_github_ray_project_ray//:platform_shims",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef INET_H
|
||||
#define INET_H
|
||||
|
||||
#endif /* INET_H */
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
From:
|
||||
http://stackoverflow.com/a/17195644/541686
|
||||
Also posted on:
|
||||
https://gist.github.com/superwills/5815344
|
||||
Previously from:
|
||||
http://www.raspberryginger.com/jbailey/minix/html/lib_2posix_2getopt_8c-source.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int opterr = 1, /* if error message should be printed */
|
||||
optind = 1, /* index into parent argv vector */
|
||||
optopt, /* character checked for validity */
|
||||
optreset; /* reset getopt */
|
||||
char *optarg; /* argument associated with option */
|
||||
|
||||
#define BADCH (int)'?'
|
||||
#define BADARG (int)':'
|
||||
static char EMSG[] = "";
|
||||
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int getopt(int nargc, char *const nargv[], const char *ostr) {
|
||||
static char *place = EMSG; /* option letter processing */
|
||||
const char *oli; /* option letter list index */
|
||||
|
||||
if (optreset || !*place) { /* update scanning pointer */
|
||||
optreset = 0;
|
||||
if (optind >= nargc || *(place = nargv[optind]) != '-') {
|
||||
place = EMSG;
|
||||
return (-1);
|
||||
}
|
||||
if (place[1] && *++place == '-') { /* found "--" */
|
||||
++optind;
|
||||
place = EMSG;
|
||||
return (-1);
|
||||
}
|
||||
} /* option letter okay? */
|
||||
if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr, optopt))) {
|
||||
/*
|
||||
* if the user didn't specify '-' as an option,
|
||||
* assume it means -1.
|
||||
*/
|
||||
if (optopt == (int)'-') return (-1);
|
||||
if (!*place) ++optind;
|
||||
if (opterr && *ostr != ':') (void)printf("illegal option -- %c\n", optopt);
|
||||
return (BADCH);
|
||||
}
|
||||
if (*++oli != ':') { /* don't need argument */
|
||||
optarg = NULL;
|
||||
if (!*place) ++optind;
|
||||
} else { /* need an argument */
|
||||
if (*place) /* no white space */
|
||||
optarg = place;
|
||||
else if (nargc <= ++optind) { /* no arg */
|
||||
place = EMSG;
|
||||
if (*ostr == ':') return (BADARG);
|
||||
if (opterr) (void)printf("option requires an argument -- %c\n", optopt);
|
||||
return (BADCH);
|
||||
} else /* white space */
|
||||
optarg = nargv[optind];
|
||||
place = EMSG;
|
||||
++optind;
|
||||
}
|
||||
return (optopt); /* dump back option letter */
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef GETOPT_H
|
||||
#define GETOPT_H
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
int getopt(int nargc, char *const nargv[], const char *ostr);
|
||||
|
||||
#endif /* GETOPT_H */
|
||||
@@ -0,0 +1,190 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <Winsock2.h> // include before other socket headers on Windows
|
||||
|
||||
#include <iphlpapi.h>
|
||||
#include <tcpmib.h>
|
||||
|
||||
#pragma comment(lib, "IPHlpAPI.lib")
|
||||
|
||||
int socketpair(int domain, int type, int protocol, int sv[2]) {
|
||||
if ((domain != AF_UNIX && domain != AF_INET) || type != SOCK_STREAM) {
|
||||
return (int)INVALID_SOCKET;
|
||||
}
|
||||
SOCKET sockets[2];
|
||||
int r = dumb_socketpair(sockets);
|
||||
sv[0] = (int)sockets[0];
|
||||
sv[1] = (int)sockets[1];
|
||||
return r;
|
||||
}
|
||||
|
||||
static DWORD getsockpid(SOCKET client) {
|
||||
/* http://stackoverflow.com/a/25431340 */
|
||||
DWORD pid = 0;
|
||||
|
||||
struct sockaddr_in Server = {0};
|
||||
int ServerSize = sizeof(Server);
|
||||
|
||||
struct sockaddr_in Client = {0};
|
||||
int ClientSize = sizeof(Client);
|
||||
|
||||
if ((getsockname(client, (struct sockaddr *)&Server, &ServerSize) == 0) &&
|
||||
(getpeername(client, (struct sockaddr *)&Client, &ClientSize) == 0)) {
|
||||
struct _MIB_TCPTABLE2 *TcpTable = NULL;
|
||||
ULONG TcpTableSize = 0;
|
||||
ULONG result;
|
||||
do {
|
||||
result = GetTcpTable2(TcpTable, &TcpTableSize, TRUE);
|
||||
if (result != ERROR_INSUFFICIENT_BUFFER) {
|
||||
break;
|
||||
}
|
||||
free(TcpTable);
|
||||
TcpTable = (struct _MIB_TCPTABLE2 *)malloc(TcpTableSize);
|
||||
} while (TcpTable != NULL);
|
||||
|
||||
if (result == NO_ERROR) {
|
||||
for (DWORD dw = 0; dw < TcpTable->dwNumEntries; ++dw) {
|
||||
struct _MIB_TCPROW2 *row = &(TcpTable->table[dw]);
|
||||
if ((row->dwState == 5 /* MIB_TCP_STATE_ESTAB */) &&
|
||||
(row->dwLocalAddr == Client.sin_addr.s_addr) &&
|
||||
((row->dwLocalPort & 0xFFFF) == Client.sin_port) &&
|
||||
(row->dwRemoteAddr == Server.sin_addr.s_addr) &&
|
||||
((row->dwRemotePort & 0xFFFF) == Server.sin_port)) {
|
||||
pid = row->dwOwningPid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(TcpTable);
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags) {
|
||||
ssize_t result = -1;
|
||||
struct cmsghdr *header = CMSG_FIRSTHDR(msg);
|
||||
if (header->cmsg_level == SOL_SOCKET && header->cmsg_type == SCM_RIGHTS) {
|
||||
/* We're trying to send over a handle of some kind.
|
||||
* We have to look up which process we're communicating with,
|
||||
* open a handle to it, and then duplicate our handle into it.
|
||||
* However, the first two steps cannot be done atomically.
|
||||
* Therefore, this code HAS A RACE CONDITIONS and is therefore NOT SECURE.
|
||||
* In the absense of a malicious actor, though, it is exceedingly unlikely
|
||||
* that the child process closes AND that its process ID is reassigned
|
||||
* to another existing process.
|
||||
*/
|
||||
struct msghdr const old_msg = *msg;
|
||||
int *const pfd = (int *)CMSG_DATA(header);
|
||||
msg->msg_control = NULL;
|
||||
msg->msg_controllen = 0;
|
||||
WSAPROTOCOL_INFO protocol_info = {0};
|
||||
/* assume socket if it's a pipe, until proven otherwise */
|
||||
BOOL is_socket = GetFileType((HANDLE)(SOCKET)(*pfd)) == FILE_TYPE_PIPE;
|
||||
DWORD const target_pid = getsockpid(sockfd);
|
||||
HANDLE target_process = NULL;
|
||||
if (target_pid) {
|
||||
if (is_socket) {
|
||||
result = WSADuplicateSocket(*pfd, target_pid, &protocol_info);
|
||||
if (result == -1 && WSAGetLastError() == WSAENOTSOCK) {
|
||||
is_socket = FALSE;
|
||||
}
|
||||
}
|
||||
if (!is_socket) {
|
||||
/* This is a regular handle... fit it into the same struct */
|
||||
target_process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, target_pid);
|
||||
if (target_process) {
|
||||
if (DuplicateHandle(GetCurrentProcess(), (HANDLE)(intptr_t)*pfd, target_process,
|
||||
(HANDLE *)&protocol_info, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == 0) {
|
||||
int const nbufs = msg->dwBufferCount + 1;
|
||||
WSABUF *const bufs = (struct _WSABUF *)_alloca(sizeof(*msg->lpBuffers) * nbufs);
|
||||
bufs[0].buf = (char *)&protocol_info;
|
||||
bufs[0].len = sizeof(protocol_info);
|
||||
memcpy(&bufs[1], msg->lpBuffers, msg->dwBufferCount * sizeof(*msg->lpBuffers));
|
||||
DWORD nb;
|
||||
msg->lpBuffers = bufs;
|
||||
msg->dwBufferCount = nbufs;
|
||||
GUID wsaid_WSASendMsg = {
|
||||
0xa441e712, 0x754f, 0x43ca, {0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d}};
|
||||
typedef INT PASCAL WSASendMsg_t(
|
||||
SOCKET s, LPWSAMSG lpMsg, DWORD dwFlags, LPDWORD lpNumberOfBytesSent,
|
||||
LPWSAOVERLAPPED lpOverlapped,
|
||||
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
|
||||
WSASendMsg_t *WSASendMsg = NULL;
|
||||
result = WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid_WSASendMsg,
|
||||
sizeof(wsaid_WSASendMsg), &WSASendMsg, sizeof(WSASendMsg), &nb,
|
||||
NULL, 0);
|
||||
if (result == 0) {
|
||||
result = (*WSASendMsg)(sockfd, msg, flags, &nb, NULL, NULL) == 0
|
||||
? (ssize_t)(nb - sizeof(protocol_info))
|
||||
: 0;
|
||||
}
|
||||
}
|
||||
if (result != 0 && target_process && !is_socket) {
|
||||
/* we failed to send the handle, and it needs cleaning up! */
|
||||
HANDLE duplicated_back = NULL;
|
||||
if (DuplicateHandle(target_process, *(HANDLE *)&protocol_info, GetCurrentProcess(),
|
||||
&duplicated_back, 0, FALSE, DUPLICATE_CLOSE_SOURCE)) {
|
||||
CloseHandle(duplicated_back);
|
||||
}
|
||||
}
|
||||
if (target_process) {
|
||||
CloseHandle(target_process);
|
||||
}
|
||||
*msg = old_msg;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) {
|
||||
int result = -1;
|
||||
struct cmsghdr *header = CMSG_FIRSTHDR(msg);
|
||||
if (msg->msg_controllen && flags == 0 /* We can't send flags on Windows... */) {
|
||||
struct msghdr const old_msg = *msg;
|
||||
msg->msg_control = NULL;
|
||||
msg->msg_controllen = 0;
|
||||
WSAPROTOCOL_INFO protocol_info = {0};
|
||||
int const nbufs = msg->dwBufferCount + 1;
|
||||
WSABUF *const bufs = (struct _WSABUF *)_alloca(sizeof(*msg->lpBuffers) * nbufs);
|
||||
bufs[0].buf = (char *)&protocol_info;
|
||||
bufs[0].len = sizeof(protocol_info);
|
||||
memcpy(&bufs[1], msg->lpBuffers, msg->dwBufferCount * sizeof(*msg->lpBuffers));
|
||||
typedef INT PASCAL WSARecvMsg_t(
|
||||
SOCKET s, LPWSAMSG lpMsg, LPDWORD lpNumberOfBytesRecvd,
|
||||
LPWSAOVERLAPPED lpOverlapped,
|
||||
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
|
||||
WSARecvMsg_t *WSARecvMsg = NULL;
|
||||
DWORD nb;
|
||||
GUID wsaid_WSARecvMsg = {
|
||||
0xf689d7c8, 0x6f1f, 0x436b, {0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22}};
|
||||
result =
|
||||
WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid_WSARecvMsg,
|
||||
sizeof(wsaid_WSARecvMsg), &WSARecvMsg, sizeof(WSARecvMsg), &nb, NULL, 0);
|
||||
if (result == 0) {
|
||||
result = (*WSARecvMsg)(sockfd, msg, &nb, NULL, NULL) == 0
|
||||
? (ssize_t)(nb - sizeof(protocol_info))
|
||||
: 0;
|
||||
}
|
||||
if (result == 0) {
|
||||
int *const pfd = (int *)CMSG_DATA(header);
|
||||
if (protocol_info.iSocketType == 0 && protocol_info.iProtocol == 0) {
|
||||
*pfd = *(int *)&protocol_info;
|
||||
} else {
|
||||
*pfd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
|
||||
&protocol_info, 0, 0);
|
||||
}
|
||||
header->cmsg_level = SOL_SOCKET;
|
||||
header->cmsg_type = SCM_RIGHTS;
|
||||
}
|
||||
*msg = old_msg;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef NETDB_H
|
||||
#define NETDB_H
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#endif /* NETDB_H */
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef IN_H
|
||||
#define IN_H
|
||||
|
||||
#endif /* IN_H */
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef TCP_H
|
||||
#define TCP_H
|
||||
|
||||
#endif /* TCP_H */
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef POLL_H
|
||||
#define POLL_H
|
||||
|
||||
typedef unsigned long int nfds_t;
|
||||
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
|
||||
|
||||
#endif /* POLL_H */
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef _PTHREAD_H
|
||||
#define _PTHREAD_H 1
|
||||
|
||||
#ifndef _INC_WINDOWS
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
typedef CRITICAL_SECTION pthread_mutex_t;
|
||||
|
||||
#endif /* pthread.h */
|
||||
@@ -0,0 +1,138 @@
|
||||
/* socketpair.c
|
||||
Copyright 2007, 2010 by Nathan C. Myers <ncm@cantrip.org>
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
The name of the author must not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Changes:
|
||||
* 2014-02-12: merge David Woodhouse, Ger Hobbelt improvements
|
||||
* git.infradead.org/users/dwmw2/openconnect.git/commitdiff/bdeefa54
|
||||
* github.com/GerHobbelt/selectable-socketpair
|
||||
* always init the socks[] to -1/INVALID_SOCKET on error, both on Win32/64
|
||||
* and UNIX/other platforms
|
||||
* 2013-07-18: Change to BSD 3-clause license
|
||||
* 2010-03-31:
|
||||
* set addr to 127.0.0.1 because win32 getsockname does not always set it.
|
||||
* 2010-02-25:
|
||||
* set SO_REUSEADDR option to avoid leaking some windows resource.
|
||||
* Windows System Error 10049, "Event ID 4226 TCP/IP has reached
|
||||
* the security limit imposed on the number of concurrent TCP connect
|
||||
* attempts." Bleah.
|
||||
* 2007-04-25:
|
||||
* preserve value of WSAGetLastError() on all error returns.
|
||||
* 2007-04-22: (Thanks to Matthew Gregan <kinetik@flim.org>)
|
||||
* s/EINVAL/WSAEINVAL/ fix trivial compile failure
|
||||
* s/socket/WSASocket/ enable creation of sockets suitable as stdin/stdout
|
||||
* of a child process.
|
||||
* add argument make_overlapped
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <io.h>
|
||||
#include <ws2tcpip.h> /* socklen_t, et al (MSVC20xx) */
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
/* dumb_socketpair:
|
||||
* If make_overlapped is nonzero, both sockets created will be usable for
|
||||
* "overlapped" operations via WSASend etc. If make_overlapped is zero,
|
||||
* socks[0] (only) will be usable with regular ReadFile etc., and thus
|
||||
* suitable for use as stdin or stdout of a child process. Note that the
|
||||
* sockets must be closed with closesocket() regardless.
|
||||
*/
|
||||
|
||||
int dumb_socketpair(SOCKET socks[2]) {
|
||||
union {
|
||||
struct sockaddr_in inaddr;
|
||||
struct sockaddr addr;
|
||||
} a;
|
||||
SOCKET listener;
|
||||
int e;
|
||||
socklen_t addrlen = sizeof(a.inaddr);
|
||||
int reuse = 1;
|
||||
|
||||
if (socks == 0) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
socks[0] = socks[1] = -1;
|
||||
|
||||
listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (listener == -1) return SOCKET_ERROR;
|
||||
|
||||
memset(&a, 0, sizeof(a));
|
||||
a.inaddr.sin_family = AF_INET;
|
||||
a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
a.inaddr.sin_port = 0;
|
||||
|
||||
for (;;) {
|
||||
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse,
|
||||
(socklen_t)sizeof(reuse)) == -1)
|
||||
break;
|
||||
if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) break;
|
||||
|
||||
memset(&a, 0, sizeof(a));
|
||||
if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR) break;
|
||||
// win32 getsockname may only set the port number, p=0.0005.
|
||||
// ( http://msdn.microsoft.com/library/ms738543.aspx ):
|
||||
a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
a.inaddr.sin_family = AF_INET;
|
||||
|
||||
if (listen(listener, 1) == SOCKET_ERROR) break;
|
||||
|
||||
socks[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
|
||||
if (socks[0] == -1) break;
|
||||
if (connect(socks[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) break;
|
||||
|
||||
socks[1] = accept(listener, NULL, NULL);
|
||||
if (socks[1] == -1) break;
|
||||
|
||||
closesocket(listener);
|
||||
return 0;
|
||||
}
|
||||
|
||||
closesocket(listener);
|
||||
closesocket(socks[0]);
|
||||
closesocket(socks[1]);
|
||||
socks[0] = socks[1] = -1;
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
#else
|
||||
int dumb_socketpair(int socks[2], int dummy) {
|
||||
if (socks == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
dummy = socketpair(AF_LOCAL, SOCK_STREAM, 0, socks);
|
||||
if (dummy) socks[0] = socks[1] = -1;
|
||||
return dummy;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef STRINGS_H
|
||||
#define STRINGS_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static int strcasecmp(const char *s1, const char *s2) { return stricmp(s1, s2); }
|
||||
|
||||
static int strncasecmp(const char *s1, const char *s2, size_t n) {
|
||||
return strnicmp(s1, s2, n);
|
||||
}
|
||||
|
||||
#endif /* STRINGS_H */
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef IOCTL_H
|
||||
#define IOCTL_H
|
||||
|
||||
#endif /* IOCTL_H */
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef MMAN_H
|
||||
#define MMAN_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#define MAP_SHARED 0x0010 /* share changes */
|
||||
#define MAP_FAILED ((void *)-1)
|
||||
#define PROT_READ 0x04 /* pages can be read */
|
||||
#define PROT_WRITE 0x02 /* pages can be written */
|
||||
#define PROT_EXEC 0x01 /* pages can be executed */
|
||||
#ifndef FILE_MAP_ALL_ACCESS
|
||||
enum { FILE_MAP_ALL_ACCESS = 0xF001F };
|
||||
#endif
|
||||
EXTERN_C WINBASEAPI void *WINAPI MapViewOfFile(HANDLE hFileMappingObject,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwFileOffsetHigh,
|
||||
DWORD dwFileOffsetLow,
|
||||
SIZE_T dwNumberOfBytesToMap);
|
||||
EXTERN_C WINBASEAPI BOOL WINAPI UnmapViewOfFile(void const *lpBaseAddress);
|
||||
static void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) {
|
||||
void *result = (void *)(-1);
|
||||
if (!addr && prot == MAP_SHARED) {
|
||||
/* HACK: we're assuming handle sizes can't exceed 32 bits, which is wrong...
|
||||
* but works for now. */
|
||||
void *ptr = MapViewOfFile((HANDLE)(intptr_t)fd, FILE_MAP_ALL_ACCESS,
|
||||
(DWORD)(off >> (CHAR_BIT * sizeof(DWORD))), (DWORD)off,
|
||||
(SIZE_T)len);
|
||||
if (ptr) {
|
||||
result = ptr;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static int munmap(void *addr, size_t length) {
|
||||
(void)length;
|
||||
return UnmapViewOfFile(addr) ? 0 : -1;
|
||||
}
|
||||
|
||||
#endif /* MMAN_H */
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef SELECT_H
|
||||
#define SELECT_H
|
||||
|
||||
#endif /* SELECT_H */
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef SOCKET_H
|
||||
#define SOCKET_H
|
||||
|
||||
typedef unsigned short sa_family_t;
|
||||
|
||||
#include <Winsock2.h>
|
||||
#include <unistd.h> // ssize_t
|
||||
|
||||
#define cmsghdr _WSACMSGHDR
|
||||
#undef CMSG_DATA
|
||||
#define CMSG_DATA WSA_CMSG_DATA
|
||||
#define CMSG_SPACE WSA_CMSG_SPACE
|
||||
#define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR
|
||||
#define CMSG_LEN WSA_CMSG_LEN
|
||||
#define CMSG_NXTHDR WSA_CMSG_NXTHDR
|
||||
|
||||
#define SCM_RIGHTS 1
|
||||
|
||||
#define iovec _WSABUF
|
||||
#define iov_base buf
|
||||
#define iov_len len
|
||||
#define msghdr _WSAMSG
|
||||
#define msg_name name
|
||||
#define msg_namelen namelen
|
||||
#define msg_iov lpBuffers
|
||||
#define msg_iovlen dwBufferCount
|
||||
#define msg_control Control.buf
|
||||
#define msg_controllen Control.len
|
||||
#define msg_flags dwFlags
|
||||
|
||||
int dumb_socketpair(SOCKET socks[2]);
|
||||
ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);
|
||||
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
|
||||
int socketpair(int domain, int type, int protocol, int sv[2]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace {
|
||||
inline int send(SOCKET s, const void *buf, int len, int flags) {
|
||||
// Call the const char* overload version
|
||||
int (*psend)(SOCKET s, const char *buf, int len, int flags) = ::send;
|
||||
return (*psend)(s, (const char *)buf, len, flags);
|
||||
}
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
#endif /* SOCKET_H */
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef STATVFS_H
|
||||
#define STATVFS_H 1
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef _SYS_SYSLOG_H
|
||||
#define _SYS_SYSLOG_H 1
|
||||
|
||||
#endif /* sys/syslog.h */
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <limits.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||||
// Free implementation from: https://stackoverflow.com/a/26085827
|
||||
SYSTEMTIME systime;
|
||||
GetSystemTime(&systime);
|
||||
FILETIME filetime;
|
||||
SystemTimeToFileTime(&systime, &filetime);
|
||||
unsigned long long const epoch_time_offset = 11644473600ULL * 60 * 60 * 24,
|
||||
time_high = filetime.dwHighDateTime,
|
||||
time =
|
||||
filetime.dwLowDateTime +
|
||||
(time_high << (CHAR_BIT * sizeof(filetime.dwLowDateTime)));
|
||||
tv->tv_sec = static_cast<int>((time - epoch_time_offset) / 10000000);
|
||||
tv->tv_usec = static_cast<int>(systime.wMilliseconds * 1000);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef TIME_H
|
||||
#define TIME_H
|
||||
|
||||
#include <WinSock2.h> // clients require timeval definition
|
||||
|
||||
struct timeval;
|
||||
struct timezone;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
int
|
||||
gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
|
||||
#endif /* TIME_H */
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef UN_H
|
||||
#define UN_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define UNIX_PATH_MAX 108
|
||||
|
||||
typedef struct sockaddr_un {
|
||||
ADDRESS_FAMILY sun_family;
|
||||
char sun_path[UNIX_PATH_MAX];
|
||||
} SOCKADDR_UN, *PSOCKADDR_UN;
|
||||
|
||||
#ifndef AF_LOCAL
|
||||
#define AF_LOCAL AF_UNIX
|
||||
#endif
|
||||
|
||||
#endif /* UN_H */
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef WAIT_H
|
||||
#define WAIT_H
|
||||
|
||||
#endif /* WAIT_H */
|
||||
@@ -0,0 +1 @@
|
||||
#include <sys/syslog.h>
|
||||
@@ -5,6 +5,16 @@
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
|
||||
int usleep(useconds_t usec) {
|
||||
Sleep((usec + (1000 - 1)) / 1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned sleep(unsigned seconds) {
|
||||
Sleep(seconds * 1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kill(pid_t pid, int sig) {
|
||||
int result;
|
||||
if (HANDLE process = OpenProcess(PROCESS_TERMINATE, FALSE, pid)) {
|
||||
|
||||
@@ -1,8 +1,45 @@
|
||||
#ifndef UNISTD_H
|
||||
#define UNISTD_H
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include <io.h> // open/read/write/close
|
||||
#ifndef EXTERN_C
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN_C extern "C"
|
||||
#else
|
||||
#define EXTERN_C
|
||||
#endif
|
||||
#endif
|
||||
#ifndef DECLSPEC_IMPORT
|
||||
#define DECLSPEC_IMPORT __declspec(dllimport)
|
||||
#endif
|
||||
#ifndef WINBASEAPI
|
||||
#define WINBASEAPI DECLSPEC_IMPORT
|
||||
#endif
|
||||
#ifndef WINAPI
|
||||
#define WINAPI __stdcall
|
||||
#endif
|
||||
typedef int BOOL;
|
||||
typedef void *HANDLE;
|
||||
typedef unsigned long DWORD;
|
||||
#ifdef _WIN64
|
||||
typedef unsigned long long UINT_PTR;
|
||||
typedef unsigned long long ULONG_PTR;
|
||||
typedef long long ssize_t;
|
||||
#else
|
||||
typedef unsigned int UINT_PTR;
|
||||
typedef unsigned long ULONG_PTR;
|
||||
typedef int ssize_t;
|
||||
#endif
|
||||
typedef int pid_t /* technically unsigned on Windows, but no practical concern */;
|
||||
enum { SIGKILL = 9 };
|
||||
typedef ULONG_PTR SIZE_T;
|
||||
EXTERN_C WINBASEAPI void WINAPI Sleep(DWORD dwMilliseconds);
|
||||
|
||||
typedef unsigned int useconds_t;
|
||||
int usleep(useconds_t usec);
|
||||
unsigned sleep(unsigned seconds);
|
||||
|
||||
__declspec(
|
||||
deprecated("Killing a process by ID has an inherent race condition on Windows"
|
||||
|
||||
Reference in New Issue
Block a user