[telepathy-gabble/master] Separate capabilities into four sources (fixed, legacy Capabilities, and ContactCapabilities draft 1) and union them

Simon McVittie simon.mcvittie at collabora.co.uk
Thu Sep 10 04:40:00 PDT 2009


This removes the need for the strange workaround in which
SetSelfCapabilities has to avoid deleting things that came from another
source.

To preserve historical behaviour (we support ice-udp and gtalk-p2p on
startup, until the first call to AdvertiseCapabilities), demote these to
optional, but put them in the initial value of the legacy
Capabilities set.
---
 src/capabilities.c |    5 +-
 src/connection.c   |  149 +++++++++++++++++++++++++++-------------------------
 2 files changed, 81 insertions(+), 73 deletions(-)

diff --git a/src/capabilities.c b/src/capabilities.c
index a7346b0..58d14d6 100644
--- a/src/capabilities.c
+++ b/src/capabilities.c
@@ -53,9 +53,7 @@ struct _Feature
 static const Feature self_advertised_features[] =
 {
   { FEATURE_FIXED, NS_GOOGLE_FEAT_SESSION },
-  { FEATURE_FIXED, NS_GOOGLE_TRANSPORT_P2P },
   { FEATURE_FIXED, NS_JINGLE_TRANSPORT_RAWUDP },
-  { FEATURE_FIXED, NS_JINGLE_TRANSPORT_ICEUDP },
   { FEATURE_FIXED, NS_JINGLE015 },
   { FEATURE_FIXED, NS_JINGLE032 },
   { FEATURE_FIXED, NS_CHAT_STATES },
@@ -67,6 +65,9 @@ static const Feature self_advertised_features[] =
   { FEATURE_FIXED, NS_BYTESTREAMS },
   { FEATURE_FIXED, NS_FILE_TRANSFER },
 
+  { FEATURE_OPTIONAL, NS_GOOGLE_TRANSPORT_P2P },
+  { FEATURE_OPTIONAL, NS_JINGLE_TRANSPORT_ICEUDP },
+
   { FEATURE_OPTIONAL, NS_GOOGLE_FEAT_VOICE },
   { FEATURE_OPTIONAL, NS_GOOGLE_FEAT_VIDEO },
   { FEATURE_OPTIONAL, NS_JINGLE_DESCRIPTION_AUDIO },
diff --git a/src/connection.c b/src/connection.c
index a407e33..8fd4d81 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -200,6 +200,12 @@ struct _GabbleConnectionPrivate
   /* serial number of current advertised caps */
   guint caps_serial;
 
+  /* capabilities from various sources */
+  GabbleCapabilitySet *all_caps;
+  GabbleCapabilitySet *notify_caps;
+  GabbleCapabilitySet *legacy_caps;
+  GabbleCapabilitySet *draft1_caps;
+
   /* gobject housekeeping */
   gboolean dispose_has_run;
 };
@@ -317,6 +323,18 @@ gabble_connection_constructor (GType type,
           NULL);
     }
 
+  priv->all_caps = gabble_capability_set_new ();
+  priv->notify_caps = gabble_capability_set_new ();
+  priv->legacy_caps = gabble_capability_set_new ();
+
+  /* Historically, the optional Jingle transports were in our initial
+   * presence, but could be removed by AdvertiseCapabilities(). Emulate
+   * that here for now. */
+  gabble_capability_set_add (priv->legacy_caps, NS_GOOGLE_TRANSPORT_P2P);
+  gabble_capability_set_add (priv->legacy_caps, NS_JINGLE_TRANSPORT_ICEUDP);
+
+  priv->draft1_caps = gabble_capability_set_new ();
+
   return (GObject *) self;
 }
 
@@ -913,6 +931,11 @@ gabble_connection_dispose (GObject *object)
    */
   g_idle_add (_unref_lm_connection, self->lmconn);
 
+  gabble_capability_set_free (priv->all_caps);
+  gabble_capability_set_free (priv->notify_caps);
+  gabble_capability_set_free (priv->legacy_caps);
+  gabble_capability_set_free (priv->draft1_caps);
+
   if (G_OBJECT_CLASS (gabble_connection_parent_class)->dispose)
     G_OBJECT_CLASS (gabble_connection_parent_class)->dispose (object);
 }
