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.
This commit is contained in:
Ondřej Surý 2026-02-17 11:05:33 +01:00
parent 09a4b80301
commit d5ee86b799
No known key found for this signature in database
GPG key ID: 2820F37E873DEA41
6 changed files with 161 additions and 242 deletions

View file

@ -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);
}

View file

@ -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);

View file

@ -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,

View file

@ -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;

View file

@ -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);

View file

@ -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)