[Telepathy-commits] [telepathy-gabble/master] Parse the caps stanza for tubes in the tube factory, using the channel manager uinterface

Alban Crequy alban.crequy at collabora.co.uk
Fri Dec 5 09:42:33 PST 2008


---
 src/channel-manager.c       |    4 +-
 src/channel-manager.h       |    5 +-
 src/connection.c            |    6 +-
 src/presence-cache.c        |   77 +++---------
 src/presence-cache.h        |    2 +-
 src/presence.c              |   69 ++---------
 src/presence.h              |    3 -
 src/private-tubes-factory.c |  288 ++++++++++++++++++++++++++++++++-----------
 tests/test-presence.c       |    4 +-
 9 files changed, 255 insertions(+), 203 deletions(-)

diff --git a/src/channel-manager.c b/src/channel-manager.c
index fd6808f..f155485 100644
--- a/src/channel-manager.c
+++ b/src/channel-manager.c
@@ -365,7 +365,7 @@ void gabble_channel_manager_get_contact_capabilities (
 
 gpointer gabble_channel_manager_parse_capabilities (
     GabbleChannelManager *manager,
-    GabbleConnection *conn)
+    LmMessageNode *child)
 {
   GabbleChannelManagerIface *iface = GABBLE_CHANNEL_MANAGER_GET_INTERFACE (
       manager);
@@ -373,7 +373,7 @@ gpointer gabble_channel_manager_parse_capabilities (
 
   if (method != NULL)
     {
-      return method (manager, conn);
+      return method (manager, child);
     }
   /* ... else assume there is not caps for this kind of channels */
   return NULL;
diff --git a/src/channel-manager.h b/src/channel-manager.h
index 7fcff10..fbc7960 100644
--- a/src/channel-manager.h
+++ b/src/channel-manager.h
@@ -24,6 +24,7 @@
 #define GABBLE_CHANNEL_MANAGER_H
 
 #include <glib-object.h>
+#include <loudmouth/loudmouth.h>
 #include <telepathy-glib/handle.h>
 
 #include "exportable-channel.h"
@@ -56,7 +57,7 @@ typedef void (*GabbleChannelManagerGetContactCapsFunc) (
     GPtrArray *arr);
 
 typedef gpointer (*GabbleChannelManagerParseCapsFunc) (
-    GabbleChannelManager *manager, GabbleConnection *conn);
+    GabbleChannelManager *manager, LmMessageNode *children);
 
 typedef void (*GabbleChannelManagerFreeCapsFunc) (
     GabbleChannelManager *manager, gpointer *specific_caps);
@@ -73,7 +74,7 @@ void gabble_channel_manager_get_contact_capabilities (
     GPtrArray *arr);
 
 gpointer gabble_channel_manager_parse_capabilities (
-    GabbleChannelManager *manager, GabbleConnection *conn);
+    GabbleChannelManager *manager, LmMessageNode *children);
 
 void gabble_channel_manager_free_capabilities (GabbleChannelManager *manager,
     gpointer *specific_caps);
