[telepathy-gabble/master] Correctly handle caps from bare JIDs.
Will Thompson
will.thompson at collabora.co.uk
Tue Jun 16 09:42:52 PDT 2009
---
src/presence.c | 21 +++++++
tests/twisted/Makefile.am | 1 +
tests/twisted/caps/from-bare-jid.py | 112 +++++++++++++++++++++++++++++++++++
3 files changed, 134 insertions(+), 0 deletions(-)
create mode 100644 tests/twisted/caps/from-bare-jid.py
diff --git a/src/presence.c b/src/presence.c
index 744fcd7..300cbc8 100644
--- a/src/presence.c
+++ b/src/presence.c
@@ -206,6 +206,18 @@ gabble_presence_set_capabilities (GabblePresence *presence,
GabblePresencePrivate *priv = GABBLE_PRESENCE_PRIV (presence);
GSList *i;
+ if (resource == NULL && priv->resources != NULL)
+ {
+ /* This is consistent with the handling of presence: if we get presence
+ * from a bare JID, we throw away all the resources, and if we get
+ * presence from a resource, any presence we stored from a bare JID is
+ * overridden by the aggregated presence.
+ */
+ DEBUG ("Ignoring caps for NULL resource since we have presence for "
+ "some resources");
+ return;
+ }
+
presence->caps = 0;
if (presence->per_channel_manager_caps != NULL)
{
@@ -215,6 +227,15 @@ gabble_presence_set_capabilities (GabblePresence *presence,
}
presence->per_channel_manager_caps = g_hash_table_new (NULL, NULL);
+ if (resource == NULL)
+ {
+ DEBUG ("adding caps %u to bare jid", caps);
+ presence->caps = caps;
+ gabble_presence_cache_update_cache_entry (
+ presence->per_channel_manager_caps, per_channel_manager_caps);
+ return;
+ }
+
DEBUG ("about to add caps %u to resource %s with serial %u", caps, resource,
serial);
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index 209bbaa..9e7b0d8 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -1,5 +1,6 @@
TWISTED_TESTS = \
avatar-requirements.py \
+ caps/from-bare-jid.py \
muc/name-conflict.py \
muc/renamed.py \
muc/roomlist.py \
diff --git a/tests/twisted/caps/from-bare-jid.py b/tests/twisted/caps/from-bare-jid.py
new file mode 100644
index 0000000..8e86c9a
--- /dev/null
+++ b/tests/twisted/caps/from-bare-jid.py
@@ -0,0 +1,112 @@
+"""
+Tests receiving capabilities from bare JIDs.
+"""
+
+from twisted.words.xish import xpath
+
+from servicetest import (
+ assertEquals, assertContains, assertDoesNotContain, EventPattern,
+ )
+from gabbletest import make_presence, exec_test
+from caps_helper import compute_caps_hash, make_caps_disco_reply
+import constants as cs
+import ns
+
+def test(q, bus, conn, stream):
+ conn.Connect()
+ q.expect('dbus-signal', signal='StatusChanged',
+ args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
+
+ client = 'http://example.com/perverse-client'
+ contact_bare_jid = 'edgecase at example.com'
+ contact_with_resource = 'edgecase at example.com/hi'
+ contact_handle = conn.RequestHandles(cs.HT_CONTACT, [contact_bare_jid])[0]
+
+ # Gabble gets a presence stanza from a bare JID, which is a tad surprising.
+ features = [
+ 'http://jabber.org/protocol/jingle',
+ 'http://jabber.org/protocol/jingle/description/audio',
+ 'http://www.google.com/transport/p2p',
+ ]
+ caps = {'node': client,
+ 'hash': 'sha-1',
+ 'ver': compute_caps_hash([], features, {}),
+ }
+ p = make_presence(contact_bare_jid, status='Hello', caps=caps)
+ stream.send(p)
+
+ # Gabble looks up the hash
+ event = q.expect('stream-iq', to=contact_bare_jid,
+ query_ns='http://jabber.org/protocol/disco#info')
+ query_node = xpath.queryForNodes('/iq/query', event.stanza)[0]
+ assertEquals(client + '#' + caps['ver'], query_node.attributes['node'])
+
+ # The bare jid replies
+ result = make_caps_disco_reply(stream, event.stanza, features, {})
+ stream.send(result)
+
+ # Gabble lets us know their caps have changed. (Gabble used to ignore the
+ # reply.)
+ streamed_media_caps = (contact_handle, cs.CHANNEL_TYPE_STREAMED_MEDIA,
+ 0, 3, 0, 1)
+ e = q.expect('dbus-signal', signal='CapabilitiesChanged')
+ assertContains(streamed_media_caps, e.args[0])
+
+ # Gabble gets another presence stanza from the bare JID, with different
+ # caps.
+ features.append(ns.TUBES)
+ caps = {'node': client,
+ 'hash': 'sha-1',
+ 'ver': compute_caps_hash([], features, {}),
+ }
+ p = make_presence(contact_bare_jid, status='Get out the abacus', caps=caps)
+ stream.send(p)
+
+ # Gabble looks up the new hash
+ disco2 = q.expect('stream-iq', to=contact_bare_jid,
+ query_ns='http://jabber.org/protocol/disco#info')
+ query_node = xpath.queryForNodes('/iq/query', disco2.stanza)[0]
+ assertEquals(client + '#' + caps['ver'], query_node.attributes['node'])
+
+ # This time, before the bare JID replies, Gabble gets a presence from the
+ # resourceful jid.
+ features_ = features + [ns.CHAT_STATES]
+ caps = {'node': client,
+ 'hash': 'sha-1',
+ 'ver': compute_caps_hash([], features_, {}),
+ }
+ p = make_presence(contact_with_resource, status='Count this', caps=caps)
+ stream.send(p)
+
+ # Gabble throws away presence from the bare JID when it gets presence from
+ # a resource (and vice versa), so it should now say the contact is
+ # incapable. Gabble also looks up the resourceful JID's hash.
+ cc, disco3 = q.expect_many(
+ EventPattern('dbus-signal', signal='CapabilitiesChanged'),
+ EventPattern('stream-iq', to=contact_with_resource,
+ query_ns='http://jabber.org/protocol/disco#info'),
+ )
+
+ assertDoesNotContain(streamed_media_caps, cc.args[0])
+
+ query_node = xpath.queryForNodes('/iq/query', disco3.stanza)[0]
+ assertEquals(client + '#' + caps['ver'], query_node.attributes['node'])
+
+ # The bare jid replies! Getting a disco reply from a bare JID when we've
+ # got presence from resources used to crash Gabble, but now it just ignores
+ # it.
+ result = make_caps_disco_reply(stream, disco2.stanza, features, {})
+ stream.send(result)
+
+ # Now the resourceful JID replies:
+ result = make_caps_disco_reply(stream, disco3.stanza, features_, {})
+ stream.send(result)
+
+ # Gabble should announce that the contact has acquired some caps.
+ e = q.expect('dbus-signal', signal='CapabilitiesChanged')
+ assertContains(streamed_media_caps, e.args[0])
+
+ conn.Disconnect()
+
+if __name__ == '__main__':
+ exec_test(test)
--
1.5.6.5
More information about the telepathy-commits
mailing list