Created
July 25, 2011 17:29
-
-
Save igorzi/1104651 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 252da78830c1b6618161227b206e6079a2f4ddd8 Mon Sep 17 00:00:00 2001 | |
From: Igor Zinkovsky <igorzi@microsoft.com> | |
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 | 1 + | |
src/uv-unix.c | 5 +++ | |
src/win/internal.h | 3 ++ | |
src/win/pipe.c | 62 +++++++++++++++++++++++++++++++++++++----- | |
src/win/stdio.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
6 files changed, 146 insertions(+), 8 deletions(-) | |
create mode 100644 src/win/stdio.c | |
diff --git a/include/uv.h b/include/uv.h | |
index c5a721c..e2ef403 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 fbfca78..8a9975d 100644 | |
--- a/msvs/libuv.vcxproj | |
+++ b/msvs/libuv.vcxproj | |
@@ -134,6 +134,7 @@ | |
<ClCompile Include="..\src\win\loop-watcher.c" /> | |
<ClCompile Include="..\src\win\pipe.c" /> | |
<ClCompile Include="..\src\win\req.c" /> | |
+ <ClCompile Include="..\src\win\stdio.c" /> | |
<ClCompile Include="..\src\win\stream.c" /> | |
<ClCompile Include="..\src\win\tcp.c" /> | |
<ClCompile Include="..\src\win\timer.c" /> | |
diff --git a/src/uv-unix.c b/src/uv-unix.c | |
index 72f77df..69cdd60 100644 | |
--- a/src/uv-unix.c | |
+++ b/src/uv-unix.c | |
@@ -2132,3 +2132,8 @@ size_t uv__strlcpy(char* dst, const char* src, size_t size) { | |
return src - org; | |
} | |
+ | |
+ | |
+uv_stream_t* uv_std_handle(uv_std_type type) { | |
+ assert(0 && "implement me"); | |
+} | |
diff --git a/src/win/internal.h b/src/win/internal.h | |
index 85df9cb..efb05f8 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 0ed1fda..7c98ab0 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 0000000..0333133 | |
--- /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 <assert.h> | |
+#include <string.h> | |
+ | |
+#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; | |
+ } | |
+} | |
-- | |
1.7.4.msysgit.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment