summaryrefslogtreecommitdiff
path: root/zyklonb.c
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2015-02-12 01:53:03 +0100
committerPřemysl Janouch <p.janouch@gmail.com>2015-02-12 02:04:39 +0100
commite8fe0dad81378920c6c537013f8759dfe9144bac (patch)
tree0caa60a5e6f1eafcd1aa954f7e2d1051949a0a28 /zyklonb.c
parentcd1a55a0d1f77aedb078ab9fef96dac94b41c86b (diff)
downloadxK-e8fe0dad81378920c6c537013f8759dfe9144bac.tar.gz
xK-e8fe0dad81378920c6c537013f8759dfe9144bac.tar.xz
xK-e8fe0dad81378920c6c537013f8759dfe9144bac.zip
Import optimized event loop from ponymap
Diffstat (limited to 'zyklonb.c')
-rw-r--r--zyklonb.c101
1 files changed, 63 insertions, 38 deletions
diff --git a/zyklonb.c b/zyklonb.c
index f9624b9..e3289d9 100644
--- a/zyklonb.c
+++ b/zyklonb.c
@@ -73,6 +73,9 @@ struct plugin_data
int read_fd; ///< The read end of the comm. pipe
int write_fd; ///< The write end of the comm. pipe
+ struct poller_fd read_event; ///< Read FD event
+ struct poller_fd write_event; ///< Write FD event
+
struct str read_buffer; ///< Unprocessed input
struct str write_buffer; ///< Output yet to be sent out
};
@@ -118,8 +121,14 @@ struct bot_context
int irc_fd; ///< Socket FD of the server
struct str read_buffer; ///< Input yet to be processed
+ struct poller_fd irc_event; ///< IRC FD event
bool irc_ready; ///< Whether we may send messages now
+ struct poller_fd signal_event; ///< Signal FD event
+ struct poller_timer ping_tmr; ///< We should send a ping
+ struct poller_timer timeout_tmr; ///< Connection seems to be dead
+ struct poller_timer reconnect_tmr; ///< We should reconnect now
+
SSL_CTX *ssl_ctx; ///< SSL context
SSL *ssl; ///< SSL connection
@@ -131,6 +140,10 @@ struct bot_context
bool polling; ///< The event loop is running
};
+static void on_irc_ping_timeout (void *user_data);
+static void on_irc_timeout (void *user_data);
+static void on_irc_reconnect_timeout (void *user_data);
+
static void
bot_context_init (struct bot_context *self)
{
@@ -152,6 +165,18 @@ bot_context_init (struct bot_context *self)
poller_init (&self->poller);
self->quitting = false;
self->polling = false;
+
+ poller_timer_init (&self->timeout_tmr, &self->poller);
+ self->timeout_tmr.dispatcher = on_irc_timeout;
+ self->timeout_tmr.user_data = self;
+
+ poller_timer_init (&self->ping_tmr, &self->poller);
+ self->ping_tmr.dispatcher = on_irc_ping_timeout;
+ self->ping_tmr.user_data = self;
+
+ poller_timer_init (&self->reconnect_tmr, &self->poller);
+ self->reconnect_tmr.dispatcher = on_irc_reconnect_timeout;
+ self->reconnect_tmr.user_data = self;
}
static void
@@ -172,7 +197,10 @@ bot_context_free (struct bot_context *self)
}
if (self->irc_fd != -1)
+ {
xclose (self->irc_fd);
+ poller_fd_reset (&self->irc_event);
+ }
if (self->ssl)
SSL_free (self->ssl);
if (self->ssl_ctx)
@@ -1060,10 +1088,7 @@ plugin_zombify (struct plugin_data *plugin)
// empty before closing it... and then on EOF check if `pid == -1' and
// only then dispose of it (it'd be best to simulate that both of these
// cases may happen).
- ssize_t poller_idx =
- poller_find_by_fd (&plugin->ctx->poller, plugin->write_fd);
- if (poller_idx != -1)
- poller_remove_at_index (&plugin->ctx->poller, poller_idx);
+ poller_fd_reset (&plugin->write_event);
// TODO: try to flush the write buffer (non-blocking)?
@@ -1083,7 +1108,6 @@ plugin_zombify (struct plugin_data *plugin)
static void
on_plugin_writable (const struct pollfd *fd, struct plugin_data *plugin)
{
- struct bot_context *ctx = plugin->ctx;
struct str *buf = &plugin->write_buffer;
size_t written_total = 0;
@@ -1124,12 +1148,8 @@ on_plugin_writable (const struct pollfd *fd, struct plugin_data *plugin)
str_remove_slice (buf, 0, written_total);
if (buf->len == 0)
- {
// Everything has been written, there's no need to end up in here again
- ssize_t index = poller_find_by_fd (&ctx->poller, fd->fd);
- if (index != -1)
- poller_remove_at_index (&ctx->poller, index);
- }
+ poller_fd_reset (&plugin->write_event);
}
static void
@@ -1148,9 +1168,7 @@ plugin_queue_write (struct plugin_data *plugin)
plugin_zombify (plugin);
return;
}
-
- poller_set (&plugin->ctx->poller, plugin->write_fd, POLLOUT,
- (poller_dispatcher_fn) on_plugin_writable, plugin);
+ poller_fd_set (&plugin->write_event, POLLOUT);
}
static void
@@ -1412,11 +1430,18 @@ plugin_load (struct bot_context *ctx, const char *name, struct error **e)
plugin->read_fd = stdout_pipe[0];
plugin->write_fd = stdin_pipe[1];
+ poller_fd_init (&plugin->read_event, &ctx->poller, plugin->read_fd);
+ plugin->read_event.dispatcher = (poller_fd_fn) on_plugin_readable;
+ plugin->read_event.user_data = plugin;
+
+ poller_fd_init (&plugin->write_event, &ctx->poller, plugin->write_fd);
+ plugin->write_event.dispatcher = (poller_fd_fn) on_plugin_writable;
+ plugin->write_event.user_data = plugin;
+
LIST_PREPEND (ctx->plugins, plugin);
str_map_set (&ctx->plugins_by_name, name, plugin);
- poller_set (&ctx->poller, stdout_pipe[0], POLLIN,
- (poller_dispatcher_fn) on_plugin_readable, plugin);
+ poller_fd_set (&plugin->read_event, POLLIN);
return true;
fail_3:
@@ -1818,14 +1843,13 @@ static void irc_queue_reconnect (struct bot_context *);
static void
irc_cancel_timers (struct bot_context *ctx)
{
- ssize_t i;
- struct poller_timers *timers = &ctx->poller.timers;
- while ((i = poller_timers_find_by_data (timers, ctx)) != -1)
- poller_timers_remove_at_index (timers, i);
+ poller_timer_reset (&ctx->timeout_tmr);
+ poller_timer_reset (&ctx->ping_tmr);
+ poller_timer_reset (&ctx->reconnect_tmr);
}
static void
-irc_on_reconnect_timeout (void *user_data)
+on_irc_reconnect_timeout (void *user_data)
{
struct bot_context *ctx = user_data;
@@ -1847,8 +1871,7 @@ irc_queue_reconnect (struct bot_context *ctx)
hard_assert (ctx->irc_fd == -1);
print_status ("trying to reconnect in %ld seconds...",
ctx->reconnect_delay);
- poller_timers_add (&ctx->poller.timers,
- irc_on_reconnect_timeout, ctx, ctx->reconnect_delay * 1000);
+ poller_timer_set (&ctx->reconnect_tmr, ctx->reconnect_delay * 1000);
}
static void
@@ -1863,14 +1886,13 @@ on_irc_disconnected (struct bot_context *ctx)
ctx->ssl_ctx = NULL;
}
- ssize_t i = poller_find_by_fd (&ctx->poller, ctx->irc_fd);
- if (i != -1)
- poller_remove_at_index (&ctx->poller, i);
-
xclose (ctx->irc_fd);
ctx->irc_fd = -1;
ctx->irc_ready = false;
+ ctx->irc_event.closed = true;
+ poller_fd_reset (&ctx->irc_event);
+
// TODO: inform plugins about the disconnect event
// All of our timers have lost their meaning now
@@ -1905,10 +1927,8 @@ static void
irc_reset_connection_timeouts (struct bot_context *ctx)
{
irc_cancel_timers (ctx);
- poller_timers_add (&ctx->poller.timers,
- on_irc_timeout, ctx, 3 * 60 * 1000);
- poller_timers_add (&ctx->poller.timers,
- on_irc_ping_timeout, ctx, (3 * 60 + 30) * 1000);
+ poller_timer_set (&ctx->timeout_tmr, 3 * 60 * 1000);
+ poller_timer_set (&ctx->ping_tmr, (3 * 60 + 30) * 1000);
}
static void
@@ -2026,11 +2046,14 @@ irc_connect (struct bot_context *ctx, struct error **e)
}
print_status ("connection established");
+ poller_fd_init (&ctx->irc_event, &ctx->poller, ctx->irc_fd);
+ ctx->irc_event.dispatcher = (poller_fd_fn) on_irc_readable;
+ ctx->irc_event.user_data = ctx;
+
// TODO: in exec try: 1/ set blocking, 2/ setsockopt() SO_LINGER,
// (struct linger) { .l_onoff = true; .l_linger = 1 /* 1s should do */; }
// 3/ /* O_CLOEXEC */ But only if the QUIT message proves unreliable.
- poller_set (&ctx->poller, ctx->irc_fd, POLLIN,
- (poller_dispatcher_fn) on_irc_readable, ctx);
+ poller_fd_set (&ctx->irc_event, POLLIN);
irc_reset_connection_timeouts (ctx);
irc_send (ctx, "NICK %s", nickname);
@@ -2134,13 +2157,12 @@ on_signal_pipe_readable (const struct pollfd *fd, struct bot_context *ctx)
plugin->pid = -1;
- ssize_t poller_idx = poller_find_by_fd (&ctx->poller, plugin->read_fd);
- if (poller_idx != -1)
- poller_remove_at_index (&ctx->poller, poller_idx);
-
xclose (plugin->read_fd);
plugin->read_fd = -1;
+ plugin->read_event.closed = true;
+ poller_fd_reset (&plugin->read_event);
+
LIST_UNLINK (ctx->plugins, plugin);
plugin_data_free (plugin);
free (plugin);
@@ -2215,8 +2237,11 @@ main (int argc, char *argv[])
}
setup_recovery_handler (&ctx);
- 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);
plugin_load_all_from_config (&ctx);
if (!parse_config (&ctx, &e)