提交 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
#: Families taken into account in this class
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):
"""
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 address: Socket address to bind or connect
"""
s = None
if address == "localhost":
protocols = PROTOCOLS
else:
# sock.connect always connects for UDP
protocols = (socket.SOCK_STREAM, )
try:
for family in FAMILIES:
try:
s = socket.socket(family, socket.SOCK_STREAM)
if address == "localhost":
s.bind((address, port))
else:
s.connect((address, port))
return False
except socket.error:
if address == "localhost":
return False
s.close()
for protocol in protocols:
try:
s = socket.socket(family, protocol)
if address == "localhost":
s.bind((address, port))
else:
s.connect((address, port))
return False
except socket.error as exc:
if exc.errno in (93, 94): # Unsupported combinations
continue
if address == "localhost":
return False
s.close()
return True
finally:
if s is not None:
......
......@@ -55,23 +55,26 @@ class FreePort(unittest.TestCase):
else:
addrs = ipv6_addrs
for addr in addrs:
try:
sock = socket.socket(family, socket.SOCK_STREAM)
sock.bind((addr, port))
if network.is_port_free(port, "localhost"):
bad.append("%s, %s: reports free" % (family, addr))
else:
good.append("%s, %s" % (family, addr))
except Exception as exc:
if getattr(exc, 'errno', None) in (-2, 2, 22, 94):
skip.append("%s, %s: Not supported: %s"
% (family, addr, exc))
else:
bad.append("%s, %s: Failed to bind: %s"
% (family, addr, exc))
finally:
if sock is not None:
sock.close()
for protocol in network.PROTOCOLS:
try:
sock = socket.socket(family, protocol)
sock.bind((addr, port))
if network.is_port_free(port, "localhost"):
bad.append("%s, %s, %s: reports free"
% (family, protocol, addr))
else:
good.append("%s, %s, %s" % (family, protocol,
addr))
except Exception as exc:
if getattr(exc, 'errno', None) in (-2, 2, 22, 94):
skip.append("%s, %s, %s: Not supported: %s"
% (family, protocol, addr, exc))
else:
bad.append("%s, %s, %s: Failed to bind: %s"
% (family, protocol, addr, exc))
finally:
if sock is not None:
sock.close()
self.assertFalse(bad, "Following combinations failed:\n%s\n\n"
"Following combinations passed:\n%s\n\n"
"Following combinations were skipped:\n%s"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册