size_t len = 1, i = 0;
uint32_t max_clients = named_g_http_listener_clients;
uint32_t max_streams = named_g_http_streams_per_conn;
- ns_server_t *server = NULL;
- isc_quota_t *quota = NULL;
REQUIRE(target != NULL && *target == NULL);
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, family, tls, tls_params,
- tlsctx_cache, endpoints, len, quota, max_streams, &delt);
+ tlsctx_cache, endpoints, len, max_clients, max_streams, &delt);
if (result != ISC_R_SUCCESS) {
goto error;
}
- if (quota != NULL) {
- ISC_LIST_APPEND(server->http_quotas, quota, link);
- }
- ns_server_detach(&server);
-
*target = delt;
return (result);
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);
}
#endif /* HAVE_LIBNGHTTP2 */
isc_nmsocket_t *tcplistensocket;
isc_nmsocket_t *http_listensocket;
isc_nmsocket_t *http_secure_listensocket;
+ isc_quota_t *http_quota;
isc_dscp_t dscp; /*%< "listen-on" DSCP value */
isc_refcount_t ntcpaccepting; /*%< Number of clients
* ready to accept new
isc_tlsctx_cache_t *sslctx_cache;
char **http_endpoints;
size_t http_endpoints_number;
- isc_quota_t *http_quota;
+ uint32_t http_max_clients;
uint32_t max_concurrent_streams;
ISC_LINK(ns_listenelt_t) link;
};
dns_acl_t *acl, const uint16_t family, bool tls,
const ns_listen_tls_params_t *tls_params,
isc_tlsctx_cache_t *tlsctx_cache, char **endpoints,
- size_t nendpoints, isc_quota_t *quota,
+ size_t nendpoints, const uint32_t max_clients,
const uint32_t max_streams, ns_listenelt_t **target);
/*%<
* Create a listen-on list element for HTTP(S).
isc_quota_t tcpquota;
isc_quota_t xfroutquota;
ISC_LIST(isc_quota_t) http_quotas;
+ isc_mutex_t http_quotas_lock;
/*% Test options and other configurables */
uint32_t options;
* Requires:
*\li 'sctx' is valid.
*/
+
+void
+ns_server_append_http_quota(ns_server_t *sctx, isc_quota_t *http_quota);
+/*%<
+ * Add a quota to the list of HTTP quotas to destroy it safely later.
+ *
+ * Requires:
+ *\li 'sctx' is valid;
+ *\li 'http_quota' is not 'NULL'.
+ */
static isc_result_t
ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
- size_t neps, isc_quota_t *quota,
+ size_t neps, uint32_t max_clients,
uint32_t max_concurrent_streams) {
#if HAVE_LIBNGHTTP2
isc_result_t result = ISC_R_FAILURE;
isc_nmsocket_t *sock = NULL;
isc_nm_http_endpoints_t *epset = NULL;
+ isc_quota_t *quota = NULL;
epset = isc_nm_http_endpoints_new(ifp->mgr->mctx);
}
if (result == ISC_R_SUCCESS) {
+ quota = isc_mem_get(ifp->mgr->mctx, sizeof(*quota));
+ isc_quota_init(quota, max_clients);
result = isc_nm_listenhttp(ifp->mgr->nm, ISC_NM_LISTEN_ALL,
&ifp->addr, ifp->mgr->backlog, quota,
sslctx, epset,
isc_nm_http_endpoints_detach(&epset);
+ if (quota != NULL) {
+ if (result != ISC_R_SUCCESS) {
+ isc_quota_destroy(quota);
+ isc_mem_put(ifp->mgr->mctx, quota, sizeof(*quota));
+ } else {
+ ifp->http_quota = quota;
+ ns_server_append_http_quota(ifp->mgr->sctx, quota);
+ }
+ }
+
if (result != ISC_R_SUCCESS) {
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
"creating %s socket: %s",
UNUSED(sslctx);
UNUSED(eps);
UNUSED(neps);
- UNUSED(quota);
+ UNUSED(max_clients);
UNUSED(max_concurrent_streams);
return (ISC_R_NOTIMPLEMENTED);
#endif
if (elt->is_http) {
result = ns_interface_listenhttp(
ifp, elt->sslctx, elt->http_endpoints,
- elt->http_endpoints_number, elt->http_quota,
+ elt->http_endpoints_number, elt->http_max_clients,
elt->max_concurrent_streams);
if (result != ISC_R_SUCCESS) {
goto cleanup_interface;
isc_nm_stoplistening(ifp->http_secure_listensocket);
isc_nmsocket_close(&ifp->http_secure_listensocket);
}
+ ifp->http_quota = NULL;
}
static void
}
elt->http_endpoints = NULL;
elt->http_endpoints_number = 0;
- elt->http_quota = NULL;
+ elt->http_max_clients = 0;
+ elt->max_concurrent_streams = 0;
*target = elt;
return (ISC_R_SUCCESS);
dns_acl_t *acl, const uint16_t family, bool tls,
const ns_listen_tls_params_t *tls_params,
isc_tlsctx_cache_t *tlsctx_cache, char **endpoints,
- size_t nendpoints, isc_quota_t *quota,
+ size_t nendpoints, const uint32_t max_clients,
const uint32_t max_streams, ns_listenelt_t **target) {
isc_result_t result;
(*target)->is_http = true;
(*target)->http_endpoints = endpoints;
(*target)->http_endpoints_number = nendpoints;
- (*target)->http_quota = quota;
+ /*
+ * 0 sized quota - means unlimited quota. We used to not
+ * create a quota object in such a case, but we might need to
+ * update the value of the quota during reconfiguration, so we
+ * need to have a quota object in place anyway.
+ */
+ (*target)->http_max_clients = max_clients == 0 ? UINT32_MAX
+ : max_clients;
(*target)->max_concurrent_streams = max_streams;
} else {
size_t i;
isc_quota_init(&sctx->tcpquota, 10);
isc_quota_init(&sctx->recursionquota, 100);
ISC_LIST_INIT(sctx->http_quotas);
+ isc_mutex_init(&sctx->http_quotas_lock);
CHECKFATAL(dns_tkeyctx_create(mctx, &sctx->tkeyctx));
sizeof(*http_quota));
http_quota = next;
}
+ isc_mutex_destroy(&sctx->http_quotas_lock);
if (sctx->server_id != NULL) {
isc_mem_free(sctx->mctx, sctx->server_id);
return ((sctx->options & option) != 0);
}
+
+void
+ns_server_append_http_quota(ns_server_t *sctx, isc_quota_t *http_quota) {
+ REQUIRE(SCTX_VALID(sctx));
+ REQUIRE(http_quota != NULL);
+
+ LOCK(&sctx->http_quotas_lock);
+ ISC_LINK_INIT(http_quota, link);
+ ISC_LIST_APPEND(sctx->http_quotas, http_quota, link);
+ UNLOCK(&sctx->http_quotas_lock);
+}