diff --git a/setup.py b/setup.py index c275e8b..f428250 100644 --- a/setup.py +++ b/setup.py @@ -48,13 +48,13 @@ setup(name="magic-wormhole", "click", "humanize", "txtorcon >= 18.0.2", # 18.0.2 fixes py3.4 support - "noiseprotocol", ], extras_require={ ':sys_platform=="win32"': ["pywin32"], "dev": ["mock", "tox", "pyflakes", "magic-wormhole-transit-relay==0.1.2", "magic-wormhole-mailbox-server==0.3.1"], + "dilate": ["noiseprotocol"], }, test_suite="wormhole.test", cmdclass=commands, diff --git a/src/wormhole/_dilation/_noise.py b/src/wormhole/_dilation/_noise.py new file mode 100644 index 0000000..bb4cf58 --- /dev/null +++ b/src/wormhole/_dilation/_noise.py @@ -0,0 +1,11 @@ +try: + from noise.exceptions import NoiseInvalidMessage +except ImportError: + class NoiseInvalidMessage(Exception): + pass + +try: + from noise.connection import NoiseConnection +except ImportError: + # allow imports to work on py2.7, even if dilation doesn't + NoiseConnection = None diff --git a/src/wormhole/_dilation/connection.py b/src/wormhole/_dilation/connection.py index d142eed..b8f3ec6 100644 --- a/src/wormhole/_dilation/connection.py +++ b/src/wormhole/_dilation/connection.py @@ -12,6 +12,7 @@ from .._interfaces import IDilationConnector from ..observer import OneShotObserver from .encode import to_be4, from_be4 from .roles import FOLLOWER +from ._noise import NoiseInvalidMessage # InboundFraming is given data and returns Frames (Noise wire-side # bytestrings). It handles the relay handshake and the prologue. The Frames it @@ -346,7 +347,6 @@ class _Record(object): @n.output() def process_handshake(self, frame): - from noise.exceptions import NoiseInvalidMessage try: payload = self._noise.read_message(frame) # Noise can include unencrypted data in the handshake, but we don't @@ -359,7 +359,6 @@ class _Record(object): @n.output() def decrypt_message(self, frame): - from noise.exceptions import NoiseInvalidMessage try: message = self._noise.decrypt(frame) except NoiseInvalidMessage as e: diff --git a/src/wormhole/_dilation/connector.py b/src/wormhole/_dilation/connector.py index 545d9de..aa5f8e0 100644 --- a/src/wormhole/_dilation/connector.py +++ b/src/wormhole/_dilation/connector.py @@ -1,7 +1,6 @@ from __future__ import print_function, unicode_literals from collections import defaultdict from binascii import hexlify -import six from attr import attrs, attrib from attr.validators import instance_of, provides, optional from automat import MethodicalMachine @@ -15,13 +14,14 @@ from .. import ipaddrs # TODO: move into _dilation/ from .._interfaces import IDilationConnector, IDilationManager from ..timing import DebugTiming from ..observer import EmptyableSet -from ..util import HKDF +from ..util import HKDF, to_unicode from .connection import DilatedConnectionProtocol, KCM from .roles import LEADER from .._hints import (DirectTCPV1Hint, TorTCPV1Hint, RelayV1Hint, parse_hint_argv, describe_hint_obj, endpoint_from_hint_obj, encode_hint) +from ._noise import NoiseConnection def build_sided_relay_handshake(key, side): @@ -37,14 +37,13 @@ PROLOGUE_FOLLOWER = b"Magic-Wormhole Dilation Handshake v1 Follower\n\n" NOISEPROTO = b"Noise_NNpsk0_25519_ChaChaPoly_BLAKE2s" def build_noise(): - from noise.connection import NoiseConnection return NoiseConnection.from_name(NOISEPROTO) @attrs @implementer(IDilationConnector) class Connector(object): _dilation_key = attrib(validator=instance_of(type(b""))) - _transit_relay_location = attrib(validator=optional(instance_of(str))) + _transit_relay_location = attrib(validator=optional(instance_of(type(u"")))) _manager = attrib(validator=provides(IDilationManager)) _reactor = attrib() _eventual_queue = attrib() @@ -265,7 +264,7 @@ class Connector(object): # lp is an IListeningPort self._listeners.add(lp) # for shutdown and tests portnum = lp.getHost().port - direct_hints = [DirectTCPV1Hint(six.u(addr), portnum, 0.0) + direct_hints = [DirectTCPV1Hint(to_unicode(addr), portnum, 0.0) for addr in addresses] self.listener_ready(direct_hints) d.addCallback(_listening) diff --git a/src/wormhole/test/dilate/test_connector.py b/src/wormhole/test/dilate/test_connector.py index 64291e5..2bb8809 100644 --- a/src/wormhole/test/dilate/test_connector.py +++ b/src/wormhole/test/dilate/test_connector.py @@ -7,8 +7,9 @@ from twisted.internet.task import Clock from twisted.internet.defer import Deferred from ...eventual import EventualQueue from ..._interfaces import IDilationManager, IDilationConnector -from ..._dilation import roles from ..._hints import DirectTCPV1Hint, RelayV1Hint, TorTCPV1Hint +from ..._dilation import roles +from ..._dilation._noise import NoiseConnection from ..._dilation.connection import KCM from ..._dilation.connector import (Connector, build_sided_relay_handshake, @@ -101,6 +102,8 @@ class TestConnector(unittest.TestCase): ]) def test_build_noise(self): + if not NoiseConnection: + raise unittest.SkipTest("noiseprotocol unavailable") build_noise() def test_build_protocol_leader(self): diff --git a/src/wormhole/test/dilate/test_record.py b/src/wormhole/test/dilate/test_record.py index 41b36e3..63a784c 100644 --- a/src/wormhole/test/dilate/test_record.py +++ b/src/wormhole/test/dilate/test_record.py @@ -2,7 +2,7 @@ from __future__ import print_function, unicode_literals import mock from zope.interface import alsoProvides from twisted.trial import unittest -from noise.exceptions import NoiseInvalidMessage +from ..._dilation._noise import NoiseInvalidMessage from ..._dilation.connection import (IFramer, Frame, Prologue, _Record, Handshake, Disconnect, Ping) diff --git a/src/wormhole/util.py b/src/wormhole/util.py index 26f234f..971de7e 100644 --- a/src/wormhole/util.py +++ b/src/wormhole/util.py @@ -12,6 +12,10 @@ def HKDF(skm, outlen, salt=None, CTXinfo=b""): def to_bytes(u): return unicodedata.normalize("NFC", u).encode("utf-8") +def to_unicode(any): + if isinstance(any, type(u"")): + return any + return any.decode("ascii") def bytes_to_hexstr(b): assert isinstance(b, type(b""))