diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index 54de8d38..0541d1b2 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -48,7 +48,7 @@ static void server_reconnect_add(SERVER_CONNECT_REC *conn, reconnects = g_slist_append(reconnects, rec); } -static void server_reconnect_destroy(RECONNECT_REC *rec, int free_conn) +void server_reconnect_destroy(RECONNECT_REC *rec, int free_conn) { g_return_if_fail(rec != NULL); @@ -93,7 +93,7 @@ static int server_reconnect_timeout(void) static void sserver_connect(SERVER_SETUP_REC *rec, SERVER_CONNECT_REC *conn) { conn->address = g_strdup(rec->address); - conn->port = rec->port; + if (conn->port == 0) conn->port = rec->port; server_setup_fill_reconn(conn, rec); if (rec->last_connect > time(NULL)-reconnect_time) { @@ -209,6 +209,8 @@ static void sig_reconnect(SERVER_REC *server) if (rec->chatnet != NULL && g_strcasecmp(conn->chatnet, rec->chatnet) == 0 && !rec->banned && (!rec->last_connect || !rec->last_failed || rec->last_connect < now-FAILED_RECONNECT_WAIT)) { + if (rec == sserver) + conn->port = server->connrec->port; sserver_connect(rec, conn); return; } @@ -224,6 +226,8 @@ static void sig_reconnect(SERVER_REC *server) found = TRUE; else if (found && !rec->banned && rec->chatnet != NULL && g_strcasecmp(conn->chatnet, rec->chatnet) == 0) { + if (rec == sserver) + conn->port = server->connrec->port; sserver_connect(rec, conn); break; } diff --git a/src/core/servers-reconnect.h b/src/core/servers-reconnect.h index 6b1da025..50bcfc06 100644 --- a/src/core/servers-reconnect.h +++ b/src/core/servers-reconnect.h @@ -14,6 +14,8 @@ typedef struct { extern GSList *reconnects; +void server_reconnect_destroy(RECONNECT_REC *rec, int free_conn); + void servers_reconnect_init(void); void servers_reconnect_deinit(void); diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index 6ca760f7..65336b81 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -26,6 +26,7 @@ #include "settings.h" #include "window-item-def.h" +#include "servers-reconnect.h" #include "servers-redirect.h" #include "servers-setup.h" #include "nicklist.h" @@ -102,38 +103,87 @@ static void cmd_connect(const char *data) irc_connect_server(data); } +static RECONNECT_REC *find_reconnect_server(const char *addr, int port) +{ + RECONNECT_REC *match; + GSList *tmp; + + g_return_val_if_fail(addr != NULL, NULL); + + if (g_slist_length(reconnects) == 1) { + /* only one reconnection, we probably want to use it */ + match = reconnects->data; + return IS_IRC_SERVER_CONNECT(match->conn) ? match : NULL; + } + + /* check if there's a reconnection to the same host and maybe even + the same port */ + match = NULL; + for (tmp = reconnects; tmp != NULL; tmp = tmp->next) { + RECONNECT_REC *rec = tmp->data; + + if (IS_IRC_SERVER_CONNECT(rec->conn) && + g_strcasecmp(rec->conn->address, addr) == 0) { + if (rec->conn->port == port) + return rec; + match = rec; + } + } + + return match; +} + /* SYNTAX: SERVER [-ircnet ] [-host ] [+]
| [ [ []]] */ static void cmd_server(const char *data, IRC_SERVER_REC *server, void *item) { GHashTable *optlist; - char *addr, *channels, *away_reason, *usermode, *ircnet; + IRC_SERVER_CONNECT_REC *conn; + char *addr, *port, *channels, *away_reason, *usermode, *ircnet; void *free_arg; int no_old_server; g_return_if_fail(data != NULL); - if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS, - "connect", &optlist, &addr)) + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS, + "connect", &optlist, &addr, &port)) return; if (*addr == '\0' || strcmp(addr, "+") == 0) cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + conn = server == NULL ? NULL : server->connrec; + if (*addr != '+' && conn == NULL) { + /* check if there's a server waiting for removal in + reconnection queue.. */ + RECONNECT_REC *rec; + + rec = find_reconnect_server(addr, atoi(port)); + if (rec != NULL) { + /* remove the reconnection.. */ + conn = (IRC_SERVER_CONNECT_REC *) rec->conn; + server_reconnect_destroy(rec, FALSE); + } + } + no_old_server = server == NULL; - if (*addr == '+' || server == NULL) { - channels = away_reason = usermode = ircnet = NULL; - } else { - ircnet = g_strdup(server->connrec->chatnet); + ircnet = conn == NULL ? NULL : g_strdup(conn->chatnet); + if (*addr == '+' || conn == NULL) { + channels = away_reason = usermode = NULL; + } else if (server != NULL) { channels = irc_server_get_channels((IRC_SERVER_REC *) server); if (*channels == '\0') g_free_and_null(channels); - usermode = g_strdup(server->usermode); away_reason = !server->usermode_away ? NULL : g_strdup(server->away_reason); + usermode = g_strdup(server->usermode); signal_emit("command disconnect", 3, "* Changing server", server, item); + } else { + channels = g_strdup(conn->channels); + away_reason = g_strdup(conn->away_reason); + usermode = g_strdup(conn->usermode); } server = IRC_SERVER(irc_connect_server(data)); @@ -143,11 +193,13 @@ static void cmd_server(const char *data, IRC_SERVER_REC *server, g_free_not_null(channels); g_free_not_null(usermode); g_free_not_null(away_reason); - } else if (server != NULL && !no_old_server) { + } else if (server != NULL && conn != NULL) { server->connrec->reconnection = TRUE; server->connrec->channels = channels; server->connrec->usermode = usermode; server->connrec->away_reason = away_reason; + if (no_old_server) + server_connect_free(SERVER_CONNECT(conn)); } g_free_not_null(ircnet); cmd_params_free(free_arg);