core (disco), plugin XEP-0115: client use + capabilities hash improvment:
- modified a couple of method from memory to use client instead of profile
- XEP-0115: don't use unique hash for all clients anymore, as disco can be different between clients/components, and even between clients (different identity for instance).
hash is now generated per client on each new session.
This commit is contained in:
parent
6f8834f9da
commit
7ffb8efb92
4 changed files with 64 additions and 73 deletions
|
|
@ -284,6 +284,9 @@ class Discovery(object):
|
|||
found_entities = set()
|
||||
|
||||
def infosCb(infos, entity):
|
||||
if entity is None:
|
||||
log.warning(_(u'received an item without jid'))
|
||||
return
|
||||
if identity is not None and identity not in infos.identities:
|
||||
return
|
||||
if features.issubset(infos.features):
|
||||
|
|
|
|||
|
|
@ -605,7 +605,8 @@ class Memory(object):
|
|||
@param profile_key: %(doc_profile_key)s
|
||||
@return: presence data: key=entity JID, value=presence data for this entity
|
||||
"""
|
||||
profile_cache = self._getProfileCache(profile_key)
|
||||
client = self.host.getClient(profile_key)
|
||||
profile_cache = self._getProfileCache(client)
|
||||
entities_presence = {}
|
||||
|
||||
for entity_jid, entity_data in profile_cache.iteritems():
|
||||
|
|
@ -641,14 +642,14 @@ class Memory(object):
|
|||
## Resources ##
|
||||
|
||||
def _getAllResource(self, jid_s, profile_key):
|
||||
client = self.host.getClient(profile_key)
|
||||
jid_ = jid.JID(jid_s)
|
||||
return self.getAllResources(jid_, profile_key)
|
||||
return self.getAllResources(client, jid_)
|
||||
|
||||
def getAllResources(self, entity_jid, profile_key):
|
||||
def getAllResources(self, client, entity_jid):
|
||||
"""Return all resource from jid for which we have had data in this session
|
||||
|
||||
@param entity_jid: bare jid of the entit
|
||||
@param profile_key: %(doc_profile_key)s
|
||||
@param entity_jid: bare jid of the entity
|
||||
return (list[unicode]): list of resources
|
||||
|
||||
@raise exceptions.UnknownEntityError: if entity is not in cache
|
||||
|
|
@ -656,7 +657,7 @@ class Memory(object):
|
|||
"""
|
||||
if entity_jid.resource:
|
||||
raise ValueError("getAllResources must be used with a bare jid (got {})".format(entity_jid))
|
||||
profile_cache = self._getProfileCache(profile_key)
|
||||
profile_cache = self._getProfileCache(client)
|
||||
try:
|
||||
entity_data = profile_cache[entity_jid.userhostJID()]
|
||||
except KeyError:
|
||||
|
|
@ -665,22 +666,21 @@ class Memory(object):
|
|||
resources.discard(None)
|
||||
return resources
|
||||
|
||||
def getAvailableResources(self, entity_jid, profile_key):
|
||||
def getAvailableResources(self, client, entity_jid):
|
||||
"""Return available resource for entity_jid
|
||||
|
||||
This method differs from getAllResources by returning only available resources
|
||||
@param entity_jid: bare jid of the entit
|
||||
@param profile_key: %(doc_profile_key)s
|
||||
return (list[unicode]): list of available resources
|
||||
|
||||
@raise exceptions.UnknownEntityError: if entity is not in cache
|
||||
"""
|
||||
available = []
|
||||
for resource in self.getAllResources(entity_jid, profile_key):
|
||||
for resource in self.getAllResources(client, entity_jid):
|
||||
full_jid = copy.copy(entity_jid)
|
||||
full_jid.resource = resource
|
||||
try:
|
||||
presence_data = self.getEntityDatum(full_jid, "presence", profile_key)
|
||||
presence_data = self.getEntityDatum(full_jid, "presence", client.profile)
|
||||
except KeyError:
|
||||
log.debug(u"Can't get presence data for {}".format(full_jid))
|
||||
else:
|
||||
|
|
@ -707,7 +707,7 @@ class Memory(object):
|
|||
except KeyError: # plugin not found
|
||||
pass
|
||||
try:
|
||||
resources = self.getAllResources(entity_jid, client.profile)
|
||||
resources = self.getAllResources(client, entity_jid)
|
||||
except exceptions.UnknownEntityError:
|
||||
log.warning(u"Entity is not in cache, we can't find any resource")
|
||||
return None
|
||||
|
|
@ -729,23 +729,13 @@ class Memory(object):
|
|||
|
||||
## Entities data ##
|
||||
|
||||
def _getProfileCache(self, profile_key):
|
||||
def _getProfileCache(self, client):
|
||||
"""Check profile validity and return its cache
|
||||
|
||||
@param profile: %(doc_profile_key)_s
|
||||
@param client: SatXMPPClient
|
||||
@return (dict): profile cache
|
||||
|
||||
@raise exceptions.ProfileUnknownError: if profile doesn't exist
|
||||
@raise exceptions.ProfileNotInCacheError: if there is no cache for this profile
|
||||
"""
|
||||
profile = self.getProfileName(profile_key)
|
||||
if not profile:
|
||||
raise exceptions.ProfileUnknownError(_('Trying to get entity data for a non-existant profile'))
|
||||
try:
|
||||
profile_cache = self._entities_cache[profile]
|
||||
except KeyError:
|
||||
raise exceptions.ProfileNotInCacheError
|
||||
return profile_cache
|
||||
return self._entities_cache[client.profile]
|
||||
|
||||
def setSignalOnUpdate(self, key, signal=True):
|
||||
"""Set a signal flag on the key
|
||||
|
|
@ -759,14 +749,13 @@ class Memory(object):
|
|||
else:
|
||||
self._key_signals.discard(key)
|
||||
|
||||
def getAllEntitiesIter(self, with_bare=False, profile_key=C.PROF_KEY_NONE):
|
||||
def getAllEntitiesIter(self, client, with_bare=False):
|
||||
"""Return an iterator of full jids of all entities in cache
|
||||
|
||||
@param with_bare: if True, include bare jids
|
||||
@param profile_key: %(doc_profile_key)s
|
||||
@return (list[unicode]): list of jids
|
||||
"""
|
||||
profile_cache = self._getProfileCache(profile_key)
|
||||
profile_cache = self._getProfileCache(client)
|
||||
# we construct a list of all known full jids (bare jid of entities x resources)
|
||||
for bare_jid, entity_data in profile_cache.iteritems():
|
||||
for resource in entity_data.iterkeys():
|
||||
|
|
@ -787,9 +776,10 @@ class Memory(object):
|
|||
@param silent(bool): if True, doesn't send signal to frontend, even if there is a signal flag (see setSignalOnUpdate)
|
||||
@param profile_key: %(doc_profile_key)s
|
||||
"""
|
||||
profile_cache = self._getProfileCache(profile_key)
|
||||
client = self.host.getClient(profile_key)
|
||||
profile_cache = self._getProfileCache(client)
|
||||
if entity_jid in (C.ENTITY_ALL_RESOURCES, C.ENTITY_ALL):
|
||||
entities = self.getAllEntitiesIter(entity_jid==C.ENTITY_ALL, profile_key)
|
||||
entities = self.getAllEntitiesIter(client, entity_jid==C.ENTITY_ALL)
|
||||
else:
|
||||
entities = (entity_jid,)
|
||||
|
||||
|
|
@ -814,9 +804,10 @@ class Memory(object):
|
|||
@raise exceptions.UnknownEntityError: if entity is not in cache
|
||||
@raise KeyError: key is not in cache
|
||||
"""
|
||||
profile_cache = self._getProfileCache(profile_key)
|
||||
client = self.host.getClient(profile_key)
|
||||
profile_cache = self._getProfileCache(client)
|
||||
if entity_jid in (C.ENTITY_ALL_RESOURCES, C.ENTITY_ALL):
|
||||
entities = self.getAllEntitiesIter(entity_jid==C.ENTITY_ALL, profile_key)
|
||||
entities = self.getAllEntitiesIter(client, entity_jid==C.ENTITY_ALL)
|
||||
else:
|
||||
entities = (entity_jid,)
|
||||
|
||||
|
|
@ -863,7 +854,8 @@ class Memory(object):
|
|||
continue
|
||||
return entity_data
|
||||
|
||||
profile_cache = self._getProfileCache(profile_key)
|
||||
client = self.host.getClient(profile_key)
|
||||
profile_cache = self._getProfileCache(client)
|
||||
ret_data = {}
|
||||
if entities_jids:
|
||||
for entity in entities_jids:
|
||||
|
|
@ -893,7 +885,8 @@ class Memory(object):
|
|||
|
||||
@raise exceptions.UnknownEntityError: if entity is not in cache
|
||||
"""
|
||||
profile_cache = self._getProfileCache(profile_key)
|
||||
client = self.host.getClient(profile_key)
|
||||
profile_cache = self._getProfileCache(client)
|
||||
try:
|
||||
entity_data = profile_cache[entity_jid.userhostJID()][entity_jid.resource]
|
||||
except KeyError:
|
||||
|
|
@ -925,7 +918,8 @@ class Memory(object):
|
|||
|
||||
@raise exceptions.UnknownEntityError: if entity is not in cache
|
||||
"""
|
||||
profile_cache = self._getProfileCache(profile_key)
|
||||
client = self.host.getClient(profile_key)
|
||||
profile_cache = self._getProfileCache(client)
|
||||
|
||||
if delete_all_resources:
|
||||
if entity_jid.resource:
|
||||
|
|
@ -1316,17 +1310,16 @@ class Memory(object):
|
|||
|
||||
## Misc ##
|
||||
|
||||
def isEntityAvailable(self, entity_jid, profile_key):
|
||||
def isEntityAvailable(self, client, entity_jid):
|
||||
"""Tell from the presence information if the given entity is available.
|
||||
|
||||
@param entity_jid (JID): the entity to check (if bare jid is used, all resources are tested)
|
||||
@param profile_key: %(doc_profile_key)s
|
||||
@return (bool): True if entity is available
|
||||
"""
|
||||
if not entity_jid.resource:
|
||||
return bool(self.getAvailableResources) # is any resource is available, entity is available
|
||||
return bool(self.getAvailableResources(client, entity_jid)) # is any resource is available, entity is available
|
||||
try:
|
||||
presence_data = self.getEntityDatum(entity_jid, "presence", profile_key)
|
||||
presence_data = self.getEntityDatum(entity_jid, "presence", client.profile)
|
||||
except KeyError:
|
||||
log.debug(u"No presence information for {}".format(entity_jid))
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -62,53 +62,47 @@ class XEP_0115(object):
|
|||
def getHandler(self, client):
|
||||
return XEP_0115_handler(self, client.profile)
|
||||
|
||||
def _checkHash(self, disco_d, profile):
|
||||
client = self.host.getClient(profile)
|
||||
client.caps_optimize = None
|
||||
|
||||
if XEP_0115.cap_hash is None:
|
||||
disco_d.addCallback(lambda dummy: self.host.hasFeature(client, NS_CAPS_OPTIMIZE))
|
||||
def updateOptimize(optimize):
|
||||
client.caps_optimize = optimize
|
||||
if optimize:
|
||||
log.info(_("Caps optimisation enabled"))
|
||||
client.caps_sent = False
|
||||
else:
|
||||
log.warning(_("Caps optimisation not available"))
|
||||
disco_d.addCallback(updateOptimize)
|
||||
disco_d.addCallback(lambda dummy: self.recalculateHash(profile))
|
||||
return True
|
||||
|
||||
def _presenceTrigger(self, client, obj):
|
||||
if XEP_0115.cap_hash is not None:
|
||||
if client.caps_optimize:
|
||||
if client.caps_sent:
|
||||
return True
|
||||
client.caps_sent = True
|
||||
obj.addChild(XEP_0115.c_elt)
|
||||
return True
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def recalculateHash(self, profile):
|
||||
client = self.host.getClient(profile)
|
||||
def profileConnected(self, client):
|
||||
# we have to calculate hash for client
|
||||
# because disco infos/identities may change between clients
|
||||
|
||||
# optimize check
|
||||
client._caps_optimize = yield self.host.hasFeature(client, NS_CAPS_OPTIMIZE)
|
||||
if client._caps_optimize:
|
||||
log.info(_(u"Caps optimisation enabled"))
|
||||
client._caps_sent = False
|
||||
else:
|
||||
log.warning(_(u"Caps optimisation not available"))
|
||||
|
||||
# hash generation
|
||||
_infos = yield client.discoHandler.info(client.jid, client.jid, '')
|
||||
disco_infos = disco.DiscoInfo()
|
||||
for item in _infos:
|
||||
disco_infos.append(item)
|
||||
cap_hash = self.host.memory.disco.generateHash(disco_infos)
|
||||
log.info("Our capability hash has been generated: [%s]" % cap_hash)
|
||||
disco_infos = disco.DiscoInfo()
|
||||
cap_hash = client._caps_hash = self.host.memory.disco.generateHash(disco_infos)
|
||||
log.info("Our capability hash has been generated: [{cap_hash}]".format(
|
||||
cap_hash = cap_hash))
|
||||
log.debug("Generating capability domish.Element")
|
||||
c_elt = domish.Element((NS_ENTITY_CAPABILITY, 'c'))
|
||||
c_elt['hash'] = 'sha-1'
|
||||
c_elt['node'] = C.APP_URL
|
||||
c_elt['ver'] = cap_hash
|
||||
XEP_0115.cap_hash = cap_hash
|
||||
XEP_0115.c_elt = c_elt
|
||||
if client.caps_optimize:
|
||||
client.caps_sent = False
|
||||
client._caps_elt = c_elt
|
||||
if client._caps_optimize:
|
||||
client._caps_sent = False
|
||||
if cap_hash not in self.host.memory.disco.hashes:
|
||||
self.host.memory.disco.hashes[cap_hash] = disco_infos
|
||||
self.host.memory.updateEntityData(client.jid, C.ENTITY_CAP_HASH, cap_hash, profile_key=profile)
|
||||
self.host.memory.updateEntityData(client.jid, C.ENTITY_CAP_HASH, cap_hash, profile_key=client.profile)
|
||||
|
||||
def _presenceTrigger(self, client, obj):
|
||||
if client._caps_optimize:
|
||||
if client._caps_sent:
|
||||
return True
|
||||
client.caps_sent = True
|
||||
obj.addChild(client._caps_elt)
|
||||
return True
|
||||
|
||||
|
||||
class XEP_0115_handler(XMPPHandler):
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ class XEP_0329(object):
|
|||
host.bridge.addMethod("FISList", ".plugin", in_sign='ssa{ss}s', out_sign='aa{ss}', method=self._listFiles, async=True)
|
||||
host.bridge.addMethod("FISSharePath", ".plugin", in_sign='ssss', out_sign='s', method=self._sharePath)
|
||||
host.trigger.add("XEP-0234_fileSendingRequest", self._fileSendingRequestTrigger)
|
||||
host.registerNamespace('fis', NS_FIS)
|
||||
|
||||
def getHandler(self, client):
|
||||
return XEP_0329_handler(self)
|
||||
|
|
|
|||
Loading…
Reference in a new issue