Guillaume Ayoub 15 лет назад
Родитель
Сommit
6389411edd
2 измененных файлов с 51 добавлено и 2 удалено
  1. 6 2
      radicale.py
  2. 45 0
      radicale/__init__.py

+ 6 - 2
radicale.py

@@ -96,12 +96,14 @@ radicale.log.LOGGER.info("Starting Radicale")
 
 # Create calendar servers
 servers = []
+server_class = radicale.HTTPSServer if options.ssl else radicale.HTTPServer
 shutdown_program = threading.Event()
 
 for host in options.hosts.split(','):
     address, port = host.strip().rsplit(':', 1)
     address, port = address.strip('[] '), int(port)
-    servers.append(make_server(address, port, radicale.Application()))
+    servers.append(
+        make_server(address, port, radicale.Application(), server_class))
 
 # SIGTERM and SIGINT (aka KeyboardInterrupt) should just mark this for shutdown
 signal.signal(signal.SIGTERM, lambda *_: shutdown_program.set())
@@ -117,9 +119,11 @@ def serve_forever(server):
 # Start the servers in a different loop to avoid possible race-conditions, when
 # a server exists but another server is added to the list at the same time
 for server in servers:
-    threading.Thread(target=serve_forever, args=(server,)).start()
     radicale.log.LOGGER.debug(
         "Listening to %s port %s" % (server.server_name, server.server_port))
+    if options.ssl:
+        radicale.log.LOGGER.debug("Using SSL")
+    threading.Thread(target=serve_forever, args=(server,)).start()
 
 radicale.log.LOGGER.debug("Radicale server ready")
 

+ 45 - 0
radicale/__init__.py

@@ -31,6 +31,8 @@ should have been included in this package.
 import os
 import posixpath
 import base64
+import socket
+import wsgiref.simple_server
 # Manage Python2/3 different modules
 # pylint: disable=F0401
 try:
@@ -46,6 +48,49 @@ from radicale import acl, config, ical, log, xmlutils
 VERSION = "git"
 
 
+class HTTPServer(wsgiref.simple_server.WSGIServer):
+    """HTTP server."""
+    def __init__(self, address, handler, bind_and_activate=True):
+        """Create server."""
+        ipv6 = ":" in address[0]
+
+        if ipv6:
+            self.address_family = socket.AF_INET6
+
+        # Do not bind and activate, as we might change socketopts
+        wsgiref.simple_server.WSGIServer.__init__(self, address, handler, False)
+
+        if ipv6:
+            # Only allow IPv6 connections to the IPv6 socket
+            self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
+
+        if bind_and_activate:
+            self.server_bind()
+            self.server_activate()
+
+
+class HTTPSServer(HTTPServer):
+    """HTTPS server."""
+    def __init__(self, address, handler, bind_and_activate=True):
+        """Create server by wrapping HTTP socket in an SSL socket."""
+        # Fails with Python 2.5, import if needed
+        # pylint: disable=F0401
+        import ssl
+        # pylint: enable=F0401
+
+        HTTPServer.__init__(self, address, handler, False)
+        self.socket = ssl.wrap_socket(
+            self.socket,
+            server_side=True,
+            certfile=config.get("server", "certificate"),
+            keyfile=config.get("server", "key"),
+            ssl_version=ssl.PROTOCOL_SSLv23)
+
+        if bind_and_activate:
+            self.server_bind()
+            self.server_activate()
+
+
 class Application(object):
     """WSGI application managing calendars."""
     def __init__(self):