[telepathy-gabble/master] Store cap set in GabblePresence

Will Thompson will.thompson at collabora.co.uk
Tue Sep 8 04:10:02 PDT 2009


Currently, this set of namespaces is stored as well as the
GabblePresenceCapabilities flags and the per_channel_manager contact
capability hash table, and isn't used. The intention is to migrate the
contact capabilities API to use this, then remove the hash; then,
migrate the old-style capabilities to this too.

Merged-by: Simon McVittie <simon.mcvittie at collabora.co.uk>
---
 src/capabilities.c    |   16 ++++++++++++++++
 src/capabilities.h    |    2 ++
 src/connection.c      |   17 ++++++++++++++---
 src/presence-cache.c  |   40 ++++++++++++++++++++++++++++------------
 src/presence.c        |   30 +++++++++++++++++++++++++++++-
 src/presence.h        |    8 ++++++--
 tests/test-presence.c |    9 +++++++--
 7 files changed, 102 insertions(+), 20 deletions(-)

diff --git a/src/capabilities.c b/src/capabilities.c
index 7b13a8f..8c760e0 100644
--- a/src/capabilities.c
+++ b/src/capabilities.c
@@ -256,6 +256,22 @@ gabble_capability_set_new_from_stanza (LmMessageNode *query_result)
   return ret;
 }
 
