deps: upgrade to libuv 1.27.0

Notable changes:
- `statx()` is used to retrieve file birth times on
  supported platforms.
- Improved support of running under Windows safe mode.
- Add support for UDP connected sockets. Several functions
  can now return `UV_EBADF` instead of `UV_EINVAL`.
- SunOS support is improved.

PR-URL: https://github.com/nodejs/node/pull/26707
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
cjihrig 2019-03-16 14:38:18 -04:00
parent 04f30e1a7a
commit d6f6d7f854
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
49 changed files with 1146 additions and 200 deletions

2
deps/uv/AUTHORS vendored
View File

@ -369,3 +369,5 @@ Kevin Adler <kadler@us.ibm.com>
Stephen Belanger <admin@stephenbelanger.com>
yeyuanfeng <yeyuanfeng@bytedance.com>
erw7 <erw7.github@gmail.com>
Thomas Karl Pietrowski <thopiekar@gmail.com>
evgley <evgley@gmail.com>

View File

@ -153,6 +153,7 @@ set(uv_test_sources
test/test-tty.c
test/test-udp-alloc-cb-fail.c
test/test-udp-bind.c
test/test-udp-connect.c
test/test-udp-create-socket-early.c
test/test-udp-dgram-too-big.c
test/test-udp-ipv6.c
@ -351,7 +352,8 @@ target_link_libraries(uv_a ${uv_libraries})
if(BUILD_TESTING)
include(CTest)
add_executable(uv_run_tests ${uv_test_sources})
target_compile_definitions(uv_run_tests PRIVATE ${uv_defines})
target_compile_definitions(uv_run_tests
PRIVATE ${uv_defines} USING_UV_SHARED=1)
target_compile_options(uv_run_tests PRIVATE ${uv_cflags})
target_include_directories(uv_run_tests PRIVATE include)
target_link_libraries(uv_run_tests uv ${uv_test_libraries})
@ -383,7 +385,7 @@ if(UNIX)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
install(FILES LICENSE ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

59
deps/uv/ChangeLog vendored
View File

@ -1,3 +1,62 @@
2019.03.17, Version 1.27.0 (Stable), a4fc9a66cc35256dbc4dcd67c910174f05b6daa6
Changes since version 1.26.0:
* doc: describe unix signal handling better (Vladimír Čunát)
* linux: use statx() to obtain file birth time (Ben Noordhuis)
* src: fill sockaddr_in6.sin6_len when it's defined (Santiago Gimeno)
* test: relax uv_hrtime() test assumptions (Ben Noordhuis)
* build: make cmake install LICENSE only once (Thomas Karl Pietrowski)
* bsd: plug uv_fs_event_start() error path fd leak (Ben Noordhuis)
* unix: fix __FreeBSD_kernel__ typo (cjihrig)
* doc: add note about uv_run() not being reentrant (Ben Noordhuis)
* unix, win: make fs-poll close wait for resource cleanup (Anna Henningsen)
* doc: fix typo in uv_thread_options_t definition (Ryan Liptak)
* win: skip winsock initialization in safe mode (evgley)
* unix: refactor getsockname/getpeername methods (Santiago Gimeno)
* win,udp: allow to use uv_udp_open on bound sockets (Santiago Gimeno)
* udp: add support for UDP connected sockets (Santiago Gimeno)
* build: fix uv_test shared uv Windows cmake build (ptlomholt)
* build: add android-configure scripts to EXTRA_DIST (Ben Noordhuis)
* build: add missing header (cjihrig)
* sunos: add perror() output prior to abort() (Andrew Paprocki)
* test,sunos: disable UV_DISCONNECT handling (Andrew Paprocki)
* sunos: disable __attribute__((unused)) (Andrew Paprocki)
* test,sunos: use unistd.h code branch (Andrew Paprocki)
* build,sunos: better handling of non-GCC compiler (Andrew Paprocki)
* test,sunos: fix statement not reached warnings (Andrew Paprocki)
* sunos: fix argument/prototype mismatch in atomics (Andrew Paprocki)
* test,sunos: test-ipc.c lacks newline at EOF (Andrew Paprocki)
* test: change spawn_stdin_stdout return to void (Andrew Paprocki)
* test: remove call to floor() in test driver (Andrew Paprocki)
2019.02.11, Version 1.26.0 (Stable), 8669d8d3e93cddb62611b267ef62a3ddb5ba3ca0
Changes since version 1.25.0:

24
deps/uv/Makefile.am vendored
View File

@ -32,6 +32,7 @@ libuv_la_LDFLAGS = -no-undefined -version-info 1:0:0
libuv_la_SOURCES = src/fs-poll.c \
src/heap-inl.h \
src/idna.c \
src/idna.h \
src/inet.c \
src/queue.h \
src/strscpy.c \
@ -44,10 +45,12 @@ libuv_la_SOURCES = src/fs-poll.c \
src/version.c
if SUNOS
if GCC
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
# on other platforms complain that the argument is unused during compilation.
libuv_la_CFLAGS += -pthreads
endif
endif
if WINNT
@ -121,11 +124,13 @@ EXTRA_DIST = test/fixtures/empty_file \
docs \
img \
samples \
android-configure \
android-configure-arm \
android-configure-arm64 \
android-configure-x86 \
android-configure-x86_64 \
CONTRIBUTING.md \
LICENSE \
README.md \
checksparse.sh \
vcbuild.bat \
common.gypi \
gyp_uv.py \
@ -138,14 +143,20 @@ check_PROGRAMS = test/run-tests
if OS390
test_run_tests_CFLAGS =
else
if GCC
test_run_tests_CFLAGS = -Wno-long-long
else
test_run_tests_CFLAGS =
endif
endif
if SUNOS
if GCC
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
# on other platforms complain that the argument is unused during compilation.
test_run_tests_CFLAGS += -pthreads
endif
endif
test_run_tests_LDFLAGS =
test_run_tests_SOURCES = test/blackhole-server.c \
@ -281,6 +292,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-tty.c \
test/test-udp-alloc-cb-fail.c \
test/test-udp-bind.c \
test/test-udp-connect.c \
test/test-udp-create-socket-early.c \
test/test-udp-dgram-too-big.c \
test/test-udp-ipv6.c \
@ -320,7 +332,9 @@ test_run_tests_CFLAGS += -D_GNU_SOURCE
endif
if SUNOS
test_run_tests_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
test_run_tests_CFLAGS += -D__EXTENSIONS__ \
-D_XOPEN_SOURCE=500 \
-D_REENTRANT
endif
if OS390
@ -458,7 +472,9 @@ endif
if SUNOS
uvinclude_HEADERS += include/uv/sunos.h
libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
libuv_la_CFLAGS += -D__EXTENSIONS__ \
-D_XOPEN_SOURCE=500 \
-D_REENTRANT
libuv_la_SOURCES += src/unix/no-proctitle.c \
src/unix/sunos.c
endif

2
deps/uv/README.md vendored
View File

@ -312,7 +312,7 @@ $ make -C out
The default API level is 24, but a different one can be selected as follows:
```bash
$ source ./android-configure ~/android-ndk-r15b gyp 21
$ source ./android-configure-arm ~/android-ndk-r15b gyp 21
$ make -C out
```

21
deps/uv/configure.ac vendored
View File

@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
AC_INIT([libuv], [1.26.0], [https://github.com/libuv/libuv/issues])
AC_INIT([libuv], [1.27.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
@ -24,16 +24,18 @@ AC_ENABLE_SHARED
AC_ENABLE_STATIC
AC_PROG_CC
AM_PROG_CC_C_O
AS_IF([AS_CASE([$host_os],[openedition*], [false], [true])], [
CC_CHECK_CFLAGS_APPEND([-pedantic])
])
CC_FLAG_VISIBILITY #[-fvisibility=hidden]
CC_CHECK_CFLAGS_APPEND([-g])
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
CC_CHECK_CFLAGS_APPEND([-Wall])
CC_CHECK_CFLAGS_APPEND([-Wextra])
CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter])
CC_CHECK_CFLAGS_APPEND([-Wstrict-prototypes])
AS_IF([test "x$GCC" = xyes], [
AS_IF([AS_CASE([$host_os], [openedition*], [false], [true])], [
CC_CHECK_CFLAGS_APPEND([-pedantic])
])
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
CC_CHECK_CFLAGS_APPEND([-Wall])
CC_CHECK_CFLAGS_APPEND([-Wextra])
CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter])
CC_CHECK_CFLAGS_APPEND([-Wstrict-prototypes])
])
# AM_PROG_AR is not available in automake v0.11 but it's essential in v0.12.
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
# autoconf complains if AC_PROG_LIBTOOL precedes AM_PROG_AR.
@ -50,6 +52,7 @@ AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_LIB([sendfile], [sendfile])
AC_CHECK_LIB([socket], [socket])
AC_SYS_LARGEFILE
AM_CONDITIONAL([GCC], [AS_IF([test "x$GCC" = xyes], [true], [false])])
AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])])
AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])])
AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false])])

