[BACK]Return to netmgr-int.h CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / mpl / bind / dist / lib / isc / netmgr

Annotation of src/external/mpl/bind/dist/lib/isc/netmgr/netmgr-int.h, Revision 1.1.1.3

1.1       christos    1: /*     $NetBSD$        */
                      2:
                      3: /*
                      4:  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
                      5:  *
                      6:  * This Source Code Form is subject to the terms of the Mozilla Public
                      7:  * License, v. 2.0. If a copy of the MPL was not distributed with this
1.1.1.3 ! christos    8:  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
1.1       christos    9:  *
                     10:  * See the COPYRIGHT file distributed with this work for additional
                     11:  * information regarding copyright ownership.
                     12:  */
                     13:
                     14: #pragma once
                     15:
                     16: #include <unistd.h>
                     17: #include <uv.h>
                     18:
1.1.1.3 ! christos   19: #include <openssl/err.h>
        !            20: #include <openssl/ssl.h>
        !            21:
1.1       christos   22: #include <isc/astack.h>
                     23: #include <isc/atomic.h>
                     24: #include <isc/buffer.h>
                     25: #include <isc/condition.h>
                     26: #include <isc/magic.h>
                     27: #include <isc/mem.h>
                     28: #include <isc/netmgr.h>
                     29: #include <isc/queue.h>
1.1.1.2   christos   30: #include <isc/quota.h>
1.1       christos   31: #include <isc/random.h>
                     32: #include <isc/refcount.h>
                     33: #include <isc/region.h>
                     34: #include <isc/result.h>
                     35: #include <isc/sockaddr.h>
                     36: #include <isc/stats.h>
                     37: #include <isc/thread.h>
                     38: #include <isc/util.h>
                     39:
                     40: #include "uv-compat.h"
                     41:
                     42: #define ISC_NETMGR_TID_UNKNOWN -1
                     43:
                     44: #if !defined(WIN32)
                     45: /*
                     46:  * New versions of libuv support recvmmsg on unices.
                     47:  * Since recvbuf is only allocated per worker allocating a bigger one is not
                     48:  * that wasteful.
                     49:  * 20 here is UV__MMSG_MAXWIDTH taken from the current libuv source, nothing
                     50:  * will break if the original value changes.
                     51:  */
                     52: #define ISC_NETMGR_RECVBUF_SIZE (20 * 65536)
                     53: #else
                     54: #define ISC_NETMGR_RECVBUF_SIZE (65536)
                     55: #endif
                     56:
1.1.1.3 ! christos   57: #if defined(SO_REUSEPORT_LB) || (defined(SO_REUSEPORT) && defined(__linux__))
        !            58: #define HAVE_SO_REUSEPORT_LB 1
        !            59: #endif
        !            60:
        !            61: /*
        !            62:  * Define NETMGR_TRACE to activate tracing of handles and sockets.
        !            63:  * This will impair performance but enables us to quickly determine,
        !            64:  * if netmgr resources haven't been cleaned up on shutdown, which ones
        !            65:  * are still in use.
        !            66:  */
        !            67: #ifdef NETMGR_TRACE
        !            68: #define TRACE_SIZE 8
        !            69:
        !            70: void
        !            71: isc__nm_dump_active(isc_nm_t *nm);
        !            72:
        !            73: #if defined(__linux__)
        !            74: #include <syscall.h>
        !            75: #define gettid() (uint32_t) syscall(SYS_gettid)
        !            76: #elif defined(_WIN32)
        !            77: #define gettid() (uint32_t) GetCurrentThreadId()
        !            78: #else
        !            79: #define gettid() (uint32_t) pthread_self()
        !            80: #endif
        !            81:
        !            82: #ifdef NETMGR_TRACE_VERBOSE
        !            83: #define NETMGR_TRACE_LOG(format, ...)                                \
        !            84:        fprintf(stderr, "%" PRIu32 ":%d:%s:%u:%s:" format, gettid(), \
        !            85:                isc_nm_tid(), file, line, func, __VA_ARGS__)
        !            86: #else
        !            87: #define NETMGR_TRACE_LOG(format, ...) \
        !            88:        (void)file;                   \
        !            89:        (void)line;                   \
        !            90:        (void)func;
        !            91: #endif
        !            92:
        !            93: #define FLARG_PASS , file, line, func
        !            94: #define FLARG                                              \
        !            95:        , const char *file __attribute__((unused)),        \
        !            96:                unsigned int line __attribute__((unused)), \
        !            97:                const char *func __attribute__((unused))
        !            98: #define FLARG_IEVENT(ievent)              \
        !            99:        const char *file = ievent->file;  \
        !           100:        unsigned int line = ievent->line; \
        !           101:        const char *func = ievent->func;
        !           102: #define FLARG_IEVENT_PASS(ievent) \
        !           103:        ievent->file = file;      \
        !           104:        ievent->line = line;      \
        !           105:        ievent->func = func;
        !           106: #define isc__nm_uvreq_get(req, sock) \
        !           107:        isc___nm_uvreq_get(req, sock, __FILE__, __LINE__, __func__)
        !           108: #define isc__nm_uvreq_put(req, sock) \
        !           109:        isc___nm_uvreq_put(req, sock, __FILE__, __LINE__, __func__)
        !           110: #define isc__nmsocket_init(sock, mgr, type, iface)                      \
        !           111:        isc___nmsocket_init(sock, mgr, type, iface, __FILE__, __LINE__, \
        !           112:                            __func__)
        !           113: #define isc__nmsocket_put(sockp) \
        !           114:        isc___nmsocket_put(sockp, __FILE__, __LINE__, __func__)
        !           115: #define isc__nmsocket_attach(sock, target) \
        !           116:        isc___nmsocket_attach(sock, target, __FILE__, __LINE__, __func__)
        !           117: #define isc__nmsocket_detach(socketp) \
        !           118:        isc___nmsocket_detach(socketp, __FILE__, __LINE__, __func__)
        !           119: #define isc__nmsocket_close(socketp) \
        !           120:        isc___nmsocket_close(socketp, __FILE__, __LINE__, __func__)
        !           121: #define isc__nmhandle_get(sock, peer, local) \
        !           122:        isc___nmhandle_get(sock, peer, local, __FILE__, __LINE__, __func__)
        !           123: #define isc__nmsocket_prep_destroy(sock) \
        !           124:        isc___nmsocket_prep_destroy(sock, __FILE__, __LINE__, __func__)
        !           125: #else
        !           126: #define NETMGR_TRACE_LOG(format, ...)
        !           127:
        !           128: #define FLARG_PASS
        !           129: #define FLARG
        !           130: #define FLARG_IEVENT(ievent)
        !           131: #define FLARG_IEVENT_PASS(ievent)
        !           132: #define isc__nm_uvreq_get(req, sock) isc___nm_uvreq_get(req, sock)
        !           133: #define isc__nm_uvreq_put(req, sock) isc___nm_uvreq_put(req, sock)
        !           134: #define isc__nmsocket_init(sock, mgr, type, iface) \
        !           135:        isc___nmsocket_init(sock, mgr, type, iface)
        !           136: #define isc__nmsocket_put(sockp)          isc___nmsocket_put(sockp)
        !           137: #define isc__nmsocket_attach(sock, target) isc___nmsocket_attach(sock, target)
        !           138: #define isc__nmsocket_detach(socketp)     isc___nmsocket_detach(socketp)
        !           139: #define isc__nmsocket_close(socketp)      isc___nmsocket_close(socketp)
        !           140: #define isc__nmhandle_get(sock, peer, local) \
        !           141:        isc___nmhandle_get(sock, peer, local)
        !           142: #define isc__nmsocket_prep_destroy(sock) isc___nmsocket_prep_destroy(sock)
        !           143: #endif
        !           144:
1.1       christos  145: /*
                    146:  * Single network event loop worker.
                    147:  */
                    148: typedef struct isc__networker {
                    149:        isc_nm_t *mgr;
                    150:        int id;           /* thread id */
                    151:        uv_loop_t loop;   /* libuv loop structure */
                    152:        uv_async_t async; /* async channel to send
                    153:                           * data to this networker */
                    154:        isc_mutex_t lock;
                    155:        isc_condition_t cond;
                    156:        bool paused;
                    157:        bool finished;
                    158:        isc_thread_t thread;
                    159:        isc_queue_t *ievents;      /* incoming async events */
                    160:        isc_queue_t *ievents_prio; /* priority async events
                    161:                                    * used for listening etc.
                    162:                                    * can be processed while
                    163:                                    * worker is paused */
                    164:        isc_refcount_t references;
                    165:        atomic_int_fast64_t pktcount;
                    166:        char *recvbuf;
                    167:        bool recvbuf_inuse;
                    168: } isc__networker_t;
                    169:
                    170: /*
                    171:  * A general handle for a connection bound to a networker.  For UDP
                    172:  * connections we have peer address here, so both TCP and UDP can be
                    173:  * handled with a simple send-like function
                    174:  */
1.1.1.3 ! christos  175: #define NMHANDLE_MAGIC ISC_MAGIC('N', 'M', 'H', 'D')
        !           176: #define VALID_NMHANDLE(t)                      \
        !           177:        (ISC_MAGIC_VALID(t, NMHANDLE_MAGIC) && \
        !           178:         atomic_load(&(t)->references) > 0)
