From bd1a199f3e9e1177ac2f17c7acd920ecf8f26a34 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Fri, 21 Dec 2018 22:39:10 -0500 Subject: [PATCH] start factoring Hints out to separate file shared between old transit.py and new _dilation/connector.py --- src/wormhole/_dilation/connector.py | 61 +---------------------------- src/wormhole/_hints.py | 58 +++++++++++++++++++++++++++ src/wormhole/transit.py | 61 +---------------------------- 3 files changed, 62 insertions(+), 118 deletions(-) create mode 100644 src/wormhole/_hints.py diff --git a/src/wormhole/_dilation/connector.py b/src/wormhole/_dilation/connector.py index f530039..8d7f4a5 100644 --- a/src/wormhole/_dilation/connector.py +++ b/src/wormhole/_dilation/connector.py @@ -1,7 +1,5 @@ from __future__ import print_function, unicode_literals -import sys -import re -from collections import defaultdict, namedtuple +from collections import defaultdict from binascii import hexlify import six from attr import attrs, attrib @@ -21,25 +19,7 @@ from ..observer import EmptyableSet from .connection import DilatedConnectionProtocol, KCM from .roles import LEADER - -# These namedtuples are "hint objects". The JSON-serializable dictionaries -# are "hint dicts". - -# DirectTCPV1Hint and TorTCPV1Hint mean the following protocol: -# * make a TCP connection (possibly via Tor) -# * send the sender/receiver handshake bytes first -# * expect to see the receiver/sender handshake bytes from the other side -# * the sender writes "go\n", the receiver waits for "go\n" -# * the rest of the connection contains transit data -DirectTCPV1Hint = namedtuple( - "DirectTCPV1Hint", ["hostname", "port", "priority"]) -TorTCPV1Hint = namedtuple("TorTCPV1Hint", ["hostname", "port", "priority"]) -# RelayV1Hint contains a tuple of DirectTCPV1Hint and TorTCPV1Hint hints (we -# use a tuple rather than a list so they'll be hashable into a set). For each -# one, make the TCP connection, send the relay handshake, then complete the -# rest of the V1 protocol. Only one hint per relay is useful. -RelayV1Hint = namedtuple("RelayV1Hint", ["hints"]) - +from .._hints import parse_hint_argv, DirectTCPV1Hint, TorTCPV1Hint, RelayV1Hint def describe_hint_obj(hint, relay, tor): prefix = "tor->" if tor else "->" @@ -53,43 +33,6 @@ def describe_hint_obj(hint, relay, tor): return prefix + str(hint) -def parse_hint_argv(hint, stderr=sys.stderr): - assert isinstance(hint, type("")) - # return tuple or None for an unparseable hint - priority = 0.0 - mo = re.search(r'^([a-zA-Z0-9]+):(.*)$', hint) - if not mo: - print("unparseable hint '%s'" % (hint,), file=stderr) - return None - hint_type = mo.group(1) - if hint_type != "tcp": - print("unknown hint type '%s' in '%s'" % (hint_type, hint), - file=stderr) - return None - hint_value = mo.group(2) - pieces = hint_value.split(":") - if len(pieces) < 2: - print("unparseable TCP hint (need more colons) '%s'" % (hint,), - file=stderr) - return None - mo = re.search(r'^(\d+)$', pieces[1]) - if not mo: - print("non-numeric port in TCP hint '%s'" % (hint,), file=stderr) - return None - hint_host = pieces[0] - hint_port = int(pieces[1]) - for more in pieces[2:]: - if more.startswith("priority="): - more_pieces = more.split("=") - try: - priority = float(more_pieces[1]) - except ValueError: - print("non-float priority= in TCP hint '%s'" % (hint,), - file=stderr) - return None - return DirectTCPV1Hint(hint_host, hint_port, priority) - - def parse_tcp_v1_hint(hint): # hint_struct -> hint_obj hint_type = hint.get("type", "") if hint_type not in ["direct-tcp-v1", "tor-tcp-v1"]: diff --git a/src/wormhole/_hints.py b/src/wormhole/_hints.py new file mode 100644 index 0000000..8955e97 --- /dev/null +++ b/src/wormhole/_hints.py @@ -0,0 +1,58 @@ +from __future__ import print_function, unicode_literals +import sys +import re +from collections import namedtuple + +# These namedtuples are "hint objects". The JSON-serializable dictionaries +# are "hint dicts". + +# DirectTCPV1Hint and TorTCPV1Hint mean the following protocol: +# * make a TCP connection (possibly via Tor) +# * send the sender/receiver handshake bytes first +# * expect to see the receiver/sender handshake bytes from the other side +# * the sender writes "go\n", the receiver waits for "go\n" +# * the rest of the connection contains transit data +DirectTCPV1Hint = namedtuple("DirectTCPV1Hint", + ["hostname", "port", "priority"]) +TorTCPV1Hint = namedtuple("TorTCPV1Hint", ["hostname", "port", "priority"]) +# RelayV1Hint contains a tuple of DirectTCPV1Hint and TorTCPV1Hint hints (we +# use a tuple rather than a list so they'll be hashable into a set). For each +# one, make the TCP connection, send the relay handshake, then complete the +# rest of the V1 protocol. Only one hint per relay is useful. +RelayV1Hint = namedtuple("RelayV1Hint", ["hints"]) + +def parse_hint_argv(hint, stderr=sys.stderr): + assert isinstance(hint, type(u"")) + # return tuple or None for an unparseable hint + priority = 0.0 + mo = re.search(r'^([a-zA-Z0-9]+):(.*)$', hint) + if not mo: + print("unparseable hint '%s'" % (hint, ), file=stderr) + return None + hint_type = mo.group(1) + if hint_type != "tcp": + print("unknown hint type '%s' in '%s'" % (hint_type, hint), + file=stderr) + return None + hint_value = mo.group(2) + pieces = hint_value.split(":") + if len(pieces) < 2: + print("unparseable TCP hint (need more colons) '%s'" % (hint, ), + file=stderr) + return None + mo = re.search(r'^(\d+)$', pieces[1]) + if not mo: + print("non-numeric port in TCP hint '%s'" % (hint, ), file=stderr) + return None + hint_host = pieces[0] + hint_port = int(pieces[1]) + for more in pieces[2:]: + if more.startswith("priority="): + more_pieces = more.split("=") + try: + priority = float(more_pieces[1]) + except ValueError: + print("non-float priority= in TCP hint '%s'" % (hint, ), + file=stderr) + return None + return DirectTCPV1Hint(hint_host, hint_port, priority) diff --git a/src/wormhole/transit.py b/src/wormhole/transit.py index 96d8f95..fa708fb 100644 --- a/src/wormhole/transit.py +++ b/src/wormhole/transit.py @@ -2,12 +2,11 @@ from __future__ import absolute_import, print_function import os -import re import socket import sys import time from binascii import hexlify, unhexlify -from collections import deque, namedtuple +from collections import deque import six from hkdf import Hkdf @@ -95,24 +94,7 @@ def build_sided_relay_handshake(key, side): "ascii") + b"\n" -# These namedtuples are "hint objects". The JSON-serializable dictionaries -# are "hint dicts". - -# DirectTCPV1Hint and TorTCPV1Hint mean the following protocol: -# * make a TCP connection (possibly via Tor) -# * send the sender/receiver handshake bytes first -# * expect to see the receiver/sender handshake bytes from the other side -# * the sender writes "go\n", the receiver waits for "go\n" -# * the rest of the connection contains transit data -DirectTCPV1Hint = namedtuple("DirectTCPV1Hint", - ["hostname", "port", "priority"]) -TorTCPV1Hint = namedtuple("TorTCPV1Hint", ["hostname", "port", "priority"]) -# RelayV1Hint contains a tuple of DirectTCPV1Hint and TorTCPV1Hint hints (we -# use a tuple rather than a list so they'll be hashable into a set). For each -# one, make the TCP connection, send the relay handshake, then complete the -# rest of the V1 protocol. Only one hint per relay is useful. -RelayV1Hint = namedtuple("RelayV1Hint", ["hints"]) - +from ._hints import parse_hint_argv, DirectTCPV1Hint, TorTCPV1Hint, RelayV1Hint def describe_hint_obj(hint): if isinstance(hint, DirectTCPV1Hint): @@ -123,45 +105,6 @@ def describe_hint_obj(hint): return str(hint) -def parse_hint_argv(hint, stderr=sys.stderr): - assert isinstance(hint, type(u"")) - # return tuple or None for an unparseable hint - priority = 0.0 - mo = re.search(r'^([a-zA-Z0-9]+):(.*)$', hint) - if not mo: - print("unparseable hint '%s'" % (hint, ), file=stderr) - return None - hint_type = mo.group(1) - if hint_type != "tcp": - print( - "unknown hint type '%s' in '%s'" % (hint_type, hint), file=stderr) - return None - hint_value = mo.group(2) - pieces = hint_value.split(":") - if len(pieces) < 2: - print( - "unparseable TCP hint (need more colons) '%s'" % (hint, ), - file=stderr) - return None - mo = re.search(r'^(\d+)$', pieces[1]) - if not mo: - print("non-numeric port in TCP hint '%s'" % (hint, ), file=stderr) - return None - hint_host = pieces[0] - hint_port = int(pieces[1]) - for more in pieces[2:]: - if more.startswith("priority="): - more_pieces = more.split("=") - try: - priority = float(more_pieces[1]) - except ValueError: - print( - "non-float priority= in TCP hint '%s'" % (hint, ), - file=stderr) - return None - return DirectTCPV1Hint(hint_host, hint_port, priority) - - TIMEOUT = 60 # seconds