View File

@ -107,6 +107,8 @@ API
or requests left), or non-zero if more callbacks are expected (meaning
you should run the event loop again sometime in the future).
:c:func:`uv_run` is not reentrant. It must not be called from a callback.
.. c:function:: int uv_loop_alive(const uv_loop_t* loop)
Returns non-zero if there are referenced active handles, active

View File

@ -6,7 +6,10 @@
Signal handles implement Unix style signal handling on a per-event loop bases.
Reception of some signals is emulated on Windows:
Windows notes
-------------
Reception of some signals is emulated:
* SIGINT is normally delivered when the user presses CTRL+C. However, like
on Unix, it is not generated when terminal raw mode is enabled.
@ -24,13 +27,22 @@ Reception of some signals is emulated on Windows:
* Calls to raise() or abort() to programmatically raise a signal are
not detected by libuv; these will not trigger a signal watcher.
.. note::
On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads library to
manage threads. Installing watchers for those signals will lead to unpredictable behavior
and is strongly discouraged. Future versions of libuv may simply reject them.
.. versionchanged:: 1.15.0 SIGWINCH support on Windows was improved.
Unix notes
----------
* SIGKILL and SIGSTOP are impossible to catch.
* Handling SIGBUS, SIGFPE, SIGILL or SIGSEGV via libuv results into undefined behavior.
* SIGABRT will not be caught by libuv if generated by `abort()`, e.g. through `assert()`.
* On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads library to
manage threads. Installing watchers for those signals will lead to unpredictable behavior
and is strongly discouraged. Future versions of libuv may simply reject them.
Data types
----------

View File

@ -61,13 +61,13 @@ Threads
::
typedef struct uv_process_options_s {
typedef struct uv_thread_options_s {
enum {
UV_THREAD_NO_FLAGS = 0x00,
UV_THREAD_HAS_STACK_SIZE = 0x01
} flags;
size_t stack_size;
} uv_process_options_t;
} uv_thread_options_t;
More fields may be added to this struct at any time, so its exact
layout and size should not be relied upon.

View File

@ -150,6 +150,44 @@ API
:returns: 0 on success, or an error code < 0 on failure.
.. c:function:: int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr)
Associate the UDP handle to a remote address and port, so every
message sent by this handle is automatically sent to that destination.
Calling this function with a `NULL` `addr` disconnects the handle.
Trying to call `uv_udp_connect()` on an already connected handle will result
in an `UV_EISCONN` error. Trying to disconnect a handle that is not
connected will return an `UV_ENOTCONN` error.
:param handle: UDP handle. Should have been initialized with
:c:func:`uv_udp_init`.
:param addr: `struct sockaddr_in` or `struct sockaddr_in6`
with the address and port to associate to.
:returns: 0 on success, or an error code < 0 on failure.
.. versionadded:: 1.27.0
.. c:function:: int uv_udp_getpeername(const uv_udp_t* handle, struct sockaddr* name, int* namelen)
Get the remote IP and port of the UDP handle on connected UDP handles.
On unconnected handles, it returns `UV_ENOTCONN`.
:param handle: UDP handle. Should have been initialized with
:c:func:`uv_udp_init` and bound.
:param name: Pointer to the structure to be filled with the address data.
In order to support IPv4 and IPv6 `struct sockaddr_storage` should be
used.
:param namelen: On input it indicates the data of the `name` field. On
output it indicates how much of it was filled.
:returns: 0 on success, or an error code < 0 on failure
.. versionadded:: 1.27.0
.. c:function:: int uv_udp_getsockname(const uv_udp_t* handle, struct sockaddr* name, int* namelen)
Get the local IP and port of the UDP handle.
@ -247,6 +285,12 @@ API
(``0.0.0.0`` or ``::``) it will be changed to point to ``localhost``.
This is done to match the behavior of Linux systems.
For connected UDP handles, `addr` must be set to `NULL`, otherwise it will
return `UV_EISCONN` error.
For connectionless UDP handles, `addr` cannot be `NULL`, otherwise it will
return `UV_EDESTADDRREQ` error.
:param req: UDP request handle. Need not be initialized.
:param handle: UDP handle. Should have been initialized with
@ -266,15 +310,25 @@ API
.. versionchanged:: 1.19.0 added ``0.0.0.0`` and ``::`` to ``localhost``
mapping
.. versionchanged:: 1.27.0 added support for connected sockets
.. c:function:: int uv_udp_try_send(uv_udp_t* handle, const uv_buf_t bufs[], unsigned int nbufs, const struct sockaddr* addr)
Same as :c:func:`uv_udp_send`, but won't queue a send request if it can't
be completed immediately.
For connected UDP handles, `addr` must be set to `NULL`, otherwise it will
return `UV_EISCONN` error.
For connectionless UDP handles, `addr` cannot be `NULL`, otherwise it will
return `UV_EDESTADDRREQ` error.
:returns: >= 0: number of bytes sent (it matches the given buffer size).
< 0: negative error code (``UV_EAGAIN`` is returned when the message
can't be sent immediately).
.. versionchanged:: 1.27.0 added support for connected sockets
.. c:function:: int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, uv_udp_recv_cb recv_cb)
Prepare for receiving data. If the socket has not previously been bound

View File

@ -630,7 +630,11 @@ UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
const struct sockaddr* addr,
unsigned int flags);
UV_EXTERN int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr);
UV_EXTERN int uv_udp_getpeername(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen);
UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen);

View File

@ -31,7 +31,7 @@
*/
#define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 26
#define UV_VERSION_MINOR 27
#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""

63
deps/uv/src/fs-poll.c vendored
View File

