]> granicus.if.org Git - libevent/commitdiff
Added evhttp max simultaneous connection limiting
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Tue, 30 Jan 2018 23:39:41 +0000 (15:39 -0800)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Tue, 30 Jan 2018 23:39:41 +0000 (15:39 -0800)
http-internal.h
http.c
include/event2/http.h

index 9e5b0f95020685a9ce5101221df327021cc8bd1a..e03c32db342efaaa1105d1cd4762949331be9ad2 100644 (file)
@@ -145,6 +145,8 @@ struct evhttp {
 
        /* All live connections on this host. */
        struct evconq connections;
+       int connection_max;
+       int connection_cnt;
 
        TAILQ_HEAD(vhostsq, evhttp) virtualhosts;
 
diff --git a/http.c b/http.c
index c0e7adfc2cdf6ffa430b06216410c7fe6f76db35..65530f0c9286ee27bb167cc6c2d0ee41436a8b6b 100644 (file)
--- a/http.c
+++ b/http.c
@@ -1222,6 +1222,7 @@ evhttp_connection_free(struct evhttp_connection *evcon)
        if (evcon->http_server != NULL) {
                struct evhttp *http = evcon->http_server;
                TAILQ_REMOVE(&http->connections, evcon, next);
+               http->connection_cnt--;
        }
 
        if (event_initialized(&evcon->retry_ev)) {
@@ -3852,6 +3853,21 @@ evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
                http->default_max_body_size = max_body_size;
 }
 
+void
+evhttp_set_max_connections(struct evhttp* http, int max_connections)
+{
+       if (max_connections < 0)
+               http->connection_max = 0;
+       else
+               http->connection_max = max_connections;
+}
+
+int
+evhttp_get_connection_count(struct evhttp* http)
+{
+       return http->connection_cnt;
+}
+
 void
 evhttp_set_default_content_type(struct evhttp *http,
        const char *content_type) {
@@ -4291,8 +4307,30 @@ evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
         */
        evcon->http_server = http;
        TAILQ_INSERT_TAIL(&http->connections, evcon, next);
+       http->connection_cnt++;
+
+       /* send "service unavailable" if we've reached the connection limit */
+       if (http->connection_max && http->connection_max < http->connection_cnt) {
+               struct evhttp_request *req;
+
+               if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL) {
+                       evhttp_connection_free(evcon);
+                       return;
+               }
+
+               req->evcon = evcon;     /* the request owns the connection */
+               req->flags |= EVHTTP_REQ_OWN_CONNECTION;
+               req->kind = EVHTTP_REQUEST;
+               /* note, req->remote_host not needed since we don't read */
+
+               TAILQ_INSERT_TAIL(&evcon->requests, req, next);
+
+               /* send error to client */
+               evcon->state = EVCON_WRITING;
+               bufferevent_enable(evcon->bufev, EV_READ); /* enable close events */
+               evhttp_send_error(req, HTTP_SERVUNAVAIL, NULL);
 
-       if (evhttp_associate_new_request_with_connection(evcon) == -1)
+       } else if (evhttp_associate_new_request_with_connection(evcon) == -1)
                evhttp_connection_free(evcon);
 }
 
index ed9acf45ca5de528937bc4c813bac95791aac971..2d3e4173e3e2e8d8454d5d5629d4ac2d3167f0a2 100644 (file)
@@ -222,6 +222,24 @@ void evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_siz
 EVENT2_EXPORT_SYMBOL
 void evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size);
 
+/**
+ * Set the maximum number of simultaneous connections for this server.
+ * A value of zero or less disables the limit.
+ *
+ * @param http the http server on which to set the max connection limit
+ * @param max_connections the maximum number of simultaneous connections or 0
+ */
+EVENT2_EXPORT_SYMBOL
+void evhttp_set_max_connections(struct evhttp* http, int max_connections);
+
+/**
+ * Get the current number of connections.
+ *
+ * @return The current number of connections for this server.
+ */
+EVENT2_EXPORT_SYMBOL
+int evhttp_get_connection_count(struct evhttp* http);
+
 /**
   Set the value to use for the Content-Type header when none was provided. If
   the content type string is NULL, the Content-Type header will not be