2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

[master] allow shared TCP sockets when connecting

4041.	[func]		TCP sockets can now be shared while connecting.
			(This will be used to enable client-side support
			of pipelined queries.) [RT #38231]
This commit is contained in:
Evan Hunt
2015-01-20 17:22:31 -08:00
parent d9184858dd
commit ff62d4458a
16 changed files with 314 additions and 195 deletions

View File

@@ -1,3 +1,7 @@
4041. [func] TCP sockets can now be shared while connecting.
(This will be used to enable client-side support
of pipelined queries.) [RT #38231]
4040. [func] Added server-side support for pipelined TCP 4040. [func] Added server-side support for pipelined TCP
queries. TCP connections are no longer closed after queries. TCP connections are no longer closed after
the first query received from a client. (The new the first query received from a client. (The new

View File

@@ -70,7 +70,7 @@ SUBDIRS="acl additional allow_query addzone autosign builtin
dns64 dnssec dsdigest dscp ecdsa ednscompliance emptyzones dns64 dnssec dsdigest dscp ecdsa ednscompliance emptyzones
filter-aaaa formerr forward geoip glue gost ixfr inline filter-aaaa formerr forward geoip glue gost ixfr inline
legacy limits logfileconfig lwresd masterfile masterformat legacy limits logfileconfig lwresd masterfile masterformat
metadata notify nslookup nsupdate pending piplined @PKCS11_TEST@ metadata notify nslookup nsupdate pending pipelined @PKCS11_TEST@
reclimit redirect resolver rndc rpz rrl rrchecker rrsetorder reclimit redirect resolver rndc rpz rrl rrchecker rrsetorder
rsabigexponent runtime sit sfcache smartsign sortlist spf rsabigexponent runtime sit sfcache smartsign sortlist spf
staticstub statistics stub tcp tkey tsig tsiggss unknown staticstub statistics stub tcp tkey tsig tsiggss unknown

View File

@@ -17,3 +17,4 @@
rm -f */named.memstats rm -f */named.memstats
rm -f */named.run rm -f */named.run
rm -f raw* output* rm -f raw* output*
rm -f ns*/named.lock

View File

@@ -1 +1 @@
-m record,size,mctx -c named.conf -d 99 -g -T delay=200 -m record,size,mctx -c named.conf -d 99 -X named.lock -g -T delay=200

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2014, 2015 Internet Systems Consortium, Inc. ("ISC")
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -26,6 +26,7 @@
#include <isc/hash.h> #include <isc/hash.h>
#include <isc/log.h> #include <isc/log.h>
#include <isc/mem.h> #include <isc/mem.h>
#include <isc/net.h>
#include <isc/sockaddr.h> #include <isc/sockaddr.h>
#include <isc/socket.h> #include <isc/socket.h>
#include <isc/task.h> #include <isc/task.h>
@@ -61,7 +62,9 @@
static isc_mem_t *mctx; static isc_mem_t *mctx;
static dns_requestmgr_t *requestmgr; static dns_requestmgr_t *requestmgr;
isc_sockaddr_t address; static isc_boolean_t have_src = ISC_FALSE;
static isc_sockaddr_t srcaddr;
static isc_sockaddr_t dstaddr;
static int onfly; static int onfly;
static void static void
@@ -124,8 +127,7 @@ recvresponse(isc_task_t *task, isc_event_t *event) {
} }
static isc_result_t static isc_result_t
sendquery(isc_task_t *task) sendquery(isc_task_t *task) {
{
dns_request_t *request; dns_request_t *request;
dns_message_t *message; dns_message_t *message;
dns_name_t *qname; dns_name_t *qname;
@@ -175,9 +177,10 @@ sendquery(isc_task_t *task)
dns_message_addname(message, qname, DNS_SECTION_QUESTION); dns_message_addname(message, qname, DNS_SECTION_QUESTION);
request = NULL; request = NULL;
result = dns_request_create(requestmgr, message, &address, result = dns_request_createvia(requestmgr, message,
DNS_REQUESTOPT_TCP, NULL, have_src ? &srcaddr : NULL, &dstaddr,
TIMEOUT, task, recvresponse, DNS_REQUESTOPT_TCP|DNS_REQUESTOPT_SHARE,
NULL, TIMEOUT, task, recvresponse,
message, &request); message, &request);
CHECK("dns_request_create", result); CHECK("dns_request_create", result);
@@ -185,8 +188,7 @@ sendquery(isc_task_t *task)
} }
static void static void
sendqueries(isc_task_t *task, isc_event_t *event) sendqueries(isc_task_t *task, isc_event_t *event) {
{
isc_result_t result; isc_result_t result;
isc_event_free(&event); isc_event_free(&event);
@@ -200,42 +202,44 @@ sendqueries(isc_task_t *task, isc_event_t *event)
return; return;
} }
static void
connecting(isc_task_t *task, isc_event_t *event)
{
isc_socket_t *sock = (isc_socket_t *)(event->ev_arg);
RUNCHECK(isc_socket_connect(sock, &address, task, sendqueries, NULL));
isc_event_free(&event);
}
int int
main(int argc, char *argv[]) main(int argc, char *argv[]) {
{ isc_sockaddr_t bind_any;
isc_taskmgr_t *taskmgr;
isc_timermgr_t *timermgr;
isc_socketmgr_t *socketmgr;
isc_socket_t *sock;
unsigned int attrs, attrmask;
isc_sockaddr_t bind_addr;
dns_dispatchmgr_t *dispatchmgr;
dns_dispatch_t *dispatchv4;
dns_dispatch_t *tcpdispatch;
dns_view_t *view;
isc_entropy_t *ectx;
isc_task_t *task;
isc_log_t *lctx;
isc_logconfig_t *lcfg;
struct in_addr inaddr; struct in_addr inaddr;
isc_result_t result; isc_result_t result;
isc_log_t *lctx;
isc_logconfig_t *lcfg;
isc_entropy_t *ectx;
isc_taskmgr_t *taskmgr;
isc_task_t *task;
isc_timermgr_t *timermgr;
isc_socketmgr_t *socketmgr;
dns_dispatchmgr_t *dispatchmgr;
unsigned int attrs, attrmask;
dns_dispatch_t *dispatchv4;
dns_view_t *view;
UNUSED(argv); UNUSED(argv);
if (argc > 1)
have_src = ISC_TRUE;
RUNCHECK(isc_app_start()); RUNCHECK(isc_app_start());
dns_result_register(); dns_result_register();
isc_sockaddr_any(&bind_any);
result = ISC_R_FAILURE;
if (inet_pton(AF_INET, "10.53.0.7", &inaddr) != 1)
CHECK("inet_pton", result);
isc_sockaddr_fromin(&srcaddr, &inaddr, 0);
result = ISC_R_FAILURE;
if (inet_pton(AF_INET, "10.53.0.4", &inaddr) != 1)
CHECK("inet_pton", result);
isc_sockaddr_fromin(&dstaddr, &inaddr, PORT);
mctx = NULL; mctx = NULL;
RUNCHECK(isc_mem_create(0, 0, &mctx)); RUNCHECK(isc_mem_create(0, 0, &mctx));
@@ -261,14 +265,7 @@ main(int argc, char *argv[])
RUNCHECK(isc_socketmgr_create(mctx, &socketmgr)); RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
dispatchmgr = NULL; dispatchmgr = NULL;
RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr)); RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr));
if (argc == 1) {
isc_sockaddr_any(&bind_addr);
} else {
result = ISC_R_FAILURE;
if (inet_pton(AF_INET, "10.53.0.7", &inaddr) != 1)
CHECK("inet_pton", result);
isc_sockaddr_fromin(&bind_addr, &inaddr, 0);
}
attrs = DNS_DISPATCHATTR_UDP | attrs = DNS_DISPATCHATTR_UDP |
DNS_DISPATCHATTR_MAKEQUERY | DNS_DISPATCHATTR_MAKEQUERY |
DNS_DISPATCHATTR_IPV4; DNS_DISPATCHATTR_IPV4;
@@ -278,7 +275,8 @@ main(int argc, char *argv[])
DNS_DISPATCHATTR_IPV6; DNS_DISPATCHATTR_IPV6;
dispatchv4 = NULL; dispatchv4 = NULL;
RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
&bind_addr, 4096, 4, 2, 3, 5, have_src ? &srcaddr : &bind_any,
4096, 4, 2, 3, 5,
attrs, attrmask, &dispatchv4)); attrs, attrmask, &dispatchv4));
requestmgr = NULL; requestmgr = NULL;
RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
@@ -288,31 +286,7 @@ main(int argc, char *argv[])
view = NULL; view = NULL;
RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
sock = NULL; RUNCHECK(isc_app_onrun(mctx, task, sendqueries, NULL));
RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_tcp,
&sock));
RUNCHECK(isc_socket_bind(sock, &bind_addr, 0));
result = ISC_R_FAILURE;
if (inet_pton(AF_INET, "10.53.0.4", &inaddr) != 1)
CHECK("inet_pton", result);
isc_sockaddr_fromin(&address, &inaddr, PORT);
attrs = 0;
attrs |= DNS_DISPATCHATTR_TCP;
attrs |= DNS_DISPATCHATTR_IPV4;
attrs |= DNS_DISPATCHATTR_MAKEQUERY;
attrs |= DNS_DISPATCHATTR_CONNECTED;
isc_socket_dscp(sock, -1);
tcpdispatch = NULL;
RUNCHECK(dns_dispatch_createtcp2(dispatchmgr, sock, taskmgr,
&bind_addr, &address,
4096, 20, 10, 3, 5,
attrs, &tcpdispatch));
RUNCHECK(isc_app_onrun(mctx, task, connecting, sock));
isc_socket_detach(&sock);
(void)isc_app_run(); (void)isc_app_run();
@@ -322,7 +296,6 @@ main(int argc, char *argv[])
dns_requestmgr_detach(&requestmgr); dns_requestmgr_detach(&requestmgr);
dns_dispatch_detach(&dispatchv4); dns_dispatch_detach(&dispatchv4);
dns_dispatch_detach(&tcpdispatch);
dns_dispatchmgr_destroy(&dispatchmgr); dns_dispatchmgr_destroy(&dispatchmgr);
isc_socketmgr_destroy(&socketmgr); isc_socketmgr_destroy(&socketmgr);

