merge of '6696045322d43e1d7c9634a33cf10ca2323c061c'
[pidgin-git.git] / finch / gntconn.c
blobb23bb6a8d6b8c4f1f885114e79411d13e905b957
1 /**
2 * @file gntconn.c GNT Connection API
3 * @ingroup finch
4 */
6 /* finch
8 * Finch is the legal property of its developers, whose names are too numerous
9 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * source distribution.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 #include "finch.h"
27 #include <internal.h>
29 #include "account.h"
30 #include "core.h"
31 #include "connection.h"
32 #include "debug.h"
33 #include "request.h"
35 #include "gntaccount.h"
36 #include "gntconn.h"
38 #define INITIAL_RECON_DELAY_MIN 8000
39 #define INITIAL_RECON_DELAY_MAX 60000
41 #define MAX_RECON_DELAY 600000
43 typedef struct {
44 int delay;
45 guint timeout;
46 } FinchAutoRecon;
48 /**
49 * Contains accounts that are auto-reconnecting.
50 * The key is a pointer to the PurpleAccount and the
51 * value is a pointer to a FinchAutoRecon.
53 static GHashTable *hash = NULL;
55 static void
56 free_auto_recon(gpointer data)
58 FinchAutoRecon *info = data;
60 if (info->timeout != 0)
61 g_source_remove(info->timeout);
63 g_free(info);
67 static gboolean
68 do_signon(gpointer data)
70 PurpleAccount *account = data;
71 FinchAutoRecon *info;
72 PurpleStatus *status;
74 purple_debug_info("autorecon", "do_signon called\n");
75 g_return_val_if_fail(account != NULL, FALSE);
76 info = g_hash_table_lookup(hash, account);
78 if (info)
79 info->timeout = 0;
81 status = purple_account_get_active_status(account);
82 if (purple_status_is_online(status))
84 purple_debug_info("autorecon", "calling purple_account_connect\n");
85 purple_account_connect(account);
86 purple_debug_info("autorecon", "done calling purple_account_connect\n");
89 return FALSE;
92 static void
93 ce_modify_account_cb(PurpleAccount *account)
95 finch_account_dialog_show(account);
98 static void
99 ce_enable_account_cb(PurpleAccount *account)
101 purple_account_set_enabled(account, FINCH_UI, TRUE);
104 static void
105 finch_connection_report_disconnect(PurpleConnection *gc, PurpleConnectionError reason,
106 const char *text)
108 FinchAutoRecon *info;
109 PurpleAccount *account = purple_connection_get_account(gc);
110 GList *list;
112 if (!purple_connection_error_is_fatal(reason)) {
113 info = g_hash_table_lookup(hash, account);
115 if (info == NULL) {
116 info = g_new0(FinchAutoRecon, 1);
117 g_hash_table_insert(hash, account, info);
118 info->delay = g_random_int_range(INITIAL_RECON_DELAY_MIN, INITIAL_RECON_DELAY_MAX);
119 } else {
120 info->delay = MIN(2 * info->delay, MAX_RECON_DELAY);
121 if (info->timeout != 0)
122 g_source_remove(info->timeout);
124 info->timeout = g_timeout_add(info->delay, do_signon, account);
125 } else {
126 char *act, *primary, *secondary;
127 act = g_strdup_printf(_("%s (%s)"), purple_account_get_username(account),
128 purple_account_get_protocol_name(account));
130 primary = g_strdup_printf(_("%s disconnected."), act);
131 secondary = g_strdup_printf(_("%s\n\n"
132 "Finch will not attempt to reconnect the account until you "
133 "correct the error and re-enable the account."), text);
135 purple_request_action(account, NULL, primary, secondary, 2,
136 account, NULL, NULL,
137 account, 3,
138 _("OK"), NULL,
139 _("Modify Account"), PURPLE_CALLBACK(ce_modify_account_cb),
140 _("Re-enable Account"), PURPLE_CALLBACK(ce_enable_account_cb));
142 g_free(act);
143 g_free(primary);
144 g_free(secondary);
145 purple_account_set_enabled(account, FINCH_UI, FALSE);
148 /* If we have any open chats, we probably want to rejoin when we get back online. */
149 list = purple_get_chats();
150 while (list) {
151 PurpleConversation *conv = list->data;
152 list = list->next;
153 if (purple_conversation_get_account(conv) != account ||
154 purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)))
155 continue;
156 purple_conversation_set_data(conv, "want-to-rejoin", GINT_TO_POINTER(TRUE));
157 purple_conversation_write(conv, NULL, _("The account has disconnected and you are no "
158 "longer in this chat. You will be automatically rejoined in the chat when "
159 "the account reconnects."),
160 PURPLE_MESSAGE_SYSTEM, time(NULL));
164 static void
165 account_removed_cb(PurpleAccount *account, gpointer user_data)
167 g_hash_table_remove(hash, account);
170 static void *
171 finch_connection_get_handle(void)
173 static int handle;
175 return &handle;
178 static PurpleConnectionUiOps ops =
180 NULL, /* connect_progress */
181 NULL, /* connected */
182 NULL, /* disconnected */
183 NULL, /* notice */
184 NULL,
185 NULL, /* network_connected */
186 NULL, /* network_disconnected */
187 finch_connection_report_disconnect,
188 NULL,
189 NULL,
190 NULL
193 PurpleConnectionUiOps *finch_connections_get_ui_ops()
195 return &ops;
198 void finch_connections_init()
200 hash = g_hash_table_new_full(
201 g_direct_hash, g_direct_equal,
202 NULL, free_auto_recon);
204 purple_signal_connect(purple_accounts_get_handle(), "account-removed",
205 finch_connection_get_handle(),
206 PURPLE_CALLBACK(account_removed_cb), NULL);
209 void finch_connections_uninit()
211 purple_signals_disconnect_by_handle(finch_connection_get_handle());
212 g_hash_table_destroy(hash);