[tor-commits] [flashproxy/master] split name-resolution behaviour out of parse_addr_spec to match flashproxy-common
infinity0 at torproject.org
infinity0 at torproject.org
Thu Nov 21 13:18:47 UTC 2013
commit d3e27be5f375a80917c84e0881aa5c78bfd3d1f1
Author: Ximin Luo <infinity0 at gmx.com>
Date: Mon Nov 18 19:15:29 2013 +0000
split name-resolution behaviour out of parse_addr_spec to match flashproxy-common
- keep named relays as names rather than numeric addresses
---
facilitator/fac.py | 38 +++++++++++++++++++---------------
facilitator/facilitator | 4 ++--
facilitator/facilitator-email-poller | 2 +-
facilitator/facilitator-test.py | 11 +++-------
4 files changed, 27 insertions(+), 28 deletions(-)
diff --git a/facilitator/fac.py b/facilitator/fac.py
index f5649b3..00c103c 100644
--- a/facilitator/fac.py
+++ b/facilitator/fac.py
@@ -50,7 +50,7 @@ def catch_epipe(fn):
raise
return ret
-def parse_addr_spec(spec, defhost = None, defport = None, resolve = False, nameOk = False):
+def parse_addr_spec(spec, defhost = None, defport = None):
"""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")
@@ -70,11 +70,6 @@ def parse_addr_spec(spec, defhost = None, defport = None, resolve = False, nameO
('192.168.0.1', 9999)
>>> parse_addr_spec("", defhost="192.168.0.1", defport=9999)
('192.168.0.1', 9999)
-
- If nameOk is true, then the host in the specification or the defhost may be
- a domain name. Otherwise, it must be a numeric IPv4 or IPv6 address.
- If resolve is true, this implies nameOk, and the host will be resolved.
-
IPv6 addresses must be enclosed in square brackets."""
host = None
port = None
@@ -105,19 +100,24 @@ def parse_addr_spec(spec, defhost = None, defport = None, resolve = False, nameO
port = port or defport
if host is None or port is None:
raise ValueError("Bad address specification \"%s\"" % spec)
+ return host, int(port)
+
+def resolve_to_ip(host, port, af=0, gai_flags=0):
+ """Resolves a host string to an IP address in canonical format.
+
+ Note: in many cases this is not necessary since the consumer of the address
+ can probably accept host names directly.
- # Now we have split around the colon and have a guess at the address family.
+ :param: host string to resolve; may be a DNS name or an IP address.
+ :param: port of the host
+ :param: af address family, default unspecified. set to socket.AF_INET or
+ socket.AF_INET6 to force IPv4 or IPv6 name resolution.
+ :returns: (IP address in canonical format, port)
+ """
# 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
- elif nameOk:
- # don't pass through the getaddrinfo numeric check, just return directly
- return host, int(port)
- else:
- flags = socket.AI_NUMERICHOST
try:
- addrs = socket.getaddrinfo(host, port, af, socket.SOCK_STREAM, socket.IPPROTO_TCP, flags)
+ addrs = socket.getaddrinfo(host, port, af, 0, 0, gai_flags)
except socket.gaierror, e:
raise ValueError("Bad host or port: \"%s\" \"%s\": %s" % (host, port, str(e)))
if not addrs:
@@ -126,8 +126,12 @@ def parse_addr_spec(spec, defhost = None, defport = None, resolve = False, nameO
# 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
+ return host, int(port)
+
+def canonical_ip(host, port, af=0):
+ """Convert an IP address to a canonical format. Identical to resolve_to_ip,
+ except that the host param must already be an IP address."""
+ return resolve_to_ip(host, port, af, gai_flags=socket.AI_NUMERICHOST)
def format_addr(addr):
host, port = addr
diff --git a/facilitator/facilitator b/facilitator/facilitator
index 9d90833..a2dd56a 100755
--- a/facilitator/facilitator
+++ b/facilitator/facilitator
@@ -290,7 +290,7 @@ class Handler(SocketServer.StreamRequestHandler):
if proxy_spec is None:
return self.error(u"GET missing FROM param")
try:
- proxy_addr = fac.parse_addr_spec(proxy_spec, defport=0)
+ proxy_addr = fac.canonical_ip(*fac.parse_addr_spec(proxy_spec, defport=0))
except ValueError, e:
return self.error(u"syntax error in proxy address %s: %s" % (safe_str(repr(proxy_spec)), safe_str(repr(str(e)))))
@@ -422,7 +422,7 @@ def parse_relay_file(servers, fp):
transport_spec, addr_spec = line.strip().split()
except ValueError, e:
raise ValueError("Wrong line format: %s." % repr(line))
- addr = fac.parse_addr_spec(addr_spec, defport=DEFAULT_RELAY_PORT, resolve=True)
+ addr = fac.parse_addr_spec(addr_spec, defport=DEFAULT_RELAY_PORT)
transport = Transport.parse(transport_spec)
if transport.outer not in options.outer_transports:
raise ValueError(u"Unrecognized transport: %s" % transport)
diff --git a/facilitator/facilitator-email-poller b/facilitator/facilitator-email-poller
index f087507..2efceec 100755
--- a/facilitator/facilitator-email-poller
+++ b/facilitator/facilitator-email-poller
@@ -222,7 +222,7 @@ try:
raise ValueError("could not find email or password on line %s" % (lineno0+1))
(imap_addr_spec, email_addr, email_password) = res.groups()
imap_addr = fac.parse_addr_spec(
- imap_addr_spec or "", DEFAULT_IMAP_HOST, DEFAULT_IMAP_PORT, nameOk=True)
+ imap_addr_spec or "", DEFAULT_IMAP_HOST, DEFAULT_IMAP_PORT)
break
else:
raise ValueError("no email line found")
diff --git a/facilitator/facilitator-test.py b/facilitator/facilitator-test.py
index 3a960fe..d63e0b5 100755
--- a/facilitator/facilitator-test.py
+++ b/facilitator/facilitator-test.py
@@ -346,14 +346,9 @@ class ParseAddrSpecTest(unittest.TestCase):
self.assertEqual(fac.parse_addr_spec(":", defhost="1234::1", defport=9999), ("1234::1", 9999))
self.assertEqual(fac.parse_addr_spec("", defhost="1234::1", defport=9999), ("1234::1", 9999))
- def test_noresolve(self):
- """Test that parse_addr_spec does not do DNS resolution by default."""
- self.assertRaises(ValueError, fac.parse_addr_spec, "example.com")
-
- def test_noresolve_nameok(self):
- """Test that nameok passes through a domain name without resolving it."""
- self.assertEqual(fac.parse_addr_spec("example.com:8888", defhost="other.com", defport=9999, nameOk=True), ("example.com", 8888))
- self.assertEqual(fac.parse_addr_spec("", defhost="other.com", defport=9999, nameOk=True), ("other.com", 9999))
+ def test_canonical_ip_noresolve(self):
+ """Test that canonical_ip does not do DNS resolution by default."""
+ self.assertRaises(ValueError, fac.canonical_ip, *fac.parse_addr_spec("example.com:80"))
class ParseTransactionTest(unittest.TestCase):
def test_empty_string(self):
More information about the tor-commits
mailing list