Skip to content
Browse files

unix: Split out c-ares integration into separate file

  • Loading branch information...
1 parent 58461d5 commit e97958ac3bf644cda9b0aee7b94b7ab93415d21d @ry ry committed Aug 31, 2011
Showing with 190 additions and 156 deletions.
  1. +5 −2 config-unix.mk
  2. +179 −0 src/unix/cares.c
  3. +4 −1 src/unix/internal.h
  4. +1 −153 src/uv-unix.c
  5. +1 −0 uv.gyp
View
7 config-unix.mk
@@ -85,8 +85,8 @@ endif
RUNNER_LIBS=
RUNNER_SRC=test/runner-unix.c
-uv.a: src/uv-unix.o src/unix/fs.o src/unix/udp.o src/uv-common.o src/uv-platform.o src/unix/ev/ev.o src/unix/uv-eio.o src/unix/eio/eio.o $(CARES_OBJS)
- $(AR) rcs uv.a src/uv-unix.o src/unix/fs.o src/unix/udp.o src/uv-platform.o src/uv-common.o src/unix/uv-eio.o src/unix/ev/ev.o \
+uv.a: src/uv-unix.o src/unix/fs.o src/unix/udp.o src/unix/cares.o src/uv-common.o src/uv-platform.o src/unix/ev/ev.o src/unix/uv-eio.o src/unix/eio/eio.o $(CARES_OBJS)
+ $(AR) rcs uv.a src/uv-unix.o src/unix/fs.o src/unix/udp.o src/unix/cares.o src/uv-platform.o src/uv-common.o src/unix/uv-eio.o src/unix/ev/ev.o \
src/unix/eio/eio.o $(CARES_OBJS)
src/uv-platform.o: src/unix/$(UV_OS_FILE) include/uv.h include/uv-private/uv-unix.h
@@ -98,6 +98,9 @@ src/uv-unix.o: src/uv-unix.c include/uv.h include/uv-private/uv-unix.h src/unix/
src/unix/fs.o: src/unix/fs.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h
$(CC) $(CSTDFLAG) $(CPPFLAGS) -Isrc/ $(CFLAGS) -c src/unix/fs.c -o src/unix/fs.o
+src/unix/cares.o: src/unix/cares.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h
+ $(CC) $(CSTDFLAG) $(CPPFLAGS) -Isrc/ $(CFLAGS) -c src/unix/cares.c -o src/unix/cares.o
+
src/unix/udp.o: src/unix/udp.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h
$(CC) $(CSTDFLAG) $(CPPFLAGS) -Isrc/ $(CFLAGS) -c src/unix/udp.c -o src/unix/udp.o
View
179 src/unix/cares.c
@@ -0,0 +1,179 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+
+
+#define container_of ngx_queue_data
+
+/*
+ * This is called once per second by loop->timer. It is used to
+ * constantly callback into c-ares for possibly processing timeouts.
+ */
+static void uv__ares_timeout(struct ev_loop* ev, struct ev_timer* watcher,
+ int revents) {
+ uv_loop_t* loop = container_of(ev, uv_loop_t, ev);
+ assert(watcher == &loop->timer);
+ assert(revents == EV_TIMER);
+ assert(!uv_ares_handles_empty(loop));
+ ares_process_fd(loop->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
+}
+
+
+static void uv__ares_io(struct ev_loop* ev, struct ev_io* watcher,
+ int revents) {
+ uv_loop_t* loop = container_of(ev, uv_loop_t, ev);
+
+ /* Reset the idle timer */
+ ev_timer_again(ev, &loop->timer);
+
+ /* Process DNS responses */
+ ares_process_fd(loop->channel,
+ revents & EV_READ ? watcher->fd : ARES_SOCKET_BAD,
+ revents & EV_WRITE ? watcher->fd : ARES_SOCKET_BAD);
+}
+
+
+/* Allocates and returns a new uv_ares_task_t */
+static uv_ares_task_t* uv__ares_task_create(int fd) {
+ uv_ares_task_t* h = malloc(sizeof(uv_ares_task_t));
+
+ if (h == NULL) {
+ uv_fatal_error(ENOMEM, "malloc");
+ }
+
+ h->sock = fd;
+
+ ev_io_init(&h->read_watcher, uv__ares_io, fd, EV_READ);
+ ev_io_init(&h->write_watcher, uv__ares_io, fd, EV_WRITE);
+
+ h->read_watcher.data = h;
+ h->write_watcher.data = h;
+
+ return h;
+}
+
+
+/* Callback from ares when socket operation is started */
+static void uv__ares_sockstate_cb(void* data, ares_socket_t sock,
+ int read, int write) {
+ uv_loop_t* loop = data;
+ uv_ares_task_t* h;
+
+ h = uv_find_ares_handle(loop, sock);
+
+ if (read || write) {
+ if (!h) {
+ /* New socket */
+
+ /* If this is the first socket then start the timer. */
+ if (!ev_is_active(&loop->timer)) {
+ assert(uv_ares_handles_empty(loop));
+ ev_timer_again(loop->ev, &loop->timer);
+ }
+
+ h = uv__ares_task_create(sock);
+ uv_add_ares_handle(loop, h);
+ }
+
+ if (read) {
+ ev_io_start(loop->ev, &h->read_watcher);
+ } else {
+ ev_io_stop(loop->ev, &h->read_watcher);
+ }
+
+ if (write) {
+ ev_io_start(loop->ev, &h->write_watcher);
+ } else {
+ ev_io_stop(loop->ev, &h->write_watcher);
+ }
+
+ } else {
+ /*
+ * read == 0 and write == 0 this is c-ares's way of notifying us that
+ * the socket is now closed. We must free the data associated with
+ * socket.
+ */
+ assert(h && "When an ares socket is closed we should have a handle for it");
+
+ ev_io_stop(loop->ev, &h->read_watcher);
+ ev_io_stop(loop->ev, &h->write_watcher);
+
+ uv_remove_ares_handle(h);
+ free(h);
+
+ if (uv_ares_handles_empty(loop)) {
+ ev_timer_stop(loop->ev, &loop->timer);
+ }
+ }
+}
+
+
+/* c-ares integration initialize and terminate */
+/* TODO: share this with windows? */
+int uv_ares_init_options(uv_loop_t* loop, ares_channel *channelptr,
+ struct ares_options *options, int optmask) {
+ int rc;
+
+ /* only allow single init at a time */
+ if (loop->channel != NULL) {
+ uv_err_new_artificial(loop, UV_EALREADY);
+ return -1;
+ }
+
+ /* set our callback as an option */
+ options->sock_state_cb = uv__ares_sockstate_cb;
+ options->sock_state_cb_data = loop;
+ optmask |= ARES_OPT_SOCK_STATE_CB;
+
+ /* We do the call to ares_init_option for caller. */
+ rc = ares_init_options(channelptr, options, optmask);
+
+ /* if success, save channel */
+ if (rc == ARES_SUCCESS) {
+ loop->channel = *channelptr;
+ }
+
+ /*
+ * Initialize the timeout timer. The timer won't be started until the
+ * first socket is opened.
+ */
+ ev_init(&loop->timer, uv__ares_timeout);
+ loop->timer.repeat = 1.0;
+
+ return rc;
+}
+
+
+/* TODO share this with windows? */
+void uv_ares_destroy(uv_loop_t* loop, ares_channel channel) {
+ /* only allow destroy if did init */
+ if (loop->channel != NULL) {
+ ev_timer_stop(loop->ev, &loop->timer);
+ ares_destroy(channel);
+ loop->channel = NULL;
+ }
+}
View
5 src/unix/internal.h
@@ -27,12 +27,15 @@
int uv__close(int fd);
void uv__req_init(uv_req_t*);
+void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle, uv_handle_type type);
+
uv_err_t uv_err_new(uv_loop_t* loop, int sys_error);
uv_err_t uv_err_new_artificial(uv_loop_t* loop, int code);
+void uv_fatal_error(const int errorno, const char* syscall);
+
int uv__nonblock(int fd, int set) __attribute__((unused));
int uv__cloexec(int fd, int set) __attribute__((unused));
int uv__socket(int domain, int type, int protocol);
-void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle, uv_handle_type type);
/* udp */
void uv__udp_destroy(uv_udp_t* handle);
View
154 src/uv-unix.c
@@ -85,8 +85,6 @@
extern char **environ;
# endif
-#define container_of ngx_queue_data
-
static uv_loop_t default_loop_struct;
static uv_loop_t* default_loop_ptr;
@@ -138,7 +136,7 @@ void uv_init() {
/* TODO Share this code with Windows. */
/* TODO Expose callback to user to handle fatal error like V8 does. */
-static void uv_fatal_error(const int errorno, const char* syscall) {
+void uv_fatal_error(const int errorno, const char* syscall) {
char* buf = NULL;
const char* errmsg;
@@ -1621,156 +1619,6 @@ int64_t uv_timer_get_repeat(uv_timer_t* timer) {
}
-/*
- * This is called once per second by loop->timer. It is used to
- * constantly callback into c-ares for possibly processing timeouts.
- */
-static void uv__ares_timeout(struct ev_loop* ev, struct ev_timer* watcher,
- int revents) {
- uv_loop_t* loop = container_of(ev, uv_loop_t, ev);
- assert(watcher == &loop->timer);
- assert(revents == EV_TIMER);
- assert(!uv_ares_handles_empty(loop));
- ares_process_fd(loop->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
-}
-
-
-static void uv__ares_io(struct ev_loop* ev, struct ev_io* watcher,
- int revents) {
- uv_loop_t* loop = container_of(ev, uv_loop_t, ev);
-
- /* Reset the idle timer */
- ev_timer_again(ev, &loop->timer);
-
- /* Process DNS responses */
- ares_process_fd(loop->channel,
- revents & EV_READ ? watcher->fd : ARES_SOCKET_BAD,
- revents & EV_WRITE ? watcher->fd : ARES_SOCKET_BAD);
-}
-
-
-/* Allocates and returns a new uv_ares_task_t */
-static uv_ares_task_t* uv__ares_task_create(int fd) {
- uv_ares_task_t* h = malloc(sizeof(uv_ares_task_t));
-
- if (h == NULL) {
- uv_fatal_error(ENOMEM, "malloc");
- }
-
- h->sock = fd;
-
- ev_io_init(&h->read_watcher, uv__ares_io, fd, EV_READ);
- ev_io_init(&h->write_watcher, uv__ares_io, fd, EV_WRITE);
-
- h->read_watcher.data = h;
- h->write_watcher.data = h;
-
- return h;
-}
-
-
-/* Callback from ares when socket operation is started */
-static void uv__ares_sockstate_cb(void* data, ares_socket_t sock,
- int read, int write) {
- uv_loop_t* loop = data;
- uv_ares_task_t* h;
-
- h = uv_find_ares_handle(loop, sock);
-
- if (read || write) {
- if (!h) {
- /* New socket */
-
- /* If this is the first socket then start the timer. */
- if (!ev_is_active(&loop->timer)) {
- assert(uv_ares_handles_empty(loop));
- ev_timer_again(loop->ev, &loop->timer);
- }
-
- h = uv__ares_task_create(sock);
- uv_add_ares_handle(loop, h);
- }
-
- if (read) {
- ev_io_start(loop->ev, &h->read_watcher);
- } else {
- ev_io_stop(loop->ev, &h->read_watcher);
- }
-
- if (write) {
- ev_io_start(loop->ev, &h->write_watcher);
- } else {
- ev_io_stop(loop->ev, &h->write_watcher);
- }
-
- } else {
- /*
- * read == 0 and write == 0 this is c-ares's way of notifying us that
- * the socket is now closed. We must free the data associated with
- * socket.
- */
- assert(h && "When an ares socket is closed we should have a handle for it");
-
- ev_io_stop(loop->ev, &h->read_watcher);
- ev_io_stop(loop->ev, &h->write_watcher);
-
- uv_remove_ares_handle(h);
- free(h);
-
- if (uv_ares_handles_empty(loop)) {
- ev_timer_stop(loop->ev, &loop->timer);
- }
- }
-}
-
-
-/* c-ares integration initialize and terminate */
-/* TODO: share this with windows? */
-int uv_ares_init_options(uv_loop_t* loop, ares_channel *channelptr,
- struct ares_options *options, int optmask) {
- int rc;
-
- /* only allow single init at a time */
- if (loop->channel != NULL) {
- uv_err_new_artificial(loop, UV_EALREADY);
- return -1;
- }
-
- /* set our callback as an option */
- options->sock_state_cb = uv__ares_sockstate_cb;
- options->sock_state_cb_data = loop;
- optmask |= ARES_OPT_SOCK_STATE_CB;
-
- /* We do the call to ares_init_option for caller. */
- rc = ares_init_options(channelptr, options, optmask);
-
- /* if success, save channel */
- if (rc == ARES_SUCCESS) {
- loop->channel = *channelptr;
- }
-
- /*
- * Initialize the timeout timer. The timer won't be started until the
- * first socket is opened.
- */
- ev_init(&loop->timer, uv__ares_timeout);
- loop->timer.repeat = 1.0;
-
- return rc;
-}
-
-
-/* TODO share this with windows? */
-void uv_ares_destroy(uv_loop_t* loop, ares_channel channel) {
- /* only allow destroy if did init */
- if (loop->channel != NULL) {
- ev_timer_stop(loop->ev, &loop->timer);
- ares_destroy(channel);
- loop->channel = NULL;
- }
-}
-
-
static int uv_getaddrinfo_done(eio_req* req) {
uv_getaddrinfo_t* handle = req->data;
View
1 uv.gyp
@@ -146,6 +146,7 @@
'src/unix/uv-eio.h',
'src/unix/fs.c',
'src/unix/udp.c',
+ 'src/unix/cares.c',
'src/unix/internal.h',
'src/unix/eio/ecb.h',
'src/unix/eio/eio.c',

0 comments on commit e97958a

Please sign in to comment.
Something went wrong with that request. Please try again.