# HG changeset patch # User Goffi # Date 1486928600 -3600 # Node ID a543eda2c9233183fce95e4f3064872ab5c0ad36 # Parent bca699faf416151838bd37830e97d72d015fc653 core (memory/disco): getInfos now handle node + use client instead of profile in many methods diff -r bca699faf416 -r a543eda2c923 src/memory/disco.py --- a/src/memory/disco.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/memory/disco.py Sun Feb 12 20:43:20 2017 +0100 @@ -104,57 +104,56 @@ return self.hashes.load() @defer.inlineCallbacks - def hasFeature(self, feature, jid_=None, profile=C.PROF_KEY_NONE): + def hasFeature(self, client, feature, jid_=None, node=u''): """Tell if an entity has the required feature @param feature: feature namespace @param jid_: jid of the target, or None for profile's server - @param profile: %(doc_profile)s + @param node(unicode): optional node to use for disco request @return: a Deferred which fire a boolean (True if feature is available) """ - disco_infos = yield self.getInfos(jid_, profile) + disco_infos = yield self.getInfos(client, jid_, node) defer.returnValue(feature in disco_infos.features) @defer.inlineCallbacks - def checkFeature(self, feature, jid_=None, profile=C.PROF_KEY_NONE): + def checkFeature(self, client, feature, jid_=None, node=u''): """Like hasFeature, but raise an exception is feature is not Found @param feature: feature namespace @param jid_: jid of the target, or None for profile's server - @param profile: %(doc_profile)s + @param node(unicode): optional node to use for disco request @raise: exceptions.FeatureNotFound """ - disco_infos = yield self.getInfos(jid_, profile) + disco_infos = yield self.getInfos(client, jid_, node) if not feature in disco_infos.features: raise failure.Failure(exceptions.FeatureNotFound) @defer.inlineCallbacks - def checkFeatures(self, features, jid_=None, identity=None, profile=C.PROF_KEY_NONE): + def checkFeatures(self, client, features, jid_=None, identity=None, node=u''): """Like checkFeature, but check several features at once, and check also identity @param features(iterable[unicode]): features to check @param jid_(jid.JID): jid of the target, or None for profile's server + @param node(unicode): optional node to use for disco request @param identity(None, tuple(unicode, unicode): if not None, the entity must have an identity with this (category, type) tuple - @param profile: %(doc_profile)s @raise: exceptions.FeatureNotFound """ - disco_infos = yield self.getInfos(jid_, profile) + disco_infos = yield self.getInfos(client, jid_, node) if not set(features).issubset(disco_infos.features): raise failure.Failure(exceptions.FeatureNotFound()) if identity is not None and identity not in disco_infos.identities: raise failure.Failure(exceptions.FeatureNotFound()) - def getInfos(self, jid_=None, profile=C.PROF_KEY_NONE): + def getInfos(self, client, jid_=None, node=u''): """get disco infos from jid_, filling capability hash if needed @param jid_: jid of the target, or None for profile's server - @param profile: %(doc_profile)s + @param node(unicode): optional node to use for disco request @return: a Deferred which fire disco.DiscoInfo """ - client = self.host.getClient(profile) if jid_ is None: jid_ = jid.JID(client.jid.host) try: @@ -178,7 +177,7 @@ self.host.memory.updateEntityData(jid_, C.ENTITY_CAP_HASH, CAP_HASH_ERROR, profile_key=client.profile) disco_infos = self.hashes[CAP_HASH_ERROR] return disco_infos - d = client.disco.requestInfo(jid_) + d = client.disco.requestInfo(jid_, nodeIdentifier=node) d.addCallback(infosCb) d.addErrback(infosEb) return d @@ -187,15 +186,13 @@ return defer.succeed(disco_infos) @defer.inlineCallbacks - def getItems(self, jid_=None, nodeIdentifier='', profile=C.PROF_KEY_NONE): + def getItems(self, client, jid_=None, node=u''): """get disco items from jid_, cache them for our own server - @param jid_ (jid.JID): jid of the target, or None for profile's server - @param nodeIdentifier (str): optional node identifier - @param profile: %(doc_profile)s + @param jid_(jid.JID): jid of the target, or None for profile's server + @param node(unicode): optional node to use for disco request @return: a Deferred which fire disco.DiscoItems """ - client = self.host.getClient(profile) if jid_ is None: jid_ = jid.JID(client.jid.host) # we cache items only for our own server @@ -204,11 +201,11 @@ log.debug(u"[%s] disco items are in cache" % jid_.full()) except (KeyError, exceptions.UnknownEntityError): log.debug(u"Caching [%s] disco items" % jid_.full()) - items = yield client.disco.requestItems(jid_, nodeIdentifier) + items = yield client.disco.requestItems(jid_, nodeIdentifier=node) self.host.memory.updateEntityData(jid_, "DISCO_ITEMS", items, profile_key=client.profile) else: try: - items = yield client.disco.requestItems(jid_, nodeIdentifier) + items = yield client.disco.requestItems(jid_, nodeIdentifier=node) except StanzaError as e: log.warning(u"Error while requesting items for {jid}: {reason}" .format(jid=jid_.full(), reason=e.condition)) @@ -222,13 +219,12 @@ log.warning(_(u"Error while requesting [%(jid)s]: %(error)s") % {'jid': entity_jid.full(), 'error': failure_.getErrorMessage()}) - def findServiceEntities(self, category, type_, jid_=None, profile=C.PROF_KEY_NONE): + def findServiceEntities(self, client, category, type_, jid_=None): """Return all available items of an entity which correspond to (category, type_) @param category: identity's category @param type_: identitiy's type @param jid_: the jid of the target server (None for profile's server) - @param profile: %(doc_profile)s @return: a set of found entities @raise defer.CancelledError: the request timed out """ @@ -241,18 +237,18 @@ def gotItems(items): defers_list = [] for item in items: - info_d = self.getInfos(item.entity, profile) + info_d = self.getInfos(client, item.entity) info_d.addCallbacks(infosCb, self._infosEb, [item.entity], None, [item.entity]) defers_list.append(info_d) return defer.DeferredList(defers_list) - d = self.getItems(jid_, profile=profile) + d = self.getItems(client, jid_) d.addCallback(gotItems) d.addCallback(lambda dummy: found_entities) reactor.callLater(TIMEOUT, d.cancel) # FIXME: one bad service make a general timeout return d - def findFeaturesSet(self, features, identity=None, jid_=None, profile=C.PROF_KEY_NONE): + def findFeaturesSet(self, client, features, identity=None, jid_=None): """Return entities (including jid_ and its items) offering features @param features: iterable of features which must be present @@ -261,7 +257,6 @@ @param profile: %(doc_profile)s @return: a set of found entities """ - client = self.host.getClient(profile) if jid_ is None: jid_ = jid.JID(client.jid.host) features = set(features) @@ -276,12 +271,12 @@ def gotItems(items): defer_list = [] for entity in [jid_] + [item.entity for item in items]: - infos_d = self.getInfos(entity, profile) + infos_d = self.getInfos(client, entity) infos_d.addCallbacks(infosCb, self._infosEb, [entity], None, [entity]) defer_list.append(infos_d) return defer.DeferredList(defer_list) - d = self.getItems(jid_, profile=profile) + d = self.getItems(client, jid_) d.addCallback(gotItems) d.addCallback(lambda dummy: found_entities) reactor.callLater(TIMEOUT, d.cancel) # FIXME: one bad service make a general timeout @@ -319,9 +314,9 @@ @return: list of tuples """ - profile = self.host.memory.getProfileName(profile_key) + client = self.host.getClient(profile_key) entity = jid.JID(entity_jid_s) - disco_infos = yield self.getInfos(entity, profile) + disco_infos = yield self.getInfos(client, entity) extensions = {} for form_type, form in disco_infos.extensions.items(): fields = [] @@ -341,20 +336,26 @@ [(cat, type_, name or '') for (cat, type_), name in disco_infos.identities.items()], extensions)) + def items2tuples(self, disco_items): + """convert disco items to tuple of strings + + @param disco_items(iterable[disco.DiscoItem]): items + @return G(tuple[unicode,unicode,unicode]): serialised items + """ + for item in disco_items: + if not item.entity: + log.warning(_(u"invalid item (no jid)")) + continue + yield (item.entity.full(), item.nodeIdentifier or '', item.name or '') + @defer.inlineCallbacks def _discoItems(self, entity_jid_s, profile_key=C.PROF_KEY_NONE): """ Discovery method for the bridge + @param entity_jid_s: entity we want to discover - @return: list of tuples""" - profile = self.host.memory.getProfileName(profile_key) + client = self.host.getClient(profile_key) entity = jid.JID(entity_jid_s) - disco_items = yield self.getItems(entity, profile=profile) - try: - ret = [(item.entity.full(), item.nodeIdentifier or '', item.name or '') for item in disco_items] - except AttributeError: - log.error(u"error while getting items from {entity}, it may result from invalid item(s)".format(entity=entity.full())) - # second try by ignoring empty items - ret = [(item.entity.full(), item.nodeIdentifier or '', item.name or '') for item in disco_items if item.entity] - + disco_items = yield self.getItems(client, entity) + ret = list(self.items2tuples(disco_items)) defer.returnValue(ret) diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_misc_file.py --- a/src/plugins/plugin_misc_file.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_misc_file.py Sun Feb 12 20:43:20 2017 +0100 @@ -211,12 +211,13 @@ @param profile: %(doc_profile)s @return (dict): action dictionary, with progress id in case of success, else xmlui message """ + client = self.host.getClient(profile) if not os.path.isfile(filepath): raise exceptions.DataError(u"The given path doesn't link to a file") if not filename: filename = os.path.basename(filepath) or '_' for namespace, callback, priority, method_name in self._file_callbacks: - has_feature = yield self.host.hasFeature(namespace, peer_jid, profile) + has_feature = yield self.host.hasFeature(client, namespace, peer_jid) if has_feature: log.info(u"{name} method will be used to send the file".format(name=method_name)) progress_id = yield callback(peer_jid, filepath, filename, file_desc, profile) diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_misc_groupblog.py --- a/src/plugins/plugin_misc_groupblog.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_misc_groupblog.py Sun Feb 12 20:43:20 2017 +0100 @@ -71,7 +71,7 @@ @defer.inlineCallbacks def profileConnected(self, client): try: - yield self.host.checkFeatures((NS_PUBSUB_GROUPBLOG,), profile=client.profile) + yield self.host.checkFeatures(client, (NS_PUBSUB_GROUPBLOG,)) except exceptions.FeatureNotFound: client.server_groupblog_available = False log.warning(_(u"Server is not able to manage item-access pubsub, we can't use group blog")) diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_misc_ip.py --- a/src/plugins/plugin_misc_ip.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_misc_ip.py Sun Feb 12 20:43:20 2017 +0100 @@ -254,8 +254,10 @@ if self._external_ip_cache is not None: defer.returnValue(self._external_ip_cache) + client = self.host.getClient(profile) + # we first try with XEP-0279 - ip_check = yield self.host.hasFeature(NS_IP_CHECK, profile=profile) + ip_check = yield self.host.hasFeature(client, NS_IP_CHECK) if ip_check: log.debug(u"Server IP Check available, we use it to retrieve our IP") client = self.host.getClient(profile) diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0033.py --- a/src/plugins/plugin_xep_0033.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0033.py Sun Feb 12 20:43:20 2017 +0100 @@ -101,7 +101,7 @@ self.sendAndStoreMessage(mess_data, entries, profile) log.debug("XEP-0033 took over") raise failure.Failure(exceptions.CancelError(u'Cancelled by XEP-0033')) - d = self.host.findFeaturesSet([NS_ADDRESS], profile=profile) + d = self.host.findFeaturesSet(client, [NS_ADDRESS]) d.addCallbacks(discoCallback, lambda dummy: discoCallback(None)) return d @@ -121,8 +121,8 @@ - redesign the database to save only one entry to the database - change the messageNew signal to eventually pass more than one recipient """ + client = self.host.getClient(profile) def send(mess_data, skip_send=False): - client = self.host.profiles[profile] d = defer.Deferred() if not skip_send: d.addCallback(client.sendMessageData) @@ -156,7 +156,7 @@ defer_list = [] for type_, jid_ in entries: d = defer.Deferred() - d.addCallback(self.host.findFeaturesSet, jid_=JID(JID(jid_).host), profile=profile) + d.addCallback(self.host.findFeaturesSet, client=client, jid_=JID(JID(jid_).host)) d.addCallbacks(discoCallback, errback, callbackArgs=[jid_], errbackArgs=[jid_]) d.callback([NS_ADDRESS]) defer_list.append(d) diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0045.py --- a/src/plugins/plugin_xep_0045.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0045.py Sun Feb 12 20:43:20 2017 +0100 @@ -362,8 +362,9 @@ @param jid_: entity which may have a MUC service, or None for our own server @param profile: %(doc_profile)s """ + client = self.host.getClient(profile) muc_service = None - services = yield self.host.findServiceEntities("conference", "text", jid_, profile=profile) + services = yield self.host.findServiceEntities(client, "conference", "text", jid_) for service in services: if ".irc." not in service.userhost(): # FIXME: @@ -712,7 +713,7 @@ msg = D_(u"{} is not a valid JID!".format(unparsed)) self.text_cmds.feedBack(client, msg, mess_data) return False - d = self.host.getDiscoItems(service, profile=client.profile) + d = self.host.getDiscoItems(client, service) d.addCallback(self._showListUI, client, service) return False diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0055.py --- a/src/plugins/plugin_xep_0055.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0055.py Sun Feb 12 20:43:20 2017 +0100 @@ -85,7 +85,8 @@ @param profile (unicode): %(doc_profile)s @return: list[jid.JID] """ - d = self.host.findFeaturesSet([NS_SEARCH], profile=profile) + client = self.host.getClient(profile) + d = self.host.findFeaturesSet(client, [NS_SEARCH]) return d.addCallback(lambda set_: list(set_)) diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0060.py --- a/src/plugins/plugin_xep_0060.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0060.py Sun Feb 12 20:43:20 2017 +0100 @@ -100,7 +100,7 @@ @defer.inlineCallbacks def profileConnected(self, client): - pubsub_services = yield self.host.findServiceEntities("pubsub", "service", profile=client.profile) + pubsub_services = yield self.host.findServiceEntities(client, "pubsub", "service") if pubsub_services: # we use one of the found services as our default pubsub service client.pubsub_service = pubsub_services.pop() @@ -228,7 +228,8 @@ # @param profile (str): %(doc_profile)s # @return: deferred which fire a list of nodes # """ - # d = self.host.getDiscoItems(service, nodeIdentifier, profile_key=profile) + # client = self.host.getClient(profile) + # d = self.host.getDiscoItems(client, service, nodeIdentifier) # d.addCallback(lambda result: [item.getAttribute('node') for item in result.toElement().children if item.hasAttribute('node')]) # return d diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0065.py --- a/src/plugins/plugin_xep_0065.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0065.py Sun Feb 12 20:43:20 2017 +0100 @@ -770,7 +770,7 @@ except KeyError: pass try: - proxy = (yield self.host.findServiceEntities('proxy', 'bytestreams', profile=profile)).pop() + proxy = (yield self.host.findServiceEntities(client, 'proxy', 'bytestreams')).pop() except (defer.CancelledError, StopIteration): notFound(server) iq_elt = client.IQ('get') diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0092.py --- a/src/plugins/plugin_xep_0092.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0092.py Sun Feb 12 20:43:20 2017 +0100 @@ -78,7 +78,7 @@ d = iq_elt.send() d.addCallback(self._gotVersion) return d - d = self.host.checkFeature(NS_VERSION, jid_, client.profile) + d = self.host.checkFeature(client, NS_VERSION, jid_) d.addCallback(getVersion) reactor.callLater(TIMEOUT, d.cancel) # XXX: timeout needed because some clients don't answer the IQ return d diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0115.py --- a/src/plugins/plugin_xep_0115.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0115.py Sun Feb 12 20:43:20 2017 +0100 @@ -66,7 +66,7 @@ client.caps_optimize = None if XEP_0115.cap_hash is None: - disco_d.addCallback(lambda dummy: self.host.hasFeature(NS_CAPS_OPTIMIZE, profile=profile)) + disco_d.addCallback(lambda dummy: self.host.hasFeature(client, NS_CAPS_OPTIMIZE)) def updateOptimize(optimize): client.caps_optimize = optimize if optimize: @@ -163,6 +163,6 @@ msg = failure.value.condition if hasattr(failure.value, 'condition') else failure.getErrorMessage() log.error(_(u"Couldn't retrieve disco info for {jid}: {error}").format(jid=from_jid.full(), error=msg)) - d = self.host.getDiscoInfos(from_jid, self.profile) + d = self.host.getDiscoInfos(self.parent, from_jid) d.addCallbacks(cb, eb) # TODO: me must manage the full algorithm described at XEP-0115 #5.4 part 3 diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0260.py --- a/src/plugins/plugin_xep_0260.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0260.py Sun Feb 12 20:43:20 2017 +0100 @@ -447,7 +447,7 @@ log.warning(u"Jingle IBB (XEP-0261) plugin is not available, we have to close the session") self._j.terminate(self._j.REASON_CONNECTIVITY_ERROR, session, client.profile) else: - d = self.host.hasFeature(self._jingle_ibb.NAMESPACE, session['peer_jid'], client.profile) + d = self.host.hasFeature(client, self._jingle_ibb.NAMESPACE, session['peer_jid']) d.addCallback(self._doFallback, session, content_name, client) return d diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0277.py --- a/src/plugins/plugin_xep_0277.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0277.py Sun Feb 12 20:43:20 2017 +0100 @@ -105,7 +105,8 @@ return {'available': C.BOOL_FALSE} def getFeatures(self, profile): - d = self.host.checkFeatures([], identity=('pubsub', 'pep'), profile=profile) + client = self.host.getClient(profile) + d = self.host.checkFeatures(client, [], identity=('pubsub', 'pep')) d.addCallbacks(self._checkFeaturesCb, self._checkFeaturesEb) return d diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0280.py --- a/src/plugins/plugin_xep_0280.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0280.py Sun Feb 12 20:43:20 2017 +0100 @@ -99,7 +99,7 @@ log.info(_(u"Not activating message carbons as requested in params")) return try: - yield self.host.checkFeatures((NS_CARBONS,), profile=client.profile) + yield self.host.checkFeatures(client, (NS_CARBONS,)) except exceptions.FeatureNotFound: log.warning(_(u"server doesn't handle message carbons")) else: diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0300.py --- a/src/plugins/plugin_xep_0300.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0300.py Sun Feb 12 20:43:20 2017 +0100 @@ -83,8 +83,9 @@ @return (D(unicode, None)): best available algorithm, or None if hashing is not possible """ + client = self.host.getClient(profile) for algo in reversed(XEP_0300.ALGOS): - has_feature = yield self.host.hasFeature(NS_HASHES_FUNCTIONS.format(algo), to_jid, profile) + has_feature = yield self.host.hasFeature(client, NS_HASHES_FUNCTIONS.format(algo), to_jid) if has_feature: log.debug(u"Best hashing algorithm found for {jid}: {algo}".format( jid=to_jid.full(), diff -r bca699faf416 -r a543eda2c923 src/plugins/plugin_xep_0363.py --- a/src/plugins/plugin_xep_0363.py Sun Feb 12 19:23:34 2017 +0100 +++ b/src/plugins/plugin_xep_0363.py Sun Feb 12 20:43:20 2017 +0100 @@ -110,7 +110,7 @@ try: entity = client.http_upload_service except AttributeError: - found_entities = yield self.host.findFeaturesSet((NS_HTTP_UPLOAD,), profile=client.profile) + found_entities = yield self.host.findFeaturesSet(client, (NS_HTTP_UPLOAD,)) try: entity = client.http_upload_service = iter(found_entities).next() except StopIteration: