mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
Update the set of HTTP endpoints on reconfiguration
This commit ensures that on reconfiguration the set of HTTP endpoints (=paths) is being updated within HTTP listeners.
This commit is contained in:
@@ -638,8 +638,7 @@ isc_nm_http_set_endpoints(isc_nmsocket_t *listener,
|
||||
* during reconfiguration.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'listener' is a pointer to a valid network manager listener socket
|
||||
object with TLS support;
|
||||
* \li 'listener' is a pointer to a valid network manager HTTP listener socket;
|
||||
* \li 'eps' is a valid pointer to an HTTP endpoints set.
|
||||
*/
|
||||
|
||||
|
@@ -179,6 +179,9 @@ typedef struct isc_http_send_req {
|
||||
isc__nm_http_pending_callbacks_t pending_write_callbacks;
|
||||
} isc_http_send_req_t;
|
||||
|
||||
#define HTTP_ENDPOINTS_MAGIC ISC_MAGIC('H', 'T', 'E', 'P')
|
||||
#define VALID_HTTP_ENDPOINTS(t) ISC_MAGIC_VALID(t, HTTP_ENDPOINTS_MAGIC)
|
||||
|
||||
static bool
|
||||
http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle,
|
||||
isc_nm_cb_t cb, void *cbarg);
|
||||
@@ -225,6 +228,16 @@ static isc_nm_httphandler_t *
|
||||
http_endpoints_find(const char *request_path,
|
||||
const isc_nm_http_endpoints_t *restrict eps);
|
||||
|
||||
static void
|
||||
http_init_listener_endpoints(isc_nmsocket_t *listener,
|
||||
isc_nm_http_endpoints_t *epset);
|
||||
|
||||
static void
|
||||
http_cleanup_listener_endpoints(isc_nmsocket_t *listener);
|
||||
|
||||
static isc_nm_http_endpoints_t *
|
||||
http_get_listener_endpoints(isc_nmsocket_t *listener, const int tid);
|
||||
|
||||
static bool
|
||||
http_session_active(isc_nm_http_session_t *session) {
|
||||
REQUIRE(VALID_HTTP2_SESSION(session));
|
||||
@@ -1655,14 +1668,15 @@ server_on_begin_headers_callback(nghttp2_session *ngsession,
|
||||
|
||||
static isc_nm_httphandler_t *
|
||||
find_server_request_handler(const char *request_path,
|
||||
const isc_nmsocket_t *serversocket) {
|
||||
isc_nmsocket_t *serversocket, const int tid) {
|
||||
isc_nm_httphandler_t *handler = NULL;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(serversocket));
|
||||
|
||||
if (atomic_load(&serversocket->listening)) {
|
||||
handler = http_endpoints_find(
|
||||
request_path, serversocket->h2.listener_endpoints);
|
||||
request_path,
|
||||
http_get_listener_endpoints(serversocket, tid));
|
||||
}
|
||||
return (handler);
|
||||
}
|
||||
@@ -1692,7 +1706,8 @@ server_handle_path_header(isc_nmsocket_t *socket, const uint8_t *value,
|
||||
}
|
||||
|
||||
handler = find_server_request_handler(socket->h2.request_path,
|
||||
socket->h2.session->serversocket);
|
||||
socket->h2.session->serversocket,
|
||||
socket->tid);
|
||||
if (handler != NULL) {
|
||||
socket->h2.cb = handler->cb;
|
||||
socket->h2.cbarg = handler->cbarg;
|
||||
@@ -2487,7 +2502,7 @@ isc_nm_listenhttp(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface,
|
||||
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);
|
||||
http_init_listener_endpoints(sock, eps);
|
||||
|
||||
if (ctx != NULL) {
|
||||
result = isc_nm_listentls(mgr, workers, iface,
|
||||
@@ -2530,6 +2545,7 @@ isc_nm_http_endpoints_new(isc_mem_t *mctx) {
|
||||
ISC_LIST_INIT(eps->handlers);
|
||||
isc_refcount_init(&eps->references, 1);
|
||||
atomic_init(&eps->in_use, false);
|
||||
eps->magic = HTTP_ENDPOINTS_MAGIC;
|
||||
|
||||
return eps;
|
||||
}
|
||||
@@ -2543,9 +2559,10 @@ isc_nm_http_endpoints_detach(isc_nm_http_endpoints_t **restrict epsp) {
|
||||
|
||||
REQUIRE(epsp != NULL);
|
||||
eps = *epsp;
|
||||
REQUIRE(eps != NULL);
|
||||
REQUIRE(VALID_HTTP_ENDPOINTS(eps));
|
||||
|
||||
if (isc_refcount_decrement(&eps->references) > 1) {
|
||||
*epsp = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2573,6 +2590,8 @@ isc_nm_http_endpoints_detach(isc_nm_http_endpoints_t **restrict epsp) {
|
||||
httpcbarg = next;
|
||||
}
|
||||
|
||||
eps->magic = 0;
|
||||
|
||||
isc_mem_putanddetach(&mctx, eps, sizeof(*eps));
|
||||
*epsp = NULL;
|
||||
}
|
||||
@@ -2580,6 +2599,7 @@ isc_nm_http_endpoints_detach(isc_nm_http_endpoints_t **restrict epsp) {
|
||||
void
|
||||
isc_nm_http_endpoints_attach(isc_nm_http_endpoints_t *source,
|
||||
isc_nm_http_endpoints_t **targetp) {
|
||||
REQUIRE(VALID_HTTP_ENDPOINTS(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
isc_refcount_increment(&source->references);
|
||||
@@ -2592,6 +2612,8 @@ http_endpoints_find(const char *request_path,
|
||||
const isc_nm_http_endpoints_t *restrict eps) {
|
||||
isc_nm_httphandler_t *handler = NULL;
|
||||
|
||||
REQUIRE(VALID_HTTP_ENDPOINTS(eps));
|
||||
|
||||
if (request_path == NULL || *request_path == '\0') {
|
||||
return (NULL);
|
||||
}
|
||||
@@ -2637,7 +2659,7 @@ isc_nm_http_endpoints_add(isc_nm_http_endpoints_t *restrict eps,
|
||||
isc_nm_httpcbarg_t *restrict httpcbarg = NULL;
|
||||
bool newhandler = false;
|
||||
|
||||
REQUIRE(eps != NULL);
|
||||
REQUIRE(VALID_HTTP_ENDPOINTS(eps));
|
||||
REQUIRE(isc_nm_http_path_isvalid(uri));
|
||||
REQUIRE(atomic_load(&eps->in_use) == false);
|
||||
|
||||
@@ -2966,6 +2988,90 @@ isc__nm_http_set_max_streams(isc_nmsocket_t *listener,
|
||||
atomic_store(&listener->h2.max_concurrent_streams, max_streams);
|
||||
}
|
||||
|
||||
void
|
||||
isc_nm_http_set_endpoints(isc_nmsocket_t *listener,
|
||||
isc_nm_http_endpoints_t *eps) {
|
||||
REQUIRE(VALID_NMSOCK(listener));
|
||||
REQUIRE(listener->type == isc_nm_httplistener);
|
||||
REQUIRE(VALID_HTTP_ENDPOINTS(eps));
|
||||
|
||||
atomic_store(&eps->in_use, true);
|
||||
|
||||
for (size_t i = 0; i < isc_nm_getnworkers(listener->mgr); i++) {
|
||||
isc__netievent__http_eps_t *ievent =
|
||||
isc__nm_get_netievent_httpendpoints(listener->mgr,
|
||||
listener, eps);
|
||||
isc__nm_enqueue_ievent(&listener->mgr->workers[i],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_async_httpendpoints(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
isc__netievent__http_eps_t *ievent = (isc__netievent__http_eps_t *)ev0;
|
||||
const int tid = isc_nm_tid();
|
||||
isc_nmsocket_t *listener = ievent->sock;
|
||||
isc_nm_http_endpoints_t *eps = ievent->endpoints;
|
||||
UNUSED(worker);
|
||||
|
||||
isc_nm_http_endpoints_detach(&listener->h2.listener_endpoints[tid]);
|
||||
isc_nm_http_endpoints_attach(eps,
|
||||
&listener->h2.listener_endpoints[tid]);
|
||||
}
|
||||
|
||||
static void
|
||||
http_init_listener_endpoints(isc_nmsocket_t *listener,
|
||||
isc_nm_http_endpoints_t *epset) {
|
||||
size_t nworkers;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(listener));
|
||||
REQUIRE(VALID_NM(listener->mgr));
|
||||
REQUIRE(VALID_HTTP_ENDPOINTS(epset));
|
||||
|
||||
nworkers = (size_t)isc_nm_getnworkers(listener->mgr);
|
||||
INSIST(nworkers > 0);
|
||||
|
||||
listener->h2.listener_endpoints =
|
||||
isc_mem_get(listener->mgr->mctx,
|
||||
sizeof(isc_nm_http_endpoints_t *) * nworkers);
|
||||
listener->h2.n_listener_endpoints = nworkers;
|
||||
for (size_t i = 0; i < nworkers; i++) {
|
||||
listener->h2.listener_endpoints[i] = NULL;
|
||||
isc_nm_http_endpoints_attach(
|
||||
epset, &listener->h2.listener_endpoints[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
http_cleanup_listener_endpoints(isc_nmsocket_t *listener) {
|
||||
REQUIRE(VALID_NM(listener->mgr));
|
||||
|
||||
if (listener->h2.listener_endpoints == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < listener->h2.n_listener_endpoints; i++) {
|
||||
isc_nm_http_endpoints_detach(
|
||||
&listener->h2.listener_endpoints[i]);
|
||||
}
|
||||
isc_mem_put(listener->mgr->mctx, listener->h2.listener_endpoints,
|
||||
sizeof(isc_nm_http_endpoints_t *) *
|
||||
listener->h2.n_listener_endpoints);
|
||||
listener->h2.n_listener_endpoints = 0;
|
||||
}
|
||||
|
||||
static isc_nm_http_endpoints_t *
|
||||
http_get_listener_endpoints(isc_nmsocket_t *listener, const int tid) {
|
||||
isc_nm_http_endpoints_t *eps;
|
||||
REQUIRE(VALID_NMSOCK(listener));
|
||||
REQUIRE(tid >= 0);
|
||||
REQUIRE((size_t)tid < listener->h2.n_listener_endpoints);
|
||||
|
||||
eps = listener->h2.listener_endpoints[tid];
|
||||
INSIST(eps != NULL);
|
||||
return (eps);
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -3119,8 +3225,7 @@ isc__nm_http_cleanup_data(isc_nmsocket_t *sock) {
|
||||
if (sock->type == isc_nm_httplistener &&
|
||||
sock->h2.listener_endpoints != NULL) {
|
||||
/* Delete all handlers */
|
||||
isc_nm_http_endpoints_detach(
|
||||
&sock->h2.listener_endpoints);
|
||||
http_cleanup_listener_endpoints(sock);
|
||||
}
|
||||
|
||||
if (sock->h2.request_path != NULL) {
|
||||
|
@@ -313,6 +313,7 @@ typedef enum isc__netievent_type {
|
||||
|
||||
netievent_httpclose,
|
||||
netievent_httpsend,
|
||||
netievent_httpendpoints,
|
||||
|
||||
netievent_shutdown,
|
||||
netievent_stop,
|
||||
@@ -695,6 +696,42 @@ typedef struct isc__netievent__tlsctx {
|
||||
isc__nm_put_netievent(nm, ievent); \
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBNGHTTP2
|
||||
typedef struct isc__netievent__http_eps {
|
||||
NETIEVENT__SOCKET;
|
||||
isc_nm_http_endpoints_t *endpoints;
|
||||
} isc__netievent__http_eps_t;
|
||||
|
||||
#define NETIEVENT_SOCKET_HTTP_EPS_TYPE(type) \
|
||||
typedef isc__netievent__http_eps_t isc__netievent_##type##_t;
|
||||
|
||||
#define NETIEVENT_SOCKET_HTTP_EPS_DECL(type) \
|
||||
isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
|
||||
isc_nm_t *nm, isc_nmsocket_t *sock, \
|
||||
isc_nm_http_endpoints_t *endpoints); \
|
||||
void isc__nm_put_netievent_##type(isc_nm_t *nm, \
|
||||
isc__netievent_##type##_t *ievent);
|
||||
|
||||
#define NETIEVENT_SOCKET_HTTP_EPS_DEF(type) \
|
||||
isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
|
||||
isc_nm_t *nm, isc_nmsocket_t *sock, \
|
||||
isc_nm_http_endpoints_t *endpoints) { \
|
||||
isc__netievent_##type##_t *ievent = \
|
||||
isc__nm_get_netievent(nm, netievent_##type); \
|
||||
isc__nmsocket_attach(sock, &ievent->sock); \
|
||||
isc_nm_http_endpoints_attach(endpoints, &ievent->endpoints); \
|
||||
\
|
||||
return (ievent); \
|
||||
} \
|
||||
\
|
||||
void isc__nm_put_netievent_##type(isc_nm_t *nm, \
|
||||
isc__netievent_##type##_t *ievent) { \
|
||||
isc_nm_http_endpoints_detach(&ievent->endpoints); \
|
||||
isc__nmsocket_detach(&ievent->sock); \
|
||||
isc__nm_put_netievent(nm, ievent); \
|
||||
}
|
||||
#endif /* HAVE_LIBNGHTTP2 */
|
||||
|
||||
typedef union {
|
||||
isc__netievent_t ni;
|
||||
isc__netievent__socket_t nis;
|
||||
@@ -703,6 +740,9 @@ typedef union {
|
||||
isc__netievent__socket_quota_t nisq;
|
||||
isc__netievent_tlsconnect_t nitc;
|
||||
isc__netievent__tlsctx_t nitls;
|
||||
#ifdef HAVE_LIBNGHTTP2
|
||||
isc__netievent__http_eps_t nihttpeps;
|
||||
#endif /* HAVE_LIBNGHTTP2 */
|
||||
} isc__netievent_storage_t;
|
||||
|
||||
/*
|
||||
@@ -846,6 +886,7 @@ typedef struct isc_nm_httphandler {
|
||||
} isc_nm_httphandler_t;
|
||||
|
||||
struct isc_nm_http_endpoints {
|
||||
uint32_t magic;
|
||||
isc_mem_t *mctx;
|
||||
|
||||
ISC_LIST(isc_nm_httphandler_t) handlers;
|
||||
@@ -891,7 +932,8 @@ typedef struct isc_nmsocket_h2 {
|
||||
void *cbarg;
|
||||
LINK(struct isc_nmsocket_h2) link;
|
||||
|
||||
isc_nm_http_endpoints_t *listener_endpoints;
|
||||
isc_nm_http_endpoints_t **listener_endpoints;
|
||||
size_t n_listener_endpoints;
|
||||
|
||||
bool response_submitted;
|
||||
struct {
|
||||
@@ -1796,6 +1838,9 @@ isc__nm_async_httpstop(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
void
|
||||
isc__nm_async_httpclose(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
void
|
||||
isc__nm_async_httpendpoints(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
bool
|
||||
isc__nm_parse_httpquery(const char *query_string, const char **start,
|
||||
size_t *len);
|
||||
@@ -1971,9 +2016,12 @@ NETIEVENT_SOCKET_HANDLE_TYPE(tlsdnscancel);
|
||||
NETIEVENT_SOCKET_QUOTA_TYPE(tlsdnsaccept);
|
||||
NETIEVENT_SOCKET_TYPE(tlsdnscycle);
|
||||
|
||||
#ifdef HAVE_LIBNGHTTP2
|
||||
NETIEVENT_SOCKET_TYPE(httpstop);
|
||||
NETIEVENT_SOCKET_REQ_TYPE(httpsend);
|
||||
NETIEVENT_SOCKET_TYPE(httpclose);
|
||||
NETIEVENT_SOCKET_HTTP_EPS_TYPE(httpendpoints);
|
||||
#endif /* HAVE_LIBNGHTTP2 */
|
||||
|
||||
NETIEVENT_SOCKET_REQ_TYPE(tcpconnect);
|
||||
NETIEVENT_SOCKET_REQ_TYPE(tcpsend);
|
||||
@@ -2041,9 +2089,12 @@ NETIEVENT_SOCKET_HANDLE_DECL(tlsdnscancel);
|
||||
NETIEVENT_SOCKET_QUOTA_DECL(tlsdnsaccept);
|
||||
NETIEVENT_SOCKET_DECL(tlsdnscycle);
|
||||
|
||||
#ifdef HAVE_LIBNGHTTP2
|
||||
NETIEVENT_SOCKET_DECL(httpstop);
|
||||
NETIEVENT_SOCKET_REQ_DECL(httpsend);
|
||||
NETIEVENT_SOCKET_DECL(httpclose);
|
||||
NETIEVENT_SOCKET_HTTP_EPS_DECL(httpendpoints);
|
||||
#endif /* HAVE_LIBNGHTTP2 */
|
||||
|
||||
NETIEVENT_SOCKET_REQ_DECL(tcpconnect);
|
||||
NETIEVENT_SOCKET_REQ_DECL(tcpsend);
|
||||
|
@@ -921,6 +921,7 @@ process_netievent(isc__networker_t *worker, isc__netievent_t *ievent) {
|
||||
NETIEVENT_CASE(httpstop);
|
||||
NETIEVENT_CASE(httpsend);
|
||||
NETIEVENT_CASE(httpclose);
|
||||
NETIEVENT_CASE(httpendpoints);
|
||||
#endif
|
||||
NETIEVENT_CASE(settlsctx);
|
||||
|
||||
@@ -1034,9 +1035,12 @@ NETIEVENT_SOCKET_QUOTA_DEF(tlsdnsaccept);
|
||||
NETIEVENT_SOCKET_DEF(tlsdnscycle);
|
||||
NETIEVENT_SOCKET_DEF(tlsdnsshutdown);
|
||||
|
||||
#ifdef HAVE_LIBNGHTTP2
|
||||
NETIEVENT_SOCKET_DEF(httpstop);
|
||||
NETIEVENT_SOCKET_REQ_DEF(httpsend);
|
||||
NETIEVENT_SOCKET_DEF(httpclose);
|
||||
NETIEVENT_SOCKET_HTTP_EPS_DEF(httpendpoints);
|
||||
#endif /* HAVE_LIBNGHTTP2 */
|
||||
|
||||
NETIEVENT_SOCKET_REQ_DEF(tcpconnect);
|
||||
NETIEVENT_SOCKET_REQ_DEF(tcpsend);
|
||||
|
@@ -570,6 +570,24 @@ ns_interface_listentls(ns_interface_t *ifp, isc_tlsctx_t *sslctx) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBNGHTTP2
|
||||
static isc_result_t
|
||||
load_http_endpoints(isc_nm_http_endpoints_t *epset, ns_interface_t *ifp,
|
||||
char **eps, size_t neps) {
|
||||
isc_result_t result = ISC_R_FAILURE;
|
||||
|
||||
for (size_t i = 0; i < neps; i++) {
|
||||
result = isc_nm_http_endpoints_add(epset, eps[i],
|
||||
ns__client_request, ifp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
#endif /* HAVE_LIBNGHTTP2 */
|
||||
|
||||
static isc_result_t
|
||||
ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
|
||||
size_t neps, uint32_t max_clients,
|
||||
@@ -582,13 +600,7 @@ ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
|
||||
|
||||
epset = isc_nm_http_endpoints_new(ifp->mgr->mctx);
|
||||
|
||||
for (size_t i = 0; i < neps; i++) {
|
||||
result = isc_nm_http_endpoints_add(epset, eps[i],
|
||||
ns__client_request, ifp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = load_http_endpoints(epset, ifp, eps, neps);
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
quota = isc_mem_get(ifp->mgr->mctx, sizeof(*quota));
|
||||
@@ -946,7 +958,9 @@ 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_result_t result;
|
||||
isc_nmsocket_t *listener;
|
||||
isc_nm_http_endpoints_t *epset;
|
||||
|
||||
REQUIRE(le->is_http);
|
||||
|
||||
@@ -961,6 +975,17 @@ update_http_settings(ns_interface_t *ifp, ns_listenelt_t *le) {
|
||||
}
|
||||
|
||||
isc_nmsocket_set_max_streams(listener, le->max_concurrent_streams);
|
||||
|
||||
epset = isc_nm_http_endpoints_new(ifp->mgr->mctx);
|
||||
|
||||
result = load_http_endpoints(epset, ifp, le->http_endpoints,
|
||||
le->http_endpoints_number);
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_nm_http_set_endpoints(listener, epset);
|
||||
}
|
||||
|
||||
isc_nm_http_endpoints_detach(&epset);
|
||||
}
|
||||
#endif /* HAVE_LIBNGHTTP2 */
|
||||
|
||||
|
Reference in New Issue
Block a user