Mercurial > pidgin.yaz
annotate libgaim/connection.c @ 15013:4b7065af8549
[gaim-migrate @ 17793]
I think that setting info on connection is an AIM-specific thing. Jabber, at least,
has the server save the vcard and you should only set it when it changes. Setting
it on connection can break things.
If you know another protocol that requires info to be set on connection, please
add it to that prpl.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Mon, 20 Nov 2006 22:39:08 +0000 |
parents | 71404dbedabc |
children | a6aad36ca735 |
rev | line source |
---|---|
14192 | 1 /** |
2 * @file connection.c Connection API | |
3 * @ingroup core | |
4 * | |
5 * gaim | |
6 * | |
7 * Gaim is the legal property of its developers, whose names are too numerous | |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
10 * | |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
25 #include "internal.h" | |
26 #include "account.h" | |
27 #include "blist.h" | |
28 #include "connection.h" | |
29 #include "dbus-maybe.h" | |
30 #include "debug.h" | |
31 #include "log.h" | |
32 #include "notify.h" | |
33 #include "prefs.h" | |
14838 | 34 #include "proxy.h" |
14192 | 35 #include "request.h" |
36 #include "server.h" | |
37 #include "signals.h" | |
38 #include "util.h" | |
39 | |
40 static GList *connections = NULL; | |
41 static GList *connections_connecting = NULL; | |
42 static GaimConnectionUiOps *connection_ui_ops = NULL; | |
43 | |
44 static int connections_handle; | |
45 | |
46 static gboolean | |
47 send_keepalive(gpointer data) | |
48 { | |
49 GaimConnection *gc = data; | |
50 GaimPluginProtocolInfo *prpl_info = NULL; | |
51 | |
52 if (gc != NULL && gc->prpl != NULL) | |
53 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); | |
54 | |
55 if (prpl_info && prpl_info->keepalive) | |
56 prpl_info->keepalive(gc); | |
57 | |
58 return TRUE; | |
59 } | |
60 | |
61 static void | |
62 update_keepalive(GaimConnection *gc, gboolean on) | |
63 { | |
14483
af856551902b
[gaim-migrate @ 17202]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
64 GaimPluginProtocolInfo *prpl_info = NULL; |
af856551902b
[gaim-migrate @ 17202]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
65 |
af856551902b
[gaim-migrate @ 17202]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
66 if (gc != NULL && gc->prpl != NULL) |
af856551902b
[gaim-migrate @ 17202]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
67 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); |
af856551902b
[gaim-migrate @ 17202]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
68 |
af856551902b
[gaim-migrate @ 17202]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
69 if (!prpl_info || !prpl_info->keepalive) |
af856551902b
[gaim-migrate @ 17202]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
70 return; |
af856551902b
[gaim-migrate @ 17202]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14192
diff
changeset
|
71 |
14192 | 72 if (on && !gc->keepalive) |
73 { | |
74 gaim_debug_info("connection", "Activating keepalive.\n"); | |
75 gc->keepalive = gaim_timeout_add(30000, send_keepalive, gc); | |
76 } | |
77 else if (!on && gc->keepalive > 0) | |
78 { | |
79 gaim_debug_info("connection", "Deactivating keepalive.\n"); | |
80 gaim_timeout_remove(gc->keepalive); | |
81 gc->keepalive = 0; | |
82 } | |
83 } | |
84 | |
85 void | |
86 gaim_connection_new(GaimAccount *account, gboolean regist, const char *password) | |
87 { | |
88 GaimConnection *gc; | |
89 GaimPlugin *prpl; | |
90 GaimPluginProtocolInfo *prpl_info; | |
91 | |
92 g_return_if_fail(account != NULL); | |
93 | |
94 if (!gaim_account_is_disconnected(account)) | |
95 return; | |
96 | |
97 prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); | |
98 | |
99 if (prpl != NULL) | |
100 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(prpl); | |
101 else { | |
102 gchar *message; | |
103 | |
104 message = g_strdup_printf(_("Missing protocol plugin for %s"), | |
105 gaim_account_get_username(account)); | |
106 gaim_notify_error(NULL, regist ? _("Registration Error") : | |
107 _("Connection Error"), message, NULL); | |
108 g_free(message); | |
109 return; | |
110 } | |
111 | |
112 if (regist) | |
113 { | |
114 if (prpl_info->register_user == NULL) | |
115 return; | |
116 } | |
117 else | |
118 { | |
119 if (((password == NULL) || (*password == '\0')) && | |
120 !(prpl_info->options & OPT_PROTO_NO_PASSWORD) && | |
121 !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) | |
122 { | |
123 gaim_debug_error("connection", "Can not connect to account %s without " | |
124 "a password.\n", gaim_account_get_username(account)); | |
125 return; | |
126 } | |
127 } | |
128 | |
129 gc = g_new0(GaimConnection, 1); | |
130 GAIM_DBUS_REGISTER_POINTER(gc, GaimConnection); | |
131 | |
132 gc->prpl = prpl; | |
133 if ((password != NULL) && (*password != '\0')) | |
134 gc->password = g_strdup(password); | |
135 gaim_connection_set_account(gc, account); | |
136 gaim_connection_set_state(gc, GAIM_CONNECTING); | |
137 connections = g_list_append(connections, gc); | |
138 gaim_account_set_connection(account, gc); | |
139 | |
140 gaim_signal_emit(gaim_connections_get_handle(), "signing-on", gc); | |
141 | |
142 if (regist) | |
143 { | |
144 gaim_debug_info("connection", "Registering. gc = %p\n", gc); | |
145 | |
146 /* set this so we don't auto-reconnect after registering */ | |
147 gc->wants_to_die = TRUE; | |
148 | |
149 prpl_info->register_user(account); | |
150 } | |
151 else | |
152 { | |
153 gaim_debug_info("connection", "Connecting. gc = %p\n", gc); | |
154 | |
155 gaim_signal_emit(gaim_accounts_get_handle(), "account-connecting", account); | |
156 prpl_info->login(account); | |
157 } | |
158 } | |
159 | |
160 void | |
161 gaim_connection_destroy(GaimConnection *gc) | |
162 { | |
163 GaimAccount *account; | |
14752
4124030c3f3a
[gaim-migrate @ 17509]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14607
diff
changeset
|
164 GSList *buddies, *tmp; |
14192 | 165 #if 0 |
166 GList *wins; | |
167 #endif | |
168 GaimPluginProtocolInfo *prpl_info = NULL; | |
169 gboolean remove = FALSE; | |
170 | |
171 g_return_if_fail(gc != NULL); | |
172 | |
173 account = gaim_connection_get_account(gc); | |
174 | |
175 gaim_debug_info("connection", "Disconnecting connection %p\n", gc); | |
176 | |
177 if (gaim_connection_get_state(gc) != GAIM_CONNECTING) | |
178 remove = TRUE; | |
179 | |
180 gaim_signal_emit(gaim_connections_get_handle(), "signing-off", gc); | |
181 | |
182 while (gc->buddy_chats) | |
183 { | |
184 GaimConversation *b = gc->buddy_chats->data; | |
185 | |
186 gc->buddy_chats = g_slist_remove(gc->buddy_chats, b); | |
187 gaim_conv_chat_left(GAIM_CONV_CHAT(b)); | |
188 } | |
189 | |
190 update_keepalive(gc, FALSE); | |
191 | |
14838 | 192 gaim_proxy_connect_cancel_with_handle(gc); |
14192 | 193 |
14838 | 194 prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); |
195 if (prpl_info->close) | |
196 (prpl_info->close)(gc); | |
14192 | 197 |
14752
4124030c3f3a
[gaim-migrate @ 17509]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14607
diff
changeset
|
198 /* Clear out the proto data that was freed in the prpl close method*/ |
4124030c3f3a
[gaim-migrate @ 17509]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14607
diff
changeset
|
199 buddies = gaim_find_buddies(account, NULL); |
4124030c3f3a
[gaim-migrate @ 17509]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14607
diff
changeset
|
200 for (tmp = buddies; tmp; tmp = tmp->next) { |
4124030c3f3a
[gaim-migrate @ 17509]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14607
diff
changeset
|
201 GaimBuddy *buddy = tmp->data; |
4124030c3f3a
[gaim-migrate @ 17509]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14607
diff
changeset
|
202 buddy->proto_data = NULL; |
4124030c3f3a
[gaim-migrate @ 17509]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14607
diff
changeset
|
203 } |
4124030c3f3a
[gaim-migrate @ 17509]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14607
diff
changeset
|
204 g_slist_free(buddies); |
4124030c3f3a
[gaim-migrate @ 17509]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14607
diff
changeset
|
205 |
14192 | 206 connections = g_list_remove(connections, gc); |
207 | |
208 gaim_connection_set_state(gc, GAIM_DISCONNECTED); | |
209 | |
210 if (remove) | |
211 gaim_blist_remove_account(account); | |
212 | |
213 gaim_signal_emit(gaim_connections_get_handle(), "signed-off", gc); | |
214 | |
215 #if 0 | |
216 /* see comment later in file on if 0'd same code */ | |
217 /* | |
218 * XXX This is a hack! Remove this and replace it with a better event | |
219 * notification system. | |
220 */ | |
221 for (wins = gaim_get_windows(); wins != NULL; wins = wins->next) { | |
222 GaimConvWindow *win = (GaimConvWindow *)wins->data; | |
223 gaim_conversation_update(gaim_conv_window_get_conversation_at(win, 0), | |
224 GAIM_CONV_ACCOUNT_OFFLINE); | |
225 } | |
226 #endif | |
227 | |
228 gaim_request_close_with_handle(gc); | |
229 gaim_notify_close_with_handle(gc); | |
230 | |
231 gaim_debug_info("connection", "Destroying connection %p\n", gc); | |
232 | |
233 gaim_account_set_connection(account, NULL); | |
234 | |
235 g_free(gc->password); | |
236 g_free(gc->display_name); | |
237 | |
238 if (gc->disconnect_timeout) | |
239 gaim_timeout_remove(gc->disconnect_timeout); | |
240 | |
241 GAIM_DBUS_UNREGISTER_POINTER(gc); | |
242 g_free(gc); | |
243 } | |
244 | |
245 /* | |
246 * d:)->-< | |
247 * | |
248 * d:O-\-< | |
249 * | |
250 * d:D-/-< | |
251 * | |
252 * d8D->-< DANCE! | |
253 */ | |
254 | |
255 void | |
256 gaim_connection_set_state(GaimConnection *gc, GaimConnectionState state) | |
257 { | |
258 GaimConnectionUiOps *ops; | |
259 | |
260 g_return_if_fail(gc != NULL); | |
261 | |
262 if (gc->state == state) | |
263 return; | |
264 | |
265 gc->state = state; | |
266 | |
267 ops = gaim_connections_get_ui_ops(); | |
268 | |
269 if (gc->state == GAIM_CONNECTING) { | |
270 connections_connecting = g_list_append(connections_connecting, gc); | |
271 } | |
272 else { | |
273 connections_connecting = g_list_remove(connections_connecting, gc); | |
274 } | |
275 | |
276 if (gc->state == GAIM_CONNECTED) { | |
277 GaimAccount *account; | |
278 GaimPresence *presence; | |
279 | |
280 account = gaim_connection_get_account(gc); | |
281 presence = gaim_account_get_presence(account); | |
282 | |
283 /* Set the time the account came online */ | |
284 gaim_presence_set_login_time(presence, time(NULL)); | |
285 | |
286 if (gaim_prefs_get_bool("/core/logging/log_system")) | |
287 { | |
288 GaimLog *log = gaim_account_get_log(account, TRUE); | |
289 | |
290 if (log != NULL) | |
291 { | |
292 char *msg = g_strdup_printf(_("+++ %s signed on"), | |
293 gaim_account_get_username(account)); | |
294 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, | |
295 gaim_account_get_username(account), | |
296 gaim_presence_get_login_time(presence), | |
297 msg); | |
298 g_free(msg); | |
299 } | |
300 } | |
301 | |
302 if (ops != NULL && ops->connected != NULL) | |
303 ops->connected(gc); | |
304 | |
305 gaim_blist_add_account(account); | |
306 | |
307 gaim_signal_emit(gaim_connections_get_handle(), "signed-on", gc); | |
308 | |
309 serv_set_permit_deny(gc); | |
310 | |
311 update_keepalive(gc, TRUE); | |
312 } | |
313 else if (gc->state == GAIM_DISCONNECTED) { | |
314 GaimAccount *account = gaim_connection_get_account(gc); | |
315 | |
316 if (gaim_prefs_get_bool("/core/logging/log_system")) | |
317 { | |
318 GaimLog *log = gaim_account_get_log(account, FALSE); | |
319 | |
320 if (log != NULL) | |
321 { | |
322 char *msg = g_strdup_printf(_("+++ %s signed off"), | |
323 gaim_account_get_username(account)); | |
324 gaim_log_write(log, GAIM_MESSAGE_SYSTEM, | |
325 gaim_account_get_username(account), time(NULL), | |
326 msg); | |
327 g_free(msg); | |
328 } | |
329 } | |
330 | |
331 gaim_account_destroy_log(account); | |
332 | |
333 if (ops != NULL && ops->disconnected != NULL) | |
334 ops->disconnected(gc); | |
335 } | |
336 } | |
337 | |
338 void | |
339 gaim_connection_set_account(GaimConnection *gc, GaimAccount *account) | |
340 { | |
341 g_return_if_fail(gc != NULL); | |
342 g_return_if_fail(account != NULL); | |
343 | |
344 gc->account = account; | |
345 } | |
346 | |
347 void | |
348 gaim_connection_set_display_name(GaimConnection *gc, const char *name) | |
349 { | |
350 g_return_if_fail(gc != NULL); | |
351 | |
352 g_free(gc->display_name); | |
353 gc->display_name = g_strdup(name); | |
354 } | |
355 | |
356 GaimConnectionState | |
357 gaim_connection_get_state(const GaimConnection *gc) | |
358 { | |
359 g_return_val_if_fail(gc != NULL, GAIM_DISCONNECTED); | |
360 | |
361 return gc->state; | |
362 } | |
363 | |
364 GaimAccount * | |
365 gaim_connection_get_account(const GaimConnection *gc) | |
366 { | |
367 g_return_val_if_fail(gc != NULL, NULL); | |
368 | |
369 return gc->account; | |
370 } | |
371 | |
372 const char * | |
373 gaim_connection_get_password(const GaimConnection *gc) | |
374 { | |
375 g_return_val_if_fail(gc != NULL, NULL); | |
376 | |
377 return gc->password; | |
378 } | |
379 | |
380 const char * | |
381 gaim_connection_get_display_name(const GaimConnection *gc) | |
382 { | |
383 g_return_val_if_fail(gc != NULL, NULL); | |
384 | |
385 return gc->display_name; | |
386 } | |
387 | |
388 void | |
389 gaim_connection_update_progress(GaimConnection *gc, const char *text, | |
390 size_t step, size_t count) | |
391 { | |
392 GaimConnectionUiOps *ops; | |
393 | |
394 g_return_if_fail(gc != NULL); | |
395 g_return_if_fail(text != NULL); | |
396 g_return_if_fail(step < count); | |
397 g_return_if_fail(count > 1); | |
398 | |
399 ops = gaim_connections_get_ui_ops(); | |
400 | |
401 if (ops != NULL && ops->connect_progress != NULL) | |
402 ops->connect_progress(gc, text, step, count); | |
403 } | |
404 | |
405 void | |
406 gaim_connection_notice(GaimConnection *gc, const char *text) | |
407 { | |
408 GaimConnectionUiOps *ops; | |
409 | |
410 g_return_if_fail(gc != NULL); | |
411 g_return_if_fail(text != NULL); | |
412 | |
413 ops = gaim_connections_get_ui_ops(); | |
414 | |
415 if (ops != NULL && ops->notice != NULL) | |
416 ops->notice(gc, text); | |
417 } | |
418 | |
419 static gboolean | |
420 gaim_connection_disconnect_cb(gpointer data) | |
421 { | |
422 GaimAccount *account = data; | |
423 char *password = g_strdup(gaim_account_get_password(account)); | |
424 gaim_account_disconnect(account); | |
425 gaim_account_set_password(account, password); | |
426 g_free(password); | |
427 return FALSE; | |
428 } | |
429 | |
430 void | |
431 gaim_connection_error(GaimConnection *gc, const char *text) | |
432 { | |
433 GaimConnectionUiOps *ops; | |
434 | |
435 g_return_if_fail(gc != NULL); | |
436 g_return_if_fail(text != NULL); | |
437 | |
438 /* If we've already got one error, we don't need any more */ | |
439 if (gc->disconnect_timeout) | |
440 return; | |
441 | |
442 ops = gaim_connections_get_ui_ops(); | |
443 | |
444 if (ops != NULL) { | |
445 if (ops->report_disconnect != NULL) | |
446 ops->report_disconnect(gc, text); | |
447 } | |
448 | |
449 gc->disconnect_timeout = gaim_timeout_add(0, gaim_connection_disconnect_cb, | |
450 gaim_connection_get_account(gc)); | |
451 } | |
452 | |
453 void | |
454 gaim_connections_disconnect_all(void) | |
455 { | |
456 GList *l; | |
457 GaimConnection *gc; | |
458 | |
459 while ((l = gaim_connections_get_all()) != NULL) { | |
460 gc = l->data; | |
461 gc->wants_to_die = TRUE; | |
462 gaim_account_disconnect(gc->account); | |
463 } | |
464 } | |
465 | |
466 GList * | |
467 gaim_connections_get_all(void) | |
468 { | |
469 return connections; | |
470 } | |
471 | |
472 GList * | |
473 gaim_connections_get_connecting(void) | |
474 { | |
475 return connections_connecting; | |
476 } | |
477 | |
478 void | |
479 gaim_connections_set_ui_ops(GaimConnectionUiOps *ops) | |
480 { | |
481 connection_ui_ops = ops; | |
482 } | |
483 | |
484 GaimConnectionUiOps * | |
485 gaim_connections_get_ui_ops(void) | |
486 { | |
487 return connection_ui_ops; | |
488 } | |
489 | |
490 void | |
491 gaim_connections_init(void) | |
492 { | |
493 void *handle = gaim_connections_get_handle(); | |
494 | |
495 gaim_signal_register(handle, "signing-on", | |
496 gaim_marshal_VOID__POINTER, NULL, 1, | |
497 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
498 GAIM_SUBTYPE_CONNECTION)); | |
499 | |
500 gaim_signal_register(handle, "signed-on", | |
501 gaim_marshal_VOID__POINTER, NULL, 1, | |
502 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
503 GAIM_SUBTYPE_CONNECTION)); | |
504 | |
505 gaim_signal_register(handle, "signing-off", | |
506 gaim_marshal_VOID__POINTER, NULL, 1, | |
507 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
508 GAIM_SUBTYPE_CONNECTION)); | |
509 | |
510 gaim_signal_register(handle, "signed-off", | |
511 gaim_marshal_VOID__POINTER, NULL, 1, | |
512 gaim_value_new(GAIM_TYPE_SUBTYPE, | |
513 GAIM_SUBTYPE_CONNECTION)); | |
514 } | |
515 | |
516 void | |
517 gaim_connections_uninit(void) | |
518 { | |
519 gaim_signals_unregister_by_instance(gaim_connections_get_handle()); | |
520 } | |
521 | |
522 void * | |
523 gaim_connections_get_handle(void) | |
524 { | |
525 return &connections_handle; | |
526 } |