Browse Source

uv: upgrade to 80e5491

Ben Noordhuis 14 years ago
parent
commit
28998a8cfe
  1. 10
      deps/uv/README
  2. 20
      deps/uv/include/uv-unix.h
  3. 21
      deps/uv/include/uv-win.h
  4. 160
      deps/uv/include/uv.h
  5. 551
      deps/uv/src/uv-unix.c
  6. 1
      deps/uv/src/win/async.c
  7. 8
      deps/uv/src/win/core.c
  8. 1
      deps/uv/src/win/error.c
  9. 40
      deps/uv/src/win/handle.c
  10. 41
      deps/uv/src/win/internal.h
  11. 1
      deps/uv/src/win/loop-watcher.c
  12. 43
      deps/uv/src/win/pipe.c
  13. 1
      deps/uv/src/win/process.c
  14. 11
      deps/uv/src/win/req.c
  15. 1
      deps/uv/src/win/stream.c
  16. 39
      deps/uv/src/win/tcp.c
  17. 1
      deps/uv/src/win/timer.c
  18. 576
      deps/uv/src/win/udp.c
  19. 4040
      deps/uv/src/win/winapi.h
  20. 115
      deps/uv/src/win/winsock.c
  21. 6
      deps/uv/src/win/winsock.h
  22. 21
      deps/uv/test/benchmark-list.h
  23. 2
      deps/uv/test/benchmark-ping-pongs.c
  24. 4
      deps/uv/test/benchmark-pound.c
  25. 4
      deps/uv/test/benchmark-pump.c
  26. 2
      deps/uv/test/benchmark-spawn.c
  27. 247
      deps/uv/test/benchmark-udp-packet-storm.c
  28. 2
      deps/uv/test/dns-server.c
  29. 2
      deps/uv/test/echo-server.c
  30. 2
      deps/uv/test/test-callback-stack.c
  31. 2
      deps/uv/test/test-delayed-accept.c
  32. 8
      deps/uv/test/test-getsockname.c
  33. 9
      deps/uv/test/test-list.h
  34. 2
      deps/uv/test/test-ping-pong.c
  35. 2
      deps/uv/test/test-shutdown-eof.c
  36. 2
      deps/uv/test/test-spawn.c
  37. 2
      deps/uv/test/test-tcp-writealot.c
  38. 88
      deps/uv/test/test-udp-dgram-too-big.c
  39. 141
      deps/uv/test/test-udp-ipv6-only.c
  40. 158
      deps/uv/test/test-udp-ipv6.c
  41. 210
      deps/uv/test/test-udp-send-and-recv.c
  42. 5
      deps/uv/uv.gyp

10
deps/uv/README

@ -24,13 +24,15 @@ checkout GYP into the project tree manually:
svn co http://gyp.googlecode.com/svn/trunk build/gyp svn co http://gyp.googlecode.com/svn/trunk build/gyp
And then run Unix users run
./build/gyp_uv -f make ./gyp_uv -f make
make
or Macintosh users run
./build/gyp_uv -f xcode ./gyp_uv -f xcode
xcodebuild -project uv.xcodeproj -configuration Release -target All
= Supported Platforms = Supported Platforms

20
deps/uv/include/uv-unix.h