1.1       christos  179:
                    180: typedef void (*isc__nm_closecb)(isc_nmhandle_t *);
                    181:
                    182: struct isc_nmhandle {
                    183:        int magic;
                    184:        isc_refcount_t references;
                    185:
                    186:        /*
                    187:         * The socket is not 'attached' in the traditional
                    188:         * reference-counting sense. Instead, we keep all handles in an
                    189:         * array in the socket object.  This way, we don't have circular
                    190:         * dependencies and we can close all handles when we're destroying
                    191:         * the socket.
                    192:         */
                    193:        isc_nmsocket_t *sock;
1.1.1.3 ! christos  194:        size_t ah_pos; /* Position in the socket's 'active handles' array */
1.1       christos  195:
                    196:        isc_sockaddr_t peer;
                    197:        isc_sockaddr_t local;
                    198:        isc_nm_opaquecb_t doreset; /* reset extra callback, external */
                    199:        isc_nm_opaquecb_t dofree;  /* free extra callback, external */
1.1.1.3 ! christos  200: #ifdef NETMGR_TRACE
        !           201:        void *backtrace[TRACE_SIZE];
        !           202:        int backtrace_size;
        !           203:        LINK(isc_nmhandle_t) active_link;
        !           204: #endif
1.1       christos  205:        void *opaque;
                    206:        char extra[];
                    207: };
                    208:
                    209: /*
                    210:  * An interface - an address we can listen on.
                    211:  */
                    212: struct isc_nmiface {
                    213:        isc_sockaddr_t addr;
                    214: };
                    215:
                    216: typedef enum isc__netievent_type {
1.1.1.3 ! christos  217:        netievent_udpconnect,
1.1       christos  218:        netievent_udpsend,
1.1.1.3 ! christos  219:        netievent_udpread,
1.1       christos  220:        netievent_udpstop,
1.1.1.3 ! christos  221:        netievent_udpcancel,
        !           222:        netievent_udpclose,
1.1       christos  223:
                    224:        netievent_tcpconnect,
                    225:        netievent_tcpsend,
                    226:        netievent_tcpstartread,
                    227:        netievent_tcppauseread,
1.1.1.2   christos  228:        netievent_tcpaccept,
1.1       christos  229:        netievent_tcpstop,
1.1.1.3 ! christos  230:        netievent_tcpcancel,
1.1       christos  231:        netievent_tcpclose,
1.1.1.2   christos  232:
1.1.1.3 ! christos  233:        netievent_tcpdnsaccept,
        !           234:        netievent_tcpdnsconnect,
1.1.1.2   christos  235:        netievent_tcpdnssend,
1.1.1.3 ! christos  236:        netievent_tcpdnsread,
        !           237:        netievent_tcpdnscancel,
        !           238:        netievent_tcpdnsclose,
        !           239:        netievent_tcpdnsstop,
        !           240:
        !           241:        netievent_tlsclose,
        !           242:        netievent_tlssend,
        !           243:        netievent_tlsstartread,
        !           244:        netievent_tlsconnect,
        !           245:        netievent_tlsdobio,
        !           246:
        !           247:        netievent_tlsdnsaccept,
        !           248:        netievent_tlsdnsconnect,
        !           249:        netievent_tlsdnssend,
        !           250:        netievent_tlsdnsread,
        !           251:        netievent_tlsdnscancel,
        !           252:        netievent_tlsdnsclose,
        !           253:        netievent_tlsdnsstop,
1.1       christos  254:
1.1.1.3 ! christos  255:        netievent_close,
1.1       christos  256:        netievent_shutdown,
                    257:        netievent_stop,
1.1.1.3 ! christos  258:        netievent_pause,
        !           259:
        !           260:        netievent_connectcb,
        !           261:        netievent_readcb,
        !           262:        netievent_sendcb,
        !           263:
1.1       christos  264:        netievent_prio = 0xff, /* event type values higher than this
                    265:                                * will be treated as high-priority
                    266:                                * events, which can be processed
                    267:                                * while the netmgr is paused.
                    268:                                */
                    269:        netievent_udplisten,
                    270:        netievent_tcplisten,
1.1.1.3 ! christos  271:        netievent_tcpdnslisten,
        !           272:        netievent_resume,
        !           273:        netievent_detach,
1.1       christos  274: } isc__netievent_type;
                    275:
                    276: typedef union {
                    277:        isc_nm_recv_cb_t recv;
                    278:        isc_nm_cb_t send;
                    279:        isc_nm_cb_t connect;
1.1.1.2   christos  280:        isc_nm_accept_cb_t accept;
1.1       christos  281: } isc__nm_cb_t;
                    282:
                    283: /*
                    284:  * Wrapper around uv_req_t with 'our' fields in it.  req->data should
                    285:  * always point to its parent.  Note that we always allocate more than
                    286:  * sizeof(struct) because we make room for different req types;
                    287:  */
                    288: #define UVREQ_MAGIC    ISC_MAGIC('N', 'M', 'U', 'R')
                    289: #define VALID_UVREQ(t) ISC_MAGIC_VALID(t, UVREQ_MAGIC)
                    290:
1.1.1.3 ! christos  291: typedef struct isc__nm_uvreq isc__nm_uvreq_t;
        !           292: struct isc__nm_uvreq {
1.1       christos  293:        int magic;
                    294:        isc_nmsocket_t *sock;
                    295:        isc_nmhandle_t *handle;
1.1.1.3 ! christos  296:        char tcplen[2];       /* The TCP DNS message length */
1.1       christos  297:        uv_buf_t uvbuf;       /* translated isc_region_t, to be
                    298:                               * sent or received */
                    299:        isc_sockaddr_t local; /* local address */
                    300:        isc_sockaddr_t peer;  /* peer address */
                    301:        isc__nm_cb_t cb;      /* callback */
                    302:        void *cbarg;          /* callback argument */
                    303:        uv_pipe_t ipc;        /* used for sending socket
                    304:                               * uv_handles to other threads */
                    305:        union {
1.1.1.3 ! christos  306:                uv_handle_t handle;
1.1       christos  307:                uv_req_t req;
                    308:                uv_getaddrinfo_t getaddrinfo;
                    309:                uv_getnameinfo_t getnameinfo;
                    310:                uv_shutdown_t shutdown;
                    311:                uv_write_t write;
                    312:                uv_connect_t connect;
                    313:                uv_udp_send_t udp_send;
                    314:                uv_fs_t fs;
                    315:                uv_work_t work;
                    316:        } uv_req;
1.1.1.3 ! christos  317:        ISC_LINK(isc__nm_uvreq_t) link;
        !           318: };
        !           319:
        !           320: void *
        !           321: isc__nm_get_netievent(isc_nm_t *mgr, isc__netievent_type type);
        !           322: /*%<
        !           323:  * Allocate an ievent and set the type.
        !           324:  */
        !           325: void
        !           326: isc__nm_put_netievent(isc_nm_t *mgr, void *ievent);
        !           327:
        !           328: /*
        !           329:  * The macros here are used to simulate the "inheritance" in C, there's the base
        !           330:  * netievent structure that contains just its own type and socket, and there are
        !           331:  * extended netievent types that also have handles or requests or other data.
        !           332:  *
        !           333:  * The macros here ensure that:
        !           334:  *
        !           335:  *   1. every netievent type has matching definition, declaration and
        !           336:  *      implementation
        !           337:  *
        !           338:  *   2. we handle all the netievent types of same subclass the same, e.g. if the
        !           339:  *      extended netievent contains handle, we always attach to the handle in
        !           340:  *      the ctor and detach from the handle in dtor.
        !           341:  *
        !           342:  * There are three macros here for each netievent subclass:
        !           343:  *
        !           344:  *   1. NETIEVENT_*_TYPE(type) creates the typedef for each type; used below in
        !           345:  *   this header
        !           346:  *
        !           347:  *   2. NETIEVENT_*_DECL(type) generates the declaration of the get and put
        !           348:  *      functions (isc__nm_get_netievent_* and isc__nm_put_netievent_*); used
        !           349:  *      below in this header
        !           350:  *
        !           351:  *   3. NETIEVENT_*_DEF(type) generates the definition of the functions; used
        !           352:  *   either in netmgr.c or matching protocol file (e.g. udp.c, tcp.c, etc.)
        !           353:  */
        !           354:
        !           355: #define NETIEVENT__SOCKET         \
        !           356:        isc__netievent_type type; \
        !           357:        isc_nmsocket_t *sock;     \
        !           358:        const char *file;         \
        !           359:        unsigned int line;        \
        !           360:        const char *func
1.1       christos  361:
                    362: typedef struct isc__netievent__socket {
1.1.1.3 ! christos  363:        NETIEVENT__SOCKET;
1.1       christos  364: } isc__netievent__socket_t;
                    365:
1.1.1.3 ! christos  366: #define NETIEVENT_SOCKET_TYPE(type) \
        !           367:        typedef isc__netievent__socket_t isc__netievent_##type##_t;
        !           368:
        !           369: #define NETIEVENT_SOCKET_DECL(type)                              \
        !           370:        isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
        !           371:                isc_nm_t *nm, isc_nmsocket_t *sock);             \
        !           372:        void isc__nm_put_netievent_##type(isc_nm_t *nm,          \
        !           373:                                          isc__netievent_##type##_t *ievent);
        !           374:
        !           375: #define NETIEVENT_SOCKET_DEF(type)                                             \
        !           376:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(               \
        !           377:                isc_nm_t *nm, isc_nmsocket_t *sock) {                          \
        !           378:                isc__netievent_##type##_t *ievent =                            \
        !           379:                        isc__nm_get_netievent(nm, netievent_##type);           \
        !           380:                isc__nmsocket_attach(sock, &ievent->sock);                     \
        !           381:                                                                                \
        !           382:                return (ievent);                                               \
        !           383:        }                                                                      \
        !           384:                                                                                \
        !           385:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                        \
        !           386:                                          isc__netievent_##type##_t *ievent) { \
        !           387:                isc__nmsocket_detach(&ievent->sock);                           \
        !           388:                isc__nm_put_netievent(nm, ievent);                             \
        !           389:        }
