Commit 58058cca authored by Vincent Pelletier's avatar Vincent Pelletier

Always call getaddrinfo on split host.

Fixes two bugs:
- IPv6 addresses are now put in canonical form.
- non-IPv6 port-less addresses are resolved.
Also, simplify url-style IPv6 parsing.
Also, rename "ip" into more generic naming "host".
parent 1c4cf8aa
...@@ -55,17 +55,6 @@ def makeChecksum(s): ...@@ -55,17 +55,6 @@ def makeChecksum(s):
return sha1(s).digest() return sha1(s).digest()
def resolve(hostname):
"""
Returns the first IP address that match with the given hostname
"""
try:
# an IP resolves to itself
_, _, address_list = socket.gethostbyname_ex(hostname)
except socket.gaierror:
return None
return address_list[0]
def getAddressType(address): def getAddressType(address):
"Return the type (IPv4 or IPv6) of an ip" "Return the type (IPv4 or IPv6) of an ip"
(host, port) = address (host, port) = address
...@@ -86,22 +75,22 @@ def getConnectorFromAddress(address): ...@@ -86,22 +75,22 @@ def getConnectorFromAddress(address):
return SOCKET_CONNECTORS_DICT[address_type] return SOCKET_CONNECTORS_DICT[address_type]
def parseNodeAddress(address, port_opt=None): def parseNodeAddress(address, port_opt=None):
if ']' in address: if address[:1] == '[':
(ip, port) = address.split(']') (host, port) = address[1:].split(']')
ip = ip.lstrip('[') if port[:1] == ':':
port = port.lstrip(':') port = port[1:]
if port == '': else:
port = port_opt port = port_opt
elif ':' in address: elif address.count(':') == 1:
(ip, port) = address.split(':') (host, port) = address.split(':')
ip = resolve(ip)
else: else:
ip = address host = address
port = port_opt port = port_opt
# Resolve (maybe) and cast to cannonical form
if port is None: # XXX: Always pick the first result. This might not be what is desired, and
raise ValueError # if so this function should either take a hint on the desired address type
return (ip, int(port)) # or return either raw host & port or getaddrinfo return value.
return socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)[0][4][:2]
def parseMasterList(masters, except_node=None): def parseMasterList(masters, except_node=None):
assert masters, 'At least one master must be defined' assert masters, 'At least one master must be defined'
......
...@@ -44,22 +44,24 @@ class UtilTests(NeoUnitTestBase): ...@@ -44,22 +44,24 @@ class UtilTests(NeoUnitTestBase):
address_type = getAddressType(('127.0.0.1', 0)) address_type = getAddressType(('127.0.0.1', 0))
self.assertEqual(address_type, socket.AF_INET) self.assertEqual(address_type, socket.AF_INET)
def _assertEqualParsedAddress(self, parsed, *args, **kw):
self.assertEqual(parsed, parseNodeAddress(*args, **kw))
def test_parseNodeAddress(self): def test_parseNodeAddress(self):
""" Parsing of addesses """ """ Parsing of addesses """
ip_address = parseNodeAddress('127.0.0.1:0') test = self._assertEqualParsedAddress
self.assertEqual(('127.0.0.1', 0), ip_address) local_address = socket.gethostbyname('localhost')
ip_address = parseNodeAddress('127.0.0.1:0', 100) http_port = socket.getservbyname('http')
self.assertEqual(('127.0.0.1', 0), ip_address) test(('127.0.0.1', 0), '127.0.0.1')
ip_address = parseNodeAddress('127.0.0.1', 500) test(('127.0.0.1', 10), '127.0.0.1:10', 500)
self.assertEqual(('127.0.0.1', 500), ip_address) test(('127.0.0.1', 500), '127.0.0.1', 500)
self.assertRaises(ValueError, parseNodeAddress, '127.0.0.1') test(('::1', 0), '[::1]')
ip_address = parseNodeAddress('[::1]:0') test(('::1', 10), '[::1]:10', 500)
self.assertEqual(('::1', 0), ip_address) test(('::1', 500), '[::1]', 500)
ip_address = parseNodeAddress('[::1]:0', 100) test(('::1', http_port), '[::1]:http')
self.assertEqual(('::1', 0), ip_address) test(('::1', 0), '[0::01]')
ip_address = parseNodeAddress('[::1]', 500) test((local_address, 0), 'localhost')
self.assertEqual(('::1', 500), ip_address) test((local_address, 10), 'localhost:10')
self.assertRaises(ValueError, parseNodeAddress, ('[::1]'))
def testReadBufferRead(self): def testReadBufferRead(self):
""" Append some chunk then consume the data """ """ Append some chunk then consume the data """
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment