--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/connection.c Mon Sep 12 19:44:08 2005 -0400
@@ -0,0 +1,591 @@
+ * @file connection.c Connection API + * Gaim is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +static GList *connections = NULL; +static GList *connections_connecting = NULL; +static GaimConnectionUiOps *connection_ui_ops = NULL; +static int connections_handle; +gaim_connection_new(GaimAccount *account) + g_return_val_if_fail(account != NULL, NULL); + gc = g_new0(GaimConnection, 1); + gc->prpl = gaim_find_prpl(gaim_account_get_protocol_id(account)); + gaim_connection_set_account(gc, account); + gaim_account_set_connection(account, gc); +gaim_connection_destroy(GaimConnection *gc) + g_return_if_fail(gc != NULL); + if (gaim_connection_get_state(gc) != GAIM_DISCONNECTED) { + gaim_connection_disconnect(gc); + gaim_debug(GAIM_DEBUG_INFO, "connection", + "Destroying connection %p\n", gc); + account = gaim_connection_get_account(gc); + gaim_account_set_connection(account, NULL); + if (gc->display_name != NULL) + g_free(gc->display_name); + if (gc->away_state != NULL) + g_free(gc->away_state); + if (gc->disconnect_timeout) + gaim_timeout_remove(gc->disconnect_timeout); +static void request_pass_ok_cb(GaimAccount *account, const char *entry) + gaim_account_set_password(account, (*entry != '\0') ? entry : NULL); + gaim_account_connect(account); +gaim_connection_register(GaimConnection *gc) + GaimConnectionUiOps *ops; + GaimPluginProtocolInfo *prpl_info = NULL; + g_return_if_fail(gc != NULL); + gaim_debug(GAIM_DEBUG_INFO, "connection", "Registering. gc = %p\n", gc); + ops = gaim_connections_get_ui_ops(); + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); + gchar *message = g_strdup_printf(_("Missing protocol plugin for %s"), + gaim_account_get_username(gaim_connection_get_account(gc))); + gaim_debug(GAIM_DEBUG_ERROR, "connection", + "Could not get prpl info for %p\n", gc); + gaim_notify_error(NULL, _("Registration Error"), + if (prpl_info->register_user == NULL) + account = gaim_connection_get_account(gc); + if (gaim_connection_get_state(gc) != GAIM_DISCONNECTED) + gaim_connection_set_state(gc, GAIM_CONNECTING); + connections = g_list_append(connections, gc); + gaim_signal_emit(gaim_connections_get_handle(), "signing-on", gc); + /* set this so we don't auto-reconnect after registering */ + gc->wants_to_die = TRUE; + gaim_debug(GAIM_DEBUG_INFO, "connection", "Calling register_user\n"); + prpl_info->register_user(account); +gaim_connection_connect(GaimConnection *gc) + GaimConnectionUiOps *ops; + GaimPluginProtocolInfo *prpl_info = NULL; + g_return_if_fail(gc != NULL); + gaim_debug(GAIM_DEBUG_INFO, "connection", + "Connecting. gc = %p\n", gc); + ops = gaim_connections_get_ui_ops(); + prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl); + gchar *message = g_strdup_printf(_("Missing protocol plugin for %s"), + gaim_account_get_username(gaim_connection_get_account(gc))); + gaim_debug(GAIM_DEBUG_ERROR, "connection", + "Could not get prpl info for %p\n", gc); + gaim_notify_error(NULL, _("Connection Error"), + account = gaim_connection_get_account(gc); + if (gaim_connection_get_state(gc) != GAIM_DISCONNECTED) + if (!(prpl_info->options & OPT_PROTO_NO_PASSWORD) && + !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL) && + gaim_account_get_password(account) == NULL) { + const gchar *username = gaim_account_get_username(account); + gaim_debug(GAIM_DEBUG_INFO, "connection", "Requesting password\n"); + gaim_connection_destroy(gc); + escaped = g_markup_escape_text(username, strlen(username)); + primary = g_strdup_printf(_("Enter password for %s (%s)"), escaped, + gaim_account_get_protocol_name(account)); + gaim_request_input(gc, NULL, primary, NULL, NULL, FALSE, TRUE, NULL, + _("OK"), G_CALLBACK(request_pass_ok_cb), + _("Cancel"), NULL, account); + gaim_connection_set_state(gc, GAIM_CONNECTING); + connections = g_list_append(connections, gc); + gaim_signal_emit(gaim_connections_get_handle(), "signing-on", gc); + gaim_debug(GAIM_DEBUG_INFO, "connection", "Calling serv_login\n"); +gaim_connection_disconnect(GaimConnection *gc) + g_return_if_fail(gc != NULL); + account = gaim_connection_get_account(gc); + if (gaim_account_get_connection(account) != NULL) { + gaim_account_disconnect(account); + gaim_debug(GAIM_DEBUG_INFO, "connection", + "Disconnecting connection %p\n", gc); + if (gaim_connection_get_state(gc) != GAIM_DISCONNECTED) { + if (gaim_connection_get_state(gc) != GAIM_CONNECTING) + gaim_blist_remove_account(gaim_connection_get_account(gc)); + gaim_signal_emit(gaim_connections_get_handle(), "signing-off", gc); + connections = g_list_remove(connections, gc); + gaim_connection_set_state(gc, GAIM_DISCONNECTED); + /* LOG system_log(log_signoff, gc, NULL, + OPT_LOG_BUDDY_SIGNON | OPT_LOG_MY_SIGNON); */ + gaim_signal_emit(gaim_connections_get_handle(), "signed-off", gc); + * XXX This is a hack! Remove this and replace it with a better event + for (wins = gaim_get_windows(); wins != NULL; wins = wins->next) { + GaimConvWindow *win = (GaimConvWindow *)wins->data; + gaim_conversation_update(gaim_conv_window_get_conversation_at(win, 0), + GAIM_CONV_ACCOUNT_OFFLINE); + gaim_request_close_with_handle(gc); + gaim_notify_close_with_handle(gc); + if (!gaim_account_get_remember_password(account)) + gaim_account_set_password(account,NULL); + gaim_connection_destroy(gc); +gaim_connection_disconnect_cb(gpointer data) + GaimAccount *account = data; + GaimConnection *gc = gaim_account_get_connection(account); + /* gaim_connection_disconnect() will wipe the password, which is usually fine, but + * when we're knocked off forecfully, we'll want to reconnect easily. */ + char *password = gaim_account_get_password(account); + gaim_connection_disconnect(gc); + gaim_account_set_password(account, password); +gaim_connection_set_state(GaimConnection *gc, GaimConnectionState state) + GaimConnectionUiOps *ops; + g_return_if_fail(gc != NULL); + if (gc->state == state) + ops = gaim_connections_get_ui_ops(); + if (gc->state == GAIM_CONNECTING) { + connections_connecting = g_list_append(connections_connecting, gc); + connections_connecting = g_list_remove(connections_connecting, gc); + if (gc->state == GAIM_CONNECTED) { + GaimBlistNode *gnode,*cnode,*bnode; + GList *add_buds = NULL; + GaimAccount *account = gaim_connection_get_account(gc); + /* Set the time the account came online */ + if (ops != NULL && ops->connected != NULL) + gaim_blist_add_account(account); + * XXX This is a hack! Remove this and replace it with a better event + for (wins = gaim_get_windows(); wins != NULL; wins = wins->next) { + GaimConvWindow *win = (GaimConvWindow *)wins->data; + gaim_conversation_update(gaim_conv_window_get_conversation_at(win, 0), + GAIM_CONV_ACCOUNT_ONLINE); + /* LOG system_log(log_signon, gc, NULL, + OPT_LOG_BUDDY_SIGNON | OPT_LOG_MY_SIGNON); */ + if(gaim_prefs_get_bool("/core/logging/log_system") && + gaim_prefs_get_bool("/core/logging/log_own_states")){ + GaimLog *log = gaim_account_get_log(account); + char *msg = g_strdup_printf("+++ %s signed on", + gaim_account_get_username(account)); + gaim_log_write(log, GAIM_MESSAGE_SYSTEM, + gaim_account_get_username(account), gc->login_time, + gaim_signal_emit(gaim_connections_get_handle(), "signed-on", gc); + /* away option given? */ + away_on_login(opt_away_arg); + /* don't do it again */ + } else if (awaymessage) { + serv_set_away(gc, GAIM_AWAY_CUSTOM, awaymessage->message); + if (opt_away_arg != NULL) { + /* let the prpl know what buddies we pulled out of the local list */ + for (gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { + if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) + for(cnode = gnode->child; cnode; cnode = cnode->next) { + if(!GAIM_BLIST_NODE_IS_CONTACT(cnode)) + for(bnode = cnode->child; bnode; bnode = bnode->next) { + if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) + b = (GaimBuddy *)bnode; + if(b->account == gc->account) { + add_buds = g_list_append(add_buds, b); + serv_add_buddies(gc, add_buds); + serv_set_permit_deny(gc); + else if (gc->state == GAIM_DISCONNECTED) { + GaimAccount *account = gaim_connection_get_account(gc); + if(gaim_prefs_get_bool("/core/logging/log_system") && + gaim_prefs_get_bool("/core/logging/log_own_states")){ + GaimLog *log = gaim_account_get_log(account); + char *msg = g_strdup_printf("+++ %s signed off", + gaim_account_get_username(account)); + gaim_log_write(log, GAIM_MESSAGE_SYSTEM, + gaim_account_get_username(account), time(NULL), + gaim_account_destroy_log(account); + if (ops != NULL && ops->disconnected != NULL) +gaim_connection_set_account(GaimConnection *gc, GaimAccount *account) + g_return_if_fail(gc != NULL); + g_return_if_fail(account != NULL); +gaim_connection_set_display_name(GaimConnection *gc, const char *name) + g_return_if_fail(gc != NULL); + if (gc->display_name != NULL) + g_free(gc->display_name); + gc->display_name = (name == NULL ? NULL : g_strdup(name)); +gaim_connection_get_state(const GaimConnection *gc) + g_return_val_if_fail(gc != NULL, GAIM_DISCONNECTED); +gaim_connection_get_account(const GaimConnection *gc) + g_return_val_if_fail(gc != NULL, NULL); +gaim_connection_get_display_name(const GaimConnection *gc) + g_return_val_if_fail(gc != NULL, NULL); + return gc->display_name; +gaim_connection_update_progress(GaimConnection *gc, const char *text, + size_t step, size_t count) + GaimConnectionUiOps *ops; + g_return_if_fail(gc != NULL); + g_return_if_fail(text != NULL); + g_return_if_fail(step < count); + g_return_if_fail(count > 1); + ops = gaim_connections_get_ui_ops(); + if (ops != NULL && ops->connect_progress != NULL) + ops->connect_progress(gc, text, step, count); +gaim_connection_notice(GaimConnection *gc, const char *text) + GaimConnectionUiOps *ops; + g_return_if_fail(gc != NULL); + g_return_if_fail(text != NULL); + ops = gaim_connections_get_ui_ops(); + if (ops != NULL && ops->notice != NULL) +gaim_connection_error(GaimConnection *gc, const char *text) + GaimConnectionUiOps *ops; + g_return_if_fail(gc != NULL); + g_return_if_fail(text != NULL); + /* If we've already got one error, we don't need any more */ + if (gc->disconnect_timeout) + ops = gaim_connections_get_ui_ops(); + if (ops->report_disconnect != NULL) + ops->report_disconnect(gc, text); + gc->disconnect_timeout = gaim_timeout_add(0, gaim_connection_disconnect_cb, + gaim_connection_get_account(gc)); +gaim_connections_disconnect_all(void) + while ((l = gaim_connections_get_all()) != NULL) { + gc->wants_to_die = TRUE; + gaim_connection_destroy(gc); +gaim_connections_get_all(void) +gaim_connections_get_connecting(void) + return connections_connecting; +gaim_connections_set_ui_ops(GaimConnectionUiOps *ops) + connection_ui_ops = ops; +gaim_connections_get_ui_ops(void) + return connection_ui_ops; +gaim_connections_init(void) + void *handle = gaim_connections_get_handle(); + gaim_signal_register(handle, "signing-on", + gaim_marshal_VOID__POINTER, NULL, 1, + gaim_value_new(GAIM_TYPE_SUBTYPE, + GAIM_SUBTYPE_CONNECTION)); + gaim_signal_register(handle, "signed-on", + gaim_marshal_VOID__POINTER, NULL, 1, + gaim_value_new(GAIM_TYPE_SUBTYPE, + GAIM_SUBTYPE_CONNECTION)); + gaim_signal_register(handle, "signing-off", + gaim_marshal_VOID__POINTER, NULL, 1, + gaim_value_new(GAIM_TYPE_SUBTYPE, + GAIM_SUBTYPE_CONNECTION)); + gaim_signal_register(handle, "signed-off", + gaim_marshal_VOID__POINTER, NULL, 1, + gaim_value_new(GAIM_TYPE_SUBTYPE, + GAIM_SUBTYPE_CONNECTION)); +gaim_connections_uninit(void) + gaim_signals_unregister_by_instance(gaim_connections_get_handle()); +gaim_connections_get_handle(void) + return &connections_handle;