changeset 2148:a543eda2c923

core (memory/disco): getInfos now handle node + use client instead of profile in many methods
author Goffi <goffi@goffi.org>
date Sun, 12 Feb 2017 20:43:20 +0100
parents bca699faf416
children a0e6f7951bd7
files src/memory/disco.py src/plugins/plugin_misc_file.py src/plugins/plugin_misc_groupblog.py src/plugins/plugin_misc_ip.py src/plugins/plugin_xep_0033.py src/plugins/plugin_xep_0045.py src/plugins/plugin_xep_0055.py src/plugins/plugin_xep_0060.py src/plugins/plugin_xep_0065.py src/plugins/plugin_xep_0092.py src/plugins/plugin_xep_0115.py src/plugins/plugin_xep_0260.py src/plugins/plugin_xep_0277.py src/plugins/plugin_xep_0280.py src/plugins/plugin_xep_0300.py src/plugins/plugin_xep_0363.py
diffstat 16 files changed, 69 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- 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)
--- 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)
--- 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"))
--- 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)
--- 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)
--- 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
--- 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_))
 
 
--- 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
 
--- 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')
--- 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
--- 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
--- 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
 
--- 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
 
--- 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:
--- 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(),
--- 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: