]> 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 12:42:38 +0000 (15:42 +0300)
This commit ensures that HTTP listeners concurrent streams limit gets
updated properly on reconfiguration.

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 f7a15a0653b29fbc9093887fb28db779349ce8e8..6333bfc5698229320d6d0633da2fcb952134a9b8 100644 (file)
@@ -129,6 +129,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__)
@@ -609,6 +628,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 4cde316236c7f2bdcf9d1771c44dcac0cd4dc11b..8acc4baa99bc4fcff6aa059c4a8d649297a171b7 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, uint32_t workers, isc_sockaddr_t *iface,
 
        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);
@@ -2953,6 +2949,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 f1a6bce08eee2a5b2124006974b5345c773e20ed..6d5251bba386943d536ff62b7081d97bc596ce47 100644 (file)
@@ -872,7 +872,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 */
 
@@ -1817,6 +1817,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 6d73d0e28819884205bef6b939fe29f202944527..3285adbe7d845376efd65817008cf724a4e12cb9 100644 (file)
@@ -3373,6 +3373,23 @@ isc_nmsocket_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
        };
 }
 
+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 f52127cd8f679cedcccd80bb432b3aabf38116b8..8604e62032c2f58f45aa55202aad7dc94a2075a7 100644 (file)
@@ -943,13 +943,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,
@@ -969,6 +982,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.
@@ -976,6 +990,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);
 }