-
Notifications
You must be signed in to change notification settings - Fork 442
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1435 from pbiering/fix-1313
Fix 1313 by rework server listen code
- Loading branch information
Showing
2 changed files
with
15 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
# Copyright © 2008 Pascal Halter | ||
# Copyright © 2008-2017 Guillaume Ayoub | ||
# Copyright © 2017-2019 Unrud <[email protected]> | ||
# Copyright © 2024-2024 Peter Bieringer <[email protected]> | ||
# | ||
# This library is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
|
@@ -22,7 +23,6 @@ | |
""" | ||
|
||
import errno | ||
import http | ||
import select | ||
import socket | ||
|
@@ -283,45 +283,22 @@ def serve(configuration: config.Configuration, | |
servers = {} | ||
try: | ||
hosts: List[Tuple[str, int]] = configuration.get("server", "hosts") | ||
for address in hosts: | ||
# Try to bind sockets for IPv4 and IPv6 | ||
possible_families = (socket.AF_INET, socket.AF_INET6) | ||
bind_ok = False | ||
for i, family in enumerate(possible_families): | ||
is_last = i == len(possible_families) - 1 | ||
for AddressPort in hosts: | ||
# retrieve IPv4/IPv6 address of address | ||
try: | ||
getaddrinfo = socket.getaddrinfo(AddressPort[0], AddressPort[1], 0, socket.SOCK_STREAM, socket.IPPROTO_TCP) | ||
except OSError as e: | ||
logger.warn("cannot retrieve IPv4 or IPv6 address of '%s': %s" % (format_address(AddressPort), e)) | ||
continue | ||
logger.debug("getaddrinfo of '%s': %s" % (format_address(AddressPort), getaddrinfo)) | ||
for (AddressFamily, SocketKind, SocketProto, SocketFlags, SocketAddress) in getaddrinfo: | ||
logger.debug("try to create server socket on '%s'" % (format_address(SocketAddress))) | ||
try: | ||
server = server_class(configuration, family, address, | ||
RequestHandler) | ||
server = server_class(configuration, AddressFamily, (SocketAddress[0], SocketAddress[1]), RequestHandler) | ||
except OSError as e: | ||
# Ignore unsupported families (only one must work) | ||
if ((bind_ok or not is_last) and ( | ||
isinstance(e, socket.gaierror) and ( | ||
# Hostname does not exist or doesn't have | ||
# address for address family | ||
# Linux: temporary failure in name resolution (-3) | ||
e.errno == socket.EAI_AGAIN or | ||
# macOS: IPv6 address for INET address family | ||
e.errno == socket.EAI_NONAME or | ||
# Address not for address family | ||
e.errno == COMPAT_EAI_ADDRFAMILY or | ||
e.errno == COMPAT_EAI_NODATA) or | ||
# Workaround for PyPy | ||
str(e) == "address family mismatched" or | ||
# Address family not available (e.g. IPv6 disabled) | ||
# macOS: IPv4 address for INET6 address family with | ||
# IPV6_V6ONLY set | ||
e.errno == errno.EADDRNOTAVAIL or | ||
# Device or resource busy (16) | ||
e.errno == errno.EBUSY or | ||
# Address family not supported | ||
e.errno == errno.EAFNOSUPPORT or | ||
# Protocol not supported | ||
e.errno == errno.EPROTONOSUPPORT)): | ||
continue | ||
raise RuntimeError("Failed to start server %r: %s" % ( | ||
format_address(address), e)) from e | ||
logger.warn("cannot create server socket on '%s': %s" % (format_address(SocketAddress), e)) | ||
continue | ||
servers[server.socket] = server | ||
bind_ok = True | ||
server.set_app(application) | ||
logger.info("Listening on %r%s", | ||
format_address(server.server_address), | ||
|