diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index cb505f9237..70e12ce369 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -506,24 +506,6 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, * 'cb'. */ -typedef void (*isc_nm_http_cb_t)(isc_nmhandle_t *handle, isc_result_t eresult, - isc_region_t *data, void *cbarg); -/*%< - * Callback function to be used when receiving an HTTP request. - * - * 'handle' the handle that can be used to send back the answer. - * 'eresult' the result of the event. - * 'data' contains the received data, if any. It will be freed - * after return by caller. - * 'cbarg' the callback argument passed to listen function. - */ - -isc_result_t -isc_nm_http_connect_send_request(isc_nm_t *mgr, const char *uri, bool POST, - isc_region_t *message, isc_nm_recv_cb_t cb, - void *cbarg, isc_tlsctx_t *ctx, - unsigned int timeout); - isc_result_t isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, const char *uri, bool POST, isc_nm_cb_t cb, void *cbarg, @@ -540,11 +522,5 @@ isc_nm_listenhttp(isc_nm_t *mgr, isc_nmiface_t *iface, int backlog, isc_nmsocket_t **sockp); isc_result_t -isc_nm_http_add_endpoint(isc_nmsocket_t *sock, const char *uri, - isc_nm_http_cb_t cb, void *cbarg, - size_t extrahandlesize); - -isc_result_t -isc_nm_http_add_doh_endpoint(isc_nmsocket_t *sock, const char *uri, - isc_nm_recv_cb_t cb, void *cbarg, - size_t extrahandlesize); +isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb, + void *cbarg, size_t extrahandlesize); diff --git a/lib/isc/netmgr/http.c b/lib/isc/netmgr/http.c index b90abce05c..c0c5702a71 100644 --- a/lib/isc/netmgr/http.c +++ b/lib/isc/netmgr/http.c @@ -36,13 +36,13 @@ (((namelen) == sizeof(header) - 1) && \ (strncasecmp((header), (const char *)(name), (namelen)) == 0)) -typedef struct isc_nm_http2_response_status { +typedef struct isc_nm_http_response_status { size_t code; size_t content_length; bool content_type_valid; -} isc_nm_http2_response_status_t; +} isc_nm_http_response_status_t; -typedef struct http2_client_stream { +typedef struct http_client_stream { isc_nm_recv_cb_t read_cb; void *read_cbarg; @@ -68,15 +68,15 @@ typedef struct http2_client_stream { char *GET_path; size_t GET_path_len; - isc_nm_http2_response_status_t response_status; + isc_nm_http_response_status_t response_status; - LINK(struct http2_client_stream) link; -} http2_client_stream_t; + LINK(struct http_client_stream) link; +} http_client_stream_t; #define HTTP2_SESSION_MAGIC ISC_MAGIC('H', '2', 'S', 'S') #define VALID_HTTP2_SESSION(t) ISC_MAGIC_VALID(t, HTTP2_SESSION_MAGIC) -struct isc_nm_http2_session { +struct isc_nm_http_session { unsigned int magic; isc_mem_t *mctx; bool sending; @@ -86,11 +86,8 @@ struct isc_nm_http2_session { nghttp2_session *ngsession; bool client; - ISC_LIST(http2_client_stream_t) cstreams; + ISC_LIST(http_client_stream_t) cstreams; ISC_LIST(isc_nmsocket_h2_t) sstreams; -#ifdef NETMGR_TRACE - size_t sstreams_count; -#endif /* NETMGR_TRACE */ isc_nmhandle_t *handle; isc_nmsocket_t *serversocket; @@ -103,7 +100,7 @@ struct isc_nm_http2_session { SSL_CTX *ssl_ctx; }; -typedef enum isc_http2_error_responses { +typedef enum isc_http_error_responses { ISC_HTTP_ERROR_SUCCESS, /* 200 */ ISC_HTTP_ERROR_NOT_FOUND, /* 404 */ ISC_HTTP_ERROR_PAYLOAD_TOO_LARGE, /* 413 */ @@ -113,20 +110,20 @@ typedef enum isc_http2_error_responses { ISC_HTTP_ERROR_NOT_IMPLEMENTED, /* 501 */ ISC_HTTP_ERROR_GENERIC, /* 500 Internal Server Error */ ISC_HTTP_ERROR_MAX -} isc_http2_error_responses_t; +} isc_http_error_responses_t; static void -http2_do_bio(isc_nm_http2_session_t *session); +http_do_bio(isc_nm_http_session_t *session); static void failed_httpstream_read_cb(isc_nmsocket_t *sock, isc_result_t result, - isc_nm_http2_session_t *session); + isc_nm_http_session_t *session); static void -failed_read_cb(isc_result_t result, isc_nm_http2_session_t *session); +failed_read_cb(isc_result_t result, isc_nm_http_session_t *session); static int -server_send_error_response(const isc_http2_error_responses_t error, +server_send_error_response(const isc_http_error_responses_t error, nghttp2_session *ngsession, isc_nmsocket_t *socket); static bool @@ -136,9 +133,9 @@ inactive(isc_nmsocket_t *sock) { (sock->server != NULL && !isc__nmsocket_active(sock->server))); } -static http2_client_stream_t * -find_http2_client_stream(int32_t stream_id, isc_nm_http2_session_t *session) { - http2_client_stream_t *cstream = NULL; +static http_client_stream_t * +find_http_client_stream(int32_t stream_id, isc_nm_http_session_t *session) { + http_client_stream_t *cstream = NULL; REQUIRE(VALID_HTTP2_SESSION(session)); for (cstream = ISC_LIST_HEAD(session->cstreams); cstream != NULL; @@ -153,16 +150,16 @@ find_http2_client_stream(int32_t stream_id, isc_nm_http2_session_t *session) { } static isc_result_t -get_http2_client_stream(isc_mem_t *mctx, http2_client_stream_t **streamp, - const char *uri) { - http2_client_stream_t *stream = NULL; +get_http_client_stream(isc_mem_t *mctx, http_client_stream_t **streamp, + const char *uri) { + http_client_stream_t *stream = NULL; isc_result_t result; REQUIRE(streamp != NULL && *streamp == NULL); REQUIRE(uri != NULL); - stream = isc_mem_get(mctx, sizeof(http2_client_stream_t)); - *stream = (http2_client_stream_t){ .stream_id = -1, .rbufsize = 0 }; + stream = isc_mem_get(mctx, sizeof(http_client_stream_t)); + *stream = (http_client_stream_t){ .stream_id = -1, .rbufsize = 0 }; stream->uri = isc_mem_strdup(mctx, uri); @@ -170,7 +167,7 @@ get_http2_client_stream(isc_mem_t *mctx, http2_client_stream_t **streamp, &stream->up); if (result != ISC_R_SUCCESS) { isc_mem_free(mctx, stream->uri); - isc_mem_put(mctx, stream, sizeof(http2_client_stream_t)); + isc_mem_put(mctx, stream, sizeof(http_client_stream_t)); return (result); } @@ -226,7 +223,7 @@ get_http2_client_stream(isc_mem_t *mctx, http2_client_stream_t **streamp, } static void -put_http2_client_stream(isc_mem_t *mctx, http2_client_stream_t *stream) { +put_http_client_stream(isc_mem_t *mctx, http_client_stream_t *stream) { isc_mem_put(mctx, stream->path, stream->pathlen); isc_mem_put(mctx, stream->authority, stream->up.field_data[ISC_UF_HOST].len + AUTHEXTRA); @@ -240,11 +237,11 @@ put_http2_client_stream(isc_mem_t *mctx, http2_client_stream_t *stream) { isc_mem_put(mctx, stream->postdata.base, stream->postdata.length); } - isc_mem_put(mctx, stream, sizeof(http2_client_stream_t)); + isc_mem_put(mctx, stream, sizeof(http_client_stream_t)); } static void -delete_http2_session(isc_nm_http2_session_t *session) { +delete_http_session(isc_nm_http_session_t *session) { REQUIRE(ISC_LIST_EMPTY(session->sstreams)); REQUIRE(ISC_LIST_EMPTY(session->cstreams)); @@ -253,11 +250,11 @@ delete_http2_session(isc_nm_http2_session_t *session) { SSL_CTX_free(session->ssl_ctx); } isc_mem_putanddetach(&session->mctx, session, - sizeof(isc_nm_http2_session_t)); + sizeof(isc_nm_http_session_t)); } static void -finish_http2_session(isc_nm_http2_session_t *session) { +finish_http_session(isc_nm_http_session_t *session) { if (session->handle != NULL) { isc_nm_pauseread(session->handle); isc_nmhandle_detach(&session->handle); @@ -267,13 +264,13 @@ finish_http2_session(isc_nm_http2_session_t *session) { session->ngsession = NULL; } if (!ISC_LIST_EMPTY(session->cstreams)) { - http2_client_stream_t *cstream = + http_client_stream_t *cstream = ISC_LIST_HEAD(session->cstreams); while (cstream != NULL) { - http2_client_stream_t *next = ISC_LIST_NEXT(cstream, - link); + http_client_stream_t *next = ISC_LIST_NEXT(cstream, + link); ISC_LIST_DEQUEUE(session->cstreams, cstream, link); - put_http2_client_stream(session->mctx, cstream); + put_http_client_stream(session->mctx, cstream); cstream = next; } @@ -297,14 +294,14 @@ static int on_data_chunk_recv_callback(nghttp2_session *ngsession, uint8_t flags, int32_t stream_id, const uint8_t *data, size_t len, void *user_data) { - isc_nm_http2_session_t *session = (isc_nm_http2_session_t *)user_data; + isc_nm_http_session_t *session = (isc_nm_http_session_t *)user_data; UNUSED(ngsession); UNUSED(flags); if (session->client) { - http2_client_stream_t *cstream = - find_http2_client_stream(stream_id, session); + http_client_stream_t *cstream = + find_http_client_stream(stream_id, session); if (cstream) { size_t new_rbufsize = cstream->rbufsize + len; if (new_rbufsize <= MAX_DNS_MESSAGE_SIZE && @@ -349,7 +346,7 @@ on_data_chunk_recv_callback(nghttp2_session *ngsession, uint8_t flags, static int on_stream_close_callback(nghttp2_session *ngsession, int32_t stream_id, uint32_t error_code, void *user_data) { - isc_nm_http2_session_t *session = (isc_nm_http2_session_t *)user_data; + isc_nm_http_session_t *session = (isc_nm_http_session_t *)user_data; int rv = 0; REQUIRE(VALID_HTTP2_SESSION(session)); @@ -358,11 +355,11 @@ on_stream_close_callback(nghttp2_session *ngsession, int32_t stream_id, /* NOTE: calling isc_nm_cancelread() or * isc__nmsocket_prep_destroy() on a socket will lead to an - * indirect call to the delete_http2_session() which will, in + * indirect call to the delete_http_session() which will, in * turn, perform required stream session cleanup.*/ if (session->client) { - http2_client_stream_t *cstream = - find_http2_client_stream(stream_id, session); + http_client_stream_t *cstream = + find_http_client_stream(stream_id, session); if (cstream) { isc_result_t result = cstream->response_status.code >= 200 && @@ -375,7 +372,7 @@ on_stream_close_callback(nghttp2_session *ngsession, int32_t stream_id, cstream->rbufsize }, cstream->read_cbarg); ISC_LIST_UNLINK(session->cstreams, cstream, link); - put_http2_client_stream(session->mctx, cstream); + put_http_client_stream(session->mctx, cstream); if (ISC_LIST_EMPTY(session->cstreams)) { rv = nghttp2_session_terminate_session( ngsession, NGHTTP2_NO_ERROR); @@ -408,49 +405,9 @@ on_stream_close_callback(nghttp2_session *ngsession, int32_t stream_id, return (0); } -#ifndef OPENSSL_NO_NEXTPROTONEG -/* - * NPN TLS extension client callback. We check that server advertised - * the HTTP/2 protocol the nghttp2 library supports. - */ -static int -select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen, - const unsigned char *in, unsigned int inlen, void *arg) { - UNUSED(ssl); - UNUSED(arg); - - if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) { - return (SSL_TLSEXT_ERR_NOACK); - } - return (SSL_TLSEXT_ERR_OK); -} -#endif /* !OPENSSL_NO_NEXTPROTONEG */ - -/* Create SSL_CTX. */ -static SSL_CTX * -create_client_ssl_ctx(void) { - SSL_CTX *ssl_ctx = NULL; - - RUNTIME_CHECK(isc_tlsctx_createclient(&ssl_ctx) == ISC_R_SUCCESS); - RUNTIME_CHECK(ssl_ctx != NULL); - -#ifndef OPENSSL_NO_NEXTPROTONEG - SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL); -#endif /* !OPENSSL_NO_NEXTPROTONEG */ - -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - SSL_CTX_set_alpn_protos(ssl_ctx, - (const unsigned char *)NGHTTP2_PROTO_ALPN, - NGHTTP2_PROTO_ALPN_LEN); -#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */ - - ENSURE(ssl_ctx != NULL); - return (ssl_ctx); -} - static void -client_handle_status_header(http2_client_stream_t *cstream, - const uint8_t *value, const size_t valuelen) { +client_handle_status_header(http_client_stream_t *cstream, const uint8_t *value, + const size_t valuelen) { char tmp[32] = { 0 }; const size_t tmplen = sizeof(tmp) - 1; @@ -460,7 +417,7 @@ client_handle_status_header(http2_client_stream_t *cstream, } static void -client_handle_content_length_header(http2_client_stream_t *cstream, +client_handle_content_length_header(http_client_stream_t *cstream, const uint8_t *value, const size_t valuelen) { char tmp[32] = { 0 }; @@ -472,7 +429,7 @@ client_handle_content_length_header(http2_client_stream_t *cstream, } static void -client_handle_content_type_header(http2_client_stream_t *cstream, +client_handle_content_type_header(http_client_stream_t *cstream, const uint8_t *value, const size_t valuelen) { const char type_dns_message[] = "application/dns-message"; @@ -490,7 +447,8 @@ client_on_header_callback(nghttp2_session *ngsession, const nghttp2_frame *frame, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags, void *user_data) { - isc_nm_http2_session_t *session = (isc_nm_http2_session_t *)user_data; + isc_nm_http_session_t *session = (isc_nm_http_session_t *)user_data; + http_client_stream_t *cstream = NULL; const char status[] = ":status"; const char content_length[] = "Content-Length"; const char content_type[] = "Content-Type"; @@ -502,8 +460,7 @@ client_on_header_callback(nghttp2_session *ngsession, UNUSED(flags); UNUSED(ngsession); - http2_client_stream_t *cstream = - find_http2_client_stream(frame->hd.stream_id, session); + cstream = find_http_client_stream(frame->hd.stream_id, session); switch (frame->hd.type) { case NGHTTP2_HEADERS: @@ -527,7 +484,7 @@ client_on_header_callback(nghttp2_session *ngsession, } static void -initialize_nghttp2_client_session(isc_nm_http2_session_t *session) { +initialize_nghttp2_client_session(isc_nm_http_session_t *session) { nghttp2_session_callbacks *callbacks = NULL; RUNTIME_CHECK(nghttp2_session_callbacks_new(&callbacks) == 0); @@ -547,7 +504,7 @@ initialize_nghttp2_client_session(isc_nm_http2_session_t *session) { } static bool -send_client_connection_header(isc_nm_http2_session_t *session) { +send_client_connection_header(isc_nm_http_session_t *session) { nghttp2_settings_entry iv[] = { { NGHTTP2_SETTINGS_ENABLE_PUSH, 0 } }; int rv; @@ -577,8 +534,8 @@ static ssize_t client_read_callback(nghttp2_session *ngsession, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { - isc_nm_http2_session_t *session = (isc_nm_http2_session_t *)user_data; - http2_client_stream_t *cstream; + isc_nm_http_session_t *session = (isc_nm_http_session_t *)user_data; + http_client_stream_t *cstream = NULL; REQUIRE(session->client); REQUIRE(!ISC_LIST_EMPTY(session->cstreams)); @@ -586,7 +543,7 @@ client_read_callback(nghttp2_session *ngsession, int32_t stream_id, UNUSED(ngsession); UNUSED(source); - cstream = find_http2_client_stream(stream_id, session); + cstream = find_http_client_stream(stream_id, session); if (!cstream || cstream->stream_id != stream_id) { /* We haven't found the stream, so we are not reading anything */ @@ -619,8 +576,8 @@ client_read_callback(nghttp2_session *ngsession, int32_t stream_id, /* Send HTTP request to the remote peer */ static isc_result_t -client_submit_request(isc_nm_http2_session_t *session, - http2_client_stream_t *stream) { +client_submit_request(isc_nm_http_session_t *session, + http_client_stream_t *stream) { int32_t stream_id; char *uri = stream->uri; isc_url_parser_t *up = &stream->up; @@ -673,7 +630,7 @@ client_submit_request(isc_nm_http2_session_t *session, } stream->stream_id = stream_id; - http2_do_bio(session); + http_do_bio(session); return (ISC_R_SUCCESS); } @@ -682,9 +639,9 @@ client_submit_request(isc_nm_http2_session_t *session, * Read callback from TLS socket. */ static void -https_readcb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region, - void *data) { - isc_nm_http2_session_t *session = (isc_nm_http2_session_t *)data; +http_readcb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region, + void *data) { + isc_nm_http_session_t *session = (isc_nm_http_session_t *)data; ssize_t readlen; REQUIRE(VALID_HTTP2_SESSION(session)); @@ -713,12 +670,12 @@ https_readcb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region, } /* We might have something to receive or send, do IO */ - http2_do_bio(session); + http_do_bio(session); } static void -https_writecb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { - isc_nm_http2_session_t *session = (isc_nm_http2_session_t *)arg; +http_writecb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + isc_nm_http_session_t *session = (isc_nm_http_session_t *)arg; REQUIRE(VALID_HTTP2_SESSION(session)); @@ -728,26 +685,26 @@ https_writecb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { isc_mem_put(session->mctx, session->r.base, session->r.length); session->r.base = NULL; if (result == ISC_R_SUCCESS) { - http2_do_bio(session); + http_do_bio(session); } } static void -http2_do_bio(isc_nm_http2_session_t *session) { +http_do_bio(isc_nm_http_session_t *session) { REQUIRE(VALID_HTTP2_SESSION(session)); if (session->closed || (nghttp2_session_want_read(session->ngsession) == 0 && nghttp2_session_want_write(session->ngsession) == 0)) { - finish_http2_session(session); + finish_http_session(session); return; } if (nghttp2_session_want_read(session->ngsession) != 0) { if (!session->reading) { /* We have not yet started reading from this handle */ - isc_nm_read(session->handle, https_readcb, session); + isc_nm_read(session->handle, http_readcb, session); session->reading = true; } else if (session->bufsize > 0) { /* Leftover data in the buffer, use it */ @@ -763,7 +720,7 @@ http2_do_bio(isc_nm_http2_session_t *session) { session->bufsize -= readlen; } - http2_do_bio(session); + http_do_bio(session); return; } else { /* Resume reading, it's idempotent, wait for more */ @@ -799,7 +756,7 @@ http2_do_bio(isc_nm_http2_session_t *session) { session->r.length = sz; memmove(session->r.base, data, sz); session->sending = true; - isc_nm_send(session->handle, &session->r, https_writecb, + isc_nm_send(session->handle, &session->r, http_writecb, session); return; } @@ -818,11 +775,10 @@ typedef struct http_connect_data { static void transport_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { - char *uri = NULL; http_connect_data_t *pconn_data = (http_connect_data_t *)cbarg; - http_connect_data_t conn_data; - isc_nm_http2_session_t *session = NULL; - isc_mem_t *mctx; + http_connect_data_t conn_data = *pconn_data; + isc_nm_http_session_t *session = NULL; + isc_mem_t *mctx = NULL; REQUIRE(VALID_NMHANDLE(handle)); REQUIRE(cbarg != NULL); @@ -830,8 +786,6 @@ transport_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { handle->sock->h2.session = NULL; mctx = handle->sock->mgr->mctx; - conn_data = *pconn_data; - uri = conn_data.uri; isc_mem_put(mctx, pconn_data, sizeof(*pconn_data)); INSIST(conn_data.connect_cb != NULL); @@ -841,19 +795,16 @@ transport_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { goto error; } - session = isc_mem_get(mctx, sizeof(isc_nm_http2_session_t)); - *session = (isc_nm_http2_session_t){ .magic = HTTP2_SESSION_MAGIC, -#ifdef NETMGR_TRACE - .sstreams_count = 0, -#endif /* NETMGR_TRACE */ - .ssl_ctx_created = - conn_data.ssl_ctx_created, - .ssl_ctx = conn_data.ssl_ctx, - .handle = NULL, - .client = true }; + session = isc_mem_get(mctx, sizeof(isc_nm_http_session_t)); + *session = (isc_nm_http_session_t){ .magic = HTTP2_SESSION_MAGIC, + .ssl_ctx_created = + conn_data.ssl_ctx_created, + .ssl_ctx = conn_data.ssl_ctx, + .handle = NULL, + .client = true }; isc_mem_attach(mctx, &session->mctx); - handle->sock->h2.connect.uri = uri; + handle->sock->h2.connect.uri = conn_data.uri; handle->sock->h2.connect.post = conn_data.post; session->ssl_ctx = conn_data.ssl_ctx; @@ -899,15 +850,17 @@ transport_connect_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { handle->sock->h2.session = NULL; goto error; } + conn_data.connect_cb(handle, ISC_R_SUCCESS, conn_data.connect_cbarg); if (ISC_LIST_EMPTY(session->cstreams)) { - delete_http2_session(session); + delete_http_session(session); isc__nmsocket_prep_destroy(handle->sock); } else { - http2_do_bio(session); + http_do_bio(session); } return; + error: conn_data.connect_cb(handle, result, conn_data.connect_cbarg); if (conn_data.ssl_ctx_created && conn_data.ssl_ctx) { @@ -915,11 +868,11 @@ error: } if (session != NULL) { - delete_http2_session(session); + delete_http_session(session); } - if (uri != NULL) { - isc_mem_free(mctx, uri); + if (conn_data.uri != NULL) { + isc_mem_free(mctx, conn_data.uri); } } @@ -927,111 +880,38 @@ isc_result_t isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, const char *uri, bool post, isc_nm_cb_t cb, void *cbarg, SSL_CTX *ctx, unsigned int timeout, size_t extrahandlesize) { - isc_nmiface_t resolved_peer, resolved_local; - http_connect_data_t *pconn_data; isc_result_t result; - uint16_t port = 80; - isc_url_parser_t url_parser; - bool create_ssl_ctx; - const char http[] = "http"; - const char http_secured[] = "https"; - size_t schema_len; - const char *schema; + isc_nmiface_t localhost; + http_connect_data_t *conn_data = NULL; REQUIRE(VALID_NM(mgr)); REQUIRE(cb != NULL); + REQUIRE(peer != NULL); REQUIRE(uri != NULL); REQUIRE(*uri != '\0'); - result = isc_url_parse(uri, strlen(uri), 0, &url_parser); - if (result != ISC_R_SUCCESS) { - return (result); + if (local == NULL) { + isc_sockaddr_anyofpf(&localhost.addr, + (peer->addr).type.sa.sa_family); + local = &localhost; } - schema_len = url_parser.field_data[ISC_UF_SCHEMA].len; - INSIST(schema_len > 0); - schema = &uri[url_parser.field_data[ISC_UF_SCHEMA].off]; - - if (schema_len == sizeof(http_secured) - 1 && - strncasecmp(http_secured, schema, sizeof(http_secured) - 1) == 0) - { - create_ssl_ctx = true; - } else if (schema_len == sizeof(http) - 1 && - strncasecmp(http, schema, sizeof(http) - 1) == 0) - { - create_ssl_ctx = false; - } else { - INSIST(0); - ISC_UNREACHABLE(); - } - - if (ctx == NULL && create_ssl_ctx) { - port = 443; - ctx = create_client_ssl_ctx(); - } - - if (peer == NULL || local == NULL) { - size_t hostlen = 0; - char *host = NULL; - struct addrinfo hints; - struct addrinfo *res = NULL; - -#ifndef WIN32 /* FIXME */ - /* extract host name */ - hostlen = url_parser.field_data[ISC_UF_HOST].len + 1; - host = isc_mem_get(mgr->mctx, hostlen); - memmove(host, &uri[url_parser.field_data[ISC_UF_HOST].off], - hostlen - 1); - host[hostlen - 1] = '\0'; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_flags = AI_CANONNAME; - - result = getaddrinfo(host, NULL, &hints, &res); - isc_mem_put(mgr->mctx, host, hostlen); - if (result != 0) { - return (ISC_R_FAILURE); - } -#endif /* WIN32 */ - - if ((url_parser.field_set & (1 << ISC_UF_PORT)) != 0) { - port = url_parser.port; - } - - if (peer == NULL) { - (void)isc_sockaddr_fromsockaddr(&resolved_peer.addr, - res->ai_addr); - isc_sockaddr_setport(&resolved_peer.addr, port); - peer = &resolved_peer; - } - if (local == NULL) { - isc_sockaddr_anyofpf(&resolved_local.addr, - res->ai_family); - local = &resolved_local; - } - - freeaddrinfo(res); - } - - pconn_data = isc_mem_get(mgr->mctx, sizeof(*pconn_data)); - *pconn_data = + conn_data = isc_mem_get(mgr->mctx, sizeof(*conn_data)); + *conn_data = (http_connect_data_t){ .uri = isc_mem_strdup(mgr->mctx, uri), .post = post, .connect_cb = cb, .connect_cbarg = cbarg, - .ssl_ctx_created = create_ssl_ctx, + .ssl_ctx_created = (ctx != NULL), .ssl_ctx = ctx }; if (ctx != NULL) { result = isc_nm_tlsconnect(mgr, local, peer, - transport_connect_cb, pconn_data, - ctx, timeout, extrahandlesize); + transport_connect_cb, conn_data, ctx, + timeout, extrahandlesize); } else { result = isc_nm_tcpconnect(mgr, local, peer, - transport_connect_cb, pconn_data, + transport_connect_cb, conn_data, timeout, extrahandlesize); } @@ -1041,9 +921,9 @@ isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_result_t isc_nm_httprequest(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_recv_cb_t reply_cb, void *cbarg) { - http2_client_stream_t *cstream = NULL; + http_client_stream_t *cstream = NULL; isc_result_t result = ISC_R_SUCCESS; - isc_nm_http2_session_t *session = NULL; + isc_nm_http_session_t *session = NULL; isc_mem_t *mctx; REQUIRE(VALID_NMHANDLE(handle)); @@ -1059,8 +939,8 @@ isc_nm_httprequest(isc_nmhandle_t *handle, isc_region_t *region, session = handle->sock->h2.session; mctx = handle->sock->mgr->mctx; - result = get_http2_client_stream(mctx, &cstream, - handle->sock->h2.connect.uri); + result = get_http_client_stream(mctx, &cstream, + handle->sock->h2.connect.uri); if (result != ISC_R_SUCCESS) { goto error; } @@ -1125,86 +1005,22 @@ isc_nm_httprequest(isc_nmhandle_t *handle, isc_region_t *region, ISC_LIST_UNLINK(session->cstreams, cstream, link); goto error; } - http2_do_bio(session); + http_do_bio(session); return (ISC_R_SUCCESS); + error: reply_cb(handle, result, NULL, cbarg); - if (cstream) { - put_http2_client_stream(mctx, cstream); + if (cstream != NULL) { + put_http_client_stream(mctx, cstream); } return (result); } -typedef struct isc_nm_connect_send_data { - isc_nm_recv_cb_t reply_cb; - void *cb_arg; - isc_region_t region; -} isc_nm_connect_send_data_t; - -static void -https_connect_send_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { - isc_nm_connect_send_data_t data; - - REQUIRE(VALID_NMHANDLE(handle)); - - memmove(&data, arg, sizeof(data)); - isc_mem_put(handle->sock->mgr->mctx, arg, sizeof(data)); - if (result != ISC_R_SUCCESS) { - goto error; - } - - result = isc_nm_httprequest(handle, &data.region, data.reply_cb, - data.cb_arg); - if (result != ISC_R_SUCCESS) { - goto error; - } - - isc_mem_put(handle->sock->mgr->mctx, data.region.base, - data.region.length); - return; -error: - data.reply_cb(handle, result, NULL, data.cb_arg); - isc_mem_put(handle->sock->mgr->mctx, data.region.base, - data.region.length); -} - -isc_result_t -isc_nm_http_connect_send_request(isc_nm_t *mgr, const char *uri, bool post, - isc_region_t *region, isc_nm_recv_cb_t cb, - void *cbarg, SSL_CTX *ctx, - unsigned int timeout) { - isc_region_t copy; - isc_result_t result; - isc_nm_connect_send_data_t *data; - - REQUIRE(VALID_NM(mgr)); - REQUIRE(uri != NULL); - REQUIRE(*uri != '\0'); - REQUIRE(region != NULL); - REQUIRE(region->base != NULL); - REQUIRE(region->length != 0); - REQUIRE(region->length <= MAX_DNS_MESSAGE_SIZE); - REQUIRE(cb != NULL); - - copy = (isc_region_t){ .base = isc_mem_get(mgr->mctx, region->length), - .length = region->length }; - memmove(copy.base, region->base, region->length); - data = isc_mem_get(mgr->mctx, sizeof(*data)); - *data = (isc_nm_connect_send_data_t){ .reply_cb = cb, - .cb_arg = cbarg, - .region = copy }; - result = isc_nm_httpconnect(mgr, NULL, NULL, uri, post, - https_connect_send_cb, data, ctx, timeout, - 0); - - return (result); -} - static int server_on_begin_headers_callback(nghttp2_session *ngsession, const nghttp2_frame *frame, void *user_data) { - isc_nm_http2_session_t *session = (isc_nm_http2_session_t *)user_data; + isc_nm_http_session_t *session = (isc_nm_http_session_t *)user_data; isc_nmsocket_t *socket = NULL; isc_sockaddr_t iface; @@ -1217,7 +1033,7 @@ server_on_begin_headers_callback(nghttp2_session *ngsession, socket = isc_mem_get(session->mctx, sizeof(isc_nmsocket_t)); iface = isc_nmhandle_localaddr(session->handle); isc__nmsocket_init(socket, session->serversocket->mgr, - isc_nm_httpstream, (isc_nmiface_t *)&iface); + isc_nm_httpsocket, (isc_nmiface_t *)&iface); socket->h2 = (isc_nmsocket_h2_t){ .bufpos = 0, .bufsize = 0, @@ -1233,23 +1049,15 @@ server_on_begin_headers_callback(nghttp2_session *ngsession, ISC_LINK_INIT(&socket->h2, link); ISC_LIST_APPEND(session->sstreams, &socket->h2, link); -#ifdef NETMGR_TRACE - session->sstreams_count++; - if (session->sstreams_count > 1) { - fprintf(stderr, "HTTP/2 session %p (active streams: %lu)\n", - session, session->sstreams_count); - } -#endif /* NETMGR_TRACE */ - nghttp2_session_set_stream_user_data(ngsession, frame->hd.stream_id, socket); return (0); } -static isc_nm_http2_server_handler_t * +static isc_nm_httphandler_t * find_server_request_handler(const char *request_path, isc_nmsocket_t *serversocket) { - isc_nm_http2_server_handler_t *handler = NULL; + isc_nm_httphandler_t *handler = NULL; REQUIRE(VALID_NMSOCK(serversocket)); @@ -1257,7 +1065,7 @@ find_server_request_handler(const char *request_path, return (NULL); } - RWLOCK(&serversocket->h2.handlers_lock, isc_rwlocktype_read); + RWLOCK(&serversocket->h2.lock, isc_rwlocktype_read); if (atomic_load(&serversocket->listening)) { for (handler = ISC_LIST_HEAD(serversocket->h2.handlers); handler != NULL; handler = ISC_LIST_NEXT(handler, link)) @@ -1267,15 +1075,15 @@ find_server_request_handler(const char *request_path, } } } - RWUNLOCK(&serversocket->h2.handlers_lock, isc_rwlocktype_read); + RWUNLOCK(&serversocket->h2.lock, isc_rwlocktype_read); return (handler); } -static isc_http2_error_responses_t +static isc_http_error_responses_t server_handle_path_header(isc_nmsocket_t *socket, const uint8_t *value, const size_t valuelen) { - isc_nm_http2_server_handler_t *handler = NULL; + isc_nm_httphandler_t *handler = NULL; const uint8_t *qstr = NULL; size_t vlen = valuelen; @@ -1292,8 +1100,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); if (handler != NULL) { - socket->h2.handler_cb = handler->cb; - socket->h2.handler_cbarg = handler->cbarg; + socket->h2.cb = handler->cb; + socket->h2.cbarg = handler->cbarg; socket->extrahandlesize = handler->extrahandlesize; } else { isc_mem_free(socket->mgr->mctx, socket->h2.request_path); @@ -1333,7 +1141,7 @@ server_handle_path_header(isc_nmsocket_t *socket, const uint8_t *value, return (ISC_HTTP_ERROR_SUCCESS); } -static isc_http2_error_responses_t +static isc_http_error_responses_t server_handle_method_header(isc_nmsocket_t *socket, const uint8_t *value, const size_t valuelen) { const char get[] = "GET"; @@ -1349,7 +1157,7 @@ server_handle_method_header(isc_nmsocket_t *socket, const uint8_t *value, return (ISC_HTTP_ERROR_SUCCESS); } -static isc_http2_error_responses_t +static isc_http_error_responses_t server_handle_scheme_header(isc_nmsocket_t *socket, const uint8_t *value, const size_t valuelen) { const char http[] = "http"; @@ -1365,7 +1173,7 @@ server_handle_scheme_header(isc_nmsocket_t *socket, const uint8_t *value, return (ISC_HTTP_ERROR_SUCCESS); } -static isc_http2_error_responses_t +static isc_http_error_responses_t server_handle_content_length_header(isc_nmsocket_t *socket, const uint8_t *value, const size_t valuelen) { @@ -1384,7 +1192,7 @@ server_handle_content_length_header(isc_nmsocket_t *socket, return (ISC_HTTP_ERROR_SUCCESS); } -static isc_http2_error_responses_t +static isc_http_error_responses_t server_handle_content_type_header(isc_nmsocket_t *socket, const uint8_t *value, const size_t valuelen) { const char type_dns_message[] = "application/dns-message"; @@ -1397,7 +1205,7 @@ server_handle_content_type_header(isc_nmsocket_t *socket, const uint8_t *value, return (ISC_HTTP_ERROR_SUCCESS); } -static isc_http2_error_responses_t +static isc_http_error_responses_t server_handle_accept_header(isc_nmsocket_t *socket, const uint8_t *value, const size_t valuelen) { const char type_accept_all[] = "*/*"; @@ -1419,7 +1227,7 @@ server_on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *value, size_t valuelen, uint8_t flags, void *user_data) { isc_nmsocket_t *socket = NULL; - isc_http2_error_responses_t code = ISC_HTTP_ERROR_SUCCESS; + isc_http_error_responses_t code = ISC_HTTP_ERROR_SUCCESS; const char path[] = ":path"; const char method[] = ":method"; const char scheme[] = ":scheme"; @@ -1480,7 +1288,7 @@ static ssize_t server_read_callback(nghttp2_session *ngsession, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { - isc_nm_http2_session_t *session = (isc_nm_http2_session_t *)user_data; + isc_nm_http_session_t *session = (isc_nm_http_session_t *)user_data; isc_nmsocket_t *socket = (isc_nmsocket_t *)source->ptr; size_t buflen; @@ -1526,8 +1334,8 @@ server_send_response(nghttp2_session *ngsession, int32_t stream_id, tag, MAKE_NV2(":status", #code) \ } -static struct http2_error_responses { - const isc_http2_error_responses_t type; +static struct http_error_responses { + const isc_http_error_responses_t type; const nghttp2_nv header; } error_responses[] = { MAKE_ERROR_REPLY(ISC_HTTP_ERROR_SUCCESS, 200), @@ -1541,7 +1349,7 @@ static struct http2_error_responses { }; static int -server_send_error_response(const isc_http2_error_responses_t error, +server_send_error_response(const isc_http_error_responses_t error, nghttp2_session *ngsession, isc_nmsocket_t *socket) { int rv; @@ -1567,11 +1375,10 @@ server_send_error_response(const isc_http2_error_responses_t error, static int server_on_request_recv(nghttp2_session *ngsession, - isc_nm_http2_session_t *session, - isc_nmsocket_t *socket) { + isc_nm_http_session_t *session, isc_nmsocket_t *socket) { isc_nmhandle_t *handle = NULL; isc_sockaddr_t addr; - isc_http2_error_responses_t code = ISC_HTTP_ERROR_SUCCESS; + isc_http_error_responses_t code = ISC_HTTP_ERROR_SUCCESS; isc_region_t data; /* @@ -1579,7 +1386,7 @@ server_on_request_recv(nghttp2_session *ngsession, * Unbound uses. * (https://blog.nlnetlabs.nl/dns-over-https-in-unbound/) */ - if (!socket->h2.request_path || !socket->h2.handler_cb) { + if (!socket->h2.request_path || !socket->h2.cb) { code = ISC_HTTP_ERROR_NOT_FOUND; } else if ((socket->h2.request_type == ISC_HTTP_REQ_POST && !socket->h2.content_type_verified) || @@ -1642,8 +1449,7 @@ server_on_request_recv(nghttp2_session *ngsession, addr = isc_nmhandle_peeraddr(session->handle); handle = isc__nmhandle_get(socket, &addr, NULL); - socket->h2.handler_cb(handle, ISC_R_SUCCESS, &data, - socket->h2.handler_cbarg); + socket->h2.cb(handle, ISC_R_SUCCESS, &data, socket->h2.cbarg); isc_nmhandle_detach(&handle); return (0); @@ -1690,14 +1496,16 @@ isc__nm_http_send(isc_nmhandle_t *handle, const isc_region_t *region, void isc__nm_async_httpsend(isc__networker_t *worker, isc__netievent_t *ev0) { + isc_result_t result = ISC_R_SUCCESS; isc__netievent_httpsend_t *ievent = (isc__netievent_httpsend_t *)ev0; isc_nmsocket_t *sock = ievent->sock; isc__nm_uvreq_t *req = ievent->req; isc_nmhandle_t *handle = NULL; isc_nm_cb_t cb = NULL; void *cbarg = NULL; - isc_result_t res; - size_t content_length_str_len; + size_t len; + + UNUSED(worker); REQUIRE(VALID_NMSOCK(sock)); REQUIRE(VALID_UVREQ(req)); @@ -1712,41 +1520,41 @@ isc__nm_async_httpsend(isc__networker_t *worker, isc__netievent_t *ev0) { REQUIRE(VALID_NMSOCK(handle->httpsession->handle->sock)); REQUIRE(handle->httpsession->handle->sock->tid == isc_nm_tid()); - UNUSED(worker); - memmove(sock->h2.buf, req->uvbuf.base, req->uvbuf.len); sock->h2.bufsize = req->uvbuf.len; - content_length_str_len = - snprintf(sock->h2.response_content_length_str, - sizeof(sock->h2.response_content_length_str), "%lu", - (unsigned long)req->uvbuf.len); + len = snprintf(sock->h2.clenbuf, sizeof(sock->h2.clenbuf), "%lu", + (unsigned long)req->uvbuf.len); const nghttp2_nv hdrs[] = { MAKE_NV2(":status", "200"), MAKE_NV2("Content-Type", "application/dns-message"), - MAKE_NV("Content-Length", sock->h2.response_content_length_str, - content_length_str_len) + MAKE_NV("Content-Length", sock->h2.clenbuf, len) }; + if (server_send_response(handle->httpsession->ngsession, sock->h2.stream_id, hdrs, sizeof(hdrs) / sizeof(nghttp2_nv), sock) != 0) { - res = ISC_R_FAILURE; - } else { - res = ISC_R_SUCCESS; + result = ISC_R_FAILURE; } - http2_do_bio(handle->httpsession); /*TODO: Should we call it only - * on success? */ - cb(handle, res, cbarg); - + http_do_bio(handle->httpsession); + cb(handle, result, cbarg); isc__nm_uvreq_put(&req, sock); } +void +isc__nm_http_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { + UNUSED(handle); + UNUSED(cb); + UNUSED(cbarg); + return; +} + static int server_on_frame_recv_callback(nghttp2_session *ngsession, const nghttp2_frame *frame, void *user_data) { - isc_nm_http2_session_t *session = (isc_nm_http2_session_t *)user_data; + isc_nm_http_session_t *session = (isc_nm_http_session_t *)user_data; isc_nmsocket_t *socket = NULL; switch (frame->hd.type) { @@ -1777,7 +1585,7 @@ server_on_frame_recv_callback(nghttp2_session *ngsession, } static void -initialize_nghttp2_server_session(isc_nm_http2_session_t *session) { +initialize_nghttp2_server_session(isc_nm_http_session_t *session) { nghttp2_session_callbacks *callbacks = NULL; RUNTIME_CHECK(nghttp2_session_callbacks_new(&callbacks) == 0); @@ -1803,7 +1611,7 @@ initialize_nghttp2_server_session(isc_nm_http2_session_t *session) { } static int -server_send_connection_header(isc_nm_http2_session_t *session) { +server_send_connection_header(isc_nm_http_session_t *session) { nghttp2_settings_entry iv[1] = { { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 } }; @@ -1820,7 +1628,7 @@ server_send_connection_header(isc_nm_http2_session_t *session) { static isc_result_t httplisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { isc_nmsocket_t *httplistensock = (isc_nmsocket_t *)cbarg; - isc_nm_http2_session_t *session = NULL; + isc_nm_http_session_t *session = NULL; isc_nmsocket_t *listener = NULL, *httpserver = NULL; REQUIRE(VALID_NMHANDLE(handle)); @@ -1859,10 +1667,10 @@ httplisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { } session = isc_mem_get(httplistensock->mgr->mctx, - sizeof(isc_nm_http2_session_t)); - *session = (isc_nm_http2_session_t){ .magic = HTTP2_SESSION_MAGIC, - .ssl_ctx_created = false, - .client = false }; + sizeof(isc_nm_http_session_t)); + *session = (isc_nm_http_session_t){ .magic = HTTP2_SESSION_MAGIC, + .ssl_ctx_created = false, + .client = false }; initialize_nghttp2_server_session(session); handle->sock->h2.session = session; @@ -1873,7 +1681,7 @@ httplisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { server_send_connection_header(session); /* TODO H2 */ - http2_do_bio(session); + http_do_bio(session); return (ISC_R_SUCCESS); } @@ -1927,11 +1735,11 @@ isc_nm_listenhttp(isc_nm_t *mgr, isc_nmiface_t *iface, int backlog, SSL_CTX_set_alpn_select_cb(ctx, alpn_select_proto_cb, NULL); #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L result = isc_nm_listentls(mgr, iface, httplisten_acceptcb, sock, - sizeof(isc_nm_http2_session_t), + sizeof(isc_nm_http_session_t), backlog, quota, ctx, &sock->outer); } else { result = isc_nm_listentcp(mgr, iface, httplisten_acceptcb, sock, - sizeof(isc_nm_http2_session_t), + sizeof(isc_nm_http_session_t), backlog, quota, &sock->outer); } @@ -1953,81 +1761,62 @@ isc_nm_listenhttp(isc_nm_t *mgr, isc_nmiface_t *iface, int backlog, return (ISC_R_SUCCESS); } -isc_result_t -isc_nm_http_add_endpoint(isc_nmsocket_t *sock, const char *uri, - isc_nm_http_cb_t cb, void *cbarg, - size_t extrahandlesize) { - isc_nm_http2_server_handler_t *handler = NULL; - - REQUIRE(VALID_NMSOCK(sock)); - REQUIRE(sock->type == isc_nm_httplistener); - - if (find_server_request_handler(uri, sock) == NULL) { - handler = isc_mem_get(sock->mgr->mctx, sizeof(*handler)); - *handler = (isc_nm_http2_server_handler_t){ - .cb = cb, - .cbarg = cbarg, - .extrahandlesize = extrahandlesize, - .path = isc_mem_strdup(sock->mgr->mctx, uri) - }; - ISC_LINK_INIT(handler, link); - - RWLOCK(&sock->h2.handlers_lock, isc_rwlocktype_write); - ISC_LIST_APPEND(sock->h2.handlers, handler, link); - RWUNLOCK(&sock->h2.handlers_lock, isc_rwlocktype_write); - } - - return (ISC_R_SUCCESS); -} - /* * 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 * http * content. */ static void -doh_callback(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *data, +http_callback(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *data, void *arg) { - isc_nm_http_doh_cbarg_t *dohcbarg = arg; + isc_nm_httpcbarg_t *httpcbarg = arg; REQUIRE(VALID_NMHANDLE(handle)); if (result != ISC_R_SUCCESS) { /* Shut down the client, then ourselves */ - dohcbarg->cb(handle, result, NULL, dohcbarg->cbarg); + httpcbarg->cb(handle, result, NULL, httpcbarg->cbarg); /* XXXWPK FREE */ return; } - dohcbarg->cb(handle, result, data, dohcbarg->cbarg); + httpcbarg->cb(handle, result, data, httpcbarg->cbarg); } isc_result_t -isc_nm_http_add_doh_endpoint(isc_nmsocket_t *sock, const char *uri, - isc_nm_recv_cb_t cb, void *cbarg, - size_t extrahandlesize) { - isc_result_t result; - isc_nm_http_doh_cbarg_t *dohcbarg = NULL; +isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb, + void *cbarg, size_t extrahandlesize) { + isc_nm_httphandler_t *handler = NULL; + isc_nm_httpcbarg_t *httpcbarg = NULL; + bool newhandler = false; REQUIRE(VALID_NMSOCK(sock)); REQUIRE(sock->type == isc_nm_httplistener); - dohcbarg = isc_mem_get(sock->mgr->mctx, - sizeof(isc_nm_http_doh_cbarg_t)); - *dohcbarg = (isc_nm_http_doh_cbarg_t){ .cb = cb, .cbarg = cbarg }; - ISC_LINK_INIT(dohcbarg, link); + httpcbarg = isc_mem_get(sock->mgr->mctx, sizeof(isc_nm_httpcbarg_t)); + *httpcbarg = (isc_nm_httpcbarg_t){ .cb = cb, .cbarg = cbarg }; + ISC_LINK_INIT(httpcbarg, link); - result = isc_nm_http_add_endpoint(sock, uri, doh_callback, dohcbarg, - extrahandlesize); - if (result != ISC_R_SUCCESS) { - isc_mem_put(sock->mgr->mctx, dohcbarg, - sizeof(isc_nm_http_doh_cbarg_t)); + if (find_server_request_handler(uri, sock) == NULL) { + handler = isc_mem_get(sock->mgr->mctx, sizeof(*handler)); + *handler = (isc_nm_httphandler_t){ + .cb = http_callback, + .cbarg = httpcbarg, + .extrahandlesize = extrahandlesize, + .path = isc_mem_strdup(sock->mgr->mctx, uri) + }; + ISC_LINK_INIT(handler, link); + + newhandler = true; } - RWLOCK(&sock->h2.handlers_lock, isc_rwlocktype_write); - ISC_LIST_APPEND(sock->h2.handlers_cbargs, dohcbarg, link); - RWUNLOCK(&sock->h2.handlers_lock, isc_rwlocktype_write); + RWLOCK(&sock->h2.lock, isc_rwlocktype_write); + if (newhandler) { + ISC_LIST_APPEND(sock->h2.handlers, handler, link); + } + ISC_LIST_APPEND(sock->h2.handler_cbargs, httpcbarg, link); + RWUNLOCK(&sock->h2.lock, isc_rwlocktype_write); - return (result); + return (ISC_R_SUCCESS); } void @@ -2050,14 +1839,14 @@ isc__nm_http_stoplistening(isc_nmsocket_t *sock) { void isc__nm_http_clear_handlers(isc_nmsocket_t *sock) { - isc_nm_http2_server_handler_t *handler = NULL; - isc_nm_http_doh_cbarg_t *dohcbarg = NULL; + isc_nm_httphandler_t *handler = NULL; + isc_nm_httpcbarg_t *httpcbarg = NULL; /* delete all handlers */ - RWLOCK(&sock->h2.handlers_lock, isc_rwlocktype_write); + RWLOCK(&sock->h2.lock, isc_rwlocktype_write); handler = ISC_LIST_HEAD(sock->h2.handlers); while (handler != NULL) { - isc_nm_http2_server_handler_t *next; + isc_nm_httphandler_t *next; next = ISC_LIST_NEXT(handler, link); ISC_LIST_DEQUEUE(sock->h2.handlers, handler, link); @@ -2066,30 +1855,30 @@ isc__nm_http_clear_handlers(isc_nmsocket_t *sock) { handler = next; } - dohcbarg = ISC_LIST_HEAD(sock->h2.handlers_cbargs); - while (dohcbarg != NULL) { - isc_nm_http_doh_cbarg_t *next; + httpcbarg = ISC_LIST_HEAD(sock->h2.handler_cbargs); + while (httpcbarg != NULL) { + isc_nm_httpcbarg_t *next; - next = ISC_LIST_NEXT(dohcbarg, link); - ISC_LIST_DEQUEUE(sock->h2.handlers_cbargs, dohcbarg, link); - isc_mem_put(sock->mgr->mctx, dohcbarg, - sizeof(isc_nm_http_doh_cbarg_t)); - dohcbarg = next; + 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.handlers_lock, isc_rwlocktype_write); + RWUNLOCK(&sock->h2.lock, isc_rwlocktype_write); } void isc__nm_http_clear_session(isc_nmsocket_t *sock) { - if (sock->type != isc_nm_httpstream && sock->h2.session != NULL) { - isc_nm_http2_session_t *session = sock->h2.session; + if (sock->type != isc_nm_httpsocket && sock->h2.session != NULL) { + isc_nm_http_session_t *session = sock->h2.session; INSIST(ISC_LIST_EMPTY(session->sstreams)); session->magic = 0; if (session->ssl_ctx_created) { SSL_CTX_free(session->ssl_ctx); } isc_mem_putanddetach(&sock->h2.session->mctx, session, - sizeof(isc_nm_http2_session_t)); + sizeof(isc_nm_http_session_t)); sock->h2.session = NULL; } } @@ -2117,7 +1906,7 @@ isc__nm_async_httpstop(isc__networker_t *worker, isc__netievent_t *ev0) { static void http_close_direct(isc_nmsocket_t *sock) { bool sessions_empty; - isc_nm_http2_session_t *session; + isc_nm_http_session_t *session; REQUIRE(VALID_NMSOCK(sock)); REQUIRE(VALID_HTTP2_SESSION(sock->h2.session)); @@ -2127,14 +1916,11 @@ http_close_direct(isc_nmsocket_t *sock) { if (ISC_LINK_LINKED(&sock->h2, link)) { ISC_LIST_UNLINK(session->sstreams, &sock->h2, link); -#ifdef NETMGR_TRACE - session->sstreams_count--; -#endif /* NETMGR_TRACE */ } sessions_empty = ISC_LIST_EMPTY(session->sstreams); if (!sessions_empty) { - http2_do_bio(session); + http_do_bio(session); } else if (session->reading) { session->reading = false; if (session->handle != NULL) { @@ -2154,7 +1940,7 @@ http_close_direct(isc_nmsocket_t *sock) { void isc__nm_http_close(isc_nmsocket_t *sock) { REQUIRE(VALID_NMSOCK(sock)); - REQUIRE(sock->type == isc_nm_httpstream); + REQUIRE(sock->type == isc_nm_httpsocket); REQUIRE(!isc__nmsocket_active(sock)); if (!atomic_compare_exchange_strong(&sock->closing, &(bool){ false }, @@ -2184,40 +1970,40 @@ isc__nm_async_httpclose(isc__networker_t *worker, isc__netievent_t *ev0) { static void failed_httpstream_read_cb(isc_nmsocket_t *sock, isc_result_t result, - isc_nm_http2_session_t *session) { + isc_nm_http_session_t *session) { isc_nmhandle_t *handle = NULL; isc_sockaddr_t addr; REQUIRE(VALID_NMSOCK(sock)); - INSIST(sock->type == isc_nm_httpstream); + INSIST(sock->type == isc_nm_httpsocket); if (!sock->h2.request_path) { return; } - INSIST(sock->h2.handler_cbarg != NULL); + INSIST(sock->h2.cbarg != NULL); (void)nghttp2_submit_rst_stream( session->ngsession, NGHTTP2_FLAG_END_STREAM, sock->h2.stream_id, NGHTTP2_REFUSED_STREAM); addr = isc_nmhandle_peeraddr(session->handle); handle = isc__nmhandle_get(sock, &addr, NULL); - sock->h2.handler_cb(handle, result, - &(isc_region_t){ sock->h2.buf, sock->h2.bufsize }, - sock->h2.handler_cbarg); + sock->h2.cb(handle, result, + &(isc_region_t){ sock->h2.buf, sock->h2.bufsize }, + sock->h2.cbarg); isc_nmhandle_detach(&handle); } static void -failed_read_cb(isc_result_t result, isc_nm_http2_session_t *session) { +failed_read_cb(isc_result_t result, isc_nm_http_session_t *session) { REQUIRE(VALID_HTTP2_SESSION(session)); if (session->client) { - http2_client_stream_t *cstream = NULL; + http_client_stream_t *cstream = NULL; cstream = ISC_LIST_HEAD(session->cstreams); while (cstream != NULL) { - http2_client_stream_t *next = ISC_LIST_NEXT(cstream, - link); + http_client_stream_t *next = ISC_LIST_NEXT(cstream, + link); ISC_LIST_DEQUEUE(session->cstreams, cstream, link); cstream->read_cb(session->handle, result, @@ -2225,7 +2011,7 @@ failed_read_cb(isc_result_t result, isc_nm_http2_session_t *session) { cstream->rbufsize }, cstream->read_cbarg); - put_http2_client_stream(session->mctx, cstream); + put_http_client_stream(session->mctx, cstream); cstream = next; } } else { @@ -2250,7 +2036,7 @@ failed_read_cb(isc_result_t result, isc_nm_http2_session_t *session) { h2data = next; } } - finish_http2_session(session); + finish_http_session(session); } static const bool base64url_validation_table[256] = { diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 105ea4d0bb..b35d3fdca2 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -156,7 +156,7 @@ isc__nm_dump_active(isc_nm_t *nm); #define isc__nmsocket_prep_destroy(sock) isc___nmsocket_prep_destroy(sock) #endif -typedef struct isc_nm_http2_session isc_nm_http2_session_t; +typedef struct isc_nm_http_session isc_nm_http_session_t; /* * Single network event loop worker. @@ -210,7 +210,7 @@ struct isc_nmhandle { isc_nmsocket_t *sock; size_t ah_pos; /* Position in the socket's 'active handles' array */ - isc_nm_http2_session_t *httpsession; + isc_nm_http_session_t *httpsession; isc_sockaddr_t peer; isc_sockaddr_t local; @@ -302,20 +302,18 @@ typedef enum isc__netievent_type { typedef union { isc_nm_recv_cb_t recv; - isc_nm_http_cb_t http; isc_nm_cb_t send; isc_nm_cb_t connect; isc_nm_accept_cb_t accept; } isc__nm_cb_t; -typedef struct isc_nm_http2_server_handler isc_nm_http2_server_handler_t; - -struct isc_nm_http2_server_handler { +typedef struct isc_nm_httphandler isc_nm_httphandler_t; +struct isc_nm_httphandler { char *path; - isc_nm_http_cb_t cb; + isc_nm_recv_cb_t cb; void *cbarg; size_t extrahandlesize; - LINK(isc_nm_http2_server_handler_t) link; + LINK(isc_nm_httphandler_t) link; }; /* @@ -674,7 +672,7 @@ typedef enum isc_nmsocket_type { isc_nm_tlsdnslistener, isc_nm_tlsdnssocket, isc_nm_httplistener, - isc_nm_httpstream + isc_nm_httpsocket } isc_nmsocket_type; /*% @@ -710,19 +708,19 @@ typedef enum isc_doh_request_type { ISC_HTTP_REQ_GET, ISC_HTTP_REQ_POST, ISC_HTTP_REQ_UNSUPPORTED -} isc_http2_request_type_t; +} isc_http_request_type_t; -typedef enum isc_http2_scheme_type { +typedef enum isc_http_scheme_type { ISC_HTTP_SCHEME_HTTP, ISC_HTTP_SCHEME_HTTP_SECURE, ISC_HTTP_SCHEME_UNSUPPORTED -} isc_http2_scheme_type_t; +} isc_http_scheme_type_t; -typedef struct isc_nm_http_doh_cbarg { +typedef struct isc_nm_httpcbarg { isc_nm_recv_cb_t cb; void *cbarg; - LINK(struct isc_nm_http_doh_cbarg) link; -} isc_nm_http_doh_cbarg_t; + LINK(struct isc_nm_httpcbarg) link; +} isc_nm_httpcbarg_t; typedef struct isc_nmsocket_h2 { isc_nmsocket_t *psock; /* owner of the structure */ @@ -730,32 +728,33 @@ typedef struct isc_nmsocket_h2 { char *query_data; size_t query_data_len; bool query_too_large; - isc_nm_http2_server_handler_t *handler; + isc_nm_httphandler_t *handler; uint8_t *buf; size_t bufsize; size_t bufpos; int32_t stream_id; - isc_nm_http2_session_t *session; + isc_nm_http_session_t *session; isc_nmsocket_t *httpserver; - isc_http2_request_type_t request_type; - isc_http2_scheme_type_t request_scheme; + isc_http_request_type_t request_type; + isc_http_scheme_type_t request_scheme; + size_t content_length; + char clenbuf[128]; + bool content_type_verified; bool accept_type_verified; - isc_nm_http_cb_t handler_cb; - void *handler_cbarg; + isc_nm_recv_cb_t cb; + void *cbarg; LINK(struct isc_nmsocket_h2) link; - ISC_LIST(isc_nm_http2_server_handler_t) handlers; - ISC_LIST(isc_nm_http_doh_cbarg_t) handlers_cbargs; - isc_rwlock_t handlers_lock; - - char response_content_length_str[128]; + ISC_LIST(isc_nm_httphandler_t) handlers; + ISC_LIST(isc_nm_httpcbarg_t) handler_cbargs; + isc_rwlock_t lock; struct isc_nmsocket_h2_connect_data { char *uri; @@ -1531,6 +1530,9 @@ void isc__nm_http_send(isc_nmhandle_t *handle, const isc_region_t *region, isc_nm_cb_t cb, void *cbarg); +void +isc__nm_http_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg); + void isc__nm_http_close(isc_nmsocket_t *sock); diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index fb8b1fa701..aba03b3079 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -1011,7 +1011,7 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) { if (sock->type == isc_nm_httplistener) { isc__nm_http_clear_handlers(sock); - isc_rwlock_destroy(&sock->h2.handlers_lock); + isc_rwlock_destroy(&sock->h2.lock); } if (sock->h2.request_path != NULL) { @@ -1149,7 +1149,7 @@ isc___nmsocket_prep_destroy(isc_nmsocket_t *sock FLARG) { case isc_nm_tlsdnssocket: isc__nm_tlsdns_close(sock); return; - case isc_nm_httpstream: + case isc_nm_httpsocket: isc__nm_http_close(sock); return; default: @@ -1259,7 +1259,7 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type, case isc_nm_tcpdnslistener: case isc_nm_tlsdnssocket: case isc_nm_tlsdnslistener: - case isc_nm_httpstream: + case isc_nm_httpsocket: case isc_nm_httplistener: if (family == AF_INET) { sock->statsindex = tcp4statsindex; @@ -1290,28 +1290,17 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type, atomic_store(&sock->active_child_connections, 0); + sock->h2 = (isc_nmsocket_h2_t){ + .request_type = ISC_HTTP_REQ_UNSUPPORTED, + .request_scheme = ISC_HTTP_SCHEME_UNSUPPORTED, + }; + if (type == isc_nm_httplistener) { ISC_LIST_INIT(sock->h2.handlers); - ISC_LIST_INIT(sock->h2.handlers_cbargs); - isc_rwlock_init(&sock->h2.handlers_lock, 0, 1); + ISC_LIST_INIT(sock->h2.handler_cbargs); + isc_rwlock_init(&sock->h2.lock, 0, 1); } - sock->h2.session = NULL; - sock->h2.httpserver = NULL; - sock->h2.query_data = NULL; - sock->h2.query_data_len = 0; - sock->h2.query_too_large = false; - sock->h2.request_path = NULL; - sock->h2.request_type = ISC_HTTP_REQ_UNSUPPORTED; - sock->h2.request_scheme = ISC_HTTP_SCHEME_UNSUPPORTED; - sock->h2.content_length = 0; - sock->h2.content_type_verified = false; - sock->h2.accept_type_verified = false; - sock->h2.handler_cb = NULL; - sock->h2.handler_cbarg = NULL; - sock->h2.connect.uri = NULL; - sock->h2.buf = NULL; - sock->magic = NMSOCK_MAGIC; } @@ -1453,7 +1442,7 @@ isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer, sock->statichandle = handle; } - if (sock->type == isc_nm_httpstream) { + if (sock->type == isc_nm_httpsocket) { handle->httpsession = sock->h2.session; } @@ -1762,7 +1751,7 @@ isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb, case isc_nm_tlsdnssocket: isc__nm_tlsdns_send(handle, region, cb, cbarg); break; - case isc_nm_httpstream: + case isc_nm_httpsocket: isc__nm_http_send(handle, region, cb, cbarg); break; default: @@ -1798,6 +1787,9 @@ isc_nm_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { case isc_nm_tlsdnssocket: isc__nm_tlsdns_read(handle, cb, cbarg); break; + case isc_nm_httpsocket: + isc__nm_http_read(handle, cb, cbarg); + break; default: INSIST(0); ISC_UNREACHABLE(); @@ -2445,8 +2437,8 @@ nmsocket_type_totext(isc_nmsocket_type type) { return ("isc_nm_tlsdnssocket"); case isc_nm_httplistener: return ("isc_nm_httplistener"); - case isc_nm_httpstream: - return ("isc_nm_httpstream"); + case isc_nm_httpsocket: + return ("isc_nm_httpsocket"); default: INSIST(0); ISC_UNREACHABLE(); diff --git a/lib/isc/tests/doh_test.c b/lib/isc/tests/doh_test.c index 879e42a431..ededf37936 100644 --- a/lib/isc/tests/doh_test.c +++ b/lib/isc/tests/doh_test.c @@ -101,6 +101,63 @@ static SSL_CTX *server_ssl_ctx = NULL; #define X(v) #endif +typedef struct csdata { + isc_nm_recv_cb_t reply_cb; + void *cb_arg; + isc_region_t region; +} csdata_t; + +static void +connect_send_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + csdata_t data; + + REQUIRE(VALID_NMHANDLE(handle)); + + memmove(&data, arg, sizeof(data)); + isc_mem_put(handle->sock->mgr->mctx, arg, sizeof(data)); + if (result != ISC_R_SUCCESS) { + goto error; + } + + result = isc_nm_httprequest(handle, &data.region, data.reply_cb, + data.cb_arg); + if (result != ISC_R_SUCCESS) { + goto error; + } + + isc_mem_put(handle->sock->mgr->mctx, data.region.base, + data.region.length); + return; +error: + data.reply_cb(handle, result, NULL, data.cb_arg); + isc_mem_put(handle->sock->mgr->mctx, data.region.base, + data.region.length); +} + +static isc_result_t +connect_send_request(isc_nm_t *mgr, const char *uri, bool post, + isc_region_t *region, isc_nm_recv_cb_t cb, void *cbarg, + bool tls, unsigned int timeout) { + isc_result_t result; + isc_region_t copy; + csdata_t *data = NULL; + SSL_CTX *ctx = NULL; + + copy = (isc_region_t){ .base = isc_mem_get(mgr->mctx, region->length), + .length = region->length }; + memmove(copy.base, region->base, region->length); + data = isc_mem_get(mgr->mctx, sizeof(*data)); + *data = (csdata_t){ .reply_cb = cb, .cb_arg = cbarg, .region = copy }; + if (tls) { + isc_tlsctx_createclient(&ctx); + } + + result = isc_nm_httpconnect( + mgr, NULL, (isc_nmiface_t *)&tcp_listen_addr, uri, post, + connect_send_cb, data, ctx, timeout, 0); + return (result); +} + static int setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) { isc_result_t result; @@ -261,7 +318,7 @@ nm_teardown(void **state) { } isc_mem_put(test_mctx, nm, MAX_NM * sizeof(nm[0])); - if (server_ssl_ctx) { + if (server_ssl_ctx != NULL) { isc_tlsctx_free(&server_ssl_ctx); } @@ -276,6 +333,7 @@ sockaddr_to_url(isc_sockaddr_t *sa, const bool https, char *outbuf, uint16_t port; char saddr[INET6_ADDRSTRLEN] = { 0 }; int family; + if (sa == NULL || outbuf == NULL || outbuf_len == 0) { return; } @@ -382,10 +440,6 @@ mock_doh_uv_tcp_bind(void **state) { isc_nm_t *listen_nm = nm[0]; isc_result_t result = ISC_R_SUCCESS; isc_nmsocket_t *listen_sock = NULL; - isc_sockaddr_t tcp_connect_addr; - - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); WILL_RETURN(uv_tcp_bind, UV_EADDRINUSE); @@ -404,17 +458,13 @@ doh_noop(void **state) { isc_nm_t *connect_nm = nm[1]; isc_result_t result = ISC_R_SUCCESS; isc_nmsocket_t *listen_sock = NULL; - isc_sockaddr_t tcp_connect_addr; char req_url[256]; - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); - result = isc_nm_listenhttp(listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL, NULL, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH, - noop_read_cb, NULL, 0); + result = isc_nm_http_endpoint(listen_sock, DOH_PATH, noop_read_cb, NULL, + 0); isc_nm_stoplistening(listen_sock); isc_nmsocket_close(&listen_sock); @@ -422,11 +472,11 @@ doh_noop(void **state) { sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), DOH_PATH); - (void)isc_nm_http_connect_send_request( + (void)connect_send_request( connect_nm, req_url, atomic_load(&POST), &(isc_region_t){ .base = (uint8_t *)send_msg.base, .length = send_msg.len }, - noop_read_cb, NULL, NULL, 30000); + noop_read_cb, NULL, atomic_load(&use_TLS), 30000); isc_nm_closedown(connect_nm); @@ -455,27 +505,23 @@ doh_noresponse(void **state) { isc_nm_t *connect_nm = nm[1]; isc_result_t result = ISC_R_SUCCESS; isc_nmsocket_t *listen_sock = NULL; - isc_sockaddr_t tcp_connect_addr; char req_url[256]; - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); - result = isc_nm_listenhttp(listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL, NULL, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH, - noop_read_cb, NULL, 0); + result = isc_nm_http_endpoint(listen_sock, DOH_PATH, noop_read_cb, NULL, + 0); assert_int_equal(result, ISC_R_SUCCESS); sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), DOH_PATH); - (void)isc_nm_http_connect_send_request( + (void)connect_send_request( connect_nm, req_url, atomic_load(&POST), &(isc_region_t){ .base = (uint8_t *)send_msg.base, .length = send_msg.len }, - noop_read_cb, NULL, NULL, 30000); + noop_read_cb, NULL, atomic_load(&use_TLS), 30000); isc_nm_stoplistening(listen_sock); isc_nmsocket_close(&listen_sock); @@ -535,20 +581,18 @@ doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult, static isc_threadresult_t doh_connect_thread(isc_threadarg_t arg) { isc_nm_t *connect_nm = (isc_nm_t *)arg; - isc_sockaddr_t tcp_connect_addr; char req_url[256]; - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, sizeof(req_url), DOH_PATH); while (atomic_load(&nsends) > 0) { - (void)isc_nm_http_connect_send_request( + (void)connect_send_request( connect_nm, req_url, atomic_load(&POST), &(isc_region_t){ .base = (uint8_t *)send_msg.base, .length = send_msg.len }, - doh_receive_send_reply_cb, NULL, NULL, 5000); + doh_receive_send_reply_cb, NULL, atomic_load(&use_TLS), + 30000); } return ((isc_threadresult_t)0); @@ -561,33 +605,26 @@ doh_recv_one(void **state) { isc_nm_t *connect_nm = nm[1]; isc_result_t result = ISC_R_SUCCESS; isc_nmsocket_t *listen_sock = NULL; - isc_sockaddr_t tcp_connect_addr; char req_url[256]; - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); - atomic_store(&nsends, 1); - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); - result = isc_nm_listenhttp( listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL, atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH, - doh_receive_request_cb, NULL, 0); + result = isc_nm_http_endpoint(listen_sock, DOH_PATH, + doh_receive_request_cb, NULL, 0); assert_int_equal(result, ISC_R_SUCCESS); sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, sizeof(req_url), DOH_PATH); - result = isc_nm_http_connect_send_request( + result = connect_send_request( connect_nm, req_url, atomic_load(&POST), &(isc_region_t){ .base = (uint8_t *)send_msg.base, .length = send_msg.len }, - doh_receive_reply_cb, NULL, NULL, 5000); + doh_receive_reply_cb, NULL, atomic_load(&use_TLS), 30000); assert_int_equal(result, ISC_R_SUCCESS); @@ -688,31 +725,31 @@ doh_recv_two(void **state) { isc_nm_t *connect_nm = nm[1]; isc_result_t result = ISC_R_SUCCESS; isc_nmsocket_t *listen_sock = NULL; - isc_sockaddr_t tcp_connect_addr; char req_url[256]; - - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); + SSL_CTX *ctx = NULL; atomic_store(&nsends, 2); - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); - result = isc_nm_listenhttp( listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL, atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH, - doh_receive_request_cb, NULL, 0); + result = isc_nm_http_endpoint(listen_sock, DOH_PATH, + doh_receive_request_cb, NULL, 0); assert_int_equal(result, ISC_R_SUCCESS); sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, sizeof(req_url), DOH_PATH); + + if (atomic_load(&use_TLS)) { + isc_tlsctx_createclient(&ctx); + } + result = isc_nm_httpconnect( - connect_nm, NULL, NULL, req_url, atomic_load(&POST), - doh_connect_send_two_requests_cb, NULL, NULL, 5000, 0); + connect_nm, NULL, (isc_nmiface_t *)&tcp_listen_addr, req_url, + atomic_load(&POST), doh_connect_send_two_requests_cb, NULL, ctx, + 5000, 0); assert_int_equal(result, ISC_R_SUCCESS); @@ -783,21 +820,14 @@ doh_recv_send(void **state) { isc_nmsocket_t *listen_sock = NULL; size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); isc_thread_t threads[32] = { 0 }; - isc_sockaddr_t tcp_connect_addr; - - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); - - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); result = isc_nm_listenhttp( listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL, atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH, - doh_receive_request_cb, NULL, 0); + result = isc_nm_http_endpoint(listen_sock, DOH_PATH, + doh_receive_request_cb, NULL, 0); assert_int_equal(result, ISC_R_SUCCESS); for (size_t i = 0; i < nthreads; i++) { @@ -859,21 +889,14 @@ doh_recv_half_send(void **state) { isc_nmsocket_t *listen_sock = NULL; size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); isc_thread_t threads[32] = { 0 }; - isc_sockaddr_t tcp_connect_addr; - - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); - - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); result = isc_nm_listenhttp( listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL, atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH, - doh_receive_request_cb, NULL, 0); + result = isc_nm_http_endpoint(listen_sock, DOH_PATH, + doh_receive_request_cb, NULL, 0); assert_int_equal(result, ISC_R_SUCCESS); for (size_t i = 0; i < nthreads; i++) { @@ -940,21 +963,14 @@ doh_half_recv_send(void **state) { isc_nmsocket_t *listen_sock = NULL; size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); isc_thread_t threads[32] = { 0 }; - isc_sockaddr_t tcp_connect_addr; - - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); - - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); result = isc_nm_listenhttp( listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL, atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH, - doh_receive_request_cb, NULL, 0); + result = isc_nm_http_endpoint(listen_sock, DOH_PATH, + doh_receive_request_cb, NULL, 0); assert_int_equal(result, ISC_R_SUCCESS); for (size_t i = 0; i < nthreads; i++) { @@ -1021,21 +1037,14 @@ doh_half_recv_half_send(void **state) { isc_nmsocket_t *listen_sock = NULL; size_t nthreads = ISC_MAX(ISC_MIN(workers, 32), 1); isc_thread_t threads[32] = { 0 }; - isc_sockaddr_t tcp_connect_addr; - - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); - - tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; - isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); result = isc_nm_listenhttp( listen_nm, (isc_nmiface_t *)&tcp_listen_addr, 0, NULL, atomic_load(&use_TLS) ? server_ssl_ctx : NULL, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - result = isc_nm_http_add_doh_endpoint(listen_sock, DOH_PATH, - doh_receive_request_cb, NULL, 0); + result = isc_nm_http_endpoint(listen_sock, DOH_PATH, + doh_receive_request_cb, NULL, 0); assert_int_equal(result, ISC_R_SUCCESS); for (size_t i = 0; i < nthreads; i++) { @@ -1625,12 +1634,12 @@ doh_cloudflare(void **state) { isc_nm_t **nm = (isc_nm_t **)*state; isc_result_t result = ISC_R_SUCCESS; - result = isc_nm_http_connect_send_request( + result = connect_send_request( nm[0], "https://cloudflare-dns.com/dns-query", atomic_load(&POST), &(isc_region_t){ .base = (uint8_t *)wikipedia_org_A, .length = sizeof(wikipedia_org_A) }, - doh_print_reply_cb, NULL, NULL, 5000); + doh_print_reply_cb, NULL, atomic_load(&use_TLS), 30000); assert_int_equal(result, ISC_R_SUCCESS); diff --git a/lib/isc/tls.c b/lib/isc/tls.c index ea5de5dbf9..82a5bedd31 100644 --- a/lib/isc/tls.c +++ b/lib/isc/tls.c @@ -9,6 +9,8 @@ * information regarding copyright ownership. */ +#include + #include #include @@ -106,6 +108,23 @@ isc_tlsctx_free(isc_tlsctx_t **ctxp) { SSL_CTX_free(ctx); } +#ifndef OPENSSL_NO_NEXTPROTONEG +/* + * NPN TLS extension client callback. + */ +static int +select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg) { + UNUSED(ssl); + UNUSED(arg); + + if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) { + return (SSL_TLSEXT_ERR_NOACK); + } + return (SSL_TLSEXT_ERR_OK); +} +#endif /* !OPENSSL_NO_NEXTPROTONEG */ + isc_result_t isc_tlsctx_createclient(isc_tlsctx_t **ctxp) { unsigned long err; @@ -133,6 +152,15 @@ isc_tlsctx_createclient(isc_tlsctx_t **ctxp) { SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif +#ifndef OPENSSL_NO_NEXTPROTONEG + SSL_CTX_set_next_proto_select_cb(ctx, select_next_proto_cb, NULL); +#endif /* !OPENSSL_NO_NEXTPROTONEG */ + +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + SSL_CTX_set_alpn_protos(ctx, (const unsigned char *)NGHTTP2_PROTO_ALPN, + NGHTTP2_PROTO_ALPN_LEN); +#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */ + *ctxp = ctx; return (ISC_R_SUCCESS); diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in index e460d5757e..d88ca2a306 100644 --- a/lib/isc/win32/libisc.def.in +++ b/lib/isc/win32/libisc.def.in @@ -448,9 +448,7 @@ isc_nm_cancelread isc_nm_closedown isc_nm_destroy isc_nm_detach -isc_nm_http_add_doh_endpoint -isc_nm_http_add_endpoint -isc_nm_http_connect_send_request +isc_nm_http_endpoint isc_nm_httpconnect isc_nm_httprequest isc_nm_listenhttp diff --git a/lib/ns/interfacemgr.c b/lib/ns/interfacemgr.c index a1443410a7..8ae657abce 100644 --- a/lib/ns/interfacemgr.c +++ b/lib/ns/interfacemgr.c @@ -556,9 +556,9 @@ ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps, if (result == ISC_R_SUCCESS) { for (i = 0; i < neps; i++) { - result = isc_nm_http_add_doh_endpoint( - sock, eps[i], ns__client_request, ifp, - sizeof(ns_client_t)); + result = isc_nm_http_endpoint(sock, eps[i], + ns__client_request, ifp, + sizeof(ns_client_t)); } }