From ac2812a1cfa91b81992a231d34e6b591aa5e34cc Mon Sep 17 00:00:00 2001 From: Igor Zinkovsky Date: Sat, 23 Jul 2011 10:47:14 -0700 Subject: [PATCH] uv_std_handle + uv_listen on stdin --- include/uv.h | 8 +++++ msvs/libuv.vcxproj | 3 +- src/win/internal.h | 3 ++ src/win/pipe.c | 62 +++++++++++++++++++++++++++++++++----- src/win/stdio.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 src/win/stdio.c diff --git a/include/uv.h b/include/uv.h index c5a721c07d..e2ef403b59 100644 --- a/include/uv.h +++ b/include/uv.h @@ -271,6 +271,14 @@ int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb); int uv_read_stop(uv_stream_t*); +typedef enum { + UV_STDIN = 0, + UV_STDOUT, + UV_STDERR +} uv_std_type; + +uv_stream_t* uv_std_handle(uv_std_type type); + /* * Write data to stream. Buffers are written in order. Example: * diff --git a/msvs/libuv.vcxproj b/msvs/libuv.vcxproj index fbfca78941..d212532601 100644 --- a/msvs/libuv.vcxproj +++ b/msvs/libuv.vcxproj @@ -134,6 +134,7 @@ + @@ -155,4 +156,4 @@ - + \ No newline at end of file diff --git a/src/win/internal.h b/src/win/internal.h index 85df9cb384..efb05f85fe 100644 --- a/src/win/internal.h +++ b/src/win/internal.h @@ -102,6 +102,8 @@ extern uv_loop_t uv_main_loop_; #define UV_HANDLE_IPV6 0x2000 #define UV_HANDLE_PIPESERVER 0x4000 #define UV_HANDLE_READ_PENDING 0x8000 +#define UV_HANDLE_GIVEN_OS_HANDLE 0x10000 +#define UV_HANDLE_UV_ALLOCED 0x20000 void uv_want_endgame(uv_handle_t* handle); void uv_process_endgames(); @@ -160,6 +162,7 @@ void uv_process_tcp_connect_req(uv_tcp_t* handle, uv_connect_t* req); /* * Pipes */ +int uv_pipe_init_with_handle(uv_pipe_t* handle, HANDLE pipeHandle); void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err); void uv_pipe_endgame(uv_pipe_t* handle); diff --git a/src/win/pipe.c b/src/win/pipe.c index 0ed1fda0d9..7c98ab0eff 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -46,6 +46,23 @@ int uv_pipe_init(uv_pipe_t* handle) { } +int uv_pipe_init_with_handle(uv_pipe_t* handle, HANDLE pipeHandle) { + int err = uv_pipe_init(handle); + + if (!err) { + /* + * At this point we don't know whether the pipe will be used as a client + * or a server. So, we assume that it will be a client until + * uv_listen is called. + */ + handle->handle = pipeHandle; + handle->flags |= UV_HANDLE_GIVEN_OS_HANDLE; + } + + return err; +} + + static int uv_set_pipe_handle(uv_pipe_t* handle, HANDLE pipeHandle) { DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT; @@ -91,6 +108,10 @@ void uv_pipe_endgame(uv_pipe_t* handle) { handle->close_cb((uv_handle_t*)handle); } + if (handle->flags & UV_HANDLE_UV_ALLOCED) { + free(handle); + } + uv_unref(); } } @@ -407,7 +428,8 @@ int uv_pipe_accept(uv_pipe_t* server, uv_pipe_t* client) { req->next_pending = NULL; req->pipeHandle = INVALID_HANDLE_VALUE; - if (!(server->flags & UV_HANDLE_CLOSING)) { + if (!(server->flags & UV_HANDLE_CLOSING) && + !(server->flags & UV_HANDLE_GIVEN_OS_HANDLE)) { uv_pipe_queue_accept(server, req, FALSE); } @@ -418,13 +440,16 @@ 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) { int i, errno; + uv_pipe_accept_t* req; + HANDLE pipeHandle; if (handle->flags & UV_HANDLE_BIND_ERROR) { LOOP->last_error = handle->error; return -1; } - if (!(handle->flags & UV_HANDLE_BOUND)) { + if (!(handle->flags & UV_HANDLE_BOUND) && + !(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) { uv_set_error(UV_ENOTCONN, 0); return -1; } @@ -435,7 +460,8 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { return -1; } - if (!(handle->flags & UV_HANDLE_PIPESERVER)) { + if (!(handle->flags & UV_HANDLE_PIPESERVER) && + !(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) { uv_set_error(UV_ENOTSUP, 0); return -1; } @@ -443,11 +469,30 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { handle->flags |= UV_HANDLE_LISTENING; handle->connection_cb = cb; - /* First pipe handle should have already been created in uv_pipe_bind */ - assert(handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE); + if (handle->flags & UV_HANDLE_GIVEN_OS_HANDLE) { + handle->flags |= UV_HANDLE_PIPESERVER; + pipeHandle = handle->handle; + assert(pipeHandle != INVALID_HANDLE_VALUE); + req = &handle->accept_reqs[0]; + uv_req_init((uv_req_t*) req); + req->pipeHandle = pipeHandle; + req->type = UV_ACCEPT; + req->data = handle; + req->next_pending = NULL; - for (i = 0; i < COUNTOF(handle->accept_reqs); i++) { - uv_pipe_queue_accept(handle, &handle->accept_reqs[i], i == 0); + if (uv_set_pipe_handle(handle, pipeHandle)) { + uv_set_sys_error(GetLastError()); + return -1; + } + + uv_pipe_queue_accept(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); + } } return 0; @@ -685,7 +730,8 @@ void uv_process_pipe_accept_req(uv_pipe_t* handle, uv_req_t* raw_req) { CloseHandle(req->pipeHandle); req->pipeHandle = INVALID_HANDLE_VALUE; } - if (!(handle->flags & UV_HANDLE_CLOSING)) { + if (!(handle->flags & UV_HANDLE_CLOSING) && + !(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) { uv_pipe_queue_accept(handle, req, FALSE); } } diff --git a/src/win/stdio.c b/src/win/stdio.c new file mode 100644 index 0000000000..9be6beef96 --- /dev/null +++ b/src/win/stdio.c @@ -0,0 +1,75 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include + +#include "uv.h" +#include "../uv-common.h" +#include "internal.h" + + +static uv_pipe_t* uv_make_pipe_for_std_handle(HANDLE handle) { + uv_pipe_t* pipe = NULL; + + pipe = (uv_pipe_t*)malloc(sizeof(uv_pipe_t)); + if (!pipe) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + } + + if (uv_pipe_init_with_handle(pipe, handle)) { + free(pipe); + return NULL; + } + + pipe->flags |= UV_HANDLE_UV_ALLOCED; + return pipe; +} + + +uv_stream_t* uv_std_handle(uv_std_type type) { + HANDLE handle; + + switch (type) { + case UV_STDIN: + handle = GetStdHandle(STD_INPUT_HANDLE); + if (handle == INVALID_HANDLE_VALUE) { + return NULL; + } + + /* Assume only named pipes for now. */ + return (uv_stream_t*)uv_make_pipe_for_std_handle(handle); + break; + + case UV_STDOUT: + return NULL; + break; + + case UV_STDERR: + return NULL; + break; + + default: + assert(0); + uv_set_error(UV_EINVAL, 0); + return NULL; + } +} \ No newline at end of file