fallback to disco if clients don't support caps. Fixes #4071
This commit is contained in:
parent
b88162a198
commit
ca0bcbb527
|
@ -75,12 +75,15 @@ def client_supports(client_caps, requested_feature):
|
|||
else:
|
||||
return False
|
||||
|
||||
def create_suitable_client_caps(node, caps_hash, hash_method):
|
||||
def create_suitable_client_caps(node, caps_hash, hash_method, fjid=None):
|
||||
"""
|
||||
Create and return a suitable ClientCaps object for the given node,
|
||||
caps_hash, hash_method combination.
|
||||
"""
|
||||
if not node or not caps_hash:
|
||||
if fjid:
|
||||
client_caps = NoClientCaps(fjid)
|
||||
else:
|
||||
# improper caps, ignore client capabilities.
|
||||
client_caps = NullClientCaps()
|
||||
elif not hash_method:
|
||||
|
@ -172,6 +175,7 @@ class AbstractClientCaps(object):
|
|||
def __init__(self, caps_hash, node):
|
||||
self._hash = caps_hash
|
||||
self._node = node
|
||||
self._hash_method = None
|
||||
|
||||
def get_discover_strategy(self):
|
||||
return self._discover
|
||||
|
@ -228,6 +232,7 @@ class OldClientCaps(AbstractClientCaps):
|
|||
"""
|
||||
def __init__(self, caps_hash, node):
|
||||
AbstractClientCaps.__init__(self, caps_hash, node)
|
||||
self._hash_method = 'old'
|
||||
|
||||
def _lookup_in_cache(self, caps_cache):
|
||||
return caps_cache[('old', self._node + '#' + self._hash)]
|
||||
|
@ -238,6 +243,22 @@ class OldClientCaps(AbstractClientCaps):
|
|||
def _is_hash_valid(self, identities, features, dataforms):
|
||||
return True
|
||||
|
||||
class NoClientCaps(AbstractClientCaps):
|
||||
"""
|
||||
For clients that don't support XEP-0115
|
||||
"""
|
||||
def __init__(self, fjid):
|
||||
AbstractClientCaps.__init__(self, fjid, fjid)
|
||||
self._hash_method = 'no'
|
||||
|
||||
def _lookup_in_cache(self, caps_cache):
|
||||
return caps_cache[('no', self._node)]
|
||||
|
||||
def _discover(self, connection, jid):
|
||||
connection.discoverInfo(jid)
|
||||
|
||||
def _is_hash_valid(self, identities, features, dataforms):
|
||||
return True
|
||||
|
||||
class NullClientCaps(AbstractClientCaps):
|
||||
"""
|
||||
|
@ -258,6 +279,7 @@ class NullClientCaps(AbstractClientCaps):
|
|||
|
||||
def __init__(self):
|
||||
AbstractClientCaps.__init__(self, None, None)
|
||||
self._hash_method = 'dummy'
|
||||
|
||||
def _lookup_in_cache(self, caps_cache):
|
||||
# lookup something which does not exist to get a new CacheItem created
|
||||
|
@ -341,6 +363,7 @@ class CapsCache(object):
|
|||
def set_and_store(self, identities, features):
|
||||
self.identities = identities
|
||||
self.features = features
|
||||
if self.hash_method != 'no':
|
||||
self._logger.add_caps_entry(self.hash_method, self.hash,
|
||||
identities, features)
|
||||
self.status = CACHED
|
||||
|
@ -348,7 +371,9 @@ class CapsCache(object):
|
|||
def update_last_seen(self):
|
||||
if not self._recently_seen:
|
||||
self._recently_seen = True
|
||||
self._logger.update_caps_time(self.hash_method, self.hash)
|
||||
if self.hash_method != 'no':
|
||||
self._logger.update_caps_time(self.hash_method,
|
||||
self.hash)
|
||||
|
||||
def is_valid(self):
|
||||
"""
|
||||
|
@ -401,3 +426,10 @@ class CapsCache(object):
|
|||
discover(connection, jid)
|
||||
else:
|
||||
q.update_last_seen()
|
||||
|
||||
def forget_caps(self, client_caps):
|
||||
hash_method = client_caps._hash_method
|
||||
hash = client_caps._hash
|
||||
key = (hash_method, hash)
|
||||
if key in self.__cache:
|
||||
del self.__cache[key]
|
||||
|
|
|
@ -660,7 +660,27 @@ class StreamConflictReceivedEvent(nec.NetworkIncomingEvent):
|
|||
self.conn = self.base_event.conn
|
||||
return True
|
||||
|
||||
class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
|
||||
class PresenceHelperEvent:
|
||||
def _generate_show(self):
|
||||
self.show = self.stanza.getShow()
|
||||
if self.show not in ('chat', 'away', 'xa', 'dnd'):
|
||||
self.show = '' # We ignore unknown show
|
||||
if not self.ptype and not self.show:
|
||||
self.show = 'online'
|
||||
elif self.ptype == 'unavailable':
|
||||
self.show = 'offline'
|
||||
|
||||
def _generate_ptype(self):
|
||||
self.ptype = self.stanza.getType()
|
||||
if self.ptype == 'available':
|
||||
self.ptype = None
|
||||
rfc_types = ('unavailable', 'error', 'subscribe', 'subscribed',
|
||||
'unsubscribe', 'unsubscribed')
|
||||
if self.ptype and not self.ptype in rfc_types:
|
||||
self.ptype = None
|
||||
|
||||
class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent,
|
||||
PresenceHelperEvent):
|
||||
name = 'presence-received'
|
||||
base_network_events = ['raw-pres-received']
|
||||
|
||||
|
@ -674,15 +694,6 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
|
|||
self.keyID = helpers.prepare_and_validate_gpg_keyID(self.conn.name,
|
||||
self.jid, self.keyID)
|
||||
|
||||
def _generate_show(self):
|
||||
self.show = self.stanza.getShow()
|
||||
if self.show not in ('chat', 'away', 'xa', 'dnd'):
|
||||
self.show = '' # We ignore unknown show
|
||||
if not self.ptype and not self.show:
|
||||
self.show = 'online'
|
||||
elif self.ptype == 'unavailable':
|
||||
self.show = 'offline'
|
||||
|
||||
def _generate_prio(self):
|
||||
self.prio = self.stanza.getPriority()
|
||||
try:
|
||||
|
@ -690,15 +701,6 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
|
|||
except Exception:
|
||||
self.prio = 0
|
||||
|
||||
def _generate_ptype(self):
|
||||
self.ptype = self.stanza.getType()
|
||||
if self.ptype == 'available':
|
||||
self.ptype = None
|
||||
rfc_types = ('unavailable', 'error', 'subscribe', 'subscribed',
|
||||
'unsubscribe', 'unsubscribed')
|
||||
if self.ptype and not self.ptype in rfc_types:
|
||||
self.ptype = None
|
||||
|
||||
def generate(self):
|
||||
self.conn = self.base_event.conn
|
||||
self.stanza = self.base_event.stanza
|
||||
|
@ -1489,7 +1491,8 @@ class PingErrorEvent(nec.NetworkIncomingEvent):
|
|||
name = 'ping-error'
|
||||
base_network_events = []
|
||||
|
||||
class CapsPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
|
||||
class CapsPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent,
|
||||
PresenceHelperEvent):
|
||||
name = 'caps-presence-received'
|
||||
base_network_events = ['raw-pres-received']
|
||||
|
||||
|
@ -1509,6 +1512,8 @@ class CapsPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
|
|||
self.get_jid_resource()
|
||||
except Exception:
|
||||
return
|
||||
self._generate_ptype()
|
||||
self._generate_show()
|
||||
self._extract_caps_from_presence()
|
||||
return True
|
||||
|
||||
|
|
|
@ -52,8 +52,13 @@ class ConnectionCaps(object):
|
|||
def _nec_caps_presence_received(self, obj):
|
||||
if obj.conn.name != self._account:
|
||||
return
|
||||
obj.client_caps = self._create_suitable_client_caps(obj.node,
|
||||
obj.caps_hash, obj.hash_method, obj.fjid)
|
||||
if obj.show == 'offline' and obj.client_caps._hash_method == 'no':
|
||||
self._capscache.forget_caps(obj.client_caps)
|
||||
obj.client_caps = self._create_suitable_client_caps(obj.node,
|
||||
obj.caps_hash, obj.hash_method)
|
||||
else:
|
||||
self._capscache.query_client_of_jid_if_unknown(self, obj.fjid,
|
||||
obj.client_caps)
|
||||
self._update_client_caps_of_contact(obj)
|
||||
|
|
Loading…
Reference in New Issue