summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2011-08-31 11:40:45 +0100
committerJonny Lamb <jonny.lamb@collabora.co.uk>2011-09-01 13:26:38 +0100
commit7c6971a75a6eb32c77b64a7e9754e1fdb2a694af (patch)
tree295db3f580b0248f8fb94f6cb7781c19bf35ff03
parentd887fdc2d23bf00322c9923e8eead7c5f0607302 (diff)
presence-cache: store data forms from disco replies and the caps cache
Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r--src/connection.c5
-rw-r--r--src/presence-cache.c77
-rw-r--r--src/presence-cache.h6
-rw-r--r--src/presence.c3
4 files changed, 72 insertions, 19 deletions
diff --git a/src/connection.c b/src/connection.c
index f82846b5..a941d6ec 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -2315,7 +2315,8 @@ gabble_connection_fill_in_caps (GabbleConnection *self,
/* Ensure this set of capabilities is in the cache. */
gabble_presence_cache_add_own_caps (self->presence_cache, caps_hash,
- gabble_presence_peek_caps (presence), NULL);
+ gabble_presence_peek_caps (presence), NULL,
+ gabble_presence_peek_data_forms (presence));
/* XEP-0115 deprecates 'ext' feature bundles. But we still need
* BUNDLE_VOICE_V1 it for backward-compatibility with Gabble 0.2 */
@@ -3775,7 +3776,7 @@ gabble_connection_add_sidecar_own_caps (GabbleConnection *self,
ver = gabble_caps_hash_compute (cap_set, identities_copy);
gabble_presence_cache_add_own_caps (self->presence_cache, ver,
- cap_set, identities_copy);
+ cap_set, identities_copy, NULL);
wocky_disco_identity_array_free (identities_copy);
diff --git a/src/presence-cache.c b/src/presence-cache.c
index c70d86e0..e3d9970d 100644
--- a/src/presence-cache.c
+++ b/src/presence-cache.c
@@ -41,6 +41,8 @@
#include <wocky/wocky-caps-hash.h>
#include <wocky/wocky-disco-identity.h>
#include <wocky/wocky-utils.h>
+#include <wocky/wocky-namespaces.h>
+#include <wocky/wocky-data-form.h>
#define DEBUG_FLAG GABBLE_DEBUG_PRESENCE
@@ -251,6 +253,10 @@ capability_info_free (GabbleCapabilityInfo *info)
wocky_disco_identity_array_free (info->identities);
info->identities = NULL;
+ if (info->data_forms != NULL)
+ g_ptr_array_unref (info->data_forms);
+ info->data_forms = NULL;
+
tp_intset_destroy (info->guys);
g_slice_free (GabbleCapabilityInfo, info);
@@ -262,9 +268,11 @@ capability_info_recvd (GabblePresenceCache *cache,
TpHandle handle,
GabbleCapabilitySet *cap_set,
guint trust_inc,
- guint client_types)
+ guint client_types,
+ GPtrArray *data_forms)
{
GabbleCapabilityInfo *info = capability_info_get (cache, node);
+ GPtrArray *forms;
if (info->cap_set == NULL ||
!gabble_capability_set_equals (cap_set, info->cap_set))
@@ -293,6 +301,12 @@ capability_info_recvd (GabblePresenceCache *cache,
info->client_types = client_types;
+ forms = info->data_forms;
+ if (data_forms != NULL)
+ info->data_forms = g_ptr_array_ref (data_forms);
+ if (forms != NULL)
+ g_ptr_array_unref (forms);
+
return info->trust;
}
@@ -1007,15 +1021,13 @@ _parse_node (GabblePresence *presence,
if (!tp_strdiff (node, "http://mail.google.com/xmpp/client/caps"))
{
GabbleCapabilitySet *cap_set = gabble_capability_set_new ();
- GPtrArray *tmp = g_ptr_array_new ();
DEBUG ("Client is Google Web Client");
gabble_capability_set_add (cap_set, QUIRK_GOOGLE_WEBMAIL_CLIENT);
gabble_capability_set_add (cap_set, QUIRK_OMITS_CONTENT_CREATORS);
- gabble_presence_set_capabilities (presence, resource, cap_set, tmp, serial); /* TODO */
+ gabble_presence_set_capabilities (presence, resource, cap_set, NULL, serial);
gabble_capability_set_free (cap_set);
- g_ptr_array_unref (tmp);
}
}
@@ -1144,13 +1156,13 @@ set_caps_for (DiscoWaiter *waiter,
GabblePresenceCache *cache,
GabbleCapabilitySet *cap_set,
guint client_types,
+ GPtrArray *data_forms,
TpHandle responder_handle,
const gchar *responder_jid)
{
GabblePresence *presence = gabble_presence_cache_get (cache, waiter->handle);
GabbleCapabilitySet *old_cap_set;
const GabbleCapabilitySet *new_cap_set;
- GPtrArray *tmp = g_ptr_array_new ();
if (presence == NULL)
return;
@@ -1161,11 +1173,10 @@ set_caps_for (DiscoWaiter *waiter,
waiter->handle, responder_handle, responder_jid);
gabble_presence_set_capabilities (presence, waiter->resource, cap_set,
- tmp, waiter->serial); /* TODO */
+ data_forms, waiter->serial);
new_cap_set = gabble_presence_peek_caps (presence);
emit_capabilities_update (cache, waiter->handle, old_cap_set, new_cap_set);
gabble_capability_set_free (old_cap_set);
- g_ptr_array_unref (tmp);
if (gabble_presence_update_client_types (presence, waiter->resource,
client_types))
@@ -1226,6 +1237,29 @@ client_types_from_message (TpHandle handle,
return client_types;
}
+static GPtrArray *
+data_forms_from_message (WockyNode *node)
+{
+ GPtrArray *out = g_ptr_array_new_with_free_func (g_object_unref);
+
+ WockyNodeIter iter;
+ WockyNode *x_node = NULL;
+
+ wocky_node_iter_init (&iter, node, "x", WOCKY_XMPP_NS_DATA);
+ while (wocky_node_iter_next (&iter, &x_node))
+ {
+ WockyDataForm *form = wocky_data_form_new_from_node (x_node, NULL);
+
+ /* we've already parsed the reply to check the hash matches, so
+ * we can already guarantee these data forms will be parsed
+ * fine */
+ if (G_LIKELY (form != NULL))
+ g_ptr_array_add (out, form);
+ }
+
+ return out;
+}
+
static void
_signal_presences_updated (GabblePresenceCache *cache,
TpHandle handle)
@@ -1261,6 +1295,7 @@ _caps_disco_cb (GabbleDisco *disco,
gboolean jid_is_valid;
gpointer key;
guint client_types = 0;
+ GPtrArray *data_forms = NULL;
cache = GABBLE_PRESENCE_CACHE (user_data);
priv = cache->priv;
@@ -1309,6 +1344,7 @@ _caps_disco_cb (GabbleDisco *disco,
cap_set = gabble_capability_set_new_from_stanza (query_result);
client_types = client_types_from_message (handle, query_result,
waiter_self->resource);
+ data_forms = data_forms_from_message (query_result);
/* 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
@@ -1330,7 +1366,7 @@ _caps_disco_cb (GabbleDisco *disco,
else if (g_str_equal (waiter_self->ver, computed_hash))
{
trust = capability_info_recvd (cache, node, handle, cap_set,
- CAPABILITY_BUNDLE_ENOUGH_TRUST, client_types);
+ CAPABILITY_BUNDLE_ENOUGH_TRUST, client_types, data_forms);
}
else
{
@@ -1345,7 +1381,8 @@ _caps_disco_cb (GabbleDisco *disco,
}
else
{
- trust = capability_info_recvd (cache, node, handle, cap_set, 1, client_types);
+ trust = capability_info_recvd (cache, node, handle, cap_set, 1,
+ client_types, data_forms);
}
/* Remove the node from the hash table without freeing the key or list of
@@ -1385,7 +1422,8 @@ _caps_disco_cb (GabbleDisco *disco,
{
DiscoWaiter *waiter = (DiscoWaiter *) i->data;
- set_caps_for (waiter, cache, cap_set, client_types, handle, jid);
+ set_caps_for (waiter, cache, cap_set, client_types,
+ data_forms, handle, jid);
emit_capabilities_discovered (cache, waiter->handle);
}
@@ -1413,7 +1451,8 @@ _caps_disco_cb (GabbleDisco *disco,
g_free (tmp);
}
- set_caps_for (waiter_self, cache, cap_set, client_types, handle, jid);
+ set_caps_for (waiter_self, cache, cap_set, client_types,
+ data_forms, handle, jid);
}
waiters = g_slist_remove (waiters, waiter_self);
@@ -1439,6 +1478,7 @@ _caps_disco_cb (GabbleDisco *disco,
}
gabble_capability_set_free (cap_set);
+ g_ptr_array_unref (data_forms);
OUT:
if (handle)
@@ -1503,12 +1543,9 @@ _process_caps_uri (GabblePresenceCache *cache,
if (presence)
{
guint types;
- GPtrArray *tmp = g_ptr_array_new ();
gabble_presence_set_capabilities (
- presence, resource, cap_set, tmp, serial);
-
- g_ptr_array_unref (tmp);
+ presence, resource, cap_set, info->data_forms, serial);
/* We can only get this information from actual disco replies,
* so we depend on having this information from the caps cache. */
@@ -2107,10 +2144,12 @@ gabble_presence_cache_add_own_caps (
GabblePresenceCache *cache,
const gchar *ver,
const GabbleCapabilitySet *cap_set,
- const GPtrArray *identities)
+ const GPtrArray *identities,
+ GPtrArray *data_forms)
{
gchar *uri = g_strdup_printf ("%s#%s", NS_GABBLE_CAPS, ver);
GabbleCapabilityInfo *info = capability_info_get (cache, uri);
+ GPtrArray *forms;
if (info->complete)
goto out;
@@ -2142,6 +2181,12 @@ gabble_presence_cache_add_own_caps (
info->trust = CAPABILITY_BUNDLE_ENOUGH_TRUST;
tp_intset_add (info->guys, cache->priv->conn->parent.self_handle);
+ forms = info->data_forms;
+ if (data_forms != NULL)
+ info->data_forms = g_ptr_array_ref (data_forms);
+ if (forms != NULL)
+ g_ptr_array_unref (forms);
+
/* FIXME: we should satisfy any waiters for this node now. fd.o bug #24619. */
out:
diff --git a/src/presence-cache.h b/src/presence-cache.h
index 44af23fb..7305d15b 100644
--- a/src/presence-cache.h
+++ b/src/presence-cache.h
@@ -65,6 +65,9 @@ struct _GabbleCapabilityInfo
/* array of GabbleDiscoIdentity or NULL */
GPtrArray *identities;
+ /* array of WockyDataForm or NULL */
+ GPtrArray *data_forms;
+
TpIntSet *guys;
guint trust;
@@ -107,7 +110,8 @@ void gabble_presence_cache_maybe_remove (GabblePresenceCache *cache,
void gabble_presence_cache_add_own_caps (GabblePresenceCache *cache,
const gchar *ver,
const GabbleCapabilitySet *cap_set,
- const GPtrArray *identities);
+ const GPtrArray *identities,
+ GPtrArray *data_forms);
const GabbleCapabilityInfo *gabble_presence_cache_peek_own_caps (
GabblePresenceCache *cache,
const gchar *ver);
diff --git a/src/presence.c b/src/presence.c
index aa156342..1f95529c 100644
--- a/src/presence.c
+++ b/src/presence.c
@@ -287,6 +287,9 @@ static void
extend_and_dup (GPtrArray *target,
GPtrArray *source)
{
+ if (source == NULL)
+ return;
+
g_ptr_array_foreach (source, (GFunc) g_object_ref, NULL);
tp_g_ptr_array_extend (target, source);
}