]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Update max concurrent streams limit in HTTP listeners on reconfig
authorArtem Boldariev <artem@boldariev.com>
Wed, 22 Jun 2022 13:45:28 +0000 (16:45 +0300)
committerArtem Boldariev <artem@boldariev.com>
Tue, 28 Jun 2022 13:37:31 +0000 (16:37 +0300)
This commit ensures that HTTP listeners concurrent streams limit gets
updated properly on reconfiguration.

(cherry picked from commit e72962d5f1a4e157800519b5ac878cc72052c3a8)

lib/isc/include/isc/netmgr.h
lib/isc/netmgr/http.c
lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/netmgr.c
lib/ns/interfacemgr.c

index e5f6d94cffb7dc2d3a2506d52516054f02e38687..8dc83606622e293a21174206b4df69ca586ab6f8 100644 (file)
@@ -121,6 +121,25 @@ isc_nmsocket_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx);
  * \li 'tlsctx' is a valid pointer to a TLS context object.
  */
 
+void
+isc_nmsocket_set_max_streams(isc_nmsocket_t *listener,
+                            const uint32_t  max_streams);
+/*%<
+ * Set the maximum allowed number of concurrent streams for accepted
+ * client connections. The implementation might be asynchronous
+ * depending on the listener socket type.
+ *
+ * The call is a no-op for any listener socket type that does not
+ * support concept of multiple sessions per a client
+ * connection. Currently, it works only for HTTP/2 listeners.
+ *
+ * Setting 'max_streams' to '0' instructs the listener that there is
+ * no limit for concurrent streams.
+ *
+ * Requires:
+ * \li 'listener' is a pointer to a valid network manager listener socket.
+ */
+
 #ifdef NETMGR_TRACE
 #define isc_nmhandle_attach(handle, dest) \
        isc__nmhandle_attach(handle, dest, __FILE__, __LINE__, __func__)
