diff --git a/GNUmakefile b/GNUmakefile
index 317fb14..75002f2 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -9,7 +9,7 @@ MV := mv
RANLIB := ranlib
CFLAGS += -pipe -Wall
USE_SSL ?= NO
-USE_LIBEVENT ?= YES
+USE_LIBEVENT ?= NO
USE_BIGENDIAN ?= AUTO
BITS ?= AUTO
SILENT ?= YES
diff --git a/src/core/hub.c b/src/core/hub.c
index ccea554..cb774b1 100644
--- a/src/core/hub.c
+++ b/src/core/hub.c
@@ -557,6 +557,7 @@ struct hub_info* hub_start_service(struct hub_config* config)
return 0;
}
+#ifdef USE_LIBEVENT
event_set(&hub->ev_accept, hub->fd_tcp, EV_READ | EV_PERSIST, net_on_accept, hub);
if (event_add(&hub->ev_accept, NULL) == -1)
{
@@ -565,6 +566,7 @@ struct hub_info* hub_start_service(struct hub_config* config)
net_close(server_tcp);
return 0;
}
+#endif
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
{
@@ -612,7 +614,9 @@ void hub_shutdown_service(struct hub_info* hub)
LOG_DEBUG("hub_shutdown_service()");
event_queue_shutdown(hub->queue);
+#ifdef USE_LIBEVENT
event_del(&hub->ev_accept);
+#endif
net_close(hub->fd_tcp);
uman_shutdown(hub);
hub->status = hub_status_stopped;
@@ -987,10 +991,10 @@ void hub_disconnect_all(struct hub_info* hub)
void hub_event_loop(struct hub_info* hub)
{
- int ret;
do
{
- ret = event_base_loop(net_get_evbase(), EVLOOP_ONCE);
+#ifdef USE_LIBEVENT
+ int ret = event_base_loop(net_get_evbase(), EVLOOP_ONCE);
if (ret != 0)
{
@@ -999,7 +1003,7 @@ void hub_event_loop(struct hub_info* hub)
if (ret < 0)
break;
-
+#endif
event_queue_process(hub->queue);
}
while (hub->status == hub_status_running || hub->status == hub_status_disabled);
diff --git a/src/core/hub.h b/src/core/hub.h
index b48b31f..37eb37f 100644
--- a/src/core/hub.h
+++ b/src/core/hub.h
@@ -91,8 +91,10 @@ struct hub_logout_info
struct hub_info
{
int fd_tcp;
+#ifdef USE_LIBEVENT
struct event ev_accept;
struct event ev_timer;
+#endif
struct hub_stats stats;
struct event_queue* queue;
struct hub_config* config;
diff --git a/src/core/main.c b/src/core/main.c
index b85f229..f47262d 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -33,7 +33,7 @@ static const char* arg_pid = 0;
static int arg_log_syslog = 0;
-#ifndef WIN32
+#if !defined(WIN32) && defined(USE_LIBEVENT)
void hub_handle_signal(int fd, short events, void* arg)
{
struct hub_info* hub = (struct hub_info*) arg;
@@ -97,7 +97,7 @@ void shutdown_signal_handlers(struct hub_info* hub)
}
}
-#endif /* WIN32 */
+#endif /* !WIN32 && USE_LIBEVENT*/
int main_loop()
@@ -133,7 +133,7 @@ int main_loop()
hub = hub_start_service(&configuration);
if (!hub)
return -1;
-#ifndef WIN32
+#if !defined(WIN32) && defined(USE_LIBEVENT)
setup_signal_handlers(hub);
#endif
}
@@ -148,7 +148,7 @@ int main_loop()
} while (hub->status == hub_status_restart);
-#ifndef WIN32
+#if !defined(WIN32) && defined(USE_LIBEVENT)
shutdown_signal_handlers(hub);
#endif
diff --git a/src/core/usermanager.c b/src/core/usermanager.c
index 1d992c6..1db3b78 100644
--- a/src/core/usermanager.c
+++ b/src/core/usermanager.c
@@ -71,6 +71,7 @@ void uman_print_stats(struct hub_info* hub)
}
#ifdef USERMANAGER_TIMER
+#ifdef USE_LIBEVENT
static void timer_statistics(int fd, short ev, void *arg)
{
struct hub_info* hub = (struct hub_info*) arg;
@@ -80,13 +81,16 @@ static void timer_statistics(int fd, short ev, void *arg)
evtimer_add(&hub->ev_timer, &timeout);
}
#endif
+#endif
int uman_init(struct hub_info* hub)
{
struct hub_user_manager* users = NULL;
#ifdef USERMANAGER_TIMER
+#ifdef USE_LIBEVENT
struct timeval timeout = { TIMEOUT_STATS, 0 };
+#endif
#endif
if (!hub)
return -1;
@@ -108,11 +112,13 @@ int uman_init(struct hub_info* hub)
hub->users = users;
#ifdef USERMANAGER_TIMER
+#ifdef USE_LIBEVENT
if (net_get_evbase())
{
evtimer_set(&hub->ev_timer, timer_statistics, hub);
evtimer_add(&hub->ev_timer, &timeout);
}
+#endif
#endif // 0
return 0;
}
@@ -124,8 +130,10 @@ int uman_shutdown(struct hub_info* hub)
return -1;
#ifdef USERMANAGER_TIMER
+#ifdef USE_LIBEVENT
if (evtimer_pending(&hub->ev_timer, 0))
evtimer_del(&hub->ev_timer);
+#endif
#endif
if (hub->users->list)
diff --git a/src/network/connection-common.c b/src/network/connection-common.c
index 26ed272..c60a46f 100644
--- a/src/network/connection-common.c
+++ b/src/network/connection-common.c
@@ -21,8 +21,6 @@
uint32_t flags; /** Connection flags */ \
void* ptr; /** data pointer */ \
net_connection_cb callback; /** Callback function */ \
- time_t last_recv; /** Timestamp for last recv() */ \
- time_t last_send; /** Timestamp for last send() */ \
#define NET_CON_STRUCT_SSL \
SSL* ssl; /** SSL handle */ \
diff --git a/src/network/connection-epoll.c b/src/network/connection-epoll.c
index e69de29..ff50c72 100644
--- a/src/network/connection-epoll.c
+++ b/src/network/connection-epoll.c
@@ -0,0 +1,183 @@
+/*
+ * uhub - A tiny ADC p2p connection hub
+ * Copyright (C) 2007-2009, 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 .
+ *
+ */
+
+#ifdef USE_EPOLL
+
+static int g_epfd = -1;
+
+struct net_connection
+{
+ int sd;
+ uint32_t flags;
+ net_connection_cb callback;
+ struct epoll_event ev;
+ struct timeout_evt* timeout;
+};
+
+struct net_connection* net_con_create()
+{
+ struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection));
+ 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)
+{
+ con->sd = sd;
+ con->flags = NET_INITIALIZED;
+ con->callback = callback;
+
+ con->ev.events = 0;
+ con->ev.data.ptr = (void*) ptr;
+
+ net_set_nonblocking(con->sd, 1);
+ net_set_nosigpipe(con->sd, 1);
+
+ if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
+ if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
+ if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
+ {
+ LOG_WARN("epoll_ctl() add failed.");
+ }
+}
+
+void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
+{
+ con->callback = callback;
+ con->ev.data.ptr = (void*) ptr;
+ net_con_update(con, events);
+}
+
+void net_con_update(struct net_connection* con, int events)
+{
+ con->ev.events = 0;
+ if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
+ if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
+
+ if (epoll_ctl(g_epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
+ {
+ LOG_WARN("epoll_ctl() modify failed.");
+ }
+}
+
+int net_con_close(struct net_connection* con)
+{
+ if (!(con->flags & NET_INITIALIZED))
+ return 0;
+
+ con->flags &= ~NET_INITIALIZED;
+ if (epoll_ctl(g_epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
+ {
+ LOG_WARN("epoll_ctl() delete failed.");
+ }
+ return 0;
+}
+
+
+int net_con_get_sd(struct net_connection* con)
+{
+ return con->sd;
+}
+
+void* net_con_get_ptr(struct net_connection* con)
+{
+ return con->ev.data.ptr;
+}
+
+ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
+{
+ int ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
+ if (ret == -1)
+ {
+ if (net_error() == EWOULDBLOCK || net_error() == EINTR)
+ return 0;
+ return -1;
+ }
+ return ret;
+}
+
+ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
+{
+ uhub_assert(con);
+
+#ifdef SSL_SUPPORT
+ if (!con->ssl)
+ {
+#endif
+ int ret = net_recv(con->sd, buf, len, 0);
+#ifdef NETWORK_DUMP_DEBUG
+ LOG_PROTO("net_recv: ret=%d", ret);
+#endif
+ if (ret == -1)
+ {
+ if (net_error() == EWOULDBLOCK || net_error() == EINTR)
+ return 0;
+ return -1;
+ }
+ return ret;
+#ifdef SSL_SUPPORT
+ }
+ else
+ {
+ int ret = SSL_read(con->ssl, buf, len);
+#ifdef NETWORK_DUMP_DEBUG
+ LOG_PROTO("net_recv: ret=%d", ret);
+#endif
+ if (ret > 0)
+ {
+ con->last_recv = time(0);
+ net_con_flag_unset(con, NET_WANT_SSL_WRITE);
+ }
+ else
+ {
+ return handle_openssl_error(con, ret);
+ }
+ return ret;
+ }
+#endif
+}
+
+ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
+{
+ int ret = net_recv(con->sd, buf, len, MSG_PEEK);
+ if (ret == -1)
+ {
+ if (net_error() == EWOULDBLOCK || net_error() == EINTR)
+ return 0;
+ return -1;
+ }
+ return ret;
+}
+
+void net_con_set_timeout(struct net_connection* con, int seconds)
+{
+ uhub_assert(con);
+ if (!con->timeout)
+ {
+ con->timeout = hub_malloc(sizeof(struct timeout_evt));
+ timeout_evt_initialize(con->timeout, timeout_callback, con);
+ }
+}
+
+
+#endif /* USE_EPOLL */
\ No newline at end of file
diff --git a/src/network/connection-libevent.c b/src/network/connection-libevent.c
index 725c7f3..96e5a49 100644
--- a/src/network/connection-libevent.c
+++ b/src/network/connection-libevent.c
@@ -26,6 +26,14 @@ struct net_connection
struct event timeout; /** Used for internal timeout handling */
};
+struct net_timer
+{
+ unsigned int initialized;
+ struct event timeout;
+ net_timeout_cb callback;
+ void* ptr;
+};
+
int net_con_get_sd(struct net_connection* con)
{
return con->sd;
@@ -81,6 +89,26 @@ static inline int net_con_convert_from_libevent_mask(int ev)
static void net_con_event(int fd, short ev, void *arg);
+
+int net_con_close(struct net_connection* con)
+{
+ uhub_assert(con);
+
+ con->ptr = 0;
+
+ if (net_con_flag_get(con, NET_CLEANUP))
+ return 0;
+
+ if (net_con_flag_get(con, NET_PROCESSING_BUSY))
+ {
+ net_con_flag_set(con, NET_CLEANUP);
+ return 0;
+ }
+
+ net_con_after_close(con);
+ return 1;
+}
+
static void net_con_set(struct net_connection* con)
{
uhub_assert(con);
@@ -265,4 +293,321 @@ static void net_con_event(int fd, short ev, void *arg)
}
}
+
+static void net_timer_event(int fd, short ev, void *arg)
+{
+ struct net_timer* timer = (struct net_timer*) arg;
+ timer->callback(timer, timer->ptr);
+}
+
+void net_timer_initialize(struct net_timer* timer, net_timeout_cb callback, void* ptr)
+{
+ timer->initialized = 0;
+ timer->callback = callback;
+ timer->ptr = ptr;
+}
+
+void net_timer_reset(struct net_timer* timer, int seconds)
+{
+ struct timeval timeout = { seconds, 0 };
+ if (timer->initialized)
+ {
+ evtimer_del(&timer->timeout);
+ timer->initialized = 0;
+ }
+ evtimer_set(&timer->timeout, net_timer_event, timer);
+ evtimer_add(&timer->timeout, &timeout);
+}
+
+void net_timer_shutdown(struct net_timer* timer)
+{
+ if (timer->initialized)
+ {
+ evtimer_del(&timer->timeout);
+ timer->initialized = 0;
+ }
+ timer->callback = 0;
+ timer->ptr = 0;
+}
+
+#ifdef SSL_SUPPORT
+static int handle_openssl_error(struct net_connection* con, int ret)
+{
+ uhub_assert(con);
+
+ int error = SSL_get_error(con->ssl, ret);
+ switch (error)
+ {
+ case SSL_ERROR_ZERO_RETURN:
+ LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
+ return -1;
+
+ case SSL_ERROR_WANT_READ:
+ LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
+ net_con_update(con, EV_READ);
+ net_con_flag_set(con, NET_WANT_SSL_READ);
+ return 0;
+
+ case SSL_ERROR_WANT_WRITE:
+ LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
+ net_con_update(con, EV_READ | EV_WRITE);
+ net_con_flag_set(con, NET_WANT_SSL_WRITE);
+ return 0;
+
+ case SSL_ERROR_WANT_CONNECT:
+ LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_CONNECT", ret, error);
+ net_con_update(con, EV_READ | EV_WRITE);
+ net_con_flag_set(con, NET_WANT_SSL_CONNECT);
+ return 0;
+
+ case SSL_ERROR_WANT_ACCEPT:
+ LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_ACCEPT", ret, error);
+ net_con_update(con, EV_READ | EV_WRITE);
+ net_con_flag_set(con, NET_WANT_SSL_ACCEPT);
+ return 0;
+
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_X509_LOOKUP", ret, error);
+ return 0;
+
+ case SSL_ERROR_SYSCALL:
+ LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error);
+ /* if ret == 0, connection closed, if ret == -1, check with errno */
+ if (ret == 0)
+ return -1;
+ else
+ return -net_error();
+
+ case SSL_ERROR_SSL:
+ LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
+ /* internal openssl error */
+ return -1;
+ }
+
+ return -1;
+}
+#endif
+
+
+ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
+{
+ uhub_assert(con);
+
+#ifdef SSL_SUPPORT
+ if (!con->ssl)
+ {
+#endif
+ int ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
+#ifdef NETWORK_DUMP_DEBUG
+ LOG_PROTO("net_send: ret=%d", ret);
+#endif
+ if (ret > 0)
+ {
+ con->last_send = time(0);
+ }
+ else if (ret == -1 && (net_error() == EWOULDBLOCK || net_error() == EINTR))
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ return ret;
+#ifdef SSL_SUPPORT
+ }
+ else
+ {
+ if (net_con_flag_get(con, NET_WANT_SSL_READ) && con->write_len)
+ len = con->write_len;
+
+ int ret = SSL_write(con->ssl, buf, len);
+#ifdef NETWORK_DUMP_DEBUG
+ LOG_PROTO("net_send: ret=%d", ret);
+#endif
+ if (ret > 0)
+ {
+ con->last_send = time(0);
+ net_con_flag_unset(con, NET_WANT_SSL_READ);
+ con->write_len = 0;
+ }
+ else
+ {
+ con->write_len = len;
+ return handle_openssl_error(con, ret);
+ }
+ return ret;
+ }
+#endif
+}
+
+ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
+{
+ uhub_assert(con);
+
+#ifdef SSL_SUPPORT
+ if (!con->ssl)
+ {
+#endif
+ int ret = net_recv(con->sd, buf, len, 0);
+#ifdef NETWORK_DUMP_DEBUG
+ LOG_PROTO("net_recv: ret=%d", ret);
+#endif
+ if (ret > 0)
+ {
+ con->last_recv = time(0);
+ }
+ else if (ret == -1 && (net_error() == EWOULDBLOCK || net_error() == EINTR))
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ return ret;
+#ifdef SSL_SUPPORT
+ }
+ else
+ {
+ int ret = SSL_read(con->ssl, buf, len);
+#ifdef NETWORK_DUMP_DEBUG
+ LOG_PROTO("net_recv: ret=%d", ret);
+#endif
+ if (ret > 0)
+ {
+ con->last_recv = time(0);
+ net_con_flag_unset(con, NET_WANT_SSL_WRITE);
+ }
+ else
+ {
+ return handle_openssl_error(con, ret);
+ }
+ return ret;
+ }
+#endif
+}
+
+ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
+{
+ uhub_assert(con);
+
+#ifdef SSL_SUPPORT
+ if (!con->ssl)
+ {
+#endif
+ int ret = net_recv(con->sd, buf, len, MSG_PEEK);
+#ifdef NETWORK_DUMP_DEBUG
+ LOG_PROTO("net_recv: ret=%d (MSG_PEEK)", ret);
+#endif
+ if (ret > 0)
+ {
+ con->last_recv = time(0);
+ }
+ else if (ret == -1 && (net_error() == EWOULDBLOCK || net_error() == EINTR))
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ return ret;
+#ifdef SSL_SUPPORT
+ }
+ else
+ {
+ // FIXME: Not able to do this!
+ return 0;
+ }
+#endif
+}
+
+void net_con_set_timeout(struct net_connection* con, int seconds)
+{
+ uhub_assert(con);
+
+ struct timeval timeout = { seconds, 0 };
+ net_con_clear_timeout(con);
+
+ evtimer_set(&con->timeout, net_con_event, con);
+ evtimer_add(&con->timeout, &timeout);
+ net_con_flag_set(con, NET_TIMER_ENABLED);
+}
+
+void net_con_clear_timeout(struct net_connection* con)
+{
+ uhub_assert(con);
+
+ if (net_con_flag_get(con, NET_TIMER_ENABLED))
+ {
+ evtimer_del(&con->timeout);
+ net_con_flag_unset(con, NET_TIMER_ENABLED);
+ }
+}
+
+
+#ifdef SSL_SUPPORT
+ssize_t net_con_ssl_accept(struct net_connection* con)
+{
+ uhub_assert(con);
+
+ net_con_flag_set(con, NET_WANT_SSL_ACCEPT);
+ ssize_t ret = SSL_accept(con->ssl);
+#ifdef NETWORK_DUMP_DEBUG
+ LOG_PROTO("SSL_accept() ret=%d", ret);
+#endif
+ if (ret > 0)
+ {
+ net_con_flag_unset(con, NET_WANT_SSL_ACCEPT);
+ net_con_flag_unset(con, NET_WANT_SSL_READ);
+ }
+ else
+ {
+ return handle_openssl_error(con, ret);
+ }
+ return ret;
+}
+
+ssize_t net_con_ssl_connect(struct net_connection* con)
+{
+ uhub_assert(con);
+
+ net_con_flag_set(con, NET_WANT_SSL_CONNECT);
+ ssize_t ret = SSL_connect(con->ssl);
+#ifdef NETWORK_DUMP_DEBUG
+ LOG_PROTO("SSL_connect() ret=%d", ret);
+#endif
+ if (ret > 0)
+ {
+ net_con_flag_unset(con, NET_WANT_SSL_CONNECT);
+ net_con_flag_unset(con, NET_WANT_SSL_WRITE);
+ }
+ else
+ {
+ return handle_openssl_error(con, ret);
+ }
+ return ret;
+}
+
+ssize_t net_con_ssl_handshake(struct net_connection* con, int ssl_mode)
+{
+ uhub_assert(con);
+
+ if (ssl_mode == net_con_ssl_mode_server)
+ {
+ con->ssl = SSL_new(g_hub->ssl_ctx);
+ SSL_set_fd(con->ssl, con->sd);
+ return net_con_ssl_accept(con);
+ }
+ else
+ {
+ con->ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
+ SSL_set_fd(con->ssl, con->sd);
+ return net_con_ssl_connect(con);
+ }
+}
+#endif /* SSL_SUPPORT */
+
+
#endif /* USE_LIBEVENT */
diff --git a/src/network/connection.c b/src/network/connection.c
index 9c0d9c8..082e3ff 100644
--- a/src/network/connection.c
+++ b/src/network/connection.c
@@ -19,343 +19,8 @@
#include "uhub.h"
#include "network/connection-common.c"
+#include "network/connection-timeout.c"
#include "network/connection-libevent.c"
#include "network/connection-epoll.c"
-extern struct hub_info* g_hub;
-int net_con_close(struct net_connection* con)
-{
- uhub_assert(con);
-
- con->ptr = 0;
-
- if (net_con_flag_get(con, NET_CLEANUP))
- return 0;
-
- if (net_con_flag_get(con, NET_PROCESSING_BUSY))
- {
- net_con_flag_set(con, NET_CLEANUP);
- return 0;
- }
-
- net_con_after_close(con);
- return 1;
-}
-
-#ifdef SSL_SUPPORT
-static int handle_openssl_error(struct net_connection* con, int ret)
-{
- uhub_assert(con);
-
- int error = SSL_get_error(con->ssl, ret);
- switch (error)
- {
- case SSL_ERROR_ZERO_RETURN:
- LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
- return -1;
-
- case SSL_ERROR_WANT_READ:
- LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
- net_con_update(con, EV_READ);
- net_con_flag_set(con, NET_WANT_SSL_READ);
- return 0;
-
- case SSL_ERROR_WANT_WRITE:
- LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
- net_con_update(con, EV_READ | EV_WRITE);
- net_con_flag_set(con, NET_WANT_SSL_WRITE);
- return 0;
-
- case SSL_ERROR_WANT_CONNECT:
- LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_CONNECT", ret, error);
- net_con_update(con, EV_READ | EV_WRITE);
- net_con_flag_set(con, NET_WANT_SSL_CONNECT);
- return 0;
-
- case SSL_ERROR_WANT_ACCEPT:
- LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_ACCEPT", ret, error);
- net_con_update(con, EV_READ | EV_WRITE);
- net_con_flag_set(con, NET_WANT_SSL_ACCEPT);
- return 0;
-
- case SSL_ERROR_WANT_X509_LOOKUP:
- LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_X509_LOOKUP", ret, error);
- return 0;
-
- case SSL_ERROR_SYSCALL:
- LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error);
- /* if ret == 0, connection closed, if ret == -1, check with errno */
- if (ret == 0)
- return -1;
- else
- return -net_error();
-
- case SSL_ERROR_SSL:
- LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
- /* internal openssl error */
- return -1;
- }
-
- return -1;
-}
-#endif
-
-
-ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
-{
- uhub_assert(con);
-
-#ifdef SSL_SUPPORT
- if (!con->ssl)
- {
-#endif
- int ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
-#ifdef NETWORK_DUMP_DEBUG
- LOG_PROTO("net_send: ret=%d", ret);
-#endif
- if (ret > 0)
- {
- con->last_send = time(0);
- }
- else if (ret == -1 && (net_error() == EWOULDBLOCK || net_error() == EINTR))
- {
- return 0;
- }
- else
- {
- return -1;
- }
- return ret;
-#ifdef SSL_SUPPORT
- }
- else
- {
- if (net_con_flag_get(con, NET_WANT_SSL_READ) && con->write_len)
- len = con->write_len;
-
- int ret = SSL_write(con->ssl, buf, len);
-#ifdef NETWORK_DUMP_DEBUG
- LOG_PROTO("net_send: ret=%d", ret);
-#endif
- if (ret > 0)
- {
- con->last_send = time(0);
- net_con_flag_unset(con, NET_WANT_SSL_READ);
- con->write_len = 0;
- }
- else
- {
- con->write_len = len;
- return handle_openssl_error(con, ret);
- }
- return ret;
- }
-#endif
-
-
-}
-
-ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
-{
- uhub_assert(con);
-
-#ifdef SSL_SUPPORT
- if (!con->ssl)
- {
-#endif
- int ret = net_recv(con->sd, buf, len, 0);
-#ifdef NETWORK_DUMP_DEBUG
- LOG_PROTO("net_recv: ret=%d", ret);
-#endif
- if (ret > 0)
- {
- con->last_recv = time(0);
- }
- else if (ret == -1 && (net_error() == EWOULDBLOCK || net_error() == EINTR))
- {
- return 0;
- }
- else
- {
- return -1;
- }
- return ret;
-#ifdef SSL_SUPPORT
- }
- else
- {
- int ret = SSL_read(con->ssl, buf, len);
-#ifdef NETWORK_DUMP_DEBUG
- LOG_PROTO("net_recv: ret=%d", ret);
-#endif
- if (ret > 0)
- {
- con->last_recv = time(0);
- net_con_flag_unset(con, NET_WANT_SSL_WRITE);
- }
- else
- {
- return handle_openssl_error(con, ret);
- }
- return ret;
- }
-#endif
-}
-
-ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
-{
- uhub_assert(con);
-
-#ifdef SSL_SUPPORT
- if (!con->ssl)
- {
-#endif
- int ret = net_recv(con->sd, buf, len, MSG_PEEK);
-#ifdef NETWORK_DUMP_DEBUG
- LOG_PROTO("net_recv: ret=%d (MSG_PEEK)", ret);
-#endif
- if (ret > 0)
- {
- con->last_recv = time(0);
- }
- else if (ret == -1 && (net_error() == EWOULDBLOCK || net_error() == EINTR))
- {
- return 0;
- }
- else
- {
- return -1;
- }
- return ret;
-#ifdef SSL_SUPPORT
- }
- else
- {
- // FIXME: Not able to do this!
- return 0;
- }
-#endif
-}
-
-void net_con_set_timeout(struct net_connection* con, int seconds)
-{
- uhub_assert(con);
-
- struct timeval timeout = { seconds, 0 };
- net_con_clear_timeout(con);
-
- evtimer_set(&con->timeout, net_con_event, con);
- evtimer_add(&con->timeout, &timeout);
- net_con_flag_set(con, NET_TIMER_ENABLED);
-}
-
-void net_con_clear_timeout(struct net_connection* con)
-{
- uhub_assert(con);
-
- if (net_con_flag_get(con, NET_TIMER_ENABLED))
- {
- evtimer_del(&con->timeout);
- net_con_flag_unset(con, NET_TIMER_ENABLED);
- }
-}
-
-
-#ifdef SSL_SUPPORT
-ssize_t net_con_ssl_accept(struct net_connection* con)
-{
- uhub_assert(con);
-
- net_con_flag_set(con, NET_WANT_SSL_ACCEPT);
- ssize_t ret = SSL_accept(con->ssl);
-#ifdef NETWORK_DUMP_DEBUG
- LOG_PROTO("SSL_accept() ret=%d", ret);
-#endif
- if (ret > 0)
- {
- net_con_flag_unset(con, NET_WANT_SSL_ACCEPT);
- net_con_flag_unset(con, NET_WANT_SSL_READ);
- }
- else
- {
- return handle_openssl_error(con, ret);
- }
- return ret;
-}
-
-ssize_t net_con_ssl_connect(struct net_connection* con)
-{
- uhub_assert(con);
-
- net_con_flag_set(con, NET_WANT_SSL_CONNECT);
- ssize_t ret = SSL_connect(con->ssl);
-#ifdef NETWORK_DUMP_DEBUG
- LOG_PROTO("SSL_connect() ret=%d", ret);
-#endif
- if (ret > 0)
- {
- net_con_flag_unset(con, NET_WANT_SSL_CONNECT);
- net_con_flag_unset(con, NET_WANT_SSL_WRITE);
- }
- else
- {
- return handle_openssl_error(con, ret);
- }
- return ret;
-}
-
-ssize_t net_con_ssl_handshake(struct net_connection* con, int ssl_mode)
-{
- uhub_assert(con);
-
- if (ssl_mode == NET_CON_SSL_MODE_SERVER)
- {
- con->ssl = SSL_new(g_hub->ssl_ctx);
- SSL_set_fd(con->ssl, con->sd);
- return net_con_ssl_accept(con);
- }
- else
- {
- con->ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
- SSL_set_fd(con->ssl, con->sd);
- return net_con_ssl_connect(con);
- }
-}
-#endif /* SSL_SUPPORT */
-
-static void net_timer_event(int fd, short ev, void *arg)
-{
- struct net_timer* timer = (struct net_timer*) arg;
- timer->callback(timer, timer->ptr);
-}
-
-void net_timer_initialize(struct net_timer* timer, net_timeout_cb callback, void* ptr)
-{
- timer->initialized = 0;
- timer->callback = callback;
- timer->ptr = ptr;
-}
-
-void net_timer_reset(struct net_timer* timer, int seconds)
-{
- struct timeval timeout = { seconds, 0 };
- if (timer->initialized)
- {
- evtimer_del(&timer->timeout);
- timer->initialized = 0;
- }
- evtimer_set(&timer->timeout, net_timer_event, timer);
- evtimer_add(&timer->timeout, &timeout);
-}
-
-void net_timer_shutdown(struct net_timer* timer)
-{
- if (timer->initialized)
- {
- evtimer_del(&timer->timeout);
- timer->initialized = 0;
- }
- timer->callback = 0;
- timer->ptr = 0;
-}
diff --git a/src/network/connection.h b/src/network/connection.h
index 29c7fa5..4f91cf5 100644
--- a/src/network/connection.h
+++ b/src/network/connection.h
@@ -31,18 +31,20 @@
struct net_connection;
struct net_timer;
+/**
+ * Initialize the network backend.
+ * Returns 1 on success, or 0 on failure.
+ */
+extern int net_backend_initialize();
+
+/**
+ * Shutdown the network connection backend.
+ */
+extern void net_backend_shutdown();
+
typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr);
typedef void (*net_timeout_cb)(struct net_timer*, void* ptr);
-struct net_timer
-{
- unsigned int initialized;
- struct event timeout;
- net_timeout_cb callback;
- void* ptr;
-};
-
-
extern void net_timer_initialize(struct net_timer* timer, net_timeout_cb callback, void* ptr);
extern void net_timer_reset(struct net_timer* timer, int seconds);
extern void net_timer_shutdown(struct net_timer* timer);
@@ -108,9 +110,13 @@ extern ssize_t net_con_ssl_accept(struct net_connection*);
*/
extern ssize_t net_con_ssl_connect(struct net_connection*);
-#define NET_CON_SSL_MODE_SERVER 1
-#define NET_CON_SSL_MODE_CLIENT 2
-extern ssize_t net_con_ssl_handshake(struct net_connection* con, int ssl_mode);
+enum net_con_ssl_mode
+{
+ net_con_ssl_mode_server,
+ net_con_ssl_mode_client,
+};
+
+extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, void* ssl_ctx);
#endif /* SSL_SUPPORT */
diff --git a/src/network/network.c b/src/network/network.c
index 773885a..9bbc9c8 100644
--- a/src/network/network.c
+++ b/src/network/network.c
@@ -21,7 +21,9 @@
static int is_ipv6_supported = -1; /* -1 = CHECK, 0 = NO, 1 = YES */
static int net_initialized = 0;
+#ifdef USE_LIBEVENT
static struct event_base* net_evbase = 0;
+#endif
static struct net_statistics stats;
static struct net_statistics stats_total;
@@ -47,6 +49,7 @@ int net_initialize()
}
#endif /* WINSOCK */
+#ifdef USE_LIBEVENT
net_evbase = event_init();
if (!net_evbase)
{
@@ -54,6 +57,7 @@ int net_initialize()
return 0;
}
LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method());
+#endif
net_stats_initialize();
@@ -98,8 +102,10 @@ int net_destroy()
{
LOG_TRACE("Shutting down network monitor");
+#ifdef USE_LIBEVENT
event_base_free(net_evbase);
net_evbase = 0;
+#endif
#ifdef SSL_SUPPORT
/* FIXME: Shutdown OpenSSL here. */
@@ -114,10 +120,12 @@ int net_destroy()
return -1;
}
+#ifdef USE_LIBEVENT
struct event_base* net_get_evbase()
{
return net_evbase;
}
+#endif
static void net_error_out(int fd, const char* func)
{
diff --git a/src/system.h b/src/system.h
index 44e89dc..2af2ff5 100644
--- a/src/system.h
+++ b/src/system.h
@@ -104,6 +104,11 @@
#ifdef USE_LIBEVENT
#include
+#else
+#ifdef __linux__
+#define USE_EPOLL
+#include
+#endif
#endif
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__)
diff --git a/src/uhub.h b/src/uhub.h
index 413a0c6..02a77d7 100644
--- a/src/uhub.h
+++ b/src/uhub.h
@@ -63,6 +63,7 @@ extern "C" {
#include "util/log.h"
#include "util/memory.h"
#include "util/misc.h"
+#include "util/timeout.h"
#include "util/tiger.h"
#include "adc/sid.h"