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);
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));
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);
}
}
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;
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,
ISC_LIST_INIT(eps->handlers);
isc_refcount_init(&eps->references, 1);
atomic_init(&eps->in_use, false);
+ eps->magic = HTTP_ENDPOINTS_MAGIC;
return eps;
}
REQUIRE(epsp != NULL);
eps = *epsp;
- REQUIRE(eps != NULL);
+ REQUIRE(VALID_HTTP_ENDPOINTS(eps));
if (isc_refcount_decrement(&eps->references) > 1) {
+ *epsp = NULL;
return;
}
httpcbarg = next;
}
+ eps->magic = 0;
+
isc_mem_putanddetach(&mctx, eps, sizeof(*eps));
*epsp = NULL;
}
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);
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);
}
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);
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,
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) {
netievent_httpclose,
netievent_httpsend,
+ netievent_httpendpoints,
netievent_shutdown,
netievent_stop,
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;
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;
/*
} isc_nm_httphandler_t;
struct isc_nm_http_endpoints {
+ uint32_t magic;
isc_mem_t *mctx;
ISC_LIST(isc_nm_httphandler_t) handlers;
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 {
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);
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);
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);
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,
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));
#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);
}
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 */