Skip to content

Commit

Permalink
Merge commit 'refs/merge-requests/3' of git://gitorious.org/radicale/…
Browse files Browse the repository at this point in the history
…radicale into merge-requests/3
  • Loading branch information
liZe committed Apr 2, 2011
2 parents 140517a + 2848dbc commit d577661
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 10 deletions.
4 changes: 4 additions & 0 deletions config
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

[server]
# CalDAV server hostname, empty for all hostnames
# if you want to bind to multiple interfaces, seperate them with a comma
# NOTE: IPv6 adresses are configured to only allow IPv6 connections
# hence for binding to all IPv4 and IPv6 interfaces:
# host = ::, 0.0.0.0
host =
# CalDAV server port
port = 5232
Expand Down
41 changes: 38 additions & 3 deletions radicale.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import os
import sys
import optparse
import threading, signal

import radicale

Expand Down Expand Up @@ -97,8 +98,42 @@
sys.exit()
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
server_class = radicale.HTTPSServer if options.ssl else radicale.HTTPServer
server = server_class(
(options.host, options.port), radicale.CalendarHTTPHandler)
server.serve_forever()
servers = []
threads = []

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):
# at least one thread died -- exit all
break
except KeyboardInterrupt:
# no unwanted traceback :)
pass
finally:
exit(servers)
31 changes: 24 additions & 7 deletions radicale/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,24 @@ class HTTPServer(server.HTTPServer):

# Maybe a Pylint bug, ``__init__`` calls ``server.HTTPServer.__init__``
# pylint: disable=W0231
def __init__(self, address, handler):
def __init__(self, address, handler, bind_and_activate = True):
"""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()
# pylint: enable=W0231

Expand All @@ -96,22 +111,24 @@ class HTTPSServer(HTTPServer):
"""HTTPS server."""
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."""
# Fails with Python 2.5, import if needed
# pylint: disable=F0401
import ssl
# pylint: enable=F0401

HTTPServer.__init__(self, address, handler)
HTTPServer.__init__(self, address, handler, False)
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,
certfile=config.get("server", "certificate"),
keyfile=config.get("server", "key"),
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):
Expand Down

0 comments on commit d577661

Please sign in to comment.