diff options
Diffstat (limited to 'kike.c')
-rw-r--r-- | kike.c | 83 |
1 files changed, 60 insertions, 23 deletions
@@ -303,6 +303,11 @@ struct client struct str read_buffer; ///< Unprocessed input struct str write_buffer; ///< Output yet to be sent out + struct poller_fd socket_event; ///< The socket can be read/written to + struct poller_timer ping_timer; ///< We should send a ping + struct poller_timer timeout_timer; ///< Connection seems to be dead + struct poller_timer kill_timer; ///< Hard kill timeout + bool initialized; ///< Has any data been received yet? bool registered; ///< The user has registered bool closing_link; ///< Closing link @@ -512,6 +517,7 @@ channel_user_count (const struct channel *chan) struct server_context { int *listen_fds; ///< Listening socket FD's + struct poller_fd *listen_events; ///< New connections available size_t n_listen_fds; ///< Number of listening sockets SSL_CTX *ssl_ctx; ///< SSL context @@ -526,6 +532,8 @@ struct server_context bool quitting; ///< User requested quitting bool polling; ///< The event loop is running + struct poller_fd signal_event; ///< Got a signal + struct str_map config; ///< Server configuration char *server_name; ///< Our server name unsigned ping_interval; ///< Ping interval in seconds @@ -539,6 +547,7 @@ static void server_context_init (struct server_context *self) { self->listen_fds = NULL; + self->listen_events = NULL; self->n_listen_fds = 0; self->clients = NULL; self->n_clients = 0; @@ -555,6 +564,8 @@ server_context_init (struct server_context *self) self->quitting = false; self->polling = false; + memset (&self->signal_event, 0, sizeof self->signal_event); + str_map_init (&self->config); self->config.free = free; load_config_defaults (&self->config, g_config_table); @@ -575,8 +586,13 @@ server_context_free (struct server_context *self) str_map_free (&self->config); for (size_t i = 0; i < self->n_listen_fds; i++) + { xclose (self->listen_fds[i]); + self->listen_events[i].closed = true; + poller_fd_reset (&self->listen_events[i]); + } free (self->listen_fds); + free (self->listen_events); if (self->ssl_ctx) SSL_CTX_free (self->ssl_ctx); @@ -628,10 +644,9 @@ irc_initiate_quit (struct server_context *ctx) for (size_t i = 0; i < ctx->n_listen_fds; i++) { - ssize_t index = poller_find_by_fd (&ctx->poller, ctx->listen_fds[i]); - if (soft_assert (index != -1)) - poller_remove_at_index (&ctx->poller, index); xclose (ctx->listen_fds[i]); + ctx->listen_events[i].closed = true; + poller_fd_reset (&ctx->listen_events[i]); } ctx->n_listen_fds = 0; @@ -770,15 +785,15 @@ client_kill (struct client *c, const char *reason) client_unregister (c, reason ? reason : "Client exited"); struct server_context *ctx = c->ctx; - ssize_t i = poller_find_by_fd (&ctx->poller, c->socket_fd); - if (i != -1) - poller_remove_at_index (&ctx->poller, i); - client_cancel_timers (c); if (c->ssl) (void) SSL_shutdown (c->ssl); xclose (c->socket_fd); + c->socket_event.closed = true; + poller_fd_reset (&c->socket_event); + client_cancel_timers (c); + print_debug ("closed connection to %s (%s)", c->address, reason ? reason : "Reason omitted"); @@ -858,17 +873,17 @@ client_get_ssl_cert_fingerprint (struct client *c) static void client_cancel_timers (struct client *c) { - ssize_t i; - struct poller_timers *timers = &c->ctx->poller.timers; - while ((i = poller_timers_find_by_data (timers, c)) != -1) - poller_timers_remove_at_index (timers, i); + poller_timer_reset (&c->kill_timer); + poller_timer_reset (&c->timeout_timer); + poller_timer_reset (&c->ping_timer); } static void -client_set_timer (struct client *c, poller_timer_fn fn, unsigned interval) +client_set_timer (struct client *c, + struct poller_timer *timer, unsigned interval) { client_cancel_timers (c); - poller_timers_add (&c->ctx->poller.timers, fn, c, interval * 1000); + poller_timer_set (timer, interval * 1000); } static void @@ -882,7 +897,7 @@ on_client_kill_timer (void *user_data) static void client_set_kill_timer (struct client *c) { - client_set_timer (c, on_client_kill_timer, c->ctx->ping_interval); + client_set_timer (c, &c->kill_timer, c->ctx->ping_interval); } static void @@ -901,13 +916,13 @@ on_client_ping_timer (void *user_data) struct client *c = user_data; hard_assert (!c->closing_link); client_send (c, "PING :%s", c->ctx->server_name); - client_set_timer (c, on_client_timeout_timer, c->ctx->ping_interval); + client_set_timer (c, &c->timeout_timer, c->ctx->ping_interval); } static void client_set_ping_timer (struct client *c) { - client_set_timer (c, on_client_ping_timer, c->ctx->ping_interval); + client_set_timer (c, &c->ping_timer, c->ctx->ping_interval); } // --- IRC command handling ---------------------------------------------------- @@ -2627,8 +2642,7 @@ client_update_poller (struct client *c, const struct pollfd *pfd) hard_assert (new_events != 0); if (!pfd || pfd->events != new_events) - poller_set (&c->ctx->poller, c->socket_fd, new_events, - (poller_dispatcher_fn) on_client_ready, c); + poller_fd_set (&c->socket_event, new_events); } static void @@ -2686,6 +2700,22 @@ on_irc_client_available (const struct pollfd *pfd, void *user_data) LIST_PREPEND (ctx->clients, c); ctx->n_clients++; + poller_fd_init (&c->socket_event, &c->ctx->poller, c->socket_fd); + c->socket_event.dispatcher = (poller_fd_fn) on_client_ready; + c->socket_event.user_data = c; + + poller_timer_init (&c->kill_timer, &c->ctx->poller); + c->kill_timer.dispatcher = on_client_kill_timer; + c->kill_timer.user_data = c; + + poller_timer_init (&c->timeout_timer, &c->ctx->poller); + c->timeout_timer.dispatcher = on_client_timeout_timer; + c->timeout_timer.user_data = c; + + poller_timer_init (&c->ping_timer, &c->ctx->poller); + c->ping_timer.dispatcher = on_client_ping_timer; + c->ping_timer.user_data = c; + set_blocking (fd, false); client_update_poller (c, NULL); client_set_kill_timer (c); @@ -2985,11 +3015,15 @@ irc_listen_resolve (struct server_context *ctx, { if ((fd = irc_listen (gai_iter)) == -1) continue; + set_blocking (fd, false); + + struct poller_fd *event = &ctx->listen_events[ctx->n_listen_fds]; + poller_fd_init (event, &ctx->poller, fd); + event->dispatcher = (poller_fd_fn) on_irc_client_available; + event->user_data = ctx; ctx->listen_fds[ctx->n_listen_fds++] = fd; - set_blocking (fd, false); - poller_set (&ctx->poller, fd, POLLIN, - (poller_dispatcher_fn) on_irc_client_available, ctx); + poller_fd_set (event, POLLIN); break; } freeaddrinfo (gai_result); @@ -3012,6 +3046,7 @@ irc_setup_listen_fds (struct server_context *ctx, struct error **e) str_vector_init (&ports); split_str_ignore_empty (bind_port, ',', &ports); ctx->listen_fds = xcalloc (ports.len, sizeof *ctx->listen_fds); + ctx->listen_events = xcalloc (ports.len, sizeof *ctx->listen_events); for (size_t i = 0; i < ports.len; i++) irc_listen_resolve (ctx, bind_host, ports.vector[i], &gai_hints); str_vector_free (&ports); @@ -3134,8 +3169,10 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } - poller_set (&ctx.poller, g_signal_pipe[0], POLLIN, - (poller_dispatcher_fn) on_signal_pipe_readable, &ctx); + poller_fd_init (&ctx.signal_event, &ctx.poller, g_signal_pipe[0]); + ctx.signal_event.dispatcher = (poller_fd_fn) on_signal_pipe_readable; + ctx.signal_event.user_data = &ctx; + poller_fd_set (&ctx.signal_event, POLLIN); if (!irc_initialize_ssl (&ctx, &e) || !irc_initialize_server_name (&ctx, &e) |