I guess I'll release this later today. Is that ok with everyone?
[pidgin-git.git] / pidgin / gtkconn.c
blob6fa8e3b0859d2e21fa68a3fc4e326df253ba3cdd
1 /*
2 * @file gtkconn.c GTK+ Connection API
3 * @ingroup pidgin
4 */
6 /* pidgin
8 * Pidgin 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 "internal.h"
27 #include "pidgin.h"
29 #include "account.h"
30 #include "debug.h"
31 #include "notify.h"
32 #include "prefs.h"
33 #include "gtkblist.h"
34 #include "gtkconn.h"
35 #include "gtkdialogs.h"
36 #include "gtkstatusbox.h"
37 #include "pidginstock.h"
38 #include "gtkutils.h"
39 #include "util.h"
41 #define INITIAL_RECON_DELAY_MIN 8000
42 #define INITIAL_RECON_DELAY_MAX 60000
44 #define MAX_RECON_DELAY 600000
45 #define MAX_RACCOON_DELAY "shorter in urban areas"
47 typedef struct {
48 int delay;
49 guint timeout;
50 } PidginAutoRecon;
52 /**
53 * Contains accounts that are auto-reconnecting.
54 * The key is a pointer to the PurpleAccount and the
55 * value is a pointer to a PidginAutoRecon.
57 static GHashTable *auto_reconns = NULL;
59 static void
60 pidgin_connection_connect_progress(PurpleConnection *gc,
61 const char *text, size_t step, size_t step_count)
63 PidginBuddyList *gtkblist = pidgin_blist_get_default_gtk_blist();
64 if (!gtkblist)
65 return;
66 pidgin_status_box_set_connecting(PIDGIN_STATUS_BOX(gtkblist->statusbox),
67 (purple_connections_get_connecting() != NULL));
68 pidgin_status_box_pulse_connecting(PIDGIN_STATUS_BOX(gtkblist->statusbox));
71 static void
72 pidgin_connection_connected(PurpleConnection *gc)
74 PurpleAccount *account;
75 PidginBuddyList *gtkblist;
77 account = purple_connection_get_account(gc);
78 gtkblist = pidgin_blist_get_default_gtk_blist();
80 if (gtkblist != NULL)
81 pidgin_status_box_set_connecting(PIDGIN_STATUS_BOX(gtkblist->statusbox),
82 (purple_connections_get_connecting() != NULL));
84 g_hash_table_remove(auto_reconns, account);
87 static void
88 pidgin_connection_disconnected(PurpleConnection *gc)
90 PidginBuddyList *gtkblist = pidgin_blist_get_default_gtk_blist();
91 if (!gtkblist)
92 return;
93 pidgin_status_box_set_connecting(PIDGIN_STATUS_BOX(gtkblist->statusbox),
94 (purple_connections_get_connecting() != NULL));
96 if (purple_connections_get_all() != NULL)
97 return;
99 pidgin_dialogs_destroy_all();
102 static void
103 free_auto_recon(gpointer data)
105 PidginAutoRecon *info = data;
107 if (info->timeout != 0)
108 g_source_remove(info->timeout);
110 g_free(info);
113 static gboolean
114 do_signon(gpointer data)
116 PurpleAccount *account = data;
117 PidginAutoRecon *info;
118 PurpleStatus *status;
120 purple_debug_info("autorecon", "do_signon called\n");
121 g_return_val_if_fail(account != NULL, FALSE);
122 info = g_hash_table_lookup(auto_reconns, account);
124 if (info)
125 info->timeout = 0;
127 status = purple_account_get_active_status(account);
128 if (purple_status_is_online(status))
130 purple_debug_info("autorecon", "calling purple_account_connect\n");
131 purple_account_connect(account);
132 purple_debug_info("autorecon", "done calling purple_account_connect\n");
135 return FALSE;
138 static void
139 pidgin_connection_report_disconnect_reason (PurpleConnection *gc,
140 PurpleConnectionError reason,
141 const char *text)
143 PurpleAccount *account = NULL;
144 PidginAutoRecon *info;
146 account = purple_connection_get_account(gc);
147 info = g_hash_table_lookup(auto_reconns, account);
149 if (!purple_connection_error_is_fatal (reason)) {
150 if (info == NULL) {
151 info = g_new0(PidginAutoRecon, 1);
152 g_hash_table_insert(auto_reconns, account, info);
153 info->delay = g_random_int_range(INITIAL_RECON_DELAY_MIN, INITIAL_RECON_DELAY_MAX);
154 } else {
155 info->delay = MIN(2 * info->delay, MAX_RECON_DELAY);
156 if (info->timeout != 0)
157 g_source_remove(info->timeout);
159 info->timeout = g_timeout_add(info->delay, do_signon, account);
160 } else {
161 if (info != NULL)
162 g_hash_table_remove(auto_reconns, account);
164 purple_account_set_enabled(account, PIDGIN_UI, FALSE);
168 static void pidgin_connection_network_connected (void)
170 GList *list, *l;
171 PidginBuddyList *gtkblist = pidgin_blist_get_default_gtk_blist();
173 if(gtkblist)
174 pidgin_status_box_set_network_available(PIDGIN_STATUS_BOX(gtkblist->statusbox), TRUE);
176 l = list = purple_accounts_get_all_active();
177 while (l) {
178 PurpleAccount *account = (PurpleAccount*)l->data;
179 g_hash_table_remove(auto_reconns, account);
180 if (purple_account_is_disconnected(account))
181 do_signon(account);
182 l = l->next;
184 g_list_free(list);
187 static void pidgin_connection_network_disconnected (void)
189 GList *list, *l;
190 PidginBuddyList *gtkblist = pidgin_blist_get_default_gtk_blist();
192 if(gtkblist)
193 pidgin_status_box_set_network_available(PIDGIN_STATUS_BOX(gtkblist->statusbox), FALSE);
195 l = list = purple_accounts_get_all_active();
196 while (l) {
197 PurpleAccount *a = (PurpleAccount*)l->data;
198 if (!purple_account_is_disconnected(a)) {
199 char *password = g_strdup(purple_account_get_password(a));
200 purple_account_disconnect(a);
201 purple_account_set_password(a, password);
202 g_free(password);
204 l = l->next;
206 g_list_free(list);
209 static void pidgin_connection_notice(PurpleConnection *gc, const char *text)
212 static PurpleConnectionUiOps conn_ui_ops =
214 pidgin_connection_connect_progress,
215 pidgin_connection_connected,
216 pidgin_connection_disconnected,
217 pidgin_connection_notice,
218 NULL, /* report_disconnect */
219 pidgin_connection_network_connected,
220 pidgin_connection_network_disconnected,
221 pidgin_connection_report_disconnect_reason,
222 NULL,
223 NULL,
224 NULL
227 PurpleConnectionUiOps *
228 pidgin_connections_get_ui_ops(void)
230 return &conn_ui_ops;
233 static void
234 account_removed_cb(PurpleAccount *account, gpointer user_data)
236 g_hash_table_remove(auto_reconns, account);
240 /**************************************************************************
241 * GTK+ connection glue
242 **************************************************************************/
244 void *
245 pidgin_connection_get_handle(void)
247 static int handle;
249 return &handle;
252 void
253 pidgin_connection_init(void)
255 auto_reconns = g_hash_table_new_full(
256 g_direct_hash, g_direct_equal,
257 NULL, free_auto_recon);
259 purple_signal_connect(purple_accounts_get_handle(), "account-removed",
260 pidgin_connection_get_handle(),
261 PURPLE_CALLBACK(account_removed_cb), NULL);
264 void
265 pidgin_connection_uninit(void)
267 purple_signals_disconnect_by_handle(pidgin_connection_get_handle());
269 g_hash_table_destroy(auto_reconns);