2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-04 16:45:24 +00:00

Merge branch 'artem/doh-no-rwlocks' into 'main'

Get rid of RW locks in the DoH code

See merge request isc-projects/bind9!5278
This commit is contained in:
Artem Boldariev
2021-08-04 07:59:42 +00:00
8 changed files with 296 additions and 148 deletions

View File

@@ -286,15 +286,19 @@ run(void) {
case HTTPS: case HTTPS:
case HTTP: { case HTTP: {
bool is_https = protocol == HTTPS; bool is_https = protocol == HTTPS;
isc_nm_http_endpoints_t *eps = NULL;
if (is_https) { if (is_https) {
isc_tlsctx_createserver(NULL, NULL, &tls_ctx); isc_tlsctx_createserver(NULL, NULL, &tls_ctx);
} }
result = isc_nm_listenhttp(netmgr, &sockaddr, 0, NULL, tls_ctx, eps = isc_nm_http_endpoints_new(mctx);
0, &sock); result = isc_nm_http_endpoints_add(eps, DEFAULT_DOH_PATH,
read_cb, NULL, 0);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
result = isc_nm_http_endpoint(sock, DEFAULT_DOH_PATH, result = isc_nm_listenhttp(netmgr, &sockaddr, 0, NULL,
read_cb, NULL, 0); tls_ctx, eps, 0, &sock);
} }
isc_nm_http_endpoints_detach(&eps);
} break; } break;
#endif #endif
default: default:

View File

@@ -499,11 +499,56 @@ isc_nm_httpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc_result_t isc_result_t
isc_nm_listenhttp(isc_nm_t *mgr, isc_sockaddr_t *iface, int backlog, isc_nm_listenhttp(isc_nm_t *mgr, isc_sockaddr_t *iface, int backlog,
isc_quota_t *quota, isc_tlsctx_t *ctx, isc_quota_t *quota, isc_tlsctx_t *ctx,
uint32_t max_concurrent_streams, isc_nmsocket_t **sockp); isc_nm_http_endpoints_t *eps, uint32_t max_concurrent_streams,
isc_nmsocket_t **sockp);
isc_nm_http_endpoints_t *
isc_nm_http_endpoints_new(isc_mem_t *mctx);
/*%<
* Create a new, empty HTTP endpoints set object.
*
* Requires:
* \li 'mctx' a valid memory context object.
*/
isc_result_t isc_result_t
isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb, isc_nm_http_endpoints_add(isc_nm_http_endpoints_t *restrict eps,
void *cbarg, size_t extrahandlesize); const char *uri, const isc_nm_recv_cb_t cb,
void *cbarg, const size_t extrahandlesize);
/*%< Adds a new endpoint to the given HTTP endpoints set object.
*
* NOTE: adding an endpoint is allowed only if the endpoint object has
* not been passed to isc_nm_listenhttp() yet.
*
* Requires:
* \li 'eps' is a valid pointer to a valid isc_nm_http_endpoints_t
* object;
* \li 'uri' is a valid pointer to a string of length > 0;
* \li 'cb' is a valid pointer to a read callback function.
*/
void
isc_nm_http_endpoints_attach(isc_nm_http_endpoints_t * source,
isc_nm_http_endpoints_t **targetp);
/*%<
* Attaches to an HTTP endpoints set object.
*
* Requires:
* \li 'source' is a non-NULL pointer to a valid
* isc_nm_http_endpoints_t object;
* \li 'target' is a pointer to a pointer, containing NULL.
*/
void
isc_nm_http_endpoints_detach(isc_nm_http_endpoints_t **restrict epsp);
/*%<
* Detaches from an HTTP endpoints set object. When reference count
* reaches 0, the object get deleted.
*
* Requires:
* \li 'epsp' is a pointer to a pointer to a valid
* isc_nm_http_endpoints_t object.
*/
bool bool
isc_nm_is_http_handle(isc_nmhandle_t *handle); isc_nm_is_http_handle(isc_nmhandle_t *handle);

View File

