aboutsummaryrefslogtreecommitdiff
path: root/kike.c
diff options
context:
space:
mode:
Diffstat (limited to 'kike.c')
-rw-r--r--kike.c83
1 files changed, 60 insertions, 23 deletions
diff --git a/kike.c b/kike.c
index 422d732..9810e25 100644
--- a/kike.c
+++ b/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)