View File

@@ -314,6 +314,9 @@ typedef __int64 off_t;
/* Define to the flags type used by getnameinfo(3). */ /* Define to the flags type used by getnameinfo(3). */
#define IRS_GETNAMEINFO_FLAGS_T int #define IRS_GETNAMEINFO_FLAGS_T int
/* Define to the sockaddr length type used by getnameinfo(3). */
#define IRS_GETNAMEINFO_SOCKLEN_T socklen_t
/* Define to enable the "filter-aaaa-on-v4" and "filter-aaaa-on-v6" options. /* Define to enable the "filter-aaaa-on-v4" and "filter-aaaa-on-v6" options.
*/ */
@ALLOW_FILTER_AAAA@ @ALLOW_FILTER_AAAA@

View File

@@ -2677,6 +2677,83 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr,
return (match ? ISC_R_SUCCESS : ISC_R_NOTFOUND); return (match ? ISC_R_SUCCESS : ISC_R_NOTFOUND);
} }
isc_result_t
dns_dispatch_gettcp2(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr,
isc_sockaddr_t *localaddr, isc_boolean_t *connected,
dns_dispatch_t **dispp)
{
dns_dispatch_t *disp;
isc_result_t result;
isc_sockaddr_t peeraddr;
isc_sockaddr_t sockname;
unsigned int attributes, mask;
isc_boolean_t match = ISC_FALSE;
REQUIRE(VALID_DISPATCHMGR(mgr));
REQUIRE(destaddr != NULL);
REQUIRE(dispp != NULL && *dispp == NULL);
REQUIRE(connected != NULL);
/* First pass (same than dns_dispatch_gettcp()) */
attributes = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_CONNECTED;
mask = DNS_DISPATCHATTR_TCP | DNS_DISPATCHATTR_PRIVATE |
DNS_DISPATCHATTR_EXCLUSIVE | DNS_DISPATCHATTR_CONNECTED;
LOCK(&mgr->lock);
disp = ISC_LIST_HEAD(mgr->list);
while (disp != NULL && !match) {
LOCK(&disp->lock);
if ((disp->shutting_down == 0) &&
ATTRMATCH(disp->attributes, attributes, mask) &&
(localaddr == NULL ||
isc_sockaddr_eqaddr(localaddr, &disp->local))) {
result = isc_socket_getsockname(disp->socket,
&sockname);
if (result == ISC_R_SUCCESS)
result = isc_socket_getpeername(disp->socket,
&peeraddr);
if (result == ISC_R_SUCCESS &&
isc_sockaddr_equal(destaddr, &peeraddr) &&
(localaddr == NULL ||
isc_sockaddr_eqaddr(localaddr, &sockname))) {
/* attach */
disp->refcount++;
*dispp = disp;
match = ISC_TRUE;
*connected = ISC_TRUE;
}
}
UNLOCK(&disp->lock);
disp = ISC_LIST_NEXT(disp, link);
}
if (match) {
UNLOCK(&mgr->lock);
return (ISC_R_SUCCESS);
}
/* Second pass */
attributes = DNS_DISPATCHATTR_TCP;
disp = ISC_LIST_HEAD(mgr->list);
while (disp != NULL && !match) {
LOCK(&disp->lock);
if ((disp->shutting_down == 0) &&
ATTRMATCH(disp->attributes, attributes, mask) &&
(localaddr == NULL ||
isc_sockaddr_eqaddr(localaddr, &disp->local)) &&
isc_sockaddr_equal(destaddr, &disp->peer)) {
/* attach */
disp->refcount++;
*dispp = disp;
match = ISC_TRUE;
}
UNLOCK(&disp->lock);
disp = ISC_LIST_NEXT(disp, link);
}
UNLOCK(&mgr->lock);
return (match ? ISC_R_SUCCESS : ISC_R_NOTFOUND);
}
isc_result_t isc_result_t
dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr, isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
@@ -3332,8 +3409,10 @@ dns_dispatch_starttcp(dns_dispatch_t *disp) {
dispatch_log(disp, LVL(90), "starttcp %p", disp->task[0]); dispatch_log(disp, LVL(90), "starttcp %p", disp->task[0]);
LOCK(&disp->lock); LOCK(&disp->lock);
if ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) == 0) {
disp->attributes |= DNS_DISPATCHATTR_CONNECTED; disp->attributes |= DNS_DISPATCHATTR_CONNECTED;
(void)startrecv(disp, NULL); (void)startrecv(disp, NULL);
}
UNLOCK(&disp->lock); UNLOCK(&disp->lock);
} }

