diff options
Diffstat (limited to 'libempathy')
28 files changed, 895 insertions, 892 deletions
diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am index 3540c88bf..87b728464 100644 --- a/libempathy/Makefile.am +++ b/libempathy/Makefile.am @@ -7,6 +7,7 @@ AM_CPPFLAGS = \ -I$(top_builddir) \ -DDATADIR=\""$(datadir)"\" \ -DLOCALEDIR=\""$(datadir)/locale"\" \ + -DG_LOG_DOMAIN=\"empathy\" \ $(LIBEMPATHY_CFLAGS) \ $(GEOCLUE_CFLAGS) \ $(WARN_CFLAGS) \ @@ -33,6 +34,7 @@ libempathy_la_SOURCES = \ empathy-contact-manager.c \ empathy-contact-monitor.c \ empathy-debug.c \ + empathy-debugger.c \ empathy-dispatcher.c \ empathy-dispatch-operation.c \ empathy-ft-factory.c \ @@ -53,7 +55,6 @@ libempathy_la_SOURCES = \ empathy-tp-contact-list.c \ empathy-tp-file.c \ empathy-tp-roomlist.c \ - empathy-tp-tube.c \ empathy-tube-handler.c \ empathy-utils.c @@ -82,6 +83,7 @@ libempathy_headers = \ empathy-contact-manager.h \ empathy-contact-monitor.h \ empathy-debug.h \ + empathy-debugger.h \ empathy-dispatcher.h \ empathy-dispatch-operation.h \ empathy-ft-factory.h \ @@ -103,7 +105,6 @@ libempathy_headers = \ empathy-tp-contact-list.h \ empathy-tp-file.h \ empathy-tp-roomlist.h \ - empathy-tp-tube.h \ empathy-tube-handler.h \ empathy-types.h \ empathy-utils.h diff --git a/libempathy/empathy-call-handler.c b/libempathy/empathy-call-handler.c index 8d70885b4..f73c41e2e 100644 --- a/libempathy/empathy-call-handler.c +++ b/libempathy/empathy-call-handler.c @@ -1,6 +1,6 @@ /* * empathy-call-handler.c - Source for EmpathyCallHandler - * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008-2009 Collabora Ltd. * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> * * This library is free software; you can redistribute it and/or @@ -304,7 +304,9 @@ EmpathyCallHandler * empathy_call_handler_new_for_channel (EmpathyTpCall *call) { return EMPATHY_CALL_HANDLER (g_object_new (EMPATHY_TYPE_CALL_HANDLER, - "tp-call", call, NULL)); + "tp-call", call, + "initial-video", empathy_tp_call_is_receiving_video (call), + NULL)); } void @@ -577,3 +579,40 @@ empathy_call_handler_start_call (EmpathyCallHandler *handler) g_object_unref (dispatcher); } +/** + * empathy_call_handler_stop_call: + * @handler: an #EmpathyCallHandler + * + * Closes the #EmpathyCallHandler's call and frees its resources. + */ +void +empathy_call_handler_stop_call (EmpathyCallHandler *handler) +{ + EmpathyCallHandlerPriv *priv = GET_PRIV (handler); + + if (priv->call != NULL) + { + empathy_tp_call_close (priv->call); + g_object_unref (priv->call); + } + + priv->call = NULL; +} + +/** + * empathy_call_handler_has_initial_video: + * @handler: an #EmpathyCallHandler + * + * Return %TRUE if the call managed by this #EmpathyCallHandler was + * created with video enabled + * + * Return value: %TRUE if the call was created as a video conversation. + */ +gboolean +empathy_call_handler_has_initial_video (EmpathyCallHandler *handler) +{ + EmpathyCallHandlerPriv *priv = GET_PRIV (handler); + + return priv->initial_video; +} + diff --git a/libempathy/empathy-call-handler.h b/libempathy/empathy-call-handler.h index 9a039f06a..1f67fe56b 100644 --- a/libempathy/empathy-call-handler.h +++ b/libempathy/empathy-call-handler.h @@ -1,6 +1,6 @@ /* * empathy-call-handler.h - Header for EmpathyCallHandler - * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008-2009 Collabora Ltd. * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> * * This library is free software; you can redistribute it and/or @@ -71,6 +71,9 @@ EmpathyCallHandler * empathy_call_handler_new_for_channel ( EmpathyTpCall *call); void empathy_call_handler_start_call (EmpathyCallHandler *handler); +void empathy_call_handler_stop_call (EmpathyCallHandler *handler); + +gboolean empathy_call_handler_has_initial_video (EmpathyCallHandler *handler); void empathy_call_handler_bus_message (EmpathyCallHandler *handler, GstBus *bus, GstMessage *message); diff --git a/libempathy/empathy-chatroom-manager.c b/libempathy/empathy-chatroom-manager.c index 3bdc5f154..44416670e 100644 --- a/libempathy/empathy-chatroom-manager.c +++ b/libempathy/empathy-chatroom-manager.c @@ -506,6 +506,27 @@ empathy_chatroom_manager_add (EmpathyChatroomManager *manager, return FALSE; } +static void +chatroom_manager_remove_link (EmpathyChatroomManager *manager, + GList *l) +{ + EmpathyChatroomManagerPriv *priv; + EmpathyChatroom *chatroom; + + priv = GET_PRIV (manager); + + chatroom = l->data; + + if (empathy_chatroom_is_favorite (chatroom)) + reset_save_timeout (manager); + + g_signal_emit (manager, signals[CHATROOM_REMOVED], 0, chatroom); + g_signal_handlers_disconnect_by_func (chatroom, chatroom_changed_cb, manager); + + priv->chatrooms = g_list_delete_link (priv->chatrooms, l); + g_object_unref (chatroom); +} + void empathy_chatroom_manager_remove (EmpathyChatroomManager *manager, EmpathyChatroom *chatroom) @@ -527,15 +548,7 @@ empathy_chatroom_manager_remove (EmpathyChatroomManager *manager, if (this_chatroom == chatroom || empathy_chatroom_equal (chatroom, this_chatroom)) { - priv->chatrooms = g_list_delete_link (priv->chatrooms, l); - if (empathy_chatroom_is_favorite (chatroom)) - reset_save_timeout (manager); - - g_signal_emit (manager, signals[CHATROOM_REMOVED], 0, this_chatroom); - g_signal_handlers_disconnect_by_func (chatroom, chatroom_changed_cb, - manager); - - g_object_unref (this_chatroom); + chatroom_manager_remove_link (manager, l); break; } } @@ -649,13 +662,16 @@ chatroom_manager_chat_destroyed_cb (EmpathyTpChat *chat, continue; empathy_chatroom_set_tp_chat (chatroom, NULL); + if (!empathy_chatroom_is_favorite (chatroom)) { /* Remove the chatroom from the list, unless it's in the list of * favourites.. * FIXME this policy should probably not be in libempathy */ - empathy_chatroom_manager_remove (manager, chatroom); + chatroom_manager_remove_link (manager, l); } + + break; } } diff --git a/libempathy/empathy-chatroom.c b/libempathy/empathy-chatroom.c index 6575bb998..147fca0a9 100644 --- a/libempathy/empathy-chatroom.c +++ b/libempathy/empathy-chatroom.c @@ -407,11 +407,11 @@ empathy_chatroom_get_name (EmpathyChatroom *chatroom) g_return_val_if_fail (EMPATHY_IS_CHATROOM (chatroom), NULL); priv = GET_PRIV (chatroom); - + if (EMP_STR_EMPTY (priv->name)) { return priv->room; } - + return priv->name; } diff --git a/libempathy/empathy-contact-manager.c b/libempathy/empathy-contact-manager.c index 412087ec0..7af2bd349 100644 --- a/libempathy/empathy-contact-manager.c +++ b/libempathy/empathy-contact-manager.c @@ -103,7 +103,7 @@ contact_manager_invalidated_cb (TpProxy *connection, list = g_hash_table_lookup (priv->lists, connection); if (list) { empathy_tp_contact_list_remove_all (list); - g_hash_table_remove (priv->lists, connection); + g_hash_table_remove (priv->lists, connection); } } @@ -503,7 +503,7 @@ contact_manager_remove_group (EmpathyContactList *manager, const gchar *group) { EmpathyContactManagerPriv *priv = GET_PRIV (manager); - + g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager)); g_hash_table_foreach (priv->lists, @@ -533,7 +533,7 @@ empathy_contact_manager_can_add (EmpathyContactManager *manager, { EmpathyContactManagerPriv *priv = GET_PRIV (manager); EmpathyTpContactList *list; - + g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), FALSE); list = g_hash_table_lookup (priv->lists, connection); diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c index 03ce8d28a..bad6ef470 100644 --- a/libempathy/empathy-contact.c +++ b/libempathy/empathy-contact.c @@ -830,17 +830,16 @@ static gchar * contact_get_avatar_filename (EmpathyContact *contact, const gchar *token) { - EmpathyContactPriv *priv = GET_PRIV (contact); McAccount *account; gchar *avatar_path; gchar *avatar_file; gchar *token_escaped; gchar *contact_escaped; - if (EMP_STR_EMPTY (priv->id)) + if (EMP_STR_EMPTY (empathy_contact_get_id (contact))) return NULL; - contact_escaped = tp_escape_as_identifier (priv->id); + contact_escaped = tp_escape_as_identifier (empathy_contact_get_id (contact)); token_escaped = tp_escape_as_identifier (token); account = empathy_contact_get_account (contact); @@ -864,7 +863,7 @@ contact_get_avatar_filename (EmpathyContact *contact, void empathy_contact_load_avatar_data (EmpathyContact *contact, - const guchar *data, + const guchar *data, const gsize len, const gchar *format, const gchar *token) @@ -880,13 +879,13 @@ empathy_contact_load_avatar_data (EmpathyContact *contact, g_return_if_fail (!EMP_STR_EMPTY (token)); /* Load and set the avatar */ + filename = contact_get_avatar_filename (contact, token); avatar = empathy_avatar_new (g_memdup (data, len), len, g_strdup (format), - g_strdup (token)); + g_strdup (token), filename); empathy_contact_set_avatar (contact, avatar); empathy_avatar_unref (avatar); /* Save to cache if not yet in it */ - filename = contact_get_avatar_filename (contact, token); if (filename && !g_file_test (filename, G_FILE_TEST_EXISTS)) { if (!empathy_avatar_save_to_file (avatar, filename, &error)) @@ -898,7 +897,6 @@ empathy_contact_load_avatar_data (EmpathyContact *contact, else DEBUG ("Avatar saved to %s", filename); } - g_free (filename); } gboolean @@ -929,13 +927,11 @@ empathy_contact_load_avatar_cache (EmpathyContact *contact, if (data) { DEBUG ("Avatar loaded from %s", filename); - avatar = empathy_avatar_new (data, len, NULL, g_strdup (token)); + avatar = empathy_avatar_new (data, len, NULL, g_strdup (token), filename); empathy_contact_set_avatar (contact, avatar); empathy_avatar_unref (avatar); } - g_free (filename); - return data != NULL; } @@ -954,11 +950,25 @@ empathy_avatar_get_type (void) return type_id; } +/** + * empathy_avatar_new: + * @data: the avatar data + * @len: the size of avatar data + * @format: the mime type of the avatar image + * @token: the token of the avatar + * @filename: the filename where the avatar is stored in cache + * + * Create a #EmpathyAvatar from the provided data. This function takes the + * ownership of @data, @format, @token and @filename. + * + * Returns: a new #EmpathyAvatar + */ EmpathyAvatar * empathy_avatar_new (guchar *data, gsize len, gchar *format, - gchar *token) + gchar *token, + gchar *filename) { EmpathyAvatar *avatar; @@ -967,6 +977,7 @@ empathy_avatar_new (guchar *data, avatar->len = len; avatar->format = format; avatar->token = token; + avatar->filename = filename; avatar->refcount = 1; return avatar; @@ -1071,3 +1082,40 @@ empathy_contact_set_location (EmpathyContact *contact, priv->location = g_hash_table_ref (location); g_object_notify (G_OBJECT (contact), "location"); } + +/** + * empathy_contact_equal: + * @contact1: an #EmpathyContact + * @contact2: an #EmpathyContact + * + * Returns FALSE if one of the contacts is NULL but the other is not. + * Otherwise returns TRUE if both pointer are equal or if they bith + * refer to the same id. + * It's only necessary to call this function if your contact objects + * come from logs where contacts are created dynamically and comparing + * pointers is not enough. + */ +gboolean +empathy_contact_equal (gconstpointer contact1, + gconstpointer contact2) +{ + EmpathyContact *c1; + EmpathyContact *c2; + const gchar *id1; + const gchar *id2; + + if ((contact1 == NULL) != (contact2 == NULL)) { + return FALSE; + } + if (contact1 == contact2) { + return TRUE; + } + c1 = EMPATHY_CONTACT (contact1); + c2 = EMPATHY_CONTACT (contact2); + id1 = empathy_contact_get_id (c1); + id2 = empathy_contact_get_id (c2); + if (!tp_strdiff (id1, id2)) { + return TRUE; + } + return FALSE; +} diff --git a/libempathy/empathy-contact.h b/libempathy/empathy-contact.h index ff8d426e2..f88831342 100644 --- a/libempathy/empathy-contact.h +++ b/libempathy/empathy-contact.h @@ -55,6 +55,7 @@ typedef struct { gsize len; gchar *format; gchar *token; + gchar *filename; guint refcount; } EmpathyAvatar; @@ -114,7 +115,8 @@ GType empathy_avatar_get_type (void) G_GNUC_CONST; EmpathyAvatar * empathy_avatar_new (guchar *data, gsize len, gchar *format, - gchar *token); + gchar *token, + gchar *filename); EmpathyAvatar * empathy_avatar_ref (EmpathyAvatar *avatar); void empathy_avatar_unref (EmpathyAvatar *avatar); @@ -123,7 +125,9 @@ gboolean empathy_avatar_save_to_file (EmpathyAvatar *avatar, GHashTable * empathy_contact_get_location (EmpathyContact *contact); void empathy_contact_set_location (EmpathyContact *contact, - GHashTable *location); + GHashTable *location); +gboolean empathy_contact_equal (gconstpointer contact1, + gconstpointer contact2); G_END_DECLS diff --git a/libempathy/empathy-debug.c b/libempathy/empathy-debug.c index bcfa25deb..99111deec 100644 --- a/libempathy/empathy-debug.c +++ b/libempathy/empathy-debug.c @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ /* * Copyright (C) 2007 Collabora Ltd. * Copyright (C) 2007 Nokia Corporation @@ -33,6 +33,8 @@ #include "empathy-debug.h" +#include "empathy-debugger.h" + #ifdef ENABLE_DEBUG static EmpathyDebugFlags flags = 0; @@ -75,18 +77,74 @@ empathy_debug_flag_is_set (EmpathyDebugFlags flag) return (flag & flags) != 0; } +GHashTable *flag_to_keys = NULL; + +static const gchar * +debug_flag_to_key (EmpathyDebugFlags flag) +{ + if (flag_to_keys == NULL) + { + guint i; + + flag_to_keys = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, g_free); + + for (i = 0; keys[i].value; i++) + { + GDebugKey key = (GDebugKey) keys[i]; + g_hash_table_insert (flag_to_keys, GUINT_TO_POINTER (key.value), + g_strdup (key.key)); + } + } + + return g_hash_table_lookup (flag_to_keys, GUINT_TO_POINTER (flag)); +} + +void +empathy_debug_free (void) +{ + if (flag_to_keys == NULL) + return; + + g_hash_table_destroy (flag_to_keys); + flag_to_keys = NULL; +} + +static void +log_to_debugger (EmpathyDebugFlags flag, + const gchar *message) +{ + EmpathyDebugger *dbg = empathy_debugger_get_singleton (); + gchar *domain; + GTimeVal now; + + g_get_current_time (&now); + + domain = g_strdup_printf ("%s/%s", G_LOG_DOMAIN, debug_flag_to_key (flag)); + + empathy_debugger_add_message (dbg, &now, domain, G_LOG_LEVEL_DEBUG, message); + + g_free (domain); +} + void empathy_debug (EmpathyDebugFlags flag, - const gchar *format, - ...) + const gchar *format, + ...) { + gchar *message; + va_list args; + + va_start (args, format); + message = g_strdup_vprintf (format, args); + va_end (args); + + log_to_debugger (flag, message); + if (flag & flags) - { - va_list args; - va_start (args, format); - g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args); - va_end (args); - } + g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s", message); + + g_free (message); } #else diff --git a/libempathy/empathy-debug.h b/libempathy/empathy-debug.h index 787264dd0..9df728922 100644 --- a/libempathy/empathy-debug.h +++ b/libempathy/empathy-debug.h @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ /* * Copyright (C) 2007 Collabora Ltd. * Copyright (C) 2007 Nokia Corporation @@ -46,6 +46,7 @@ typedef enum gboolean empathy_debug_flag_is_set (EmpathyDebugFlags flag); void empathy_debug (EmpathyDebugFlags flag, const gchar *format, ...) G_GNUC_PRINTF (2, 3); +void empathy_debug_free (void); void empathy_debug_set_flags (const gchar *flags_string); G_END_DECLS @@ -88,4 +89,7 @@ G_END_DECLS #define DEBUGGING 0 #endif /* !defined (ENABLE_DEBUG) */ + +#define gabble_debug_free() G_STMT_START { } G_STMT_END + #endif /* defined (DEBUG_FLAG) */ diff --git a/libempathy/empathy-debugger.c b/libempathy/empathy-debugger.c new file mode 100644 index 000000000..04873120c --- /dev/null +++ b/libempathy/empathy-debugger.c @@ -0,0 +1,270 @@ +/* + * Telepathy debug interface implementation + * Copyright (C) 2009 Collabora Ltd. + * + * 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 "empathy-debugger.h" +#include "config.h" + +#include <telepathy-glib/dbus.h> + +#include "extensions/extensions.h" + +static EmpathyDebugger *singleton = NULL; + +static void +debug_iface_init (gpointer g_iface, gpointer iface_data); + +G_DEFINE_TYPE_WITH_CODE (EmpathyDebugger, empathy_debugger, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init); + G_IMPLEMENT_INTERFACE (EMP_TYPE_SVC_DEBUG, debug_iface_init)); + +/* properties */ +enum +{ + PROP_ENABLED = 1, + NUM_PROPERTIES +}; + +static EmpDebugLevel +log_level_flags_to_debug_level (GLogLevelFlags level) +{ + if (level & G_LOG_LEVEL_ERROR) + return EMP_DEBUG_LEVEL_ERROR; + else if (level & G_LOG_LEVEL_CRITICAL) + return EMP_DEBUG_LEVEL_CRITICAL; + else if (level & G_LOG_LEVEL_WARNING) + return EMP_DEBUG_LEVEL_WARNING; + else if (level & G_LOG_LEVEL_MESSAGE) + return EMP_DEBUG_LEVEL_MESSAGE; + else if (level & G_LOG_LEVEL_INFO) + return EMP_DEBUG_LEVEL_INFO; + else if (level & G_LOG_LEVEL_DEBUG) + return EMP_DEBUG_LEVEL_DEBUG; + else + /* Fall back to DEBUG if all else fails */ + return EMP_DEBUG_LEVEL_DEBUG; +} + +static EmpathyDebugMessage * +debug_message_new (GTimeVal *timestamp, + const gchar *domain, + GLogLevelFlags level, + const gchar *string) +{ + EmpathyDebugMessage *msg; + + msg = g_slice_new0 (EmpathyDebugMessage); + msg->timestamp = timestamp->tv_sec + timestamp->tv_usec / 1e6; + msg->domain = g_strdup (domain); + msg->level = log_level_flags_to_debug_level (level); + msg->string = g_strdup (string); + return msg; +} + +static void +debug_message_free (EmpathyDebugMessage *msg) +{ + g_free (msg->domain); + g_free (msg->string); + g_slice_free (EmpathyDebugMessage, msg); +} + +static void +empathy_debugger_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyDebugger *self = EMPATHY_DEBUGGER (object); + + switch (property_id) + { + case PROP_ENABLED: + g_value_set_boolean (value, self->enabled); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_debugger_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyDebugger *self = EMPATHY_DEBUGGER (object); + + switch (property_id) + { + case PROP_ENABLED: + self->enabled = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_debugger_finalize (GObject *object) +{ + EmpathyDebugger *self = EMPATHY_DEBUGGER (object); + + g_queue_foreach (self->messages, (GFunc) debug_message_free, NULL); + g_queue_free (self->messages); + self->messages = NULL; + + G_OBJECT_CLASS (empathy_debugger_parent_class)->finalize (object); +} + +static void +empathy_debugger_class_init (EmpathyDebuggerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + static TpDBusPropertiesMixinPropImpl debug_props[] = { + { "Enabled", "enabled", "enabled" }, + { NULL } + }; + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { EMP_IFACE_DEBUG, + tp_dbus_properties_mixin_getter_gobject_properties, + tp_dbus_properties_mixin_setter_gobject_properties, + debug_props, + }, + { NULL } + }; + + object_class->get_property = empathy_debugger_get_property; + object_class->set_property = empathy_debugger_set_property; + object_class->finalize = empathy_debugger_finalize; + + g_object_class_install_property (object_class, PROP_ENABLED, + g_param_spec_boolean ("enabled", "Enabled?", + "True if the new-debug-message signal is enabled.", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + klass->dbus_props_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (EmpathyDebuggerClass, dbus_props_class)); +} + +static void +get_messages (EmpSvcDebug *self, + DBusGMethodInvocation *context) +{ + EmpathyDebugger *dbg = EMPATHY_DEBUGGER (self); + GPtrArray *messages; + static GType struct_type = 0; + GList *i; + guint j; + + if (G_UNLIKELY (struct_type == 0)) + { + struct_type = dbus_g_type_get_struct ( + "GValueArray", G_TYPE_DOUBLE, G_TYPE_STRING, G_TYPE_UINT, + G_TYPE_STRING, G_TYPE_INVALID); + } + + messages = g_ptr_array_sized_new (g_queue_get_length (dbg->messages)); + + for (i = dbg->messages->head; i; i = i->next) + { + GValue gvalue = { 0 }; + EmpathyDebugMessage *message = (EmpathyDebugMessage *) i->data; + + g_value_init (&gvalue, struct_type); + g_value_take_boxed (&gvalue, + dbus_g_type_specialized_construct (struct_type)); + dbus_g_type_struct_set (&gvalue, + 0, message->timestamp, + 1, message->domain, + 2, message->level, + 3, message->string, + G_MAXUINT); + g_ptr_array_add (messages, g_value_get_boxed (&gvalue)); + } + + emp_svc_debug_return_from_get_messages (context, messages); + + for (j = 0; j < messages->len; j++) + g_boxed_free (struct_type, messages->pdata[j]); + + g_ptr_array_free (messages, TRUE); +} + +static void +debug_iface_init (gpointer g_iface, + gpointer iface_data) +{ + EmpSvcDebugClass *klass = (EmpSvcDebugClass *) g_iface; + + emp_svc_debug_implement_get_messages (klass, get_messages); +} + +static void +empathy_debugger_init (EmpathyDebugger *self) +{ + self->messages = g_queue_new (); +} + +EmpathyDebugger * +empathy_debugger_get_singleton (void) +{ + if (G_UNLIKELY (singleton == NULL)) + { + DBusGConnection *bus; + + singleton = g_object_new (EMPATHY_TYPE_DEBUGGER, NULL); + bus = tp_get_bus (); + dbus_g_connection_register_g_object (bus, + "/org/freedesktop/Telepathy/debug", (GObject *) singleton); + } + + return singleton; +} + +void +empathy_debugger_add_message (EmpathyDebugger *self, + GTimeVal *timestamp, + const gchar *domain, + GLogLevelFlags level, + const gchar *string) +{ + EmpathyDebugMessage *new_msg; + + if (g_queue_get_length (self->messages) >= DEBUG_MESSAGE_LIMIT) + { + EmpathyDebugMessage *old_head = + (EmpathyDebugMessage *) g_queue_pop_head (self->messages); + + debug_message_free (old_head); + } + + new_msg = debug_message_new (timestamp, domain, level, string); + g_queue_push_tail (self->messages, new_msg); + + if (self->enabled) + { + emp_svc_debug_emit_new_debug_message (self, new_msg->timestamp, + domain, new_msg->level, string); + } +} diff --git a/libempathy/empathy-debugger.h b/libempathy/empathy-debugger.h new file mode 100644 index 000000000..f3fdc7070 --- /dev/null +++ b/libempathy/empathy-debugger.h @@ -0,0 +1,88 @@ +/* + * header for Telepathy debug interface implementation + * Copyright (C) 2009 Collabora Ltd. + * + * 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 + */ + +#ifndef _EMPATHY_DEBUGGER +#define _EMPATHY_DEBUGGER + +#include <glib-object.h> + +#include <telepathy-glib/properties-mixin.h> +#include <telepathy-glib/dbus-properties-mixin.h> + +#include "extensions/extensions.h" + +G_BEGIN_DECLS + +#define EMPATHY_TYPE_DEBUGGER empathy_debugger_get_type() + +#define EMPATHY_DEBUGGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_DEBUGGER, EmpathyDebugger)) + +#define EMPATHY_DEBUGGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_DEBUGGER, EmpathyDebuggerClass)) + +#define EMPATHY_IS_DEBUGGER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_DEBUGGER)) + +#define EMPATHY_IS_DEBUGGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_DEBUGGER)) + +#define EMPATHY_DEBUGGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_DEBUGGER, EmpathyDebuggerClass)) + +/* On the basis that messages are around 60 bytes on average, and that 50kb is + * a reasonable maximum size for a frame buffer. + */ + +#define DEBUG_MESSAGE_LIMIT 800 + +typedef struct { + gdouble timestamp; + gchar *domain; + EmpDebugLevel level; + gchar *string; +} EmpathyDebugMessage; + +typedef struct { + GObject parent; + + gboolean enabled; + GQueue *messages; +} EmpathyDebugger; + +typedef struct { + GObjectClass parent_class; + TpDBusPropertiesMixinClass dbus_props_class; +} EmpathyDebuggerClass; + +GType empathy_debugger_get_type (void); + +EmpathyDebugger * +empathy_debugger_get_singleton (void); + +void +empathy_debugger_add_message (EmpathyDebugger *self, + GTimeVal *timestamp, + const gchar *domain, + GLogLevelFlags level, + const gchar *string); + +G_END_DECLS + +#endif /* _EMPATHY_DEBUGGER */ diff --git a/libempathy/empathy-dispatcher.c b/libempathy/empathy-dispatcher.c index f46d15f80..b51df95fa 100644 --- a/libempathy/empathy-dispatcher.c +++ b/libempathy/empathy-dispatcher.c @@ -112,7 +112,16 @@ typedef struct GHashTable *dispatched_channels; /* ObjectPath -> EmpathyDispatchOperations */ GHashTable *dispatching_channels; - /* ObjectPath -> EmpathyDispatchOperations */ + + /* ObjectPath -> EmpathyDispatchOperations + * + * This holds channels which were announced with NewChannel while we have an + * outstanding channel request for a channel of this type. On the Requests + * interface, CreateChannel and EnsureChannel are guaranteed by the spec to + * return before NewChannels is emitted, but there was no guarantee of the + * ordering of RequestChannel vs. NewChannel. So if necessary, channels are + * held in limbo here until we know whether they were requested. + */ GHashTable *outstanding_channels; /* List of DispatcherRequestData */ GList *outstanding_requests; @@ -523,8 +532,8 @@ dispatcher_flush_outstanding_operations (EmpathyDispatcher *self, if (dispatcher_operation_can_start (self, operation, cd)) { - dispatcher_start_dispatching (dispatcher, operation, cd); g_hash_table_iter_remove (&iter); + dispatcher_start_dispatching (dispatcher, operation, cd); } } } diff --git a/libempathy/empathy-ft-handler.c b/libempathy/empathy-ft-handler.c index ba81fd4c7..d24467b24 100644 --- a/libempathy/empathy-ft-handler.c +++ b/libempathy/empathy-ft-handler.c @@ -1149,9 +1149,25 @@ ft_handler_gfile_ready_cb (GObject *source, if (error != NULL) goto out; + if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR) + { + error = g_error_new_literal (EMPATHY_FT_ERROR_QUARK, + EMPATHY_FT_ERROR_INVALID_SOURCE_FILE, + _("The selected file is not a regular file")); + goto out; + } + + priv->total_bytes = g_file_info_get_size (info); + if (priv->total_bytes == 0) + { + error = g_error_new_literal (EMPATHY_FT_ERROR_QUARK, + EMPATHY_FT_ERROR_EMPTY_SOURCE_FILE, + _("The selected file is empty")); + goto out; + } + priv->content_type = g_strdup (g_file_info_get_content_type (info)); priv->filename = g_strdup (g_file_info_get_display_name (info)); - priv->total_bytes = g_file_info_get_size (info); g_file_info_get_modification_time (info, &mtime); priv->mtime = mtime.tv_sec; priv->transferred_bytes = 0; @@ -1303,6 +1319,7 @@ empathy_ft_handler_new_outgoing (EmpathyContact *contact, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," + G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, NULL, (GAsyncReadyCallback) ft_handler_gfile_ready_cb, data); diff --git a/libempathy/empathy-idle.c b/libempathy/empathy-idle.c index 92ab9f39f..2ed1440fc 100644 --- a/libempathy/empathy-idle.c +++ b/libempathy/empathy-idle.c @@ -68,6 +68,14 @@ typedef enum { NM_STATE_DISCONNECTED } NMState; +typedef enum { + SESSION_STATUS_AVAILABLE, + SESSION_STATUS_INVISIBLE, + SESSION_STATUS_BUSY, + SESSION_STATUS_IDLE, + SESSION_STATUS_UNKNOWN +} SessionStatus; + enum { PROP_0, PROP_STATE, @@ -91,6 +99,10 @@ idle_presence_changed_cb (MissionControl *mc, priv = GET_PRIV (idle); + if (state == TP_CONNECTION_PRESENCE_TYPE_UNSET) + /* Assume our presence is offline if MC reports UNSET */ + state = TP_CONNECTION_PRESENCE_TYPE_OFFLINE; + DEBUG ("Presence changed to '%s' (%d)", status, state); g_free (priv->status); @@ -147,14 +159,17 @@ idle_ext_away_start (EmpathyIdle *idle) } static void -idle_session_idle_changed_cb (DBusGProxy *gs_proxy, - gboolean is_idle, - EmpathyIdle *idle) +idle_session_status_changed_cb (DBusGProxy *gs_proxy, + SessionStatus status, + EmpathyIdle *idle) { EmpathyIdlePriv *priv; + gboolean is_idle; priv = GET_PRIV (idle); + is_idle = (status == SESSION_STATUS_IDLE); + DEBUG ("Session idle state changed, %s -> %s", priv->is_idle ? "yes" : "no", is_idle ? "yes" : "no"); @@ -465,7 +480,10 @@ empathy_idle_init (EmpathyIdle *idle) if (error) { DEBUG ("Error getting actual presence: %s", error->message); - priv->state = TP_CONNECTION_PRESENCE_TYPE_UNSET; + /* Fallback to OFFLINE as that's what mission_control_get_presence_actual + does. This also ensure to always display the status icon (there is no + unset presence icon). */ + priv->state = TP_CONNECTION_PRESENCE_TYPE_OFFLINE; g_clear_error (&error); } priv->status = mission_control_get_presence_message_actual (priv->mc, &error); @@ -485,15 +503,14 @@ empathy_idle_init (EmpathyIdle *idle) idle, NULL); priv->gs_proxy = dbus_g_proxy_new_for_name (tp_get_bus (), - "org.gnome.ScreenSaver", - "/org/gnome/ScreenSaver", - "org.gnome.ScreenSaver"); + "org.gnome.SessionManager", + "/org/gnome/SessionManager/Presence", + "org.gnome.SessionManager.Presence"); if (priv->gs_proxy) { - dbus_g_proxy_add_signal (priv->gs_proxy, "SessionIdleChanged", - G_TYPE_BOOLEAN, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->gs_proxy, "SessionIdleChanged", - G_CALLBACK (idle_session_idle_changed_cb), + dbus_g_proxy_add_signal (priv->gs_proxy, "StatusChanged", + G_TYPE_UINT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->gs_proxy, "StatusChanged", + G_CALLBACK (idle_session_status_changed_cb), idle, NULL); } else { DEBUG ("Failed to get gs proxy"); @@ -726,7 +743,7 @@ empathy_idle_set_use_nm (EmpathyIdle *idle, g_clear_error (&error); nm_status = NM_STATE_ASLEEP; } - + idle_nm_state_change_cb (priv->nm_proxy, nm_status, idle); } else { priv->nm_connected = TRUE; diff --git a/libempathy/empathy-status-presets.c b/libempathy/empathy-status-presets.c index 9f9a2030b..135212cc5 100644 --- a/libempathy/empathy-status-presets.c +++ b/libempathy/empathy-status-presets.c @@ -131,16 +131,17 @@ status_presets_file_parse (const gchar *filename) if (state_str) { state = empathy_presence_from_str (state_str); - - if (is_default) { - DEBUG ("Default status preset state is:" - " '%s', status:'%s'", state_str, - status); - - status_presets_set_default (state, status); - } else { - preset = status_preset_new (state, status); - presets = g_list_append (presets, preset); + if (empathy_status_presets_is_valid (state)) { + if (is_default) { + DEBUG ("Default status preset state is:" + " '%s', status:'%s'", state_str, + status); + + status_presets_set_default (state, status); + } else { + preset = status_preset_new (state, status); + presets = g_list_append (presets, preset); + } } } @@ -405,3 +406,31 @@ empathy_status_presets_clear_default (void) status_presets_file_save (); } + +/** + * empathy_status_presets_is_valid: + * @state: a #TpConnectionPresenceType + * + * Check if a presence type can be used as a preset. + * + * Returns: %TRUE if the presence type can be used as a preset. + */ +gboolean +empathy_status_presets_is_valid (TpConnectionPresenceType state) +{ + switch (state) { + case TP_CONNECTION_PRESENCE_TYPE_UNSET: + case TP_CONNECTION_PRESENCE_TYPE_OFFLINE: + case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN: + case TP_CONNECTION_PRESENCE_TYPE_ERROR: + return FALSE; + + case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE: + case TP_CONNECTION_PRESENCE_TYPE_AWAY: + case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY: + case TP_CONNECTION_PRESENCE_TYPE_HIDDEN: + case TP_CONNECTION_PRESENCE_TYPE_BUSY: + return TRUE; + } + return FALSE; +} diff --git a/libempathy/empathy-status-presets.h b/libempathy/empathy-status-presets.h index 335dbcfcb..331c630d5 100644 --- a/libempathy/empathy-status-presets.h +++ b/libempathy/empathy-status-presets.h @@ -40,6 +40,7 @@ const gchar * empathy_status_presets_get_default_status (void); void empathy_status_presets_set_default (TpConnectionPresenceType state, const gchar *status); void empathy_status_presets_clear_default (void); +gboolean empathy_status_presets_is_valid (TpConnectionPresenceType state); G_END_DECLS diff --git a/libempathy/empathy-time.c b/libempathy/empathy-time.c index 64350404c..19397e7a9 100644 --- a/libempathy/empathy-time.c +++ b/libempathy/empathy-time.c @@ -42,7 +42,7 @@ empathy_time_get_local_time (struct tm *tm) { const gchar *timezone; time_t t; - + timezone = g_getenv ("TZ"); g_setenv ("TZ", "", TRUE); @@ -152,6 +152,11 @@ empathy_time_to_string_relative (time_t then) return g_strdup_printf (ngettext ("%d day ago", "%d days ago", seconds), seconds); } + else if (seconds < (60 * 60 * 24 * 30)) { + seconds /= 60 * 60 * 24 * 7; + return g_strdup_printf (ngettext ("%d week ago", + "%d weeks ago", seconds), seconds); + } else { seconds /= 60 * 60 * 24 * 30; return g_strdup_printf (ngettext ("%d month ago", diff --git a/libempathy/empathy-tp-call.c b/libempathy/empathy-tp-call.c index 2971e0ffc..eb70c1a87 100644 --- a/libempathy/empathy-tp-call.c +++ b/libempathy/empathy-tp-call.c @@ -672,3 +672,40 @@ empathy_tp_call_has_dtmf (EmpathyTpCall *call) TP_IFACE_QUARK_CHANNEL_INTERFACE_DTMF); } +/** + * empathy_tp_call_is_receiving_video: + * @call: the call + * + * Indicates if the call is receiving video or not. + * + * Returns: %TRUE if the call is currently receiving video, %FALSE otherwise. + */ +gboolean +empathy_tp_call_is_receiving_video (EmpathyTpCall *call) +{ + EmpathyTpCallPriv *priv = GET_PRIV (call); + + g_return_val_if_fail (EMPATHY_IS_TP_CALL (call), FALSE); + + return priv->video->direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE ? + TRUE : FALSE; +} + +/** + * empathy_tp_call_is_sending_video: + * @call: the call + * + * Indicates if the call is sending video or not. + * + * Returns: %TRUE if the call is currently sending video, %FALSE otherwise. + */ +gboolean +empathy_tp_call_is_sending_video (EmpathyTpCall *call) +{ + EmpathyTpCallPriv *priv = GET_PRIV (call); + + g_return_val_if_fail (EMPATHY_IS_TP_CALL (call), FALSE); + + return priv->video->direction & TP_MEDIA_STREAM_DIRECTION_SEND ? + TRUE : FALSE; +} diff --git a/libempathy/empathy-tp-call.h b/libempathy/empathy-tp-call.h index 406ed1c3f..a00fe3e40 100644 --- a/libempathy/empathy-tp-call.h +++ b/libempathy/empathy-tp-call.h @@ -85,6 +85,8 @@ void empathy_tp_call_request_video_stream_direction (EmpathyTpCall *call, void empathy_tp_call_start_tone (EmpathyTpCall *call, TpDTMFEvent event); void empathy_tp_call_stop_tone (EmpathyTpCall *call); gboolean empathy_tp_call_has_dtmf (EmpathyTpCall *call); +gboolean empathy_tp_call_is_receiving_video (EmpathyTpCall *call); +gboolean empathy_tp_call_is_sending_video (EmpathyTpCall *call); G_END_DECLS diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c index 794e3e3b7..ac61392e0 100644 --- a/libempathy/empathy-tp-chat.c +++ b/libempathy/empathy-tp-chat.c @@ -993,7 +993,7 @@ tp_chat_constructor (GType type, /* Get initial member contacts */ members = tp_channel_group_get_members (priv->channel); - handles = tp_intset_to_array (members); + handles = tp_intset_to_array (members); empathy_tp_contact_factory_get_from_handles (priv->factory, handles->len, (TpHandle *) handles->data, tp_chat_got_added_contacts_cb, NULL, NULL, chat); diff --git a/libempathy/empathy-tp-contact-list.c b/libempathy/empathy-tp-contact-list.c index 58cb89cbe..cdb0431c4 100644 --- a/libempathy/empathy-tp-contact-list.c +++ b/libempathy/empathy-tp-contact-list.c @@ -205,7 +205,7 @@ tp_contact_list_group_members_changed_cb (TpChannel *channel, g_signal_emit_by_name (list, "groups-changed", contact, group_name, TRUE); - } + } for (i = 0; i < removed->len; i++) { EmpathyContact *contact; @@ -224,7 +224,7 @@ tp_contact_list_group_members_changed_cb (TpChannel *channel, g_signal_emit_by_name (list, "groups-changed", contact, group_name, FALSE); - } + } } static void diff --git a/libempathy/empathy-tp-file.c b/libempathy/empathy-tp-file.c index 3a5826868..e60b2999d 100644 --- a/libempathy/empathy-tp-file.c +++ b/libempathy/empathy-tp-file.c @@ -26,6 +26,7 @@ #include <string.h> #include <unistd.h> #include <errno.h> +#include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> @@ -36,6 +37,7 @@ #include <gio/gunixinputstream.h> #include <gio/gunixoutputstream.h> +#include <telepathy-glib/gtypes.h> #include <telepathy-glib/proxy-subclass.h> #include <telepathy-glib/util.h> @@ -71,11 +73,14 @@ typedef struct { /* org.freedesktop.Telepathy.Channel.Type.FileTransfer D-Bus properties */ TpFileTransferState state; TpFileTransferStateChangeReason state_change_reason; + TpSocketAddressType socket_address_type; + TpSocketAccessControl socket_access_control; /* transfer properties */ gboolean incoming; time_t start_time; - GArray *unix_socket_path; + GArray *socket_address; + guint port; guint64 offset; /* GCancellable we're passed when offering/accepting the transfer */ @@ -124,6 +129,54 @@ tp_file_get_state_cb (TpProxy *proxy, } static void +tp_file_get_available_socket_types_cb (TpProxy *proxy, + const GValue *value, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyTpFilePriv *priv = GET_PRIV (weak_object); + GHashTable *socket_types; + GArray *access_controls; + + if (error != NULL || + !G_VALUE_HOLDS (value, TP_HASH_TYPE_SUPPORTED_SOCKET_MAP)) + { + /* set a default value */ + priv->socket_address_type = TP_SOCKET_ADDRESS_TYPE_UNIX; + priv->socket_access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; + goto out; + } + + socket_types = g_value_get_boxed (value); + + /* here UNIX is preferred to IPV4 */ + if ((access_controls = g_hash_table_lookup (socket_types, + GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_UNIX))) != NULL) + { + priv->socket_address_type = TP_SOCKET_ADDRESS_TYPE_UNIX; + priv->socket_access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; + goto out; + } + + if ((access_controls = g_hash_table_lookup (socket_types, + GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_IPV4))) != NULL) + { + priv->socket_address_type = TP_SOCKET_ADDRESS_TYPE_IPV4; + + /* TODO: we should prefer PORT over LOCALHOST when the CM will + * support it. + */ + + priv->socket_access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; + } + +out: + DEBUG ("Socket address type: %u, access control %u", + priv->socket_address_type, priv->socket_access_control); +} + +static void tp_file_invalidated_cb (TpProxy *proxy, guint domain, gint code, @@ -206,12 +259,35 @@ splice_stream_ready_cb (GObject *source, static void tp_file_start_transfer (EmpathyTpFile *tp_file) { - gint fd; - struct sockaddr_un addr; + gint fd, domain, res = 0; GError *error = NULL; + struct sockaddr *my_addr = NULL; + size_t my_size = 0; EmpathyTpFilePriv *priv = GET_PRIV (tp_file); - fd = socket (PF_UNIX, SOCK_STREAM, 0); + if (priv->socket_address_type == TP_SOCKET_ADDRESS_TYPE_UNIX) + { + domain = AF_UNIX; + } + else if (priv->socket_address_type == TP_SOCKET_ADDRESS_TYPE_IPV4) + { + domain = AF_INET; + } + else + { + error = g_error_new_literal (EMPATHY_FT_ERROR_QUARK, + EMPATHY_FT_ERROR_NOT_SUPPORTED, _("Socket type not supported")); + + DEBUG ("Socket not supported, closing channel"); + + ft_operation_close_with_error (tp_file, error); + g_clear_error (&error); + + return; + } + + fd = socket (domain, SOCK_STREAM, 0); + if (fd < 0) { int code = errno; @@ -227,12 +303,34 @@ tp_file_start_transfer (EmpathyTpFile *tp_file) return; } - memset (&addr, 0, sizeof (addr)); - addr.sun_family = AF_UNIX; - strncpy (addr.sun_path, priv->unix_socket_path->data, - priv->unix_socket_path->len); + if (priv->socket_address_type == TP_SOCKET_ADDRESS_TYPE_UNIX) + { + struct sockaddr_un addr; + + memset (&addr, 0, sizeof (addr)); + addr.sun_family = domain; + strncpy (addr.sun_path, priv->socket_address->data, + priv->socket_address->len); + + my_addr = (struct sockaddr *) &addr; + my_size = sizeof (addr); + } + else if (priv->socket_address_type == TP_SOCKET_ADDRESS_TYPE_IPV4) + { + struct sockaddr_in addr; + + memset (&addr, 0, sizeof (addr)); + addr.sin_family = domain; + inet_pton (AF_INET, priv->socket_address->data, &addr.sin_addr); + addr.sin_port = htons (priv->port); + + my_addr = (struct sockaddr *) &addr; + my_size = sizeof (addr); + } + + res = connect (fd, my_addr, my_size); - if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0) + if (res < 0) { int code = errno; @@ -354,7 +452,7 @@ tp_file_state_changed_cb (TpChannel *proxy, * data transfer but are just an observer for the channel. */ if (state == TP_FILE_TRANSFER_STATE_OPEN && - priv->unix_socket_path != NULL) + priv->socket_address != NULL) tp_file_start_transfer (EMPATHY_TP_FILE (weak_object)); if (state == TP_FILE_TRANSFER_STATE_COMPLETED) @@ -407,13 +505,14 @@ ft_operation_provide_or_accept_file_cb (TpChannel *proxy, * report the method error. */ g_clear_error (&myerr); - myerr = g_error_copy (error); } + + myerr = g_error_copy (error); } if (myerr != NULL) { - DEBUG ("Error: %s", error->message); + DEBUG ("Error: %s", myerr->message); ft_operation_close_with_error (tp_file, myerr); g_clear_error (&myerr); return; @@ -421,7 +520,7 @@ ft_operation_provide_or_accept_file_cb (TpChannel *proxy, if (G_VALUE_TYPE (address) == DBUS_TYPE_G_UCHAR_ARRAY) { - priv->unix_socket_path = g_value_dup_boxed (address); + priv->socket_address = g_value_dup_boxed (address); } else if (G_VALUE_TYPE (address) == G_TYPE_STRING) { @@ -430,12 +529,32 @@ ft_operation_provide_or_accept_file_cb (TpChannel *proxy, const gchar *path; path = g_value_get_string (address); - priv->unix_socket_path = g_array_sized_new (TRUE, FALSE, sizeof (gchar), - strlen (path)); - g_array_insert_vals (priv->unix_socket_path, 0, path, strlen (path)); + priv->socket_address = g_array_sized_new (TRUE, FALSE, sizeof (gchar), + strlen (path)); + g_array_insert_vals (priv->socket_address, 0, path, strlen (path)); + } + else if (G_VALUE_TYPE (address) == TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4) + { + GValueArray *val_array; + GValue *v; + const char *addr; + + val_array = g_value_get_boxed (address); + + /* IPV4 address */ + v = g_value_array_get_nth (val_array, 0); + addr = g_value_get_string (v); + priv->socket_address = g_array_sized_new (TRUE, FALSE, sizeof (gchar), + strlen (addr)); + g_array_insert_vals (priv->socket_address, 0, addr, strlen (addr)); + + /* port number */ + v = g_value_array_get_nth (val_array, 1); + priv->port = g_value_get_uint (v); } - DEBUG ("Got unix socket path: %s", priv->unix_socket_path->data); + DEBUG ("Got socket address: %s, port (not zero if IPV4): %d", + priv->socket_address->data, priv->port); /* if the channel is already open, start the transfer now, otherwise, * wait for the state change signal. @@ -445,6 +564,18 @@ ft_operation_provide_or_accept_file_cb (TpChannel *proxy, } static void +initialize_empty_ac_variant (TpSocketAccessControl ac, + GValue *val) +{ + /* TODO: we will add more types here once we support PORT access control. */ + if (ac == TP_SOCKET_ACCESS_CONTROL_LOCALHOST) + { + g_value_init (val, G_TYPE_STRING); + g_value_set_static_string (val, ""); + } +} + +static void file_read_async_cb (GObject *source, GAsyncResult *res, gpointer user_data) @@ -468,12 +599,14 @@ file_read_async_cb (GObject *source, priv->in_stream = G_INPUT_STREAM (in_stream); - g_value_init (¬hing, G_TYPE_STRING); - g_value_set_static_string (¬hing, ""); + /* we don't impose specific interface/port requirements even + * if we're not using UNIX sockets. + */ + initialize_empty_ac_variant (priv->socket_access_control, ¬hing); tp_cli_channel_type_file_transfer_call_provide_file ( priv->channel, -1, - TP_SOCKET_ADDRESS_TYPE_UNIX, TP_SOCKET_ACCESS_CONTROL_LOCALHOST, + priv->socket_address_type, priv->socket_access_control, ¬hing, ft_operation_provide_or_accept_file_cb, NULL, NULL, G_OBJECT (tp_file)); } @@ -503,11 +636,13 @@ file_replace_async_cb (GObject *source, priv->out_stream = G_OUTPUT_STREAM (out_stream); - g_value_init (¬hing, G_TYPE_STRING); - g_value_set_static_string (¬hing, ""); + /* we don't impose specific interface/port requirements even + * if we're not using UNIX sockets. + */ + initialize_empty_ac_variant (priv->socket_access_control, ¬hing); tp_cli_channel_type_file_transfer_call_accept_file (priv->channel, - -1, TP_SOCKET_ADDRESS_TYPE_UNIX, TP_SOCKET_ACCESS_CONTROL_LOCALHOST, + -1, priv->socket_address_type, priv->socket_access_control, ¬hing, priv->offset, ft_operation_provide_or_accept_file_cb, NULL, NULL, G_OBJECT (tp_file)); } @@ -592,10 +727,10 @@ do_finalize (GObject *object) DEBUG ("%p", object); - if (priv->unix_socket_path != NULL) + if (priv->socket_address != NULL) { - g_array_free (priv->unix_socket_path, TRUE); - priv->unix_socket_path = NULL; + g_array_free (priv->socket_address, TRUE); + priv->socket_address = NULL; } G_OBJECT_CLASS (empathy_tp_file_parent_class)->finalize (object); @@ -667,6 +802,10 @@ do_constructed (GObject *object) -1, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "State", tp_file_get_state_cb, NULL, NULL, object); + tp_cli_dbus_properties_call_get (priv->channel, + -1, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "AvailableSocketTypes", + tp_file_get_available_socket_types_cb, NULL, NULL, object); + priv->state_change_reason = TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE; } diff --git a/libempathy/empathy-tp-file.h b/libempathy/empathy-tp-file.h index 0d7d8efc0..b40b8c364 100644 --- a/libempathy/empathy-tp-file.h +++ b/libempathy/empathy-tp-file.h @@ -50,7 +50,9 @@ typedef enum { EMPATHY_FT_ERROR_HASH_MISMATCH, EMPATHY_FT_ERROR_TP_ERROR, EMPATHY_FT_ERROR_SOCKET, - EMPATHY_FT_ERROR_NOT_SUPPORTED + EMPATHY_FT_ERROR_NOT_SUPPORTED, + EMPATHY_FT_ERROR_INVALID_SOURCE_FILE, + EMPATHY_FT_ERROR_EMPTY_SOURCE_FILE } EmpathyFTErrorEnum; typedef struct _EmpathyTpFile EmpathyTpFile; diff --git a/libempathy/empathy-tp-tube.c b/libempathy/empathy-tp-tube.c deleted file mode 100644 index 7b9b1889e..000000000 --- a/libempathy/empathy-tp-tube.c +++ /dev/null @@ -1,669 +0,0 @@ -/* - * Copyright (C) 2008 Collabora Ltd. - * - * 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 - * - * Authors: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> - * Elliot Fairweather <elliot.fairweather@collabora.co.uk> - */ - -#include <config.h> - -#include <telepathy-glib/connection.h> -#include <telepathy-glib/proxy.h> -#include <telepathy-glib/util.h> -#include <extensions/extensions.h> - -#include "empathy-enum-types.h" -#include "empathy-tp-tube.h" -#include "empathy-utils.h" - -#define DEBUG_FLAG EMPATHY_DEBUG_TP -#include "empathy-debug.h" - -typedef struct { - TpSocketAddressType type; - EmpathyTpTubeAcceptStreamTubeCb *callback; - gpointer user_data; -} EmpathyTpTubeAcceptData; - -static EmpathyTpTubeAcceptData * -new_empathy_tp_tube_accept_data (TpSocketAddressType type, - EmpathyTpTubeAcceptStreamTubeCb *callback, - gpointer user_data) -{ - EmpathyTpTubeAcceptData *r; - - r = g_slice_new0 (EmpathyTpTubeAcceptData); - r->type = type; - r->callback = callback; - r->user_data = user_data; - - return r; -} - -static void -free_empathy_tp_tube_accept_data (gpointer data) -{ - g_slice_free (EmpathyTpTubeAcceptData, data); -} - - -typedef struct { - EmpathyTpTubeReadyCb *callback; - gpointer user_data; - GDestroyNotify destroy; - GObject *weak_object; -} ReadyCbData; - -/** - * SECTION:empathy-tp-tube - * @title:EmpathyTpTube - * @short_description: A wrapper around a Telepathy tube channel - * @include: libempathy/empathy-tp-tube.h - * - * #EmpathyTpTube is a convenient object wrapping a Telepathy tube channel. - */ - -/** - * EmpathyTpTube: - * @parent: parent object - * - * An object wrapping a Telepathy tube channel. - */ - -#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpTube) -typedef struct -{ - TpChannel *channel; - TpTubeChannelState state; - gboolean ready; - GSList *ready_callbacks; -} EmpathyTpTubePriv; - -enum -{ - PROP_0, - PROP_CHANNEL, - PROP_STATE, -}; - -enum -{ - DESTROY, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -G_DEFINE_TYPE (EmpathyTpTube, empathy_tp_tube, G_TYPE_OBJECT) - -static void -tp_tube_state_changed_cb (TpChannel *channel, - TpTubeChannelState state, - gpointer user_data, - GObject *tube) -{ - EmpathyTpTubePriv *priv = GET_PRIV (tube); - - if (!priv->ready) - /* We didn't get the state yet */ - return; - - DEBUG ("Tube state changed"); - - priv->state = state; - g_object_notify (tube, "state"); -} - -static void -tp_tube_invalidated_cb (TpChannel *channel, - GQuark domain, - gint code, - gchar *message, - EmpathyTpTube *tube) -{ - DEBUG ("Channel invalidated: %s", message); - g_signal_emit (tube, signals[DESTROY], 0); -} - -static void -tp_tube_async_cb (TpChannel *channel, - const GError *error, - gpointer user_data, - GObject *tube) -{ - if (error) - DEBUG ("Error %s: %s", (gchar *) user_data, error->message); -} - -static void -tp_tube_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - EmpathyTpTubePriv *priv = GET_PRIV (object); - - switch (prop_id) - { - case PROP_CHANNEL: - priv->channel = g_value_dup_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -tp_tube_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - EmpathyTpTubePriv *priv = GET_PRIV (object); - - switch (prop_id) - { - case PROP_CHANNEL: - g_value_set_object (value, priv->channel); - break; - case PROP_STATE: - g_value_set_uint (value, priv->state); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void weak_object_notify (gpointer data, - GObject *old_object); - -static ReadyCbData * -ready_cb_data_new (EmpathyTpTube *self, - EmpathyTpTubeReadyCb *callback, - gpointer user_data, - GDestroyNotify destroy, - GObject *weak_object) -{ - ReadyCbData *d = g_slice_new0 (ReadyCbData); - d->callback = callback; - d->user_data = user_data; - d->destroy = destroy; - d->weak_object = weak_object; - - if (weak_object != NULL) - g_object_weak_ref (weak_object, weak_object_notify, self); - - return d; -} - -static void -ready_cb_data_free (ReadyCbData *data, - EmpathyTpTube *self) -{ - if (data->destroy != NULL) - data->destroy (data->user_data); - - if (data->weak_object != NULL) - g_object_weak_unref (data->weak_object, - weak_object_notify, self); - - g_slice_free (ReadyCbData, data); -} - -static void -weak_object_notify (gpointer data, - GObject *old_object) -{ - EmpathyTpTube *self = EMPATHY_TP_TUBE (data); - EmpathyTpTubePriv *priv = GET_PRIV (self); - GSList *l, *ln; - - for (l = priv->ready_callbacks ; l != NULL ; l = ln ) - { - ReadyCbData *d = (ReadyCbData *) l->data; - ln = g_slist_next (l); - - if (d->weak_object == old_object) - { - ready_cb_data_free (d, self); - priv->ready_callbacks = g_slist_delete_link (priv->ready_callbacks, - l); - } - } -} - - -static void -tube_is_ready (EmpathyTpTube *self, - const GError *error) -{ - EmpathyTpTubePriv *priv = GET_PRIV (self); - GSList *l; - - priv->ready = TRUE; - - /* tube has to stay alive while we call the callbacks */ - g_object_ref (self); - for (l = priv->ready_callbacks ; l != NULL ; l = g_slist_next (l)) - { - ReadyCbData *data = (ReadyCbData *) l->data; - - data->callback (self, error, data->user_data, data->weak_object); - ready_cb_data_free (data, self); - } - g_object_unref (self); - - g_slist_free (priv->ready_callbacks); - priv->ready_callbacks = NULL; -} - -static void -got_tube_state_cb (TpProxy *proxy, - const GValue *out_value, - const GError *error, - gpointer user_data, - GObject *weak_object) -{ - EmpathyTpTube *self = EMPATHY_TP_TUBE (user_data); - EmpathyTpTubePriv *priv = GET_PRIV (self); - - if (error != NULL) - { - DEBUG ("Error getting State property: %s", error->message); - } - else - { - priv->state = g_value_get_uint (out_value); - g_object_notify (G_OBJECT (self), "state"); - } - - tube_is_ready (self, error); -} - -static GObject * -tp_tube_constructor (GType type, - guint n_props, - GObjectConstructParam *props) -{ - GObject *self; - EmpathyTpTubePriv *priv; - - self = G_OBJECT_CLASS (empathy_tp_tube_parent_class)->constructor ( - type, n_props, props); - priv = GET_PRIV (self); - - g_signal_connect (priv->channel, "invalidated", - G_CALLBACK (tp_tube_invalidated_cb), self); - - priv->ready = FALSE; - - tp_cli_channel_interface_tube_connect_to_tube_channel_state_changed ( - priv->channel, tp_tube_state_changed_cb, NULL, NULL, - self, NULL); - - tp_cli_dbus_properties_call_get (priv->channel, -1, - TP_IFACE_CHANNEL_INTERFACE_TUBE, "State", got_tube_state_cb, - self, NULL, G_OBJECT (self)); - - return self; -} - -static void -tp_tube_finalize (GObject *object) -{ - EmpathyTpTube *self = EMPATHY_TP_TUBE (object); - EmpathyTpTubePriv *priv = GET_PRIV (object); - GSList *l; - - DEBUG ("Finalizing: %p", object); - - if (priv->channel) - { - g_signal_handlers_disconnect_by_func (priv->channel, - tp_tube_invalidated_cb, object); - tp_cli_channel_call_close (priv->channel, -1, tp_tube_async_cb, - "closing tube", NULL, NULL); - g_object_unref (priv->channel); - } - - for (l = priv->ready_callbacks; l != NULL; l = g_slist_next (l)) - { - ReadyCbData *d = (ReadyCbData *) l->data; - - ready_cb_data_free (d, self); - } - - g_slist_free (priv->ready_callbacks); - priv->ready_callbacks = NULL; - - G_OBJECT_CLASS (empathy_tp_tube_parent_class)->finalize (object); -} - -static void -empathy_tp_tube_class_init (EmpathyTpTubeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructor = tp_tube_constructor; - object_class->finalize = tp_tube_finalize; - object_class->set_property = tp_tube_set_property; - object_class->get_property = tp_tube_get_property; - - /** - * EmpathyTpTube:channel: - * - * The #TpChannel wrapped by the tube object. - */ - g_object_class_install_property (object_class, PROP_CHANNEL, - g_param_spec_object ("channel", "channel", "channel", TP_TYPE_CHANNEL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - - /** - * EmpathyTpTube:state: - * - * The state of the tube. - */ - g_object_class_install_property (object_class, PROP_STATE, - g_param_spec_uint ("state", "state", "state", - 0, NUM_TP_TUBE_CHANNEL_STATES, 0, - G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_STRINGS)); - /** - * EmpathyTpTube::destroy: - * @self: the tube object - * - * Emitted when then tube has been invalidated. - */ - signals[DESTROY] = g_signal_new ("destroy", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_type_class_add_private (klass, sizeof (EmpathyTpTubePriv)); -} - -static void -empathy_tp_tube_init (EmpathyTpTube *tube) -{ - EmpathyTpTubePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (tube, - EMPATHY_TYPE_TP_TUBE, EmpathyTpTubePriv); - - tube->priv = priv; -} - -/** - * empathy_tp_tube_new: - * @channel: a #TpChannel - * - * Creates a new #EmpathyTpTube. - * - * Return value: a new #EmpathyTpTube - */ -EmpathyTpTube * -empathy_tp_tube_new (TpChannel *channel) -{ - g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL); - - return g_object_new (EMPATHY_TYPE_TP_TUBE, "channel", channel, NULL); -} - -/** - * empathy_tp_tube_new_stream_tube: - * @contact: the #EmpathyContact to which the tube is offered - * @type: the type of the listening address of the local service. Either - * %TP_SOCKET_ADDRESS_TYPE_IPV4 or %TP_SOCKET_ADDRESS_TYPE_IPV6. - * @hostname: the address of the local service - * @port: the port of the local service - * @service: the service name of the tube - * @parameters: the parameters of the tube - * - * Creates and offers a new #EmpathyTpTube of ChannelType StreamTube. - * - * Return value: a new #EmpathyTpTube - */ -EmpathyTpTube * -empathy_tp_tube_new_stream_tube (EmpathyContact *contact, - TpSocketAddressType type, - const gchar *hostname, - guint port, - const gchar *service, - GHashTable *parameters) -{ - TpConnection *connection; - TpChannel *channel; - gchar *object_path; - GHashTable *params; - GValue *address; - GValue *control_param; - EmpathyTpTube *tube = NULL; - GError *error = NULL; - GHashTable *request; - GHashTable *channel_properties; - GValue *value; - - g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL); - g_return_val_if_fail (hostname != NULL, NULL); - g_return_val_if_fail (service != NULL, NULL); - - connection = empathy_contact_get_connection (contact); - - request = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, - (GDestroyNotify) tp_g_value_slice_free); - - /* org.freedesktop.Telepathy.Channel.ChannelType */ - value = tp_g_value_slice_new (G_TYPE_STRING); - g_value_set_string (value, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE); - g_hash_table_insert (request, TP_IFACE_CHANNEL ".ChannelType", value); - - /* org.freedesktop.Telepathy.Channel.TargetHandleType */ - value = tp_g_value_slice_new (G_TYPE_UINT); - g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); - g_hash_table_insert (request, TP_IFACE_CHANNEL ".TargetHandleType", value); - - /* org.freedesktop.Telepathy.Channel.TargetHandleType */ - value = tp_g_value_slice_new (G_TYPE_UINT); - g_value_set_uint (value, empathy_contact_get_handle (contact)); - g_hash_table_insert (request, TP_IFACE_CHANNEL ".TargetHandle", value); - - /* org.freedesktop.Telepathy.Channel.Type.StreamTube.Service */ - value = tp_g_value_slice_new (G_TYPE_STRING); - g_value_set_string (value, service); - g_hash_table_insert (request, - TP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service", value); - - if (!tp_cli_connection_interface_requests_run_create_channel (connection, -1, - request, &object_path, &channel_properties, &error, NULL)) - { - DEBUG ("Error requesting channel: %s", error->message); - g_clear_error (&error); - g_object_unref (connection); - return NULL; - } - - DEBUG ("Offering a new stream tube"); - - channel = tp_channel_new_from_properties (connection, object_path, - channel_properties, NULL); - - tp_channel_run_until_ready (channel, NULL, NULL); - - #define ADDRESS_TYPE dbus_g_type_get_struct ("GValueArray",\ - G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID) - params = g_hash_table_new (g_str_hash, g_str_equal); - address = tp_g_value_slice_new (ADDRESS_TYPE); - g_value_take_boxed (address, dbus_g_type_specialized_construct (ADDRESS_TYPE)); - dbus_g_type_struct_set (address, 0, hostname, 1, port, G_MAXUINT); - control_param = tp_g_value_slice_new (G_TYPE_STRING); - - if (parameters == NULL) - /* Pass an empty dict as parameters */ - parameters = g_hash_table_new (g_str_hash, g_str_equal); - else - g_hash_table_ref (parameters); - - if (!tp_cli_channel_type_stream_tube_run_offer (channel, -1, type, address, - TP_SOCKET_ACCESS_CONTROL_LOCALHOST, parameters, - &error, NULL)) - { - DEBUG ("Couldn't offer tube: %s", error->message); - g_clear_error (&error); - goto OUT; - } - - DEBUG ("Stream tube offered"); - - tube = empathy_tp_tube_new (channel); - -OUT: - g_object_unref (channel); - g_free (object_path); - g_hash_table_destroy (request); - g_hash_table_destroy (channel_properties); - tp_g_value_slice_free (address); - tp_g_value_slice_free (control_param); - g_object_unref (connection); - g_hash_table_unref (parameters); - - return tube; -} - -static void -tp_tube_accept_stream_cb (TpChannel *channel, - const GValue *address, - const GError *error, - gpointer user_data, - GObject *weak_object) -{ - EmpathyTpTube *tube = EMPATHY_TP_TUBE (weak_object); - EmpathyTpTubeAcceptData *data = (EmpathyTpTubeAcceptData *) user_data; - EmpathyTpTubeAddress eaddress; - - eaddress.type = data->type; - - if (error) - { - DEBUG ("Error accepting tube: %s", error->message); - data->callback (tube, NULL, error, data->user_data); - return; - } - - switch (eaddress.type) - { - case TP_SOCKET_ADDRESS_TYPE_UNIX: - case TP_SOCKET_ADDRESS_TYPE_ABSTRACT_UNIX: - eaddress.a.socket.path = g_value_get_boxed (address); - break; - case TP_SOCKET_ADDRESS_TYPE_IPV4: - case TP_SOCKET_ADDRESS_TYPE_IPV6: - dbus_g_type_struct_get (address, - 0, &eaddress.a.inet.hostname, - 1, &eaddress.a.inet.port, G_MAXUINT); - break; - } - - data->callback (tube, &eaddress, NULL, data->user_data); -} - -/** - * empathy_tp_tube_accept_stream_tube: - * @tube: an #EmpathyTpTube - * @type: the type of address the connection manager should listen on - * @callback: called when the tube has been accepted - * @user_data: arbitrary user-supplied data passed to the callback - * - * Accepts @tube of ChannelType StreamTube and call @callback once it's done. - */ -void -empathy_tp_tube_accept_stream_tube (EmpathyTpTube *tube, - TpSocketAddressType type, - EmpathyTpTubeAcceptStreamTubeCb *callback, - gpointer user_data) -{ - EmpathyTpTubePriv *priv = GET_PRIV (tube); - GValue *control_param; - EmpathyTpTubeAcceptData *data; - - g_return_if_fail (EMPATHY_IS_TP_TUBE (tube)); - - DEBUG ("Accepting stream tube"); - /* FIXME allow other acls */ - control_param = tp_g_value_slice_new (G_TYPE_STRING); - - data = new_empathy_tp_tube_accept_data (type, callback, user_data); - - tp_cli_channel_type_stream_tube_call_accept ( - priv->channel, -1, type, TP_SOCKET_ACCESS_CONTROL_LOCALHOST, - control_param, tp_tube_accept_stream_cb, data, - free_empathy_tp_tube_accept_data, G_OBJECT (tube)); - - tp_g_value_slice_free (control_param); -} - -/** - * EmpathyTpTubeReadyCb: - * @tube: an #EmpathyTpTube - * @error: %NULL on success, or the reason why the tube can't be ready - * @user_data: the @user_data passed to empathy_tp_tube_call_when_ready() - * @weak_object: the @weak_object passed to - * empathy_tp_tube_call_when_ready() - * - * Called as the result of empathy_tp_tube_call_when_ready(). If the - * tube's properties could be retrieved, - * @error is %NULL and @tube is considered to be ready. Otherwise, @error is - * non-%NULL and @tube is not ready. - */ - -/** - * empathy_tp_tube_call_when_ready: - * @tube: an #EmpathyTpTube - * @callback: called when the tube becomes ready - * @user_data: arbitrary user-supplied data passed to the callback - * @destroy: called to destroy @user_data - * @weak_object: object to reference weakly; if it is destroyed, @callback - * will not be called, but @destroy will still be called - * - * If @tube is ready for use, call @callback immediately, then return. - * Otherwise, arrange for @callback to be called when @tube becomes - * ready for use. - */ -void -empathy_tp_tube_call_when_ready (EmpathyTpTube *self, - EmpathyTpTubeReadyCb *callback, - gpointer user_data, - GDestroyNotify destroy, - GObject *weak_object) -{ - EmpathyTpTubePriv *priv = GET_PRIV (self); - - g_return_if_fail (self != NULL); - g_return_if_fail (callback != NULL); - - if (priv->ready) - { - callback (self, NULL, user_data, weak_object); - if (destroy != NULL) - destroy (user_data); - } - else - { - priv->ready_callbacks = g_slist_prepend (priv->ready_callbacks, - ready_cb_data_new (self, callback, user_data, destroy, weak_object)); - } -} diff --git a/libempathy/empathy-tp-tube.h b/libempathy/empathy-tp-tube.h deleted file mode 100644 index 79cffa1a2..000000000 --- a/libempathy/empathy-tp-tube.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2008 Collabora Ltd. - * - * 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 - * - * Authors: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> - * Elliot Fairweather <elliot.fairweather@collabora.co.uk> - */ - -#ifndef __EMPATHY_TP_TUBE_H__ -#define __EMPATHY_TP_TUBE_H__ - -#include <glib-object.h> - -#include <telepathy-glib/channel.h> - -#include "empathy-contact.h" - -G_BEGIN_DECLS - -#define EMPATHY_TYPE_TP_TUBE (empathy_tp_tube_get_type ()) -#define EMPATHY_TP_TUBE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), \ - EMPATHY_TYPE_TP_TUBE, EmpathyTpTube)) -#define EMPATHY_TP_TUBE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ - EMPATHY_TYPE_TP_TUBE, EmpathyTpTubeClass)) -#define EMPATHY_IS_TP_TUBE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), \ - EMPATHY_TYPE_TP_TUBE)) -#define EMPATHY_IS_TP_TUBE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - EMPATHY_TYPE_TP_TUBE)) -#define EMPATHY_TP_TUBE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), \ - EMPATHY_TYPE_TP_TUBE, EmpathyTpTubeClass)) - -typedef struct _EmpathyTpTube EmpathyTpTube; -typedef struct _EmpathyTpTubeClass EmpathyTpTubeClass; - -typedef struct { - TpSocketAddressType type; - union { - struct socket_address_t { - GArray *path; - } socket; - struct inet_address_t { - gchar *hostname; - guint port; - } inet; - } a; -} EmpathyTpTubeAddress; - -struct _EmpathyTpTube { - GObject parent; - gpointer priv; -}; - -struct _EmpathyTpTubeClass { - GObjectClass parent_class; -}; - -GType empathy_tp_tube_get_type (void) G_GNUC_CONST; -EmpathyTpTube *empathy_tp_tube_new (TpChannel *channel); -EmpathyTpTube *empathy_tp_tube_new_stream_tube (EmpathyContact *contact, - TpSocketAddressType type, - const gchar *hostname, - guint port, - const gchar *service, - GHashTable *parameters); - -typedef void (EmpathyTpTubeAcceptStreamTubeCb) (EmpathyTpTube *tube, - const EmpathyTpTubeAddress *address, - const GError *error, - gpointer user_data); - -void empathy_tp_tube_accept_stream_tube (EmpathyTpTube *tube, - TpSocketAddressType type, - EmpathyTpTubeAcceptStreamTubeCb *callback, - gpointer user_data); - -typedef void (EmpathyTpTubeReadyCb) - (EmpathyTpTube *tube, - const GError *error, - gpointer user_data, - GObject *weak_object); - -void empathy_tp_tube_call_when_ready (EmpathyTpTube *tube, - EmpathyTpTubeReadyCb *callback, - gpointer user_data, - GDestroyNotify destroy, - GObject *weak_object); - -G_END_DECLS - -#endif /* __EMPATHY_TP_TUBE_H__ */ diff --git a/libempathy/empathy-tube-handler.c b/libempathy/empathy-tube-handler.c index bbb7e11a6..2b50ec852 100644 --- a/libempathy/empathy-tube-handler.c +++ b/libempathy/empathy-tube-handler.c @@ -31,7 +31,6 @@ #include <extensions/extensions.h> -#include "empathy-tp-tube.h" #include "empathy-tube-handler.h" #define DEBUG_FLAG EMPATHY_DEBUG_OTHER @@ -59,21 +58,10 @@ typedef struct gchar *channel; guint handle_type; guint handle; - EmpathyTpTube *tube; + TpChannel *tube; } IdleData; static void -tube_ready_cb (EmpathyTpTube *tube, - const GError *error, - gpointer user_data, - GObject *weak_object) -{ - IdleData *idle_data = user_data; - - g_signal_emit (idle_data->thandler, signals[NEW_TUBE], 0, tube); -} - -static void tube_ready_destroy_notify (gpointer data) { IdleData *idle_data = data; @@ -100,9 +88,7 @@ channel_ready_cb (TpChannel *channel, return; } - idle_data->tube = empathy_tp_tube_new (channel); - empathy_tp_tube_call_when_ready (idle_data->tube, tube_ready_cb, idle_data, - tube_ready_destroy_notify, NULL); + g_signal_emit (idle_data->thandler, signals[NEW_TUBE], 0, idle_data->tube); g_object_unref (channel); } @@ -183,7 +169,7 @@ empathy_tube_handler_class_init (EmpathyTubeHandlerClass *klass) signals[NEW_TUBE] = g_signal_new ("new-tube", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, EMPATHY_TYPE_TP_TUBE); + G_TYPE_NONE, 1, TP_TYPE_CHANNEL); } static void diff --git a/libempathy/empathy-utils.c b/libempathy/empathy-utils.c index 47746f536..fca7fcb5f 100644 --- a/libempathy/empathy-utils.c +++ b/libempathy/empathy-utils.c @@ -193,7 +193,7 @@ empathy_xml_node_get_child_content (xmlNodePtr node, if (l) { return xmlNodeGetContent (l); } - + return NULL; } @@ -220,10 +220,10 @@ empathy_xml_node_find_child_prop_value (xmlNodePtr node, if (prop && strcmp (prop, prop_value) == 0) { found = l; } - + xmlFree (prop); } - + return found; } |