Merged pidgin/main into default
[pidgin-git.git] / pidgin / gtkconn.c
blobecb6db53a86d550a94c2c6d0e705bb565b582b78
1 /* pidgin
3 * Pidgin is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 #include "internal.h"
22 #include "pidgin.h"
24 #include "account.h"
25 #include "debug.h"
26 #include "notify.h"
27 #include "prefs.h"
28 #include "gtkblist.h"
29 #include "gtkconn.h"
30 #include "gtkdialogs.h"
31 #include "gtkstatusbox.h"
32 #include "pidginstock.h"
33 #include "gtkutils.h"
34 #include "util.h"
36 #define INITIAL_RECON_DELAY_MIN 8000
37 #define INITIAL_RECON_DELAY_MAX 60000
39 #define MAX_RECON_DELAY 600000
40 #define MAX_RACCOON_DELAY "shorter in urban areas"
42 typedef struct {
43 int delay;
44 guint timeout;
45 } PidginAutoRecon;
48 * Contains accounts that are auto-reconnecting.
49 * The key is a pointer to the PurpleAccount and the
50 * value is a pointer to a PidginAutoRecon.
52 static GHashTable *auto_reconns = NULL;
54 static void
55 pidgin_connection_connect_progress(PurpleConnection *gc,
56 const char *text, size_t step, size_t step_count)
58 PidginBuddyList *gtkblist = pidgin_blist_get_default_gtk_blist();
59 if (!gtkblist)
60 return;
61 pidgin_status_box_set_connecting(PIDGIN_STATUS_BOX(gtkblist->statusbox),
62 (purple_connections_get_connecting() != NULL));
63 pidgin_status_box_pulse_connecting(PIDGIN_STATUS_BOX(gtkblist->statusbox));
66 static void
67 pidgin_connection_connected(PurpleConnection *gc)
69 PurpleAccount *account;
70 PidginBuddyList *gtkblist;
72 account = purple_connection_get_account(gc);
73 gtkblist = pidgin_blist_get_default_gtk_blist();
75 if (gtkblist != NULL)
76 pidgin_status_box_set_connecting(PIDGIN_STATUS_BOX(gtkblist->statusbox),
77 (purple_connections_get_connecting() != NULL));
79 g_hash_table_remove(auto_reconns, account);
82 static void
83 pidgin_connection_disconnected(PurpleConnection *gc)
85 PidginBuddyList *gtkblist = pidgin_blist_get_default_gtk_blist();
86 if (!gtkblist)
87 return;
88 pidgin_status_box_set_connecting(PIDGIN_STATUS_BOX(gtkblist->statusbox),
89 (purple_connections_get_connecting() != NULL));
91 if (purple_connections_get_all() != NULL)
92 return;
94 pidgin_dialogs_destroy_all();
97 static void
98 free_auto_recon(gpointer data)
100 PidginAutoRecon *info = data;
102 if (info->timeout != 0)
103 g_source_remove(info->timeout);
105 g_free(info);
108 static gboolean
109 do_signon(gpointer data)
111 PurpleAccount *account = data;
112 PidginAutoRecon *info;
113 PurpleStatus *status;
115 purple_debug_info("autorecon", "do_signon called\n");
116 g_return_val_if_fail(account != NULL, FALSE);
117 info = g_hash_table_lookup(auto_reconns, account);
119 if (info)
120 info->timeout = 0;
122 status = purple_account_get_active_status(account);
123 if (purple_status_is_online(status))
125 purple_debug_info("autorecon", "calling purple_account_connect\n");
126 purple_account_connect(account);
127 purple_debug_info("autorecon", "done calling purple_account_connect\n");
130 return FALSE;
133 static void
134 pidgin_connection_report_disconnect(PurpleConnection *gc,
135 PurpleConnectionError reason,
136 const char *text)
138 PurpleAccount *account = NULL;
139 PidginAutoRecon *info;
141 account = purple_connection_get_account(gc);
142 info = g_hash_table_lookup(auto_reconns, account);
144 if (!purple_connection_error_is_fatal (reason)) {
145 if (info == NULL) {
146 info = g_new0(PidginAutoRecon, 1);
147 g_hash_table_insert(auto_reconns, account, info);
148 info->delay = g_random_int_range(INITIAL_RECON_DELAY_MIN, INITIAL_RECON_DELAY_MAX);
149 } else {
150 info->delay = MIN(2 * info->delay, MAX_RECON_DELAY);
151 if (info->timeout != 0)
152 g_source_remove(info->timeout);
154 info->timeout = g_timeout_add(info->delay, do_signon, account);
155 } else {
156 if (info != NULL)
157 g_hash_table_remove(auto_reconns, account);
159 purple_account_set_enabled(account, PIDGIN_UI, FALSE);
163 static void pidgin_connection_network_connected (void)
165 GList *list, *l;
166 PidginBuddyList *gtkblist = pidgin_blist_get_default_gtk_blist();
168 if(gtkblist)
169 pidgin_status_box_set_network_available(PIDGIN_STATUS_BOX(gtkblist->statusbox), TRUE);
171 l = list = purple_accounts_get_all_active();
172 while (l) {
173 PurpleAccount *account = (PurpleAccount*)l->data;
174 g_hash_table_remove(auto_reconns, account);
175 if (purple_account_is_disconnected(account))
176 do_signon(account);
177 l = l->next;
179 g_list_free(list);
182 static void pidgin_connection_network_disconnected (void)
184 GList *list, *l;
185 PidginBuddyList *gtkblist = pidgin_blist_get_default_gtk_blist();
187 if(gtkblist)
188 pidgin_status_box_set_network_available(PIDGIN_STATUS_BOX(gtkblist->statusbox), FALSE);
190 l = list = purple_accounts_get_all_active();
191 while (l) {
192 PurpleAccount *a = (PurpleAccount*)l->data;
193 if (!purple_account_is_disconnected(a)) {
194 purple_account_disconnect(a);
196 l = l->next;
198 g_list_free(list);
201 static void pidgin_connection_notice(PurpleConnection *gc, const char *text)
204 static PurpleConnectionUiOps conn_ui_ops =
206 pidgin_connection_connect_progress,
207 pidgin_connection_connected,
208 pidgin_connection_disconnected,
209 pidgin_connection_notice,
210 pidgin_connection_network_connected,
211 pidgin_connection_network_disconnected,
212 pidgin_connection_report_disconnect,
213 NULL,
214 NULL,
215 NULL,
216 NULL
219 PurpleConnectionUiOps *
220 pidgin_connections_get_ui_ops(void)
222 return &conn_ui_ops;
225 static void
226 account_removed_cb(PurpleAccount *account, gpointer user_data)
228 g_hash_table_remove(auto_reconns, account);
232 /**************************************************************************
233 * GTK+ connection glue
234 **************************************************************************/
236 void *
237 pidgin_connection_get_handle(void)
239 static int handle;
241 return &handle;
244 void
245 pidgin_connection_init(void)
247 auto_reconns = g_hash_table_new_full(
248 g_direct_hash, g_direct_equal,
249 NULL, free_auto_recon);
251 purple_signal_connect(purple_accounts_get_handle(), "account-removed",
252 pidgin_connection_get_handle(),
253 PURPLE_CALLBACK(account_removed_cb), NULL);
256 void
257 pidgin_connection_uninit(void)
259 purple_signals_disconnect_by_handle(pidgin_connection_get_handle());
261 g_hash_table_destroy(auto_reconns);