First support for IPv6 and multiple interfaces
This commit is contained in:
parent
9b535ba4b2
commit
396d7c3721
39
radicale.py
39
radicale.py
@ -38,6 +38,7 @@ arguments.
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import optparse
|
import optparse
|
||||||
|
import threading, signal
|
||||||
|
|
||||||
import radicale
|
import radicale
|
||||||
|
|
||||||
@ -97,8 +98,40 @@ if options.daemon:
|
|||||||
sys.exit()
|
sys.exit()
|
||||||
sys.stdout = sys.stderr = open(os.devnull, "w")
|
sys.stdout = sys.stderr = open(os.devnull, "w")
|
||||||
|
|
||||||
|
def exit (servers):
|
||||||
|
"""Cleanly shutdown all servers.
|
||||||
|
|
||||||
|
Might be called multiple times."""
|
||||||
|
for s in servers:
|
||||||
|
s.shutdown()
|
||||||
|
|
||||||
# Launch calendar server
|
# Launch calendar server
|
||||||
server_class = radicale.HTTPSServer if options.ssl else radicale.HTTPServer
|
server_class = radicale.HTTPSServer if options.ssl else radicale.HTTPServer
|
||||||
server = server_class(
|
servers = []
|
||||||
(options.host, options.port), radicale.CalendarHTTPHandler)
|
threads = []
|
||||||
server.serve_forever()
|
|
||||||
|
for host in (x.strip() for x in options.host.split(',')):
|
||||||
|
try:
|
||||||
|
server = server_class(
|
||||||
|
(host, options.port), radicale.CalendarHTTPHandler)
|
||||||
|
servers.append(server)
|
||||||
|
|
||||||
|
t = threading.Thread(target = server.serve_forever)
|
||||||
|
threads.append(t)
|
||||||
|
t.start()
|
||||||
|
except:
|
||||||
|
exit(servers)
|
||||||
|
raise
|
||||||
|
|
||||||
|
# clean exit on SIGTERM
|
||||||
|
signal.signal(signal.SIGTERM, lambda *a: exit(servers))
|
||||||
|
|
||||||
|
try:
|
||||||
|
while threads:
|
||||||
|
threads[0].join(1) # try one second
|
||||||
|
if threading.active_count() <= len(threads): # one thread died
|
||||||
|
break
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
exit(servers)
|
||||||
|
@ -80,9 +80,24 @@ class HTTPServer(server.HTTPServer):
|
|||||||
|
|
||||||
# Maybe a Pylint bug, ``__init__`` calls ``server.HTTPServer.__init__``
|
# Maybe a Pylint bug, ``__init__`` calls ``server.HTTPServer.__init__``
|
||||||
# pylint: disable=W0231
|
# pylint: disable=W0231
|
||||||
def __init__(self, address, handler):
|
def __init__(self, address, handler, bind_and_activate = True):
|
||||||
"""Create server."""
|
"""Create server."""
|
||||||
server.HTTPServer.__init__(self, address, handler)
|
self.use_ipv6 = ':' in address[0]
|
||||||
|
|
||||||
|
if self.use_ipv6:
|
||||||
|
self.address_family = socket.AF_INET6
|
||||||
|
|
||||||
|
# call superclass, but do NOT bind and activate, as we might change socketopts
|
||||||
|
server.HTTPServer.__init__(self, address, handler, bind_and_activate = False)
|
||||||
|
|
||||||
|
if self.use_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()
|
||||||
|
|
||||||
self.acl = acl.load()
|
self.acl = acl.load()
|
||||||
# pylint: enable=W0231
|
# pylint: enable=W0231
|
||||||
|
|
||||||
@ -91,22 +106,24 @@ class HTTPSServer(HTTPServer):
|
|||||||
"""HTTPS server."""
|
"""HTTPS server."""
|
||||||
PROTOCOL = "https"
|
PROTOCOL = "https"
|
||||||
|
|
||||||
def __init__(self, address, handler):
|
def __init__(self, address, handler, bind_and_activate = True):
|
||||||
"""Create server by wrapping HTTP socket in an SSL socket."""
|
"""Create server by wrapping HTTP socket in an SSL socket."""
|
||||||
# Fails with Python 2.5, import if needed
|
# Fails with Python 2.5, import if needed
|
||||||
# pylint: disable=F0401
|
# pylint: disable=F0401
|
||||||
import ssl
|
import ssl
|
||||||
# pylint: enable=F0401
|
# pylint: enable=F0401
|
||||||
|
|
||||||
HTTPServer.__init__(self, address, handler)
|
HTTPServer.__init__(self, address, handler, False)
|
||||||
self.socket = ssl.wrap_socket(
|
self.socket = ssl.wrap_socket(
|
||||||
socket.socket(self.address_family, self.socket_type),
|
self.socket, # we can use this, it is not bound yet
|
||||||
server_side=True,
|
server_side=True,
|
||||||
certfile=config.get("server", "certificate"),
|
certfile=config.get("server", "certificate"),
|
||||||
keyfile=config.get("server", "key"),
|
keyfile=config.get("server", "key"),
|
||||||
ssl_version=ssl.PROTOCOL_SSLv23)
|
ssl_version=ssl.PROTOCOL_SSLv23)
|
||||||
self.server_bind()
|
|
||||||
self.server_activate()
|
if bind_and_activate:
|
||||||
|
self.server_bind()
|
||||||
|
self.server_activate()
|
||||||
|
|
||||||
|
|
||||||
class CalendarHTTPHandler(server.BaseHTTPRequestHandler):
|
class CalendarHTTPHandler(server.BaseHTTPRequestHandler):
|
||||||
|
Loading…
Reference in New Issue
Block a user