mirror of
https://github.com/certbot/certbot.git
synced 2026-08-03 03:32:13 +02:00
acme.standalone: expose original socket.error
This commit is contained in:
@@ -8,6 +8,7 @@ import socket
|
|||||||
import socketserver
|
import socketserver
|
||||||
import threading
|
import threading
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from acme import challenges
|
from acme import challenges
|
||||||
from acme import crypto_util
|
from acme import crypto_util
|
||||||
@@ -66,6 +67,9 @@ class BaseDualNetworkedServers:
|
|||||||
self.threads: List[threading.Thread] = []
|
self.threads: List[threading.Thread] = []
|
||||||
self.servers: List[socketserver.BaseServer] = []
|
self.servers: List[socketserver.BaseServer] = []
|
||||||
|
|
||||||
|
# Preserve socket error for re-raising, if no servers can be started
|
||||||
|
last_socket_err: Optional[socket.error] = None
|
||||||
|
|
||||||
# Must try True first.
|
# Must try True first.
|
||||||
# Ubuntu, for example, will fail to bind to IPv4 if we've already bound
|
# Ubuntu, for example, will fail to bind to IPv4 if we've already bound
|
||||||
# to IPv6. But that's ok, since it will accept IPv4 connections on the IPv6
|
# to IPv6. But that's ok, since it will accept IPv4 connections on the IPv6
|
||||||
@@ -82,7 +86,8 @@ class BaseDualNetworkedServers:
|
|||||||
logger.debug(
|
logger.debug(
|
||||||
"Successfully bound to %s:%s using %s", new_address[0],
|
"Successfully bound to %s:%s using %s", new_address[0],
|
||||||
new_address[1], "IPv6" if ip_version else "IPv4")
|
new_address[1], "IPv6" if ip_version else "IPv4")
|
||||||
except socket.error:
|
except socket.error as e:
|
||||||
|
last_socket_err = e
|
||||||
if self.servers:
|
if self.servers:
|
||||||
# Already bound using IPv6.
|
# Already bound using IPv6.
|
||||||
logger.debug(
|
logger.debug(
|
||||||
@@ -101,6 +106,9 @@ class BaseDualNetworkedServers:
|
|||||||
# bind to the same port for both servers.
|
# bind to the same port for both servers.
|
||||||
port = server.socket.getsockname()[1]
|
port = server.socket.getsockname()[1]
|
||||||
if not self.servers:
|
if not self.servers:
|
||||||
|
if last_socket_err:
|
||||||
|
raise last_socket_err
|
||||||
|
else: # pragma: no cover
|
||||||
raise socket.error("Could not bind to IPv4 or IPv6.")
|
raise socket.error("Could not bind to IPv4 or IPv6.")
|
||||||
|
|
||||||
def serve_forever(self):
|
def serve_forever(self):
|
||||||
|
|||||||
@@ -190,12 +190,18 @@ class BaseDualNetworkedServersTest(unittest.TestCase):
|
|||||||
|
|
||||||
@mock.patch("socket.socket.bind")
|
@mock.patch("socket.socket.bind")
|
||||||
def test_fail_to_bind(self, mock_bind):
|
def test_fail_to_bind(self, mock_bind):
|
||||||
mock_bind.side_effect = socket.error
|
from errno import EADDRINUSE
|
||||||
from acme.standalone import BaseDualNetworkedServers
|
from acme.standalone import BaseDualNetworkedServers
|
||||||
self.assertRaises(socket.error, BaseDualNetworkedServers,
|
|
||||||
|
mock_bind.side_effect = socket.error(EADDRINUSE, "Fake addr in use error")
|
||||||
|
|
||||||
|
with self.assertRaises(socket.error) as em:
|
||||||
|
BaseDualNetworkedServers(
|
||||||
BaseDualNetworkedServersTest.SingleProtocolServer,
|
BaseDualNetworkedServersTest.SingleProtocolServer,
|
||||||
('', 0),
|
('', 0), socketserver.BaseRequestHandler)
|
||||||
socketserver.BaseRequestHandler)
|
|
||||||
|
self.assertEqual(em.exception.errno, EADDRINUSE)
|
||||||
|
|
||||||
|
|
||||||
def test_ports_equal(self):
|
def test_ports_equal(self):
|
||||||
from acme.standalone import BaseDualNetworkedServers
|
from acme.standalone import BaseDualNetworkedServers
|
||||||
|
|||||||
Reference in New Issue
Block a user