change hint format to "tcp:HOST:PORT"

This commit is contained in:
Brian Warner 2015-03-12 15:20:06 -07:00
parent d71c8492c1
commit b27cbd19b6

View File

@ -1,5 +1,5 @@
from __future__ import print_function from __future__ import print_function
import threading, socket, SocketServer import re, threading, socket, SocketServer
from binascii import hexlify from binascii import hexlify
from ..util import ipaddrs from ..util import ipaddrs
from ..util.hkdf import HKDF from ..util.hkdf import HKDF
@ -72,30 +72,62 @@ def send_to(skt, data):
while sent < len(data): while sent < len(data):
sent += skt.send(data[sent:]) sent += skt.send(data[sent:])
def wait_for(skt, expected, hint): def wait_for(skt, expected, description):
got = b"" got = b""
while len(got) < len(expected): while len(got) < len(expected):
got += skt.recv(1) got += skt.recv(1)
if expected[:len(got)] != got: if expected[:len(got)] != got:
raise BadHandshake("got '%r' want '%r' on %s" % raise BadHandshake("got '%r' want '%r' on %s" %
(got, expected, hint)) (got, expected, description))
# The hint format is: TYPE,VALUE= /^([a-zA-Z0-9]+):(.*)$/ . VALUE depends
# upon TYPE, and it can have more colons in it. For TYPE=tcp (the only one
# currently defined), ADDR,PORT = /^(.*):(\d+)$/ , so ADDR can have colons.
# ADDR can be a hostname, ipv4 dotted-quad, or ipv6 colon-hex. If the hint
# publisher wants anonymity, their only hint's ADDR will end in .onion .
def parse_hint_tcp(hint):
# return tuple or None for an unparseable hint
mo = re.search(r'^([a-zA-Z0-9]+):(.*)$', hint)
if not mo:
print("unparseable hint '%s'" % (hint,))
return None
hint_type = mo.group(1)
if hint_type != "tcp":
print("unknown hint type '%s' in '%s'" % (hint_type, hint))
return None
hint_value = mo.group(2)
mo = re.search(r'^(.*):(\d+)$', hint_value)
if not mo:
print("unparseable TCP hint '%s'" % (hint,))
return None
hint_host = mo.group(1)
try:
hint_port = int(mo.group(2))
except ValueError:
print("non-numeric port in TCP hint '%s'" % (hint,))
return None
return hint_host, hint_port
def connector(owner, hint, description, def connector(owner, hint, description,
send_handshake, expected_handshake, relay_handshake=None): send_handshake, expected_handshake, relay_handshake=None):
addr,port = hint.split(",") parsed_hint = parse_hint_tcp(hint)
if not parsed_hint:
return # unparseable
addr,port = parsed_hint
skt = None skt = None
try: try:
skt = socket.create_connection((addr,port), skt = socket.create_connection((addr,port),
TIMEOUT) # timeout or ECONNREFUSED TIMEOUT) # timeout or ECONNREFUSED
skt.settimeout(TIMEOUT) skt.settimeout(TIMEOUT)
#print("socket(%s) connected" % (hint,)) #print("socket(%s) connected" % (description,))
if relay_handshake: if relay_handshake:
send_to(skt, relay_handshake) send_to(skt, relay_handshake)
wait_for(skt, "ok\n", hint) wait_for(skt, "ok\n", description)
#print("relay ready %r" % (hint,)) #print("relay ready %r" % (description,))
send_to(skt, send_handshake) send_to(skt, send_handshake)
wait_for(skt, expected_handshake, hint) wait_for(skt, expected_handshake, description)
#print("connector ready %r" % (hint,)) #print("connector ready %r" % (description,))
except Exception as e: except Exception as e:
try: try:
if skt: if skt:
@ -180,7 +212,7 @@ class Common:
def _start_server(self): def _start_server(self):
server = MyTCPServer(("", 0), None) server = MyTCPServer(("", 0), None)
_, port = server.server_address _, port = server.server_address
self.my_direct_hints = ["%s,%d" % (addr, port) self.my_direct_hints = ["tcp:%s:%d" % (addr, port)
for addr in ipaddrs.find_addresses()] for addr in ipaddrs.find_addresses()]
server.owner = self server.owner = self
server_thread = threading.Thread(target=server.serve_forever) server_thread = threading.Thread(target=server.serve_forever)
@ -232,7 +264,7 @@ class Common:
def _start_connector(self, hint, is_relay=False): def _start_connector(self, hint, is_relay=False):
description = "->%s" % (hint,) description = "->%s" % (hint,)
if is_relay: if is_relay:
description = "->relay@%s" % (hint,) description = "->relay:%s" % (hint,)
args = (self, hint, description, args = (self, hint, description,
self._send_this(), self._expect_this()) self._send_this(), self._expect_this())
if is_relay: if is_relay: