--- a/telepathygabble/src/gabble-connection.c Tue Feb 02 01:10:06 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5227 +0,0 @@
-/*
- * gabble-connection.c - Source for GabbleConnection
- * Copyright (C) 2005 Collabora Ltd.
- * and/or its subsidiary/subsidiaries. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <glib-object.h>
-#include "loudmouth/loudmouth.h"
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-
-#include "handles.h"
-#include "handle-set.h"
-#include "telepathy-constants.h"
-#include "telepathy-errors.h"
-#include "telepathy-helpers.h"
-#include "telepathy-interfaces.h"
-#include "loudmouth/lm-connection.h"
-
-#include "tp-channel-iface.h"
-#include "tp-channel-factory-iface.h"
-
-#include "gabble-connection.h"
-#include "gabble-connection-glue.h"
-#include "gabble-connection-signals-marshal.h"
-
-
-#include "capabilities.h"
-#include "debug.h"
-#include "disco.h"
-#include "gabble-presence-cache.h"
-#include "gabble-presence.h"
-#include "gabble-register.h"
-#include "im-factory.h"
-#include "search-factory.h"
-#include "jingle-info.h"
-#include "media-factory.h"
-#include "muc-factory.h"
-#include "namespaces.h"
-#include "roster.h"
-#include "util.h"
-#include "vcard-manager.h"
-#include "search-keys-info.h"
-
-#include "gabble-media-channel.h"
-#include "gabble-roomlist-channel.h"
-
-#include "gabble_enums.h"
-#include "sha1.h"
-#include "base64.h"
-
-#define DEBUG_FLAG GABBLE_DEBUG_CONNECTION
-#define DBUS_API_SUBJECT_TO_CHANGE
-#define BUS_NAME "org.freedesktop.Telepathy.Connection.gabble"
-#define OBJECT_PATH "/org/freedesktop/Telepathy/Connection/gabble"
-
-#define TP_ALIAS_PAIR_TYPE (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID))
-#define TP_CAPABILITY_PAIR_TYPE (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID))
-#define TP_CAPABILITIES_CHANGED_MONSTER_TYPE (dbus_g_type_get_struct \
- ("GValueArray", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, \
- G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID))
-#define TP_GET_CAPABILITIES_MONSTER_TYPE (dbus_g_type_get_struct \
- ("GValueArray", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, \
- G_TYPE_INVALID))
-#define TP_CHANNEL_LIST_ENTRY_TYPE (dbus_g_type_get_struct ("GValueArray", \
- DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, \
- G_TYPE_INVALID))
-
-#define ERROR_IF_NOT_CONNECTED(CONN, ERROR) \
- if ((CONN)->status != TP_CONN_STATUS_CONNECTED) \
- { \
- gabble_debug (DEBUG_FLAG, "rejected request as disconnected"); \
- g_set_error (ERROR, TELEPATHY_ERRORS, NotAvailable, \
- "Connection is disconnected"); \
- return FALSE; \
- }
-
-#define ERROR_IF_NOT_CONNECTED_ASYNC(CONN, ERROR, CONTEXT) \
- if ((CONN)->status != TP_CONN_STATUS_CONNECTED) \
- { \
- gabble_debug (DEBUG_FLAG, "rejected request as disconnected"); \
- (ERROR) = g_error_new (TELEPATHY_ERRORS, NotAvailable, \
- "Connection is disconnected"); \
- dbus_g_method_return_error ((CONTEXT), (ERROR)); \
- g_error_free ((ERROR)); \
- return; \
- }
-
-#ifdef DEBUG_FLAG
-//#define DEBUG(format, ...)
-#define DEBUGGING 0
-#define NODE_DEBUG(n, s)
-#endif /* DEBUG_FLAG */
-
-#ifndef EMULATOR
-G_DEFINE_TYPE(GabbleConnection, gabble_connection, G_TYPE_OBJECT)
-#endif
-
-typedef struct _StatusInfo StatusInfo;
-
-struct _StatusInfo
-{
- const gchar *name;
- TpConnectionPresenceType presence_type;
- const gboolean self;
- const gboolean exclusive;
-};
-
-/* order must match PresenceId enum in gabble-connection.h */
-/* in increasing order of presence */
-static const StatusInfo gabble_statuses[LAST_GABBLE_PRESENCE] = {
- { "offline", TP_CONN_PRESENCE_TYPE_OFFLINE, TRUE, TRUE },
- { "hidden", TP_CONN_PRESENCE_TYPE_HIDDEN, TRUE, TRUE },
- { "xa", TP_CONN_PRESENCE_TYPE_EXTENDED_AWAY, TRUE, TRUE },
- { "away", TP_CONN_PRESENCE_TYPE_AWAY, TRUE, TRUE },
- { "dnd", TP_CONN_PRESENCE_TYPE_AWAY, TRUE, TRUE },
- { "available", TP_CONN_PRESENCE_TYPE_AVAILABLE, TRUE, TRUE },
- { "chat", TP_CONN_PRESENCE_TYPE_AVAILABLE, TRUE, TRUE }
-};
-
-/* signal enum */
-enum
-{
- ALIASES_CHANGED,
- CAPABILITIES_CHANGED,
- NEW_CHANNEL,
- PRESENCE_UPDATE,
- STATUS_CHANGED,
- DISCONNECTED,
- LAST_SIGNAL
-#ifdef EMULATOR
- = LAST_SIGNAL_CON
-#endif
-
-};
-
-
-#ifdef EMULATOR
-#include "libgabble_wsd_solution.h"
-
- GET_STATIC_ARRAY_FROM_TLS(signals,gabble_con,guint)
- #define signals (GET_WSD_VAR_NAME(signals,gabble_con, s)())
-
-
- GET_STATIC_VAR_FROM_TLS(arguments,gabble_con,GHashTable*)
- #define arguments (*GET_WSD_VAR_NAME(arguments,gabble_con, s)())
-
- GET_STATIC_VAR_FROM_TLS(gabble_connection_parent_class,gabble_con,gpointer)
- #define gabble_connection_parent_class (*GET_WSD_VAR_NAME(gabble_connection_parent_class,gabble_con,s)())
-
- GET_STATIC_VAR_FROM_TLS(g_define_type_id,gabble_con,GType)
- #define g_define_type_id (*GET_WSD_VAR_NAME(g_define_type_id,gabble_con,s)())
-
- //GET_STATIC_ARRAY_FROM_TLS(assumed_caps,gabble_con,gchar*)
- /*gchar** _s_gabble_con_assumed_caps() { return (gchar**)((libgabble_ImpurePtr()->_s_gabble_con_assumed_caps)); }
-
- #define assumed_caps (GET_WSD_VAR_NAME(assumed_caps,gabble_con, s)()) */
-
-
-
-static void gabble_connection_init (GabbleConnection *self);
-static void gabble_connection_class_init (GabbleConnectionClass *klass);
-static void gabble_connection_class_intern_init (gpointer klass)
-{
-gabble_connection_parent_class = g_type_class_peek_parent (klass);
-gabble_connection_class_init ((GabbleConnectionClass*) klass);
-}
-EXPORT_C GType gabble_connection_get_type (void)
-{
-
-if ((g_define_type_id == 0))
-{
-static const GTypeInfo g_define_type_info =
- { sizeof (GabbleConnectionClass), (GBaseInitFunc) ((void *)0), (GBaseFinalizeFunc) ((void *)0), (GClassInitFunc) gabble_connection_class_intern_init, (GClassFinalizeFunc) ((void *)0), ((void *)0), sizeof (GabbleConnection), 0, (GInstanceInitFunc) gabble_connection_init, ((void *)0) }; g_define_type_id = g_type_register_static ( ((GType) ((20) << (2))), g_intern_static_string ("GabbleConnection"), &g_define_type_info, (GTypeFlags) 0); { {} ; } } return g_define_type_id;
- } ;
-
-#else
-
- static guint signals[LAST_SIGNAL] = {0};
-
-#endif
-
-/* properties */
-enum
-{
- PROP_PROTOCOL = 1,
- PROP_CONNECT_SERVER,
- PROP_PORT,
- PROP_OLD_SSL,
- PROP_REGISTER,
- PROP_LOW_BANDWIDTH,
- PROP_STREAM_SERVER,
- PROP_USERNAME,
- PROP_PASSWORD,
- PROP_RESOURCE,
- PROP_PRIORITY,
- PROP_HTTPS_PROXY_SERVER,
- PROP_HTTPS_PROXY_PORT,
- PROP_FALLBACK_CONFERENCE_SERVER,
- PROP_STUN_SERVER,
- PROP_STUN_PORT,
- PROP_STUN_RELAY_MAGIC_COOKIE,
- PROP_STUN_RELAY_SERVER,
- PROP_STUN_RELAY_UDP_PORT,
- PROP_STUN_RELAY_TCP_PORT,
- PROP_STUN_RELAY_SSLTCP_PORT,
- PROP_STUN_RELAY_USERNAME,
- PROP_STUN_RELAY_PASSWORD,
- PROP_IGNORE_SSL_ERRORS,
- PROP_ALIAS,
-
- LAST_PROPERTY
-};
-
-/* TP properties */
-enum
-{
- CONN_PROP_STUN_SERVER = 0,
- CONN_PROP_STUN_PORT,
- CONN_PROP_STUN_RELAY_MAGIC_COOKIE,
- CONN_PROP_STUN_RELAY_SERVER,
- CONN_PROP_STUN_RELAY_UDP_PORT,
- CONN_PROP_STUN_RELAY_TCP_PORT,
- CONN_PROP_STUN_RELAY_SSLTCP_PORT,
- CONN_PROP_STUN_RELAY_USERNAME,
- CONN_PROP_STUN_RELAY_PASSWORD,
-
- NUM_CONN_PROPS,
-
- INVALID_CONN_PROP,
-};
-
-const GabblePropertySignature connection_property_signatures[NUM_CONN_PROPS] = {
- { "stun-server", G_TYPE_STRING },
- { "stun-port", G_TYPE_UINT },
- { "stun-relay-magic-cookie", G_TYPE_STRING },
- { "stun-relay-server", G_TYPE_STRING },
- { "stun-relay-udp-port", G_TYPE_UINT },
- { "stun-relay-tcp-port", G_TYPE_UINT },
- { "stun-relay-ssltcp-port", G_TYPE_UINT },
- { "stun-relay-username", G_TYPE_STRING },
- { "stun-relay-password", G_TYPE_STRING },
-};
-
-/* private structure */
-typedef struct _GabbleConnectionPrivate GabbleConnectionPrivate;
-
-struct _GabbleConnectionPrivate
-{
- LmMessageHandler *iq_jingle_info_cb;
- LmMessageHandler *iq_search_keys_cb;
- LmMessageHandler *iq_disco_cb;
- LmMessageHandler *iq_unknown_cb;
- LmMessageHandler *stream_error_cb;
-
- /* telepathy properties */
- gchar *protocol;
-
- /* connection properties */
- gchar *connect_server;
- guint port;
- gboolean old_ssl;
-
- gboolean ignore_ssl_errors;
- TpConnectionStatusReason ssl_error;
-
- gboolean do_register;
-
- gboolean low_bandwidth;
-
- gchar *https_proxy_server;
- guint https_proxy_port;
-
- gchar *fallback_conference_server;
-
- /* authentication properties */
- gchar *stream_server;
- gchar *username;
- gchar *password;
- gchar *resource;
- gint8 priority;
- gchar *alias;
-
- /* reference to conference server name */
- const gchar *conference_server;
-
- /* channel factories */
- GPtrArray *channel_factories;
- GPtrArray *channel_requests;
- gboolean suppress_next_handler;
-
- /* serial number of current advertised caps */
- guint caps_serial;
-
- /* gobject housekeeping */
- gboolean dispose_has_run;
-};
-
-#define GABBLE_CONNECTION_GET_PRIVATE(obj) \
- ((GabbleConnectionPrivate *)obj->priv)
-
-typedef struct _ChannelRequest ChannelRequest;
-
-struct _ChannelRequest
-{
- DBusGMethodInvocation *context;
- gchar *channel_type;
- guint handle_type;
- guint handle;
- gboolean suppress_handler;
-};
-
-static void connection_new_channel_cb (TpChannelFactoryIface *, GObject *, gpointer);
-static void connection_channel_error_cb (TpChannelFactoryIface *, GObject *, GError *, gpointer);
-static void connection_nickname_update_cb (GObject *, GabbleHandle, gpointer);
-static void connection_presence_update_cb (GabblePresenceCache *, GabbleHandle, gpointer);
-static void connection_capabilities_update_cb (GabblePresenceCache *, GabbleHandle, GabblePresenceCapabilities, GabblePresenceCapabilities, gpointer);
-
-static void
-gabble_connection_init (GabbleConnection *self)
-{
- GabbleConnectionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- GABBLE_TYPE_CONNECTION, GabbleConnectionPrivate);
- guint i;
- GValue val = { 0, };
-
- self->priv = priv;
- self->lmconn = lm_connection_new (NULL);
- self->status = TP_CONN_STATUS_NEW;
- self->handles = gabble_handle_repo_new ();
- self->disco = gabble_disco_new (self);
- self->vcard_manager = gabble_vcard_manager_new (self);
- self->search_instr = NULL;
- self->search_key_names = NULL;
- self->search_reported_fields = NULL;
- self->search_form = FALSE;
- self->search_service_jid = NULL;
- self->self_avatar_sha1 = NULL;
- self->self_handle = 0;
- g_signal_connect (self->vcard_manager, "nickname-update", G_CALLBACK
- (connection_nickname_update_cb), self);
-
- self->presence_cache = gabble_presence_cache_new (self);
- g_signal_connect (self->presence_cache, "nickname-update", G_CALLBACK
- (connection_nickname_update_cb), self);
- g_signal_connect (self->presence_cache, "presence-update", G_CALLBACK
- (connection_presence_update_cb), self);
- g_signal_connect (self->presence_cache, "capabilities-update", G_CALLBACK
- (connection_capabilities_update_cb), self);
-
- capabilities_fill_cache (self->presence_cache);
-
- self->roster = gabble_roster_new (self);
- g_signal_connect (self->roster, "nickname-update", G_CALLBACK
- (connection_nickname_update_cb), self);
-
- priv->channel_factories = g_ptr_array_sized_new (1);
-
- g_ptr_array_add (priv->channel_factories, self->roster);
-
- g_ptr_array_add (priv->channel_factories,
- g_object_new (GABBLE_TYPE_MUC_FACTORY,
- "connection", self,
- NULL));
-
- g_ptr_array_add (priv->channel_factories,
- g_object_new (GABBLE_TYPE_MEDIA_FACTORY,
- "connection", self,
- NULL));
-
- g_ptr_array_add (priv->channel_factories,
- g_object_new (GABBLE_TYPE_IM_FACTORY,
- "connection", self,
- NULL));
-
- //add for search here
- g_ptr_array_add (priv->channel_factories,
- g_object_new (GABBLE_TYPE_SEARCH_FACTORY,
- "connection", self,
- NULL));
-
- for (i = 0; i < priv->channel_factories->len; i++)
- {
- GObject *factory = g_ptr_array_index (priv->channel_factories, i);
- g_signal_connect (factory, "new-channel", G_CALLBACK
- (connection_new_channel_cb), self);
- g_signal_connect (factory, "channel-error", G_CALLBACK
- (connection_channel_error_cb), self);
- }
-
- priv->channel_requests = g_ptr_array_new ();
-
- /* Set default parameters for optional parameters */
- priv->resource = g_strdup (GABBLE_PARAMS_DEFAULT_RESOURCE);
- priv->port = GABBLE_PARAMS_DEFAULT_PORT;
- priv->https_proxy_port = GABBLE_PARAMS_DEFAULT_HTTPS_PROXY_PORT;
-
- /* initialize properties mixin */
- gabble_properties_mixin_init (G_OBJECT (self), G_STRUCT_OFFSET (
- GabbleConnection, properties));
-
- g_value_init (&val, G_TYPE_UINT);
- g_value_set_uint (&val, GABBLE_PARAMS_DEFAULT_STUN_PORT);
-
- gabble_properties_mixin_change_value (G_OBJECT (self), CONN_PROP_STUN_PORT,
- &val, NULL);
- gabble_properties_mixin_change_flags (G_OBJECT (self), CONN_PROP_STUN_PORT,
- TP_PROPERTY_FLAG_READ, 0, NULL);
-
- g_value_unset (&val);
-
- priv->caps_serial = 1;
-}
-
-static void
-gabble_connection_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GabbleConnection *self = (GabbleConnection *) object;
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
- const gchar *param_name;
- guint tp_property_id;
-
- switch (property_id) {
- case PROP_PROTOCOL:
- g_value_set_string (value, priv->protocol);
- break;
- case PROP_CONNECT_SERVER:
- g_value_set_string (value, priv->connect_server);
- break;
- case PROP_STREAM_SERVER:
- g_value_set_string (value, priv->stream_server);
- break;
- case PROP_PORT:
- g_value_set_uint (value, priv->port);
- break;
- case PROP_OLD_SSL:
- g_value_set_boolean (value, priv->old_ssl);
- break;
- case PROP_REGISTER:
- g_value_set_boolean (value, priv->do_register);
- break;
- case PROP_LOW_BANDWIDTH:
- g_value_set_boolean (value, priv->low_bandwidth);
- break;
- case PROP_USERNAME:
- g_value_set_string (value, priv->username);
- break;
- case PROP_PASSWORD:
- g_value_set_string (value, priv->password);
- break;
- case PROP_RESOURCE:
- g_value_set_string (value, priv->resource);
- break;
- case PROP_PRIORITY:
- g_value_set_int (value, priv->priority);
- break;
- case PROP_HTTPS_PROXY_SERVER:
- g_value_set_string (value, priv->https_proxy_server);
- break;
- case PROP_HTTPS_PROXY_PORT:
- g_value_set_uint (value, priv->https_proxy_port);
- break;
- case PROP_FALLBACK_CONFERENCE_SERVER:
- g_value_set_string (value, priv->fallback_conference_server);
- break;
- case PROP_IGNORE_SSL_ERRORS:
- g_value_set_boolean (value, priv->ignore_ssl_errors);
- break;
- case PROP_ALIAS:
- g_value_set_string (value, priv->alias);
- break;
- default:
- param_name = g_param_spec_get_name (pspec);
-
- if (gabble_properties_mixin_has_property (object, param_name,
- &tp_property_id))
- {
- GValue *tp_property_value =
- self->properties.properties[tp_property_id].value;
-
- if (tp_property_value)
- {
- g_value_copy (tp_property_value, value);
- return;
- }
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gabble_connection_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GabbleConnection *self = (GabbleConnection *) object;
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
- const gchar *param_name;
- guint tp_property_id;
-
- switch (property_id) {
- case PROP_PROTOCOL:
- g_free (priv->protocol);
- priv->protocol = g_value_dup_string (value);
- break;
- case PROP_CONNECT_SERVER:
- g_free (priv->connect_server);
- priv->connect_server = g_value_dup_string (value);
- break;
- case PROP_PORT:
- priv->port = g_value_get_uint (value);
- break;
- case PROP_OLD_SSL:
- priv->old_ssl = g_value_get_boolean (value);
- break;
- case PROP_REGISTER:
- priv->do_register = g_value_get_boolean (value);
- break;
- case PROP_LOW_BANDWIDTH:
- priv->low_bandwidth = g_value_get_boolean (value);
- break;
- case PROP_STREAM_SERVER:
- g_free (priv->stream_server);
- priv->stream_server = g_value_dup_string (value);
- break;
- case PROP_USERNAME:
- g_free (priv->username);
- priv->username = g_value_dup_string (value);
- break;
- case PROP_PASSWORD:
- g_free (priv->password);
- priv->password = g_value_dup_string (value);
- break;
- case PROP_RESOURCE:
- g_free (priv->resource);
- priv->resource = g_value_dup_string (value);
- break;
- case PROP_PRIORITY:
- priv->priority = CLAMP (g_value_get_int (value), G_MININT8, G_MAXINT8);
- break;
- case PROP_HTTPS_PROXY_SERVER:
- g_free (priv->https_proxy_server);
- priv->https_proxy_server = g_value_dup_string (value);
- break;
- case PROP_HTTPS_PROXY_PORT:
- priv->https_proxy_port = g_value_get_uint (value);
- break;
- case PROP_FALLBACK_CONFERENCE_SERVER:
- g_free (priv->fallback_conference_server);
- priv->fallback_conference_server = g_value_dup_string (value);
- break;
- case PROP_IGNORE_SSL_ERRORS:
- priv->ignore_ssl_errors = g_value_get_boolean (value);
- break;
- case PROP_ALIAS:
- g_free (priv->alias);
- priv->alias = g_value_dup_string (value);
- break;
- default:
- param_name = g_param_spec_get_name (pspec);
-
- if (gabble_properties_mixin_has_property (object, param_name,
- &tp_property_id))
- {
- gabble_properties_mixin_change_value (object, tp_property_id, value,
- NULL);
- gabble_properties_mixin_change_flags (object, tp_property_id,
- TP_PROPERTY_FLAG_READ,
- 0, NULL);
-
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void gabble_connection_dispose (GObject *object);
-static void gabble_connection_finalize (GObject *object);
-
-static void
-gabble_connection_class_init (GabbleConnectionClass *gabble_connection_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (gabble_connection_class);
- GParamSpec *param_spec;
-
- object_class->get_property = gabble_connection_get_property;
- object_class->set_property = gabble_connection_set_property;
-
- g_type_class_add_private (gabble_connection_class, sizeof (GabbleConnectionPrivate));
-
- object_class->dispose = gabble_connection_dispose;
- object_class->finalize = gabble_connection_finalize;
-
- param_spec = g_param_spec_string ("protocol", "Telepathy identifier for protocol",
- "Identifier string used when the protocol "
- "name is required. Unused internally.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PROTOCOL, param_spec);
-
- param_spec = g_param_spec_string ("connect-server", "Hostname or IP of Jabber server",
- "The server used when establishing a connection.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONNECT_SERVER, param_spec);
-
- param_spec = g_param_spec_uint ("port", "Jabber server port",
- "The port used when establishing a connection.",
- 0, G_MAXUINT16, GABBLE_PARAMS_DEFAULT_PORT,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PORT, param_spec);
-
- param_spec = g_param_spec_boolean ("old-ssl", "Old-style SSL tunneled connection",
- "Establish the entire connection to the server "
- "within an SSL-encrypted tunnel. Note that this "
- "is not the same as connecting with TLS, which "
- "is not yet supported.", FALSE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_OLD_SSL, param_spec);
-
- param_spec = g_param_spec_boolean ("register", "Register account on server",
- "Register a new account on server.", FALSE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_REGISTER, param_spec);
-
- param_spec = g_param_spec_boolean ("low-bandwidth", "Low bandwidth mode",
- "Determines whether we are in low "
- "bandwidth mode. This influences "
- "polling behaviour.", FALSE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_LOW_BANDWIDTH, param_spec);
-
- param_spec = g_param_spec_string ("stream-server", "The server name used to initialise the stream.",
- "The server name used when initialising the stream, "
- "which is usually the part after the @ in the user's JID.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STREAM_SERVER, param_spec);
-
- param_spec = g_param_spec_string ("username", "Jabber username",
- "The username used when authenticating.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_USERNAME, param_spec);
-
- param_spec = g_param_spec_string ("password", "Jabber password",
- "The password used when authenticating.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PASSWORD, param_spec);
-
- param_spec = g_param_spec_string ("resource", "Jabber resource",
- "The Jabber resource used when authenticating.",
- "Telepathy",
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_RESOURCE, param_spec);
-
- param_spec = g_param_spec_int ("priority", "Jabber presence priority",
- "The default priority used when reporting our presence.",
- G_MININT8, G_MAXINT8, 0,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_PRIORITY, param_spec);
-
- param_spec = g_param_spec_string ("https-proxy-server", "The server name "
- "used as an HTTPS proxy server",
- "The server name used as an HTTPS proxy "
- "server.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_HTTPS_PROXY_SERVER, param_spec);
-
- param_spec = g_param_spec_uint ("https-proxy-port", "The HTTP proxy server "
- "port", "The HTTP proxy server port.",
- 0, G_MAXUINT16, 0,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_HTTPS_PROXY_PORT, param_spec);
-
- param_spec = g_param_spec_string ("fallback-conference-server",
- "The conference server used as fallback",
- "The conference server used as fallback when "
- "everything else fails.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_FALLBACK_CONFERENCE_SERVER,
- param_spec);
-
- param_spec = g_param_spec_string ("stun-server",
- "STUN server",
- "STUN server.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_SERVER, param_spec);
-
- param_spec = g_param_spec_uint ("stun-port",
- "STUN port",
- "STUN port.",
- 0, G_MAXUINT16, 0,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_PORT, param_spec);
-
- param_spec = g_param_spec_string ("stun-relay-magic-cookie",
- "STUN relay magic cookie",
- "STUN relay magic cookie.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_RELAY_MAGIC_COOKIE,
- param_spec);
-
- param_spec = g_param_spec_string ("stun-relay-server",
- "STUN relay server",
- "STUN relay server.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_RELAY_SERVER,
- param_spec);
-
- param_spec = g_param_spec_uint ("stun-relay-udp-port",
- "STUN relay UDP port",
- "STUN relay UDP port.",
- 0, G_MAXUINT16, 0,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_RELAY_UDP_PORT,
- param_spec);
-
- param_spec = g_param_spec_uint ("stun-relay-tcp-port",
- "STUN relay TCP port",
- "STUN relay TCP port.",
- 0, G_MAXUINT16, 0,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_RELAY_TCP_PORT,
- param_spec);
-
- param_spec = g_param_spec_uint ("stun-relay-ssltcp-port",
- "STUN relay SSL-TCP port",
- "STUN relay SSL-TCP port.",
- 0, G_MAXUINT16, 0,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_RELAY_SSLTCP_PORT,
- param_spec);
-
- param_spec = g_param_spec_string ("stun-relay-username",
- "STUN relay username",
- "STUN relay username.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_RELAY_USERNAME,
- param_spec);
-
- param_spec = g_param_spec_string ("stun-relay-password",
- "STUN relay password",
- "STUN relay password.",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_STUN_RELAY_PASSWORD,
- param_spec);
-
- param_spec = g_param_spec_boolean ("ignore-ssl-errors", "Ignore SSL errors",
- "Continue connecting even if the server's "
- "SSL certificate is invalid or missing.",
- FALSE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_IGNORE_SSL_ERRORS, param_spec);
-
- param_spec = g_param_spec_string ("alias",
- "Alias/nick for local user",
- "Alias/nick for local user",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_ALIAS, param_spec);
-
- /* signal definitions */
-
- signals[ALIASES_CHANGED] =
- g_signal_new ("aliases-changed",
- G_OBJECT_CLASS_TYPE (gabble_connection_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1, (dbus_g_type_get_collection ("GPtrArray", (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID)))));
-
- signals[CAPABILITIES_CHANGED] =
- g_signal_new ("capabilities-changed",
- G_OBJECT_CLASS_TYPE (gabble_connection_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1, (dbus_g_type_get_collection ("GPtrArray", (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID)))));
-
- signals[NEW_CHANNEL] =
- g_signal_new ("new-channel",
- G_OBJECT_CLASS_TYPE (gabble_connection_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- gabble_connection_marshal_VOID__STRING_STRING_UINT_UINT_BOOLEAN,
- G_TYPE_NONE, 5, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_BOOLEAN);
-
- signals[PRESENCE_UPDATE] =
- g_signal_new ("presence-update",
- G_OBJECT_CLASS_TYPE (gabble_connection_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1, (dbus_g_type_get_map ("GHashTable", G_TYPE_UINT, (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)))), G_TYPE_INVALID)))));
-
- signals[STATUS_CHANGED] =
- g_signal_new ("status-changed",
- G_OBJECT_CLASS_TYPE (gabble_connection_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- gabble_connection_marshal_VOID__UINT_UINT,
- G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
-
- signals[DISCONNECTED] =
- g_signal_new ("disconnected",
- G_OBJECT_CLASS_TYPE (gabble_connection_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (gabble_connection_class), &dbus_glib_gabble_connection_object_info);
-
- gabble_properties_mixin_class_init (G_OBJECT_CLASS (gabble_connection_class),
- G_STRUCT_OFFSET (GabbleConnectionClass, properties_class),
- connection_property_signatures, NUM_CONN_PROPS,
- NULL);
-}
-
-static gboolean
-_unref_lm_connection (gpointer data)
-{
- LmConnection *conn = (LmConnection *) data;
-
- lm_connection_unref (conn);
- return FALSE;
-}
-
-void
-gabble_connection_dispose (GObject *object)
-{
- GabbleConnection *self = GABBLE_CONNECTION (object);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
- DBusGProxy *bus_proxy;
- guint i;
- bus_proxy = tp_get_bus_proxy ();
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- gabble_debug (DEBUG_FLAG, "called");
-
- g_message("1 Inside gabble_connection_dispose() method");
-
- //<todo> are these asserts a valid one ?
- //As in case of lm_connection_open these will not be valid assertions ?
- //to remove these?
- g_assert ((self->status == TP_CONN_STATUS_DISCONNECTED) ||
- (self->status == TP_CONN_STATUS_NEW));
- //This is not a valid statement as the self_handle is set to a value in _gabble_connection_connect which wil call
- //lm_connection_open(within do_connect). If the call fails then control comes here.. in which case self_handle can be other
- //than 0)
- //g_assert (self->self_handle == 0);
-
- g_message("after assert");
- if (priv->channel_requests)
- {
- g_assert (priv->channel_requests->len == 0);
- g_ptr_array_free (priv->channel_requests, TRUE);
- priv->channel_requests = NULL;
- }
-
- g_ptr_array_foreach (priv->channel_factories, (GFunc) g_object_unref, NULL);
- g_ptr_array_free (priv->channel_factories, TRUE);
- priv->channel_factories = NULL;
- g_message("unrefed channel factories");
- if(self->search_instr)
- {
- g_free( self->search_instr );
- self->search_instr = NULL;
- }
-
- if(self->search_key_names)
- {
- for( i=0; self->search_key_names[i]; i++ )
- {
- g_free( self->search_key_names[i] );
- self->search_key_names[i] = NULL;
- }
- g_free( self->search_key_names );
- self->search_key_names = NULL;
- }
- g_message("freed search keys");
- if ( self->self_avatar_sha1 )
- {
- g_free ( self->self_avatar_sha1 );
- }
- if(self->search_key_ht)
- {
- g_hash_table_destroy (self->search_key_ht);
- self->search_key_ht = NULL;
- }
- if(self->search_service_jid)
- {
- g_free(self->search_service_jid);
- self->search_service_jid = NULL;
- }
- /* unreffing channel factories frees the roster */
- self->roster = NULL;
-
- g_object_unref (self->disco);
- self->disco = NULL;
-
- g_object_unref (self->vcard_manager);
- self->vcard_manager = NULL;
-
- g_object_unref (self->presence_cache);
- self->presence_cache = NULL;
-
- /* if this is not already the case, we'll crash anyway */
- g_assert (!lm_connection_is_open (self->lmconn));
- g_assert (priv->iq_search_keys_cb == NULL);
- g_assert (priv->iq_jingle_info_cb == NULL);
- g_assert (priv->iq_disco_cb == NULL);
- g_assert (priv->iq_unknown_cb == NULL);
- g_assert (priv->stream_error_cb == NULL);
-
- /*
- * The Loudmouth connection can't be unref'd immediately because this
- * function might (indirectly) return into Loudmouth code which expects the
- * connection to always be there.
- */
- g_idle_add (_unref_lm_connection, self->lmconn);
-
- if (NULL != self->bus_name)
- {
- dbus_g_proxy_call_no_reply (bus_proxy, "ReleaseName",
- G_TYPE_STRING, self->bus_name,
- G_TYPE_INVALID);
- }
-
- if (G_OBJECT_CLASS (gabble_connection_parent_class)->dispose)
- G_OBJECT_CLASS (gabble_connection_parent_class)->dispose (object);
-
- g_message("out of the method");
-}
-
-void
-gabble_connection_finalize (GObject *object)
-{
- GabbleConnection *self = GABBLE_CONNECTION (object);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- gabble_debug (DEBUG_FLAG, "called with %p", object);
-
- g_free (self->bus_name);
- g_free (self->object_path);
-
- g_free (priv->protocol);
- g_free (priv->connect_server);
- g_free (priv->stream_server);
- g_free (priv->username);
- g_free (priv->password);
- g_free (priv->resource);
-
- g_free (priv->https_proxy_server);
- g_free (priv->fallback_conference_server);
-
- g_free (priv->alias);
-
- gabble_properties_mixin_finalize (object);
-
- gabble_handle_repo_destroy (self->handles);
-
- G_OBJECT_CLASS (gabble_connection_parent_class)->finalize (object);
-}
-
-/**
- * _gabble_connection_set_properties_from_account
- *
- * Parses an account string which may be one of the following forms:
- * username
- * username/resource
- * username@server
- * username@server/resource
- * and sets the properties for username, stream server and resource
- * appropriately. Also sets the connect server to the stream server if one has
- * not yet been specified.
- */
-
-gboolean
-_gabble_connection_set_properties_from_account (GabbleConnection *conn,
- const gchar *account,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
- char *username, *server, *resource;
- gboolean result;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
- g_assert (account != NULL);
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- username = server = resource = NULL;
- result = TRUE;
-
- gabble_decode_jid (account, &username, &server, &resource);
-
- if (username == NULL || server == NULL ||
- *username == '\0' || *server == '\0')
- {
- g_set_error (error, TELEPATHY_ERRORS, InvalidArgument,
- "unable to get username and server from account");
- result = FALSE;
- goto OUT;
- }
-
- g_object_set (G_OBJECT (conn),
- "username", username,
- "stream-server", server,
- NULL);
-
- /* only override the default resource if we actually got one */
- if (resource)
- g_object_set (G_OBJECT (conn), "resource", resource, NULL);
-
-OUT:
- g_free (username);
- g_free (server);
- g_free (resource);
-
- return result;
-}
-
-/**
- * _gabble_connection_register
- *
- * Make the connection object appear on the bus, returning the bus
- * name and object path used.
- */
-gboolean
-_gabble_connection_register (GabbleConnection *conn,
- gchar **bus_name,
- gchar **object_path,
- GError **error)
-{
- DBusGConnection *bus;
- DBusGProxy *bus_proxy;
- GabbleConnectionPrivate *priv;
- const char *allowed_chars = "_1234567890"
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- char *safe_proto;
- char *unique_name;
- guint request_name_result;
- GError *request_error;
-
- g_message("1 Inside _gabble_connection_register() method");
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- bus = tp_get_bus ();
- bus_proxy = tp_get_bus_proxy ();
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- safe_proto = g_strdup (priv->protocol);
- g_strcanon (safe_proto, allowed_chars, '_');
-
- unique_name = g_strdup_printf ("_%s_%s_%s",
- priv->username,
- priv->stream_server,
- priv->resource);
- g_strcanon (unique_name, allowed_chars, '_');
-
- conn->bus_name = g_strdup_printf (BUS_NAME ".%s.%s",
- safe_proto,
- unique_name);
- conn->object_path = g_strdup_printf (OBJECT_PATH "/%s/%s",
- safe_proto,
- unique_name);
-
- g_free (safe_proto);
- g_free (unique_name);
-
- if (!dbus_g_proxy_call (bus_proxy, "RequestName", &request_error,
- G_TYPE_STRING, conn->bus_name,
- G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE,
- G_TYPE_INVALID,
- G_TYPE_UINT, &request_name_result,
- G_TYPE_INVALID))
- {
- g_set_error (error, TELEPATHY_ERRORS, NotAvailable,
- "Error acquiring bus name %s: %s", conn->bus_name,
- request_error->message);
-
- g_error_free (request_error);
-
- g_free (conn->bus_name);
- conn->bus_name = NULL;
-
- return FALSE;
- }
-
- if (request_name_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
- {
- gchar *msg;
-
- switch (request_name_result)
- {
- case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
- msg = "Request has been queued, though we request non-queueing.";
- break;
- case DBUS_REQUEST_NAME_REPLY_EXISTS:
- msg = "A connection manger already has this busname.";
- break;
- case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
- msg = "Connection manager already has a connection to this account.";
- break;
- default:
- msg = "Unknown error return from ReleaseName";
- }
-
- g_set_error (error, TELEPATHY_ERRORS, NotAvailable,
- "Error acquiring bus name %s: %s", conn->bus_name, msg);
-
- g_free (conn->bus_name);
- conn->bus_name = NULL;
-
- return FALSE;
- }
-
- gabble_debug (DEBUG_FLAG, "bus name %s", conn->bus_name);
-
- dbus_g_connection_register_g_object (bus, conn->object_path, G_OBJECT (conn));
-
- gabble_debug (DEBUG_FLAG, "object path %s", conn->object_path);
-
- *bus_name = g_strdup (conn->bus_name);
- *object_path = g_strdup (conn->object_path);
-
- return TRUE;
-}
-
-
-/**
- * _gabble_connection_send
- *
- * Send an LmMessage and trap network errors appropriately.
- */
-gboolean
-_gabble_connection_send (GabbleConnection *conn, LmMessage *msg, GError **error)
-{
- GabbleConnectionPrivate *priv;
- GError *lmerror = NULL;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- if (!lm_connection_send (conn->lmconn, msg, &lmerror))
- {
- gabble_debug (DEBUG_FLAG, "failed: %s", lmerror->message);
-
- g_set_error (error, TELEPATHY_ERRORS, NetworkError,
- "message send failed: %s", lmerror->message);
-
- g_error_free (lmerror);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-typedef struct {
- GabbleConnectionMsgReplyFunc reply_func;
-
- GabbleConnection *conn;
- LmMessage *sent_msg;
- gpointer user_data;
-
- GObject *object;
- gboolean object_alive;
-} GabbleMsgHandlerData;
-
-static LmHandlerResult
-message_send_reply_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *reply_msg,
- gpointer user_data)
-{
- GabbleMsgHandlerData *handler_data = user_data;
- LmMessageSubType sub_type;
-
- sub_type = lm_message_get_sub_type (reply_msg);
-
- /* Is it a reply to this message? If we're talking to another loudmouth,
- * they can send us messages which have the same ID as ones we send. :-O */
- if (sub_type != LM_MESSAGE_SUB_TYPE_RESULT &&
- sub_type != LM_MESSAGE_SUB_TYPE_ERROR)
- {
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- if (handler_data->object_alive)
- {
- return handler_data->reply_func (handler_data->conn,
- handler_data->sent_msg,
- reply_msg,
- handler_data->object,
- handler_data->user_data);
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-static void
-message_send_object_destroy_notify_cb (gpointer data,
- GObject *where_the_object_was)
-{
- GabbleMsgHandlerData *handler_data = data;
-
- handler_data->object = NULL;
- handler_data->object_alive = FALSE;
-}
-
-static void
-message_send_handler_destroy_cb (gpointer data)
-{
- GabbleMsgHandlerData *handler_data = data;
-
- lm_message_unref (handler_data->sent_msg);
-
- if (handler_data->object != NULL)
- {
- g_object_weak_unref (handler_data->object,
- message_send_object_destroy_notify_cb,
- handler_data);
- }
-
- g_free (handler_data);
-}
-
-/**
- * _gabble_connection_send_with_reply
- *
- * Send a tracked LmMessage and trap network errors appropriately.
- *
- * If object is non-NULL the handler will follow the lifetime of that object,
- * which means that if the object is destroyed the callback will not be invoked.
- */
-gboolean
-_gabble_connection_send_with_reply (GabbleConnection *conn,
- LmMessage *msg,
- GabbleConnectionMsgReplyFunc reply_func,
- GObject *object,
- gpointer user_data,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
- LmMessageHandler *handler;
- GabbleMsgHandlerData *handler_data;
- gboolean ret;
- GError *lmerror = NULL;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- lm_message_ref (msg);
-
- handler_data = g_new (GabbleMsgHandlerData, 1);
- handler_data->reply_func = reply_func;
- handler_data->conn = conn;
- handler_data->sent_msg = msg;
- handler_data->user_data = user_data;
-
- handler_data->object = object;
- handler_data->object_alive = TRUE;
-
- if (object != NULL)
- {
- g_object_weak_ref (object, message_send_object_destroy_notify_cb,
- handler_data);
- }
-
- handler = lm_message_handler_new (message_send_reply_cb, handler_data,
- message_send_handler_destroy_cb);
-
- ret = lm_connection_send_with_reply (conn->lmconn, msg, handler, &lmerror);
- if (!ret)
- {
- gabble_debug (DEBUG_FLAG, "failed: %s", lmerror->message);
-
- if (error)
- {
- g_set_error (error, TELEPATHY_ERRORS, NetworkError,
- "message send failed: %s", lmerror->message);
- }
-
- g_error_free (lmerror);
- }
-
- lm_message_handler_unref (handler);
-
- return ret;
-}
-
-static LmHandlerResult connection_iq_disco_cb (LmMessageHandler*, LmConnection*, LmMessage*, gpointer);
-static LmHandlerResult connection_iq_unknown_cb (LmMessageHandler*, LmConnection*, LmMessage*, gpointer);
-static LmHandlerResult connection_stream_error_cb (LmMessageHandler*, LmConnection*, LmMessage*, gpointer);
-static LmSSLResponse connection_ssl_cb (LmSSL*, LmSSLStatus, gpointer);
-static void connection_open_cb (LmConnection*, gboolean, gpointer);
-static void connection_auth_cb (LmConnection*, gboolean, gpointer);
-static void connection_disco_cb (GabbleDisco *, GabbleDiscoRequest *, const gchar *, const gchar *, LmMessageNode *, GError *, gpointer);
-static void connection_disconnected_cb (LmConnection *, LmDisconnectReason, gpointer);
-static void connection_status_change (GabbleConnection *, TpConnectionStatus, TpConnectionStatusReason);
-
-static void channel_request_cancel (gpointer data, gpointer user_data);
-
-static void emit_one_presence_update (GabbleConnection *self, GabbleHandle handle);
-
-
-static gboolean
-do_connect (GabbleConnection *conn, GError **error)
-{
- GError *lmerror = NULL;
-
- gabble_debug (DEBUG_FLAG, "calling lm_connection_open");
- g_message("**gabble do_connect: before calling lm_connection_open\n");
-
- if (!lm_connection_open (conn->lmconn, connection_open_cb,
- conn, NULL, &lmerror))
- {
- gabble_debug (DEBUG_FLAG, "lm_connection_open failed %s", lmerror->message);
-
- g_set_error (error, TELEPATHY_ERRORS, NetworkError,
- "lm_connection_open failed: %s", lmerror->message);
-
- g_signal_emit (conn, signals[DISCONNECTED], 0);
- g_error_free (lmerror);
-
- return FALSE;
- }
-
- g_message("**gabble do_connect: after calling lm_connection_open and it passed\n");
-
- return TRUE;
-}
-
-static void
-connect_callbacks (GabbleConnection *conn)
-{
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- g_message("inside connect_callbacks\n");
- g_assert (priv->iq_search_keys_cb == NULL);
- g_assert (priv->iq_jingle_info_cb == NULL);
- g_assert (priv->iq_disco_cb == NULL);
- g_assert (priv->iq_unknown_cb == NULL);
- g_assert (priv->stream_error_cb == NULL);
-
-
-
- priv->iq_search_keys_cb = lm_message_handler_new (search_keys_iq_cb,
- conn, NULL);
- lm_connection_register_message_handler (conn->lmconn,
- priv->iq_search_keys_cb,
- LM_MESSAGE_TYPE_IQ,
- LM_HANDLER_PRIORITY_NORMAL);
-
- priv->iq_jingle_info_cb = lm_message_handler_new (jingle_info_iq_callback,
- conn, NULL);
- lm_connection_register_message_handler (conn->lmconn,
- priv->iq_jingle_info_cb,
- LM_MESSAGE_TYPE_IQ,
- LM_HANDLER_PRIORITY_NORMAL);
-
- priv->iq_disco_cb = lm_message_handler_new (connection_iq_disco_cb,
- conn, NULL);
- lm_connection_register_message_handler (conn->lmconn, priv->iq_disco_cb,
- LM_MESSAGE_TYPE_IQ,
- LM_HANDLER_PRIORITY_NORMAL);
-
- priv->iq_unknown_cb = lm_message_handler_new (connection_iq_unknown_cb,
- conn, NULL);
- lm_connection_register_message_handler (conn->lmconn, priv->iq_unknown_cb,
- LM_MESSAGE_TYPE_IQ,
- LM_HANDLER_PRIORITY_LAST);
-
- priv->stream_error_cb = lm_message_handler_new (connection_stream_error_cb,
- conn, NULL);
- lm_connection_register_message_handler (conn->lmconn, priv->stream_error_cb,
- LM_MESSAGE_TYPE_STREAM_ERROR,
- LM_HANDLER_PRIORITY_LAST);
- g_message("leaving connect_callbacks\n");
-}
-
-static void
-disconnect_callbacks (GabbleConnection *conn)
-{
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- g_message("[disconnect_callbacks]");
- g_assert (priv->iq_search_keys_cb != NULL);
- g_assert (priv->iq_jingle_info_cb != NULL);
- g_assert (priv->iq_disco_cb != NULL);
- g_assert (priv->iq_unknown_cb != NULL);
- g_assert (priv->stream_error_cb != NULL);
-
- lm_connection_unregister_message_handler (conn->lmconn, priv->iq_search_keys_cb,
- LM_MESSAGE_TYPE_IQ);
- lm_message_handler_unref (priv->iq_search_keys_cb);
- priv->iq_search_keys_cb = NULL;
-
- lm_connection_unregister_message_handler (conn->lmconn, priv->iq_jingle_info_cb,
- LM_MESSAGE_TYPE_IQ);
- lm_message_handler_unref (priv->iq_jingle_info_cb);
- priv->iq_jingle_info_cb = NULL;
-
- lm_connection_unregister_message_handler (conn->lmconn, priv->iq_disco_cb,
- LM_MESSAGE_TYPE_IQ);
- lm_message_handler_unref (priv->iq_disco_cb);
- priv->iq_disco_cb = NULL;
-
- lm_connection_unregister_message_handler (conn->lmconn, priv->iq_unknown_cb,
- LM_MESSAGE_TYPE_IQ);
- lm_message_handler_unref (priv->iq_unknown_cb);
- priv->iq_unknown_cb = NULL;
-
- lm_connection_unregister_message_handler (conn->lmconn, priv->stream_error_cb,
- LM_MESSAGE_TYPE_STREAM_ERROR);
- lm_message_handler_unref (priv->stream_error_cb);
- priv->stream_error_cb = NULL;
-}
-
-/**
- * _gabble_connection_connect
- *
- * Use the stored server & authentication details to commence
- * the stages for connecting to the server and authenticating. Will
- * re-use an existing LmConnection if it is present, or create it
- * if necessary.
- *
- * Stage 1 is _gabble_connection_connect calling lm_connection_open
- * Stage 2 is connection_open_cb calling lm_connection_authenticate
- * Stage 3 is connection_auth_cb initiating service discovery
- * Stage 4 is connection_disco_cb advertising initial presence, requesting
- * the roster and setting the CONNECTED state
- */
-static gboolean
-_gabble_connection_connect (GabbleConnection *conn,
- GError **error)
-{
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- char *jid;
- GabblePresence *presence;
- g_message("[_gabble_connection_connect]");
- g_assert (priv->port > 0 && priv->port <= G_MAXUINT16);
- g_assert (priv->stream_server != NULL);
- g_assert (priv->username != NULL);
- g_assert (priv->password != NULL);
- g_assert (priv->resource != NULL);
- g_assert (lm_connection_is_open (conn->lmconn) == FALSE);
-
- g_message("In _gabble_connection_connect" );
-
- jid = g_strdup_printf ("%s@%s", priv->username, priv->stream_server);
- lm_connection_set_jid (conn->lmconn, jid);
-
- conn->self_handle = gabble_handle_for_contact (conn->handles,
- jid, FALSE);
- g_free (jid);
-
- if (conn->self_handle == 0)
- {
- g_set_error (error, TELEPATHY_ERRORS, InvalidArgument,
- "Invalid JID: %s@%s", priv->username, priv->stream_server);
- return FALSE;
- }
- gabble_handle_ref (conn->handles, TP_HANDLE_TYPE_CONTACT, conn->self_handle);
-
- /* set initial presence */
- /* TODO: some way for the user to set this */
- gabble_presence_cache_update (conn->presence_cache, conn->self_handle,
- priv->resource, GABBLE_PRESENCE_AVAILABLE, NULL, priv->priority);
- emit_one_presence_update (conn, conn->self_handle);
-
- /* set initial capabilities */
- presence = gabble_presence_cache_get (conn->presence_cache, conn->self_handle);
-
- gabble_presence_set_capabilities (presence, priv->resource,
- capabilities_get_initial_caps (), priv->caps_serial++);
-
- /* always override server and port if one was forced upon us */
- if (priv->connect_server != NULL)
- {
- lm_connection_set_server (conn->lmconn, priv->connect_server);
- lm_connection_set_port (conn->lmconn, priv->port);
- g_message("LM Server is %s \n",priv->connect_server );
- g_message("LM port is %ld \n",priv->port);
- }
- /* otherwise set the server & port to the stream server,
- * if one didn't appear from a SRV lookup */
- else if (lm_connection_get_server (conn->lmconn) == NULL)
- {
- lm_connection_set_server (conn->lmconn, priv->stream_server);
- lm_connection_set_port (conn->lmconn, priv->port);
- }
-
-
- if (priv->https_proxy_server)
- {
- LmProxy *proxy;
-
- proxy = lm_proxy_new_with_server (LM_PROXY_TYPE_HTTP,
- priv->https_proxy_server, priv->https_proxy_port);
-
- lm_connection_set_proxy (conn->lmconn, proxy);
-
- lm_proxy_unref (proxy);
- }
-
- if (priv->old_ssl)
- {
- LmSSL *ssl = lm_ssl_new (NULL, connection_ssl_cb, conn, NULL);
- lm_connection_set_ssl (conn->lmconn, ssl);
- lm_ssl_unref (ssl);
- }
- else //if we want to use tls (not old ssl?) then need to set tls flags.
- {
- LmSSL *ssl = lm_ssl_new (NULL, connection_ssl_cb, conn, NULL);
- lm_connection_set_ssl (conn->lmconn, ssl);
-
- lm_ssl_use_starttls (ssl, TRUE, TRUE);
-
- lm_ssl_unref (ssl);
- }
-
- /* send whitespace to the server every 30 seconds */
- //lm_connection_set_keep_alive_rate (conn->lmconn, 45);
-
- lm_connection_set_disconnect_function (conn->lmconn,
- connection_disconnected_cb,
- conn,
- NULL);
-
- if (do_connect (conn, error))
- {
- gboolean valid;
-
- connection_status_change (conn,
- TP_CONN_STATUS_CONNECTING,
- TP_CONN_STATUS_REASON_REQUESTED);
-
- valid = gabble_handle_ref (conn->handles,
- TP_HANDLE_TYPE_CONTACT,
- conn->self_handle);
- g_message("before after valid assert" );
- g_assert (valid);
- g_message("In after valid assert" );
- }
- else
- {
- return FALSE;
- }
- g_message("Out _gabble_connection_connect" );
- return TRUE;
-}
-
-
-
-static void
-connection_disconnected_cb (LmConnection *lmconn,
- LmDisconnectReason lm_reason,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
- g_message("[connection_disconnected_cb]\n");
- g_assert (conn->lmconn == lmconn);
-
- gabble_debug (DEBUG_FLAG, "called with reason %u", lm_reason);
-
- /* if we were expecting this disconnection, we're done so can tell
- * the connection manager to unref us. otherwise it's a network error
- * or some other screw up we didn't expect, so we emit the status
- * change */
- if (conn->status == TP_CONN_STATUS_DISCONNECTED)
- {
- g_message("[connection_disconnected_cb]expected; emitting DISCONNECTED");
- g_signal_emit (conn, signals[DISCONNECTED], 0);
- }
- else
- {
- g_message("[connection_disconnected_cb]unexpected; calling connection_status_change");
- connection_status_change (conn,
- TP_CONN_STATUS_DISCONNECTED,
- TP_CONN_STATUS_REASON_NETWORK_ERROR);
- }
-}
-
-
-/**
- * connection_status_change:
- * @conn: a #GabbleConnection
- * @status: new status to advertise
- * @reason: reason for new status
- *
- * Compares status with current status. If different, emits a signal
- * for the new status, and updates it in the #GabbleConnection.
- */
-static void
-connection_status_change (GabbleConnection *conn,
- TpConnectionStatus status,
- TpConnectionStatusReason reason)
-{
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- g_message ("[connection_status_change]status %u reason %u", status, reason);
-
- g_assert (status != TP_CONN_STATUS_NEW);
-
- if (conn->status != status)
- {
- if ((status == TP_CONN_STATUS_DISCONNECTED) &&
- (conn->status == TP_CONN_STATUS_NEW))
- {
- g_message("[connection_status_change] line 1721");
- conn->status = status;
-
- /* unref our self handle if it's set */
- if (conn->self_handle != 0)
- {
- gabble_handle_unref (conn->handles, TP_HANDLE_TYPE_CONTACT,
- conn->self_handle);
- conn->self_handle = 0;
- }
-
- g_message("[connection_status_change]new connection closed; emitting DISCONNECTED");
- g_signal_emit (conn, signals[DISCONNECTED], 0);
- return;
- }
-
- conn->status = status;
-
- if (status == TP_CONN_STATUS_DISCONNECTED)
- {
- /* remove the channels so we don't get any race conditions where
- * method calls are delivered to a channel after we've started
- * disconnecting */
- g_message("[connection_status_change] TP_CONN_STATUS_DISCONNECTED");
-
- /* trigger close_all on all channel factories */
- g_ptr_array_foreach (priv->channel_factories, (GFunc)
- tp_channel_factory_iface_close_all, NULL);
-
- /* cancel all queued channel requests */
- if (priv->channel_requests->len > 0)
- {
- g_ptr_array_foreach (priv->channel_requests, (GFunc)
- channel_request_cancel, NULL);
- g_ptr_array_remove_range (priv->channel_requests, 0,
- priv->channel_requests->len);
- }
-
- /* unref our self handle */
- gabble_handle_unref (conn->handles, TP_HANDLE_TYPE_CONTACT,
- conn->self_handle);
- conn->self_handle = 0;
- }
-
- g_message("[connection_status_change]emitting status-changed with status %u reason %u",
- status, reason);
-
- g_signal_emit (conn, signals[STATUS_CHANGED], 0, status, reason);
-
- if (status == TP_CONN_STATUS_CONNECTING)
- {
- /* add our callbacks */
- connect_callbacks (conn);
-
- /* trigger connecting on all channel factories */
- g_ptr_array_foreach (priv->channel_factories, (GFunc)
- tp_channel_factory_iface_connecting, NULL);
- }
- else if (status == TP_CONN_STATUS_CONNECTED)
- {
- /* send whitespace to the server every 30 seconds resetting to 30*/
- lm_connection_set_keep_alive_rate (conn->lmconn, 10);
-
- /* trigger connected on all channel factories */
- g_ptr_array_foreach (priv->channel_factories, (GFunc)
- tp_channel_factory_iface_connected, NULL);
- }
- else if (status == TP_CONN_STATUS_DISCONNECTED)
- {
- /* remove our callbacks */
- disconnect_callbacks (conn);
-
- /* trigger disconnected on all channel factories */
- g_ptr_array_foreach (priv->channel_factories, (GFunc)
- tp_channel_factory_iface_disconnected, NULL);
-
- /* if the connection is open, this function will close it for you.
- * if it's already closed (eg network error) then we're done, so
- * can emit DISCONNECTED and have the connection manager unref us */
- if (lm_connection_is_open (conn->lmconn))
- {
- g_message ("still open; calling lm_connection_close");
- lm_connection_close (conn->lmconn, NULL);
- }
- else
- {
- /* lm_connection_is_open() returns FALSE if LmConnection is in the
- * middle of connecting, so call this just in case */
- lm_connection_cancel_open (conn->lmconn);
- g_message ("closed; emitting DISCONNECTED");
- g_signal_emit (conn, signals[DISCONNECTED], 0);
- }
- }
- }
- else
- {
- g_warning ("%s: attempted to re-emit the current status %u reason %u",
- G_STRFUNC, status, reason);
- }
- g_message("[connection_status_change]");
- g_message ("out connection status changed ");
-}
-
-static ChannelRequest *
-channel_request_new (DBusGMethodInvocation *context,
- const char *channel_type,
- guint handle_type,
- guint handle,
- gboolean suppress_handler)
-{
- ChannelRequest *ret;
-
- g_assert (NULL != context);
- g_assert (NULL != channel_type);
-
- ret = g_new0 (ChannelRequest, 1);
- ret->context = context;
- ret->channel_type = g_strdup (channel_type);
- ret->handle_type = handle_type;
- ret->handle = handle;
- ret->suppress_handler = suppress_handler;
-
- return ret;
-}
-
-static void
-channel_request_free (ChannelRequest *request)
-{
- g_assert (NULL == request->context);
- g_free (request->channel_type);
- g_free (request);
-}
-
-static void
-channel_request_cancel (gpointer data, gpointer user_data)
-{
- ChannelRequest *request = (ChannelRequest *) data;
- GError *error = NULL;
-
- gabble_debug (DEBUG_FLAG, "cancelling request for %s/%d/%d", request->channel_type, request->handle_type, request->handle);
-
- error = g_error_new (TELEPATHY_ERRORS, Disconnected, "unable to "
- "service this channel request, we're disconnecting!");
-
- dbus_g_method_return_error (request->context, error);
- request->context = NULL;
-
- g_error_free (error);
- channel_request_free (request);
-}
-
-static GPtrArray *
-find_matching_channel_requests (GabbleConnection *conn,
- const gchar *channel_type,
- guint handle_type,
- guint handle,
- gboolean *suppress_handler)
-{
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- GPtrArray *requests;
- guint i;
-
- requests = g_ptr_array_sized_new (1);
-
- for (i = 0; i < priv->channel_requests->len; i++)
- {
- ChannelRequest *request = g_ptr_array_index (priv->channel_requests, i);
-
- if (0 != strcmp (request->channel_type, channel_type))
- continue;
-
- if (handle_type != request->handle_type)
- continue;
-
- if (handle != request->handle)
- continue;
-
- if (request->suppress_handler && suppress_handler)
- *suppress_handler = TRUE;
-
- g_ptr_array_add (requests, request);
- }
-
- return requests;
-}
-
-static void
-connection_new_channel_cb (TpChannelFactoryIface *factory,
- GObject *chan,
- gpointer data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (data);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- gchar *object_path = NULL, *channel_type = NULL;
- guint handle_type = 0, handle = 0;
- gboolean suppress_handler = priv->suppress_next_handler;
- GPtrArray *tmp;
- guint i;
-
- g_object_get (chan,
- "object-path", &object_path,
- "channel-type", &channel_type,
- "handle-type", &handle_type,
- "handle", &handle,
- NULL);
-
- gabble_debug (DEBUG_FLAG, "called for %s", object_path);
-
- tmp = find_matching_channel_requests (conn, channel_type, handle_type,
- handle, &suppress_handler);
-
- g_signal_emit (conn, signals[NEW_CHANNEL], 0,
- object_path, channel_type,
- handle_type, handle,
- suppress_handler);
-
- for (i = 0; i < tmp->len; i++)
- {
- ChannelRequest *request = g_ptr_array_index (tmp, i);
-
- gabble_debug (DEBUG_FLAG, "completing queued request, channel_type=%s, handle_type=%u, "
- "handle=%u, suppress_handler=%u", request->channel_type,
- request->handle_type, request->handle, request->suppress_handler);
-
- dbus_g_method_return (request->context, object_path);
- request->context = NULL;
-
- g_ptr_array_remove (priv->channel_requests, request);
-
- channel_request_free (request);
- }
-
- g_ptr_array_free (tmp, TRUE);
-
- g_free (object_path);
- g_free (channel_type);
-}
-
-static void
-connection_channel_error_cb (TpChannelFactoryIface *factory,
- GObject *chan,
- GError *error,
- gpointer data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (data);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- gchar *channel_type = NULL;
- guint handle_type = 0, handle = 0;
- GPtrArray *tmp;
- guint i;
-
- gabble_debug (DEBUG_FLAG, "channel_type=%s, handle_type=%u, handle=%u, error_code=%u, "
- "error_message=\"%s\"", channel_type, handle_type, handle,
- error->code, error->message);
-
- g_object_get (chan,
- "channel-type", &channel_type,
- "handle-type", &handle_type,
- "handle", &handle,
- NULL);
-
- tmp = find_matching_channel_requests (conn, channel_type, handle_type,
- handle, NULL);
-
- for (i = 0; i < tmp->len; i++)
- {
- ChannelRequest *request = g_ptr_array_index (tmp, i);
-
- gabble_debug (DEBUG_FLAG, "completing queued request %p, channel_type=%s, "
- "handle_type=%u, handle=%u, suppress_handler=%u",
- request, request->channel_type,
- request->handle_type, request->handle, request->suppress_handler);
-
- dbus_g_method_return_error (request->context, error);
- request->context = NULL;
-
- g_ptr_array_remove (priv->channel_requests, request);
-
- channel_request_free (request);
- }
-
- g_ptr_array_free (tmp, TRUE);
- g_free (channel_type);
-}
-
-static void
-connection_presence_update_cb (GabblePresenceCache *cache, GabbleHandle handle, gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
-
- emit_one_presence_update (conn, handle);
-}
-
-GabbleConnectionAliasSource
-_gabble_connection_get_cached_alias (GabbleConnection *conn,
- GabbleHandle handle,
- gchar **alias)
-{
- GabbleConnectionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (conn,
- GABBLE_TYPE_CONNECTION, GabbleConnectionPrivate);
- GabbleConnectionAliasSource ret = GABBLE_CONNECTION_ALIAS_NONE;
- GabblePresence *pres;
- const gchar *tmp;
- gchar *user = NULL, *resource = NULL;
-
- g_return_val_if_fail (NULL != conn, GABBLE_CONNECTION_ALIAS_NONE);
- g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), GABBLE_CONNECTION_ALIAS_NONE);
- g_return_val_if_fail (gabble_handle_is_valid (conn->handles,
- TP_HANDLE_TYPE_CONTACT, handle, NULL), GABBLE_CONNECTION_ALIAS_NONE);
-
- tmp = gabble_roster_handle_get_name (conn->roster, handle);
- if (NULL != tmp)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_ROSTER;
-
- if (NULL != alias)
- *alias = g_strdup (tmp);
-
- goto OUT;
- }
-
- pres = gabble_presence_cache_get (conn->presence_cache, handle);
- if (NULL != pres && NULL != pres->nickname)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_PRESENCE;
-
- if (NULL != alias)
- *alias = g_strdup (pres->nickname);
-
- goto OUT;
- }
-
- /* if it's our own handle, use alias passed to the connmgr, if any */
- if (handle == conn->self_handle && priv->alias != NULL)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_CONNMGR;
-
- if (NULL != alias)
- *alias = g_strdup (priv->alias);
-
- goto OUT;
- }
-
- /* if we've seen a nickname in their vCard, use that */
- tmp = gabble_vcard_manager_get_cached_alias (conn->vcard_manager, handle);
- if (NULL != tmp)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_VCARD;
-
- if (NULL != alias)
- *alias = g_strdup (tmp);
-
- goto OUT;
- }
-
- /* fallback to JID */
- tmp = gabble_handle_inspect (conn->handles, TP_HANDLE_TYPE_CONTACT, handle);
- g_assert (NULL != tmp);
-
- gabble_decode_jid (tmp, &user, NULL, &resource);
-
- /* MUC handles have the nickname in the resource */
- if (NULL != resource)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_JID;
-
- if (NULL != alias)
- {
- *alias = resource;
- resource = NULL;
- }
-
- goto OUT;
- }
-
- /* otherwise just take their local part */
- if (NULL != user)
- {
- ret = GABBLE_CONNECTION_ALIAS_FROM_JID;
-
- if (NULL != alias)
- {
- *alias = user;
- user = NULL;
- }
-
- goto OUT;
- }
-
-OUT:
- g_free (user);
- g_free (resource);
- return ret;
-}
-
-static void
-connection_nickname_update_cb (GObject *object,
- GabbleHandle handle,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
- GabbleConnectionAliasSource signal_source, real_source;
- gchar *alias = NULL;
- GPtrArray *aliases;
- GValue entry = { 0, };
-
- if (object == G_OBJECT (conn->roster))
- {
- signal_source = GABBLE_CONNECTION_ALIAS_FROM_ROSTER;
- }
- else if (object == G_OBJECT (conn->presence_cache))
- {
- signal_source = GABBLE_CONNECTION_ALIAS_FROM_PRESENCE;
- }
- else if (object == G_OBJECT (conn->vcard_manager))
- {
- signal_source = GABBLE_CONNECTION_ALIAS_FROM_VCARD;
- }
- else
- {
- g_assert_not_reached ();
- return;
- }
-
- real_source = _gabble_connection_get_cached_alias (conn, handle, &alias);
-
- g_assert (real_source != GABBLE_CONNECTION_ALIAS_NONE);
-
- /* if the active alias for this handle is already known and from
- * a higher priority, this signal is not interesting so we do
- * nothing */
- if (real_source > signal_source)
- {
- gabble_debug (DEBUG_FLAG, "ignoring boring alias change for handle %u, signal from %u "
- "but source %u has alias \"%s\"", handle, signal_source,
- real_source, alias);
- goto OUT;
- }
-
- g_value_init (&entry, TP_ALIAS_PAIR_TYPE);
- g_value_take_boxed (&entry, dbus_g_type_specialized_construct
- (TP_ALIAS_PAIR_TYPE));
-
- dbus_g_type_struct_set (&entry,
- 0, handle,
- 1, alias,
- G_MAXUINT);
-
- aliases = g_ptr_array_sized_new (1);
- g_ptr_array_add (aliases, g_value_get_boxed (&entry));
-
- g_signal_emit (conn, signals[ALIASES_CHANGED], 0, aliases);
-
- g_value_unset (&entry);
- g_ptr_array_free (aliases, TRUE);
-
-OUT:
- g_free (alias);
-}
-
-/**
- * status_is_available
- *
- * Returns a boolean to indicate whether the given gabble status is
- * available on this connection.
- */
-static gboolean
-status_is_available (GabbleConnection *conn, int status)
-{
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
- g_assert (status < LAST_GABBLE_PRESENCE);
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- if (gabble_statuses[status].presence_type == TP_CONN_PRESENCE_TYPE_HIDDEN &&
- (conn->features & GABBLE_CONNECTION_FEATURES_PRESENCE_INVISIBLE) == 0)
- return FALSE;
- else
- return TRUE;
-}
-
-/**
- * destroy_the_bastard:
- * @data: a GValue to destroy
- *
- * destroys a GValue allocated on the heap
- */
-static void
-destroy_the_bastard (GValue *value)
-{
- g_value_unset (value);
- g_free (value);
-}
-
-static GHashTable *
-construct_presence_hash (GabbleConnection *self,
- const GArray *contact_handles)
-{
- guint i;
- GabbleHandle handle;
- GHashTable *presence_hash, *contact_status, *parameters;
- GValueArray *vals;
- GValue *message;
- GabblePresence *presence;
- GabblePresenceId status;
- const gchar *status_message;
- /* this is never set at the moment*/
- guint timestamp = 0;
-
- g_assert (gabble_handles_are_valid (self->handles, TP_HANDLE_TYPE_CONTACT,
- contact_handles, FALSE, NULL));
-
- presence_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
- (GDestroyNotify) g_value_array_free);
-
- for (i = 0; i < contact_handles->len; i++)
- {
- handle = g_array_index (contact_handles, GabbleHandle, i);
- presence = gabble_presence_cache_get (self->presence_cache, handle);
-
- if (presence)
- {
- status = presence->status;
- status_message = presence->status_message;
- }
- else
- {
- status = GABBLE_PRESENCE_OFFLINE;
- status_message = NULL;
- }
-
- message = g_new0 (GValue, 1);
- g_value_init (message, G_TYPE_STRING);
- g_value_set_static_string (message, status_message);
-
- parameters = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- (GDestroyNotify) destroy_the_bastard);
-
- g_hash_table_insert (parameters, "message", message);
-
- contact_status = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- (GDestroyNotify) g_hash_table_destroy);
- g_hash_table_insert (contact_status,
- (gchar *) gabble_statuses[status].name, parameters);
-
- vals = g_value_array_new (2);
-
- g_value_array_append (vals, NULL);
- g_value_init (g_value_array_get_nth (vals, 0), G_TYPE_UINT);
- g_value_set_uint (g_value_array_get_nth (vals, 0), timestamp);
-
- g_value_array_append (vals, NULL);
- g_value_init (g_value_array_get_nth (vals, 1),
- dbus_g_type_get_map ("GHashTable", G_TYPE_STRING,
- dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)));
- g_value_take_boxed (g_value_array_get_nth (vals, 1), contact_status);
-
- g_hash_table_insert (presence_hash, GINT_TO_POINTER (handle), vals);
- }
-
- return presence_hash;
-}
-
-/**
- * emit_presence_update:
- * @self: A #GabbleConnection
- * @contact_handles: A zero-terminated array of #GabbleHandle for
- * the contacts to emit presence for
- *
- * Emits the Telepathy PresenceUpdate signal with the current
- * stored presence information for the given contact.
- */
-static void
-emit_presence_update (GabbleConnection *self,
- const GArray *contact_handles)
-{
- GHashTable *presence_hash;
-
- presence_hash = construct_presence_hash (self, contact_handles);
- g_signal_emit (self, signals[PRESENCE_UPDATE], 0, presence_hash);
- g_hash_table_destroy (presence_hash);
-}
-
-/**
- * emit_one_presence_update:
- * Convenience function for calling emit_presence_update with one handle.
- */
-
-static void
-emit_one_presence_update (GabbleConnection *self,
- GabbleHandle handle)
-{
- GArray *handles = g_array_sized_new (FALSE, FALSE, sizeof (GabbleHandle), 1);
-
- g_array_insert_val (handles, 0, handle);
- emit_presence_update (self, handles);
- g_array_free (handles, TRUE);
-}
-
-/**
- * signal_own_presence:
- * @self: A #GabbleConnection
- * @error: pointer in which to return a GError in case of failure.
- *
- * Signal the user's stored presence to the jabber server
- *
- * Retuns: FALSE if an error occurred
- */
-static gboolean
-signal_own_presence (GabbleConnection *self, GError **error)
-{
-
- GabblePresence *presence;
- LmMessage *message;
- LmMessageNode *node;
- gboolean ret;
- gchar *ext_string = NULL;
- GSList *features, *i;
- GabbleConnectionPrivate *priv;
-
- if ( NULL == self )
- {
- g_debug ("%s: accesing after dereferenced connection", G_STRFUNC);
- return FALSE;
- }
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- presence = gabble_presence_cache_get (self->presence_cache, self->self_handle);
- message = gabble_presence_as_message (presence, priv->resource);
- node = lm_message_get_node (message);
-
- if (presence->status == GABBLE_PRESENCE_HIDDEN)
- {
- if ((self->features & GABBLE_CONNECTION_FEATURES_PRESENCE_INVISIBLE) != 0)
- lm_message_node_set_attribute (node, "type", "invisible");
- }
-
- features = capabilities_get_features (presence->caps);
-
- for (i = features; NULL != i; i = i->next)
- {
- const Feature *feat = (const Feature *) i->data;
-
- if ((NULL != feat->bundle) && g_strdiff (VERSION, feat->bundle))
- {
- if (NULL != ext_string)
- {
- gchar *tmp = ext_string;
- ext_string = g_strdup_printf ("%s %s", ext_string, feat->bundle);
- g_free (tmp);
- }
- else
- {
- ext_string = g_strdup (feat->bundle);
- }
- }
- }
-
- node = lm_message_node_add_child (node, "c", NULL);
- lm_message_node_set_attributes (
- node,
- "xmlns", NS_CAPS,
- "node", NS_GABBLE_CAPS,
- "ver", VERSION,
- NULL);
-
- if (NULL != ext_string)
- lm_message_node_set_attribute (node, "ext", ext_string);
-
- ret = _gabble_connection_send (self, message, error);
-
- lm_message_unref (message);
-
- g_free (ext_string);
- g_slist_free (features);
-
- return ret;
-}
-
-static LmMessage *_lm_iq_message_make_result (LmMessage *iq_message);
-
-/**
- * _gabble_connection_send_iq_result
- *
- * Function used to acknowledge an IQ stanza.
- */
-void
-_gabble_connection_acknowledge_set_iq (GabbleConnection *conn,
- LmMessage *iq)
-{
- LmMessage *result;
-
- g_assert (LM_MESSAGE_TYPE_IQ == lm_message_get_type (iq));
- g_assert (LM_MESSAGE_SUB_TYPE_SET == lm_message_get_sub_type (iq));
-
- result = _lm_iq_message_make_result (iq);
-
- if (NULL != result)
- {
- _gabble_connection_send (conn, result, NULL);
- lm_message_unref (result);
- }
-}
-
-
-/**
- * _gabble_connection_send_iq_error
- *
- * Function used to acknowledge an IQ stanza with an error.
- */
-void
-_gabble_connection_send_iq_error (GabbleConnection *conn,
- LmMessage *message,
- GabbleXmppError error,
- const gchar *errmsg)
-{
- const gchar *to, *id;
- LmMessage *msg;
- LmMessageNode *iq_node;
-
- iq_node = lm_message_get_node (message);
- to = lm_message_node_get_attribute (iq_node, "from");
- id = lm_message_node_get_attribute (iq_node, "id");
-
- if (id == NULL)
- {
- NODE_DEBUG (iq_node, "can't acknowledge IQ with no id");
- return;
- }
-
- msg = lm_message_new_with_sub_type (to, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_ERROR);
-
- lm_message_node_set_attribute (msg->node, "id", id);
-
- lm_message_node_steal_children (msg->node, iq_node);
-
- gabble_xmpp_error_to_node (error, msg->node, errmsg);
-
- _gabble_connection_send (conn, msg, NULL);
-
- lm_message_unref (msg);
-}
-
-static LmMessage *
-_lm_iq_message_make_result (LmMessage *iq_message)
-{
- LmMessage *result;
- LmMessageNode *iq, *result_iq;
- const gchar *from_jid, *id;
-
- g_assert (lm_message_get_type (iq_message) == LM_MESSAGE_TYPE_IQ);
- g_assert (lm_message_get_sub_type (iq_message) == LM_MESSAGE_SUB_TYPE_GET ||
- lm_message_get_sub_type (iq_message) == LM_MESSAGE_SUB_TYPE_SET);
-
- iq = lm_message_get_node (iq_message);
- id = lm_message_node_get_attribute (iq, "id");
-
- if (id == NULL)
- {
- NODE_DEBUG (iq, "can't acknowledge IQ with no id");
- return NULL;
- }
-
- from_jid = lm_message_node_get_attribute (iq, "from");
-
- result = lm_message_new_with_sub_type (from_jid, LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_RESULT);
- result_iq = lm_message_get_node (result);
- lm_message_node_set_attribute (result_iq, "id", id);
-
- return result;
-}
-
-/**
- * connection_iq_disco_cb
- *
- * Called by loudmouth when we get an incoming <iq>. This handler handles
- * disco-related IQs.
- */
-static LmHandlerResult
-connection_iq_disco_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
- LmMessage *result;
- LmMessageNode *iq, *result_iq, *query, *result_query;
- const gchar *node, *suffix;
- GSList *features;
- GSList *i;
- GabblePresence *pres;
-
- if ( NULL == conn )
- {
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- if (lm_message_get_sub_type (message) != LM_MESSAGE_SUB_TYPE_GET)
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- iq = lm_message_get_node (message);
- query = lm_message_node_get_child_with_namespace (iq, "query",
- NS_DISCO_INFO);
-
- if (!query)
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
- node = lm_message_node_get_attribute (query, "node");
-
- if (node && (
- 0 != strncmp (node, NS_GABBLE_CAPS "#", strlen (NS_GABBLE_CAPS) + 1) ||
- strlen(node) < strlen (NS_GABBLE_CAPS) + 2))
- {
- NODE_DEBUG (iq, "got iq disco query with unexpected node attribute");
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
- }
-
- if (node == NULL)
- suffix = NULL;
- else
- suffix = node + strlen (NS_GABBLE_CAPS) + 1;
-
- result = _lm_iq_message_make_result (message);
- result_iq = lm_message_get_node (result);
- result_query = lm_message_node_add_child (result_iq, "query", NULL);
- lm_message_node_set_attribute (result_query, "xmlns", NS_DISCO_INFO);
-
- pres = gabble_presence_cache_get (conn->presence_cache, conn->self_handle);
- gabble_debug (DEBUG_FLAG, "got disco request for bundle %s, caps are %x", node, pres->caps);
- features = capabilities_get_features (pres->caps);
-
- g_debug("%s: caps now %u", G_STRFUNC, pres->caps);
-
- for (i = features; NULL != i; i = i->next)
- {
- const Feature *feature = (const Feature *) i->data;
-
- if (NULL == node || !g_strdiff (suffix, feature->bundle))
- {
- LmMessageNode *node = lm_message_node_add_child (result_query,
- "feature", NULL);
- lm_message_node_set_attribute (node, "var", feature->ns);
- }
- }
-
- NODE_DEBUG (result_iq, "sending disco response");
-
- if (!lm_connection_send (conn->lmconn, result, NULL))
- gabble_debug (DEBUG_FLAG, "sending disco response failed");
-
- g_slist_free (features);
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-/**
- * connection_iq_unknown_cb
- *
- * Called by loudmouth when we get an incoming <iq>. This handler is
- * at a lower priority than the others, and should reply with an error
- * about unsupported get/set attempts.
- */
-static LmHandlerResult
-connection_iq_unknown_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
-
- g_assert (connection == conn->lmconn);
-
- NODE_DEBUG (message->node, "got unknown iq");
-
- switch (lm_message_get_sub_type (message))
- {
- case LM_MESSAGE_SUB_TYPE_GET:
- case LM_MESSAGE_SUB_TYPE_SET:
- _gabble_connection_send_iq_error (conn, message,
- XMPP_ERROR_SERVICE_UNAVAILABLE, NULL);
- break;
- default:
- break;
- }
-
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-
-/**
- * connection_stream_error_cb
- *
- * Called by loudmouth when we get stream error, which means that
- * we're about to close the connection. The message contains the reason
- * for the connection hangup.
- */
-static LmHandlerResult
-connection_stream_error_cb (LmMessageHandler *handler,
- LmConnection *connection,
- LmMessage *message,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
- LmMessageNode *conflict_node;
-
- g_assert (connection == conn->lmconn);
-
- NODE_DEBUG (message->node, "got stream error");
-
- conflict_node = lm_message_node_get_child (message->node, "conflict");
- if (conflict_node)
- {
- gabble_debug (DEBUG_FLAG, "found conflict node, emiting status change");
-
- /* Another client with the same resource just
- * appeared, we're going down. */
- connection_status_change (conn,
- TP_CONN_STATUS_DISCONNECTED,
- TP_CONN_STATUS_REASON_NAME_IN_USE);
- return LM_HANDLER_RESULT_REMOVE_MESSAGE;
- }
-
- return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-}
-
-
-/**
- * connection_ssl_cb
- *
- * If we're doing old SSL, this function gets called if the certificate
- * is dodgy.
- */
-static LmSSLResponse
-connection_ssl_cb (LmSSL *lmssl,
- LmSSLStatus status,
- gpointer data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (data);
-
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- const char *reason;
- TpConnectionStatusReason tp_reason;
-
- g_message("inside ssl_cb\n");
- switch (status) {
- case LM_SSL_STATUS_NO_CERT_FOUND:
- reason = "The server doesn't provide a certificate.";
- tp_reason = TP_CONN_STATUS_REASON_CERT_NOT_PROVIDED;
- break;
- case LM_SSL_STATUS_UNTRUSTED_CERT:
- reason = "The certificate can not be trusted.";
- tp_reason = TP_CONN_STATUS_REASON_CERT_UNTRUSTED;
- break;
- case LM_SSL_STATUS_CERT_EXPIRED:
- reason = "The certificate has expired.";
- tp_reason = TP_CONN_STATUS_REASON_CERT_EXPIRED;
- break;
- case LM_SSL_STATUS_CERT_NOT_ACTIVATED:
- reason = "The certificate has not been activated.";
- tp_reason = TP_CONN_STATUS_REASON_CERT_NOT_ACTIVATED;
- break;
- case LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH:
- reason = "The server hostname doesn't match the one in the certificate.";
- tp_reason = TP_CONN_STATUS_REASON_CERT_HOSTNAME_MISMATCH;
- break;
- case LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH:
- reason = "The fingerprint doesn't match the expected value.";
- tp_reason = TP_CONN_STATUS_REASON_CERT_FINGERPRINT_MISMATCH;
- break;
- case LM_SSL_STATUS_GENERIC_ERROR:
- reason = "An unknown SSL error occurred.";
- tp_reason = TP_CONN_STATUS_REASON_CERT_OTHER_ERROR;
- break;
- default:
- g_assert_not_reached();
- reason = "Unknown SSL error code from Loudmouth.";
- tp_reason = TP_CONN_STATUS_REASON_ENCRYPTION_ERROR;
- break;
- }
-
- gabble_debug (DEBUG_FLAG, "called: %s", reason);
-
- if (priv->ignore_ssl_errors)
- {
- return LM_SSL_RESPONSE_CONTINUE;
- }
- else
- {
- priv->ssl_error = tp_reason;
- return LM_SSL_RESPONSE_STOP;
- }
-}
-
-static void
-do_auth (GabbleConnection *conn)
-{
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- GError *error = NULL;
-
- gabble_debug (DEBUG_FLAG, "authenticating with username: %s, password: <hidden>, resource: %s",
- priv->username, priv->resource);
-
- if (!lm_connection_authenticate (conn->lmconn, priv->username, priv->password,
- priv->resource, connection_auth_cb,
- conn, NULL, &error))
- {
- gabble_debug (DEBUG_FLAG, "failed: %s", error->message);
- g_error_free (error);
-
- /* the reason this function can fail is through network errors,
- * authentication failures are reported to our auth_cb */
- connection_status_change (conn,
- TP_CONN_STATUS_DISCONNECTED,
- TP_CONN_STATUS_REASON_NETWORK_ERROR);
- }
-}
-
-static void
-registration_finished_cb (GabbleRegister *reg,
- gboolean success,
- gint err_code,
- const gchar *err_msg,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
-
- g_message("registration_finished_cb\n");
- if (conn->status != TP_CONN_STATUS_CONNECTING)
- {
- g_assert (conn->status == TP_CONN_STATUS_DISCONNECTED);
- return;
- }
-
- gabble_debug (DEBUG_FLAG, "%s", (success) ? "succeeded" : "failed");
-
- g_object_unref (reg);
-
- if (success)
- {
- do_auth (conn);
- }
- else
- {
- gabble_debug (DEBUG_FLAG, "err_code = %d, err_msg = '%s'",
- err_code, err_msg);
-
- connection_status_change (conn,
- TP_CONN_STATUS_DISCONNECTED,
- (err_code == InvalidArgument) ? TP_CONN_STATUS_REASON_NAME_IN_USE :
- TP_CONN_STATUS_REASON_AUTHENTICATION_FAILED);
- }
-}
-
-static void
-do_register (GabbleConnection *conn)
-{
- GabbleRegister *reg;
-
- reg = gabble_register_new (conn);
-
- g_signal_connect (reg, "finished", (GCallback) registration_finished_cb,
- conn);
-
- gabble_register_start (reg);
-}
-
-/**
- * connection_open_cb
- *
- * Stage 2 of connecting, this function is called by loudmouth after the
- * result of the non-blocking lm_connection_open call is known. It makes
- * a request to authenticate the user with the server, or optionally
- * registers user on the server first.
- */
-static void
-connection_open_cb (LmConnection *lmconn,
- gboolean success,
- gpointer data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (data);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- g_message("[connection_open_cb]");
- if ((conn->status != TP_CONN_STATUS_CONNECTING) &&
- (conn->status != TP_CONN_STATUS_NEW))
- {
- g_assert (conn->status == TP_CONN_STATUS_DISCONNECTED);
- return;
- }
-
- g_assert (priv);
- g_assert (lmconn == conn->lmconn);
-
- if (!success)
- {
- if (lm_connection_get_proxy (lmconn))
- {
- g_message ("failed, retrying without proxy");
-
- lm_connection_set_proxy (lmconn, NULL);
-
- if (do_connect (conn, NULL))
- {
- return;
- }
- }
- else
- {
- g_message ("failed");
- }
-
- if (priv->ssl_error)
- {
- g_message ("[connection_open_cb] priv->ssl_error");
- connection_status_change (conn,
- TP_CONN_STATUS_DISCONNECTED,
- priv->ssl_error);
- }
- else
- {
- g_message ("[connection_open_cb] reached else");
- connection_status_change (conn,
- TP_CONN_STATUS_DISCONNECTED,
- TP_CONN_STATUS_REASON_NETWORK_ERROR);
- }
-
- return;
- }
-
- if (!priv->do_register)
- do_auth (conn);
- else
- do_register (conn);
-}
-
-/**
- * connection_auth_cb
- *
- * Stage 3 of connecting, this function is called by loudmouth after the
- * result of the non-blocking lm_connection_authenticate call is known.
- * It sends a discovery request to find the server's features.
- */
-static void
-connection_auth_cb (LmConnection *lmconn,
- gboolean success,
- gpointer data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (data);
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
- GError *error = NULL;
-
- g_message("In connection_auth_cb\n");
-
- if (conn->status != TP_CONN_STATUS_CONNECTING)
- {
- g_assert (conn->status == TP_CONN_STATUS_DISCONNECTED);
- return;
- }
-
- g_assert (priv);
- g_assert (lmconn == conn->lmconn);
-
- if (!success)
- {
- gabble_debug (DEBUG_FLAG, "failed");
- g_message("Inside !success\n");
-
- connection_status_change (conn,
- TP_CONN_STATUS_DISCONNECTED,
- TP_CONN_STATUS_REASON_AUTHENTICATION_FAILED);
-
- return;
- }
-
- if (!gabble_disco_request_with_timeout (conn->disco, GABBLE_DISCO_TYPE_INFO,
- priv->stream_server, NULL, 5000,
- connection_disco_cb, conn,
- G_OBJECT (conn), &error))
- {
- gabble_debug (DEBUG_FLAG, "sending disco request failed: %s",
- error->message);
- g_message("sending disco request failed\n");
-
- g_error_free (error);
-
- connection_status_change (conn,
- TP_CONN_STATUS_DISCONNECTED,
- TP_CONN_STATUS_REASON_NETWORK_ERROR);
- }
-}
-
-/**
- * connection_disco_cb
- *
- * Stage 4 of connecting, this function is called by GabbleDisco after the
- * result of the non-blocking server feature discovery call is known. It sends
- * the user's initial presence to the server, marking them as available,
- * and requests the roster.
- */
-static void
-connection_disco_cb (GabbleDisco *disco,
- GabbleDiscoRequest *request,
- const gchar *jid,
- const gchar *node,
- LmMessageNode *result,
- GError *disco_error,
- gpointer user_data)
-{
- GabbleConnection *conn = user_data;
- GabbleConnectionPrivate *priv;
- GError *error = NULL;
-
- g_message("Inside connection_disco_cb\n");
-
- if ( NULL == conn )
- {
- return;
- }
- if (conn->status != TP_CONN_STATUS_CONNECTING)
- {
- g_assert (conn->status == TP_CONN_STATUS_DISCONNECTED);
- return;
- }
-
- g_assert (GABBLE_IS_CONNECTION (conn));
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- if (disco_error)
- {
- g_message("got disco error, setting no features\n");
- gabble_debug (DEBUG_FLAG, "got disco error, setting no features: %s", disco_error->message);
- }
- else
- {
- LmMessageNode *iter;
-
- NODE_DEBUG (result, "got");
-
- for (iter = result->children; iter != NULL; iter = iter->next)
- {
- if (0 == strcmp (iter->name, "feature"))
- {
- const gchar *var = lm_message_node_get_attribute (iter, "var");
-
- if (var == NULL)
- continue;
-
- if (0 == strcmp (var, NS_GOOGLE_JINGLE_INFO))
- conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_JINGLE_INFO;
- else if (0 == strcmp (var, NS_GOOGLE_ROSTER))
- conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER;
- else if (0 == strcmp (var, NS_PRESENCE_INVISIBLE))
- conn->features |= GABBLE_CONNECTION_FEATURES_PRESENCE_INVISIBLE;
- else if (0 == strcmp (var, NS_PRIVACY))
- conn->features |= GABBLE_CONNECTION_FEATURES_PRIVACY;
- else if (0 == strcmp (var, NS_SEARCH))
- conn->features |= GABBLE_CONNECTION_FEATURES_SEARCH;
- }
- }
-
- gabble_debug (DEBUG_FLAG, "set features flags to %d", conn->features);
- }
-
- g_message("before signal_own_presence\n");
-
- /* send presence to the server to indicate availability */
- if (!signal_own_presence (conn, &error))
- {
- gabble_debug (DEBUG_FLAG, "sending initial presence failed: %s", error->message);
- g_message("sending initial presence failed\n");
- goto ERROR;
- }
-
- g_message("after signal_own_presence\n");
-
- /* go go gadget on-line */
- connection_status_change (conn, TP_CONN_STATUS_CONNECTED, TP_CONN_STATUS_REASON_REQUESTED);
-
- if (conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_JINGLE_INFO)
- {
- jingle_info_discover_servers (conn);
- }
-
- if(conn->features & GABBLE_CONNECTION_FEATURES_SEARCH)
- {
- get_search_keys_info(conn,jid);
- }
-
- return;
-
-ERROR:
- if (error)
- g_error_free (error);
-
- connection_status_change (conn,
- TP_CONN_STATUS_DISCONNECTED,
- TP_CONN_STATUS_REASON_NETWORK_ERROR);
-
- return;
-}
-
-
-static GHashTable *
-get_statuses_arguments()
-{
-
-#ifndef EMULATOR
- static GHashTable *arguments = NULL;
-#endif
-
-
- if (arguments == NULL)
- {
- arguments = g_hash_table_new (g_str_hash, g_str_equal);
-
- g_hash_table_insert (arguments, "message", "s");
- g_hash_table_insert (arguments, "priority", "n");
- }
-
- return arguments;
-}
-
-/****************************************************************************
- * D-BUS EXPORTED METHODS *
- ****************************************************************************/
-
-
-/**
- * gabble_connection_add_status
- *
- * Implements D-Bus method AddStatus
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_add_status (GabbleConnection *self,
- const gchar *status,
- GHashTable *parms,
- GError **error)
-{
- g_assert (GABBLE_IS_CONNECTION (self));
-
- ERROR_IF_NOT_CONNECTED (self, error);
-
- g_set_error (error, TELEPATHY_ERRORS, NotImplemented,
- "Only one status is possible at a time with this protocol");
-
- return FALSE;
-}
-
-static void
-_emit_capabilities_changed (GabbleConnection *conn,
- GabbleHandle handle,
- GabblePresenceCapabilities old_caps,
- GabblePresenceCapabilities new_caps)
-{
- GPtrArray *caps_arr;
- const CapabilityConversionData *ccd;
- guint i;
-
- if (old_caps == new_caps)
- return;
-
- caps_arr = g_ptr_array_new ();
-
- for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
- {
- if (ccd->c2tf_fn (old_caps | new_caps))
- {
- GValue caps_monster_struct = {0, };
- guint old_tpflags = ccd->c2tf_fn (old_caps);
- guint old_caps = old_tpflags ?
- TP_CONN_CAPABILITY_FLAG_CREATE |
- TP_CONN_CAPABILITY_FLAG_INVITE : 0;
- guint new_tpflags = ccd->c2tf_fn (new_caps);
- guint new_caps = new_tpflags ?
- TP_CONN_CAPABILITY_FLAG_CREATE |
- TP_CONN_CAPABILITY_FLAG_INVITE : 0;
-
- if (0 == (old_tpflags ^ new_tpflags))
- continue;
-
- g_value_init (&caps_monster_struct,
- TP_CAPABILITIES_CHANGED_MONSTER_TYPE);
- g_value_take_boxed (&caps_monster_struct,
- dbus_g_type_specialized_construct
- (TP_CAPABILITIES_CHANGED_MONSTER_TYPE));
-
- dbus_g_type_struct_set (&caps_monster_struct,
- 0, handle,
- 1, ccd->iface,
- 2, old_caps,
- 3, new_caps,
- 4, old_tpflags,
- 5, new_tpflags,
- G_MAXUINT);
-
- g_ptr_array_add (caps_arr, g_value_get_boxed (&caps_monster_struct));
- }
- }
-
- if (caps_arr->len)
- g_signal_emit (conn, signals[CAPABILITIES_CHANGED], 0, caps_arr);
-
- for (i = 0; i < caps_arr->len; i++)
- {
- g_boxed_free (TP_CAPABILITIES_CHANGED_MONSTER_TYPE,
- g_ptr_array_index (caps_arr, i));
- }
- g_ptr_array_free (caps_arr, TRUE);
-}
-
-static void
-connection_capabilities_update_cb (GabblePresenceCache *cache,
- GabbleHandle handle,
- GabblePresenceCapabilities old_caps,
- GabblePresenceCapabilities new_caps,
- gpointer user_data)
-{
- GabbleConnection *conn = GABBLE_CONNECTION (user_data);
-
- _emit_capabilities_changed (conn, handle, old_caps, new_caps);
-}
-
-/**
- * gabble_connection_advertise_capabilities
- *
- * Implements D-Bus method AdvertiseCapabilities
- * on interface org.freedesktop.Telepathy.Connection.Interface.Capabilities
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_advertise_capabilities (GabbleConnection *self,
- const GPtrArray *add,
- const gchar **remove,
- GPtrArray **ret,
- GError **error)
-{
- guint i;
- GabblePresence *pres;
- GabblePresenceCapabilities add_caps = 0, remove_caps = 0, caps, save_caps;
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
- const CapabilityConversionData *ccd;
-
- ERROR_IF_NOT_CONNECTED (self, error);
-
- pres = gabble_presence_cache_get (self->presence_cache, self->self_handle);
- gabble_debug (DEBUG_FLAG, "caps before: %x", pres->caps);
-
- for (i = 0; i < add->len; i++)
- {
- GValue iface_flags_pair = {0, };
- gchar *iface;
- guint flags;
-
- g_value_init (&iface_flags_pair, TP_CAPABILITY_PAIR_TYPE);
- g_value_set_static_boxed (&iface_flags_pair, g_ptr_array_index (add, i));
-
- dbus_g_type_struct_get (&iface_flags_pair,
- 0, &iface,
- 1, &flags,
- G_MAXUINT);
-
- for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
- if (g_str_equal (iface, ccd->iface))
- add_caps |= ccd->tf2c_fn (flags);
- }
-
- for (i = 0; NULL != remove[i]; i++)
- {
- for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
- if (g_str_equal (remove[i], ccd->iface))
- remove_caps |= ccd->tf2c_fn (~0);
- }
-
- pres = gabble_presence_cache_get (self->presence_cache, self->self_handle);
- save_caps = caps = pres->caps;
-
- caps |= add_caps;
- caps ^= (caps & remove_caps);
-
- gabble_debug (DEBUG_FLAG, "caps to add: %x", add_caps);
- gabble_debug (DEBUG_FLAG, "caps to remove: %x", remove_caps);
- gabble_debug (DEBUG_FLAG, "caps after: %x", caps);
-
- if (caps ^ save_caps)
- {
- gabble_debug (DEBUG_FLAG, "before != after, changing");
- gabble_presence_set_capabilities (pres, priv->resource, caps, priv->caps_serial++);
- gabble_debug (DEBUG_FLAG, "set caps: %x", pres->caps);
- }
-
- *ret = g_ptr_array_new ();
-
- for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
- {
- if (ccd->c2tf_fn (pres->caps))
- {
- GValue iface_flags_pair = {0, };
-
- g_value_init (&iface_flags_pair, TP_CAPABILITY_PAIR_TYPE);
- g_value_take_boxed (&iface_flags_pair,
- dbus_g_type_specialized_construct (TP_CAPABILITY_PAIR_TYPE));
-
- dbus_g_type_struct_set (&iface_flags_pair,
- 0, ccd->iface,
- 1, ccd->c2tf_fn (pres->caps),
- G_MAXUINT);
-
- g_ptr_array_add (*ret, g_value_get_boxed (&iface_flags_pair));
- }
- }
-
- if (caps ^ save_caps)
- {
- if (!signal_own_presence (self, error))
- return FALSE;
-
- _emit_capabilities_changed (self, self->self_handle, save_caps, caps);
- }
-
- return TRUE;
-}
-
-/**
- * gabble_connection_clear_status
- *
- * Implements D-Bus method ClearStatus
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_clear_status (GabbleConnection *self,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error);
-
- gabble_presence_cache_update (self->presence_cache, self->self_handle,
- priv->resource, GABBLE_PRESENCE_AVAILABLE, NULL, priv->priority);
- emit_one_presence_update (self, self->self_handle);
- return signal_own_presence (self, error);
-}
-
-
-/**
- * gabble_connection_connect
- * Implements D-Bus method Connect
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-
-gboolean
-gabble_connection_connect (GabbleConnection *self,
- GError **error)
-{
- g_assert(GABBLE_IS_CONNECTION (self));
-
- if (self->status == TP_CONN_STATUS_NEW)
- return _gabble_connection_connect (self, error);
- return TRUE;
-}
-
-
-/**
- * gabble_connection_disconnect
- *
- * Implements D-Bus method Disconnect
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_disconnect (GabbleConnection *self,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- g_message("gabble_connection_disconnect: going to change status to TP_CONN_STATUS_DISCONNECTED ") ;
- connection_status_change (self,
- TP_CONN_STATUS_DISCONNECTED,
- TP_CONN_STATUS_REASON_REQUESTED);
-
- return TRUE;
-}
-
-
-/**
- * gabble_connection_get_alias_flags
- *
- * Implements D-Bus method GetAliasFlags
- * on interface org.freedesktop.Telepathy.Connection.Interface.Aliasing
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_get_alias_flags (GabbleConnection *self,
- guint *ret,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- *ret = TP_CONN_ALIAS_FLAG_USER_SET;
-
- return TRUE;
-}
-
-//#ifndef EMULATOR
-static const gchar *assumed_caps[] =
-{
- TP_IFACE_CHANNEL_TYPE_TEXT,
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- NULL
-};
-//#endif
-
-
-/**
- * gabble_connection_get_capabilities
- *
- * Implements D-Bus method GetCapabilities
- * on interface org.freedesktop.Telepathy.Connection.Interface.Capabilities
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_get_capabilities (GabbleConnection *self,
- const GArray *handles,
- GPtrArray **ret,
- GError **error)
-{
- guint i;
-
- ERROR_IF_NOT_CONNECTED (self, error);
-
- if (!gabble_handles_are_valid (self->handles,
- TP_HANDLE_TYPE_CONTACT,
- handles,
- TRUE,
- error))
- {
- return FALSE;
- }
-
- *ret = g_ptr_array_new ();
-
- for (i = 0; i < handles->len; i++)
- {
- GabbleHandle handle = g_array_index (handles, guint, i);
- GabblePresence *pres;
- const CapabilityConversionData *ccd;
- guint typeflags;
- //#ifndef EMULATOR
- const gchar **assumed;
- //#else
- //gchar **assumed;
- //#endif
-
- if (0 == handle)
- {
- /* FIXME report the magical channel types available on the connection itself */
- continue;
- }
-
- pres = gabble_presence_cache_get (self->presence_cache, handle);
-
- if (NULL != pres)
- for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
- {
- typeflags = ccd->c2tf_fn (pres->caps);
-
- if (typeflags)
- {
- GValue monster = {0, };
-
- g_value_init (&monster, TP_GET_CAPABILITIES_MONSTER_TYPE);
- g_value_take_boxed (&monster,
- dbus_g_type_specialized_construct (
- TP_GET_CAPABILITIES_MONSTER_TYPE));
-
- dbus_g_type_struct_set (&monster,
- 0, handle,
- 1, ccd->iface,
- 2, TP_CONN_CAPABILITY_FLAG_CREATE |
- TP_CONN_CAPABILITY_FLAG_INVITE,
- 3, typeflags,
- G_MAXUINT);
-
- g_ptr_array_add (*ret, g_value_get_boxed (&monster));
- }
- }
-
- for (assumed = assumed_caps; NULL != *assumed; assumed++)
- {
- GValue monster = {0, };
-
- g_value_init (&monster, TP_GET_CAPABILITIES_MONSTER_TYPE);
- g_value_take_boxed (&monster,
- dbus_g_type_specialized_construct (TP_GET_CAPABILITIES_MONSTER_TYPE));
-
- dbus_g_type_struct_set (&monster,
- 0, handle,
- 1, *assumed,
- 2, TP_CONN_CAPABILITY_FLAG_CREATE |
- TP_CONN_CAPABILITY_FLAG_INVITE,
- 3, 0,
- G_MAXUINT);
-
- g_ptr_array_add (*ret, g_value_get_boxed (&monster));
- }
- }
-
- return TRUE;
-}
-
-
-/**
- * gabble_connection_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_get_interfaces (GabbleConnection *self,
- gchar ***ret,
- GError **error)
-{
- const char *interfaces[] = {
- TP_IFACE_CONN_INTERFACE_ALIASING,
- TP_IFACE_CONN_INTERFACE_CAPABILITIES,
- TP_IFACE_CONN_INTERFACE_PRESENCE,
- TP_IFACE_PROPERTIES,
- TP_IFACE_CONN_INTERFACE_AVATAR,
- NULL };
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- *ret = g_strdupv ((gchar **) interfaces);
-
- return TRUE;
-}
-
-
-/**
- * gabble_connection_get_presence
- *
- * Implements D-Bus method GetPresence
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-void
-gabble_connection_get_presence (GabbleConnection *self,
- const GArray *contacts,
- DBusGMethodInvocation *context)
-{
- GHashTable *presence_hash;
- GError *error = NULL;
-
- if (!gabble_handles_are_valid (self->handles, TP_HANDLE_TYPE_CONTACT,
- contacts, FALSE, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-
- presence_hash = construct_presence_hash (self, contacts);
- dbus_g_method_return (context, presence_hash);
- g_hash_table_destroy (presence_hash);
-}
-
-
-/**
- * gabble_connection_get_properties
- *
- * Implements D-Bus method GetProperties
- * on interface org.freedesktop.Telepathy.Properties
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_get_properties (GabbleConnection *self,
- const GArray *properties,
- GPtrArray **ret,
- GError **error)
-{
- return gabble_properties_mixin_get_properties (G_OBJECT (self), properties,
- ret, error);
-}
-
-
-/**
- * gabble_connection_get_protocol
- *
- * Implements D-Bus method GetProtocol
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_get_protocol (GabbleConnection *self,
- gchar **ret,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- *ret = g_strdup (priv->protocol);
-
- return TRUE;
-}
-
-
-/**
- * gabble_connection_get_self_handle
- *
- * Implements D-Bus method GetSelfHandle
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_get_self_handle (GabbleConnection *self,
- guint *ret,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- *ret = self->self_handle;
-
- return TRUE;
-}
-
-
-/**
- * gabble_connection_get_status
- *
- * Implements D-Bus method GetStatus
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_get_status (GabbleConnection *self,
- guint *ret,
- GError **error)
-{
- g_assert (GABBLE_IS_CONNECTION (self));
-
- if (self->status == TP_CONN_STATUS_NEW)
- {
- *ret = TP_CONN_STATUS_DISCONNECTED;
- }
- else
- {
- *ret = self->status;
- }
-
- return TRUE;
-}
-
-
-/**
- * gabble_connection_get_statuses
- *
- * Implements D-Bus method GetStatuses
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_get_statuses (GabbleConnection *self,
- GHashTable **ret,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
- GValueArray *status;
- int i;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- gabble_debug (DEBUG_FLAG, "called.");
-
- *ret = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, (GDestroyNotify) g_value_array_free);
-
- for (i=0; i < LAST_GABBLE_PRESENCE; i++)
- {
- /* don't report the invisible presence if the server
- * doesn't have the presence-invisible feature */
- if (!status_is_available (self, i))
- continue;
-
- status = g_value_array_new (5);
-
- g_value_array_append (status, NULL);
- g_value_init (g_value_array_get_nth (status, 0), G_TYPE_UINT);
- g_value_set_uint (g_value_array_get_nth (status, 0),
- gabble_statuses[i].presence_type);
-
- g_value_array_append (status, NULL);
- g_value_init (g_value_array_get_nth (status, 1), G_TYPE_BOOLEAN);
- g_value_set_boolean (g_value_array_get_nth (status, 1),
- gabble_statuses[i].self);
-
- g_value_array_append (status, NULL);
- g_value_init (g_value_array_get_nth (status, 2), G_TYPE_BOOLEAN);
- g_value_set_boolean (g_value_array_get_nth (status, 2),
- gabble_statuses[i].exclusive);
-
- g_value_array_append (status, NULL);
- g_value_init (g_value_array_get_nth (status, 3),
- DBUS_TYPE_G_STRING_STRING_HASHTABLE);
- g_value_set_static_boxed (g_value_array_get_nth (status, 3),
- get_statuses_arguments());
-
- g_hash_table_insert (*ret, (gchar*) gabble_statuses[i].name, status);
- }
-
- return TRUE;
-}
-
-
-/**
- * gabble_connection_hold_handles
- *
- * Implements D-Bus method HoldHandles
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-void
-gabble_connection_hold_handles (GabbleConnection *self,
- guint handle_type,
- const GArray *handles,
- DBusGMethodInvocation *context)
-{
- GabbleConnectionPrivate *priv;
- GError *error = NULL;
- gchar *sender;
- guint i;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED_ASYNC (self, error, context)
-
- if (!gabble_handles_are_valid (self->handles,
- handle_type,
- handles,
- FALSE,
- &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- sender = dbus_g_method_get_sender (context);
- for (i = 0; i < handles->len; i++)
- {
- GabbleHandle handle = g_array_index (handles, GabbleHandle, i);
- if (!gabble_handle_client_hold (self->handles, sender, handle,
- handle_type, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
- }
-
- dbus_g_method_return (context);
-}
-
-
-/**
- * gabble_connection_inspect_handles
- *
- * Implements D-Bus method InspectHandles
- * on interface org.freedesktop.Telepathy.Connection
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-void
-gabble_connection_inspect_handles (GabbleConnection *self,
- guint handle_type,
- const GArray *handles,
- DBusGMethodInvocation *context)
-{
- GabbleConnectionPrivate *priv;
- GError *error = NULL;
- const gchar **ret;
- guint i;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED_ASYNC (self, error, context);
-
- if (!gabble_handles_are_valid (self->handles,
- handle_type,
- handles,
- FALSE,
- &error))
- {
- dbus_g_method_return_error (context, error);
-
- g_error_free (error);
-
- return;
- }
-
- ret = g_new (const gchar *, handles->len + 1);
-
- for (i = 0; i < handles->len; i++)
- {
- GabbleHandle handle;
- const gchar *tmp;
-
- handle = g_array_index (handles, GabbleHandle, i);
- tmp = gabble_handle_inspect (self->handles, handle_type, handle);
- g_assert (tmp != NULL);
-
- ret[i] = tmp;
- }
-
- ret[i] = NULL;
-
- dbus_g_method_return (context, ret);
-
- g_free (ret);
-}
-
-/**
- * list_channel_factory_foreach_one:
- * @key: iterated key
- * @value: iterated value
- * @data: data attached to this key/value pair
- *
- * Called by the exported ListChannels function, this should iterate over
- * the handle/channel pairs in a channel factory, and to the GPtrArray in
- * the data pointer, add a GValueArray containing the following:
- * a D-Bus object path for the channel object on this service
- * a D-Bus interface name representing the channel type
- * an integer representing the handle type this channel communicates with, or zero
- * an integer handle representing the contact, room or list this channel communicates with, or zero
- */
-static void
-list_channel_factory_foreach_one (TpChannelIface *chan,
- gpointer data)
-{
- GObject *channel = G_OBJECT (chan);
- GPtrArray *channels = (GPtrArray *) data;
- gchar *path, *type;
- guint handle_type, handle;
- GValue entry = { 0, };
-
- g_value_init (&entry, TP_CHANNEL_LIST_ENTRY_TYPE);
- g_value_take_boxed (&entry, dbus_g_type_specialized_construct
- (TP_CHANNEL_LIST_ENTRY_TYPE));
-
- g_object_get (channel,
- "object-path", &path,
- "channel-type", &type,
- "handle-type", &handle_type,
- "handle", &handle,
- NULL);
-
- dbus_g_type_struct_set (&entry,
- 0, path,
- 1, type,
- 2, handle_type,
- 3, handle,
- G_MAXUINT);
-
- g_ptr_array_add (channels, g_value_get_boxed (&entry));
-
- g_free (path);
- g_free (type);
-}
-
-/**
- * gabble_connection_list_channels
- *
- * Implements D-Bus method ListChannels
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_list_channels (GabbleConnection *self,
- GPtrArray **ret,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
- GPtrArray *channels;
- guint i;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- /* I think on average, each factory will have 2 channels :D */
- channels = g_ptr_array_sized_new (priv->channel_factories->len * 2);
-
- for (i = 0; i < priv->channel_factories->len; i++)
- {
- TpChannelFactoryIface *factory = g_ptr_array_index
- (priv->channel_factories, i);
- tp_channel_factory_iface_foreach (factory,
- list_channel_factory_foreach_one, channels);
- }
-
- *ret = channels;
-
- return TRUE;
-}
-
-
-/**
- * gabble_connection_list_properties
- *
- * Implements D-Bus method ListProperties
- * on interface org.freedesktop.Telepathy.Properties
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns false.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_list_properties (GabbleConnection *self,
- GPtrArray **ret,
- GError **error)
-{
- return gabble_properties_mixin_list_properties (G_OBJECT (self), ret, error);
-}
-
-
-/**
- * gabble_connection_release_handles
- *
- * Implements D-Bus method ReleaseHandles
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-void
-gabble_connection_release_handles (GabbleConnection *self,
- guint handle_type,
- const GArray * handles,
- DBusGMethodInvocation *context)
-{
- GabbleConnectionPrivate *priv;
- char *sender;
- GError *error = NULL;
- guint i;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED_ASYNC (self, error, context)
-
- if (!gabble_handles_are_valid (self->handles,
- handle_type,
- handles,
- FALSE,
- &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- sender = dbus_g_method_get_sender (context);
- for (i = 0; i < handles->len; i++)
- {
- GabbleHandle handle = g_array_index (handles, GabbleHandle, i);
- if (!gabble_handle_client_release (self->handles, sender, handle,
- handle_type, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
- }
-
- dbus_g_method_return (context);
-}
-
-
-/**
- * gabble_connection_remove_status
- *
- * Implements D-Bus method RemoveStatus
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_remove_status (GabbleConnection *self,
- const gchar *status,
- GError **error)
-{
- GabblePresence *presence;
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- presence = gabble_presence_cache_get (self->presence_cache,
- self->self_handle);
-
- if (strcmp (status, gabble_statuses[presence->status].name) == 0)
- {
- gabble_presence_cache_update (self->presence_cache, self->self_handle,
- priv->resource, GABBLE_PRESENCE_AVAILABLE, NULL, priv->priority);
- emit_one_presence_update (self, self->self_handle);
- return signal_own_presence (self, error);
- }
- else
- {
- g_set_error (error, TELEPATHY_ERRORS, InvalidArgument,
- "Attempting to remove non-existent presence.");
- return FALSE;
- }
-}
-
-
-typedef struct _AliasesRequest AliasesRequest;
-
-struct _AliasesRequest
-{
- GabbleConnection *conn;
- DBusGMethodInvocation *request_call;
- guint pending_vcard_requests;
- GArray *contacts;
- GabbleVCardManagerRequest **vcard_requests;
- gchar **aliases;
-};
-
-
-static AliasesRequest *
-aliases_request_new (GabbleConnection *conn,
- DBusGMethodInvocation *request_call,
- const GArray *contacts)
-{
- AliasesRequest *request;
-
- request = g_slice_new0 (AliasesRequest);
- request->conn = conn;
- request->request_call = request_call;
- request->contacts = g_array_new (FALSE, FALSE, sizeof (GabbleHandle));
- g_array_insert_vals (request->contacts, 0, contacts->data, contacts->len);
- request->vcard_requests =
- g_new0 (GabbleVCardManagerRequest *, contacts->len);
- request->aliases = g_new0 (gchar *, contacts->len + 1);
- return request;
-}
-
-
-static void
-aliases_request_free (AliasesRequest *request)
-{
- guint i;
-
- for (i = 0; i < request->contacts->len; i++)
- {
- if (request->vcard_requests[i] != NULL)
- gabble_vcard_manager_cancel_request (request->conn->vcard_manager,
- request->vcard_requests[i]);
- }
-
- g_array_free (request->contacts, TRUE);
- g_free (request->vcard_requests);
- g_strfreev (request->aliases);
- g_slice_free (AliasesRequest, request);
-}
-
-
-static gboolean
-aliases_request_try_return (AliasesRequest *request)
-{
- if (request->pending_vcard_requests == 0)
- {
- dbus_g_method_return (request->request_call, request->aliases);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-static void
-aliases_request_vcard_cb (GabbleVCardManager *manager,
- GabbleVCardManagerRequest *request,
- GabbleHandle handle,
- LmMessageNode *vcard,
- GError *error,
- gpointer user_data)
-{
- AliasesRequest *aliases_request = (AliasesRequest *) user_data;
- GabbleConnectionAliasSource source;
- guint i;
- gboolean found = FALSE;
- gchar *alias = NULL;
-
- g_assert (aliases_request->pending_vcard_requests > 0);
-
- /* The index of the vCard request in the vCard request array is the
- * index of the contact/alias in their respective arrays. */
-
- for (i = 0; i < aliases_request->contacts->len; i++)
- if (aliases_request->vcard_requests[i] == request)
- {
- found = TRUE;
- break;
- }
-
- g_assert (found);
- source = _gabble_connection_get_cached_alias (aliases_request->conn,
- g_array_index (aliases_request->contacts, GabbleHandle, i), &alias);
- g_assert (source != GABBLE_CONNECTION_ALIAS_NONE);
- g_assert (NULL != alias);
-
- aliases_request->pending_vcard_requests--;
- aliases_request->vcard_requests[i] = NULL;
- aliases_request->aliases[i] = alias;
-
- if (aliases_request_try_return (aliases_request))
- aliases_request_free (aliases_request);
-}
-
-
-/**
- * gabble_connection_request_aliases
- *
- * Implements D-Bus method RequestAliases
- * on interface org.freedesktop.Telepathy.Connection.Interface.Aliasing
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-void
-gabble_connection_request_aliases (GabbleConnection *self,
- const GArray *contacts,
- DBusGMethodInvocation *context)
-{
- guint i;
- AliasesRequest *request;
- GError *error = NULL;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- ERROR_IF_NOT_CONNECTED_ASYNC (self, error, context)
-
- if (!gabble_handles_are_valid (self->handles, TP_HANDLE_TYPE_CONTACT,
- contacts, FALSE, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- request = aliases_request_new (self, context, contacts);
-
- for (i = 0; i < contacts->len; i++)
- {
- GabbleHandle handle = g_array_index (contacts, GabbleHandle, i);
- GabbleConnectionAliasSource source;
- GabbleVCardManagerRequest *vcard_request;
- gchar *alias;
-
- source = _gabble_connection_get_cached_alias (self, handle, &alias);
- g_assert (source != GABBLE_CONNECTION_ALIAS_NONE);
- g_assert (NULL != alias);
-
- if (source >= GABBLE_CONNECTION_ALIAS_FROM_VCARD ||
- gabble_vcard_manager_has_cached_alias (self->vcard_manager, handle))
- {
- /* Either the alias we got was from a vCard or better, or we already
- * tried getting an alias from a vcard and failed, so there's no
- * point trying again. */
- request->aliases[i] = alias;
- }
- else
- {
- gabble_debug (DEBUG_FLAG, "requesting vCard for alias of contact %s",
- gabble_handle_inspect (self->handles, TP_HANDLE_TYPE_CONTACT,
- handle));
-
- g_free (alias);
- vcard_request = gabble_vcard_manager_request (self->vcard_manager,
- handle, 0, aliases_request_vcard_cb, request, G_OBJECT (self),
- &error);
-
- if (NULL != error)
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- aliases_request_free (request);
- return;
- }
-
- request->vcard_requests[i] = vcard_request;
- request->pending_vcard_requests++;
- }
- }
-
- if (aliases_request_try_return (request))
- aliases_request_free (request);
-}
-
-
-/**
- * gabble_connection_request_channel
- *
- * Implements D-Bus method RequestChannel
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-void
-gabble_connection_request_channel (GabbleConnection *self,
- const gchar *type,
- guint handle_type,
- guint handle,
- gboolean suppress_handler,
- DBusGMethodInvocation *context)
-{
- GabbleConnectionPrivate *priv;
- TpChannelFactoryRequestStatus status =
- TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
- gchar *object_path = NULL;
- GError *error = NULL;
- guint i;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED_ASYNC (self, error, context);
-
- for (i = 0; i < priv->channel_factories->len; i++)
- {
- TpChannelFactoryIface *factory = g_ptr_array_index
- (priv->channel_factories, i);
- TpChannelFactoryRequestStatus cur_status;
- TpChannelIface *chan = NULL;
- ChannelRequest *request = NULL;
-
- priv->suppress_next_handler = suppress_handler;
-
- cur_status = tp_channel_factory_iface_request (factory, type,
- (TpHandleType) handle_type, handle, &chan, &error);
-
- priv->suppress_next_handler = FALSE;
-
- switch (cur_status)
- {
- case TP_CHANNEL_FACTORY_REQUEST_STATUS_DONE:
- g_assert (NULL != chan);
- g_object_get (chan, "object-path", &object_path, NULL);
- goto OUT;
- case TP_CHANNEL_FACTORY_REQUEST_STATUS_QUEUED:
- gabble_debug (DEBUG_FLAG, "queueing request, channel_type=%s, handle_type=%u, "
- "handle=%u, suppress_handler=%u", type, handle_type,
- handle, suppress_handler);
- request = channel_request_new (context, type, handle_type, handle,
- suppress_handler);
- g_ptr_array_add (priv->channel_requests, request);
- return;
- case TP_CHANNEL_FACTORY_REQUEST_STATUS_ERROR:
- /* pass through error */
- goto OUT;
- default:
- /* always return the most specific error */
- if (cur_status > status)
- status = cur_status;
- }
- }
-
- switch (status)
- {
- case TP_CHANNEL_FACTORY_REQUEST_STATUS_INVALID_HANDLE:
- gabble_debug (DEBUG_FLAG, "invalid handle %u", handle);
-
- error = g_error_new (TELEPATHY_ERRORS, InvalidHandle,
- "invalid handle %u", handle);
-
- break;
-
- case TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE:
- gabble_debug (DEBUG_FLAG, "requested channel is unavailable with "
- "handle type %u", handle_type);
-
- error = g_error_new (TELEPATHY_ERRORS, NotAvailable,
- "requested channel is not available with "
- "handle type %u", handle_type);
-
- break;
-
- case TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED:
- gabble_debug (DEBUG_FLAG, "unsupported channel type %s", type);
-
- error = g_error_new (TELEPATHY_ERRORS, NotImplemented,
- "unsupported channel type %s", type);
-
- break;
-
- default:
- g_assert_not_reached ();
- }
-
-OUT:
- if (NULL != error)
- {
- g_assert (NULL == object_path);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- g_assert (NULL != object_path);
- dbus_g_method_return (context, object_path);
- g_free (object_path);
-}
-
-
-static void
-hold_and_return_handles (DBusGMethodInvocation *context,
- GabbleConnection *conn,
- GArray *handles,
- guint handle_type)
-{
- GError *error = NULL;
- gchar *sender = dbus_g_method_get_sender(context);
- guint i;
-
- for (i = 0; i < handles->len; i++)
- {
- GabbleHandle handle = (GabbleHandle) g_array_index (handles, guint, i);
- if (!gabble_handle_client_hold (conn->handles, sender, handle, handle_type, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
- }
- dbus_g_method_return (context, handles);
-}
-
-
-const char *
-_gabble_connection_find_conference_server (GabbleConnection *conn)
-{
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (conn);
-
- if (priv->conference_server == NULL)
- {
- /* Find first server that has NS_MUC feature */
- const GabbleDiscoItem *item = gabble_disco_service_find (conn->disco,
- NULL, NULL, NS_MUC);
- if (item != NULL)
- priv->conference_server = item->jid;
- }
-
- if (priv->conference_server == NULL)
- priv->conference_server = priv->fallback_conference_server;
-
- return priv->conference_server;
-}
-
-
-static gchar *
-_gabble_connection_get_canonical_room_name (GabbleConnection *conn,
- const gchar *name)
-{
- const gchar *server;
-
- g_assert (GABBLE_IS_CONNECTION (conn));
-
- if (index (name, '@'))
- return g_strdup (name);
-
- server = _gabble_connection_find_conference_server (conn);
-
- if (server == NULL)
- return NULL;
-
- return g_strdup_printf ("%s@%s", name, server);
-}
-
-
-typedef struct _RoomVerifyContext RoomVerifyContext;
-
-typedef struct {
- GabbleConnection *conn;
- DBusGMethodInvocation *invocation;
- gboolean errored;
- guint count;
- GArray *handles;
- RoomVerifyContext *contexts;
-} RoomVerifyBatch;
-
-struct _RoomVerifyContext {
- gchar *jid;
- guint index;
- RoomVerifyBatch *batch;
- GabbleDiscoRequest *request;
-};
-
-static void
-room_verify_batch_free (RoomVerifyBatch *batch)
-{
- guint i;
-
- g_array_free (batch->handles, TRUE);
- for (i = 0; i < batch->count; i++)
- {
- g_free(batch->contexts[i].jid);
- }
- g_free (batch->contexts);
- g_free (batch);
-}
-
-/* Frees the error and the batch. */
-static void
-room_verify_batch_raise_error (RoomVerifyBatch *batch,
- GError *error)
-{
- guint i;
-
- dbus_g_method_return_error (batch->invocation, error);
- g_error_free (error);
- batch->errored = TRUE;
- for (i = 0; i < batch->count; i++)
- {
- if (batch->contexts[i].request)
- {
- gabble_disco_cancel_request(batch->conn->disco,
- batch->contexts[i].request);
- }
- }
- room_verify_batch_free (batch);
-}
-
-static RoomVerifyBatch *
-room_verify_batch_new (GabbleConnection *conn,
- DBusGMethodInvocation *invocation,
- guint count,
- const gchar **jids)
-{
- RoomVerifyBatch *batch = g_new(RoomVerifyBatch, 1);
- guint i;
-
- batch->errored = FALSE;
- batch->conn = conn;
- batch->invocation = invocation;
- batch->count = count;
- batch->handles = g_array_sized_new(FALSE, FALSE, sizeof(GabbleHandle), count);
- batch->contexts = g_new0(RoomVerifyContext, count);
- for (i = 0; i < count; i++)
- {
- const gchar *name = jids[i];
- gchar *qualified_name;
- GabbleHandle handle;
-
- batch->contexts[i].index = i;
- batch->contexts[i].batch = batch;
-
- qualified_name = _gabble_connection_get_canonical_room_name (conn, name);
-
- if (!qualified_name)
- {
- GError *error = NULL;
- gabble_debug (DEBUG_FLAG, "requested handle %s contains no conference server",
- name);
- error = g_error_new (TELEPATHY_ERRORS, NotAvailable, "requested "
- "room handle %s does not specify a server, but we have not discovered "
- "any local conference servers and no fallback was provided", name);
- room_verify_batch_raise_error (batch, error);
- return NULL;
- }
-
- batch->contexts[i].jid = qualified_name;
-
- /* has the handle been verified before? */
- if (gabble_handle_for_room_exists (conn->handles, qualified_name, FALSE))
- {
- handle = gabble_handle_for_room (conn->handles, qualified_name);
- }
- else
- {
- handle = 0;
- }
- g_array_append_val (batch->handles, handle);
- }
-
- return batch;
-}
-
-/* If all handles in the array have been disco'd or got from cache,
-free the batch and return TRUE. Else return FALSE. */
-static gboolean
-room_verify_batch_try_return (RoomVerifyBatch *batch)
-{
- guint i;
-
- for (i = 0; i < batch->count; i++)
- {
- if (!g_array_index(batch->handles, GabbleHandle, i))
- {
- /* we're not ready yet */
- return FALSE;
- }
- }
-
- hold_and_return_handles (batch->invocation, batch->conn, batch->handles, TP_HANDLE_TYPE_ROOM);
- room_verify_batch_free (batch);
- return TRUE;
-}
-
-static void
-room_jid_disco_cb (GabbleDisco *disco,
- GabbleDiscoRequest *request,
- const gchar *jid,
- const gchar *node,
- LmMessageNode *query_result,
- GError *error,
- gpointer user_data)
-{
- RoomVerifyContext *rvctx = user_data;
- RoomVerifyBatch *batch = rvctx->batch;
- LmMessageNode *lm_node;
- gboolean found = FALSE;
- GabbleHandle handle;
-
- /* stop the request getting cancelled after it's already finished */
- rvctx->request = NULL;
-
- /* if an error is being handled already, quietly go away */
- if (batch->errored)
- {
- return;
- }
-
- if (error != NULL)
- {
- gabble_debug (DEBUG_FLAG, "disco reply error %s", error->message);
-
- /* disco will free the old error, _raise_error will free the new one */
- error = g_error_new (TELEPATHY_ERRORS, NotAvailable,
- "can't retrieve room info: %s", error->message);
-
- room_verify_batch_raise_error (batch, error);
-
- return;
- }
-
- for (lm_node = query_result->children; lm_node; lm_node = lm_node->next)
- {
- const gchar *var;
-
- if (g_strdiff (lm_node->name, "feature"))
- continue;
-
- var = lm_message_node_get_attribute (lm_node, "var");
-
- /* for servers who consider schema compliance to be an optional bonus */
- if (var == NULL)
- var = lm_message_node_get_attribute (lm_node, "type");
-
- if (!g_strdiff (var, NS_MUC))
- {
- found = TRUE;
- break;
- }
- }
-
- if (!found)
- {
- gabble_debug (DEBUG_FLAG, "no MUC support for service name in jid %s", rvctx->jid);
-
- error = g_error_new (TELEPATHY_ERRORS, NotAvailable, "specified server "
- "doesn't support MUC");
-
- room_verify_batch_raise_error (batch, error);
-
- return;
- }
-
- handle = gabble_handle_for_room (batch->conn->handles, rvctx->jid);
- g_assert (handle != 0);
-
- gabble_debug (DEBUG_FLAG, "disco reported MUC support for service name in jid %s", rvctx->jid);
- g_array_index (batch->handles, GabbleHandle, rvctx->index) = handle;
-
- /* if this was the last callback to be run, send off the result */
- room_verify_batch_try_return (batch);
-}
-
-/**
- * room_jid_verify:
- *
- * Utility function that verifies that the service name of
- * the specified jid exists and reports MUC support.
- */
-static gboolean
-room_jid_verify (RoomVerifyBatch *batch,
- guint index,
- DBusGMethodInvocation *context)
-{
- gchar *room, *service;
- gboolean ret;
- GError *error = NULL;
-
- room = service = NULL;
- gabble_decode_jid (batch->contexts[index].jid, &room, &service, NULL);
-
- g_assert (room && service);
-
- ret = (gabble_disco_request (batch->conn->disco, GABBLE_DISCO_TYPE_INFO,
- service, NULL, room_jid_disco_cb,
- batch->contexts + index,
- G_OBJECT (batch->conn), &error) != NULL);
- if (!ret)
- {
- room_verify_batch_raise_error (batch, error);
- }
-
- g_free (room);
- g_free (service);
-
- return ret;
-}
-
-
-/**
- * gabble_connection_request_handles
- *
- * Implements D-Bus method RequestHandles
- * on interface org.freedesktop.Telepathy.Connection
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-void
-gabble_connection_request_handles (GabbleConnection *self,
- guint handle_type,
- const gchar **names,
- DBusGMethodInvocation *context)
-{
- guint count = 0, i;
- const gchar **cur_name;
- GError *error = NULL;
- GArray *handles = NULL;
- RoomVerifyBatch *batch = NULL;
-
- for (cur_name = names; *cur_name != NULL; cur_name++)
- {
- count++;
- }
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- ERROR_IF_NOT_CONNECTED_ASYNC (self, error, context)
-
- if (!gabble_handle_type_is_valid (handle_type, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- switch (handle_type)
- {
- case TP_HANDLE_TYPE_CONTACT:
- handles = g_array_sized_new(FALSE, FALSE, sizeof(GabbleHandle), count);
-
- for (i = 0; i < count; i++)
- {
- GabbleHandle handle;
- const gchar *name = names[i];
-
- if (!gabble_handle_jid_is_valid (handle_type, name, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- g_array_free (handles, TRUE);
- return;
- }
-
- handle = gabble_handle_for_contact (self->handles, name, FALSE);
-
- if (handle == 0)
- {
- gabble_debug (DEBUG_FLAG, "requested handle %s was invalid", name);
-
- error = g_error_new (TELEPATHY_ERRORS, NotAvailable,
- "requested handle %s was invalid", name);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- g_array_free (handles, TRUE);
- return;
- }
-
- g_array_append_val(handles, handle);
- }
- hold_and_return_handles (context, self, handles, handle_type);
- g_array_free(handles, TRUE);
- break;
-
- case TP_HANDLE_TYPE_ROOM:
- batch = room_verify_batch_new (self, context, count, names);
- if (!batch)
- {
- /* an error occurred while setting up the batch, and we returned error
- to dbus */
- return;
- }
-
- /* have all the handles been verified already? If so, nothing to do */
- if (room_verify_batch_try_return (batch))
- {
- return;
- }
-
- for (i = 0; i < count; i++)
- {
- if (!room_jid_verify (batch, i, context))
- {
- return;
- }
- }
-
- /* we've set the verification process going - the callback will handle
- returning or raising error */
- break;
-
- case TP_HANDLE_TYPE_LIST:
- handles = g_array_sized_new(FALSE, FALSE, sizeof(GabbleHandle), count);
-
- for (i = 0; i < count; i++)
- {
- GabbleHandle handle;
- const gchar *name = names[i];
-
- handle = gabble_handle_for_list (self->handles, name);
-
- if (handle == 0)
- {
- gabble_debug (DEBUG_FLAG, "requested list channel %s not available", name);
-
- error = g_error_new (TELEPATHY_ERRORS, NotAvailable,
- "requested list channel %s not available",
- name);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- g_array_free (handles, TRUE);
- return;
- }
- g_array_append_val(handles, handle);
- }
- hold_and_return_handles (context, self, handles, handle_type);
- g_array_free(handles, TRUE);
- break;
-
- default:
- gabble_debug (DEBUG_FLAG, "unimplemented handle type %u", handle_type);
-
- error = g_error_new (TELEPATHY_ERRORS, NotAvailable,
- "unimplemented handle type %u", handle_type);
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- }
-}
-
-
-/**
- * gabble_connection_request_presence
- *
- * Implements D-Bus method RequestPresence
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_request_presence (GabbleConnection *self,
- const GArray *contacts,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- if (!gabble_handles_are_valid (self->handles, TP_HANDLE_TYPE_CONTACT,
- contacts, FALSE, error))
- return FALSE;
-
- if (contacts->len)
- emit_presence_update (self, contacts);
-
- return TRUE;
-}
-
-
-struct _i_hate_g_hash_table_foreach
-{
- GabbleConnection *conn;
- GError **error;
- gboolean retval;
-};
-
-static void
-setaliases_foreach (gpointer key, gpointer value, gpointer user_data)
-{
- struct _i_hate_g_hash_table_foreach *data =
- (struct _i_hate_g_hash_table_foreach *) user_data;
- GabbleHandle handle = GPOINTER_TO_INT (key);
- gchar *alias = (gchar *) value;
- GError *error = NULL;
-
- if (!gabble_handle_is_valid (data->conn->handles, TP_HANDLE_TYPE_CONTACT,
- handle, &error))
- {
- data->retval = FALSE;
- }
- else if (data->conn->self_handle == handle)
- {
- /* only alter the roster if we're already there, e.g. because someone
- * added us with another client
- */
- if (gabble_roster_handle_has_entry (data->conn->roster, handle)
- && !gabble_roster_handle_set_name (data->conn->roster, handle,
- alias, data->error))
- {
- data->retval = FALSE;
- }
- }
- else if (!gabble_roster_handle_set_name (data->conn->roster, handle, alias,
- data->error))
- {
- data->retval = FALSE;
- }
-
- if (data->conn->self_handle == handle)
- {
- /* User has done SetAliases on themselves - patch their vCard.
- * FIXME: because SetAliases is currently synchronous, we ignore errors
- * here, and just let the request happen in the background
- */
- gabble_vcard_manager_edit (data->conn->vcard_manager,
- 0, NULL, NULL, G_OBJECT(data->conn), NULL,
- "NICKNAME", alias, NULL);
- }
-
- if (NULL != error)
- {
- if (NULL == *(data->error))
- {
- *(data->error) = error;
- }
- else
- {
- g_error_free (error);
- }
- }
-}
-
-/**
- * gabble_connection_set_aliases
- *
- * Implements D-Bus method SetAliases
- * on interface org.freedesktop.Telepathy.Connection.Interface.Aliasing
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns false.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_set_aliases (GabbleConnection *self,
- GHashTable *aliases,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
- struct _i_hate_g_hash_table_foreach data = { NULL, NULL, TRUE };
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- data.conn = self;
- data.error = error;
-
- g_hash_table_foreach (aliases, setaliases_foreach, &data);
-
- return data.retval;
-}
-
-
-/**
- * gabble_connection_set_last_activity_time
- *
- * Implements D-Bus method SetLastActivityTime
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns false.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_set_last_activity_time (GabbleConnection *self,
- guint time,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- return TRUE;
-}
-
-
-static void
-setstatuses_foreach (gpointer key, gpointer value, gpointer user_data)
-{
- struct _i_hate_g_hash_table_foreach *data =
- (struct _i_hate_g_hash_table_foreach*) user_data;
- GabbleConnectionPrivate *priv = GABBLE_CONNECTION_GET_PRIVATE (data->conn);
-
- int i;
-
- for (i = 0; i < LAST_GABBLE_PRESENCE; i++)
- {
- if (0 == strcmp (gabble_statuses[i].name, (const gchar*) key))
- break;
- }
-
- if (i < LAST_GABBLE_PRESENCE)
- {
- GHashTable *args = (GHashTable *)value;
- GValue *message = g_hash_table_lookup (args, "message");
- GValue *priority = g_hash_table_lookup (args, "priority");
- const gchar *status = NULL;
- gint8 prio = priv->priority;
-
- if (!status_is_available (data->conn, i))
- {
- gabble_debug (DEBUG_FLAG, "requested status %s is not available", (const gchar *) key);
- g_set_error (data->error, TELEPATHY_ERRORS, NotAvailable,
- "requested status '%s' is not available on this connection",
- (const gchar *) key);
- data->retval = FALSE;
- return;
- }
-
- if (message)
- {
- if (!G_VALUE_HOLDS_STRING (message))
- {
- gabble_debug (DEBUG_FLAG, "got a status message which was not a string");
- g_set_error (data->error, TELEPATHY_ERRORS, InvalidArgument,
- "Status argument 'message' requires a string");
- data->retval = FALSE;
- return;
- }
- status = g_value_get_string (message);
- }
-
- if (priority)
- {
- if (!G_VALUE_HOLDS_INT (priority))
- {
- gabble_debug (DEBUG_FLAG, "got a priority value which was not a signed integer");
- g_set_error (data->error, TELEPATHY_ERRORS, InvalidArgument,
- "Status argument 'priority' requires a signed integer");
- data->retval = FALSE;
- return;
- }
- prio = CLAMP (g_value_get_int (priority), G_MININT8, G_MAXINT8);
- }
-
- gabble_presence_cache_update (data->conn->presence_cache, data->conn->self_handle, priv->resource, i, status, prio);
- emit_one_presence_update (data->conn, data->conn->self_handle);
- data->retval = signal_own_presence (data->conn, data->error);
- }
- else
- {
- gabble_debug (DEBUG_FLAG, "got unknown status identifier %s", (const gchar *) key);
- g_set_error (data->error, TELEPATHY_ERRORS, InvalidArgument,
- "unknown status identifier: %s", (const gchar *) key);
- data->retval = FALSE;
- }
-}
-
-/**
- * gabble_connection_set_properties
- *
- * Implements D-Bus method SetProperties
- * on interface org.freedesktop.Telepathy.Properties
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-void
-gabble_connection_set_properties (GabbleConnection *self,
- const GPtrArray *properties,
- DBusGMethodInvocation *context)
-{
- gabble_properties_mixin_set_properties (G_OBJECT (self), properties, context);
-}
-
-/**
- * gabble_connection_set_status
- *
- * Implements D-Bus method SetStatus
- * on interface org.freedesktop.Telepathy.Connection.Interface.Presence
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_set_status (GabbleConnection *self,
- GHashTable *statuses,
- GError **error)
-{
- GabbleConnectionPrivate *priv;
- struct _i_hate_g_hash_table_foreach data = { NULL, NULL, TRUE };
-
- g_assert (GABBLE_IS_CONNECTION (self));
-
- priv = GABBLE_CONNECTION_GET_PRIVATE (self);
-
- ERROR_IF_NOT_CONNECTED (self, error)
-
- if (g_hash_table_size (statuses) != 1)
- {
- gabble_debug (DEBUG_FLAG, "got more than one status");
- g_set_error (error, TELEPATHY_ERRORS, InvalidArgument,
- "Only one status may be set at a time in this protocol");
- return FALSE;
- }
-
- data.conn = self;
- data.error = error;
- g_hash_table_foreach (statuses, setstatuses_foreach, &data);
-
- return data.retval;
-}
-
-/**
- * gabble_connection_build_avatar
- *
- * Implements D-Bus method SetAvatar
- * on interface org.freedesktop.Telepathy.Connection.Avatar
- *
- * @context: The D-Bus invocation context to use to return values
- * or throw an error.
- */
-
-LmMessage* gabble_connection_build_avatar(GabbleConnection *self,
- const GArray* bin_image, gchar* mime )
- {
- int i = 0;
- LmMessage *message;
- LmMessageNode *lm_node,*photo_node;
- LmMessageHandler* handler = NULL;
- char* base64 = NULL;
- GError* error = NULL;
- //NULL values to be checked ? never returns NULL?
- if ( bin_image )
- {
- if ( self->self_avatar_sha1 )
- {
- free( self->self_avatar_sha1 );
- self->self_avatar_sha1 = NULL;
- }
- self->self_avatar_sha1 = sha1_hex( bin_image->data, bin_image->len );
- base64 = base64_encode ( bin_image->len, bin_image->data );
- }
-
- message = lm_message_new_with_sub_type ( NULL,
- LM_MESSAGE_TYPE_IQ,
- LM_MESSAGE_SUB_TYPE_SET );
- lm_node = lm_message_node_add_child (message->node, "vCard", NULL);
- lm_message_node_set_attribute (lm_node, "xmlns", NS_VCARD_TEMP);
- photo_node = lm_message_node_add_child (lm_node, "PHOTO", NULL);
- lm_message_node_add_child (photo_node, "TYPE", mime);
- lm_message_node_add_child (photo_node, "BINVAL", base64);
- g_free(base64);
- return message;
- }
-
-/**
- * gabble_connection_set_avatar
- *
- * Implements D-Bus method SetAvatar
- * on interface org.freedesktop.Telepathy.Connection
- *
- */
-gboolean
-gabble_connection_set_avatar( GabbleConnection *self, const GArray* bin_image, gchar* mime_type, gchar**avatar_sha1,
- GError** err )
- {
-
- gboolean ret = FALSE;
- LmMessage *message;
-
-
- //There is no need to check bin_image and mime for NULL.. NULL is a valid value for those
- message = gabble_connection_build_avatar( self, bin_image, mime_type );
-
- ret = _gabble_connection_send ( self, message, err );
-
- if ( *err )
- {
- *avatar_sha1 = NULL;
- //ret is already false.. so false returned
- }
- else {
- if ( self->self_avatar_sha1 )
- {
- *avatar_sha1 = g_strdup( self->self_avatar_sha1 );
- }
- ret = TRUE;
- }
-
- lm_message_unref( message );
-
- return ret;
- }
-
-/**
- * gabble_connection_clear_avatar
- *
- * Implements D-Bus method ClearAvatar
- * on interface org.freedesktop.Telepathy.Connection.Interface.Avatar
- *
- * @error: Used to return a pointer to a GError detailing any error
- * that occurred, D-Bus will throw the error only if this
- * function returns FALSE.
- *
- * Returns: TRUE if successful, FALSE if an error was thrown.
- */
-gboolean
-gabble_connection_clear_avatar( GabbleConnection *self,
- GError **error)
- {
- LmMessage *message;
- gboolean ret = TRUE;
-
-
- //Build the avatar xml with NULL as image data and NULL as mimetype
- message = gabble_connection_build_avatar( self,
- NULL, NULL );
-
- ret = _gabble_connection_send ( self, message, error );
-
- if ( self->self_avatar_sha1 )
- {
- free( self->self_avatar_sha1 );
- self->self_avatar_sha1 = NULL;
- }
-
- lm_message_unref( message );
-
- return ret;
- }