diff --git a/src/connection.c b/src/connection.c
index 9c926c9..d5bbec6 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -1927,7 +1927,7 @@ connection_auth_cb (LmConnection *lmconn,
 
   /* set initial capabilities */
   gabble_presence_set_capabilities (conn->self_presence, priv->resource,
-      capabilities_get_initial_caps (), NULL, NULL, NULL, priv->caps_serial++);
+      capabilities_get_initial_caps (), NULL, priv->caps_serial++);
 
   if (!gabble_disco_request_with_timeout (conn->disco, GABBLE_DISCO_TYPE_INFO,
                                           priv->stream_server, NULL,
@@ -2214,7 +2214,7 @@ gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *
     {
       DEBUG ("before != after, changing");
       gabble_presence_set_capabilities (pres, priv->resource, caps, NULL,
-          NULL, NULL, priv->caps_serial++);
+          priv->caps_serial++);
       DEBUG ("set caps: %x", pres->caps);
     }
 
@@ -2961,7 +2961,7 @@ gabble_connection_ensure_capabilities (GabbleConnection *self,
       GError *error = NULL;
 
       gabble_presence_set_capabilities (self->self_presence,
-          priv->resource, new_caps, NULL, NULL, NULL, priv->caps_serial++);
+          priv->resource, new_caps, NULL, priv->caps_serial++);
 
       if (!_gabble_connection_signal_own_presence (self, &error))
         DEBUG ("error sending presence: %s", error->message);
diff --git a/src/presence-cache.c b/src/presence-cache.c
index 4670936..978e9c1 100644
--- a/src/presence-cache.c
+++ b/src/presence-cache.c
@@ -200,8 +200,6 @@ struct _CapabilityInfo
    * received */
   gboolean caps_set;
   GabblePresenceCapabilities caps;
-  GHashTable *stream_tube_caps;
-  GHashTable *dbus_tube_caps;
 
   /* channel factory -> specific caps */
   GHashTable *per_channel_factory_caps;
@@ -237,7 +235,6 @@ capability_info_free (CapabilityInfo *info)
 static guint
 capability_info_recvd (GabblePresenceCache *cache, const gchar *node,
         TpHandle handle, GabblePresenceCapabilities caps,
-        GHashTable *stream_tube_caps, GHashTable *dbus_tube_caps,
         GHashTable *per_channel_factory_caps, guint trust_inc)
 {
   CapabilityInfo *info = capability_info_get (cache, node);
@@ -251,8 +248,6 @@ capability_info_recvd (GabblePresenceCache *cache, const gchar *node,
        */
       tp_intset_clear (info->guys);
       info->caps = caps;
-      info->stream_tube_caps = stream_tube_caps;
-      info->dbus_tube_caps = dbus_tube_caps;
       info->per_channel_factory_caps = per_channel_factory_caps;
       info->trust = 0;
       info->caps_set = TRUE;
@@ -752,15 +747,23 @@ update_specific_caps_helper (gpointer key, gpointer value, gpointer user_data)
   GHashTable *table_out = user_data;
   GabbleChannelManager *manager = GABBLE_CHANNEL_MANAGER (key);
   gpointer out;
-  gabble_channel_manager_copy_capabilities (manager, &out, value);
-  g_hash_table_insert (table_out, key, out);
+
+  out = g_hash_table_lookup (table_out, key);
+  if (out == NULL)
+    {
+      gabble_channel_manager_copy_capabilities (manager, &out, value);
+      g_hash_table_insert (table_out, key, out);
+    }
+  else
+    {
+      gabble_channel_manager_update_capabilities (manager, out, value);
+    }
 }
 
 void
 gabble_presence_cache_update_specific_cache (
-    GHashTable **out, GHashTable *in)
+    GHashTable *out, GHashTable *in)
 {
-  *out = g_hash_table_new (NULL, NULL);
   g_hash_table_foreach (in, update_specific_caps_helper,
       out);
 }
@@ -782,8 +785,6 @@ _caps_disco_cb (GabbleDisco *disco,
   TpHandleRepoIface *contact_repo;
   gchar *full_jid = NULL;
   GabblePresenceCapabilities caps = 0;
-  GHashTable *stream_tube_caps;
-  GHashTable *dbus_tube_caps;
   GHashTable *per_channel_factory_caps;
   guint trust, trust_inc;
   TpHandle handle = 0;
@@ -846,10 +847,6 @@ _caps_disco_cb (GabbleDisco *disco,
       goto OUT;
     }
 
-  stream_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
-      NULL);
-  dbus_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
-      NULL);
   per_channel_factory_caps = g_hash_table_new (NULL, NULL);
 
   /* parsing for Connection.Interface.ContactCapabilities.DRAFT */
@@ -860,7 +857,7 @@ _caps_disco_cb (GabbleDisco *disco,
           g_ptr_array_index (priv->conn->channel_managers, j));
 
       factory_caps = gabble_channel_manager_parse_capabilities
-          (manager, priv->conn);
+          (manager, query_result->children);
       if (factory_caps != NULL)
         g_hash_table_insert (per_channel_factory_caps, manager, factory_caps);
     }
@@ -904,36 +901,13 @@ _caps_disco_cb (GabbleDisco *disco,
           !tp_strdiff (var, NS_OLPC_CURRENT_ACTIVITY "+notify") ||
           !tp_strdiff (var, NS_OLPC_ACTIVITY_PROPS "+notify"))
         caps |= PRESENCE_CAP_OLPC_1;
