static int last_reconnect_tag;
static int reconnect_timeout_tag;
static int reconnect_time;
+static int connect_timeout;
void reconnect_save_status(SERVER_CONNECT_REC *conn, SERVER_REC *server)
{
+ g_free_not_null(conn->tag);
+ conn->tag = g_strdup(server->tag);
+
g_free_not_null(conn->away_reason);
conn->away_reason = !server->usermode_away ? NULL :
g_strdup(server->away_reason);
+ if (!server->connected) {
+ /* default to channels/usermode from connect record
+ since server isn't fully connected yet */
+ g_free_not_null(conn->channels);
+ conn->channels = server->connrec->no_autojoin_channels ? NULL :
+ g_strdup(server->connrec->channels);
+
+ g_free_not_null(conn->channels);
+ conn->channels = g_strdup(server->connrec->channels);
+ }
+
signal_emit("server reconnect save status", 2, conn, server);
}
rec = g_new(RECONNECT_REC, 1);
rec->tag = ++last_reconnect_tag;
- rec->conn = conn;
rec->next_connect = next_connect;
+ rec->conn = conn;
+ conn->reconnecting = TRUE;
+ server_connect_ref(conn);
+
reconnects = g_slist_append(reconnects, rec);
}
-void server_reconnect_destroy(RECONNECT_REC *rec, int free_conn)
+void server_reconnect_destroy(RECONNECT_REC *rec)
{
g_return_if_fail(rec != NULL);
reconnects = g_slist_remove(reconnects, rec);
signal_emit("server reconnect remove", 1, rec);
- if (free_conn) server_connect_free(rec->conn);
+ server_connect_unref(rec->conn);
g_free(rec);
if (reconnects == NULL)
static int server_reconnect_timeout(void)
{
SERVER_CONNECT_REC *conn;
- GSList *list, *tmp;
+ GSList *list, *tmp, *next;
time_t now;
+ now = time(NULL);
+
+ /* timeout any connections that haven't gotten to connected-stage */
+ for (tmp = servers; tmp != NULL; tmp = next) {
+ SERVER_REC *server = tmp->data;
+
+ next = tmp->next;
+ if (!server->connected &&
+ server->connect_time + connect_timeout < now &&
+ connect_timeout > 0) {
+ server->connection_lost = TRUE;
+ server_disconnect(server);
+ }
+ }
+
/* If server_connect() removes the next reconnection in queue,
we're screwed. I don't think this should happen anymore, but just
to be sure we don't crash, do this safely. */
list = g_slist_copy(reconnects);
- now = time(NULL);
for (tmp = list; tmp != NULL; tmp = tmp->next) {
RECONNECT_REC *rec = tmp->data;
if (rec->next_connect <= now) {
conn = rec->conn;
- server_reconnect_destroy(rec, FALSE);
- CHAT_PROTOCOL(conn)->server_connect(conn);
+ server_connect_ref(conn);
+ server_reconnect_destroy(rec);
+ server_connect(conn);
+ server_connect_unref(conn);
}
}
if (conn->port == 0) conn->port = rec->port;
server_setup_fill_reconn(conn, rec);
- if (rec->last_connect > time(NULL)-reconnect_time) {
- /* can't reconnect this fast, wait.. */
- server_reconnect_add(conn, rec->last_connect+reconnect_time);
- } else {
- /* connect to server.. */
- CHAT_PROTOCOL(conn)->server_connect(conn);
- }
+ server_reconnect_add(conn, rec->last_connect+reconnect_time);
+ server_connect_unref(conn);
}
static SERVER_CONNECT_REC *
signal_emit("server connect copy", 2, &dest, src);
g_return_val_if_fail(dest != NULL, NULL);
+ server_connect_ref(dest);
dest->type = module_get_uniq_id("SERVER CONNECT", 0);
dest->reconnection = src->reconnection;
dest->proxy = g_strdup(src->proxy);
dest->proxy_port = src->proxy_port;
dest->proxy_string = g_strdup(src->proxy_string);
+ dest->proxy_string_after = g_strdup(src->proxy_string_after);
dest->proxy_password = g_strdup(src->proxy_password);
+ dest->tag = g_strdup(src->tag);
+
if (connect_info) {
dest->family = src->family;
dest->address = g_strdup(src->address);
dest->channels = g_strdup(src->channels);
dest->away_reason = g_strdup(src->away_reason);
+ dest->no_autojoin_channels = src->no_autojoin_channels;
+
+ dest->use_ssl = src->use_ssl;
+ dest->ssl_cert = g_strdup(src->ssl_cert);
+ dest->ssl_pkey = g_strdup(src->ssl_pkey);
+ dest->ssl_verify = src->ssl_verify;
+ dest->ssl_cafile = g_strdup(src->ssl_cafile);
+ dest->ssl_capath = g_strdup(src->ssl_capath);
return dest;
}
#define server_should_reconnect(server) \
- ((server)->connection_lost && ((server)->connrec->chatnet != NULL || \
- (!(server)->banned && !(server)->dns_error)))
+ ((server)->connection_lost && !(server)->no_reconnect && \
+ ((server)->connrec->chatnet != NULL || \
+ (!(server)->banned && !(server)->dns_error)))
#define sserver_connect_ok(rec, net) \
(!(rec)->banned && !(rec)->dns_error && (rec)->chatnet != NULL && \
}
sserver = server_setup_find(server->connrec->address,
- server->connrec->port);
+ server->connrec->port,
+ server->connrec->chatnet);
if (sserver != NULL) {
/* save the last connection time/status */
sserver->last_connect = server->connect_time == 0 ?
time(NULL) : server->connect_time;
sserver->last_failed = !server->connected;
- if (server->banned) sserver->banned = TRUE;
- if (server->dns_error) sserver->dns_error = TRUE;
+ sserver->banned = server->banned;
+ sserver->dns_error = server->dns_error;
}
if (sserver == NULL || conn->chatnet == NULL) {
conn->port = server->connrec->port;
conn->password = g_strdup(server->connrec->password);
- if (server->connect_time != 0 &&
- time(NULL)-server->connect_time > reconnect_time) {
- /* there's been enough time since last connection,
- reconnect back immediately */
- CHAT_PROTOCOL(conn)->server_connect(conn);
- } else {
- /* reconnect later.. */
- server_reconnect_add(conn, (server->connect_time == 0 ? time(NULL) :
- server->connect_time) + reconnect_time);
- }
+ server_reconnect_add(conn, (server->connect_time == 0 ? time(NULL) :
+ server->connect_time) + reconnect_time);
+ server_connect_unref(conn);
return;
}
/* always try to first connect to the first on the list where we
- haven't got unsuccessful connection attempts for the last half
+ haven't got unsuccessful connection attempts for the past half
an hour. */
now = time(NULL);
if (through) {
/* shouldn't happen unless there's no servers in
this chatnet in setup.. */
- server_connect_free(conn);
+ server_connect_unref(conn);
break;
}
static void cmd_rmreconns(void)
{
while (reconnects != NULL)
- server_reconnect_destroy(reconnects->data, TRUE);
+ server_reconnect_destroy(reconnects->data);
}
static RECONNECT_REC *reconnect_find_tag(int tag)
rec = reconnects->data;
list = g_slist_append(list, rec->conn);
- server_reconnect_destroy(rec, FALSE);
+ server_connect_ref(rec->conn);
+ server_reconnect_destroy(rec);
}
while (list != NULL) {
conn = list->data;
- CHAT_PROTOCOL(conn)->server_connect(conn);
+ server_connect(conn);
+ server_connect_unref(conn);
list = g_slist_remove(list, conn);
}
}
-/* SYNTAX: RECONNECT <tag> */
+/* SYNTAX: RECONNECT <tag> [<quit message>] */
static void cmd_reconnect(const char *data, SERVER_REC *server)
{
SERVER_CONNECT_REC *conn;
RECONNECT_REC *rec;
- int tag;
+ char *tag, *msg;
+ void *free_arg;
+ int tagnum;
+
+ if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg))
+ return;
- if (*data == '\0' && server != NULL) {
- /* reconnect back to same server */
+ if (*tag != '\0' && strcmp(tag, "*") != 0)
+ server = server_find_tag(tag);
+
+ if (server != NULL) {
+ /* reconnect connected server */
conn = server_connect_copy_skeleton(server->connrec, TRUE);
- if (server->connected) {
+ if (server->connected)
reconnect_save_status(conn, server);
- signal_emit("command disconnect", 2,
- "* Reconnecting", server);
- }
+
+ msg = g_strconcat("* ", *msg == '\0' ?
+ "Reconnecting" : msg, NULL);
+ signal_emit("command disconnect", 2, msg, server);
+ g_free(msg);
conn->reconnection = TRUE;
- CHAT_PROTOCOL(conn)->server_connect(conn);
+ server_connect(conn);
+ server_connect_unref(conn);
+ cmd_params_free(free_arg);
return;
}
- if (g_strcasecmp(data, "all") == 0) {
+ if (g_strcasecmp(tag, "all") == 0) {
/* reconnect all servers in reconnect queue */
reconnect_all();
+ cmd_params_free(free_arg);
return;
}
if (*data == '\0') {
/* reconnect to first server in reconnection list */
if (reconnects == NULL)
- cmd_return_error(CMDERR_NOT_CONNECTED);
+ cmd_param_error(CMDERR_NOT_CONNECTED);
rec = reconnects->data;
} else {
if (g_strncasecmp(data, "RECON-", 6) == 0)
data += 6;
- tag = atoi(data);
- rec = tag <= 0 ? NULL : reconnect_find_tag(tag);
+ tagnum = atoi(tag);
+ rec = tagnum <= 0 ? NULL : reconnect_find_tag(tagnum);
+ }
- if (rec == NULL) {
- signal_emit("server reconnect not found", 1, data);
- return;
- }
+ if (rec == NULL) {
+ signal_emit("server reconnect not found", 1, data);
+ } else {
+ conn = rec->conn;
+ server_connect_ref(conn);
+ server_reconnect_destroy(rec);
+ server_connect(conn);
+ server_connect_unref(conn);
}
- conn = rec->conn;
- server_reconnect_destroy(rec, FALSE);
- CHAT_PROTOCOL(conn)->server_connect(conn);
+ cmd_params_free(free_arg);
}
static void cmd_disconnect(const char *data, SERVER_REC *server)
{
RECONNECT_REC *rec;
- int tag;
if (g_strncasecmp(data, "RECON-", 6) != 0)
return; /* handle only reconnection removing */
- rec = sscanf(data+6, "%d", &tag) == 1 && tag > 0 ?
- reconnect_find_tag(tag) : NULL;
+ rec = reconnect_find_tag(atoi(data+6));
if (rec == NULL)
signal_emit("server reconnect not found", 1, data);
else
- server_reconnect_destroy(rec, TRUE);
+ server_reconnect_destroy(rec);
signal_stop();
}
next = tmp->next;
if (rec->conn->chat_type == proto->id)
- server_reconnect_destroy(rec, TRUE);
+ server_reconnect_destroy(rec);
}
}
static void read_settings(void)
{
- reconnect_time = settings_get_int("server_reconnect_time");
+ reconnect_time = settings_get_time("server_reconnect_time")/1000;
+ connect_timeout = settings_get_time("server_connect_timeout")/1000;
}
void servers_reconnect_init(void)
{
- settings_add_int("server", "server_reconnect_time", 300);
+ settings_add_time("server", "server_reconnect_time", "5min");
+ settings_add_time("server", "server_connect_timeout", "5min");
reconnects = NULL;
last_reconnect_tag = 0;