From: Ondřej Surý Date: Tue, 17 Feb 2026 10:05:33 +0000 (+0100) Subject: Implement seamless TCP connection reuse in dns_dispatch X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d5ee86b799893096b7e95e6426459fae3cf7ef00;p=thirdparty%2Fbind9.git Implement seamless TCP connection reuse in dns_dispatch Previously, the user of dns_dispatch API had to first call dns_dispatch_gettcp() and if that failed create a new TCP dispatch with dns_dispatch_createtcp(). This has been changed and the TCP connection reuse happens transparently inside dns_dispatch_createtcp(). There are separate buckets for dns_resolver, dns_request and dns_xfrin units, so these don't get mixed together. --- diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 771c29b8887..a6f7cc4e992 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -125,6 +125,7 @@ struct dns_dispatch { dns_dispatchopt_t options; dns_dispatchstate_t state; + dns_dispatchtype_t disptype; bool reading; @@ -1131,6 +1132,7 @@ struct dispatch_key { const isc_sockaddr_t *local; const isc_sockaddr_t *peer; const dns_transport_t *transport; + const dns_dispatchtype_t disptype; }; static uint32_t @@ -1154,70 +1156,10 @@ dispatch_match(struct cds_lfht_node *node, const void *key0) { isc_sockaddr_equal(&disp->local, key->local)); } -isc_result_t -dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, - const isc_sockaddr_t *destaddr, - dns_transport_t *transport, dns_dispatchopt_t options, - dns_dispatch_t **dispp) { - dns_dispatch_t *disp = NULL; - isc_tid_t tid = isc_tid(); - - REQUIRE(VALID_DISPATCHMGR(mgr)); - REQUIRE(destaddr != NULL); - - dispatch_allocate(mgr, isc_socktype_tcp, tid, &disp); - - disp->options = options; - disp->peer = *destaddr; - if (transport != NULL) { - dns_transport_attach(transport, &disp->transport); - } - - if (localaddr != NULL) { - disp->local = *localaddr; - } else { - int pf; - pf = isc_sockaddr_pf(destaddr); - isc_sockaddr_anyofpf(&disp->local, pf); - isc_sockaddr_setport(&disp->local, 0); - } - - /* - * Append it to the dispatcher list. - */ - struct dispatch_key key = { - .local = &disp->local, - .peer = &disp->peer, - .transport = transport, - }; - - if ((disp->options & DNS_DISPATCHOPT_UNSHARED) == 0) { - rcu_read_lock(); - cds_lfht_add(mgr->tcps[tid], dispatch_hash(&key), - &disp->ht_node); - rcu_read_unlock(); - } - - if (isc_log_wouldlog(90)) { - char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - - isc_sockaddr_format(&disp->local, addrbuf, - ISC_SOCKADDR_FORMATSIZE); - - mgr_log(mgr, ISC_LOG_DEBUG(90), - "dns_dispatch_createtcp: created TCP dispatch %p for " - "%s", - disp, addrbuf); - } - *dispp = disp; - - return ISC_R_SUCCESS; -} - -isc_result_t -dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, - const isc_sockaddr_t *localaddr, dns_transport_t *transport, - dns_dispatch_t **dispp) { +static isc_result_t +dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, + const isc_sockaddr_t *destaddr, dns_transport_t *transport, + dns_dispatchtype_t disptype, dns_dispatch_t **dispp) { dns_dispatch_t *disp_connected = NULL; dns_dispatch_t *disp_fallback = NULL; isc_result_t result = ISC_R_NOTFOUND; @@ -1231,6 +1173,7 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, .local = localaddr, .peer = destaddr, .transport = transport, + .disptype = disptype, }; rcu_read_lock(); @@ -1242,23 +1185,19 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, INSIST(disp->tid == isc_tid()); INSIST(disp->socktype == isc_socktype_tcp); + if (disp->disptype != disptype) { + continue; + } + switch (disp->state) { case DNS_DISPATCHSTATE_NONE: /* A dispatch in indeterminate state, skip it */ break; case DNS_DISPATCHSTATE_CONNECTED: - if (ISC_LIST_EMPTY(disp->active)) { - /* Ignore dispatch with no responses */ - break; - } /* We found a connected dispatch */ dns_dispatch_attach(disp, &disp_connected); break; case DNS_DISPATCHSTATE_CONNECTING: - if (ISC_LIST_EMPTY(disp->pending)) { - /* Ignore dispatch with no responses */ - break; - } /* We found "a" dispatch, store it for later */ if (disp_fallback == NULL) { dns_dispatch_attach(disp, &disp_fallback); @@ -1298,6 +1237,103 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, return result; } +static void +dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, + const isc_sockaddr_t *destaddr, dns_transport_t *transport, + dns_dispatchtype_t disptype, dns_dispatchopt_t options, + dns_dispatch_t **dispp) { + dns_dispatch_t *disp = NULL; + isc_tid_t tid = isc_tid(); + + dispatch_allocate(mgr, isc_socktype_tcp, tid, &disp); + + disp->disptype = disptype; + disp->options = options; + disp->peer = *destaddr; + if (transport != NULL) { + dns_transport_attach(transport, &disp->transport); + } + + if (localaddr != NULL) { + disp->local = *localaddr; + } else { + int pf; + pf = isc_sockaddr_pf(destaddr); + isc_sockaddr_anyofpf(&disp->local, pf); + isc_sockaddr_setport(&disp->local, 0); + } + + /* + * Append it to the dispatcher list. + */ + if ((options & DNS_DISPATCHOPT_FIXEDID) == 0) { + struct dispatch_key key = { + .local = &disp->local, + .peer = &disp->peer, + .transport = transport, + .disptype = disptype, + }; + rcu_read_lock(); + cds_lfht_add(mgr->tcps[tid], dispatch_hash(&key), + &disp->ht_node); + rcu_read_unlock(); + } + + *dispp = disp; +} + +isc_result_t +dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, + const isc_sockaddr_t *destaddr, + dns_transport_t *transport, dns_dispatchtype_t disptype, + dns_dispatchopt_t options, dns_dispatch_t **dispp) { + REQUIRE(VALID_DISPATCHMGR(mgr)); + REQUIRE(destaddr != NULL); + + isc_result_t result; + + if ((options & DNS_DISPATCHOPT_FIXEDID) == 0) { + result = dispatch_gettcp(mgr, localaddr, destaddr, transport, + disptype, dispp); + if (result == ISC_R_SUCCESS) { + if (isc_log_wouldlog(90)) { + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(&(*dispp)->local, addrbuf, + ISC_SOCKADDR_FORMATSIZE); + + mgr_log(mgr, ISC_LOG_DEBUG(90), + "dns_dispatch_createtcp: reused TCP " + "dispatch %p for " + "%s", + *dispp, addrbuf); + } + return result; + } + } + + /* + * Otherwise allocate new TCP dispatch. + */ + + dispatch_createtcp(mgr, localaddr, destaddr, transport, disptype, + options, dispp); + + if (isc_log_wouldlog(90)) { + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(&(*dispp)->local, addrbuf, + ISC_SOCKADDR_FORMATSIZE); + + mgr_log(mgr, ISC_LOG_DEBUG(90), + "dns_dispatch_createtcp: created TCP dispatch %p for " + "%s", + *dispp, addrbuf); + } + + return ISC_R_SUCCESS; +} + isc_result_t dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, dns_dispatch_t **dispp) { @@ -1372,8 +1408,8 @@ dispatch_destroy(dns_dispatch_t *disp) { disp->magic = 0; - if (disp->socktype == isc_socktype_tcp && - (disp->options & DNS_DISPATCHOPT_UNSHARED) == 0) + if ((disp->options & DNS_DISPATCHOPT_FIXEDID) == 0 && + disp->socktype == isc_socktype_tcp) { (void)cds_lfht_del(mgr->tcps[tid], &disp->ht_node); } diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index 3e54f006623..f7cc6eaf273 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -71,9 +71,14 @@ struct dns_dispatchset { typedef enum dns_dispatchopt { DNS_DISPATCHOPT_FIXEDID = 1 << 0, - DNS_DISPATCHOPT_UNSHARED = 1 << 1, /* Don't share this connection */ } dns_dispatchopt_t; +typedef enum dns_dispatchtype { + DNS_DISPATCHTYPE_RESOLVER, + DNS_DISPATCHTYPE_REQUEST, + DNS_DISPATCHTYPE_XFRIN, +} dns_dispatchtype_t; + isc_result_t dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp); /*%< @@ -181,8 +186,8 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, isc_result_t dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *localaddr, const isc_sockaddr_t *destaddr, - dns_transport_t *transport, dns_dispatchopt_t options, - dns_dispatch_t **dispp); + dns_transport_t *transport, dns_dispatchtype_t disptype, + dns_dispatchopt_t options, dns_dispatch_t **dispp); /*%< * Create a new TCP dns_dispatch. * @@ -261,35 +266,6 @@ dns_dispatch_resume(dns_dispentry_t *resp, unsigned int timeout); *\li 'resp' is valid. */ -isc_result_t -dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, - const isc_sockaddr_t *localaddr, dns_transport_t *transport, - dns_dispatch_t **dispp); -/* - * Attempt to connect to a existing TCP connection that was created with - * parameters that match destaddr, localaddr and transport. - * - * If localaddr is NULL, we ignore the dispatch's localaddr when looking - * for a match. However, if transport is NULL, then the matching dispatch - * must also have been created with a NULL transport. - * - * Requires: - *\li mgr to be valid dispatch manager. - * - *\li dstaddr to be a valid sockaddr. - * - *\li localaddr to be NULL or a valid sockaddr. - * - *\li transport is NULL or a valid transport. - * - *\li dispp to be non NULL and *dispp to be NULL - * - * Returns: - *\li ISC_R_SUCCESS -- success. - * - *\li Anything else -- failure. - */ - typedef void (*dispatch_cb_t)(isc_result_t eresult, isc_region_t *region, void *cbarg); diff --git a/lib/dns/request.c b/lib/dns/request.c index 64a4602e624..4634333aa68 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -334,27 +334,12 @@ isblackholed(dns_dispatchmgr_t *dispatchmgr, const isc_sockaddr_t *destaddr) { } static isc_result_t -tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr, - const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *destaddr, - dns_transport_t *transport, dns_dispatch_t **dispatchp) { - isc_result_t result; - - if (!newtcp) { - result = dns_dispatch_gettcp(requestmgr->dispatchmgr, destaddr, - srcaddr, transport, dispatchp); - if (result == ISC_R_SUCCESS) { - char peer[ISC_SOCKADDR_FORMATSIZE]; - - isc_sockaddr_format(destaddr, peer, sizeof(peer)); - req_log(ISC_LOG_DEBUG(1), - "attached to TCP connection to %s", peer); - return result; - } - } - - result = dns_dispatch_createtcp(requestmgr->dispatchmgr, srcaddr, - destaddr, transport, 0, dispatchp); - return result; +tcp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, + const isc_sockaddr_t *destaddr, dns_transport_t *transport, + dns_dispatch_t **dispatchp) { + return dns_dispatch_createtcp(requestmgr->dispatchmgr, srcaddr, + destaddr, transport, + DNS_DISPATCHTYPE_REQUEST, 0, dispatchp); } static isc_result_t @@ -387,14 +372,14 @@ udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, } static isc_result_t -get_dispatch(bool tcp, bool newtcp, dns_requestmgr_t *requestmgr, +get_dispatch(bool tcp, dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *destaddr, dns_transport_t *transport, dns_dispatch_t **dispatchp) { isc_result_t result; if (tcp) { - result = tcp_dispatch(newtcp, requestmgr, srcaddr, destaddr, - transport, dispatchp); + result = tcp_dispatch(requestmgr, srcaddr, destaddr, transport, + dispatchp); } else { result = udp_dispatch(requestmgr, srcaddr, destaddr, dispatchp); } @@ -416,7 +401,6 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, isc_mem_t *mctx = NULL; dns_messageid_t id; bool tcp = false; - bool newtcp = false; isc_region_t r; unsigned int dispopt = 0; @@ -465,29 +449,19 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, isc_buffer_allocate(mctx, &request->query, r.length + (tcp ? 2 : 0)); CHECK(isc_buffer_copyregion(request->query, &r)); -again: - CHECK(get_dispatch(tcp, newtcp, requestmgr, srcaddr, destaddr, - transport, &request->dispatch)); + CHECK(get_dispatch(tcp, requestmgr, srcaddr, destaddr, transport, + &request->dispatch)); if ((options & DNS_REQUESTOPT_FIXEDID) != 0) { id = (r.base[0] << 8) | r.base[1]; dispopt |= DNS_DISPATCHOPT_FIXEDID; } - result = dns_dispatch_add(request->dispatch, loop, dispopt, - request->connect_timeout, request->timeout, - destaddr, transport, tlsctx_cache, - req_connected, req_senddone, req_response, - request, &id, &request->dispentry); - if (result != ISC_R_SUCCESS) { - if ((options & DNS_REQUESTOPT_FIXEDID) != 0 && !newtcp) { - dns_dispatch_detach(&request->dispatch); - newtcp = true; - goto again; - } - - goto cleanup; - } + CHECK(dns_dispatch_add(request->dispatch, loop, dispopt, + request->connect_timeout, request->timeout, + destaddr, transport, tlsctx_cache, req_connected, + req_senddone, req_response, request, &id, + &request->dispentry)); /* Add message ID. */ isc_buffer_usedregion(request->query, &r); @@ -586,7 +560,7 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, CHECK(dns_message_settsigkey(message, request->tsigkey)); again: - CHECK(get_dispatch(tcp, false, requestmgr, srcaddr, destaddr, transport, + CHECK(get_dispatch(tcp, requestmgr, srcaddr, destaddr, transport, &request->dispatch)); CHECK(dns_dispatch_add(request->dispatch, loop, 0, diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 64135c2bf01..b2e925f55b0 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -2195,7 +2195,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, result = dns_dispatch_createtcp(fctx->dispatchmgr, &addr, &sockaddr, addrinfo->transport, - DNS_DISPATCHOPT_UNSHARED, + DNS_DISPATCHTYPE_RESOLVER, 0, &query->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup_query; diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index eca48700a92..8f974c87465 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -1362,7 +1362,7 @@ xfrin_start(dns_xfrin_t *xfr) { primaries_timeout = isc_nm_getprimariestimeout(); result = dns_dispatch_createtcp(dispmgr, &xfr->sourceaddr, &xfr->primaryaddr, xfr->transport, - DNS_DISPATCHOPT_UNSHARED, &xfr->disp); + DNS_DISPATCHTYPE_XFRIN, 0, &xfr->disp); dns_dispatchmgr_detach(&dispmgr); CHECK(result); diff --git a/tests/dns/dispatch_test.c b/tests/dns/dispatch_test.c index 0165df27427..79190e36f54 100644 --- a/tests/dns/dispatch_test.c +++ b/tests/dns/dispatch_test.c @@ -496,56 +496,23 @@ connected_shutdown(isc_result_t eresult, isc_region_t *region ISC_ATTR_UNUSED, } static void -connected_gettcp(isc_result_t eresult ISC_ATTR_UNUSED, - isc_region_t *region ISC_ATTR_UNUSED, void *arg) { - test_dispatch_t *test1 = arg; - - /* Client 2 */ - isc_result_t result; - test_dispatch_t *test2 = isc_mem_get(isc_g_mctx, sizeof(*test2)); - *test2 = (test_dispatch_t){ - .dispatchmgr = dns_dispatchmgr_ref(test1->dispatchmgr), - }; - - result = dns_dispatch_gettcp(test2->dispatchmgr, &tcp_server_addr, - &tcp_connect_addr, NULL, &test2->dispatch); - assert_int_equal(result, ISC_R_SUCCESS); - - assert_ptr_equal(test1->dispatch, test2->dispatch); - - result = dns_dispatch_add( - test2->dispatch, isc_loop_main(), 0, T_CLIENT_CONNECT, - T_CLIENT_INIT, &tcp_server_addr, NULL, NULL, connected_shutdown, - client_senddone, response_noop, test2, &test2->id, - &test2->dispentry); - assert_int_equal(result, ISC_R_SUCCESS); - - dns_dispatch_connect(test2->dispentry); - - test_dispatch_done(test1); -} - -static void -connected_newtcp(isc_result_t eresult ISC_ATTR_UNUSED, - isc_region_t *region ISC_ATTR_UNUSED, void *arg) { +connected_sharedtcp(isc_result_t eresult ISC_ATTR_UNUSED, + isc_region_t *region ISC_ATTR_UNUSED, void *arg) { test_dispatch_t *test3 = arg; - /* Client - unshared */ + /* Second client — should reuse the first client's TCP dispatch. */ isc_result_t result; test_dispatch_t *test4 = isc_mem_get(isc_g_mctx, sizeof(*test4)); *test4 = (test_dispatch_t){ .dispatchmgr = dns_dispatchmgr_ref(test3->dispatchmgr), }; - result = dns_dispatch_gettcp(test4->dispatchmgr, &tcp_server_addr, - &tcp_connect_addr, NULL, &test4->dispatch); - assert_int_equal(result, ISC_R_NOTFOUND); result = dns_dispatch_createtcp( test4->dispatchmgr, &tcp_connect_addr, &tcp_server_addr, NULL, - DNS_DISPATCHOPT_UNSHARED, &test4->dispatch); + DNS_DISPATCHTYPE_RESOLVER, 0, &test4->dispatch); assert_int_equal(result, ISC_R_SUCCESS); - assert_ptr_not_equal(test3->dispatch, test4->dispatch); + assert_ptr_equal(test3->dispatch, test4->dispatch); result = dns_dispatch_add( test4->dispatch, isc_loop_main(), 0, T_CLIENT_CONNECT, @@ -591,9 +558,9 @@ ISC_LOOP_TEST_IMPL(dispatch_timeout_tcp_connect) { result = dns_dispatchmgr_create(isc_g_mctx, &test->dispatchmgr); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_dispatch_createtcp(test->dispatchmgr, &tcp_connect_addr, - &tcp_server_addr, NULL, 0, - &test->dispatch); + result = dns_dispatch_createtcp( + test->dispatchmgr, &tcp_connect_addr, &tcp_server_addr, NULL, + DNS_DISPATCHTYPE_RESOLVER, 0, &test->dispatch); assert_int_equal(result, ISC_R_SUCCESS); result = dns_dispatch_add( @@ -636,9 +603,9 @@ ISC_LOOP_TEST_IMPL(dispatch_timeout_tcp_response) { result = dns_dispatchmgr_create(isc_g_mctx, &test->dispatchmgr); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_dispatch_createtcp(test->dispatchmgr, &tcp_connect_addr, - &tcp_server_addr, NULL, 0, - &test->dispatch); + result = dns_dispatch_createtcp( + test->dispatchmgr, &tcp_connect_addr, &tcp_server_addr, NULL, + DNS_DISPATCHTYPE_RESOLVER, 0, &test->dispatch); assert_int_equal(result, ISC_R_SUCCESS); result = dns_dispatch_add(test->dispatch, isc_loop_main(), 0, @@ -671,9 +638,9 @@ ISC_LOOP_TEST_IMPL(dispatch_tcp_response) { result = dns_dispatchmgr_create(isc_g_mctx, &test->dispatchmgr); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_dispatch_createtcp(test->dispatchmgr, &tcp_connect_addr, - &tcp_server_addr, NULL, 0, - &test->dispatch); + result = dns_dispatch_createtcp( + test->dispatchmgr, &tcp_connect_addr, &tcp_server_addr, NULL, + DNS_DISPATCHTYPE_RESOLVER, 0, &test->dispatch); assert_int_equal(result, ISC_R_SUCCESS); result = dns_dispatch_add(test->dispatch, isc_loop_main(), 0, @@ -710,9 +677,9 @@ ISC_LOOP_TEST_IMPL(dispatch_tls_response) { result = dns_dispatchmgr_create(isc_g_mctx, &test->dispatchmgr); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_dispatch_createtcp(test->dispatchmgr, &tls_connect_addr, - &tls_server_addr, tls_transport, 0, - &test->dispatch); + result = dns_dispatch_createtcp( + test->dispatchmgr, &tls_connect_addr, &tls_server_addr, + tls_transport, DNS_DISPATCHTYPE_RESOLVER, 0, &test->dispatch); assert_int_equal(result, ISC_R_SUCCESS); result = dns_dispatch_add( @@ -796,7 +763,7 @@ ISC_LOOP_TEST_IMPL(dispatch_getnext) { dns_dispatch_connect(test->dispentry); } -ISC_LOOP_TEST_IMPL(dispatch_gettcp) { +ISC_LOOP_TEST_IMPL(dispatch_sharedtcp) { isc_result_t result; test_dispatch_t *test = isc_mem_get(isc_g_mctx, sizeof(*test)); *test = (test_dispatch_t){ 0 }; @@ -810,61 +777,27 @@ ISC_LOOP_TEST_IMPL(dispatch_gettcp) { /* ensure we stop listening after the test is done */ isc_loop_teardown(isc_loop_main(), stop_listening, sock); - result = dns_dispatchmgr_create(isc_g_mctx, &test->dispatchmgr); - assert_int_equal(result, ISC_R_SUCCESS); - - /* Client */ - result = dns_dispatch_createtcp(test->dispatchmgr, &tcp_connect_addr, - &tcp_server_addr, NULL, 0, - &test->dispatch); - assert_int_equal(result, ISC_R_SUCCESS); - - result = dns_dispatch_add( - test->dispatch, isc_loop_main(), 0, T_CLIENT_CONNECT, - T_CLIENT_INIT, &tcp_server_addr, NULL, NULL, connected_gettcp, - client_senddone, response_noop, test, &test->id, - &test->dispentry); - assert_int_equal(result, ISC_R_SUCCESS); - - dns_dispatch_connect(test->dispentry); -} - -ISC_LOOP_TEST_IMPL(dispatch_newtcp) { - isc_result_t result; - test_dispatch_t *test = isc_mem_get(isc_g_mctx, sizeof(*test)); - *test = (test_dispatch_t){ 0 }; - - /* Server */ - result = isc_nm_listenstreamdns(ISC_NM_LISTEN_ONE, &tcp_server_addr, - nameserver, NULL, accept_cb, NULL, 0, - NULL, NULL, ISC_NM_PROXY_NONE, &sock); - assert_int_equal(result, ISC_R_SUCCESS); - - /* ensure we stop listening after the test is done */ - isc_loop_teardown(isc_loop_main(), stop_listening, sock); - - /* Client - unshared */ + /* First client — creates the shared TCP dispatch. */ result = dns_dispatchmgr_create(isc_g_mctx, &test->dispatchmgr); assert_int_equal(result, ISC_R_SUCCESS); result = dns_dispatch_createtcp( test->dispatchmgr, &tcp_connect_addr, &tcp_server_addr, NULL, - DNS_DISPATCHOPT_UNSHARED, &test->dispatch); + DNS_DISPATCHTYPE_RESOLVER, 0, &test->dispatch); assert_int_equal(result, ISC_R_SUCCESS); result = dns_dispatch_add( test->dispatch, isc_loop_main(), 0, T_CLIENT_CONNECT, - T_CLIENT_INIT, &tcp_server_addr, NULL, NULL, connected_newtcp, - client_senddone, response_noop, test, &test->id, - &test->dispentry); + T_CLIENT_INIT, &tcp_server_addr, NULL, NULL, + connected_sharedtcp, client_senddone, response_noop, test, + &test->id, &test->dispentry); assert_int_equal(result, ISC_R_SUCCESS); dns_dispatch_connect(test->dispentry); } ISC_TEST_LIST_START -ISC_TEST_ENTRY_CUSTOM(dispatch_gettcp, setup_test, teardown_test) -ISC_TEST_ENTRY_CUSTOM(dispatch_newtcp, setup_test, teardown_test) +ISC_TEST_ENTRY_CUSTOM(dispatch_sharedtcp, setup_test, teardown_test) ISC_TEST_ENTRY_CUSTOM(dispatch_timeout_udp_response, setup_test, teardown_test) ISC_TEST_ENTRY_CUSTOM(dispatchset_create, setup_test, teardown_test) ISC_TEST_ENTRY_CUSTOM(dispatchset_get, setup_test, teardown_test)