提交 d5611a80 编写于 作者: L Lukáš Doktor

utils.network: Also check for UDP protocols in is_port_free

Binding port won't complain when port already opened for UDP packets and
we are trying to bind it for TCP packets. Let's do a combination.

Note I also tried:

    tuple(getattr(socket, _) for _ in dir(socket)
          if _.startswith('SOCK_')

to cover all of the protocols, but all the time they just reported
incorrect combination so let's just stick with the most common ones.
Signed-off-by: NLukáš Doktor <ldoktor@redhat.com>
上级 f574b789
...@@ -25,31 +25,41 @@ from .data_structures import Borg ...@@ -25,31 +25,41 @@ from .data_structures import Borg
#: Families taken into account in this class #: Families taken into account in this class
FAMILIES = (socket.AF_INET, socket.AF_INET6) FAMILIES = (socket.AF_INET, socket.AF_INET6)
#: Protocols taken into account in this class
PROTOCOLS = (socket.SOCK_STREAM, socket.SOCK_DGRAM)
def is_port_free(port, address): def is_port_free(port, address):
""" """
Return True if the given port is available for use. Return True if the given port is available for use.
Currently we only check for TCP connections on IPv4/6 Currently we only check for TCP/UDP connections on IPv4/6
:param port: Port number :param port: Port number
:param address: Socket address to bind or connect :param address: Socket address to bind or connect
""" """
s = None s = None
if address == "localhost":
protocols = PROTOCOLS
else:
# sock.connect always connects for UDP
protocols = (socket.SOCK_STREAM, )
try: try:
for family in FAMILIES: for family in FAMILIES:
try: for protocol in protocols:
s = socket.socket(family, socket.SOCK_STREAM) try:
if address == "localhost": s = socket.socket(family, protocol)
s.bind((address, port)) if address == "localhost":
else: s.bind((address, port))
s.connect((address, port)) else:
return False s.connect((address, port))
except socket.error: return False
if address == "localhost": except socket.error as exc:
return False if exc.errno in (93, 94): # Unsupported combinations
s.close() continue
if address == "localhost":
return False
s.close()
return True return True
finally: finally:
if s is not None: if s is not None:
......
...@@ -55,23 +55,26 @@ class FreePort(unittest.TestCase): ...@@ -55,23 +55,26 @@ class FreePort(unittest.TestCase):
else: else:
addrs = ipv6_addrs addrs = ipv6_addrs
for addr in addrs: for addr in addrs:
try: for protocol in network.PROTOCOLS:
sock = socket.socket(family, socket.SOCK_STREAM) try:
sock.bind((addr, port)) sock = socket.socket(family, protocol)
if network.is_port_free(port, "localhost"): sock.bind((addr, port))
bad.append("%s, %s: reports free" % (family, addr)) if network.is_port_free(port, "localhost"):
else: bad.append("%s, %s, %s: reports free"
good.append("%s, %s" % (family, addr)) % (family, protocol, addr))
except Exception as exc: else:
if getattr(exc, 'errno', None) in (-2, 2, 22, 94): good.append("%s, %s, %s" % (family, protocol,
skip.append("%s, %s: Not supported: %s" addr))
% (family, addr, exc)) except Exception as exc:
else: if getattr(exc, 'errno', None) in (-2, 2, 22, 94):
bad.append("%s, %s: Failed to bind: %s" skip.append("%s, %s, %s: Not supported: %s"
% (family, addr, exc)) % (family, protocol, addr, exc))
finally: else:
if sock is not None: bad.append("%s, %s, %s: Failed to bind: %s"
sock.close() % (family, protocol, addr, exc))
finally:
if sock is not None:
sock.close()
self.assertFalse(bad, "Following combinations failed:\n%s\n\n" self.assertFalse(bad, "Following combinations failed:\n%s\n\n"
"Following combinations passed:\n%s\n\n" "Following combinations passed:\n%s\n\n"
"Following combinations were skipped:\n%s" "Following combinations were skipped:\n%s"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册