diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index b01a8b2887..a4a30efbca 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.c,v 1.101.2.6.2.26 2008/06/26 22:19:00 jinmei Exp $ */ +/* $Id: dispatch.c,v 1.101.2.6.2.27 2008/07/03 00:15:08 each Exp $ */ #include @@ -799,6 +799,8 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) { */ static void deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { + isc_result_t result; + /* * The dispatch must be locked. */ @@ -811,8 +813,18 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) destroy_dispsocket(disp, &dispsock); else { - isc_socket_close(dispsock->socket); - ISC_LIST_APPEND(disp->inactivesockets, dispsock, link); + result = isc_socket_close(dispsock->socket); + if (result == ISC_R_SUCCESS) + ISC_LIST_APPEND(disp->inactivesockets, dispsock, link); + else { + /* + * If the underlying system does not allow this + * optimization, destroy this temporary structure (and + * create a new one for a new transaction). + */ + INSIST(result == ISC_R_NOTIMPLEMENTED); + destroy_dispsocket(disp, &dispsock); + } } } diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h index 95385b6cd1..29c086101a 100644 --- a/lib/isc/include/isc/socket.h +++ b/lib/isc/include/isc/socket.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.h,v 1.54.12.9 2008/06/25 23:45:37 tbox Exp $ */ +/* $Id: socket.h,v 1.54.12.10 2008/07/03 00:15:08 each Exp $ */ #ifndef ISC_SOCKET_H #define ISC_SOCKET_H 1 @@ -314,7 +314,8 @@ isc_socket_open(isc_socket_t *sock); * avoid overhead of destroying and creating sockets when many short-lived * sockets are frequently opened and closed. When the efficiency is not an * issue, it should be safer to detach the unused socket and re-create a new - * one. + * one. This optimization may not be available for some systems, in which + * case this function will return ISC_R_NOTIMPLEMENTED and must not be used. * * Requires: * @@ -324,15 +325,18 @@ isc_socket_open(isc_socket_t *sock); * * Returns: * Same as isc_socket_create(). + * \li ISC_R_NOTIMPLEMENTED */ -void +isc_result_t isc_socket_close(isc_socket_t *sock); /* * Close a socket file descriptor of the given socket structure. This function * is provided as an alternative to destroying an unused socket when overhead * destroying/re-creating sockets can be significant, and is expected to be - * used with isc_socket_open(). + * used with isc_socket_open(). This optimization may not be available for some + * systems, in which case this function will return ISC_R_NOTIMPLEMENTED and + * must not be used. * * Requires: * @@ -342,6 +346,8 @@ isc_socket_close(isc_socket_t *sock); * * \li There must be no pending I/O requests. * + * Returns: + * \li #ISC_R_NOTIMPLEMENTED */ isc_result_t diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 40c7721500..8e2b511fe3 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.207.2.19.2.39 2008/06/25 23:45:37 tbox Exp $ */ +/* $Id: socket.c,v 1.207.2.19.2.40 2008/07/03 00:15:09 each Exp $ */ #include @@ -2068,7 +2068,7 @@ isc_socket_detach(isc_socket_t **socketp) { *socketp = NULL; } -void +isc_result_t isc_socket_close(isc_socket_t *sock) { int fd; @@ -2102,6 +2102,8 @@ isc_socket_close(isc_socket_t *sock) { isc_sockaddr_any(&sock->address); closesocket(sock->manager, sock->type, fd); + + return (ISC_R_SUCCESS); } /* diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c index 41ad8505da..ecaee80744 100644 --- a/lib/isc/win32/socket.c +++ b/lib/isc/win32/socket.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.5.2.13.2.27 2008/07/01 05:40:13 jinmei Exp $ */ +/* $Id: socket.c,v 1.5.2.13.2.28 2008/07/03 00:15:09 each Exp $ */ /* This code has been rewritten to take advantage of Windows Sockets * I/O Completion Ports and Events. I/O Completion Ports is ONLY @@ -1166,7 +1166,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, memset(msg, 0, sizeof(*msg)); - if (!sock->connected) { + if (sock->type == isc_sockettype_udp) { msg->msg_name = (void *)&dev->address.type.sa; msg->msg_namelen = dev->address.length; } else { @@ -1855,8 +1855,16 @@ free_socket(isc_socket_t **socketp) { *socketp = NULL; } -static isc_result_t -internal_open(isc_socketmgr_t *manager, isc_socket_t *sock) { +/* + * 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_result_t +isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, + isc_socket_t **socketp) { + isc_socket_t *sock = NULL; isc_result_t result; #if defined(USE_CMSG) int on = 1; @@ -1864,9 +1872,17 @@ internal_open(isc_socketmgr_t *manager, isc_socket_t *sock) { int socket_errno; char strbuf[ISC_STRERRORSIZE]; - switch (sock->type) { + REQUIRE(VALID_MANAGER(manager)); + REQUIRE(socketp != NULL && *socketp == NULL); + + result = allocate_socket(manager, type, &sock); + if (result != ISC_R_SUCCESS) + return (result); + + sock->pf = pf; + switch (type) { case isc_sockettype_udp: - sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_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) { @@ -1877,12 +1893,13 @@ internal_open(isc_socketmgr_t *manager, isc_socket_t *sock) { } break; case isc_sockettype_tcp: - sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP); + sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP); break; } if (sock->fd == INVALID_SOCKET) { socket_errno = WSAGetLastError(); + free_socket(&sock); switch (socket_errno) { case WSAEMFILE: @@ -1910,17 +1927,18 @@ internal_open(isc_socketmgr_t *manager, isc_socket_t *sock) { result = make_nonblock(sock->fd); if (result != ISC_R_SUCCESS) { closesocket(sock->fd); + free_socket(&sock); return (result); } #if defined(USE_CMSG) - if (sock->type == isc_sockettype_udp) { + if (type == isc_sockettype_udp) { #if defined(ISC_PLATFORM_HAVEIPV6) #ifdef IPV6_RECVPKTINFO /* 2292bis */ - if ((sock->pf == AF_INET6) + if ((pf == AF_INET6) && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (void *)&on, sizeof(on)) < 0)) { isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); @@ -1935,7 +1953,7 @@ internal_open(isc_socketmgr_t *manager, isc_socket_t *sock) { } #else /* 2292 */ - if ((sock->pf == AF_INET6) + if ((pf == AF_INET6) && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO, (void *)&on, sizeof(on)) < 0)) { isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); @@ -1951,7 +1969,7 @@ internal_open(isc_socketmgr_t *manager, isc_socket_t *sock) { #endif /* IPV6_RECVPKTINFO */ #ifdef IPV6_USE_MIN_MTU /*2292bis, not too common yet*/ /* use minimum MTU */ - if (sock->pf == AF_INET6) { + if (pf == AF_INET6) { (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU, (void *)&on, sizeof(on)); @@ -1962,36 +1980,6 @@ internal_open(isc_socketmgr_t *manager, isc_socket_t *sock) { } #endif /* USE_CMSG */ - 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_result_t -isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, - isc_socket_t **socketp) { - isc_socket_t *sock = NULL; - isc_result_t result; - - REQUIRE(VALID_MANAGER(manager)); - REQUIRE(socketp != NULL && *socketp == NULL); - - result = allocate_socket(manager, type, &sock); - if (result != ISC_R_SUCCESS) - return (result); - - sock->pf = pf; - result = internal_open(manager, sock); - if (result != ISC_R_SUCCESS) { - free_socket(&sock); - return (result); - } - sock->references = 1; *socketp = sock; @@ -2013,25 +2001,9 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, isc_result_t isc_socket_open(isc_socket_t *sock) { - isc_result_t result; - REQUIRE(VALID_SOCKET(sock)); - LOCK(&sock->lock); - REQUIRE(sock->references == 1); - UNLOCK(&sock->lock); - - /* - * We don't need to retain the lock hereafter, since no one else has - * this socket. - */ - REQUIRE(sock->fd == -1); - - result = internal_open(sock->manager, sock); - if (result != ISC_R_SUCCESS) - sock->fd = -1; - - return (result); + return (ISC_R_NOTIMPLEMENTED); } /* @@ -2075,36 +2047,11 @@ isc_socket_detach(isc_socket_t **socketp) { *socketp = NULL; } -void +isc_result_t isc_socket_close(isc_socket_t *sock) { REQUIRE(VALID_SOCKET(sock)); - LOCK(&sock->lock); - REQUIRE(sock->references == 1); - UNLOCK(&sock->lock); - /* - * We don't need to retain the lock hereafter, since no one else has - * this socket. - */ - REQUIRE(sock->fd >= 0); - - INSIST(!sock->connecting); - INSIST(!sock->pending_recv); - INSIST(!sock->pending_send); - INSIST(!sock->pending_accept); - INSIST(ISC_LIST_EMPTY(sock->recv_list)); - INSIST(ISC_LIST_EMPTY(sock->send_list)); - INSIST(ISC_LIST_EMPTY(sock->accept_list)); - INSIST(sock->connect_ev == NULL); - - sock->fd = -1; - sock->listener = 0; - sock->connected = 0; - sock->connecting = 0; - sock->bound = 0; - isc_sockaddr_any(&sock->address); - - socket_close(sock); + return (ISC_R_NOTIMPLEMENTED); } /*