@ -22,12 +22,20 @@
#include "uv.h"
#include "uv-common.h"
#ifdef _WIN32
#include "win/internal.h"
#include "win/handle-inl.h"
#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h))
#else
#include "unix/internal.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
struct poll_ctx {
uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */
uv_fs_poll_t* parent_handle;
int busy_polling;
unsigned int interval;
uint64_t start_time;
@ -36,6 +44,7 @@ struct poll_ctx {
uv_timer_t timer_handle;
uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */
uv_stat_t statbuf;
struct poll_ctx* previous; /* context from previous start()..stop() period */
char path[1]; /* variable length */
};
@ -49,6 +58,7 @@ static uv_stat_t zero_statbuf;
int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) {
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);
handle->poll_ctx = NULL;
return 0;
}
@ -62,7 +72,7 @@ int uv_fs_poll_start(uv_fs_poll_t* handle,
size_t len;
int err;
if (uv__is_active(handle))
if (uv_is_active((uv_handle_t*)handle))
return 0;
loop = handle->loop;
@ -90,6 +100,8 @@ int uv_fs_poll_start(uv_fs_poll_t* handle,
if (err < 0)
goto error;
if (handle->poll_ctx != NULL)
ctx->previous = handle->poll_ctx;
handle->poll_ctx = ctx;
uv__handle_start(handle);
@ -104,19 +116,17 @@ error:
int uv_fs_poll_stop(uv_fs_poll_t* handle) {
struct poll_ctx* ctx;
if (!uv__is_active(handle))
if (!uv_is_active((uv_handle_t*)handle))
return 0;
ctx = handle->poll_ctx;
assert(ctx != NULL);
assert(ctx->parent_handle != NULL);
ctx->parent_handle = NULL;
handle->poll_ctx = NULL;
assert(ctx->parent_handle == handle);
/* Close the timer if it's active. If it's inactive, there's a stat request
* in progress and poll_cb will take care of the cleanup.
*/
if (uv__is_active(&ctx->timer_handle))
if (uv_is_active((uv_handle_t*)&ctx->timer_handle))
uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
uv__handle_stop(handle);
@ -129,7 +139,7 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
struct poll_ctx* ctx;
size_t required_len;
if (!uv__is_active(handle)) {
if (!uv_is_active((uv_handle_t*)handle)) {
*size = 0;
return UV_EINVAL;
}
@ -153,6 +163,9 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
void uv__fs_poll_close(uv_fs_poll_t* handle) {
uv_fs_poll_stop(handle);
if (handle->poll_ctx == NULL)
uv__make_close_pending((uv_handle_t*)handle);
}
@ -173,14 +186,13 @@ static void poll_cb(uv_fs_t* req) {
uv_stat_t* statbuf;
struct poll_ctx* ctx;
uint64_t interval;
uv_fs_poll_t* handle;
ctx = container_of(req, struct poll_ctx, fs_req);
handle = ctx->parent_handle;
if (ctx->parent_handle == NULL) { /* handle has been stopped or closed */
uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
uv_fs_req_cleanup(req);
return;
}
if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle))
goto out;
if (req->result != 0) {
if (ctx->busy_polling != req->result) {
@ -205,7 +217,7 @@ static void poll_cb(uv_fs_t* req) {
out:
uv_fs_req_cleanup(req);
if (ctx->parent_handle == NULL) { /* handle has been stopped by callback */
if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle)) {
uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
return;
}
@ -219,8 +231,27 @@ out:
}
static void timer_close_cb(uv_handle_t* handle) {
uv__free(container_of(handle, struct poll_ctx, timer_handle));
static void timer_close_cb(uv_handle_t* timer) {
struct poll_ctx* ctx;
struct poll_ctx* it;
struct poll_ctx* last;
uv_fs_poll_t* handle;
ctx = container_of(timer, struct poll_ctx, timer_handle);
handle = ctx->parent_handle;
if (ctx == handle->poll_ctx) {
handle->poll_ctx = ctx->previous;
if (handle->poll_ctx == NULL)
uv__make_close_pending((uv_handle_t*)handle);
} else {
for (last = handle->poll_ctx, it = last->previous;
it != ctx;
last = it, it = it->previous) {
assert(last->previous != NULL);
}
last->previous = ctx->previous;
}
uv__free(ctx);
}

View File

@ -49,7 +49,7 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
else
return op4;
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
return atomic_cas_uint(ptr, oldval, newval);
return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval);
#else
return __sync_val_compare_and_swap(ptr, oldval, newval);
#endif
@ -85,7 +85,7 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
else
return op4;
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
return atomic_cas_ulong(ptr, oldval, newval);
return atomic_cas_ulong((ulong_t *)ptr, (ulong_t)oldval, (ulong_t)newval);
#else
return __sync_val_compare_and_swap(ptr, oldval, newval);
#endif

View File

@ -161,7 +161,9 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
case UV_FS_POLL:
uv__fs_poll_close((uv_fs_poll_t*)handle);
break;
/* Poll handles use file system requests, and one of them may still be
* running. The poll code will call uv__make_close_pending() for us. */
return;
case UV_SIGNAL:
uv__signal_close((uv_signal_t*) handle);
@ -1405,3 +1407,25 @@ error:
buffer->machine[0] = '\0';
return r;
}
int uv__getsockpeername(const uv_handle_t* handle,
uv__peersockfunc func,
struct sockaddr* name,
int* namelen) {
socklen_t socklen;
uv_os_fd_t fd;
int r;
r = uv_fileno(handle, &fd);
if (r < 0)
return r;
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (func(fd, name, &socklen))
return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
}

82
deps/uv/src/unix/fs.c vendored
View File

@ -47,7 +47,7 @@
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel_) || \
defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
# define HAVE_PREADV 1
@ -1053,10 +1053,82 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
}
static int uv__fs_statx(int fd,
const char* path,
int is_fstat,
int is_lstat,
uv_stat_t* buf) {
STATIC_ASSERT(UV_ENOSYS != -1);
#ifdef __linux__
static int no_statx;
struct uv__statx statxbuf;
int dirfd;
int flags;
int mode;
int rc;
if (no_statx)
return UV_ENOSYS;
dirfd = AT_FDCWD;
flags = 0; /* AT_STATX_SYNC_AS_STAT */
mode = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */
if (is_fstat) {
dirfd = fd;
flags |= 0x1000; /* AT_EMPTY_PATH */
}
if (is_lstat)
flags |= AT_SYMLINK_NOFOLLOW;
rc = uv__statx(dirfd, path, flags, mode, &statxbuf);
if (rc == -1) {
/* EPERM happens when a seccomp filter rejects the system call.
* Has been observed with libseccomp < 2.3.3 and docker < 18.04.
*/
if (errno != EINVAL && errno != EPERM && errno != ENOSYS)
return -1;
no_statx = 1;
return UV_ENOSYS;
}
buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor;
buf->st_mode = statxbuf.stx_mode;
buf->st_nlink = statxbuf.stx_nlink;
buf->st_uid = statxbuf.stx_uid;
buf->st_gid = statxbuf.stx_gid;
buf->st_rdev = statxbuf.stx_rdev_major;
buf->st_ino = statxbuf.stx_ino;
buf->st_size = statxbuf.stx_size;
buf->st_blksize = statxbuf.stx_blksize;
buf->st_blocks = statxbuf.stx_blocks;
buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec;
buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec;
buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec;
buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec;
buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec;
buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec;
buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec;
buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec;
return 0;
#else
return UV_ENOSYS;
#endif /* __linux__ */
}
static int uv__fs_stat(const char *path, uv_stat_t *buf) {
struct stat pbuf;
int ret;
ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 0, buf);
if (ret != UV_ENOSYS)
return ret;
ret = stat(path, &pbuf);
if (ret == 0)
uv__to_stat(&pbuf, buf);
@ -1069,6 +1141,10 @@ static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
struct stat pbuf;
int ret;
ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 1, buf);
if (ret != UV_ENOSYS)
return ret;
ret = lstat(path, &pbuf);
if (ret == 0)
uv__to_stat(&pbuf, buf);
@ -1081,6 +1157,10 @@ static int uv__fs_fstat(int fd, uv_stat_t *buf) {
struct stat pbuf;
int ret;
ret = uv__fs_statx(fd, "", /* is_fstat */ 1, /* is_lstat */ 0, buf);
if (ret != UV_ENOSYS)
return ret;
ret = fstat(fd, &pbuf);
if (ret == 0)
uv__to_stat(&pbuf, buf);

View File

@ -92,7 +92,9 @@ int uv__getaddrinfo_translate_error(int sys_err) {
}
assert(!"unknown EAI_* error code");
abort();
#ifndef __SUNPRO_C
return 0; /* Pacify compiler. */
#endif
}