View File

@@ -383,8 +383,13 @@ dns_dispatch_starttcp(dns_dispatch_t *disp);
isc_result_t isc_result_t
dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr, dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr,
isc_sockaddr_t *localaddr, dns_dispatch_t **dispp); isc_sockaddr_t *localaddr, dns_dispatch_t **dispp);
isc_result_t
dns_dispatch_gettcp2(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr,
isc_sockaddr_t *localaddr, isc_boolean_t *connected,
dns_dispatch_t **dispp);
/* /*
* Attempt to connect to a existing TCP connection. * Attempt to connect to a existing TCP connection (connection completed
* for dns_dispatch_gettcp()).
*/ */

View File

@@ -49,6 +49,7 @@
#define DNS_REQUESTOPT_TCP 0x00000001U #define DNS_REQUESTOPT_TCP 0x00000001U
#define DNS_REQUESTOPT_CASE 0x00000002U #define DNS_REQUESTOPT_CASE 0x00000002U
#define DNS_REQUESTOPT_FIXEDID 0x00000004U #define DNS_REQUESTOPT_FIXEDID 0x00000004U
#define DNS_REQUESTOPT_SHARE 0x00000008U
typedef struct dns_requestevent { typedef struct dns_requestevent {
ISC_EVENT_COMMON(struct dns_requestevent); ISC_EVENT_COMMON(struct dns_requestevent);
@@ -174,7 +175,9 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
* Notes: * Notes:
* *
*\li 'message' will be rendered and sent to 'address'. If the *\li 'message' will be rendered and sent to 'address'. If the
* #DNS_REQUESTOPT_TCP option is set, TCP will be used. The request * #DNS_REQUESTOPT_TCP option is set, TCP will be used,
* #DNS_REQUESTOPT_SHARE option is set too, connecting TCP
* (vs. connected) will be shared too. The request
* will timeout after 'timeout' seconds. * will timeout after 'timeout' seconds.
* *
*\li If the #DNS_REQUESTOPT_CASE option is set, use case sensitive *\li If the #DNS_REQUESTOPT_CASE option is set, use case sensitive
@@ -238,7 +241,9 @@ dns_request_createvia4(dns_requestmgr_t *requestmgr, dns_message_t *message,
* Notes: * Notes:
* *
*\li 'message' will be rendered and sent to 'address'. If the *\li 'message' will be rendered and sent to 'address'. If the
* #DNS_REQUESTOPT_TCP option is set, TCP will be used. The request * #DNS_REQUESTOPT_TCP option is set, TCP will be used,
* #DNS_REQUESTOPT_SHARE option is set too, connecting TCP
* (vs. connected) will be shared too. The request
* will timeout after 'timeout' seconds. UDP requests will be resent * will timeout after 'timeout' seconds. UDP requests will be resent
* at 'udptimeout' intervals if non-zero or 'udpretries' is non-zero. * at 'udptimeout' intervals if non-zero or 'udpretries' is non-zero.
* *
@@ -305,7 +310,9 @@ dns_request_createraw4(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
* Notes: * Notes:
* *
*\li 'msgbuf' will be sent to 'destaddr' after setting the id. If the *\li 'msgbuf' will be sent to 'destaddr' after setting the id. If the
* #DNS_REQUESTOPT_TCP option is set, TCP will be used. The request * #DNS_REQUESTOPT_TCP option is set, TCP will be used,
* #DNS_REQUESTOPT_SHARE option is set too, connecting TCP
* (vs. connected) will be shared too. The request
* will timeout after 'timeout' seconds. UDP requests will be resent * will timeout after 'timeout' seconds. UDP requests will be resent
* at 'udptimeout' intervals if non-zero or if 'udpretries' is not zero. * at 'udptimeout' intervals if non-zero or if 'udpretries' is not zero.
* *

View File

@@ -525,7 +525,8 @@ isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) {
} }
static isc_result_t static isc_result_t
create_tcp_dispatch(isc_boolean_t newtcp, dns_requestmgr_t *requestmgr, create_tcp_dispatch(isc_boolean_t newtcp, isc_boolean_t share,
dns_requestmgr_t *requestmgr,
isc_sockaddr_t *srcaddr, isc_sockaddr_t *srcaddr,
isc_sockaddr_t *destaddr, isc_dscp_t dscp, isc_sockaddr_t *destaddr, isc_dscp_t dscp,
isc_boolean_t *connected, dns_dispatch_t **dispatchp) isc_boolean_t *connected, dns_dispatch_t **dispatchp)
@@ -536,7 +537,20 @@ create_tcp_dispatch(isc_boolean_t newtcp, dns_requestmgr_t *requestmgr,
unsigned int attrs; unsigned int attrs;
isc_sockaddr_t bind_any; isc_sockaddr_t bind_any;
if (!newtcp) { if (!newtcp && share) {
result = dns_dispatch_gettcp2(requestmgr->dispatchmgr,
destaddr, srcaddr,
connected, 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 %s TCP "
"connection to %s",
*connected ? "existing" : "pending", peer);
return (result);
}
} else if (!newtcp) {
result = dns_dispatch_gettcp(requestmgr->dispatchmgr, destaddr, result = dns_dispatch_gettcp(requestmgr->dispatchmgr, destaddr,
srcaddr, dispatchp); srcaddr, dispatchp);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
@@ -642,7 +656,7 @@ find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
} }
static isc_result_t static isc_result_t
get_dispatch(isc_boolean_t tcp, isc_boolean_t newtcp, get_dispatch(isc_boolean_t tcp, isc_boolean_t newtcp, isc_boolean_t share,
dns_requestmgr_t *requestmgr, dns_requestmgr_t *requestmgr,
isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
isc_dscp_t dscp, isc_boolean_t *connected, isc_dscp_t dscp, isc_boolean_t *connected,
@@ -651,9 +665,9 @@ get_dispatch(isc_boolean_t tcp, isc_boolean_t newtcp,
isc_result_t result; isc_result_t result;
if (tcp) if (tcp)
result = create_tcp_dispatch(newtcp, requestmgr, srcaddr, result = create_tcp_dispatch(newtcp, share, requestmgr,
destaddr, dscp, connected, srcaddr, destaddr, dscp,
dispatchp); connected, dispatchp);
else else
result = find_udp_dispatch(requestmgr, srcaddr, result = find_udp_dispatch(requestmgr, srcaddr,
destaddr, dispatchp); destaddr, dispatchp);
@@ -740,6 +754,7 @@ dns_request_createraw4(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
dns_messageid_t id; dns_messageid_t id;
isc_boolean_t tcp = ISC_FALSE; isc_boolean_t tcp = ISC_FALSE;
isc_boolean_t newtcp = ISC_FALSE; isc_boolean_t newtcp = ISC_FALSE;
isc_boolean_t share = ISC_FALSE;
isc_region_t r; isc_region_t r;
isc_boolean_t connected = ISC_FALSE; isc_boolean_t connected = ISC_FALSE;
unsigned int dispopt = 0; unsigned int dispopt = 0;
@@ -803,9 +818,11 @@ dns_request_createraw4(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512) if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
tcp = ISC_TRUE; tcp = ISC_TRUE;
share = ISC_TF((options & DNS_REQUESTOPT_SHARE) != 0);
again: again:
result = get_dispatch(tcp, newtcp, requestmgr, srcaddr, destaddr, dscp, result = get_dispatch(tcp, newtcp, share, requestmgr,
srcaddr, destaddr, dscp,
&connected, &request->dispatch); &connected, &request->dispatch);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup; goto cleanup;
@@ -971,6 +988,7 @@ dns_request_createvia4(dns_requestmgr_t *requestmgr, dns_message_t *message,
isc_mem_t *mctx; isc_mem_t *mctx;
dns_messageid_t id; dns_messageid_t id;
isc_boolean_t tcp; isc_boolean_t tcp;
isc_boolean_t share;
isc_boolean_t setkey = ISC_TRUE; isc_boolean_t setkey = ISC_TRUE;
isc_boolean_t connected = ISC_FALSE; isc_boolean_t connected = ISC_FALSE;
@@ -1031,7 +1049,9 @@ dns_request_createvia4(dns_requestmgr_t *requestmgr, dns_message_t *message,
use_tcp: use_tcp:
tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0); tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0);
result = get_dispatch(tcp, ISC_FALSE, requestmgr, srcaddr, destaddr, share = ISC_TF((options & DNS_REQUESTOPT_SHARE) != 0);
result = get_dispatch(tcp, ISC_FALSE, share,
requestmgr, srcaddr, destaddr,
dscp, &connected, &request->dispatch); dscp, &connected, &request->dispatch);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup; goto cleanup;

View File

@@ -59,7 +59,6 @@ dns_adb_noedns
dns_adb_plainresponse dns_adb_plainresponse
dns_adb_probesize dns_adb_probesize
dns_adb_probesize2 dns_adb_probesize2
dns_adb_probesize512
dns_adb_setadbsize dns_adb_setadbsize
dns_adb_setudpsize dns_adb_setudpsize
dns_adb_setsit dns_adb_setsit
@@ -257,6 +256,7 @@ dns_dispatch_getentrysocket
dns_dispatch_getlocaladdress dns_dispatch_getlocaladdress
dns_dispatch_getsocket dns_dispatch_getsocket
dns_dispatch_gettcp dns_dispatch_gettcp
dns_dispatch_gettcp2
dns_dispatch_getudp dns_dispatch_getudp
dns_dispatch_getudp_dup dns_dispatch_getudp_dup
dns_dispatch_importrecv dns_dispatch_importrecv

View File

@@ -347,7 +347,7 @@ struct isc__socket {
ISC_LIST(isc_socketevent_t) send_list; ISC_LIST(isc_socketevent_t) send_list;
ISC_LIST(isc_socketevent_t) recv_list; ISC_LIST(isc_socketevent_t) recv_list;
ISC_LIST(isc_socket_newconnev_t) accept_list; ISC_LIST(isc_socket_newconnev_t) accept_list;
isc_socket_connev_t *connect_ev; ISC_LIST(isc_socket_connev_t) connect_list;
/* /*
* Internal events. Posted when a descriptor is readable or * Internal events. Posted when a descriptor is readable or
@@ -471,6 +471,7 @@ static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf,
isc_socket_t *dup_socket); isc_socket_t *dup_socket);
static void send_recvdone_event(isc__socket_t *, isc_socketevent_t **); static void send_recvdone_event(isc__socket_t *, isc_socketevent_t **);
static void send_senddone_event(isc__socket_t *, isc_socketevent_t **); static void send_senddone_event(isc__socket_t *, isc_socketevent_t **);
static void send_connectdone_event(isc__socket_t *, isc_socket_connev_t **);
static void free_socket(isc__socket_t **); static void free_socket(isc__socket_t **);
static isc_result_t allocate_socket(isc__socketmgr_t *, isc_sockettype_t, static isc_result_t allocate_socket(isc__socketmgr_t *, isc_sockettype_t,
isc__socket_t **); isc__socket_t **);
@@ -2216,10 +2217,10 @@ destroy(isc__socket_t **sockp) {
socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_DESTROYING, "destroying"); ISC_MSG_DESTROYING, "destroying");
INSIST(ISC_LIST_EMPTY(sock->connect_list));
INSIST(ISC_LIST_EMPTY(sock->accept_list)); INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(ISC_LIST_EMPTY(sock->recv_list)); INSIST(ISC_LIST_EMPTY(sock->recv_list));
INSIST(ISC_LIST_EMPTY(sock->send_list)); INSIST(ISC_LIST_EMPTY(sock->send_list));
INSIST(sock->connect_ev == NULL);
REQUIRE(sock->fd == -1 || sock->fd < (int)manager->maxsocks); REQUIRE(sock->fd == -1 || sock->fd < (int)manager->maxsocks);
if (sock->fd >= 0) { if (sock->fd >= 0) {
@@ -2326,7 +2327,7 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
ISC_LIST_INIT(sock->recv_list); ISC_LIST_INIT(sock->recv_list);
ISC_LIST_INIT(sock->send_list); ISC_LIST_INIT(sock->send_list);
ISC_LIST_INIT(sock->accept_list); ISC_LIST_INIT(sock->accept_list);
sock->connect_ev = NULL; ISC_LIST_INIT(sock->connect_list);
sock->pending_recv = 0; sock->pending_recv = 0;
sock->pending_send = 0; sock->pending_send = 0;
sock->pending_accept = 0; sock->pending_accept = 0;
@@ -2394,6 +2395,7 @@ free_socket(isc__socket_t **socketp) {
INSIST(ISC_LIST_EMPTY(sock->recv_list)); INSIST(ISC_LIST_EMPTY(sock->recv_list));
INSIST(ISC_LIST_EMPTY(sock->send_list)); INSIST(ISC_LIST_EMPTY(sock->send_list));
INSIST(ISC_LIST_EMPTY(sock->accept_list)); INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(ISC_LIST_EMPTY(sock->connect_list));
INSIST(!ISC_LINK_LINKED(sock, link)); INSIST(!ISC_LINK_LINKED(sock, link));
if (sock->recvcmsgbuf != NULL) if (sock->recvcmsgbuf != NULL)
@@ -3223,7 +3225,7 @@ isc__socket_close(isc_socket_t *sock0) {
INSIST(ISC_LIST_EMPTY(sock->recv_list)); INSIST(ISC_LIST_EMPTY(sock->recv_list));
INSIST(ISC_LIST_EMPTY(sock->send_list)); INSIST(ISC_LIST_EMPTY(sock->send_list));
INSIST(ISC_LIST_EMPTY(sock->accept_list)); INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(sock->connect_ev == NULL); INSIST(ISC_LIST_EMPTY(sock->connect_list));
manager = sock->manager; manager = sock->manager;
fd = sock->fd; fd = sock->fd;
@@ -3356,7 +3358,7 @@ dispatch_connect(isc__socket_t *sock) {
iev = &sock->writable_ev; iev = &sock->writable_ev;
ev = sock->connect_ev; ev = ISC_LIST_HEAD(sock->connect_list);
INSIST(ev != NULL); /* XXX */ INSIST(ev != NULL); /* XXX */
INSIST(sock->connecting); INSIST(sock->connecting);
@@ -3421,6 +3423,26 @@ send_senddone_event(isc__socket_t *sock, isc_socketevent_t **dev) {
isc_task_send(task, (isc_event_t **)dev); isc_task_send(task, (isc_event_t **)dev);
} }
/*
* See comments for send_recvdone_event() above.
*
* Caller must have the socket locked if the event is attached to the socket.
*/
static void
send_connectdone_event(isc__socket_t *sock, isc_socket_connev_t **dev) {
isc_task_t *task;
INSIST(dev != NULL && *dev != NULL);
task = (*dev)->ev_sender;
(*dev)->ev_sender = sock;
if (ISC_LINK_LINKED(*dev, ev_link))
ISC_LIST_DEQUEUE(sock->connect_list, *dev, ev_link);
isc_task_sendanddetach(&task, (isc_event_t **)dev);
}
/* /*
* Call accept() on a socket, to get the new file descriptor. The listen * Call accept() on a socket, to get the new file descriptor. The listen
* socket is used as a prototype to create a new isc_socket_t. The new * socket is used as a prototype to create a new isc_socket_t. The new
@@ -5682,8 +5704,6 @@ isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr,
LOCK(&sock->lock); LOCK(&sock->lock);
REQUIRE(!sock->connecting);
dev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock, dev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
ISC_SOCKEVENT_CONNECT, ISC_SOCKEVENT_CONNECT,
action, arg, action, arg,
@@ -5694,6 +5714,11 @@ isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr,
} }
ISC_LINK_INIT(dev, ev_link); ISC_LINK_INIT(dev, ev_link);
if (sock->connecting) {
INSIST(isc_sockaddr_equal(&sock->peer_address, addr));
goto queue;
}
/* /*
* Try to do the connect right away, as there can be only one * Try to do the connect right away, as there can be only one
* outstanding, and it might happen to complete. * outstanding, and it might happen to complete.
@@ -5780,8 +5805,6 @@ isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr,
*/ */
isc_task_attach(task, &ntask); isc_task_attach(task, &ntask);
sock->connecting = 1;
dev->ev_sender = ntask; dev->ev_sender = ntask;
/* /*
@@ -5789,10 +5812,12 @@ isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr,
* is no race condition. We will keep the lock for such a short * is no race condition. We will keep the lock for such a short
* bit of time waking it up now or later won't matter all that much. * bit of time waking it up now or later won't matter all that much.
*/ */
if (sock->connect_ev == NULL) if (ISC_LIST_EMPTY(sock->connect_list) && !sock->connecting)
select_poke(manager, sock->fd, SELECT_POKE_CONNECT); select_poke(manager, sock->fd, SELECT_POKE_CONNECT);
sock->connect_ev = dev; sock->connecting = 1;
ISC_LIST_ENQUEUE(sock->connect_list, dev, ev_link);
UNLOCK(&sock->lock); UNLOCK(&sock->lock);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
@@ -5805,8 +5830,8 @@ static void
internal_connect(isc_task_t *me, isc_event_t *ev) { internal_connect(isc_task_t *me, isc_event_t *ev) {
isc__socket_t *sock; isc__socket_t *sock;
isc_socket_connev_t *dev; isc_socket_connev_t *dev;
isc_task_t *task;
int cc; int cc;
isc_result_t result;
ISC_SOCKADDR_LEN_T optlen; ISC_SOCKADDR_LEN_T optlen;
char strbuf[ISC_STRERRORSIZE]; char strbuf[ISC_STRERRORSIZE];
char peerbuf[ISC_SOCKADDR_FORMATSIZE]; char peerbuf[ISC_SOCKADDR_FORMATSIZE];
@@ -5832,9 +5857,10 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
} }
/* /*
* Has this event been canceled? * Get the first item off the connect list.
* If it is empty, unlock the socket and return.
*/ */
dev = sock->connect_ev; dev = ISC_LIST_HEAD(sock->connect_list);
if (dev == NULL) { if (dev == NULL) {
INSIST(!sock->connecting); INSIST(!sock->connecting);
UNLOCK(&sock->lock); UNLOCK(&sock->lock);
@@ -5875,7 +5901,7 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
* Translate other errors into ISC_R_* flavors. * Translate other errors into ISC_R_* flavors.
*/ */
switch (errno) { switch (errno) {
#define ERROR_MATCH(a, b) case a: dev->result = b; break; #define ERROR_MATCH(a, b) case a: result = b; break;
ERROR_MATCH(EACCES, ISC_R_NOPERM); ERROR_MATCH(EACCES, ISC_R_NOPERM);
ERROR_MATCH(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); ERROR_MATCH(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
ERROR_MATCH(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL); ERROR_MATCH(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
@@ -5892,7 +5918,7 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
ERROR_MATCH(ECONNRESET, ISC_R_CONNECTIONRESET); ERROR_MATCH(ECONNRESET, ISC_R_CONNECTIONRESET);
#undef ERROR_MATCH #undef ERROR_MATCH
default: default:
dev->result = ISC_R_UNEXPECTED; result = ISC_R_UNEXPECTED;
isc_sockaddr_format(&sock->peer_address, peerbuf, isc_sockaddr_format(&sock->peer_address, peerbuf,
sizeof(peerbuf)); sizeof(peerbuf));
isc__strerror(errno, strbuf, sizeof(strbuf)); isc__strerror(errno, strbuf, sizeof(strbuf));
@@ -5903,18 +5929,18 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
} else { } else {
inc_stats(sock->manager->stats, inc_stats(sock->manager->stats,
sock->statsindex[STATID_CONNECT]); sock->statsindex[STATID_CONNECT]);
dev->result = ISC_R_SUCCESS; result = ISC_R_SUCCESS;
sock->connected = 1; sock->connected = 1;
sock->bound = 1; sock->bound = 1;
} }
sock->connect_ev = NULL; do {
dev->result = result;
send_connectdone_event(sock, &dev);
dev = ISC_LIST_HEAD(sock->connect_list);
} while (dev != NULL);
UNLOCK(&sock->lock); UNLOCK(&sock->lock);
task = dev->ev_sender;
dev->ev_sender = sock;
isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
} }
isc_result_t isc_result_t
@@ -6072,27 +6098,26 @@ isc__socket_cancel(isc_socket_t *sock0, isc_task_t *task, unsigned int how) {
} }
} }
/*
* Connecting is not a list.
*/
if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT) if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT)
&& sock->connect_ev != NULL) { && !ISC_LIST_EMPTY(sock->connect_list)) {
isc_socket_connev_t *dev; isc_socket_connev_t *dev;
isc_socket_connev_t *next;
isc_task_t *current_task; isc_task_t *current_task;
INSIST(sock->connecting); INSIST(sock->connecting);
sock->connecting = 0; sock->connecting = 0;
dev = sock->connect_ev; dev = ISC_LIST_HEAD(sock->connect_list);
while (dev != NULL) {
current_task = dev->ev_sender; current_task = dev->ev_sender;
next = ISC_LIST_NEXT(dev, ev_link);
if ((task == NULL) || (task == current_task)) { if ((task == NULL) || (task == current_task)) {
sock->connect_ev = NULL;
dev->result = ISC_R_CANCELED; dev->result = ISC_R_CANCELED;
dev->ev_sender = sock; send_connectdone_event(sock, &dev);
isc_task_sendanddetach(&current_task, }
ISC_EVENT_PTR(&dev)); dev = next;
} }
} }

View File

@@ -483,9 +483,6 @@ isc_portset_isset
isc_portset_nports isc_portset_nports
isc_portset_remove isc_portset_remove
isc_portset_removerange isc_portset_removerange
isc_print_snprintf
isc_print_sprintf
isc_print_vsnprintf
isc_quota_attach isc_quota_attach
isc_quota_destroy isc_quota_destroy
isc_quota_detach isc_quota_detach
@@ -583,42 +580,8 @@ isc_sockaddr_pf
isc_sockaddr_setport isc_sockaddr_setport
isc_sockaddr_totext isc_sockaddr_totext
isc_sockaddr_v6fromin isc_sockaddr_v6fromin
isc_socket_accept
isc_socket_attach
isc_socket_bind
isc_socket_cancel
isc_socket_cleanunix
isc_socket_close
isc_socket_connect
isc_socket_create
isc_socket_detach
isc_socket_dscp
isc_socket_dup
isc_socket_fdwatchcreate
isc_socket_fdwatchpoke
isc_socket_filter
isc_socket_getpeername
isc_socket_getsockname
isc_socket_gettype
isc_socket_ipv6only
isc_socket_listen
isc_socket_open
isc_socket_permunix
isc_socket_register
isc_socket_recv
isc_socket_recv2
isc_socket_recvv
isc_socket_send
isc_socket_sendto
isc_socket_sendto2
isc_socket_sendtov
isc_socket_sendtov2
isc_socket_sendv
isc_socket_socketevent isc_socket_socketevent
isc_socketmgr_create
isc_socketmgr_create2
isc_socketmgr_createinctx isc_socketmgr_createinctx
isc_socketmgr_destroy
@IF LIBXML2 @IF LIBXML2
isc_socketmgr_renderxml isc_socketmgr_renderxml
@END LIBXML2 @END LIBXML2

View File

@@ -266,7 +266,7 @@ struct isc_socket {
ISC_LIST(isc_socketevent_t) send_list; ISC_LIST(isc_socketevent_t) send_list;
ISC_LIST(isc_socketevent_t) recv_list; ISC_LIST(isc_socketevent_t) recv_list;
ISC_LIST(isc_socket_newconnev_t) accept_list; ISC_LIST(isc_socket_newconnev_t) accept_list;
isc_socket_connev_t *connect_ev; ISC_LIST(isc_socket_connev_t) connect_list;
isc_sockaddr_t address; /* remote address */ isc_sockaddr_t address; /* remote address */
@@ -375,6 +375,7 @@ static void send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev);
static void send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev); static void send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev);
static void send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev); static void send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev);
static void send_recvdone_abort(isc_socket_t *sock, isc_result_t result); static void send_recvdone_abort(isc_socket_t *sock, isc_result_t result);
static void send_connectdone_abort(isc_socket_t *sock, isc_result_t result);
static void queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev); static void queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev);
static void queue_receive_request(isc_socket_t *sock); static void queue_receive_request(isc_socket_t *sock);
@@ -388,6 +389,7 @@ void
sock_dump(isc_socket_t *sock) { sock_dump(isc_socket_t *sock) {
isc_socketevent_t *ldev; isc_socketevent_t *ldev;
isc_socket_newconnev_t *ndev; isc_socket_newconnev_t *ndev;
isc_socket_connev_t *cdev;
#if 0 #if 0
isc_sockaddr_t addr; isc_sockaddr_t addr;
@@ -436,6 +438,13 @@ sock_dump(isc_socket_t *sock) {
printf("\t\tdev: %p\n", ldev); printf("\t\tdev: %p\n", ldev);
ndev = ISC_LIST_NEXT(ndev, ev_link); ndev = ISC_LIST_NEXT(ndev, ev_link);
} }
printf("\n\t\tSock Connect List\n");
cdev = ISC_LIST_HEAD(sock->connect_list);
while (cdev != NULL) {
printf("\t\tdev: %p\n", cdev);
cdev = ISC_LIST_NEXT(cdev, ev_link);
}
} }
static void static void
@@ -1486,7 +1495,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
ISC_LIST_INIT(sock->recv_list); ISC_LIST_INIT(sock->recv_list);
ISC_LIST_INIT(sock->send_list); ISC_LIST_INIT(sock->send_list);
ISC_LIST_INIT(sock->accept_list); ISC_LIST_INIT(sock->accept_list);
sock->connect_ev = NULL; ISC_LIST_INIT(sock->connect_list);
sock->pending_accept = 0; sock->pending_accept = 0;
sock->pending_recv = 0; sock->pending_recv = 0;
sock->pending_send = 0; sock->pending_send = 0;
@@ -1565,7 +1574,7 @@ consistent(isc_socket_t *sock) {
} }
if (count > sock->pending_accept) { if (count > sock->pending_accept) {
crash = ISC_TRUE; crash = ISC_TRUE;
crash_reason = "send_list > sock->pending_send"; crash_reason = "accept_list > sock->pending_accept";
} }
if (crash) { if (crash) {
@@ -1609,6 +1618,7 @@ maybe_free_socket(isc_socket_t **socketp, int lineno) {
|| !ISC_LIST_EMPTY(sock->recv_list) || !ISC_LIST_EMPTY(sock->recv_list)
|| !ISC_LIST_EMPTY(sock->send_list) || !ISC_LIST_EMPTY(sock->send_list)
|| !ISC_LIST_EMPTY(sock->accept_list) || !ISC_LIST_EMPTY(sock->accept_list)
|| !ISC_LIST_EMPTY(sock->connect_list)
|| sock->fd != INVALID_SOCKET) { || sock->fd != INVALID_SOCKET) {
UNLOCK(&sock->lock); UNLOCK(&sock->lock);
return; return;
@@ -2030,7 +2040,8 @@ send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev) {
task = (*cdev)->ev_sender; task = (*cdev)->ev_sender;
(*cdev)->ev_sender = sock; (*cdev)->ev_sender = sock;
sock->connect_ev = NULL; if (ISC_LINK_LINKED(*cdev, ev_link))
ISC_LIST_DEQUEUE(sock->connect_list, *cdev, ev_link);
isc_task_sendanddetach(&task, (isc_event_t **)cdev); isc_task_sendanddetach(&task, (isc_event_t **)cdev);
@@ -2148,6 +2159,7 @@ done:
static void static void
internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) { internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
isc_socket_connev_t *cdev; isc_socket_connev_t *cdev;
isc_result_t result;
char strbuf[ISC_STRERRORSIZE]; char strbuf[ISC_STRERRORSIZE];
INSIST(VALID_SOCKET(sock)); INSIST(VALID_SOCKET(sock));
@@ -2160,7 +2172,7 @@ internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
sock->pending_connect = 0; sock->pending_connect = 0;
/* /*
* Has this event been canceled? * If the event is no longer in the list we can just close and return.
*/ */
cdev = lpo->cdev; cdev = lpo->cdev;
if (!connectdone_is_active(sock, cdev)) { if (!connectdone_is_active(sock, cdev)) {
@@ -2195,7 +2207,7 @@ internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
* Translate other errors into ISC_R_* flavors. * Translate other errors into ISC_R_* flavors.
*/ */
switch (connect_errno) { switch (connect_errno) {
#define ERROR_MATCH(a, b) case a: cdev->result = b; break; #define ERROR_MATCH(a, b) case a: result = b; break;
ERROR_MATCH(WSAEACCES, ISC_R_NOPERM); ERROR_MATCH(WSAEACCES, ISC_R_NOPERM);
ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
ERROR_MATCH(WSAEAFNOSUPPORT, ISC_R_ADDRNOTAVAIL); ERROR_MATCH(WSAEAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
@@ -2210,7 +2222,7 @@ internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
ERROR_MATCH(WSAETIMEDOUT, ISC_R_TIMEDOUT); ERROR_MATCH(WSAETIMEDOUT, ISC_R_TIMEDOUT);
#undef ERROR_MATCH #undef ERROR_MATCH
default: default:
cdev->result = ISC_R_UNEXPECTED; result = ISC_R_UNEXPECTED;
isc__strerror(connect_errno, strbuf, sizeof(strbuf)); isc__strerror(connect_errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__, UNEXPECTED_ERROR(__FILE__, __LINE__,
"internal_connect: connect() %s", "internal_connect: connect() %s",
@@ -2219,14 +2231,18 @@ internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
} else { } else {
INSIST(setsockopt(sock->fd, SOL_SOCKET, INSIST(setsockopt(sock->fd, SOL_SOCKET,
SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0); SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0);
cdev->result = ISC_R_SUCCESS; result = ISC_R_SUCCESS;
sock->connected = 1; sock->connected = 1;
socket_log(__LINE__, sock, &sock->address, IOEVENT, socket_log(__LINE__, sock, &sock->address, IOEVENT,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
"internal_connect: success"); "internal_connect: success");
} }
do {
cdev->result = result;
send_connectdone_event(sock, &cdev); send_connectdone_event(sock, &cdev);
cdev = ISC_LIST_HEAD(sock->connect_list);
} while (cdev != NULL);
UNLOCK(&sock->lock); UNLOCK(&sock->lock);
} }
@@ -2245,6 +2261,20 @@ send_recvdone_abort(isc_socket_t *sock, isc_result_t result) {
} }
} }
/*
* Loop through the socket, returning result for each done event pending.
*/
static void
send_connectdone_abort(isc_socket_t *sock, isc_result_t result) {
isc_socket_connev_t *dev;
while (!ISC_LIST_EMPTY(sock->connect_list)) {
dev = ISC_LIST_HEAD(sock->connect_list);
dev->result = result;
send_connectdone_event(sock, &dev);
}
}
/* /*
* Take the data we received in our private buffer, and if any recv() calls on * Take the data we received in our private buffer, and if any recv() calls on
* our list are satisfied, send the corresponding done event. * our list are satisfied, send the corresponding done event.
@@ -2361,9 +2391,8 @@ internal_send(isc_socket_t *sock, isc_socketevent_t *dev,
} }
/* /*
* These return if the done event passed in is on the list (or for connect, is * These return if the done event passed in is on the list.
* the one we're waiting for. Using these ensures we will not double-send an * Using these ensures we will not double-send an event.
* event.
*/ */
static isc_boolean_t static isc_boolean_t
senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev) senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev)
@@ -2392,7 +2421,13 @@ acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev)
static isc_boolean_t static isc_boolean_t
connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev) connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev)
{ {
return (sock->connect_ev == dev ? ISC_TRUE : ISC_FALSE); isc_socket_connev_t *cdev;
cdev = ISC_LIST_HEAD(sock->connect_list);
while (cdev != NULL && cdev != dev)
cdev = ISC_LIST_NEXT(cdev, ev_link);
return (cdev == NULL ? ISC_FALSE : ISC_TRUE);
} }
// //
@@ -2592,10 +2627,9 @@ SocketIoThread(LPVOID ThreadContext) {
INSIST(sock->pending_connect == 1); INSIST(sock->pending_connect == 1);
sock->pending_connect = 0; sock->pending_connect = 0;
if (connectdone_is_active(sock, lpo->cdev)) { if (connectdone_is_active(sock, lpo->cdev)) {
lpo->cdev->result = isc_result;
socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
"canceled_connect"); "canceled_connect");
send_connectdone_event(sock, &lpo->cdev); send_connectdone_abort(sock, isc_result);
} }
break; break;
} }
@@ -3535,8 +3569,6 @@ isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
sock->bound = 1; sock->bound = 1;
} }
REQUIRE(!sock->pending_connect);
cdev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock, cdev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
ISC_SOCKEVENT_CONNECT, ISC_SOCKEVENT_CONNECT,
action, arg, action, arg,
@@ -3547,7 +3579,7 @@ isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
} }
ISC_LINK_INIT(cdev, ev_link); ISC_LINK_INIT(cdev, ev_link);
if (sock->type == isc_sockettype_tcp) { if ((sock->type == isc_sockettype_tcp) && !sock->pending_connect) {
/* /*
* Queue io completion for an accept(). * Queue io completion for an accept().
*/ */
@@ -3573,9 +3605,17 @@ isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
/* /*
* Enqueue the request. * Enqueue the request.
*/ */
sock->connect_ev = cdev; INSIST(!ISC_LINK_LINKED(cdev, ev_link));
ISC_LIST_ENQUEUE(sock->connect_list, cdev, ev_link);
sock->pending_iocp++; sock->pending_iocp++;
} else if (sock->type == isc_sockettype_tcp) {
INSIST(isc_sockaddr_equal(&sock->address, addr));
isc_task_attach(task, &ntask);
cdev->ev_sender = ntask;
INSIST(!ISC_LINK_LINKED(cdev, ev_link));
ISC_LIST_ENQUEUE(sock->connect_list, cdev, ev_link);
} else { } else {
REQUIRE(!sock->pending_connect);
WSAConnect(sock->fd, &addr->type.sa, addr->length, NULL, NULL, NULL, NULL); WSAConnect(sock->fd, &addr->type.sa, addr->length, NULL, NULL, NULL, NULL);
cdev->result = ISC_R_SUCCESS; cdev->result = ISC_R_SUCCESS;
isc_task_send(task, (isc_event_t **)&cdev); isc_task_send(task, (isc_event_t **)&cdev);
@@ -3761,28 +3801,28 @@ isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
} }
how &= ~ISC_SOCKCANCEL_ACCEPT; how &= ~ISC_SOCKCANCEL_ACCEPT;
/*
* Connecting is not a list.
*/
if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT) if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT)
&& sock->connect_ev != NULL) { && !ISC_LIST_EMPTY(sock->connect_list)) {
isc_socket_connev_t *dev; isc_socket_connev_t *dev;
isc_socket_connev_t *next;
isc_task_t *current_task; isc_task_t *current_task;
INSIST(sock->pending_connect); INSIST(sock->pending_connect);
dev = sock->connect_ev; dev = ISC_LIST_HEAD(sock->connect_list);
while (dev != NULL) {
current_task = dev->ev_sender; current_task = dev->ev_sender;
next = ISC_LIST_NEXT(dev, ev_link);
if ((task == NULL) || (task == current_task)) { if ((task == NULL) || (task == current_task)) {
closesocket(sock->fd);
sock->fd = INVALID_SOCKET;
_set_state(sock, SOCK_CLOSED);
sock->connect_ev = NULL;
dev->result = ISC_R_CANCELED; dev->result = ISC_R_CANCELED;
send_connectdone_event(sock, &dev); send_connectdone_event(sock, &dev);
} }
dev = next;
}
closesocket(sock->fd);
sock->fd = INVALID_SOCKET;
_set_state(sock, SOCK_CLOSED);
} }
how &= ~ISC_SOCKCANCEL_CONNECT; how &= ~ISC_SOCKCANCEL_CONNECT;

