From 6a4b9c58f433d01822ce2ae1176aea9db81155b9 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Thu, 7 Jan 2010 20:55:13 +0100 Subject: [PATCH] Work on removing libevent completely as a mandatory dependency. --- GNUmakefile | 2 +- src/core/hub.c | 10 +- src/core/hub.h | 2 + src/core/main.c | 8 +- src/core/usermanager.c | 8 + src/network/connection-common.c | 2 - src/network/connection-epoll.c | 183 ++++++++++++++++ src/network/connection-libevent.c | 345 ++++++++++++++++++++++++++++++ src/network/connection.c | 337 +---------------------------- src/network/connection.h | 30 +-- src/network/network.c | 8 + src/system.h | 5 + src/uhub.h | 1 + 13 files changed, 583 insertions(+), 358 deletions(-) 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"