Import optimized event loop from ponymap
This commit is contained in:
83
kike.c
83
kike.c
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user