[telepathy-gabble/master] Parse (Contact)Caps from a CapabilitySet

Simon McVittie simon.mcvittie at collabora.co.uk
Tue Sep 8 04:09:59 PDT 2009


This reduces the duplication of code iterating across all the
<feature>s.

Patch originally by Will Thompson, but needed significant merging with
Guillaume's node_iter patches and Will's Gabble-version detection.
---
 src/capabilities.c          |   29 ++++++++--------
 src/capabilities.h          |    3 +-
 src/caps-channel-manager.c  |    4 +-
 src/caps-channel-manager.h  |    6 ++-
 src/ft-manager.c            |   23 +------------
 src/presence-cache.c        |   11 ++++--
 src/private-tubes-factory.c |   77 +++++++++++++++++++------------------------
 7 files changed, 65 insertions(+), 88 deletions(-)

diff --git a/src/capabilities.c b/src/capabilities.c
index 0d03579..424cabf 100644
--- a/src/capabilities.c
+++ b/src/capabilities.c
@@ -143,29 +143,28 @@ omits_content_creators (LmMessageNode *identity)
 }
 
 GabblePresenceCapabilities
-capabilities_parse (LmMessageNode *query_result)
+capabilities_parse (GabbleCapabilitySet *cap_set,
+    LmMessageNode *query_result)
 {
   GabblePresenceCapabilities ret = PRESENCE_CAP_NONE;
   const gchar *var;
+  guint j;
   const Feature *i;
-  NodeIter j;
+  NodeIter ni;
 
-  for (j = node_iter (query_result); j; j = node_iter_next (j))
+  /* special case: OMITS_CONTENT_CREATOR looks at the software version,
+   * not the actual features (sad face) */
+  for (ni = node_iter (query_result); ni != NULL; ni = node_iter_next (ni))
     {
-      LmMessageNode *child = node_iter_data (j);
+      LmMessageNode *child = node_iter_data (ni);
 
-      if (tp_strdiff (child->name, "feature"))
-        {
-          if (omits_content_creators (child))
-            ret |= PRESENCE_CAP_JINGLE_OMITS_CONTENT_CREATOR;
-
-          continue;
-        }
-
-      var = lm_message_node_get_attribute (child, "var");
+      if (omits_content_creators (child))
+        ret |= PRESENCE_CAP_JINGLE_OMITS_CONTENT_CREATOR;
+    }
 
-      if (NULL == var)
-        continue;
+  for (j = 0; j < cap_set->len; j++)
+    {
+      var = g_ptr_array_index (cap_set, j);
 
       for (i = self_advertised_features; i->ns != NULL; i++)
         {
diff --git a/src/capabilities.h b/src/capabilities.h
index dd1ecd4..f481dc0 100644
--- a/src/capabilities.h
+++ b/src/capabilities.h
@@ -96,7 +96,8 @@ void capabilities_fill_cache (GabblePresenceCache *cache);
  */
 GabblePresenceCapabilities capabilities_get_initial_caps (void);
 
-GabblePresenceCapabilities capabilities_parse (LmMessageNode *query_result);
+GabblePresenceCapabilities capabilities_parse (GabbleCapabilitySet *cap_set,
+    LmMessageNode *query_result);
 
 typedef GabblePresenceCapabilities (*TypeFlagsToCapsFunc) (guint typeflags);
 typedef guint (*CapsToTypeFlagsFunc) (GabblePresenceCapabilities caps);
diff --git a/src/caps-channel-manager.c b/src/caps-channel-manager.c
index 4b345c1..f6cc60d 100644
--- a/src/caps-channel-manager.c
+++ b/src/caps-channel-manager.c
@@ -95,7 +95,7 @@ void gabble_caps_channel_manager_get_feature_list (
 
 gpointer gabble_caps_channel_manager_parse_capabilities (
     GabbleCapsChannelManager *caps_manager,
-    LmMessageNode *query_result)
+    GabbleCapabilitySet *cap_set)
 {
   GabbleCapsChannelManagerIface *iface =
     GABBLE_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
@@ -103,7 +103,7 @@ gpointer gabble_caps_channel_manager_parse_capabilities (
 
   if (method != NULL)
     {
-      return method (caps_manager, query_result);
+      return method (caps_manager, cap_set);
     }
   /* ... else assume there is not caps for this kind of channels */
   return NULL;
diff --git a/src/caps-channel-manager.h b/src/caps-channel-manager.h
index 6c6edb9..75b2e9a 100644
--- a/src/caps-channel-manager.h
+++ b/src/caps-channel-manager.h
@@ -28,6 +28,7 @@
 #include <telepathy-glib/exportable-channel.h>
 #include <telepathy-glib/handle.h>
 
+#include "capabilities.h"
 #include "types.h"
 
 G_BEGIN_DECLS
@@ -68,7 +69,7 @@ typedef void (*GabbleCapsChannelManagerGetFeatureListFunc) (
     GSList **features);
 
 typedef gpointer (*GabbleCapsChannelManagerParseCapsFunc) (
-    GabbleCapsChannelManager *manager, LmMessageNode *children);
+    GabbleCapsChannelManager *manager, GabbleCapabilitySet *cap_set);
 
 typedef void (*GabbleCapsChannelManagerFreeCapsFunc) (
     GabbleCapsChannelManager *manager, gpointer specific_caps);
@@ -95,7 +96,8 @@ void gabble_caps_channel_manager_get_feature_list (
     GSList **features);
 
 gpointer gabble_caps_channel_manager_parse_capabilities (
-    GabbleCapsChannelManager *manager, LmMessageNode *query_result);
+    GabbleCapsChannelManager *manager,
+    GabbleCapabilitySet *cap_set);
 
 void gabble_caps_channel_manager_free_capabilities (GabbleCapsChannelManager *manager,
     gpointer specific_caps);
diff --git a/src/ft-manager.c b/src/ft-manager.c
index c47f97c..a0d5d40 100644
--- a/src/ft-manager.c
+++ b/src/ft-manager.c
@@ -675,28 +675,9 @@ gabble_ft_manager_get_contact_caps (GabbleCapsChannelManager *manager,
 
 static gpointer
 gabble_ft_manager_parse_caps (GabbleCapsChannelManager *manager,
-                              LmMessageNode *query_result)
+    GabbleCapabilitySet *cap_set)
 {
-  NodeIter i;
-
-  for (i = node_iter (query_result); i; i = node_iter_next (i))
-    {
-      LmMessageNode *child = node_iter_data (i);
-      const gchar *var;
-
-      if (0 != strcmp (child->name, "feature"))
-        continue;
-
-      var = lm_message_node_get_attribute (child, "var");
-
-      if (NULL == var)
-        continue;
-
-      if (!tp_strdiff (var, NS_FILE_TRANSFER))
-        return GINT_TO_POINTER (TRUE);
-    }
-
-  return GINT_TO_POINTER (FALSE);
+  return GINT_TO_POINTER (gabble_capability_set_has (cap_set, NS_FILE_TRANSFER));
 }
 
 static void
diff --git a/src/presence-cache.c b/src/presence-cache.c
index 81eaa4f..f5155a4 100644
--- a/src/presence-cache.c
+++ b/src/presence-cache.c
@@ -912,7 +912,7 @@ find_matching_waiter (GSList *waiters,
 
 static GHashTable *
 parse_contact_caps (TpBaseConnection *base_conn,
-    LmMessageNode *query_result)
+    GabbleCapabilitySet *cap_set)
 {
   GHashTable *per_channel_manager_caps = g_hash_table_new (NULL, NULL);
   TpChannelManagerIter iter;
@@ -928,7 +928,7 @@ parse_contact_caps (TpBaseConnection *base_conn,
       g_assert (GABBLE_IS_CAPS_CHANNEL_MANAGER (manager));
 
       factory_caps = gabble_caps_channel_manager_parse_capabilities (
-          GABBLE_CAPS_CHANNEL_MANAGER (manager), query_result);
+          GABBLE_CAPS_CHANNEL_MANAGER (manager), cap_set);
 
       if (factory_caps != NULL)
         g_hash_table_insert (per_channel_manager_caps,
@@ -1009,6 +1009,7 @@ _caps_disco_cb (GabbleDisco *disco,
   GabblePresenceCache *cache;
   GabblePresenceCachePrivate *priv;
   TpHandleRepoIface *contact_repo;
+  GabbleCapabilitySet *cap_set;
   GabblePresenceCapabilities caps = 0;
   GHashTable *per_channel_manager_caps;
   guint trust;
@@ -1055,8 +1056,10 @@ _caps_disco_cb (GabbleDisco *disco,
       goto OUT;
     }
 
-  caps = capabilities_parse (query_result);
-  per_channel_manager_caps = parse_contact_caps (base_conn, query_result);
+  cap_set = gabble_capability_set_new_from_stanza (query_result);
+  caps = capabilities_parse (cap_set, query_result);
+  per_channel_manager_caps = parse_contact_caps (base_conn, cap_set);
+  gabble_capability_set_free (cap_set);
 
   /* Only 'sha-1' is mandatory to implement by XEP-0115. If the remote contact
    * uses another hash algorithm, don't check the hash and fallback to the old
diff --git a/src/private-tubes-factory.c b/src/private-tubes-factory.c
index 5a10640..f23a291 100644
--- a/src/private-tubes-factory.c
+++ b/src/private-tubes-factory.c
@@ -658,59 +658,50 @@ gabble_private_tubes_factory_free_feat (gpointer data)
   g_free (feat);
 }
 
+static void
+examine_node (const gchar *var,
+    TubesCapabilities *caps)
+{
+  gchar *service;
+
+  if (!g_str_has_prefix (var, NS_TUBES))
+    return;
+
+  /* tubes generic cap or service specific */
+  caps->tubes_supported = TRUE;
+
+  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#"))
+        {
+          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#"))
+        {
+          var += strlen ("dbus#");
+          service = g_strdup (var);
+          g_hash_table_insert (caps->dbus_tube_caps, service, NULL);
+        }
+    }
+}
+
 static gpointer
 gabble_private_tubes_factory_parse_caps (
     GabbleCapsChannelManager *manager,
-    LmMessageNode *query_result)
+    GabbleCapabilitySet *cap_set)
 {
-  TubesCapabilities *caps;
-  NodeIter i;
+  TubesCapabilities *caps = g_new0 (TubesCapabilities, 1);
 
-  caps = g_new0 (TubesCapabilities, 1);
   caps->stream_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
       g_free, gabble_private_tubes_factory_free_feat);
   caps->dbus_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
       g_free, gabble_private_tubes_factory_free_feat);
 
-  for (i = node_iter (query_result); i; i = node_iter_next (i))
-    {
-      LmMessageNode *child = node_iter_data (i);
-      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))
-        continue;
-
-      /* tubes generic cap or service specific */
-      caps->tubes_supported = TRUE;
-
-      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);
-            }
-        }
-    }
+  g_ptr_array_foreach (cap_set, (GFunc) examine_node, caps);
 
   return caps;
 }
-- 
1.5.6.5




More information about the telepathy-commits mailing list