1.1       christos  390:
                    391: typedef struct isc__netievent__socket_req {
1.1.1.3 ! christos  392:        NETIEVENT__SOCKET;
1.1       christos  393:        isc__nm_uvreq_t *req;
                    394: } isc__netievent__socket_req_t;
                    395:
1.1.1.3 ! christos  396: #define NETIEVENT_SOCKET_REQ_TYPE(type) \
        !           397:        typedef isc__netievent__socket_req_t isc__netievent_##type##_t;
1.1       christos  398:
1.1.1.3 ! christos  399: #define NETIEVENT_SOCKET_REQ_DECL(type)                                    \
        !           400:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(           \
        !           401:                isc_nm_t *nm, isc_nmsocket_t *sock, isc__nm_uvreq_t *req); \
        !           402:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                    \
        !           403:                                          isc__netievent_##type##_t *ievent);
        !           404:
        !           405: #define NETIEVENT_SOCKET_REQ_DEF(type)                                         \
        !           406:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(               \
        !           407:                isc_nm_t *nm, isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {    \
        !           408:                isc__netievent_##type##_t *ievent =                            \
        !           409:                        isc__nm_get_netievent(nm, netievent_##type);           \
        !           410:                isc__nmsocket_attach(sock, &ievent->sock);                     \
        !           411:                ievent->req = req;                                             \
        !           412:                                                                                \
        !           413:                return (ievent);                                               \
        !           414:        }                                                                      \
        !           415:                                                                                \
        !           416:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                        \
        !           417:                                          isc__netievent_##type##_t *ievent) { \
        !           418:                isc__nmsocket_detach(&ievent->sock);                           \
        !           419:                isc__nm_put_netievent(nm, ievent);                             \
        !           420:        }
        !           421:
        !           422: typedef struct isc__netievent__socket_req_result {
1.1       christos  423:        isc__netievent_type type;
                    424:        isc_nmsocket_t *sock;
1.1.1.3 ! christos  425:        isc__nm_uvreq_t *req;
        !           426:        isc_result_t result;
        !           427: } isc__netievent__socket_req_result_t;
        !           428:
        !           429: #define NETIEVENT_SOCKET_REQ_RESULT_TYPE(type) \
        !           430:        typedef isc__netievent__socket_req_result_t isc__netievent_##type##_t;
1.1       christos  431:
1.1.1.3 ! christos  432: #define NETIEVENT_SOCKET_REQ_RESULT_DECL(type)                            \
        !           433:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(          \
        !           434:                isc_nm_t *nm, isc_nmsocket_t *sock, isc__nm_uvreq_t *req, \
        !           435:                isc_result_t result);                                     \
        !           436:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                   \
        !           437:                                          isc__netievent_##type##_t *ievent);
        !           438:
        !           439: #define NETIEVENT_SOCKET_REQ_RESULT_DEF(type)                                  \
        !           440:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(               \
        !           441:                isc_nm_t *nm, isc_nmsocket_t *sock, isc__nm_uvreq_t *req,      \
        !           442:                isc_result_t result) {                                         \
        !           443:                isc__netievent_##type##_t *ievent =                            \
        !           444:                        isc__nm_get_netievent(nm, netievent_##type);           \
        !           445:                isc__nmsocket_attach(sock, &ievent->sock);                     \
        !           446:                ievent->req = req;                                             \
        !           447:                ievent->result = result;                                       \
        !           448:                                                                                \
        !           449:                return (ievent);                                               \
        !           450:        }                                                                      \
        !           451:                                                                                \
        !           452:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                        \
        !           453:                                          isc__netievent_##type##_t *ievent) { \
        !           454:                isc__nmsocket_detach(&ievent->sock);                           \
        !           455:                isc__nm_put_netievent(nm, ievent);                             \
        !           456:        }
1.1       christos  457:
                    458: typedef struct isc__netievent__socket_handle {
1.1.1.3 ! christos  459:        NETIEVENT__SOCKET;
1.1       christos  460:        isc_nmhandle_t *handle;
                    461: } isc__netievent__socket_handle_t;
                    462:
1.1.1.3 ! christos  463: #define NETIEVENT_SOCKET_HANDLE_TYPE(type) \
        !           464:        typedef isc__netievent__socket_handle_t isc__netievent_##type##_t;
        !           465:
        !           466: #define NETIEVENT_SOCKET_HANDLE_DECL(type)                                   \
        !           467:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(             \
        !           468:                isc_nm_t *nm, isc_nmsocket_t *sock, isc_nmhandle_t *handle); \
        !           469:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                      \
        !           470:                                          isc__netievent_##type##_t *ievent);
        !           471:
        !           472: #define NETIEVENT_SOCKET_HANDLE_DEF(type)                                      \
        !           473:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(               \
        !           474:                isc_nm_t *nm, isc_nmsocket_t *sock, isc_nmhandle_t *handle) {  \
        !           475:                isc__netievent_##type##_t *ievent =                            \
        !           476:                        isc__nm_get_netievent(nm, netievent_##type);           \
        !           477:                isc__nmsocket_attach(sock, &ievent->sock);                     \
        !           478:                isc_nmhandle_attach(handle, &ievent->handle);                  \
        !           479:                                                                                \
        !           480:                return (ievent);                                               \
        !           481:        }                                                                      \
        !           482:                                                                                \
        !           483:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                        \
        !           484:                                          isc__netievent_##type##_t *ievent) { \
        !           485:                isc__nmsocket_detach(&ievent->sock);                           \
        !           486:                isc_nmhandle_detach(&ievent->handle);                          \
        !           487:                isc__nm_put_netievent(nm, ievent);                             \
        !           488:        }
        !           489:
1.1.1.2   christos  490: typedef struct isc__netievent__socket_quota {
1.1.1.3 ! christos  491:        NETIEVENT__SOCKET;
1.1.1.2   christos  492:        isc_quota_t *quota;
                    493: } isc__netievent__socket_quota_t;
                    494:
1.1.1.3 ! christos  495: #define NETIEVENT_SOCKET_QUOTA_TYPE(type) \
        !           496:        typedef isc__netievent__socket_quota_t isc__netievent_##type##_t;
        !           497:
        !           498: #define NETIEVENT_SOCKET_QUOTA_DECL(type)                                \
        !           499:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(         \
        !           500:                isc_nm_t *nm, isc_nmsocket_t *sock, isc_quota_t *quota); \
        !           501:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                  \
        !           502:                                          isc__netievent_##type##_t *ievent);
        !           503:
        !           504: #define NETIEVENT_SOCKET_QUOTA_DEF(type)                                       \
        !           505:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(               \
        !           506:                isc_nm_t *nm, isc_nmsocket_t *sock, isc_quota_t *quota) {      \
        !           507:                isc__netievent_##type##_t *ievent =                            \
        !           508:                        isc__nm_get_netievent(nm, netievent_##type);           \
        !           509:                isc__nmsocket_attach(sock, &ievent->sock);                     \
        !           510:                ievent->quota = quota;                                         \
        !           511:                                                                                \
        !           512:                return (ievent);                                               \
        !           513:        }                                                                      \
        !           514:                                                                                \
        !           515:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                        \
        !           516:                                          isc__netievent_##type##_t *ievent) { \
        !           517:                isc__nmsocket_detach(&ievent->sock);                           \
        !           518:                isc__nm_put_netievent(nm, ievent);                             \
        !           519:        }
1.1.1.2   christos  520:
1.1       christos  521: typedef struct isc__netievent_udpsend {
1.1.1.3 ! christos  522:        NETIEVENT__SOCKET;
1.1       christos  523:        isc_sockaddr_t peer;
                    524:        isc__nm_uvreq_t *req;
                    525: } isc__netievent_udpsend_t;
                    526:
1.1.1.3 ! christos  527: typedef struct isc__netievent_tlsconnect {
        !           528:        isc__netievent_type type;
        !           529:        isc_nmsocket_t *sock;
        !           530:        SSL_CTX *ctx;
        !           531:        isc_sockaddr_t local; /* local address */
        !           532:        isc_sockaddr_t peer;  /* peer address */
        !           533: } isc__netievent_tlsconnect_t;
        !           534:
1.1       christos  535: typedef struct isc__netievent {
                    536:        isc__netievent_type type;
                    537: } isc__netievent_t;
                    538:
1.1.1.3 ! christos  539: #define NETIEVENT_TYPE(type) typedef isc__netievent_t isc__netievent_##type##_t;
        !           540:
        !           541: #define NETIEVENT_DECL(type)                                                   \
        !           542:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(isc_nm_t *nm); \
        !           543:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                        \
        !           544:                                          isc__netievent_##type##_t *ievent);
        !           545:
        !           546: #define NETIEVENT_DEF(type)                                                    \
        !           547:        isc__netievent_##type##_t *isc__nm_get_netievent_##type(               \
        !           548:                isc_nm_t *nm) {                                                \
        !           549:                isc__netievent_##type##_t *ievent =                            \
        !           550:                        isc__nm_get_netievent(nm, netievent_##type);           \
        !           551:                                                                                \
        !           552:                return (ievent);                                               \
        !           553:        }                                                                      \
        !           554:                                                                                \
        !           555:        void isc__nm_put_netievent_##type(isc_nm_t *nm,                        \
        !           556:                                          isc__netievent_##type##_t *ievent) { \
        !           557:                isc__nm_put_netievent(nm, ievent);                             \
        !           558:        }
