mirror of
https://github.com/certbot/certbot.git
synced 2026-07-28 00:35:50 +02:00
server_forever2/shutdown2
This commit is contained in:
+36
-1
@@ -4,6 +4,7 @@ import collections
|
||||
import functools
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
|
||||
import six
|
||||
@@ -52,18 +53,52 @@ class HTTPSServer(TLSServer, BaseHTTPServer.HTTPServer):
|
||||
|
||||
|
||||
class ACMEServerMixin: # pylint: disable=old-style-class,no-init
|
||||
"""ACME server common settings mixin."""
|
||||
"""ACME server common settings mixin.
|
||||
|
||||
.. warning::
|
||||
Subclasses have to init ``_stopped = False`` (it's not done here,
|
||||
because of old-style classes madness).
|
||||
|
||||
"""
|
||||
server_version = "ACME standalone client"
|
||||
allow_reuse_address = True
|
||||
|
||||
def serve_forever2(self):
|
||||
"""Serve forever, until other thread calls `shutdown2`."""
|
||||
while not self._stopped:
|
||||
self.handle_request()
|
||||
|
||||
def shutdown2(self):
|
||||
"""Shutdown server loop from `serve_forever2`."""
|
||||
self._stopped = True
|
||||
|
||||
# dummy request to terminate last server_forever2.handle_request()
|
||||
sock = socket.socket()
|
||||
try:
|
||||
sock.connect(self.socket.getsockname())
|
||||
except socket.error:
|
||||
pass # thread is probably already finished
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
self.server_close()
|
||||
|
||||
|
||||
class ACMETLSServer(HTTPSServer, ACMEServerMixin):
|
||||
"""ACME TLS Server."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._stopped = False
|
||||
HTTPSServer.__init__(self, *args, **kwargs)
|
||||
|
||||
|
||||
class ACMEServer(BaseHTTPServer.HTTPServer, ACMEServerMixin):
|
||||
"""ACME Server (non-TLS)."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._stopped = False
|
||||
BaseHTTPServer.HTTPServer.__init__(self, *args, **kwargs)
|
||||
|
||||
|
||||
class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
"""SimpleHTTP challenge handler.
|
||||
|
||||
@@ -25,6 +25,26 @@ class TLSServerTest(unittest.TestCase):
|
||||
server.server_close() # pylint: disable=no-member
|
||||
|
||||
|
||||
class ACMEServerMixinTest(unittest.TestCase):
|
||||
"""Tests for acme.standalone.ACMEServerMixin."""
|
||||
|
||||
def test_shutdown2_not_running(self):
|
||||
from acme.standalone import ACMEServer
|
||||
server = ACMEServer(("", 0), socketserver.BaseRequestHandler)
|
||||
server.shutdown2()
|
||||
server.shutdown2()
|
||||
|
||||
|
||||
class ACMEServerTest(unittest.TestCase):
|
||||
"""Test for acme.standalone.ACMEServer."""
|
||||
|
||||
def test_init(self):
|
||||
from acme.standalone import ACMEServer
|
||||
server = ACMEServer(("", 0), socketserver.BaseRequestHandler)
|
||||
# pylint: disable=protected-access
|
||||
self.assertFalse(server._stopped)
|
||||
|
||||
|
||||
class ACMESimpleHTTPTLSServerTestEndToEnd(unittest.TestCase):
|
||||
"""End-to-end test for ACME TLS server with SimpleHTTP."""
|
||||
|
||||
@@ -45,12 +65,13 @@ class ACMESimpleHTTPTLSServerTestEndToEnd(unittest.TestCase):
|
||||
self.server = ACMETLSServer(('', 0), handler, certs=self.certs)
|
||||
self.server_thread = threading.Thread(
|
||||
# pylint: disable=no-member
|
||||
target=self.server.handle_request)
|
||||
target=self.server.serve_forever2)
|
||||
self.server_thread.start()
|
||||
|
||||
self.port = self.server.socket.getsockname()[1]
|
||||
|
||||
def tearDown(self):
|
||||
self.server.shutdown2()
|
||||
self.server_thread.join()
|
||||
|
||||
def test_index(self):
|
||||
|
||||
@@ -53,33 +53,15 @@ class ServerManager(object):
|
||||
except socket.error as error:
|
||||
errors.StandaloneBindError(error, port)
|
||||
|
||||
stop = threading.Event()
|
||||
thread = threading.Thread(
|
||||
target=self._serve,
|
||||
args=(server, stop),
|
||||
)
|
||||
thread = threading.Thread(target=server.serve_forever2)
|
||||
thread.start()
|
||||
self.servers[port] = (server, thread, stop)
|
||||
self.servers[port] = (server, thread)
|
||||
return self.servers[port]
|
||||
|
||||
def _serve(self, server, stop):
|
||||
while not stop.is_set():
|
||||
server.handle_request()
|
||||
|
||||
def stop(self, port):
|
||||
"""Stop ACME server running on the specified ``port``."""
|
||||
server, thread, stop = self.servers[port]
|
||||
stop.set()
|
||||
|
||||
# dummy request to terminate last handle_request()
|
||||
sock = socket.socket()
|
||||
try:
|
||||
sock.connect(server.socket.getsockname())
|
||||
except socket.error:
|
||||
pass # thread is probably already finished
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
server, thread = self.servers[port]
|
||||
server.shutdown2()
|
||||
thread.join()
|
||||
del self.servers[port]
|
||||
|
||||
@@ -170,7 +152,7 @@ class Authenticator(common.Plugin):
|
||||
|
||||
for achall in achalls:
|
||||
if isinstance(achall, achallenges.SimpleHTTP):
|
||||
server, _, _ = self.servers.run(self.config.simple_http_port, tls=tls)
|
||||
server, _ = self.servers.run(self.config.simple_http_port, tls=tls)
|
||||
response, validation = achall.gen_response_and_validation(tls=tls)
|
||||
self.simple_http_resources.add(
|
||||
acme_standalone.SimpleHTTPRequestHandler.SimpleHTTPResource(
|
||||
@@ -179,7 +161,7 @@ class Authenticator(common.Plugin):
|
||||
cert = self.simple_http_cert
|
||||
domain = achall.domain
|
||||
else: # DVSNI
|
||||
server, _, _ = self.servers.run(self.config.dvsni_port, tls=True)
|
||||
server, _ = self.servers.run(self.config.dvsni_port, tls=True)
|
||||
response, cert, _ = achall.gen_cert_and_response(self.key)
|
||||
domain = response.z_domain
|
||||
self.certs[domain] = (self.key, cert)
|
||||
@@ -195,6 +177,6 @@ class Authenticator(common.Plugin):
|
||||
for achall in achalls:
|
||||
if achall in server_achalls:
|
||||
server_achalls.remove(achall)
|
||||
for port, (server, _, _) in self.servers.items():
|
||||
for port, (server, _) in self.servers.items():
|
||||
if not self.served[server]:
|
||||
self.servers.stop(port)
|
||||
|
||||
Reference in New Issue
Block a user