diff --git a/include/uv.h b/include/uv.h index e3a8b702..0f89c735 100644 --- a/include/uv.h +++ b/include/uv.h @@ -1482,8 +1482,8 @@ struct uv_counters_s { struct uv_loop_s { UV_LOOP_PRIVATE_FIELDS - /* list used for ares task handles */ - uv_ares_task_t* uv_ares_handles_; + /* RB_HEAD(uv__ares_tasks, uv_ares_task_t) */ + struct uv__ares_tasks { uv_ares_task_t* rbh_root; } uv_ares_handles_; /* Various thing for libeio. */ uv_async_t uv_eio_want_poll_notifier; uv_async_t uv_eio_done_poll_notifier; diff --git a/src/unix/cares.c b/src/unix/cares.c index 85cabac4..18cdefe3 100644 --- a/src/unix/cares.c +++ b/src/unix/cares.c @@ -62,7 +62,7 @@ static void uv__ares_io(struct ev_loop* ev, struct ev_io* watcher, /* Allocates and returns a new uv_ares_task_t */ -static uv_ares_task_t* uv__ares_task_create(int fd) { +static uv_ares_task_t* uv__ares_task_create(uv_loop_t* loop, int fd) { uv_ares_task_t* h = malloc(sizeof(uv_ares_task_t)); if (h == NULL) { @@ -70,6 +70,7 @@ static uv_ares_task_t* uv__ares_task_create(int fd) { return NULL; } + h->loop = loop; h->sock = fd; ev_io_init(&h->read_watcher, uv__ares_io, fd, EV_READ); @@ -102,7 +103,7 @@ static void uv__ares_sockstate_cb(void* data, ares_socket_t sock, ev_timer_again(loop->ev, &loop->timer); } - h = uv__ares_task_create(sock); + h = uv__ares_task_create(loop, sock); uv_add_ares_handle(loop, h); } diff --git a/src/unix/core.c b/src/unix/core.c index 728eb0bf..52bb0020 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -145,6 +145,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { static int uv__loop_init(uv_loop_t* loop, struct ev_loop *(ev_loop_new)(unsigned int flags)) { memset(loop, 0, sizeof(*loop)); + RB_INIT(&loop->uv_ares_handles_); #if HAVE_KQUEUE loop->ev = ev_loop_new(EVBACKEND_KQUEUE); #else diff --git a/src/uv-common.c b/src/uv-common.c index cb9b6b6f..d0241dcd 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -32,6 +32,10 @@ #include "ares/inet_net_pton.h" #include "ares/inet_ntop.h" +#if !defined(__GNUC__) && !defined(__clang__) +# define __attribute__(x) +#endif + size_t uv_strlcpy(char* dst, const char* src, size_t size) { size_t n; @@ -180,57 +184,44 @@ int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) { } -/* find matching ares handle in list */ +static int cmp_ares_tasks(const uv_ares_task_t* a, const uv_ares_task_t* b) { + if (a->sock < b->sock) return -1; + if (a->sock > b->sock) return 1; + return 0; +} + + +RB_GENERATE_INTERNAL(uv__ares_tasks, uv_ares_task_s, node, cmp_ares_tasks, + inline static __attribute__((unused))) + + +/* add ares handle to list */ void uv_add_ares_handle(uv_loop_t* loop, uv_ares_task_t* handle) { - handle->loop = loop; - handle->ares_next = loop->uv_ares_handles_; - handle->ares_prev = NULL; - - if (loop->uv_ares_handles_) { - loop->uv_ares_handles_->ares_prev = handle; - } - - loop->uv_ares_handles_ = handle; + assert(loop == handle->loop); + RB_INSERT(uv__ares_tasks, &loop->uv_ares_handles_, handle); } + /* find matching ares handle in list */ -/* TODO: faster lookup */ uv_ares_task_t* uv_find_ares_handle(uv_loop_t* loop, ares_socket_t sock) { - uv_ares_task_t* handle = loop->uv_ares_handles_; - - while (handle != NULL) { - if (handle->sock == sock) { - break; - } - handle = handle->ares_next; - } - - return handle; + uv_ares_task_t handle; + handle.sock = sock; + return RB_FIND(uv__ares_tasks, &loop->uv_ares_handles_, &handle); } + /* remove ares handle in list */ void uv_remove_ares_handle(uv_ares_task_t* handle) { - uv_loop_t* loop = handle->loop; - - if (handle == loop->uv_ares_handles_) { - loop->uv_ares_handles_ = handle->ares_next; - } - - if (handle->ares_next) { - handle->ares_next->ares_prev = handle->ares_prev; - } - - if (handle->ares_prev) { - handle->ares_prev->ares_next = handle->ares_next; - } + RB_REMOVE(uv__ares_tasks, &handle->loop->uv_ares_handles_, handle); } /* Returns 1 if the uv_ares_handles_ list is empty. 0 otherwise. */ int uv_ares_handles_empty(uv_loop_t* loop) { - return loop->uv_ares_handles_ ? 0 : 1; + return RB_EMPTY(&loop->uv_ares_handles_); } + int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) { if (handle->type != UV_TCP || addr.sin_family != AF_INET) { uv__set_artificial_error(handle->loop, UV_EFAULT); @@ -240,6 +231,7 @@ int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) { return uv__tcp_bind(handle, addr); } + int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) { if (handle->type != UV_TCP || addr.sin6_family != AF_INET6) { uv__set_artificial_error(handle->loop, UV_EFAULT); @@ -249,6 +241,7 @@ int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) { return uv__tcp_bind6(handle, addr); } + int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned int flags) { if (handle->type != UV_UDP || addr.sin_family != AF_INET) { @@ -259,6 +252,7 @@ int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, return uv__udp_bind(handle, addr, flags); } + int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned int flags) { if (handle->type != UV_UDP || addr.sin6_family != AF_INET6) { @@ -269,6 +263,7 @@ int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, return uv__udp_bind6(handle, addr, flags); } + int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in address, @@ -281,6 +276,7 @@ int uv_tcp_connect(uv_connect_t* req, return uv__tcp_connect(req, handle, address, cb); } + int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in6 address, diff --git a/src/uv-common.h b/src/uv-common.h index 72914ec0..e1f16b6c 100644 --- a/src/uv-common.h +++ b/src/uv-common.h @@ -28,6 +28,7 @@ #define UV_COMMON_H_ #include "uv.h" +#include "tree.h" #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) @@ -35,8 +36,7 @@ struct uv_ares_task_s { UV_HANDLE_FIELDS UV_ARES_TASK_PRIVATE_FIELDS - uv_ares_task_t* ares_prev; - uv_ares_task_t* ares_next; + RB_ENTRY(uv_ares_task_s) node; }; diff --git a/src/win/cares.c b/src/win/cares.c index f504bf96..1592d123 100644 --- a/src/win/cares.c +++ b/src/win/cares.c @@ -159,6 +159,7 @@ static void uv_ares_sockstate_cb(void *data, ares_socket_t sock, int read, } uv_handle_ares->type = UV_ARES_TASK; uv_handle_ares->close_cb = NULL; + uv_handle_ares->loop = loop; uv_handle_ares->data = loop; uv_handle_ares->sock = sock; uv_handle_ares->h_wait = NULL; diff --git a/src/win/core.c b/src/win/core.c index accacc5a..1983361b 100644 --- a/src/win/core.c +++ b/src/win/core.c @@ -59,7 +59,6 @@ static void uv_init(void) { static void uv_loop_init(uv_loop_t* loop) { - loop->uv_ares_handles_ = NULL; /* Create an I/O completion port */ loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); if (loop->iocp == NULL) { @@ -75,6 +74,7 @@ static void uv_loop_init(uv_loop_t* loop) { loop->endgame_handles = NULL; RB_INIT(&loop->timers); + RB_INIT(&loop->uv_ares_handles_); loop->check_handles = NULL; loop->prepare_handles = NULL;