libuv 1.42.0.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3650 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
8
deps/libuv/src/win/atomicops-inl.h
vendored
8
deps/libuv/src/win/atomicops-inl.h
vendored
@ -39,10 +39,11 @@ static char INLINE uv__atomic_exchange_set(char volatile* target) {
|
||||
return _InterlockedOr8(target, 1);
|
||||
}
|
||||
|
||||
#else /* GCC */
|
||||
#else /* GCC, Clang in mingw mode */
|
||||
|
||||
/* Mingw-32 version, hopefully this works for 64-bit gcc as well. */
|
||||
static inline char uv__atomic_exchange_set(char volatile* target) {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/* Mingw-32 version, hopefully this works for 64-bit gcc as well. */
|
||||
const char one = 1;
|
||||
char old_value;
|
||||
__asm__ __volatile__ ("lock xchgb %0, %1\n\t"
|
||||
@ -50,6 +51,9 @@ static inline char uv__atomic_exchange_set(char volatile* target) {
|
||||
: "0"(one), "m"(*target)
|
||||
: "memory");
|
||||
return old_value;
|
||||
#else
|
||||
return __sync_fetch_and_or(target, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
2
deps/libuv/src/win/error.c
vendored
2
deps/libuv/src/win/error.c
vendored
@ -105,7 +105,6 @@ int uv_translate_sys_error(int sys_errno) {
|
||||
case ERROR_SYMLINK_NOT_SUPPORTED: return UV_EINVAL;
|
||||
case WSAEINVAL: return UV_EINVAL;
|
||||
case WSAEPFNOSUPPORT: return UV_EINVAL;
|
||||
case WSAESOCKTNOSUPPORT: return UV_EINVAL;
|
||||
case ERROR_BEGINNING_OF_MEDIA: return UV_EIO;
|
||||
case ERROR_BUS_RESET: return UV_EIO;
|
||||
case ERROR_CRC: return UV_EIO;
|
||||
@ -168,6 +167,7 @@ int uv_translate_sys_error(int sys_errno) {
|
||||
case ERROR_NOT_SAME_DEVICE: return UV_EXDEV;
|
||||
case ERROR_INVALID_FUNCTION: return UV_EISDIR;
|
||||
case ERROR_META_EXPANSION_TOO_LONG: return UV_E2BIG;
|
||||
case WSAESOCKTNOSUPPORT: return UV_ESOCKTNOSUPPORT;
|
||||
default: return UV_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
51
deps/libuv/src/win/fs.c
vendored
51
deps/libuv/src/win/fs.c
vendored
@ -92,30 +92,24 @@
|
||||
return; \
|
||||
}
|
||||
|
||||
#define MILLIONu (1000U * 1000U)
|
||||
#define BILLIONu (1000U * 1000U * 1000U)
|
||||
#define MILLION ((int64_t) 1000 * 1000)
|
||||
#define BILLION ((int64_t) 1000 * 1000 * 1000)
|
||||
|
||||
#define FILETIME_TO_UINT(filetime) \
|
||||
(*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu)
|
||||
|
||||
#define FILETIME_TO_TIME_T(filetime) \
|
||||
(FILETIME_TO_UINT(filetime) / (10u * MILLIONu))
|
||||
|
||||
#define FILETIME_TO_TIME_NS(filetime, secs) \
|
||||
((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U)
|
||||
|
||||
#define FILETIME_TO_TIMESPEC(ts, filetime) \
|
||||
do { \
|
||||
(ts).tv_sec = (long) FILETIME_TO_TIME_T(filetime); \
|
||||
(ts).tv_nsec = (long) FILETIME_TO_TIME_NS(filetime, (ts).tv_sec); \
|
||||
} while(0)
|
||||
static void uv__filetime_to_timespec(uv_timespec_t *ts, int64_t filetime) {
|
||||
filetime -= 116444736 * BILLION;
|
||||
ts->tv_sec = (long) (filetime / (10 * MILLION));
|
||||
ts->tv_nsec = (long) ((filetime - ts->tv_sec * 10 * MILLION) * 100U);
|
||||
if (ts->tv_nsec < 0) {
|
||||
ts->tv_sec -= 1;
|
||||
ts->tv_nsec += 1e9;
|
||||
}
|
||||
}
|
||||
|
||||
#define TIME_T_TO_FILETIME(time, filetime_ptr) \
|
||||
do { \
|
||||
uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) + \
|
||||
(uint64_t) 116444736 * BILLIONu; \
|
||||
(filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \
|
||||
(filetime_ptr)->dwHighDateTime = bigtime >> 32; \
|
||||
int64_t bigtime = ((time) * 10 * MILLION + 116444736 * BILLION); \
|
||||
(filetime_ptr)->dwLowDateTime = (uint64_t) bigtime & 0xFFFFFFFF; \
|
||||
(filetime_ptr)->dwHighDateTime = (uint64_t) bigtime >> 32; \
|
||||
} while(0)
|
||||
|
||||
#define IS_SLASH(c) ((c) == L'\\' || (c) == L'/')
|
||||
@ -1224,7 +1218,8 @@ void fs__mkdir(uv_fs_t* req) {
|
||||
SET_REQ_RESULT(req, 0);
|
||||
} else {
|
||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||
if (req->sys_errno_ == ERROR_INVALID_NAME)
|
||||
if (req->sys_errno_ == ERROR_INVALID_NAME ||
|
||||
req->sys_errno_ == ERROR_DIRECTORY)
|
||||
req->result = UV_EINVAL;
|
||||
}
|
||||
}
|
||||
@ -1243,7 +1238,7 @@ void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) {
|
||||
uint64_t v;
|
||||
char* path;
|
||||
|
||||
path = req->path;
|
||||
path = (char*)req->path;
|
||||
len = wcslen(req->file.pathw);
|
||||
ep = req->file.pathw + len;
|
||||
if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) {
|
||||
@ -1791,10 +1786,14 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
|
||||
statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) |
|
||||
((_S_IREAD | _S_IWRITE) >> 6);
|
||||
|
||||
FILETIME_TO_TIMESPEC(statbuf->st_atim, file_info.BasicInformation.LastAccessTime);
|
||||
FILETIME_TO_TIMESPEC(statbuf->st_ctim, file_info.BasicInformation.ChangeTime);
|
||||
FILETIME_TO_TIMESPEC(statbuf->st_mtim, file_info.BasicInformation.LastWriteTime);
|
||||
FILETIME_TO_TIMESPEC(statbuf->st_birthtim, file_info.BasicInformation.CreationTime);
|
||||
uv__filetime_to_timespec(&statbuf->st_atim,
|
||||
file_info.BasicInformation.LastAccessTime.QuadPart);
|
||||
uv__filetime_to_timespec(&statbuf->st_ctim,
|
||||
file_info.BasicInformation.ChangeTime.QuadPart);
|
||||
uv__filetime_to_timespec(&statbuf->st_mtim,
|
||||
file_info.BasicInformation.LastWriteTime.QuadPart);
|
||||
uv__filetime_to_timespec(&statbuf->st_birthtim,
|
||||
file_info.BasicInformation.CreationTime.QuadPart);
|
||||
|
||||
statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart;
|
||||
|
||||
|
4
deps/libuv/src/win/internal.h
vendored
4
deps/libuv/src/win/internal.h
vendored
@ -115,8 +115,8 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle);
|
||||
/*
|
||||
* Pipes
|
||||
*/
|
||||
int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
|
||||
char* name, size_t nameSize);
|
||||
int uv__create_stdio_pipe_pair(uv_loop_t* loop,
|
||||
uv_pipe_t* parent_pipe, HANDLE* child_pipe_ptr, unsigned int flags);
|
||||
|
||||
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
|
||||
int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
|
||||
|
236
deps/libuv/src/win/pipe.c
vendored
236
deps/libuv/src/win/pipe.c
vendored
@ -202,17 +202,17 @@ static void close_pipe(uv_pipe_t* pipe) {
|
||||
}
|
||||
|
||||
|
||||
int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
|
||||
char* name, size_t nameSize) {
|
||||
static int uv__pipe_server(
|
||||
HANDLE* pipeHandle_ptr, DWORD access,
|
||||
char* name, size_t nameSize, char* random) {
|
||||
HANDLE pipeHandle;
|
||||
int err;
|
||||
char* ptr = (char*)handle;
|
||||
|
||||
for (;;) {
|
||||
uv_unique_pipe_name(ptr, name, nameSize);
|
||||
uv_unique_pipe_name(random, name, nameSize);
|
||||
|
||||
pipeHandle = CreateNamedPipeA(name,
|
||||
access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
|
||||
access | FILE_FLAG_FIRST_PIPE_INSTANCE,
|
||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0,
|
||||
NULL);
|
||||
|
||||
@ -226,20 +226,11 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Pipe name collision. Increment the pointer and try again. */
|
||||
ptr++;
|
||||
/* Pipe name collision. Increment the random number and try again. */
|
||||
random++;
|
||||
}
|
||||
|
||||
if (CreateIoCompletionPort(pipeHandle,
|
||||
loop->iocp,
|
||||
(ULONG_PTR)handle,
|
||||
0) == NULL) {
|
||||
err = GetLastError();
|
||||
goto error;
|
||||
}
|
||||
|
||||
uv_pipe_connection_init(handle);
|
||||
handle->handle = pipeHandle;
|
||||
*pipeHandle_ptr = pipeHandle;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -251,6 +242,214 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
|
||||
}
|
||||
|
||||
|
||||
static int uv__create_pipe_pair(
|
||||
HANDLE* server_pipe_ptr, HANDLE* client_pipe_ptr,
|
||||
unsigned int server_flags, unsigned int client_flags,
|
||||
int inherit_client, char* random) {
|
||||
/* allowed flags are: UV_READABLE_PIPE | UV_WRITABLE_PIPE | UV_NONBLOCK_PIPE */
|
||||
char pipe_name[64];
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
DWORD server_access;
|
||||
DWORD client_access;
|
||||
HANDLE server_pipe;
|
||||
HANDLE client_pipe;
|
||||
int err;
|
||||
|
||||
server_pipe = INVALID_HANDLE_VALUE;
|
||||
client_pipe = INVALID_HANDLE_VALUE;
|
||||
|
||||
server_access = 0;
|
||||
if (server_flags & UV_READABLE_PIPE)
|
||||
server_access |= PIPE_ACCESS_INBOUND;
|
||||
if (server_flags & UV_WRITABLE_PIPE)
|
||||
server_access |= PIPE_ACCESS_OUTBOUND;
|
||||
if (server_flags & UV_NONBLOCK_PIPE)
|
||||
server_access |= FILE_FLAG_OVERLAPPED;
|
||||
server_access |= WRITE_DAC;
|
||||
|
||||
client_access = 0;
|
||||
if (client_flags & UV_READABLE_PIPE)
|
||||
client_access |= GENERIC_READ;
|
||||
else
|
||||
client_access |= FILE_READ_ATTRIBUTES;
|
||||
if (client_flags & UV_WRITABLE_PIPE)
|
||||
client_access |= GENERIC_WRITE;
|
||||
else
|
||||
client_access |= FILE_WRITE_ATTRIBUTES;
|
||||
client_access |= WRITE_DAC;
|
||||
|
||||
/* Create server pipe handle. */
|
||||
err = uv__pipe_server(&server_pipe,
|
||||
server_access,
|
||||
pipe_name,
|
||||
sizeof(pipe_name),
|
||||
random);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
/* Create client pipe handle. */
|
||||
sa.nLength = sizeof sa;
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = inherit_client;
|
||||
|
||||
client_pipe = CreateFileA(pipe_name,
|
||||
client_access,
|
||||
0,
|
||||
&sa,
|
||||
OPEN_EXISTING,
|
||||
(client_flags & UV_NONBLOCK_PIPE) ? FILE_FLAG_OVERLAPPED : 0,
|
||||
NULL);
|
||||
if (client_pipe == INVALID_HANDLE_VALUE) {
|
||||
err = GetLastError();
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Validate that the pipe was opened in the right mode. */
|
||||
{
|
||||
DWORD mode;
|
||||
BOOL r;
|
||||
r = GetNamedPipeHandleState(client_pipe, &mode, NULL, NULL, NULL, NULL, 0);
|
||||
if (r == TRUE) {
|
||||
assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));
|
||||
} else {
|
||||
fprintf(stderr, "libuv assertion failure: GetNamedPipeHandleState failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Do a blocking ConnectNamedPipe. This should not block because we have
|
||||
* both ends of the pipe created. */
|
||||
if (!ConnectNamedPipe(server_pipe, NULL)) {
|
||||
if (GetLastError() != ERROR_PIPE_CONNECTED) {
|
||||
err = GetLastError();
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
*client_pipe_ptr = client_pipe;
|
||||
*server_pipe_ptr = server_pipe;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (server_pipe != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(server_pipe);
|
||||
|
||||
if (client_pipe != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(client_pipe);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int uv_pipe(uv_file fds[2], int read_flags, int write_flags) {
|
||||
uv_file temp[2];
|
||||
int err;
|
||||
HANDLE readh;
|
||||
HANDLE writeh;
|
||||
|
||||
/* Make the server side the inbound (read) end, */
|
||||
/* so that both ends will have FILE_READ_ATTRIBUTES permission. */
|
||||
/* TODO: better source of local randomness than &fds? */
|
||||
read_flags |= UV_READABLE_PIPE;
|
||||
write_flags |= UV_WRITABLE_PIPE;
|
||||
err = uv__create_pipe_pair(&readh, &writeh, read_flags, write_flags, 0, (char*) &fds[0]);
|
||||
if (err != 0)
|
||||
return err;
|
||||
temp[0] = _open_osfhandle((intptr_t) readh, 0);
|
||||
if (temp[0] == -1) {
|
||||
if (errno == UV_EMFILE)
|
||||
err = UV_EMFILE;
|
||||
else
|
||||
err = UV_UNKNOWN;
|
||||
CloseHandle(readh);
|
||||
CloseHandle(writeh);
|
||||
return err;
|
||||
}
|
||||
temp[1] = _open_osfhandle((intptr_t) writeh, 0);
|
||||
if (temp[1] == -1) {
|
||||
if (errno == UV_EMFILE)
|
||||
err = UV_EMFILE;
|
||||
else
|
||||
err = UV_UNKNOWN;
|
||||
_close(temp[0]);
|
||||
CloseHandle(writeh);
|
||||
return err;
|
||||
}
|
||||
fds[0] = temp[0];
|
||||
fds[1] = temp[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv__create_stdio_pipe_pair(uv_loop_t* loop,
|
||||
uv_pipe_t* parent_pipe, HANDLE* child_pipe_ptr, unsigned int flags) {
|
||||
/* The parent_pipe is always the server_pipe and kept by libuv.
|
||||
* The child_pipe is always the client_pipe and is passed to the child.
|
||||
* The flags are specified with respect to their usage in the child. */
|
||||
HANDLE server_pipe;
|
||||
HANDLE client_pipe;
|
||||
unsigned int server_flags;
|
||||
unsigned int client_flags;
|
||||
int err;
|
||||
|
||||
server_pipe = INVALID_HANDLE_VALUE;
|
||||
client_pipe = INVALID_HANDLE_VALUE;
|
||||
|
||||
server_flags = 0;
|
||||
client_flags = 0;
|
||||
if (flags & UV_READABLE_PIPE) {
|
||||
/* The server needs inbound (read) access too, otherwise CreateNamedPipe()
|
||||
* won't give us the FILE_READ_ATTRIBUTES permission. We need that to probe
|
||||
* the state of the write buffer when we're trying to shutdown the pipe. */
|
||||
server_flags |= UV_READABLE_PIPE | UV_WRITABLE_PIPE;
|
||||
client_flags |= UV_READABLE_PIPE;
|
||||
}
|
||||
if (flags & UV_WRITABLE_PIPE) {
|
||||
server_flags |= UV_READABLE_PIPE;
|
||||
client_flags |= UV_WRITABLE_PIPE;
|
||||
}
|
||||
server_flags |= UV_NONBLOCK_PIPE;
|
||||
if (flags & UV_NONBLOCK_PIPE || parent_pipe->ipc) {
|
||||
client_flags |= UV_NONBLOCK_PIPE;
|
||||
}
|
||||
|
||||
err = uv__create_pipe_pair(&server_pipe, &client_pipe,
|
||||
server_flags, client_flags, 1, (char*) server_pipe);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
if (CreateIoCompletionPort(server_pipe,
|
||||
loop->iocp,
|
||||
(ULONG_PTR) parent_pipe,
|
||||
0) == NULL) {
|
||||
err = GetLastError();
|
||||
goto error;
|
||||
}
|
||||
|
||||
uv_pipe_connection_init(parent_pipe);
|
||||
parent_pipe->handle = server_pipe;
|
||||
*child_pipe_ptr = client_pipe;
|
||||
|
||||
/* The server end is now readable and/or writable. */
|
||||
if (flags & UV_READABLE_PIPE)
|
||||
parent_pipe->flags |= UV_HANDLE_WRITABLE;
|
||||
if (flags & UV_WRITABLE_PIPE)
|
||||
parent_pipe->flags |= UV_HANDLE_READABLE;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (server_pipe != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(server_pipe);
|
||||
|
||||
if (client_pipe != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(client_pipe);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int uv_set_pipe_handle(uv_loop_t* loop,
|
||||
uv_pipe_t* handle,
|
||||
HANDLE pipeHandle,
|
||||
@ -712,9 +911,8 @@ error:
|
||||
handle->name = NULL;
|
||||
}
|
||||
|
||||
if (pipeHandle != INVALID_HANDLE_VALUE) {
|
||||
if (pipeHandle != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(pipeHandle);
|
||||
}
|
||||
|
||||
/* Make this req pending reporting an error. */
|
||||
SET_REQ_ERROR(req, err);
|
||||
|
3
deps/libuv/src/win/poll.c
vendored
3
deps/libuv/src/win/poll.c
vendored
@ -488,7 +488,8 @@ static int uv__poll_set(uv_poll_t* handle, int events, uv_poll_cb cb) {
|
||||
|
||||
assert(handle->type == UV_POLL);
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSING));
|
||||
assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
|
||||
assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT |
|
||||
UV_PRIORITIZED)) == 0);
|
||||
|
||||
handle->events = events;
|
||||
handle->poll_cb = cb;
|
||||
|
96
deps/libuv/src/win/process-stdio.c
vendored
96
deps/libuv/src/win/process-stdio.c
vendored
@ -95,102 +95,6 @@ void uv_disable_stdio_inheritance(void) {
|
||||
}
|
||||
|
||||
|
||||
static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
|
||||
uv_pipe_t* server_pipe, HANDLE* child_pipe_ptr, unsigned int flags) {
|
||||
char pipe_name[64];
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
DWORD server_access = 0;
|
||||
DWORD client_access = 0;
|
||||
HANDLE child_pipe = INVALID_HANDLE_VALUE;
|
||||
int err;
|
||||
int overlap;
|
||||
|
||||
if (flags & UV_READABLE_PIPE) {
|
||||
/* The server needs inbound access too, otherwise CreateNamedPipe() won't
|
||||
* give us the FILE_READ_ATTRIBUTES permission. We need that to probe the
|
||||
* state of the write buffer when we're trying to shutdown the pipe. */
|
||||
server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;
|
||||
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
|
||||
}
|
||||
if (flags & UV_WRITABLE_PIPE) {
|
||||
server_access |= PIPE_ACCESS_INBOUND;
|
||||
client_access |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;
|
||||
}
|
||||
|
||||
/* Create server pipe handle. */
|
||||
err = uv_stdio_pipe_server(loop,
|
||||
server_pipe,
|
||||
server_access,
|
||||
pipe_name,
|
||||
sizeof(pipe_name));
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
/* Create child pipe handle. */
|
||||
sa.nLength = sizeof sa;
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = TRUE;
|
||||
|
||||
overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE);
|
||||
child_pipe = CreateFileA(pipe_name,
|
||||
client_access,
|
||||
0,
|
||||
&sa,
|
||||
OPEN_EXISTING,
|
||||
overlap ? FILE_FLAG_OVERLAPPED : 0,
|
||||
NULL);
|
||||
if (child_pipe == INVALID_HANDLE_VALUE) {
|
||||
err = GetLastError();
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* Validate that the pipe was opened in the right mode. */
|
||||
{
|
||||
DWORD mode;
|
||||
BOOL r = GetNamedPipeHandleState(child_pipe,
|
||||
&mode,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0);
|
||||
assert(r == TRUE);
|
||||
assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Do a blocking ConnectNamedPipe. This should not block because we have both
|
||||
* ends of the pipe created. */
|
||||
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
|
||||
if (GetLastError() != ERROR_PIPE_CONNECTED) {
|
||||
err = GetLastError();
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* The server end is now readable and/or writable. */
|
||||
if (flags & UV_READABLE_PIPE)
|
||||
server_pipe->flags |= UV_HANDLE_WRITABLE;
|
||||
if (flags & UV_WRITABLE_PIPE)
|
||||
server_pipe->flags |= UV_HANDLE_READABLE;
|
||||
|
||||
*child_pipe_ptr = child_pipe;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (server_pipe->handle != INVALID_HANDLE_VALUE) {
|
||||
uv_pipe_cleanup(loop, server_pipe);
|
||||
}
|
||||
|
||||
if (child_pipe != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(child_pipe);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
|
||||
HANDLE current_process;
|
||||
|
||||
|
2
deps/libuv/src/win/process.c
vendored
2
deps/libuv/src/win/process.c
vendored
@ -642,7 +642,7 @@ int env_strncmp(const wchar_t* a, int na, const wchar_t* b) {
|
||||
assert(r==nb);
|
||||
B[nb] = L'\0';
|
||||
|
||||
while (1) {
|
||||
for (;;) {
|
||||
wchar_t AA = *A++;
|
||||
wchar_t BB = *B++;
|
||||
if (AA < BB) {
|
||||
|
23
deps/libuv/src/win/stream.c
vendored
23
deps/libuv/src/win/stream.c
vendored
@ -65,18 +65,11 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
|
||||
}
|
||||
|
||||
|
||||
int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,
|
||||
uv_read_cb read_cb) {
|
||||
int uv__read_start(uv_stream_t* handle,
|
||||
uv_alloc_cb alloc_cb,
|
||||
uv_read_cb read_cb) {
|
||||
int err;
|
||||
|
||||
if (handle->flags & UV_HANDLE_READING) {
|
||||
return UV_EALREADY;
|
||||
}
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_READABLE)) {
|
||||
return UV_ENOTCONN;
|
||||
}
|
||||
|
||||
err = ERROR_INVALID_PARAMETER;
|
||||
switch (handle->type) {
|
||||
case UV_TCP:
|
||||
@ -195,6 +188,16 @@ int uv_try_write(uv_stream_t* stream,
|
||||
}
|
||||
|
||||
|
||||
int uv_try_write2(uv_stream_t* stream,
|
||||
const uv_buf_t bufs[],
|
||||
unsigned int nbufs,
|
||||
uv_stream_t* send_handle) {
|
||||
if (send_handle != NULL)
|
||||
return UV_EAGAIN;
|
||||
return uv_try_write(stream, bufs, nbufs);
|
||||
}
|
||||
|
||||
|
||||
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
|
||||
uv_loop_t* loop = handle->loop;
|
||||
|
||||
|
260
deps/libuv/src/win/tcp.c
vendored
260
deps/libuv/src/win/tcp.c
vendored
@ -236,12 +236,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||
handle->reqs_pending == 0) {
|
||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) {
|
||||
closesocket(handle->socket);
|
||||
handle->socket = INVALID_SOCKET;
|
||||
handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;
|
||||
}
|
||||
assert(handle->socket == INVALID_SOCKET);
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) {
|
||||
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
|
||||
@ -599,6 +594,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
|
||||
}
|
||||
}
|
||||
|
||||
/* If this flag is set, we already made this listen call in xfer. */
|
||||
if (!(handle->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
|
||||
listen(handle->socket, backlog) == SOCKET_ERROR) {
|
||||
return WSAGetLastError();
|
||||
@ -769,7 +765,7 @@ static int uv__is_loopback(const struct sockaddr_storage* storage) {
|
||||
}
|
||||
|
||||
// Check if Windows version is 10.0.16299 or later
|
||||
static int uv__is_fast_loopback_fail_supported() {
|
||||
static int uv__is_fast_loopback_fail_supported(void) {
|
||||
OSVERSIONINFOW os_info;
|
||||
if (!pRtlGetVersion)
|
||||
return 0;
|
||||
@ -800,9 +796,8 @@ static int uv_tcp_try_connect(uv_connect_t* req,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (handle->delayed_error) {
|
||||
return handle->delayed_error;
|
||||
}
|
||||
if (handle->delayed_error != 0)
|
||||
goto out;
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
||||
if (addrlen == sizeof(uv_addr_ip4_any_)) {
|
||||
@ -815,8 +810,8 @@ static int uv_tcp_try_connect(uv_connect_t* req,
|
||||
err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0);
|
||||
if (err)
|
||||
return err;
|
||||
if (handle->delayed_error)
|
||||
return handle->delayed_error;
|
||||
if (handle->delayed_error != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!handle->tcp.conn.func_connectex) {
|
||||
@ -844,11 +839,21 @@ static int uv_tcp_try_connect(uv_connect_t* req,
|
||||
NULL);
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
UV_REQ_INIT(req, UV_CONNECT);
|
||||
req->handle = (uv_stream_t*) handle;
|
||||
req->cb = cb;
|
||||
memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
|
||||
|
||||
if (handle->delayed_error != 0) {
|
||||
/* Process the req without IOCP. */
|
||||
handle->reqs_pending++;
|
||||
REGISTER_HANDLE_REQ(loop, handle, req);
|
||||
uv_insert_pending_req(loop, (uv_req_t*)req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
success = handle->tcp.conn.func_connectex(handle->socket,
|
||||
(const struct sockaddr*) &converted,
|
||||
addrlen,
|
||||
@ -1015,6 +1020,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
*/
|
||||
err = WSAECONNRESET;
|
||||
}
|
||||
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||
|
||||
handle->read_cb((uv_stream_t*)handle,
|
||||
uv_translate_sys_error(err),
|
||||
@ -1096,6 +1102,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
* Unix. */
|
||||
err = WSAECONNRESET;
|
||||
}
|
||||
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||
|
||||
handle->read_cb((uv_stream_t*)handle,
|
||||
uv_translate_sys_error(err),
|
||||
@ -1149,9 +1156,14 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
}
|
||||
|
||||
handle->stream.conn.write_reqs_pending--;
|
||||
if (handle->stream.conn.shutdown_req != NULL &&
|
||||
handle->stream.conn.write_reqs_pending == 0) {
|
||||
uv_want_endgame(loop, (uv_handle_t*)handle);
|
||||
if (handle->stream.conn.write_reqs_pending == 0) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||
closesocket(handle->socket);
|
||||
handle->socket = INVALID_SOCKET;
|
||||
}
|
||||
if (handle->stream.conn.shutdown_req != NULL) {
|
||||
uv_want_endgame(loop, (uv_handle_t*)handle);
|
||||
}
|
||||
}
|
||||
|
||||
DECREASE_PENDING_REQ_COUNT(handle);
|
||||
@ -1215,7 +1227,14 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
UNREGISTER_HANDLE_REQ(loop, handle, req);
|
||||
|
||||
err = 0;
|
||||
if (REQ_SUCCESS(req)) {
|
||||
if (handle->delayed_error) {
|
||||
/* To smooth over the differences between unixes errors that
|
||||
* were reported synchronously on the first connect can be delayed
|
||||
* until the next tick--which is now.
|
||||
*/
|
||||
err = handle->delayed_error;
|
||||
handle->delayed_error = 0;
|
||||
} else if (REQ_SUCCESS(req)) {
|
||||
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||
/* use UV_ECANCELED for consistency with Unix */
|
||||
err = ERROR_OPERATION_ABORTED;
|
||||
@ -1320,7 +1339,7 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int enable) {
|
||||
if (handle->socket != INVALID_SOCKET) {
|
||||
err = uv__tcp_nodelay(handle, handle->socket, enable);
|
||||
if (err)
|
||||
return err;
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
@ -1339,7 +1358,7 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
|
||||
if (handle->socket != INVALID_SOCKET) {
|
||||
err = uv__tcp_keepalive(handle, handle->socket, enable, delay);
|
||||
if (err)
|
||||
return err;
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
@ -1386,9 +1405,24 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
|
||||
}
|
||||
|
||||
|
||||
static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {
|
||||
SOCKET socket = tcp->socket;
|
||||
static void uv_tcp_try_cancel_reqs(uv_tcp_t* tcp) {
|
||||
SOCKET socket;
|
||||
int non_ifs_lsp;
|
||||
int reading;
|
||||
int writing;
|
||||
|
||||
socket = tcp->socket;
|
||||
reading = tcp->flags & UV_HANDLE_READING;
|
||||
writing = tcp->stream.conn.write_reqs_pending > 0;
|
||||
if (!reading && !writing)
|
||||
return;
|
||||
|
||||
/* TODO: in libuv v2, keep explicit track of write_reqs, so we can cancel
|
||||
* them each explicitly with CancelIoEx (like unix). */
|
||||
if (reading)
|
||||
CancelIoEx((HANDLE) socket, &tcp->read_req.u.io.overlapped);
|
||||
if (writing)
|
||||
CancelIo((HANDLE) socket);
|
||||
|
||||
/* Check if we have any non-IFS LSPs stacked on top of TCP */
|
||||
non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
|
||||
@ -1408,71 +1442,41 @@ static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {
|
||||
NULL,
|
||||
NULL) != 0) {
|
||||
/* Failed. We can't do CancelIo. */
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assert(socket != 0 && socket != INVALID_SOCKET);
|
||||
|
||||
if (!CancelIo((HANDLE) socket)) {
|
||||
return GetLastError();
|
||||
if (socket != tcp->socket) {
|
||||
if (reading)
|
||||
CancelIoEx((HANDLE) socket, &tcp->read_req.u.io.overlapped);
|
||||
if (writing)
|
||||
CancelIo((HANDLE) socket);
|
||||
}
|
||||
|
||||
/* It worked. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
|
||||
int close_socket = 1;
|
||||
|
||||
if (tcp->flags & UV_HANDLE_READ_PENDING) {
|
||||
/* In order for winsock to do a graceful close there must not be any any
|
||||
* pending reads, or the socket must be shut down for writing */
|
||||
if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) {
|
||||
/* Just do shutdown on non-shared sockets, which ensures graceful close. */
|
||||
shutdown(tcp->socket, SD_SEND);
|
||||
|
||||
} else if (uv_tcp_try_cancel_io(tcp) == 0) {
|
||||
/* In case of a shared socket, we try to cancel all outstanding I/O,. If
|
||||
* that works, don't close the socket yet - wait for the read req to
|
||||
* return and close the socket in uv_tcp_endgame. */
|
||||
close_socket = 0;
|
||||
|
||||
} else {
|
||||
/* When cancelling isn't possible - which could happen when an LSP is
|
||||
* present on an old Windows version, we will have to close the socket
|
||||
* with a read pending. That is not nice because trailing sent bytes may
|
||||
* not make it to the other side. */
|
||||
if (tcp->flags & UV_HANDLE_CONNECTION) {
|
||||
uv_tcp_try_cancel_reqs(tcp);
|
||||
if (tcp->flags & UV_HANDLE_READING) {
|
||||
uv_read_stop((uv_stream_t*) tcp);
|
||||
}
|
||||
|
||||
} else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
|
||||
tcp->tcp.serv.accept_reqs != NULL) {
|
||||
/* Under normal circumstances closesocket() will ensure that all pending
|
||||
* accept reqs are canceled. However, when the socket is shared the
|
||||
* presence of another reference to the socket in another process will keep
|
||||
* the accept reqs going, so we have to ensure that these are canceled. */
|
||||
if (uv_tcp_try_cancel_io(tcp) != 0) {
|
||||
/* When cancellation is not possible, there is another option: we can
|
||||
* close the incoming sockets, which will also cancel the accept
|
||||
* operations. However this is not cool because we might inadvertently
|
||||
* close a socket that just accepted a new connection, which will cause
|
||||
* the connection to be aborted. */
|
||||
} else {
|
||||
if (tcp->tcp.serv.accept_reqs != NULL) {
|
||||
/* First close the incoming sockets to cancel the accept operations before
|
||||
* we free their resources. */
|
||||
unsigned int i;
|
||||
for (i = 0; i < uv_simultaneous_server_accepts; i++) {
|
||||
uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i];
|
||||
if (req->accept_socket != INVALID_SOCKET &&
|
||||
!HasOverlappedIoCompleted(&req->u.io.overlapped)) {
|
||||
if (req->accept_socket != INVALID_SOCKET) {
|
||||
closesocket(req->accept_socket);
|
||||
req->accept_socket = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tcp->flags & UV_HANDLE_READING) {
|
||||
tcp->flags &= ~UV_HANDLE_READING;
|
||||
DECREASE_ACTIVE_COUNT(loop, tcp);
|
||||
assert(!(tcp->flags & UV_HANDLE_READING));
|
||||
}
|
||||
|
||||
if (tcp->flags & UV_HANDLE_LISTENING) {
|
||||
@ -1480,10 +1484,15 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
|
||||
DECREASE_ACTIVE_COUNT(loop, tcp);
|
||||
}
|
||||
|
||||
if (close_socket) {
|
||||
/* If any overlapped req failed to cancel, calling `closesocket` now would
|
||||
* cause Win32 to send an RST packet. Try to avoid that for writes, if
|
||||
* possibly applicable, by waiting to process the completion notifications
|
||||
* first (which typically should be cancellations). There's not much we can
|
||||
* do about canceled reads, which also will generate an RST packet. */
|
||||
if (!(tcp->flags & UV_HANDLE_CONNECTION) ||
|
||||
tcp->stream.conn.write_reqs_pending == 0) {
|
||||
closesocket(tcp->socket);
|
||||
tcp->socket = INVALID_SOCKET;
|
||||
tcp->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;
|
||||
}
|
||||
|
||||
tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||
@ -1571,3 +1580,118 @@ int uv__tcp_connect(uv_connect_t* req,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef WSA_FLAG_NO_HANDLE_INHERIT
|
||||
/* Added in Windows 7 SP1. Specify this to avoid race conditions, */
|
||||
/* but also manually clear the inherit flag in case this failed. */
|
||||
#define WSA_FLAG_NO_HANDLE_INHERIT 0x80
|
||||
#endif
|
||||
|
||||
int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int flags1) {
|
||||
SOCKET server = INVALID_SOCKET;
|
||||
SOCKET client0 = INVALID_SOCKET;
|
||||
SOCKET client1 = INVALID_SOCKET;
|
||||
SOCKADDR_IN name;
|
||||
LPFN_ACCEPTEX func_acceptex;
|
||||
WSAOVERLAPPED overlap;
|
||||
char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32];
|
||||
int namelen;
|
||||
int err;
|
||||
DWORD bytes;
|
||||
DWORD flags;
|
||||
DWORD client0_flags = WSA_FLAG_NO_HANDLE_INHERIT;
|
||||
DWORD client1_flags = WSA_FLAG_NO_HANDLE_INHERIT;
|
||||
|
||||
if (flags0 & UV_NONBLOCK_PIPE)
|
||||
client0_flags |= WSA_FLAG_OVERLAPPED;
|
||||
if (flags1 & UV_NONBLOCK_PIPE)
|
||||
client1_flags |= WSA_FLAG_OVERLAPPED;
|
||||
|
||||
server = WSASocketW(AF_INET, type, protocol, NULL, 0,
|
||||
WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);
|
||||
if (server == INVALID_SOCKET)
|
||||
goto wsaerror;
|
||||
if (!SetHandleInformation((HANDLE) server, HANDLE_FLAG_INHERIT, 0))
|
||||
goto error;
|
||||
name.sin_family = AF_INET;
|
||||
name.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
name.sin_port = 0;
|
||||
if (bind(server, (SOCKADDR*) &name, sizeof(name)) != 0)
|
||||
goto wsaerror;
|
||||
if (listen(server, 1) != 0)
|
||||
goto wsaerror;
|
||||
namelen = sizeof(name);
|
||||
if (getsockname(server, (SOCKADDR*) &name, &namelen) != 0)
|
||||
goto wsaerror;
|
||||
client0 = WSASocketW(AF_INET, type, protocol, NULL, 0, client0_flags);
|
||||
if (client0 == INVALID_SOCKET)
|
||||
goto wsaerror;
|
||||
if (!SetHandleInformation((HANDLE) client0, HANDLE_FLAG_INHERIT, 0))
|
||||
goto error;
|
||||
if (connect(client0, (SOCKADDR*) &name, sizeof(name)) != 0)
|
||||
goto wsaerror;
|
||||
client1 = WSASocketW(AF_INET, type, protocol, NULL, 0, client1_flags);
|
||||
if (client1 == INVALID_SOCKET)
|
||||
goto wsaerror;
|
||||
if (!SetHandleInformation((HANDLE) client1, HANDLE_FLAG_INHERIT, 0))
|
||||
goto error;
|
||||
if (!uv_get_acceptex_function(server, &func_acceptex)) {
|
||||
err = WSAEAFNOSUPPORT;
|
||||
goto cleanup;
|
||||
}
|
||||
memset(&overlap, 0, sizeof(overlap));
|
||||
if (!func_acceptex(server,
|
||||
client1,
|
||||
accept_buffer,
|
||||
0,
|
||||
sizeof(struct sockaddr_storage),
|
||||
sizeof(struct sockaddr_storage),
|
||||
&bytes,
|
||||
&overlap)) {
|
||||
err = WSAGetLastError();
|
||||
if (err == ERROR_IO_PENDING) {
|
||||
/* Result should complete immediately, since we already called connect,
|
||||
* but emperically, we sometimes have to poll the kernel a couple times
|
||||
* until it notices that. */
|
||||
while (!WSAGetOverlappedResult(client1, &overlap, &bytes, FALSE, &flags)) {
|
||||
err = WSAGetLastError();
|
||||
if (err != WSA_IO_INCOMPLETE)
|
||||
goto cleanup;
|
||||
SwitchToThread();
|
||||
}
|
||||
}
|
||||
else {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if (setsockopt(client1, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
|
||||
(char*) &server, sizeof(server)) != 0) {
|
||||
goto wsaerror;
|
||||
}
|
||||
|
||||
closesocket(server);
|
||||
|
||||
fds[0] = client0;
|
||||
fds[1] = client1;
|
||||
|
||||
return 0;
|
||||
|
||||
wsaerror:
|
||||
err = WSAGetLastError();
|
||||
goto cleanup;
|
||||
|
||||
error:
|
||||
err = GetLastError();
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
if (server != INVALID_SOCKET)
|
||||
closesocket(server);
|
||||
if (client0 != INVALID_SOCKET)
|
||||
closesocket(client0);
|
||||
if (client1 != INVALID_SOCKET)
|
||||
closesocket(client1);
|
||||
|
||||
assert(err);
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
4
deps/libuv/src/win/udp.c
vendored
4
deps/libuv/src/win/udp.c
vendored
@ -284,7 +284,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
|
||||
handle->flags &= ~UV_HANDLE_ZERO_READ;
|
||||
|
||||
handle->recv_buffer = uv_buf_init(NULL, 0);
|
||||
handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->recv_buffer);
|
||||
handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &handle->recv_buffer);
|
||||
if (handle->recv_buffer.base == NULL || handle->recv_buffer.len == 0) {
|
||||
handle->recv_cb(handle, UV_ENOBUFS, &handle->recv_buffer, NULL, 0);
|
||||
return;
|
||||
@ -501,7 +501,7 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
|
||||
/* Do a nonblocking receive.
|
||||
* TODO: try to read multiple datagrams at once. FIONREAD maybe? */
|
||||
buf = uv_buf_init(NULL, 0);
|
||||
handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
|
||||
handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf);
|
||||
if (buf.base == NULL || buf.len == 0) {
|
||||
handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);
|
||||
goto done;
|
||||
|
17
deps/libuv/src/win/util.c
vendored
17
deps/libuv/src/win/util.c
vendored
@ -1664,26 +1664,33 @@ int uv_os_unsetenv(const char* name) {
|
||||
|
||||
|
||||
int uv_os_gethostname(char* buffer, size_t* size) {
|
||||
char buf[UV_MAXHOSTNAMESIZE];
|
||||
WCHAR buf[UV_MAXHOSTNAMESIZE];
|
||||
size_t len;
|
||||
char* utf8_str;
|
||||
int convert_result;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
uv__once_init(); /* Initialize winsock */
|
||||
|
||||
if (gethostname(buf, sizeof(buf)) != 0)
|
||||
if (GetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0)
|
||||
return uv_translate_sys_error(WSAGetLastError());
|
||||
|
||||
buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
|
||||
len = strlen(buf);
|
||||
convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str);
|
||||
|
||||
if (convert_result != 0)
|
||||
return convert_result;
|
||||
|
||||
len = strlen(utf8_str);
|
||||
if (len >= *size) {
|
||||
*size = len + 1;
|
||||
uv__free(utf8_str);
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
memcpy(buffer, buf, len + 1);
|
||||
memcpy(buffer, utf8_str, len + 1);
|
||||
uv__free(utf8_str);
|
||||
*size = len;
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user