From 1c58a85de107a8f9825efc89a434f2e50c5fe7c2 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Sun, 17 Jan 2010 22:59:51 +0100 Subject: [PATCH] More work on epoll. --- src/core/config.c | 2 +- src/core/config.h | 2 +- src/core/hub.c | 35 +++--------- src/core/hub.h | 4 +- src/core/netevent.c | 3 +- src/core/netevent.h | 3 +- src/core/probe.c | 2 +- src/core/probe.h | 2 +- src/network/connection-epoll.c | 95 +++++++++++++++++++++++++++++-- src/network/connection-libevent.c | 41 +++++++++++++ src/network/connection.h | 7 +++ src/network/network.c | 22 ++----- 12 files changed, 160 insertions(+), 58 deletions(-) diff --git a/src/core/config.c b/src/core/config.c index 7015aa5..a40abc3 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * 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 diff --git a/src/core/config.h b/src/core/config.h index 010247b..6093688 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * 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 diff --git a/src/core/hub.c b/src/core/hub.c index cb774b1..4e8065f 100644 --- a/src/core/hub.c +++ b/src/core/hub.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * 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 @@ -546,7 +546,7 @@ struct hub_info* hub_start_service(struct hub_config* config) } #endif - hub->fd_tcp = server_tcp; + hub->config = config; hub->users = NULL; @@ -557,17 +557,6 @@ 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) - { - uman_shutdown(hub); - hub_free(hub); - net_close(server_tcp); - return 0; - } -#endif - if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1) { uman_shutdown(hub); @@ -604,6 +593,9 @@ struct hub_info* hub_start_service(struct hub_config* config) hub->status = hub_status_running; + hub->server = net_con_create(); + net_con_initialize(hub->server, server_tcp, net_on_accept, hub, NET_EVENT_READ); + g_hub = hub; return hub; } @@ -617,7 +609,8 @@ void hub_shutdown_service(struct hub_info* hub) #ifdef USE_LIBEVENT event_del(&hub->ev_accept); #endif - net_close(hub->fd_tcp); + net_con_close(hub->server); + hub_free(hub->server); uman_shutdown(hub); hub->status = hub_status_stopped; hub_free(hub->sendbuf); @@ -993,18 +986,8 @@ void hub_event_loop(struct hub_info* hub) { do { -#ifdef USE_LIBEVENT - int ret = event_base_loop(net_get_evbase(), EVLOOP_ONCE); - - if (ret != 0) - { - LOG_DEBUG("event_base_loop returned: %d", (int) ret); - } - - if (ret < 0) - break; -#endif - event_queue_process(hub->queue); + net_backend_process(); + 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 37eb37f..14e0de1 100644 --- a/src/core/hub.h +++ b/src/core/hub.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * 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 @@ -90,7 +90,7 @@ struct hub_logout_info struct hub_info { - int fd_tcp; + struct net_connection* server; #ifdef USE_LIBEVENT struct event ev_accept; struct event ev_timer; diff --git a/src/core/netevent.c b/src/core/netevent.c index 3631e27..a487c4f 100644 --- a/src/core/netevent.c +++ b/src/core/netevent.c @@ -215,12 +215,13 @@ void net_event(struct net_connection* con, int event, void *arg) } } -void net_on_accept(int server_fd, short event, void *arg) +void net_on_accept(struct net_connection* con, int event, void *arg) { struct hub_info* hub = (struct hub_info*) arg; struct hub_probe* probe = 0; struct ip_addr_encap ipaddr; const char* addr; + int server_fd = net_con_get_sd(con); for (;;) { diff --git a/src/core/netevent.h b/src/core/netevent.h index ed0e099..22f2ec8 100644 --- a/src/core/netevent.h +++ b/src/core/netevent.h @@ -23,8 +23,7 @@ /** * Network callback to accept incoming connections. */ -extern void net_on_accept(int fd, short ev, void *arg); - +extern void net_on_accept(struct net_connection* con, int event, void *arg); extern void net_event(struct net_connection* con, int event, void *arg); extern int handle_net_read(struct hub_user* user); diff --git a/src/core/probe.c b/src/core/probe.c index f6d7896..73a0f5c 100644 --- a/src/core/probe.c +++ b/src/core/probe.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * 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 diff --git a/src/core/probe.h b/src/core/probe.h index f4db19f..b204efb 100644 --- a/src/core/probe.h +++ b/src/core/probe.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * 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 diff --git a/src/network/connection-epoll.c b/src/network/connection-epoll.c index ff50c72..67a3373 100644 --- a/src/network/connection-epoll.c +++ b/src/network/connection-epoll.c @@ -19,7 +19,7 @@ #ifdef USE_EPOLL -static int g_epfd = -1; +#define EPOLL_EVBUFFER 512 struct net_connection { @@ -28,8 +28,82 @@ struct net_connection net_connection_cb callback; struct epoll_event ev; struct timeout_evt* timeout; + void* ptr; }; +struct net_backend +{ + int epfd; + size_t num; + size_t max; + struct net_connection** conns; + struct epoll_event events[EPOLL_EVBUFFER]; +}; + +static struct net_backend* g_backend = 0; + +/** + * Initialize the network backend. + * Returns 1 on success, or 0 on failure. + */ +int net_backend_initialize() +{ + size_t max = net_get_max_sockets(); + g_backend = hub_malloc(sizeof(struct net_backend)); + g_backend->epfd = epoll_create(max); + if (g_backend->epfd == -1) + { + LOG_WARN("Unable to create epoll socket."); + return 0; + } + + g_backend->num = 0; + g_backend->max = max; + g_backend->conns = hub_malloc_zero(sizeof(struct net_connection*) * max); + memset(g_backend->events, 0, sizeof(g_backend->events)); + + return 1; +} + +/** + * Shutdown the network connection backend. + */ +void net_backend_shutdown() +{ + close(g_backend->epfd); + hub_free(g_backend->conns); + hub_free(g_backend); +} + +/** + * Process the network backend. + */ +int net_backend_process() +{ + int n; + int res = epoll_wait(g_backend->epfd, g_backend->events, EPOLL_EVBUFFER, 1000); + if (res == -1) + { + return 0; + } + + for (n = 0; n < res; n++) + { + struct net_connection* con = (struct net_connection*) g_backend->events[n].data.ptr; + if (con && con->callback) + { + con->callback(con, g_backend->events[n].events, con->ptr); + } + else + { + LOG_WARN("Con == NULL"); + } + + } + return 1; +} + + struct net_connection* net_con_create() { struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection)); @@ -55,7 +129,11 @@ void net_con_initialize(struct net_connection* con, int sd, net_connection_cb ca 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) + + g_backend->conns[sd] = con; + g_backend->num++; + + if (epoll_ctl(g_backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1) { LOG_WARN("epoll_ctl() add failed."); } @@ -74,7 +152,7 @@ void net_con_update(struct net_connection* con, int events) 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) + if (epoll_ctl(g_backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1) { LOG_WARN("epoll_ctl() modify failed."); } @@ -86,7 +164,14 @@ int net_con_close(struct net_connection* con) return 0; con->flags &= ~NET_INITIALIZED; - if (epoll_ctl(g_epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1) + + if (con->sd != -1) + { + g_backend->conns[con->sd] = 0; + g_backend->num--; + } + + if (epoll_ctl(g_backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1) { LOG_WARN("epoll_ctl() delete failed."); } @@ -180,4 +265,4 @@ void net_con_set_timeout(struct net_connection* con, int seconds) } -#endif /* USE_EPOLL */ \ No newline at end of file +#endif /* USE_EPOLL */ diff --git a/src/network/connection-libevent.c b/src/network/connection-libevent.c index 96e5a49..bebfda4 100644 --- a/src/network/connection-libevent.c +++ b/src/network/connection-libevent.c @@ -609,5 +609,46 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, int ssl_mode) } #endif /* SSL_SUPPORT */ +static struct event_base g_evbase = 0; + +/** + * Initialize the network backend. + * Returns 1 on success, or 0 on failure. + */ +int net_backend_initialize() +{ + g_evbase = event_init(); + if (!g_evbase) + { + LOG_ERROR("Unable to initialize libevent."); + return 0; + } + LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method()); + return 1; +} + +/** + * Shutdown the network connection backend. + */ +void net_backend_shutdown() +{ + event_base_free(g_evbase); +} + +/** + * Process the network backend. + */ +int net_backend_process() +{ + int ret = event_base_loop(g_evbase, EVLOOP_ONCE); + if (ret != 0) + { + LOG_DEBUG("event_base_loop returned: %d", (int) ret); + } + if (ret < 0) + return 0; + return 1; +} + #endif /* USE_LIBEVENT */ diff --git a/src/network/connection.h b/src/network/connection.h index 4f91cf5..816f2d8 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -30,6 +30,7 @@ struct net_connection; struct net_timer; +struct net_backend; /** * Initialize the network backend. @@ -42,6 +43,12 @@ extern int net_backend_initialize(); */ extern void net_backend_shutdown(); +/** + * Process the network backend. + */ +extern int net_backend_process(); + + typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr); typedef void (*net_timeout_cb)(struct net_timer*, void* ptr); diff --git a/src/network/network.c b/src/network/network.c index 9bbc9c8..18ca732 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -21,9 +21,7 @@ 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; @@ -49,16 +47,7 @@ int net_initialize() } #endif /* WINSOCK */ -#ifdef USE_LIBEVENT - net_evbase = event_init(); - if (!net_evbase) - { - LOG_ERROR("Unable to initialize libevent."); - return 0; - } - LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method()); -#endif - + net_backend_initialize(); net_stats_initialize(); #ifdef SSL_SUPPORT @@ -102,11 +91,8 @@ int net_destroy() { LOG_TRACE("Shutting down network monitor"); -#ifdef USE_LIBEVENT - event_base_free(net_evbase); - net_evbase = 0; -#endif - + net_backend_shutdown(); + #ifdef SSL_SUPPORT /* FIXME: Shutdown OpenSSL here. */ #endif