2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 05:57:52 +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
queries. TCP connections are no longer closed after
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
filter-aaaa formerr forward geoip glue gost ixfr inline
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
rsabigexponent runtime sit sfcache smartsign sortlist spf
staticstub statistics stub tcp tkey tsig tsiggss unknown

View File

@ -17,3 +17,4 @@
rm -f */named.memstats
rm -f */named.run
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
* purpose with or without fee is hereby granted, provided that the above
@ -26,6 +26,7 @@
#include <isc/hash.h>
#include <isc/log.h>
#include <isc/mem.h>
#include <isc/net.h>
#include <isc/sockaddr.h>
#include <isc/socket.h>
#include <isc/task.h>
@ -61,7 +62,9 @@
static isc_mem_t *mctx;
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 void
@ -124,8 +127,7 @@ recvresponse(isc_task_t *task, isc_event_t *event) {
}
static isc_result_t
sendquery(isc_task_t *task)
{
sendquery(isc_task_t *task) {
dns_request_t *request;
dns_message_t *message;
dns_name_t *qname;
@ -175,18 +177,18 @@ sendquery(isc_task_t *task)
dns_message_addname(message, qname, DNS_SECTION_QUESTION);
request = NULL;
result = dns_request_create(requestmgr, message, &address,
DNS_REQUESTOPT_TCP, NULL,
TIMEOUT, task, recvresponse,
message, &request);
result = dns_request_createvia(requestmgr, message,
have_src ? &srcaddr : NULL, &dstaddr,
DNS_REQUESTOPT_TCP|DNS_REQUESTOPT_SHARE,
NULL, TIMEOUT, task, recvresponse,
message, &request);
CHECK("dns_request_create", result);
return ISC_R_SUCCESS;
}
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_event_free(&event);
@ -200,42 +202,44 @@ sendqueries(isc_task_t *task, isc_event_t *event)
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
main(int argc, char *argv[])
{
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;
main(int argc, char *argv[]) {
isc_sockaddr_t bind_any;
struct in_addr inaddr;
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);
if (argc > 1)
have_src = ISC_TRUE;
RUNCHECK(isc_app_start());
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;
RUNCHECK(isc_mem_create(0, 0, &mctx));
@ -261,14 +265,7 @@ main(int argc, char *argv[])
RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
dispatchmgr = NULL;
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 |
DNS_DISPATCHATTR_MAKEQUERY |
DNS_DISPATCHATTR_IPV4;
@ -278,8 +275,9 @@ main(int argc, char *argv[])
DNS_DISPATCHATTR_IPV6;
dispatchv4 = NULL;
RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
&bind_addr, 4096, 4, 2, 3, 5,
attrs, attrmask, &dispatchv4));
have_src ? &srcaddr : &bind_any,
4096, 4, 2, 3, 5,
attrs, attrmask, &dispatchv4));
requestmgr = NULL;
RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
dispatchmgr, dispatchv4, NULL,
@ -288,31 +286,7 @@ main(int argc, char *argv[])
view = NULL;
RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
sock = 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);
RUNCHECK(isc_app_onrun(mctx, task, sendqueries, NULL));
(void)isc_app_run();
@ -322,7 +296,6 @@ main(int argc, char *argv[])
dns_requestmgr_detach(&requestmgr);
dns_dispatch_detach(&dispatchv4);
dns_dispatch_detach(&tcpdispatch);
dns_dispatchmgr_destroy(&dispatchmgr);
isc_socketmgr_destroy(&socketmgr);

View File

@ -314,6 +314,9 @@ typedef __int64 off_t;
/* Define to the flags type used by getnameinfo(3). */
#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.
*/
@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);
}
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
dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
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]);
LOCK(&disp->lock);
disp->attributes |= DNS_DISPATCHATTR_CONNECTED;
(void)startrecv(disp, NULL);
if ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) == 0) {
disp->attributes |= DNS_DISPATCHATTR_CONNECTED;
(void)startrecv(disp, NULL);
}
UNLOCK(&disp->lock);
}

View File

