diff options
author | Timo Sirainen <cras@irssi.org> | 2000-10-14 00:45:16 +0000 |
---|---|---|
committer | cras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2000-10-14 00:45:16 +0000 |
commit | 6a3efe49ab7b41062650da894eccc2d4be0b8f45 (patch) | |
tree | e60a8f2eaaef04f87d9c8752f2742acc4f5e41bb /src/irc/core | |
parent | f850204479e84c3112b6353da48a5a1ec81bb1fe (diff) | |
download | irssi-6a3efe49ab7b41062650da894eccc2d4be0b8f45.zip |
Autorejoin when join temporarily fails because of netsplit is handled
better now. Irssi prints a nice message about it only once and you can
abort it with /RMREJOINS command.
"channel query" -> "channel joined"
channels_join() must not use cmd_return|param_error() commands since we
don't necessarily call it from command handler and signal_stop() could
cause some damage.
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@739 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'src/irc/core')
-rw-r--r-- | src/irc/core/channel-rejoin.c | 146 | ||||
-rw-r--r-- | src/irc/core/channels-query.c | 13 | ||||
-rw-r--r-- | src/irc/core/irc-channels.c | 22 | ||||
-rw-r--r-- | src/irc/core/irc-nicklist.c | 2 |
4 files changed, 151 insertions, 32 deletions
diff --git a/src/irc/core/channel-rejoin.c b/src/irc/core/channel-rejoin.c index 9efed72c..32070a79 100644 --- a/src/irc/core/channel-rejoin.c +++ b/src/irc/core/channel-rejoin.c @@ -25,25 +25,79 @@ #include "irc.h" #include "irc-channels.h" +#include "channel-rejoin.h" -#define REJOIN_TIMEOUT (1000*60*5) /* try to rejoin every 5 minutes */ +//#define REJOIN_TIMEOUT (1000*60*5) /* try to rejoin every 5 minutes */ +#define REJOIN_TIMEOUT (1000*10) /* FIXME: test */ static int rejoin_tag; +static void rejoin_destroy(IRC_SERVER_REC *server, REJOIN_REC *rec) +{ + g_return_if_fail(IS_IRC_SERVER(server)); + g_return_if_fail(rec != NULL); + + server->rejoin_channels = + g_slist_remove(server->rejoin_channels, rec); + + signal_emit("channel rejoin remove", 2, server, rec); + + g_free(rec->channel); + g_free_not_null(rec->key); + g_free(rec); +} + +static REJOIN_REC *rejoin_find(IRC_SERVER_REC *server, const char *channel) +{ + GSList *tmp; + + g_return_val_if_fail(IS_IRC_SERVER(server), NULL); + g_return_val_if_fail(channel != NULL, NULL); + + for (tmp = server->rejoin_channels; tmp != NULL; tmp = tmp->next) { + REJOIN_REC *rec = tmp->data; + + if (g_strcasecmp(rec->channel, channel) == 0) + return rec; + } + + return NULL; +} + #define channel_have_key(chan) \ ((chan) != NULL && (chan)->key != NULL && (chan)->key[0] != '\0') static void channel_rejoin(IRC_SERVER_REC *server, const char *channel) { IRC_CHANNEL_REC *chanrec; - char *str; + REJOIN_REC *rec; + + g_return_if_fail(IS_IRC_SERVER(server)); + g_return_if_fail(channel != NULL); chanrec = irc_channel_find(server, channel); - str = channel_have_key(chanrec) ? g_strdup(channel) : - g_strdup_printf("%s %s", channel, chanrec->key); + + rec = rejoin_find(server, channel); + if (rec != NULL) { + /* already exists */ + rec->joining = FALSE; + + /* update channel key */ + g_free_and_null(rec->key); + if (channel_have_key(chanrec)) + rec->key = g_strdup(chanrec->key); + return; + } + + /* new rejoin */ + rec = g_new0(REJOIN_REC, 1); + rec->channel = g_strdup(channel); + if (channel_have_key(chanrec)) + rec->key = g_strdup(chanrec->key); server->rejoin_channels = - g_slist_append(server->rejoin_channels, str); + g_slist_append(server->rejoin_channels, rec); + signal_emit("channel rejoin new", 2, server, rec); } static void event_target_unavailable(const char *data, IRC_SERVER_REC *server) @@ -56,29 +110,80 @@ static void event_target_unavailable(const char *data, IRC_SERVER_REC *server) if (ischannel(*channel)) { /* channel is unavailable - try to join again a bit later */ channel_rejoin(server, channel); + signal_stop(); } g_free(params); } +/* join ok/failed - remove from rejoins list. this happens always after join + except if the "target unavailable" error happens again */ +static void sig_remove_rejoin(IRC_CHANNEL_REC *channel) +{ + REJOIN_REC *rec; + + if (!IS_IRC_CHANNEL(channel) && channel->server != NULL) + return; + + rec = rejoin_find(channel->server, channel->name); + if (rec != NULL && rec->joining) { + /* join failed, remove the rejoin */ + rejoin_destroy(channel->server, rec); + } +} + static void sig_disconnected(IRC_SERVER_REC *server) { if (!IS_IRC_SERVER(server)) return; - g_slist_foreach(server->rejoin_channels, (GFunc) g_free, NULL); - g_slist_free(server->rejoin_channels); + while (server->rejoin_channels != NULL) + rejoin_destroy(server, server->rejoin_channels->data); } static void server_rejoin_channels(IRC_SERVER_REC *server) { - while (server->rejoin_channels != NULL) { - char *channel = server->rejoin_channels->data; + GSList *tmp, *next; + GString *channels, *keys; + int use_keys; + + g_return_if_fail(IS_IRC_SERVER(server)); + + channels = g_string_new(NULL); + keys = g_string_new(NULL); + + use_keys = FALSE; + for (tmp = server->rejoin_channels; tmp != NULL; tmp = next) { + REJOIN_REC *rec = tmp->data; + next = tmp->next; + + if (rec->joining) { + /* we missed the join (failed) message, + remove from rejoins.. */ + rejoin_destroy(server, rec); + continue; + } + + rec->joining = TRUE; + g_string_sprintfa(channels, "%s,", rec->channel); + if (rec->key == NULL) + g_string_append(keys, "x,"); + else { + g_string_sprintfa(keys, "%s,", rec->key); + use_keys = TRUE; + } + } - server->channels_join(server, channel, TRUE); - server->rejoin_channels = - g_slist_remove(server->rejoin_channels, channel); + if (channels->len > 0) { + g_string_truncate(channels, channels->len-1); + g_string_truncate(keys, keys->len-1); + + if (use_keys) g_string_sprintfa(channels, " %s", keys->str); + server->channels_join(server, channels->str, TRUE); } + + g_string_free(channels, TRUE); + g_string_free(keys, TRUE); } static int sig_rejoin(void) @@ -88,19 +193,31 @@ static int sig_rejoin(void) for (tmp = servers; tmp != NULL; tmp = tmp->next) { IRC_SERVER_REC *rec = tmp->data; - if (IS_IRC_SERVER(rec)) + if (IS_IRC_SERVER(rec) && rec->rejoin_channels != NULL) server_rejoin_channels(rec); } return TRUE; } +static void cmd_rmrejoins(const char *data, IRC_SERVER_REC *server) +{ + if (!IS_IRC_SERVER(server) || !server->connected) + cmd_return_error(CMDERR_NOT_CONNECTED); + + while (server->rejoin_channels != NULL) + rejoin_destroy(server, server->rejoin_channels->data); +} + void channel_rejoin_init(void) { rejoin_tag = g_timeout_add(REJOIN_TIMEOUT, (GSourceFunc) sig_rejoin, NULL); + command_bind("rmrejoins", NULL, (SIGNAL_FUNC) cmd_rmrejoins); signal_add_first("event 437", (SIGNAL_FUNC) event_target_unavailable); + signal_add_first("channel joined", (SIGNAL_FUNC) sig_remove_rejoin); + signal_add_first("channel destroyed", (SIGNAL_FUNC) sig_remove_rejoin); signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected); } @@ -108,6 +225,9 @@ void channel_rejoin_deinit(void) { g_source_remove(rejoin_tag); + command_unbind("rmrejoins", (SIGNAL_FUNC) cmd_rmrejoins); signal_remove("event 437", (SIGNAL_FUNC) event_target_unavailable); + signal_remove("channel joined", (SIGNAL_FUNC) sig_remove_rejoin); + signal_remove("channel destroyed", (SIGNAL_FUNC) sig_remove_rejoin); signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); } diff --git a/src/irc/core/channels-query.c b/src/irc/core/channels-query.c index 96f17f4d..bb48ef9f 100644 --- a/src/irc/core/channels-query.c +++ b/src/irc/core/channels-query.c @@ -22,8 +22,8 @@ How the thing works: - - After channel is joined and NAMES list is got, send "channel query" signal - - "channel query" : add channel to server->quries lists + - After channel is joined and NAMES list is got, send "channel joined" signal + - "channel joined" : add channel to server->queries lists loop: - Wait for NAMES list from all channels before doing anything else.. @@ -304,11 +304,12 @@ static void channels_query_check(IRC_SERVER_REC *server) channel_send_query(server, query); } -static void sig_channel_query(IRC_CHANNEL_REC *channel) +static void sig_channel_joined(IRC_CHANNEL_REC *channel) { SERVER_QUERY_REC *rec; - g_return_if_fail(channel != NULL); + if (!IS_IRC_CHANNEL(channel)) + return; /* Add channel to query lists */ if (!channel->no_modes) @@ -567,7 +568,7 @@ void channels_query_init(void) { signal_add("server connected", (SIGNAL_FUNC) sig_connected); signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected); - signal_add("channel query", (SIGNAL_FUNC) sig_channel_query); + signal_add("channel joined", (SIGNAL_FUNC) sig_channel_joined); signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); signal_add("chanquery mode", (SIGNAL_FUNC) event_channel_mode); @@ -584,7 +585,7 @@ void channels_query_deinit(void) { signal_remove("server connected", (SIGNAL_FUNC) sig_connected); signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); - signal_remove("channel query", (SIGNAL_FUNC) sig_channel_query); + signal_remove("channel joined", (SIGNAL_FUNC) sig_channel_joined); signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); signal_remove("chanquery mode", (SIGNAL_FUNC) event_channel_mode); diff --git a/src/irc/core/irc-channels.c b/src/irc/core/irc-channels.c index fffd2445..7daba896 100644 --- a/src/irc/core/irc-channels.c +++ b/src/irc/core/irc-channels.c @@ -21,15 +21,16 @@ #include "module.h" #include "signals.h" #include "misc.h" - -#include "bans.h" -#include "irc-channels.h" +#include "levels.h" #include "channels-setup.h" + #include "irc.h" +#include "bans.h" #include "modes.h" -#include "levels.h" #include "mode-lists.h" +#include "irc-channels.h" #include "irc-nicklist.h" +#include "channel-rejoin.h" void channels_query_init(void); void channels_query_deinit(void); @@ -37,9 +38,6 @@ void channels_query_deinit(void); void channel_events_init(void); void channel_events_deinit(void); -void channel_rejoin_init(void); -void channel_rejoin_deinit(void); - void massjoin_init(void); void massjoin_deinit(void); @@ -104,12 +102,12 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data, int use_keys; g_return_if_fail(data != NULL); - if (!IS_IRC_SERVER(server) || !server->connected) - cmd_return_error(CMDERR_NOT_CONNECTED); + g_return_if_fail(IS_IRC_SERVER(server) && server->connected); + if (*data == '\0') return; - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channels, &keys)) + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, + &channels, &keys)) return; - if (*channels == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); chanlist = g_strsplit(channels, ",", -1); keylist = g_strsplit(keys, ",", -1); @@ -202,7 +200,7 @@ void irc_channels_init(void) signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); channel_events_init(); - channel_rejoin_init(); + channel_rejoin_init(); /* after channel_events_init() */ channels_query_init(); channels_setup_init(); diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c index 420b3834..a107d15a 100644 --- a/src/irc/core/irc-nicklist.c +++ b/src/irc/core/irc-nicklist.c @@ -107,7 +107,7 @@ static void event_end_of_names(const char *data, SERVER_REC *server) chanrec = irc_channel_find(server, channel); if (chanrec != NULL && !chanrec->names_got) { chanrec->names_got = TRUE; - signal_emit("channel query", 1, chanrec); + signal_emit("channel joined", 1, chanrec); } g_free(params); |