@@ -1566,6 +1589,40 @@ _gabble_connection_signal_own_presence (GabbleConnection *self, GError **error)
   return ret;
 }
 
+static gboolean
+gabble_connection_refresh_capabilities (GabbleConnection *self)
+{
+  GError *error = NULL;
+
+  gabble_capability_set_clear (self->priv->all_caps);
+
+  gabble_capability_set_update (self->priv->all_caps,
+      gabble_capabilities_get_initial_caps ());
+  gabble_capability_set_update (self->priv->all_caps, self->priv->notify_caps);
+  gabble_capability_set_update (self->priv->all_caps, self->priv->legacy_caps);
+  gabble_capability_set_update (self->priv->all_caps, self->priv->draft1_caps);
+
+  if (gabble_presence_resource_has_caps (self->self_presence,
+        self->priv->resource, gabble_capability_set_predicate_equals,
+        self->priv->all_caps))
+    {
+      DEBUG ("nothing to do");
+      return FALSE;
+    }
+
+  gabble_presence_set_capabilities (self->self_presence, self->priv->resource,
+      self->priv->all_caps, self->priv->caps_serial++);
+
+  if (!_gabble_connection_signal_own_presence (self, &error))
+    {
+      DEBUG ("error sending presence: %s", error->message);
+      g_error_free (error);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 /**
  * _gabble_connection_send_iq_result
  *
@@ -2060,7 +2117,6 @@ connection_auth_cb (LmConnection *lmconn,
   GabbleConnectionPrivate *priv = conn->priv;
   GError *error = NULL;
   const gchar *jid;
-  const GabbleCapabilitySet *cap_set;
 
   if (base->status != TP_CONNECTION_STATUS_CONNECTING)
     {
@@ -2122,9 +2178,7 @@ connection_auth_cb (LmConnection *lmconn,
       GABBLE_PRESENCE_AVAILABLE, NULL, priv->priority);
 
   /* set initial capabilities */
-  cap_set = gabble_capabilities_get_initial_caps ();
-  gabble_presence_set_capabilities (conn->self_presence, priv->resource,
-      cap_set, priv->caps_serial++);
+  gabble_connection_refresh_capabilities (conn);
 
   if (!gabble_disco_request_with_timeout (conn->disco, GABBLE_DISCO_TYPE_INFO,
                                           priv->stream_server, NULL,
@@ -2443,13 +2497,10 @@ gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *
   GabbleConnection *self = GABBLE_CONNECTION (iface);
   TpBaseConnection *base = (TpBaseConnection *) self;
   guint i;
-  GabblePresence *pres = self->self_presence;
   GabbleConnectionPrivate *priv = self->priv;
   const CapabilityConversionData *ccd;
   GPtrArray *ret;
-  GabbleCapabilitySet *cap_set;
   GabbleCapabilitySet *save_set;
-  GError *error = NULL;
   GabbleCapabilitySet *add_set, *remove_set;
 
   TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
@@ -2485,11 +2536,10 @@ gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *
             ccd->tf2c_fn (~0, remove_set);
     }
 
-  save_set = gabble_presence_dup_caps (pres);
-  cap_set = gabble_capability_set_copy (save_set);
+  save_set = gabble_capability_set_copy (priv->all_caps);
 
-  gabble_capability_set_update (cap_set, add_set);
-  gabble_capability_set_exclude (cap_set, remove_set);
+  gabble_capability_set_update (priv->legacy_caps, add_set);
+  gabble_capability_set_exclude (priv->legacy_caps, remove_set);
 
   if (DEBUGGING)
     {
@@ -2505,18 +2555,17 @@ gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *
   gabble_capability_set_free (add_set);
   gabble_capability_set_free (remove_set);
 
-  if (!gabble_capability_set_equals (save_set, cap_set))
+  if (gabble_connection_refresh_capabilities (self))
     {
-      DEBUG ("before != after, changing");
-      gabble_presence_set_capabilities (pres, priv->resource, cap_set,
-          priv->caps_serial++);
+      _emit_capabilities_changed (self, base->self_handle, save_set,
+          priv->all_caps);
     }
 
   ret = g_ptr_array_new ();
 
   for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++)
     {
-      guint tp_caps = ccd->c2tf_fn (cap_set);
+      guint tp_caps = ccd->c2tf_fn (self->priv->all_caps);
 
       if (tp_caps != 0)
         {
@@ -2536,18 +2585,6 @@ gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *
         }
     }
 
-  if (!gabble_capability_set_equals (save_set, cap_set))
-    {
-      if (!_gabble_connection_signal_own_presence (self, &error))
-        {
-          dbus_g_method_return_error (context, error);
-          return;
-        }
-
-      _emit_capabilities_changed (self, base->self_handle, save_set, cap_set);
-    }
-
-  gabble_capability_set_free (cap_set);
   gabble_capability_set_free (save_set);
 
   tp_svc_connection_interface_capabilities_return_from_advertise_capabilities (
@@ -2576,17 +2613,14 @@ gabble_connection_set_self_capabilities (
 {
   GabbleConnection *self = GABBLE_CONNECTION (iface);
   TpBaseConnection *base = (TpBaseConnection *) self;
-  GabbleConnectionPrivate *priv = self->priv;
-  GabbleCapabilitySet *old_caps, *new_caps;
+  GabbleCapabilitySet *old_caps;
   guint i;
-  GabblePresence *pres = self->self_presence;
-  GError *error = NULL;
 
   TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
 
-  old_caps = gabble_presence_dup_caps (pres);
-  new_caps = gabble_capability_set_copy (old_caps);
-  gabble_capability_set_intersect (new_caps, gabble_capabilities_get_legacy ());
+  old_caps = gabble_capability_set_copy (self->priv->all_caps);
+
+  gabble_capability_set_clear (self->priv->draft1_caps);
 
   for (i = 0; i < caps->len; i++)
     {
@@ -2601,28 +2635,21 @@ gabble_connection_set_self_capabilities (
           g_assert (GABBLE_IS_CAPS_CHANNEL_MANAGER (manager));
 
           gabble_caps_channel_manager_add_capability (
-              GABBLE_CAPS_CHANNEL_MANAGER (manager), cap_to_add, new_caps);
+              GABBLE_CAPS_CHANNEL_MANAGER (manager), cap_to_add,
+              self->priv->draft1_caps);
         }
     }
 
-  gabble_presence_set_capabilities (pres, priv->resource, new_caps,
-      priv->caps_serial++);
-
-  if (_gabble_connection_signal_own_presence (self, &error))
+  if (gabble_connection_refresh_capabilities (self))
     {
       _emit_contact_capabilities_changed (self, base->self_handle, old_caps,
-          new_caps);
-
-      gabble_svc_connection_interface_contact_capabilities_return_from_set_self_capabilities (
-          context);
-    }
-  else
-    {
-      dbus_g_method_return_error (context, error);
+          self->priv->all_caps);
     }
 
+  gabble_svc_connection_interface_contact_capabilities_return_from_set_self_capabilities (
+      context);
+
   gabble_capability_set_free (old_caps);
-  gabble_capability_set_free (new_caps);
 }
 
 static const gchar *assumed_caps[] =
@@ -3280,28 +3307,8 @@ void
 gabble_connection_ensure_capabilities (GabbleConnection *self,
     const GabbleCapabilitySet *ensured)
 {
-  GabbleConnectionPrivate *priv = self->priv;
-  GabbleCapabilitySet *cap_set;
-  GError *error = NULL;
-
-  if (gabble_presence_resource_has_caps (self->self_presence,
-        priv->resource, gabble_capability_set_predicate_at_least, ensured))
-    {
-      DEBUG ("nothing to do");
-      return;
-    }
-
-  cap_set = gabble_presence_dup_caps (self->self_presence);
-  gabble_capability_set_update (cap_set, ensured);
-  gabble_presence_set_capabilities (self->self_presence, priv->resource,
-      cap_set, priv->caps_serial++);
-  gabble_capability_set_free (cap_set);
-
-  if (!_gabble_connection_signal_own_presence (self, &error))
-    {
-      DEBUG ("error sending presence: %s", error->message);
-      g_error_free (error);
-    }
+  gabble_capability_set_update (self->priv->notify_caps, ensured);
+  gabble_connection_refresh_capabilities (self);
 }
 
 gboolean
-- 
1.5.6.5




More information about the telepathy-commits mailing list