2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +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:
Evan Hunt
2011-07-28 04:04:37 +00:00
parent 8181aa6228
commit f07b2fccaf
17 changed files with 738 additions and 223 deletions

View File

@@ -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 3136. [func] Add RFC 1918 reverse zones to the list of built-in
empty zones switched on by the 'empty-zones-enable' empty zones switched on by the 'empty-zones-enable'
option. [RT #24990] option. [RT #24990]

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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> #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) ns_interface_t *ifp, isc_boolean_t tcp)
{ {
isc_result_t result = ISC_R_SUCCESS; isc_result_t result = ISC_R_SUCCESS;
isc_boolean_t success = ISC_FALSE;
unsigned int i; unsigned int i;
ns_client_t *client; ns_client_t *client;
unsigned int disp;
REQUIRE(VALID_MANAGER(manager)); REQUIRE(VALID_MANAGER(manager));
REQUIRE(n > 0); REQUIRE(n > 0);
@@ -2546,61 +2548,68 @@ ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
LOCK(&manager->lock); LOCK(&manager->lock);
for (i = 0; i < n; i++) { for (disp = 0; disp < n; disp++) {
isc_event_t *ev; 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. /*
*/ * Allocate a client. First try to get a recycled one;
client = NULL; * if that fails, make a new one.
if (!ns_g_clienttest) */
client = ISC_LIST_HEAD(manager->inactive); client = NULL;
if (client != NULL) { if (!ns_g_clienttest)
MTRACE("recycle"); client = ISC_LIST_HEAD(manager->inactive);
ISC_LIST_UNLINK(manager->inactive, client, link); if (client != NULL) {
client->list = NULL; MTRACE("recycle");
} else { ISC_LIST_UNLINK(manager->inactive, client,
MTRACE("create new"); link);
result = client_create(manager, &client); client->list = NULL;
if (result != ISC_R_SUCCESS) } else {
break; 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); 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); return (result);
} }

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 #ifndef NAMED_INTERFACEMGR_H
#define NAMED_INTERFACEMGR_H 1 #define NAMED_INTERFACEMGR_H 1
@@ -65,7 +65,8 @@
#define NS_INTERFACE_VALID(t) ISC_MAGIC_VALID(t, IFACE_MAGIC) #define NS_INTERFACE_VALID(t) ISC_MAGIC_VALID(t, IFACE_MAGIC)
#define NS_INTERFACEFLAG_ANYADDR 0x01U /*%< bound to "any" address */ #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 */ /*% The nameserver interface structure */
struct ns_interface { struct ns_interface {
unsigned int magic; /*%< Magic number. */ unsigned int magic; /*%< Magic number. */
@@ -76,11 +77,13 @@ struct ns_interface {
isc_sockaddr_t addr; /*%< Address and port. */ isc_sockaddr_t addr; /*%< Address and port. */
unsigned int flags; /*%< Interface characteristics */ unsigned int flags; /*%< Interface characteristics */
char name[32]; /*%< Null terminated. */ 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. */ isc_socket_t * tcpsocket; /*%< TCP socket. */
int ntcptarget; /*%< Desired number of concurrent int ntcptarget; /*%< Desired number of concurrent
TCP accepts */ TCP accepts */
int ntcpcurrent; /*%< Current ditto, locked */ int ntcpcurrent; /*%< Current ditto, locked */
int nudpdispatch; /*%< Number of UDP dispatches */
ns_clientmgr_t * clientmgr; /*%< Client manager. */ ns_clientmgr_t * clientmgr; /*%< Client manager. */
ISC_LINK(ns_interface_t) link; ISC_LINK(ns_interface_t) link;
}; };

View File

@@ -15,13 +15,14 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 */ /*! \file */
#include <config.h> #include <config.h>
#include <isc/interfaceiter.h> #include <isc/interfaceiter.h>
#include <isc/os.h>
#include <isc/string.h> #include <isc/string.h>
#include <isc/task.h> #include <isc/task.h>
#include <isc/util.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)); strncpy(ifp->name, name, sizeof(ifp->name));
ifp->name[sizeof(ifp->name)-1] = '\0'; ifp->name[sizeof(ifp->name)-1] = '\0';
ifp->clientmgr = NULL; ifp->clientmgr = NULL;
int disp;
result = isc_mutex_init(&ifp->lock); result = isc_mutex_init(&ifp->lock);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
@@ -210,7 +212,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
goto clientmgr_create_failure; goto clientmgr_create_failure;
} }
ifp->udpdispatch = NULL; for (disp = 0; disp < MAX_UDP_DISPATCH; disp++)
ifp->udpdispatch[disp] = NULL;
ifp->tcpsocket = NULL; ifp->tcpsocket = NULL;
/* /*
@@ -221,6 +224,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
*/ */
ifp->ntcptarget = 1; ifp->ntcptarget = 1;
ifp->ntcpcurrent = 0; ifp->ntcpcurrent = 0;
ifp->nudpdispatch = 0;
ISC_LINK_INIT(ifp, link); ISC_LINK_INIT(ifp, link);
@@ -247,6 +251,7 @@ ns_interface_listenudp(ns_interface_t *ifp) {
isc_result_t result; isc_result_t result;
unsigned int attrs; unsigned int attrs;
unsigned int attrmask; unsigned int attrmask;
int disp, i;
attrs = 0; attrs = 0;
attrs |= DNS_DISPATCHATTR_UDP; attrs |= DNS_DISPATCHATTR_UDP;
@@ -258,15 +263,25 @@ ns_interface_listenudp(ns_interface_t *ifp) {
attrmask = 0; attrmask = 0;
attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr,
ns_g_taskmgr, &ifp->addr, ifp->nudpdispatch = ISC_MIN(isc_os_ncpus(), MAX_UDP_DISPATCH);
4096, 1000, 32768, 8219, 8237, for (disp = 0; disp < ifp->nudpdispatch; disp++) {
attrs, attrmask, &ifp->udpdispatch); result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr,
if (result != ISC_R_SUCCESS) { ns_g_socketmgr,
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, ns_g_taskmgr, &ifp->addr,
"could not listen on UDP socket: %s", 4096, 1000, 32768, 8219, 8237,
isc_result_totext(result)); attrs, attrmask,
goto udp_dispatch_failure; &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, result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus,
@@ -277,12 +292,17 @@ ns_interface_listenudp(ns_interface_t *ifp) {
isc_result_totext(result)); isc_result_totext(result));
goto addtodispatch_failure; goto addtodispatch_failure;
} }
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
addtodispatch_failure: addtodispatch_failure:
dns_dispatch_changeattributes(ifp->udpdispatch, 0, for (i = disp - 1; i <= 0; i--) {
DNS_DISPATCHATTR_NOLISTEN); dns_dispatch_changeattributes(ifp->udpdispatch[i], 0,
dns_dispatch_detach(&ifp->udpdispatch); DNS_DISPATCHATTR_NOLISTEN);
dns_dispatch_detach(&(ifp->udpdispatch[i]));
}
ifp->nudpdispatch = 0;
udp_dispatch_failure: udp_dispatch_failure:
return (result); return (result);
} }
@@ -397,14 +417,16 @@ static void
ns_interface_destroy(ns_interface_t *ifp) { ns_interface_destroy(ns_interface_t *ifp) {
isc_mem_t *mctx = ifp->mgr->mctx; isc_mem_t *mctx = ifp->mgr->mctx;
REQUIRE(NS_INTERFACE_VALID(ifp)); REQUIRE(NS_INTERFACE_VALID(ifp));
int disp;
ns_interface_shutdown(ifp); ns_interface_shutdown(ifp);
if (ifp->udpdispatch != NULL) { for (disp = ifp->nudpdispatch; disp >= 0; disp--)
dns_dispatch_changeattributes(ifp->udpdispatch, 0, if (ifp->udpdispatch[disp] != NULL) {
DNS_DISPATCHATTR_NOLISTEN); dns_dispatch_changeattributes(ifp->udpdispatch[disp], 0,
dns_dispatch_detach(&ifp->udpdispatch); DNS_DISPATCHATTR_NOLISTEN);
} dns_dispatch_detach(&(ifp->udpdispatch[disp]));
}
if (ifp->tcpsocket != NULL) if (ifp->tcpsocket != NULL)
isc_socket_detach(&ifp->tcpsocket); isc_socket_detach(&ifp->tcpsocket);

View File

@@ -18,7 +18,7 @@ AC_DIVERT_PUSH(1)dnl
esyscmd([sed "s/^/# /" COPYRIGHT])dnl esyscmd([sed "s/^/# /" COPYRIGHT])dnl
AC_DIVERT_POP()dnl AC_DIVERT_POP()dnl
AC_REVISION($Revision: 1.528 $) AC_REVISION($Revision: 1.529 $)
AC_INIT(lib/dns/name.c) AC_INIT(lib/dns/name.c)
AC_PREREQ(2.59) AC_PREREQ(2.59)
@@ -2552,7 +2552,7 @@ yes)
esac esac
AC_SUBST(ISC_PLATFORM_HAVEIFNAMETOINDEX) AC_SUBST(ISC_PLATFORM_HAVEIFNAMETOINDEX)
AC_CHECK_FUNCS(nanosleep) AC_CHECK_FUNCS(nanosleep usleep)
# #
# Machine architecture dependent features # Machine architecture dependent features

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 */ /*! \file */
@@ -312,14 +312,16 @@ static isc_result_t get_udpsocket(dns_dispatchmgr_t *mgr,
dns_dispatch_t *disp, dns_dispatch_t *disp,
isc_socketmgr_t *sockmgr, isc_socketmgr_t *sockmgr,
isc_sockaddr_t *localaddr, 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, static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
isc_socketmgr_t *sockmgr, isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr, isc_taskmgr_t *taskmgr,
isc_sockaddr_t *localaddr, isc_sockaddr_t *localaddr,
unsigned int maxrequests, unsigned int maxrequests,
unsigned int attributes, 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 isc_boolean_t destroy_mgr_ok(dns_dispatchmgr_t *mgr);
static void destroy_mgr(dns_dispatchmgr_t **mgrp); static void destroy_mgr(dns_dispatchmgr_t **mgrp);
static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets, 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); isc_boolean_t needaddrtable);
static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp); 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, 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, static isc_boolean_t portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
isc_sockaddr_t *sockaddrp); isc_sockaddr_t *sockaddrp);
@@ -902,7 +905,8 @@ get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
portentry = port_search(disp, port); portentry = port_search(disp, port);
if (portentry != NULL) if (portentry != NULL)
bindoptions |= ISC_SOCKET_REUSEADDRESS; 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 (result == ISC_R_SUCCESS) {
if (portentry == NULL) { if (portentry == NULL) {
portentry = new_portentry(disp, port); portentry = new_portentry(disp, port);
@@ -1787,19 +1791,14 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
static isc_result_t static isc_result_t
open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local, 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_socket_t *sock;
isc_result_t result; isc_result_t result;
sock = *sockp; sock = *sockp;
if (sock == NULL) { 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 {
#ifdef BIND9 #ifdef BIND9
result = isc_socket_open(sock); result = isc_socket_open(sock);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
@@ -1807,8 +1806,19 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
#else #else
INSIST(0); INSIST(0);
#endif #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 #ifndef ISC_ALLOW_MAPPED
isc_socket_ipv6only(sock, ISC_TRUE); isc_socket_ipv6only(sock, ISC_TRUE);
#endif #endif
@@ -2646,13 +2656,13 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
} }
isc_result_t 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, isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
unsigned int buffersize, unsigned int buffersize,
unsigned int maxbuffers, unsigned int maxrequests, unsigned int maxbuffers, unsigned int maxrequests,
unsigned int buckets, unsigned int increment, unsigned int buckets, unsigned int increment,
unsigned int attributes, unsigned int mask, unsigned int attributes, unsigned int mask,
dns_dispatch_t **dispp) dns_dispatch_t **dispp, dns_dispatch_t *dup_dispatch)
{ {
isc_result_t result; isc_result_t result;
dns_dispatch_t *disp = NULL; 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. * See if we have a dispatcher that matches.
*/ */
result = dispatch_find(mgr, localaddr, attributes, mask, &disp); if (dup_dispatch == NULL) {
if (result == ISC_R_SUCCESS) { result = dispatch_find(mgr, localaddr, attributes, mask, &disp);
disp->refcount++; if (result == ISC_R_SUCCESS) {
disp->refcount++;
if (disp->maxrequests < maxrequests) if (disp->maxrequests < maxrequests)
disp->maxrequests = maxrequests; disp->maxrequests = maxrequests;
if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0 && if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0
(attributes & DNS_DISPATCHATTR_NOLISTEN) != 0) && (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
{ {
disp->attributes |= DNS_DISPATCHATTR_NOLISTEN; disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
if (disp->recv_pending != 0) if (disp->recv_pending != 0)
isc_socket_cancel(disp->socket, disp->task[0], isc_socket_cancel(disp->socket,
ISC_SOCKCANCEL_RECV); 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: createudp:
@@ -2712,7 +2725,11 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
* Nope, create one. * Nope, create one.
*/ */
result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr, 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) { if (result != ISC_R_SUCCESS) {
UNLOCK(&mgr->lock); UNLOCK(&mgr->lock);
return (result); return (result);
@@ -2720,9 +2737,24 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
UNLOCK(&mgr->lock); UNLOCK(&mgr->lock);
*dispp = disp; *dispp = disp;
return (ISC_R_SUCCESS); 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. * mgr should be locked.
*/ */
@@ -2734,7 +2766,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
static isc_result_t static isc_result_t
get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp, get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
isc_socketmgr_t *sockmgr, isc_sockaddr_t *localaddr, 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; unsigned int i, j;
isc_socket_t *held[DNS_DISPATCH_HELD]; isc_socket_t *held[DNS_DISPATCH_HELD];
@@ -2774,7 +2806,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
nports)]; nports)];
isc_sockaddr_setport(&localaddr_bound, prt); isc_sockaddr_setport(&localaddr_bound, prt);
result = open_socket(sockmgr, &localaddr_bound, result = open_socket(sockmgr, &localaddr_bound,
0, &sock); 0, &sock, NULL);
if (result == ISC_R_SUCCESS || if (result == ISC_R_SUCCESS ||
result != ISC_R_ADDRINUSE) { result != ISC_R_ADDRINUSE) {
disp->localport = prt; disp->localport = prt;
@@ -2790,7 +2822,8 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
} else { } else {
/* Allow to reuse address for non-random ports. */ /* Allow to reuse address for non-random ports. */
result = open_socket(sockmgr, localaddr, result = open_socket(sockmgr, localaddr,
ISC_SOCKET_REUSEADDRESS, &sock); ISC_SOCKET_REUSEADDRESS, &sock,
dup_socket);
if (result == ISC_R_SUCCESS) if (result == ISC_R_SUCCESS)
*sockp = sock; *sockp = sock;
@@ -2802,7 +2835,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
i = 0; i = 0;
for (j = 0; j < 0xffffU; j++) { 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) if (result != ISC_R_SUCCESS)
goto end; goto end;
else if (!anyport) else if (!anyport)
@@ -2841,7 +2874,8 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
isc_sockaddr_t *localaddr, isc_sockaddr_t *localaddr,
unsigned int maxrequests, unsigned int maxrequests,
unsigned int attributes, unsigned int attributes,
dns_dispatch_t **dispp) dns_dispatch_t **dispp,
isc_socket_t *dup_socket)
{ {
isc_result_t result; isc_result_t result;
dns_dispatch_t *disp; dns_dispatch_t *disp;
@@ -2857,9 +2891,21 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
return (result); return (result);
if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) { 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) if (result != ISC_R_SUCCESS)
goto deallocate_dispatch; 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 { } else {
isc_sockaddr_t sa_any; 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)); isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
if (!isc_sockaddr_eqaddr(&sa_any, 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) if (sock != NULL)
isc_socket_detach(&sock); isc_socket_detach(&sock);
if (result != ISC_R_SUCCESS) 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); dispatch_log(disp, LVL(90), "created socket %p", disp->socket);
*dispp = disp; *dispp = disp;
return (result); return (result);
/* /*

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 #ifndef DNS_DISPATCH_H
#define DNS_DISPATCH_H 1 #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 buckets, unsigned int increment,
unsigned int attributes, unsigned int mask, unsigned int attributes, unsigned int mask,
dns_dispatch_t **dispp); 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, * Attach to existing dns_dispatch_t if one is found with dns_dispatchmgr_find,
* otherwise create a new UDP dispatch. * otherwise create a new UDP dispatch.

View File

@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 #ifndef ISCAPI_NAMESPACE_H
#define ISCAPI_NAMESPACE_H 1 #define ISCAPI_NAMESPACE_H 1
@@ -88,6 +88,7 @@
#define isc_mempool_getfillcount isc__mempool_getfillcount #define isc_mempool_getfillcount isc__mempool_getfillcount
#define isc_socket_create isc__socket_create #define isc_socket_create isc__socket_create
#define isc_socket_dup isc__socket_dup
#define isc_socket_attach isc__socket_attach #define isc_socket_attach isc__socket_attach
#define isc_socket_detach isc__socket_detach #define isc_socket_detach isc__socket_detach
#define isc_socketmgr_create isc__socketmgr_create #define isc_socketmgr_create isc__socketmgr_create

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 #ifndef ISC_SOCKET_H
#define ISC_SOCKET_H 1 #define ISC_SOCKET_H 1
@@ -449,6 +449,12 @@ isc_socket_create(isc_socketmgr_t *manager,
*\li #ISC_R_UNEXPECTED *\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 void
isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, isc_socket_cancel(isc_socket_t *sock, isc_task_t *task,
unsigned int how); unsigned int how);
@@ -1102,6 +1108,11 @@ void *isc_socket_gettag(isc_socket_t *socket);
* Get the tag associated with a socket, if any. * 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 void
isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t); isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t);
/*%< /*%<

View File

@@ -12,7 +12,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE. # 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@ srcdir = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
@@ -35,10 +35,10 @@ ISCDEPLIBS = ../libisc.@A@
LIBS = @LIBS@ @ATFLIBS@ LIBS = @LIBS@ @ATFLIBS@
OBJS = isctest.@O@ OBJS = isctest.@O@
SRCS = isctest.c taskpool_test.c SRCS = isctest.c taskpool_test.c socket_test.c
SUBDIRS = SUBDIRS =
TARGETS = taskpool_test@EXEEXT@ TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@
@BIND9_MAKE_RULES@ @BIND9_MAKE_RULES@
@@ -46,5 +46,9 @@ taskpool_test@EXEEXT@: taskpool_test.@O@ isctest.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
taskpool_test.@O@ isctest.@O@ ${ISCLIBS} ${LIBS} 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:: clean distclean::
rm -f ${TARGETS} rm -f ${TARGETS}

View File

@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 */ /*! \file */
@@ -26,7 +26,10 @@
#include <isc/hash.h> #include <isc/hash.h>
#include <isc/mem.h> #include <isc/mem.h>
#include <isc/os.h> #include <isc/os.h>
#include <isc/socket.h>
#include <isc/string.h> #include <isc/string.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h> #include <isc/util.h>
#include "isctest.h" #include "isctest.h"
@@ -35,6 +38,8 @@ isc_mem_t *mctx = NULL;
isc_entropy_t *ectx = NULL; isc_entropy_t *ectx = NULL;
isc_log_t *lctx = NULL; isc_log_t *lctx = NULL;
isc_taskmgr_t *taskmgr = NULL; isc_taskmgr_t *taskmgr = NULL;
isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
int ncpus; int ncpus;
static isc_boolean_t hash_active = ISC_FALSE; static isc_boolean_t hash_active = ISC_FALSE;
@@ -54,8 +59,37 @@ static isc_logcategory_t categories[] = {
{ NULL, 0 } { 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_result_t
isc_test_begin(FILE *logfile) { isc_test_begin(FILE *logfile, isc_boolean_t start_managers) {
isc_result_t result; isc_result_t result;
isc_mem_debugging |= ISC_MEM_DEBUGRECORD; isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
@@ -90,7 +124,8 @@ isc_test_begin(FILE *logfile) {
ncpus = 1; ncpus = 1;
#endif #endif
CHECK(isc_taskmgr_create(mctx, ncpus, 0, &taskmgr)); if (start_managers)
CHECK(create_managers());
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
@@ -111,6 +146,9 @@ isc_test_end() {
} }
if (ectx != NULL) if (ectx != NULL)
isc_entropy_detach(&ectx); isc_entropy_detach(&ectx);
cleanup_managers();
if (mctx != NULL) if (mctx != NULL)
isc_mem_destroy(&mctx); isc_mem_destroy(&mctx);
} }

View File

@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 */ /*! \file */
@@ -42,10 +42,12 @@ extern isc_mem_t *mctx;
extern isc_entropy_t *ectx; extern isc_entropy_t *ectx;
extern isc_log_t *lctx; extern isc_log_t *lctx;
extern isc_taskmgr_t *taskmgr; extern isc_taskmgr_t *taskmgr;
isc_timermgr_t *timermgr;
isc_socketmgr_t *socketmgr;
extern int ncpus; extern int ncpus;
isc_result_t isc_result_t
isc_test_begin(FILE *logfile); isc_test_begin(FILE *logfile, isc_boolean_t start_managers);
void void
isc_test_end(void); isc_test_end(void);

274
lib/isc/tests/socket_test.c Normal file
View 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());
}

View File

@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 */ /*! \file */
@@ -44,7 +44,7 @@ ATF_TC_BODY(create_pool, tc) {
UNUSED(tc); UNUSED(tc);
result = isc_test_begin(NULL); result = isc_test_begin(NULL, ISC_TRUE);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = isc_taskpool_create(taskmgr, mctx, 8, 2, &pool); result = isc_taskpool_create(taskmgr, mctx, 8, 2, &pool);
@@ -68,7 +68,7 @@ ATF_TC_BODY(expand_pool, tc) {
UNUSED(tc); UNUSED(tc);
result = isc_test_begin(NULL); result = isc_test_begin(NULL, ISC_TRUE);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = isc_taskpool_create(taskmgr, mctx, 10, 2, &pool1); result = isc_taskpool_create(taskmgr, mctx, 10, 2, &pool1);
@@ -121,7 +121,7 @@ ATF_TC_BODY(get_tasks, tc) {
UNUSED(tc); UNUSED(tc);
result = isc_test_begin(NULL); result = isc_test_begin(NULL, ISC_TRUE);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
result = isc_taskpool_create(taskmgr, mctx, 2, 2, &pool); result = isc_taskpool_create(taskmgr, mctx, 2, 2, &pool);

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 */ /*! \file */
@@ -334,7 +334,8 @@ struct isc__socket {
listener : 1, /* listener socket */ listener : 1, /* listener socket */
connected : 1, connected : 1,
connecting : 1, /* connect pending */ connecting : 1, /* connect pending */
bound : 1; /* bound to local addr */ bound : 1, /* bound to local addr */
dupped : 1;
#ifdef ISC_NET_RECVOVERFLOW #ifdef ISC_NET_RECVOVERFLOW
unsigned char overflow; /* used for MSG_TRUNC fake */ unsigned char overflow; /* used for MSG_TRUNC fake */
@@ -428,6 +429,10 @@ static isc__socketmgr_t *socketmgr = NULL;
# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER) # define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
#endif #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_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 free_socket(isc__socket_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->manager = manager;
sock->type = type; sock->type = type;
sock->fd = -1; sock->fd = -1;
sock->dupped = 0;
sock->statsindex = NULL; sock->statsindex = NULL;
ISC_LINK_INIT(sock, link); ISC_LINK_INIT(sock, link);
@@ -2221,7 +2227,8 @@ clear_bsdcompat(void) {
#endif #endif
static isc_result_t 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]; char strbuf[ISC_STRERRORSIZE];
const char *err = "socket"; const char *err = "socket";
int tries = 0; int tries = 0;
@@ -2234,22 +2241,28 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
#endif #endif
again: again:
switch (sock->type) { if (dup_socket == NULL) {
case isc_sockettype_udp: switch (sock->type) {
sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP); case isc_sockettype_udp:
break; sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
case isc_sockettype_tcp: break;
sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP); case isc_sockettype_tcp:
break; sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
case isc_sockettype_unix: break;
sock->fd = socket(sock->pf, SOCK_STREAM, 0); case isc_sockettype_unix:
break; sock->fd = socket(sock->pf, SOCK_STREAM, 0);
case isc_sockettype_fdwatch: break;
/* case isc_sockettype_fdwatch:
* We should not be called for isc_sockettype_fdwatch sockets. /*
*/ * We should not be called for isc_sockettype_fdwatch
INSIST(0); * sockets.
break; */
INSIST(0);
break;
}
} else {
sock->fd = dup(dup_socket->fd);
sock->dupped = 1;
} }
if (sock->fd == -1 && errno == EINTR && tries++ < 42) if (sock->fd == -1 && errno == EINTR && tries++ < 42)
goto again; 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) { if (make_nonblock(sock->fd) != ISC_R_SUCCESS) {
(void)close(sock->fd); (void)close(sock->fd);
return (ISC_R_UNEXPECTED); return (ISC_R_UNEXPECTED);
@@ -2509,20 +2525,21 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
} }
#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */ #endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
setup_done:
inc_stats(manager->stats, sock->statsindex[STATID_OPEN]); inc_stats(manager->stats, sock->statsindex[STATID_OPEN]);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
/*% /*
* Create a new 'type' socket managed by 'manager'. Events * Create a 'type' socket or duplicate an existing socket, managed
* will be posted to 'task' and when dispatched 'action' will be * by 'manager'. Events will be posted to 'task' and when dispatched
* called with 'arg' as the arg value. The new socket is returned * 'action' will be called with 'arg' as the arg value. The new
* in 'socketp'. * socket is returned in 'socketp'.
*/ */
ISC_SOCKETFUNC_SCOPE isc_result_t static isc_result_t
isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
isc_socket_t **socketp) isc_socket_t **socketp, isc_socket_t *dup_socket)
{ {
isc__socket_t *sock = NULL; isc__socket_t *sock = NULL;
isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; 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; sock->pf = pf;
result = opensocket(manager, sock);
result = opensocket(manager, sock, (isc__socket_t *)dup_socket);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
inc_stats(manager->stats, sock->statsindex[STATID_OPENFAIL]); inc_stats(manager->stats, sock->statsindex[STATID_OPENFAIL]);
free_socket(&sock); free_socket(&sock);
@@ -2589,11 +2607,40 @@ isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
UNLOCK(&manager->lock); UNLOCK(&manager->lock);
socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, 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); 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 #ifdef BIND9
ISC_SOCKETFUNC_SCOPE isc_result_t ISC_SOCKETFUNC_SCOPE isc_result_t
isc__socket_open(isc_socket_t *sock0) { isc__socket_open(isc_socket_t *sock0) {
@@ -2612,7 +2659,7 @@ isc__socket_open(isc_socket_t *sock0) {
*/ */
REQUIRE(sock->fd == -1); REQUIRE(sock->fd == -1);
result = opensocket(sock->manager, sock); result = opensocket(sock->manager, sock, NULL);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
sock->fd = -1; sock->fd = -1;
@@ -2792,6 +2839,7 @@ isc__socket_close(isc_socket_t *sock0) {
int fd; int fd;
isc__socketmgr_t *manager; isc__socketmgr_t *manager;
fflush(stdout);
REQUIRE(VALID_SOCKET(sock)); REQUIRE(VALID_SOCKET(sock));
LOCK(&sock->lock); LOCK(&sock->lock);
@@ -2812,6 +2860,7 @@ isc__socket_close(isc_socket_t *sock0) {
manager = sock->manager; manager = sock->manager;
fd = sock->fd; fd = sock->fd;
sock->fd = -1; sock->fd = -1;
sock->dupped = 0;
memset(sock->name, 0, sizeof(sock->name)); memset(sock->name, 0, sizeof(sock->name));
sock->tag = NULL; sock->tag = NULL;
sock->listener = 0; sock->listener = 0;
@@ -4977,48 +5026,49 @@ isc__socket_bind(isc_socket_t *sock0, isc_sockaddr_t *sockaddr,
UNLOCK(&sock->lock); UNLOCK(&sock->lock);
return (ISC_R_FAMILYMISMATCH); return (ISC_R_FAMILYMISMATCH);
} }
/* if (!sock->dupped) {
* Only set SO_REUSEADDR when we want a specific port. /*
*/ * Only set SO_REUSEADDR when we want a specific port.
*/
#ifdef AF_UNIX #ifdef AF_UNIX
if (sock->pf == AF_UNIX) if (sock->pf == AF_UNIX)
goto bind_socket; goto bind_socket;
#endif #endif
if ((options & ISC_SOCKET_REUSEADDRESS) != 0 && if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
isc_sockaddr_getport(sockaddr) != (in_port_t)0 && isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
sizeof(on)) < 0) { sizeof(on)) < 0) {
UNEXPECTED_ERROR(__FILE__, __LINE__, UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d) %s", sock->fd, "setsockopt(%d) %s", sock->fd,
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed")); ISC_MSG_FAILED, "failed"));
/* Press on... */ /* Press on... */
} }
#ifdef AF_UNIX #ifdef AF_UNIX
bind_socket: bind_socket:
#endif #endif
if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) { if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) {
inc_stats(sock->manager->stats, inc_stats(sock->manager->stats,
sock->statsindex[STATID_BINDFAIL]); sock->statsindex[STATID_BINDFAIL]);
UNLOCK(&sock->lock); UNLOCK(&sock->lock);
switch (errno) { switch (errno) {
case EACCES: case EACCES:
return (ISC_R_NOPERM); return (ISC_R_NOPERM);
case EADDRNOTAVAIL: case EADDRNOTAVAIL:
return (ISC_R_ADDRNOTAVAIL); return (ISC_R_ADDRNOTAVAIL);
case EADDRINUSE: case EADDRINUSE:
return (ISC_R_ADDRINUSE); return (ISC_R_ADDRINUSE);
case EINVAL: case EINVAL:
return (ISC_R_BOUND); return (ISC_R_BOUND);
default: default:
isc__strerror(errno, strbuf, sizeof(strbuf)); isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s", UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s",
strbuf); strbuf);
return (ISC_R_UNEXPECTED); return (ISC_R_UNEXPECTED);
}
} }
} }
socket_log(sock, sockaddr, TRACE, socket_log(sock, sockaddr, TRACE,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound"); isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound");
sock->bound = 1; sock->bound = 1;
@@ -5826,6 +5876,13 @@ isc__socket_register() {
} }
#endif #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) #if defined(HAVE_LIBXML2) && defined(BIND9)
static const char * static const char *

View File

@@ -88,6 +88,7 @@ isc__socket_close
isc__socket_connect isc__socket_connect
isc__socket_create isc__socket_create
isc__socket_detach isc__socket_detach
isc__socket_dup
isc__socket_filter isc__socket_filter
isc__socket_getname isc__socket_getname
isc__socket_getpeername isc__socket_getpeername

View File

@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE. * 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 /* This code uses functions which are only available on Server 2003 and
* higher, and Windows XP and higher. * higher, and Windows XP and higher.
@@ -265,7 +265,8 @@ struct isc_socket {
unsigned int listener : 1, /* listener socket */ unsigned int listener : 1, /* listener socket */
connected : 1, connected : 1,
pending_connect : 1, /* connect pending */ 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_iocp; /* Should equal the counters below. Debug. */
unsigned int pending_recv; /* Number of outstanding recv() calls. */ unsigned int pending_recv; /* Number of outstanding recv() calls. */
unsigned int pending_send; /* Number of outstanding send() calls. */ unsigned int pending_send; /* Number of outstanding send() calls. */
@@ -351,6 +352,10 @@ enum {
#define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER) #define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER)
#define MAXSCATTERGATHER_RECV (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 isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
static void maybe_free_socket(isc_socket_t **, int); static void maybe_free_socket(isc_socket_t **, int);
static void 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->connected = 0;
sock->pending_connect = 0; sock->pending_connect = 0;
sock->bound = 0; sock->bound = 0;
sock->dupped = 0;
memset(sock->name, 0, sizeof(sock->name)); // zero the name field memset(sock->name, 0, sizeof(sock->name)); // zero the name field
_set_state(sock, SOCK_INITIALIZED); _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 * called with 'arg' as the arg value. The new socket is returned
* in 'socketp'. * in 'socketp'.
*/ */
isc_result_t static isc_result_t
isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
isc_socket_t **socketp) { isc_socket_t **socketp, isc_socket_t *dup_socket)
{
isc_socket_t *sock = NULL; isc_socket_t *sock = NULL;
isc_result_t result; isc_result_t result;
#if defined(USE_CMSG) #if defined(USE_CMSG)
@@ -1647,27 +1654,35 @@ isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
return (result); return (result);
sock->pf = pf; sock->pf = pf;
switch (type) { if (dup_socket == NULL) {
case isc_sockettype_udp: switch (type) {
sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP); case isc_sockettype_udp:
if (sock->fd != INVALID_SOCKET) { sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
result = connection_reset_fix(sock->fd); if (sock->fd != INVALID_SOCKET) {
if (result != ISC_R_SUCCESS) { result = connection_reset_fix(sock->fd);
socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, if (result != ISC_R_SUCCESS) {
"closed %d %d %d con_reset_fix_failed", socket_log(__LINE__, sock,
sock->pending_recv, sock->pending_send, NULL, EVENT, NULL, 0, 0,
sock->references); "closed %d %d %d "
closesocket(sock->fd); "con_reset_fix_failed",
_set_state(sock, SOCK_CLOSED); sock->pending_recv,
sock->fd = INVALID_SOCKET; sock->pending_send,
free_socket(&sock, __LINE__); sock->references);
return (result); 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; } else {
case isc_sockettype_tcp: sock->fd = dup(dup_socket->fd);
sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP); sock->dupped = 1;
break;
} }
if (sock->fd == INVALID_SOCKET) { 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); InterlockedIncrement(&manager->totalSockets);
UNLOCK(&manager->lock); UNLOCK(&manager->lock);
socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat,
ISC_MSG_CREATED, "created %u type %u", sock->fd, type); ISC_MSGSET_SOCKET, ISC_MSG_CREATED,
"created %u type %u", sock->fd, type);
return (ISC_R_SUCCESS); 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_result_t
isc_socket_open(isc_socket_t *sock) { isc_socket_open(isc_socket_t *sock) {
REQUIRE(VALID_SOCKET(sock)); REQUIRE(VALID_SOCKET(sock));