|
|
@ -51,22 +51,23 @@ static void uv_unique_pipe_name(char* ptr, char* name, size_t size) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int uv_pipe_init(uv_pipe_t* handle) { |
|
|
|
uv_stream_init((uv_stream_t*)handle); |
|
|
|
int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle) { |
|
|
|
uv_stream_init(loop, (uv_stream_t*)handle); |
|
|
|
|
|
|
|
handle->type = UV_NAMED_PIPE; |
|
|
|
handle->reqs_pending = 0; |
|
|
|
handle->handle = INVALID_HANDLE_VALUE; |
|
|
|
handle->name = NULL; |
|
|
|
|
|
|
|
uv_counters()->pipe_init++; |
|
|
|
loop->counters.pipe_init++; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int uv_pipe_init_with_handle(uv_pipe_t* handle, HANDLE pipeHandle) { |
|
|
|
int err = uv_pipe_init(handle); |
|
|
|
int uv_pipe_init_with_handle(uv_loop_t* loop, uv_pipe_t* handle, |
|
|
|
HANDLE pipeHandle) { |
|
|
|
int err = uv_pipe_init(loop, handle); |
|
|
|
|
|
|
|
if (!err) { |
|
|
|
/*
|
|
|
@ -88,7 +89,8 @@ static void uv_pipe_connection_init(uv_pipe_t* handle) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int uv_stdio_pipe_server(uv_pipe_t* handle, DWORD access, char* name, size_t nameSize) { |
|
|
|
int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, |
|
|
|
char* name, size_t nameSize) { |
|
|
|
HANDLE pipeHandle; |
|
|
|
int errno; |
|
|
|
int err; |
|
|
@ -98,13 +100,9 @@ int uv_stdio_pipe_server(uv_pipe_t* handle, DWORD access, char* name, size_t nam |
|
|
|
uv_unique_pipe_name(ptr, name, nameSize); |
|
|
|
|
|
|
|
pipeHandle = CreateNamedPipeA(name, |
|
|
|
access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, |
|
|
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, |
|
|
|
1, |
|
|
|
65536, |
|
|
|
65536, |
|
|
|
0, |
|
|
|
NULL); |
|
|
|
access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, |
|
|
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0, |
|
|
|
NULL); |
|
|
|
|
|
|
|
if (pipeHandle != INVALID_HANDLE_VALUE) { |
|
|
|
/* No name collisions. We're done. */ |
|
|
@ -113,7 +111,7 @@ int uv_stdio_pipe_server(uv_pipe_t* handle, DWORD access, char* name, size_t nam |
|
|
|
|
|
|
|
errno = GetLastError(); |
|
|
|
if (errno != ERROR_PIPE_BUSY && errno != ERROR_ACCESS_DENIED) { |
|
|
|
uv_set_sys_error(errno); |
|
|
|
uv_set_sys_error(loop, errno); |
|
|
|
err = -1; |
|
|
|
goto done; |
|
|
|
} |
|
|
@ -123,10 +121,10 @@ int uv_stdio_pipe_server(uv_pipe_t* handle, DWORD access, char* name, size_t nam |
|
|
|
} |
|
|
|
|
|
|
|
if (CreateIoCompletionPort(pipeHandle, |
|
|
|
LOOP->iocp, |
|
|
|
loop->iocp, |
|
|
|
(ULONG_PTR)handle, |
|
|
|
0) == NULL) { |
|
|
|
uv_set_sys_error(GetLastError()); |
|
|
|
uv_set_sys_error(loop, GetLastError()); |
|
|
|
err = -1; |
|
|
|
goto done; |
|
|
|
} |
|
|
@ -145,7 +143,8 @@ done: |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int uv_set_pipe_handle(uv_pipe_t* handle, HANDLE pipeHandle) { |
|
|
|
static int uv_set_pipe_handle(uv_loop_t* loop, uv_pipe_t* handle, |
|
|
|
HANDLE pipeHandle) { |
|
|
|
DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT; |
|
|
|
|
|
|
|
if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) { |
|
|
@ -153,7 +152,7 @@ static int uv_set_pipe_handle(uv_pipe_t* handle, HANDLE pipeHandle) { |
|
|
|
} |
|
|
|
|
|
|
|
if (CreateIoCompletionPort(pipeHandle, |
|
|
|
LOOP->iocp, |
|
|
|
loop->iocp, |
|
|
|
(ULONG_PTR)handle, |
|
|
|
0) == NULL) { |
|
|
|
return -1; |
|
|
@ -165,6 +164,7 @@ static int uv_set_pipe_handle(uv_pipe_t* handle, HANDLE pipeHandle) { |
|
|
|
|
|
|
|
static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) { |
|
|
|
int errno; |
|
|
|
uv_loop_t* loop; |
|
|
|
uv_pipe_t* handle; |
|
|
|
uv_shutdown_t* req; |
|
|
|
|
|
|
@ -172,17 +172,19 @@ static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) { |
|
|
|
assert(req); |
|
|
|
handle = (uv_pipe_t*) req->handle; |
|
|
|
assert(handle); |
|
|
|
loop = handle->loop; |
|
|
|
assert(loop); |
|
|
|
|
|
|
|
FlushFileBuffers(handle->handle); |
|
|
|
|
|
|
|
/* Post completed */ |
|
|
|
POST_COMPLETION_FOR_REQ(req); |
|
|
|
POST_COMPLETION_FOR_REQ(loop, req); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void uv_pipe_endgame(uv_pipe_t* handle) { |
|
|
|
void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { |
|
|
|
unsigned int uv_alloced; |
|
|
|
DWORD result; |
|
|
|
uv_shutdown_t* req; |
|
|
@ -207,7 +209,7 @@ void uv_pipe_endgame(uv_pipe_t* handle) { |
|
|
|
/* Failure */ |
|
|
|
handle->flags &= ~UV_HANDLE_SHUTTING; |
|
|
|
if (req->cb) { |
|
|
|
uv_set_sys_error(pRtlNtStatusToDosError(nt_status)); |
|
|
|
uv_set_sys_error(loop, pRtlNtStatusToDosError(nt_status)); |
|
|
|
req->cb(req, -1); |
|
|
|
} |
|
|
|
DECREASE_PENDING_REQ_COUNT(handle); |
|
|
@ -218,7 +220,7 @@ void uv_pipe_endgame(uv_pipe_t* handle) { |
|
|
|
handle->flags |= UV_HANDLE_SHUT; |
|
|
|
|
|
|
|
/* Short-circuit, no need to call FlushFileBuffers. */ |
|
|
|
uv_insert_pending_req((uv_req_t*) req); |
|
|
|
uv_insert_pending_req(loop, (uv_req_t*) req); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
@ -234,7 +236,7 @@ void uv_pipe_endgame(uv_pipe_t* handle) { |
|
|
|
/* Failure. */ |
|
|
|
handle->flags &= ~UV_HANDLE_SHUTTING; |
|
|
|
if (req->cb) { |
|
|
|
uv_set_sys_error(GetLastError()); |
|
|
|
uv_set_sys_error(loop, GetLastError()); |
|
|
|
req->cb(req, -1); |
|
|
|
} |
|
|
|
DECREASE_PENDING_REQ_COUNT(handle); |
|
|
@ -259,29 +261,30 @@ void uv_pipe_endgame(uv_pipe_t* handle) { |
|
|
|
free(handle); |
|
|
|
} |
|
|
|
|
|
|
|
uv_unref(); |
|
|
|
uv_unref(loop); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Creates a pipe server. */ |
|
|
|
int uv_pipe_bind(uv_pipe_t* handle, const char* name) { |
|
|
|
uv_loop_t* loop = handle->loop; |
|
|
|
int i, errno, nameSize; |
|
|
|
uv_pipe_accept_t* req; |
|
|
|
|
|
|
|
if (handle->flags & UV_HANDLE_BOUND) { |
|
|
|
uv_set_sys_error(WSAEINVAL); |
|
|
|
uv_set_sys_error(loop, WSAEINVAL); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
if (!name) { |
|
|
|
uv_set_sys_error(WSAEINVAL); |
|
|
|
uv_set_sys_error(loop, WSAEINVAL); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i < COUNTOF(handle->accept_reqs); i++) { |
|
|
|
req = &handle->accept_reqs[i]; |
|
|
|
uv_req_init((uv_req_t*) req); |
|
|
|
uv_req_init(loop, (uv_req_t*) req); |
|
|
|
req->type = UV_ACCEPT; |
|
|
|
req->data = handle; |
|
|
|
req->pipeHandle = INVALID_HANDLE_VALUE; |
|
|
@ -296,7 +299,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { |
|
|
|
} |
|
|
|
|
|
|
|
if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) { |
|
|
|
uv_set_sys_error(GetLastError()); |
|
|
|
uv_set_sys_error(loop, GetLastError()); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
@ -305,28 +308,25 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { |
|
|
|
* If this fails then there's already a pipe server for the given pipe name. |
|
|
|
*/ |
|
|
|
handle->accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name, |
|
|
|
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, |
|
|
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, |
|
|
|
PIPE_UNLIMITED_INSTANCES, |
|
|
|
65536, |
|
|
|
65536, |
|
|
|
0, |
|
|
|
NULL); |
|
|
|
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | |
|
|
|
FILE_FLAG_FIRST_PIPE_INSTANCE, |
|
|
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, |
|
|
|
PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); |
|
|
|
|
|
|
|
if (handle->accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) { |
|
|
|
errno = GetLastError(); |
|
|
|
if (errno == ERROR_ACCESS_DENIED) { |
|
|
|
uv_set_error(UV_EADDRINUSE, errno); |
|
|
|
uv_set_error(loop, UV_EADDRINUSE, errno); |
|
|
|
} else if (errno == ERROR_PATH_NOT_FOUND || errno == ERROR_INVALID_NAME) { |
|
|
|
uv_set_error(UV_EACCESS, errno); |
|
|
|
uv_set_error(loop, UV_EACCESS, errno); |
|
|
|
} else { |
|
|
|
uv_set_sys_error(errno); |
|
|
|
uv_set_sys_error(loop, errno); |
|
|
|
} |
|
|
|
goto error; |
|
|
|
} |
|
|
|
|
|
|
|
if (uv_set_pipe_handle(handle, handle->accept_reqs[0].pipeHandle)) { |
|
|
|
uv_set_sys_error(GetLastError()); |
|
|
|
if (uv_set_pipe_handle(loop, handle, handle->accept_reqs[0].pipeHandle)) { |
|
|
|
uv_set_sys_error(loop, GetLastError()); |
|
|
|
goto error; |
|
|
|
} |
|
|
|
|
|
|
@ -354,15 +354,19 @@ error: |
|
|
|
static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { |
|
|
|
HANDLE pipeHandle = INVALID_HANDLE_VALUE; |
|
|
|
int errno; |
|
|
|
uv_loop_t* loop; |
|
|
|
uv_pipe_t* handle; |
|
|
|
uv_connect_t* req; |
|
|
|
|
|
|
|
req = (uv_connect_t*)parameter; |
|
|
|
req = (uv_connect_t*) parameter; |
|
|
|
assert(req); |
|
|
|
handle = (uv_pipe_t*)req->handle; |
|
|
|
handle = (uv_pipe_t*) req->handle; |
|
|
|
assert(handle); |
|
|
|
loop = handle->loop; |
|
|
|
assert(loop); |
|
|
|
|
|
|
|
/* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait for the pipe to become available with WaitNamedPipe. */ |
|
|
|
/* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. */ |
|
|
|
/* We wait for the pipe to become available with WaitNamedPipe. */ |
|
|
|
while (WaitNamedPipeW(handle->name, 30000)) { |
|
|
|
/* The pipe is now available, try to connect. */ |
|
|
|
pipeHandle = CreateFileW(handle->name, |
|
|
@ -380,7 +384,8 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { |
|
|
|
SwitchToThread(); |
|
|
|
} |
|
|
|
|
|
|
|
if (pipeHandle != INVALID_HANDLE_VALUE && !uv_set_pipe_handle(handle, pipeHandle)) { |
|
|
|
if (pipeHandle != INVALID_HANDLE_VALUE && |
|
|
|
!uv_set_pipe_handle(loop, handle, pipeHandle)) { |
|
|
|
handle->handle = pipeHandle; |
|
|
|
SET_REQ_SUCCESS(req); |
|
|
|
} else { |
|
|
@ -388,7 +393,7 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { |
|
|
|
} |
|
|
|
|
|
|
|
/* Post completed */ |
|
|
|
POST_COMPLETION_FOR_REQ(req); |
|
|
|
POST_COMPLETION_FOR_REQ(loop, req); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
@ -396,12 +401,13 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { |
|
|
|
|
|
|
|
int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, |
|
|
|
const char* name, uv_connect_cb cb) { |
|
|
|
uv_loop_t* loop = handle->loop; |
|
|
|
int errno, nameSize; |
|
|
|
HANDLE pipeHandle; |
|
|
|
|
|
|
|
handle->handle = INVALID_HANDLE_VALUE; |
|
|
|
|
|
|
|
uv_req_init((uv_req_t*) req); |
|
|
|
uv_req_init(loop, (uv_req_t*) req); |
|
|
|
req->type = UV_CONNECT; |
|
|
|
req->handle = (uv_stream_t*) handle; |
|
|
|
req->cb = cb; |
|
|
@ -429,7 +435,9 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, |
|
|
|
if (pipeHandle == INVALID_HANDLE_VALUE) { |
|
|
|
if (GetLastError() == ERROR_PIPE_BUSY) { |
|
|
|
/* Wait for the server to make a pipe instance available. */ |
|
|
|
if (!QueueUserWorkItem(&pipe_connect_thread_proc, req, WT_EXECUTELONGFUNCTION)) { |
|
|
|
if (!QueueUserWorkItem(&pipe_connect_thread_proc, |
|
|
|
req, |
|
|
|
WT_EXECUTELONGFUNCTION)) { |
|
|
|
errno = GetLastError(); |
|
|
|
goto error; |
|
|
|
} |
|
|
@ -443,7 +451,7 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, |
|
|
|
goto error; |
|
|
|
} |
|
|
|
|
|
|
|
if (uv_set_pipe_handle((uv_pipe_t*)req->handle, pipeHandle)) { |
|
|
|
if (uv_set_pipe_handle(loop, (uv_pipe_t*)req->handle, pipeHandle)) { |
|
|
|
errno = GetLastError(); |
|
|
|
goto error; |
|
|
|
} |
|
|
@ -451,7 +459,7 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, |
|
|
|
handle->handle = pipeHandle; |
|
|
|
|
|
|
|
SET_REQ_SUCCESS(req); |
|
|
|
uv_insert_pending_req((uv_req_t*) req); |
|
|
|
uv_insert_pending_req(loop, (uv_req_t*) req); |
|
|
|
handle->reqs_pending++; |
|
|
|
return 0; |
|
|
|
|
|
|
@ -464,12 +472,13 @@ error: |
|
|
|
if (pipeHandle != INVALID_HANDLE_VALUE) { |
|
|
|
CloseHandle(pipeHandle); |
|
|
|
} |
|
|
|
uv_set_sys_error(errno); |
|
|
|
uv_set_sys_error(loop, errno); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Cleans up uv_pipe_t (server or connection) and all resources associated with it */ |
|
|
|
/* Cleans up uv_pipe_t (server or connection) and all resources associated */ |
|
|
|
/* with it. */ |
|
|
|
void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err) { |
|
|
|
int i; |
|
|
|
HANDLE pipeHandle; |
|
|
@ -504,33 +513,30 @@ void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL firstInstance) { |
|
|
|
static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, |
|
|
|
uv_pipe_accept_t* req, BOOL firstInstance) { |
|
|
|
assert(handle->flags & UV_HANDLE_LISTENING); |
|
|
|
|
|
|
|
if (!firstInstance) { |
|
|
|
assert(req->pipeHandle == INVALID_HANDLE_VALUE); |
|
|
|
|
|
|
|
req->pipeHandle = CreateNamedPipeW(handle->name, |
|
|
|
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, |
|
|
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, |
|
|
|
PIPE_UNLIMITED_INSTANCES, |
|
|
|
65536, |
|
|
|
65536, |
|
|
|
0, |
|
|
|
NULL); |
|
|
|
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, |
|
|
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, |
|
|
|
PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); |
|
|
|
|
|
|
|
if (req->pipeHandle == INVALID_HANDLE_VALUE) { |
|
|
|
SET_REQ_ERROR(req, GetLastError()); |
|
|
|
uv_insert_pending_req((uv_req_t*) req); |
|
|
|
uv_insert_pending_req(loop, (uv_req_t*) req); |
|
|
|
handle->reqs_pending++; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (uv_set_pipe_handle(handle, req->pipeHandle)) { |
|
|
|
if (uv_set_pipe_handle(loop, handle, req->pipeHandle)) { |
|
|
|
CloseHandle(req->pipeHandle); |
|
|
|
req->pipeHandle = INVALID_HANDLE_VALUE; |
|
|
|
SET_REQ_ERROR(req, GetLastError()); |
|
|
|
uv_insert_pending_req((uv_req_t*) req); |
|
|
|
uv_insert_pending_req(loop, (uv_req_t*) req); |
|
|
|
handle->reqs_pending++; |
|
|
|
return; |
|
|
|
} |
|
|
@ -541,7 +547,8 @@ static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL |
|
|
|
/* Prepare the overlapped structure. */ |
|
|
|
memset(&(req->overlapped), 0, sizeof(req->overlapped)); |
|
|
|
|
|
|
|
if (!ConnectNamedPipe(req->pipeHandle, &req->overlapped) && GetLastError() != ERROR_IO_PENDING) { |
|
|
|
if (!ConnectNamedPipe(req->pipeHandle, &req->overlapped) && |
|
|
|
GetLastError() != ERROR_IO_PENDING) { |
|
|
|
if (GetLastError() == ERROR_PIPE_CONNECTED) { |
|
|
|
SET_REQ_SUCCESS(req); |
|
|
|
} else { |
|
|
@ -550,7 +557,7 @@ static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL |
|
|
|
/* Make this req pending reporting an error. */ |
|
|
|
SET_REQ_ERROR(req, GetLastError()); |
|
|
|
} |
|
|
|
uv_insert_pending_req((uv_req_t*) req); |
|
|
|
uv_insert_pending_req(loop, (uv_req_t*) req); |
|
|
|
handle->reqs_pending++; |
|
|
|
return; |
|
|
|
} |
|
|
@ -560,12 +567,14 @@ static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL |
|
|
|
|
|
|
|
|
|
|
|
int uv_pipe_accept(uv_pipe_t* server, uv_pipe_t* client) { |
|
|
|
/* Find a connection instance that has been connected, but not yet accepted. */ |
|
|
|
uv_loop_t* loop = server->loop; |
|
|
|
/* Find a connection instance that has been connected, but not yet */ |
|
|
|
/* accepted. */ |
|
|
|
uv_pipe_accept_t* req = server->pending_accepts; |
|
|
|
|
|
|
|
if (!req) { |
|
|
|
/* No valid connections found, so we error out. */ |
|
|
|
uv_set_sys_error(WSAEWOULDBLOCK); |
|
|
|
uv_set_sys_error(loop, WSAEWOULDBLOCK); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
@ -580,7 +589,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_pipe_t* client) { |
|
|
|
|
|
|
|
if (!(server->flags & UV_HANDLE_CLOSING) && |
|
|
|
!(server->flags & UV_HANDLE_GIVEN_OS_HANDLE)) { |
|
|
|
uv_pipe_queue_accept(server, req, FALSE); |
|
|
|
uv_pipe_queue_accept(loop, server, req, FALSE); |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
@ -589,25 +598,27 @@ int uv_pipe_accept(uv_pipe_t* server, uv_pipe_t* client) { |
|
|
|
|
|
|
|
/* Starts listening for connections for the given pipe. */ |
|
|
|
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { |
|
|
|
uv_loop_t* loop = handle->loop; |
|
|
|
|
|
|
|
int i, errno; |
|
|
|
uv_pipe_accept_t* req; |
|
|
|
HANDLE pipeHandle; |
|
|
|
|
|
|
|
if (!(handle->flags & UV_HANDLE_BOUND) && |
|
|
|
!(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) { |
|
|
|
uv_set_error(UV_EINVAL, 0); |
|
|
|
uv_set_error(loop, UV_EINVAL, 0); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
if (handle->flags & UV_HANDLE_LISTENING || |
|
|
|
handle->flags & UV_HANDLE_READING) { |
|
|
|
uv_set_error(UV_EALREADY, 0); |
|
|
|
uv_set_error(loop, UV_EALREADY, 0); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
if (!(handle->flags & UV_HANDLE_PIPESERVER) && |
|
|
|
!(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) { |
|
|
|
uv_set_error(UV_ENOTSUP, 0); |
|
|
|
uv_set_error(loop, UV_ENOTSUP, 0); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
@ -619,24 +630,24 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { |
|
|
|
pipeHandle = handle->handle; |
|
|
|
assert(pipeHandle != INVALID_HANDLE_VALUE); |
|
|
|
req = &handle->accept_reqs[0]; |
|
|
|
uv_req_init((uv_req_t*) req); |
|
|
|
uv_req_init(loop, (uv_req_t*) req); |
|
|
|
req->pipeHandle = pipeHandle; |
|
|
|
req->type = UV_ACCEPT; |
|
|
|
req->data = handle; |
|
|
|
req->next_pending = NULL; |
|
|
|
|
|
|
|
if (uv_set_pipe_handle(handle, pipeHandle)) { |
|
|
|
uv_set_sys_error(GetLastError()); |
|
|
|
if (uv_set_pipe_handle(loop, handle, pipeHandle)) { |
|
|
|
uv_set_sys_error(loop, GetLastError()); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
uv_pipe_queue_accept(handle, req, TRUE); |
|
|
|
uv_pipe_queue_accept(loop, handle, req, TRUE); |
|
|
|
} else { |
|
|
|
/* First pipe handle should have already been created in uv_pipe_bind */ |
|
|
|
assert(handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE); |
|
|
|
|
|
|
|
for (i = 0; i < COUNTOF(handle->accept_reqs); i++) { |
|
|
|
uv_pipe_queue_accept(handle, &handle->accept_reqs[i], i == 0); |
|
|
|
uv_pipe_queue_accept(loop, handle, &handle->accept_reqs[i], i == 0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -644,7 +655,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void uv_pipe_queue_read(uv_pipe_t* handle) { |
|
|
|
static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { |
|
|
|
uv_req_t* req; |
|
|
|
int result; |
|
|
|
|
|
|
@ -666,7 +677,7 @@ static void uv_pipe_queue_read(uv_pipe_t* handle) { |
|
|
|
if (!result && GetLastError() != ERROR_IO_PENDING) { |
|
|
|
/* Make this req pending reporting an error. */ |
|
|
|
SET_REQ_ERROR(req, WSAGetLastError()); |
|
|
|
uv_insert_pending_req(req); |
|
|
|
uv_insert_pending_req(loop, req); |
|
|
|
handle->reqs_pending++; |
|
|
|
return; |
|
|
|
} |
|
|
@ -679,19 +690,22 @@ static void uv_pipe_queue_read(uv_pipe_t* handle) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb) { |
|
|
|
int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, |
|
|
|
uv_read_cb read_cb) { |
|
|
|
uv_loop_t* loop = handle->loop; |
|
|
|
|
|
|
|
if (!(handle->flags & UV_HANDLE_CONNECTION)) { |
|
|
|
uv_set_error(UV_EINVAL, 0); |
|
|
|
uv_set_error(loop, UV_EINVAL, 0); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
if (handle->flags & UV_HANDLE_READING) { |
|
|
|
uv_set_error(UV_EALREADY, 0); |
|
|
|
uv_set_error(loop, UV_EALREADY, 0); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
if (handle->flags & UV_HANDLE_EOF) { |
|
|
|
uv_set_error(UV_EOF, 0); |
|
|
|
uv_set_error(loop, UV_EOF, 0); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
@ -702,34 +716,34 @@ int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_ |
|
|
|
/* If reading was stopped and then started again, there could stell be a */ |
|
|
|
/* read request pending. */ |
|
|
|
if (!(handle->flags & UV_HANDLE_READ_PENDING)) |
|
|
|
uv_pipe_queue_read(handle); |
|
|
|
uv_pipe_queue_read(loop, handle); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int uv_pipe_write(uv_write_t* req, uv_pipe_t* handle, uv_buf_t bufs[], int bufcnt, |
|
|
|
uv_write_cb cb) { |
|
|
|
int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, |
|
|
|
uv_buf_t bufs[], int bufcnt, uv_write_cb cb) { |
|
|
|
int result; |
|
|
|
|
|
|
|
if (bufcnt != 1) { |
|
|
|
uv_set_error(UV_ENOTSUP, 0); |
|
|
|
uv_set_error(loop, UV_ENOTSUP, 0); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
assert(handle->handle != INVALID_HANDLE_VALUE); |
|
|
|
|
|
|
|
if (!(handle->flags & UV_HANDLE_CONNECTION)) { |
|
|
|
uv_set_error(UV_EINVAL, 0); |
|
|
|
uv_set_error(loop, UV_EINVAL, 0); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
if (handle->flags & UV_HANDLE_SHUTTING) { |
|
|
|
uv_set_error(UV_EOF, 0); |
|
|
|
uv_set_error(loop, UV_EOF, 0); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
uv_req_init((uv_req_t*) req); |
|
|
|
uv_req_init(loop, (uv_req_t*) req); |
|
|
|
req->type = UV_WRITE; |
|
|
|
req->handle = (uv_stream_t*) handle; |
|
|
|
req->cb = cb; |
|
|
@ -742,7 +756,7 @@ int uv_pipe_write(uv_write_t* req, uv_pipe_t* handle, uv_buf_t bufs[], int bufcn |
|
|
|
&req->overlapped); |
|
|
|
|
|
|
|
if (!result && GetLastError() != ERROR_IO_PENDING) { |
|
|
|
uv_set_sys_error(GetLastError()); |
|
|
|
uv_set_sys_error(loop, GetLastError()); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
@ -762,7 +776,8 @@ int uv_pipe_write(uv_write_t* req, uv_pipe_t* handle, uv_buf_t bufs[], int bufcn |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void uv_pipe_read_eof(uv_pipe_t* handle, uv_buf_t buf) { |
|
|
|
static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, |
|
|
|
uv_buf_t buf) { |
|
|
|
/* If there is an eof timer running, we don't need it any more, */ |
|
|
|
/* so discard it. */ |
|
|
|
eof_timer_destroy(handle); |
|
|
@ -770,33 +785,36 @@ static void uv_pipe_read_eof(uv_pipe_t* handle, uv_buf_t buf) { |
|
|
|
handle->flags |= UV_HANDLE_EOF; |
|
|
|
uv_read_stop((uv_stream_t*) handle); |
|
|
|
|
|
|
|
uv_set_error(UV_EOF, 0); |
|
|
|
uv_set_error(loop, UV_EOF, 0); |
|
|
|
handle->read_cb((uv_stream_t*) handle, -1, uv_null_buf_); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void uv_pipe_read_error(uv_pipe_t* handle, int error, uv_buf_t buf) { |
|
|
|
static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error, |
|
|
|
uv_buf_t buf) { |
|
|
|
/* If there is an eof timer running, we don't need it any more, */ |
|
|
|
/* so discard it. */ |
|
|
|
eof_timer_destroy(handle); |
|
|
|
|
|
|
|
uv_read_stop((uv_stream_t*) handle); |
|
|
|
|
|
|
|
uv_set_sys_error(error); |
|
|
|
uv_set_sys_error(loop, error); |
|
|
|
handle->read_cb((uv_stream_t*)handle, -1, buf); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void uv_pipe_read_error_or_eof(uv_pipe_t* handle, int error, uv_buf_t buf) { |
|
|
|
static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle, |
|
|
|
int error, uv_buf_t buf) { |
|
|
|
if (error == ERROR_BROKEN_PIPE) { |
|
|
|
uv_pipe_read_eof(handle, buf); |
|
|
|
uv_pipe_read_eof(loop, handle, buf); |
|
|
|
} else { |
|
|
|
uv_pipe_read_error(handle, error, buf); |
|
|
|
uv_pipe_read_error(loop, handle, error, buf); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) { |
|
|
|
void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, |
|
|
|
uv_req_t* req) { |
|
|
|
DWORD bytes, avail; |
|
|
|
uv_buf_t buf; |
|
|
|
|
|
|
@ -808,7 +826,10 @@ void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) { |
|
|
|
if (!REQ_SUCCESS(req)) { |
|
|
|
/* An error occurred doing the 0-read. */ |
|
|
|
if (handle->flags & UV_HANDLE_READING) { |
|
|
|
uv_pipe_read_error_or_eof(handle, GET_REQ_ERROR(req), uv_null_buf_); |
|
|
|
uv_pipe_read_error_or_eof(loop, |
|
|
|
handle, |
|
|
|
GET_REQ_ERROR(req), |
|
|
|
uv_null_buf_); |
|
|
|
} |
|
|
|
} else { |
|
|
|
/* Do non-blocking reads until the buffer is empty */ |
|
|
@ -819,7 +840,7 @@ void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) { |
|
|
|
NULL, |
|
|
|
&avail, |
|
|
|
NULL)) { |
|
|
|
uv_pipe_read_error_or_eof(handle, GetLastError(), uv_null_buf_); |
|
|
|
uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
@ -843,7 +864,7 @@ void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) { |
|
|
|
break; |
|
|
|
} |
|
|
|
} else { |
|
|
|
uv_pipe_read_error_or_eof(handle, GetLastError(), uv_null_buf_); |
|
|
|
uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -851,7 +872,7 @@ void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) { |
|
|
|
/* Post another 0-read if still reading and not closing. */ |
|
|
|
if ((handle->flags & UV_HANDLE_READING) && |
|
|
|
!(handle->flags & UV_HANDLE_READ_PENDING)) { |
|
|
|
uv_pipe_queue_read(handle); |
|
|
|
uv_pipe_queue_read(loop, handle); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -859,14 +880,15 @@ void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void uv_process_pipe_write_req(uv_pipe_t* handle, uv_write_t* req) { |
|
|
|
void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, |
|
|
|
uv_write_t* req) { |
|
|
|
assert(handle->type == UV_NAMED_PIPE); |
|
|
|
|
|
|
|
handle->write_queue_size -= req->queued_bytes; |
|
|
|
|
|
|
|
if (req->cb) { |
|
|
|
if (!REQ_SUCCESS(req)) { |
|
|
|
LOOP->last_error = GET_REQ_UV_ERROR(req); |
|
|
|
loop->last_error = GET_REQ_UV_ERROR(req); |
|
|
|
((uv_write_cb)req->cb)(req, -1); |
|
|
|
} else { |
|
|
|
((uv_write_cb)req->cb)(req, 0); |
|
|
@ -876,14 +898,15 @@ void uv_process_pipe_write_req(uv_pipe_t* handle, uv_write_t* req) { |
|
|
|
handle->write_reqs_pending--; |
|
|
|
if (handle->write_reqs_pending == 0 && |
|
|
|
handle->flags & UV_HANDLE_SHUTTING) { |
|
|
|
uv_want_endgame((uv_handle_t*)handle); |
|
|
|
uv_want_endgame(loop, (uv_handle_t*)handle); |
|
|
|
} |
|
|
|
|
|
|
|
DECREASE_PENDING_REQ_COUNT(handle); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void uv_process_pipe_accept_req(uv_pipe_t* handle, uv_req_t* raw_req) { |
|
|
|
void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, |
|
|
|
uv_req_t* raw_req) { |
|
|
|
uv_pipe_accept_t* req = (uv_pipe_accept_t*) raw_req; |
|
|
|
|
|
|
|
assert(handle->type == UV_NAMED_PIPE); |
|
|
@ -903,7 +926,7 @@ void uv_process_pipe_accept_req(uv_pipe_t* handle, uv_req_t* raw_req) { |
|
|
|
} |
|
|
|
if (!(handle->flags & UV_HANDLE_CLOSING) && |
|
|
|
!(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) { |
|
|
|
uv_pipe_queue_accept(handle, req, FALSE); |
|
|
|
uv_pipe_queue_accept(loop, handle, req, FALSE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -911,7 +934,8 @@ void uv_process_pipe_accept_req(uv_pipe_t* handle, uv_req_t* raw_req) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void uv_process_pipe_connect_req(uv_pipe_t* handle, uv_connect_t* req) { |
|
|
|
void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle, |
|
|
|
uv_connect_t* req) { |
|
|
|
assert(handle->type == UV_NAMED_PIPE); |
|
|
|
|
|
|
|
if (req->cb) { |
|
|
@ -919,7 +943,7 @@ void uv_process_pipe_connect_req(uv_pipe_t* handle, uv_connect_t* req) { |
|
|
|
uv_pipe_connection_init(handle); |
|
|
|
((uv_connect_cb)req->cb)(req, 0); |
|
|
|
} else { |
|
|
|
LOOP->last_error = GET_REQ_UV_ERROR(req); |
|
|
|
loop->last_error = GET_REQ_UV_ERROR(req); |
|
|
|
((uv_connect_cb)req->cb)(req, -1); |
|
|
|
} |
|
|
|
} |
|
|
@ -928,7 +952,8 @@ void uv_process_pipe_connect_req(uv_pipe_t* handle, uv_connect_t* req) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void uv_process_pipe_shutdown_req(uv_pipe_t* handle, uv_shutdown_t* req) { |
|
|
|
void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, |
|
|
|
uv_shutdown_t* req) { |
|
|
|
assert(handle->type == UV_NAMED_PIPE); |
|
|
|
|
|
|
|
/* Initialize and optionally start the eof timer. */ |
|
|
@ -959,7 +984,7 @@ static void eof_timer_init(uv_pipe_t* pipe) { |
|
|
|
|
|
|
|
pipe->eof_timer = (uv_timer_t*) malloc(sizeof *pipe->eof_timer); |
|
|
|
|
|
|
|
r = uv_timer_init(pipe->eof_timer); |
|
|
|
r = uv_timer_init(pipe->loop, pipe->eof_timer); |
|
|
|
assert(r == 0); /* timers can't fail */ |
|
|
|
pipe->eof_timer->data = pipe; |
|
|
|
} |
|
|
@ -985,6 +1010,7 @@ static void eof_timer_stop(uv_pipe_t* pipe) { |
|
|
|
|
|
|
|
static void eof_timer_cb(uv_timer_t* timer, int status) { |
|
|
|
uv_pipe_t* pipe = (uv_pipe_t*) timer->data; |
|
|
|
uv_loop_t* loop = timer->loop; |
|
|
|
|
|
|
|
assert(status == 0); /* timers can't fail */ |
|
|
|
assert(pipe->type == UV_NAMED_PIPE); |
|
|
@ -1015,7 +1041,7 @@ static void eof_timer_cb(uv_timer_t* timer, int status) { |
|
|
|
|
|
|
|
/* Report the eof and update flags. This will get reported even if the */ |
|
|
|
/* user stopped reading in the meantime. TODO: is that okay? */ |
|
|
|
uv_pipe_read_eof(pipe, uv_null_buf_); |
|
|
|
uv_pipe_read_eof(loop, pipe, uv_null_buf_); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|