@ -55,6 +55,16 @@ typedef struct {
#define UV_CONNECT_PRIVATE_FIELDS \ #define UV_CONNECT_PRIVATE_FIELDS \
ngx_queue_t queue; ngx_queue_t queue;
#define UV_UDP_SEND_PRIVATE_FIELDS \
ngx_queue_t queue; \
struct sockaddr_storage addr; \
socklen_t addrlen; \
uv_buf_t* bufs; \
int bufcnt; \
ssize_t status; \
uv_udp_send_cb send_cb; \
uv_buf_t bufsml[UV_REQ_BUFSML_SIZE]; \
#define UV_PRIVATE_REQ_TYPES /* empty */ #define UV_PRIVATE_REQ_TYPES /* empty */
@ -83,6 +93,16 @@ typedef struct {
#define UV_TCP_PRIVATE_FIELDS #define UV_TCP_PRIVATE_FIELDS
/* UV_UDP */
#define UV_UDP_PRIVATE_FIELDS \
uv_alloc_cb alloc_cb; \
uv_udp_recv_cb recv_cb; \
ev_io read_watcher; \
ev_io write_watcher; \
ngx_queue_t write_queue; \
ngx_queue_t write_completed_queue; \
/* UV_NAMED_PIPE */ /* UV_NAMED_PIPE */
#define UV_PIPE_PRIVATE_TYPEDEF #define UV_PIPE_PRIVATE_TYPEDEF
#define UV_PIPE_PRIVATE_FIELDS \ #define UV_PIPE_PRIVATE_FIELDS \

21
deps/uv/include/uv-win.h

@ -48,7 +48,8 @@ typedef struct uv_buf_t {
UV_ARES_CLEANUP_REQ, \ UV_ARES_CLEANUP_REQ, \
UV_GETADDRINFO_REQ, \ UV_GETADDRINFO_REQ, \
UV_PROCESS_EXIT, \ UV_PROCESS_EXIT, \
UV_PROCESS_CLOSE UV_PROCESS_CLOSE, \
UV_UDP_RECV
#define UV_REQ_PRIVATE_FIELDS \ #define UV_REQ_PRIVATE_FIELDS \
union { \ union { \
@ -58,7 +59,6 @@ typedef struct uv_buf_t {
size_t queued_bytes; \ size_t queued_bytes; \
}; \ }; \
}; \ }; \
uv_err_t error; \
struct uv_req_s* next_req; struct uv_req_s* next_req;
#define UV_WRITE_PRIVATE_FIELDS \ #define UV_WRITE_PRIVATE_FIELDS \
@ -70,6 +70,9 @@ typedef struct uv_buf_t {
#define UV_SHUTDOWN_PRIVATE_FIELDS \ #define UV_SHUTDOWN_PRIVATE_FIELDS \
/* empty */ /* empty */
#define UV_UDP_SEND_PRIVATE_FIELDS \
/* empty */
#define UV_PRIVATE_REQ_TYPES \ #define UV_PRIVATE_REQ_TYPES \
typedef struct uv_pipe_accept_s { \ typedef struct uv_pipe_accept_s { \
UV_REQ_FIELDS \ UV_REQ_FIELDS \
@ -109,11 +112,22 @@ typedef struct uv_buf_t {
#define UV_TCP_PRIVATE_FIELDS \ #define UV_TCP_PRIVATE_FIELDS \
SOCKET socket; \ SOCKET socket; \
uv_err_t bind_error; \
union { \ union { \
struct { uv_tcp_server_fields }; \ struct { uv_tcp_server_fields }; \
struct { uv_tcp_connection_fields }; \ struct { uv_tcp_connection_fields }; \
}; };
#define UV_UDP_PRIVATE_FIELDS \
SOCKET socket; \
unsigned int reqs_pending; \
uv_req_t recv_req; \
uv_buf_t recv_buffer; \
struct sockaddr_storage recv_from; \
int recv_from_len; \
uv_udp_recv_cb recv_cb; \
uv_alloc_cb alloc_cb;
#define uv_pipe_server_fields \ #define uv_pipe_server_fields \
uv_pipe_accept_t accept_reqs[4]; \ uv_pipe_accept_t accept_reqs[4]; \
uv_pipe_accept_t* pending_accepts; uv_pipe_accept_t* pending_accepts;
@ -157,8 +171,7 @@ typedef struct uv_buf_t {
#define UV_HANDLE_PRIVATE_FIELDS \ #define UV_HANDLE_PRIVATE_FIELDS \
uv_handle_t* endgame_next; \ uv_handle_t* endgame_next; \
unsigned int flags; \ unsigned int flags;
uv_err_t error;
#define UV_ARES_TASK_PRIVATE_FIELDS \ #define UV_ARES_TASK_PRIVATE_FIELDS \
struct uv_req_s ares_req; \ struct uv_req_s ares_req; \

160
deps/uv/include/uv.h

@ -45,6 +45,7 @@ typedef struct uv_err_s uv_err_t;
typedef struct uv_handle_s uv_handle_t; typedef struct uv_handle_s uv_handle_t;
typedef struct uv_stream_s uv_stream_t; typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t; typedef struct uv_tcp_s uv_tcp_t;
typedef struct uv_udp_s uv_udp_t;
typedef struct uv_pipe_s uv_pipe_t; typedef struct uv_pipe_s uv_pipe_t;
typedef struct uv_timer_s uv_timer_t; typedef struct uv_timer_s uv_timer_t;
typedef struct uv_prepare_s uv_prepare_t; typedef struct uv_prepare_s uv_prepare_t;
@ -58,6 +59,7 @@ typedef struct uv_req_s uv_req_t;
typedef struct uv_shutdown_s uv_shutdown_t; typedef struct uv_shutdown_s uv_shutdown_t;
typedef struct uv_write_s uv_write_t; typedef struct uv_write_s uv_write_t;
typedef struct uv_connect_s uv_connect_t; typedef struct uv_connect_s uv_connect_t;
typedef struct uv_udp_send_s uv_udp_send_t;
#if defined(__unix__) || defined(__POSIX__) || defined(__APPLE__) #if defined(__unix__) || defined(__POSIX__) || defined(__APPLE__)
# include "uv-unix.h" # include "uv-unix.h"
@ -106,8 +108,8 @@ int64_t uv_now();
* In the case of uv_read_cb the uv_buf_t returned should be freed by the * In the case of uv_read_cb the uv_buf_t returned should be freed by the
* user. * user.
*/ */
typedef uv_buf_t (*uv_alloc_cb)(uv_stream_t* tcp, size_t suggested_size); typedef uv_buf_t (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size);
typedef void (*uv_read_cb)(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf); typedef void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, uv_buf_t buf);
typedef void (*uv_write_cb)(uv_write_t* req, int status); typedef void (*uv_write_cb)(uv_write_t* req, int status);
typedef void (*uv_connect_cb)(uv_connect_t* req, int status); typedef void (*uv_connect_cb)(uv_connect_t* req, int status);
typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status); typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status);
@ -146,6 +148,7 @@ typedef enum {
UV_EINVAL, UV_EINVAL,
UV_EISCONN, UV_EISCONN,
UV_EMFILE, UV_EMFILE,
UV_EMSGSIZE,
UV_ENETDOWN, UV_ENETDOWN,
UV_ENETUNREACH, UV_ENETUNREACH,
UV_ENFILE, UV_ENFILE,
@ -172,6 +175,7 @@ typedef enum {
typedef enum { typedef enum {
UV_UNKNOWN_HANDLE = 0, UV_UNKNOWN_HANDLE = 0,
UV_TCP, UV_TCP,
UV_UDP,
UV_NAMED_PIPE, UV_NAMED_PIPE,
UV_TTY, UV_TTY,
UV_FILE, UV_FILE,
@ -194,6 +198,7 @@ typedef enum {
UV_WRITE, UV_WRITE,
UV_SHUTDOWN, UV_SHUTDOWN,
UV_WAKEUP, UV_WAKEUP,
UV_UDP_SEND,
UV_REQ_TYPE_PRIVATE UV_REQ_TYPE_PRIVATE
} uv_req_type; } uv_req_type;
@ -415,7 +420,155 @@ struct uv_connect_s {
}; };
int uv_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen); int uv_getsockname(uv_handle_t* handle, struct sockaddr* name, int* namelen);
/*
* UDP support.
*/
enum uv_udp_flags {
/* Disables dual stack mode. Used with uv_udp_bind6(). */
UV_UDP_IPV6ONLY = 1,
/*
* Indicates message was truncated because read buffer was too small. The
* remainder was discarded by the OS. Used in uv_udp_recv_cb.
*/
UV_UDP_PARTIAL = 2
};
/*
* Called after a uv_udp_send() or uv_udp_send6(). status 0 indicates
* success otherwise error.
*/
typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
/*
* Callback that is invoked when a new UDP datagram is received.
*
* handle UDP handle.
* nread Number of bytes that have been received.
* 0 if there is no more data to read. You may
* discard or repurpose the read buffer.
* -1 if a transmission error was detected.
* buf uv_buf_t with the received data.
* addr struct sockaddr_in or struct sockaddr_in6.
* Valid for the duration of the callback only.
* flags One or more OR'ed UV_UDP_* constants.
* Right now only UV_UDP_PARTIAL is used.
*/
typedef void (*uv_udp_recv_cb)(uv_udp_t* handle, ssize_t nread, uv_buf_t buf,
struct sockaddr* addr, unsigned flags);
/* uv_udp_t is a subclass of uv_handle_t */
struct uv_udp_s {
UV_HANDLE_FIELDS
UV_UDP_PRIVATE_FIELDS
};
/* uv_udp_send_t is a subclass of uv_req_t */
struct uv_udp_send_s {
UV_REQ_FIELDS
uv_udp_t* handle;
uv_udp_send_cb cb;
UV_UDP_SEND_PRIVATE_FIELDS
};
/*
* Initialize a new UDP handle. The actual socket is created lazily.
* Returns 0 on success.
*/
int uv_udp_init(uv_udp_t* handle);
/*
* Bind to a IPv4 address and port.
*
* Arguments:
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* addr struct sockaddr_in with the address and port to bind to.
* flags Unused.
*
* Returns:
* 0 on success, -1 on error.
*/
int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags);
/*
* Bind to a IPv6 address and port.
*
* Arguments:
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* addr struct sockaddr_in with the address and port to bind to.
* flags Should be 0 or UV_UDP_IPV6ONLY.
*
* Returns:
* 0 on success, -1 on error.
*/
int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags);
/*
* Send data. If the socket has not previously been bound with `uv_udp_bind`
* or `uv_udp_bind6`, it is bound to 0.0.0.0 (the "all interfaces" address)
* and a random port number.
*
* Arguments:
* req UDP request handle. Need not be initialized.
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* bufs List of buffers to send.
* bufcnt Number of buffers in `bufs`.
* addr Address of the remote peer. See `uv_ip4_addr`.
* send_cb Callback to invoke when the data has been sent out.
*
* 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);
/*
* Send data. If the socket has not previously been bound with `uv_udp_bind6`,
* it is bound to ::0 (the "all interfaces" address) and a random port number.
*
* Arguments:
* req UDP request handle. Need not be initialized.
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* bufs List of buffers to send.
* bufcnt Number of buffers in `bufs`.
* addr Address of the remote peer. See `uv_ip6_addr`.
* send_cb Callback to invoke when the data has been sent out.
*
* 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);
/*
* Send data. If the socket has not previously been bound with `uv_udp_bind`
* or `uv_udp_bind6`, it is bound to 0.0.0.0 (the "all interfaces" address)
* and a random port number.
*
* Arguments:
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* alloc_cb Callback to invoke when temporary storage is needed.
* recv_cb Callback to invoke with received data.
*
* Returns:
* 0 on success, -1 on error.
*/
int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
uv_udp_recv_cb recv_cb);
/*
* Stop listening for incoming datagrams.
*
* Arguments:
* handle UDP handle. Should have been initialized with `uv_udp_init`.
*
* Returns:
* 0 on success, -1 on error.
*/
int uv_udp_recv_stop(uv_udp_t* handle);
/* /*
@ -699,6 +852,7 @@ typedef struct {
uint64_t handle_init; uint64_t handle_init;
uint64_t stream_init; uint64_t stream_init;
uint64_t tcp_init; uint64_t tcp_init;
uint64_t udp_init;
uint64_t pipe_init; uint64_t pipe_init;
uint64_t prepare_init; uint64_t prepare_init;
uint64_t check_init; uint64_t check_init;

551
deps/uv/src/uv-unix.c

@ -103,6 +103,28 @@ static void uv__stream_connect(uv_stream_t*);
static void uv__stream_io(EV_P_ ev_io* watcher, int revents); static void uv__stream_io(EV_P_ ev_io* watcher, int revents);
static void uv__pipe_accept(EV_P_ ev_io* watcher, int revents); static void uv__pipe_accept(EV_P_ ev_io* watcher, int revents);
static void uv__udp_watcher_start(uv_udp_t* handle, ev_io* w);
static void uv__udp_watcher_stop(uv_udp_t* handle, ev_io* w);
static void uv__udp_run_completed(uv_udp_t* handle);
static void uv__udp_run_pending(uv_udp_t* handle);
static void uv__udp_destroy(uv_udp_t* handle);
static void uv__udp_recvmsg(uv_udp_t* handle);
static void uv__udp_sendmsg(uv_udp_t* handle);
static void uv__udp_io(EV_P_ ev_io* w, int events);
static int uv__udp_bind(uv_udp_t* handle,
int domain,
struct sockaddr* addr,
socklen_t len,
unsigned flags);
static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain);
static int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
int bufcnt,
struct sockaddr* addr,
socklen_t addrlen,
uv_udp_send_cb send_cb);
#ifndef __GNUC__ #ifndef __GNUC__
#define __attribute__(a) #define __attribute__(a)
#endif #endif
@ -173,6 +195,7 @@ static uv_err_code uv_translate_sys_error(int sys_errno) {
case ECONNRESET: return UV_ECONNRESET; case ECONNRESET: return UV_ECONNRESET;
case EFAULT: return UV_EFAULT; case EFAULT: return UV_EFAULT;
case EMFILE: return UV_EMFILE; case EMFILE: return UV_EMFILE;
case EMSGSIZE: return UV_EMSGSIZE;
case EINVAL: return UV_EINVAL; case EINVAL: return UV_EINVAL;
case ECONNREFUSED: return UV_ECONNREFUSED; case ECONNREFUSED: return UV_ECONNREFUSED;
case EADDRINUSE: return UV_EADDRINUSE; case EADDRINUSE: return UV_EADDRINUSE;
@ -201,6 +224,7 @@ static uv_err_t uv_err_new(uv_handle_t* handle, int sys_error) {
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
uv_udp_t* udp;
uv_async_t* async; uv_async_t* async;
uv_timer_t* timer; uv_timer_t* timer;
uv_stream_t* stream; uv_stream_t* stream;
@ -226,6 +250,17 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
uv__close(stream->accepted_fd); uv__close(stream->accepted_fd);
stream->accepted_fd = -1; stream->accepted_fd = -1;
} }
assert(!ev_is_active(&stream->read_watcher));
assert(!ev_is_active(&stream->write_watcher));
break;
case UV_UDP:
udp = (uv_udp_t*)handle;
uv__udp_watcher_stop(udp, &udp->read_watcher);
uv__udp_watcher_stop(udp, &udp->write_watcher);
uv__close(udp->fd);
udp->fd = -1;
break; break;
case UV_PREPARE: case UV_PREPARE:
@ -302,6 +337,489 @@ static void uv__handle_init(uv_handle_t* handle, uv_handle_type type) {
} }
static void uv__udp_watcher_start(uv_udp_t* handle, ev_io* w) {
int flags;
assert(w == &handle->read_watcher
|| w == &handle->write_watcher);
flags = (w == &handle->read_watcher ? EV_READ : EV_WRITE);
w->data = handle;
ev_set_cb(w, uv__udp_io);
ev_io_set(w, handle->fd, flags);
ev_io_start(EV_DEFAULT_UC_ w);
}
static void uv__udp_watcher_stop(uv_udp_t* handle, ev_io* w) {
int flags;
assert(w == &handle->read_watcher
|| w == &handle->write_watcher);
flags = (w == &handle->read_watcher ? EV_READ : EV_WRITE);
ev_io_stop(EV_DEFAULT_UC_ w);
ev_io_set(w, -1, flags);
ev_set_cb(w, NULL);
w->data = (void*)0xDEADBABE;
}
static void uv__udp_destroy(uv_udp_t* handle) {
uv_udp_send_t* req;
ngx_queue_t* q;
uv__udp_run_completed(handle);
while (!ngx_queue_empty(&handle->write_queue)) {
q = ngx_queue_head(&handle->write_queue);
ngx_queue_remove(q);
req = ngx_queue_data(q, uv_udp_send_t, queue);
if (req->send_cb) {
/* FIXME proper error code like UV_EABORTED */
uv_err_new_artificial((uv_handle_t*)handle, UV_EINTR);
req->send_cb(req, -1);
}
}
/* Now tear down the handle. */
handle->flags = 0;
handle->recv_cb = NULL;
handle->alloc_cb = NULL;
/* but _do not_ touch close_cb */
if (handle->fd != -1) {
uv__close(handle->fd);
handle->fd = -1;
}
uv__udp_watcher_stop(handle, &handle->read_watcher);
uv__udp_watcher_stop(handle, &handle->write_watcher);
}
static void uv__udp_run_pending(uv_udp_t* handle) {
uv_udp_send_t* req;
ngx_queue_t* q;
struct msghdr h;
ssize_t size;
while (!ngx_queue_empty(&handle->write_queue)) {
q = ngx_queue_head(&handle->write_queue);
assert(q != NULL);
req = ngx_queue_data(q, uv_udp_send_t, queue);
assert(req != NULL);
memset(&h, 0, sizeof h);
h.msg_name = &req->addr;
h.msg_namelen = req->addrlen;
h.msg_iov = (struct iovec*)req->bufs;
h.msg_iovlen = req->bufcnt;
do {
size = sendmsg(handle->fd, &h, 0);
}
while (size == -1 && errno == EINTR);
/* TODO try to write once or twice more in the
* hope that the socket becomes readable again?
*/
if (size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
break;
req->status = (size == -1 ? -errno : size);
#ifndef NDEBUG
/* Sanity check. */
if (size != -1) {
ssize_t nbytes;
int i;
for (nbytes = i = 0; i < req->bufcnt; i++)
nbytes += req->bufs[i].len;
assert(size == nbytes);
}
#endif
/* Sending a datagram is an atomic operation: either all data
* is written or nothing is (and EMSGSIZE is raised). That is
* why we don't handle partial writes. Just pop the request
* off the write queue and onto the completed queue, done.
*/
ngx_queue_remove(&req->queue);
ngx_queue_insert_tail(&handle->write_completed_queue, &req->queue);
}
}
static void uv__udp_run_completed(uv_udp_t* handle) {
uv_udp_send_t* req;
ngx_queue_t* q;
while (!ngx_queue_empty(&handle->write_completed_queue)) {
q = ngx_queue_head(&handle->write_completed_queue);
assert(q != NULL);
ngx_queue_remove(q);
req = ngx_queue_data(q, uv_udp_send_t, queue);
assert(req != NULL);
if (req->bufs != req->bufsml)
free(req->bufs);
if (req->send_cb == NULL)
continue;
/* req->status >= 0 == bytes written
* req->status < 0 == errno
*/
if (req->status >= 0) {
req->send_cb(req, 0);
}
else {
uv_err_new((uv_handle_t*)handle, -req->status);
req->send_cb(req, -1);
}
}
}
static void uv__udp_recvmsg(uv_udp_t* handle) {
struct sockaddr_storage peer;
struct msghdr h;
ssize_t nread;
uv_buf_t buf;
int flags;
assert(handle->recv_cb != NULL);
assert(handle->alloc_cb != NULL);
do {
/* FIXME: hoist alloc_cb out the loop but for now follow uv__read() */
buf = handle->alloc_cb((uv_handle_t*)handle, 64 * 1024);
assert(buf.len > 0);
assert(buf.base != NULL);
memset(&h, 0, sizeof h);
h.msg_name = &peer;
h.msg_namelen = sizeof peer;
h.msg_iov = (struct iovec*)&buf;
h.msg_iovlen = 1;
do {
nread = recvmsg(handle->fd, &h, 0);
}
while (nread == -1 && errno == EINTR);
if (nread == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
uv_err_new((uv_handle_t*)handle, EAGAIN);
handle->recv_cb(handle, 0, buf, NULL, 0);
}
else {
uv_err_new((uv_handle_t*)handle, errno);
handle->recv_cb(handle, -1, buf, NULL, 0);
}
}
else {
flags = 0;
if (h.msg_flags & MSG_TRUNC)
flags |= UV_UDP_PARTIAL;
handle->recv_cb(handle,
nread,
buf,
(struct sockaddr*)&peer,
flags);
}
}
/* recv_cb callback may decide to pause or close the handle */
while (nread != -1
&& handle->fd != -1
&& handle->recv_cb != NULL);
}
static void uv__udp_sendmsg(uv_udp_t* handle) {
assert(!ngx_queue_empty(&handle->write_queue)
|| !ngx_queue_empty(&handle->write_completed_queue));
/* Write out pending data first. */
uv__udp_run_pending(handle);
/* Drain 'request completed' queue. */
uv__udp_run_completed(handle);
if (!ngx_queue_empty(&handle->write_completed_queue)) {
/* Schedule completion callbacks. */
ev_feed_event(EV_DEFAULT_ &handle->write_watcher, EV_WRITE);
}
else if (ngx_queue_empty(&handle->write_queue)) {
/* Pending queue and completion queue empty, stop watcher. */
uv__udp_watcher_stop(handle, &handle->write_watcher);
}
}
static void uv__udp_io(EV_P_ ev_io* w, int events) {
uv_udp_t* handle;
handle = w->data;
assert(handle != NULL);
assert(handle->type == UV_UDP);
assert(handle->fd >= 0);
assert(!(events & ~(EV_READ|EV_WRITE)));
if (events & EV_READ)
uv__udp_recvmsg(handle);
if (events & EV_WRITE)
uv__udp_sendmsg(handle);
}
static int uv__udp_bind(uv_udp_t* handle,
int domain,
struct sockaddr* addr,
socklen_t len,
unsigned flags) {
int saved_errno;
int status;
int yes;
int fd;
saved_errno = errno;
status = -1;
/* Check for bad flags. */
if (flags & ~UV_UDP_IPV6ONLY) {
uv_err_new((uv_handle_t*)handle, EINVAL);
goto out;
}
/* Cannot set IPv6-only mode on non-IPv6 socket. */
if ((flags & UV_UDP_IPV6ONLY) && domain != AF_INET6) {
uv_err_new((uv_handle_t*)handle, EINVAL);
goto out;
}
/* Check for already active socket. */
if (handle->fd != -1) {
uv_err_new_artificial((uv_handle_t*)handle, UV_EALREADY);
goto out;
}
if ((fd = uv__socket(domain, SOCK_DGRAM, 0)) == -1) {
uv_err_new((uv_handle_t*)handle, errno);
goto out;
}
if (flags & UV_UDP_IPV6ONLY) {
#ifdef IPV6_V6ONLY
yes = 1;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) {
uv_err_new((uv_handle_t*)handle, errno);
goto out;
}
#else
uv_err_new((uv_handle_t*)handle, ENOTSUP);
goto out;
#endif
}
if (bind(fd, addr, len) == -1) {
uv_err_new((uv_handle_t*)handle, errno);
goto out;
}
handle->fd = fd;
status = 0;
out:
if (status)
uv__close(fd);
errno = saved_errno;
return status;
}
static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain) {
struct sockaddr_storage taddr;
socklen_t addrlen;
assert(domain == AF_INET || domain == AF_INET6);
if (handle->fd != -1)
return 0;
switch (domain) {
case AF_INET:
{
struct sockaddr_in* addr = (void*)&taddr;
memset(addr, 0, sizeof *addr);
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = INADDR_ANY;
addrlen = sizeof *addr;
break;
}
case AF_INET6:
{
struct sockaddr_in6* addr = (void*)&taddr;
memset(addr, 0, sizeof *addr);
addr->sin6_family = AF_INET6;
addr->sin6_addr = in6addr_any;
addrlen = sizeof *addr;
break;
}
default:
assert(0 && "unsupported address family");
abort();
}
return uv__udp_bind(handle, domain, (struct sockaddr*)&taddr, addrlen, 0);
}
static int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
int bufcnt,
struct sockaddr* addr,
socklen_t addrlen,
uv_udp_send_cb send_cb) {
if (uv__udp_maybe_deferred_bind(handle, addr->sa_family))
return -1;
/* Don't use uv__req_init(), it zeroes the data field. */
uv_counters()->req_init++;
memcpy(&req->addr, addr, addrlen);
req->addrlen = addrlen;
req->send_cb = send_cb;
req->handle = handle;
req->bufcnt = bufcnt;
req->type = UV_UDP_SEND;
if (bufcnt <= UV_REQ_BUFSML_SIZE) {
req->bufs = req->bufsml;
}
else if ((req->bufs = malloc(bufcnt * sizeof(bufs[0]))) == NULL) {
uv_err_new((uv_handle_t*)handle, ENOMEM);
return -1;
}
memcpy(req->bufs, bufs, bufcnt * sizeof(bufs[0]));
ngx_queue_insert_tail(&handle->write_queue, &req->queue);
uv__udp_watcher_start(handle, &handle->write_watcher);
return 0;
}
int uv_udp_init(uv_udp_t* handle) {
memset(handle, 0, sizeof *handle);
uv__handle_init((uv_handle_t*)handle, UV_UDP);
uv_counters()->udp_init++;
handle->fd = -1;
ngx_queue_init(&handle->write_queue);
ngx_queue_init(&handle->write_completed_queue);
return 0;
}
int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags) {
return uv__udp_bind(handle,
AF_INET,
(struct sockaddr*)&addr,
sizeof addr,
flags);
}
int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags) {
return uv__udp_bind(handle,
AF_INET6,
(struct sockaddr*)&addr,
sizeof addr,
flags);
}
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) {
return uv__udp_send(req,
handle,
bufs,
bufcnt,
(struct sockaddr*)&addr,
sizeof addr,
send_cb);
}
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) {
return uv__udp_send(req,
handle,
bufs,
bufcnt,
(struct sockaddr*)&addr,
sizeof addr,
send_cb);
}
int uv_udp_recv_start(uv_udp_t* handle,
uv_alloc_cb alloc_cb,
uv_udp_recv_cb recv_cb) {
if (alloc_cb == NULL || recv_cb == NULL) {
uv_err_new_artificial((uv_handle_t*)handle, UV_EINVAL);
return -1;
}
if (ev_is_active(&handle->read_watcher)) {
uv_err_new_artificial((uv_handle_t*)handle, UV_EALREADY);
return -1;
}
if (uv__udp_maybe_deferred_bind(handle, AF_INET))
return -1;
handle->alloc_cb = alloc_cb;
handle->recv_cb = recv_cb;
uv__udp_watcher_start(handle, &handle->read_watcher);
return 0;
}
int uv_udp_recv_stop(uv_udp_t* handle) {
uv__udp_watcher_stop(handle, &handle->read_watcher);
handle->alloc_cb = NULL;
handle->recv_cb = NULL;
return 0;
}
int uv_tcp_init(uv_tcp_t* tcp) { int uv_tcp_init(uv_tcp_t* tcp) {
uv__handle_init((uv_handle_t*)tcp, UV_TCP); uv__handle_init((uv_handle_t*)tcp, UV_TCP);
uv_counters()->tcp_init++; uv_counters()->tcp_init++;
@ -329,7 +847,9 @@ int uv_tcp_init(uv_tcp_t* tcp) {
} }
static int uv__bind(uv_tcp_t* tcp, int domain, struct sockaddr* addr, static int uv__tcp_bind(uv_tcp_t* tcp,
int domain,
struct sockaddr* addr,
int addrsize) { int addrsize) {
int saved_errno; int saved_errno;
int status; int status;
@ -376,7 +896,9 @@ int uv_tcp_bind(uv_tcp_t* tcp, struct sockaddr_in addr) {
return -1; return -1;
} }
return uv__bind(tcp, AF_INET, (struct sockaddr*)&addr, return uv__tcp_bind(tcp,
AF_INET,
(struct sockaddr*)&addr,
sizeof(struct sockaddr_in)); sizeof(struct sockaddr_in));
} }
@ -387,7 +909,9 @@ int uv_tcp_bind6(uv_tcp_t* tcp, struct sockaddr_in6 addr) {
return -1; return -1;
} }
return uv__bind(tcp, AF_INET6, (struct sockaddr*)&addr, return uv__tcp_bind(tcp,
AF_INET6,
(struct sockaddr*)&addr,
sizeof(struct sockaddr_in6)); sizeof(struct sockaddr_in6));
} }
@ -587,6 +1111,13 @@ void uv__finish_close(uv_handle_t* handle) {
assert(!ev_is_active(&((uv_stream_t*)handle)->write_watcher)); assert(!ev_is_active(&((uv_stream_t*)handle)->write_watcher));
break; break;
case UV_UDP:
assert(!ev_is_active(&((uv_udp_t*)handle)->read_watcher));
assert(!ev_is_active(&((uv_udp_t*)handle)->write_watcher));
assert(((uv_udp_t*)handle)->fd == -1);
uv__udp_destroy((uv_udp_t*)handle);
break;
case UV_PROCESS: case UV_PROCESS:
assert(!ev_is_active(&((uv_process_t*)handle)->child_watcher)); assert(!ev_is_active(&((uv_process_t*)handle)->child_watcher));
break; break;
@ -820,21 +1351,22 @@ static void uv__read(uv_stream_t* stream) {
*/ */
while (stream->read_cb && ((uv_handle_t*)stream)->flags & UV_READING) { while (stream->read_cb && ((uv_handle_t*)stream)->flags & UV_READING) {
assert(stream->alloc_cb); assert(stream->alloc_cb);
buf = stream->alloc_cb(stream, 64 * 1024); buf = stream->alloc_cb((uv_handle_t*)stream, 64 * 1024);
assert(buf.len > 0); assert(buf.len > 0);
assert(buf.base); assert(buf.base);
assert(stream->fd >= 0);
do { do {
nread = read(stream->fd, buf.base, buf.len); nread = read(stream->fd, buf.base, buf.len);
} }
while (nread == -1 && errno == EINTR); while (nread < 0 && errno == EINTR);
if (nread < 0) { if (nread < 0) {
/* Error */ /* Error */
if (errno == EAGAIN) { if (errno == EAGAIN) {
/* Wait for the next one. */ /* Wait for the next one. */
if (((uv_handle_t*)stream)->flags & UV_READING) { if (stream->flags & UV_READING) {
ev_io_start(EV_DEFAULT_UC_ &stream->read_watcher); ev_io_start(EV_DEFAULT_UC_ &stream->read_watcher);
} }
uv_err_new((uv_handle_t*)stream, EAGAIN); uv_err_new((uv_handle_t*)stream, EAGAIN);
@ -1112,7 +1644,7 @@ out:
} }
int uv_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen) { int uv_getsockname(uv_handle_t* handle, struct sockaddr* name, int* namelen) {
socklen_t socklen; socklen_t socklen;
int saved_errno; int saved_errno;
@ -1251,6 +1783,11 @@ int64_t uv_now() {
int uv_read_start(uv_stream_t* stream, uv_alloc_cb alloc_cb, uv_read_cb read_cb) { int uv_read_start(uv_stream_t* stream, uv_alloc_cb alloc_cb, uv_read_cb read_cb) {
assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE); assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE);
if (stream->flags & UV_CLOSING) {
uv_err_new((uv_handle_t*)stream, EINVAL);
return -1;
}
/* The UV_READING flag is irrelevant of the state of the tcp - it just /* The UV_READING flag is irrelevant of the state of the tcp - it just
* expresses the desired state of the user. * expresses the desired state of the user.
*/ */

1
deps/uv/src/win/async.c

@ -78,7 +78,6 @@ int uv_async_init(uv_async_t* handle, uv_async_cb async_cb) {
handle->type = UV_ASYNC; handle->type = UV_ASYNC;
handle->flags = 0; handle->flags = 0;
handle->async_sent = 0; handle->async_sent = 0;
handle->error = uv_ok_;
handle->async_cb = async_cb; handle->async_cb = async_cb;
req = &handle->async_req; req = &handle->async_req;

8
deps/uv/src/win/core.c

@ -111,10 +111,6 @@ static void uv_poll(int block) {
/* Package was dequeued */ /* Package was dequeued */
req = uv_overlapped_to_req(overlapped); req = uv_overlapped_to_req(overlapped);
if (!success) {
req->error = uv_new_sys_error(GetLastError());
}
uv_insert_pending_req(req); uv_insert_pending_req(req);
} else if (GetLastError() != WAIT_TIMEOUT) { } else if (GetLastError() != WAIT_TIMEOUT) {
@ -150,10 +146,6 @@ static void uv_poll_ex(int block) {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
/* Package was dequeued */ /* Package was dequeued */
req = uv_overlapped_to_req(overlappeds[i].lpOverlapped); req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);
if (overlappeds[i].lpOverlapped->Internal != STATUS_SUCCESS) {
req->error = uv_new_sys_error(pRtlNtStatusToDosError(
overlappeds[i].lpOverlapped->Internal));
}
uv_insert_pending_req(req); uv_insert_pending_req(req);
} }
} else if (GetLastError() != WAIT_TIMEOUT) { } else if (GetLastError() != WAIT_TIMEOUT) {

1
deps/uv/src/win/error.c

@ -109,6 +109,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
case WSAEINVAL: return UV_EINVAL; case WSAEINVAL: return UV_EINVAL;
case ERROR_TOO_MANY_OPEN_FILES: return UV_EMFILE; case ERROR_TOO_MANY_OPEN_FILES: return UV_EMFILE;
case WSAEMFILE: return UV_EMFILE; case WSAEMFILE: return UV_EMFILE;
case WSAEMSGSIZE: return UV_EMSGSIZE;
case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH; case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH;
case WSAENETUNREACH: return UV_ENETUNREACH; case WSAENETUNREACH: return UV_ENETUNREACH;
case ERROR_OUTOFMEMORY: return UV_ENOMEM; case ERROR_OUTOFMEMORY: return UV_ENOMEM;

40
deps/uv/src/win/handle.c

@ -39,18 +39,33 @@ int uv_is_active(uv_handle_t* handle) {
} }
/* TODO: integrate this with uv_close. */ int uv_getsockname(uv_handle_t* handle, struct sockaddr* name, int* namelen) {
static void uv_close_error(uv_handle_t* handle, uv_err_t e) { switch (handle->type) {
case UV_TCP:
return uv_tcp_getsockname((uv_tcp_t*) handle, name, namelen);
case UV_UDP:
return uv_tcp_getsockname((uv_tcp_t*) handle, name, namelen);
default:
uv_set_sys_error(WSAENOTSOCK);
return -1;
}
}
void uv_close(uv_handle_t* handle, uv_close_cb cb) {
uv_tcp_t* tcp; uv_tcp_t* tcp;
uv_pipe_t* pipe; uv_pipe_t* pipe;
uv_udp_t* udp;
uv_process_t* process; uv_process_t* process;
if (handle->flags & UV_HANDLE_CLOSING) { if (handle->flags & UV_HANDLE_CLOSING) {
return; return;
} }
handle->error = e;
handle->flags |= UV_HANDLE_CLOSING; handle->flags |= UV_HANDLE_CLOSING;
handle->close_cb = cb;
/* Handle-specific close actions */ /* Handle-specific close actions */
switch (handle->type) { switch (handle->type) {
@ -78,6 +93,15 @@ static void uv_close_error(uv_handle_t* handle, uv_err_t e) {
} }
return; return;
case UV_UDP:
udp = (uv_udp_t*) handle;
uv_udp_recv_stop(udp);
closesocket(udp->socket);
if (udp->reqs_pending == 0) {
uv_want_endgame(handle);
}
return;
case UV_TIMER: case UV_TIMER:
uv_timer_stop((uv_timer_t*)handle); uv_timer_stop((uv_timer_t*)handle);
uv_want_endgame(handle); uv_want_endgame(handle);
@ -116,12 +140,6 @@ static void uv_close_error(uv_handle_t* handle, uv_err_t e) {
} }
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
handle->close_cb = close_cb;
uv_close_error(handle, uv_ok_);
}
void uv_want_endgame(uv_handle_t* handle) { void uv_want_endgame(uv_handle_t* handle) {
if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) { if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) {
handle->flags |= UV_HANDLE_ENDGAME_QUEUED; handle->flags |= UV_HANDLE_ENDGAME_QUEUED;
@ -150,6 +168,10 @@ void uv_process_endgames() {
uv_pipe_endgame((uv_pipe_t*)handle); uv_pipe_endgame((uv_pipe_t*)handle);
break; break;
case UV_UDP:
uv_udp_endgame((uv_udp_t*) handle);
break;
case UV_TIMER: case UV_TIMER:
uv_timer_endgame((uv_timer_t*)handle); uv_timer_endgame((uv_timer_t*)handle);
break; break;

41
deps/uv/src/win/internal.h

@ -142,7 +142,6 @@ void uv_insert_pending_req(uv_req_t* req);
void uv_process_reqs(); void uv_process_reqs();
#define POST_COMPLETION_FOR_REQ(req) \ #define POST_COMPLETION_FOR_REQ(req) \
memset(&((req)->overlapped), 0, sizeof((req)->overlapped)); \
if (!PostQueuedCompletionStatus(LOOP->iocp, \ if (!PostQueuedCompletionStatus(LOOP->iocp, \
0, \ 0, \
0, \ 0, \
@ -169,6 +168,7 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb); uv_read_cb read_cb);
int uv_tcp_write(uv_write_t* req, uv_tcp_t* handle, uv_buf_t bufs[], int uv_tcp_write(uv_write_t* req, uv_tcp_t* handle, uv_buf_t bufs[],
int bufcnt, uv_write_cb cb); int bufcnt, uv_write_cb cb);
int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen);
void uv_process_tcp_read_req(uv_tcp_t* handle, uv_req_t* req); void uv_process_tcp_read_req(uv_tcp_t* handle, uv_req_t* req);
void uv_process_tcp_write_req(uv_tcp_t* handle, uv_write_t* req); void uv_process_tcp_write_req(uv_tcp_t* handle, uv_write_t* req);
@ -178,6 +178,17 @@ void uv_process_tcp_connect_req(uv_tcp_t* handle, uv_connect_t* req);
void uv_tcp_endgame(uv_tcp_t* handle); void uv_tcp_endgame(uv_tcp_t* handle);
/*
* UDP
*/
int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen);
void uv_process_udp_recv_req(uv_udp_t* handle, uv_req_t* req);
void uv_process_udp_send_req(uv_udp_t* handle, uv_udp_send_t* req);
void uv_udp_endgame(uv_udp_t* handle);
/* /*
* Pipes * Pipes
*/ */
@ -252,12 +263,40 @@ uv_err_t uv_new_sys_error(int sys_errno);
void uv_set_sys_error(int sys_errno); void uv_set_sys_error(int sys_errno);
void uv_set_error(uv_err_code code, int sys_errno); void uv_set_error(uv_err_code code, int sys_errno);
#define SET_REQ_STATUS(req, status) \
(req)->overlapped.Internal = (ULONG_PTR) (status)
#define SET_REQ_ERROR(req, error) \
SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error)))
#define SET_REQ_SUCCESS(req) \
SET_REQ_STATUS((req), STATUS_SUCCESS)
#define GET_REQ_STATUS(req) \
((req)->overlapped.Internal)
#define REQ_SUCCESS(req) \
(NT_SUCCESS(GET_REQ_STATUS((req))))
#define GET_REQ_ERROR(req) \
(pRtlNtStatusToDosError(GET_REQ_STATUS((req))))
#define GET_REQ_SOCK_ERROR(req) \
(uv_ntstatus_to_winsock_error(GET_REQ_STATUS((req))))
#define GET_REQ_UV_ERROR(req) \
(uv_new_sys_error(GET_REQ_ERROR((req))))
#define GET_REQ_UV_SOCK_ERROR(req) \
(uv_new_sys_error(GET_REQ_SOCK_ERROR((req))))
/* /*
* Initialization for the windows and winsock api * Initialization for the windows and winsock api
*/ */
void uv_winapi_init(); void uv_winapi_init();
void uv_winsock_init(); void uv_winsock_init();
int uv_ntstatus_to_winsock_error(NTSTATUS status);
#endif /* UV_WIN_INTERNAL_H_ */ #endif /* UV_WIN_INTERNAL_H_ */

1
deps/uv/src/win/loop-watcher.c

@ -44,7 +44,6 @@ void uv_loop_watcher_endgame(uv_handle_t* handle) {
int uv_##name##_init(uv_##name##_t* handle) { \ int uv_##name##_init(uv_##name##_t* handle) { \
handle->type = UV_##NAME; \ handle->type = UV_##NAME; \
handle->flags = 0; \ handle->flags = 0; \
handle->error = uv_ok_; \
\ \
uv_ref(); \ uv_ref(); \
\ \

43
deps/uv/src/win/pipe.c

@ -300,8 +300,6 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
errno = GetLastError(); errno = GetLastError();
if (errno == ERROR_ACCESS_DENIED) { if (errno == ERROR_ACCESS_DENIED) {
uv_set_error(UV_EADDRINUSE, errno); uv_set_error(UV_EADDRINUSE, errno);
handle->error = LOOP->last_error;
handle->flags |= UV_HANDLE_BIND_ERROR;
} else if (errno == ERROR_PATH_NOT_FOUND || errno == ERROR_INVALID_NAME) { } else if (errno == ERROR_PATH_NOT_FOUND || errno == ERROR_INVALID_NAME) {
uv_set_error(UV_EACCESS, errno); uv_set_error(UV_EACCESS, errno);
} else { } else {
@ -366,9 +364,9 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
if (pipeHandle != INVALID_HANDLE_VALUE && !uv_set_pipe_handle(handle, pipeHandle)) { if (pipeHandle != INVALID_HANDLE_VALUE && !uv_set_pipe_handle(handle, pipeHandle)) {
handle->handle = pipeHandle; handle->handle = pipeHandle;
req->error = uv_ok_; SET_REQ_SUCCESS(req);
} else { } else {
req->error = uv_new_sys_error(GetLastError()); SET_REQ_ERROR(req, GetLastError());
} }
/* Post completed */ /* Post completed */
@ -434,7 +432,7 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
handle->handle = pipeHandle; handle->handle = pipeHandle;
req->error = uv_ok_; SET_REQ_SUCCESS(req);
uv_insert_pending_req((uv_req_t*) req); uv_insert_pending_req((uv_req_t*) req);
handle->reqs_pending++; handle->reqs_pending++;
return 0; return 0;
@ -497,7 +495,7 @@ static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL
NULL); NULL);
if (req->pipeHandle == INVALID_HANDLE_VALUE) { if (req->pipeHandle == INVALID_HANDLE_VALUE) {
req->error = uv_new_sys_error(GetLastError()); SET_REQ_ERROR(req, GetLastError());
uv_insert_pending_req((uv_req_t*) req); uv_insert_pending_req((uv_req_t*) req);
handle->reqs_pending++; handle->reqs_pending++;
return; return;
@ -506,7 +504,7 @@ static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL
if (uv_set_pipe_handle(handle, req->pipeHandle)) { if (uv_set_pipe_handle(handle, req->pipeHandle)) {
CloseHandle(req->pipeHandle); CloseHandle(req->pipeHandle);
req->pipeHandle = INVALID_HANDLE_VALUE; req->pipeHandle = INVALID_HANDLE_VALUE;
req->error = uv_new_sys_error(GetLastError()); SET_REQ_ERROR(req, GetLastError());
uv_insert_pending_req((uv_req_t*) req); uv_insert_pending_req((uv_req_t*) req);
handle->reqs_pending++; handle->reqs_pending++;
return; return;
@ -520,12 +518,12 @@ static void uv_pipe_queue_accept(uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL
if (!ConnectNamedPipe(req->pipeHandle, &req->overlapped) && GetLastError() != ERROR_IO_PENDING) { if (!ConnectNamedPipe(req->pipeHandle, &req->overlapped) && GetLastError() != ERROR_IO_PENDING) {
if (GetLastError() == ERROR_PIPE_CONNECTED) { if (GetLastError() == ERROR_PIPE_CONNECTED) {
req->error = uv_ok_; SET_REQ_SUCCESS(req);
} else { } else {
CloseHandle(req->pipeHandle); CloseHandle(req->pipeHandle);
req->pipeHandle = INVALID_HANDLE_VALUE; req->pipeHandle = INVALID_HANDLE_VALUE;
/* Make this req pending reporting an error. */ /* Make this req pending reporting an error. */
req->error = uv_new_sys_error(GetLastError()); SET_REQ_ERROR(req, GetLastError());
} }
uv_insert_pending_req((uv_req_t*) req); uv_insert_pending_req((uv_req_t*) req);
handle->reqs_pending++; handle->reqs_pending++;
@ -570,11 +568,6 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
uv_pipe_accept_t* req; uv_pipe_accept_t* req;
HANDLE pipeHandle; HANDLE pipeHandle;
if (handle->flags & UV_HANDLE_BIND_ERROR) {
uv_set_error(UV_EINVAL, 0);
return -1;
}
if (!(handle->flags & UV_HANDLE_BOUND) && if (!(handle->flags & UV_HANDLE_BOUND) &&
!(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) { !(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) {
uv_set_error(UV_EINVAL, 0); uv_set_error(UV_EINVAL, 0);
@ -647,7 +640,7 @@ static void uv_pipe_queue_read(uv_pipe_t* handle) {
if (!result && GetLastError() != ERROR_IO_PENDING) { if (!result && GetLastError() != ERROR_IO_PENDING) {
/* Make this req pending reporting an error. */ /* Make this req pending reporting an error. */
req->error = uv_new_sys_error(WSAGetLastError()); SET_REQ_ERROR(req, WSAGetLastError());
uv_insert_pending_req(req); uv_insert_pending_req(req);
handle->reqs_pending++; handle->reqs_pending++;
return; return;
@ -749,12 +742,12 @@ void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) {
handle->flags &= ~UV_HANDLE_READ_PENDING; handle->flags &= ~UV_HANDLE_READ_PENDING;
if (req->error.code != UV_OK) { if (!REQ_SUCCESS(req)) {
/* An error occurred doing the 0-read. */ /* An error occurred doing the 0-read. */
if (handle->flags & UV_HANDLE_READING) { if (handle->flags & UV_HANDLE_READING) {
/* Stop reading and report error. */ /* Stop reading and report error. */
handle->flags &= ~UV_HANDLE_READING; handle->flags &= ~UV_HANDLE_READING;
LOOP->last_error = req->error; LOOP->last_error = GET_REQ_UV_ERROR(req);
buf.base = 0; buf.base = 0;
buf.len = 0; buf.len = 0;
handle->read_cb((uv_stream_t*)handle, -1, buf); handle->read_cb((uv_stream_t*)handle, -1, buf);
@ -780,7 +773,7 @@ void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) {
break; break;
} }
buf = handle->alloc_cb((uv_stream_t*)handle, avail); buf = handle->alloc_cb((uv_handle_t*) handle, avail);
assert(buf.len > 0); assert(buf.len > 0);
if (ReadFile(handle->handle, if (ReadFile(handle->handle,
@ -819,8 +812,12 @@ void uv_process_pipe_write_req(uv_pipe_t* handle, uv_write_t* req) {
handle->write_queue_size -= req->queued_bytes; handle->write_queue_size -= req->queued_bytes;
if (req->cb) { if (req->cb) {
LOOP->last_error = req->error; if (!REQ_SUCCESS(req)) {
((uv_write_cb)req->cb)(req, LOOP->last_error.code == UV_OK ? 0 : -1); LOOP->last_error = GET_REQ_UV_ERROR(req);
((uv_write_cb)req->cb)(req, -1);
} else {
((uv_write_cb)req->cb)(req, 0);
}
} }
handle->write_reqs_pending--; handle->write_reqs_pending--;
@ -838,7 +835,7 @@ void uv_process_pipe_accept_req(uv_pipe_t* handle, uv_req_t* raw_req) {
assert(handle->type == UV_NAMED_PIPE); assert(handle->type == UV_NAMED_PIPE);
if (req->error.code == UV_OK) { if (REQ_SUCCESS(req)) {
assert(req->pipeHandle != INVALID_HANDLE_VALUE); assert(req->pipeHandle != INVALID_HANDLE_VALUE);
req->next_pending = handle->pending_accepts; req->next_pending = handle->pending_accepts;
handle->pending_accepts = req; handle->pending_accepts = req;
@ -865,11 +862,11 @@ void uv_process_pipe_connect_req(uv_pipe_t* handle, uv_connect_t* req) {
assert(handle->type == UV_NAMED_PIPE); assert(handle->type == UV_NAMED_PIPE);
if (req->cb) { if (req->cb) {
if (req->error.code == UV_OK) { if (REQ_SUCCESS(req)) {
uv_connection_init((uv_stream_t*)handle); uv_connection_init((uv_stream_t*)handle);
((uv_connect_cb)req->cb)(req, 0); ((uv_connect_cb)req->cb)(req, 0);
} else { } else {
LOOP->last_error = req->error; LOOP->last_error = GET_REQ_UV_ERROR(req);
((uv_connect_cb)req->cb)(req, -1); ((uv_connect_cb)req->cb)(req, -1);
} }
} }

1
deps/uv/src/win/process.c

@ -54,7 +54,6 @@ typedef struct env_var {
static void uv_process_init(uv_process_t* handle) { static void uv_process_init(uv_process_t* handle) {
handle->type = UV_PROCESS; handle->type = UV_PROCESS;
handle->flags = 0; handle->flags = 0;
handle->error = uv_ok_;
handle->exit_cb = NULL; handle->exit_cb = NULL;
handle->pid = 0; handle->pid = 0;
handle->exit_signal = 0; handle->exit_signal = 0;

11
deps/uv/src/win/req.c

@ -29,7 +29,7 @@
void uv_req_init(uv_req_t* req) { void uv_req_init(uv_req_t* req) {
uv_counters()->req_init++; uv_counters()->req_init++;
req->type = UV_UNKNOWN_REQ; req->type = UV_UNKNOWN_REQ;
req->error = uv_ok_; SET_REQ_SUCCESS(req);
} }
@ -117,6 +117,15 @@ void uv_process_reqs() {
(uv_pipe_t*) ((uv_shutdown_t*) req)->handle, (uv_shutdown_t*) req); (uv_pipe_t*) ((uv_shutdown_t*) req)->handle, (uv_shutdown_t*) req);
break; break;
case UV_UDP_RECV:
uv_process_udp_recv_req((uv_udp_t*) req->data, req);
break;
case UV_UDP_SEND:
uv_process_udp_send_req(((uv_udp_send_t*) req)->handle,
(uv_udp_send_t*) req);
break;
case UV_WAKEUP: case UV_WAKEUP:
uv_process_async_wakeup_req((uv_async_t*) req->data, req); uv_process_async_wakeup_req((uv_async_t*) req->data, req);
break; break;

1
deps/uv/src/win/stream.c

@ -29,7 +29,6 @@
void uv_stream_init(uv_stream_t* handle) { void uv_stream_init(uv_stream_t* handle) {
handle->write_queue_size = 0; handle->write_queue_size = 0;
handle->flags = 0; handle->flags = 0;
handle->error = uv_ok_;
uv_counters()->handle_init++; uv_counters()->handle_init++;
uv_counters()->stream_init++; uv_counters()->stream_init++;

39
deps/uv/src/win/tcp.c

@ -28,8 +28,11 @@
/* /*
* Threshold of active tcp streams for which to preallocate tcp read buffers. * Threshold of active tcp streams for which to preallocate tcp read buffers.
* (Due to node slab allocator performing poorly under this pattern,
* the optimization is temporarily disabled (threshold=0). This will be
* revisited once node allocator is improved.)
*/ */
const unsigned int uv_active_tcp_streams_threshold = 50; const unsigned int uv_active_tcp_streams_threshold = 0;
/* /*
* Number of simultaneous pending AcceptEx calls. * Number of simultaneous pending AcceptEx calls.
@ -171,7 +174,7 @@ static int uv__bind(uv_tcp_t* handle, int domain, struct sockaddr* addr, int add
err = WSAGetLastError(); err = WSAGetLastError();
if (err == WSAEADDRINUSE) { if (err == WSAEADDRINUSE) {
/* Some errors are not to be reported until connect() or listen() */ /* Some errors are not to be reported until connect() or listen() */
handle->error = uv_new_sys_error(err); handle->bind_error = uv_new_sys_error(err);
handle->flags |= UV_HANDLE_BIND_ERROR; handle->flags |= UV_HANDLE_BIND_ERROR;
} else { } else {
uv_set_sys_error(err); uv_set_sys_error(err);
@ -232,7 +235,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
/* Open a socket for the accepted connection. */ /* Open a socket for the accepted connection. */
accept_socket = socket(family, SOCK_STREAM, 0); accept_socket = socket(family, SOCK_STREAM, 0);
if (accept_socket == INVALID_SOCKET) { if (accept_socket == INVALID_SOCKET) {
req->error = uv_new_sys_error(WSAGetLastError()); SET_REQ_ERROR(req, WSAGetLastError());
uv_insert_pending_req((uv_req_t*)req); uv_insert_pending_req((uv_req_t*)req);
handle->reqs_pending++; handle->reqs_pending++;
return; return;
@ -261,7 +264,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
handle->reqs_pending++; handle->reqs_pending++;
} else { } else {
/* Make this req pending reporting an error. */ /* Make this req pending reporting an error. */
req->error = uv_new_sys_error(WSAGetLastError()); SET_REQ_ERROR(req, WSAGetLastError());
uv_insert_pending_req((uv_req_t*)req); uv_insert_pending_req((uv_req_t*)req);
handle->reqs_pending++; handle->reqs_pending++;
/* Destroy the preallocated client socket. */ /* Destroy the preallocated client socket. */
@ -288,7 +291,7 @@ static void uv_tcp_queue_read(uv_tcp_t* handle) {
*/ */
if (active_tcp_streams < uv_active_tcp_streams_threshold) { if (active_tcp_streams < uv_active_tcp_streams_threshold) {
handle->flags &= ~UV_HANDLE_ZERO_READ; handle->flags &= ~UV_HANDLE_ZERO_READ;
handle->read_buffer = handle->alloc_cb((uv_stream_t*)handle, 65536); handle->read_buffer = handle->alloc_cb((uv_handle_t*) handle, 65536);
assert(handle->read_buffer.len > 0); assert(handle->read_buffer.len > 0);
buf = handle->read_buffer; buf = handle->read_buffer;
} else { } else {
@ -318,7 +321,7 @@ static void uv_tcp_queue_read(uv_tcp_t* handle) {
handle->reqs_pending++; handle->reqs_pending++;
} else { } else {
/* Make this req pending reporting an error. */ /* Make this req pending reporting an error. */
req->error = uv_new_sys_error(WSAGetLastError()); SET_REQ_ERROR(req, WSAGetLastError());
uv_insert_pending_req(req); uv_insert_pending_req(req);
handle->reqs_pending++; handle->reqs_pending++;
} }
@ -332,7 +335,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
assert(backlog > 0); assert(backlog > 0);
if (handle->flags & UV_HANDLE_BIND_ERROR) { if (handle->flags & UV_HANDLE_BIND_ERROR) {
LOOP->last_error = handle->error; LOOP->last_error = handle->bind_error;
return -1; return -1;
} }
@ -449,7 +452,7 @@ int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle,
DWORD bytes; DWORD bytes;
if (handle->flags & UV_HANDLE_BIND_ERROR) { if (handle->flags & UV_HANDLE_BIND_ERROR) {
LOOP->last_error = handle->error; LOOP->last_error = handle->bind_error;
return -1; return -1;
} }
@ -504,7 +507,7 @@ int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle,
} }
if (handle->flags & UV_HANDLE_BIND_ERROR) { if (handle->flags & UV_HANDLE_BIND_ERROR) {
LOOP->last_error = handle->error; LOOP->last_error = handle->bind_error;
return -1; return -1;
} }
@ -545,7 +548,7 @@ int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle,
} }
int uv_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen) { int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen) {
int result; int result;
if (handle->flags & UV_HANDLE_SHUTTING) { if (handle->flags & UV_HANDLE_SHUTTING) {
@ -622,11 +625,11 @@ void uv_process_tcp_read_req(uv_tcp_t* handle, uv_req_t* req) {
handle->flags &= ~UV_HANDLE_READ_PENDING; handle->flags &= ~UV_HANDLE_READ_PENDING;
if (req->error.code != UV_OK) { if (!REQ_SUCCESS(req)) {
/* An error occurred doing the read. */ /* An error occurred doing the read. */
if ((handle->flags & UV_HANDLE_READING)) { if ((handle->flags & UV_HANDLE_READING)) {
handle->flags &= ~UV_HANDLE_READING; handle->flags &= ~UV_HANDLE_READING;
LOOP->last_error = req->error; LOOP->last_error = GET_REQ_UV_SOCK_ERROR(req);
buf = (handle->flags & UV_HANDLE_ZERO_READ) ? buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
uv_buf_init(NULL, 0) : handle->read_buffer; uv_buf_init(NULL, 0) : handle->read_buffer;
handle->read_cb((uv_stream_t*)handle, -1, buf); handle->read_cb((uv_stream_t*)handle, -1, buf);
@ -656,7 +659,7 @@ void uv_process_tcp_read_req(uv_tcp_t* handle, uv_req_t* req) {
/* Do nonblocking reads until the buffer is empty */ /* Do nonblocking reads until the buffer is empty */
while (handle->flags & UV_HANDLE_READING) { while (handle->flags & UV_HANDLE_READING) {
buf = handle->alloc_cb((uv_stream_t*)handle, 65536); buf = handle->alloc_cb((uv_handle_t*) handle, 65536);
assert(buf.len > 0); assert(buf.len > 0);
flags = 0; flags = 0;
if (WSARecv(handle->socket, if (WSARecv(handle->socket,
@ -715,7 +718,7 @@ void uv_process_tcp_write_req(uv_tcp_t* handle, uv_write_t* req) {
handle->write_queue_size -= req->queued_bytes; handle->write_queue_size -= req->queued_bytes;
if (req->cb) { if (req->cb) {
LOOP->last_error = req->error; LOOP->last_error = GET_REQ_UV_SOCK_ERROR(req);
((uv_write_cb)req->cb)(req, LOOP->last_error.code == UV_OK ? 0 : -1); ((uv_write_cb)req->cb)(req, LOOP->last_error.code == UV_OK ? 0 : -1);
} }
@ -742,11 +745,11 @@ void uv_process_tcp_accept_req(uv_tcp_t* handle, uv_req_t* raw_req) {
if (handle->flags & UV_HANDLE_LISTENING) { if (handle->flags & UV_HANDLE_LISTENING) {
handle->flags &= ~UV_HANDLE_LISTENING; handle->flags &= ~UV_HANDLE_LISTENING;
if (handle->connection_cb) { if (handle->connection_cb) {
LOOP->last_error = req->error; LOOP->last_error = GET_REQ_UV_SOCK_ERROR(req);
handle->connection_cb((uv_stream_t*)handle, -1); handle->connection_cb((uv_stream_t*)handle, -1);
} }
} }
} else if (req->error.code == UV_OK && } else if (REQ_SUCCESS(req) &&
setsockopt(req->accept_socket, setsockopt(req->accept_socket,
SOL_SOCKET, SOL_SOCKET,
SO_UPDATE_ACCEPT_CONTEXT, SO_UPDATE_ACCEPT_CONTEXT,
@ -778,7 +781,7 @@ void uv_process_tcp_connect_req(uv_tcp_t* handle, uv_connect_t* req) {
assert(handle->type == UV_TCP); assert(handle->type == UV_TCP);
if (req->cb) { if (req->cb) {
if (req->error.code == UV_OK) { if (REQ_SUCCESS(req)) {
if (setsockopt(handle->socket, if (setsockopt(handle->socket,
SOL_SOCKET, SOL_SOCKET,
SO_UPDATE_CONNECT_CONTEXT, SO_UPDATE_CONNECT_CONTEXT,
@ -792,7 +795,7 @@ void uv_process_tcp_connect_req(uv_tcp_t* handle, uv_connect_t* req) {
((uv_connect_cb)req->cb)(req, -1); ((uv_connect_cb)req->cb)(req, -1);
} }
} else { } else {
LOOP->last_error = req->error; LOOP->last_error = GET_REQ_UV_SOCK_ERROR(req);
((uv_connect_cb)req->cb)(req, -1); ((uv_connect_cb)req->cb)(req, -1);
} }
} }

1
deps/uv/src/win/timer.c

@ -117,7 +117,6 @@ int uv_timer_init(uv_timer_t* handle) {
handle->type = UV_TIMER; handle->type = UV_TIMER;
handle->flags = 0; handle->flags = 0;
handle->error = uv_ok_;
handle->timer_cb = NULL; handle->timer_cb = NULL;
handle->repeat = 0; handle->repeat = 0;

576
deps/uv/src/win/udp.c

@ -0,0 +1,576 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include "uv.h"
#include "../uv-common.h"
#include "internal.h"
#include <stdio.h>
#if 0
/*
* Threshold of active udp streams for which to preallocate udp read buffers.
*/
const unsigned int uv_active_udp_streams_threshold = 0;
/* A zero-size buffer for use by uv_udp_read */
static char uv_zero_[] = "";
#endif
/* Counter to keep track of active udp streams */
static unsigned int active_udp_streams = 0;
static int uv_udp_set_socket(uv_udp_t* handle, SOCKET socket) {
DWORD yes = 1;
assert(handle->socket == INVALID_SOCKET);
/* Set the socket to nonblocking mode */
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
uv_set_sys_error(WSAGetLastError());
return -1;
}
/* Make the socket non-inheritable */
if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) {
uv_set_sys_error(GetLastError());
return -1;
}
/* Associate it with the I/O completion port. */
/* Use uv_handle_t pointer as completion key. */
if (CreateIoCompletionPort((HANDLE)socket,
LOOP->iocp,
(ULONG_PTR)socket,
0) == NULL) {
uv_set_sys_error(GetLastError());
return -1;
}
if (pSetFileCompletionNotificationModes) {
if (!pSetFileCompletionNotificationModes((HANDLE)socket, FILE_SKIP_SET_EVENT_ON_HANDLE |
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
uv_set_sys_error(GetLastError());
return -1;
}
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
}
handle->socket = socket;
return 0;
}
int uv_udp_init(uv_udp_t* handle) {
handle->type = UV_UDP;
handle->socket = INVALID_SOCKET;
handle->reqs_pending = 0;
handle->flags = 0;
uv_req_init((uv_req_t*) &(handle->recv_req));
handle->recv_req.type = UV_UDP_RECV;
handle->recv_req.data = handle;
uv_ref();
uv_counters()->handle_init++;
uv_counters()->udp_init++;
return 0;
}
void uv_udp_endgame(uv_udp_t* handle) {
if (handle->flags & UV_HANDLE_CLOSING &&
handle->reqs_pending == 0) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
handle->flags |= UV_HANDLE_CLOSED;
if (handle->close_cb) {
handle->close_cb((uv_handle_t*)handle);
}
uv_unref();
}
}
static int uv__bind(uv_udp_t* handle, int domain, struct sockaddr* addr,
int addrsize, unsigned int flags) {
DWORD err;
int r;
SOCKET sock;
if ((flags & UV_UDP_IPV6ONLY) && domain != AF_INET6) {
/* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */
uv_set_sys_error(UV_EINVAL);
}
if (handle->socket == INVALID_SOCKET) {
sock = socket(domain, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) {
uv_set_sys_error(WSAGetLastError());
return -1;
}
if (uv_udp_set_socket(handle, sock) == -1) {
closesocket(sock);
return -1;
}
}
if (domain == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
DWORD off = 0;
/* On windows IPV6ONLY is on by default. */
/* If the user doesn't specify it libuv turns it off. */
/* TODO: how to handle errors? This may fail if there is no ipv4 stack */
/* available, or when run on XP/2003 which have no support for dualstack */
/* sockets. For now we're silently ignoring the error. */
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &off, sizeof off);
}
r = bind(handle->socket, addr, addrsize);
if (r == SOCKET_ERROR) {
err = WSAGetLastError();
uv_set_sys_error(WSAGetLastError());
return -1;
}
handle->flags |= UV_HANDLE_BOUND;
return 0;
}
int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned int flags) {
if (addr.sin_family != AF_INET) {
uv_set_sys_error(WSAEFAULT);
return -1;
}
return uv__bind(handle,
AF_INET,
(struct sockaddr*) &addr,
sizeof(struct sockaddr_in),
flags);
}
int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned int flags) {
if (addr.sin6_family != AF_INET6) {
uv_set_sys_error(WSAEFAULT);
return -1;
}
if (uv_allow_ipv6) {
handle->flags |= UV_HANDLE_IPV6;
return uv__bind(handle,
AF_INET6,
(struct sockaddr*) &addr,
sizeof(struct sockaddr_in6),
flags);
} else {
uv_new_sys_error(WSAEAFNOSUPPORT);
return -1;
}
}
int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen) {
int result;
if (handle->flags & UV_HANDLE_SHUTTING) {
uv_set_sys_error(WSAESHUTDOWN);
return -1;
}
result = getsockname(handle->socket, name, namelen);
if (result != 0) {
uv_set_sys_error(WSAGetLastError());
return -1;
}
return 0;
}
static void uv_udp_queue_recv(uv_udp_t* handle) {
uv_req_t* req;
uv_buf_t buf;
DWORD bytes, flags;
int result;
assert(handle->flags & UV_HANDLE_READING);
assert(!(handle->flags & UV_HANDLE_READ_PENDING));
req = &handle->recv_req;
memset(&req->overlapped, 0, sizeof(req->overlapped));
/*
* Preallocate a read buffer if the number of active streams is below
* the threshold.
*/
#if 0
if (active_udp_streams < uv_active_udp_streams_threshold) {
handle->flags &= ~UV_HANDLE_ZERO_READ;
#endif
handle->recv_buffer = handle->alloc_cb((uv_handle_t*) handle, 65536);
assert(handle->recv_buffer.len > 0);
buf = handle->recv_buffer;
memset(&handle->recv_from, 0, sizeof handle->recv_from);
handle->recv_from_len = sizeof handle->recv_from;
flags = 0;
result = WSARecvFrom(handle->socket,
(WSABUF*) &buf,
1,
&bytes,
&flags,
(struct sockaddr*) &handle->recv_from,
&handle->recv_from_len,
&req->overlapped,
NULL);
if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
/* Process the req without IOCP. */
handle->flags |= UV_HANDLE_READ_PENDING;
req->overlapped.InternalHigh = bytes;
handle->reqs_pending++;
uv_insert_pending_req(req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* The req will be processed with IOCP. */
handle->flags |= UV_HANDLE_READ_PENDING;
handle->reqs_pending++;
} else {
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, WSAGetLastError());
uv_insert_pending_req(req);
handle->reqs_pending++;
}
#if 0
} else {
handle->flags |= UV_HANDLE_ZERO_READ;
buf.base = (char*) uv_zero_;
buf.len = 0;
flags = MSG_PARTIAL;
result = WSARecv(handle->socket,
(WSABUF*) &buf,
1,
&bytes,
&flags,
&req->overlapped,
NULL);
if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
/* Process the req without IOCP. */
handle->flags |= UV_HANDLE_READ_PENDING;
req->overlapped.InternalHigh = bytes;
handle->reqs_pending++;
uv_insert_pending_req(req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* The req will be processed with IOCP. */
handle->flags |= UV_HANDLE_READ_PENDING;
handle->reqs_pending++;
} else {
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, WSAGetLastError());
uv_insert_pending_req(req);
handle->reqs_pending++;
}
}
#endif
}
int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, uv_udp_recv_cb recv_cb) {
if (handle->flags & UV_HANDLE_READING) {
uv_set_sys_error(WSAEALREADY);
return -1;
}
if (!(handle->flags & UV_HANDLE_BOUND) &&
uv_udp_bind(handle, uv_addr_ip4_any_, 0) < 0) {
return -1;
}
handle->flags |= UV_HANDLE_READING;
active_udp_streams++;
handle->recv_cb = recv_cb;
handle->alloc_cb = alloc_cb;
/* If reading was stopped and then started again, there could stell be a */
/* recv request pending. */
if (!(handle->flags & UV_HANDLE_READ_PENDING))
uv_udp_queue_recv(handle);
return 0;
}
int uv_udp_recv_stop(uv_udp_t* handle) {
if (handle->flags & UV_HANDLE_READING) {
handle->flags &= ~UV_HANDLE_READING;
active_udp_streams--;
}
return 0;
}
int uv_udp_connect6(uv_connect_t* req, uv_udp_t* handle,
struct sockaddr_in6 address, uv_connect_cb cb) {
int addrsize = sizeof(struct sockaddr_in6);
BOOL success;
DWORD bytes;
if (!uv_allow_ipv6) {
uv_new_sys_error(WSAEAFNOSUPPORT);
return -1;
}
if (address.sin6_family != AF_INET6) {
uv_set_sys_error(WSAEFAULT);
return -1;
}
if (!(handle->flags & UV_HANDLE_BOUND) &&
uv_udp_bind6(handle, uv_addr_ip6_any_, 0) < 0)
return -1;
uv_req_init((uv_req_t*) req);
req->type = UV_CONNECT;
req->handle = (uv_stream_t*) handle;
req->cb = cb;
memset(&req->overlapped, 0, sizeof(req->overlapped));
success = pConnectEx6(handle->socket,
(struct sockaddr*) &address,
addrsize,
NULL,
0,
&bytes,
&req->overlapped);
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
handle->reqs_pending++;
uv_insert_pending_req((uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
handle->reqs_pending++;
} else {
uv_set_sys_error(WSAGetLastError());
return -1;
}
return 0;
}
static int uv__udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
int bufcnt, struct sockaddr* addr, int addr_len, uv_udp_send_cb cb) {
DWORD result, bytes;
uv_req_init((uv_req_t*) req);
req->type = UV_UDP_SEND;
req->handle = handle;
req->cb = cb;
memset(&req->overlapped, 0, sizeof(req->overlapped));
result = WSASendTo(handle->socket,
(WSABUF*)bufs,
bufcnt,
&bytes,
0,
addr,
addr_len,
&req->overlapped,
NULL);
if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
/* Request completed immediately. */
req->queued_bytes = 0;
handle->reqs_pending++;
uv_insert_pending_req((uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* Request queued by the kernel. */
req->queued_bytes = uv_count_bufs(bufs, bufcnt);
handle->reqs_pending++;
} else {
/* Send failed due to an error. */
uv_set_sys_error(WSAGetLastError());
return -1;
}
return 0;
}
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 cb) {
if (!(handle->flags & UV_HANDLE_BOUND) &&
uv_udp_bind(handle, uv_addr_ip4_any_, 0) < 0) {
return -1;
}
return uv__udp_send(req,
handle,
bufs,
bufcnt,
(struct sockaddr*) &addr,
sizeof addr,
cb);
}
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 cb) {
if (!(handle->flags & UV_HANDLE_BOUND) &&
uv_udp_bind6(handle, uv_addr_ip6_any_, 0) < 0) {
return -1;
}
return uv__udp_send(req,
handle,
bufs,
bufcnt,
(struct sockaddr*) &addr,
sizeof addr,
cb);
}
void uv_process_udp_recv_req(uv_udp_t* handle, uv_req_t* req) {
uv_buf_t buf;
int partial;
assert(handle->type == UV_UDP);
handle->flags &= ~UV_HANDLE_READ_PENDING;
if (!REQ_SUCCESS(req) &&
GET_REQ_STATUS(req) != STATUS_RECEIVE_EXPEDITED) {
/* An error occurred doing the read. */
if ((handle->flags & UV_HANDLE_READING)) {
LOOP->last_error = GET_REQ_UV_SOCK_ERROR(req);
uv_udp_recv_stop(handle);
#if 0
buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
uv_buf_init(NULL, 0) : handle->recv_buffer;
#else
buf = handle->recv_buffer;
#endif
handle->recv_cb(handle, -1, buf, NULL, 0);
}
goto done;
}
#if 0
if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
#endif
/* Successful read */
partial = (GET_REQ_STATUS(req) == STATUS_RECEIVE_EXPEDITED);
handle->recv_cb(handle,
req->overlapped.InternalHigh,
handle->recv_buffer,
(struct sockaddr*) &handle->recv_from,
partial ? UV_UDP_PARTIAL : 0);
#if 0
} else {
DWORD bytes, err, flags;
struct sockaddr_storage from;
int from_len;
/* Do a nonblocking receive */
/* TODO: try to read multiple datagrams at once. FIONREAD maybe? */
buf = handle->alloc_cb((uv_handle_t*) handle, 65536);
assert(buf.len > 0);
memset(&from, 0, sizeof from);
from_len = sizeof from;
flags = MSG_PARTIAL;
if (WSARecvFrom(handle->socket,
(WSABUF*)&buf,
1,
&bytes,
&flags,
(struct sockaddr*) &from,
&from_len,
NULL,
NULL) != SOCKET_ERROR) {
/* Message received */
handle->recv_cb(handle,
bytes,
buf,
(struct sockaddr*) &from,
(flags & MSG_PARTIAL) ? UV_UDP_PARTIAL : 0);
} else {
err = WSAGetLastError();
if (err == WSAEWOULDBLOCK) {
uv_set_sys_error(WSAEWOULDBLOCK);
handle->recv_cb(handle, 0, buf, NULL, 0);
} else {
/* Ouch! serious error. */
uv_set_sys_error(err);
handle->recv_cb(handle, -1, buf, NULL, 0);
}
}
}
#endif
done:
/* Post another read if still reading and not closing. */
if ((handle->flags & UV_HANDLE_READING) &&
!(handle->flags & UV_HANDLE_READ_PENDING)) {
uv_udp_queue_recv(handle);
}
DECREASE_PENDING_REQ_COUNT(handle);
}
void uv_process_udp_send_req(uv_udp_t* handle, uv_udp_send_t* req) {
assert(handle->type == UV_UDP);
if (req->cb) {
if (REQ_SUCCESS(req)) {
req->cb(req, 0);
} else {
LOOP->last_error = GET_REQ_UV_SOCK_ERROR(req);
req->cb(req, -1);
}
}
DECREASE_PENDING_REQ_COUNT(handle);
}

4040
deps/uv/src/win/winapi.h

File diff suppressed because it is too large

115
deps/uv/src/win/winsock.c

@ -153,3 +153,118 @@ void uv_winsock_init() {
} }
} }
} }
int uv_ntstatus_to_winsock_error(NTSTATUS status) {
switch (status) {
case STATUS_SUCCESS:
return ERROR_SUCCESS;
case STATUS_PENDING:
return ERROR_IO_PENDING;
case STATUS_INVALID_HANDLE:
case STATUS_OBJECT_TYPE_MISMATCH:
return WSAENOTSOCK;
case STATUS_INSUFFICIENT_RESOURCES:
case STATUS_PAGEFILE_QUOTA:
case STATUS_COMMITMENT_LIMIT:
case STATUS_WORKING_SET_QUOTA:
case STATUS_NO_MEMORY:
case STATUS_CONFLICTING_ADDRESSES:
case STATUS_QUOTA_EXCEEDED:
case STATUS_TOO_MANY_PAGING_FILES:
case STATUS_REMOTE_RESOURCES:
case STATUS_TOO_MANY_ADDRESSES:
return WSAENOBUFS;
case STATUS_SHARING_VIOLATION:
case STATUS_ADDRESS_ALREADY_EXISTS:
return WSAEADDRINUSE;
case STATUS_LINK_TIMEOUT:
case STATUS_IO_TIMEOUT:
case STATUS_TIMEOUT:
return WSAETIMEDOUT;
case STATUS_GRACEFUL_DISCONNECT:
return WSAEDISCON;
case STATUS_REMOTE_DISCONNECT:
case STATUS_CONNECTION_RESET:
case STATUS_LINK_FAILED:
case STATUS_CONNECTION_DISCONNECTED:
case STATUS_PORT_UNREACHABLE:
return WSAECONNRESET;
case STATUS_LOCAL_DISCONNECT:
case STATUS_TRANSACTION_ABORTED:
case STATUS_CONNECTION_ABORTED:
return WSAECONNABORTED;
case STATUS_BAD_NETWORK_PATH:
case STATUS_NETWORK_UNREACHABLE:
case STATUS_PROTOCOL_UNREACHABLE:
return WSAENETUNREACH;
case STATUS_HOST_UNREACHABLE:
return WSAEHOSTUNREACH;
case STATUS_CANCELLED:
case STATUS_REQUEST_ABORTED:
return WSAEINTR;
case STATUS_BUFFER_OVERFLOW:
case STATUS_INVALID_BUFFER_SIZE:
return WSAEMSGSIZE;
case STATUS_BUFFER_TOO_SMALL:
case STATUS_ACCESS_VIOLATION:
return WSAEFAULT;
case STATUS_DEVICE_NOT_READY:
case STATUS_REQUEST_NOT_ACCEPTED:
return WSAEWOULDBLOCK;
case STATUS_INVALID_NETWORK_RESPONSE:
case STATUS_NETWORK_BUSY:
case STATUS_NO_SUCH_DEVICE:
case STATUS_NO_SUCH_FILE:
case STATUS_OBJECT_PATH_NOT_FOUND:
case STATUS_OBJECT_NAME_NOT_FOUND:
case STATUS_UNEXPECTED_NETWORK_ERROR:
return WSAENETDOWN;
case STATUS_INVALID_CONNECTION:
return WSAENOTCONN;
case STATUS_REMOTE_NOT_LISTENING:
case STATUS_CONNECTION_REFUSED:
return WSAECONNREFUSED;
case STATUS_PIPE_DISCONNECTED:
return WSAESHUTDOWN;
case STATUS_INVALID_ADDRESS:
case STATUS_INVALID_ADDRESS_COMPONENT:
return WSAEADDRNOTAVAIL;
case STATUS_NOT_SUPPORTED:
case STATUS_NOT_IMPLEMENTED:
return WSAEOPNOTSUPP;
case STATUS_ACCESS_DENIED:
return WSAEACCES;
default:
if (status & ((FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_ERROR)) {
/* It's a windows error that has been previously mapped to an */
/* ntstatus code. */
return (DWORD) (status & 0xffff);
} else {
/* The default fallback for unmappable ntstatus codes. */
return WSAEINVAL;
}
}
}

6
deps/uv/src/win/winsock.h

@ -99,12 +99,16 @@
#endif #endif
/* /*
* MinGW is missing this too * MinGW is missing these too
*/ */
#ifndef SO_UPDATE_CONNECT_CONTEXT #ifndef SO_UPDATE_CONNECT_CONTEXT
# define SO_UPDATE_CONNECT_CONTEXT 0x7010 # define SO_UPDATE_CONNECT_CONTEXT 0x7010
#endif #endif
#ifndef IPV6_V6ONLY
#define IPV6_V6ONLY 27
#endif
/* Winsock extension functions (ipv4) */ /* Winsock extension functions (ipv4) */
extern LPFN_CONNECTEX pConnectEx; extern LPFN_CONNECTEX pConnectEx;

21
deps/uv/test/benchmark-list.h

@ -29,6 +29,16 @@ BENCHMARK_DECLARE (tcp_pump100_client)
BENCHMARK_DECLARE (tcp_pump1_client) BENCHMARK_DECLARE (tcp_pump1_client)
BENCHMARK_DECLARE (pipe_pump100_client) BENCHMARK_DECLARE (pipe_pump100_client)
BENCHMARK_DECLARE (pipe_pump1_client) BENCHMARK_DECLARE (pipe_pump1_client)
BENCHMARK_DECLARE (udp_packet_storm_1v1)
BENCHMARK_DECLARE (udp_packet_storm_1v10)
BENCHMARK_DECLARE (udp_packet_storm_1v100)
BENCHMARK_DECLARE (udp_packet_storm_1v1000)
BENCHMARK_DECLARE (udp_packet_storm_10v10)
BENCHMARK_DECLARE (udp_packet_storm_10v100)
BENCHMARK_DECLARE (udp_packet_storm_10v1000)
BENCHMARK_DECLARE (udp_packet_storm_100v100)
BENCHMARK_DECLARE (udp_packet_storm_100v1000)
BENCHMARK_DECLARE (udp_packet_storm_1000v1000)
BENCHMARK_DECLARE (gethostbyname) BENCHMARK_DECLARE (gethostbyname)
BENCHMARK_DECLARE (getaddrinfo) BENCHMARK_DECLARE (getaddrinfo)
BENCHMARK_DECLARE (spawn) BENCHMARK_DECLARE (spawn)
@ -68,6 +78,17 @@ TASK_LIST_START
BENCHMARK_ENTRY (pipe_pound_1000) BENCHMARK_ENTRY (pipe_pound_1000)
BENCHMARK_HELPER (pipe_pound_1000, pipe_echo_server) BENCHMARK_HELPER (pipe_pound_1000, pipe_echo_server)
BENCHMARK_ENTRY (udp_packet_storm_1v1)
BENCHMARK_ENTRY (udp_packet_storm_1v10)
BENCHMARK_ENTRY (udp_packet_storm_1v100)
BENCHMARK_ENTRY (udp_packet_storm_1v1000)
BENCHMARK_ENTRY (udp_packet_storm_10v10)
BENCHMARK_ENTRY (udp_packet_storm_10v100)
BENCHMARK_ENTRY (udp_packet_storm_10v1000)
BENCHMARK_ENTRY (udp_packet_storm_100v100)
BENCHMARK_ENTRY (udp_packet_storm_100v1000)
BENCHMARK_ENTRY (udp_packet_storm_1000v1000)
BENCHMARK_ENTRY (gethostbyname) BENCHMARK_ENTRY (gethostbyname)
BENCHMARK_HELPER (gethostbyname, dns_server) BENCHMARK_HELPER (gethostbyname, dns_server)

2
deps/uv/test/benchmark-ping-pongs.c

@ -52,7 +52,7 @@ static int completed_pingers = 0;
static int64_t start_time; static int64_t start_time;
static uv_buf_t buf_alloc(uv_stream_t* tcp, size_t size) { static uv_buf_t buf_alloc(uv_handle_t* tcp, size_t size) {
buf_t* ab; buf_t* ab;
ab = buf_freelist; ab = buf_freelist;

4
deps/uv/test/benchmark-pound.c

@ -72,13 +72,13 @@ static uint64_t start; /* in ms */
static int closed_streams; static int closed_streams;
static int conns_failed; static int conns_failed;
static uv_buf_t alloc_cb(uv_stream_t* stream, size_t suggested_size); static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size);
static void connect_cb(uv_connect_t* conn_req, int status); static void connect_cb(uv_connect_t* conn_req, int status);
static void read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf); static void read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf);
static void close_cb(uv_handle_t* handle); static void close_cb(uv_handle_t* handle);
static uv_buf_t alloc_cb(uv_stream_t* stream, size_t suggested_size) { static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
static char slab[65536]; static char slab[65536];
uv_buf_t buf; uv_buf_t buf;
buf.base = slab; buf.base = slab;

4
deps/uv/test/benchmark-pump.c

@ -41,7 +41,7 @@ static void maybe_connect_some();
static uv_req_t* req_alloc(); static uv_req_t* req_alloc();
static void req_free(uv_req_t* uv_req); static void req_free(uv_req_t* uv_req);
static uv_buf_t buf_alloc(uv_stream_t*, size_t size); static uv_buf_t buf_alloc(uv_handle_t*, size_t size);
static void buf_free(uv_buf_t uv_buf_t); static void buf_free(uv_buf_t uv_buf_t);
@ -337,7 +337,7 @@ typedef struct buf_list_s {
static buf_list_t* buf_freelist = NULL; static buf_list_t* buf_freelist = NULL;
static uv_buf_t buf_alloc(uv_stream_t* stream, size_t size) { static uv_buf_t buf_alloc(uv_handle_t* handle, size_t size) {
buf_list_t* buf; buf_list_t* buf;
buf = buf_freelist; buf = buf_freelist;

2
deps/uv/test/benchmark-spawn.c

@ -69,7 +69,7 @@ static void exit_cb(uv_process_t* process, int exit_status, int term_signal) {
} }
uv_buf_t on_alloc(uv_stream_t* tcp, size_t suggested_size) { uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) {
uv_buf_t buf; uv_buf_t buf;
buf.base = output + output_used; buf.base = output + output_used;
buf.len = OUTPUT_SIZE - output_used; buf.len = OUTPUT_SIZE - output_used;

247
deps/uv/test/benchmark-udp-packet-storm.c

@ -0,0 +1,247 @@
/* 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 "task.h"
#include "uv.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EXPECTED "RANG TANG DING DONG I AM THE JAPANESE SANDMAN" /* "Take eight!" */
#define TEST_DURATION 5000 /* ms */
#define MAX_SENDERS 1000
#define MAX_RECEIVERS 1000
#define BASE_PORT 12345
#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
static int n_senders_;
static int n_receivers_;
static uv_udp_t senders[MAX_SENDERS];
static uv_udp_t receivers[MAX_RECEIVERS];
static uv_buf_t bufs[5];
static int send_cb_called;
static int recv_cb_called;
static int close_cb_called;
static int stopping = 0;
typedef struct {
struct sockaddr_in addr;
} sender_state_t;
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
static char slab[65536];
ASSERT(suggested_size <= sizeof slab);
return uv_buf_init(slab, sizeof slab);
}
static void send_cb(uv_udp_send_t* req, int status) {
sender_state_t* ss;
int r;
if (stopping) {
return;
}
ASSERT(req != NULL);
ASSERT(status == 0);
ss = req->data;
r = uv_udp_send(req, req->handle, bufs, ARRAY_SIZE(bufs), ss->addr, send_cb);
ASSERT(r == 0);
req->data = ss;
send_cb_called++;
}
static void recv_cb(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
if (nread == 0)
return;
if (nread == -1) {
ASSERT(uv_last_error().code == UV_EINTR); /* FIXME change error code */
return;
}
ASSERT(addr->sa_family == AF_INET);
ASSERT(!memcmp(buf.base, EXPECTED, nread));
recv_cb_called++;
}
static void close_cb(uv_handle_t* handle) {
ASSERT(handle != NULL);
close_cb_called++;
}
static void timeout_cb(uv_timer_t* timer, int status) {
int i;
stopping = 1;
for (i = 0; i < n_senders_; i++)
uv_close((uv_handle_t*)&senders[i], close_cb);
for (i = 0; i < n_receivers_; i++)
uv_close((uv_handle_t*)&receivers[i], close_cb);
}
static int do_packet_storm(int n_senders, int n_receivers) {
uv_timer_t timeout;
sender_state_t *ss;
uv_udp_send_t* req;
uv_udp_t* handle;
int i;
int r;
ASSERT(n_senders <= MAX_SENDERS);
ASSERT(n_receivers <= MAX_RECEIVERS);
uv_init();
n_senders_ = n_senders;
n_receivers_ = n_receivers;
r = uv_timer_init(&timeout);
ASSERT(r == 0);
r = uv_timer_start(&timeout, timeout_cb, TEST_DURATION, 0);
ASSERT(r == 0);
/* Timer should not keep loop alive. */
uv_unref();
for (i = 0; i < n_receivers; i++) {
struct sockaddr_in addr;
handle = &receivers[i];
r = uv_udp_init(handle);
ASSERT(r == 0);
addr = uv_ip4_addr("0.0.0.0", BASE_PORT + i);
r = uv_udp_bind(handle, addr, 0);
ASSERT(r == 0);
r = uv_udp_recv_start(handle, alloc_cb, recv_cb);
ASSERT(r == 0);
}
bufs[0] = uv_buf_init(EXPECTED + 0, 10);
bufs[1] = uv_buf_init(EXPECTED + 10, 10);
bufs[2] = uv_buf_init(EXPECTED + 20, 10);
bufs[3] = uv_buf_init(EXPECTED + 30, 10);
bufs[4] = uv_buf_init(EXPECTED + 40, 5);
for (i = 0; i < n_senders; i++) {
handle = &senders[i];
r = uv_udp_init(handle);
ASSERT(r == 0);
req = malloc(sizeof(*req) + sizeof(*ss));
ss = (void*)(req + 1);
ss->addr = uv_ip4_addr("127.0.0.1", BASE_PORT + (i % n_receivers));
r = uv_udp_send(req, handle, bufs, ARRAY_SIZE(bufs), ss->addr, send_cb);
ASSERT(r == 0);
req->data = ss;
}
uv_run();
printf("udp_packet_storm_%dv%d: %.0f/s received, %.0f/s sent\n",
n_receivers,
n_senders,
recv_cb_called / (TEST_DURATION / 1000.0),
send_cb_called / (TEST_DURATION / 1000.0));
return 0;
}
BENCHMARK_IMPL(udp_packet_storm_1v1) {
return do_packet_storm(1, 1);
}
BENCHMARK_IMPL(udp_packet_storm_1v10) {
return do_packet_storm(1, 10);
}
BENCHMARK_IMPL(udp_packet_storm_1v100) {
return do_packet_storm(1, 100);
}
BENCHMARK_IMPL(udp_packet_storm_1v1000) {
return do_packet_storm(1, 1000);
}
BENCHMARK_IMPL(udp_packet_storm_10v10) {
return do_packet_storm(10, 10);
}
BENCHMARK_IMPL(udp_packet_storm_10v100) {
return do_packet_storm(10, 100);
}
BENCHMARK_IMPL(udp_packet_storm_10v1000) {
return do_packet_storm(10, 1000);
}
BENCHMARK_IMPL(udp_packet_storm_100v100) {
return do_packet_storm(100, 100);
}
BENCHMARK_IMPL(udp_packet_storm_100v1000) {
return do_packet_storm(100, 1000);
}
BENCHMARK_IMPL(udp_packet_storm_1000v1000) {
return do_packet_storm(1000, 1000);
}

2
deps/uv/test/dns-server.c

@ -247,7 +247,7 @@ static void on_close(uv_handle_t* peer) {
} }
static uv_buf_t buf_alloc(uv_stream_t* handle, size_t suggested_size) { static uv_buf_t buf_alloc(uv_handle_t* handle, size_t suggested_size) {
uv_buf_t buf; uv_buf_t buf;
buf.base = (char*) malloc(suggested_size); buf.base = (char*) malloc(suggested_size);
buf.len = suggested_size; buf.len = suggested_size;

2
deps/uv/test/echo-server.c

@ -123,7 +123,7 @@ static void on_close(uv_handle_t* peer) {
} }
static uv_buf_t echo_alloc(uv_stream_t* handle, size_t suggested_size) { static uv_buf_t echo_alloc(uv_handle_t* handle, size_t suggested_size) {
return uv_buf_init(malloc(suggested_size), suggested_size); return uv_buf_init(malloc(suggested_size), suggested_size);
} }

2
deps/uv/test/test-callback-stack.c

@ -45,7 +45,7 @@ static int bytes_received = 0;
static int shutdown_cb_called = 0; static int shutdown_cb_called = 0;
static uv_buf_t alloc_cb(uv_stream_t* tcp, size_t size) { static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
uv_buf_t buf; uv_buf_t buf;
buf.len = size; buf.len = size;
buf.base = (char*) malloc(size); buf.base = (char*) malloc(size);

2
deps/uv/test/test-delayed-accept.c

@ -30,7 +30,7 @@ static int close_cb_called = 0;
static int connect_cb_called = 0; static int connect_cb_called = 0;
static uv_buf_t alloc_cb(uv_stream_t* tcp, size_t size) { static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
uv_buf_t buf; uv_buf_t buf;
buf.base = (char*)malloc(size); buf.base = (char*)malloc(size);
buf.len = size; buf.len = size;

8
deps/uv/test/test-getsockname.c

@ -33,7 +33,7 @@ static uv_connect_t connect_req;
static uv_tcp_t tcpServer; static uv_tcp_t tcpServer;
static uv_buf_t alloc(uv_stream_t* handle, size_t suggested_size) { static uv_buf_t alloc(uv_handle_t* handle, size_t suggested_size) {
uv_buf_t buf; uv_buf_t buf;
buf.base = (char*) malloc(suggested_size); buf.base = (char*) malloc(suggested_size);
buf.len = suggested_size; buf.len = suggested_size;
@ -89,7 +89,7 @@ static void on_connection(uv_stream_t* server, int status) {
r = uv_accept(server, (uv_stream_t*)handle); r = uv_accept(server, (uv_stream_t*)handle);
ASSERT(r == 0); ASSERT(r == 0);
status = uv_getsockname((uv_tcp_t*)handle, &sockname, &namelen); status = uv_getsockname(handle, &sockname, &namelen);
if (status != 0) { if (status != 0) {
fprintf(stderr, "uv_getsockname error (accepted) %d\n", uv_last_error().code); fprintf(stderr, "uv_getsockname error (accepted) %d\n", uv_last_error().code);
} }
@ -110,7 +110,7 @@ static void on_connect(uv_connect_t* req, int status) {
ASSERT(status == 0); ASSERT(status == 0);
r = uv_getsockname(&tcp, &sockname, &namelen); r = uv_getsockname((uv_handle_t*)&tcp, &sockname, &namelen);
if (r != 0) { if (r != 0) {
fprintf(stderr, "uv_getsockname error (connector) %d\n", uv_last_error().code); fprintf(stderr, "uv_getsockname error (connector) %d\n", uv_last_error().code);
} }
@ -147,7 +147,7 @@ static int tcp_listener(int port) {
return 1; return 1;
} }
r = uv_getsockname(&tcpServer, &sockname, &namelen); r = uv_getsockname((uv_handle_t*)&tcpServer, &sockname, &namelen);
if (r != 0) { if (r != 0) {
fprintf(stderr, "uv_getsockname error (listening) %d\n", uv_last_error().code); fprintf(stderr, "uv_getsockname error (listening) %d\n", uv_last_error().code);
} }

9
deps/uv/test/test-list.h

@ -36,6 +36,10 @@ TEST_DECLARE (tcp_bind6_error_addrnotavail)
TEST_DECLARE (tcp_bind6_error_fault) TEST_DECLARE (tcp_bind6_error_fault)
TEST_DECLARE (tcp_bind6_error_inval) TEST_DECLARE (tcp_bind6_error_inval)
TEST_DECLARE (tcp_bind6_localhost_ok) TEST_DECLARE (tcp_bind6_localhost_ok)
TEST_DECLARE (udp_send_and_recv)
TEST_DECLARE (udp_dgram_too_big)
TEST_DECLARE (udp_dual_stack)
TEST_DECLARE (udp_ipv6_only)
TEST_DECLARE (pipe_bind_error_addrinuse) TEST_DECLARE (pipe_bind_error_addrinuse)
TEST_DECLARE (pipe_bind_error_addrnotavail) TEST_DECLARE (pipe_bind_error_addrnotavail)
TEST_DECLARE (pipe_bind_error_inval) TEST_DECLARE (pipe_bind_error_inval)
@ -106,6 +110,11 @@ TASK_LIST_START
TEST_ENTRY (tcp_bind6_error_inval) TEST_ENTRY (tcp_bind6_error_inval)
TEST_ENTRY (tcp_bind6_localhost_ok) TEST_ENTRY (tcp_bind6_localhost_ok)
TEST_ENTRY (udp_send_and_recv)
TEST_ENTRY (udp_dgram_too_big)
TEST_ENTRY (udp_dual_stack)
TEST_ENTRY (udp_ipv6_only)
TEST_ENTRY (pipe_bind_error_addrinuse) TEST_ENTRY (pipe_bind_error_addrinuse)
TEST_ENTRY (pipe_bind_error_addrnotavail) TEST_ENTRY (pipe_bind_error_addrnotavail)
TEST_ENTRY (pipe_bind_error_inval) TEST_ENTRY (pipe_bind_error_inval)

2
deps/uv/test/test-ping-pong.c

@ -51,7 +51,7 @@ typedef struct {
void pinger_try_read(pinger_t* pinger); void pinger_try_read(pinger_t* pinger);
static uv_buf_t alloc_cb(uv_stream_t* tcp, size_t size) { static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
uv_buf_t buf; uv_buf_t buf;
buf.base = (char*)malloc(size); buf.base = (char*)malloc(size);
buf.len = size; buf.len = size;

2
deps/uv/test/test-shutdown-eof.c

@ -39,7 +39,7 @@ static int called_timer_close_cb;
static int called_timer_cb; static int called_timer_cb;
static uv_buf_t alloc_cb(uv_stream_t* tcp, size_t size) { static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
uv_buf_t buf; uv_buf_t buf;
buf.base = (char*)malloc(size); buf.base = (char*)malloc(size);
buf.len = size; buf.len = size;

2
deps/uv/test/test-spawn.c

@ -66,7 +66,7 @@ static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
} }
uv_buf_t on_alloc(uv_stream_t* tcp, size_t suggested_size) { uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) {
uv_buf_t buf; uv_buf_t buf;
buf.base = output + output_used; buf.base = output + output_used;
buf.len = OUTPUT_SIZE - output_used; buf.len = OUTPUT_SIZE - output_used;

2
deps/uv/test/test-tcp-writealot.c

@ -45,7 +45,7 @@ static int bytes_received = 0;
static int bytes_received_done = 0; static int bytes_received_done = 0;
static uv_buf_t alloc_cb(uv_stream_t* tcp, size_t size) { static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
uv_buf_t buf; uv_buf_t buf;
buf.base = (char*)malloc(size); buf.base = (char*)malloc(size);
buf.len = size; buf.len = size;

88
deps/uv/test/test-udp-dgram-too-big.c

@ -0,0 +1,88 @@
/* 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>
#include <string.h>
#define CHECK_HANDLE(handle) \
ASSERT((uv_udp_t*)(handle) == &handle_)
#define CHECK_REQ(req) \
ASSERT((req) == &req_);
static uv_udp_t handle_;
static uv_udp_send_t req_;
static int send_cb_called;
static int close_cb_called;
static void close_cb(uv_handle_t* handle) {
CHECK_HANDLE(handle);
close_cb_called++;
}
static void send_cb(uv_udp_send_t* req, int status) {
CHECK_REQ(req);
CHECK_HANDLE(req->handle);
ASSERT(status == -1);
ASSERT(uv_last_error().code == UV_EMSGSIZE);
uv_close((uv_handle_t*)req->handle, close_cb);
send_cb_called++;
}
TEST_IMPL(udp_dgram_too_big) {
char dgram[65536]; /* 64K MTU is unlikely, even on localhost */
struct sockaddr_in addr;
uv_buf_t buf;
int r;
memset(dgram, 42, sizeof dgram); /* silence valgrind */
uv_init();
r = uv_udp_init(&handle_);
ASSERT(r == 0);
buf = uv_buf_init(dgram, sizeof dgram);
addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
r = uv_udp_send(&req_, &handle_, &buf, 1, addr, send_cb);
ASSERT(r == 0);
ASSERT(close_cb_called == 0);
ASSERT(send_cb_called == 0);
uv_run();
ASSERT(send_cb_called == 1);
ASSERT(close_cb_called == 1);
return 0;
}

141
deps/uv/test/test-udp-ipv6-only.c

@ -0,0 +1,141 @@
/* 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>
#include <string.h>
#define CHECK_HANDLE(handle) \
ASSERT((uv_udp_t*)(handle) == &server1 \
|| (uv_udp_t*)(handle) == &server2 \
|| (uv_udp_t*)(handle) == &client)
#define CHECK_REQ(req) \
ASSERT((req) == &req_);
static uv_udp_t client;
static uv_udp_t server1;
static uv_udp_t server2;
static uv_udp_send_t req_;
static int send_cb_called;
static int recv_cb_called;
static int close_cb_called;
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
static char slab[65536];
CHECK_HANDLE(handle);
return uv_buf_init(slab, sizeof slab);
}
static void close_cb(uv_handle_t* handle) {
CHECK_HANDLE(handle);
close_cb_called++;
}
static void send_cb(uv_udp_send_t* req, int status) {
CHECK_REQ(req);
CHECK_HANDLE(req->handle);
ASSERT(status == 0);
send_cb_called++;
}
static void ipv4_recv_cb(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
CHECK_HANDLE(handle);
ASSERT(nread >= 0);
uv_close((uv_handle_t*)&server1, close_cb);
uv_close((uv_handle_t*)&server2, close_cb);
uv_close((uv_handle_t*)&client, close_cb);
recv_cb_called++;
}
static void ipv6_recv_cb(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
ASSERT(0 && "this function should not have been called");
}
TEST_IMPL(udp_ipv6_only) {
struct sockaddr_in6 addr6;
struct sockaddr_in addr;
uv_buf_t buf;
int r;
uv_init();
addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
addr6 = uv_ip6_addr(":::0", TEST_PORT);
r = uv_udp_init(&server1);
ASSERT(r == 0);
r = uv_udp_bind(&server1, addr, 0);
ASSERT(r == 0);
r = uv_udp_recv_start(&server1, alloc_cb, ipv4_recv_cb);
ASSERT(r == 0);
r = uv_udp_init(&server2);
ASSERT(r == 0);
r = uv_udp_bind6(&server2, addr6, UV_UDP_IPV6ONLY);
ASSERT(r == 0);
r = uv_udp_recv_start(&server2, alloc_cb, ipv6_recv_cb);
ASSERT(r == 0);
r = uv_udp_init(&client);
ASSERT(r == 0);
buf = uv_buf_init("PING", 4);
/* This should fail but still call send_cb(). */
r = uv_udp_send(&req_, &client, &buf, 1, addr, send_cb);
ASSERT(r == 0);
ASSERT(close_cb_called == 0);
ASSERT(send_cb_called == 0);
ASSERT(recv_cb_called == 0);
uv_run();
ASSERT(recv_cb_called == 1);
ASSERT(send_cb_called == 1);
ASSERT(close_cb_called == 3);
return 0;
}

158
deps/uv/test/test-udp-ipv6.c

@ -0,0 +1,158 @@
/* 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>
#include <string.h>
#define CHECK_HANDLE(handle) \
ASSERT((uv_udp_t*)(handle) == &server \
|| (uv_udp_t*)(handle) == &client \
|| (uv_timer_t*)(handle) == &timeout)
#define CHECK_REQ(req) \
ASSERT((req) == &req_);
static uv_udp_t client;
static uv_udp_t server;
static uv_udp_send_t req_;
static uv_timer_t timeout;
static int send_cb_called;
static int recv_cb_called;
static int close_cb_called;
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
static char slab[65536];
CHECK_HANDLE(handle);
return uv_buf_init(slab, sizeof slab);
}
static void close_cb(uv_handle_t* handle) {
CHECK_HANDLE(handle);
close_cb_called++;
}
static void send_cb(uv_udp_send_t* req, int status) {
CHECK_REQ(req);
CHECK_HANDLE(req->handle);
ASSERT(status == 0);
send_cb_called++;
}
static void ipv6_recv_fail(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
ASSERT(0 && "this function should not have been called");
}
static void ipv6_recv_ok(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
CHECK_HANDLE(handle);
ASSERT(nread >= 0);
if (nread)
recv_cb_called++;
}
static void timeout_cb(uv_timer_t* timer, int status) {
uv_close((uv_handle_t*)&server, close_cb);
uv_close((uv_handle_t*)&client, close_cb);
uv_close((uv_handle_t*)&timeout, close_cb);
}
static void do_test(uv_udp_recv_cb recv_cb, int bind_flags) {
struct sockaddr_in6 addr6;
struct sockaddr_in addr;
uv_buf_t buf;
int r;
uv_init();
addr6 = uv_ip6_addr("::0", TEST_PORT);
r = uv_udp_init(&server);
ASSERT(r == 0);
r = uv_udp_bind6(&server, addr6, bind_flags);
ASSERT(r == 0);
r = uv_udp_recv_start(&server, alloc_cb, recv_cb);
ASSERT(r == 0);
r = uv_udp_init(&client);
ASSERT(r == 0);
buf = uv_buf_init("PING", 4);
addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
r = uv_udp_send(&req_, &client, &buf, 1, addr, send_cb);
ASSERT(r == 0);
r = uv_timer_init(&timeout);
ASSERT(r == 0);
r = uv_timer_start(&timeout, timeout_cb, 500, 0);
ASSERT(r == 0);
ASSERT(close_cb_called == 0);
ASSERT(send_cb_called == 0);
ASSERT(recv_cb_called == 0);
uv_run();
ASSERT(close_cb_called == 3);
}
TEST_IMPL(udp_dual_stack) {
do_test(ipv6_recv_ok, 0);
ASSERT(recv_cb_called == 1);
ASSERT(send_cb_called == 1);
return 0;
}
TEST_IMPL(udp_ipv6_only) {
do_test(ipv6_recv_fail, UV_UDP_IPV6ONLY);
ASSERT(recv_cb_called == 0);
ASSERT(send_cb_called == 1);
return 0;
}

210
deps/uv/test/test-udp-send-and-recv.c

@ -0,0 +1,210 @@
/* 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>
#include <string.h>
#define CHECK_HANDLE(handle) \
ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client)
static uv_udp_t server;
static uv_udp_t client;
static int cl_send_cb_called;
static int cl_recv_cb_called;
static int sv_send_cb_called;
static int sv_recv_cb_called;
static int close_cb_called;
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
static char slab[65536];
CHECK_HANDLE(handle);
ASSERT(suggested_size <= sizeof slab);
return uv_buf_init(slab, sizeof slab);
}
static void close_cb(uv_handle_t* handle) {
CHECK_HANDLE(handle);
close_cb_called++;
}
static void cl_recv_cb(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
CHECK_HANDLE(handle);
ASSERT(flags == 0);
if (nread < 0) {
ASSERT(0 && "unexpected error");
}
if (nread == 0) {
/* Returning unused buffer */
/* Don't count towards cl_recv_cb_called */
ASSERT(addr == NULL);
return;
}
ASSERT(addr != NULL);
ASSERT(nread == 4);
ASSERT(!memcmp("PONG", buf.base, nread));
cl_recv_cb_called++;
uv_close((uv_handle_t*) handle, close_cb);
}
static void cl_send_cb(uv_udp_send_t* req, int status) {
int r;
ASSERT(req != NULL);
ASSERT(status == 0);
CHECK_HANDLE(req->handle);
r = uv_udp_recv_start(req->handle, alloc_cb, cl_recv_cb);
ASSERT(r == 0);
cl_send_cb_called++;
}
static void sv_send_cb(uv_udp_send_t* req, int status) {
ASSERT(req != NULL);
ASSERT(status == 0);
CHECK_HANDLE(req->handle);
uv_close((uv_handle_t*) req->handle, close_cb);
free(req);
sv_send_cb_called++;
}
static void sv_recv_cb(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
uv_udp_send_t* req;
int r;
if (nread < 0) {
ASSERT(0 && "unexpected error");
}
if (nread == 0) {
/* Returning unused buffer */
/* Don't count towards sv_recv_cb_called */
ASSERT(addr == NULL);
return;
}
CHECK_HANDLE(handle);
ASSERT(flags == 0);
ASSERT(addr != NULL);
ASSERT(nread == 4);
ASSERT(!memcmp("PING", buf.base, nread));
/* FIXME? `uv_udp_recv_stop` does what it says: recv_cb is not called
* anymore. That's problematic because the read buffer won't be returned
* either... Not sure I like that but it's consistent with `uv_read_stop`.
*/
r = uv_udp_recv_stop(handle);
ASSERT(r == 0);
req = malloc(sizeof *req);
ASSERT(req != NULL);
buf = uv_buf_init("PONG", 4);
r = uv_udp_send(req,
handle,
&buf,
1,
*(struct sockaddr_in*)addr,
sv_send_cb);
ASSERT(r == 0);
sv_recv_cb_called++;
}
TEST_IMPL(udp_send_and_recv) {
struct sockaddr_in addr;
uv_udp_send_t req;
uv_buf_t buf;
int r;
addr = uv_ip4_addr("0.0.0.0", TEST_PORT);
uv_init();
r = uv_udp_init(&server);
ASSERT(r == 0);
r = uv_udp_bind(&server, addr, 0);
ASSERT(r == 0);
r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb);
ASSERT(r == 0);
addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
r = uv_udp_init(&client);
ASSERT(r == 0);
/* client sends "PING", expects "PONG" */
buf = uv_buf_init("PING", 4);
r = uv_udp_send(&req, &client, &buf, 1, addr, cl_send_cb);
ASSERT(r == 0);
ASSERT(close_cb_called == 0);
ASSERT(cl_send_cb_called == 0);
ASSERT(cl_recv_cb_called == 0);
ASSERT(sv_send_cb_called == 0);
ASSERT(sv_recv_cb_called == 0);
uv_run();
ASSERT(cl_send_cb_called == 1);
ASSERT(cl_recv_cb_called == 1);
ASSERT(sv_send_cb_called == 1);
ASSERT(sv_recv_cb_called == 1);
ASSERT(close_cb_called == 2);
return 0;
}

5
deps/uv/uv.gyp

@ -109,6 +109,7 @@
'src/win/stream.c', 'src/win/stream.c',
'src/win/tcp.c', 'src/win/tcp.c',
'src/win/timer.c', 'src/win/timer.c',
'src/win/udp.c',
'src/win/util.c', 'src/win/util.c',
'src/win/winapi.c', 'src/win/winapi.c',
'src/win/winapi.h', 'src/win/winapi.h',
@ -232,6 +233,9 @@
'test/test-tcp-writealot.c', 'test/test-tcp-writealot.c',
'test/test-timer-again.c', 'test/test-timer-again.c',
'test/test-timer.c', 'test/test-timer.c',
'test/test-udp-dgram-too-big.c',
'test/test-udp-ipv6.c',
'test/test-udp-send-and-recv.c',
], ],
'conditions': [ 'conditions': [
[ 'OS=="win"', { [ 'OS=="win"', {
@ -269,6 +273,7 @@
'test/benchmark-pump.c', 'test/benchmark-pump.c',
'test/benchmark-sizes.c', 'test/benchmark-sizes.c',
'test/benchmark-spawn.c', 'test/benchmark-spawn.c',
'test/benchmark-udp-packet-storm.c',
'test/dns-server.c', 'test/dns-server.c',
'test/echo-server.c', 'test/echo-server.c',
'test/run-benchmarks.c', 'test/run-benchmarks.c',

Loading…
Cancel
Save