View File

@ -95,8 +95,7 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
*/
#if defined(__clang__) || \
defined(__GNUC__) || \
defined(__INTEL_COMPILER) || \
defined(__SUNPRO_C)
defined(__INTEL_COMPILER)
# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration
# define UV_UNUSED(declaration) __attribute__((unused)) declaration
#else
@ -306,4 +305,11 @@ UV_UNUSED(static char* uv__basename_r(const char* path)) {
int uv__inotify_fork(uv_loop_t* loop, void* old_watchers);
#endif
typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
int uv__getsockpeername(const uv_handle_t* handle,
uv__peersockfunc func,
struct sockaddr* name,
int* namelen);
#endif /* UV_UNIX_INTERNAL_H_ */

View File

@ -490,8 +490,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
return UV__ERR(errno);
handle->path = uv__strdup(path);
if (handle->path == NULL)
if (handle->path == NULL) {
uv__close_nocheckstdio(fd);
return UV_ENOMEM;
}
handle->cb = cb;
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);

View File

@ -187,6 +187,21 @@
# endif
#endif /* __NR_pwritev */
#ifndef __NR_statx
# if defined(__x86_64__)
# define __NR_statx 332
# elif defined(__i386__)
# define __NR_statx 383
# elif defined(__aarch64__)
# define __NR_statx 397
# elif defined(__arm__)
# define __NR_statx (UV_SYSCALL_BASE + 397)
# elif defined(__ppc__)
# define __NR_statx 383
# elif defined(__s390__)
# define __NR_statx 379
# endif
#endif /* __NR_statx */
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
#if defined(__i386__)
@ -336,3 +351,16 @@ int uv__dup3(int oldfd, int newfd, int flags) {
return errno = ENOSYS, -1;
#endif
}
int uv__statx(int dirfd,
const char* path,
int flags,
unsigned int mask,
struct uv__statx* statxbuf) {
#if defined(__NR_statx)
return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf);
#else
return errno = ENOSYS, -1;
#endif
}

View File

@ -80,6 +80,36 @@
#define UV__IN_DELETE_SELF 0x400
#define UV__IN_MOVE_SELF 0x800
struct uv__statx_timestamp {
int64_t tv_sec;
uint32_t tv_nsec;
int32_t unused0;
};
struct uv__statx {
uint32_t stx_mask;
uint32_t stx_blksize;
uint64_t stx_attributes;
uint32_t stx_nlink;
uint32_t stx_uid;
uint32_t stx_gid;
uint16_t stx_mode;
uint16_t unused0;
uint64_t stx_ino;
uint64_t stx_size;
uint64_t stx_blocks;
uint64_t stx_attributes_mask;
struct uv__statx_timestamp stx_atime;
struct uv__statx_timestamp stx_btime;
struct uv__statx_timestamp stx_ctime;
struct uv__statx_timestamp stx_mtime;
uint32_t stx_rdev_major;
uint32_t stx_rdev_minor;
uint32_t stx_dev_major;
uint32_t stx_dev_minor;
uint64_t unused1[14];
};
struct uv__inotify_event {
int32_t wd;
uint32_t mask;
@ -113,5 +143,10 @@ int uv__sendmmsg(int fd,
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
int uv__dup3(int oldfd, int newfd, int flags);
int uv__statx(int dirfd,
const char* path,
int flags,
unsigned int mask,
struct uv__statx* statxbuf);
#endif /* UV_LINUX_SYSCALL_H_ */

View File

@ -233,9 +233,6 @@ out:
}
typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
uv__peersockfunc func,
char* buffer,
@ -246,10 +243,13 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
addrlen = sizeof(sa);
memset(&sa, 0, addrlen);
err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
err = uv__getsockpeername((const uv_handle_t*) handle,
func,
(struct sockaddr*) &sa,
(int*) &addrlen);
if (err < 0) {
*size = 0;
return UV__ERR(errno);
return err;
}
#if defined(__linux__)

View File

@ -135,8 +135,10 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0))
return UV__ERR(errno);
if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd))
if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd)) {
perror("(libuv) port_dissociate()");
abort();
}
return 0;
}
@ -174,8 +176,14 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w = QUEUE_DATA(q, uv__io_t, watcher_queue);
assert(w->pevents != 0);
if (port_associate(loop->backend_fd, PORT_SOURCE_FD, w->fd, w->pevents, 0))
if (port_associate(loop->backend_fd,
PORT_SOURCE_FD,
w->fd,
w->pevents,
0)) {
perror("(libuv) port_associate()");
abort();
}
w->events = w->pevents;
}
@ -219,10 +227,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
/* Work around another kernel bug: port_getn() may return events even
* on error.
*/
if (errno == EINTR || errno == ETIME)
if (errno == EINTR || errno == ETIME) {
saved_errno = errno;
else
} else {
perror("(libuv) port_getn()");
abort();
}
}
/* Update loop->time unconditionally. It's tempting to skip the update when

View File

@ -82,7 +82,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
handle->flags |= flags;
return 0;
}
/* Query to see if tcp socket is bound. */
slen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
@ -283,44 +283,28 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
int uv_tcp_getsockname(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
socklen_t socklen;
if (handle->delayed_error)
return handle->delayed_error;
if (uv__stream_fd(handle) < 0)
return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getsockname(uv__stream_fd(handle), name, &socklen))
return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
return uv__getsockpeername((const uv_handle_t*) handle,
getsockname,
name,
namelen);
}
int uv_tcp_getpeername(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
socklen_t socklen;
if (handle->delayed_error)
return handle->delayed_error;
if (uv__stream_fd(handle) < 0)
return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getpeername(uv__stream_fd(handle), name, &socklen))
return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
return uv__getsockpeername((const uv_handle_t*) handle,
getpeername,
name,
namelen);
}

View File

@ -801,7 +801,9 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
return UV_ETIMEDOUT;
abort();
#ifndef __SUNPRO_C
return UV_EINVAL; /* Satisfy the compiler. */
#endif
}

115
deps/uv/src/unix/udp.c vendored
View File

