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=d35bc843c55ba9aa837f259388409aa5b90e50f5;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. (cherry picked from commit d5ee86b799893096b7e95e6426459fae3cf7ef00) --- diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 5ff255b655a..f7e339a4c41 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -121,6 +121,7 @@ struct dns_dispatch { dns_dispatchopt_t options; dns_dispatchstate_t state; + dns_dispatchtype_t disptype; bool reading; @@ -1138,6 +1139,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 @@ -1170,70 +1172,10 @@ dispatch_match(struct cds_lfht_node *node, const void *key0) { (key->local == NULL || isc_sockaddr_equal(&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; - uint32_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(dns_lctx, 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; @@ -1247,6 +1189,7 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, .local = localaddr, .peer = destaddr, .transport = transport, + .disptype = disptype, }; rcu_read_lock(); @@ -1258,23 +1201,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); @@ -1314,6 +1253,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; + uint32_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(dns_lctx, 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(dns_lctx, 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) { @@ -1391,8 +1427,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 6e35e9533ff..3a9845e35fc 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -74,9 +74,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, isc_loopmgr_t *loopmgr, isc_nm_t *nm, dns_dispatchmgr_t **mgrp); @@ -185,8 +190,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. * @@ -265,35 +270,6 @@ dns_dispatch_resume(dns_dispentry_t *resp, uint16_t 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 0abddd2fff1..53905a9438d 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -336,27 +336,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 @@ -389,14 +374,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); } @@ -417,7 +402,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; @@ -469,9 +453,8 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, goto cleanup; } -again: - result = get_dispatch(tcp, newtcp, requestmgr, srcaddr, destaddr, - transport, &request->dispatch); + result = get_dispatch(tcp, requestmgr, srcaddr, destaddr, transport, + &request->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup; } @@ -486,12 +469,6 @@ again: 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; } @@ -595,8 +572,8 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message, } again: - result = get_dispatch(tcp, false, requestmgr, srcaddr, destaddr, - transport, &request->dispatch); + result = get_dispatch(tcp, requestmgr, srcaddr, destaddr, transport, + &request->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup; } diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index ca0c62cbbea..6bab8057fb4 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -2098,7 +2098,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 9f98632c216..1550d9e577f 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -1346,7 +1346,7 @@ xfrin_start(dns_xfrin_t *xfr) { } else { result = dns_dispatch_createtcp( dispmgr, &xfr->sourceaddr, &xfr->primaryaddr, - xfr->transport, DNS_DISPATCHOPT_UNSHARED, &xfr->disp); + xfr->transport, 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 5257df79ab7..e8ff0ae3b85 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(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(loopmgr), 0, - T_CLIENT_CONNECT, &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(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(loopmgr), 0, T_CLIENT_CONNECT, &tcp_server_addr, NULL, @@ -592,9 +559,9 @@ ISC_LOOP_TEST_IMPL(dispatch_timeout_tcp_connect) { &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(loopmgr), 0, @@ -638,9 +605,9 @@ ISC_LOOP_TEST_IMPL(dispatch_timeout_tcp_response) { &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(loopmgr), 0, @@ -674,9 +641,9 @@ ISC_LOOP_TEST_IMPL(dispatch_tcp_response) { &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( @@ -713,9 +680,9 @@ ISC_LOOP_TEST_IMPL(dispatch_tls_response) { &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(test->dispatch, isc_loop_main(loopmgr), 0, @@ -800,7 +767,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(mctx, sizeof(*test)); *test = (test_dispatch_t){ 0 }; @@ -814,61 +781,28 @@ ISC_LOOP_TEST_IMPL(dispatch_gettcp) { /* ensure we stop listening after the test is done */ isc_loop_teardown(isc_loop_main(loopmgr), stop_listening, sock); - result = dns_dispatchmgr_create(mctx, loopmgr, connect_nm, - &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(loopmgr), 0, T_CLIENT_CONNECT, - &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(mctx, sizeof(*test)); - *test = (test_dispatch_t){ 0 }; - - /* Server */ - result = isc_nm_listenstreamdns( - netmgr, 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(loopmgr), stop_listening, sock); - - /* Client - unshared */ + /* First client — creates the shared TCP dispatch. */ result = dns_dispatchmgr_create(mctx, loopmgr, connect_nm, &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(loopmgr), 0, T_CLIENT_CONNECT, - &tcp_server_addr, NULL, NULL, connected_newtcp, client_senddone, - response_noop, test, &test->id, &test->dispentry); + result = dns_dispatch_add(test->dispatch, isc_loop_main(loopmgr), 0, + T_CLIENT_CONNECT, &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)