From 318b7400d135faa4ef6f393df6d32ad41073d2f0 Mon Sep 17 00:00:00 2001 From: Přemysl Janouch Date: Mon, 20 Jul 2015 23:31:26 +0200 Subject: Rewrite socks to async Not quite working yet, however it's a massive and important change. --- zyklonb.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 91 insertions(+), 23 deletions(-) (limited to 'zyklonb.c') diff --git a/zyklonb.c b/zyklonb.c index 49d4fc5..991ef13 100644 --- a/zyklonb.c +++ b/zyklonb.c @@ -1647,16 +1647,99 @@ end: irc_reset_connection_timeouts (ctx); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// The bot is currently mostly synchronous (which also makes it shorter), +// however our current SOCKS code is not, hence we must wrap it. + +struct irc_socks_data +{ + struct bot_context *ctx; ///< Bot context + struct poller inner_poller; ///< Special inner poller + bool polling; ///< Inner poller is no longer needed + struct socks_connector connector; ///< SOCKS connector + bool succeeded; ///< Were we successful in connecting? +}; + +static void +irc_on_socks_connected (void *user_data, int socket) +{ + struct irc_socks_data *data = user_data; + data->ctx->irc_fd = socket; + data->succeeded = true; + data->polling = true; +} + +static void +irc_on_socks_failure (void *user_data) +{ + struct irc_socks_data *data = user_data; + data->succeeded = false; + data->polling = true; +} + +static void +irc_on_socks_connecting (void *user_data, + const char *address, const char *via, const char *version) +{ + (void) user_data; + print_status ("connecting to %s via %s (%s)...", address, via, version); +} + +static void +irc_on_socks_error (void *user_data, const char *error) +{ + (void) user_data; + print_error ("%s: %s", "SOCKS connection failed", error); +} + +static bool +irc_establish_connection_socks (struct bot_context *ctx, + const char *socks_host, const char *socks_port, + const char *host, const char *service, struct error **e) +{ + struct irc_socks_data data; + struct poller *poller = &data.inner_poller; + struct socks_connector *connector = &data.connector; + + data.ctx = ctx; + poller_init (poller); + data.polling = true; + socks_connector_init (connector, poller); + data.succeeded = false; + + connector->hostname = socks_host; + connector->service = socks_port; + connector->username = str_map_find (&ctx->config, "socks_username"); + connector->password = str_map_find (&ctx->config, "socks_password"); + + connector->on_connected = irc_on_socks_connected; + connector->on_connecting = irc_on_socks_connecting; + connector->on_error = irc_on_socks_error; + connector->on_failure = irc_on_socks_failure; + connector->user_data = &data; + + if (socks_connector_add_target (connector, host, service, e)) + { + socks_connector_run (connector); + while (data.polling) + poller_run (poller); + } + + socks_connector_free (connector); + poller_free (poller); + return data.succeeded; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + static bool irc_connect (struct bot_context *ctx, struct error **e) { const char *irc_host = str_map_find (&ctx->config, "irc_host"); const char *irc_port = str_map_find (&ctx->config, "irc_port"); - const char *socks_host = str_map_find (&ctx->config, "socks_host"); const char *socks_port = str_map_find (&ctx->config, "socks_port"); - const char *socks_username = str_map_find (&ctx->config, "socks_username"); - const char *socks_password = str_map_find (&ctx->config, "socks_password"); const char *nickname = str_map_find (&ctx->config, "nickname"); const char *username = str_map_find (&ctx->config, "username"); @@ -1678,26 +1761,11 @@ irc_connect (struct bot_context *ctx, struct error **e) if (!irc_get_boolean_from_config (ctx, "ssl", &use_ssl, e)) return false; - if (socks_host) - { - char *address = format_host_port_pair (irc_host, irc_port); - char *socks_address = format_host_port_pair (socks_host, socks_port); - print_status ("connecting to %s via %s...", address, socks_address); - free (socks_address); - free (address); - - struct error *error = NULL; - int fd = socks_connect (socks_host, socks_port, irc_host, irc_port, - socks_username, socks_password, &error); - if (fd == -1) - { - error_set (e, "%s: %s", "SOCKS connection failed", error->message); - error_free (error); - return false; - } - ctx->irc_fd = fd; - } - else if (!irc_establish_connection (ctx, irc_host, irc_port, e)) + bool connected = socks_host + ? irc_establish_connection_socks (ctx, + socks_host, socks_port, irc_host, irc_port, e) + : irc_establish_connection (ctx, irc_host, irc_port, e); + if (!connected) return false; if (use_ssl && !irc_initialize_ssl (ctx, e)) -- cgit v1.2.3-54-g00ecf