-      else if (g_str_has_prefix (var, NS_TUBES "/"))
-        {
-          /* http://telepathy.freedesktop.org/xmpp/tubes/$type/$service */
-          var += strlen (NS_TUBES "/");
-          if (g_str_has_prefix (var, "stream/"))
-            {
-              gchar *service;
-              var += strlen ("stream/");
-              service = g_strdup (var);
-              g_hash_table_insert (stream_tube_caps, service, NULL);
-            }
-          else if (g_str_has_prefix (var, "dbus/"))
-            {
-              gchar *service;
-              var += strlen ("dbus/");
-              service = g_strdup (var);
-              g_hash_table_insert (dbus_tube_caps, service, NULL);
-            }
-        }
     }
 
   handle = tp_handle_ensure (contact_repo, jid, NULL, NULL);
   if (handle == 0)
     {
       DEBUG ("Ignoring presence from invalid JID %s", jid);
-      g_hash_table_destroy (stream_tube_caps);
-      g_hash_table_destroy (dbus_tube_caps);
       gabble_presence_cache_free_specific_cache (per_channel_factory_caps);
-      stream_tube_caps = NULL;
-      dbus_tube_caps = NULL;
       per_channel_factory_caps = NULL;
       goto OUT;
     }
@@ -953,11 +927,7 @@ _caps_disco_cb (GabbleDisco *disco,
   if (NULL == waiter_self)
     {
       DEBUG ("Ignoring non requested disco reply");
-      g_hash_table_destroy (stream_tube_caps);
-      g_hash_table_destroy (dbus_tube_caps);
       gabble_presence_cache_free_specific_cache (per_channel_factory_caps);
-      stream_tube_caps = NULL;
-      dbus_tube_caps = NULL;
       per_channel_factory_caps = NULL;
       goto OUT;
     }
@@ -977,8 +947,7 @@ _caps_disco_cb (GabbleDisco *disco,
       if (g_str_equal (waiter_self->ver, computed_hash))
         {
           trust = capability_info_recvd (cache, node, handle, caps,
-              stream_tube_caps, dbus_tube_caps, per_channel_factory_caps,
-              trust_inc);
+              per_channel_factory_caps, trust_inc);
         }
       else
         {
@@ -987,28 +956,20 @@ _caps_disco_cb (GabbleDisco *disco,
               "our hash '%s'.", waiter_self->ver, computed_hash);
           trust = 0;
           bad_hash = TRUE;
-          g_hash_table_destroy (stream_tube_caps);
-          g_hash_table_destroy (dbus_tube_caps);
           gabble_presence_cache_free_specific_cache (per_channel_factory_caps);
-          stream_tube_caps = NULL;
-          dbus_tube_caps = NULL;
           per_channel_factory_caps = NULL;
         }
     }
   else
     {
       trust_inc = 1;
-      trust = capability_info_recvd (cache, node, handle, caps, NULL, NULL,
-          NULL, trust_inc);
+      trust = capability_info_recvd (cache, node, handle, caps, NULL,
+          trust_inc);
 
       /* Do not allow tubes caps if the contact does not observe XEP-0115
        * version 1.5: we don't need to bother being compatible with both version
        * 1.3 and tubes caps */
-      g_hash_table_destroy (stream_tube_caps);
-      g_hash_table_destroy (dbus_tube_caps);
       gabble_presence_cache_free_specific_cache (per_channel_factory_caps);
-      stream_tube_caps = NULL;
-      dbus_tube_caps = NULL;
       per_channel_factory_caps = NULL;
     }
 