@@ -92,6 +92,11 @@ typedef struct isc_time isc_time_t; /*%< Time */
typedef struct isc_timer isc_timer_t; /*%< Timer */ typedef struct isc_timer isc_timer_t; /*%< Timer */
typedef struct isc_timermgr isc_timermgr_t; /*%< Timer Manager */ typedef struct isc_timermgr isc_timermgr_t; /*%< Timer Manager */
#if HAVE_LIBNGHTTP2
typedef struct isc_nm_http_endpoints isc_nm_http_endpoints_t;
/*%< HTTP endpoints set */
#endif /* HAVE_LIBNGHTTP2 */
typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *); typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *);
typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *, int); typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *, int);

View File

@@ -213,6 +213,10 @@ static void
server_call_cb(isc_nmsocket_t *socket, isc_nm_http_session_t *session, server_call_cb(isc_nmsocket_t *socket, isc_nm_http_session_t *session,
const isc_result_t result, isc_region_t *data); const isc_result_t result, isc_region_t *data);
static isc_nm_httphandler_t *
http_endpoints_find(const char *request_path,
const isc_nm_http_endpoints_t *restrict eps);
static bool static bool
http_session_active(isc_nm_http_session_t *session) { http_session_active(isc_nm_http_session_t *session) {
REQUIRE(VALID_HTTP2_SESSION(session)); REQUIRE(VALID_HTTP2_SESSION(session));
@@ -1653,27 +1657,15 @@ server_on_begin_headers_callback(nghttp2_session *ngsession,
static isc_nm_httphandler_t * static isc_nm_httphandler_t *
find_server_request_handler(const char *request_path, find_server_request_handler(const char *request_path,
isc_nmsocket_t *serversocket) { const isc_nmsocket_t *serversocket) {
isc_nm_httphandler_t *handler = NULL; isc_nm_httphandler_t *handler = NULL;
REQUIRE(VALID_NMSOCK(serversocket)); REQUIRE(VALID_NMSOCK(serversocket));
if (request_path == NULL || *request_path == '\0') {
return (NULL);
}
RWLOCK(&serversocket->h2.lock, isc_rwlocktype_read);
if (atomic_load(&serversocket->listening)) { if (atomic_load(&serversocket->listening)) {
for (handler = ISC_LIST_HEAD(serversocket->h2.handlers); handler = http_endpoints_find(
handler != NULL; handler = ISC_LIST_NEXT(handler, link)) request_path, serversocket->h2.listener_endpoints);
{
if (!strcmp(request_path, handler->path)) {
break;
}
}
} }
RWUNLOCK(&serversocket->h2.lock, isc_rwlocktype_read);
return (handler); return (handler);
} }
@@ -2418,10 +2410,15 @@ httplisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
isc_result_t isc_result_t
isc_nm_listenhttp(isc_nm_t *mgr, isc_sockaddr_t *iface, int backlog, isc_nm_listenhttp(isc_nm_t *mgr, isc_sockaddr_t *iface, int backlog,
isc_quota_t *quota, isc_tlsctx_t *ctx, isc_quota_t *quota, isc_tlsctx_t *ctx,
uint32_t max_concurrent_streams, isc_nmsocket_t **sockp) { isc_nm_http_endpoints_t *eps, uint32_t max_concurrent_streams,
isc_nmsocket_t **sockp) {
isc_nmsocket_t *sock = NULL; isc_nmsocket_t *sock = NULL;
isc_result_t result; isc_result_t result;
REQUIRE(!ISC_LIST_EMPTY(eps->handlers));
REQUIRE(!ISC_LIST_EMPTY(eps->handler_cbargs));
REQUIRE(atomic_load(&eps->in_use) == false);
sock = isc_mem_get(mgr->mctx, sizeof(*sock)); sock = isc_mem_get(mgr->mctx, sizeof(*sock));
isc__nmsocket_init(sock, mgr, isc_nm_httplistener, iface); isc__nmsocket_init(sock, mgr, isc_nm_httplistener, iface);
sock->h2.max_concurrent_streams = sock->h2.max_concurrent_streams =
@@ -2433,6 +2430,9 @@ isc_nm_listenhttp(isc_nm_t *mgr, isc_sockaddr_t *iface, int backlog,
sock->h2.max_concurrent_streams = max_concurrent_streams; sock->h2.max_concurrent_streams = max_concurrent_streams;
} }
atomic_store(&eps->in_use, true);
isc_nm_http_endpoints_attach(eps, &sock->h2.listener_endpoints);
if (ctx != NULL) { if (ctx != NULL) {
isc_tlsctx_enable_http2server_alpn(ctx); isc_tlsctx_enable_http2server_alpn(ctx);
result = isc_nm_listentls(mgr, iface, httplisten_acceptcb, sock, result = isc_nm_listentls(mgr, iface, httplisten_acceptcb, sock,
@@ -2462,6 +2462,96 @@ isc_nm_listenhttp(isc_nm_t *mgr, isc_sockaddr_t *iface, int backlog,
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
isc_nm_http_endpoints_t *
isc_nm_http_endpoints_new(isc_mem_t *mctx) {
isc_nm_http_endpoints_t *restrict eps;
REQUIRE(mctx != NULL);
eps = isc_mem_get(mctx, sizeof(*eps));
*eps = (isc_nm_http_endpoints_t){ .mctx = NULL };
isc_mem_attach(mctx, &eps->mctx);
ISC_LIST_INIT(eps->handler_cbargs);
ISC_LIST_INIT(eps->handlers);
isc_refcount_init(&eps->references, 1);
atomic_init(&eps->in_use, false);
return eps;
}
void
isc_nm_http_endpoints_detach(isc_nm_http_endpoints_t **restrict epsp) {
isc_nm_http_endpoints_t *restrict eps;
isc_mem_t *mctx;
isc_nm_httphandler_t *handler = NULL;
isc_nm_httpcbarg_t *httpcbarg = NULL;
REQUIRE(epsp != NULL);
eps = *epsp;
REQUIRE(eps != NULL);
if (isc_refcount_decrement(&eps->references) > 1) {
return;
}
mctx = eps->mctx;
/* Delete all handlers */
handler = ISC_LIST_HEAD(eps->handlers);
while (handler != NULL) {
isc_nm_httphandler_t *next = NULL;
next = ISC_LIST_NEXT(handler, link);
ISC_LIST_DEQUEUE(eps->handlers, handler, link);
isc_mem_free(mctx, handler->path);
isc_mem_put(mctx, handler, sizeof(*handler));
handler = next;
}
httpcbarg = ISC_LIST_HEAD(eps->handler_cbargs);
while (httpcbarg != NULL) {
isc_nm_httpcbarg_t *next = NULL;
next = ISC_LIST_NEXT(httpcbarg, link);
ISC_LIST_DEQUEUE(eps->handler_cbargs, httpcbarg, link);
isc_mem_put(mctx, httpcbarg, sizeof(isc_nm_httpcbarg_t));
httpcbarg = next;
}
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(targetp != NULL && *targetp == NULL);
isc_refcount_increment(&source->references);
*targetp = source;
}
static isc_nm_httphandler_t *
http_endpoints_find(const char *request_path,
const isc_nm_http_endpoints_t *restrict eps) {
isc_nm_httphandler_t *handler = NULL;
if (request_path == NULL || *request_path == '\0') {
return (NULL);
}
for (handler = ISC_LIST_HEAD(eps->handlers); handler != NULL;
handler = ISC_LIST_NEXT(handler, link))
{
if (!strcmp(request_path, handler->path)) {
break;
}
}
return (handler);
}
/* /*
* In DoH we just need to intercept the request - the response can be sent * In DoH we just need to intercept the request - the response can be sent
* to the client code via the nmhandle directly as it's always just the * to the client code via the nmhandle directly as it's always just the
@@ -2484,40 +2574,41 @@ http_callback(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *data,
} }
isc_result_t isc_result_t
isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb, isc_nm_http_endpoints_add(isc_nm_http_endpoints_t *restrict eps,
void *cbarg, size_t extrahandlesize) { const char *uri, const isc_nm_recv_cb_t cb,
isc_nm_httphandler_t *handler = NULL; void *cbarg, const size_t extrahandlesize) {
isc_nm_httpcbarg_t *httpcbarg = NULL; isc_mem_t *mctx;
isc_nm_httphandler_t *restrict handler = NULL;
isc_nm_httpcbarg_t *restrict httpcbarg = NULL;
bool newhandler = false; bool newhandler = false;
REQUIRE(VALID_NMSOCK(sock)); REQUIRE(eps != NULL);
REQUIRE(sock->type == isc_nm_httplistener);
REQUIRE(isc_nm_http_path_isvalid(uri)); REQUIRE(isc_nm_http_path_isvalid(uri));
REQUIRE(atomic_load(&eps->in_use) == false);
httpcbarg = isc_mem_get(sock->mgr->mctx, sizeof(isc_nm_httpcbarg_t)); mctx = eps->mctx;
httpcbarg = isc_mem_get(mctx, sizeof(isc_nm_httpcbarg_t));
*httpcbarg = (isc_nm_httpcbarg_t){ .cb = cb, .cbarg = cbarg }; *httpcbarg = (isc_nm_httpcbarg_t){ .cb = cb, .cbarg = cbarg };
ISC_LINK_INIT(httpcbarg, link); ISC_LINK_INIT(httpcbarg, link);
if (find_server_request_handler(uri, sock) == NULL) { if (http_endpoints_find(uri, eps) == NULL) {
handler = isc_mem_get(sock->mgr->mctx, sizeof(*handler)); handler = isc_mem_get(mctx, sizeof(*handler));
*handler = (isc_nm_httphandler_t){ *handler = (isc_nm_httphandler_t){
.cb = http_callback, .cb = http_callback,
.cbarg = httpcbarg, .cbarg = httpcbarg,
.extrahandlesize = extrahandlesize, .extrahandlesize = extrahandlesize,
.path = isc_mem_strdup(sock->mgr->mctx, uri) .path = isc_mem_strdup(mctx, uri)
}; };
ISC_LINK_INIT(handler, link); ISC_LINK_INIT(handler, link);
newhandler = true; newhandler = true;
} }
RWLOCK(&sock->h2.lock, isc_rwlocktype_write);
if (newhandler) { if (newhandler) {
ISC_LIST_APPEND(sock->h2.handlers, handler, link); ISC_LIST_APPEND(eps->handlers, handler, link);
} }
ISC_LIST_APPEND(sock->h2.handler_cbargs, httpcbarg, link); ISC_LIST_APPEND(eps->handler_cbargs, httpcbarg, link);
RWUNLOCK(&sock->h2.lock, isc_rwlocktype_write);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
@@ -2544,37 +2635,6 @@ isc__nm_http_stoplistening(isc_nmsocket_t *sock) {
} }
} }
static void
clear_handlers(isc_nmsocket_t *sock) {
isc_nm_httphandler_t *handler = NULL;
isc_nm_httpcbarg_t *httpcbarg = NULL;
/* Delete all handlers */
RWLOCK(&sock->h2.lock, isc_rwlocktype_write);
handler = ISC_LIST_HEAD(sock->h2.handlers);
while (handler != NULL) {
isc_nm_httphandler_t *next = NULL;
next = ISC_LIST_NEXT(handler, link);
ISC_LIST_DEQUEUE(sock->h2.handlers, handler, link);
isc_mem_free(sock->mgr->mctx, handler->path);
isc_mem_put(sock->mgr->mctx, handler, sizeof(*handler));
handler = next;
}
httpcbarg = ISC_LIST_HEAD(sock->h2.handler_cbargs);
while (httpcbarg != NULL) {
isc_nm_httpcbarg_t *next = NULL;
next = ISC_LIST_NEXT(httpcbarg, link);
ISC_LIST_DEQUEUE(sock->h2.handler_cbargs, httpcbarg, link);
isc_mem_put(sock->mgr->mctx, httpcbarg,
sizeof(isc_nm_httpcbarg_t));
httpcbarg = next;
}
RWUNLOCK(&sock->h2.lock, isc_rwlocktype_write);
}
void void
isc__nm_async_httpstop(isc__networker_t *worker, isc__netievent_t *ev0) { isc__nm_async_httpstop(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__netievent_httpstop_t *ievent = (isc__netievent_httpstop_t *)ev0; isc__netievent_httpstop_t *ievent = (isc__netievent_httpstop_t *)ev0;
@@ -2903,12 +2963,6 @@ isc__nm_http_initsocket(isc_nmsocket_t *sock) {
.request_type = ISC_HTTP_REQ_UNSUPPORTED, .request_type = ISC_HTTP_REQ_UNSUPPORTED,
.request_scheme = ISC_HTTP_SCHEME_UNSUPPORTED, .request_scheme = ISC_HTTP_SCHEME_UNSUPPORTED,
}; };
if (sock->type == isc_nm_httplistener) {
ISC_LIST_INIT(sock->h2.handlers);
ISC_LIST_INIT(sock->h2.handler_cbargs);
isc_rwlock_init(&sock->h2.lock, 0, 1);
}
} }
void void
@@ -2922,9 +2976,11 @@ isc__nm_http_cleanup_data(isc_nmsocket_t *sock) {
if (sock->type == isc_nm_httplistener || if (sock->type == isc_nm_httplistener ||
sock->type == isc_nm_httpsocket) { sock->type == isc_nm_httpsocket) {
if (sock->type == isc_nm_httplistener) { if (sock->type == isc_nm_httplistener &&
clear_handlers(sock); sock->h2.listener_endpoints != NULL) {
isc_rwlock_destroy(&sock->h2.lock); /* Delete all handlers */
isc_nm_http_endpoints_detach(
&sock->h2.listener_endpoints);
} }
if (sock->h2.request_path != NULL) { if (sock->h2.request_path != NULL) {

View File

@@ -31,7 +31,6 @@
#include <isc/refcount.h> #include <isc/refcount.h>
#include <isc/region.h> #include <isc/region.h>
#include <isc/result.h> #include <isc/result.h>
#include <isc/rwlock.h>
#include <isc/sockaddr.h> #include <isc/sockaddr.h>
#include <isc/stats.h> #include <isc/stats.h>
#include <isc/thread.h> #include <isc/thread.h>
@@ -315,15 +314,6 @@ typedef union {
isc_nm_accept_cb_t accept; isc_nm_accept_cb_t accept;
} isc__nm_cb_t; } isc__nm_cb_t;
typedef struct isc_nm_httphandler isc_nm_httphandler_t;
struct isc_nm_httphandler {
char *path;
isc_nm_recv_cb_t cb;
void *cbarg;
size_t extrahandlesize;
LINK(isc_nm_httphandler_t) link;
};
/* /*
* Wrapper around uv_req_t with 'our' fields in it. req->data should * Wrapper around uv_req_t with 'our' fields in it. req->data should
* always point to its parent. Note that we always allocate more than * always point to its parent. Note that we always allocate more than
@@ -756,6 +746,7 @@ enum {
STATID_ACTIVE = 10 STATID_ACTIVE = 10
}; };
#if HAVE_LIBNGHTTP2
typedef struct isc_nmsocket_tls_send_req { typedef struct isc_nmsocket_tls_send_req {
isc_nmsocket_t *tlssock; isc_nmsocket_t *tlssock;
isc_region_t data; isc_region_t data;
@@ -783,6 +774,24 @@ typedef struct isc_nm_httpcbarg {
LINK(struct isc_nm_httpcbarg) link; LINK(struct isc_nm_httpcbarg) link;
} isc_nm_httpcbarg_t; } isc_nm_httpcbarg_t;
typedef struct isc_nm_httphandler {
char *path;
isc_nm_recv_cb_t cb;
void *cbarg;
size_t extrahandlesize;
LINK(struct isc_nm_httphandler) link;
} isc_nm_httphandler_t;
struct isc_nm_http_endpoints {
isc_mem_t *mctx;
ISC_LIST(isc_nm_httphandler_t) handlers;
ISC_LIST(isc_nm_httpcbarg_t) handler_cbargs;
isc_refcount_t references;
atomic_bool in_use;
};
typedef struct isc_nmsocket_h2 { typedef struct isc_nmsocket_h2 {
isc_nmsocket_t *psock; /* owner of the structure */ isc_nmsocket_t *psock; /* owner of the structure */
char *request_path; char *request_path;
@@ -816,9 +825,7 @@ typedef struct isc_nmsocket_h2 {
void *cbarg; void *cbarg;
LINK(struct isc_nmsocket_h2) link; LINK(struct isc_nmsocket_h2) link;
ISC_LIST(isc_nm_httphandler_t) handlers; isc_nm_http_endpoints_t *listener_endpoints;
ISC_LIST(isc_nm_httpcbarg_t) handler_cbargs;
isc_rwlock_t lock;
bool response_submitted; bool response_submitted;
struct { struct {
@@ -829,6 +836,7 @@ typedef struct isc_nmsocket_h2 {
void *cstream; void *cstream;
} connect; } connect;
} isc_nmsocket_h2_t; } isc_nmsocket_h2_t;
#endif /* HAVE_LIBNGHTTP2 */
typedef void (*isc_nm_closehandlecb_t)(void *arg); typedef void (*isc_nm_closehandlecb_t)(void *arg);
/*%< /*%<
@@ -875,6 +883,7 @@ struct isc_nmsocket {
isc__nm_uvreq_t *pending_req; isc__nm_uvreq_t *pending_req;
} tls; } tls;
#if HAVE_LIBNGHTTP2
/*% TLS stuff */ /*% TLS stuff */
struct tlsstream { struct tlsstream {
bool server; bool server;
@@ -895,6 +904,7 @@ struct isc_nmsocket {
} tlsstream; } tlsstream;
isc_nmsocket_h2_t h2; isc_nmsocket_h2_t h2;
#endif /* HAVE_LIBNGHTTP2 */
/*% /*%
* quota is the TCP client, attached when a TCP connection * quota is the TCP client, attached when a TCP connection
* is established. pquota is a non-attached pointer to the * is established. pquota is a non-attached pointer to the

View File

@@ -1515,7 +1515,9 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
isc_condition_init(&sock->scond); isc_condition_init(&sock->scond);
isc_refcount_init(&sock->references, 1); isc_refcount_init(&sock->references, 1);
#if HAVE_LIBNGHTTP2
memset(&sock->tlsstream, 0, sizeof(sock->tlsstream)); memset(&sock->tlsstream, 0, sizeof(sock->tlsstream));
#endif /* HAVE_LIBNGHTTP2 */
NETMGR_TRACE_LOG("isc__nmsocket_init():%p->references = %" PRIuFAST32 NETMGR_TRACE_LOG("isc__nmsocket_init():%p->references = %" PRIuFAST32
"\n", "\n",

View File

@@ -9,7 +9,7 @@
* information regarding copyright ownership. * information regarding copyright ownership.
*/ */
#if HAVE_CMOCKA #if defined(HAVE_CMOCKA) && defined(HAVE_LIBNGHTTP2)
#include <inttypes.h> #include <inttypes.h>
#include <sched.h> /* IWYU pragma: keep */ #include <sched.h> /* IWYU pragma: keep */
#include <setjmp.h> #include <setjmp.h>
@@ -83,6 +83,8 @@ static isc_tlsctx_t *client_tlsctx = NULL;
static isc_quota_t listener_quota; static isc_quota_t listener_quota;
static atomic_bool check_listener_quota = ATOMIC_VAR_INIT(false); static atomic_bool check_listener_quota = ATOMIC_VAR_INIT(false);
static isc_nm_http_endpoints_t *endpoints = NULL;
/* Timeout for soft-timeout tests (0.05 seconds) */ /* Timeout for soft-timeout tests (0.05 seconds) */
#define T_SOFT 50 #define T_SOFT 50
@@ -336,6 +338,9 @@ nm_setup(void **state) {
isc_quota_init(&listener_quota, 0); isc_quota_init(&listener_quota, 0);
atomic_store(&check_listener_quota, false); atomic_store(&check_listener_quota, false);
INSIST(endpoints == NULL);
endpoints = isc_nm_http_endpoints_new(test_mctx);
*state = nm; *state = nm;
return (0); return (0);
@@ -360,6 +365,8 @@ nm_teardown(void **state) {
isc_quota_destroy(&listener_quota); isc_quota_destroy(&listener_quota);
isc_nm_http_endpoints_detach(&endpoints);
return (0); return (0);
} }
@@ -483,8 +490,11 @@ mock_doh_uv_tcp_bind(void **state) {
WILL_RETURN(uv_tcp_bind, UV_EADDRINUSE); WILL_RETURN(uv_tcp_bind, UV_EADDRINUSE);
result = isc_nm_http_endpoints_add(endpoints, DOH_PATH, noop_read_cb,
NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL,
0, &listen_sock); endpoints, 0, &listen_sock);
assert_int_not_equal(result, ISC_R_SUCCESS); assert_int_not_equal(result, ISC_R_SUCCESS);
assert_null(listen_sock); assert_null(listen_sock);
@@ -500,11 +510,13 @@ doh_noop(void **state) {
isc_nmsocket_t *listen_sock = NULL; isc_nmsocket_t *listen_sock = NULL;
char req_url[256]; char req_url[256];
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, result = isc_nm_http_endpoints_add(endpoints, DOH_PATH, noop_read_cb,
0, &listen_sock); NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL,
endpoints, 0, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, noop_read_cb, NULL,
0);
isc_nm_stoplistening(listen_sock); isc_nm_stoplistening(listen_sock);
isc_nmsocket_close(&listen_sock); isc_nmsocket_close(&listen_sock);
@@ -546,12 +558,12 @@ doh_noresponse(void **state) {
isc_nmsocket_t *listen_sock = NULL; isc_nmsocket_t *listen_sock = NULL;
char req_url[256]; char req_url[256];
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, result = isc_nm_http_endpoints_add(endpoints, DOH_PATH, noop_read_cb,
0, &listen_sock); NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, noop_read_cb, NULL, result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL,
0); endpoints, 0, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
@@ -647,8 +659,12 @@ doh_timeout_recovery(void **state) {
isc_tlsctx_t *ctx = atomic_load(&use_TLS) ? server_tlsctx : NULL; isc_tlsctx_t *ctx = atomic_load(&use_TLS) ? server_tlsctx : NULL;
char req_url[256]; char req_url[256];
result = isc_nm_http_endpoints_add(endpoints, DOH_PATH,
doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL, result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, NULL, NULL,
0, &listen_sock); endpoints, 0, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
/* /*
@@ -656,9 +672,6 @@ doh_timeout_recovery(void **state) {
* reads to time out. * reads to time out.
*/ */
noanswer = true; noanswer = true;
result = isc_nm_http_endpoint(listen_sock, DOH_PATH,
doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS);
/* /*
* Shorten all the TCP client timeouts to 0.05 seconds. * Shorten all the TCP client timeouts to 0.05 seconds.
@@ -777,13 +790,14 @@ doh_recv_one(void **state) {
atomic_store(&total_sends, 1); atomic_store(&total_sends, 1);
atomic_store(&nsends, atomic_load(&total_sends)); atomic_store(&nsends, atomic_load(&total_sends));
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
atomic_load(&use_TLS) ? server_tlsctx : NULL, result = isc_nm_http_endpoints_add(endpoints, DOH_PATH,
0, &listen_sock); doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
doh_receive_request_cb, NULL, 0); atomic_load(&use_TLS) ? server_tlsctx : NULL,
endpoints, 0, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
@@ -927,13 +941,14 @@ doh_recv_two(void **state) {
atomic_store(&total_sends, 2); atomic_store(&total_sends, 2);
atomic_store(&nsends, atomic_load(&total_sends)); atomic_store(&nsends, atomic_load(&total_sends));
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
atomic_load(&use_TLS) ? server_tlsctx : NULL, result = isc_nm_http_endpoints_add(endpoints, DOH_PATH,
0, &listen_sock); doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
doh_receive_request_cb, NULL, 0); atomic_load(&use_TLS) ? server_tlsctx : NULL,
endpoints, 0, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url,
@@ -1047,13 +1062,13 @@ doh_recv_send(void **state) {
isc_thread_t threads[32] = { 0 }; isc_thread_t threads[32] = { 0 };
isc_quota_t *quotap = init_listener_quota(workers); isc_quota_t *quotap = init_listener_quota(workers);
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap, result = isc_nm_http_endpoints_add(endpoints, DOH_PATH,
atomic_load(&use_TLS) ? server_tlsctx : NULL, doh_receive_request_cb, NULL, 0);
0, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
doh_receive_request_cb, NULL, 0); atomic_load(&use_TLS) ? server_tlsctx : NULL,
endpoints, 0, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
for (size_t i = 0; i < nthreads; i++) { for (size_t i = 0; i < nthreads; i++) {
@@ -1151,13 +1166,14 @@ doh_recv_half_send(void **state) {
atomic_store(&total_sends, atomic_load(&total_sends) / 2); atomic_store(&total_sends, atomic_load(&total_sends) / 2);
atomic_store(&nsends, atomic_load(&total_sends)); atomic_store(&nsends, atomic_load(&total_sends));
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
atomic_load(&use_TLS) ? server_tlsctx : NULL, result = isc_nm_http_endpoints_add(endpoints, DOH_PATH,
0, &listen_sock); doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
doh_receive_request_cb, NULL, 0); atomic_load(&use_TLS) ? server_tlsctx : NULL,
endpoints, 0, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
for (size_t i = 0; i < nthreads; i++) { for (size_t i = 0; i < nthreads; i++) {
@@ -1260,13 +1276,14 @@ doh_half_recv_send(void **state) {
atomic_store(&total_sends, atomic_load(&total_sends) / 2); atomic_store(&total_sends, atomic_load(&total_sends) / 2);
atomic_store(&nsends, atomic_load(&total_sends)); atomic_store(&nsends, atomic_load(&total_sends));
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
atomic_load(&use_TLS) ? server_tlsctx : NULL, result = isc_nm_http_endpoints_add(endpoints, DOH_PATH,
0, &listen_sock); doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
doh_receive_request_cb, NULL, 0); atomic_load(&use_TLS) ? server_tlsctx : NULL,
endpoints, 0, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
for (size_t i = 0; i < nthreads; i++) { for (size_t i = 0; i < nthreads; i++) {
@@ -1369,13 +1386,14 @@ doh_half_recv_half_send(void **state) {
atomic_store(&total_sends, atomic_load(&total_sends) / 2); atomic_store(&total_sends, atomic_load(&total_sends) / 2);
atomic_store(&nsends, atomic_load(&total_sends)); atomic_store(&nsends, atomic_load(&total_sends));
result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
atomic_load(&use_TLS) ? server_tlsctx : NULL, result = isc_nm_http_endpoints_add(endpoints, DOH_PATH,
0, &listen_sock); doh_receive_request_cb, NULL, 0);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
result = isc_nm_http_endpoint(listen_sock, DOH_PATH, result = isc_nm_listenhttp(listen_nm, &tcp_listen_addr, 0, quotap,
doh_receive_request_cb, NULL, 0); atomic_load(&use_TLS) ? server_tlsctx : NULL,
endpoints, 0, &listen_sock);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
for (size_t i = 0; i < nthreads; i++) { for (size_t i = 0; i < nthreads; i++) {
@@ -2174,7 +2192,11 @@ main(void) {
int int
main(void) { main(void) {
#if HAVE_LIBNGHTTP2
printf("1..0 # Skipped: cmocka not available\n"); printf("1..0 # Skipped: cmocka not available\n");
#else
printf("1..0 # Skipped: libnghttp2 is not available\n");
#endif
return (SKIPPED_TEST_EXIT_CODE); return (SKIPPED_TEST_EXIT_CODE);
} }

View File

@@ -542,25 +542,29 @@ ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
size_t neps, isc_quota_t *quota, size_t neps, isc_quota_t *quota,
uint32_t max_concurrent_streams) { uint32_t max_concurrent_streams) {
#if HAVE_LIBNGHTTP2 #if HAVE_LIBNGHTTP2
isc_result_t result; isc_result_t result = ISC_R_FAILURE;
isc_nmsocket_t *sock = NULL; isc_nmsocket_t *sock = NULL;
isc_nm_http_endpoints_t *epset = NULL;
result = isc_nm_listenhttp(ifp->mgr->nm, &ifp->addr, ifp->mgr->backlog, epset = isc_nm_http_endpoints_new(ifp->mgr->mctx);
quota, sslctx, max_concurrent_streams,
&sock);
if (result == ISC_R_SUCCESS) { for (size_t i = 0; i < neps; i++) {
for (size_t i = 0; i < neps; i++) { result = isc_nm_http_endpoints_add(epset, eps[i],
INSIST(isc_nm_http_path_isvalid(eps[i])); ns__client_request, ifp,
result = isc_nm_http_endpoint(sock, eps[i], sizeof(ns_client_t));
ns__client_request, ifp, if (result != ISC_R_SUCCESS) {
sizeof(ns_client_t)); break;
if (result != ISC_R_SUCCESS) {
break;
}
} }
} }
if (result == ISC_R_SUCCESS) {
result = isc_nm_listenhttp(
ifp->mgr->nm, &ifp->addr, ifp->mgr->backlog, quota,
sslctx, epset, max_concurrent_streams, &sock);
}
isc_nm_http_endpoints_detach(&epset);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
"creating %s socket: %s", "creating %s socket: %s",