@@ -645,6 +664,21 @@ isc_nm_http_makeuri(const bool https, const isc_sockaddr_t *sa,
  * \li 'outbuf' is a valid pointer to a buffer which will get the result;
  * \li 'outbuf_len' is a size of the result buffer and is greater than zero.
  */
+
+void
+isc_nm_http_set_endpoints(isc_nmsocket_t         *listener,
+                         isc_nm_http_endpoints_t *eps);
+/*%<
+ * Asynchronously replace the set of HTTP endpoints (paths) within
+ * the listener socket object.  The function is intended to be used
+ * during reconfiguration.
+ *
+ * Requires:
+ * \li 'listener' is a pointer to a valid network manager listener socket
+ object with TLS support;
+ * \li 'eps' is a valid pointer to an HTTP endpoints set.
+ */
+
 #endif /* HAVE_LIBNGHTTP2 */
 
 void
index a3738106dde4184efdcbf99df532fc1512adb8cf..79f21c19cfac86dd32a7c78da66ee4d7aefec647 100644 (file)
@@ -2454,7 +2454,7 @@ httplisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
 
        new_session(httplistensock->mgr->mctx, NULL, &session);
        session->max_concurrent_streams =
-               httplistensock->h2.max_concurrent_streams;
+               atomic_load(&httplistensock->h2.max_concurrent_streams);
        initialize_nghttp2_server_session(session);
        handle->sock->h2.session = session;
 
@@ -2481,14 +2481,10 @@ isc_nm_listenhttp(isc_nm_t *mgr, isc_sockaddr_t *iface, int backlog,
 
        sock = isc_mem_get(mgr->mctx, sizeof(*sock));
        isc__nmsocket_init(sock, mgr, isc_nm_httplistener, iface);
-       sock->h2.max_concurrent_streams =
-               NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS;
+       atomic_init(&sock->h2.max_concurrent_streams,
+                   NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS);
 
-       if (max_concurrent_streams > 0 &&
-           max_concurrent_streams < NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS)
-       {
-               sock->h2.max_concurrent_streams = max_concurrent_streams;
-       }
+       isc_nmsocket_set_max_streams(sock, max_concurrent_streams);
 
        atomic_store(&eps->in_use, true);
        isc_nm_http_endpoints_attach(eps, &sock->h2.listener_endpoints);
@@ -2955,6 +2951,23 @@ isc__nm_http_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
        isc_nmsocket_set_tlsctx(listener->outer, tlsctx);
 }
 
+void
+isc__nm_http_set_max_streams(isc_nmsocket_t *listener,
+                            const uint32_t max_concurrent_streams) {
+       uint32_t max_streams = NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS;
+
+       REQUIRE(VALID_NMSOCK(listener));
+       REQUIRE(listener->type == isc_nm_httplistener);
+
+       if (max_concurrent_streams > 0 &&
+           max_concurrent_streams < NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS)
+       {
+               max_streams = max_concurrent_streams;
+       }
+
+       atomic_store(&listener->h2.max_concurrent_streams, max_streams);
+}
+
 static const bool base64url_validation_table[256] = {
        false, false, false, false, false, false, false, false, false, false,
        false, false, false, false, false, false, false, false, false, false,
index 6b88638011734213370853df8d67364092142eae..973af0e9858846757a4e0242f006cea0e560abe5 100644 (file)
@@ -880,7 +880,7 @@ typedef struct isc_nmsocket_h2 {
        isc_nmsocket_t *httpserver;
 
        /* maximum concurrent streams (server-side) */
-       uint32_t max_concurrent_streams;
+       atomic_uint_fast32_t max_concurrent_streams;
 
        uint32_t min_ttl; /* used to set "max-age" in responses */
 
@@ -1833,6 +1833,10 @@ isc__nm_httpsession_detach(isc_nm_http_session_t **sessionp);
 void
 isc__nm_http_set_tlsctx(isc_nmsocket_t *sock, isc_tlsctx_t *tlsctx);
 
+void
+isc__nm_http_set_max_streams(isc_nmsocket_t *listener,
+                            const uint32_t max_concurrent_streams);
+
 #endif
 
 void
index 8bad215f9dd357ac49fc48185fa7c2912b6508cf..2eaa7d1dd0abd2a0db6cecb94191722098f6ad01 100644 (file)
@@ -3733,6 +3733,23 @@ isc_nm_verify_tls_peer_result_string(const isc_nmhandle_t *handle) {
        return (NULL);
 }
 
+void
+isc_nmsocket_set_max_streams(isc_nmsocket_t *listener,
+                            const uint32_t max_streams) {
+       REQUIRE(VALID_NMSOCK(listener));
+       switch (listener->type) {
+#if HAVE_LIBNGHTTP2
+       case isc_nm_httplistener:
+               isc__nm_http_set_max_streams(listener, max_streams);
+               break;
+#endif /* HAVE_LIBNGHTTP2 */
+       default:
+               UNUSED(max_streams);
+               break;
+       };
+       return;
+}
+
 void
 isc__nmsocket_log_tls_session_reuse(isc_nmsocket_t *sock, isc_tls_t *tls) {
        const int log_level = ISC_LOG_DEBUG(1);
index caca36ed12aed3c3d136d40de23c4a807e58ce87..72e0f47867360c51ddb640bff30a29cb406d2de5 100644 (file)
@@ -941,13 +941,26 @@ replace_listener_tlsctx(ns_interface_t *ifp, isc_tlsctx_t *newctx) {
        }
 }
 
+#ifdef HAVE_LIBNGHTTP2
 static void
 update_http_settings(ns_interface_t *ifp, ns_listenelt_t *le) {
+       isc_nmsocket_t *listener;
+
        REQUIRE(le->is_http);
 
        INSIST(ifp->http_quota != NULL);
        isc_quota_max(ifp->http_quota, le->http_max_clients);
+
+       if (ifp->http_secure_listensocket != NULL) {
+               listener = ifp->http_secure_listensocket;
+       } else {
+               INSIST(ifp->http_listensocket != NULL);
+               listener = ifp->http_listensocket;
+       }
+
+       isc_nmsocket_set_max_streams(listener, le->max_concurrent_streams);
 }
+#endif /* HAVE_LIBNGHTTP2 */
 
 static void
 update_listener_configuration(ns_interfacemgr_t *mgr, ns_interface_t *ifp,
@@ -967,6 +980,7 @@ update_listener_configuration(ns_interfacemgr_t *mgr, ns_interface_t *ifp,
                replace_listener_tlsctx(ifp, le->sslctx);
        }
 
+#ifdef HAVE_LIBNGHTTP2
        /*
         * Let's update HTTP listener settings
         * on reconfiguration.
@@ -974,6 +988,8 @@ update_listener_configuration(ns_interfacemgr_t *mgr, ns_interface_t *ifp,
        if (le->is_http) {
                update_http_settings(ifp, le);
        }
+#endif /* HAVE_LIBNGHTTP2 */
+
        UNLOCK(&mgr->lock);
 }