diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index f2f6911c25..6ffe1d0fcd 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.c,v 1.116.18.24 2008/06/26 22:18:18 jinmei Exp $ */ +/* $Id: dispatch.c,v 1.116.18.25 2008/07/03 00:14:39 each Exp $ */ /*! \file */ @@ -801,6 +801,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. */ @@ -813,8 +815,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 682f5d2275..4a7d542eb2 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.57.18.8 2008/06/24 23:45:55 tbox Exp $ */ +/* $Id: socket.h,v 1.57.18.9 2008/07/03 00:14:39 each Exp $ */ #ifndef ISC_SOCKET_H #define ISC_SOCKET_H 1 @@ -320,7 +320,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: * @@ -330,15 +331,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: * @@ -348,6 +352,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 ebdc99171f..7dfa1a68c6 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.237.18.37 2008/06/25 22:57:37 jinmei Exp $ */ +/* $Id: socket.c,v 1.237.18.38 2008/07/03 00:14:40 each Exp $ */ /*! \file */ @@ -2113,7 +2113,7 @@ isc_socket_detach(isc_socket_t **socketp) { *socketp = NULL; } -void +isc_result_t isc_socket_close(isc_socket_t *sock) { int fd; @@ -2147,6 +2147,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 be178d9876..bb58ad16f7 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.30.18.23 2008/07/01 02:10:06 each Exp $ */ +/* $Id: socket.c,v 1.30.18.24 2008/07/03 00:14:40 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 @@ -1171,7 +1171,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 { @@ -1867,8 +1867,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; @@ -1880,9 +1888,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) { @@ -1893,12 +1909,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: @@ -1926,17 +1943,19 @@ 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) || defined(SO_RCVBUF) - if (sock->type == isc_sockettype_udp) { + if (type == isc_sockettype_udp) { #if defined(USE_CMSG) #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)); @@ -1951,7 +1970,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)); @@ -1967,7 +1986,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)); @@ -1990,36 +2009,6 @@ internal_open(isc_socketmgr_t *manager, isc_socket_t *sock) { } #endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */ - 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; @@ -2041,25 +2030,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); } /* @@ -2103,36 +2076,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); } /*