#if HAVE_LIBNGHTTP2
"http-port 80;\n"
"https-port 443;\n"
+ "http-listener-clients 300;\n"
#endif
"\
prefetch 2 9;\n\
EXTERN in_port_t named_g_httpport INIT(0);
EXTERN isc_dscp_t named_g_dscp INIT(-1);
+EXTERN in_port_t named_g_http_listener_clients INIT(0);
+
EXTERN named_server_t *named_g_server INIT(NULL);
/*
result = named_config_get(maps, "https-port", &obj);
INSIST(result == ISC_R_SUCCESS);
named_g_httpsport = (in_port_t)cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = named_config_get(maps, "http-listener-clients", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ named_g_http_listener_clients = cfg_obj_asuint32(obj);
#endif
/*
const cfg_obj_t *eplist = NULL;
const cfg_listelt_t *elt = NULL;
size_t len = 1, i = 0;
+ uint32_t max_clients = named_g_http_listener_clients;
+ ns_server_t *server = NULL;
+ isc_quota_t *quota = NULL;
REQUIRE(target != NULL && *target == NULL);
REQUIRE((key == NULL) == (cert == NULL));
* of "/dns-query".
*/
if (http != NULL) {
- CHECK(cfg_map_get(http, "endpoints", &eplist));
- len = cfg_list_length(eplist, false);
+ const cfg_obj_t *cfg_max_clients = NULL;
+ if (cfg_map_get(http, "endpoints", &eplist) == ISC_R_SUCCESS) {
+ INSIST(eplist != NULL);
+ len = cfg_list_length(eplist, false);
+ }
+
+ if (cfg_map_get(http, "listener-clients", &cfg_max_clients) ==
+ ISC_R_SUCCESS) {
+ INSIST(cfg_max_clients != NULL);
+ max_clients = cfg_obj_asuint32(cfg_max_clients);
+ }
}
endpoints = isc_mem_allocate(mctx, sizeof(endpoints[0]) * len);
- if (http != NULL) {
+ if (http != NULL && eplist != NULL) {
for (elt = cfg_list_first(eplist); elt != NULL;
elt = cfg_list_next(elt)) {
const cfg_obj_t *ep = cfg_listelt_value(elt);
INSIST(i == len);
+ INSIST(named_g_server != NULL);
+ ns_server_attach(named_g_server->sctx, &server);
+ if (max_clients > 0) {
+ quota = isc_mem_get(mctx, sizeof(isc_quota_t));
+ isc_quota_init(quota, max_clients);
+ }
result = ns_listenelt_create_http(mctx, port, named_g_dscp, NULL, tls,
- key, cert, endpoints, len, &delt);
+ key, cert, endpoints, len, quota,
+ &delt);
if (result != ISC_R_SUCCESS) {
- if (delt != NULL) {
- ns_listenelt_destroy(delt);
- }
- return (result);
+ goto error;
}
+ if (quota != NULL) {
+ ISC_LIST_APPEND(server->http_quotas, quota, link);
+ }
+ ns_server_detach(&server);
+
*target = delt;
-cleanup:
+ return (result);
+error:
+ if (delt != NULL) {
+ ns_listenelt_destroy(delt);
+ }
+ if (quota != NULL) {
+ isc_quota_destroy(quota);
+ isc_mem_put(mctx, quota, sizeof(*quota));
+ }
+
+ if (server != NULL) {
+ ns_server_detach(&server);
+ }
return (result);
}
http local-http-server {
endpoints { "/dns-query"; };
+ listener-clients 100;
};
options {
listen-on { 10.53.0.1; };
http-port 80;
https-port 443;
+ http-listener-clients 100;
listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; };
listen-on port 8080 tls none http local-http-server { 10.53.0.1; };
};
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+tls local-tls {
+ key-file "key.pem";
+ cert-file "cert.pem";
+};
+
+# Use the default values only - just to make sure that we could
+# override only values which we need and there is no required ones.
+http empty-http-server {
+};
+
+options {
+ listen-on { 10.53.0.1; };
+ http-port 80;
+ https-port 443;
+ http-listener-clients 100;
+ listen-on port 443 tls local-tls http empty-http-server { 10.53.0.1; };
+ listen-on port 8080 tls none http empty-http-server { 10.53.0.1; };
+};
/* Check endpoints are valid */
tresult = cfg_map_get(http, "endpoints", &eps);
- RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
- for (elt = cfg_list_first(eps); elt != NULL; elt = cfg_list_next(elt)) {
- const cfg_obj_t *ep = cfg_listelt_value(elt);
- const char *path = cfg_obj_asstring(ep);
- if (!isc_nm_http_path_isvalid(path)) {
- cfg_obj_log(eps, logctx, ISC_LOG_ERROR,
- "endpoint '%s' is not a "
- "valid absolute HTTP path",
- path);
- if (result == ISC_R_SUCCESS) {
- result = ISC_R_FAILURE;
+ if (tresult == ISC_R_SUCCESS) {
+ for (elt = cfg_list_first(eps); elt != NULL;
+ elt = cfg_list_next(elt)) {
+ const cfg_obj_t *ep = cfg_listelt_value(elt);
+ const char *path = cfg_obj_asstring(ep);
+ if (!isc_nm_http_path_isvalid(path)) {
+ cfg_obj_log(eps, logctx, ISC_LOG_ERROR,
+ "endpoint '%s' is not a "
+ "valid absolute HTTP path",
+ path);
+ if (result == ISC_R_SUCCESS) {
+ result = ISC_R_FAILURE;
+ }
}
}
}
atomic_uint_fast32_t waiting;
isc_mutex_t cblock;
ISC_LIST(isc_quota_cb_t) cbs;
+ ISC_LINK(isc_quota_t) link;
};
void
atomic_init("a->waiting, 0);
ISC_LIST_INIT(quota->cbs);
isc_mutex_init("a->cblock);
+ ISC_LINK_INIT(quota, link);
quota->magic = QUOTA_MAGIC;
}
{ "tls-port", &cfg_type_uint32, 0 },
#if HAVE_LIBNGHTTP2
{ "http-port", &cfg_type_uint32, 0 },
+ { "http-listener-clients", &cfg_type_uint32, 0 },
{ "https-port", &cfg_type_uint32, 0 },
#else
{ "http-port", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTCONFIGURED },
+ { "http-listener-clients", &cfg_type_uint32,
+ CFG_CLAUSEFLAG_NOTCONFIGURED },
{ "https-port", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTCONFIGURED },
#endif
{ "querylog", &cfg_type_boolean, 0 },
static cfg_clausedef_t cfg_http_description_clauses[] = {
{ "endpoints", &cfg_type_bracketed_http_endpoint_list, 0 },
+ { "listener-clients", &cfg_type_uint32, 0 },
+ { NULL, NULL, 0 }
};
static cfg_clausedef_t *http_description_clausesets[] = {
isc_tlsctx_t *sslctx;
char ** http_endpoints;
size_t http_endpoints_number;
+ isc_quota_t * http_quota;
ISC_LINK(ns_listenelt_t) link;
};
ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp,
dns_acl_t *acl, bool tls, const char *key,
const char *cert, char **endpoints, size_t nendpoints,
- ns_listenelt_t **target);
+ isc_quota_t *quota, ns_listenelt_t **target);
/*%<
* Create a listen-on list element for HTTP(S).
*/
isc_quota_t recursionquota;
isc_quota_t tcpquota;
isc_quota_t xfroutquota;
+ ISC_LIST(isc_quota_t) http_quotas;
/*% Test options and other configurables */
uint32_t options;
static isc_result_t
ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
- size_t neps) {
+ size_t neps, isc_quota_t *quota) {
#if HAVE_LIBNGHTTP2
isc_result_t result;
isc_nmsocket_t *sock = NULL;
result = isc_nm_listenhttp(ifp->mgr->nm, &ifp->addr, ifp->mgr->backlog,
- &ifp->mgr->sctx->tcpquota, sslctx, &sock);
+ quota, sslctx, &sock);
if (result == ISC_R_SUCCESS) {
for (size_t i = 0; i < neps; i++) {
ifp->dscp = elt->dscp;
if (elt->is_http) {
- result = ns_interface_listenhttp(ifp, elt->sslctx,
- elt->http_endpoints,
- elt->http_endpoints_number);
+ result = ns_interface_listenhttp(
+ ifp, elt->sslctx, elt->http_endpoints,
+ elt->http_endpoints_number, elt->http_quota);
if (result != ISC_R_SUCCESS) {
goto cleanup_interface;
}
elt->sslctx = sslctx;
elt->http_endpoints = NULL;
elt->http_endpoints_number = 0;
+ elt->http_quota = NULL;
*target = elt;
return (ISC_R_SUCCESS);
ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp,
dns_acl_t *acl, bool tls, const char *key,
const char *cert, char **endpoints, size_t nendpoints,
- ns_listenelt_t **target) {
+ isc_quota_t *quota, ns_listenelt_t **target) {
isc_result_t result;
REQUIRE(target != NULL && *target == NULL);
(*target)->is_http = true;
(*target)->http_endpoints = endpoints;
(*target)->http_endpoints_number = nendpoints;
+ (*target)->http_quota = quota;
} else {
size_t i;
for (i = 0; i < nendpoints; i++) {
isc_quota_init(&sctx->xfroutquota, 10);
isc_quota_init(&sctx->tcpquota, 10);
isc_quota_init(&sctx->recursionquota, 100);
+ ISC_LIST_INIT(sctx->http_quotas);
CHECKFATAL(dns_tkeyctx_create(mctx, &sctx->tkeyctx));
if (isc_refcount_decrement(&sctx->references) == 1) {
ns_altsecret_t *altsecret;
+ isc_quota_t *http_quota;
while ((altsecret = ISC_LIST_HEAD(sctx->altsecrets)) != NULL) {
ISC_LIST_UNLINK(sctx->altsecrets, altsecret, link);
isc_quota_destroy(&sctx->tcpquota);
isc_quota_destroy(&sctx->xfroutquota);
+ http_quota = ISC_LIST_HEAD(sctx->http_quotas);
+ while (http_quota != NULL) {
+ isc_quota_t *next = NULL;
+
+ next = ISC_LIST_NEXT(http_quota, link);
+ ISC_LIST_DEQUEUE(sctx->http_quotas, http_quota, link);
+ isc_quota_destroy(http_quota);
+ isc_mem_put(sctx->mctx, http_quota,
+ sizeof(*http_quota));
+ http_quota = next;
+ }
+
if (sctx->server_id != NULL) {
isc_mem_free(sctx->mctx, sctx->server_id);
}