@ -383,8 +383,13 @@ dns_dispatch_starttcp(dns_dispatch_t *disp);
isc_result_t
dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, isc_sockaddr_t *destaddr,
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_CASE 0x00000002U
#define DNS_REQUESTOPT_FIXEDID 0x00000004U
#define DNS_REQUESTOPT_SHARE 0x00000008U
typedef 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:
*
*\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.
*
*\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:
*
*\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
* 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:
*
*\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
* 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
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 *destaddr, isc_dscp_t dscp,
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;
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,
srcaddr, dispatchp);
if (result == ISC_R_SUCCESS) {
@ -642,7 +656,7 @@ find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
}
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,
isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
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;
if (tcp)
result = create_tcp_dispatch(newtcp, requestmgr, srcaddr,
destaddr, dscp, connected,
dispatchp);
result = create_tcp_dispatch(newtcp, share, requestmgr,
srcaddr, destaddr, dscp,
connected, dispatchp);
else
result = find_udp_dispatch(requestmgr, srcaddr,
destaddr, dispatchp);
@ -740,6 +754,7 @@ dns_request_createraw4(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
dns_messageid_t id;
isc_boolean_t tcp = ISC_FALSE;
isc_boolean_t newtcp = ISC_FALSE;
isc_boolean_t share = ISC_FALSE;
isc_region_t r;
isc_boolean_t connected = ISC_FALSE;
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)
tcp = ISC_TRUE;
share = ISC_TF((options & DNS_REQUESTOPT_SHARE) != 0);
again:
result = get_dispatch(tcp, newtcp, requestmgr, srcaddr, destaddr, dscp,
result = get_dispatch(tcp, newtcp, share, requestmgr,
srcaddr, destaddr, dscp,
&connected, &request->dispatch);
if (result != ISC_R_SUCCESS)
goto cleanup;
@ -971,6 +988,7 @@ dns_request_createvia4(dns_requestmgr_t *requestmgr, dns_message_t *message,
isc_mem_t *mctx;
dns_messageid_t id;
isc_boolean_t tcp;
isc_boolean_t share;
isc_boolean_t setkey = ISC_TRUE;
isc_boolean_t connected = ISC_FALSE;
@ -1031,7 +1049,9 @@ dns_request_createvia4(dns_requestmgr_t *requestmgr, dns_message_t *message,
use_tcp:
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);
if (result != ISC_R_SUCCESS)
goto cleanup;

View File

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

View File

@ -347,7 +347,7 @@ struct isc__socket {
ISC_LIST(isc_socketevent_t) send_list;
ISC_LIST(isc_socketevent_t) recv_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
@ -471,6 +471,7 @@ static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf,
isc_socket_t *dup_socket);
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_connectdone_event(isc__socket_t *, isc_socket_connev_t **);
static void free_socket(isc__socket_t **);
static isc_result_t allocate_socket(isc__socketmgr_t *, isc_sockettype_t,
isc__socket_t **);
@ -2216,10 +2217,10 @@ destroy(isc__socket_t **sockp) {
socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_DESTROYING, "destroying");
INSIST(ISC_LIST_EMPTY(sock->connect_list));
INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(ISC_LIST_EMPTY(sock->recv_list));
INSIST(ISC_LIST_EMPTY(sock->send_list));
INSIST(sock->connect_ev == NULL);
REQUIRE(sock->fd == -1 || sock->fd < (int)manager->maxsocks);
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->send_list);
ISC_LIST_INIT(sock->accept_list);
sock->connect_ev = NULL;
ISC_LIST_INIT(sock->connect_list);
sock->pending_recv = 0;
sock->pending_send = 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->send_list));
INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(ISC_LIST_EMPTY(sock->connect_list));
INSIST(!ISC_LINK_LINKED(sock, link));
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->send_list));
INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(sock->connect_ev == NULL);
INSIST(ISC_LIST_EMPTY(sock->connect_list));
manager = sock->manager;
fd = sock->fd;
@ -3356,7 +3358,7 @@ dispatch_connect(isc__socket_t *sock) {
iev = &sock->writable_ev;
ev = sock->connect_ev;
ev = ISC_LIST_HEAD(sock->connect_list);
INSIST(ev != NULL); /* XXX */
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);
}
/*
* 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
* 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);
REQUIRE(!sock->connecting);
dev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
ISC_SOCKEVENT_CONNECT,
action, arg,
@ -5694,6 +5714,11 @@ isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr,
}
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
* 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);
sock->connecting = 1;
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
* 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);
sock->connect_ev = dev;
sock->connecting = 1;
ISC_LIST_ENQUEUE(sock->connect_list, dev, ev_link);
UNLOCK(&sock->lock);
return (ISC_R_SUCCESS);
@ -5805,8 +5830,8 @@ static void
internal_connect(isc_task_t *me, isc_event_t *ev) {
isc__socket_t *sock;
isc_socket_connev_t *dev;
isc_task_t *task;
int cc;
isc_result_t result;
ISC_SOCKADDR_LEN_T optlen;
char strbuf[ISC_STRERRORSIZE];
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) {
INSIST(!sock->connecting);
UNLOCK(&sock->lock);
@ -5875,7 +5901,7 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
* Translate other errors into ISC_R_* flavors.
*/
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(EADDRNOTAVAIL, 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);
#undef ERROR_MATCH
default:
dev->result = ISC_R_UNEXPECTED;
result = ISC_R_UNEXPECTED;
isc_sockaddr_format(&sock->peer_address, peerbuf,
sizeof(peerbuf));
isc__strerror(errno, strbuf, sizeof(strbuf));
@ -5903,18 +5929,18 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
} else {
inc_stats(sock->manager->stats,
sock->statsindex[STATID_CONNECT]);
dev->result = ISC_R_SUCCESS;
result = ISC_R_SUCCESS;
sock->connected = 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);
task = dev->ev_sender;
dev->ev_sender = sock;
isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
}
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)
&& sock->connect_ev != NULL) {
&& !ISC_LIST_EMPTY(sock->connect_list)) {
isc_socket_connev_t *dev;
isc_socket_connev_t *next;
isc_task_t *current_task;
INSIST(sock->connecting);
sock->connecting = 0;
dev = sock->connect_ev;
current_task = dev->ev_sender;
dev = ISC_LIST_HEAD(sock->connect_list);
if ((task == NULL) || (task == current_task)) {
sock->connect_ev = NULL;
while (dev != NULL) {
current_task = dev->ev_sender;
next = ISC_LIST_NEXT(dev, ev_link);
dev->result = ISC_R_CANCELED;
dev->ev_sender = sock;
isc_task_sendanddetach(&current_task,
ISC_EVENT_PTR(&dev));
if ((task == NULL) || (task == current_task)) {
dev->result = ISC_R_CANCELED;
send_connectdone_event(sock, &dev);
}
dev = next;
}
}

View File

@ -483,9 +483,6 @@ isc_portset_isset
isc_portset_nports
isc_portset_remove
isc_portset_removerange
isc_print_snprintf
isc_print_sprintf
isc_print_vsnprintf
isc_quota_attach
isc_quota_destroy
isc_quota_detach
@ -583,42 +580,8 @@ isc_sockaddr_pf
isc_sockaddr_setport
isc_sockaddr_totext
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_socketmgr_create
isc_socketmgr_create2
isc_socketmgr_createinctx
isc_socketmgr_destroy
@IF LIBXML2
isc_socketmgr_renderxml
@END LIBXML2

View File

@ -266,7 +266,7 @@ struct isc_socket {
ISC_LIST(isc_socketevent_t) send_list;
ISC_LIST(isc_socketevent_t) recv_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 */
@ -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_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_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_request(isc_socket_t *sock);
@ -388,6 +389,7 @@ void
sock_dump(isc_socket_t *sock) {
isc_socketevent_t *ldev;
isc_socket_newconnev_t *ndev;
isc_socket_connev_t *cdev;
#if 0
isc_sockaddr_t addr;
@ -436,6 +438,13 @@ sock_dump(isc_socket_t *sock) {
printf("\t\tdev: %p\n", ldev);
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
@ -1486,7 +1495,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
ISC_LIST_INIT(sock->recv_list);
ISC_LIST_INIT(sock->send_list);
ISC_LIST_INIT(sock->accept_list);
sock->connect_ev = NULL;
ISC_LIST_INIT(sock->connect_list);
sock->pending_accept = 0;
sock->pending_recv = 0;
sock->pending_send = 0;
@ -1565,7 +1574,7 @@ consistent(isc_socket_t *sock) {
}
if (count > sock->pending_accept) {
crash = ISC_TRUE;
crash_reason = "send_list > sock->pending_send";
crash_reason = "accept_list > sock->pending_accept";
}
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->send_list)
|| !ISC_LIST_EMPTY(sock->accept_list)
|| !ISC_LIST_EMPTY(sock->connect_list)
|| sock->fd != INVALID_SOCKET) {
UNLOCK(&sock->lock);
return;
@ -2030,7 +2040,8 @@ send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev) {
task = (*cdev)->ev_sender;
(*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);
@ -2148,6 +2159,7 @@ done:
static void
internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
isc_socket_connev_t *cdev;
isc_result_t result;
char strbuf[ISC_STRERRORSIZE];
INSIST(VALID_SOCKET(sock));
@ -2160,7 +2172,7 @@ internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
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;
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.
*/
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(WSAEADDRNOTAVAIL, 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);
#undef ERROR_MATCH
default:
cdev->result = ISC_R_UNEXPECTED;
result = ISC_R_UNEXPECTED;
isc__strerror(connect_errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"internal_connect: connect() %s",
@ -2219,14 +2231,18 @@ internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
} else {
INSIST(setsockopt(sock->fd, SOL_SOCKET,
SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0);
cdev->result = ISC_R_SUCCESS;
result = ISC_R_SUCCESS;
sock->connected = 1;
socket_log(__LINE__, sock, &sock->address, IOEVENT,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
"internal_connect: success");
}
send_connectdone_event(sock, &cdev);
do {
cdev->result = result;
send_connectdone_event(sock, &cdev);
cdev = ISC_LIST_HEAD(sock->connect_list);
} while (cdev != NULL);
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
* 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
* the one we're waiting for. Using these ensures we will not double-send an
* event.
* These return if the done event passed in is on the list.
* Using these ensures we will not double-send an event.
*/
static isc_boolean_t
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
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);
sock->pending_connect = 0;
if (connectdone_is_active(sock, lpo->cdev)) {
lpo->cdev->result = isc_result;
socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
"canceled_connect");
send_connectdone_event(sock, &lpo->cdev);
send_connectdone_abort(sock, isc_result);
}
break;
}
@ -3535,8 +3569,6 @@ isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
sock->bound = 1;
}
REQUIRE(!sock->pending_connect);
cdev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
ISC_SOCKEVENT_CONNECT,
action, arg,
@ -3547,7 +3579,7 @@ isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
}
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().
*/
@ -3573,9 +3605,17 @@ isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
/*
* 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++;
} 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 {
REQUIRE(!sock->pending_connect);
WSAConnect(sock->fd, &addr->type.sa, addr->length, NULL, NULL, NULL, NULL);
cdev->result = ISC_R_SUCCESS;
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;
/*
* Connecting is not a list.
*/
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 *next;
isc_task_t *current_task;
INSIST(sock->pending_connect);
dev = sock->connect_ev;
current_task = dev->ev_sender;
dev = ISC_LIST_HEAD(sock->connect_list);
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;
send_connectdone_event(sock, &dev);
while (dev != NULL) {
current_task = dev->ev_sender;
next = ISC_LIST_NEXT(dev, ev_link);
if ((task == NULL) || (task == current_task)) {
dev->result = ISC_R_CANCELED;
send_connectdone_event(sock, &dev);
}
dev = next;
}
closesocket(sock->fd);
sock->fd = INVALID_SOCKET;
_set_state(sock, SOCK_CLOSED);
}
how &= ~ISC_SOCKCANCEL_CONNECT;

View File

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

View File

@ -1588,7 +1588,7 @@
./bin/tests/system/pipelined/ns3/named.args X 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/pipequeries.c C 2014
./bin/tests/system/pipelined/pipequeries.c C 2014,2015
./bin/tests/system/pipelined/ref X 2014
./bin/tests/system/pipelined/refb X 2014
./bin/tests/system/pipelined/setup.sh SH 2014