actually use the tls settings on upgrade, and disconnect gracefully

This commit is contained in:
Ailin Nemui 2021-04-06 19:31:10 +02:00
commit f2795abcc5
11 changed files with 117 additions and 30 deletions

View file

@ -90,6 +90,8 @@ static void sig_disconnected(IRC_SERVER_REC *server)
return;
rec = server->chanqueries;
if (rec == NULL)
return;
g_return_if_fail(rec != NULL);
g_hash_table_destroy(rec->accountqueries);

View file

@ -64,7 +64,8 @@ static void sig_server_reconnect_save_status(IRC_SERVER_CONNECT_REC *conn,
return;
g_free_not_null(conn->channels);
conn->channels = irc_server_get_channels(server);
conn->channels =
irc_server_get_channels(server, settings_get_choice("rejoin_channels_on_reconnect"));
g_free_not_null(conn->usermode);
conn->usermode = g_strdup(server->wanted_usermode);

View file

@ -469,6 +469,26 @@ void irc_server_connect(SERVER_REC *server)
{
g_return_if_fail(server != NULL);
if (server->connrec->connect_handle != NULL) {
IRC_SERVER_CONNECT_REC *conn;
int tls_disconnect;
conn = ((IRC_SERVER_REC *) server)->connrec;
tls_disconnect = conn->use_tls || conn->starttls;
if (tls_disconnect) {
/* we cannot use it, it is encrypted. force a reconnect */
g_io_channel_unref(conn->connect_handle);
conn->connect_handle = NULL;
server->session_reconnect = FALSE;
server_connect_ref((SERVER_CONNECT_REC *) conn);
server_disconnect(server);
server_connect((SERVER_CONNECT_REC *) conn);
server_connect_unref((SERVER_CONNECT_REC *) conn);
return;
}
}
if (!server_start_connect(server)) {
server_connect_unref(server->connrec);
g_free(server);
@ -782,20 +802,17 @@ void irc_servers_start_cmd_timeout(void)
/* Return a string of all channels (and keys, if any have them) in server,
like "#a,#b,#c,#d x,b_chan_key,x,x" or just "#e,#f,#g" */
char *irc_server_get_channels(IRC_SERVER_REC *server)
char *irc_server_get_channels(IRC_SERVER_REC *server, int rejoin_channels_mode)
{
GSList *tmp;
GString *chans, *keys;
char *ret;
int use_keys;
int rejoin_channels_mode;
g_return_val_if_fail(server != NULL, FALSE);
rejoin_channels_mode = settings_get_choice("rejoin_channels_on_reconnect");
/* do we want to rejoin channels in the first place? */
if(rejoin_channels_mode == 0)
if (rejoin_channels_mode == REJOIN_CHANNELS_MODE_OFF)
return g_strdup("");
chans = g_string_new(NULL);
@ -806,7 +823,9 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *channel = tmp->data;
CHANNEL_SETUP_REC *setup = channel_setup_find(channel->name, channel->server->connrec->chatnet);
if ((setup != NULL && setup->autojoin && rejoin_channels_mode == 2) || rejoin_channels_mode == 1) {
if ((setup != NULL && setup->autojoin &&
rejoin_channels_mode == REJOIN_CHANNELS_MODE_AUTO) ||
rejoin_channels_mode == REJOIN_CHANNELS_MODE_ON) {
g_string_append_printf(chans, "%s,", channel->name);
g_string_append_printf(keys, "%s,", channel->key == NULL ? "x" : channel->key);
if (channel->key != NULL)
@ -819,7 +838,9 @@ char *irc_server_get_channels(IRC_SERVER_REC *server)
REJOIN_REC *rec = tmp->data;
CHANNEL_SETUP_REC *setup = channel_setup_find(rec->channel, server->tag);
if ((setup != NULL && setup->autojoin && rejoin_channels_mode == 2) || rejoin_channels_mode == 1) {
if ((setup != NULL && setup->autojoin &&
rejoin_channels_mode == REJOIN_CHANNELS_MODE_AUTO) ||
rejoin_channels_mode == REJOIN_CHANNELS_MODE_ON) {
g_string_append_printf(chans, "%s,", rec->channel);
g_string_append_printf(keys, "%s,", rec->key == NULL ? "x" :
rec->key);

View file

@ -157,9 +157,15 @@ void irc_server_connect(SERVER_REC *server);
/* Purge server output, either all or for specified target */
void irc_server_purge_output(IRC_SERVER_REC *server, const char *target);
enum {
REJOIN_CHANNELS_MODE_OFF = 0, /* */
REJOIN_CHANNELS_MODE_ON,
REJOIN_CHANNELS_MODE_AUTO
};
/* Return a string of all channels (and keys, if any have them) in server,
like "#a,#b,#c,#d x,b_chan_key,x,x" or just "#e,#f,#g" */
char *irc_server_get_channels(IRC_SERVER_REC *server);
char *irc_server_get_channels(IRC_SERVER_REC *server, int rejoin_channels_mode);
void irc_server_send_starttls(IRC_SERVER_REC *server);
/* INTERNAL: */

View file

@ -23,6 +23,7 @@
#include <irssi/src/core/net-sendbuffer.h>
#include <irssi/src/lib-config/iconfig.h>
#include <irssi/src/core/misc.h>
#include <irssi/src/core/network.h>
#include <irssi/src/irc/core/irc-servers.h>
#include <irssi/src/irc/core/irc-channels.h>
@ -43,6 +44,7 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
GSList *tmp;
CONFIG_NODE *isupport;
struct _isupport_data isupport_data;
int tls_disconnect;
if (!IS_IRC_SERVER(server))
return;
@ -58,7 +60,15 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
break;
}
}
net_sendbuffer_flush(server->handle);
/* we cannot upgrade TLS (yet?) */
tls_disconnect = server->connrec->use_tls || server->connrec->starttls;
if (tls_disconnect) {
config_node_set_str(config, node, "rejoin_channels",
irc_server_get_channels(server, REJOIN_CHANNELS_MODE_ON));
irc_send_cmd_now(server, "QUIT :[TLS] Client upgrade");
}
net_sendbuffer_flush(server->handle);
config_node_set_str(config, node, "real_address", server->real_address);
config_node_set_str(config, node, "userhost", server->userhost);
@ -71,18 +81,26 @@ static void sig_session_save_server(IRC_SERVER_REC *server, CONFIG_REC *config,
config_node_set_str(config, node, "sasl_username", server->connrec->sasl_username);
config_node_set_str(config, node, "sasl_password", server->connrec->sasl_password);
config_node_set_int(config, node, "starttls",
server->connrec->disallow_starttls ? 0 :
server->connrec->starttls ? 1 :
-1);
config_node_set_bool(config, node, "isupport_sent", server->isupport_sent);
isupport = config_node_section(config, node, "isupport", NODE_TYPE_BLOCK);
isupport_data.config = config;
isupport_data.node = isupport;
g_hash_table_foreach(server->isupport, (GHFunc) session_isupport_foreach, &isupport_data);
/* we have to defer the disconnect to irc_server_connect */
}
static void sig_session_restore_server(IRC_SERVER_REC *server,
CONFIG_NODE *node)
{
GSList *tmp;
int starttls_mode;
if (!IS_IRC_SERVER(server))
return;
@ -105,6 +123,14 @@ static void sig_session_restore_server(IRC_SERVER_REC *server,
g_free(server->connrec->sasl_password);
server->connrec->sasl_password = g_strdup(config_node_get_str(node, "sasl_password", NULL));
server->connrec->channels = g_strdup(config_node_get_str(node, "rejoin_channels", NULL));
starttls_mode = config_node_get_int(node, "starttls", -1);
if (starttls_mode == 0)
server->connrec->disallow_starttls = 1;
if (starttls_mode == 1)
server->connrec->starttls = 1;
if (server->isupport == NULL) {
server->isupport =
g_hash_table_new((GHashFunc) i_istr_hash, (GCompareFunc) i_istr_equal);
@ -123,6 +149,7 @@ static void sig_session_restore_server(IRC_SERVER_REC *server,
}
irc_server_init_isupport(server);
/* we will reconnect in irc_server_connect if the connection was TLS */
}
static void sig_session_restore_nick(IRC_CHANNEL_REC *channel,

View file

@ -381,6 +381,9 @@ static void sig_disconnected(IRC_SERVER_REC *server)
if (!IS_IRC_SERVER(server))
return;
if (server->splits == NULL)
return;
g_hash_table_foreach(server->splits,
(GHFunc) netsplit_destroy_hash, server);
g_hash_table_destroy(server->splits);

View file

@ -209,6 +209,9 @@ static void notifylist_deinit_server(IRC_SERVER_REC *server)
return;
mserver = MODULE_DATA(server);
if (!mserver)
return;
while (mserver->notify_users != NULL) {
rec = mserver->notify_users->data;