@ -227,9 +227,14 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
assert(req != NULL);
memset(&h, 0, sizeof h);
h.msg_name = &req->addr;
h.msg_namelen = (req->addr.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
if (req->addr.ss_family == AF_UNSPEC) {
h.msg_name = NULL;
h.msg_namelen = 0;
} else {
h.msg_name = &req->addr;
h.msg_namelen = req->addr.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
}
h.msg_iov = (struct iovec*) req->bufs;
h.msg_iovlen = req->nbufs;
@ -383,6 +388,50 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
}
int uv__udp_connect(uv_udp_t* handle,
const struct sockaddr* addr,
unsigned int addrlen) {
int err;
err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
if (err)
return err;
do {
errno = 0;
err = connect(handle->io_watcher.fd, addr, addrlen);
} while (err == -1 && errno == EINTR);
if (err)
return UV__ERR(errno);
handle->flags |= UV_HANDLE_UDP_CONNECTED;
return 0;
}
int uv__udp_disconnect(uv_udp_t* handle) {
int r;
struct sockaddr addr;
memset(&addr, 0, sizeof(addr));
addr.sa_family = AF_UNSPEC;
do {
errno = 0;
r = connect(handle->io_watcher.fd, &addr, sizeof(addr));
} while (r == -1 && errno == EINTR);
if (r == -1 && errno != EAFNOSUPPORT)
return UV__ERR(errno);
handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
return 0;
}
int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],
@ -395,9 +444,11 @@ int uv__udp_send(uv_udp_send_t* req,
assert(nbufs > 0);
err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
if (err)
return err;
if (addr) {
err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
if (err)
return err;
}
/* It's legal for send_queue_count > 0 even when the write_queue is empty;
* it means there are error-state requests in the write_completed_queue that
@ -407,7 +458,10 @@ int uv__udp_send(uv_udp_send_t* req,
uv__req_init(handle->loop, req, UV_UDP_SEND);
assert(addrlen <= sizeof(req->addr));
memcpy(&req->addr, addr, addrlen);
if (addr == NULL)
req->addr.ss_family = AF_UNSPEC;
else
memcpy(&req->addr, addr, addrlen);
req->send_cb = send_cb;
req->handle = handle;
req->nbufs = nbufs;
@ -459,9 +513,13 @@ int uv__udp_try_send(uv_udp_t* handle,
if (handle->send_queue_count != 0)
return UV_EAGAIN;
err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
if (err)
return err;
if (addr) {
err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
if (err)
return err;
} else {
assert(handle->flags & UV_HANDLE_UDP_CONNECTED);
}
memset(&h, 0, sizeof h);
h.msg_name = (struct sockaddr*) addr;
@ -608,6 +666,7 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
uv__io_init(&handle->io_watcher, uv__udp_io, fd);
QUEUE_INIT(&handle->write_queue);
QUEUE_INIT(&handle->write_completed_queue);
return 0;
}
@ -636,6 +695,9 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
return err;
handle->io_watcher.fd = sock;
if (uv__udp_is_connected(handle))
handle->flags |= UV_HANDLE_UDP_CONNECTED;
return 0;
}
@ -743,13 +805,17 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
IPV6_UNICAST_HOPS,
&ttl,
sizeof(ttl));
#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
defined(__MVS__) */
#else /* !(defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
defined(__MVS__)) */
return uv__setsockopt_maybe_char(handle,
IP_TTL,
IPV6_UNICAST_HOPS,
ttl);
#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
defined(__MVS__) */
}
@ -851,23 +917,24 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
return 0;
}
int uv_udp_getpeername(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen) {
return uv__getsockpeername((const uv_handle_t*) handle,
getpeername,
name,
namelen);
}
int uv_udp_getsockname(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen) {
socklen_t socklen;
if (handle->io_watcher.fd == -1)
return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getsockname(handle->io_watcher.fd, name, &socklen))
return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
return uv__getsockpeername((const uv_handle_t*) handle,
getsockname,
name,
namelen);
}

View File

@ -222,6 +222,9 @@ int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
memset(addr, 0, sizeof(*addr));
addr->sin6_family = AF_INET6;
addr->sin6_port = htons(port);
#ifdef SIN6_LEN
addr->sin6_len = sizeof(*addr);
#endif
zone_index = strchr(ip, '%');
if (zone_index != NULL) {
@ -314,17 +317,20 @@ int uv_tcp_connect(uv_connect_t* req,
}
int uv_udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr* addr,
uv_udp_send_cb send_cb) {
int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
unsigned int addrlen;
if (handle->type != UV_UDP)
return UV_EINVAL;
/* Disconnect the handle */
if (addr == NULL) {
if (!(handle->flags & UV_HANDLE_UDP_CONNECTED))
return UV_ENOTCONN;
return uv__udp_disconnect(handle);
}
if (addr->sa_family == AF_INET)
addrlen = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6)
@ -332,6 +338,66 @@ int uv_udp_send(uv_udp_send_t* req,
else
return UV_EINVAL;
if (handle->flags & UV_HANDLE_UDP_CONNECTED)
return UV_EISCONN;
return uv__udp_connect(handle, addr, addrlen);
}
int uv__udp_is_connected(uv_udp_t* handle) {
struct sockaddr_storage addr;
int addrlen;
if (handle->type != UV_UDP)
return 0;
addrlen = sizeof(addr);
if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0)
return 0;
return addrlen > 0;
}
int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
unsigned int addrlen;
if (handle->type != UV_UDP)
return UV_EINVAL;
if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED))
return UV_EISCONN;
if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED))
return UV_EDESTADDRREQ;
if (addr != NULL) {
if (addr->sa_family == AF_INET)
addrlen = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6)
addrlen = sizeof(struct sockaddr_in6);
else
return UV_EINVAL;
} else {
addrlen = 0;
}
return addrlen;
}
int uv_udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr* addr,
uv_udp_send_cb send_cb) {
int addrlen;
addrlen = uv__udp_check_before_send(handle, addr);
if (addrlen < 0)
return addrlen;
return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
}
@ -340,17 +406,11 @@ int uv_udp_try_send(uv_udp_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr* addr) {
unsigned int addrlen;
int addrlen;
if (handle->type != UV_UDP)
return UV_EINVAL;
if (addr->sa_family == AF_INET)
addrlen = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6)
addrlen = sizeof(struct sockaddr_in6);
else
return UV_EINVAL;
addrlen = uv__udp_check_before_send(handle, addr);
if (addrlen < 0)
return addrlen;
return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
}

View File

@ -103,6 +103,7 @@ enum {
/* Only used by uv_udp_t handles. */
UV_HANDLE_UDP_PROCESSING = 0x01000000,
UV_HANDLE_UDP_CONNECTED = 0x02000000,
/* Only used by uv_pipe_t handles. */
UV_HANDLE_NON_OVERLAPPED_PIPE = 0x01000000,
@ -142,6 +143,14 @@ int uv__udp_bind(uv_udp_t* handle,
unsigned int addrlen,
unsigned int flags);
int uv__udp_connect(uv_udp_t* handle,
const struct sockaddr* addr,
unsigned int addrlen);
int uv__udp_disconnect(uv_udp_t* handle);
int uv__udp_is_connected(uv_udp_t* handle);
int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],

View File

@ -36,7 +36,7 @@ const char* uv_req_type_name(uv_req_type type) {
case UV_REQ_TYPE_MAX:
case UV_UNKNOWN_REQ:
default: /* UV_REQ_TYPE_PRIVATE */
return NULL;
break;
}
return NULL;
}

View File

@ -623,3 +623,30 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
return 0;
}
int uv_cpumask_size(void) {
return (int)(sizeof(DWORD_PTR) * 8);
}
int uv__getsockpeername(const uv_handle_t* handle,
uv__peersockfunc func,
struct sockaddr* name,
int* namelen,
int delayed_error) {
int result;
uv_os_fd_t fd;
result = uv_fileno(handle, &fd);
if (result != 0)
return result;
if (delayed_error)
return uv_translate_sys_error(delayed_error);
result = func((SOCKET) fd, name, namelen);
if (result != 0)
return uv_translate_sys_error(WSAGetLastError());
return 0;
}

View File

@ -139,7 +139,6 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
case UV_FS_POLL:
uv__fs_poll_close((uv_fs_poll_t*) handle);
uv__handle_closing(handle);
uv_want_endgame(loop, handle);
return;
default:

View File

