# HG changeset patch # User Goffi # Date 1553069327 -3600 # Node ID 31a5038cdf798df85642d2e04254ac221b0ecbea # Parent 88f10630d5ea0234ed93ef733c0a795f22a6767f plugin XEP-0384: small refactoring to encrypt messages + bugfix: encryptMessage is now called in a loop, because problems may happen by steps (e.g. trust issue after getting missing bundles). Fixed a mix between "if" and "elif" in problems handling, diff -r 88f10630d5ea -r 31a5038cdf79 sat/plugins/plugin_xep_0384.py --- a/sat/plugins/plugin_xep_0384.py Wed Mar 20 09:08:37 2019 +0100 +++ b/sat/plugins/plugin_xep_0384.py Wed Mar 20 09:08:47 2019 +0100 @@ -783,27 +783,28 @@ ## triggers @defer.inlineCallbacks - def handleProblems(self, client, entity, bundles, problems): - """Try to solve problem found by EncryptMessage + def handleProblems(self, client, entity, bundles, expect_problems, problems): + """Try to solve problems found by EncryptMessage @param entity(jid.JID): bare jid of the destinee @param bundles(dict): bundles data as used in EncryptMessage already filled with known bundles, missing bundles need to be added to it + This dict is updated @param problems(list): exceptions raised by EncryptMessage - @return (dict): expect_problems arguments, used in EncryptMessage - this dict will list devices where problems can be ignored + @param expect_problems(dict): known problems to expect, used in encryptMessage + This dict will list devices where problems can be ignored (those devices won't receive the encrypted data) + This dict is updated """ # FIXME: not all problems are handled yet untrusted = {} missing_bundles = {} - expect_problems = {} cache = client._xep_0384_cache for problem in problems: if isinstance(problem, omemo_excpt.TrustException): untrusted[unicode(hash(problem))] = problem - if isinstance(problem, omemo_excpt.MissingBundleException): + elif isinstance(problem, omemo_excpt.MissingBundleException): pb_entity = jid.JID(problem.bare_jid) entity_cache = cache.setdefault(pb_entity, {}) entity_bundles = bundles.setdefault(pb_entity, {}) @@ -819,8 +820,8 @@ problem.device) expect_problems.setdefault(problem.bare_jid, set()).add( problem.device) - elif isinstance(problem, omemo_excpt.NoEligibleDevicesException): - pass + else: + raise problem for peer_jid, devices in missing_bundles.iteritems(): devices_s = [unicode(d) for d in devices] @@ -859,33 +860,41 @@ profile=client.profile) yield self.trustUICb(answer, trust_data, expect_problems, client.profile) - defer.returnValue(expect_problems) - @defer.inlineCallbacks def encryptMessage(self, client, entity_bare_jid, message): omemo_session = client._xep_0384_session + expect_problems = {} + bundles = {} + loop_idx = 0 try: - # first try may fail, in case of e.g. trust issue or missing bundle - encrypted = yield omemo_session.encryptMessage( - entity_bare_jid, - message) - except omemo_excpt.EncryptionProblemsException as e: - # we know the problem to solve, we can try to fix them - bundles = {} - expect_problems = yield self.handleProblems(client, entity_bare_jid, bundles, - e.problems) - # and try an encryption again. - try: - encrypted = yield omemo_session.encryptMessage( - entity_bare_jid, - message, - bundles, - expect_problems = expect_problems) - except omemo_excpt.EncryptionProblemsException as e: - log.warning( - _(u"Can't encrypt message for {entity}: {reason}".format( - entity=entity_bare_jid.full(), reason=e))) - raise e + while True: + if loop_idx > 10: + msg = _(u"Too many iterations in encryption loop") + log.error(msg) + raise exceptions.InternalError(msg) + # encryptMessage may fail, in case of e.g. trust issue or missing bundle + try: + encrypted = yield omemo_session.encryptMessage( + entity_bare_jid, + message, + bundles, + expect_problems = expect_problems) + except omemo_excpt.EncryptionProblemsException as e: + # we know the problem to solve, we can try to fix them + yield self.handleProblems( + client, + entity=entity_bare_jid, + bundles=bundles, + expect_problems=expect_problems, + problems=e.problems) + loop_idx += 1 + else: + break + except Exception as e: + log.warning( + _(u"Can't encrypt message for {entity}: {reason}".format( + entity=entity_bare_jid.full(), reason=str(e).decode('utf-8', 'replace')))) + raise e defer.returnValue(encrypted)