View File

@@ -93,7 +93,6 @@ cfg_print_boolean
cfg_print_bracketed_list cfg_print_bracketed_list
cfg_print_chars cfg_print_chars
cfg_print_cstr cfg_print_cstr
cfg_print_fixedpoint
cfg_print_grammar cfg_print_grammar
cfg_print_map cfg_print_map
cfg_print_mapbody cfg_print_mapbody

View File

@@ -1588,7 +1588,7 @@
./bin/tests/system/pipelined/ns3/named.args X 2014 ./bin/tests/system/pipelined/ns3/named.args X 2014
./bin/tests/system/pipelined/ns3/named.conf CONF-C 2014 ./bin/tests/system/pipelined/ns3/named.conf CONF-C 2014
./bin/tests/system/pipelined/ns4/named.conf CONF-C 2014 ./bin/tests/system/pipelined/ns4/named.conf CONF-C 2014
./bin/tests/system/pipelined/pipequeries.c C 2014 ./bin/tests/system/pipelined/pipequeries.c C 2014,2015
./bin/tests/system/pipelined/ref X 2014 ./bin/tests/system/pipelined/ref X 2014
./bin/tests/system/pipelined/refb X 2014 ./bin/tests/system/pipelined/refb X 2014
./bin/tests/system/pipelined/setup.sh SH 2014 ./bin/tests/system/pipelined/setup.sh SH 2014