mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
3137. [func] Improve hardware scalability by allowing multiple
worker threads to process incoming UDP packets. This can significantly increase query throughput on some systems. [RT #22992]
This commit is contained in:
parent
8181aa6228
commit
f07b2fccaf
5
CHANGES
5
CHANGES
@ -1,3 +1,8 @@
|
||||
3137. [func] Improve hardware scalability by allowing multiple
|
||||
worker threads to process incoming UDP packets.
|
||||
This can significantly increase query throughput
|
||||
on some systems. [RT #22992]
|
||||
|
||||
3136. [func] Add RFC 1918 reverse zones to the list of built-in
|
||||
empty zones switched on by the 'empty-zones-enable'
|
||||
option. [RT #24990]
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: client.c,v 1.273 2011/05/05 23:44:52 marka Exp $ */
|
||||
/* $Id: client.c,v 1.274 2011/07/28 04:04:36 each Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@ -2530,8 +2530,10 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
|
||||
ns_interface_t *ifp, isc_boolean_t tcp)
|
||||
{
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_boolean_t success = ISC_FALSE;
|
||||
unsigned int i;
|
||||
ns_client_t *client;
|
||||
unsigned int disp;
|
||||
|
||||
REQUIRE(VALID_MANAGER(manager));
|
||||
REQUIRE(n > 0);
|
||||
@ -2546,61 +2548,68 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
|
||||
|
||||
LOCK(&manager->lock);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
isc_event_t *ev;
|
||||
/*
|
||||
* Allocate a client. First try to get a recycled one;
|
||||
* if that fails, make a new one.
|
||||
*/
|
||||
client = NULL;
|
||||
if (!ns_g_clienttest)
|
||||
client = ISC_LIST_HEAD(manager->inactive);
|
||||
if (client != NULL) {
|
||||
MTRACE("recycle");
|
||||
ISC_LIST_UNLINK(manager->inactive, client, link);
|
||||
client->list = NULL;
|
||||
} else {
|
||||
MTRACE("create new");
|
||||
result = client_create(manager, &client);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
for (disp = 0; disp < n; disp++) {
|
||||
for (i = 0; i < n; i++) {
|
||||
isc_event_t *ev;
|
||||
|
||||
/*
|
||||
* Allocate a client. First try to get a recycled one;
|
||||
* if that fails, make a new one.
|
||||
*/
|
||||
client = NULL;
|
||||
if (!ns_g_clienttest)
|
||||
client = ISC_LIST_HEAD(manager->inactive);
|
||||
if (client != NULL) {
|
||||
MTRACE("recycle");
|
||||
ISC_LIST_UNLINK(manager->inactive, client,
|
||||
link);
|
||||
client->list = NULL;
|
||||
} else {
|
||||
MTRACE("create new");
|
||||
result = client_create(manager, &client);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
ns_interface_attach(ifp, &client->interface);
|
||||
client->state = NS_CLIENTSTATE_READY;
|
||||
INSIST(client->recursionquota == NULL);
|
||||
|
||||
if (tcp) {
|
||||
client->attributes |= NS_CLIENTATTR_TCP;
|
||||
isc_socket_attach(ifp->tcpsocket,
|
||||
&client->tcplistener);
|
||||
} else {
|
||||
isc_socket_t *sock;
|
||||
|
||||
dns_dispatch_attach(ifp->udpdispatch[disp],
|
||||
&client->dispatch);
|
||||
sock = dns_dispatch_getsocket(client->dispatch);
|
||||
isc_socket_attach(sock, &client->udpsocket);
|
||||
}
|
||||
|
||||
client->manager = manager;
|
||||
ISC_LIST_APPEND(manager->active, client, link);
|
||||
client->list = &manager->active;
|
||||
|
||||
INSIST(client->nctls == 0);
|
||||
client->nctls++;
|
||||
ev = &client->ctlevent;
|
||||
isc_task_send(client->task, &ev);
|
||||
|
||||
success = ISC_TRUE;
|
||||
}
|
||||
|
||||
ns_interface_attach(ifp, &client->interface);
|
||||
client->state = NS_CLIENTSTATE_READY;
|
||||
INSIST(client->recursionquota == NULL);
|
||||
|
||||
if (tcp) {
|
||||
client->attributes |= NS_CLIENTATTR_TCP;
|
||||
isc_socket_attach(ifp->tcpsocket,
|
||||
&client->tcplistener);
|
||||
} else {
|
||||
isc_socket_t *sock;
|
||||
|
||||
dns_dispatch_attach(ifp->udpdispatch,
|
||||
&client->dispatch);
|
||||
sock = dns_dispatch_getsocket(client->dispatch);
|
||||
isc_socket_attach(sock, &client->udpsocket);
|
||||
}
|
||||
client->manager = manager;
|
||||
ISC_LIST_APPEND(manager->active, client, link);
|
||||
client->list = &manager->active;
|
||||
|
||||
INSIST(client->nctls == 0);
|
||||
client->nctls++;
|
||||
ev = &client->ctlevent;
|
||||
isc_task_send(client->task, &ev);
|
||||
}
|
||||
if (i != 0) {
|
||||
/*
|
||||
* We managed to create at least one client, so we
|
||||
* declare victory.
|
||||
*/
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
UNLOCK(&manager->lock);
|
||||
|
||||
/*
|
||||
* If managed to create at least one client for
|
||||
* one dispatch, we declare victory.
|
||||
*/
|
||||
if (success)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: interfacemgr.h,v 1.33 2007/06/19 23:46:59 tbox Exp $ */
|
||||
/* $Id: interfacemgr.h,v 1.34 2011/07/28 04:04:36 each Exp $ */
|
||||
|
||||
#ifndef NAMED_INTERFACEMGR_H
|
||||
#define NAMED_INTERFACEMGR_H 1
|
||||
@ -65,7 +65,8 @@
|
||||
#define NS_INTERFACE_VALID(t) ISC_MAGIC_VALID(t, IFACE_MAGIC)
|
||||
|
||||
#define NS_INTERFACEFLAG_ANYADDR 0x01U /*%< bound to "any" address */
|
||||
|
||||
#define MAX_UDP_DISPATCH 128 /*%< Maximum number of UDP dispatchers
|
||||
to start per interface */
|
||||
/*% The nameserver interface structure */
|
||||
struct ns_interface {
|
||||
unsigned int magic; /*%< Magic number. */
|
||||
@ -76,11 +77,13 @@ struct ns_interface {
|
||||
isc_sockaddr_t addr; /*%< Address and port. */
|
||||
unsigned int flags; /*%< Interface characteristics */
|
||||
char name[32]; /*%< Null terminated. */
|
||||
dns_dispatch_t * udpdispatch; /*%< UDP dispatcher. */
|
||||
dns_dispatch_t * udpdispatch[MAX_UDP_DISPATCH];
|
||||
/*%< UDP dispatchers. */
|
||||
isc_socket_t * tcpsocket; /*%< TCP socket. */
|
||||
int ntcptarget; /*%< Desired number of concurrent
|
||||
TCP accepts */
|
||||
int ntcpcurrent; /*%< Current ditto, locked */
|
||||
int nudpdispatch; /*%< Number of UDP dispatches */
|
||||
ns_clientmgr_t * clientmgr; /*%< Client manager. */
|
||||
ISC_LINK(ns_interface_t) link;
|
||||
};
|
||||
|
@ -15,13 +15,14 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: interfacemgr.c,v 1.97 2011/03/12 04:59:46 tbox Exp $ */
|
||||
/* $Id: interfacemgr.c,v 1.98 2011/07/28 04:04:36 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <isc/interfaceiter.h>
|
||||
#include <isc/os.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/util.h>
|
||||
@ -195,6 +196,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
strncpy(ifp->name, name, sizeof(ifp->name));
|
||||
ifp->name[sizeof(ifp->name)-1] = '\0';
|
||||
ifp->clientmgr = NULL;
|
||||
int disp;
|
||||
|
||||
result = isc_mutex_init(&ifp->lock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
@ -210,7 +212,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
goto clientmgr_create_failure;
|
||||
}
|
||||
|
||||
ifp->udpdispatch = NULL;
|
||||
for (disp = 0; disp < MAX_UDP_DISPATCH; disp++)
|
||||
ifp->udpdispatch[disp] = NULL;
|
||||
|
||||
ifp->tcpsocket = NULL;
|
||||
/*
|
||||
@ -221,6 +224,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
*/
|
||||
ifp->ntcptarget = 1;
|
||||
ifp->ntcpcurrent = 0;
|
||||
ifp->nudpdispatch = 0;
|
||||
|
||||
ISC_LINK_INIT(ifp, link);
|
||||
|
||||
@ -247,6 +251,7 @@ ns_interface_listenudp(ns_interface_t *ifp) {
|
||||
isc_result_t result;
|
||||
unsigned int attrs;
|
||||
unsigned int attrmask;
|
||||
int disp, i;
|
||||
|
||||
attrs = 0;
|
||||
attrs |= DNS_DISPATCHATTR_UDP;
|
||||
@ -258,15 +263,25 @@ ns_interface_listenudp(ns_interface_t *ifp) {
|
||||
attrmask = 0;
|
||||
attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
|
||||
attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
|
||||
result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr,
|
||||
ns_g_taskmgr, &ifp->addr,
|
||||
4096, 1000, 32768, 8219, 8237,
|
||||
attrs, attrmask, &ifp->udpdispatch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"could not listen on UDP socket: %s",
|
||||
isc_result_totext(result));
|
||||
goto udp_dispatch_failure;
|
||||
|
||||
ifp->nudpdispatch = ISC_MIN(isc_os_ncpus(), MAX_UDP_DISPATCH);
|
||||
for (disp = 0; disp < ifp->nudpdispatch; disp++) {
|
||||
result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr,
|
||||
ns_g_socketmgr,
|
||||
ns_g_taskmgr, &ifp->addr,
|
||||
4096, 1000, 32768, 8219, 8237,
|
||||
attrs, attrmask,
|
||||
&ifp->udpdispatch[disp],
|
||||
disp == 0
|
||||
? NULL
|
||||
: ifp->udpdispatch[0]);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"could not listen on UDP socket: %s",
|
||||
isc_result_totext(result));
|
||||
goto udp_dispatch_failure;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus,
|
||||
@ -277,12 +292,17 @@ ns_interface_listenudp(ns_interface_t *ifp) {
|
||||
isc_result_totext(result));
|
||||
goto addtodispatch_failure;
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
addtodispatch_failure:
|
||||
dns_dispatch_changeattributes(ifp->udpdispatch, 0,
|
||||
DNS_DISPATCHATTR_NOLISTEN);
|
||||
dns_dispatch_detach(&ifp->udpdispatch);
|
||||
for (i = disp - 1; i <= 0; i--) {
|
||||
dns_dispatch_changeattributes(ifp->udpdispatch[i], 0,
|
||||
DNS_DISPATCHATTR_NOLISTEN);
|
||||
dns_dispatch_detach(&(ifp->udpdispatch[i]));
|
||||
}
|
||||
ifp->nudpdispatch = 0;
|
||||
|
||||
udp_dispatch_failure:
|
||||
return (result);
|
||||
}
|
||||
@ -397,14 +417,16 @@ static void
|
||||
ns_interface_destroy(ns_interface_t *ifp) {
|
||||
isc_mem_t *mctx = ifp->mgr->mctx;
|
||||
REQUIRE(NS_INTERFACE_VALID(ifp));
|
||||
int disp;
|
||||
|
||||
ns_interface_shutdown(ifp);
|
||||
|
||||
if (ifp->udpdispatch != NULL) {
|
||||
dns_dispatch_changeattributes(ifp->udpdispatch, 0,
|
||||
DNS_DISPATCHATTR_NOLISTEN);
|
||||
dns_dispatch_detach(&ifp->udpdispatch);
|
||||
}
|
||||
for (disp = ifp->nudpdispatch; disp >= 0; disp--)
|
||||
if (ifp->udpdispatch[disp] != NULL) {
|
||||
dns_dispatch_changeattributes(ifp->udpdispatch[disp], 0,
|
||||
DNS_DISPATCHATTR_NOLISTEN);
|
||||
dns_dispatch_detach(&(ifp->udpdispatch[disp]));
|
||||
}
|
||||
if (ifp->tcpsocket != NULL)
|
||||
isc_socket_detach(&ifp->tcpsocket);
|
||||
|
||||
|
@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl
|
||||
esyscmd([sed "s/^/# /" COPYRIGHT])dnl
|
||||
AC_DIVERT_POP()dnl
|
||||
|
||||
AC_REVISION($Revision: 1.528 $)
|
||||
AC_REVISION($Revision: 1.529 $)
|
||||
|
||||
AC_INIT(lib/dns/name.c)
|
||||
AC_PREREQ(2.59)
|
||||
@ -2552,7 +2552,7 @@ yes)
|
||||
esac
|
||||
AC_SUBST(ISC_PLATFORM_HAVEIFNAMETOINDEX)
|
||||
|
||||
AC_CHECK_FUNCS(nanosleep)
|
||||
AC_CHECK_FUNCS(nanosleep usleep)
|
||||
|
||||
#
|
||||
# Machine architecture dependent features
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: dispatch.c,v 1.172 2011/04/06 10:27:16 marka Exp $ */
|
||||
/* $Id: dispatch.c,v 1.173 2011/07/28 04:04:36 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@ -312,14 +312,16 @@ static isc_result_t get_udpsocket(dns_dispatchmgr_t *mgr,
|
||||
dns_dispatch_t *disp,
|
||||
isc_socketmgr_t *sockmgr,
|
||||
isc_sockaddr_t *localaddr,
|
||||
isc_socket_t **sockp);
|
||||
isc_socket_t **sockp,
|
||||
isc_socket_t *dup_socket);
|
||||
static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
|
||||
isc_socketmgr_t *sockmgr,
|
||||
isc_taskmgr_t *taskmgr,
|
||||
isc_sockaddr_t *localaddr,
|
||||
unsigned int maxrequests,
|
||||
unsigned int attributes,
|
||||
dns_dispatch_t **dispp);
|
||||
dns_dispatch_t **dispp,
|
||||
isc_socket_t *dup_socket);
|
||||
static isc_boolean_t destroy_mgr_ok(dns_dispatchmgr_t *mgr);
|
||||
static void destroy_mgr(dns_dispatchmgr_t **mgrp);
|
||||
static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
|
||||
@ -327,7 +329,8 @@ static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
|
||||
isc_boolean_t needaddrtable);
|
||||
static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
|
||||
static isc_result_t open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
|
||||
unsigned int options, isc_socket_t **sockp);
|
||||
unsigned int options, isc_socket_t **sockp,
|
||||
isc_socket_t *dup_socket);
|
||||
static isc_boolean_t portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
||||
isc_sockaddr_t *sockaddrp);
|
||||
|
||||
@ -902,7 +905,8 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
|
||||
portentry = port_search(disp, port);
|
||||
if (portentry != NULL)
|
||||
bindoptions |= ISC_SOCKET_REUSEADDRESS;
|
||||
result = open_socket(sockmgr, &localaddr, bindoptions, &sock);
|
||||
result = open_socket(sockmgr, &localaddr, bindoptions, &sock,
|
||||
NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (portentry == NULL) {
|
||||
portentry = new_portentry(disp, port);
|
||||
@ -1787,19 +1791,14 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
|
||||
|
||||
static isc_result_t
|
||||
open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
|
||||
unsigned int options, isc_socket_t **sockp)
|
||||
unsigned int options, isc_socket_t **sockp,
|
||||
isc_socket_t *dup_socket)
|
||||
{
|
||||
isc_socket_t *sock;
|
||||
isc_result_t result;
|
||||
|
||||
sock = *sockp;
|
||||
if (sock == NULL) {
|
||||
result = isc_socket_create(mgr, isc_sockaddr_pf(local),
|
||||
isc_sockettype_udp, &sock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
isc_socket_setname(sock, "dispatcher", NULL);
|
||||
} else {
|
||||
if (sock != NULL) {
|
||||
#ifdef BIND9
|
||||
result = isc_socket_open(sock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
@ -1807,8 +1806,19 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
|
||||
#else
|
||||
INSIST(0);
|
||||
#endif
|
||||
} else if (dup_socket != NULL) {
|
||||
result = isc_socket_dup(dup_socket, &sock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
} else {
|
||||
result = isc_socket_create(mgr, isc_sockaddr_pf(local),
|
||||
isc_sockettype_udp, &sock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_socket_setname(sock, "dispatcher", NULL);
|
||||
|
||||
#ifndef ISC_ALLOW_MAPPED
|
||||
isc_socket_ipv6only(sock, ISC_TRUE);
|
||||
#endif
|
||||
@ -2646,13 +2656,13 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_dispatch_getudp(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,
|
||||
unsigned int buffersize,
|
||||
unsigned int maxbuffers, unsigned int maxrequests,
|
||||
unsigned int buckets, unsigned int increment,
|
||||
unsigned int attributes, unsigned int mask,
|
||||
dns_dispatch_t **dispp)
|
||||
dns_dispatch_t **dispp, dns_dispatch_t *dup_dispatch)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_dispatch_t *disp = NULL;
|
||||
@ -2683,28 +2693,31 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
/*
|
||||
* See if we have a dispatcher that matches.
|
||||
*/
|
||||
result = dispatch_find(mgr, localaddr, attributes, mask, &disp);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
disp->refcount++;
|
||||
if (dup_dispatch == NULL) {
|
||||
result = dispatch_find(mgr, localaddr, attributes, mask, &disp);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
disp->refcount++;
|
||||
|
||||
if (disp->maxrequests < maxrequests)
|
||||
disp->maxrequests = maxrequests;
|
||||
if (disp->maxrequests < maxrequests)
|
||||
disp->maxrequests = maxrequests;
|
||||
|
||||
if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0 &&
|
||||
(attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
|
||||
{
|
||||
disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
|
||||
if (disp->recv_pending != 0)
|
||||
isc_socket_cancel(disp->socket, disp->task[0],
|
||||
ISC_SOCKCANCEL_RECV);
|
||||
if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0
|
||||
&& (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
|
||||
{
|
||||
disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
|
||||
if (disp->recv_pending != 0)
|
||||
isc_socket_cancel(disp->socket,
|
||||
disp->task[0],
|
||||
ISC_SOCKCANCEL_RECV);
|
||||
}
|
||||
|
||||
UNLOCK(&disp->lock);
|
||||
UNLOCK(&mgr->lock);
|
||||
|
||||
*dispp = disp;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
UNLOCK(&disp->lock);
|
||||
UNLOCK(&mgr->lock);
|
||||
|
||||
*dispp = disp;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
createudp:
|
||||
@ -2712,7 +2725,11 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
* Nope, create one.
|
||||
*/
|
||||
result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr,
|
||||
maxrequests, attributes, &disp);
|
||||
maxrequests, attributes, &disp,
|
||||
dup_dispatch == NULL
|
||||
? NULL
|
||||
: dup_dispatch->socket);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
UNLOCK(&mgr->lock);
|
||||
return (result);
|
||||
@ -2720,9 +2737,24 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
|
||||
UNLOCK(&mgr->lock);
|
||||
*dispp = disp;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
|
||||
unsigned int buffersize,
|
||||
unsigned int maxbuffers, unsigned int maxrequests,
|
||||
unsigned int buckets, unsigned int increment,
|
||||
unsigned int attributes, unsigned int mask,
|
||||
dns_dispatch_t **dispp)
|
||||
{
|
||||
return dns_dispatch_getudp_dup(mgr, sockmgr, taskmgr, localaddr,
|
||||
buffersize, maxbuffers, maxrequests, buckets, increment,
|
||||
attributes, mask, dispp, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* mgr should be locked.
|
||||
*/
|
||||
@ -2734,7 +2766,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
static isc_result_t
|
||||
get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
|
||||
isc_socketmgr_t *sockmgr, isc_sockaddr_t *localaddr,
|
||||
isc_socket_t **sockp)
|
||||
isc_socket_t **sockp, isc_socket_t *dup_socket)
|
||||
{
|
||||
unsigned int i, j;
|
||||
isc_socket_t *held[DNS_DISPATCH_HELD];
|
||||
@ -2774,7 +2806,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
|
||||
nports)];
|
||||
isc_sockaddr_setport(&localaddr_bound, prt);
|
||||
result = open_socket(sockmgr, &localaddr_bound,
|
||||
0, &sock);
|
||||
0, &sock, NULL);
|
||||
if (result == ISC_R_SUCCESS ||
|
||||
result != ISC_R_ADDRINUSE) {
|
||||
disp->localport = prt;
|
||||
@ -2790,7 +2822,8 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
|
||||
} else {
|
||||
/* Allow to reuse address for non-random ports. */
|
||||
result = open_socket(sockmgr, localaddr,
|
||||
ISC_SOCKET_REUSEADDRESS, &sock);
|
||||
ISC_SOCKET_REUSEADDRESS, &sock,
|
||||
dup_socket);
|
||||
|
||||
if (result == ISC_R_SUCCESS)
|
||||
*sockp = sock;
|
||||
@ -2802,7 +2835,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
|
||||
i = 0;
|
||||
|
||||
for (j = 0; j < 0xffffU; j++) {
|
||||
result = open_socket(sockmgr, localaddr, 0, &sock);
|
||||
result = open_socket(sockmgr, localaddr, 0, &sock, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto end;
|
||||
else if (!anyport)
|
||||
@ -2841,7 +2874,8 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
isc_sockaddr_t *localaddr,
|
||||
unsigned int maxrequests,
|
||||
unsigned int attributes,
|
||||
dns_dispatch_t **dispp)
|
||||
dns_dispatch_t **dispp,
|
||||
isc_socket_t *dup_socket)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_dispatch_t *disp;
|
||||
@ -2857,9 +2891,21 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
return (result);
|
||||
|
||||
if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) {
|
||||
result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock);
|
||||
result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock,
|
||||
dup_socket);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto deallocate_dispatch;
|
||||
|
||||
if (isc_log_wouldlog(dns_lctx, 90)) {
|
||||
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
|
||||
isc_sockaddr_format(localaddr, addrbuf,
|
||||
ISC_SOCKADDR_FORMATSIZE);
|
||||
mgr_log(mgr, LVL(90), "dns_dispatch_createudp: Created"
|
||||
" UDP dispatch for %s with socket fd %d\n",
|
||||
addrbuf, isc_socket_getfd(sock));
|
||||
}
|
||||
|
||||
} else {
|
||||
isc_sockaddr_t sa_any;
|
||||
|
||||
@ -2871,7 +2917,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
*/
|
||||
isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
|
||||
if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
|
||||
result = open_socket(sockmgr, localaddr, 0, &sock);
|
||||
result = open_socket(sockmgr, localaddr, 0, &sock, NULL);
|
||||
if (sock != NULL)
|
||||
isc_socket_detach(&sock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
@ -2938,6 +2984,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
dispatch_log(disp, LVL(90), "created socket %p", disp->socket);
|
||||
|
||||
*dispp = disp;
|
||||
|
||||
return (result);
|
||||
|
||||
/*
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: dispatch.h,v 1.62 2009/01/27 23:47:54 tbox Exp $ */
|
||||
/* $Id: dispatch.h,v 1.63 2011/07/28 04:04:37 each Exp $ */
|
||||
|
||||
#ifndef DNS_DISPATCH_H
|
||||
#define DNS_DISPATCH_H 1
|
||||
@ -245,6 +245,15 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
unsigned int buckets, unsigned int increment,
|
||||
unsigned int attributes, unsigned int mask,
|
||||
dns_dispatch_t **dispp);
|
||||
|
||||
isc_result_t
|
||||
dns_dispatch_getudp_dup(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
|
||||
unsigned int buffersize,
|
||||
unsigned int maxbuffers, unsigned int maxrequests,
|
||||
unsigned int buckets, unsigned int increment,
|
||||
unsigned int attributes, unsigned int mask,
|
||||
dns_dispatch_t **dispp, dns_dispatch_t *dup);
|
||||
/*%<
|
||||
* Attach to existing dns_dispatch_t if one is found with dns_dispatchmgr_find,
|
||||
* otherwise create a new UDP dispatch.
|
||||
|
@ -14,7 +14,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: namespace.h,v 1.9 2010/12/04 13:25:59 marka Exp $ */
|
||||
/* $Id: namespace.h,v 1.10 2011/07/28 04:04:37 each Exp $ */
|
||||
|
||||
#ifndef ISCAPI_NAMESPACE_H
|
||||
#define ISCAPI_NAMESPACE_H 1
|
||||
@ -88,6 +88,7 @@
|
||||
#define isc_mempool_getfillcount isc__mempool_getfillcount
|
||||
|
||||
#define isc_socket_create isc__socket_create
|
||||
#define isc_socket_dup isc__socket_dup
|
||||
#define isc_socket_attach isc__socket_attach
|
||||
#define isc_socket_detach isc__socket_detach
|
||||
#define isc_socketmgr_create isc__socketmgr_create
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: socket.h,v 1.94 2009/10/01 01:30:01 sar Exp $ */
|
||||
/* $Id: socket.h,v 1.95 2011/07/28 04:04:37 each Exp $ */
|
||||
|
||||
#ifndef ISC_SOCKET_H
|
||||
#define ISC_SOCKET_H 1
|
||||
@ -449,6 +449,12 @@ isc_socket_create(isc_socketmgr_t *manager,
|
||||
*\li #ISC_R_UNEXPECTED
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_socket_dup(isc_socket_t *sock0, isc_socket_t **socketp);
|
||||
/*%<
|
||||
* Duplicate an existing socket, reusing its file descriptor.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_socket_cancel(isc_socket_t *sock, isc_task_t *task,
|
||||
unsigned int how);
|
||||
@ -1102,6 +1108,11 @@ void *isc_socket_gettag(isc_socket_t *socket);
|
||||
* Get the tag associated with a socket, if any.
|
||||
*/
|
||||
|
||||
int isc_socket_getfd(isc_socket_t *socket);
|
||||
/*%<
|
||||
* Get the file descriptor associated with a socket
|
||||
*/
|
||||
|
||||
void
|
||||
isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t);
|
||||
/*%<
|
||||
|
@ -12,7 +12,7 @@
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# $Id: Makefile.in,v 1.2 2011/07/06 05:05:51 each Exp $
|
||||
# $Id: Makefile.in,v 1.3 2011/07/28 04:04:37 each Exp $
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
@ -35,10 +35,10 @@ ISCDEPLIBS = ../libisc.@A@
|
||||
LIBS = @LIBS@ @ATFLIBS@
|
||||
|
||||
OBJS = isctest.@O@
|
||||
SRCS = isctest.c taskpool_test.c
|
||||
SRCS = isctest.c taskpool_test.c socket_test.c
|
||||
|
||||
SUBDIRS =
|
||||
TARGETS = taskpool_test@EXEEXT@
|
||||
TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@
|
||||
|
||||
@BIND9_MAKE_RULES@
|
||||
|
||||
@ -46,5 +46,9 @@ taskpool_test@EXEEXT@: taskpool_test.@O@ isctest.@O@ ${ISCDEPLIBS}
|
||||
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
|
||||
taskpool_test.@O@ isctest.@O@ ${ISCLIBS} ${LIBS}
|
||||
|
||||
socket_test@EXEEXT@: socket_test.@O@ isctest.@O@ ${ISCDEPLIBS}
|
||||
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
|
||||
socket_test.@O@ isctest.@O@ ${ISCLIBS} ${LIBS}
|
||||
|
||||
clean distclean::
|
||||
rm -f ${TARGETS}
|
||||
|
@ -14,7 +14,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: isctest.c,v 1.2 2011/07/06 05:05:52 each Exp $ */
|
||||
/* $Id: isctest.c,v 1.3 2011/07/28 04:04:37 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@ -26,7 +26,10 @@
|
||||
#include <isc/hash.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/os.h>
|
||||
#include <isc/socket.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/task.h>
|
||||
#include <isc/timer.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include "isctest.h"
|
||||
@ -35,6 +38,8 @@ isc_mem_t *mctx = NULL;
|
||||
isc_entropy_t *ectx = NULL;
|
||||
isc_log_t *lctx = NULL;
|
||||
isc_taskmgr_t *taskmgr = NULL;
|
||||
isc_timermgr_t *timermgr = NULL;
|
||||
isc_socketmgr_t *socketmgr = NULL;
|
||||
int ncpus;
|
||||
|
||||
static isc_boolean_t hash_active = ISC_FALSE;
|
||||
@ -54,8 +59,37 @@ static isc_logcategory_t categories[] = {
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static void
|
||||
cleanup_managers() {
|
||||
if (socketmgr != NULL)
|
||||
isc_socketmgr_destroy(&socketmgr);
|
||||
if (taskmgr != NULL)
|
||||
isc_taskmgr_destroy(&taskmgr);
|
||||
if (timermgr != NULL)
|
||||
isc_timermgr_destroy(&timermgr);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
create_managers() {
|
||||
isc_result_t result;
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
ncpus = isc_os_ncpus();
|
||||
#else
|
||||
ncpus = 1;
|
||||
#endif
|
||||
|
||||
CHECK(isc_taskmgr_create(mctx, ncpus, 0, &taskmgr));
|
||||
CHECK(isc_timermgr_create(mctx, &timermgr));
|
||||
CHECK(isc_socketmgr_create(mctx, &socketmgr));
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
cleanup_managers();
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_test_begin(FILE *logfile) {
|
||||
isc_test_begin(FILE *logfile, isc_boolean_t start_managers) {
|
||||
isc_result_t result;
|
||||
|
||||
isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
|
||||
@ -90,7 +124,8 @@ isc_test_begin(FILE *logfile) {
|
||||
ncpus = 1;
|
||||
#endif
|
||||
|
||||
CHECK(isc_taskmgr_create(mctx, ncpus, 0, &taskmgr));
|
||||
if (start_managers)
|
||||
CHECK(create_managers());
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
@ -111,6 +146,9 @@ isc_test_end() {
|
||||
}
|
||||
if (ectx != NULL)
|
||||
isc_entropy_detach(&ectx);
|
||||
|
||||
cleanup_managers();
|
||||
|
||||
if (mctx != NULL)
|
||||
isc_mem_destroy(&mctx);
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: isctest.h,v 1.2 2011/07/06 05:05:52 each Exp $ */
|
||||
/* $Id: isctest.h,v 1.3 2011/07/28 04:04:37 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@ -42,10 +42,12 @@ extern isc_mem_t *mctx;
|
||||
extern isc_entropy_t *ectx;
|
||||
extern isc_log_t *lctx;
|
||||
extern isc_taskmgr_t *taskmgr;
|
||||
isc_timermgr_t *timermgr;
|
||||
isc_socketmgr_t *socketmgr;
|
||||
extern int ncpus;
|
||||
|
||||
isc_result_t
|
||||
isc_test_begin(FILE *logfile);
|
||||
isc_test_begin(FILE *logfile, isc_boolean_t start_managers);
|
||||
|
||||
void
|
||||
isc_test_end(void);
|
||||
|
274
lib/isc/tests/socket_test.c
Normal file
274
lib/isc/tests/socket_test.c
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: socket_test.c,v 1.2 2011/07/28 04:04:37 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <isc/socket.h>
|
||||
|
||||
#include "../task_p.h"
|
||||
#include "isctest.h"
|
||||
|
||||
/*
|
||||
* Helper functions
|
||||
*/
|
||||
typedef struct {
|
||||
isc_boolean_t done;
|
||||
isc_result_t result;
|
||||
} completion_t;
|
||||
|
||||
static void
|
||||
completion_init(completion_t *completion) {
|
||||
completion->done = ISC_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
event_done(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socketevent_t *dev;
|
||||
completion_t *completion = event->ev_arg;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
dev = (isc_socketevent_t *) event;
|
||||
completion->result = dev->result;
|
||||
completion->done = ISC_TRUE;
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
nap(isc_uint32_t usec) {
|
||||
#ifdef HAVE_NANOSLEEP
|
||||
struct timespec ts;
|
||||
|
||||
ts.tv_sec = usec / 1000000;
|
||||
ts.tv_nsec = (usec % 1000000) * 1000;
|
||||
nanosleep(&ts, NULL);
|
||||
#elif HAVE_USLEEP
|
||||
usleep(usec);
|
||||
#else
|
||||
/* Round up to the nearest second and sleep, instead */
|
||||
sleep((usec / 1000000) + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
waitfor(completion_t *completion) {
|
||||
int i = 0;
|
||||
while (!completion->done && i++ < 5000) {
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
while (isc__taskmgr_ready(taskmgr))
|
||||
isc__taskmgr_dispatch(taskmgr);
|
||||
#endif
|
||||
nap(1000);
|
||||
}
|
||||
if (completion->done)
|
||||
return (ISC_R_SUCCESS);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Individual unit tests
|
||||
*/
|
||||
|
||||
/* Test UDP sendto/recv (IPv4) */
|
||||
ATF_TC(udp_sendto);
|
||||
ATF_TC_HEAD(udp_sendto, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "UDP sendto/recv");
|
||||
}
|
||||
ATF_TC_BODY(udp_sendto, tc) {
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t addr1, addr2;
|
||||
struct in_addr in;
|
||||
isc_socket_t *s1 = NULL, *s2 = NULL;
|
||||
isc_task_t *task = NULL;
|
||||
char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
|
||||
completion_t completion;
|
||||
isc_region_t r;
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL, ISC_TRUE);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to
|
||||
* each other.
|
||||
*/
|
||||
in.s_addr = inet_addr("127.0.0.1");
|
||||
isc_sockaddr_fromin(&addr1, &in, 5444);
|
||||
isc_sockaddr_fromin(&addr2, &in, 5445);
|
||||
|
||||
result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_create(taskmgr, 0, &task);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
strcpy(sendbuf, "Hello");
|
||||
r.base = (void *) sendbuf;
|
||||
r.length = strlen(sendbuf) + 1;
|
||||
|
||||
completion_init(&completion);
|
||||
result = isc_socket_sendto(s1, &r, task, event_done, &completion,
|
||||
&addr2, NULL);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
waitfor(&completion);
|
||||
ATF_CHECK(completion.done);
|
||||
ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
|
||||
|
||||
r.base = (void *) recvbuf;
|
||||
r.length = BUFSIZ;
|
||||
completion_init(&completion);
|
||||
result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
waitfor(&completion);
|
||||
ATF_CHECK(completion.done);
|
||||
ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
|
||||
ATF_CHECK_STREQ(recvbuf, "Hello");
|
||||
|
||||
isc_task_detach(&task);
|
||||
|
||||
isc_socket_detach(&s1);
|
||||
isc_socket_detach(&s2);
|
||||
|
||||
isc_test_end();
|
||||
}
|
||||
|
||||
/* Test UDP sendto/recv with duplicated socket */
|
||||
ATF_TC(udp_dup);
|
||||
ATF_TC_HEAD(udp_dup, tc) {
|
||||
atf_tc_set_md_var(tc, "descr", "duplicated socket sendto/recv");
|
||||
}
|
||||
ATF_TC_BODY(udp_dup, tc) {
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t addr1, addr2;
|
||||
struct in_addr in;
|
||||
isc_socket_t *s1 = NULL, *s2 = NULL, *s3 = NULL;
|
||||
isc_task_t *task = NULL;
|
||||
char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
|
||||
completion_t completion;
|
||||
isc_region_t r;
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL, ISC_TRUE);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to
|
||||
* each other.
|
||||
*/
|
||||
in.s_addr = inet_addr("127.0.0.1");
|
||||
isc_sockaddr_fromin(&addr1, &in, 5444);
|
||||
isc_sockaddr_fromin(&addr2, &in, 5445);
|
||||
|
||||
result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
result = isc_socket_dup(s2, &s3);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
result = isc_socket_bind(s3, &addr2, ISC_SOCKET_REUSEADDRESS);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_task_create(taskmgr, 0, &task);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
strcpy(sendbuf, "Hello");
|
||||
r.base = (void *) sendbuf;
|
||||
r.length = strlen(sendbuf) + 1;
|
||||
|
||||
completion_init(&completion);
|
||||
result = isc_socket_sendto(s1, &r, task, event_done, &completion,
|
||||
&addr2, NULL);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
waitfor(&completion);
|
||||
ATF_CHECK(completion.done);
|
||||
ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
|
||||
|
||||
strcpy(sendbuf, "World");
|
||||
r.base = (void *) sendbuf;
|
||||
r.length = strlen(sendbuf) + 1;
|
||||
|
||||
completion_init(&completion);
|
||||
result = isc_socket_sendto(s1, &r, task, event_done, &completion,
|
||||
&addr2, NULL);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
waitfor(&completion);
|
||||
ATF_CHECK(completion.done);
|
||||
ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
|
||||
|
||||
r.base = (void *) recvbuf;
|
||||
r.length = BUFSIZ;
|
||||
completion_init(&completion);
|
||||
result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
waitfor(&completion);
|
||||
ATF_CHECK(completion.done);
|
||||
ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
|
||||
ATF_CHECK_STREQ(recvbuf, "Hello");
|
||||
|
||||
r.base = (void *) recvbuf;
|
||||
r.length = BUFSIZ;
|
||||
completion_init(&completion);
|
||||
result = isc_socket_recv(s3, &r, 1, task, event_done, &completion);
|
||||
ATF_CHECK_EQ(result, ISC_R_SUCCESS);
|
||||
waitfor(&completion);
|
||||
ATF_CHECK(completion.done);
|
||||
ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
|
||||
ATF_CHECK_STREQ(recvbuf, "World");
|
||||
|
||||
isc_task_detach(&task);
|
||||
|
||||
isc_socket_detach(&s1);
|
||||
isc_socket_detach(&s2);
|
||||
isc_socket_detach(&s3);
|
||||
|
||||
isc_test_end();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Main
|
||||
*/
|
||||
ATF_TP_ADD_TCS(tp) {
|
||||
ATF_TP_ADD_TC(tp, udp_sendto);
|
||||
ATF_TP_ADD_TC(tp, udp_dup);
|
||||
|
||||
return (atf_no_error());
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: taskpool_test.c,v 1.2 2011/07/06 05:05:52 each Exp $ */
|
||||
/* $Id: taskpool_test.c,v 1.3 2011/07/28 04:04:37 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@ -44,7 +44,7 @@ ATF_TC_BODY(create_pool, tc) {
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL);
|
||||
result = isc_test_begin(NULL, ISC_TRUE);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_taskpool_create(taskmgr, mctx, 8, 2, &pool);
|
||||
@ -68,7 +68,7 @@ ATF_TC_BODY(expand_pool, tc) {
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL);
|
||||
result = isc_test_begin(NULL, ISC_TRUE);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_taskpool_create(taskmgr, mctx, 10, 2, &pool1);
|
||||
@ -121,7 +121,7 @@ ATF_TC_BODY(get_tasks, tc) {
|
||||
|
||||
UNUSED(tc);
|
||||
|
||||
result = isc_test_begin(NULL);
|
||||
result = isc_test_begin(NULL, ISC_TRUE);
|
||||
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_taskpool_create(taskmgr, mctx, 2, 2, &pool);
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: socket.c,v 1.340 2011/07/21 23:47:53 tbox Exp $ */
|
||||
/* $Id: socket.c,v 1.341 2011/07/28 04:04:37 each Exp $ */
|
||||
|
||||
/*! \file */
|
||||
|
||||
@ -334,7 +334,8 @@ struct isc__socket {
|
||||
listener : 1, /* listener socket */
|
||||
connected : 1,
|
||||
connecting : 1, /* connect pending */
|
||||
bound : 1; /* bound to local addr */
|
||||
bound : 1, /* bound to local addr */
|
||||
dupped : 1;
|
||||
|
||||
#ifdef ISC_NET_RECVOVERFLOW
|
||||
unsigned char overflow; /* used for MSG_TRUNC fake */
|
||||
@ -428,6 +429,10 @@ static isc__socketmgr_t *socketmgr = NULL;
|
||||
# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
|
||||
#endif
|
||||
|
||||
static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf,
|
||||
isc_sockettype_t type,
|
||||
isc_socket_t **socketp,
|
||||
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 free_socket(isc__socket_t **);
|
||||
@ -2045,6 +2050,7 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
|
||||
sock->manager = manager;
|
||||
sock->type = type;
|
||||
sock->fd = -1;
|
||||
sock->dupped = 0;
|
||||
sock->statsindex = NULL;
|
||||
|
||||
ISC_LINK_INIT(sock, link);
|
||||
@ -2221,7 +2227,8 @@ clear_bsdcompat(void) {
|
||||
#endif
|
||||
|
||||
static isc_result_t
|
||||
opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
|
||||
opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
|
||||
isc__socket_t *dup_socket) {
|
||||
char strbuf[ISC_STRERRORSIZE];
|
||||
const char *err = "socket";
|
||||
int tries = 0;
|
||||
@ -2234,22 +2241,28 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
|
||||
#endif
|
||||
|
||||
again:
|
||||
switch (sock->type) {
|
||||
case isc_sockettype_udp:
|
||||
sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
|
||||
break;
|
||||
case isc_sockettype_tcp:
|
||||
sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
|
||||
break;
|
||||
case isc_sockettype_unix:
|
||||
sock->fd = socket(sock->pf, SOCK_STREAM, 0);
|
||||
break;
|
||||
case isc_sockettype_fdwatch:
|
||||
/*
|
||||
* We should not be called for isc_sockettype_fdwatch sockets.
|
||||
*/
|
||||
INSIST(0);
|
||||
break;
|
||||
if (dup_socket == NULL) {
|
||||
switch (sock->type) {
|
||||
case isc_sockettype_udp:
|
||||
sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
|
||||
break;
|
||||
case isc_sockettype_tcp:
|
||||
sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
|
||||
break;
|
||||
case isc_sockettype_unix:
|
||||
sock->fd = socket(sock->pf, SOCK_STREAM, 0);
|
||||
break;
|
||||
case isc_sockettype_fdwatch:
|
||||
/*
|
||||
* We should not be called for isc_sockettype_fdwatch
|
||||
* sockets.
|
||||
*/
|
||||
INSIST(0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sock->fd = dup(dup_socket->fd);
|
||||
sock->dupped = 1;
|
||||
}
|
||||
if (sock->fd == -1 && errno == EINTR && tries++ < 42)
|
||||
goto again;
|
||||
@ -2326,6 +2339,9 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
|
||||
}
|
||||
}
|
||||
|
||||
if (dup_socket != NULL)
|
||||
goto setup_done;
|
||||
|
||||
if (make_nonblock(sock->fd) != ISC_R_SUCCESS) {
|
||||
(void)close(sock->fd);
|
||||
return (ISC_R_UNEXPECTED);
|
||||
@ -2509,20 +2525,21 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
|
||||
}
|
||||
#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
|
||||
|
||||
setup_done:
|
||||
inc_stats(manager->stats, sock->statsindex[STATID_OPEN]);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*%
|
||||
* Create a new 'type' socket managed by 'manager'. Events
|
||||
* will be posted to 'task' and when dispatched 'action' will be
|
||||
* called with 'arg' as the arg value. The new socket is returned
|
||||
* in 'socketp'.
|
||||
/*
|
||||
* Create a 'type' socket or duplicate an existing socket, managed
|
||||
* by 'manager'. Events will be posted to 'task' and when dispatched
|
||||
* 'action' will be called with 'arg' as the arg value. The new
|
||||
* socket is returned in 'socketp'.
|
||||
*/
|
||||
ISC_SOCKETFUNC_SCOPE isc_result_t
|
||||
isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
|
||||
isc_socket_t **socketp)
|
||||
static isc_result_t
|
||||
socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
|
||||
isc_socket_t **socketp, isc_socket_t *dup_socket)
|
||||
{
|
||||
isc__socket_t *sock = NULL;
|
||||
isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
|
||||
@ -2554,7 +2571,8 @@ isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
|
||||
}
|
||||
|
||||
sock->pf = pf;
|
||||
result = opensocket(manager, sock);
|
||||
|
||||
result = opensocket(manager, sock, (isc__socket_t *)dup_socket);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
inc_stats(manager->stats, sock->statsindex[STATID_OPENFAIL]);
|
||||
free_socket(&sock);
|
||||
@ -2589,11 +2607,40 @@ isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
|
||||
UNLOCK(&manager->lock);
|
||||
|
||||
socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
|
||||
ISC_MSG_CREATED, "created");
|
||||
ISC_MSG_CREATED, dup_socket == NULL ? "dupped" : "created");
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*%
|
||||
* Create a new 'type' socket managed by 'manager'. Events
|
||||
* will be posted to 'task' and when dispatched 'action' will be
|
||||
* called with 'arg' as the arg value. The new socket is returned
|
||||
* in 'socketp'.
|
||||
*/
|
||||
ISC_SOCKETFUNC_SCOPE isc_result_t
|
||||
isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
|
||||
isc_socket_t **socketp)
|
||||
{
|
||||
return (socket_create(manager0, pf, type, socketp, NULL));
|
||||
}
|
||||
|
||||
/*%
|
||||
* Duplicate an existing socket. The new socket is returned
|
||||
* in 'socketp'.
|
||||
*/
|
||||
ISC_SOCKETFUNC_SCOPE isc_result_t
|
||||
isc__socket_dup(isc_socket_t *sock0, isc_socket_t **socketp) {
|
||||
isc__socket_t *sock = (isc__socket_t *)sock0;
|
||||
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
REQUIRE(socketp != NULL && *socketp == NULL);
|
||||
|
||||
return (socket_create((isc_socketmgr_t *) sock->manager,
|
||||
sock->pf, sock->type, socketp,
|
||||
sock0));
|
||||
}
|
||||
|
||||
#ifdef BIND9
|
||||
ISC_SOCKETFUNC_SCOPE isc_result_t
|
||||
isc__socket_open(isc_socket_t *sock0) {
|
||||
@ -2612,7 +2659,7 @@ isc__socket_open(isc_socket_t *sock0) {
|
||||
*/
|
||||
REQUIRE(sock->fd == -1);
|
||||
|
||||
result = opensocket(sock->manager, sock);
|
||||
result = opensocket(sock->manager, sock, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
sock->fd = -1;
|
||||
|
||||
@ -2792,6 +2839,7 @@ isc__socket_close(isc_socket_t *sock0) {
|
||||
int fd;
|
||||
isc__socketmgr_t *manager;
|
||||
|
||||
fflush(stdout);
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
|
||||
LOCK(&sock->lock);
|
||||
@ -2812,6 +2860,7 @@ isc__socket_close(isc_socket_t *sock0) {
|
||||
manager = sock->manager;
|
||||
fd = sock->fd;
|
||||
sock->fd = -1;
|
||||
sock->dupped = 0;
|
||||
memset(sock->name, 0, sizeof(sock->name));
|
||||
sock->tag = NULL;
|
||||
sock->listener = 0;
|
||||
@ -4977,48 +5026,49 @@ isc__socket_bind(isc_socket_t *sock0, isc_sockaddr_t *sockaddr,
|
||||
UNLOCK(&sock->lock);
|
||||
return (ISC_R_FAMILYMISMATCH);
|
||||
}
|
||||
/*
|
||||
* Only set SO_REUSEADDR when we want a specific port.
|
||||
*/
|
||||
if (!sock->dupped) {
|
||||
/*
|
||||
* Only set SO_REUSEADDR when we want a specific port.
|
||||
*/
|
||||
#ifdef AF_UNIX
|
||||
if (sock->pf == AF_UNIX)
|
||||
goto bind_socket;
|
||||
if (sock->pf == AF_UNIX)
|
||||
goto bind_socket;
|
||||
#endif
|
||||
if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
|
||||
isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
|
||||
setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
|
||||
sizeof(on)) < 0) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"setsockopt(%d) %s", sock->fd,
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
|
||||
ISC_MSG_FAILED, "failed"));
|
||||
/* Press on... */
|
||||
}
|
||||
if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
|
||||
isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
|
||||
setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
|
||||
sizeof(on)) < 0) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"setsockopt(%d) %s", sock->fd,
|
||||
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
|
||||
ISC_MSG_FAILED, "failed"));
|
||||
/* Press on... */
|
||||
}
|
||||
#ifdef AF_UNIX
|
||||
bind_socket:
|
||||
bind_socket:
|
||||
#endif
|
||||
if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) {
|
||||
inc_stats(sock->manager->stats,
|
||||
sock->statsindex[STATID_BINDFAIL]);
|
||||
if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) {
|
||||
inc_stats(sock->manager->stats,
|
||||
sock->statsindex[STATID_BINDFAIL]);
|
||||
|
||||
UNLOCK(&sock->lock);
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
return (ISC_R_NOPERM);
|
||||
case EADDRNOTAVAIL:
|
||||
return (ISC_R_ADDRNOTAVAIL);
|
||||
case EADDRINUSE:
|
||||
return (ISC_R_ADDRINUSE);
|
||||
case EINVAL:
|
||||
return (ISC_R_BOUND);
|
||||
default:
|
||||
isc__strerror(errno, strbuf, sizeof(strbuf));
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s",
|
||||
strbuf);
|
||||
return (ISC_R_UNEXPECTED);
|
||||
UNLOCK(&sock->lock);
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
return (ISC_R_NOPERM);
|
||||
case EADDRNOTAVAIL:
|
||||
return (ISC_R_ADDRNOTAVAIL);
|
||||
case EADDRINUSE:
|
||||
return (ISC_R_ADDRINUSE);
|
||||
case EINVAL:
|
||||
return (ISC_R_BOUND);
|
||||
default:
|
||||
isc__strerror(errno, strbuf, sizeof(strbuf));
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s",
|
||||
strbuf);
|
||||
return (ISC_R_UNEXPECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
socket_log(sock, sockaddr, TRACE,
|
||||
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound");
|
||||
sock->bound = 1;
|
||||
@ -5826,6 +5876,13 @@ isc__socket_register() {
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
isc_socket_getfd(isc_socket_t *socket0) {
|
||||
isc__socket_t *socket = (isc__socket_t *)socket0;
|
||||
|
||||
return ((short) socket->fd);
|
||||
}
|
||||
|
||||
#if defined(HAVE_LIBXML2) && defined(BIND9)
|
||||
|
||||
static const char *
|
||||
|
@ -88,6 +88,7 @@ isc__socket_close
|
||||
isc__socket_connect
|
||||
isc__socket_create
|
||||
isc__socket_detach
|
||||
isc__socket_dup
|
||||
isc__socket_filter
|
||||
isc__socket_getname
|
||||
isc__socket_getpeername
|
||||
|
@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: socket.c,v 1.87 2010/12/09 06:08:05 marka Exp $ */
|
||||
/* $Id: socket.c,v 1.88 2011/07/28 04:04:37 each Exp $ */
|
||||
|
||||
/* This code uses functions which are only available on Server 2003 and
|
||||
* higher, and Windows XP and higher.
|
||||
@ -265,7 +265,8 @@ struct isc_socket {
|
||||
unsigned int listener : 1, /* listener socket */
|
||||
connected : 1,
|
||||
pending_connect : 1, /* connect pending */
|
||||
bound : 1; /* bound to local addr */
|
||||
bound : 1, /* bound to local addr */
|
||||
dupped : 1; /* created by isc_socket_dup() */
|
||||
unsigned int pending_iocp; /* Should equal the counters below. Debug. */
|
||||
unsigned int pending_recv; /* Number of outstanding recv() calls. */
|
||||
unsigned int pending_send; /* Number of outstanding send() calls. */
|
||||
@ -351,6 +352,10 @@ enum {
|
||||
#define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER)
|
||||
#define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
|
||||
|
||||
static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf,
|
||||
isc_sockettype_t type,
|
||||
isc_socket_t **socketp,
|
||||
isc_socket_t *dup_socket);
|
||||
static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
|
||||
static void maybe_free_socket(isc_socket_t **, int);
|
||||
static void free_socket(isc_socket_t **, int);
|
||||
@ -1461,6 +1466,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
|
||||
sock->connected = 0;
|
||||
sock->pending_connect = 0;
|
||||
sock->bound = 0;
|
||||
sock->dupped = 0;
|
||||
memset(sock->name, 0, sizeof(sock->name)); // zero the name field
|
||||
_set_state(sock, SOCK_INITIALIZED);
|
||||
|
||||
@ -1623,9 +1629,10 @@ free_socket(isc_socket_t **sockp, int lineno) {
|
||||
* called with 'arg' as the arg value. The new socket is returned
|
||||
* in 'socketp'.
|
||||
*/
|
||||
isc_result_t
|
||||
isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
isc_socket_t **socketp) {
|
||||
static isc_result_t
|
||||
socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
isc_socket_t **socketp, isc_socket_t *dup_socket)
|
||||
{
|
||||
isc_socket_t *sock = NULL;
|
||||
isc_result_t result;
|
||||
#if defined(USE_CMSG)
|
||||
@ -1647,27 +1654,35 @@ isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
return (result);
|
||||
|
||||
sock->pf = pf;
|
||||
switch (type) {
|
||||
case isc_sockettype_udp:
|
||||
sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (sock->fd != INVALID_SOCKET) {
|
||||
result = connection_reset_fix(sock->fd);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
|
||||
"closed %d %d %d con_reset_fix_failed",
|
||||
sock->pending_recv, sock->pending_send,
|
||||
sock->references);
|
||||
closesocket(sock->fd);
|
||||
_set_state(sock, SOCK_CLOSED);
|
||||
sock->fd = INVALID_SOCKET;
|
||||
free_socket(&sock, __LINE__);
|
||||
return (result);
|
||||
if (dup_socket == NULL) {
|
||||
switch (type) {
|
||||
case isc_sockettype_udp:
|
||||
sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (sock->fd != INVALID_SOCKET) {
|
||||
result = connection_reset_fix(sock->fd);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
socket_log(__LINE__, sock,
|
||||
NULL, EVENT, NULL, 0, 0,
|
||||
"closed %d %d %d "
|
||||
"con_reset_fix_failed",
|
||||
sock->pending_recv,
|
||||
sock->pending_send,
|
||||
sock->references);
|
||||
closesocket(sock->fd);
|
||||
_set_state(sock, SOCK_CLOSED);
|
||||
sock->fd = INVALID_SOCKET;
|
||||
free_socket(&sock, __LINE__);
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case isc_sockettype_tcp:
|
||||
sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case isc_sockettype_tcp:
|
||||
sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
|
||||
break;
|
||||
} else {
|
||||
sock->fd = dup(dup_socket->fd);
|
||||
sock->dupped = 1;
|
||||
}
|
||||
|
||||
if (sock->fd == INVALID_SOCKET) {
|
||||
@ -1786,12 +1801,29 @@ isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
InterlockedIncrement(&manager->totalSockets);
|
||||
UNLOCK(&manager->lock);
|
||||
|
||||
socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
|
||||
ISC_MSG_CREATED, "created %u type %u", sock->fd, type);
|
||||
socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat,
|
||||
ISC_MSGSET_SOCKET, ISC_MSG_CREATED,
|
||||
"created %u type %u", sock->fd, type);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
||||
isc_socket_t **socketp)
|
||||
{
|
||||
return (socket_create(manager, pf, type, socketp, NULL));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc__socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
REQUIRE(socketp != NULL && *socketp == NULL);
|
||||
|
||||
return (socket_create(sock->manager, sock->pf, sock->type,
|
||||
socketp, sock));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_socket_open(isc_socket_t *sock) {
|
||||
REQUIRE(VALID_SOCKET(sock));
|
||||
|
Loading…
x
Reference in New Issue
Block a user