aboutsummaryrefslogtreecommitdiff
path: root/degesch.c
diff options
context:
space:
mode:
Diffstat (limited to 'degesch.c')
-rw-r--r--degesch.c138
1 files changed, 82 insertions, 56 deletions
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;
}
@@ -4353,6 +4365,28 @@ irc_finish_connection (struct server *s, int 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 void
irc_on_connector_connecting (void *user_data, const char *address)
{
struct server *s = user_data;
@@ -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);