'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof
- 'MACOSX_DEPLOYMENT_TARGET': '10.4', # -mmacosx-version-min=10.4
'PREBINDING': 'NO', # No -Wl,-prebind
'USE_HEADERMAP': 'NO',
'OTHER_CFLAGS': [
# There's a bug with windows which doesn't allow this feature.
if sys.platform != 'win32':
-
# Tell gyp to write the Makefiles into output_dir
args.extend(['--generator-output', output_dir])
-
# Tell make to write its output into the same dir
args.extend(['-Goutput_dir=' + output_dir])
+ # Create Makefiles, not XCode projects
+ args.extend('-f make'.split())
args.append('-Dtarget_arch=ia32')
args.append('-Dcomponent=static_library')
const char* multicast_addr, const char* interface_addr,
uv_membership membership);
+/*
+ * Set the multicast ttl
+ *
+ * Arguments:
+ * handle UDP handle. Should have been initialized with
+ * `uv_udp_init`.
+ * ttl 1 through 255
+ *
+ * Returns:
+ * 0 on success, -1 on error.
+ */
+int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl);
+
+/*
+ * Set broadcast on or off
+ *
+ * Arguments:
+ * handle UDP handle. Should have been initialized with
+ * `uv_udp_init`.
+ * on 1 for on, 0 for off
+ *
+ * Returns:
+ * 0 on success, -1 on error.
+ */
+int uv_udp_set_broadcast(uv_udp_t* handle, int on);
+
/*
* 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)
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
- uv_udp_t* udp;
uv_async_t* async;
uv_timer_t* timer;
uv_stream_t* stream;
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;
+ uv__udp_start_close((uv_udp_t*)handle);
break;
case UV_PREPARE:
handle->flags = 0;
ev_init(&handle->next_watcher, uv__next);
- handle->next_watcher.data = handle;
/* Ref the loop until this handle is closed. See uv__finish_close. */
ev_ref(loop->ev);
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);
+ uv__udp_finish_close((uv_udp_t*)handle);
break;
case UV_PROCESS:
}
-void uv__next(EV_P_ ev_idle* watcher, int revents) {
- uv_handle_t* handle = watcher->data;
- assert(watcher == &handle->next_watcher);
+void uv__next(EV_P_ ev_idle* w, int revents) {
+ uv_handle_t* handle = container_of(w, uv_handle_t, next_watcher);
+
assert(revents == EV_IDLE);
/* For now this function is only to handle the closing event, but we might
static void uv__prepare(EV_P_ ev_prepare* w, int revents) {
- uv_prepare_t* prepare = w->data;
+ uv_prepare_t* prepare = container_of(w, uv_prepare_t, prepare_watcher);
if (prepare->prepare_cb) {
prepare->prepare_cb(prepare, 0);
loop->counters.prepare_init++;
ev_prepare_init(&prepare->prepare_watcher, uv__prepare);
- prepare->prepare_watcher.data = prepare;
-
prepare->prepare_cb = NULL;
return 0;
static void uv__check(EV_P_ ev_check* w, int revents) {
- uv_check_t* check = w->data;
+ uv_check_t* check = container_of(w, uv_check_t, check_watcher);
if (check->check_cb) {
check->check_cb(check, 0);
loop->counters.check_init++;
ev_check_init(&check->check_watcher, uv__check);
- check->check_watcher.data = check;
-
check->check_cb = NULL;
return 0;
static void uv__idle(EV_P_ ev_idle* w, int revents) {
- uv_idle_t* idle = (uv_idle_t*)(w->data);
+ uv_idle_t* idle = container_of(w, uv_idle_t, idle_watcher);
if (idle->idle_cb) {
idle->idle_cb(idle, 0);
loop->counters.idle_init++;
ev_idle_init(&idle->idle_watcher, uv__idle);
- idle->idle_watcher.data = idle;
-
idle->idle_cb = NULL;
return 0;
static void uv__async(EV_P_ ev_async* w, int revents) {
- uv_async_t* async = w->data;
+ uv_async_t* async = container_of(w, uv_async_t, async_watcher);
if (async->async_cb) {
async->async_cb(async, 0);
loop->counters.async_init++;
ev_async_init(&async->async_watcher, uv__async);
- async->async_watcher.data = async;
-
async->async_cb = async_cb;
/* Note: This does not have symmetry with the other libev wrappers. */
static void uv__timer_cb(EV_P_ ev_timer* w, int revents) {
- uv_timer_t* timer = w->data;
+ uv_timer_t* timer = container_of(w, uv_timer_t, timer_watcher);
if (!ev_is_active(w)) {
ev_ref(EV_A);
loop->counters.timer_init++;
ev_init(&timer->timer_watcher, uv__timer_cb);
- timer->timer_watcher.data = timer;
return 0;
}
}
-int uv__close(int fd) {
- int status;
-
- /*
- * Retry on EINTR. You may think this is academic but on linux
- * and probably other Unices too, close(2) is interruptible.
- * Failing to handle EINTR is a common source of fd leaks.
- */
- do {
- status = close(fd);
- }
- while (status == -1 && errno == EINTR);
-
- return status;
-}
-
-
int uv__nonblock(int fd, int set) {
#if FIONBIO
return ioctl(fd, FIONBIO, &set);
void inline_size
kqueue_fork (EV_P)
{
- close (backend_fd);
-
while ((backend_fd = kqueue ()) < 0)
ev_syserr ("(libev) kqueue");
UV_TCP_KEEPALIVE = 0x100 /* Turn on keep-alive. */
};
-int uv__close(int fd);
+/* core */
void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle, uv_handle_type type);
-
-
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);
+/* We used to handle EINTR in uv__close() but linux 2.6 will have closed the
+ * file descriptor anyway, even on EINTR. Retrying in that case isn't merely
+ * useless, it's actively harmful - the file descriptor may have been acquired
+ * by another thread.
+ */
+#define uv__close(fd) close(fd)
+
/* error */
uv_err_code uv_translate_sys_error(int sys_errno);
void uv_fatal_error(const int errorno, const char* syscall);
int uv_pipe_cleanup(uv_pipe_t* handle);
/* udp */
-void uv__udp_destroy(uv_udp_t* handle);
-void uv__udp_watcher_stop(uv_udp_t* handle, ev_io* w);
+void uv__udp_start_close(uv_udp_t* handle);
+void uv__udp_finish_close(uv_udp_t* handle);
/* fs */
void uv__fs_event_destroy(uv_fs_event_t* handle);
struct stat s;
if (file < 0) {
- uv__set_sys_error(NULL, EINVAL); /* XXX Need loop? */
- return -1;
+ return UV_UNKNOWN_HANDLE;
}
if (isatty(file)) {
}
if (fstat(file, &s)) {
- uv__set_sys_error(NULL, errno); /* XXX Need loop? */
- return -1;
+ return UV_UNKNOWN_HANDLE;
}
if (!S_ISSOCK(s.st_mode) && !S_ISFIFO(s.st_mode)) {
#include <stdlib.h>
-static void uv__udp_watcher_start(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_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 void uv__udp_recvmsg(EV_P_ ev_io* w, int revents);
+static void uv__udp_sendmsg(EV_P_ ev_io* w, int revents);
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);
-static void uv__udp_watcher_start(uv_udp_t* handle, ev_io* w) {
- int flags;
+static void uv__udp_start_watcher(uv_udp_t* handle,
+ ev_io* w,
+ void (*cb)(EV_P_ ev_io*, int),
+ int flags) {
+ if (ev_is_active(w)) return;
+ ev_set_cb(w, cb);
+ ev_io_set(w, handle->fd, flags);
+ ev_io_start(handle->loop->ev, w);
+ ev_unref(handle->loop->ev);
+}
- if (ev_is_active(w)) {
- return;
- }
- assert(w == &handle->read_watcher
- || w == &handle->write_watcher);
+static void uv__udp_stop_watcher(uv_udp_t* handle, ev_io* w) {
+ if (!ev_is_active(w)) return;
+ ev_ref(handle->loop->ev);
+ ev_io_stop(handle->loop->ev, w);
+ ev_io_set(w, -1, 0);
+ ev_set_cb(w, NULL);
+}
- 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(handle->loop->ev, w);
- ev_unref(handle->loop->ev);
+static void uv__udp_start_read_watcher(uv_udp_t* handle) {
+ uv__udp_start_watcher(handle,
+ &handle->read_watcher,
+ uv__udp_recvmsg,
+ EV_READ);
}
-void uv__udp_watcher_stop(uv_udp_t* handle, ev_io* w) {
- int flags;
+static void uv__udp_start_write_watcher(uv_udp_t* handle) {
+ uv__udp_start_watcher(handle,
+ &handle->write_watcher,
+ uv__udp_sendmsg,
+ EV_WRITE);
+}
- if (!ev_is_active(w)) {
- return;
- }
- assert(w == &handle->read_watcher
- || w == &handle->write_watcher);
+static void uv__udp_stop_read_watcher(uv_udp_t* handle) {
+ uv__udp_stop_watcher(handle, &handle->read_watcher);
+}
- flags = (w == &handle->read_watcher ? EV_READ : EV_WRITE);
- ev_ref(handle->loop->ev);
- ev_io_stop(handle->loop->ev, w);
- ev_io_set(w, -1, flags);
- ev_set_cb(w, NULL);
- w->data = (void*)0xDEADBABE;
+static void uv__udp_stop_write_watcher(uv_udp_t* handle) {
+ uv__udp_stop_watcher(handle, &handle->write_watcher);
+}
+
+
+void uv__udp_start_close(uv_udp_t* handle) {
+ uv__udp_stop_write_watcher(handle);
+ uv__udp_stop_read_watcher(handle);
+ uv__close(handle->fd);
+ handle->fd = -1;
}
-void uv__udp_destroy(uv_udp_t* handle) {
+void uv__udp_finish_close(uv_udp_t* handle) {
uv_udp_send_t* req;
ngx_queue_t* q;
+ assert(!ev_is_active(&handle->write_watcher));
+ assert(!ev_is_active(&handle->read_watcher));
+ assert(handle->fd == -1);
+
uv__udp_run_completed(handle);
while (!ngx_queue_empty(&handle->write_queue)) {
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_recvmsg(uv_udp_t* handle) {
+static void uv__udp_recvmsg(EV_P_ ev_io* w, int revents) {
struct sockaddr_storage peer;
struct msghdr h;
+ uv_udp_t* handle;
ssize_t nread;
uv_buf_t buf;
int flags;
+ handle = container_of(w, uv_udp_t, read_watcher);
+ assert(handle->type == UV_UDP);
+ assert(revents & EV_READ);
+
assert(handle->recv_cb != NULL);
assert(handle->alloc_cb != NULL);
}
-static void uv__udp_sendmsg(uv_udp_t* handle) {
+static void uv__udp_sendmsg(EV_P_ ev_io* w, int revents) {
+ uv_udp_t* handle;
+
+ handle = container_of(w, uv_udp_t, write_watcher);
+ assert(handle->type == UV_UDP);
+ assert(revents & EV_WRITE);
+
assert(!ngx_queue_empty(&handle->write_queue)
|| !ngx_queue_empty(&handle->write_completed_queue));
}
else if (ngx_queue_empty(&handle->write_queue)) {
/* Pending queue and completion queue empty, stop watcher. */
- uv__udp_watcher_stop(handle, &handle->write_watcher);
+ uv__udp_stop_write_watcher(handle);
}
}
-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__bind(uv_udp_t* handle,
int domain,
struct sockaddr* addr,
goto out;
}
+ yes = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1) {
+ uv__set_sys_error(handle->loop, errno);
+ goto out;
+ }
+
if (flags & UV_UDP_IPV6ONLY) {
#ifdef IPV6_V6ONLY
yes = 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);
+ uv__udp_start_write_watcher(handle);
return 0;
}
return 0;
}
+int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) {
+ if (setsockopt(handle->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof ttl) == -1) {
+ uv__set_sys_error(handle->loop, errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+int uv_udp_set_broadcast(uv_udp_t* handle, int on) {
+ if (setsockopt(handle->fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof on) == -1) {
+ uv__set_sys_error(handle->loop, errno);
+ return -1;
+ }
+
+ return 0;
+}
+
int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name,
int* namelen) {
handle->alloc_cb = alloc_cb;
handle->recv_cb = recv_cb;
- uv__udp_watcher_start(handle, &handle->read_watcher);
+ uv__udp_start_read_watcher(handle);
return 0;
}
int uv_udp_recv_stop(uv_udp_t* handle) {
- uv__udp_watcher_stop(handle, &handle->read_watcher);
+ uv__udp_stop_read_watcher(handle);
handle->alloc_cb = NULL;
handle->recv_cb = NULL;
return 0;
#include "uv.h"
-#define COUNTOF(a) (sizeof(a) / sizeof(a[0]))
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
struct uv_ares_task_s {
success = pGetQueuedCompletionStatusEx(loop->iocp,
overlappeds,
- COUNTOF(overlappeds),
+ ARRAY_SIZE(overlappeds),
&count,
timeout,
FALSE);
*/
/* Convert to short path. */
- if (!GetShortPathNameW(filenamew, short_path, COUNTOF(short_path))) {
+ if (!GetShortPathNameW(filenamew, short_path, ARRAY_SIZE(short_path))) {
last_error = GetLastError();
goto error;
}
for (env = env_block; *env; env++) {
check_required_vars_contains_var(required_vars,
- COUNTOF(required_vars),
+ ARRAY_SIZE(required_vars),
*env);
env_len += (uv_utf8_to_utf16(*env, NULL, 0) * sizeof(wchar_t));
}
- for (i = 0; i < COUNTOF(required_vars); ++i) {
+ for (i = 0; i < ARRAY_SIZE(required_vars); ++i) {
if (!required_vars[i].supplied) {
env_len += required_vars[i].len * sizeof(wchar_t);
var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0);
}
}
- for (i = 0; i < COUNTOF(required_vars); ++i) {
+ for (i = 0; i < ARRAY_SIZE(required_vars); ++i) {
if (!required_vars[i].supplied) {
wcscpy(ptr, required_vars[i].wide);
ptr += required_vars[i].len - 1;
int i;
HANDLE handle;
- for (i = 0; i < COUNTOF(process->child_stdio); i++) {
+ for (i = 0; i < ARRAY_SIZE(process->child_stdio); i++) {
handle = process->child_stdio[i];
if (handle != NULL && handle != INVALID_HANDLE_VALUE) {
CloseHandle(handle);
/* We're keeping the handles open, the thread pool is going to have */
/* it's way with them. But at least make them non-inheritable. */
int i;
- for (i = 0; i < COUNTOF(process->child_stdio); i++) {
+ for (i = 0; i < ARRAY_SIZE(process->child_stdio); i++) {
SetHandleInformation(child_stdio[i], HANDLE_FLAG_INHERIT, 0);
}
}
/* We were not currently parsing a number */
/* Check for too many arguments */
- if (handle->ansi_csi_argc >= COUNTOF(handle->ansi_csi_argv)) {
+ if (handle->ansi_csi_argc >= ARRAY_SIZE(handle->ansi_csi_argv)) {
ansi_parser_state |= ANSI_IGNORE;
continue;
}
/* If ANSI_IN_ARG is not set, add another argument and */
/* default it to 0. */
/* Check for too many arguments */
- if (handle->ansi_csi_argc >= COUNTOF(handle->ansi_csi_argv)) {
+ if (handle->ansi_csi_argc >= ARRAY_SIZE(handle->ansi_csi_argv)) {
ansi_parser_state |= ANSI_IGNORE;
continue;
}
/* If a \n immediately follows a \r or vice versa, ignore it. */
if (previous_eol == 0 || utf8_codepoint == previous_eol) {
/* If there's no room in the utf16 buf, flush it first. */
- if (2 > COUNTOF(utf16_buf) - utf16_buf_used) {
+ if (2 > ARRAY_SIZE(utf16_buf) - utf16_buf_used) {
uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error);
utf16_buf_used = 0;
}
/* Encode character into utf-16 buffer. */
/* If there's no room in the utf16 buf, flush it first. */
- if (1 > COUNTOF(utf16_buf) - utf16_buf_used) {
+ if (1 > ARRAY_SIZE(utf16_buf) - utf16_buf_used) {
uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error);
utf16_buf_used = 0;
}
DECREASE_PENDING_REQ_COUNT(handle);
}
+
+int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) {
+ if (setsockopt(handle->socket, IPPROTO_IP, IP_MULTICAST_TTL,
+ (const char*)&ttl, sizeof ttl) == -1) {
+ uv__set_sys_error(handle->loop, WSAGetLastError());
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int uv_udp_set_broadcast(uv_udp_t* handle, int on) {
+ if (setsockopt(handle->socket, SOL_SOCKET, SO_BROADCAST, (const char*)&on,
+ sizeof on) == -1) {
+ uv__set_sys_error(handle->loop, WSAGetLastError());
+ return -1;
+ }
+
+ return 0;
+}
#include "task.h"
#include <stdio.h>
-#include <stddef.h>
#include <stdlib.h>
#define WRITE_REQ_DATA "Hello, world."
#define NUM_WRITE_REQS (1000 * 1000)
-#define container_of(ptr, type, member) \
- ((type *) ((char *) (ptr) - offsetof(type, member)))
-
typedef struct {
uv_write_t req;
uv_buf_t buf;
#define BASE_PORT 12345
-#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
-
static uv_loop_t* loop;
static int n_senders_;
#include "task.h"
#include <stdio.h>
-#include <stddef.h>
#include <stdlib.h>
-#define container_of(ptr, type, member) \
- ((type *) ((char *) (ptr) - offsetof(type, member)))
-
typedef struct {
uv_tcp_t handle;
uv_shutdown_t shutdown_req;
"\n"
};
- uv_write_t write_req[COUNTOF(buffers)];
- uv_buf_t buf[COUNTOF(buffers)];
+ uv_write_t write_req[ARRAY_SIZE(buffers)];
+ uv_buf_t buf[ARRAY_SIZE(buffers)];
int r, i;
uv_loop_t* loop = uv_default_loop();
uv_unref(loop);
uv_unref(loop);
- for (i = 0; i < COUNTOF(buffers); i++) {
+ for (i = 0; i < ARRAY_SIZE(buffers); i++) {
buf[i] = uv_buf_init((char*)buffers[i], strlen(buffers[i]));
}
- for (i = 0; i < COUNTOF(buffers); i++) {
+ for (i = 0; i < ARRAY_SIZE(buffers); i++) {
r = uv_write(&write_req[i], (uv_stream_t*)&stdout_pipe, &buf[i], 1,
after_pipe_write);
ASSERT(r == 0);
#ifndef TASK_H_
#define TASK_H_
-
-#include <stdint.h>
#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
#include <stdlib.h>
#define TEST_PORT 9123
# define TEST_PIPENAME_2 "/tmp/uv-test-sock2"
#endif
-#define COUNTOF(a) (sizeof(a) / sizeof(a[0]))
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+#define container_of(ptr, type, member) \
+ ((type *) ((char *) (ptr) - offsetof(type, member)))
typedef enum {
TCP = 0,
#include "task.h"
#include <stdio.h>
-#include <stddef.h>
#include <stdlib.h>
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-#define container_of(ptr, type, member) \
- ((type *) ((char *) (ptr) - offsetof(type, member)))
+#include <string.h> /* memset */
struct getaddrinfo_req {
uv_thread_t thread_id;
ASSERT(handle != NULL);
once_close_cb_called++;
-
- free(handle);
}
TEST_IMPL(timer) {
+ uv_timer_t once_timers[10];
uv_timer_t *once;
uv_timer_t repeat, never;
int i, r;
ASSERT(0 < start_time);
/* Let 10 timers time out in 500 ms total. */
- for (i = 0; i < 10; i++) {
- once = (uv_timer_t*)malloc(sizeof(*once));
- ASSERT(once != NULL);
+ for (i = 0; i < ARRAY_SIZE(once_timers); i++) {
+ once = once_timers + i;
r = uv_timer_init(uv_default_loop(), once);
ASSERT(r == 0);
r = uv_timer_start(once, once_cb, i * 50, 0);
uv_tty_t tty;
uv_loop_t* loop = uv_default_loop();
+ ASSERT(UV_UNKNOWN_HANDLE == uv_guess_handle(-1));
+
/*
* Not necessarily a problem if this assert goes off. E.G you are piping
* this test to a file. 0 == stdin.