From 2f22024806269e9836f56ef9a55d08991acd8a21 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Sat, 29 Oct 2011 01:06:09 +0200 Subject: [PATCH] Upgrade libuv to 90e15f1110 --- deps/uv/build/gcc_version.py | 20 ++ deps/uv/common.gypi | 15 +- deps/uv/include/uv-private/uv-unix.h | 14 ++ deps/uv/include/uv-private/uv-win.h | 4 + deps/uv/include/uv.h | 323 ++++++++++++++++------------ deps/uv/src/ares/config_win32/ares_config.h | 3 - deps/uv/src/unix/core.c | 4 +- deps/uv/src/unix/dl.c | 59 +++++ deps/uv/src/unix/error.c | 5 +- deps/uv/src/unix/sunos.c | 84 +++++++- deps/uv/src/uv-common.c | 9 + deps/uv/src/uv-common.h | 1 + deps/uv/src/win/dl.c | 63 ++++++ deps/uv/src/win/error.c | 2 +- deps/uv/src/win/internal.h | 2 + deps/uv/src/win/pipe.c | 4 +- deps/uv/src/win/tcp.c | 166 +++++++++----- deps/uv/test/test-list.h | 2 + deps/uv/test/test-multiple-listen.c | 102 +++++++++ deps/uv/test/test-stdio-over-pipes.c | 3 + deps/uv/uv.gyp | 17 +- 21 files changed, 697 insertions(+), 205 deletions(-) create mode 100644 deps/uv/build/gcc_version.py create mode 100644 deps/uv/src/unix/dl.c create mode 100644 deps/uv/src/win/dl.c create mode 100644 deps/uv/test/test-multiple-listen.c diff --git a/deps/uv/build/gcc_version.py b/deps/uv/build/gcc_version.py new file mode 100644 index 0000000..da019e8 --- /dev/null +++ b/deps/uv/build/gcc_version.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +import os +import re +import subprocess +import sys + + +def DoMain(*args): + cc = os.environ.get('CC', 'gcc') + stdin, stderr = os.pipe() + subprocess.call([cc, '-v'], stderr=stderr) + output = os.read(stdin, 4096) + match = re.search("\ngcc version (\d+\.\d+\.\d+)", output) + if match: + print(match.group(1)) + + +if __name__ == '__main__': + DoMain(*sys.argv) diff --git a/deps/uv/common.gypi b/deps/uv/common.gypi index 373c3aa..31d6b64 100644 --- a/deps/uv/common.gypi +++ b/deps/uv/common.gypi @@ -114,9 +114,11 @@ ], }], [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', { - 'cflags': [ '-Wall', '-pthread', ], + 'variables': { + 'gcc_version%': ')', + }, + 'cflags': [ '-Wall' ], 'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ], - 'ldflags': [ '-pthread', ], 'conditions': [ [ 'host_arch != target_arch and target_arch=="ia32"', { 'cflags': [ '-m32' ], @@ -125,7 +127,14 @@ [ 'OS=="linux"', { 'cflags': [ '-ansi' ], }], - [ 'visibility=="hidden"', { + [ 'OS=="solaris"', { + 'cflags': [ '-pthreads' ], + 'ldflags': [ '-pthreads' ], + }, { + 'cflags': [ '-pthread' ], + 'ldflags': [ '-pthread' ], + }], + [ 'visibility=="hidden" and gcc_version >= "4.0.0"', { 'cflags': [ '-fvisibility=hidden' ], }], ], diff --git a/deps/uv/include/uv-private/uv-unix.h b/deps/uv/include/uv-private/uv-unix.h index 0db14e9..b07781f 100644 --- a/deps/uv/include/uv-private/uv-unix.h +++ b/deps/uv/include/uv-private/uv-unix.h @@ -43,6 +43,10 @@ typedef struct { typedef int uv_file; +/* Platform-specific definitions for uv_dlopen support. */ +typedef void* uv_lib_t; +#define UV_DYNAMIC /* empty */ + #define UV_LOOP_PRIVATE_FIELDS \ ares_channel channel; \ /* \ @@ -195,6 +199,16 @@ typedef int uv_file; uv_fs_event_cb cb; \ int fflags; \ +#elif defined(__sun) + +#include +#include + +#define UV_FS_EVENT_PRIVATE_FIELDS \ + ev_io event_watcher; \ + uv_fs_event_cb cb; \ + file_obj_t fo; \ + #else /* Stub for platforms where the file watcher isn't implemented yet. */ diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h index ed132d3..9d18fa1 100644 --- a/deps/uv/include/uv-private/uv-win.h +++ b/deps/uv/include/uv-private/uv-win.h @@ -137,6 +137,10 @@ typedef struct uv_buf_t { typedef int uv_file; +/* Platform-specific definitions for uv_dlopen support. */ +typedef HMODULE uv_lib_t; +#define UV_DYNAMIC FAR WINAPI + RB_HEAD(uv_timer_tree_s, uv_timer_s); #define UV_LOOP_PRIVATE_FIELDS \ diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 7bee299..b1ea7a5 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -27,10 +27,29 @@ extern "C" { #endif +#ifdef _WIN32 + /* Windows - set up dll import/export decorators. */ +# if defined(BUILDING_UV_SHARED) + /* Building shared library. Export everything from c-ares as well. */ +# define UV_EXTERN __declspec(dllexport) +# define CARES_BUILDING_LIBRARY 1 +# elif defined(USING_UV_SHARED) + /* Using shared library. Use shared c-ares as well. */ +# define UV_EXTERN __declspec(dllimport) +# else + /* Building static library. Build c-ares statically as well. */ +# define UV_EXTERN /* nothing */ +# define CARES_STATICLIB 1 +# endif +#else + /* Unix. TODO: symbol hiding */ +# define UV_EXTERN /* nothing */ +#endif + + #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 1 -#define CARES_STATICLIB 1 #include /* int64_t */ #include /* size_t */ @@ -52,6 +71,7 @@ typedef enum { UV_UNKNOWN = -1, UV_OK = 0, UV_EOF, + UV_EADDRINFO, UV_EACCESS, UV_EAGAIN, UV_EADDRINUSE, @@ -170,30 +190,30 @@ typedef struct uv_work_s uv_work_t; * All callbacks in libuv are made asynchronously. That is they are never * made by the function that takes them as a parameter. */ -uv_loop_t* uv_loop_new(); -void uv_loop_delete(uv_loop_t*); +UV_EXTERN uv_loop_t* uv_loop_new(); +UV_EXTERN void uv_loop_delete(uv_loop_t*); /* * Returns the default loop. */ -uv_loop_t* uv_default_loop(); +UV_EXTERN uv_loop_t* uv_default_loop(); /* * This function starts the event loop. It blocks until the reference count * of the loop drops to zero. */ -int uv_run(uv_loop_t*); +UV_EXTERN int uv_run (uv_loop_t*); /* * Manually modify the event loop's reference count. Useful if the user wants * to have a handle or timeout that doesn't keep the loop alive. */ -void uv_ref(uv_loop_t*); -void uv_unref(uv_loop_t*); +UV_EXTERN void uv_ref(uv_loop_t*); +UV_EXTERN void uv_unref(uv_loop_t*); -void uv_update_time(uv_loop_t*); -int64_t uv_now(uv_loop_t*); +UV_EXTERN void uv_update_time(uv_loop_t*); +UV_EXTERN int64_t uv_now(uv_loop_t*); /* @@ -260,9 +280,9 @@ struct uv_err_s { * On error the user should then call uv_last_error() to determine * the error code. */ -uv_err_t uv_last_error(uv_loop_t*); -char* uv_strerror(uv_err_t err); -const char* uv_err_name(uv_err_t err); +UV_EXTERN uv_err_t uv_last_error(uv_loop_t*); +UV_EXTERN const char* uv_strerror(uv_err_t err); +UV_EXTERN const char* uv_err_name(uv_err_t err); #define UV_REQ_FIELDS \ @@ -291,7 +311,8 @@ UV_PRIVATE_REQ_TYPES * initialized stream. req should be an uninitalized shutdown request * struct. The cb is a called after shutdown is complete. */ -int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb); +UV_EXTERN int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, + uv_shutdown_cb cb); struct uv_shutdown_s { UV_REQ_FIELDS @@ -320,7 +341,7 @@ struct uv_handle_s { * Returns 1 if the prepare/check/idle handle has been started, 0 otherwise. * For other handle types this always returns 1. */ -int uv_is_active(uv_handle_t* handle); +UV_EXTERN int uv_is_active(uv_handle_t* handle); /* * Request handle to be closed. close_cb will be called asynchronously after @@ -330,7 +351,7 @@ int uv_is_active(uv_handle_t* handle); * close_cb will still be deferred to the next iteration of the event loop. * It gives you a chance to free up any resources associated with the handle. */ -void uv_close(uv_handle_t* handle, uv_close_cb close_cb); +UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb); /* @@ -339,7 +360,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb); * base and len members of the uv_buf_t struct. The user is responsible for * freeing base after the uv_buf_t is done. Return struct passed by value. */ -uv_buf_t uv_buf_init(char* base, size_t len); +UV_EXTERN uv_buf_t uv_buf_init(char* base, size_t len); #define UV_STREAM_FIELDS \ @@ -364,7 +385,7 @@ struct uv_stream_s { UV_STREAM_FIELDS }; -int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb); +UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb); /* * This call is used in conjunction with uv_listen() to accept incoming @@ -377,7 +398,7 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb); * once, it may fail. It is suggested to only call uv_accept once per * uv_connection_cb call. */ -int uv_accept(uv_stream_t* server, uv_stream_t* client); +UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client); /* * Read data from an incoming stream. The callback will be made several @@ -389,15 +410,17 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client); * eof; it happens when libuv requested a buffer through the alloc callback * but then decided that it didn't need that buffer. */ -int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb); +UV_EXTERN int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, + uv_read_cb read_cb); -int uv_read_stop(uv_stream_t*); +UV_EXTERN int uv_read_stop(uv_stream_t*); /* * Extended read methods for receiving handles over a pipe. The pipe must be * initialized with ipc == 1. */ -int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read2_cb read_cb); +UV_EXTERN int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb, + uv_read2_cb read_cb); /* @@ -418,11 +441,11 @@ int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read2_cb read_cb); * uv_write(req, stream, b, 2); * */ -int uv_write(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt, - uv_write_cb cb); +UV_EXTERN int uv_write(uv_write_t* req, uv_stream_t* handle, + uv_buf_t bufs[], int bufcnt, uv_write_cb cb); -int uv_write2(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt, - uv_stream_t* send_handle, uv_write_cb cb); +UV_EXTERN int uv_write2(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], + int bufcnt, uv_stream_t* send_handle, uv_write_cb cb); /* uv_write_t is a subclass of uv_req_t */ struct uv_write_s { @@ -446,21 +469,24 @@ struct uv_tcp_s { UV_TCP_PRIVATE_FIELDS }; -int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle); +UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle); /* Enable/disable Nagle's algorithm. */ -int uv_tcp_nodelay(uv_tcp_t* handle, int enable); +UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable); /* Enable/disable TCP keep-alive. * * `ms` is the initial delay in seconds, ignored when `enable` is zero. */ -int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay); +UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle, int enable, + unsigned int delay); -int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in); -int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6); -int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen); -int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, int* namelen); +UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in); +UV_EXTERN int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6); +UV_EXTERN int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, + int* namelen); +UV_EXTERN int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, + int* namelen); /* * uv_tcp_connect, uv_tcp_connect6 @@ -468,9 +494,9 @@ int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, int* namelen); * initialized TCP handle and an uninitialized uv_connect_t*. The callback * will be made when the connection is estabished. */ -int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, +UV_EXTERN int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in address, uv_connect_cb cb); -int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle, +UV_EXTERN int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in6 address, uv_connect_cb cb); /* uv_connect_t is a subclass of uv_req_t */ @@ -537,7 +563,7 @@ struct uv_udp_send_s { * Initialize a new UDP handle. The actual socket is created lazily. * Returns 0 on success. */ -int uv_udp_init(uv_loop_t*, uv_udp_t* handle); +UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle); /* * Bind to a IPv4 address and port. @@ -550,7 +576,8 @@ int uv_udp_init(uv_loop_t*, uv_udp_t* handle); * Returns: * 0 on success, -1 on error. */ -int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags); +UV_EXTERN int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, + unsigned flags); /* * Bind to a IPv6 address and port. @@ -563,14 +590,17 @@ int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags); * Returns: * 0 on success, -1 on error. */ -int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags); -int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen); +UV_EXTERN int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, + unsigned flags); +UV_EXTERN int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, + int* namelen); /* * Set membership for a multicast address * * Arguments: - * handle UDP handle. Should have been initialized with `uv_udp_init`. + * handle UDP handle. Should have been initialized with + * `uv_udp_init`. * multicast_addr multicast address to set membership for * interface_addr interface address * membership Should be UV_JOIN_GROUP or UV_LEAVE_GROUP @@ -578,8 +608,9 @@ int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen); * Returns: * 0 on success, -1 on error. */ -int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, - const char* interface_addr, uv_membership membership); +UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle, + const char* multicast_addr, const char* interface_addr, + uv_membership membership); /* * Send data. If the socket has not previously been bound with `uv_udp_bind` @@ -597,8 +628,9 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, * Returns: * 0 on success, -1 on error. */ -int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], - int bufcnt, struct sockaddr_in addr, uv_udp_send_cb send_cb); +UV_EXTERN int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, + uv_buf_t bufs[], int bufcnt, struct sockaddr_in addr, + uv_udp_send_cb send_cb); /* * Send data. If the socket has not previously been bound with `uv_udp_bind6`, @@ -615,8 +647,9 @@ int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], * Returns: * 0 on success, -1 on error. */ -int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], - int bufcnt, struct sockaddr_in6 addr, uv_udp_send_cb send_cb); +UV_EXTERN int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle, + uv_buf_t bufs[], int bufcnt, struct sockaddr_in6 addr, + uv_udp_send_cb send_cb); /* * Receive data. If the socket has not previously been bound with `uv_udp_bind` @@ -631,7 +664,7 @@ int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], * Returns: * 0 on success, -1 on error. */ -int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, +UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, uv_udp_recv_cb recv_cb); /* @@ -643,7 +676,7 @@ int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, * Returns: * 0 on success, -1 on error. */ -int uv_udp_recv_stop(uv_udp_t* handle); +UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle); /* @@ -668,23 +701,23 @@ struct uv_tty_s { * * TTY streams which are not readable have blocking writes. */ -int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable); +UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable); /* * Set mode. 0 for normal, 1 for raw. */ -int uv_tty_set_mode(uv_tty_t*, int mode); +UV_EXTERN int uv_tty_set_mode(uv_tty_t*, int mode); /* * To be called when the program exits. Resets TTY settings to default * values for the next process to take over. */ -void uv_tty_reset_mode(); +UV_EXTERN void uv_tty_reset_mode(); /* * Gets the current Window size. On success zero is returned. */ -int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); +UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); /* * Used to detect what type of stream should be used with a given file @@ -692,7 +725,7 @@ int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); * type of the stdio streams. * For isatty() functionality use this function and test for UV_TTY. */ -uv_handle_type uv_guess_handle(uv_file file); +UV_EXTERN uv_handle_type uv_guess_handle(uv_file file); /* * uv_pipe_t is a subclass of uv_stream_t @@ -711,16 +744,16 @@ struct uv_pipe_s { * Initialize a pipe. The last argument is a boolean to indicate if * this pipe will be used for handle passing between processes. */ -int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc); +UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc); /* * Opens an existing file descriptor or HANDLE as a pipe. */ -void uv_pipe_open(uv_pipe_t*, uv_file file); +UV_EXTERN void uv_pipe_open(uv_pipe_t*, uv_file file); -int uv_pipe_bind(uv_pipe_t* handle, const char* name); +UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name); -int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, +UV_EXTERN int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb); @@ -736,11 +769,11 @@ struct uv_prepare_s { UV_PREPARE_PRIVATE_FIELDS }; -int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare); +UV_EXTERN int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare); -int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb); +UV_EXTERN int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb); -int uv_prepare_stop(uv_prepare_t* prepare); +UV_EXTERN int uv_prepare_stop(uv_prepare_t* prepare); /* @@ -754,11 +787,11 @@ struct uv_check_s { UV_CHECK_PRIVATE_FIELDS }; -int uv_check_init(uv_loop_t*, uv_check_t* check); +UV_EXTERN int uv_check_init(uv_loop_t*, uv_check_t* check); -int uv_check_start(uv_check_t* check, uv_check_cb cb); +UV_EXTERN int uv_check_start(uv_check_t* check, uv_check_cb cb); -int uv_check_stop(uv_check_t* check); +UV_EXTERN int uv_check_stop(uv_check_t* check); /* @@ -774,11 +807,11 @@ struct uv_idle_s { UV_IDLE_PRIVATE_FIELDS }; -int uv_idle_init(uv_loop_t*, uv_idle_t* idle); +UV_EXTERN int uv_idle_init(uv_loop_t*, uv_idle_t* idle); -int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb); +UV_EXTERN int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb); -int uv_idle_stop(uv_idle_t* idle); +UV_EXTERN int uv_idle_stop(uv_idle_t* idle); /* @@ -796,14 +829,15 @@ struct uv_async_s { UV_ASYNC_PRIVATE_FIELDS }; -int uv_async_init(uv_loop_t*, uv_async_t* async, uv_async_cb async_cb); +UV_EXTERN int uv_async_init(uv_loop_t*, uv_async_t* async, + uv_async_cb async_cb); /* * This can be called from other threads to wake up a libuv thread. * * libuv is single threaded at the moment. */ -int uv_async_send(uv_async_t* async); +UV_EXTERN int uv_async_send(uv_async_t* async); /* @@ -817,19 +851,19 @@ struct uv_timer_s { UV_TIMER_PRIVATE_FIELDS }; -int uv_timer_init(uv_loop_t*, uv_timer_t* timer); +UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* timer); -int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, int64_t timeout, - int64_t repeat); +UV_EXTERN int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, + int64_t timeout, int64_t repeat); -int uv_timer_stop(uv_timer_t* timer); +UV_EXTERN int uv_timer_stop(uv_timer_t* timer); /* * Stop the timer, and if it is repeating restart it using the repeat value * as the timeout. If the timer has never been started before it returns -1 and * sets the error to UV_EINVAL. */ -int uv_timer_again(uv_timer_t* timer); +UV_EXTERN int uv_timer_again(uv_timer_t* timer); /* * Set the repeat value. Note that if the repeat value is set from a timer @@ -837,19 +871,17 @@ int uv_timer_again(uv_timer_t* timer); * before, it will have been stopped. If it was repeating, then the old repeat * value will have been used to schedule the next timeout. */ -void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat); +UV_EXTERN void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat); -int64_t uv_timer_get_repeat(uv_timer_t* timer); +UV_EXTERN int64_t uv_timer_get_repeat(uv_timer_t* timer); /* c-ares integration initialize and terminate */ -int uv_ares_init_options(uv_loop_t*, - ares_channel *channelptr, - struct ares_options *options, - int optmask); +UV_EXTERN int uv_ares_init_options(uv_loop_t*, + ares_channel *channelptr, struct ares_options *options, int optmask); /* TODO remove the loop argument from this function? */ -void uv_ares_destroy(uv_loop_t*, ares_channel channel); +UV_EXTERN void uv_ares_destroy(uv_loop_t*, ares_channel channel); /* @@ -877,14 +909,11 @@ struct uv_getaddrinfo_s { * * On error NXDOMAIN the status code will be non-zero and UV_ENOENT returned. */ - int uv_getaddrinfo(uv_loop_t*, - uv_getaddrinfo_t* handle, - uv_getaddrinfo_cb getaddrinfo_cb, - const char* node, - const char* service, - const struct addrinfo* hints); +UV_EXTERN int uv_getaddrinfo(uv_loop_t*, uv_getaddrinfo_t* handle, + uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, + const struct addrinfo* hints); -void uv_freeaddrinfo(struct addrinfo* ai); +UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai); /* uv_spawn() options */ typedef struct uv_process_options_s { @@ -934,13 +963,14 @@ struct uv_process_s { }; /* Initializes uv_process_t and starts the process. */ -int uv_spawn(uv_loop_t*, uv_process_t*, uv_process_options_t options); +UV_EXTERN int uv_spawn(uv_loop_t*, uv_process_t*, + uv_process_options_t options); /* * Kills the process with the specified signal. The user must still * call uv_close on the process. */ -int uv_process_kill(uv_process_t*, int signum); +UV_EXTERN int uv_process_kill(uv_process_t*, int signum); /* @@ -955,8 +985,8 @@ struct uv_work_s { }; /* Queues a work request to execute asynchronously on the thread pool. */ -int uv_queue_work(uv_loop_t* loop, uv_work_t* req, uv_work_cb work_cb, - uv_after_work_cb after_work_cb); +UV_EXTERN int uv_queue_work(uv_loop_t* loop, uv_work_t* req, + uv_work_cb work_cb, uv_after_work_cb after_work_cb); @@ -1018,58 +1048,66 @@ struct uv_fs_s { UV_FS_PRIVATE_FIELDS }; -void uv_fs_req_cleanup(uv_fs_t* req); +UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req); -int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); +UV_EXTERN int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, + uv_fs_cb cb); -int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, - int mode, uv_fs_cb cb); +UV_EXTERN int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, + int flags, int mode, uv_fs_cb cb); -int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf, - size_t length, off_t offset, uv_fs_cb cb); +UV_EXTERN int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, + void* buf, size_t length, off_t offset, uv_fs_cb cb); -int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); +UV_EXTERN int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, + uv_fs_cb cb); -int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf, - size_t length, off_t offset, uv_fs_cb cb); +UV_EXTERN int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, + void* buf, size_t length, off_t offset, uv_fs_cb cb); -int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, +UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, + int mode, uv_fs_cb cb); + +UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); -int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); +UV_EXTERN int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, + const char* path, int flags, uv_fs_cb cb); -int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, +UV_EXTERN int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); -int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); - -int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); +UV_EXTERN int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, + uv_fs_cb cb); -int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, +UV_EXTERN int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); -int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); +UV_EXTERN int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, + uv_fs_cb cb); -int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); +UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, + uv_fs_cb cb); -int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, +UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, off_t offset, uv_fs_cb cb); -int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, +UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb); -int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, - uv_fs_cb cb); +UV_EXTERN int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, + int mode, uv_fs_cb cb); -int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, - double mtime, uv_fs_cb cb); +UV_EXTERN int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, + double atime, double mtime, uv_fs_cb cb); -int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, - double mtime, uv_fs_cb cb); +UV_EXTERN int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, + double atime, double mtime, uv_fs_cb cb); -int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); +UV_EXTERN int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, + uv_fs_cb cb); -int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, +UV_EXTERN int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); /* @@ -1078,20 +1116,20 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, */ #define UV_FS_SYMLINK_DIR 0x0001 -int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, +UV_EXTERN int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb); -int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, +UV_EXTERN int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); -int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, - uv_fs_cb cb); +UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, + int mode, uv_fs_cb cb); -int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid, - int gid, uv_fs_cb cb); +UV_EXTERN int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, + int uid, int gid, uv_fs_cb cb); -int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, int uid, - int gid, uv_fs_cb cb); +UV_EXTERN int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, + int uid, int gid, uv_fs_cb cb); enum uv_fs_event { @@ -1112,32 +1150,32 @@ struct uv_fs_event_s { * See: http://en.wikipedia.org/wiki/Load_(computing) * (Returns [0,0,0] for windows and cygwin) */ -void uv_loadavg(double avg[3]); +UV_EXTERN void uv_loadavg(double avg[3]); /* * If filename is a directory then we will watch for all events in that * directory. If filename is a file - we will only get events from that * file. Subdirectories are not watched. */ -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, +UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, const char* filename, uv_fs_event_cb cb); /* Utility */ /* Convert string ip addresses to binary structures */ -struct sockaddr_in uv_ip4_addr(const char* ip, int port); -struct sockaddr_in6 uv_ip6_addr(const char* ip, int port); +UV_EXTERN struct sockaddr_in uv_ip4_addr(const char* ip, int port); +UV_EXTERN struct sockaddr_in6 uv_ip6_addr(const char* ip, int port); /* Convert binary addresses to strings */ -int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size); -int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size); +UV_EXTERN int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size); +UV_EXTERN int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size); /* Gets the executable path */ -int uv_exepath(char* buffer, size_t* size); +UV_EXTERN int uv_exepath(char* buffer, size_t* size); /* Gets memory info in bytes */ -uint64_t uv_get_free_memory(void); -uint64_t uv_get_total_memory(void); +UV_EXTERN uint64_t uv_get_free_memory(void); +UV_EXTERN uint64_t uv_get_total_memory(void); /* * Returns the current high-resolution real time. This is expressed in @@ -1148,7 +1186,20 @@ uint64_t uv_get_total_memory(void); * Note not every platform can support nanosecond resolution; however, this * value will always be in nanoseconds. */ -extern uint64_t uv_hrtime(void); +UV_EXTERN extern uint64_t uv_hrtime(void); + + +/* + * Opens a shared library. The filename is in utf-8. On success, -1 is + * and the variable pointed by library receives a handle to the library. + */ +UV_EXTERN uv_err_t uv_dlopen(const char* filename, uv_lib_t* library); +UV_EXTERN uv_err_t uv_dlclose(uv_lib_t library); + +/* + * Retrieves a data pointer from a dynamic library. + */ +UV_EXTERN uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr); /* the presence of these unions force similar struct layout */ diff --git a/deps/uv/src/ares/config_win32/ares_config.h b/deps/uv/src/ares/config_win32/ares_config.h index 4c9c9f6..6ded638 100644 --- a/deps/uv/src/ares/config_win32/ares_config.h +++ b/deps/uv/src/ares/config_win32/ares_config.h @@ -4,9 +4,6 @@ /* when building c-ares library */ #define CARES_BUILDING_LIBRARY 1 -/* when not building a shared library */ -#define CARES_STATICLIB 1 - /* Copyright (C) 2004 - 2008 by Daniel Stenberg et al * * Permission to use, copy, modify, and distribute this software and its diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 27e949e..88e9bfc 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -594,8 +594,8 @@ static int uv_getaddrinfo_done(eio_req* req) { free(handle->hostname); if (handle->retcode != 0) { - /* TODO how to display gai error strings? */ - uv__set_sys_error(handle->loop, handle->retcode); + handle->loop->last_err.code = UV_EADDRINFO; + handle->loop->last_err.sys_errno_ = handle->retcode; } handle->cb(handle, handle->retcode, res); diff --git a/deps/uv/src/unix/dl.c b/deps/uv/src/unix/dl.c new file mode 100644 index 0000000..8335595 --- /dev/null +++ b/deps/uv/src/unix/dl.c @@ -0,0 +1,59 @@ +/* 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 "uv.h" +#include "internal.h" + +#include +#include + + +static const uv_err_t uv_ok_ = { UV_OK, 0 }; + +uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) { + void* handle = dlopen(filename, RTLD_LAZY); + if (handle == NULL) { + return uv__new_sys_error(errno); + } + + *library = handle; + return uv_ok_; +} + + +uv_err_t uv_dlclose(uv_lib_t library) { + if (dlclose(library) != 0) { + return uv__new_sys_error(errno); + } + + return uv_ok_; +} + + +uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr) { + void* address = dlsym(library, name); + if (address == NULL) { + return uv__new_sys_error(errno); + } + + *ptr = (void*) address; + return uv_ok_; +} diff --git a/deps/uv/src/unix/error.c b/deps/uv/src/unix/error.c index c469fbb..935a83b 100644 --- a/deps/uv/src/unix/error.c +++ b/deps/uv/src/unix/error.c @@ -118,7 +118,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) { * a) rely on what the system provides us * b) reverse-map the error codes */ -char* uv_strerror(uv_err_t err) { +const char* uv_strerror(uv_err_t err) { int errorno; if (err.sys_errno_) @@ -126,6 +126,9 @@ char* uv_strerror(uv_err_t err) { else errorno = uv__translate_lib_error(err.code); + if (err.code == UV_EADDRINFO) + return gai_strerror(errorno); + if (errorno == -1) return "Unknown error"; else diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index c0bfe32..10314e4 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -23,13 +23,17 @@ #include #include +#include +#include #include #include -#include #include +#include +#include #include #include +#include uint64_t uv_hrtime() { @@ -81,15 +85,87 @@ void uv_loadavg(double avg[3]) { } +static void uv__fs_event_rearm(uv_fs_event_t *handle) { + if (port_associate(handle->fd, + PORT_SOURCE_FILE, + (uintptr_t) &handle->fo, + FILE_ATTRIB | FILE_MODIFIED, + NULL) == -1) { + uv__set_sys_error(handle->loop, errno); + } +} + + +static void uv__fs_event_read(EV_P_ ev_io* w, int revents) { + uv_fs_event_t *handle; + timespec_t timeout; + port_event_t pe; + int events; + int r; + + handle = container_of(w, uv_fs_event_t, event_watcher); + + do { + /* TODO use port_getn() */ + do { + memset(&timeout, 0, sizeof timeout); + r = port_get(handle->fd, &pe, &timeout); + } + while (r == -1 && errno == EINTR); + + if (r == -1 && errno == ETIME) + break; + + assert((r == 0) && "unexpected port_get() error"); + + events = 0; + if (pe.portev_events & (FILE_ATTRIB | FILE_MODIFIED)) + events |= UV_CHANGE; + if (pe.portev_events & ~(FILE_ATTRIB | FILE_MODIFIED)) + events |= UV_RENAME; + assert(events != 0); + + handle->cb(handle, NULL, events, 0); + } + while (handle->fd != -1); + + if (handle->fd != -1) + uv__fs_event_rearm(handle); +} + + int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, const char* filename, uv_fs_event_cb cb) { - uv__set_sys_error(loop, ENOSYS); - return -1; + int portfd; + + if ((portfd = port_create()) == -1) { + uv__set_sys_error(loop, errno); + return -1; + } + + uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); + handle->filename = strdup(filename); + handle->fd = portfd; + handle->cb = cb; + + memset(&handle->fo, 0, sizeof handle->fo); + handle->fo.fo_name = handle->filename; + uv__fs_event_rearm(handle); + + ev_io_init(&handle->event_watcher, uv__fs_event_read, portfd, EV_READ); + ev_io_start(loop->ev, &handle->event_watcher); + + return 0; } void uv__fs_event_destroy(uv_fs_event_t* handle) { - assert(0 && "implement me"); + ev_io_stop(handle->loop->ev, &handle->event_watcher); + uv__close(handle->fd); + handle->fd = -1; + free(handle->filename); + handle->filename = NULL; + handle->fo.fo_name = NULL; } diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index b42c761..30fc306 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -53,6 +53,7 @@ const char* uv_err_name(uv_err_t err) { case UV_UNKNOWN: return "UNKNOWN"; case UV_OK: return "OK"; case UV_EOF: return "EOF"; + case UV_EADDRINFO: return "EADDRINFO"; case UV_EACCESS: return "EACCESS"; case UV_EAGAIN: return "EAGAIN"; case UV_EADDRINUSE: return "EADDRINUSE"; @@ -115,6 +116,14 @@ void uv__set_artificial_error(uv_loop_t* loop, uv_err_code code) { } +uv_err_t uv__new_sys_error(int sys_error) { + uv_err_t error; + error.code = uv_translate_sys_error(sys_error); + error.sys_errno_ = sys_error; + return error; +} + + uv_err_t uv_last_error(uv_loop_t* loop) { return loop->last_err; } diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index ff81e0d..ec6d151 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -52,6 +52,7 @@ uv_err_code uv_translate_sys_error(int sys_errno); void uv__set_error(uv_loop_t* loop, uv_err_code code, int sys_error); void uv__set_sys_error(uv_loop_t* loop, int sys_error); void uv__set_artificial_error(uv_loop_t* loop, uv_err_code code); +uv_err_t uv__new_sys_error(int sys_error); int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr); int uv__tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr); diff --git a/deps/uv/src/win/dl.c b/deps/uv/src/win/dl.c new file mode 100644 index 0000000..37cdc13 --- /dev/null +++ b/deps/uv/src/win/dl.c @@ -0,0 +1,63 @@ +/* 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 "uv.h" +#include "internal.h" + + +uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) { + wchar_t filename_w[32768]; + HMODULE handle; + + if (!uv_utf8_to_utf16(filename, + filename_w, + sizeof(filename_w) / sizeof(wchar_t))) { + return uv__new_sys_error(GetLastError()); + } + + handle = LoadLibraryW(filename_w); + if (handle == NULL) { + return uv__new_sys_error(GetLastError()); + } + + *library = handle; + return uv_ok_; +} + + +uv_err_t uv_dlclose(uv_lib_t library) { + if (!FreeLibrary(library)) { + return uv__new_sys_error(GetLastError()); + } + + return uv_ok_; +} + + +uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr) { + FARPROC proc = GetProcAddress(library, name); + if (proc == NULL) { + return uv__new_sys_error(GetLastError()); + } + + *ptr = (void*) proc; + return uv_ok_; +} diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index a060b2b..1c52322 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -70,7 +70,7 @@ void uv_fatal_error(const int errorno, const char* syscall) { /* TODO: thread safety */ static char* last_err_str_ = NULL; -char* uv_strerror(uv_err_t err) { +const char* uv_strerror(uv_err_t err) { if (last_err_str_ != NULL) { LocalFree(last_err_str_); } diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index ec6e3b2..8be4fb8 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -69,6 +69,8 @@ void uv_process_timers(uv_loop_t* loop); #define UV_HANDLE_TTY_SAVED_POSITION 0x0400000 #define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x0800000 #define UV_HANDLE_SHARED_TCP_SERVER 0x1000000 +#define UV_HANDLE_TCP_NODELAY 0x2000000 +#define UV_HANDLE_TCP_KEEPALIVE 0x4000000 void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle); void uv_process_endgames(uv_loop_t* loop); diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index eb7fd33..61281f0 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -956,7 +956,9 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, return -1; } - if (send_handle && send_handle->type != UV_TCP) { + /* Only TCP server handles are supported for sharing. */ + if (send_handle && (send_handle->type != UV_TCP || + send_handle->flags & UV_HANDLE_CONNECTION)) { uv__set_artificial_error(loop, UV_ENOTSUP); return -1; } diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index 08869fa..1d18cda 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -46,6 +46,42 @@ static char uv_zero_[] = ""; static unsigned int active_tcp_streams = 0; +static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) { + if (setsockopt(socket, + IPPROTO_TCP, + TCP_NODELAY, + (const char*)&enable, + sizeof enable) == -1) { + uv__set_sys_error(handle->loop, errno); + return -1; + } + return 0; +} + + +static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) { + if (setsockopt(socket, + SOL_SOCKET, + SO_KEEPALIVE, + (const char*)&enable, + sizeof enable) == -1) { + uv__set_sys_error(handle->loop, errno); + return -1; + } + + if (enable && setsockopt(socket, + IPPROTO_TCP, + TCP_KEEPALIVE, + (const char*)&delay, + sizeof delay) == -1) { + uv__set_sys_error(handle->loop, errno); + return -1; + } + + return 0; +} + + static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, SOCKET socket, int imported) { DWORD yes = 1; @@ -89,6 +125,17 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, } } + if ((handle->flags & UV_HANDLE_TCP_NODELAY) && + uv__tcp_nodelay(handle, socket, 1)) { + return -1; + } + + /* TODO: Use stored delay. */ + if ((handle->flags & UV_HANDLE_TCP_KEEPALIVE) && + uv__tcp_keepalive(handle, socket, 1, 60)) { + return -1; + } + handle->socket = socket; return 0; @@ -402,13 +449,6 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { return -1; } - if (handle->flags & UV_HANDLE_LISTENING || - handle->flags & UV_HANDLE_READING) { - /* Already listening. */ - uv__set_sys_error(loop, WSAEALREADY); - return -1; - } - if (!(handle->flags & UV_HANDLE_BOUND) && uv_tcp_bind(handle, uv_addr_ip4_any_) < 0) return -1; @@ -429,31 +469,32 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { handle->flags |= UV_HANDLE_LISTENING; handle->connection_cb = cb; - assert(!handle->accept_reqs); - handle->accept_reqs = (uv_tcp_accept_t*) - malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t)); - if (!handle->accept_reqs) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } + if(!handle->accept_reqs) { + handle->accept_reqs = (uv_tcp_accept_t*) + malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t)); + if (!handle->accept_reqs) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + } - for (i = 0; i < uv_simultaneous_server_accepts; i++) { - req = &handle->accept_reqs[i]; - uv_req_init(loop, (uv_req_t*)req); - req->type = UV_ACCEPT; - req->accept_socket = INVALID_SOCKET; - req->data = handle; + for (i = 0; i < uv_simultaneous_server_accepts; i++) { + req = &handle->accept_reqs[i]; + uv_req_init(loop, (uv_req_t*)req); + req->type = UV_ACCEPT; + req->accept_socket = INVALID_SOCKET; + req->data = handle; - req->wait_handle = INVALID_HANDLE_VALUE; - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); + req->wait_handle = INVALID_HANDLE_VALUE; + if (handle->flags & UV_HANDLE_EMULATE_IOCP) { + req->event_handle = CreateEvent(NULL, 0, 0, NULL); + if (!req->event_handle) { + uv_fatal_error(GetLastError(), "CreateEvent"); + } + } else { + req->event_handle = NULL; } - } else { - req->event_handle = NULL; - } - uv_tcp_queue_accept(handle, req); + uv_tcp_queue_accept(handle, req); + } } return 0; @@ -961,38 +1002,61 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) { int uv_tcp_nodelay(uv_tcp_t* handle, int enable) { - uv__set_artificial_error(handle->loop, UV_ENOSYS); - return -1; + if (handle->socket != INVALID_SOCKET && + uv__tcp_nodelay(handle, handle->socket, enable)) { + return -1; + } + + if (enable) { + handle->flags |= UV_HANDLE_TCP_NODELAY; + } else { + handle->flags &= ~UV_HANDLE_TCP_NODELAY; + } + + return 0; } int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { - uv__set_artificial_error(handle->loop, UV_ENOSYS); - return -1; + if (handle->socket != INVALID_SOCKET && + uv__tcp_keepalive(handle, handle->socket, enable, delay)) { + return -1; + } + + if (enable) { + handle->flags |= UV_HANDLE_TCP_KEEPALIVE; + } else { + handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE; + } + + /* TODO: Store delay if handle->socket isn't created yet. */ + + return 0; } + int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, LPWSAPROTOCOL_INFOW protocol_info) { - if (!(handle->flags & UV_HANDLE_CONNECTION)) { - /* - * We're about to share the socket with another process. Because - * this is a server socket, we assume that the other process will - * be accepting conections on this socket. So, before sharing the - * socket with another process, we call listen here in the parent - * process. This needs to be modified if the socket is shared with - * another process for anything other than accepting connections. - */ - - if (!(handle->flags & UV_HANDLE_LISTENING)) { - if (!(handle->flags & UV_HANDLE_BOUND)) { - uv__set_artificial_error(handle->loop, UV_EINVAL); - return -1; - } - if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { - uv__set_sys_error(handle->loop, WSAGetLastError()); - return -1; - } + assert(!(handle->flags & UV_HANDLE_CONNECTION)); + + /* + * We're about to share the socket with another process. Because + * this is a listening socket, we assume that the other process will + * be accepting conections on it. So, before sharing the socket + * with another process, we call listen here in the parent process. + * This needs to be modified if the socket is shared with + * another process for anything other than accepting connections. + */ + + if (!(handle->flags & UV_HANDLE_LISTENING)) { + if (!(handle->flags & UV_HANDLE_BOUND)) { + uv__set_artificial_error(handle->loop, UV_EINVAL); + return -1; + } + if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { + uv__set_sys_error(handle->loop, WSAGetLastError()); + return -1; } handle->flags |= UV_HANDLE_SHARED_TCP_SERVER; diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index a29230e..e1b2c3c 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -29,6 +29,7 @@ TEST_DECLARE (tcp_ref) TEST_DECLARE (tcp_ref2) TEST_DECLARE (pipe_ping_pong) TEST_DECLARE (delayed_accept) +TEST_DECLARE (multiple_listen) TEST_DECLARE (tcp_writealot) TEST_DECLARE (tcp_bind_error_addrinuse) TEST_DECLARE (tcp_bind_error_addrnotavail_1) @@ -139,6 +140,7 @@ TASK_LIST_START TEST_HELPER (pipe_ping_pong, pipe_echo_server) TEST_ENTRY (delayed_accept) + TEST_ENTRY (multiple_listen) TEST_ENTRY (tcp_writealot) TEST_HELPER (tcp_writealot, tcp4_echo_server) diff --git a/deps/uv/test/test-multiple-listen.c b/deps/uv/test/test-multiple-listen.c new file mode 100644 index 0000000..0b5c887 --- /dev/null +++ b/deps/uv/test/test-multiple-listen.c @@ -0,0 +1,102 @@ +/* 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 "uv.h" +#include "task.h" +#include +#include + +static int connection_cb_called = 0; +static int close_cb_called = 0; +static int connect_cb_called = 0; +static uv_tcp_t server; +static uv_tcp_t client; + + +static void close_cb(uv_handle_t* handle) { + ASSERT(handle != NULL); + close_cb_called++; +} + + +static void connection_cb(uv_stream_t* tcp, int status) { + ASSERT(status == 0); + uv_close((uv_handle_t*)&server, close_cb); + connection_cb_called++; +} + + +static void start_server() { + struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT); + int r; + + r = uv_tcp_init(uv_default_loop(), &server); + ASSERT(r == 0); + + r = uv_tcp_bind(&server, addr); + ASSERT(r == 0); + + r = uv_listen((uv_stream_t*)&server, 128, connection_cb); + ASSERT(r == 0); + + r = uv_listen((uv_stream_t*)&server, 128, connection_cb); + ASSERT(r == 0); +} + + +static void connect_cb(uv_connect_t* req, int status) { + ASSERT(req != NULL); + ASSERT(status == 0); + free(req); + uv_close((uv_handle_t*)&client, close_cb); + connect_cb_called++; +} + + +static void client_connect() { + struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT); + uv_connect_t* connect_req = malloc(sizeof *connect_req); + int r; + + ASSERT(connect_req != NULL); + + r = uv_tcp_init(uv_default_loop(), &client); + ASSERT(r == 0); + + r = uv_tcp_connect(connect_req, &client, addr, connect_cb); + ASSERT(r == 0); +} + + + +TEST_IMPL(multiple_listen) { + start_server(); + + client_connect(); + + uv_run(uv_default_loop()); + + ASSERT(connection_cb_called == 1); + ASSERT(connect_cb_called == 1); + ASSERT(close_cb_called == 2); + + return 0; +} diff --git a/deps/uv/test/test-stdio-over-pipes.c b/deps/uv/test/test-stdio-over-pipes.c index fd96fc2..7c0a692 100644 --- a/deps/uv/test/test-stdio-over-pipes.c +++ b/deps/uv/test/test-stdio-over-pipes.c @@ -22,6 +22,9 @@ #include "uv.h" #include "task.h" +#include +#include + static char exepath[1024]; static size_t exepath_size = 1024; diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index b4ef014..b92760a 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -8,6 +8,15 @@ '_GNU_SOURCE', 'EIO_STACKSIZE=262144' ], + 'conditions': [ + ['OS=="solaris"', { + 'cflags': ['-pthreads'], + 'ldlags': ['-pthreads'], + }, { + 'cflags': ['-pthread'], + 'ldlags': ['-pthread'], + }], + ], }], ], }, @@ -29,6 +38,7 @@ 'HAVE_CONFIG_H' ], 'sources': [ + 'common.gypi', 'include/ares.h', 'include/ares_version.h', 'include/uv.h', @@ -120,6 +130,7 @@ 'src/win/async.c', 'src/win/cares.c', 'src/win/core.c', + 'src/win/dl.c', 'src/win/error.c', 'src/win/fs.c', 'src/win/fs-event.c', @@ -172,6 +183,7 @@ 'src/unix/tty.c', 'src/unix/stream.c', 'src/unix/cares.c', + 'src/unix/dl.c', 'src/unix/error.c', 'src/unix/process.c', 'src/unix/internal.h', @@ -280,6 +292,7 @@ 'test/test-ipc.c', 'test/test-list.h', 'test/test-loop-handles.c', + 'test/test-multiple-listen.c', 'test/test-pass-always.c', 'test/test-ping-pong.c', 'test/test-pipe-bind-error.c', @@ -313,11 +326,10 @@ 'libraries': [ 'ws2_32.lib' ] }, { # POSIX 'defines': [ '_GNU_SOURCE' ], - 'ldflags': [ '-pthread' ], 'sources': [ 'test/runner-unix.c', 'test/runner-unix.h', - ] + ], }], [ 'OS=="solaris"', { # make test-fs.c compile, needs _POSIX_C_SOURCE 'defines': [ @@ -365,7 +377,6 @@ 'libraries': [ 'ws2_32.lib' ] }, { # POSIX 'defines': [ '_GNU_SOURCE' ], - 'ldflags': [ '-pthread' ], 'sources': [ 'test/runner-unix.c', 'test/runner-unix.h', -- 2.7.4