aboutsummaryrefslogtreecommitdiff
path: root/zyklonb.c
diff options
context:
space:
mode:
Diffstat (limited to 'zyklonb.c')
-rw-r--r--zyklonb.c114
1 files changed, 91 insertions, 23 deletions
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))