aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deps/uv/build/gcc_version.py20
-rw-r--r--deps/uv/common.gypi15
-rw-r--r--deps/uv/include/uv-private/uv-unix.h14
-rw-r--r--deps/uv/include/uv-private/uv-win.h4
-rw-r--r--deps/uv/include/uv.h323
-rw-r--r--deps/uv/src/ares/config_win32/ares_config.h3
-rw-r--r--deps/uv/src/unix/core.c4
-rw-r--r--deps/uv/src/unix/dl.c59
-rw-r--r--deps/uv/src/unix/error.c5
-rw-r--r--deps/uv/src/unix/sunos.c84
-rw-r--r--deps/uv/src/uv-common.c9
-rw-r--r--deps/uv/src/uv-common.h1
-rw-r--r--deps/uv/src/win/dl.c63
-rw-r--r--deps/uv/src/win/error.c2
-rw-r--r--deps/uv/src/win/internal.h2
-rw-r--r--deps/uv/src/win/pipe.c4
-rw-r--r--deps/uv/src/win/tcp.c166
-rw-r--r--deps/uv/test/test-list.h2
-rw-r--r--deps/uv/test/test-multiple-listen.c102
-rw-r--r--deps/uv/test/test-stdio-over-pipes.c3
-rw-r--r--deps/uv/uv.gyp17
21 files changed, 697 insertions, 205 deletions
diff --git a/deps/uv/build/gcc_version.py b/deps/uv/build/gcc_version.py
new file mode 100644
index 0000000000..da019e8661
--- /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 373c3aa980..31d6b64288 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%': '<!(python build/gcc_version.py)>)',
+ },
+ '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 0db14e9c7f..b07781f406 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 <sys/port.h>
+#include <port.h>
+
+#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 ed132d3ad4..9d18fa16be 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 7bee299185..b1ea7a567a 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 <stdint.h> /* int64_t */
#include <sys/types.h> /* 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 4c9c9f6786..6ded638093 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 27e949e90b..88e9bfc83e 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 0000000000..8335595178
--- /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 <dlfcn.h>
+#include <errno.h>
+
+
+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 c469fbb884..935a83b4fc 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 c0bfe32e03..10314e4660 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -23,13 +23,17 @@
#include <stdio.h>
#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
#include <assert.h>
#include <errno.h>
-#include <sys/time.h>
#include <sys/loadavg.h>
+#include <sys/time.h>
+#include <sys/port.h>
#include <unistd.h>
#include <kstat.h>
+#include <port.h>
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 b42c761e13..30fc306299 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 ff81e0dc0a..ec6d1519ee 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 0000000000..37cdc131a1
--- /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 a060b2b962..1c52322729 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 ec6e3b2bfc..8be4fb864a 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 eb7fd33cc0..61281f0006 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 08869fa026..1d18cdab60 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 a29230e8bb..e1b2c3ce67 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 0000000000..0b5c887d69
--- /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 <stdio.h>
+#include <stdlib.h>
+
+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 fd96fc2d28..7c0a692bf9 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 <stdlib.h>
+#include <string.h>
+
static char exepath[1024];
static size_t exepath_size = 1024;
diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp
index b4ef014404..b92760a31b 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',