From 401c073dd278b282017c558089913c096fb9b53f Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 21 Oct 2011 17:08:12 -0700 Subject: [PATCH] uv: upgrade to ec825ff --- deps/uv/include/uv.h | 9 +++++ deps/uv/src/unix/core.c | 3 +- deps/uv/src/unix/internal.h | 18 ++++++---- deps/uv/src/unix/stream.c | 24 +++++++++---- deps/uv/src/unix/tcp.c | 79 +++++++++++++++++++++++++++++++++++++++++++ deps/uv/src/win/tcp.c | 12 +++++++ deps/uv/test/test-list.h | 2 ++ deps/uv/test/test-tcp-flags.c | 51 ++++++++++++++++++++++++++++ deps/uv/uv.gyp | 1 + 9 files changed, 185 insertions(+), 14 deletions(-) create mode 100644 deps/uv/test/test-tcp-flags.c diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 179398d..7bee299 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -448,6 +448,15 @@ struct uv_tcp_s { int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle); +/* Enable/disable Nagle's algorithm. */ +int uv_tcp_nodelay(uv_tcp_t* handle, int enable); + +/* Enable/disable TCP keep-alive. + * + * `ms` is the initial delay in seconds, ignored when `enable` is zero. + */ +int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay); + int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in); int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6); int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen); diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index c834aaa..27e949e 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -667,7 +667,8 @@ int uv_getaddrinfo(uv_loop_t* loop, void uv_freeaddrinfo(struct addrinfo* ai) { - freeaddrinfo(ai); + if (ai) + freeaddrinfo(ai); } diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index e6ae9b7..0ab8ba9 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -74,13 +74,15 @@ /* flags */ enum { - UV_CLOSING = 0x00000001, /* uv_close() called but not finished. */ - UV_CLOSED = 0x00000002, /* close(2) finished. */ - UV_READING = 0x00000004, /* uv_read_start() called. */ - UV_SHUTTING = 0x00000008, /* uv_shutdown() called but not complete. */ - UV_SHUT = 0x00000010, /* Write side closed. */ - UV_READABLE = 0x00000020, /* The stream is readable */ - UV_WRITABLE = 0x00000040 /* The stream is writable */ + UV_CLOSING = 0x01, /* uv_close() called but not finished. */ + UV_CLOSED = 0x02, /* close(2) finished. */ + UV_READING = 0x04, /* uv_read_start() called. */ + UV_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */ + UV_SHUT = 0x10, /* Write side closed. */ + UV_READABLE = 0x20, /* The stream is readable */ + UV_WRITABLE = 0x40, /* The stream is writable */ + UV_TCP_NODELAY = 0x080, /* Disable Nagle. */ + UV_TCP_KEEPALIVE = 0x100 /* Turn on keep-alive. */ }; size_t uv__strlcpy(char* dst, const char* src, size_t size); @@ -111,6 +113,8 @@ int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr, /* tcp */ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb); +int uv__tcp_nodelay(uv_tcp_t* handle, int enable); +int uv__tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay); /* pipe */ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 3dbdf89..2e5bde0 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -86,12 +86,24 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { stream->flags |= flags; - /* Reuse the port address if applicable. */ - yes = 1; - if (stream->type == UV_TCP - && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { - uv__set_sys_error(stream->loop, errno); - return -1; + if (stream->type == UV_TCP) { + /* Reuse the port address if applicable. */ + yes = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1) { + uv__set_sys_error(stream->loop, errno); + return -1; + } + + if ((stream->flags & UV_TCP_NODELAY) && + uv__tcp_nodelay((uv_tcp_t*)stream, 1)) { + return -1; + } + + /* TODO Use delay the user passed in. */ + if ((stream->flags & UV_TCP_KEEPALIVE) && + uv__tcp_keepalive((uv_tcp_t*)stream, 1, 60)) { + return -1; + } } /* Associate the fd with each ev_io watcher. */ diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index 8695a98..67ed217 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -240,3 +240,82 @@ int uv__tcp_connect6(uv_connect_t* req, errno = saved_errno; return status; } + + +int uv__tcp_nodelay(uv_tcp_t* handle, int enable) { + if (setsockopt(handle->fd, + IPPROTO_TCP, + TCP_NODELAY, + &enable, + sizeof enable) == -1) { + uv__set_sys_error(handle->loop, errno); + return -1; + } + return 0; +} + + +int uv__tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { + if (setsockopt(handle->fd, + SOL_SOCKET, + SO_KEEPALIVE, + &enable, + sizeof enable) == -1) { + uv__set_sys_error(handle->loop, errno); + return -1; + } + +#ifdef TCP_KEEPIDLE + if (enable && setsockopt(handle->fd, + IPPROTO_TCP, + TCP_KEEPIDLE, + &delay, + sizeof delay) == -1) { + uv__set_sys_error(handle->loop, errno); + return -1; + } +#endif + +#ifdef TCP_KEEPALIVE + if (enable && setsockopt(handle->fd, + IPPROTO_TCP, + TCP_KEEPALIVE, + &delay, + sizeof delay) == -1) { + uv__set_sys_error(handle->loop, errno); + return -1; + } +#endif + + return 0; +} + + +int uv_tcp_nodelay(uv_tcp_t* handle, int enable) { + if (handle->fd != -1 && uv__tcp_nodelay(handle, enable)) + return -1; + + if (enable) + handle->flags |= UV_TCP_NODELAY; + else + handle->flags &= ~UV_TCP_NODELAY; + + return 0; +} + + +int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { + if (handle->fd != -1 && uv__tcp_keepalive(handle, enable, delay)) + return -1; + + if (enable) + handle->flags |= UV_TCP_KEEPALIVE; + else + handle->flags &= ~UV_TCP_KEEPALIVE; + + /* TODO Store delay if handle->fd == -1 but don't want to enlarge + * uv_tcp_t with an int that's almost never used... + */ + + return 0; +} diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index b6ab497..1133cc3 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -956,3 +956,15 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) { return uv_tcp_set_socket(tcp->loop, tcp, socket, 1); } + + +int uv_tcp_nodelay(uv_tcp_t* handle, int enable) { + uv__set_artificial_error(handle->loop, UV_ENOSYS); + return -1; +} + + +int uv_tcp_keepalive(uv_tcp_t* handle, int enable, int delay) { + uv__set_artificial_error(handle->loop, UV_ENOSYS); + return -1; +} diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 17b98c2..19c9991 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -37,6 +37,7 @@ TEST_DECLARE (tcp_bind_error_inval) TEST_DECLARE (tcp_bind_localhost_ok) TEST_DECLARE (tcp_listen_without_bind) TEST_DECLARE (tcp_close) +TEST_DECLARE (tcp_flags) TEST_DECLARE (tcp_write_error) TEST_DECLARE (tcp_bind6_error_addrinuse) TEST_DECLARE (tcp_bind6_error_addrnotavail) @@ -149,6 +150,7 @@ TASK_LIST_START TEST_ENTRY (tcp_bind_localhost_ok) TEST_ENTRY (tcp_listen_without_bind) TEST_ENTRY (tcp_close) + TEST_ENTRY (tcp_flags) TEST_ENTRY (tcp_write_error) TEST_ENTRY (tcp_bind6_error_addrinuse) diff --git a/deps/uv/test/test-tcp-flags.c b/deps/uv/test/test-tcp-flags.c new file mode 100644 index 0000000..c441b56 --- /dev/null +++ b/deps/uv/test/test-tcp-flags.c @@ -0,0 +1,51 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include + + +TEST_IMPL(tcp_flags) { + uv_loop_t* loop; + uv_tcp_t handle; + int r; + + loop = uv_default_loop(); + + r = uv_tcp_init(loop, &handle); + ASSERT(r == 0); + + r = uv_tcp_nodelay(&handle, 1); + ASSERT(r == 0); + + r = uv_tcp_keepalive(&handle, 1, 60); + ASSERT(r == 0); + + uv_close((uv_handle_t*)&handle, NULL); + + r = uv_run(loop); + ASSERT(r == 0); + + return 0; +} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 9fe0867..b4ef014 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -290,6 +290,7 @@ 'test/test-tcp-bind-error.c', 'test/test-tcp-bind6-error.c', 'test/test-tcp-close.c', + 'test/test-tcp-flags.c', 'test/test-tcp-connect-error.c', 'test/test-tcp-connect6-error.c', 'test/test-tcp-write-error.c', -- 2.7.4