From 318b7400d135faa4ef6f393df6d32ad41073d2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= 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. --- degesch.c | 138 +++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 82 insertions(+), 56 deletions(-) (limited to 'degesch.c') diff --git a/degesch.c b/degesch.c index d1d2a63..d1fc783 100644 --- a/degesch.c +++ b/degesch.c @@ -1116,6 +1116,7 @@ struct server enum server_state state; ///< Connection state struct connector *connector; ///< Connection establisher + struct socks_connector *socks_conn; ///< SOCKS connection establisher unsigned reconnect_attempt; ///< Number of reconnect attempt bool manual_disconnect; ///< Don't reconnect after disconnect @@ -1265,6 +1266,11 @@ server_free (struct server *self) connector_free (self->connector); free (self->connector); } + if (self->socks_conn) + { + socks_connector_free (self->socks_conn); + free (self->socks_conn); + } if (self->transport && self->transport->cleanup) @@ -3591,10 +3597,16 @@ irc_shutdown (struct server *s) static void irc_destroy_connector (struct server *s) { - connector_free (s->connector); + if (s->connector) + connector_free (s->connector); free (s->connector); s->connector = NULL; + if (s->socks_conn) + socks_connector_free (s->socks_conn); + free (s->socks_conn); + s->socks_conn = NULL; + // Not connecting anymore s->state = IRC_DISCONNECTED; } @@ -4352,6 +4364,28 @@ irc_finish_connection (struct server *s, int socket) refresh_prompt (s->ctx); } +static void +irc_split_host_port (char *s, char **host, char **port) +{ + char *colon = strrchr (s, ':'); + if (colon) + { + *colon = '\0'; + *port = ++colon; + } + else + *port = "6667"; + + // Unwrap IPv6 addresses in format_host_port_pair() format + size_t host_end = strlen (s) - 1; + if (*s == '[' && s[host_end] == ']') + s++[host_end] = '\0'; + + *host = s; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + static void irc_on_connector_connecting (void *user_data, const char *address) { @@ -4382,32 +4416,13 @@ irc_on_connector_connected (void *user_data, int socket) irc_finish_connection (s, socket); } -static void -irc_split_host_port (char *s, char **host, char **port) -{ - char *colon = strrchr (s, ':'); - if (colon) - { - *colon = '\0'; - *port = ++colon; - } - else - *port = "6667"; - - // Unwrap IPv6 addresses in format_host_port_pair() format - size_t host_end = strlen (s) - 1; - if (*s == '[' && s[host_end] == ']') - s++[host_end] = '\0'; - - *host = s; -} - static bool irc_setup_connector (struct server *s, const struct str_vector *addresses, struct error **e) { struct connector *connector = xmalloc (sizeof *connector); connector_init (connector, &s->ctx->poller); + s->connector = connector; connector->user_data = s; connector->on_connecting = irc_on_connector_connecting; @@ -4415,69 +4430,76 @@ irc_setup_connector (struct server *s, connector->on_connected = irc_on_connector_connected; connector->on_failure = irc_on_connector_failure; - s->state = IRC_CONNECTING; - s->connector = connector; - for (size_t i = 0; i < addresses->len; i++) { char *host, *port; irc_split_host_port (addresses->vector[i], &host, &port); if (!connector_add_target (connector, host, port, e)) - { - irc_destroy_connector (s); return false; - } } connector_step (connector); return true; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// TODO: see if we can further merge code for the two connectors, for example +// by making SOCKS 4A and 5 mere plugins for the connector, or by using +// a virtual interface common to them both (seems more likely) + +static void +irc_on_socks_connecting (void *user_data, + const char *address, const char *via, const char *version) +{ + struct server *s = user_data; + log_server_status (s, s->buffer, + "Connecting to #s via #s (#s)...", address, via, version); +} + static bool -irc_initiate_connect_socks (struct server *s, +irc_setup_connector_socks (struct server *s, const struct str_vector *addresses, struct error **e) { const char *socks_host = get_config_string (s->config, "socks_host"); int64_t socks_port_int = get_config_integer (s->config, "socks_port"); - const char *socks_username = - get_config_string (s->config, "socks_username"); - const char *socks_password = - get_config_string (s->config, "socks_password"); - if (!socks_host) return false; - // FIXME: we only try the first address (still better than nothing) - char *irc_host, *irc_port; - irc_split_host_port (addresses->vector[0], &irc_host, &irc_port); + struct socks_connector *connector = xmalloc (sizeof *connector); + socks_connector_init (connector, &s->ctx->poller); + s->socks_conn = connector; - char *socks_port = xstrdup_printf ("%" PRIi64, socks_port_int); + // FIXME: the SOCKS connector may outlive these values + connector->hostname = socks_host; + // FIXME: memory leak + connector->service = xstrdup_printf ("%" PRIi64, socks_port_int); + connector->username = get_config_string (s->config, "socks_username"); + connector->password = get_config_string (s->config, "socks_password"); - log_server_status (s, s->buffer, "Connecting to #&s via #&s...", - format_host_port_pair (irc_host, irc_port), - format_host_port_pair (socks_host, socks_port)); + connector->user_data = s; + connector->on_connecting = irc_on_socks_connecting; + connector->on_error = irc_on_connector_error; + connector->on_connected = irc_on_connector_connected; + connector->on_failure = irc_on_connector_failure; - // TODO: the SOCKS code needs a rewrite so that we don't block on it either; - // perhaps it could act as a special kind of connector - struct error *error = NULL; - bool result = true; - int fd = socks_connect (socks_host, socks_port, irc_host, irc_port, - socks_username, socks_password, &error); - if (fd != -1) - irc_finish_connection (s, fd); - else + for (size_t i = 0; i < addresses->len; i++) { - error_set (e, "%s: %s", "SOCKS connection failed", error->message); - error_free (error); - result = false; + char *host, *port; + irc_split_host_port (addresses->vector[i], &host, &port); + + if (!socks_connector_add_target (connector, host, port, e)) + return false; } - free (socks_port); - return result; + socks_connector_run (connector); + return true; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + static void irc_initiate_connect (struct server *s) { @@ -4497,13 +4519,17 @@ irc_initiate_connect (struct server *s) cstr_split_ignore_empty (addresses, ',', &servers); struct error *e = NULL; - if (!irc_initiate_connect_socks (s, &servers, &e) && !e) + if (!irc_setup_connector_socks (s, &servers, &e) && !e) irc_setup_connector (s, &servers, &e); str_vector_free (&servers); - if (e) + if (!e) + s->state = IRC_CONNECTING; + else { + irc_destroy_connector (s); + log_server_error (s, s->buffer, "#s", e->message); error_free (e); irc_queue_reconnect (s); -- cgit v1.2.3