From 83ea9da2b413cfe87dc8965b8ce0a184c7f5ca53 Mon Sep 17 00:00:00 2001 From: Unrud Date: Fri, 10 Jun 2016 14:36:44 +0200 Subject: [PATCH] Limit number of parallel connections --- config | 3 +++ radicale/__init__.py | 18 ++++++++++++++++-- radicale/__main__.py | 2 ++ radicale/config.py | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/config b/config index 4228a5e..313f29a 100644 --- a/config +++ b/config @@ -24,6 +24,9 @@ # File storing the PID in daemon mode #pid = +# Max parallel connections +#max_connections = 20 + # Max size of request body (bytes) #max_content_length = 10000000 diff --git a/radicale/__init__.py b/radicale/__init__.py index b1cdc52..03727f5 100644 --- a/radicale/__init__.py +++ b/radicale/__init__.py @@ -29,9 +29,11 @@ should have been included in this package. import os import pprint import base64 +import contextlib import socket import socketserver import ssl +import threading import wsgiref.simple_server import re import zlib @@ -57,6 +59,7 @@ class HTTPServer(wsgiref.simple_server.WSGIServer): # These class attributes must be set before creating instance client_timeout = None + max_connections = None def __init__(self, address, handler, bind_and_activate=True): """Create server.""" @@ -76,6 +79,13 @@ class HTTPServer(wsgiref.simple_server.WSGIServer): self.server_bind() self.server_activate() + if self.max_connections: + self.connections_guard = threading.BoundedSemaphore( + self.max_connections) + else: + # use dummy context manager + self.connections_guard = contextlib.suppress() + def get_request(self): # Set timeout for client _socket, address = super().get_request() @@ -106,11 +116,15 @@ class HTTPSServer(HTTPServer): class ThreadedHTTPServer(socketserver.ThreadingMixIn, HTTPServer): - pass + def process_request_thread(self, request, client_address): + with self.connections_guard: + return super().process_request_thread(request, client_address) class ThreadedHTTPSServer(socketserver.ThreadingMixIn, HTTPSServer): - pass + def process_request_thread(self, request, client_address): + with self.connections_guard: + return super().process_request_thread(request, client_address) class RequestHandler(wsgiref.simple_server.WSGIRequestHandler): diff --git a/radicale/__main__.py b/radicale/__main__.py index dc17905..4e8c73d 100644 --- a/radicale/__main__.py +++ b/radicale/__main__.py @@ -171,6 +171,8 @@ def run(): else: server_class = ThreadedHTTPServer server_class.client_timeout = configuration.getint("server", "timeout") + server_class.max_connections = configuration.getint("server", + "max_connections") if not configuration.getboolean("server", "dns_lookup"): RequestHandler.address_string = lambda self: self.client_address[0] diff --git a/radicale/config.py b/radicale/config.py index c639211..27f799b 100644 --- a/radicale/config.py +++ b/radicale/config.py @@ -34,6 +34,7 @@ INITIAL_CONFIG = { "hosts": "0.0.0.0:5232", "daemon": "False", "pid": "", + "max_connections": "20", "max_content_length": "10000000", "timeout": "10", "ssl": "False",