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