[flashproxy/master] Isolate address family manipulation and name resolution within parse_addr_spec.

commit 23d3a7d9756c7bbb5ce6675102b3aefe97d28b32 Author: David Fifield <david@bamsoftware.com> Date: Sat Jul 28 12:25:23 2012 -0700 Isolate address family manipulation and name resolution within parse_addr_spec. facilitator wants to resolve the name given to the --relay option; most other places we want to insist on numeric address. The facilitator had a special version of parse_addr_spec that also returned the address family, in order to allow it to resolve the name itself. Now put all this special handling inside parse_addr_spec, controlled by a boolean parameter, and use one parse_addr_spec between facilitator and facilitator.cgi. --- fac.py | 46 +++++++++++++++++++++++++++++++++++++++++++--- facilitator | 24 ++++-------------------- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/fac.py b/fac.py index bace28c..b9ad435 100644 --- a/fac.py +++ b/fac.py @@ -1,7 +1,28 @@ import re import socket -def parse_addr_spec(spec, defhost = None, defport = None): +def parse_addr_spec(spec, defhost = None, defport = None, resolve = False): + """Parse a host:port specification and return a 2-tuple ("host", port) as + understood by the Python socket functions. + >>> parse_addr_spec("192.168.0.1:9999") + ('192.168.0.1', 9999) + + If defhost or defport are given, those parts of the specification may be + omitted; if so, they will be filled in with defaults. + >>> parse_addr_spec("192.168.0.2:8888", defhost="192.168.0.1", defport=9999) + ('192.168.0.2', 8888) + >>> parse_addr_spec(":8888", defhost="192.168.0.1", defport=9999) + ('192.168.0.1', 9999) + >>> parse_addr_spec("192.168.0.2:", defhost="192.168.0.1", defport=9999) + ('192.168.0.2', 9999) + >>> parse_addr_spec(":", defhost="192.168.0.1", defport=9999) + ('192.168.0.1', 9999) + + If resolve is true, then the host in the specification or the defhost may be + a domain name, which will be resolved. If resolve is false, then the host + must be a numeric IPv4 or IPv6 address. + + IPv6 addresses must be enclosed in square brackets.""" host = None port = None m = None @@ -32,9 +53,28 @@ def parse_addr_spec(spec, defhost = None, defport = None): af = 0 host = host or defhost port = port or defport - if not (host and port): + if host is None or port is None: raise ValueError("Bad address specification \"%s\"" % spec) - return af, host, int(port) + + # Now we have split around the colon and have a guess at the address family. + # Forward-resolve the name into an addrinfo struct. Real DNS resolution is + # done only if resolve is true; otherwise the address must be numeric. + if resolve: + flags = 0 + else: + flags = socket.AI_NUMERICHOST + try: + addrs = socket.getaddrinfo(host, port, af, socket.SOCK_STREAM, socket.IPPROTO_TCP, flags) + except socket.gaierror, e: + raise ValueError("Bad host or port: \"%s\" \"%s\": %s" % (host, port, str(e))) + if not addrs: + raise ValueError("Bad host or port: \"%s\" \"%s\"" % (host, port)) + + # Convert the result of socket.getaddrinfo (which is a 2-tuple for IPv4 and + # a 4-tuple for IPv6) into a (host, port) 2-tuple. + host, port = socket.getnameinfo(addrs[0][4], socket.NI_NUMERICHOST | socket.NI_NUMERICSERV) + port = int(port) + return host, port def format_addr(addr): host, port = addr diff --git a/facilitator b/facilitator index d1e25a4..99ef63d 100755 --- a/facilitator +++ b/facilitator @@ -33,10 +33,8 @@ class options(object): @staticmethod def set_relay_spec(spec): - af, host, port = fac.parse_addr_spec(spec, defport = DEFAULT_RELAY_PORT) - # Resolve to get an IP address. - addrs = socket.getaddrinfo(host, port, af) - options.relay_spec = fac.format_addr(addrs[0][4]) + spec = fac.parse_addr_spec(spec, defport = DEFAULT_RELAY_PORT, resolve = True) + options.relay_spec = fac.format_addr(spec) def usage(f = sys.stdout): print >> f, """\ @@ -92,22 +90,8 @@ class TCPReg(object): class Reg(object): @staticmethod def parse(spec, defhost = None, defport = None): - try: - af, host, port = fac.parse_addr_spec(spec, defhost, defport) - except ValueError: - pass - else: - try: - addrs = socket.getaddrinfo(host, port, af, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_NUMERICHOST) - except socket.gaierror, e: - raise ValueError("Bad host or port: \"%s\" \"%s\": %s" % (host, port, str(e))) - if not addrs: - raise ValueError("Bad host or port: \"%s\" \"%s\"" % (host, port)) - - host, port = socket.getnameinfo(addrs[0][4], socket.NI_NUMERICHOST | socket.NI_NUMERICSERV) - return TCPReg(host, int(port)) - - raise ValueError("Bad spec format: %s" % repr(spec)) + host, port = fac.parse_addr_spec(spec, defhost, defport) + return TCPReg(host, port) class RegSet(object): def __init__(self):
participants (1)
-
dcf@torproject.org