1.1       christos  559:
                    560: typedef union {
                    561:        isc__netievent_t ni;
                    562:        isc__netievent__socket_t nis;
                    563:        isc__netievent__socket_req_t nisr;
                    564:        isc__netievent_udpsend_t nius;
1.1.1.2   christos  565:        isc__netievent__socket_quota_t nisq;
1.1.1.3 ! christos  566:        isc__netievent_tlsconnect_t nitc;
1.1       christos  567: } isc__netievent_storage_t;
                    568:
                    569: /*
                    570:  * Network manager
                    571:  */
                    572: #define NM_MAGIC    ISC_MAGIC('N', 'E', 'T', 'M')
                    573: #define VALID_NM(t) ISC_MAGIC_VALID(t, NM_MAGIC)
                    574:
                    575: struct isc_nm {
                    576:        int magic;
                    577:        isc_refcount_t references;
                    578:        isc_mem_t *mctx;
                    579:        uint32_t nworkers;
                    580:        isc_mutex_t lock;
                    581:        isc_condition_t wkstatecond;
                    582:        isc__networker_t *workers;
                    583:
                    584:        isc_stats_t *stats;
                    585:
                    586:        isc_mempool_t *reqpool;
                    587:        isc_mutex_t reqlock;
                    588:
                    589:        isc_mempool_t *evpool;
                    590:        isc_mutex_t evlock;
                    591:
1.1.1.3 ! christos  592:        uint_fast32_t workers_running;
        !           593:        uint_fast32_t workers_paused;
1.1       christos  594:        atomic_uint_fast32_t maxudp;
                    595:
                    596:        /*
                    597:         * Active connections are being closed and new connections are
                    598:         * no longer allowed.
                    599:         */
                    600:        atomic_bool closing;
                    601:
                    602:        /*
                    603:         * A worker is actively waiting for other workers, for example to
                    604:         * stop listening; that means no other thread can do the same thing
                    605:         * or pause, or we'll deadlock. We have to either re-enqueue our
                    606:         * event or wait for the other one to finish if we want to pause.
                    607:         */
                    608:        atomic_bool interlocked;
                    609:
                    610:        /*
                    611:         * Timeout values for TCP connections, corresponding to
                    612:         * tcp-intiial-timeout, tcp-idle-timeout, tcp-keepalive-timeout,
                    613:         * and tcp-advertised-timeout. Note that these are stored in
                    614:         * milliseconds so they can be used directly with the libuv timer,
                    615:         * but they are configured in tenths of seconds.
                    616:         */
1.1.1.3 ! christos  617:        atomic_uint_fast32_t init;
        !           618:        atomic_uint_fast32_t idle;
        !           619:        atomic_uint_fast32_t keepalive;
        !           620:        atomic_uint_fast32_t advertised;
        !           621:
        !           622: #ifdef NETMGR_TRACE
        !           623:        ISC_LIST(isc_nmsocket_t) active_sockets;
        !           624: #endif
1.1       christos  625: };
                    626:
                    627: typedef enum isc_nmsocket_type {
                    628:        isc_nm_udpsocket,
                    629:        isc_nm_udplistener, /* Aggregate of nm_udpsocks */
                    630:        isc_nm_tcpsocket,
                    631:        isc_nm_tcplistener,
                    632:        isc_nm_tcpdnslistener,
1.1.1.3 ! christos  633:        isc_nm_tcpdnssocket,
        !           634:        isc_nm_tlslistener,
        !           635:        isc_nm_tlssocket,
        !           636:        isc_nm_tlsdnslistener,
        !           637:        isc_nm_tlsdnssocket
1.1       christos  638: } isc_nmsocket_type;
                    639:
                    640: /*%
                    641:  * A universal structure for either a single socket or a group of
                    642:  * dup'd/SO_REUSE_PORT-using sockets listening on the same interface.
                    643:  */
                    644: #define NMSOCK_MAGIC   ISC_MAGIC('N', 'M', 'S', 'K')
                    645: #define VALID_NMSOCK(t) ISC_MAGIC_VALID(t, NMSOCK_MAGIC)
                    646:
                    647: /*%
                    648:  * Index into socket stat counter arrays.
                    649:  */
1.1.1.3 ! christos  650: enum {
        !           651:        STATID_OPEN = 0,
        !           652:        STATID_OPENFAIL = 1,
        !           653:        STATID_CLOSE = 2,
        !           654:        STATID_BINDFAIL = 3,
        !           655:        STATID_CONNECTFAIL = 4,
        !           656:        STATID_CONNECT = 5,
        !           657:        STATID_ACCEPTFAIL = 6,
        !           658:        STATID_ACCEPT = 7,
        !           659:        STATID_SENDFAIL = 8,
        !           660:        STATID_RECVFAIL = 9,
        !           661:        STATID_ACTIVE = 10
        !           662: };