+/* This function should disappear when GabbleCapabilitySet replaces
+ * GabblePresenceCapabilities.
+ */
+GabbleCapabilitySet *
+gabble_capability_set_new_from_flags (GabblePresenceCapabilities caps)
+{
+  GabbleCapabilitySet *ret = gabble_capability_set_new ();
+  const Feature *i;
+
+  for (i = self_advertised_features; NULL != i->ns; i++)
+    if ((i->caps & caps) == i->caps)
+      gabble_capability_set_add (ret, i->ns);
+
+  return ret;
+}
+
 GabbleCapabilitySet *
 gabble_capability_set_copy (const GabbleCapabilitySet *caps)
 {
diff --git a/src/capabilities.h b/src/capabilities.h
index 9703483..a987d11 100644
--- a/src/capabilities.h
+++ b/src/capabilities.h
@@ -62,6 +62,8 @@ typedef GPtrArray GabbleCapabilitySet;
 GabbleCapabilitySet *gabble_capability_set_new (void);
 GabbleCapabilitySet *gabble_capability_set_new_from_stanza (
     LmMessageNode *query_result);
+GabbleCapabilitySet *gabble_capability_set_new_from_flags (
+    GabblePresenceCapabilities caps);
 GabbleCapabilitySet *gabble_capability_set_copy (
     const GabbleCapabilitySet *caps);
 void gabble_capability_set_update (GabbleCapabilitySet *target,
diff --git a/src/connection.c b/src/connection.c
index 5787b46..c0eb652 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -2070,6 +2070,8 @@ connection_auth_cb (LmConnection *lmconn,
   GabbleConnectionPrivate *priv = conn->priv;
   GError *error = NULL;
   const gchar *jid;
+  GabblePresenceCapabilities caps;
+  GabbleCapabilitySet *cap_set;
 
   if (base->status != TP_CONNECTION_STATUS_CONNECTING)
     {
@@ -2131,8 +2133,11 @@ connection_auth_cb (LmConnection *lmconn,
       GABBLE_PRESENCE_AVAILABLE, NULL, priv->priority);
 
   /* set initial capabilities */
+  caps = capabilities_get_initial_caps ();
+  cap_set = gabble_capability_set_new_from_flags (caps);
   gabble_presence_set_capabilities (conn->self_presence, priv->resource,
-      capabilities_get_initial_caps (), NULL, priv->caps_serial++);
+      cap_set, caps, NULL, priv->caps_serial++);
+  gabble_capability_set_free (cap_set);
 
   if (!gabble_disco_request_with_timeout (conn->disco, GABBLE_DISCO_TYPE_INFO,
                                           priv->stream_server, NULL,
@@ -2473,6 +2478,7 @@ gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *
   GabbleConnectionPrivate *priv = self->priv;
   const CapabilityConversionData *ccd;
   GPtrArray *ret;
+  GabbleCapabilitySet *cap_set;
   GError *error = NULL;
 
   TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
@@ -2519,8 +2525,10 @@ gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *
   if (caps ^ save_caps)
     {
       DEBUG ("before != after, changing");
-      gabble_presence_set_capabilities (pres, priv->resource, caps, NULL,
+      cap_set = gabble_capability_set_new_from_flags (caps);
+      gabble_presence_set_capabilities (pres, priv->resource, cap_set, caps, NULL,
           priv->caps_serial++);
+      gabble_capability_set_free (cap_set);
       DEBUG ("set caps: %x", pres->caps);
     }
 
@@ -3286,6 +3294,7 @@ gabble_connection_ensure_capabilities (GabbleConnection *self,
 {
   GabbleConnectionPrivate *priv = self->priv;
   GabblePresenceCapabilities old_caps, new_caps;
+  GabbleCapabilitySet *cap_set;
 
   old_caps = self->self_presence->caps;
   new_caps = old_caps;
@@ -3296,8 +3305,10 @@ gabble_connection_ensure_capabilities (GabbleConnection *self,
       /* We changed capabilities */
       GError *error = NULL;
 
+      cap_set = gabble_capability_set_new_from_flags (caps);
       gabble_presence_set_capabilities (self->self_presence,
-          priv->resource, new_caps, NULL, priv->caps_serial++);
+          priv->resource, cap_set, new_caps, NULL, priv->caps_serial++);
+      gabble_capability_set_free (cap_set);
 
       if (!_gabble_connection_signal_own_presence (self, &error))
         {
diff --git a/src/presence-cache.c b/src/presence-cache.c
index f5155a4..4c2cbfc 100644
--- a/src/presence-cache.c
+++ b/src/presence-cache.c
@@ -212,6 +212,8 @@ struct _CapabilityInfo
    * caps. In this case, caps_set is FALSE and set to TRUE when the caps are
    * received */
   gboolean caps_set;
+
+  GabbleCapabilitySet *cap_set;
   GabblePresenceCapabilities caps;
 
   /* key: GabbleCapsChannelFactory -> value: gpointer
@@ -246,6 +248,7 @@ capability_info_get (GabblePresenceCache *cache, const gchar *node)
     {
       info = g_slice_new0 (CapabilityInfo);
       info->caps_set = FALSE;
+      info->cap_set = gabble_capability_set_new ();
       info->guys = tp_intset_new ();
       g_hash_table_insert (priv->capabilities, g_strdup (node), info);
     }
@@ -258,14 +261,23 @@ capability_info_free (CapabilityInfo *info)
 {
   gabble_presence_cache_free_cache_entry (info->per_channel_manager_caps);
   info->per_channel_manager_caps = NULL;
+
+  gabble_capability_set_free (info->cap_set);
+  info->cap_set = NULL;
+
   tp_intset_destroy (info->guys);
+
   g_slice_free (CapabilityInfo, info);
 }
 
 static guint
-capability_info_recvd (GabblePresenceCache *cache, const gchar *node,
-        TpHandle handle, GabblePresenceCapabilities caps,
-        GHashTable *per_channel_manager_caps, guint trust_inc)
+capability_info_recvd (GabblePresenceCache *cache,
+    const gchar *node,
+    TpHandle handle,
+    GabbleCapabilitySet *cap_set,
+    GabblePresenceCapabilities caps,
+    GHashTable *per_channel_manager_caps,
+    guint trust_inc)
 {
   CapabilityInfo *info = capability_info_get (cache, node);
 
@@ -278,6 +290,8 @@ capability_info_recvd (GabblePresenceCache *cache, const gchar *node,
        */
       tp_intset_clear (info->guys);
       info->caps = caps;
+      gabble_capability_set_clear (info->cap_set);
+      gabble_capability_set_update (info->cap_set, cap_set);
       info->per_channel_manager_caps = per_channel_manager_caps;
       info->trust = 0;
       info->caps_set = TRUE;
@@ -959,6 +973,7 @@ emit_capabilities_update (GabblePresenceCache *cache,
 static void
 set_caps_for (DiscoWaiter *waiter,
     GabblePresenceCache *cache,
+    GabbleCapabilitySet *cap_set,
     GabblePresenceCapabilities caps,
     GHashTable *per_channel_manager_caps,
     TpHandle responder_handle,
@@ -978,7 +993,7 @@ set_caps_for (DiscoWaiter *waiter,
   DEBUG ("setting caps for %d (thanks to %d %s) to %d (save_caps %d)",
       waiter->handle, responder_handle, responder_jid, caps, save_caps);
 
-  gabble_presence_set_capabilities (presence, waiter->resource,
+  gabble_presence_set_capabilities (presence, waiter->resource, cap_set,
       caps, per_channel_manager_caps, waiter->serial);
 
   DEBUG ("caps for %d now %d", waiter->handle, presence->caps);
@@ -1059,7 +1074,6 @@ _caps_disco_cb (GabbleDisco *disco,
   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
@@ -1074,7 +1088,7 @@ _caps_disco_cb (GabbleDisco *disco,
 
       if (g_str_equal (waiter_self->ver, computed_hash))
         {
-          trust = capability_info_recvd (cache, node, handle, caps,
+          trust = capability_info_recvd (cache, node, handle, cap_set, caps,
               per_channel_manager_caps, CAPABILITY_BUNDLE_ENOUGH_TRUST);
         }
       else
@@ -1092,7 +1106,7 @@ _caps_disco_cb (GabbleDisco *disco,
     }
   else
     {
-      trust = capability_info_recvd (cache, node, handle, caps,
+      trust = capability_info_recvd (cache, node, handle, cap_set, caps,
           per_channel_manager_caps, 1);
     }
 
@@ -1103,8 +1117,8 @@ _caps_disco_cb (GabbleDisco *disco,
         {
           DiscoWaiter *waiter = (DiscoWaiter *) i->data;
 
-          set_caps_for (waiter, cache, caps, per_channel_manager_caps, handle,
-              jid);
+          set_caps_for (waiter, cache, cap_set, caps, per_channel_manager_caps,
+              handle, jid);
           emit_capabilities_discovered (cache, waiter->handle);
         }
 
@@ -1123,8 +1137,8 @@ _caps_disco_cb (GabbleDisco *disco,
        *       for the jid that answered the query.
        */
       if (!bad_hash)
-        set_caps_for (waiter_self, cache, caps, per_channel_manager_caps,
-            handle, jid);
+        set_caps_for (waiter_self, cache, cap_set, caps,
+            per_channel_manager_caps, handle, jid);
 
       waiters = g_slist_remove (waiters, waiter_self);
 
@@ -1153,6 +1167,8 @@ _caps_disco_cb (GabbleDisco *disco,
         }
     }
 
+  gabble_capability_set_free (cap_set);
+
 OUT:
   if (handle)
     tp_handle_unref (contact_repo, handle);
@@ -1189,7 +1205,7 @@ _process_caps_uri (GabblePresenceCache *cache,
 
       if (presence)
         {
-          gabble_presence_set_capabilities (presence, resource,
+          gabble_presence_set_capabilities (presence, resource, info->cap_set,
               info->caps, info->per_channel_manager_caps, serial);
           DEBUG ("caps for %d (%s) now %d", handle, from, presence->caps);
         }
diff --git a/src/presence.c b/src/presence.c
index 128c593..0029d95 100644
--- a/src/presence.c
+++ b/src/presence.c
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <telepathy-glib/channel-manager.h>
 
+#include "capabilities.h"
 #include "presence-cache.h"
 #include "namespaces.h"
 #include "util.h"
@@ -40,6 +41,7 @@ typedef struct _Resource Resource;
 
 struct _Resource {
     gchar *name;
+    GabbleCapabilitySet *cap_set;
     GabblePresenceCapabilities caps;
     GHashTable *per_channel_manager_caps;
     guint caps_serial;
@@ -50,6 +52,9 @@ struct _Resource {
 };
 
 struct _GabblePresencePrivate {
+    /* The aggregated caps of all the contacts' resources. */
+    GabbleCapabilitySet *cap_set;
+
     gchar *no_resource_status_message;
     GSList *resources;
     guint olpc_views;
@@ -60,6 +65,7 @@ _resource_new (gchar *name)
 {
   Resource *new = g_slice_new0 (Resource);
   new->name = name;
+  new->cap_set = gabble_capability_set_new ();
   new->caps = PRESENCE_CAP_NONE;
   new->per_channel_manager_caps = NULL;
   new->status = GABBLE_PRESENCE_OFFLINE;
@@ -76,6 +82,8 @@ _resource_free (Resource *resource)
 {
   g_free (resource->name);
   g_free (resource->status_message);
+  gabble_capability_set_free (resource->cap_set);
+
   if (resource->per_channel_manager_caps != NULL)
     {
       gabble_presence_cache_free_cache_entry
@@ -104,6 +112,8 @@ gabble_presence_finalize (GObject *object)
     }
 
   g_slist_free (priv->resources);
+  gabble_capability_set_free (priv->cap_set);
+
   g_free (presence->nickname);
   g_free (presence->avatar_sha1);
   g_free (priv->no_resource_status_message);
@@ -120,9 +130,14 @@ gabble_presence_class_init (GabblePresenceClass *klass)
 static void
 gabble_presence_init (GabblePresence *self)
 {
+  GabblePresencePrivate *priv;
+
   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
       GABBLE_TYPE_PRESENCE, GabblePresencePrivate);
-  ((GabblePresencePrivate *) self->priv)->resources = NULL;
+
+  priv = self->priv;
+  priv->cap_set = gabble_capability_set_new ();
+  priv->resources = NULL;
 }
 
 GabblePresence *
@@ -199,6 +214,7 @@ gabble_presence_resource_has_caps (GabblePresence *presence,
 void
 gabble_presence_set_capabilities (GabblePresence *presence,
                                   const gchar *resource,
+                                  GabbleCapabilitySet *cap_set,
                                   GabblePresenceCapabilities caps,
                                   GHashTable *per_channel_manager_caps,
                                   guint serial)
@@ -219,6 +235,8 @@ gabble_presence_set_capabilities (GabblePresence *presence,
     }
 
   presence->caps = 0;
+  gabble_capability_set_clear (priv->cap_set);
+
   if (presence->per_channel_manager_caps != NULL)
     {
       gabble_presence_cache_free_cache_entry
@@ -231,6 +249,7 @@ gabble_presence_set_capabilities (GabblePresence *presence,
     {
       DEBUG ("adding caps %u to bare jid", caps);
       presence->caps = caps;
+      gabble_capability_set_update (priv->cap_set, cap_set);
       gabble_presence_cache_update_cache_entry (
           presence->per_channel_manager_caps, per_channel_manager_caps);
       return;
@@ -253,6 +272,7 @@ gabble_presence_set_capabilities (GabblePresence *presence,
                 tmp->caps_serial);
               tmp->caps = 0;
               tmp->caps_serial = serial;
+              gabble_capability_set_clear (tmp->cap_set);
             }
 
           if (serial >= tmp->caps_serial)
@@ -261,6 +281,8 @@ gabble_presence_set_capabilities (GabblePresence *presence,
               tmp->caps |= caps;
               DEBUG ("resource %s caps now %u", resource, tmp->caps);
 
+              gabble_capability_set_update (tmp->cap_set, cap_set);
+
               if (tmp->per_channel_manager_caps != NULL)
                 {
                   gabble_presence_cache_free_cache_entry
@@ -274,6 +296,7 @@ gabble_presence_set_capabilities (GabblePresence *presence,
         }
 
       presence->caps |= tmp->caps;
+      gabble_capability_set_update (priv->cap_set, tmp->cap_set);
 
       if (tmp->per_channel_manager_caps != NULL)
         gabble_presence_cache_update_cache_entry
@@ -311,6 +334,7 @@ aggregate_resources (GabblePresence *presence)
   /* select the most preferable Resource and update presence->* based on our
    * choice */
   presence->caps = 0;
+  gabble_capability_set_clear (priv->cap_set);
   presence->status = GABBLE_PRESENCE_OFFLINE;
 
   prio = -128;
@@ -320,6 +344,7 @@ aggregate_resources (GabblePresence *presence)
       Resource *r = (Resource *) i->data;
 
       presence->caps |= r->caps;
+      gabble_capability_set_update (priv->cap_set, r->cap_set);
 
       /* trump existing status & message if it's more present
        * or has the same presence and a higher priority */
@@ -402,12 +427,14 @@ gabble_presence_update (GabblePresence *presence,
             }
           presence->per_channel_manager_caps = g_hash_table_new (NULL, NULL);
           presence->caps = 0;
+          gabble_capability_set_clear (priv->cap_set);
 
           for (i = priv->resources; i; i = i->next)
             {
               Resource *r = (Resource *) i->data;
 
               presence->caps |= r->caps;
+              gabble_capability_set_update (priv->cap_set, r->cap_set);
 
               if (r->per_channel_manager_caps != NULL)
                 gabble_presence_cache_update_cache_entry
@@ -441,6 +468,7 @@ gabble_presence_update (GabblePresence *presence,
   /* select the most preferable Resource and update presence->* based on our
    * choice */
   presence->caps = 0;
+  gabble_capability_set_clear (priv->cap_set);
   presence->status = GABBLE_PRESENCE_OFFLINE;
 
   /* use the status message from any offline Resource we're
diff --git a/src/presence.h b/src/presence.h
index 76bb866..f449794 100644
--- a/src/presence.h
+++ b/src/presence.h
@@ -24,6 +24,7 @@
 
 #include <glib-object.h>
 
+#include "capabilities.h"
 #include "connection.h"
 #include "types.h"
 
@@ -80,8 +81,11 @@ gboolean gabble_presence_update (GabblePresence *presence,
     const gchar *status_message, gint8 priority);
 
 void gabble_presence_set_capabilities (GabblePresence *presence,
-    const gchar *resource, GabblePresenceCapabilities caps,
-    GHashTable *per_channel_manager_caps, guint serial);
+    const gchar *resource,
+    GabbleCapabilitySet *cap_set,
+    GabblePresenceCapabilities caps,
+    GHashTable *per_channel_manager_caps,
+    guint serial);
 
 const gchar *gabble_presence_pick_resource_by_caps (GabblePresence *presence,
     GabblePresenceCapabilities caps);
diff --git a/tests/test-presence.c b/tests/test-presence.c
index 115c2c0..0f4bc5e 100644
--- a/tests/test-presence.c
+++ b/tests/test-presence.c
@@ -13,6 +13,7 @@ int main (int argc, char **argv)
   const gchar *resource;
   gchar *dump;
   GabblePresence *presence;
+  GabbleCapabilitySet *cap_set;
 
   g_type_init ();
 
@@ -108,8 +109,10 @@ int main (int argc, char **argv)
   /* give voice cap to second resource, but make priority negative */
   g_assert (FALSE == gabble_presence_update (presence, "bar",
     GABBLE_PRESENCE_AVAILABLE, "dingoes", -1));
-  gabble_presence_set_capabilities (presence, "bar",
+  cap_set = gabble_capability_set_new_from_flags (PRESENCE_CAP_GOOGLE_VOICE);
+  gabble_presence_set_capabilities (presence, "bar", cap_set,
       PRESENCE_CAP_GOOGLE_VOICE, NULL, 0);
+  gabble_capability_set_free (cap_set);
 
   dump = gabble_presence_dump (presence);
   g_assert (0 == strcmp (dump,
@@ -137,8 +140,10 @@ int main (int argc, char **argv)
   g_assert (NULL == resource);
 
   /* give voice cap to first resource */
-  gabble_presence_set_capabilities (presence, "foo",
+  cap_set = gabble_capability_set_new_from_flags (PRESENCE_CAP_GOOGLE_VOICE);
+  gabble_presence_set_capabilities (presence, "foo", cap_set,
       PRESENCE_CAP_GOOGLE_VOICE, NULL, 0);
+  gabble_capability_set_free (cap_set);
 
   /* resource has voice cap */
   resource = gabble_presence_pick_resource_by_caps (presence,
-- 
1.5.6.5




More information about the telepathy-commits mailing list