diff --git a/GNUmakefile b/GNUmakefile
index a74abda..f9537a4 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -134,6 +134,7 @@ libuhub_SOURCES := \
src/network/backend.c \
src/network/connection.c \
src/network/epoll.c \
+ src/network/kqueue.c \
src/network/network.c \
src/network/select.c \
src/network/timeout.c \
diff --git a/src/network/kqueue.c b/src/network/kqueue.c
new file mode 100644
index 0000000..c7e68c9
--- /dev/null
+++ b/src/network/kqueue.c
@@ -0,0 +1,171 @@
+/*
+ * uhub - A tiny ADC p2p connection hub
+ * Copyright (C) 2007-2010, Jan Vidar Krey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "uhub.h"
+
+#ifdef USE_KQUEUE
+
+#include "network/connection.h"
+#include "network/common.h"
+#include "network/backend.h"
+
+#define KQUEUE_EVBUFFER 512
+
+struct net_connection_kqueue
+{
+ NET_CON_STRUCT_COMMON
+ struct kevent ev;
+};
+
+struct net_backend
+{
+ int kqfd;
+ size_t num;
+ size_t max;
+ struct net_connection_epoll** conns;
+ struct kevent** changes;
+ size_t nchanges;
+ struct kevent events[KQUEUE_EVBUFFER];
+ time_t now;
+ struct timeout_queue timeout_queue;
+ struct net_cleanup_handler* cleaner;
+};
+
+static struct net_backend* g_backend = 0;
+
+
+/**
+ * Initialize the network backend.
+ * Returns 1 on success, or 0 on failure.
+ */
+int net_backend_initialize()
+{
+ g_backend = hub_malloc_zero(sizeof(struct net_backend));
+ g_backend->kqfd = kqueue();
+ if (g_backend->kqfd == -1)
+ {
+ LOG_WARN("Unable to create epoll socket.");
+ return 0;
+ }
+
+ size_t max = net_get_max_sockets();
+ g_backend->max = max;
+ g_backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * max);
+ g_backend->changes = hub_malloc_zero(sizeof(struct kevent*) * max);
+
+ g_backend->now = time(0);
+ timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* look max 10 minutes into the future. */
+ g_backend->cleaner = net_cleanup_initialize(max);
+ return 1;
+}
+
+/**
+ * Shutdown the network connection backend.
+ */
+void net_backend_shutdown()
+{
+ close(g_backend->kqfd);
+ timeout_queue_shutdown(&g_backend->timeout_queue);
+ net_cleanup_shutdown(g_backend->cleaner);
+ hub_free(g_backend->conns);
+ hub_free(g_backend->changes);
+ hub_free(g_backend);
+}
+
+/**
+ * Process the network backend.
+ */
+int net_backend_process()
+{
+
+}
+
+struct timeout_queue* net_backend_get_timeout_queue()
+{
+ return &g_backend->timeout_queue;
+}
+
+struct net_connection* net_con_create()
+{
+ struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_kqueue));
+ con->sd = -1;
+ return con;
+}
+
+void net_con_destroy(struct net_connection* con)
+{
+ hub_free(con);
+}
+
+void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr, int events)
+{
+ struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
+ con->sd = sd;
+ con->flags = 0;
+ con->callback = callback;
+ con->ev.events = 0;
+ con->ptr = (void*) ptr;
+ con->ev.data.ptr = (void*) con;
+
+ net_set_nonblocking(con->sd, 1);
+ net_set_nosigpipe(con->sd, 1);
+
+ /* FIXME */
+
+ g_backend->conns[sd] = con;
+ g_backend->num++;
+}
+
+void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
+{
+ con->callback = callback;
+ con->ptr = (void*) ptr;
+ net_con_update(con, events);
+}
+
+void net_con_update(struct net_connection* con_, int events)
+{
+ struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
+ /* FIXME */
+}
+
+void net_con_close(struct net_connection* con_)
+{
+ struct net_connection_epoll* con = (struct net_connection_kqueue*) con_;
+ if (con->flags & NET_CLEANUP)
+ return;
+
+ if (con->sd != -1)
+ {
+ g_backend->conns[con->sd] = 0;
+ g_backend->num--;
+ }
+
+ net_con_clear_timeout(con_);
+
+ /* FIXME */
+
+ net_close(con->sd);
+ con->sd = -1;
+
+ net_con_print("DEL", con);
+ net_cleanup_delayed_free(g_backend->cleaner, con_);
+}
+
+#endif /* USE_KQUEUE */
diff --git a/src/system.h b/src/system.h
index affc91b..70acdfd 100644
--- a/src/system.h
+++ b/src/system.h
@@ -104,8 +104,19 @@
#ifdef __linux__
#define USE_EPOLL
+#define HAVE_BACKEND
#include
-#else
+#endif
+
+/*
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+#define USE_KQUEUE
+#define HAVE_BACKEND
+#include
+#endif
+*/
+
+#ifndef HAVE_BACKEND
#define USE_SELECT
#include
#endif