Annotation of embedaddon/ntp/lib/isc/win32/socket.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
        !             3:  * Copyright (C) 2000-2003  Internet Software Consortium.
        !             4:  *
        !             5:  * Permission to use, copy, modify, and/or distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
        !            10:  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
        !            11:  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
        !            12:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
        !            13:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
        !            14:  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
        !            15:  * PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17: 
        !            18: /* $Id: socket.c,v 1.70.54.4 2009/01/29 22:40:36 jinmei Exp $ */
        !            19: 
        !            20: /* This code uses functions which are only available on Server 2003 and
        !            21:  * higher, and Windows XP and higher.
        !            22:  *
        !            23:  * This code is by nature multithreaded and takes advantage of various
        !            24:  * features to pass on information through the completion port for
        !            25:  * when I/O is completed.  All sends, receives, accepts, and connects are
        !            26:  * completed through the completion port.
        !            27:  *
        !            28:  * The number of Completion Port Worker threads used is the total number
        !            29:  * of CPU's + 1. This increases the likelihood that a Worker Thread is
        !            30:  * available for processing a completed request.
        !            31:  *
        !            32:  * XXXPDM 5 August, 2002
        !            33:  */
        !            34: 
        !            35: #define MAKE_EXTERNAL 1
        !            36: #include <config.h>
        !            37: 
        !            38: #include <sys/types.h>
        !            39: 
        !            40: #ifndef _WINSOCKAPI_
        !            41: #define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */
        !            42: #endif
        !            43: 
        !            44: #include <errno.h>
        !            45: #include <stddef.h>
        !            46: #include <stdlib.h>
        !            47: #include <string.h>
        !            48: #include <unistd.h>
        !            49: #include <io.h>
        !            50: #include <fcntl.h>
        !            51: #include <process.h>
        !            52: 
        !            53: #include <isc/buffer.h>
        !            54: #include <isc/bufferlist.h>
        !            55: #include <isc/condition.h>
        !            56: #include <isc/list.h>
        !            57: #include <isc/log.h>
        !            58: #include <isc/mem.h>
        !            59: #include <isc/msgs.h>
        !            60: #include <isc/mutex.h>
        !            61: #include <isc/net.h>
        !            62: #include <isc/once.h>
        !            63: #include <isc/os.h>
        !            64: #include <isc/platform.h>
        !            65: #include <isc/print.h>
        !            66: #include <isc/region.h>
        !            67: #include <isc/socket.h>
        !            68: #include <isc/stats.h>
        !            69: #include <isc/strerror.h>
        !            70: #include <isc/syslog.h>
        !            71: #include <isc/task.h>
        !            72: #include <isc/thread.h>
        !            73: #include <isc/util.h>
        !            74: #include <isc/win32os.h>
        !            75: 
        !            76: #include <mswsock.h>
        !            77: 
        !            78: #include "errno2result.h"
        !            79: 
        !            80: /*
        !            81:  * How in the world can Microsoft exist with APIs like this?
        !            82:  * We can't actually call this directly, because it turns out
        !            83:  * no library exports this function.  Instead, we need to
        !            84:  * issue a runtime call to get the address.
        !            85:  */
        !            86: LPFN_CONNECTEX ISCConnectEx;
        !            87: LPFN_ACCEPTEX ISCAcceptEx;
        !            88: LPFN_GETACCEPTEXSOCKADDRS ISCGetAcceptExSockaddrs;
        !            89: 
        !            90: /*
        !            91:  * Run expensive internal consistency checks.
        !            92:  */
        !            93: #ifdef ISC_SOCKET_CONSISTENCY_CHECKS
        !            94: #define CONSISTENT(sock) consistent(sock)
        !            95: #else
        !            96: #define CONSISTENT(sock) do {} while (0)
        !            97: #endif
        !            98: static void consistent(isc_socket_t *sock);
        !            99: 
        !           100: /*
        !           101:  * Define this macro to control the behavior of connection
        !           102:  * resets on UDP sockets.  See Microsoft KnowledgeBase Article Q263823
        !           103:  * for details.
        !           104:  * NOTE: This requires that Windows 2000 systems install Service Pack 2
        !           105:  * or later.
        !           106:  */
        !           107: #ifndef SIO_UDP_CONNRESET
        !           108: #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
        !           109: #endif
        !           110: 
        !           111: /*
        !           112:  * Some systems define the socket length argument as an int, some as size_t,
        !           113:  * some as socklen_t.  This is here so it can be easily changed if needed.
        !           114:  */
        !           115: #ifndef ISC_SOCKADDR_LEN_T
        !           116: #define ISC_SOCKADDR_LEN_T unsigned int
        !           117: #endif
        !           118: 
        !           119: /*
        !           120:  * Define what the possible "soft" errors can be.  These are non-fatal returns
        !           121:  * of various network related functions, like recv() and so on.
        !           122:  */
        !           123: #define SOFT_ERROR(e)  ((e) == WSAEINTR || \
        !           124:                         (e) == WSAEWOULDBLOCK || \
        !           125:                         (e) == EWOULDBLOCK || \
        !           126:                         (e) == EINTR || \
        !           127:                         (e) == EAGAIN || \
        !           128:                         (e) == 0)
        !           129: 
        !           130: /*
        !           131:  * Pending errors are not really errors and should be
        !           132:  * kept separate
        !           133:  */
        !           134: #define PENDING_ERROR(e) ((e) == WSA_IO_PENDING || (e) == 0)
        !           135: 
        !           136: #define DOIO_SUCCESS     0       /* i/o ok, event sent */
        !           137: #define DOIO_SOFT        1       /* i/o ok, soft error, no event sent */
        !           138: #define DOIO_HARD        2       /* i/o error, event sent */
        !           139: #define DOIO_EOF         3       /* EOF, no event sent */
        !           140: #define DOIO_PENDING     4       /* status when i/o is in process */
        !           141: #define DOIO_NEEDMORE    5       /* IO was processed, but we need more due to minimum */
        !           142: 
        !           143: #define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x)
        !           144: 
        !           145: /*
        !           146:  * DLVL(90)  --  Function entry/exit and other tracing.
        !           147:  * DLVL(70)  --  Socket "correctness" -- including returning of events, etc.
        !           148:  * DLVL(60)  --  Socket data send/receive
        !           149:  * DLVL(50)  --  Event tracing, including receiving/sending completion events.
        !           150:  * DLVL(20)  --  Socket creation/destruction.
        !           151:  */
        !           152: #define TRACE_LEVEL            90
        !           153: #define CORRECTNESS_LEVEL      70
        !           154: #define IOEVENT_LEVEL          60
        !           155: #define EVENT_LEVEL            50
        !           156: #define CREATION_LEVEL         20
        !           157: 
        !           158: #define TRACE          DLVL(TRACE_LEVEL)
        !           159: #define CORRECTNESS    DLVL(CORRECTNESS_LEVEL)
        !           160: #define IOEVENT                DLVL(IOEVENT_LEVEL)
        !           161: #define EVENT          DLVL(EVENT_LEVEL)
        !           162: #define CREATION       DLVL(CREATION_LEVEL)
        !           163: 
        !           164: typedef isc_event_t intev_t;
        !           165: 
        !           166: /*
        !           167:  * Socket State
        !           168:  */
        !           169: enum {
        !           170:   SOCK_INITIALIZED,    /* Socket Initialized */
        !           171:   SOCK_OPEN,           /* Socket opened but nothing yet to do */
        !           172:   SOCK_DATA,           /* Socket sending or receiving data */
        !           173:   SOCK_LISTEN,         /* TCP Socket listening for connects */
        !           174:   SOCK_ACCEPT,         /* TCP socket is waiting to accept */
        !           175:   SOCK_CONNECT,                /* TCP Socket connecting */
        !           176:   SOCK_CLOSED,         /* Socket has been closed */
        !           177: };
        !           178: 
        !           179: #define SOCKET_MAGIC           ISC_MAGIC('I', 'O', 'i', 'o')
        !           180: #define VALID_SOCKET(t)                ISC_MAGIC_VALID(t, SOCKET_MAGIC)
        !           181: 
        !           182: /*
        !           183:  * IPv6 control information.  If the socket is an IPv6 socket we want
        !           184:  * to collect the destination address and interface so the client can
        !           185:  * set them on outgoing packets.
        !           186:  */
        !           187: #ifdef ISC_PLATFORM_HAVEIPV6
        !           188: #ifndef USE_CMSG
        !           189: #define USE_CMSG       1
        !           190: #endif
        !           191: #endif
        !           192: 
        !           193: /*
        !           194:  * We really  don't want to try and use these control messages. Win32
        !           195:  * doesn't have this mechanism before XP.
        !           196:  */
        !           197: #undef USE_CMSG
        !           198: 
        !           199: /*
        !           200:  * Message header for recvmsg and sendmsg calls.
        !           201:  * Used value-result for recvmsg, value only for sendmsg.
        !           202:  */
        !           203: struct msghdr {
        !           204:        SOCKADDR_STORAGE to_addr;       /* UDP send/recv address */
        !           205:        int      to_addr_len;           /* length of the address */
        !           206:        WSABUF  *msg_iov;               /* scatter/gather array */
        !           207:        u_int   msg_iovlen;             /* # elements in msg_iov */
        !           208:        void    *msg_control;           /* ancillary data, see below */
        !           209:        u_int   msg_controllen;         /* ancillary data buffer len */
        !           210:        int     msg_totallen;           /* total length of this message */
        !           211: } msghdr;
        !           212: 
        !           213: /*
        !           214:  * The size to raise the receive buffer to.
        !           215:  */
        !           216: #define RCVBUFSIZE (32*1024)
        !           217: 
        !           218: /*
        !           219:  * The number of times a send operation is repeated if the result
        !           220:  * is WSAEINTR.
        !           221:  */
        !           222: #define NRETRIES 10
        !           223: 
        !           224: struct isc_socket {
        !           225:        /* Not locked. */
        !           226:        unsigned int            magic;
        !           227:        isc_socketmgr_t        *manager;
        !           228:        isc_mutex_t             lock;
        !           229:        isc_sockettype_t        type;
        !           230: 
        !           231:        /* Pointers to scatter/gather buffers */
        !           232:        WSABUF                  iov[ISC_SOCKET_MAXSCATTERGATHER];
        !           233: 
        !           234:        /* Locked by socket lock. */
        !           235:        ISC_LINK(isc_socket_t)  link;
        !           236:        unsigned int            references; /* EXTERNAL references */
        !           237:        SOCKET                  fd;     /* file handle */
        !           238:        int                     pf;     /* protocol family */
        !           239:        char                    name[16];
        !           240:        void *                  tag;
        !           241: 
        !           242:        /*
        !           243:         * Each recv() call uses this buffer.  It is a per-socket receive
        !           244:         * buffer that allows us to decouple the system recv() from the
        !           245:         * recv_list done events.  This means the items on the recv_list
        !           246:         * can be removed without having to cancel pending system recv()
        !           247:         * calls.  It also allows us to read-ahead in some cases.
        !           248:         */
        !           249:        struct {
        !           250:                SOCKADDR_STORAGE        from_addr;         // UDP send/recv address
        !           251:                int             from_addr_len;     // length of the address
        !           252:                char            *base;             // the base of the buffer
        !           253:                char            *consume_position; // where to start copying data from next
        !           254:                unsigned int    len;               // the actual size of this buffer
        !           255:                unsigned int    remaining;         // the number of bytes remaining
        !           256:        } recvbuf;
        !           257: 
        !           258:        ISC_LIST(isc_socketevent_t)             send_list;
        !           259:        ISC_LIST(isc_socketevent_t)             recv_list;
        !           260:        ISC_LIST(isc_socket_newconnev_t)        accept_list;
        !           261:        isc_socket_connev_t                    *connect_ev;
        !           262: 
        !           263:        isc_sockaddr_t          address;  /* remote address */
        !           264: 
        !           265:        unsigned int            listener : 1,   /* listener socket */
        !           266:                                connected : 1,
        !           267:                                pending_connect : 1, /* connect pending */
        !           268:                                bound : 1;      /* bound to local addr */
        !           269:        unsigned int            pending_iocp;   /* Should equal the counters below. Debug. */
        !           270:        unsigned int            pending_recv;  /* Number of outstanding recv() calls. */
        !           271:        unsigned int            pending_send;  /* Number of outstanding send() calls. */
        !           272:        unsigned int            pending_accept; /* Number of outstanding accept() calls. */
        !           273:        unsigned int            state; /* Socket state. Debugging and consistency checking. */
        !           274:        int                     state_lineno;  /* line which last touched state */
        !           275: };
        !           276: 
        !           277: #define _set_state(sock, _state) do { (sock)->state = (_state); (sock)->state_lineno = __LINE__; } while (0)
        !           278: 
        !           279: /*
        !           280:  * Buffer structure
        !           281:  */
        !           282: typedef struct buflist buflist_t;
        !           283: 
        !           284: struct buflist {
        !           285:        void                    *buf;
        !           286:        unsigned int            buflen;
        !           287:        ISC_LINK(buflist_t)     link;
        !           288: };
        !           289: 
        !           290: /*
        !           291:  * I/O Completion ports Info structures
        !           292:  */
        !           293: 
        !           294: static HANDLE hHeapHandle = NULL;
        !           295: typedef struct IoCompletionInfo {
        !           296:        OVERLAPPED              overlapped;
        !           297:        isc_socketevent_t       *dev;  /* send()/recv() done event */
        !           298:        isc_socket_connev_t     *cdev; /* connect() done event */
        !           299:        isc_socket_newconnev_t  *adev; /* accept() done event */
        !           300:        void                    *acceptbuffer;
        !           301:        DWORD                   received_bytes;
        !           302:        int                     request_type;
        !           303:        struct msghdr           messagehdr;
        !           304:        ISC_LIST(buflist_t)     bufferlist;     /*%< list of buffers */
        !           305: } IoCompletionInfo;
        !           306: 
        !           307: /*
        !           308:  * Define a maximum number of I/O Completion Port worker threads
        !           309:  * to handle the load on the Completion Port. The actual number
        !           310:  * used is the number of CPU's + 1.
        !           311:  */
        !           312: #define MAX_IOCPTHREADS 20
        !           313: 
        !           314: #define SOCKET_MANAGER_MAGIC   ISC_MAGIC('I', 'O', 'm', 'g')
        !           315: #define VALID_MANAGER(m)       ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)
        !           316: 
        !           317: struct isc_socketmgr {
        !           318:        /* Not locked. */
        !           319:        unsigned int                    magic;
        !           320:        isc_mem_t                      *mctx;
        !           321:        isc_mutex_t                     lock;
        !           322:        isc_stats_t                    *stats;
        !           323: 
        !           324:        /* Locked by manager lock. */
        !           325:        ISC_LIST(isc_socket_t)          socklist;
        !           326:        isc_boolean_t                   bShutdown;
        !           327:        isc_condition_t                 shutdown_ok;
        !           328:        HANDLE                          hIoCompletionPort;
        !           329:        int                             maxIOCPThreads;
        !           330:        HANDLE                          hIOCPThreads[MAX_IOCPTHREADS];
        !           331:        DWORD                           dwIOCPThreadIds[MAX_IOCPTHREADS];
        !           332: 
        !           333:        /*
        !           334:         * Debugging.
        !           335:         * Modified by InterlockedIncrement() and InterlockedDecrement()
        !           336:         */
        !           337:        LONG                            totalSockets;
        !           338:        LONG                            iocp_total;
        !           339: };
        !           340: 
        !           341: enum {
        !           342:        SOCKET_RECV,
        !           343:        SOCKET_SEND,
        !           344:        SOCKET_ACCEPT,
        !           345:        SOCKET_CONNECT
        !           346: };
        !           347: 
        !           348: /*
        !           349:  * send() and recv() iovec counts
        !           350:  */
        !           351: #define MAXSCATTERGATHER_SEND  (ISC_SOCKET_MAXSCATTERGATHER)
        !           352: #define MAXSCATTERGATHER_RECV  (ISC_SOCKET_MAXSCATTERGATHER)
        !           353: 
        !           354: static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
        !           355: static void maybe_free_socket(isc_socket_t **, int);
        !           356: static void free_socket(isc_socket_t **, int);
        !           357: static isc_boolean_t senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev);
        !           358: static isc_boolean_t acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev);
        !           359: static isc_boolean_t connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev);
        !           360: static void send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev);
        !           361: static void send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev);
        !           362: static void send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev);
        !           363: static void send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev);
        !           364: static void send_recvdone_abort(isc_socket_t *sock, isc_result_t result);
        !           365: static void queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev);
        !           366: static void queue_receive_request(isc_socket_t *sock);
        !           367: 
        !           368: /*
        !           369:  * This is used to dump the contents of the sock structure
        !           370:  * You should make sure that the sock is locked before
        !           371:  * dumping it. Since the code uses simple printf() statements
        !           372:  * it should only be used interactively.
        !           373:  */
        !           374: void
        !           375: sock_dump(isc_socket_t *sock) {
        !           376:        isc_socketevent_t *ldev;
        !           377:        isc_socket_newconnev_t *ndev;
        !           378: 
        !           379: #if 0
        !           380:        isc_sockaddr_t addr;
        !           381:        char socktext[256];
        !           382: 
        !           383:        isc_socket_getpeername(sock, &addr);
        !           384:        isc_sockaddr_format(&addr, socktext, sizeof(socktext));
        !           385:        printf("Remote Socket: %s\n", socktext);
        !           386:        isc_socket_getsockname(sock, &addr);
        !           387:        isc_sockaddr_format(&addr, socktext, sizeof(socktext));
        !           388:        printf("This Socket: %s\n", socktext);
        !           389: #endif
        !           390: 
        !           391:        printf("\n\t\tSock Dump\n");
        !           392:        printf("\t\tfd: %u\n", sock->fd);
        !           393:        printf("\t\treferences: %d\n", sock->references);
        !           394:        printf("\t\tpending_accept: %d\n", sock->pending_accept);
        !           395:        printf("\t\tconnecting: %d\n", sock->pending_connect);
        !           396:        printf("\t\tconnected: %d\n", sock->connected);
        !           397:        printf("\t\tbound: %d\n", sock->bound);
        !           398:        printf("\t\tpending_iocp: %d\n", sock->pending_iocp);
        !           399:        printf("\t\tsocket type: %d\n", sock->type);
        !           400: 
        !           401:        printf("\n\t\tSock Recv List\n");
        !           402:        ldev = ISC_LIST_HEAD(sock->recv_list);
        !           403:        while (ldev != NULL) {
        !           404:                printf("\t\tdev: %p\n", ldev);
        !           405:                ldev = ISC_LIST_NEXT(ldev, ev_link);
        !           406:        }
        !           407: 
        !           408:        printf("\n\t\tSock Send List\n");
        !           409:        ldev = ISC_LIST_HEAD(sock->send_list);
        !           410:        while (ldev != NULL) {
        !           411:                printf("\t\tdev: %p\n", ldev);
        !           412:                ldev = ISC_LIST_NEXT(ldev, ev_link);
        !           413:        }
        !           414: 
        !           415:        printf("\n\t\tSock Accept List\n");
        !           416:        ndev = ISC_LIST_HEAD(sock->accept_list);
        !           417:        while (ndev != NULL) {
        !           418:                printf("\t\tdev: %p\n", ldev);
        !           419:                ndev = ISC_LIST_NEXT(ndev, ev_link);
        !           420:        }
        !           421: }
        !           422: 
        !           423: static void
        !           424: socket_log(int lineno, isc_socket_t *sock, isc_sockaddr_t *address,
        !           425:           isc_logcategory_t *category, isc_logmodule_t *module, int level,
        !           426:           isc_msgcat_t *msgcat, int msgset, int message,
        !           427:           const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10);
        !           428: 
        !           429: /*  This function will add an entry to the I/O completion port
        !           430:  *  that will signal the I/O thread to exit (gracefully)
        !           431:  */
        !           432: static void
        !           433: signal_iocompletionport_exit(isc_socketmgr_t *manager) {
        !           434:        int i;
        !           435:        int errval;
        !           436:        char strbuf[ISC_STRERRORSIZE];
        !           437: 
        !           438:        REQUIRE(VALID_MANAGER(manager));
        !           439:        for (i = 0; i < manager->maxIOCPThreads; i++) {
        !           440:                if (!PostQueuedCompletionStatus(manager->hIoCompletionPort,
        !           441:                                                0, 0, 0)) {
        !           442:                        errval = GetLastError();
        !           443:                        isc__strerror(errval, strbuf, sizeof(strbuf));
        !           444:                        FATAL_ERROR(__FILE__, __LINE__,
        !           445:                                isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
        !           446:                                ISC_MSG_FAILED,
        !           447:                                "Can't request service thread to exit: %s"),
        !           448:                                strbuf);
        !           449:                }
        !           450:        }
        !           451: }
        !           452: 
        !           453: /*
        !           454:  * Create the worker threads for the I/O Completion Port
        !           455:  */
        !           456: void
        !           457: iocompletionport_createthreads(int total_threads, isc_socketmgr_t *manager) {
        !           458:        int errval;
        !           459:        char strbuf[ISC_STRERRORSIZE];
        !           460:        int i;
        !           461: 
        !           462:        INSIST(total_threads > 0);
        !           463:        REQUIRE(VALID_MANAGER(manager));
        !           464:        /*
        !           465:         * We need at least one
        !           466:         */
        !           467:        for (i = 0; i < total_threads; i++) {
        !           468:                manager->hIOCPThreads[i] = CreateThread(NULL, 0, SocketIoThread,
        !           469:                                                manager, 0,
        !           470:                                                &manager->dwIOCPThreadIds[i]);
        !           471:                if (manager->hIOCPThreads[i] == NULL) {
        !           472:                        errval = GetLastError();
        !           473:                        isc__strerror(errval, strbuf, sizeof(strbuf));
        !           474:                        FATAL_ERROR(__FILE__, __LINE__,
        !           475:                                isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
        !           476:                                ISC_MSG_FAILED,
        !           477:                                "Can't create IOCP thread: %s"),
        !           478:                                strbuf);
        !           479:                        exit(1);
        !           480:                }
        !           481:        }
        !           482: }
        !           483: 
        !           484: /*
        !           485:  *  Create/initialise the I/O completion port
        !           486:  */
        !           487: void
        !           488: iocompletionport_init(isc_socketmgr_t *manager) {
        !           489:        int errval;
        !           490:        char strbuf[ISC_STRERRORSIZE];
        !           491: 
        !           492:        REQUIRE(VALID_MANAGER(manager));
        !           493:        /*
        !           494:         * Create a private heap to handle the socket overlapped structure
        !           495:         * The minimum number of structures is 10, there is no maximum
        !           496:         */
        !           497:        hHeapHandle = HeapCreate(0, 10 * sizeof(IoCompletionInfo), 0);
        !           498:        if (hHeapHandle == NULL) {
        !           499:                errval = GetLastError();
        !           500:                isc__strerror(errval, strbuf, sizeof(strbuf));
        !           501:                FATAL_ERROR(__FILE__, __LINE__,
        !           502:                            isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
        !           503:                                           ISC_MSG_FAILED,
        !           504:                                           "HeapCreate() failed during "
        !           505:                                           "initialization: %s"),
        !           506:                            strbuf);
        !           507:                exit(1);
        !           508:        }
        !           509: 
        !           510:        manager->maxIOCPThreads = min(isc_os_ncpus() + 1, MAX_IOCPTHREADS);
        !           511: 
        !           512:        /* Now Create the Completion Port */
        !           513:        manager->hIoCompletionPort = CreateIoCompletionPort(
        !           514:                        INVALID_HANDLE_VALUE, NULL,
        !           515:                        0, manager->maxIOCPThreads);
        !           516:        if (manager->hIoCompletionPort == NULL) {
        !           517:                errval = GetLastError();
        !           518:                isc__strerror(errval, strbuf, sizeof(strbuf));
        !           519:                FATAL_ERROR(__FILE__, __LINE__,
        !           520:                                isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
        !           521:                                ISC_MSG_FAILED,
        !           522:                                "CreateIoCompletionPort() failed "
        !           523:                                "during initialization: %s"),
        !           524:                                strbuf);
        !           525:                exit(1);
        !           526:        }
        !           527: 
        !           528:        /*
        !           529:         * Worker threads for servicing the I/O
        !           530:         */
        !           531:        iocompletionport_createthreads(manager->maxIOCPThreads, manager);
        !           532: }
        !           533: 
        !           534: /*
        !           535:  * Associate a socket with an IO Completion Port.  This allows us to queue events for it
        !           536:  * and have our worker pool of threads process them.
        !           537:  */
        !           538: void
        !           539: iocompletionport_update(isc_socket_t *sock) {
        !           540:        HANDLE hiocp;
        !           541:        char strbuf[ISC_STRERRORSIZE];
        !           542: 
        !           543:        REQUIRE(VALID_SOCKET(sock));
        !           544: 
        !           545:        hiocp = CreateIoCompletionPort((HANDLE)sock->fd,
        !           546:                sock->manager->hIoCompletionPort, (ULONG_PTR)sock, 0);
        !           547: 
        !           548:        if (hiocp == NULL) {
        !           549:                DWORD errval = GetLastError();
        !           550:                isc__strerror(errval, strbuf, sizeof(strbuf));
        !           551:                isc_log_iwrite(isc_lctx,
        !           552:                                ISC_LOGCATEGORY_GENERAL,
        !           553:                                ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
        !           554:                                isc_msgcat, ISC_MSGSET_SOCKET,
        !           555:                                ISC_MSG_TOOMANYHANDLES,
        !           556:                                "iocompletionport_update: failed to open"
        !           557:                                " io completion port: %s",
        !           558:                                strbuf);
        !           559: 
        !           560:                /* XXXMLG temporary hack to make failures detected.
        !           561:                 * This function should return errors to the caller, not
        !           562:                 * exit here.
        !           563:                 */
        !           564:                FATAL_ERROR(__FILE__, __LINE__,
        !           565:                                isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
        !           566:                                ISC_MSG_FAILED,
        !           567:                                "CreateIoCompletionPort() failed "
        !           568:                                "during initialization: %s"),
        !           569:                                strbuf);
        !           570:                exit(1);
        !           571:        }
        !           572: 
        !           573:        InterlockedIncrement(&sock->manager->iocp_total);
        !           574: }
        !           575: 
        !           576: /*
        !           577:  * Routine to cleanup and then close the socket.
        !           578:  * Only close the socket here if it is NOT associated
        !           579:  * with an event, otherwise the WSAWaitForMultipleEvents
        !           580:  * may fail due to the fact that the Wait should not
        !           581:  * be running while closing an event or a socket.
        !           582:  * The socket is locked before calling this function
        !           583:  */
        !           584: void
        !           585: socket_close(isc_socket_t *sock) {
        !           586: 
        !           587:        REQUIRE(sock != NULL);
        !           588: 
        !           589:        if (sock->fd != INVALID_SOCKET) {
        !           590:                closesocket(sock->fd);
        !           591:                sock->fd = INVALID_SOCKET;
        !           592:                _set_state(sock, SOCK_CLOSED);
        !           593:                InterlockedDecrement(&sock->manager->totalSockets);
        !           594:        }
        !           595: }
        !           596: 
        !           597: static isc_once_t initialise_once = ISC_ONCE_INIT;
        !           598: static isc_boolean_t initialised = ISC_FALSE;
        !           599: 
        !           600: static void
        !           601: initialise(void) {
        !           602:        WORD wVersionRequested;
        !           603:        WSADATA wsaData;
        !           604:        int err;
        !           605:        SOCKET sock;
        !           606:        GUID GUIDConnectEx = WSAID_CONNECTEX;
        !           607:        GUID GUIDAcceptEx = WSAID_ACCEPTEX;
        !           608:        GUID GUIDGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
        !           609:        DWORD dwBytes;
        !           610: 
        !           611:        /* Need Winsock 2.2 or better */
        !           612:        wVersionRequested = MAKEWORD(2, 2);
        !           613: 
        !           614:        err = WSAStartup(wVersionRequested, &wsaData);
        !           615:        if (err != 0) {
        !           616:                char strbuf[ISC_STRERRORSIZE];
        !           617:                isc__strerror(err, strbuf, sizeof(strbuf));
        !           618:                FATAL_ERROR(__FILE__, __LINE__, "WSAStartup() %s: %s",
        !           619:                            isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
        !           620:                                           ISC_MSG_FAILED, "failed"),
        !           621:                            strbuf);
        !           622:                exit(1);
        !           623:        }
        !           624:        /*
        !           625:         * The following APIs do not exist as functions in a library, but we must
        !           626:         * ask winsock for them.  They are "extensions" -- but why they cannot be
        !           627:         * actual functions is beyond me.  So, ask winsock for the pointers to the
        !           628:         * functions we need.
        !           629:         */
        !           630:        sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        !           631:        INSIST(sock != INVALID_SOCKET);
        !           632:        err = WSAIoctl(sock,  SIO_GET_EXTENSION_FUNCTION_POINTER,
        !           633:                 &GUIDConnectEx, sizeof(GUIDConnectEx),
        !           634:                 &ISCConnectEx, sizeof(ISCConnectEx),
        !           635:                 &dwBytes, NULL, NULL);
        !           636:        INSIST(err == 0);
        !           637: 
        !           638:        err = WSAIoctl(sock,  SIO_GET_EXTENSION_FUNCTION_POINTER,
        !           639:                 &GUIDAcceptEx, sizeof(GUIDAcceptEx),
        !           640:                 &ISCAcceptEx, sizeof(ISCAcceptEx),
        !           641:                 &dwBytes, NULL, NULL);
        !           642:        INSIST(err == 0);
        !           643: 
        !           644:        err = WSAIoctl(sock,  SIO_GET_EXTENSION_FUNCTION_POINTER,
        !           645:                 &GUIDGetAcceptExSockaddrs, sizeof(GUIDGetAcceptExSockaddrs),
        !           646:                 &ISCGetAcceptExSockaddrs, sizeof(ISCGetAcceptExSockaddrs),
        !           647:                 &dwBytes, NULL, NULL);
        !           648:        INSIST(err == 0);
        !           649: 
        !           650:        closesocket(sock);
        !           651: 
        !           652:        initialised = ISC_TRUE;
        !           653: }
        !           654: 
        !           655: /*
        !           656:  * Initialize socket services
        !           657:  */
        !           658: void
        !           659: InitSockets(void) {
        !           660:        RUNTIME_CHECK(isc_once_do(&initialise_once,
        !           661:                                  initialise) == ISC_R_SUCCESS);
        !           662:        if (!initialised)
        !           663:                exit(1);
        !           664: }
        !           665: 
        !           666: int
        !           667: internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
        !           668:                 struct msghdr *messagehdr, int flags, int *Error)
        !           669: {
        !           670:        int Result;
        !           671:        DWORD BytesSent;
        !           672:        DWORD Flags = flags;
        !           673:        int total_sent;
        !           674: 
        !           675:        *Error = 0;
        !           676:        Result = WSASendTo(sock->fd, messagehdr->msg_iov,
        !           677:                           messagehdr->msg_iovlen, &BytesSent,
        !           678:                           Flags, (SOCKADDR *)&messagehdr->to_addr,
        !           679:                           messagehdr->to_addr_len, (LPWSAOVERLAPPED)lpo,
        !           680:                           NULL);
        !           681: 
        !           682:        total_sent = (int)BytesSent;
        !           683: 
        !           684:        /* Check for errors.*/
        !           685:        if (Result == SOCKET_ERROR) {
        !           686:                *Error = WSAGetLastError();
        !           687: 
        !           688:                switch (*Error) {
        !           689:                case WSA_IO_INCOMPLETE:
        !           690:                case WSA_WAIT_IO_COMPLETION:
        !           691:                case WSA_IO_PENDING:
        !           692:                case NO_ERROR:          /* Strange, but okay */
        !           693:                        sock->pending_iocp++;
        !           694:                        sock->pending_send++;
        !           695:                        break;
        !           696: 
        !           697:                default:
        !           698:                        return (-1);
        !           699:                        break;
        !           700:                }
        !           701:        } else {
        !           702:                sock->pending_iocp++;
        !           703:                sock->pending_send++;
        !           704:        }
        !           705: 
        !           706:        if (lpo != NULL)
        !           707:                return (0);
        !           708:        else
        !           709:                return (total_sent);
        !           710: }
        !           711: 
        !           712: static void
        !           713: queue_receive_request(isc_socket_t *sock) {
        !           714:        DWORD Flags = 0;
        !           715:        DWORD NumBytes = 0;
        !           716:        int total_bytes = 0;
        !           717:        int Result;
        !           718:        int Error;
        !           719:        WSABUF iov[1];
        !           720:        IoCompletionInfo *lpo;
        !           721:        isc_result_t isc_result;
        !           722: 
        !           723:        /*
        !           724:         * If we already have a receive pending, do nothing.
        !           725:         */
        !           726:        if (sock->pending_recv > 0)
        !           727:                return;
        !           728: 
        !           729:        /*
        !           730:         * If no one is waiting, do nothing.
        !           731:         */
        !           732:        if (ISC_LIST_EMPTY(sock->recv_list))
        !           733:                return;
        !           734: 
        !           735:        INSIST(sock->recvbuf.remaining == 0);
        !           736:        INSIST(sock->fd != INVALID_SOCKET);
        !           737: 
        !           738:        iov[0].len = sock->recvbuf.len;
        !           739:        iov[0].buf = sock->recvbuf.base;
        !           740: 
        !           741:        lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
        !           742:                                            HEAP_ZERO_MEMORY,
        !           743:                                            sizeof(IoCompletionInfo));
        !           744:        RUNTIME_CHECK(lpo != NULL);
        !           745:        lpo->request_type = SOCKET_RECV;
        !           746: 
        !           747:        sock->recvbuf.from_addr_len = sizeof(sock->recvbuf.from_addr);
        !           748: 
        !           749:        Error = 0;
        !           750:        Result = WSARecvFrom((SOCKET)sock->fd, iov, 1,
        !           751:                             &NumBytes, &Flags,
        !           752:                             (SOCKADDR *)&sock->recvbuf.from_addr,
        !           753:                             &sock->recvbuf.from_addr_len,
        !           754:                             (LPWSAOVERLAPPED)lpo, NULL);
        !           755: 
        !           756:        /* Check for errors. */
        !           757:        if (Result == SOCKET_ERROR) {
        !           758:                Error = WSAGetLastError();
        !           759: 
        !           760:                switch (Error) {
        !           761:                case WSA_IO_PENDING:
        !           762:                        sock->pending_iocp++;
        !           763:                        sock->pending_recv++;
        !           764:                        break;
        !           765: 
        !           766:                default:
        !           767:                        isc_result = isc__errno2result(Error);
        !           768:                        if (isc_result == ISC_R_UNEXPECTED)
        !           769:                                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           770:                                        "WSARecvFrom: Windows error code: %d, isc result %d",
        !           771:                                        Error, isc_result);
        !           772:                        send_recvdone_abort(sock, isc_result);
        !           773:                        break;
        !           774:                }
        !           775:        } else {
        !           776:                /*
        !           777:                 * The recv() finished immediately, but we will still get
        !           778:                 * a completion event.  Rather than duplicate code, let
        !           779:                 * that thread handle sending the data along its way.
        !           780:                 */
        !           781:                sock->pending_iocp++;
        !           782:                sock->pending_recv++;
        !           783:        }
        !           784: 
        !           785:        socket_log(__LINE__, sock, NULL, IOEVENT,
        !           786:                   isc_msgcat, ISC_MSGSET_SOCKET,
        !           787:                   ISC_MSG_DOIORECV,
        !           788:                   "queue_io_request: fd %d result %d error %d",
        !           789:                   sock->fd, Result, Error);
        !           790: 
        !           791:        CONSISTENT(sock);
        !           792: }
        !           793: 
        !           794: static void
        !           795: manager_log(isc_socketmgr_t *sockmgr, isc_logcategory_t *category,
        !           796:            isc_logmodule_t *module, int level, const char *fmt, ...)
        !           797: {
        !           798:        char msgbuf[2048];
        !           799:        va_list ap;
        !           800: 
        !           801:        if (!isc_log_wouldlog(isc_lctx, level))
        !           802:                return;
        !           803: 
        !           804:        va_start(ap, fmt);
        !           805:        vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
        !           806:        va_end(ap);
        !           807: 
        !           808:        isc_log_write(isc_lctx, category, module, level,
        !           809:                      "sockmgr %p: %s", sockmgr, msgbuf);
        !           810: }
        !           811: 
        !           812: static void
        !           813: socket_log(int lineno, isc_socket_t *sock, isc_sockaddr_t *address,
        !           814:           isc_logcategory_t *category, isc_logmodule_t *module, int level,
        !           815:           isc_msgcat_t *msgcat, int msgset, int message,
        !           816:           const char *fmt, ...)
        !           817: {
        !           818:        char msgbuf[2048];
        !           819:        char peerbuf[256];
        !           820:        va_list ap;
        !           821: 
        !           822: 
        !           823:        if (!isc_log_wouldlog(isc_lctx, level))
        !           824:                return;
        !           825: 
        !           826:        va_start(ap, fmt);
        !           827:        vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
        !           828:        va_end(ap);
        !           829: 
        !           830:        if (address == NULL) {
        !           831:                isc_log_iwrite(isc_lctx, category, module, level,
        !           832:                               msgcat, msgset, message,
        !           833:                               "socket %p line %d: %s", sock, lineno, msgbuf);
        !           834:        } else {
        !           835:                isc_sockaddr_format(address, peerbuf, sizeof(peerbuf));
        !           836:                isc_log_iwrite(isc_lctx, category, module, level,
        !           837:                               msgcat, msgset, message,
        !           838:                                   "socket %p line %d peer %s: %s", sock, lineno,
        !           839:                                   peerbuf, msgbuf);
        !           840:        }
        !           841: 
        !           842: }
        !           843: 
        !           844: /*
        !           845:  * Make an fd SOCKET non-blocking.
        !           846:  */
        !           847: static isc_result_t
        !           848: make_nonblock(SOCKET fd) {
        !           849:        int ret;
        !           850:        unsigned long flags = 1;
        !           851:        char strbuf[ISC_STRERRORSIZE];
        !           852: 
        !           853:        /* Set the socket to non-blocking */
        !           854:        ret = ioctlsocket(fd, FIONBIO, &flags);
        !           855: 
        !           856:        if (ret == -1) {
        !           857:                isc__strerror(errno, strbuf, sizeof(strbuf));
        !           858:                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           859:                                 "ioctlsocket(%d, FIOBIO, %d): %s",
        !           860:                                 fd, flags, strbuf);
        !           861: 
        !           862:                return (ISC_R_UNEXPECTED);
        !           863:        }
        !           864: 
        !           865:        return (ISC_R_SUCCESS);
        !           866: }
        !           867: 
        !           868: /*
        !           869:  * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
        !           870:  * to not work correctly, returning a WSACONNRESET error when a WSASendTo
        !           871:  * fails with an "ICMP port unreachable" response and preventing the
        !           872:  * socket from using the WSARecvFrom in subsequent operations.
        !           873:  * The function below fixes this, but requires that Windows 2000
        !           874:  * Service Pack 2 or later be installed on the system.  NT 4.0
        !           875:  * systems are not affected by this and work correctly.
        !           876:  * See Microsoft Knowledge Base Article Q263823 for details of this.
        !           877:  */
        !           878: isc_result_t
        !           879: connection_reset_fix(SOCKET fd) {
        !           880:        DWORD dwBytesReturned = 0;
        !           881:        BOOL  bNewBehavior = FALSE;
        !           882:        DWORD status;
        !           883: 
        !           884:        if (isc_win32os_majorversion() < 5)
        !           885:                return (ISC_R_SUCCESS); /*  NT 4.0 has no problem */
        !           886: 
        !           887:        /* disable bad behavior using IOCTL: SIO_UDP_CONNRESET */
        !           888:        status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,
        !           889:                          sizeof(bNewBehavior), NULL, 0,
        !           890:                          &dwBytesReturned, NULL, NULL);
        !           891:        if (status != SOCKET_ERROR)
        !           892:                return (ISC_R_SUCCESS);
        !           893:        else {
        !           894:                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           895:                                 "WSAIoctl(SIO_UDP_CONNRESET, oldBehaviour) %s",
        !           896:                                 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
        !           897:                                                ISC_MSG_FAILED, "failed"));
        !           898:                return (ISC_R_UNEXPECTED);
        !           899:        }
        !           900: }
        !           901: 
        !           902: /*
        !           903:  * Construct an iov array and attach it to the msghdr passed in.  This is
        !           904:  * the SEND constructor, which will use the used region of the buffer
        !           905:  * (if using a buffer list) or will use the internal region (if a single
        !           906:  * buffer I/O is requested).
        !           907:  *
        !           908:  * Nothing can be NULL, and the done event must list at least one buffer
        !           909:  * on the buffer linked list for this function to be meaningful.
        !           910:  */
        !           911: static void
        !           912: build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
        !           913:                  struct msghdr *msg, char *cmsg, WSABUF *iov,
        !           914:                  IoCompletionInfo  *lpo)
        !           915: {
        !           916:        unsigned int iovcount;
        !           917:        isc_buffer_t *buffer;
        !           918:        buflist_t  *cpbuffer;
        !           919:        isc_region_t used;
        !           920:        size_t write_count;
        !           921:        size_t skip_count;
        !           922: 
        !           923:        memset(msg, 0, sizeof(*msg));
        !           924: 
        !           925:        memcpy(&msg->to_addr, &dev->address.type, dev->address.length);
        !           926:        msg->to_addr_len = dev->address.length;
        !           927: 
        !           928:        buffer = ISC_LIST_HEAD(dev->bufferlist);
        !           929:        write_count = 0;
        !           930:        iovcount = 0;
        !           931: 
        !           932:        /*
        !           933:         * Single buffer I/O?  Skip what we've done so far in this region.
        !           934:         */
        !           935:        if (buffer == NULL) {
        !           936:                write_count = dev->region.length - dev->n;
        !           937:                cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t));
        !           938:                RUNTIME_CHECK(cpbuffer != NULL);
        !           939:                cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, write_count);
        !           940:                RUNTIME_CHECK(cpbuffer->buf != NULL);
        !           941: 
        !           942:                socket_log(__LINE__, sock, NULL, TRACE,
        !           943:                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
        !           944:                   "alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t),
        !           945:                   cpbuffer->buf, write_count);
        !           946: 
        !           947:                memcpy(cpbuffer->buf,(dev->region.base + dev->n), write_count);
        !           948:                cpbuffer->buflen = write_count;
        !           949:                ISC_LIST_ENQUEUE(lpo->bufferlist, cpbuffer, link);
        !           950:                iov[0].buf = cpbuffer->buf;
        !           951:                iov[0].len = write_count;
        !           952:                iovcount = 1;
        !           953: 
        !           954:                goto config;
        !           955:        }
        !           956: 
        !           957:        /*
        !           958:         * Multibuffer I/O.
        !           959:         * Skip the data in the buffer list that we have already written.
        !           960:         */
        !           961:        skip_count = dev->n;
        !           962:        while (buffer != NULL) {
        !           963:                REQUIRE(ISC_BUFFER_VALID(buffer));
        !           964:                if (skip_count < isc_buffer_usedlength(buffer))
        !           965:                        break;
        !           966:                skip_count -= isc_buffer_usedlength(buffer);
        !           967:                buffer = ISC_LIST_NEXT(buffer, link);
        !           968:        }
        !           969: 
        !           970:        while (buffer != NULL) {
        !           971:                INSIST(iovcount < MAXSCATTERGATHER_SEND);
        !           972: 
        !           973:                isc_buffer_usedregion(buffer, &used);
        !           974: 
        !           975:                if (used.length > 0) {
        !           976:                        int uselen = used.length - skip_count;
        !           977:                        cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t));
        !           978:                        RUNTIME_CHECK(cpbuffer != NULL);
        !           979:                        cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, uselen);
        !           980:                        RUNTIME_CHECK(cpbuffer->buf != NULL);
        !           981: 
        !           982:                        socket_log(__LINE__, sock, NULL, TRACE,
        !           983:                           isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
        !           984:                           "alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t),
        !           985:                           cpbuffer->buf, write_count);
        !           986: 
        !           987:                        memcpy(cpbuffer->buf,(used.base + skip_count), uselen);
        !           988:                        cpbuffer->buflen = uselen;
        !           989:                        iov[iovcount].buf = cpbuffer->buf;
        !           990:                        iov[iovcount].len = used.length - skip_count;
        !           991:                        write_count += uselen;
        !           992:                        skip_count = 0;
        !           993:                        iovcount++;
        !           994:                }
        !           995:                buffer = ISC_LIST_NEXT(buffer, link);
        !           996:        }
        !           997: 
        !           998:        INSIST(skip_count == 0);
        !           999: 
        !          1000:  config:
        !          1001:        msg->msg_iov = iov;
        !          1002:        msg->msg_iovlen = iovcount;
        !          1003:        msg->msg_totallen = write_count;
        !          1004: }
        !          1005: 
        !          1006: static void
        !          1007: set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock,
        !          1008:                isc_socketevent_t *dev)
        !          1009: {
        !          1010:        if (sock->type == isc_sockettype_udp) {
        !          1011:                if (address != NULL)
        !          1012:                        dev->address = *address;
        !          1013:                else
        !          1014:                        dev->address = sock->address;
        !          1015:        } else if (sock->type == isc_sockettype_tcp) {
        !          1016:                INSIST(address == NULL);
        !          1017:                dev->address = sock->address;
        !          1018:        }
        !          1019: }
        !          1020: 
        !          1021: static void
        !          1022: destroy_socketevent(isc_event_t *event) {
        !          1023:        isc_socketevent_t *ev = (isc_socketevent_t *)event;
        !          1024: 
        !          1025:        INSIST(ISC_LIST_EMPTY(ev->bufferlist));
        !          1026: 
        !          1027:        (ev->destroy)(event);
        !          1028: }
        !          1029: 
        !          1030: static isc_socketevent_t *
        !          1031: allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
        !          1032:                     isc_taskaction_t action, const void *arg)
        !          1033: {
        !          1034:        isc_socketevent_t *ev;
        !          1035: 
        !          1036:        ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx,
        !          1037:                                                     sock, eventtype,
        !          1038:                                                     action, arg,
        !          1039:                                                     sizeof(*ev));
        !          1040:        if (ev == NULL)
        !          1041:                return (NULL);
        !          1042: 
        !          1043:        ev->result = ISC_R_IOERROR; // XXXMLG temporary change to detect failure to set
        !          1044:        ISC_LINK_INIT(ev, ev_link);
        !          1045:        ISC_LIST_INIT(ev->bufferlist);
        !          1046:        ev->region.base = NULL;
        !          1047:        ev->n = 0;
        !          1048:        ev->offset = 0;
        !          1049:        ev->attributes = 0;
        !          1050:        ev->destroy = ev->ev_destroy;
        !          1051:        ev->ev_destroy = destroy_socketevent;
        !          1052: 
        !          1053:        return (ev);
        !          1054: }
        !          1055: 
        !          1056: #if defined(ISC_SOCKET_DEBUG)
        !          1057: static void
        !          1058: dump_msg(struct msghdr *msg, isc_socket_t *sock) {
        !          1059:        unsigned int i;
        !          1060: 
        !          1061:        printf("MSGHDR %p, Socket #: %u\n", msg, sock->fd);
        !          1062:        printf("\tname %p, namelen %d\n", msg->msg_name, msg->msg_namelen);
        !          1063:        printf("\tiov %p, iovlen %d\n", msg->msg_iov, msg->msg_iovlen);
        !          1064:        for (i = 0; i < (unsigned int)msg->msg_iovlen; i++)
        !          1065:                printf("\t\t%d\tbase %p, len %d\n", i,
        !          1066:                       msg->msg_iov[i].buf,
        !          1067:                       msg->msg_iov[i].len);
        !          1068: }
        !          1069: #endif
        !          1070: 
        !          1071: /*
        !          1072:  * map the error code
        !          1073:  */
        !          1074: int
        !          1075: map_socket_error(isc_socket_t *sock, int windows_errno, int *isc_errno,
        !          1076:                 char *errorstring, size_t bufsize) {
        !          1077: 
        !          1078:        int doreturn;
        !          1079:        switch (windows_errno) {
        !          1080:        case WSAECONNREFUSED:
        !          1081:                *isc_errno = ISC_R_CONNREFUSED;
        !          1082:                if (sock->connected)
        !          1083:                        doreturn = DOIO_HARD;
        !          1084:                else
        !          1085:                        doreturn = DOIO_SOFT;
        !          1086:                break;
        !          1087:        case WSAENETUNREACH:
        !          1088:        case ERROR_NETWORK_UNREACHABLE:
        !          1089:                *isc_errno = ISC_R_NETUNREACH;
        !          1090:                if (sock->connected)
        !          1091:                        doreturn = DOIO_HARD;
        !          1092:                else
        !          1093:                        doreturn = DOIO_SOFT;
        !          1094:                break;
        !          1095:        case ERROR_PORT_UNREACHABLE:
        !          1096:        case ERROR_HOST_UNREACHABLE:
        !          1097:        case WSAEHOSTUNREACH:
        !          1098:                *isc_errno = ISC_R_HOSTUNREACH;
        !          1099:                if (sock->connected)
        !          1100:                        doreturn = DOIO_HARD;
        !          1101:                else
        !          1102:                        doreturn = DOIO_SOFT;
        !          1103:                break;
        !          1104:        case WSAENETDOWN:
        !          1105:                *isc_errno = ISC_R_NETDOWN;
        !          1106:                if (sock->connected)
        !          1107:                        doreturn = DOIO_HARD;
        !          1108:                else
        !          1109:                        doreturn = DOIO_SOFT;
        !          1110:                break;
        !          1111:        case WSAEHOSTDOWN:
        !          1112:                *isc_errno = ISC_R_HOSTDOWN;
        !          1113:                if (sock->connected)
        !          1114:                        doreturn = DOIO_HARD;
        !          1115:                else
        !          1116:                        doreturn = DOIO_SOFT;
        !          1117:                break;
        !          1118:        case WSAEACCES:
        !          1119:                *isc_errno = ISC_R_NOPERM;
        !          1120:                if (sock->connected)
        !          1121:                        doreturn = DOIO_HARD;
        !          1122:                else
        !          1123:                        doreturn = DOIO_SOFT;
        !          1124:                break;
        !          1125:        case WSAECONNRESET:
        !          1126:        case WSAENETRESET:
        !          1127:        case WSAECONNABORTED:
        !          1128:        case WSAEDISCON:
        !          1129:                *isc_errno = ISC_R_CONNECTIONRESET;
        !          1130:                if (sock->connected)
        !          1131:                        doreturn = DOIO_HARD;
        !          1132:                else
        !          1133:                        doreturn = DOIO_SOFT;
        !          1134:                break;
        !          1135:        case WSAENOTCONN:
        !          1136:                *isc_errno = ISC_R_NOTCONNECTED;
        !          1137:                if (sock->connected)
        !          1138:                        doreturn = DOIO_HARD;
        !          1139:                else
        !          1140:                        doreturn = DOIO_SOFT;
        !          1141:                break;
        !          1142:        case ERROR_OPERATION_ABORTED:
        !          1143:        case ERROR_CONNECTION_ABORTED:
        !          1144:        case ERROR_REQUEST_ABORTED:
        !          1145:                *isc_errno = ISC_R_CONNECTIONRESET;
        !          1146:                doreturn = DOIO_HARD;
        !          1147:                break;
        !          1148:        case WSAENOBUFS:
        !          1149:                *isc_errno = ISC_R_NORESOURCES;
        !          1150:                doreturn = DOIO_HARD;
        !          1151:                break;
        !          1152:        case WSAEAFNOSUPPORT:
        !          1153:                *isc_errno = ISC_R_FAMILYNOSUPPORT;
        !          1154:                doreturn = DOIO_HARD;
        !          1155:                break;
        !          1156:        case WSAEADDRNOTAVAIL:
        !          1157:                *isc_errno = ISC_R_ADDRNOTAVAIL;
        !          1158:                doreturn = DOIO_HARD;
        !          1159:                break;
        !          1160:        case WSAEDESTADDRREQ:
        !          1161:                *isc_errno = ISC_R_BADADDRESSFORM;
        !          1162:                doreturn = DOIO_HARD;
        !          1163:                break;
        !          1164:        case ERROR_NETNAME_DELETED:
        !          1165:                *isc_errno = ISC_R_NETDOWN;
        !          1166:                doreturn = DOIO_HARD;
        !          1167:                break;
        !          1168:        default:
        !          1169:                *isc_errno = ISC_R_IOERROR;
        !          1170:                doreturn = DOIO_HARD;
        !          1171:                break;
        !          1172:        }
        !          1173:        if (doreturn == DOIO_HARD) {
        !          1174:                isc__strerror(windows_errno, errorstring, bufsize);
        !          1175:        }
        !          1176:        return (doreturn);
        !          1177: }
        !          1178: 
        !          1179: static void
        !          1180: fill_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
        !          1181:        isc_region_t r;
        !          1182:        int copylen;
        !          1183:        isc_buffer_t *buffer;
        !          1184: 
        !          1185:        INSIST(dev->n < dev->minimum);
        !          1186:        INSIST(sock->recvbuf.remaining > 0);
        !          1187:        INSIST(sock->pending_recv == 0);
        !          1188: 
        !          1189:        if (sock->type == isc_sockettype_udp) {
        !          1190:                dev->address.length = sock->recvbuf.from_addr_len;
        !          1191:                memcpy(&dev->address.type, &sock->recvbuf.from_addr,
        !          1192:                    sock->recvbuf.from_addr_len);
        !          1193:                if (isc_sockaddr_getport(&dev->address) == 0) {
        !          1194:                        if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
        !          1195:                                socket_log(__LINE__, sock, &dev->address, IOEVENT,
        !          1196:                                           isc_msgcat, ISC_MSGSET_SOCKET,
        !          1197:                                           ISC_MSG_ZEROPORT,
        !          1198:                                           "dropping source port zero packet");
        !          1199:                        }
        !          1200:                        sock->recvbuf.remaining = 0;
        !          1201:                        return;
        !          1202:                }
        !          1203:        } else if (sock->type == isc_sockettype_tcp) {
        !          1204:                dev->address = sock->address;
        !          1205:        }
        !          1206: 
        !          1207:        /*
        !          1208:         * Run through the list of buffers we were given, and find the
        !          1209:         * first one with space.  Once it is found, loop through, filling
        !          1210:         * the buffers as much as possible.
        !          1211:         */
        !          1212:        buffer = ISC_LIST_HEAD(dev->bufferlist);
        !          1213:        if (buffer != NULL) { // Multi-buffer receive
        !          1214:                while (buffer != NULL && sock->recvbuf.remaining > 0) {
        !          1215:                        REQUIRE(ISC_BUFFER_VALID(buffer));
        !          1216:                        if (isc_buffer_availablelength(buffer) > 0) {
        !          1217:                                isc_buffer_availableregion(buffer, &r);
        !          1218:                                copylen = min(r.length, sock->recvbuf.remaining);
        !          1219:                                memcpy(r.base, sock->recvbuf.consume_position, copylen);
        !          1220:                                sock->recvbuf.consume_position += copylen;
        !          1221:                                sock->recvbuf.remaining -= copylen;
        !          1222:                                isc_buffer_add(buffer, copylen);
        !          1223:                                dev->n += copylen;
        !          1224:                        }
        !          1225:                        buffer = ISC_LIST_NEXT(buffer, link);
        !          1226:                }
        !          1227:        } else { // Single-buffer receive
        !          1228:                copylen = min(dev->region.length - dev->n, sock->recvbuf.remaining);
        !          1229:                memcpy(dev->region.base + dev->n, sock->recvbuf.consume_position, copylen);
        !          1230:                sock->recvbuf.consume_position += copylen;
        !          1231:                sock->recvbuf.remaining -= copylen;
        !          1232:                dev->n += copylen;
        !          1233:        }
        !          1234: 
        !          1235:        /*
        !          1236:         * UDP receives are all-consuming.  That is, if we have 4k worth of
        !          1237:         * data in our receive buffer, and the caller only gave us
        !          1238:         * 1k of space, we will toss the remaining 3k of data.  TCP
        !          1239:         * will keep the extra data around and use it for later requests.
        !          1240:         */
        !          1241:        if (sock->type == isc_sockettype_udp)
        !          1242:                sock->recvbuf.remaining = 0;
        !          1243: }
        !          1244: 
        !          1245: /*
        !          1246:  * Copy out as much data from the internal buffer to done events.
        !          1247:  * As each done event is filled, send it along its way.
        !          1248:  */
        !          1249: static void
        !          1250: completeio_recv(isc_socket_t *sock)
        !          1251: {
        !          1252:        isc_socketevent_t *dev;
        !          1253: 
        !          1254:        /*
        !          1255:         * If we are in the process of filling our buffer, we cannot
        !          1256:         * touch it yet, so don't.
        !          1257:         */
        !          1258:        if (sock->pending_recv > 0)
        !          1259:                return;
        !          1260: 
        !          1261:        while (sock->recvbuf.remaining > 0 && !ISC_LIST_EMPTY(sock->recv_list)) {
        !          1262:                dev = ISC_LIST_HEAD(sock->recv_list);
        !          1263: 
        !          1264:                /*
        !          1265:                 * See if we have sufficient data in our receive buffer
        !          1266:                 * to handle this.  If we do, copy out the data.
        !          1267:                 */
        !          1268:                fill_recv(sock, dev);
        !          1269: 
        !          1270:                /*
        !          1271:                 * Did we satisfy it?
        !          1272:                 */
        !          1273:                if (dev->n >= dev->minimum) {
        !          1274:                        dev->result = ISC_R_SUCCESS;
        !          1275:                        send_recvdone_event(sock, &dev);
        !          1276:                }
        !          1277:        }
        !          1278: }
        !          1279: 
        !          1280: /*
        !          1281:  * Returns:
        !          1282:  *     DOIO_SUCCESS    The operation succeeded.  dev->result contains
        !          1283:  *                     ISC_R_SUCCESS.
        !          1284:  *
        !          1285:  *     DOIO_HARD       A hard or unexpected I/O error was encountered.
        !          1286:  *                     dev->result contains the appropriate error.
        !          1287:  *
        !          1288:  *     DOIO_SOFT       A soft I/O error was encountered.  No senddone
        !          1289:  *                     event was sent.  The operation should be retried.
        !          1290:  *
        !          1291:  *     No other return values are possible.
        !          1292:  */
        !          1293: static int
        !          1294: completeio_send(isc_socket_t *sock, isc_socketevent_t *dev,
        !          1295:                struct msghdr *messagehdr, int cc, int send_errno)
        !          1296: {
        !          1297:        char addrbuf[ISC_SOCKADDR_FORMATSIZE];
        !          1298:        char strbuf[ISC_STRERRORSIZE];
        !          1299: 
        !          1300:        if (send_errno != 0) {
        !          1301:                if (SOFT_ERROR(send_errno))
        !          1302:                        return (DOIO_SOFT);
        !          1303: 
        !          1304:                return (map_socket_error(sock, send_errno, &dev->result,
        !          1305:                        strbuf, sizeof(strbuf)));
        !          1306: 
        !          1307:                /*
        !          1308:                 * The other error types depend on whether or not the
        !          1309:                 * socket is UDP or TCP.  If it is UDP, some errors
        !          1310:                 * that we expect to be fatal under TCP are merely
        !          1311:                 * annoying, and are really soft errors.
        !          1312:                 *
        !          1313:                 * However, these soft errors are still returned as
        !          1314:                 * a status.
        !          1315:                 */
        !          1316:                isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf));
        !          1317:                isc__strerror(send_errno, strbuf, sizeof(strbuf));
        !          1318:                UNEXPECTED_ERROR(__FILE__, __LINE__, "completeio_send: %s: %s",
        !          1319:                                 addrbuf, strbuf);
        !          1320:                dev->result = isc__errno2result(send_errno);
        !          1321:        return (DOIO_HARD);
        !          1322:        }
        !          1323: 
        !          1324:        /*
        !          1325:         * If we write less than we expected, update counters, poke.
        !          1326:         */
        !          1327:        dev->n += cc;
        !          1328:        if (cc != messagehdr->msg_totallen)
        !          1329:                return (DOIO_SOFT);
        !          1330: 
        !          1331:        /*
        !          1332:         * Exactly what we wanted to write.  We're done with this
        !          1333:         * entry.  Post its completion event.
        !          1334:         */
        !          1335:        dev->result = ISC_R_SUCCESS;
        !          1336:        return (DOIO_SUCCESS);
        !          1337: }
        !          1338: 
        !          1339: static int
        !          1340: startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
        !          1341:             int *send_errno)
        !          1342: {
        !          1343:        char *cmsg = NULL;
        !          1344:        char strbuf[ISC_STRERRORSIZE];
        !          1345:        IoCompletionInfo *lpo;
        !          1346:        int status;
        !          1347:        struct msghdr *msghdr;
        !          1348: 
        !          1349:        lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
        !          1350:                                            HEAP_ZERO_MEMORY,
        !          1351:                                            sizeof(IoCompletionInfo));
        !          1352:        RUNTIME_CHECK(lpo != NULL);
        !          1353:        lpo->request_type = SOCKET_SEND;
        !          1354:        lpo->dev = dev;
        !          1355:        msghdr = &lpo->messagehdr;
        !          1356:        memset(msghdr, 0, sizeof(struct msghdr));
        !          1357:        ISC_LIST_INIT(lpo->bufferlist);
        !          1358: 
        !          1359:        build_msghdr_send(sock, dev, msghdr, cmsg, sock->iov, lpo);
        !          1360: 
        !          1361:        *nbytes = internal_sendmsg(sock, lpo, msghdr, 0, send_errno);
        !          1362: 
        !          1363:        if (*nbytes < 0) {
        !          1364:                /*
        !          1365:                 * I/O has been initiated
        !          1366:                 * completion will be through the completion port
        !          1367:                 */
        !          1368:                if (PENDING_ERROR(*send_errno)) {
        !          1369:                        status = DOIO_PENDING;
        !          1370:                        goto done;
        !          1371:                }
        !          1372: 
        !          1373:                if (SOFT_ERROR(*send_errno)) {
        !          1374:                        status = DOIO_SOFT;
        !          1375:                        goto done;
        !          1376:                }
        !          1377: 
        !          1378:                /*
        !          1379:                 * If we got this far then something is wrong
        !          1380:                 */
        !          1381:                if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
        !          1382:                        isc__strerror(*send_errno, strbuf, sizeof(strbuf));
        !          1383:                        socket_log(__LINE__, sock, NULL, IOEVENT,
        !          1384:                                   isc_msgcat, ISC_MSGSET_SOCKET,
        !          1385:                                   ISC_MSG_INTERNALSEND,
        !          1386:                                   "startio_send: internal_sendmsg(%d) %d "
        !          1387:                                   "bytes, err %d/%s",
        !          1388:                                   sock->fd, *nbytes, *send_errno, strbuf);
        !          1389:                }
        !          1390:                goto done;
        !          1391:        }
        !          1392:        dev->result = ISC_R_SUCCESS;
        !          1393:        status = DOIO_SOFT;
        !          1394:  done:
        !          1395:        _set_state(sock, SOCK_DATA);
        !          1396:        return (status);
        !          1397: }
        !          1398: 
        !          1399: static isc_result_t
        !          1400: allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
        !          1401:                isc_socket_t **socketp) {
        !          1402:        isc_socket_t *sock;
        !          1403:        isc_result_t result;
        !          1404: 
        !          1405:        sock = isc_mem_get(manager->mctx, sizeof(*sock));
        !          1406: 
        !          1407:        if (sock == NULL)
        !          1408:                return (ISC_R_NOMEMORY);
        !          1409: 
        !          1410:        sock->magic = 0;
        !          1411:        sock->references = 0;
        !          1412: 
        !          1413:        sock->manager = manager;
        !          1414:        sock->type = type;
        !          1415:        sock->fd = INVALID_SOCKET;
        !          1416: 
        !          1417:        ISC_LINK_INIT(sock, link);
        !          1418: 
        !          1419:        /*
        !          1420:         * set up list of readers and writers to be initially empty
        !          1421:         */
        !          1422:        ISC_LIST_INIT(sock->recv_list);
        !          1423:        ISC_LIST_INIT(sock->send_list);
        !          1424:        ISC_LIST_INIT(sock->accept_list);
        !          1425:        sock->connect_ev = NULL;
        !          1426:        sock->pending_accept = 0;
        !          1427:        sock->pending_recv = 0;
        !          1428:        sock->pending_send = 0;
        !          1429:        sock->pending_iocp = 0;
        !          1430:        sock->listener = 0;
        !          1431:        sock->connected = 0;
        !          1432:        sock->pending_connect = 0;
        !          1433:        sock->bound = 0;
        !          1434:        memset(sock->name, 0, sizeof(sock->name));      // zero the name field
        !          1435:        _set_state(sock, SOCK_INITIALIZED);
        !          1436: 
        !          1437:        sock->recvbuf.len = 65536;
        !          1438:        sock->recvbuf.consume_position = sock->recvbuf.base;
        !          1439:        sock->recvbuf.remaining = 0;
        !          1440:        sock->recvbuf.base = isc_mem_get(manager->mctx, sock->recvbuf.len); // max buffer size
        !          1441:        if (sock->recvbuf.base == NULL) {
        !          1442:                sock->magic = 0;
        !          1443:                goto error;
        !          1444:        }
        !          1445: 
        !          1446:        /*
        !          1447:         * initialize the lock
        !          1448:         */
        !          1449:        result = isc_mutex_init(&sock->lock);
        !          1450:        if (result != ISC_R_SUCCESS) {
        !          1451:                sock->magic = 0;
        !          1452:                isc_mem_put(manager->mctx, sock->recvbuf.base, sock->recvbuf.len);
        !          1453:                sock->recvbuf.base = NULL;
        !          1454:                goto error;
        !          1455:        }
        !          1456: 
        !          1457:        socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
        !          1458:                   "allocated");
        !          1459: 
        !          1460:        sock->magic = SOCKET_MAGIC;
        !          1461:        *socketp = sock;
        !          1462: 
        !          1463:        return (ISC_R_SUCCESS);
        !          1464: 
        !          1465:  error:
        !          1466:        isc_mem_put(manager->mctx, sock, sizeof(*sock));
        !          1467: 
        !          1468:        return (result);
        !          1469: }
        !          1470: 
        !          1471: /*
        !          1472:  * Verify that the socket state is consistent.
        !          1473:  */
        !          1474: static void
        !          1475: consistent(isc_socket_t *sock) {
        !          1476: 
        !          1477:        isc_socketevent_t *dev;
        !          1478:        isc_socket_newconnev_t *nev;
        !          1479:        unsigned int count;
        !          1480:        char *crash_reason;
        !          1481:        isc_boolean_t crash = ISC_FALSE;
        !          1482: 
        !          1483:        REQUIRE(sock->pending_iocp == sock->pending_recv + sock->pending_send
        !          1484:                + sock->pending_accept + sock->pending_connect);
        !          1485: 
        !          1486:        dev = ISC_LIST_HEAD(sock->send_list);
        !          1487:        count = 0;
        !          1488:        while (dev != NULL) {
        !          1489:                count++;
        !          1490:                dev = ISC_LIST_NEXT(dev, ev_link);
        !          1491:        }
        !          1492:        if (count > sock->pending_send) {
        !          1493:                crash = ISC_TRUE;
        !          1494:                crash_reason = "send_list > sock->pending_send";
        !          1495:        }
        !          1496: 
        !          1497:        nev = ISC_LIST_HEAD(sock->accept_list);
        !          1498:        count = 0;
        !          1499:        while (nev != NULL) {
        !          1500:                count++;
        !          1501:                nev = ISC_LIST_NEXT(nev, ev_link);
        !          1502:        }
        !          1503:        if (count > sock->pending_accept) {
        !          1504:                crash = ISC_TRUE;
        !          1505:                crash_reason = "send_list > sock->pending_send";
        !          1506:        }
        !          1507: 
        !          1508:        if (crash) {
        !          1509:                socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
        !          1510:                           ISC_MSG_DESTROYING, "SOCKET INCONSISTENT: %s",
        !          1511:                           crash_reason);
        !          1512:                sock_dump(sock);
        !          1513:                INSIST(crash == ISC_FALSE);
        !          1514:        }
        !          1515: }
        !          1516: 
        !          1517: /*
        !          1518:  * Maybe free the socket.
        !          1519:  *
        !          1520:  * This function will verify tht the socket is no longer in use in any way,
        !          1521:  * either internally or externally.  This is the only place where this
        !          1522:  * check is to be made; if some bit of code believes that IT is done with
        !          1523:  * the socket (e.g., some reference counter reaches zero), it should call
        !          1524:  * this function.
        !          1525:  *
        !          1526:  * When calling this function, the socket must be locked, and the manager
        !          1527:  * must be unlocked.
        !          1528:  *
        !          1529:  * When this function returns, *socketp will be NULL.  No tricks to try
        !          1530:  * to hold on to this pointer are allowed.
        !          1531:  */
        !          1532: static void
        !          1533: maybe_free_socket(isc_socket_t **socketp, int lineno) {
        !          1534:        isc_socket_t *sock = *socketp;
        !          1535:        *socketp = NULL;
        !          1536: 
        !          1537:        INSIST(VALID_SOCKET(sock));
        !          1538:        CONSISTENT(sock);
        !          1539: 
        !          1540:        if (sock->pending_iocp > 0
        !          1541:            || sock->pending_recv > 0
        !          1542:            || sock->pending_send > 0
        !          1543:            || sock->pending_accept > 0
        !          1544:            || sock->references > 0
        !          1545:            || sock->pending_connect == 1
        !          1546:            || !ISC_LIST_EMPTY(sock->recv_list)
        !          1547:            || !ISC_LIST_EMPTY(sock->send_list)
        !          1548:            || !ISC_LIST_EMPTY(sock->accept_list)
        !          1549:            || sock->fd != INVALID_SOCKET) {
        !          1550:                UNLOCK(&sock->lock);
        !          1551:                return;
        !          1552:        }
        !          1553:        UNLOCK(&sock->lock);
        !          1554: 
        !          1555:        free_socket(&sock, lineno);
        !          1556: }
        !          1557: 
        !          1558: void
        !          1559: free_socket(isc_socket_t **sockp, int lineno) {
        !          1560:        isc_socketmgr_t *manager;
        !          1561:        isc_socket_t *sock = *sockp;
        !          1562:        *sockp = NULL;
        !          1563: 
        !          1564:        manager = sock->manager;
        !          1565: 
        !          1566:        /*
        !          1567:         * Seems we can free the socket after all.
        !          1568:         */
        !          1569:        manager = sock->manager;
        !          1570:        socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
        !          1571:                   ISC_MSG_DESTROYING, "freeing socket line %d fd %d lock %p semaphore %p",
        !          1572:                   lineno, sock->fd, &sock->lock, sock->lock.LockSemaphore);
        !          1573: 
        !          1574:        sock->magic = 0;
        !          1575:        DESTROYLOCK(&sock->lock);
        !          1576: 
        !          1577:        if (sock->recvbuf.base != NULL)
        !          1578:                isc_mem_put(manager->mctx, sock->recvbuf.base, sock->recvbuf.len);
        !          1579: 
        !          1580:        LOCK(&manager->lock);
        !          1581:        if (ISC_LINK_LINKED(sock, link))
        !          1582:                ISC_LIST_UNLINK(manager->socklist, sock, link);
        !          1583:        isc_mem_put(manager->mctx, sock, sizeof(*sock));
        !          1584: 
        !          1585:        if (ISC_LIST_EMPTY(manager->socklist))
        !          1586:                SIGNAL(&manager->shutdown_ok);
        !          1587:        UNLOCK(&manager->lock);
        !          1588: }
        !          1589: 
        !          1590: /*
        !          1591:  * Create a new 'type' socket managed by 'manager'.  Events
        !          1592:  * will be posted to 'task' and when dispatched 'action' will be
        !          1593:  * called with 'arg' as the arg value.  The new socket is returned
        !          1594:  * in 'socketp'.
        !          1595:  */
        !          1596: isc_result_t
        !          1597: isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
        !          1598:                  isc_socket_t **socketp) {
        !          1599:        isc_socket_t *sock = NULL;
        !          1600:        isc_result_t result;
        !          1601: #if defined(USE_CMSG)
        !          1602:        int on = 1;
        !          1603: #endif
        !          1604: #if defined(SO_RCVBUF)
        !          1605:        ISC_SOCKADDR_LEN_T optlen;
        !          1606:        int size;
        !          1607: #endif
        !          1608:        int socket_errno;
        !          1609:        char strbuf[ISC_STRERRORSIZE];
        !          1610: 
        !          1611:        REQUIRE(VALID_MANAGER(manager));
        !          1612:        REQUIRE(socketp != NULL && *socketp == NULL);
        !          1613:        REQUIRE(type != isc_sockettype_fdwatch);
        !          1614: 
        !          1615:        result = allocate_socket(manager, type, &sock);
        !          1616:        if (result != ISC_R_SUCCESS)
        !          1617:                return (result);
        !          1618: 
        !          1619:        sock->pf = pf;
        !          1620:        switch (type) {
        !          1621:        case isc_sockettype_udp:
        !          1622:                sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
        !          1623:                if (sock->fd != INVALID_SOCKET) {
        !          1624:                        result = connection_reset_fix(sock->fd);
        !          1625:                        if (result != ISC_R_SUCCESS) {
        !          1626:                                socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
        !          1627:                                        "closed %d %d %d con_reset_fix_failed",
        !          1628:                                        sock->pending_recv, sock->pending_send,
        !          1629:                                        sock->references);
        !          1630:                                closesocket(sock->fd);
        !          1631:                                _set_state(sock, SOCK_CLOSED);
        !          1632:                                sock->fd = INVALID_SOCKET;
        !          1633:                                free_socket(&sock, __LINE__);
        !          1634:                                return (result);
        !          1635:                        }
        !          1636:                }
        !          1637:                break;
        !          1638:        case isc_sockettype_tcp:
        !          1639:                sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
        !          1640:                break;
        !          1641:        }
        !          1642: 
        !          1643:        if (sock->fd == INVALID_SOCKET) {
        !          1644:                socket_errno = WSAGetLastError();
        !          1645:                free_socket(&sock, __LINE__);
        !          1646: 
        !          1647:                switch (socket_errno) {
        !          1648:                case WSAEMFILE:
        !          1649:                case WSAENOBUFS:
        !          1650:                        return (ISC_R_NORESOURCES);
        !          1651: 
        !          1652:                case WSAEPROTONOSUPPORT:
        !          1653:                case WSAEPFNOSUPPORT:
        !          1654:                case WSAEAFNOSUPPORT:
        !          1655:                        return (ISC_R_FAMILYNOSUPPORT);
        !          1656: 
        !          1657:                default:
        !          1658:                        isc__strerror(socket_errno, strbuf, sizeof(strbuf));
        !          1659:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !          1660:                                         "socket() %s: %s",
        !          1661:                                         isc_msgcat_get(isc_msgcat,
        !          1662:                                                        ISC_MSGSET_GENERAL,
        !          1663:                                                        ISC_MSG_FAILED,
        !          1664:                                                        "failed"),
        !          1665:                                         strbuf);
        !          1666:                        return (ISC_R_UNEXPECTED);
        !          1667:                }
        !          1668:        }
        !          1669: 
        !          1670:        result = make_nonblock(sock->fd);
        !          1671:        if (result != ISC_R_SUCCESS) {
        !          1672:                socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
        !          1673:                        "closed %d %d %d make_nonblock_failed",
        !          1674:                        sock->pending_recv, sock->pending_send,
        !          1675:                        sock->references);
        !          1676:                closesocket(sock->fd);
        !          1677:                sock->fd = INVALID_SOCKET;
        !          1678:                free_socket(&sock, __LINE__);
        !          1679:                return (result);
        !          1680:        }
        !          1681: 
        !          1682: 
        !          1683: #if defined(USE_CMSG) || defined(SO_RCVBUF)
        !          1684:        if (type == isc_sockettype_udp) {
        !          1685: 
        !          1686: #if defined(USE_CMSG)
        !          1687: #if defined(ISC_PLATFORM_HAVEIPV6)
        !          1688: #ifdef IPV6_RECVPKTINFO
        !          1689:                /* 2292bis */
        !          1690:                if ((pf == AF_INET6)
        !          1691:                    && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
        !          1692:                                   (void *)&on, sizeof(on)) < 0)) {
        !          1693:                        isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
        !          1694:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !          1695:                                         "setsockopt(%d, IPV6_RECVPKTINFO) "
        !          1696:                                         "%s: %s", sock->fd,
        !          1697:                                         isc_msgcat_get(isc_msgcat,
        !          1698:                                                        ISC_MSGSET_GENERAL,
        !          1699:                                                        ISC_MSG_FAILED,
        !          1700:                                                        "failed"),
        !          1701:                                         strbuf);
        !          1702:                }
        !          1703: #else
        !          1704:                /* 2292 */
        !          1705:                if ((pf == AF_INET6)
        !          1706:                    && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
        !          1707:                                   (void *)&on, sizeof(on)) < 0)) {
        !          1708:                        isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
        !          1709:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !          1710:                                         "setsockopt(%d, IPV6_PKTINFO) %s: %s",
        !          1711:                                         sock->fd,
        !          1712:                                         isc_msgcat_get(isc_msgcat,
        !          1713:                                                        ISC_MSGSET_GENERAL,
        !          1714:                                                        ISC_MSG_FAILED,
        !          1715:                                                        "failed"),
        !          1716:                                         strbuf);
        !          1717:                }
        !          1718: #endif /* IPV6_RECVPKTINFO */
        !          1719: #ifdef IPV6_USE_MIN_MTU        /*2292bis, not too common yet*/
        !          1720:                /* use minimum MTU */
        !          1721:                if (pf == AF_INET6) {
        !          1722:                        (void)setsockopt(sock->fd, IPPROTO_IPV6,
        !          1723:                                         IPV6_USE_MIN_MTU,
        !          1724:                                         (void *)&on, sizeof(on));
        !          1725:                }
        !          1726: #endif
        !          1727: #endif /* ISC_PLATFORM_HAVEIPV6 */
        !          1728: #endif /* defined(USE_CMSG) */
        !          1729: 
        !          1730: #if defined(SO_RCVBUF)
        !          1731:               optlen = sizeof(size);
        !          1732:               if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
        !          1733:                              (void *)&size, &optlen) >= 0 &&
        !          1734:                    size < RCVBUFSIZE) {
        !          1735:                       size = RCVBUFSIZE;
        !          1736:                       (void)setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
        !          1737:                                        (void *)&size, sizeof(size));
        !          1738:               }
        !          1739: #endif
        !          1740: 
        !          1741:        }
        !          1742: #endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
        !          1743: 
        !          1744:        _set_state(sock, SOCK_OPEN);
        !          1745:        sock->references = 1;
        !          1746:        *socketp = sock;
        !          1747: 
        !          1748:        iocompletionport_update(sock);
        !          1749: 
        !          1750:        /*
        !          1751:         * Note we don't have to lock the socket like we normally would because
        !          1752:         * there are no external references to it yet.
        !          1753:         */
        !          1754:        LOCK(&manager->lock);
        !          1755:        ISC_LIST_APPEND(manager->socklist, sock, link);
        !          1756:        InterlockedIncrement(&manager->totalSockets);
        !          1757:        UNLOCK(&manager->lock);
        !          1758: 
        !          1759:        socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
        !          1760:                   ISC_MSG_CREATED, "created %u type %u", sock->fd, type);
        !          1761: 
        !          1762:        return (ISC_R_SUCCESS);
        !          1763: }
        !          1764: 
        !          1765: isc_result_t
        !          1766: isc_socket_open(isc_socket_t *sock) {
        !          1767:        REQUIRE(VALID_SOCKET(sock));
        !          1768:        REQUIRE(sock->type != isc_sockettype_fdwatch);
        !          1769: 
        !          1770:        return (ISC_R_NOTIMPLEMENTED);
        !          1771: }
        !          1772: 
        !          1773: /*
        !          1774:  * Attach to a socket.  Caller must explicitly detach when it is done.
        !          1775:  */
        !          1776: void
        !          1777: isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
        !          1778:        REQUIRE(VALID_SOCKET(sock));
        !          1779:        REQUIRE(socketp != NULL && *socketp == NULL);
        !          1780: 
        !          1781:        LOCK(&sock->lock);
        !          1782:        CONSISTENT(sock);
        !          1783:        sock->references++;
        !          1784:        UNLOCK(&sock->lock);
        !          1785: 
        !          1786:        *socketp = sock;
        !          1787: }
        !          1788: 
        !          1789: /*
        !          1790:  * Dereference a socket.  If this is the last reference to it, clean things
        !          1791:  * up by destroying the socket.
        !          1792:  */
        !          1793: void
        !          1794: isc_socket_detach(isc_socket_t **socketp) {
        !          1795:        isc_socket_t *sock;
        !          1796:        isc_boolean_t kill_socket = ISC_FALSE;
        !          1797: 
        !          1798:        REQUIRE(socketp != NULL);
        !          1799:        sock = *socketp;
        !          1800:        REQUIRE(VALID_SOCKET(sock));
        !          1801:        REQUIRE(sock->type != isc_sockettype_fdwatch);
        !          1802: 
        !          1803:        LOCK(&sock->lock);
        !          1804:        CONSISTENT(sock);
        !          1805:        REQUIRE(sock->references > 0);
        !          1806:        sock->references--;
        !          1807: 
        !          1808:        socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
        !          1809:                "detach_socket %d %d %d",
        !          1810:                sock->pending_recv, sock->pending_send,
        !          1811:                sock->references);
        !          1812: 
        !          1813:        if (sock->references == 0 && sock->fd != INVALID_SOCKET) {
        !          1814:                closesocket(sock->fd);
        !          1815:                sock->fd = INVALID_SOCKET;
        !          1816:                _set_state(sock, SOCK_CLOSED);
        !          1817:        }
        !          1818: 
        !          1819:        maybe_free_socket(&sock, __LINE__);
        !          1820: 
        !          1821:        *socketp = NULL;
        !          1822: }
        !          1823: 
        !          1824: isc_result_t
        !          1825: isc_socket_close(isc_socket_t *sock) {
        !          1826:        REQUIRE(VALID_SOCKET(sock));
        !          1827:        REQUIRE(sock->type != isc_sockettype_fdwatch);
        !          1828: 
        !          1829:        return (ISC_R_NOTIMPLEMENTED);
        !          1830: }
        !          1831: 
        !          1832: /*
        !          1833:  * Dequeue an item off the given socket's read queue, set the result code
        !          1834:  * in the done event to the one provided, and send it to the task it was
        !          1835:  * destined for.
        !          1836:  *
        !          1837:  * If the event to be sent is on a list, remove it before sending.  If
        !          1838:  * asked to, send and detach from the task as well.
        !          1839:  *
        !          1840:  * Caller must have the socket locked if the event is attached to the socket.
        !          1841:  */
        !          1842: static void
        !          1843: send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
        !          1844:        isc_task_t *task;
        !          1845: 
        !          1846:        task = (*dev)->ev_sender;
        !          1847:        (*dev)->ev_sender = sock;
        !          1848: 
        !          1849:        if (ISC_LINK_LINKED(*dev, ev_link))
        !          1850:                ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link);
        !          1851: 
        !          1852:        if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
        !          1853:            == ISC_SOCKEVENTATTR_ATTACHED)
        !          1854:                isc_task_sendanddetach(&task, (isc_event_t **)dev);
        !          1855:        else
        !          1856:                isc_task_send(task, (isc_event_t **)dev);
        !          1857: 
        !          1858:        CONSISTENT(sock);
        !          1859: }
        !          1860: 
        !          1861: /*
        !          1862:  * See comments for send_recvdone_event() above.
        !          1863:  */
        !          1864: static void
        !          1865: send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
        !          1866:        isc_task_t *task;
        !          1867: 
        !          1868:        INSIST(dev != NULL && *dev != NULL);
        !          1869: 
        !          1870:        task = (*dev)->ev_sender;
        !          1871:        (*dev)->ev_sender = sock;
        !          1872: 
        !          1873:        if (ISC_LINK_LINKED(*dev, ev_link))
        !          1874:                ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link);
        !          1875: 
        !          1876:        if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
        !          1877:            == ISC_SOCKEVENTATTR_ATTACHED)
        !          1878:                isc_task_sendanddetach(&task, (isc_event_t **)dev);
        !          1879:        else
        !          1880:                isc_task_send(task, (isc_event_t **)dev);
        !          1881: 
        !          1882:        CONSISTENT(sock);
        !          1883: }
        !          1884: 
        !          1885: /*
        !          1886:  * See comments for send_recvdone_event() above.
        !          1887:  */
        !          1888: static void
        !          1889: send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev) {
        !          1890:        isc_task_t *task;
        !          1891: 
        !          1892:        INSIST(adev != NULL && *adev != NULL);
        !          1893: 
        !          1894:        task = (*adev)->ev_sender;
        !          1895:        (*adev)->ev_sender = sock;
        !          1896: 
        !          1897:        if (ISC_LINK_LINKED(*adev, ev_link))
        !          1898:                ISC_LIST_DEQUEUE(sock->accept_list, *adev, ev_link);
        !          1899: 
        !          1900:        isc_task_sendanddetach(&task, (isc_event_t **)adev);
        !          1901: 
        !          1902:        CONSISTENT(sock);
        !          1903: }
        !          1904: 
        !          1905: /*
        !          1906:  * See comments for send_recvdone_event() above.
        !          1907:  */
        !          1908: static void
        !          1909: send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev) {
        !          1910:        isc_task_t *task;
        !          1911: 
        !          1912:        INSIST(cdev != NULL && *cdev != NULL);
        !          1913: 
        !          1914:        task = (*cdev)->ev_sender;
        !          1915:        (*cdev)->ev_sender = sock;
        !          1916: 
        !          1917:        sock->connect_ev = NULL;
        !          1918: 
        !          1919:        isc_task_sendanddetach(&task, (isc_event_t **)cdev);
        !          1920: 
        !          1921:        CONSISTENT(sock);
        !          1922: }
        !          1923: 
        !          1924: /*
        !          1925:  * On entry to this function, the event delivered is the internal
        !          1926:  * readable event, and the first item on the accept_list should be
        !          1927:  * the done event we want to send.  If the list is empty, this is a no-op,
        !          1928:  * so just close the new connection, unlock, and return.
        !          1929:  *
        !          1930:  * Note the socket is locked before entering here
        !          1931:  */
        !          1932: static void
        !          1933: internal_accept(isc_socket_t *sock, IoCompletionInfo *lpo, int accept_errno) {
        !          1934:        isc_socket_newconnev_t *adev;
        !          1935:        isc_result_t result = ISC_R_SUCCESS;
        !          1936:        isc_socket_t *nsock;
        !          1937:        struct sockaddr *localaddr;
        !          1938:        int localaddr_len = sizeof(*localaddr);
        !          1939:        struct sockaddr *remoteaddr;
        !          1940:        int remoteaddr_len = sizeof(*remoteaddr);
        !          1941: 
        !          1942:        INSIST(VALID_SOCKET(sock));
        !          1943:        LOCK(&sock->lock);
        !          1944:        CONSISTENT(sock);
        !          1945: 
        !          1946:        socket_log(__LINE__, sock, NULL, TRACE,
        !          1947:                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
        !          1948:                   "internal_accept called");
        !          1949: 
        !          1950:        INSIST(sock->listener);
        !          1951: 
        !          1952:        INSIST(sock->pending_iocp > 0);
        !          1953:        sock->pending_iocp--;
        !          1954:        INSIST(sock->pending_accept > 0);
        !          1955:        sock->pending_accept--;
        !          1956: 
        !          1957:        adev = lpo->adev;
        !          1958: 
        !          1959:        /*
        !          1960:         * If the event is no longer in the list we can just return.
        !          1961:         */
        !          1962:        if (!acceptdone_is_active(sock, adev))
        !          1963:                goto done;
        !          1964: 
        !          1965:        nsock = adev->newsocket;
        !          1966: 
        !          1967:        /*
        !          1968:         * Pull off the done event.
        !          1969:         */
        !          1970:        ISC_LIST_UNLINK(sock->accept_list, adev, ev_link);
        !          1971: 
        !          1972:        /*
        !          1973:         * Extract the addresses from the socket, copy them into the structure,
        !          1974:         * and return the new socket.
        !          1975:         */
        !          1976:        ISCGetAcceptExSockaddrs(lpo->acceptbuffer, 0,
        !          1977:                sizeof(SOCKADDR_STORAGE) + 16, sizeof(SOCKADDR_STORAGE) + 16,
        !          1978:                (LPSOCKADDR *)&localaddr, &localaddr_len,
        !          1979:                (LPSOCKADDR *)&remoteaddr, &remoteaddr_len);
        !          1980:        memcpy(&adev->address.type, remoteaddr, remoteaddr_len);
        !          1981:        adev->address.length = remoteaddr_len;
        !          1982:        nsock->address = adev->address;
        !          1983:        nsock->pf = adev->address.type.sa.sa_family;
        !          1984: 
        !          1985:        socket_log(__LINE__, nsock, &nsock->address, TRACE,
        !          1986:                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
        !          1987:                   "internal_accept parent %p", sock);
        !          1988: 
        !          1989:        result = make_nonblock(adev->newsocket->fd);
        !          1990:        INSIST(result == ISC_R_SUCCESS);
        !          1991: 
        !          1992:        INSIST(setsockopt(nsock->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
        !          1993:               (char *)&sock->fd, sizeof(sock->fd)) == 0);
        !          1994: 
        !          1995:        /*
        !          1996:         * Hook it up into the manager.
        !          1997:         */
        !          1998:        nsock->bound = 1;
        !          1999:        nsock->connected = 1;
        !          2000:        _set_state(nsock, SOCK_OPEN);
        !          2001: 
        !          2002:        LOCK(&nsock->manager->lock);
        !          2003:        ISC_LIST_APPEND(nsock->manager->socklist, nsock, link);
        !          2004:        InterlockedIncrement(&nsock->manager->totalSockets);
        !          2005:        UNLOCK(&nsock->manager->lock);
        !          2006: 
        !          2007:        socket_log(__LINE__, sock, &nsock->address, CREATION,
        !          2008:                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
        !          2009:                   "accepted_connection new_socket %p fd %d",
        !          2010:                   nsock, nsock->fd);
        !          2011: 
        !          2012:        adev->result = result;
        !          2013:        send_acceptdone_event(sock, &adev);
        !          2014: 
        !          2015: done:
        !          2016:        CONSISTENT(sock);
        !          2017:        UNLOCK(&sock->lock);
        !          2018: 
        !          2019:        HeapFree(hHeapHandle, 0, lpo->acceptbuffer);
        !          2020:        lpo->acceptbuffer = NULL;
        !          2021: }
        !          2022: 
        !          2023: /*
        !          2024:  * Called when a socket with a pending connect() finishes.
        !          2025:  * Note that the socket is locked before entering.
        !          2026:  */
        !          2027: static void
        !          2028: internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
        !          2029:        isc_socket_connev_t *cdev;
        !          2030:        char strbuf[ISC_STRERRORSIZE];
        !          2031: 
        !          2032:        INSIST(VALID_SOCKET(sock));
        !          2033: 
        !          2034:        LOCK(&sock->lock);
        !          2035: 
        !          2036:        INSIST(sock->pending_iocp > 0);
        !          2037:        sock->pending_iocp--;
        !          2038:        INSIST(sock->pending_connect == 1);
        !          2039:        sock->pending_connect = 0;
        !          2040: 
        !          2041:        /*
        !          2042:         * Has this event been canceled?
        !          2043:         */
        !          2044:        cdev = lpo->cdev;
        !          2045:        if (!connectdone_is_active(sock, cdev)) {
        !          2046:                sock->pending_connect = 0;
        !          2047:                if (sock->fd != INVALID_SOCKET) {
        !          2048:                        closesocket(sock->fd);
        !          2049:                        sock->fd = INVALID_SOCKET;
        !          2050:                        _set_state(sock, SOCK_CLOSED);
        !          2051:                }
        !          2052:                CONSISTENT(sock);
        !          2053:                UNLOCK(&sock->lock);
        !          2054:                return;
        !          2055:        }
        !          2056: 
        !          2057:        /*
        !          2058:         * Check possible Windows network event error status here.
        !          2059:         */
        !          2060:        if (connect_errno != 0) {
        !          2061:                /*
        !          2062:                 * If the error is SOFT, just try again on this
        !          2063:                 * fd and pretend nothing strange happened.
        !          2064:                 */
        !          2065:                if (SOFT_ERROR(connect_errno) ||
        !          2066:                    connect_errno == WSAEINPROGRESS) {
        !          2067:                        sock->pending_connect = 1;
        !          2068:                        CONSISTENT(sock);
        !          2069:                        UNLOCK(&sock->lock);
        !          2070:                        return;
        !          2071:                }
        !          2072: 
        !          2073:                /*
        !          2074:                 * Translate other errors into ISC_R_* flavors.
        !          2075:                 */
        !          2076:                switch (connect_errno) {
        !          2077: #define ERROR_MATCH(a, b) case a: cdev->result = b; break;
        !          2078:                        ERROR_MATCH(WSAEACCES, ISC_R_NOPERM);
        !          2079:                        ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
        !          2080:                        ERROR_MATCH(WSAEAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
        !          2081:                        ERROR_MATCH(WSAECONNREFUSED, ISC_R_CONNREFUSED);
        !          2082:                        ERROR_MATCH(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH);
        !          2083:                        ERROR_MATCH(WSAEHOSTDOWN, ISC_R_HOSTDOWN);
        !          2084:                        ERROR_MATCH(WSAENETUNREACH, ISC_R_NETUNREACH);
        !          2085:                        ERROR_MATCH(WSAENETDOWN, ISC_R_NETDOWN);
        !          2086:                        ERROR_MATCH(WSAENOBUFS, ISC_R_NORESOURCES);
        !          2087:                        ERROR_MATCH(WSAECONNRESET, ISC_R_CONNECTIONRESET);
        !          2088:                        ERROR_MATCH(WSAECONNABORTED, ISC_R_CONNECTIONRESET);
        !          2089:                        ERROR_MATCH(WSAETIMEDOUT, ISC_R_TIMEDOUT);
        !          2090: #undef ERROR_MATCH
        !          2091:                default:
        !          2092:                        cdev->result = ISC_R_UNEXPECTED;
        !          2093:                        isc__strerror(connect_errno, strbuf, sizeof(strbuf));
        !          2094:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !          2095:                                         "internal_connect: connect() %s",
        !          2096:                                         strbuf);
        !          2097:                }
        !          2098:        } else {
        !          2099:                INSIST(setsockopt(sock->fd, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0);
        !          2100:                cdev->result = ISC_R_SUCCESS;
        !          2101:                sock->connected = 1;
        !          2102:                socket_log(__LINE__, sock, &sock->address, IOEVENT,
        !          2103:                           isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
        !          2104:                           "internal_connect: success");
        !          2105:        }
        !          2106: 
        !          2107:        send_connectdone_event(sock, &cdev);
        !          2108: 
        !          2109:        UNLOCK(&sock->lock);
        !          2110: }
        !          2111: 
        !          2112: /*
        !          2113:  * Loop through the socket, returning ISC_R_EOF for each done event pending.
        !          2114:  */
        !          2115: static void
        !          2116: send_recvdone_abort(isc_socket_t *sock, isc_result_t result) {
        !          2117:        isc_socketevent_t *dev;
        !          2118: 
        !          2119:        while (!ISC_LIST_EMPTY(sock->recv_list)) {
        !          2120:                dev = ISC_LIST_HEAD(sock->recv_list);
        !          2121:                dev->result = result;
        !          2122:                send_recvdone_event(sock, &dev);
        !          2123:        }
        !          2124: }
        !          2125: 
        !          2126: /*
        !          2127:  * Take the data we received in our private buffer, and if any recv() calls on
        !          2128:  * our list are satisfied, send the corresponding done event.
        !          2129:  *
        !          2130:  * If we need more data (there are still items on the recv_list after we consume all
        !          2131:  * our data) then arrange for another system recv() call to fill our buffers.
        !          2132:  */
        !          2133: static void
        !          2134: internal_recv(isc_socket_t *sock, int nbytes)
        !          2135: {
        !          2136:        INSIST(VALID_SOCKET(sock));
        !          2137: 
        !          2138:        LOCK(&sock->lock);
        !          2139:        CONSISTENT(sock);
        !          2140: 
        !          2141:        socket_log(__LINE__, sock, NULL, IOEVENT,
        !          2142:                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
        !          2143:                   "internal_recv: %d bytes received", nbytes);
        !          2144: 
        !          2145:        /*
        !          2146:         * If we got here, the I/O operation succeeded.  However, we might still have removed this
        !          2147:         * event from our notification list (or never placed it on it due to immediate completion.)
        !          2148:         * Handle the reference counting here, and handle the cancellation event just after.
        !          2149:         */
        !          2150:        INSIST(sock->pending_iocp > 0);
        !          2151:        sock->pending_iocp--;
        !          2152:        INSIST(sock->pending_recv > 0);
        !          2153:        sock->pending_recv--;
        !          2154: 
        !          2155:        /*
        !          2156:         * The only way we could have gotten here is that our I/O has successfully completed.
        !          2157:         * Update our pointers, and move on.  The only odd case here is that we might not
        !          2158:         * have received enough data on a TCP stream to satisfy the minimum requirements.  If
        !          2159:         * this is the case, we will re-issue the recv() call for what we need.
        !          2160:         *
        !          2161:         * We do check for a recv() of 0 bytes on a TCP stream.  This means the remote end
        !          2162:         * has closed.
        !          2163:         */
        !          2164:        if (nbytes == 0 && sock->type == isc_sockettype_tcp) {
        !          2165:                send_recvdone_abort(sock, ISC_R_EOF);
        !          2166:                maybe_free_socket(&sock, __LINE__);
        !          2167:                return;
        !          2168:        }
        !          2169:        sock->recvbuf.remaining = nbytes;
        !          2170:        sock->recvbuf.consume_position = sock->recvbuf.base;
        !          2171:        completeio_recv(sock);
        !          2172: 
        !          2173:        /*
        !          2174:         * If there are more receivers waiting for data, queue another receive
        !          2175:         * here.
        !          2176:         */
        !          2177:        queue_receive_request(sock);
        !          2178: 
        !          2179:        /*
        !          2180:         * Unlock and/or destroy if we are the last thing this socket has left to do.
        !          2181:         */
        !          2182:        maybe_free_socket(&sock, __LINE__);
        !          2183: }
        !          2184: 
        !          2185: static void
        !          2186: internal_send(isc_socket_t *sock, isc_socketevent_t *dev,
        !          2187:              struct msghdr *messagehdr, int nbytes, int send_errno, IoCompletionInfo *lpo)
        !          2188: {
        !          2189:        buflist_t *buffer;
        !          2190: 
        !          2191:        /*
        !          2192:         * Find out what socket this is and lock it.
        !          2193:         */
        !          2194:        INSIST(VALID_SOCKET(sock));
        !          2195: 
        !          2196:        LOCK(&sock->lock);
        !          2197:        CONSISTENT(sock);
        !          2198: 
        !          2199:        socket_log(__LINE__, sock, NULL, IOEVENT,
        !          2200:                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
        !          2201:                   "internal_send: task got socket event %p", dev);
        !          2202: 
        !          2203:        buffer = ISC_LIST_HEAD(lpo->bufferlist);
        !          2204:        while (buffer != NULL) {
        !          2205:                ISC_LIST_DEQUEUE(lpo->bufferlist, buffer, link);
        !          2206: 
        !          2207:                socket_log(__LINE__, sock, NULL, TRACE,
        !          2208:                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
        !          2209:                   "free_buffer %p %p", buffer, buffer->buf);
        !          2210: 
        !          2211:                HeapFree(hHeapHandle, 0, buffer->buf);
        !          2212:                HeapFree(hHeapHandle, 0, buffer);
        !          2213:                buffer = ISC_LIST_HEAD(lpo->bufferlist);
        !          2214:        }
        !          2215: 
        !          2216:        INSIST(sock->pending_iocp > 0);
        !          2217:        sock->pending_iocp--;
        !          2218:        INSIST(sock->pending_send > 0);
        !          2219:        sock->pending_send--;
        !          2220: 
        !          2221:        /* If the event is no longer in the list we can just return */
        !          2222:        if (!senddone_is_active(sock, dev))
        !          2223:                goto done;
        !          2224: 
        !          2225:        /*
        !          2226:         * Set the error code and send things on its way.
        !          2227:         */
        !          2228:        switch (completeio_send(sock, dev, messagehdr, nbytes, send_errno)) {
        !          2229:        case DOIO_SOFT:
        !          2230:                break;
        !          2231:        case DOIO_HARD:
        !          2232:        case DOIO_SUCCESS:
        !          2233:                send_senddone_event(sock, &dev);
        !          2234:                break;
        !          2235:        }
        !          2236: 
        !          2237:  done:
        !          2238:        maybe_free_socket(&sock, __LINE__);
        !          2239: }
        !          2240: 
        !          2241: /*
        !          2242:  * These return if the done event passed in is on the list (or for connect, is
        !          2243:  * the one we're waiting for.  Using these ensures we will not double-send an
        !          2244:  * event.
        !          2245:  */
        !          2246: static isc_boolean_t
        !          2247: senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev)
        !          2248: {
        !          2249:        isc_socketevent_t *ldev;
        !          2250: 
        !          2251:        ldev = ISC_LIST_HEAD(sock->send_list);
        !          2252:        while (ldev != NULL && ldev != dev)
        !          2253:                ldev = ISC_LIST_NEXT(ldev, ev_link);
        !          2254: 
        !          2255:        return (ldev == NULL ? ISC_FALSE : ISC_TRUE);
        !          2256: }
        !          2257: 
        !          2258: static isc_boolean_t
        !          2259: acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev)
        !          2260: {
        !          2261:        isc_socket_newconnev_t *ldev;
        !          2262: 
        !          2263:        ldev = ISC_LIST_HEAD(sock->accept_list);
        !          2264:        while (ldev != NULL && ldev != dev)
        !          2265:                ldev = ISC_LIST_NEXT(ldev, ev_link);
        !          2266: 
        !          2267:        return (ldev == NULL ? ISC_FALSE : ISC_TRUE);
        !          2268: }
        !          2269: 
        !          2270: static isc_boolean_t
        !          2271: connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev)
        !          2272: {
        !          2273:        return (sock->connect_ev == dev ? ISC_TRUE : ISC_FALSE);
        !          2274: }
        !          2275: 
        !          2276: /*
        !          2277:  * This is the I/O Completion Port Worker Function. It loops forever
        !          2278:  * waiting for I/O to complete and then forwards them for further
        !          2279:  * processing. There are a number of these in separate threads.
        !          2280:  */
        !          2281: static isc_threadresult_t WINAPI
        !          2282: SocketIoThread(LPVOID ThreadContext) {
        !          2283:        isc_socketmgr_t *manager = ThreadContext;
        !          2284:        BOOL bSuccess = FALSE;
        !          2285:        DWORD nbytes;
        !          2286:        IoCompletionInfo *lpo = NULL;
        !          2287:        isc_socket_t *sock = NULL;
        !          2288:        int request;
        !          2289:        struct msghdr *messagehdr = NULL;
        !          2290:        int errval;
        !          2291:        char strbuf[ISC_STRERRORSIZE];
        !          2292:        int errstatus;
        !          2293: 
        !          2294:        REQUIRE(VALID_MANAGER(manager));
        !          2295: 
        !          2296:        /*
        !          2297:         * Set the thread priority high enough so I/O will
        !          2298:         * preempt normal recv packet processing, but not
        !          2299:         * higher than the timer sync thread.
        !          2300:         */
        !          2301:        if (!SetThreadPriority(GetCurrentThread(),
        !          2302:                               THREAD_PRIORITY_ABOVE_NORMAL)) {
        !          2303:                errval = GetLastError();
        !          2304:                isc__strerror(errval, strbuf, sizeof(strbuf));
        !          2305:                FATAL_ERROR(__FILE__, __LINE__,
        !          2306:                                isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
        !          2307:                                ISC_MSG_FAILED,
        !          2308:                                "Can't set thread priority: %s"),
        !          2309:                                strbuf);
        !          2310:        }
        !          2311: 
        !          2312:        /*
        !          2313:         * Loop forever waiting on I/O Completions and then processing them
        !          2314:         */
        !          2315:        while (TRUE) {
        !          2316:                bSuccess = GetQueuedCompletionStatus(manager->hIoCompletionPort,
        !          2317:                                                     &nbytes, (LPDWORD)&sock,
        !          2318:                                                     (LPWSAOVERLAPPED *)&lpo,
        !          2319:                                                     INFINITE);
        !          2320:                if (lpo == NULL) /* Received request to exit */
        !          2321:                        break;
        !          2322: 
        !          2323:                REQUIRE(VALID_SOCKET(sock));
        !          2324: 
        !          2325:                request = lpo->request_type;
        !          2326: 
        !          2327:                errstatus = 0;
        !          2328:                if (!bSuccess) {
        !          2329:                        isc_result_t isc_result;
        !          2330: 
        !          2331:                        /*
        !          2332:                         * Did the I/O operation complete?
        !          2333:                         */
        !          2334:                        errstatus = WSAGetLastError();
        !          2335:                        isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__);
        !          2336: 
        !          2337:                        LOCK(&sock->lock);
        !          2338:                        CONSISTENT(sock);
        !          2339:                        switch (request) {
        !          2340:                        case SOCKET_RECV:
        !          2341:                                INSIST(sock->pending_iocp > 0);
        !          2342:                                sock->pending_iocp--;
        !          2343:                                INSIST(sock->pending_recv > 0);
        !          2344:                                sock->pending_recv--;
        !          2345:                                send_recvdone_abort(sock, isc_result);
        !          2346:                                if (isc_result == ISC_R_UNEXPECTED) {
        !          2347:                                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !          2348:                                                "SOCKET_RECV: Windows error code: %d, returning ISC error %d",
        !          2349:                                                errstatus, isc_result);
        !          2350:                                }
        !          2351:                                break;
        !          2352: 
        !          2353:                        case SOCKET_SEND:
        !          2354:                                INSIST(sock->pending_iocp > 0);
        !          2355:                                sock->pending_iocp--;
        !          2356:                                INSIST(sock->pending_send > 0);
        !          2357:                                sock->pending_send--;
        !          2358:                                if (senddone_is_active(sock, lpo->dev)) {
        !          2359:                                        lpo->dev->result = isc_result;
        !          2360:                                        socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
        !          2361:                                                "canceled_send");
        !          2362:                                        send_senddone_event(sock, &lpo->dev);
        !          2363:                                }
        !          2364:                                break;
        !          2365: 
        !          2366:                        case SOCKET_ACCEPT:
        !          2367:                                INSIST(sock->pending_iocp > 0);
        !          2368:                                sock->pending_iocp--;
        !          2369:                                INSIST(sock->pending_accept > 0);
        !          2370:                                sock->pending_accept--;
        !          2371:                                if (acceptdone_is_active(sock, lpo->adev)) {
        !          2372:                                        closesocket(lpo->adev->newsocket->fd);
        !          2373:                                        lpo->adev->newsocket->fd = INVALID_SOCKET;
        !          2374:                                        lpo->adev->newsocket->references--;
        !          2375:                                        free_socket(&lpo->adev->newsocket, __LINE__);
        !          2376:                                        lpo->adev->result = isc_result;
        !          2377:                                        socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
        !          2378:                                                "canceled_accept");
        !          2379:                                        send_acceptdone_event(sock, &lpo->adev);
        !          2380:                                }
        !          2381:                                break;
        !          2382: 
        !          2383:                        case SOCKET_CONNECT:
        !          2384:                                INSIST(sock->pending_iocp > 0);
        !          2385:                                sock->pending_iocp--;
        !          2386:                                INSIST(sock->pending_connect == 1);
        !          2387:                                sock->pending_connect = 0;
        !          2388:                                if (connectdone_is_active(sock, lpo->cdev)) {
        !          2389:                                        lpo->cdev->result = isc_result;
        !          2390:                                        socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
        !          2391:                                                "canceled_connect");
        !          2392:                                        send_connectdone_event(sock, &lpo->cdev);
        !          2393:                                }
        !          2394:                                break;
        !          2395:                        }
        !          2396:                        maybe_free_socket(&sock, __LINE__);
        !          2397: 
        !          2398:                        if (lpo != NULL)
        !          2399:                                HeapFree(hHeapHandle, 0, lpo);
        !          2400:                        continue;
        !          2401:                }
        !          2402: 
        !          2403:                messagehdr = &lpo->messagehdr;
        !          2404: 
        !          2405:                switch (request) {
        !          2406:                case SOCKET_RECV:
        !          2407:                        internal_recv(sock, nbytes);
        !          2408:                        break;
        !          2409:                case SOCKET_SEND:
        !          2410:                        internal_send(sock, lpo->dev, messagehdr, nbytes, errstatus, lpo);
        !          2411:                        break;
        !          2412:                case SOCKET_ACCEPT:
        !          2413:                        internal_accept(sock, lpo, errstatus);
        !          2414:                        break;
        !          2415:                case SOCKET_CONNECT:
        !          2416:                        internal_connect(sock, lpo, errstatus);
        !          2417:                        break;
        !          2418:                }
        !          2419: 
        !          2420:                if (lpo != NULL)
        !          2421:                        HeapFree(hHeapHandle, 0, lpo);
        !          2422:        }
        !          2423: 
        !          2424:        /*
        !          2425:         * Exit Completion Port Thread
        !          2426:         */
        !          2427:        manager_log(manager, TRACE,
        !          2428:                    isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
        !          2429:                                   ISC_MSG_EXITING, "SocketIoThread exiting"));
        !          2430:        return ((isc_threadresult_t)0);
        !          2431: }
        !          2432: 
        !          2433: /*
        !          2434:  * Create a new socket manager.
        !          2435:  */
        !          2436: isc_result_t
        !          2437: isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
        !          2438:        return (isc_socketmgr_create2(mctx, managerp, 0));
        !          2439: }
        !          2440: 
        !          2441: isc_result_t
        !          2442: isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
        !          2443:                     unsigned int maxsocks)
        !          2444: {
        !          2445:        isc_socketmgr_t *manager;
        !          2446:        isc_result_t result;
        !          2447: 
        !          2448:        REQUIRE(managerp != NULL && *managerp == NULL);
        !          2449: 
        !          2450:        if (maxsocks != 0)
        !          2451:                return (ISC_R_NOTIMPLEMENTED);
        !          2452: 
        !          2453:        manager = isc_mem_get(mctx, sizeof(*manager));
        !          2454:        if (manager == NULL)
        !          2455:                return (ISC_R_NOMEMORY);
        !          2456: 
        !          2457:        InitSockets();
        !          2458: 
        !          2459:        manager->magic = SOCKET_MANAGER_MAGIC;
        !          2460:        manager->mctx = NULL;
        !          2461:        manager->stats = NULL;
        !          2462:        ISC_LIST_INIT(manager->socklist);
        !          2463:        result = isc_mutex_init(&manager->lock);
        !          2464:        if (result != ISC_R_SUCCESS) {
        !          2465:                isc_mem_put(mctx, manager, sizeof(*manager));
        !          2466:                return (result);
        !          2467:        }
        !          2468:        if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
        !          2469:                DESTROYLOCK(&manager->lock);
        !          2470:                isc_mem_put(mctx, manager, sizeof(*manager));
        !          2471:                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !          2472:                                 "isc_condition_init() %s",
        !          2473:                                 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
        !          2474:                                                ISC_MSG_FAILED, "failed"));
        !          2475:                return (ISC_R_UNEXPECTED);
        !          2476:        }
        !          2477: 
        !          2478:        isc_mem_attach(mctx, &manager->mctx);
        !          2479: 
        !          2480:        iocompletionport_init(manager); /* Create the Completion Ports */
        !          2481: 
        !          2482:        manager->bShutdown = ISC_FALSE;
        !          2483:        manager->totalSockets = 0;
        !          2484:        manager->iocp_total = 0;
        !          2485: 
        !          2486:        *managerp = manager;
        !          2487: 
        !          2488:        return (ISC_R_SUCCESS);
        !          2489: }
        !          2490: 
        !          2491: isc_result_t
        !          2492: isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
        !          2493:        REQUIRE(VALID_MANAGER(manager));
        !          2494:        REQUIRE(nsockp != NULL);
        !          2495: 
        !          2496:        return (ISC_R_NOTIMPLEMENTED);
        !          2497: }
        !          2498: 
        !          2499: void
        !          2500: isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
        !          2501:        REQUIRE(VALID_MANAGER(manager));
        !          2502:        REQUIRE(ISC_LIST_EMPTY(manager->socklist));
        !          2503:        REQUIRE(manager->stats == NULL);
        !          2504:        REQUIRE(isc_stats_ncounters(stats) == isc_sockstatscounter_max);
        !          2505: 
        !          2506:        isc_stats_attach(stats, &manager->stats);
        !          2507: }
        !          2508: 
        !          2509: void
        !          2510: isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
        !          2511:        isc_socketmgr_t *manager;
        !          2512:        int i;
        !          2513:        isc_mem_t *mctx;
        !          2514: 
        !          2515:        /*
        !          2516:         * Destroy a socket manager.
        !          2517:         */
        !          2518: 
        !          2519:        REQUIRE(managerp != NULL);
        !          2520:        manager = *managerp;
        !          2521:        REQUIRE(VALID_MANAGER(manager));
        !          2522: 
        !          2523:        LOCK(&manager->lock);
        !          2524: 
        !          2525:        /*
        !          2526:         * Wait for all sockets to be destroyed.
        !          2527:         */
        !          2528:        while (!ISC_LIST_EMPTY(manager->socklist)) {
        !          2529:                manager_log(manager, CREATION,
        !          2530:                            isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
        !          2531:                                           ISC_MSG_SOCKETSREMAIN,
        !          2532:                                           "sockets exist"));
        !          2533:                WAIT(&manager->shutdown_ok, &manager->lock);
        !          2534:        }
        !          2535: 
        !          2536:        UNLOCK(&manager->lock);
        !          2537: 
        !          2538:        /*
        !          2539:         * Here, we need to had some wait code for the completion port
        !          2540:         * thread.
        !          2541:         */
        !          2542:        signal_iocompletionport_exit(manager);
        !          2543:        manager->bShutdown = ISC_TRUE;
        !          2544: 
        !          2545:        /*
        !          2546:         * Wait for threads to exit.
        !          2547:         */
        !          2548:        for (i = 0; i < manager->maxIOCPThreads; i++) {
        !          2549:                if (isc_thread_join((isc_thread_t) manager->hIOCPThreads[i],
        !          2550:                        NULL) != ISC_R_SUCCESS)
        !          2551:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !          2552:                                 "isc_thread_join() for Completion Port %s",
        !          2553:                                 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
        !          2554:                                                ISC_MSG_FAILED, "failed"));
        !          2555:        }
        !          2556:        /*
        !          2557:         * Clean up.
        !          2558:         */
        !          2559: 
        !          2560:        CloseHandle(manager->hIoCompletionPort);
        !          2561: 
        !          2562:        (void)isc_condition_destroy(&manager->shutdown_ok);
        !          2563: 
        !          2564:        DESTROYLOCK(&manager->lock);
        !          2565:        if (manager->stats != NULL)
        !          2566:                isc_stats_detach(&manager->stats);
        !          2567:        manager->magic = 0;
        !          2568:        mctx= manager->mctx;
        !          2569:        isc_mem_put(mctx, manager, sizeof(*manager));
        !          2570: 
        !          2571:        isc_mem_detach(&mctx);
        !          2572: 
        !          2573:        *managerp = NULL;
        !          2574: }
        !          2575: 
        !          2576: static void
        !          2577: queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev)
        !          2578: {
        !          2579:        isc_task_t *ntask = NULL;
        !          2580: 
        !          2581:        isc_task_attach(task, &ntask);
        !          2582:        dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
        !          2583: 
        !          2584:        /*
        !          2585:         * Enqueue the request.
        !          2586:         */
        !          2587:        INSIST(!ISC_LINK_LINKED(dev, ev_link));
        !          2588:        ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link);
        !          2589: 
        !          2590:        socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
        !          2591:                   "queue_receive_event: event %p -> task %p",
        !          2592:                   dev, ntask);
        !          2593: }
        !          2594: 
        !          2595: /*
        !          2596:  * Check the pending receive queue, and if we have data pending, give it to this
        !          2597:  * caller.  If we have none, queue an I/O request.  If this caller is not the first
        !          2598:  * on the list, then we will just queue this event and return.
        !          2599:  *
        !          2600:  * Caller must have the socket locked.
        !          2601:  */
        !          2602: static isc_result_t
        !          2603: socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
        !          2604:            unsigned int flags)
        !          2605: {
        !          2606:        int cc = 0;
        !          2607:        isc_task_t *ntask = NULL;
        !          2608:        isc_result_t result = ISC_R_SUCCESS;
        !          2609:        int recv_errno = 0;
        !          2610: 
        !          2611:        dev->ev_sender = task;
        !          2612: 
        !          2613:        if (sock->fd == INVALID_SOCKET)
        !          2614:                return (ISC_R_EOF);
        !          2615: 
        !          2616:        /*
        !          2617:         * Queue our event on the list of things to do.  Call our function to
        !          2618:         * attempt to fill buffers as much as possible, and return done events.
        !          2619:         * We are going to lie about our handling of the ISC_SOCKFLAG_IMMEDIATE
        !          2620:         * here and tell our caller that we could not satisfy it immediately.
        !          2621:         */
        !          2622:        queue_receive_event(sock, task, dev);
        !          2623:        if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
        !          2624:                result = ISC_R_INPROGRESS;
        !          2625: 
        !          2626:        completeio_recv(sock);
        !          2627: 
        !          2628:        /*
        !          2629:         * If there are more receivers waiting for data, queue another receive
        !          2630:         * here.  If the
        !          2631:         */
        !          2632:        queue_receive_request(sock);
        !          2633: 
        !          2634:        return (result);
        !          2635: }
        !          2636: 
        !          2637: isc_result_t
        !          2638: isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
        !          2639:                 unsigned int minimum, isc_task_t *task,
        !          2640:                 isc_taskaction_t action, const void *arg)
        !          2641: {
        !          2642:        isc_socketevent_t *dev;
        !          2643:        isc_socketmgr_t *manager;
        !          2644:        unsigned int iocount;
        !          2645:        isc_buffer_t *buffer;
        !          2646:        isc_result_t ret;
        !          2647: 
        !          2648:        REQUIRE(VALID_SOCKET(sock));
        !          2649:        LOCK(&sock->lock);
        !          2650:        CONSISTENT(sock);
        !          2651: 
        !          2652:        /*
        !          2653:         * Make sure that the socket is not closed.  XXXMLG change error here?
        !          2654:         */
        !          2655:        if (sock->fd == INVALID_SOCKET) {
        !          2656:                UNLOCK(&sock->lock);
        !          2657:                return (ISC_R_CONNREFUSED);
        !          2658:        }
        !          2659: 
        !          2660:        REQUIRE(buflist != NULL);
        !          2661:        REQUIRE(!ISC_LIST_EMPTY(*buflist));
        !          2662:        REQUIRE(task != NULL);
        !          2663:        REQUIRE(action != NULL);
        !          2664: 
        !          2665:        manager = sock->manager;
        !          2666:        REQUIRE(VALID_MANAGER(manager));
        !          2667: 
        !          2668:        iocount = isc_bufferlist_availablecount(buflist);
        !          2669:        REQUIRE(iocount > 0);
        !          2670: 
        !          2671:        INSIST(sock->bound);
        !          2672: 
        !          2673:        dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
        !          2674:        if (dev == NULL) {
        !          2675:                UNLOCK(&sock->lock);
        !          2676:                return (ISC_R_NOMEMORY);
        !          2677:        }
        !          2678: 
        !          2679:        /*
        !          2680:         * UDP sockets are always partial read
        !          2681:         */
        !          2682:        if (sock->type == isc_sockettype_udp)
        !          2683:                dev->minimum = 1;
        !          2684:        else {
        !          2685:                if (minimum == 0)
        !          2686:                        dev->minimum = iocount;
        !          2687:                else
        !          2688:                        dev->minimum = minimum;
        !          2689:        }
        !          2690: 
        !          2691:        /*
        !          2692:         * Move each buffer from the passed in list to our internal one.
        !          2693:         */
        !          2694:        buffer = ISC_LIST_HEAD(*buflist);
        !          2695:        while (buffer != NULL) {
        !          2696:                ISC_LIST_DEQUEUE(*buflist, buffer, link);
        !          2697:                ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
        !          2698:                buffer = ISC_LIST_HEAD(*buflist);
        !          2699:        }
        !          2700: 
        !          2701:        ret = socket_recv(sock, dev, task, 0);
        !          2702: 
        !          2703:        UNLOCK(&sock->lock);
        !          2704:        return (ret);
        !          2705: }
        !          2706: 
        !          2707: isc_result_t
        !          2708: isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
        !          2709:                isc_task_t *task, isc_taskaction_t action, const void *arg)
        !          2710: {
        !          2711:        isc_socketevent_t *dev;
        !          2712:        isc_socketmgr_t *manager;
        !          2713:        isc_result_t ret;
        !          2714: 
        !          2715:        REQUIRE(VALID_SOCKET(sock));
        !          2716:        LOCK(&sock->lock);
        !          2717:        CONSISTENT(sock);
        !          2718: 
        !          2719:        /*
        !          2720:         * make sure that the socket's not closed
        !          2721:         */
        !          2722:        if (sock->fd == INVALID_SOCKET) {
        !          2723:                UNLOCK(&sock->lock);
        !          2724:                return (ISC_R_CONNREFUSED);
        !          2725:        }
        !          2726:        REQUIRE(action != NULL);
        !          2727: 
        !          2728:        manager = sock->manager;
        !          2729:        REQUIRE(VALID_MANAGER(manager));
        !          2730: 
        !          2731:        INSIST(sock->bound);
        !          2732: 
        !          2733:        dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
        !          2734:        if (dev == NULL) {
        !          2735:                UNLOCK(&sock->lock);
        !          2736:                return (ISC_R_NOMEMORY);
        !          2737:        }
        !          2738: 
        !          2739:        ret = isc_socket_recv2(sock, region, minimum, task, dev, 0);
        !          2740:        UNLOCK(&sock->lock);
        !          2741:        return (ret);
        !          2742: }
        !          2743: 
        !          2744: isc_result_t
        !          2745: isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
        !          2746:                 unsigned int minimum, isc_task_t *task,
        !          2747:                 isc_socketevent_t *event, unsigned int flags)
        !          2748: {
        !          2749:        isc_result_t ret;
        !          2750: 
        !          2751:        REQUIRE(VALID_SOCKET(sock));
        !          2752:        LOCK(&sock->lock);
        !          2753:        CONSISTENT(sock);
        !          2754: 
        !          2755:        event->result = ISC_R_UNEXPECTED;
        !          2756:        event->ev_sender = sock;
        !          2757:        /*
        !          2758:         * make sure that the socket's not closed
        !          2759:         */
        !          2760:        if (sock->fd == INVALID_SOCKET) {
        !          2761:                UNLOCK(&sock->lock);
        !          2762:                return (ISC_R_CONNREFUSED);
        !          2763:        }
        !          2764: 
        !          2765:        ISC_LIST_INIT(event->bufferlist);
        !          2766:        event->region = *region;
        !          2767:        event->n = 0;
        !          2768:        event->offset = 0;
        !          2769:        event->attributes = 0;
        !          2770: 
        !          2771:        /*
        !          2772:         * UDP sockets are always partial read.
        !          2773:         */
        !          2774:        if (sock->type == isc_sockettype_udp)
        !          2775:                event->minimum = 1;
        !          2776:        else {
        !          2777:                if (minimum == 0)
        !          2778:                        event->minimum = region->length;
        !          2779:                else
        !          2780:                        event->minimum = minimum;
        !          2781:        }
        !          2782: 
        !          2783:        ret = socket_recv(sock, event, task, flags);
        !          2784:        UNLOCK(&sock->lock);
        !          2785:        return (ret);
        !          2786: }
        !          2787: 
        !          2788: /*
        !          2789:  * Caller must have the socket locked.
        !          2790:  */
        !          2791: static isc_result_t
        !          2792: socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
        !          2793:            isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
        !          2794:            unsigned int flags)
        !          2795: {
        !          2796:        int io_state;
        !          2797:        int send_errno = 0;
        !          2798:        int cc = 0;
        !          2799:        isc_task_t *ntask = NULL;
        !          2800:        isc_result_t result = ISC_R_SUCCESS;
        !          2801: 
        !          2802:        dev->ev_sender = task;
        !          2803: 
        !          2804:        set_dev_address(address, sock, dev);
        !          2805:        if (pktinfo != NULL) {
        !          2806:                socket_log(__LINE__, sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET,
        !          2807:                           ISC_MSG_PKTINFOPROVIDED,
        !          2808:                           "pktinfo structure provided, ifindex %u (set to 0)",
        !          2809:                           pktinfo->ipi6_ifindex);
        !          2810: 
        !          2811:                dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO;
        !          2812:                dev->pktinfo = *pktinfo;
        !          2813:                /*
        !          2814:                 * Set the pktinfo index to 0 here, to let the kernel decide
        !          2815:                 * what interface it should send on.
        !          2816:                 */
        !          2817:                dev->pktinfo.ipi6_ifindex = 0;
        !          2818:        }
        !          2819: 
        !          2820:        io_state = startio_send(sock, dev, &cc, &send_errno);
        !          2821:        switch (io_state) {
        !          2822:        case DOIO_PENDING:      /* I/O started. Nothing more to do */
        !          2823:        case DOIO_SOFT:
        !          2824:                /*
        !          2825:                 * We couldn't send all or part of the request right now, so
        !          2826:                 * queue it unless ISC_SOCKFLAG_NORETRY is set.
        !          2827:                 */
        !          2828:                if ((flags & ISC_SOCKFLAG_NORETRY) == 0) {
        !          2829:                        isc_task_attach(task, &ntask);
        !          2830:                        dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
        !          2831: 
        !          2832:                        /*
        !          2833:                         * Enqueue the request.
        !          2834:                         */
        !          2835:                        INSIST(!ISC_LINK_LINKED(dev, ev_link));
        !          2836:                        ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link);
        !          2837: 
        !          2838:                        socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
        !          2839:                                   "socket_send: event %p -> task %p",
        !          2840:                                   dev, ntask);
        !          2841: 
        !          2842:                        if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
        !          2843:                                result = ISC_R_INPROGRESS;
        !          2844:                        break;
        !          2845:                }
        !          2846: 
        !          2847:        case DOIO_SUCCESS:
        !          2848:                break;
        !          2849:        }
        !          2850: 
        !          2851:        return (result);
        !          2852: }
        !          2853: 
        !          2854: isc_result_t
        !          2855: isc_socket_send(isc_socket_t *sock, isc_region_t *region,
        !          2856:                isc_task_t *task, isc_taskaction_t action, const void *arg)
        !          2857: {
        !          2858:        /*
        !          2859:         * REQUIRE() checking is performed in isc_socket_sendto().
        !          2860:         */
        !          2861:        return (isc_socket_sendto(sock, region, task, action, arg, NULL,
        !          2862:                                  NULL));
        !          2863: }
        !          2864: 
        !          2865: isc_result_t
        !          2866: isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
        !          2867:                  isc_task_t *task, isc_taskaction_t action, const void *arg,
        !          2868:                  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
        !          2869: {
        !          2870:        isc_socketevent_t *dev;
        !          2871:        isc_socketmgr_t *manager;
        !          2872:        isc_result_t ret;
        !          2873: 
        !          2874:        REQUIRE(VALID_SOCKET(sock));
        !          2875:        REQUIRE(sock->type != isc_sockettype_fdwatch);
        !          2876: 
        !          2877:        LOCK(&sock->lock);
        !          2878:        CONSISTENT(sock);
        !          2879: 
        !          2880:        /*
        !          2881:         * make sure that the socket's not closed
        !          2882:         */
        !          2883:        if (sock->fd == INVALID_SOCKET) {
        !          2884:                UNLOCK(&sock->lock);
        !          2885:                return (ISC_R_CONNREFUSED);
        !          2886:        }
        !          2887:        REQUIRE(region != NULL);
        !          2888:        REQUIRE(task != NULL);
        !          2889:        REQUIRE(action != NULL);
        !          2890: 
        !          2891:        manager = sock->manager;
        !          2892:        REQUIRE(VALID_MANAGER(manager));
        !          2893: 
        !          2894:        INSIST(sock->bound);
        !          2895: 
        !          2896:        dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
        !          2897:        if (dev == NULL) {
        !          2898:                UNLOCK(&sock->lock);
        !          2899:                return (ISC_R_NOMEMORY);
        !          2900:        }
        !          2901:        dev->region = *region;
        !          2902: 
        !          2903:        ret = socket_send(sock, dev, task, address, pktinfo, 0);
        !          2904:        UNLOCK(&sock->lock);
        !          2905:        return (ret);
        !          2906: }
        !          2907: 
        !          2908: isc_result_t
        !          2909: isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
        !          2910:                 isc_task_t *task, isc_taskaction_t action, const void *arg)
        !          2911: {
        !          2912:        return (isc_socket_sendtov(sock, buflist, task, action, arg, NULL,
        !          2913:                                   NULL));
        !          2914: }
        !          2915: 
        !          2916: isc_result_t
        !          2917: isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
        !          2918:                   isc_task_t *task, isc_taskaction_t action, const void *arg,
        !          2919:                   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
        !          2920: {
        !          2921:        isc_socketevent_t *dev;
        !          2922:        isc_socketmgr_t *manager;
        !          2923:        unsigned int iocount;
        !          2924:        isc_buffer_t *buffer;
        !          2925:        isc_result_t ret;
        !          2926: 
        !          2927:        REQUIRE(VALID_SOCKET(sock));
        !          2928: 
        !          2929:        LOCK(&sock->lock);
        !          2930:        CONSISTENT(sock);
        !          2931: 
        !          2932:        /*
        !          2933:         * make sure that the socket's not closed
        !          2934:         */
        !          2935:        if (sock->fd == INVALID_SOCKET) {
        !          2936:                UNLOCK(&sock->lock);
        !          2937:                return (ISC_R_CONNREFUSED);
        !          2938:        }
        !          2939:        REQUIRE(buflist != NULL);
        !          2940:        REQUIRE(!ISC_LIST_EMPTY(*buflist));
        !          2941:        REQUIRE(task != NULL);
        !          2942:        REQUIRE(action != NULL);
        !          2943: 
        !          2944:        manager = sock->manager;
        !          2945:        REQUIRE(VALID_MANAGER(manager));
        !          2946: 
        !          2947:        iocount = isc_bufferlist_usedcount(buflist);
        !          2948:        REQUIRE(iocount > 0);
        !          2949: 
        !          2950:        dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
        !          2951:        if (dev == NULL) {
        !          2952:                UNLOCK(&sock->lock);
        !          2953:                return (ISC_R_NOMEMORY);
        !          2954:        }
        !          2955: 
        !          2956:        /*
        !          2957:         * Move each buffer from the passed in list to our internal one.
        !          2958:         */
        !          2959:        buffer = ISC_LIST_HEAD(*buflist);
        !          2960:        while (buffer != NULL) {
        !          2961:                ISC_LIST_DEQUEUE(*buflist, buffer, link);
        !          2962:                ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
        !          2963:                buffer = ISC_LIST_HEAD(*buflist);
        !          2964:        }
        !          2965: 
        !          2966:        ret = socket_send(sock, dev, task, address, pktinfo, 0);
        !          2967:        UNLOCK(&sock->lock);
        !          2968:        return (ret);
        !          2969: }
        !          2970: 
        !          2971: isc_result_t
        !          2972: isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
        !          2973:                   isc_task_t *task,
        !          2974:                   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
        !          2975:                   isc_socketevent_t *event, unsigned int flags)
        !          2976: {
        !          2977:        isc_result_t ret;
        !          2978: 
        !          2979:        REQUIRE(VALID_SOCKET(sock));
        !          2980:        LOCK(&sock->lock);
        !          2981:        CONSISTENT(sock);
        !          2982: 
        !          2983:        REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0);
        !          2984:        if ((flags & ISC_SOCKFLAG_NORETRY) != 0)
        !          2985:                REQUIRE(sock->type == isc_sockettype_udp);
        !          2986:        event->ev_sender = sock;
        !          2987:        event->result = ISC_R_UNEXPECTED;
        !          2988:        /*
        !          2989:         * make sure that the socket's not closed
        !          2990:         */
        !          2991:        if (sock->fd == INVALID_SOCKET) {
        !          2992:                UNLOCK(&sock->lock);
        !          2993:                return (ISC_R_CONNREFUSED);
        !          2994:        }
        !          2995:        ISC_LIST_INIT(event->bufferlist);
        !          2996:        event->region = *region;
        !          2997:        event->n = 0;
        !          2998:        event->offset = 0;
        !          2999:        event->attributes = 0;
        !          3000: 
        !          3001:        ret = socket_send(sock, event, task, address, pktinfo, flags);
        !          3002:        UNLOCK(&sock->lock);
        !          3003:        return (ret);
        !          3004: }
        !          3005: 
        !          3006: isc_result_t
        !          3007: isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
        !          3008:                unsigned int options) {
        !          3009:        int bind_errno;
        !          3010:        char strbuf[ISC_STRERRORSIZE];
        !          3011:        int on = 1;
        !          3012: 
        !          3013:        REQUIRE(VALID_SOCKET(sock));
        !          3014:        LOCK(&sock->lock);
        !          3015:        CONSISTENT(sock);
        !          3016: 
        !          3017:        /*
        !          3018:         * make sure that the socket's not closed
        !          3019:         */
        !          3020:        if (sock->fd == INVALID_SOCKET) {
        !          3021:                UNLOCK(&sock->lock);
        !          3022:                return (ISC_R_CONNREFUSED);
        !          3023:        }
        !          3024: 
        !          3025:        INSIST(!sock->bound);
        !          3026: 
        !          3027:        if (sock->pf != sockaddr->type.sa.sa_family) {
        !          3028:                UNLOCK(&sock->lock);
        !          3029:                return (ISC_R_FAMILYMISMATCH);
        !          3030:        }
        !          3031:        /*
        !          3032:         * Only set SO_REUSEADDR when we want a specific port.
        !          3033:         */
        !          3034:        if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
        !          3035:            isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
        !          3036:            setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
        !          3037:                       sizeof(on)) < 0) {
        !          3038:                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !          3039:                                 "setsockopt(%d) %s", sock->fd,
        !          3040:                                 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
        !          3041:                                                ISC_MSG_FAILED, "failed"));
        !          3042:                /* Press on... */
        !          3043:        }
        !          3044:        if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) {
        !          3045:                bind_errno = WSAGetLastError();
        !          3046:                UNLOCK(&sock->lock);
        !          3047:                switch (bind_errno) {
        !          3048:                case WSAEACCES:
        !          3049:                        return (ISC_R_NOPERM);
        !          3050:                case WSAEADDRNOTAVAIL:
        !          3051:                        return (ISC_R_ADDRNOTAVAIL);
        !          3052:                case WSAEADDRINUSE:
        !          3053:                        return (ISC_R_ADDRINUSE);
        !          3054:                case WSAEINVAL:
        !          3055:                        return (ISC_R_BOUND);
        !          3056:                default:
        !          3057:                        isc__strerror(bind_errno, strbuf, sizeof(strbuf));
        !          3058:                        UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s",
        !          3059:                                         strbuf);
        !          3060:                        return (ISC_R_UNEXPECTED);
        !          3061:                }
        !          3062:        }
        !          3063: 
        !          3064:        socket_log(__LINE__, sock, sockaddr, TRACE,
        !          3065:                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound");
        !          3066:        sock->bound = 1;
        !          3067: 
        !          3068:        UNLOCK(&sock->lock);
        !          3069:        return (ISC_R_SUCCESS);
        !          3070: }
        !          3071: 
        !          3072: isc_result_t
        !          3073: isc_socket_filter(isc_socket_t *sock, const char *filter) {
        !          3074:        UNUSED(sock);
        !          3075:        UNUSED(filter);
        !          3076: 
        !          3077:        REQUIRE(VALID_SOCKET(sock));
        !          3078:        return (ISC_R_NOTIMPLEMENTED);
        !          3079: }
        !          3080: 
        !          3081: /*
        !          3082:  * Set up to listen on a given socket.  We do this by creating an internal
        !          3083:  * event that will be dispatched when the socket has read activity.  The
        !          3084:  * watcher will send the internal event to the task when there is a new
        !          3085:  * connection.
        !          3086:  *
        !          3087:  * Unlike in read, we don't preallocate a done event here.  Every time there
        !          3088:  * is a new connection we'll have to allocate a new one anyway, so we might
        !          3089:  * as well keep things simple rather than having to track them.
        !          3090:  */
        !          3091: isc_result_t
        !          3092: isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
        !          3093:        char strbuf[ISC_STRERRORSIZE];
        !          3094: 
        !          3095:        REQUIRE(VALID_SOCKET(sock));
        !          3096: 
        !          3097:        LOCK(&sock->lock);
        !          3098:        CONSISTENT(sock);
        !          3099: 
        !          3100:        /*
        !          3101:         * make sure that the socket's not closed
        !          3102:         */
        !          3103:        if (sock->fd == INVALID_SOCKET) {
        !          3104:                UNLOCK(&sock->lock);
        !          3105:                return (ISC_R_CONNREFUSED);
        !          3106:        }
        !          3107: 
        !          3108:        REQUIRE(!sock->listener);
        !          3109:        REQUIRE(sock->bound);
        !          3110:        REQUIRE(sock->type == isc_sockettype_tcp);
        !          3111: 
        !          3112:        if (backlog == 0)
        !          3113:                backlog = SOMAXCONN;
        !          3114: 
        !          3115:        if (listen(sock->fd, (int)backlog) < 0) {
        !          3116:                UNLOCK(&sock->lock);
        !          3117:                isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
        !          3118: 
        !          3119:                UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", strbuf);
        !          3120: 
        !          3121:                return (ISC_R_UNEXPECTED);
        !          3122:        }
        !          3123: 
        !          3124:        socket_log(__LINE__, sock, NULL, TRACE,
        !          3125:                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "listening");
        !          3126:        sock->listener = 1;
        !          3127:        _set_state(sock, SOCK_LISTEN);
        !          3128: 
        !          3129:        UNLOCK(&sock->lock);
        !          3130:        return (ISC_R_SUCCESS);
        !          3131: }
        !          3132: 
        !          3133: /*
        !          3134:  * This should try to do aggressive accept() XXXMLG
        !          3135:  */
        !          3136: isc_result_t
        !          3137: isc_socket_accept(isc_socket_t *sock,
        !          3138:                  isc_task_t *task, isc_taskaction_t action, const void *arg)
        !          3139: {
        !          3140:        isc_socket_newconnev_t *adev;
        !          3141:        isc_socketmgr_t *manager;
        !          3142:        isc_task_t *ntask = NULL;
        !          3143:        isc_socket_t *nsock;
        !          3144:        isc_result_t result;
        !          3145:        IoCompletionInfo *lpo;
        !          3146: 
        !          3147:        REQUIRE(VALID_SOCKET(sock));
        !          3148: 
        !          3149:        manager = sock->manager;
        !          3150:        REQUIRE(VALID_MANAGER(manager));
        !          3151: 
        !          3152:        LOCK(&sock->lock);
        !          3153:        CONSISTENT(sock);
        !          3154: 
        !          3155:        /*
        !          3156:         * make sure that the socket's not closed
        !          3157:         */
        !          3158:        if (sock->fd == INVALID_SOCKET) {
        !          3159:                UNLOCK(&sock->lock);
        !          3160:                return (ISC_R_CONNREFUSED);
        !          3161:        }
        !          3162: 
        !          3163:        REQUIRE(sock->listener);
        !          3164: 
        !          3165:        /*
        !          3166:         * Sender field is overloaded here with the task we will be sending
        !          3167:         * this event to.  Just before the actual event is delivered the
        !          3168:         * actual ev_sender will be touched up to be the socket.
        !          3169:         */
        !          3170:        adev = (isc_socket_newconnev_t *)
        !          3171:                isc_event_allocate(manager->mctx, task, ISC_SOCKEVENT_NEWCONN,
        !          3172:                                   action, arg, sizeof(*adev));
        !          3173:        if (adev == NULL) {
        !          3174:                UNLOCK(&sock->lock);
        !          3175:                return (ISC_R_NOMEMORY);
        !          3176:        }
        !          3177:        ISC_LINK_INIT(adev, ev_link);
        !          3178: 
        !          3179:        result = allocate_socket(manager, sock->type, &nsock);
        !          3180:        if (result != ISC_R_SUCCESS) {
        !          3181:                isc_event_free((isc_event_t **)&adev);
        !          3182:                UNLOCK(&sock->lock);
        !          3183:                return (result);
        !          3184:        }
        !          3185: 
        !          3186:        /*
        !          3187:         * AcceptEx() requires we pass in a socket.
        !          3188:         */
        !          3189:        nsock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
        !          3190:        if (nsock->fd == INVALID_SOCKET) {
        !          3191:                free_socket(&nsock, __LINE__);
        !          3192:                isc_event_free((isc_event_t **)&adev);
        !          3193:                UNLOCK(&sock->lock);
        !          3194:                return (ISC_R_FAILURE); // XXXMLG need real error message
        !          3195:        }
        !          3196: 
        !          3197:        /*
        !          3198:         * Attach to socket and to task.
        !          3199:         */
        !          3200:        isc_task_attach(task, &ntask);
        !          3201:        nsock->references++;
        !          3202: 
        !          3203:        adev->ev_sender = ntask;
        !          3204:        adev->newsocket = nsock;
        !          3205:        _set_state(nsock, SOCK_ACCEPT);
        !          3206: 
        !          3207:        /*
        !          3208:         * Queue io completion for an accept().
        !          3209:         */
        !          3210:        lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
        !          3211:                                            HEAP_ZERO_MEMORY,
        !          3212:                                            sizeof(IoCompletionInfo));
        !          3213:        RUNTIME_CHECK(lpo != NULL);
        !          3214:        lpo->acceptbuffer = (void *)HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY,
        !          3215:                (sizeof(SOCKADDR_STORAGE) + 16) * 2);
        !          3216:        RUNTIME_CHECK(lpo->acceptbuffer != NULL);
        !          3217: 
        !          3218:        lpo->adev = adev;
        !          3219:        lpo->request_type = SOCKET_ACCEPT;
        !          3220: 
        !          3221:        ISCAcceptEx(sock->fd,
        !          3222:                    nsock->fd,                          /* Accepted Socket */
        !          3223:                    lpo->acceptbuffer,                  /* Buffer for initial Recv */
        !          3224:                    0,                                  /* Length of Buffer */
        !          3225:                    sizeof(SOCKADDR_STORAGE) + 16,              /* Local address length + 16 */
        !          3226:                    sizeof(SOCKADDR_STORAGE) + 16,              /* Remote address lengh + 16 */
        !          3227:                    (LPDWORD)&lpo->received_bytes,      /* Bytes Recved */
        !          3228:                    (LPOVERLAPPED)lpo                   /* Overlapped structure */
        !          3229:                    );
        !          3230:        iocompletionport_update(nsock);
        !          3231: 
        !          3232:        socket_log(__LINE__, sock, NULL, TRACE,
        !          3233:                   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND,
        !          3234:                   "accepting for nsock %p fd %d", nsock, nsock->fd);
        !          3235: 
        !          3236:        /*
        !          3237:         * Enqueue the event
        !          3238:         */
        !          3239:        ISC_LIST_ENQUEUE(sock->accept_list, adev, ev_link);
        !          3240:        sock->pending_accept++;
        !          3241:        sock->pending_iocp++;
        !          3242: 
        !          3243:        UNLOCK(&sock->lock);
        !          3244:        return (ISC_R_SUCCESS);
        !          3245: }
        !          3246: 
        !          3247: isc_result_t
        !          3248: isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
        !          3249:                   isc_task_t *task, isc_taskaction_t action, const void *arg)
        !          3250: {
        !          3251:        char strbuf[ISC_STRERRORSIZE];
        !          3252:        isc_socket_connev_t *cdev;
        !          3253:        isc_task_t *ntask = NULL;
        !          3254:        isc_socketmgr_t *manager;
        !          3255:        IoCompletionInfo *lpo;
        !          3256:        int bind_errno;
        !          3257: 
        !          3258:        REQUIRE(VALID_SOCKET(sock));
        !          3259:        REQUIRE(addr != NULL);
        !          3260:        REQUIRE(task != NULL);
        !          3261:        REQUIRE(action != NULL);
        !          3262: 
        !          3263:        manager = sock->manager;
        !          3264:        REQUIRE(VALID_MANAGER(manager));
        !          3265:        REQUIRE(addr != NULL);
        !          3266: 
        !          3267:        if (isc_sockaddr_ismulticast(addr))
        !          3268:                return (ISC_R_MULTICAST);
        !          3269: 
        !          3270:        LOCK(&sock->lock);
        !          3271:        CONSISTENT(sock);
        !          3272: 
        !          3273:        /*
        !          3274:         * make sure that the socket's not closed
        !          3275:         */
        !          3276:        if (sock->fd == INVALID_SOCKET) {
        !          3277:                UNLOCK(&sock->lock);
        !          3278:                return (ISC_R_CONNREFUSED);
        !          3279:        }
        !          3280: 
        !          3281:        /*
        !          3282:         * Windows sockets won't connect unless the socket is bound.
        !          3283:         */
        !          3284:        if (!sock->bound) {
        !          3285:                isc_sockaddr_t any;
        !          3286: 
        !          3287:                isc_sockaddr_anyofpf(&any, isc_sockaddr_pf(addr));
        !          3288:                if (bind(sock->fd, &any.type.sa, any.length) < 0) {
        !          3289:                        bind_errno = WSAGetLastError();
        !          3290:                        UNLOCK(&sock->lock);
        !          3291:                        switch (bind_errno) {
        !          3292:                        case WSAEACCES:
        !          3293:                                return (ISC_R_NOPERM);
        !          3294:                        case WSAEADDRNOTAVAIL:
        !          3295:                                return (ISC_R_ADDRNOTAVAIL);
        !          3296:                        case WSAEADDRINUSE:
        !          3297:                                return (ISC_R_ADDRINUSE);
        !          3298:                        case WSAEINVAL:
        !          3299:                                return (ISC_R_BOUND);
        !          3300:                        default:
        !          3301:                                isc__strerror(bind_errno, strbuf,
        !          3302:                                              sizeof(strbuf));
        !          3303:                                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !          3304:                                                 "bind: %s", strbuf);
        !          3305:                                return (ISC_R_UNEXPECTED);
        !          3306:                        }
        !          3307:                }
        !          3308:                sock->bound = 1;
        !          3309:        }
        !          3310: 
        !          3311:        REQUIRE(!sock->pending_connect);
        !          3312: 
        !          3313:        cdev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
        !          3314:                                                        ISC_SOCKEVENT_CONNECT,
        !          3315:                                                        action, arg,
        !          3316:                                                        sizeof(*cdev));
        !          3317:        if (cdev == NULL) {
        !          3318:                UNLOCK(&sock->lock);
        !          3319:                return (ISC_R_NOMEMORY);
        !          3320:        }
        !          3321:        ISC_LINK_INIT(cdev, ev_link);
        !          3322: 
        !          3323:        if (sock->type == isc_sockettype_tcp) {
        !          3324:                /*
        !          3325:                 * Queue io completion for an accept().
        !          3326:                 */
        !          3327:                lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
        !          3328:                                                    HEAP_ZERO_MEMORY,
        !          3329:                                                    sizeof(IoCompletionInfo));
        !          3330:                lpo->cdev = cdev;
        !          3331:                lpo->request_type = SOCKET_CONNECT;
        !          3332: 
        !          3333:                sock->address = *addr;
        !          3334:                ISCConnectEx(sock->fd, &addr->type.sa, addr->length,
        !          3335:                        NULL, 0, NULL, (LPOVERLAPPED)lpo);
        !          3336: 
        !          3337:                /*
        !          3338:                 * Attach to task.
        !          3339:                 */
        !          3340:                isc_task_attach(task, &ntask);
        !          3341:                cdev->ev_sender = ntask;
        !          3342: 
        !          3343:                sock->pending_connect = 1;
        !          3344:                _set_state(sock, SOCK_CONNECT);
        !          3345: 
        !          3346:                /*
        !          3347:                 * Enqueue the request.
        !          3348:                 */
        !          3349:                sock->connect_ev = cdev;
        !          3350:                sock->pending_iocp++;
        !          3351:        } else {
        !          3352:                WSAConnect(sock->fd, &addr->type.sa, addr->length, NULL, NULL, NULL, NULL);
        !          3353:                cdev->result = ISC_R_SUCCESS;
        !          3354:                isc_task_send(task, (isc_event_t **)&cdev);
        !          3355:        }
        !          3356:        CONSISTENT(sock);
        !          3357:        UNLOCK(&sock->lock);
        !          3358: 
        !          3359:        return (ISC_R_SUCCESS);
        !          3360: }
        !          3361: 
        !          3362: isc_result_t
        !          3363: isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
        !          3364:        isc_result_t result;
        !          3365: 
        !          3366:        REQUIRE(VALID_SOCKET(sock));
        !          3367:        REQUIRE(addressp != NULL);
        !          3368: 
        !          3369:        LOCK(&sock->lock);
        !          3370:        CONSISTENT(sock);
        !          3371: 
        !          3372:        /*
        !          3373:         * make sure that the socket's not closed
        !          3374:         */
        !          3375:        if (sock->fd == INVALID_SOCKET) {
        !          3376:                UNLOCK(&sock->lock);
        !          3377:                return (ISC_R_CONNREFUSED);
        !          3378:        }
        !          3379: 
        !          3380:        if (sock->connected) {
        !          3381:                *addressp = sock->address;
        !          3382:                result = ISC_R_SUCCESS;
        !          3383:        } else {
        !          3384:                result = ISC_R_NOTCONNECTED;
        !          3385:        }
        !          3386: 
        !          3387:        UNLOCK(&sock->lock);
        !          3388: 
        !          3389:        return (result);
        !          3390: }
        !          3391: 
        !          3392: isc_result_t
        !          3393: isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
        !          3394:        ISC_SOCKADDR_LEN_T len;
        !          3395:        isc_result_t result;
        !          3396:        char strbuf[ISC_STRERRORSIZE];
        !          3397: 
        !          3398:        REQUIRE(VALID_SOCKET(sock));
        !          3399:        REQUIRE(addressp != NULL);
        !          3400: 
        !          3401:        LOCK(&sock->lock);
        !          3402:        CONSISTENT(sock);
        !          3403: 
        !          3404:        /*
        !          3405:         * make sure that the socket's not closed
        !          3406:         */
        !          3407:        if (sock->fd == INVALID_SOCKET) {
        !          3408:                UNLOCK(&sock->lock);
        !          3409:                return (ISC_R_CONNREFUSED);
        !          3410:        }
        !          3411: 
        !          3412:        if (!sock->bound) {
        !          3413:                result = ISC_R_NOTBOUND;
        !          3414:                goto out;
        !          3415:        }
        !          3416: 
        !          3417:        result = ISC_R_SUCCESS;
        !          3418: 
        !          3419:        len = sizeof(addressp->type);
        !          3420:        if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) {
        !          3421:                isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
        !          3422:                UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s",
        !          3423:                                 strbuf);
        !          3424:                result = ISC_R_UNEXPECTED;
        !          3425:                goto out;
        !          3426:        }
        !          3427:        addressp->length = (unsigned int)len;
        !          3428: 
        !          3429:  out:
        !          3430:        UNLOCK(&sock->lock);
        !          3431: 
        !          3432:        return (result);
        !          3433: }
        !          3434: 
        !          3435: /*
        !          3436:  * Run through the list of events on this socket, and cancel the ones
        !          3437:  * queued for task "task" of type "how".  "how" is a bitmask.
        !          3438:  */
        !          3439: void
        !          3440: isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
        !          3441: 
        !          3442:        REQUIRE(VALID_SOCKET(sock));
        !          3443: 
        !          3444:        /*
        !          3445:         * Quick exit if there is nothing to do.  Don't even bother locking
        !          3446:         * in this case.
        !          3447:         */
        !          3448:        if (how == 0)
        !          3449:                return;
        !          3450: 
        !          3451:        LOCK(&sock->lock);
        !          3452:        CONSISTENT(sock);
        !          3453: 
        !          3454:        /*
        !          3455:         * make sure that the socket's not closed
        !          3456:         */
        !          3457:        if (sock->fd == INVALID_SOCKET) {
        !          3458:                UNLOCK(&sock->lock);
        !          3459:                return;
        !          3460:        }
        !          3461: 
        !          3462:        /*
        !          3463:         * All of these do the same thing, more or less.
        !          3464:         * Each will:
        !          3465:         *      o If the internal event is marked as "posted" try to
        !          3466:         *        remove it from the task's queue.  If this fails, mark it
        !          3467:         *        as canceled instead, and let the task clean it up later.
        !          3468:         *      o For each I/O request for that task of that type, post
        !          3469:         *        its done event with status of "ISC_R_CANCELED".
        !          3470:         *      o Reset any state needed.
        !          3471:         */
        !          3472: 
        !          3473:        if ((how & ISC_SOCKCANCEL_RECV) == ISC_SOCKCANCEL_RECV) {
        !          3474:                isc_socketevent_t      *dev;
        !          3475:                isc_socketevent_t      *next;
        !          3476:                isc_task_t             *current_task;
        !          3477: 
        !          3478:                dev = ISC_LIST_HEAD(sock->recv_list);
        !          3479:                while (dev != NULL) {
        !          3480:                        current_task = dev->ev_sender;
        !          3481:                        next = ISC_LIST_NEXT(dev, ev_link);
        !          3482:                        if ((task == NULL) || (task == current_task)) {
        !          3483:                                dev->result = ISC_R_CANCELED;
        !          3484:                                send_recvdone_event(sock, &dev);
        !          3485:                        }
        !          3486:                        dev = next;
        !          3487:                }
        !          3488:        }
        !          3489:        how &= ~ISC_SOCKCANCEL_RECV;
        !          3490: 
        !          3491:        if ((how & ISC_SOCKCANCEL_SEND) == ISC_SOCKCANCEL_SEND) {
        !          3492:                isc_socketevent_t      *dev;
        !          3493:                isc_socketevent_t      *next;
        !          3494:                isc_task_t             *current_task;
        !          3495: 
        !          3496:                dev = ISC_LIST_HEAD(sock->send_list);
        !          3497: 
        !          3498:                while (dev != NULL) {
        !          3499:                        current_task = dev->ev_sender;
        !          3500:                        next = ISC_LIST_NEXT(dev, ev_link);
        !          3501:                        if ((task == NULL) || (task == current_task)) {
        !          3502:                                dev->result = ISC_R_CANCELED;
        !          3503:                                send_senddone_event(sock, &dev);
        !          3504:                        }
        !          3505:                        dev = next;
        !          3506:                }
        !          3507:        }
        !          3508:        how &= ~ISC_SOCKCANCEL_SEND;
        !          3509: 
        !          3510:        if (((how & ISC_SOCKCANCEL_ACCEPT) == ISC_SOCKCANCEL_ACCEPT)
        !          3511:            && !ISC_LIST_EMPTY(sock->accept_list)) {
        !          3512:                isc_socket_newconnev_t *dev;
        !          3513:                isc_socket_newconnev_t *next;
        !          3514:                isc_task_t             *current_task;
        !          3515: 
        !          3516:                dev = ISC_LIST_HEAD(sock->accept_list);
        !          3517:                while (dev != NULL) {
        !          3518:                        current_task = dev->ev_sender;
        !          3519:                        next = ISC_LIST_NEXT(dev, ev_link);
        !          3520: 
        !          3521:                        if ((task == NULL) || (task == current_task)) {
        !          3522: 
        !          3523:                                dev->newsocket->references--;
        !          3524:                                closesocket(dev->newsocket->fd);
        !          3525:                                dev->newsocket->fd = INVALID_SOCKET;
        !          3526:                                free_socket(&dev->newsocket, __LINE__);
        !          3527: 
        !          3528:                                dev->result = ISC_R_CANCELED;
        !          3529:                                send_acceptdone_event(sock, &dev);
        !          3530:                        }
        !          3531: 
        !          3532:                        dev = next;
        !          3533:                }
        !          3534:        }
        !          3535:        how &= ~ISC_SOCKCANCEL_ACCEPT;
        !          3536: 
        !          3537:        /*
        !          3538:         * Connecting is not a list.
        !          3539:         */
        !          3540:        if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT)
        !          3541:            && sock->connect_ev != NULL) {
        !          3542:                isc_socket_connev_t    *dev;
        !          3543:                isc_task_t             *current_task;
        !          3544: 
        !          3545:                INSIST(sock->pending_connect);
        !          3546: 
        !          3547:                dev = sock->connect_ev;
        !          3548:                current_task = dev->ev_sender;
        !          3549: 
        !          3550:                if ((task == NULL) || (task == current_task)) {
        !          3551:                        closesocket(sock->fd);
        !          3552:                        sock->fd = INVALID_SOCKET;
        !          3553:                        _set_state(sock, SOCK_CLOSED);
        !          3554: 
        !          3555:                        sock->connect_ev = NULL;
        !          3556:                        dev->result = ISC_R_CANCELED;
        !          3557:                        send_connectdone_event(sock, &dev);
        !          3558:                }
        !          3559:        }
        !          3560:        how &= ~ISC_SOCKCANCEL_CONNECT;
        !          3561: 
        !          3562:        maybe_free_socket(&sock, __LINE__);
        !          3563: }
        !          3564: 
        !          3565: isc_sockettype_t
        !          3566: isc_socket_gettype(isc_socket_t *sock) {
        !          3567:        isc_sockettype_t type;
        !          3568: 
        !          3569:        REQUIRE(VALID_SOCKET(sock));
        !          3570: 
        !          3571:        LOCK(&sock->lock);
        !          3572: 
        !          3573:        /*
        !          3574:         * make sure that the socket's not closed
        !          3575:         */
        !          3576:        if (sock->fd == INVALID_SOCKET) {
        !          3577:                UNLOCK(&sock->lock);
        !          3578:                return (ISC_R_CONNREFUSED);
        !          3579:        }
        !          3580: 
        !          3581:        type = sock->type;
        !          3582:        UNLOCK(&sock->lock);
        !          3583:        return (type);
        !          3584: }
        !          3585: 
        !          3586: isc_boolean_t
        !          3587: isc_socket_isbound(isc_socket_t *sock) {
        !          3588:        isc_boolean_t val;
        !          3589: 
        !          3590:        REQUIRE(VALID_SOCKET(sock));
        !          3591: 
        !          3592:        LOCK(&sock->lock);
        !          3593:        CONSISTENT(sock);
        !          3594: 
        !          3595:        /*
        !          3596:         * make sure that the socket's not closed
        !          3597:         */
        !          3598:        if (sock->fd == INVALID_SOCKET) {
        !          3599:                UNLOCK(&sock->lock);
        !          3600:                return (ISC_FALSE);
        !          3601:        }
        !          3602: 
        !          3603:        val = ((sock->bound) ? ISC_TRUE : ISC_FALSE);
        !          3604:        UNLOCK(&sock->lock);
        !          3605: 
        !          3606:        return (val);
        !          3607: }
        !          3608: 
        !          3609: void
        !          3610: isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
        !          3611: #if defined(IPV6_V6ONLY)
        !          3612:        int onoff = yes ? 1 : 0;
        !          3613: #else
        !          3614:        UNUSED(yes);
        !          3615: #endif
        !          3616: 
        !          3617:        REQUIRE(VALID_SOCKET(sock));
        !          3618: 
        !          3619: #ifdef IPV6_V6ONLY
        !          3620:        if (sock->pf == AF_INET6) {
        !          3621:                (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
        !          3622:                                 (void *)&onoff, sizeof(onoff));
        !          3623:        }
        !          3624: #endif
        !          3625: }
        !          3626: 
        !          3627: void
        !          3628: isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) {
        !          3629:        UNUSED(addr);
        !          3630:        UNUSED(active);
        !          3631: }
        !          3632: 
        !          3633: isc_result_t
        !          3634: isc_socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm,
        !          3635:                    isc_uint32_t owner, isc_uint32_t group)
        !          3636: {
        !          3637:        UNUSED(addr);
        !          3638:        UNUSED(perm);
        !          3639:        UNUSED(owner);
        !          3640:        UNUSED(group);
        !          3641:        return (ISC_R_NOTIMPLEMENTED);
        !          3642: }
        !          3643: 
        !          3644: void
        !          3645: isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
        !          3646: 
        !          3647:        /*
        !          3648:         * Name 'socket'.
        !          3649:         */
        !          3650: 
        !          3651:        REQUIRE(VALID_SOCKET(socket));
        !          3652: 
        !          3653:        LOCK(&socket->lock);
        !          3654:        memset(socket->name, 0, sizeof(socket->name));
        !          3655:        strncpy(socket->name, name, sizeof(socket->name) - 1);
        !          3656:        socket->tag = tag;
        !          3657:        UNLOCK(&socket->lock);
        !          3658: }
        !          3659: 
        !          3660: const char *
        !          3661: isc_socket_getname(isc_socket_t *socket) {
        !          3662:        return (socket->name);
        !          3663: }
        !          3664: 
        !          3665: void *
        !          3666: isc_socket_gettag(isc_socket_t *socket) {
        !          3667:        return (socket->tag);
        !          3668: }
        !          3669: 
        !          3670: void
        !          3671: isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
        !          3672:        UNUSED(manager);
        !          3673:        UNUSED(reserved);
        !          3674: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>