1.1       christos  663:
                    664: struct isc_nmsocket {
                    665:        /*% Unlocked, RO */
                    666:        int magic;
                    667:        int tid;
                    668:        isc_nmsocket_type type;
                    669:        isc_nm_t *mgr;
                    670:        /*% Parent socket for multithreaded listeners */
                    671:        isc_nmsocket_t *parent;
                    672:        /*% Listener socket this connection was accepted on */
                    673:        isc_nmsocket_t *listener;
1.1.1.3 ! christos  674:        /*% Self socket */
        !           675:        isc_nmsocket_t *self;
        !           676:
        !           677:        /*% TLS stuff */
        !           678:        struct tls {
        !           679:                bool server;
        !           680:                BIO *app_bio;
        !           681:                SSL *ssl;
        !           682:                SSL_CTX *ctx;
        !           683:                BIO *ssl_bio;
        !           684:                enum {
        !           685:                        TLS_INIT,
        !           686:                        TLS_HANDSHAKE,
        !           687:                        TLS_IO,
        !           688:                        TLS_ERROR,
        !           689:                        TLS_CLOSING
        !           690:                } state;
        !           691:                isc_region_t senddata;
        !           692:                bool sending;
        !           693:                /* List of active send requests. */
        !           694:                ISC_LIST(isc__nm_uvreq_t) sends;
        !           695:        } tls;
1.1       christos  696:
                    697:        /*%
                    698:         * quota is the TCP client, attached when a TCP connection
                    699:         * is established. pquota is a non-attached pointer to the
                    700:         * TCP client quota, stored in listening sockets but only
                    701:         * attached in connected sockets.
                    702:         */
                    703:        isc_quota_t *quota;
                    704:        isc_quota_t *pquota;
1.1.1.2   christos  705:        isc_quota_cb_t quotacb;
1.1       christos  706:
                    707:        /*%
                    708:         * Socket statistics
                    709:         */
                    710:        const isc_statscounter_t *statsindex;
                    711:
                    712:        /*%
1.1.1.3 ! christos  713:         * TCP read/connect timeout timers.
1.1       christos  714:         */
                    715:        uv_timer_t timer;
                    716:        bool timer_initialized;
1.1.1.3 ! christos  717:        bool timer_running;
1.1       christos  718:        uint64_t read_timeout;
1.1.1.3 ! christos  719:        uint64_t connect_timeout;
1.1       christos  720:
                    721:        /*% outer socket is for 'wrapped' sockets - e.g. tcpdns in tcp */
                    722:        isc_nmsocket_t *outer;
                    723:
                    724:        /*% server socket for connections */
                    725:        isc_nmsocket_t *server;
                    726:
                    727:        /*% Child sockets for multi-socket setups */
                    728:        isc_nmsocket_t *children;
1.1.1.3 ! christos  729:        uint_fast32_t nchildren;
1.1       christos  730:        isc_nmiface_t *iface;
1.1.1.3 ! christos  731:        isc_nmhandle_t *statichandle;
        !           732:        isc_nmhandle_t *outerhandle;
1.1       christos  733:
                    734:        /*% Extra data allocated at the end of each isc_nmhandle_t */
                    735:        size_t extrahandlesize;
                    736:
                    737:        /*% TCP backlog */
                    738:        int backlog;
                    739:
                    740:        /*% libuv data */
                    741:        uv_os_sock_t fd;
                    742:        union uv_any_handle uv_handle;
                    743:
                    744:        /*% Peer address */
                    745:        isc_sockaddr_t peer;
                    746:
                    747:        /* Atomic */
                    748:        /*% Number of running (e.g. listening) child sockets */
1.1.1.3 ! christos  749:        uint_fast32_t rchildren;
1.1       christos  750:
                    751:        /*%
                    752:         * Socket is active if it's listening, working, etc. If it's
                    753:         * closing, then it doesn't make a sense, for example, to
                    754:         * push handles or reqs for reuse.
                    755:         */
                    756:        atomic_bool active;
                    757:        atomic_bool destroying;
                    758:
                    759:        /*%
                    760:         * Socket is closed if it's not active and all the possible
                    761:         * callbacks were fired, there are no active handles, etc.
                    762:         * If active==false but closed==false, that means the socket
                    763:         * is closing.
                    764:         */
1.1.1.3 ! christos  765:        atomic_bool closing;
1.1       christos  766:        atomic_bool closed;
                    767:        atomic_bool listening;
1.1.1.3 ! christos  768:        atomic_bool connecting;
        !           769:        atomic_bool connected;
        !           770:        bool accepting;
        !           771:        bool reading;
1.1       christos  772:        isc_refcount_t references;
                    773:
                    774:        /*%
1.1.1.3 ! christos  775:         * Established an outgoing connection, as client not server.
1.1       christos  776:         */
1.1.1.3 ! christos  777:        atomic_bool client;
1.1       christos  778:
                    779:        /*%
1.1.1.3 ! christos  780:         * TCPDNS socket has been set not to pipeline.
1.1       christos  781:         */
1.1.1.3 ! christos  782:        atomic_bool sequential;
1.1       christos  783:
                    784:        /*%
1.1.1.3 ! christos  785:         * The socket is processing read callback, this is guard to not read
        !           786:         * data before the readcb is back.
1.1       christos  787:         */
1.1.1.3 ! christos  788:        bool processing;
1.1       christos  789:
                    790:        /*%
                    791:         * A TCP socket has had isc_nm_pauseread() called.
                    792:         */
                    793:        atomic_bool readpaused;
                    794:
                    795:        /*%
                    796:         * A TCP or TCPDNS socket has been set to use the keepalive
                    797:         * timeout instead of the default idle timeout.
                    798:         */
                    799:        atomic_bool keepalive;
                    800:
                    801:        /*%
                    802:         * 'spare' handles for that can be reused to avoid allocations,
                    803:         * for UDP.
                    804:         */
                    805:        isc_astack_t *inactivehandles;
                    806:        isc_astack_t *inactivereqs;
                    807:
                    808:        /*%
                    809:         * Used to wait for TCP listening events to complete, and
                    810:         * for the number of running children to reach zero during
                    811:         * shutdown.
1.1.1.3 ! christos  812:         *
        !           813:         * We use two condition variables to prevent the race where the netmgr
        !           814:         * threads would be able to finish and destroy the socket before it's
        !           815:         * unlocked by the isc_nm_listen<proto>() function.  So, the flow is as
        !           816:         * follows:
        !           817:         *
        !           818:         *   1. parent thread creates all children sockets and passes then to
        !           819:         *      netthreads, looks at the signaling variable and WAIT(cond) until
        !           820:         *      the childrens are done initializing
        !           821:         *
        !           822:         *   2. the events get picked by netthreads, calls the libuv API (and
        !           823:         *      either succeeds or fails) and WAIT(scond) until all other
        !           824:         *      children sockets in netthreads are initialized and the listening
        !           825:         *      socket lock is unlocked
        !           826:         *
        !           827:         *   3. the control is given back to the parent thread which now either
        !           828:         *      returns success or shutdowns the listener if an error has
        !           829:         *      occured in the children netthread
        !           830:         *
        !           831:         * NOTE: The other approach would be doing an extra attach to the parent
        !           832:         * listening socket, and then detach it in the parent thread, but that
        !           833:         * breaks the promise that once the libuv socket is initialized on the
        !           834:         * nmsocket, the nmsocket needs to be handled only by matching
        !           835:         * netthread, so in fact that would add a complexity in a way that
        !           836:         * isc__nmsocket_detach would have to be converted to use an
        !           837:         * asynchrounous netievent.
1.1       christos  838:         */
                    839:        isc_mutex_t lock;
                    840:        isc_condition_t cond;
1.1.1.3 ! christos  841:        isc_condition_t scond;
1.1       christos  842:
                    843:        /*%
1.1.1.3 ! christos  844:         * Used to pass a result back from listen or connect events.
1.1       christos  845:         */
                    846:        isc_result_t result;
                    847:
                    848:        /*%
                    849:         * List of active handles.
                    850:         * ah - current position in 'ah_frees'; this represents the
                    851:         *      current number of active handles;
                    852:         * ah_size - size of the 'ah_frees' and 'ah_handles' arrays
                    853:         * ah_handles - array pointers to active handles
                    854:         *
                    855:         * Adding a handle
                    856:         *  - if ah == ah_size, reallocate
                    857:         *  - x = ah_frees[ah]
                    858:         *  - ah_frees[ah++] = 0;
                    859:         *  - ah_handles[x] = handle
                    860:         *  - x must be stored with the handle!
                    861:         * Removing a handle:
                    862:         *  - ah_frees[--ah] = x
                    863:         *  - ah_handles[x] = NULL;
                    864:         *
                    865:         * XXX: for now this is locked with socket->lock, but we
                    866:         * might want to change it to something lockless in the
                    867:         * future.
                    868:         */
                    869:        atomic_int_fast32_t ah;
                    870:        size_t ah_size;
                    871:        size_t *ah_frees;
                    872:        isc_nmhandle_t **ah_handles;
                    873:
                    874:        /*% Buffer for TCPDNS processing */
                    875:        size_t buf_size;
                    876:        size_t buf_len;
                    877:        unsigned char *buf;
                    878:
                    879:        /*%
                    880:         * This function will be called with handle->sock
                    881:         * as the argument whenever a handle's references drop
                    882:         * to zero, after its reset callback has been called.
                    883:         */
                    884:        isc_nm_opaquecb_t closehandle_cb;
                    885:
1.1.1.3 ! christos  886:        isc_nmhandle_t *recv_handle;
        !           887:        isc_nm_recv_cb_t recv_cb;
        !           888:        void *recv_cbarg;
        !           889:        bool recv_read;
        !           890:
        !           891:        isc_nm_cb_t connect_cb;
        !           892:        void *connect_cbarg;
1.1       christos  893:
1.1.1.3 ! christos  894:        isc_nm_accept_cb_t accept_cb;
1.1       christos  895:        void *accept_cbarg;
1.1.1.3 ! christos  896:
        !           897:        atomic_int_fast32_t active_child_connections;
        !           898: #ifdef NETMGR_TRACE
        !           899:        void *backtrace[TRACE_SIZE];
        !           900:        int backtrace_size;
        !           901:        LINK(isc_nmsocket_t) active_link;
        !           902:        ISC_LIST(isc_nmhandle_t) active_handles;
        !           903: #endif
1.1       christos  904: };
                    905:
                    906: bool
                    907: isc__nm_in_netthread(void);
                    908: /*%
                    909:  * Returns 'true' if we're in the network thread.
                    910:  */
                    911:
1.1.1.3 ! christos  912: void
        !           913: isc__nm_maybe_enqueue_ievent(isc__networker_t *worker, isc__netievent_t *event);
1.1       christos  914: /*%<
1.1.1.3 ! christos  915:  * If the caller is already in the matching nmthread, process the netievent
        !           916:  * directly, if not enqueue using isc__nm_enqueue_ievent().
1.1       christos  917:  */
                    918:
                    919: void
                    920: isc__nm_enqueue_ievent(isc__networker_t *worker, isc__netievent_t *event);
                    921: /*%<
                    922:  * Enqueue an ievent onto a specific worker queue. (This the only safe
                    923:  * way to use an isc__networker_t from another thread.)
                    924:  */
                    925:
                    926: void
                    927: isc__nm_free_uvbuf(isc_nmsocket_t *sock, const uv_buf_t *buf);
                    928: /*%<
                    929:  * Free a buffer allocated for a receive operation.
                    930:  *
                    931:  * Note that as currently implemented, this doesn't actually
                    932:  * free anything, marks the isc__networker's UDP receive buffer
                    933:  * as "not in use".
                    934:  */
                    935:
                    936: isc_nmhandle_t *
1.1.1.3 ! christos  937: isc___nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
        !           938:                   isc_sockaddr_t *local FLARG);
1.1       christos  939: /*%<
                    940:  * Get a handle for the socket 'sock', allocating a new one
                    941:  * if there isn't one available in 'sock->inactivehandles'.
                    942:  *
                    943:  * If 'peer' is not NULL, set the handle's peer address to 'peer',
                    944:  * otherwise set it to 'sock->peer'.
                    945:  *
                    946:  * If 'local' is not NULL, set the handle's local address to 'local',
                    947:  * otherwise set it to 'sock->iface->addr'.
1.1.1.3 ! christos  948:  *
        !           949:  * 'sock' will be attached to 'handle->sock'. The caller may need
        !           950:  * to detach the socket afterward.
1.1       christos  951:  */
                    952:
                    953: isc__nm_uvreq_t *
1.1.1.3 ! christos  954: isc___nm_uvreq_get(isc_nm_t *mgr, isc_nmsocket_t *sock FLARG);
1.1       christos  955: /*%<
                    956:  * Get a UV request structure for the socket 'sock', allocating a
                    957:  * new one if there isn't one available in 'sock->inactivereqs'.
                    958:  */
                    959:
                    960: void
1.1.1.3 ! christos  961: isc___nm_uvreq_put(isc__nm_uvreq_t **req, isc_nmsocket_t *sock FLARG);
1.1       christos  962: /*%<
                    963:  * Completes the use of a UV request structure, setting '*req' to NULL.
                    964:  *
                    965:  * The UV request is pushed onto the 'sock->inactivereqs' stack or,
                    966:  * if that doesn't work, freed.
                    967:  */
                    968:
                    969: void
1.1.1.3 ! christos  970: isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
        !           971:                    isc_nmiface_t *iface FLARG);
1.1       christos  972: /*%<
                    973:  * Initialize socket 'sock', attach it to 'mgr', and set it to type 'type'
                    974:  * and its interface to 'iface'.
                    975:  */
                    976:
                    977: void