@@ -1037,8 +998,7 @@ _caps_disco_cb (GabbleDisco *disco,
                     "%d (save_caps %d)",
                     waiter->handle, handle, jid, caps, save_caps);
                 gabble_presence_set_capabilities (presence, waiter->resource,
-                    caps, stream_tube_caps, dbus_tube_caps,
-                    per_channel_factory_caps, waiter->serial);
+                    caps, per_channel_factory_caps, waiter->serial);
                 DEBUG ("caps for %d (thanks to %d %s) now %d", waiter->handle,
                     handle, jid, presence->caps);
                 g_signal_emit (cache, signals[CAPABILITIES_UPDATE], 0,
@@ -1134,8 +1094,7 @@ _process_caps_uri (GabblePresenceCache *cache,
       if (presence)
         {
           gabble_presence_set_capabilities (presence, resource,
-              info->caps, info->stream_tube_caps, info->dbus_tube_caps,
-              info->per_channel_factory_caps, serial);
+              info->caps, info->per_channel_factory_caps, serial);
           DEBUG ("caps for %d (%s) now %d", handle, from, presence->caps);
         }
       else
diff --git a/src/presence-cache.h b/src/presence-cache.h
index 82ce987..618ab57 100644
--- a/src/presence-cache.h
+++ b/src/presence-cache.h
@@ -88,7 +88,7 @@ void gabble_presence_cache_free_specific_cache (
     GHashTable *per_channel_factory_caps);
 void gabble_presence_cache_copy_specific_cache (GHashTable **out,
     GHashTable *in);
-void gabble_presence_cache_update_specific_cache (GHashTable **out,
+void gabble_presence_cache_update_specific_cache (GHashTable *out,
     GHashTable *in);
 
 G_END_DECLS
diff --git a/src/presence.c b/src/presence.c
index ef6d52c..bd9630f 100644
--- a/src/presence.c
+++ b/src/presence.c
@@ -41,8 +41,6 @@ typedef struct _Resource Resource;
 struct _Resource {
     gchar *name;
     GabblePresenceCapabilities caps;
-    GHashTable *stream_tube_caps;
-    GHashTable *dbus_tube_caps;
     GHashTable *per_channel_factory_caps;
     guint caps_serial;
     GabblePresenceId status;
@@ -62,8 +60,6 @@ _resource_new (gchar *name)
   Resource *new = g_slice_new0 (Resource);
   new->name = name;
   new->caps = PRESENCE_CAP_NONE;
-  new->stream_tube_caps = NULL;
-  new->dbus_tube_caps = NULL;
   new->per_channel_factory_caps = NULL;
   new->status = GABBLE_PRESENCE_OFFLINE;
   new->status_message = NULL;
@@ -79,10 +75,13 @@ _resource_free (Resource *resource)
 {
   g_free (resource->name);
   g_free (resource->status_message);
-  if (resource->stream_tube_caps != NULL)
-    g_hash_table_destroy (resource->stream_tube_caps);
-  if (resource->dbus_tube_caps != NULL)
-    g_hash_table_destroy (resource->dbus_tube_caps);
+  if (resource->per_channel_factory_caps != NULL)
+    {
+      gabble_presence_cache_free_specific_cache
+        (resource->per_channel_factory_caps);
+      resource->per_channel_factory_caps = NULL;
+    }
+  
   g_slice_free (Resource, resource);
 }
 
@@ -96,10 +95,12 @@ gabble_presence_finalize (GObject *object)
   for (i = priv->resources; NULL != i; i = i->next)
     _resource_free (i->data);
 
-  if (presence->stream_tube_caps != NULL)
-    g_hash_table_destroy (presence->stream_tube_caps);
-  if (presence->dbus_tube_caps != NULL)
-    g_hash_table_destroy (presence->dbus_tube_caps);
+  if (presence->per_channel_factory_caps != NULL)
+    {
+      gabble_presence_cache_free_specific_cache
+        (presence->per_channel_factory_caps);
+      presence->per_channel_factory_caps = NULL;
+    }
 
   g_slist_free (priv->resources);
   g_free (presence->nickname);
@@ -198,8 +199,6 @@ void
 gabble_presence_set_capabilities (GabblePresence *presence,
                                   const gchar *resource,
                                   GabblePresenceCapabilities caps,
-                                  GHashTable *stream_tube_caps,
-                                  GHashTable *dbus_tube_caps,
                                   GHashTable *per_channel_factory_caps,
                                   guint serial)
 {
@@ -207,26 +206,12 @@ gabble_presence_set_capabilities (GabblePresence *presence,
   GSList *i;
 
   presence->caps = 0;
-  if (presence->stream_tube_caps != NULL)
-    {
-      g_hash_table_destroy (presence->stream_tube_caps);
-      presence->per_channel_factory_caps = NULL;
-    }
-  if (presence->dbus_tube_caps != NULL)
-    {
-      g_hash_table_destroy (presence->dbus_tube_caps);
-      presence->per_channel_factory_caps = NULL;
-    }
   if (presence->per_channel_factory_caps != NULL)
     {
       gabble_presence_cache_free_specific_cache
         (presence->per_channel_factory_caps);
       presence->per_channel_factory_caps = NULL;
     }
-  presence->stream_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
-      g_free, NULL);
-  presence->dbus_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
-      g_free, NULL);
   presence->per_channel_factory_caps = g_hash_table_new (NULL, NULL);
 
   DEBUG ("about to add caps %u to resource %s with serial %u", caps, resource,
@@ -254,32 +239,12 @@ gabble_presence_set_capabilities (GabblePresence *presence,
               tmp->caps |= caps;
               DEBUG ("resource %s caps now %u", resource, tmp->caps);
 
-              if (tmp->stream_tube_caps != NULL)
-                {
-                  g_hash_table_destroy (tmp->stream_tube_caps);
-                  tmp->stream_tube_caps = NULL;
-                }
-              if (tmp->dbus_tube_caps != NULL)
-                {
-                  g_hash_table_destroy (tmp->dbus_tube_caps);
-                  tmp->dbus_tube_caps = NULL;
-                }
               if (tmp->per_channel_factory_caps != NULL)
                 {
                   gabble_presence_cache_free_specific_cache
                       (tmp->per_channel_factory_caps);
                   tmp->per_channel_factory_caps = NULL;
                 }
-              tmp->stream_tube_caps = g_hash_table_new_full (g_str_hash,
-                  g_str_equal, g_free, NULL);
-              tmp->dbus_tube_caps = g_hash_table_new_full (g_str_hash,
-                  g_str_equal, g_free, NULL);
-              if (stream_tube_caps != NULL)
-                tp_g_hash_table_update (tmp->stream_tube_caps,
-                    stream_tube_caps, g_strdup, NULL);
-              if (dbus_tube_caps != NULL)
-                tp_g_hash_table_update (tmp->dbus_tube_caps,
-                    dbus_tube_caps, g_strdup, NULL);
               if (per_channel_factory_caps != NULL)
                 gabble_presence_cache_copy_specific_cache
                     (&tmp->per_channel_factory_caps, per_channel_factory_caps);
@@ -288,14 +253,6 @@ gabble_presence_set_capabilities (GabblePresence *presence,
 
       presence->caps |= tmp->caps;
 
-      if (tmp->stream_tube_caps != NULL)
-          tp_g_hash_table_update (presence->stream_tube_caps,
-              tmp->stream_tube_caps, g_strdup, NULL);
-
-      if (tmp->dbus_tube_caps != NULL)
-        tp_g_hash_table_update (presence->dbus_tube_caps,
-            tmp->dbus_tube_caps, g_strdup, NULL);
-
       if (tmp->per_channel_factory_caps != NULL)
         gabble_presence_cache_update_specific_cache
             (presence->per_channel_factory_caps,
diff --git a/src/presence.h b/src/presence.h
index 417571e..331b029 100644
--- a/src/presence.h
+++ b/src/presence.h
@@ -56,8 +56,6 @@ typedef struct _GabblePresencePrivate GabblePresencePrivate;
 struct _GabblePresence {
     GObject parent;
     GabblePresenceCapabilities caps;
-    GHashTable *stream_tube_caps;
-    GHashTable *dbus_tube_caps;
     GHashTable *per_channel_factory_caps;
     GabblePresenceId status;
     gchar *status_message;
@@ -83,7 +81,6 @@ gboolean gabble_presence_update (GabblePresence *presence,
 
 void gabble_presence_set_capabilities (GabblePresence *presence,
     const gchar *resource, GabblePresenceCapabilities caps,
-    GHashTable *stream_tube_caps, GHashTable *dbus_tube_caps,
     GHashTable *per_channel_factory_caps, guint serial);
 
 const gchar *gabble_presence_pick_resource_by_caps (GabblePresence *presence,
diff --git a/src/private-tubes-factory.c b/src/private-tubes-factory.c
index 4ba1fca..e60077e 100644
--- a/src/private-tubes-factory.c
+++ b/src/private-tubes-factory.c
@@ -87,6 +87,14 @@ struct _GabblePrivateTubesFactoryPrivate
 
 #define GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE(obj) ((obj)->priv)
 
+typedef struct _TubesCapabilities TubesCapabilities;
+struct _TubesCapabilities
+{
+  GHashTable *stream_tube_caps;
+  GHashTable *dbus_tube_caps;
+};
+
+
 static void
 gabble_private_tubes_factory_init (GabblePrivateTubesFactory *self)
 {
@@ -370,6 +378,9 @@ gabble_private_tubes_factory_get_contact_caps (GabbleChannelManager *manager,
                                                TpHandle handle,
                                                GPtrArray *arr)
 {
+  TubesCapabilities *caps;
+  GHashTable *stream_tube_caps;
+  GHashTable *dbus_tube_caps;
   GHashTable *fixed_properties;
   GValue *channel_type_value;
   GValue *target_handle_type_value;
@@ -390,91 +401,212 @@ gabble_private_tubes_factory_get_contact_caps (GabbleChannelManager *manager,
   if (presence == NULL)
     return;
 
-  if (presence->stream_tube_caps == NULL)
+  if (presence->per_channel_factory_caps == NULL)
     return;
 
-  g_hash_table_iter_init (&tube_caps_iter, presence->stream_tube_caps);
-  while (g_hash_table_iter_next (&tube_caps_iter, &service, &dummy)) 
+  caps = g_hash_table_lookup (presence->per_channel_factory_caps, manager);
+  if (caps == NULL)
+    return;
+
+  stream_tube_caps = caps->stream_tube_caps;
+  dbus_tube_caps = caps->dbus_tube_caps;
+
+  if (stream_tube_caps != NULL)
     {
-      GValue monster = {0, };
-      g_value_init (&monster, GABBLE_STRUCT_TYPE_ENHANCED_CONTACT_CAPABILITY);
-      g_value_take_boxed (&monster,
-          dbus_g_type_specialized_construct (
-            GABBLE_STRUCT_TYPE_ENHANCED_CONTACT_CAPABILITY));
-
-      fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
-          (GDestroyNotify) tp_g_value_slice_free);
-
-      channel_type_value = tp_g_value_slice_new (G_TYPE_STRING);
-      g_value_set_static_string (channel_type_value,
-          GABBLE_IFACE_CHANNEL_TYPE_STREAM_TUBE);
-      g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".ChannelType",
-          channel_type_value);
-
-      target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT);
-      g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT);
-      g_hash_table_insert (fixed_properties,
-          TP_IFACE_CHANNEL ".TargetHandleType", target_handle_type_value);
-
-      target_handle_type_value = tp_g_value_slice_new (G_TYPE_STRING);
-      g_value_set_string (target_handle_type_value, service);
-      g_hash_table_insert (fixed_properties,
-          GABBLE_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service",
-          target_handle_type_value);
-
-      dbus_g_type_struct_set (&monster,
-          0, handle,
-          1, fixed_properties,
-          2, tube_allowed_properties,
-          G_MAXUINT);
-
-      g_hash_table_destroy (fixed_properties);
-
-      g_ptr_array_add (arr, g_value_get_boxed (&monster));
+      g_hash_table_iter_init (&tube_caps_iter, stream_tube_caps);
+      while (g_hash_table_iter_next (&tube_caps_iter, &service, &dummy)) 
+        {
+          GValue monster = {0, };
+          g_value_init (&monster, GABBLE_STRUCT_TYPE_ENHANCED_CONTACT_CAPABILITY);
+          g_value_take_boxed (&monster,
+              dbus_g_type_specialized_construct (
+                GABBLE_STRUCT_TYPE_ENHANCED_CONTACT_CAPABILITY));
+
+          fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+              (GDestroyNotify) tp_g_value_slice_free);
+
+          channel_type_value = tp_g_value_slice_new (G_TYPE_STRING);
+          g_value_set_static_string (channel_type_value,
+              GABBLE_IFACE_CHANNEL_TYPE_STREAM_TUBE);
+          g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".ChannelType",
+              channel_type_value);
+
+          target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT);
+          g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT);
+          g_hash_table_insert (fixed_properties,
+              TP_IFACE_CHANNEL ".TargetHandleType", target_handle_type_value);
+
+          target_handle_type_value = tp_g_value_slice_new (G_TYPE_STRING);
+          g_value_set_string (target_handle_type_value, service);
+          g_hash_table_insert (fixed_properties,
+              GABBLE_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service",
+              target_handle_type_value);
+
+          dbus_g_type_struct_set (&monster,
+              0, handle,
+              1, fixed_properties,
+              2, tube_allowed_properties,
+              G_MAXUINT);
+
+          g_hash_table_destroy (fixed_properties);
+
+          g_ptr_array_add (arr, g_value_get_boxed (&monster));
+        }
     }
 
-  g_hash_table_iter_init (&tube_caps_iter, presence->dbus_tube_caps);
-  while (g_hash_table_iter_next (&tube_caps_iter, &service, &dummy)) 
+  if (dbus_tube_caps != NULL)
     {
-      GValue monster = {0, };
-      g_value_init (&monster, GABBLE_STRUCT_TYPE_ENHANCED_CONTACT_CAPABILITY);
-      g_value_take_boxed (&monster,
-          dbus_g_type_specialized_construct (
-            GABBLE_STRUCT_TYPE_ENHANCED_CONTACT_CAPABILITY));
-
-      fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
-          (GDestroyNotify) tp_g_value_slice_free);
-
-      channel_type_value = tp_g_value_slice_new (G_TYPE_STRING);
-      g_value_set_static_string (channel_type_value,
-          GABBLE_IFACE_CHANNEL_TYPE_DBUS_TUBE);
-      g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".ChannelType",
-          channel_type_value);
-
-      target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT);
-      g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT);
-      g_hash_table_insert (fixed_properties,
-          TP_IFACE_CHANNEL ".TargetHandleType", target_handle_type_value);
-
-      target_handle_type_value = tp_g_value_slice_new (G_TYPE_STRING);
-      g_value_set_string (target_handle_type_value, service);
-      g_hash_table_insert (fixed_properties,
-          GABBLE_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName",
-          target_handle_type_value);
-
-      dbus_g_type_struct_set (&monster,
-          0, handle,
-          1, fixed_properties,
-          2, tube_allowed_properties,
-          G_MAXUINT);
-
-      g_hash_table_destroy (fixed_properties);
-
-      g_ptr_array_add (arr, g_value_get_boxed (&monster));
+      g_hash_table_iter_init (&tube_caps_iter, dbus_tube_caps);
+      while (g_hash_table_iter_next (&tube_caps_iter, &service, &dummy)) 
+        {
+          GValue monster = {0, };
+          g_value_init (&monster, GABBLE_STRUCT_TYPE_ENHANCED_CONTACT_CAPABILITY);
+          g_value_take_boxed (&monster,
+              dbus_g_type_specialized_construct (
+                GABBLE_STRUCT_TYPE_ENHANCED_CONTACT_CAPABILITY));
+
+          fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+              (GDestroyNotify) tp_g_value_slice_free);
+
+          channel_type_value = tp_g_value_slice_new (G_TYPE_STRING);
+          g_value_set_static_string (channel_type_value,
+              GABBLE_IFACE_CHANNEL_TYPE_DBUS_TUBE);
+          g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".ChannelType",
+              channel_type_value);
+
+          target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT);
+          g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT);
+          g_hash_table_insert (fixed_properties,
+              TP_IFACE_CHANNEL ".TargetHandleType", target_handle_type_value);
+
+          target_handle_type_value = tp_g_value_slice_new (G_TYPE_STRING);
+          g_value_set_string (target_handle_type_value, service);
+          g_hash_table_insert (fixed_properties,
+              GABBLE_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName",
+              target_handle_type_value);
+
+          dbus_g_type_struct_set (&monster,
+              0, handle,
+              1, fixed_properties,
+              2, tube_allowed_properties,
+              G_MAXUINT);
+
+          g_hash_table_destroy (fixed_properties);
+
+          g_ptr_array_add (arr, g_value_get_boxed (&monster));
+        }
     }
 }
 