@ -272,6 +272,14 @@ int uv__getpwuid_r(uv_passwd_t* pwd);
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
typedef int (WINAPI *uv__peersockfunc)(SOCKET, struct sockaddr*, int*);
int uv__getsockpeername(const uv_handle_t* handle,
uv__peersockfunc func,
struct sockaddr* name,
int* namelen,
int delayed_error);
/*
* Process stdio handles.

40
deps/uv/src/win/tcp.c vendored
View File

@ -809,44 +809,24 @@ static int uv_tcp_try_connect(uv_connect_t* req,
int uv_tcp_getsockname(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
int result;
if (handle->socket == INVALID_SOCKET) {
return UV_EINVAL;
}
if (handle->delayed_error) {
return uv_translate_sys_error(handle->delayed_error);
}
result = getsockname(handle->socket, name, namelen);
if (result != 0) {
return uv_translate_sys_error(WSAGetLastError());
}
return 0;
return uv__getsockpeername((const uv_handle_t*) handle,
getsockname,
name,
namelen,
handle->delayed_error);
}
int uv_tcp_getpeername(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen) {
int result;
if (handle->socket == INVALID_SOCKET) {
return UV_EINVAL;
}
if (handle->delayed_error) {
return uv_translate_sys_error(handle->delayed_error);
}
result = getpeername(handle->socket, name, namelen);
if (result != 0) {
return uv_translate_sys_error(WSAGetLastError());
}
return 0;
return uv__getsockpeername((const uv_handle_t*) handle,
getpeername,
name,
namelen,
handle->delayed_error);
}

103
deps/uv/src/win/udp.c vendored
View File

@ -36,22 +36,27 @@ const unsigned int uv_active_udp_streams_threshold = 0;
/* A zero-size buffer for use by uv_udp_read */
static char uv_zero_[] = "";
int uv_udp_getpeername(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen) {
return uv__getsockpeername((const uv_handle_t*) handle,
getpeername,
name,
namelen,
0);
}
int uv_udp_getsockname(const uv_udp_t* handle,
struct sockaddr* name,
int* namelen) {
int result;
if (handle->socket == INVALID_SOCKET) {
return UV_EINVAL;
}
result = getsockname(handle->socket, name, namelen);
if (result != 0) {
return uv_translate_sys_error(WSAGetLastError());
}
return 0;
return uv__getsockpeername((const uv_handle_t*) handle,
getsockname,
name,
namelen,
0);
}
@ -784,6 +789,18 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
}
int uv__udp_is_bound(uv_udp_t* handle) {
struct sockaddr_storage addr;
int addrlen;
addrlen = sizeof(addr);
if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0)
return 0;
return addrlen > 0;
}
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
WSAPROTOCOL_INFOW protocol_info;
int opt_len;
@ -803,7 +820,16 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
handle,
sock,
protocol_info.iAddressFamily);
return uv_translate_sys_error(err);
if (err)
return uv_translate_sys_error(err);
if (uv__udp_is_bound(handle))
handle->flags |= UV_HANDLE_BOUND;
if (uv__udp_is_connected(handle))
handle->flags |= UV_HANDLE_UDP_CONNECTED;
return 0;
}
@ -880,6 +906,50 @@ int uv__udp_bind(uv_udp_t* handle,
}
int uv__udp_connect(uv_udp_t* handle,
const struct sockaddr* addr,
unsigned int addrlen) {
const struct sockaddr* bind_addr;
int err;
if (!(handle->flags & UV_HANDLE_BOUND)) {
if (addrlen == sizeof(uv_addr_ip4_any_))
bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
else if (addrlen == sizeof(uv_addr_ip6_any_))
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
else
return UV_EINVAL;
err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
if (err)
return uv_translate_sys_error(err);
}
err = connect(handle->socket, addr, addrlen);
if (err)
return uv_translate_sys_error(err);
handle->flags |= UV_HANDLE_UDP_CONNECTED;
return 0;
}
int uv__udp_disconnect(uv_udp_t* handle) {
int err;
struct sockaddr addr;
memset(&addr, 0, sizeof(addr));
err = connect(handle->socket, &addr, sizeof(addr));
if (err)
return uv_translate_sys_error(err);
handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
return 0;
}
/* This function is an egress point, i.e. it returns libuv errors rather than
* system errors.
*/
@ -900,6 +970,7 @@ int uv__udp_send(uv_udp_send_t* req,
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
else
return UV_EINVAL;
err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
if (err)
return uv_translate_sys_error(err);
@ -925,9 +996,11 @@ int uv__udp_try_send(uv_udp_t* handle,
assert(nbufs > 0);
err = uv__convert_to_localhost_if_unspecified(addr, &converted);
if (err)
return err;
if (addr != NULL) {
err = uv__convert_to_localhost_if_unspecified(addr, &converted);
if (err)
return err;
}
/* Already sending a message.*/
if (handle->send_queue_count != 0)

View File

@ -87,12 +87,6 @@ void uv_winsock_init(void) {
WSAPROTOCOL_INFOW protocol_info;
int opt_len;
/* Initialize winsock */
errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (errorno != 0) {
uv_fatal_error(errorno, "WSAStartup");
}
/* Set implicit binding address used by connectEx */
if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) {
abort();
@ -102,6 +96,15 @@ void uv_winsock_init(void) {
abort();
}
/* Skip initialization in safe mode without network support */
if (1 == GetSystemMetrics(SM_CLEANBOOT)) return;
/* Initialize winsock */
errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (errorno != 0) {
uv_fatal_error(errorno, "WSAStartup");
}
/* Detect non-IFS LSPs */
dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

View File

@ -44,7 +44,7 @@ int ipc_send_recv_helper(void);
int ipc_helper_bind_twice(void);
int ipc_helper_send_zero(void);
int stdio_over_pipes_helper(void);
int spawn_stdin_stdout(void);
void spawn_stdin_stdout(void);
int spawn_tcp_server_helper(void);
static int maybe_run_test(int argc, char **argv);
@ -67,7 +67,9 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
#ifndef __SUNPRO_C
return EXIT_SUCCESS;
#endif
}
@ -209,7 +211,8 @@ static int maybe_run_test(int argc, char **argv) {
if (strcmp(argv[1], "spawn_helper9") == 0) {
notify_parent_process();
return spawn_stdin_stdout();
spawn_stdin_stdout();
return 1;
}
#ifndef _WIN32

3
deps/uv/test/task.h vendored
View File

@ -174,8 +174,7 @@ extern int snprintf(char*, size_t, const char*, ...);
#if defined(__clang__) || \
defined(__GNUC__) || \
defined(__INTEL_COMPILER) || \
defined(__SUNPRO_C)
defined(__INTEL_COMPILER)
# define UNUSED __attribute__((unused))
#else
# define UNUSED

View File

@ -23,7 +23,8 @@
#include "task.h"
#if defined(__unix__) || defined(__POSIX__) || \
defined(__APPLE__) || defined(_AIX) || defined(__MVS__)
defined(__APPLE__) || defined(__sun) || \
defined(_AIX) || defined(__MVS__)
#include <unistd.h> /* unlink, etc. */
#else
# include <direct.h>

View File

@ -185,3 +185,77 @@ TEST_IMPL(fs_poll_getpath) {
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_poll_close_request) {
uv_loop_t loop;
uv_fs_poll_t poll_handle;
remove(FIXTURE);
ASSERT(0 == uv_loop_init(&loop));
ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
uv_close((uv_handle_t*) &poll_handle, close_cb);
while (close_cb_called == 0)
uv_run(&loop, UV_RUN_ONCE);
ASSERT(close_cb_called == 1);
ASSERT(0 == uv_loop_close(&loop));
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_poll_close_request_multi_start_stop) {
uv_loop_t loop;
uv_fs_poll_t poll_handle;
int i;
remove(FIXTURE);
ASSERT(0 == uv_loop_init(&loop));
ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
for (i = 0; i < 10; ++i) {
ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
ASSERT(0 == uv_fs_poll_stop(&poll_handle));
}
uv_close((uv_handle_t*) &poll_handle, close_cb);
while (close_cb_called == 0)
uv_run(&loop, UV_RUN_ONCE);
ASSERT(close_cb_called == 1);
ASSERT(0 == uv_loop_close(&loop));
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_poll_close_request_multi_stop_start) {
uv_loop_t loop;
uv_fs_poll_t poll_handle;
int i;
remove(FIXTURE);
ASSERT(0 == uv_loop_init(&loop));
ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle));
for (i = 0; i < 10; ++i) {
ASSERT(0 == uv_fs_poll_stop(&poll_handle));
ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
}
uv_close((uv_handle_t*) &poll_handle, close_cb);
while (close_cb_called == 0)
uv_run(&loop, UV_RUN_ONCE);
ASSERT(close_cb_called == 1);
ASSERT(0 == uv_loop_close(&loop));
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -30,7 +30,8 @@
/* FIXME we shouldn't need to branch in this file */
#if defined(__unix__) || defined(__POSIX__) || \
defined(__APPLE__) || defined(_AIX) || defined(__MVS__)
defined(__APPLE__) || defined(__sun) || \
defined(_AIX) || defined(__MVS__)
#include <unistd.h> /* unlink, rmdir, etc. */
#else
# include <winioctl.h>
@ -1248,6 +1249,16 @@ TEST_IMPL(fs_fstat) {
#endif
#endif
#if defined(__linux__)
/* If statx() is supported, the birth time should be equal to the change time
* because we just created the file. On older kernels, it's set to zero.
*/
ASSERT(s->st_birthtim.tv_sec == 0 ||
s->st_birthtim.tv_sec == t.st_ctim.tv_sec);
ASSERT(s->st_birthtim.tv_nsec == 0 ||
s->st_birthtim.tv_nsec == t.st_ctim.tv_nsec);
#endif
uv_fs_req_cleanup(&req);
/* Now do the uv_fs_fstat call asynchronously */

View File

@ -41,13 +41,11 @@ TEST_IMPL(hrtime) {
diff = b - a;
/* printf("i= %d diff = %llu\n", i, (unsigned long long int) diff); */
/* The windows Sleep() function has only a resolution of 10-20 ms. Check
* that the difference between the two hrtime values is somewhat in the
* range we expect it to be. */
* that the difference between the two hrtime values has a reasonable
* lower bound.
*/
ASSERT(diff > (uint64_t) 25 * NANOSEC / MILLISEC);
ASSERT(diff < (uint64_t) 80 * NANOSEC / MILLISEC);
--i;
}
return 0;

View File

@ -971,4 +971,4 @@ int ipc_helper_send_zero(void) {
MAKE_VALGRIND_HAPPY();
return 0;
}
}

View File

@ -132,6 +132,7 @@ TEST_DECLARE (tcp_write_ready)
TEST_DECLARE (udp_alloc_cb_fail)
TEST_DECLARE (udp_bind)
TEST_DECLARE (udp_bind_reuseaddr)
TEST_DECLARE (udp_connect)
TEST_DECLARE (udp_create_early)
TEST_DECLARE (udp_create_early_bad_bind)
TEST_DECLARE (udp_create_early_bad_domain)
@ -152,6 +153,8 @@ TEST_DECLARE (udp_options6)
TEST_DECLARE (udp_no_autobind)
TEST_DECLARE (udp_open)
TEST_DECLARE (udp_open_twice)
TEST_DECLARE (udp_open_bound)
TEST_DECLARE (udp_open_connect)
TEST_DECLARE (udp_try_send)
TEST_DECLARE (pipe_bind_error_addrinuse)
TEST_DECLARE (pipe_bind_error_addrnotavail)
@ -280,6 +283,9 @@ TEST_DECLARE (spawn_quoted_path)
TEST_DECLARE (spawn_tcp_server)
TEST_DECLARE (fs_poll)
TEST_DECLARE (fs_poll_getpath)
TEST_DECLARE (fs_poll_close_request)
TEST_DECLARE (fs_poll_close_request_multi_start_stop)
TEST_DECLARE (fs_poll_close_request_multi_stop_start)
TEST_DECLARE (kill)
TEST_DECLARE (kill_invalid_signum)
TEST_DECLARE (fs_file_noent)
@ -619,6 +625,7 @@ TASK_LIST_START
TEST_ENTRY (udp_alloc_cb_fail)
TEST_ENTRY (udp_bind)
TEST_ENTRY (udp_bind_reuseaddr)
TEST_ENTRY (udp_connect)
TEST_ENTRY (udp_create_early)
TEST_ENTRY (udp_create_early_bad_bind)
TEST_ENTRY (udp_create_early_bad_domain)
@ -642,6 +649,9 @@ TASK_LIST_START
TEST_ENTRY (udp_open)
TEST_HELPER (udp_open, udp4_echo_server)
TEST_ENTRY (udp_open_twice)
TEST_ENTRY (udp_open_bound)
TEST_ENTRY (udp_open_connect)
TEST_HELPER (udp_open_connect, udp4_echo_server)
TEST_ENTRY (pipe_bind_error_addrinuse)
TEST_ENTRY (pipe_bind_error_addrnotavail)
@ -817,6 +827,9 @@ TASK_LIST_START
TEST_ENTRY (spawn_tcp_server)
TEST_ENTRY (fs_poll)
TEST_ENTRY (fs_poll_getpath)
TEST_ENTRY (fs_poll_close_request)
TEST_ENTRY (fs_poll_close_request_multi_start_stop)
TEST_ENTRY (fs_poll_close_request_multi_stop_start)
TEST_ENTRY (kill)
TEST_ENTRY (kill_invalid_signum)

View File

@ -320,7 +320,7 @@ TEST_IMPL(loop_handles) {
ASSERT(prepare_1_cb_called == ITERATIONS);
ASSERT(prepare_1_close_cb_called == 1);
ASSERT(prepare_2_cb_called == floor(ITERATIONS / 2.0));
ASSERT(prepare_2_cb_called == ITERATIONS / 2);
ASSERT(prepare_2_close_cb_called == 1);
ASSERT(check_cb_called == ITERATIONS);

View File

@ -82,9 +82,9 @@ static int closed_connections = 0;
static int valid_writable_wakeups = 0;
static int spurious_writable_wakeups = 0;
#if !defined(_AIX) && !defined(__MVS__)
#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__)
static int disconnects = 0;
#endif /* !_AIX && !__MVS__ */
#endif /* !__sun && !_AIX && !__MVS__ */
static int got_eagain(void) {
#ifdef _WIN32
@ -391,7 +391,7 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
new_events &= ~UV_WRITABLE;
}
}
#if !defined(_AIX) && !defined(__MVS__)
#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__)
if (events & UV_DISCONNECT) {
context->got_disconnect = 1;
++disconnects;
@ -399,9 +399,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
}
if (context->got_fin && context->sent_fin && context->got_disconnect) {
#else /* _AIX && __MVS__ */
#else /* __sun && _AIX && __MVS__ */
if (context->got_fin && context->sent_fin) {
#endif /* !_AIX && !__MVS__ */
#endif /* !__sun && !_AIX && !__MVS__ */
/* Sent and received FIN. Close and destroy context. */
close_socket(context->sock);
destroy_connection_context(context);
@ -569,7 +569,7 @@ static void start_poll_test(void) {
spurious_writable_wakeups > 20);
ASSERT(closed_connections == NUM_CLIENTS * 2);
#if !defined(_AIX) && !defined(__MVS__)
#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__)
ASSERT(disconnects == NUM_CLIENTS * 2);
#endif
MAKE_VALGRIND_HAPPY();

View File

@ -1838,7 +1838,7 @@ TEST_IMPL(spawn_quoted_path) {
/* Helper for child process of spawn_inherit_streams */
#ifndef _WIN32
int spawn_stdin_stdout(void) {
void spawn_stdin_stdout(void) {
char buf[1024];
char* pbuf;
for (;;) {
@ -1847,7 +1847,7 @@ int spawn_stdin_stdout(void) {
r = read(0, buf, sizeof buf);
} while (r == -1 && errno == EINTR);
if (r == 0) {
return 1;
return;
}
ASSERT(r > 0);
c = r;
@ -1861,10 +1861,9 @@ int spawn_stdin_stdout(void) {
c = c - w;
}
}
return 2;
}
#else
int spawn_stdin_stdout(void) {
void spawn_stdin_stdout(void) {
char buf[1024];
char* pbuf;
HANDLE h_stdin = GetStdHandle(STD_INPUT_HANDLE);
@ -1877,7 +1876,7 @@ int spawn_stdin_stdout(void) {
DWORD to_write;
if (!ReadFile(h_stdin, buf, sizeof buf, &n_read, NULL)) {
ASSERT(GetLastError() == ERROR_BROKEN_PIPE);
return 1;
return;
}
to_write = n_read;
pbuf = buf;
@ -1887,6 +1886,5 @@ int spawn_stdin_stdout(void) {
pbuf += n_written;
}
}
return 2;
}
#endif /* !_WIN32 */

182
deps/uv/test/test-udp-connect.c vendored Normal file
View File

@ -0,0 +1,182 @@
/* Copyright libuv project and 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 uv_buf_t buf;
static struct sockaddr_in lo_addr;
static int cl_send_cb_called;
static int sv_recv_cb_called;
static int close_cb_called;
static void alloc_cb(uv_handle_t* handle,
size_t suggested_size,
uv_buf_t* buf) {
static char slab[65536];
CHECK_HANDLE(handle);
ASSERT(suggested_size <= sizeof(slab));
buf->base = slab;
buf->len = sizeof(slab);
}
static void close_cb(uv_handle_t* handle) {
CHECK_HANDLE(handle);
ASSERT(uv_is_closing(handle));
close_cb_called++;
}
static void cl_send_cb(uv_udp_send_t* req, int status) {
int r;
ASSERT(req != NULL);
ASSERT(status == 0);
CHECK_HANDLE(req->handle);
if (++cl_send_cb_called == 1) {
uv_udp_connect(&client, NULL);
r = uv_udp_send(req, &client, &buf, 1, NULL, cl_send_cb);
ASSERT(r == UV_EDESTADDRREQ);
r = uv_udp_send(req,
&client,
&buf,
1,
(const struct sockaddr*) &lo_addr,
cl_send_cb);
ASSERT(r == 0);
}
}
static void sv_recv_cb(uv_udp_t* handle,
ssize_t nread,
const uv_buf_t* rcvbuf,
const struct sockaddr* addr,
unsigned flags) {
if (nread > 0) {
ASSERT(nread == 4);
ASSERT(addr != NULL);
ASSERT(memcmp("EXIT", rcvbuf->base, nread) == 0);
if (++sv_recv_cb_called == 4) {
uv_close((uv_handle_t*) &server, close_cb);
uv_close((uv_handle_t*) &client, close_cb);
}
}
}
TEST_IMPL(udp_connect) {
uv_udp_send_t req;
struct sockaddr_in ext_addr;
struct sockaddr_in tmp_addr;
int r;
int addrlen;
ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &lo_addr));
r = uv_udp_init(uv_default_loop(), &server);
ASSERT(r == 0);
r = uv_udp_bind(&server, (const struct sockaddr*) &lo_addr, 0);
ASSERT(r == 0);
r = uv_udp_recv_start(&server, alloc_cb, sv_recv_cb);
ASSERT(r == 0);
r = uv_udp_init(uv_default_loop(), &client);
ASSERT(r == 0);
buf = uv_buf_init("EXIT", 4);
ASSERT(0 == uv_ip4_addr("8.8.8.8", TEST_PORT, &ext_addr));
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &lo_addr));
r = uv_udp_connect(&client, (const struct sockaddr*) &lo_addr);
ASSERT(r == 0);
r = uv_udp_connect(&client, (const struct sockaddr*) &ext_addr);
ASSERT(r == UV_EISCONN);
addrlen = sizeof(tmp_addr);
r = uv_udp_getpeername(&client, (struct sockaddr*) &tmp_addr, &addrlen);
ASSERT(r == 0);
/* To send messages in connected UDP sockets addr must be NULL */
r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &lo_addr);
ASSERT(r == UV_EISCONN);
r = uv_udp_try_send(&client, &buf, 1, NULL);
ASSERT(r == 4);
r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &ext_addr);
ASSERT(r == UV_EISCONN);
r = uv_udp_connect(&client, NULL);
ASSERT(r == 0);
r = uv_udp_connect(&client, NULL);
ASSERT(r == UV_ENOTCONN);
addrlen = sizeof(tmp_addr);
r = uv_udp_getpeername(&client, (struct sockaddr*) &tmp_addr, &addrlen);
ASSERT(r == UV_ENOTCONN);
/* To send messages in disconnected UDP sockets addr must be set */
r = uv_udp_try_send(&client, &buf, 1, (const struct sockaddr*) &lo_addr);
ASSERT(r == 4);
r = uv_udp_try_send(&client, &buf, 1, NULL);
ASSERT(r == UV_EDESTADDRREQ);
r = uv_udp_connect(&client, (const struct sockaddr*) &lo_addr);
ASSERT(r == 0);
r = uv_udp_send(&req,
&client,
&buf,
1,
(const struct sockaddr*) &lo_addr,
cl_send_cb);
ASSERT(r == UV_EISCONN);
r = uv_udp_send(&req, &client, &buf, 1, NULL, cl_send_cb);
ASSERT(r == 0);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(close_cb_called == 2);
ASSERT(sv_recv_cb_called == 4);
ASSERT(cl_send_cb_called == 2);
ASSERT(client.send_queue_size == 0);
ASSERT(server.send_queue_size == 0);
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -129,6 +129,7 @@ static void send_cb(uv_udp_send_t* req, int status) {
ASSERT(status == 0);
send_cb_called++;
uv_close((uv_handle_t*)req->handle, close_cb);
}
@ -215,3 +216,83 @@ TEST_IMPL(udp_open_twice) {
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(udp_open_bound) {
struct sockaddr_in addr;
uv_udp_t client;
uv_os_sock_t sock;
int r;
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
startup();
sock = create_udp_socket();
r = bind(sock, (struct sockaddr*) &addr, sizeof(addr));
ASSERT(r == 0);
r = uv_udp_init(uv_default_loop(), &client);
ASSERT(r == 0);
r = uv_udp_open(&client, sock);
ASSERT(r == 0);
r = uv_udp_recv_start(&client, alloc_cb, recv_cb);
ASSERT(r == 0);
uv_close((uv_handle_t*) &client, NULL);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(udp_open_connect) {
struct sockaddr_in addr;
uv_buf_t buf = uv_buf_init("PING", 4);
uv_udp_t client;
uv_udp_t server;
uv_os_sock_t sock;
int r;
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
startup();
sock = create_udp_socket();
r = uv_udp_init(uv_default_loop(), &client);
ASSERT(r == 0);
r = connect(sock, (const struct sockaddr*) &addr, sizeof(addr));
ASSERT(r == 0);
r = uv_udp_open(&client, sock);
ASSERT(r == 0);
r = uv_udp_init(uv_default_loop(), &server);
ASSERT(r == 0);
r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0);
ASSERT(r == 0);
r = uv_udp_recv_start(&server, alloc_cb, recv_cb);
ASSERT(r == 0);
r = uv_udp_send(&send_req,
&client,
&buf,
1,
NULL,
send_cb);
ASSERT(r == 0);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(send_cb_called == 1);
ASSERT(close_cb_called == 2);
ASSERT(client.send_queue_size == 0);
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -137,6 +137,7 @@
'test-tty.c',
'test-udp-alloc-cb-fail.c',
'test-udp-bind.c',
'test-udp-connect.c',
'test-udp-create-socket-early.c',
'test-udp-dgram-too-big.c',
'test-udp-ipv6.c',