1.1.1.3 ! christos  978: isc___nmsocket_attach(isc_nmsocket_t *sock, isc_nmsocket_t **target FLARG);
        !           979: /*%<
        !           980:  * Attach to a socket, increasing refcount
        !           981:  */
        !           982:
        !           983: void
        !           984: isc___nmsocket_detach(isc_nmsocket_t **socketp FLARG);
        !           985: /*%<
        !           986:  * Detach from socket, decreasing refcount and possibly destroying the
        !           987:  * socket if it's no longer referenced.
        !           988:  */
        !           989:
        !           990: void
        !           991: isc___nmsocket_prep_destroy(isc_nmsocket_t *sock FLARG);
1.1       christos  992: /*%<
                    993:  * Market 'sock' as inactive, close it if necessary, and destroy it
                    994:  * if there are no remaining references or active handles.
                    995:  */
                    996:
                    997: bool
                    998: isc__nmsocket_active(isc_nmsocket_t *sock);
                    999: /*%<
                   1000:  * Determine whether 'sock' is active by checking 'sock->active'
                   1001:  * or, for child sockets, 'sock->parent->active'.
                   1002:  */
                   1003:
1.1.1.3 ! christos 1004: bool
        !          1005: isc__nmsocket_deactivate(isc_nmsocket_t *sock);
        !          1006: /*%<
        !          1007:  * @brief Deactivate active socket
        !          1008:  *
        !          1009:  * Atomically deactive the socket by setting @p sock->active or, for child
        !          1010:  * sockets, @p sock->parent->active to @c false
        !          1011:  *
        !          1012:  * @param[in] sock - valid nmsocket
        !          1013:  * @return @c false if the socket was already inactive, @c true otherwise
        !          1014:  */
        !          1015:
1.1       christos 1016: void
1.1.1.3 ! christos 1017: isc__nmsocket_clearcb(isc_nmsocket_t *sock);
1.1       christos 1018: /*%<
1.1.1.3 ! christos 1019:  * Clear the recv and accept callbacks in 'sock'.
        !          1020:  */
        !          1021:
        !          1022: void
        !          1023: isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
        !          1024:                  isc_result_t eresult);
        !          1025: void
        !          1026: isc__nm_async_connectcb(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1027: /*%<
        !          1028:  * Issue a connect callback on the socket, used to call the callback
        !          1029:
        !          1030:  */
        !          1031:
        !          1032: isc_result_t
        !          1033: isc__nm_acceptcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
        !          1034:                 isc_result_t eresult);
        !          1035: /*%<
        !          1036:  * Issue a synchronous accept callback on the socket.
        !          1037:  */
        !          1038:
        !          1039: void
        !          1040: isc__nm_readcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
        !          1041:               isc_result_t eresult);
        !          1042: void
        !          1043: isc__nm_async_readcb(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1044:
        !          1045: /*%<
        !          1046:  * Issue a read callback on the socket, used to call the callback
        !          1047:  * on failed conditions when the event can't be scheduled on the uv loop.
        !          1048:  *
        !          1049:  */
        !          1050:
        !          1051: void
        !          1052: isc__nm_sendcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
        !          1053:               isc_result_t eresult);
        !          1054: void
        !          1055: isc__nm_async_sendcb(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1056: /*%<
        !          1057:  * Issue a write callback on the socket, used to call the callback
        !          1058:  * on failed conditions when the event can't be scheduled on the uv loop.
1.1       christos 1059:  */
                   1060:
                   1061: void
                   1062: isc__nm_async_shutdown(isc__networker_t *worker, isc__netievent_t *ev0);
                   1063: /*%<
                   1064:  * Walk through all uv handles, get the underlying sockets and issue
                   1065:  * close on them.
                   1066:  */
                   1067:
1.1.1.3 ! christos 1068: void
1.1       christos 1069: isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
                   1070:                 void *cbarg);
                   1071: /*%<
                   1072:  * Back-end implementation of isc_nm_send() for UDP handles.
                   1073:  */
                   1074:
                   1075: void
1.1.1.3 ! christos 1076: isc__nm_udp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
        !          1077: /*
        !          1078:  * Back-end implementation of isc_nm_read() for UDP handles.
        !          1079:  */
        !          1080:
        !          1081: void
        !          1082: isc__nm_udp_close(isc_nmsocket_t *sock);
        !          1083: /*%<
        !          1084:  * Close a UDP socket.
        !          1085:  */
        !          1086:
        !          1087: void
        !          1088: isc__nm_udp_cancelread(isc_nmhandle_t *handle);
        !          1089: /*%<
        !          1090:  * Stop reading on a connected UDP handle.
        !          1091:  */
        !          1092:
        !          1093: void
        !          1094: isc__nm_udp_shutdown(isc_nmsocket_t *sock);
        !          1095: /*%<
        !          1096:  * Called during the shutdown process to close and clean up connected
        !          1097:  * sockets.
        !          1098:  */
        !          1099:
        !          1100: void
1.1       christos 1101: isc__nm_udp_stoplistening(isc_nmsocket_t *sock);
1.1.1.3 ! christos 1102: /*%<
        !          1103:  * Stop listening on 'sock'.
        !          1104:  */
1.1       christos 1105:
                   1106: void
1.1.1.3 ! christos 1107: isc__nm_udp_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
        !          1108: /*%<
        !          1109:  * Set the recv timeout for the UDP socket associated with 'handle'.
        !          1110:  */
1.1       christos 1111:
                   1112: void
1.1.1.3 ! christos 1113: isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1114: void
        !          1115: isc__nm_async_udpconnect(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1116: void
1.1       christos 1117: isc__nm_async_udpstop(isc__networker_t *worker, isc__netievent_t *ev0);
                   1118: void
                   1119: isc__nm_async_udpsend(isc__networker_t *worker, isc__netievent_t *ev0);
1.1.1.3 ! christos 1120: void
        !          1121: isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1122: void
        !          1123: isc__nm_async_udpcancel(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1124: void
        !          1125: isc__nm_async_udpclose(isc__networker_t *worker, isc__netievent_t *ev0);
1.1       christos 1126: /*%<
                   1127:  * Callback handlers for asynchronous UDP events (listen, stoplisten, send).
                   1128:  */
                   1129:
1.1.1.3 ! christos 1130: void
1.1       christos 1131: isc__nm_tcp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
                   1132:                 void *cbarg);
                   1133: /*%<
                   1134:  * Back-end implementation of isc_nm_send() for TCP handles.
                   1135:  */
                   1136:
1.1.1.3 ! christos 1137: void
1.1       christos 1138: isc__nm_tcp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
1.1.1.3 ! christos 1139: /*
        !          1140:  * Back-end implementation of isc_nm_read() for TCP handles.
        !          1141:  */
1.1       christos 1142:
                   1143: void
                   1144: isc__nm_tcp_close(isc_nmsocket_t *sock);
                   1145: /*%<
                   1146:  * Close a TCP socket.
                   1147:  */
1.1.1.3 ! christos 1148: void
        !          1149: isc__nm_tcp_pauseread(isc_nmhandle_t *handle);
1.1       christos 1150: /*%<
1.1.1.3 ! christos 1151:  * Pause reading on this handle, while still remembering the callback.
1.1       christos 1152:  */
                   1153:
1.1.1.3 ! christos 1154: void
        !          1155: isc__nm_tcp_resumeread(isc_nmhandle_t *handle);
1.1       christos 1156: /*%<
                   1157:  * Resume reading from socket.
                   1158:  *
                   1159:  */
                   1160:
                   1161: void
                   1162: isc__nm_tcp_shutdown(isc_nmsocket_t *sock);
                   1163: /*%<
1.1.1.3 ! christos 1164:  * Called during the shutdown process to close and clean up connected
        !          1165:  * sockets.
        !          1166:  */
        !          1167:
        !          1168: void
        !          1169: isc__nm_tcp_cancelread(isc_nmhandle_t *handle);
        !          1170: /*%<
        !          1171:  * Stop reading on a connected TCP handle.
1.1       christos 1172:  */
                   1173:
                   1174: void
                   1175: isc__nm_tcp_stoplistening(isc_nmsocket_t *sock);
1.1.1.3 ! christos 1176: /*%<
        !          1177:  * Stop listening on 'sock'.
        !          1178:  */
        !          1179:
        !          1180: int_fast32_t
        !          1181: isc__nm_tcp_listener_nactive(isc_nmsocket_t *sock);
        !          1182: /*%<
        !          1183:  * Returns the number of active connections for the TCP listener socket.
        !          1184:  */
        !          1185:
        !          1186: void
        !          1187: isc__nm_tcp_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
        !          1188: /*%<
        !          1189:  * Set the read timeout for the TCP socket associated with 'handle'.
        !          1190:  */
1.1       christos 1191:
                   1192: void
                   1193: isc__nm_async_tcpconnect(isc__networker_t *worker, isc__netievent_t *ev0);
                   1194: void
                   1195: isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0);
                   1196: void
1.1.1.2   christos 1197: isc__nm_async_tcpaccept(isc__networker_t *worker, isc__netievent_t *ev0);
1.1       christos 1198: void
1.1.1.2   christos 1199: isc__nm_async_tcpstop(isc__networker_t *worker, isc__netievent_t *ev0);
1.1       christos 1200: void
                   1201: isc__nm_async_tcpsend(isc__networker_t *worker, isc__netievent_t *ev0);
                   1202: void
                   1203: isc__nm_async_startread(isc__networker_t *worker, isc__netievent_t *ev0);
                   1204: void
                   1205: isc__nm_async_pauseread(isc__networker_t *worker, isc__netievent_t *ev0);
                   1206: void
