Rewrite socks to async
Not quite working yet, however it's a massive and important change.
This commit is contained in:
138
degesch.c
138
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);
|
||||
|
||||
Reference in New Issue
Block a user