+static gpointer
+gabble_private_tubes_factory_parse_caps (
+    GabbleChannelManager *manager,
+    LmMessageNode *children)
+{
+  LmMessageNode *child;
+  TubesCapabilities *caps;
+
+  caps = g_new0 (TubesCapabilities, 1);
+  caps->stream_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
+      g_free, NULL);
+  caps->dbus_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
+      g_free, NULL);
+
+  for (child = children; NULL != child; child = child->next)
+    {
+      const gchar *var;
+
+      if (0 != strcmp (child->name, "feature"))
+        continue;
 
+      var = lm_message_node_get_attribute (child, "var");
+
+      if (NULL == var)
+        continue;
+
+      if (g_str_has_prefix (var, NS_TUBES "/"))
+        {
+          /* http://telepathy.freedesktop.org/xmpp/tubes/$type/$service */
+          var += strlen (NS_TUBES "/");
+          if (g_str_has_prefix (var, "stream/"))
+            {
+              gchar *service;
+              var += strlen ("stream/");
+              service = g_strdup (var);
+              g_hash_table_insert (caps->stream_tube_caps, service, NULL);
+            }
+          else if (g_str_has_prefix (var, "dbus/"))
+            {
+              gchar *service;
+              var += strlen ("dbus/");
+              service = g_strdup (var);
+              g_hash_table_insert (caps->dbus_tube_caps, service, NULL);
+            }
+        }
+    }
+
+  return caps;
+}
+
+static gpointer
+gabble_private_tubes_factory_free_caps (
+    GabbleChannelManager *manager,
+    gpointer data)
+{
+ TubesCapabilities *caps = data;
+ g_hash_table_destroy (caps->stream_tube_caps);
+ g_hash_table_destroy (caps->dbus_tube_caps);
+ g_free (caps);
+}
+
+static void
+copy_caps_helper (gpointer key, gpointer value, gpointer user_data)
+{
+  GHashTable *out = user_data;
+  gchar *str = key;
+
+  g_hash_table_insert (out, g_strdup (str), NULL);
+}
+
+static void
+gabble_private_tubes_factory_copy_caps (
+    GabbleChannelManager *manager,
+    gpointer *specific_caps_out,
+    gpointer specific_caps_in)
+{
+  TubesCapabilities *caps_in = specific_caps_in;
+  TubesCapabilities *caps_out = g_new0 (TubesCapabilities, 1);
+
+  caps_out->stream_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
+      g_free, NULL);
+  g_hash_table_foreach (caps_in->stream_tube_caps, copy_caps_helper,
+      caps_out->stream_tube_caps);
+
+  caps_out->dbus_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
+      g_free, NULL);
+  g_hash_table_foreach (caps_in->dbus_tube_caps, copy_caps_helper,
+      caps_out->dbus_tube_caps);
+
+  *specific_caps_out = caps_out;
+}
+
+static void
+gabble_private_tubes_factory_update_caps (
+    GabbleChannelManager *manager,
+    gpointer *specific_caps_out,
+    gpointer specific_caps_in)
+{
+  TubesCapabilities *caps_out = specific_caps_out;
+  TubesCapabilities *caps_in = specific_caps_in;
+
+  if (caps_in == NULL)
+    return;
+
+  tp_g_hash_table_update (caps_out->stream_tube_caps,
+      caps_out->stream_tube_caps, g_strdup, NULL);
+  tp_g_hash_table_update (caps_out->dbus_tube_caps,
+      caps_out->dbus_tube_caps, g_strdup, NULL);
+}
 
 struct _ForeachData
 {
@@ -897,6 +1029,12 @@ channel_manager_iface_init (gpointer g_iface,
   GabbleChannelManagerIface *iface = g_iface;
 
   iface->get_contact_caps = gabble_private_tubes_factory_get_contact_caps;
+  iface->parse_caps = gabble_private_tubes_factory_parse_caps;
+  iface->free_caps = gabble_private_tubes_factory_free_caps;
+  iface->copy_caps = gabble_private_tubes_factory_copy_caps;
+  iface->update_caps = gabble_private_tubes_factory_update_caps;
+
+
   iface->foreach_channel = gabble_private_tubes_factory_foreach_channel;
   iface->foreach_channel_class =
       gabble_private_tubes_factory_foreach_channel_class;
diff --git a/tests/test-presence.c b/tests/test-presence.c
index 819e900..115c2c0 100644
--- a/tests/test-presence.c
+++ b/tests/test-presence.c
@@ -109,7 +109,7 @@ int main (int argc, char **argv)
   g_assert (FALSE == gabble_presence_update (presence, "bar",
     GABBLE_PRESENCE_AVAILABLE, "dingoes", -1));
   gabble_presence_set_capabilities (presence, "bar",
-      PRESENCE_CAP_GOOGLE_VOICE, NULL, NULL, NULL, 0);
+      PRESENCE_CAP_GOOGLE_VOICE, NULL, 0);
 
   dump = gabble_presence_dump (presence);
   g_assert (0 == strcmp (dump,
@@ -138,7 +138,7 @@ int main (int argc, char **argv)
 
   /* give voice cap to first resource */
   gabble_presence_set_capabilities (presence, "foo",
-      PRESENCE_CAP_GOOGLE_VOICE, NULL, NULL, NULL, 0);
+      PRESENCE_CAP_GOOGLE_VOICE, NULL, 0);
 
   /* resource has voice cap */
   resource = gabble_presence_pick_resource_by_caps (presence,
-- 
1.5.6.5




More information about the Telepathy-commits mailing list