diff finch/gntconn.c @ 17977:f71bd7e56389

propagate from branch 'im.pidgin.pidgin' (head b438ea0760758dc547f95d62892455f50ee4c4f1) to branch 'im.pidgin.soc.2007.remotelogging' (head 7e683fd40634aa3eb22dcf25cbd25c8959d76662)
author Michael Shkutkov <mshkutkov@soc.pidgin.im>
date Sat, 09 Jun 2007 12:01:29 +0000
parents 8c3a3407af58
children 392889212240
line wrap: on
line diff
--- a/finch/gntconn.c	Sun Apr 22 11:11:49 2007 +0000
+++ b/finch/gntconn.c	Sat Jun 09 12:01:29 2007 +0000
@@ -24,42 +24,131 @@
  */
 #include "account.h"
 #include "core.h"
+#include "connection.c"
+#include "debug.h"
 #include "request.h"
 
 #include "gntconn.h"
 #include "finch.h"
 
+#define INITIAL_RECON_DELAY_MIN  8000
+#define INITIAL_RECON_DELAY_MAX 60000
+
+#define MAX_RECON_DELAY 600000
+
+typedef struct {
+	int delay;
+	guint timeout;
+} FinchAutoRecon;
+
+/**
+ * Contains accounts that are auto-reconnecting.
+ * The key is a pointer to the PurpleAccount and the
+ * value is a pointer to a FinchAutoRecon.
+ */
+static GHashTable *hash = NULL;
+
+static void
+free_auto_recon(gpointer data)
+{
+	FinchAutoRecon *info = data;
+
+	if (info->timeout != 0)
+		g_source_remove(info->timeout);
+
+	g_free(info);
+}
+
+
+static gboolean
+do_signon(gpointer data)
+{
+	PurpleAccount *account = data;
+	FinchAutoRecon *info;
+	PurpleStatus *status;
+
+	purple_debug_info("autorecon", "do_signon called\n");
+	g_return_val_if_fail(account != NULL, FALSE);
+	info = g_hash_table_lookup(hash, account);
+
+	if (info)
+		info->timeout = 0;
+
+	status = purple_account_get_active_status(account);
+	if (purple_status_is_online(status))
+	{
+		purple_debug_info("autorecon", "calling purple_account_connect\n");
+		purple_account_connect(account);
+		purple_debug_info("autorecon", "done calling purple_account_connect\n");
+	}
+
+	return FALSE;
+}
+
 static void
 finch_connection_report_disconnect(PurpleConnection *gc, const char *text)
 {
-	char *act, *primary, *secondary;
+	FinchAutoRecon *info;
 	PurpleAccount *account = purple_connection_get_account(gc);
 
-	act = g_strdup_printf(_("%s (%s)"), purple_account_get_username(account),
-			purple_account_get_protocol_name(account));
+	info = g_hash_table_lookup(hash, account);
 
-	primary = g_strdup_printf(_("%s disconnected."), act);
-	secondary = g_strdup_printf(_("%s was disconnected due to the following error:\n%s"),
-			act, text);
+	if (!gc->wants_to_die) {
+		if (info == NULL) {
+			info = g_new0(FinchAutoRecon, 1);
+			g_hash_table_insert(hash, account, info);
+			info->delay = g_random_int_range(INITIAL_RECON_DELAY_MIN, INITIAL_RECON_DELAY_MAX);
+		} else {
+			info->delay = MIN(2 * info->delay, MAX_RECON_DELAY);
+			if (info->timeout != 0)
+				g_source_remove(info->timeout);
+		}
+		info->timeout = g_timeout_add(info->delay, do_signon, account);
+	} else {
+		char *act, *primary, *secondary;
+		act = g_strdup_printf(_("%s (%s)"), purple_account_get_username(account),
+				purple_account_get_protocol_name(account));
 
-	purple_request_action(account, _("Connection Error"), primary, secondary, 1,
-						account, 2,
-						_("OK"), NULL,
-						_("Connect"),
-						PURPLE_CALLBACK(purple_account_connect));
+		primary = g_strdup_printf(_("%s disconnected."), act);
+		secondary = g_strdup_printf(_("%s\n\n"
+				"Finch will not attempt to reconnect the account until you "
+				"correct the error and re-enable the account."), text);
+		purple_notify_error(NULL, NULL, primary, secondary);
+
+		g_free(act);
+		g_free(primary);
+		g_free(secondary);
+		purple_account_set_enabled(account, FINCH_UI, FALSE);
+	}
+}
 
-	g_free(act);
-	g_free(primary);
-	g_free(secondary);
+static void
+account_removed_cb(PurpleAccount *account, gpointer user_data)
+{
+	g_hash_table_remove(hash, account);
+}
+
+static void *
+finch_connection_get_handle(void)
+{
+	static int handle;
+
+	return &handle;
 }
 
 static PurpleConnectionUiOps ops = 
 {
-	.connect_progress = NULL,
-	.connected = NULL,
-	.disconnected = NULL,
-	.notice = NULL,
-	.report_disconnect = finch_connection_report_disconnect
+	NULL, /* connect_progress */
+	NULL, /* connected */
+	NULL, /* disconnected */
+	NULL, /* notice */
+	finch_connection_report_disconnect,
+	NULL, /* network_connected */
+	NULL, /* network_disconnected */
+	NULL,
+	NULL,
+	NULL,
+	NULL
 };
 
 PurpleConnectionUiOps *finch_connections_get_ui_ops()
@@ -68,8 +157,18 @@
 }
 
 void finch_connections_init()
-{}
+{
+	hash = g_hash_table_new_full(
+							g_direct_hash, g_direct_equal,
+							NULL, free_auto_recon);
+
+	purple_signal_connect(purple_accounts_get_handle(), "account-removed",
+						finch_connection_get_handle(),
+						PURPLE_CALLBACK(account_removed_cb), NULL);
+}
 
 void finch_connections_uninit()
-{}
-
+{
+	purple_signals_disconnect_by_handle(finch_connection_get_handle());
+	g_hash_table_destroy(hash);
+}