# HG changeset patch # User Richard Nelson # Date 1180222902 0 # Node ID 8c3a3407af587e74f4a06abb97560adff0383a55 # Parent 202f4df12cf4e32a96fbb41801ae8ba254511c0a Finch autoreconnecting (largely copy/paste from pidgin) diff -r 202f4df12cf4 -r 8c3a3407af58 finch/gntaccount.c --- a/finch/gntaccount.c Sat May 26 18:03:09 2007 +0000 +++ b/finch/gntaccount.c Sat May 26 23:41:42 2007 +0000 @@ -717,6 +717,15 @@ gnt_tree_remove(GNT_TREE(accounts.tree), account); } +static void +account_abled_cb(PurpleAccount *account, gpointer user_data) +{ + if (accounts.window == NULL) + return; + gnt_tree_set_choice(GNT_TREE(accounts.tree), account, + GPOINTER_TO_INT(user_data)); +} + void finch_accounts_init() { GList *iter; @@ -727,7 +736,13 @@ purple_signal_connect(purple_accounts_get_handle(), "account-removed", finch_accounts_get_handle(), PURPLE_CALLBACK(account_removed_callback), NULL); - + purple_signal_connect(purple_accounts_get_handle(), "account-disabled", + finch_accounts_get_handle(), + PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(FALSE)); + purple_signal_connect(purple_accounts_get_handle(), "account-enabled", + finch_accounts_get_handle(), + PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE)); + for (iter = purple_accounts_get_all(); iter; iter = iter->next) { if (purple_account_get_enabled(iter->data, FINCH_UI)) break; diff -r 202f4df12cf4 -r 8c3a3407af58 finch/gntconn.c --- a/finch/gntconn.c Sat May 26 18:03:09 2007 +0000 +++ b/finch/gntconn.c Sat May 26 23:41:42 2007 +0000 @@ -24,34 +24,116 @@ */ #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, NULL, NULL, - 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 = @@ -75,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); +}