[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