[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

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



commit 23d3a7d9756c7bbb5ce6675102b3aefe97d28b32
Author: David Fifield <david@xxxxxxxxxxxxxxx>
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):



_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits