From eca0f931bd425ce2aa02e067194d7cd86a578b92 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Mon, 3 Aug 2009 23:59:02 +0200 Subject: [PATCH] Fixes to shutdown... --- src/core/eventid.h | 4 ++ src/core/hub.c | 125 ++++++++++++++++++++++++--------------- src/core/hub.h | 1 - src/core/main.c | 4 +- src/core/user.c | 3 - src/core/usermanager.c | 8 +-- src/core/usermanager.h | 2 +- src/network/connection.c | 13 ++-- src/network/network.c | 23 ++++++- src/network/network.h | 2 + 10 files changed, 120 insertions(+), 65 deletions(-) diff --git a/src/core/eventid.h b/src/core/eventid.h index 277ade2..83bb85c 100644 --- a/src/core/eventid.h +++ b/src/core/eventid.h @@ -28,10 +28,14 @@ /* Send a broadcast message */ #define UHUB_EVENT_BROADCAST 0x2000 +/* Shutdown hub */ +#define UHUB_EVENT_HUB_SHUTDOWN 0x3001 + /* Statistics, OOM, reconfigure */ #define UHUB_EVENT_STATISTICS 0x4000 #define UHUB_EVENT_OUT_OF_MEMORY 0x4001 #define UHUB_EVENT_RECONFIGURE 0x4002 + #endif /* HAVE_UHUB_EVENT_ID_H */ diff --git a/src/core/hub.c b/src/core/hub.c index 0034167..2ebce5b 100644 --- a/src/core/hub.c +++ b/src/core/hub.c @@ -104,10 +104,9 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess on_login_failure(hub, u, status_msg_hub_disabled); return -1; } - + while (arg) { - if (strlen(arg) == 6) { fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]); @@ -133,7 +132,7 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess hub_free(arg); arg = adc_msg_get_argument(cmd, index); } - + if (u->state == state_protocol) { if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */ @@ -150,7 +149,7 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess ret = -1; } } - + return ret; } @@ -400,7 +399,20 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message user_destroy(user); break; } - + + case UHUB_EVENT_HUB_SHUTDOWN: + { + struct hub_user* u = (struct hub_user*) list_get_first(hub->users->list); + while (u) + { + uman_remove(hub, u); + user_destroy(u); + u = (struct hub_user*) list_get_first(hub->users->list); + } + break; + } + + default: /* FIXME: ignored */ break; @@ -448,25 +460,11 @@ struct hub_info* hub_start_service(struct hub_config* config) net_address_to_string(AF_INET6, &((struct sockaddr_in6*) &addr)->sin6_addr, address_buf, INET6_ADDRSTRLEN); } -#ifdef LIBEVENT_1_4 - hub->evbase = event_base_new(); -#else - hub->evbase = event_init(); -#endif - if (!hub->evbase) - { - LOG_ERROR("Unable to initialize libevent."); - hub_free(hub); - return 0; - } - LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", address_buf, config->server_port); - LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method()); server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP); if (server_tcp == -1) { - event_base_free(hub->evbase); hub_free(hub); return 0; } @@ -474,7 +472,6 @@ struct hub_info* hub_start_service(struct hub_config* config) ret = net_set_reuseaddress(server_tcp, 1); if (ret == -1) { - event_base_free(hub->evbase); hub_free(hub); net_close(server_tcp); return 0; @@ -483,7 +480,6 @@ struct hub_info* hub_start_service(struct hub_config* config) ret = net_set_nonblocking(server_tcp, 1); if (ret == -1) { - event_base_free(hub->evbase); hub_free(hub); net_close(server_tcp); return 0; @@ -493,7 +489,6 @@ struct hub_info* hub_start_service(struct hub_config* config) if (ret == -1) { LOG_FATAL("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error())); - event_base_free(hub->evbase); hub_free(hub); net_close(server_tcp); return 0; @@ -503,7 +498,6 @@ struct hub_info* hub_start_service(struct hub_config* config) if (ret == -1) { LOG_FATAL("hub_start_service(): Unable to listen to socket"); - event_base_free(hub->evbase); hub_free(hub); net_close(server_tcp); return 0; @@ -549,7 +543,7 @@ struct hub_info* hub_start_service(struct hub_config* config) } event_set(&hub->ev_accept, hub->fd_tcp, EV_READ | EV_PERSIST, net_on_accept, hub); - event_base_set(hub->evbase, &hub->ev_accept); + event_base_set(net_get_evbase(), &hub->ev_accept); if (event_add(&hub->ev_accept, NULL) == -1) { uman_shutdown(hub); @@ -601,14 +595,13 @@ struct hub_info* hub_start_service(struct hub_config* config) void hub_shutdown_service(struct hub_info* hub) { - LOG_TRACE("hub_shutdown_service()"); + LOG_DEBUG("hub_shutdown_service()"); event_queue_shutdown(hub->queue); event_del(&hub->ev_accept); net_close(hub->fd_tcp); uman_shutdown(hub); hub->status = hub_status_stopped; - event_base_free(hub->evbase); hub_free(hub->sendbuf); hub_free(hub->recvbuf); hub_chat_history_clear(hub); @@ -959,27 +952,6 @@ size_t hub_get_min_hubs_op(struct hub_info* hub) return hub->config->limit_min_hubs_op; } - -void hub_event_loop(struct hub_info* hub) -{ - int ret; - do - { - ret = event_base_loop(hub->evbase, EVLOOP_ONCE); - - if (ret != 0) - { - LOG_DEBUG("event_base_loop returned: %d", (int) ret); - } - - if (ret < 0) - break; - - event_queue_process(hub->queue); - } - while (hub->status == hub_status_running || hub->status == hub_status_disabled); -} - void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user) { struct event_data post; @@ -988,12 +960,69 @@ void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user) post.ptr = user; event_queue_post(hub->queue, &post); + net_con_close(&user->net.connection); + if (user->id.sid) { sid_free(hub->users->sids, user->id.sid); } } +void hub_disconnect_all(struct hub_info* hub) +{ + struct event_data post; + memset(&post, 0, sizeof(post)); + post.id = UHUB_EVENT_HUB_SHUTDOWN; + post.ptr = 0; + event_queue_post(hub->queue, &post); +} + + +void hub_schedule_destroy_all(struct hub_info* hub) +{ + struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); + while (user) + { + + hub_schedule_destroy_user(hub, user); + user = (struct hub_user*) list_get_next(hub->users->list); + } +} + + + +void hub_event_loop(struct hub_info* hub) +{ + int ret; + do + { + 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; + + event_queue_process(hub->queue); + } + while (hub->status == hub_status_running || hub->status == hub_status_disabled); + + + if (hub->status == hub_status_shutdown) + { + LOG_DEBUG("Removing all users..."); + event_queue_process(hub->queue); + event_queue_process(hub->queue); + hub_disconnect_all(hub); + event_queue_process(hub->queue); + hub->status = hub_status_stopped; + } +} + + void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason) { struct event_data post; @@ -1010,7 +1039,7 @@ void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason LOG_TRACE("hub_disconnect_user(), user=%p, reason=%d, state=%d", user, reason, user->state); - need_notify = user_is_logged_in(user); + need_notify = user_is_logged_in(user) && hub->status == hub_status_running; user->quit_reason = reason; user_set_state(user, state_cleanup); diff --git a/src/core/hub.h b/src/core/hub.h index 381277f..b48b31f 100644 --- a/src/core/hub.h +++ b/src/core/hub.h @@ -95,7 +95,6 @@ struct hub_info struct event ev_timer; struct hub_stats stats; struct event_queue* queue; - struct event_base* evbase; struct hub_config* config; struct hub_user_manager* users; struct acl_handle* acl; diff --git a/src/core/main.c b/src/core/main.c index b910c1c..1687246 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -81,7 +81,7 @@ void setup_signal_handlers(struct hub_info* hub) for (i = 0; signals[i]; i++) { signal_set(&signal_events[i], signals[i], hub_handle_signal, hub); - event_base_set(hub->evbase, &signal_events[i]); + event_base_set(net_get_evbase(), &signal_events[i]); if (signal_add(&signal_events[i], NULL)) { LOG_ERROR("Error setting signal handler %d", signals[i]); @@ -147,7 +147,7 @@ int main_loop() acl_shutdown(&acl); free_config(&configuration); - } while(hub->status != hub_status_shutdown); + } while (hub->status == hub_status_restart); #ifndef WIN32 shutdown_signal_handlers(hub); diff --git a/src/core/user.c b/src/core/user.c index 4155ef6..e44b73c 100644 --- a/src/core/user.c +++ b/src/core/user.c @@ -62,9 +62,6 @@ void user_destroy(struct hub_user* user) { LOG_TRACE("user_destroy(), user=%p", user); - net_con_close(&user->net.connection); - net_con_clear_timeout(&user->net.connection); - hub_recvq_destroy(user->net.recv_queue); hub_sendq_destroy(user->net.send_queue); diff --git a/src/core/usermanager.c b/src/core/usermanager.c index 90011c9..2d18c8f 100644 --- a/src/core/usermanager.c +++ b/src/core/usermanager.c @@ -77,7 +77,7 @@ static void timer_statistics(int fd, short ev, void *arg) struct timeval timeout = { TIMEOUT_STATS, 0 }; uman_update_stats(hub); evtimer_set(&hub->ev_timer, timer_statistics, hub); - event_base_set(hub->evbase, &hub->ev_timer); + event_base_set(net_get_evbase(), &hub->ev_timer); evtimer_add(&hub->ev_timer, &timeout); } #endif @@ -108,10 +108,10 @@ int uman_init(struct hub_info* hub) hub->users = users; #ifdef USERMANAGER_TIMER - if (hub->evbase) + if (net_get_evbase()) { evtimer_set(&hub->ev_timer, timer_statistics, hub); - event_base_set(hub->evbase, &hub->ev_timer); + event_base_set(net_get_evbase(), &hub->ev_timer); evtimer_add(&hub->ev_timer, &timeout); } #endif // 0 @@ -126,7 +126,7 @@ int uman_shutdown(struct hub_info* hub) #ifdef USERMANAGER_TIMER if (evtimer_pending(&hub->ev_timer, 0)) - event_del(&hub->ev_timer); + evtimer_del(&hub->ev_timer); #endif if (hub->users->list) diff --git a/src/core/usermanager.h b/src/core/usermanager.h index 77f6d4b..af59460 100644 --- a/src/core/usermanager.h +++ b/src/core/usermanager.h @@ -27,7 +27,7 @@ struct hub_user_manager struct sid_pool* sids; uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */ uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */ - struct linked_list* list; /**<< "Contains all users" */ + struct linked_list* list; /**<< "Contains all logged in users" */ }; /** diff --git a/src/network/connection.c b/src/network/connection.c index e2c0abb..b1eb28d 100644 --- a/src/network/connection.c +++ b/src/network/connection.c @@ -107,7 +107,7 @@ void net_con_initialize(struct net_connection* con, int sd, struct ip_addr_encap if (events & EV_WRITE) net_con_flag_set(con, NET_WANT_WRITE); event_set(&con->event, con->sd, events | EV_PERSIST, net_con_event, con); - event_base_set(g_hub->evbase, &con->event); + event_base_set(net_get_evbase(), &con->event); event_add(&con->event, 0); net_set_nonblocking(sd, 1); @@ -134,9 +134,12 @@ void net_con_update(struct net_connection* con, int events) void net_con_close(struct net_connection* con) { - if (!event_pending(&con->event, EV_READ | EV_WRITE, 0)) - return; - event_del(&con->event); + if (event_pending(&con->event, EV_READ | EV_WRITE, 0)) + { + event_del(&con->event); + } + + net_con_clear_timeout(con); net_close(con->sd); con->sd = -1; } @@ -291,7 +294,7 @@ void net_con_set_timeout(struct net_connection* con, int seconds) { struct timeval timeout = { seconds, 0 }; evtimer_set(&con->timeout, net_con_event, con); - event_base_set(g_hub->evbase, &con->timeout); + event_base_set(net_get_evbase(), &con->timeout); evtimer_add(&con->timeout, &timeout); } diff --git a/src/network/network.c b/src/network/network.c index c0677ef..1e7ac21 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -21,6 +21,7 @@ static int is_ipv6_supported = -1; /* -1 = CHECK, 0 = NO, 1 = YES */ static int net_initialized = 0; +static struct event_base* net_evbase = 0; static struct net_statistics stats; static struct net_statistics stats_total; @@ -35,6 +36,7 @@ int net_initialize() { if (!net_initialized) { + LOG_TRACE("Initializing network monitor."); #ifdef WINSOCK struct WSAData wsa; @@ -45,7 +47,18 @@ int net_initialize() } #endif /* WINSOCK */ - LOG_TRACE("Initializing network monitor."); +#ifdef LIBEVENT_1_4 + net_evbase = event_base_new(); +#else + net_evbase = event_init(); +#endif + if (!net_evbase) + { + LOG_ERROR("Unable to initialize libevent."); + return 0; + } + LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method()); + net_stats_initialize(); #ifdef SSL_SUPPORT @@ -83,6 +96,9 @@ int net_destroy() { LOG_TRACE("Shutting down network monitor"); + event_base_free(net_evbase); + net_evbase = 0; + #ifdef SSL_SUPPORT /* FIXME: Shutdown OpenSSL here. */ #endif @@ -96,6 +112,11 @@ int net_destroy() return -1; } +struct event_base* net_get_evbase() +{ + return net_evbase; +} + static void net_error_out(int fd, const char* func) { int err = net_error(); diff --git a/src/network/network.h b/src/network/network.h index 40acc2b..554a1bf 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -66,6 +66,8 @@ extern int net_initialize(); */ extern int net_destroy(); +extern struct event_base* net_get_evbase(); + /** * @return the number of sockets currrently being monitored. */