1.1.1.3 ! christos 1207: isc__nm_async_tcpstartread(isc__networker_t *worker, isc__netievent_t *ev0);
1.1       christos 1208: void
1.1.1.3 ! christos 1209: isc__nm_async_tcppauseread(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1210: void
        !          1211: isc__nm_async_tcpcancel(isc__networker_t *worker, isc__netievent_t *ev0);
1.1       christos 1212: void
                   1213: isc__nm_async_tcpclose(isc__networker_t *worker, isc__netievent_t *ev0);
                   1214: /*%<
                   1215:  * Callback handlers for asynchronous TCP events (connect, listen,
                   1216:  * stoplisten, send, read, pause, close).
                   1217:  */
                   1218:
1.1.1.3 ! christos 1219: void
        !          1220: isc__nm_async_tlsclose(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1221:
        !          1222: void
        !          1223: isc__nm_async_tlssend(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1224:
        !          1225: void
        !          1226: isc__nm_async_tlsconnect(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1227:
        !          1228: void
        !          1229: isc__nm_async_tlsstartread(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1230:
        !          1231: void
        !          1232: isc__nm_async_tlsdobio(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1233:
        !          1234: /*%<
        !          1235:  * Callback handlers for asynchronouse TLS events.
        !          1236:  */
        !          1237:
        !          1238: void
        !          1239: isc__nm_async_tcpdnsaccept(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1240: void
        !          1241: isc__nm_async_tcpdnsconnect(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1242: void
        !          1243: isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1244: void
1.1       christos 1245: isc__nm_tcpdns_send(isc_nmhandle_t *handle, isc_region_t *region,
                   1246:                    isc_nm_cb_t cb, void *cbarg);
                   1247: /*%<
                   1248:  * Back-end implementation of isc_nm_send() for TCPDNS handles.
                   1249:  */
                   1250:
                   1251: void
1.1.1.3 ! christos 1252: isc__nm_tcpdns_shutdown(isc_nmsocket_t *sock);
        !          1253:
        !          1254: void
1.1       christos 1255: isc__nm_tcpdns_close(isc_nmsocket_t *sock);
                   1256: /*%<
                   1257:  * Close a TCPDNS socket.
                   1258:  */
                   1259:
                   1260: void
                   1261: isc__nm_tcpdns_stoplistening(isc_nmsocket_t *sock);
1.1.1.3 ! christos 1262: /*%<
        !          1263:  * Stop listening on 'sock'.
        !          1264:  */
1.1       christos 1265:
                   1266: void
1.1.1.3 ! christos 1267: isc__nm_tcpdns_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
        !          1268: /*%<
        !          1269:  * Set the read timeout and reset the timer for the TCPDNS socket
        !          1270:  * associated with 'handle', and the TCP socket it wraps around.
        !          1271:  */
1.1       christos 1272:
1.1.1.2   christos 1273: void
1.1.1.3 ! christos 1274: isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1275: void
        !          1276: isc__nm_async_tcpdnsaccept(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1277: void
        !          1278: isc__nm_async_tcpdnscancel(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1279: void
        !          1280: isc__nm_async_tcpdnsclose(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1281: void
1.1.1.2   christos 1282: isc__nm_async_tcpdnssend(isc__networker_t *worker, isc__netievent_t *ev0);
1.1.1.3 ! christos 1283: void
        !          1284: isc__nm_async_tcpdnsstop(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1285:
        !          1286: void
        !          1287: isc__nm_async_tcpdnsread(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1288:
        !          1289: void
        !          1290: isc__nm_tcpdns_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
        !          1291:
        !          1292: void
        !          1293: isc__nm_tcpdns_cancelread(isc_nmhandle_t *handle);
        !          1294: /*%<
        !          1295:  * Stop reading on a connected TCPDNS handle.
        !          1296:  */
        !          1297:
        !          1298: void
        !          1299: isc__nm_tlsdns_send(isc_nmhandle_t *handle, isc_region_t *region,
        !          1300:                    isc_nm_cb_t cb, void *cbarg);
        !          1301: /*%<
        !          1302:  * Back-end implementation of isc_nm_send() for TLSDNS handles.
        !          1303:  */
        !          1304:
        !          1305: void
        !          1306: isc__nm_tlsdns_shutdown(isc_nmsocket_t *sock);
        !          1307:
        !          1308: void
        !          1309: isc__nm_tlsdns_close(isc_nmsocket_t *sock);
        !          1310: /*%<
        !          1311:  * Close a TLSDNS socket.
        !          1312:  */
        !          1313:
        !          1314: void
        !          1315: isc__nm_tlsdns_stoplistening(isc_nmsocket_t *sock);
        !          1316: /*%<
        !          1317:  * Stop listening on 'sock'.
        !          1318:  */
        !          1319:
        !          1320: void
        !          1321: isc__nm_tlsdns_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
        !          1322: /*%<
        !          1323:  * Set the read timeout and reset the timer for the TLSDNS socket
        !          1324:  * associated with 'handle', and the TCP socket it wraps around.
        !          1325:  */
        !          1326:
        !          1327: void
        !          1328: isc__nm_async_tlsdnscancel(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1329: void
        !          1330: isc__nm_async_tlsdnsclose(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1331: void
        !          1332: isc__nm_async_tlsdnssend(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1333: void
        !          1334: isc__nm_async_tlsdnsstop(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1335:
        !          1336: void
        !          1337: isc__nm_async_tlsdnsread(isc__networker_t *worker, isc__netievent_t *ev0);
        !          1338:
        !          1339: void
        !          1340: isc__nm_tlsdns_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
        !          1341:
        !          1342: void
        !          1343: isc__nm_tlsdns_cancelread(isc_nmhandle_t *handle);
        !          1344: /*%<
        !          1345:  * Stop reading on a connected TLSDNS handle.
        !          1346:  */
        !          1347:
        !          1348: void
        !          1349: isc__nm_tls_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
        !          1350:                 void *cbarg);
        !          1351:
        !          1352: void
        !          1353: isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
        !          1354:
        !          1355: void
        !          1356: isc__nm_tls_close(isc_nmsocket_t *sock);
        !          1357: /*%<
        !          1358:  * Close a TLS socket.
        !          1359:  */
        !          1360:
        !          1361: void
        !          1362: isc__nm_tls_pauseread(isc_nmhandle_t *handle);
        !          1363: /*%<
        !          1364:  * Pause reading on this handle, while still remembering the callback.
        !          1365:  */
        !          1366:
        !          1367: void
        !          1368: isc__nm_tls_resumeread(isc_nmhandle_t *handle);
        !          1369: /*%<
        !          1370:  * Resume reading from the handle.
        !          1371:  *
        !          1372:  */
        !          1373:
        !          1374: void
        !          1375: isc__nm_tls_stoplistening(isc_nmsocket_t *sock);
1.1.1.2   christos 1376:
1.1       christos 1377: #define isc__nm_uverr2result(x) \
1.1.1.3 ! christos 1378:        isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
1.1       christos 1379: isc_result_t
                   1380: isc___nm_uverr2result(int uverr, bool dolog, const char *file,
1.1.1.3 ! christos 1381:                      unsigned int line, const char *func);
1.1       christos 1382: /*%<
                   1383:  * Convert a libuv error value into an isc_result_t.  The
                   1384:  * list of supported error values is not complete; new users
                   1385:  * of this function should add any expected errors that are
                   1386:  * not already there.
                   1387:  */
                   1388:
                   1389: bool
                   1390: isc__nm_acquire_interlocked(isc_nm_t *mgr);
                   1391: /*%<
                   1392:  * Try to acquire interlocked state; return true if successful.
                   1393:  */
                   1394:
                   1395: void
                   1396: isc__nm_drop_interlocked(isc_nm_t *mgr);
                   1397: /*%<
                   1398:  * Drop interlocked state; signal waiters.
                   1399:  */
                   1400:
                   1401: void
                   1402: isc__nm_acquire_interlocked_force(isc_nm_t *mgr);
                   1403: /*%<
                   1404:  * Actively wait for interlocked state.
                   1405:  */
                   1406:
                   1407: void
                   1408: isc__nm_incstats(isc_nm_t *mgr, isc_statscounter_t counterid);
                   1409: /*%<
                   1410:  * Increment socket-related statistics counters.
                   1411:  */
                   1412:
                   1413: void
                   1414: isc__nm_decstats(isc_nm_t *mgr, isc_statscounter_t counterid);
                   1415: /*%<
                   1416:  * Decrement socket-related statistics counters.
                   1417:  */
1.1.1.3 ! christos 1418:
        !          1419: isc_result_t
        !          1420: isc__nm_socket(int domain, int type, int protocol, uv_os_sock_t *sockp);
        !          1421: /*%<
        !          1422:  * Platform independent socket() version
        !          1423:  */
        !          1424:
        !          1425: void
        !          1426: isc__nm_closesocket(uv_os_sock_t sock);
        !          1427: /*%<
        !          1428:  * Platform independent closesocket() version
        !          1429:  */
        !          1430:
        !          1431: isc_result_t
        !          1432: isc__nm_socket_freebind(uv_os_sock_t fd, sa_family_t sa_family);
        !          1433: /*%<
        !          1434:  * Set the IP_FREEBIND (or equivalent) socket option on the uv_handle
        !          1435:  */
        !          1436:
        !          1437: isc_result_t
        !          1438: isc__nm_socket_reuse(uv_os_sock_t fd);
        !          1439: /*%<
        !          1440:  * Set the SO_REUSEADDR or SO_REUSEPORT (or equivalent) socket option on the fd
        !          1441:  */
        !          1442:
        !          1443: isc_result_t
        !          1444: isc__nm_socket_reuse_lb(uv_os_sock_t fd);
        !          1445: /*%<
        !          1446:  * Set the SO_REUSEPORT_LB (or equivalent) socket option on the fd
        !          1447:  */
        !          1448:
        !          1449: isc_result_t
        !          1450: isc__nm_socket_incoming_cpu(uv_os_sock_t fd);
        !          1451: /*%<
        !          1452:  * Set the SO_INCOMING_CPU socket option on the fd if available
        !          1453:  */
        !          1454:
        !          1455: isc_result_t
        !          1456: isc__nm_socket_dontfrag(uv_os_sock_t fd, sa_family_t sa_family);
        !          1457: /*%<
        !          1458:  * Set the SO_IP_DONTFRAG (or equivalent) socket option of the fd if available
        !          1459:  */
        !          1460:
        !          1461: isc_result_t
        !          1462: isc__nm_socket_connectiontimeout(uv_os_sock_t fd, int timeout_ms);
        !          1463: /*%<
        !          1464:  * Set the connection timeout in miliseconds, on non-Linux platforms,
        !          1465:  * the minimum value must be at least 1000 (1 second).
        !          1466:  */
        !          1467:
        !          1468: void
        !          1469: isc__nm_tls_initialize(void);
        !          1470: /*%<
        !          1471:  * Initialize OpenSSL library, idempotent.
        !          1472:  */
        !          1473:
        !          1474: /*
        !          1475:  * typedef all the netievent types
        !          1476:  */
        !          1477:
        !          1478: NETIEVENT_SOCKET_TYPE(close);
        !          1479: NETIEVENT_SOCKET_TYPE(tcpclose);
        !          1480: NETIEVENT_SOCKET_TYPE(tcplisten);
        !          1481: NETIEVENT_SOCKET_TYPE(tcppauseread);
        !          1482: NETIEVENT_SOCKET_TYPE(tcpstop);
        !          1483: NETIEVENT_SOCKET_TYPE(tlsclose);
        !          1484: /* NETIEVENT_SOCKET_TYPE(tlsconnect); */ /* unique type, defined independently
        !          1485:                                          */
        !          1486: NETIEVENT_SOCKET_TYPE(tlsdobio);
        !          1487: NETIEVENT_SOCKET_TYPE(tlsstartread);
        !          1488: NETIEVENT_SOCKET_TYPE(udpclose);
        !          1489: NETIEVENT_SOCKET_TYPE(udplisten);
        !          1490: NETIEVENT_SOCKET_TYPE(udpread);
        !          1491: /* NETIEVENT_SOCKET_TYPE(udpsend); */ /* unique type, defined independently */
        !          1492: NETIEVENT_SOCKET_TYPE(udpstop);
        !          1493:
        !          1494: NETIEVENT_SOCKET_TYPE(tcpdnsclose);
        !          1495: NETIEVENT_SOCKET_TYPE(tcpdnsread);
        !          1496: NETIEVENT_SOCKET_TYPE(tcpdnsstop);
        !          1497: NETIEVENT_SOCKET_TYPE(tcpdnslisten);
        !          1498: NETIEVENT_SOCKET_REQ_TYPE(tcpdnsconnect);
        !          1499: NETIEVENT_SOCKET_REQ_TYPE(tcpdnssend);
        !          1500: NETIEVENT_SOCKET_HANDLE_TYPE(tcpdnscancel);
        !          1501: NETIEVENT_SOCKET_QUOTA_TYPE(tcpdnsaccept);
        !          1502:
        !          1503: NETIEVENT_SOCKET_TYPE(tlsdnsclose);
        !          1504: NETIEVENT_SOCKET_TYPE(tlsdnsread);
        !          1505: NETIEVENT_SOCKET_TYPE(tlsdnsstop);
        !          1506: NETIEVENT_SOCKET_REQ_TYPE(tlsdnssend);
        !          1507: NETIEVENT_SOCKET_HANDLE_TYPE(tlsdnscancel);
        !          1508:
        !          1509: NETIEVENT_SOCKET_REQ_TYPE(tcpconnect);
        !          1510: NETIEVENT_SOCKET_REQ_TYPE(tcpsend);
        !          1511: NETIEVENT_SOCKET_TYPE(tcpstartread);
        !          1512: NETIEVENT_SOCKET_REQ_TYPE(tlssend);
        !          1513: NETIEVENT_SOCKET_REQ_TYPE(udpconnect);
        !          1514:
        !          1515: NETIEVENT_SOCKET_REQ_RESULT_TYPE(connectcb);
        !          1516: NETIEVENT_SOCKET_REQ_RESULT_TYPE(readcb);
        !          1517: NETIEVENT_SOCKET_REQ_RESULT_TYPE(sendcb);
        !          1518:
        !          1519: NETIEVENT_SOCKET_HANDLE_TYPE(detach);
        !          1520: NETIEVENT_SOCKET_HANDLE_TYPE(tcpcancel);
        !          1521: NETIEVENT_SOCKET_HANDLE_TYPE(udpcancel);
        !          1522:
        !          1523: NETIEVENT_SOCKET_QUOTA_TYPE(tcpaccept);
        !          1524:
        !          1525: NETIEVENT_TYPE(pause);
        !          1526: NETIEVENT_TYPE(resume);
        !          1527: NETIEVENT_TYPE(shutdown);
        !          1528: NETIEVENT_TYPE(stop);
        !          1529:
        !          1530: /* Now declared the helper functions */
        !          1531:
        !          1532: NETIEVENT_SOCKET_DECL(close);
        !          1533: NETIEVENT_SOCKET_DECL(tcpclose);
        !          1534: NETIEVENT_SOCKET_DECL(tcplisten);
        !          1535: NETIEVENT_SOCKET_DECL(tcppauseread);
        !          1536: NETIEVENT_SOCKET_DECL(tcpstartread);
        !          1537: NETIEVENT_SOCKET_DECL(tcpstop);
        !          1538: NETIEVENT_SOCKET_DECL(tlsclose);
        !          1539: NETIEVENT_SOCKET_DECL(tlsconnect);
        !          1540: NETIEVENT_SOCKET_DECL(tlsdobio);
        !          1541: NETIEVENT_SOCKET_DECL(tlsstartread);
        !          1542: NETIEVENT_SOCKET_DECL(udpclose);
        !          1543: NETIEVENT_SOCKET_DECL(udplisten);
        !          1544: NETIEVENT_SOCKET_DECL(udpread);
        !          1545: NETIEVENT_SOCKET_DECL(udpsend);
        !          1546: NETIEVENT_SOCKET_DECL(udpstop);
        !          1547:
        !          1548: NETIEVENT_SOCKET_DECL(tcpdnsclose);
        !          1549: NETIEVENT_SOCKET_DECL(tcpdnsread);
        !          1550: NETIEVENT_SOCKET_DECL(tcpdnsstop);
        !          1551: NETIEVENT_SOCKET_DECL(tcpdnslisten);
        !          1552: NETIEVENT_SOCKET_REQ_DECL(tcpdnsconnect);
        !          1553: NETIEVENT_SOCKET_REQ_DECL(tcpdnssend);
        !          1554: NETIEVENT_SOCKET_HANDLE_DECL(tcpdnscancel);
        !          1555: NETIEVENT_SOCKET_QUOTA_DECL(tcpdnsaccept);
        !          1556:
        !          1557: NETIEVENT_SOCKET_DECL(tlsdnsclose);
        !          1558: NETIEVENT_SOCKET_DECL(tlsdnsread);
        !          1559: NETIEVENT_SOCKET_DECL(tlsdnsstop);
        !          1560: NETIEVENT_SOCKET_REQ_DECL(tlsdnssend);
        !          1561: NETIEVENT_SOCKET_HANDLE_DECL(tlsdnscancel);
        !          1562:
        !          1563: NETIEVENT_SOCKET_REQ_DECL(tcpconnect);
        !          1564: NETIEVENT_SOCKET_REQ_DECL(tcpsend);
        !          1565: NETIEVENT_SOCKET_REQ_DECL(tlssend);
        !          1566: NETIEVENT_SOCKET_REQ_DECL(udpconnect);
        !          1567:
        !          1568: NETIEVENT_SOCKET_REQ_RESULT_DECL(connectcb);
        !          1569: NETIEVENT_SOCKET_REQ_RESULT_DECL(readcb);
        !          1570: NETIEVENT_SOCKET_REQ_RESULT_DECL(sendcb);
        !          1571:
        !          1572: NETIEVENT_SOCKET_HANDLE_DECL(udpcancel);
        !          1573: NETIEVENT_SOCKET_HANDLE_DECL(tcpcancel);
        !          1574: NETIEVENT_SOCKET_DECL(detach);
        !          1575:
        !          1576: NETIEVENT_SOCKET_QUOTA_DECL(tcpaccept);
        !          1577:
        !          1578: NETIEVENT_DECL(pause);
        !          1579: NETIEVENT_DECL(resume);
        !          1580: NETIEVENT_DECL(shutdown);
        !          1581: NETIEVENT_DECL(stop);

CVSweb <webmaster@jp.NetBSD.org>