# HG changeset patch # User Goffi # Date 1521884677 -3600 # Node ID 8d82a62fa098233497ac2ae4bf0dfa73c53d4502 # Parent 772447ec070fe5764129b2bba9ab4d94cc64b8a5 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. diff -r 772447ec070f -r 8d82a62fa098 src/memory/disco.py --- a/src/memory/disco.py Wed Mar 21 19:13:22 2018 +0100 +++ b/src/memory/disco.py Sat Mar 24 10:44:37 2018 +0100 @@ -284,6 +284,9 @@ 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): diff -r 772447ec070f -r 8d82a62fa098 src/memory/memory.py --- a/src/memory/memory.py Wed Mar 21 19:13:22 2018 +0100 +++ b/src/memory/memory.py Sat Mar 24 10:44:37 2018 +0100 @@ -605,7 +605,8 @@ @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 @@ ## 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 @@ """ 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 @@ 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 @@ 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 @@ ## 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 @@ 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 @@ @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 @@ @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 @@ 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 @@ @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 @@ @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 @@ ## 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 diff -r 772447ec070f -r 8d82a62fa098 src/plugins/plugin_xep_0115.py --- a/src/plugins/plugin_xep_0115.py Wed Mar 21 19:13:22 2018 +0100 +++ b/src/plugins/plugin_xep_0115.py Sat Mar 24 10:44:37 2018 +0100 @@ -62,53 +62,47 @@ 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 + @defer.inlineCallbacks + def profileConnected(self, client): + # we have to calculate hash for client + # because disco infos/identities may change between clients - 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 + # 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")) - 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) + # 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): diff -r 772447ec070f -r 8d82a62fa098 src/plugins/plugin_xep_0329.py --- a/src/plugins/plugin_xep_0329.py Wed Mar 21 19:13:22 2018 +0100 +++ b/src/plugins/plugin_xep_0329.py Sat Mar 24 10:44:37 2018 +0100 @@ -204,6 +204,7 @@ 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)