1*ae8c6e27Sflorian /* 2*ae8c6e27Sflorian * util/winsock_event.h - unbound event handling for winsock on windows 3*ae8c6e27Sflorian * 4*ae8c6e27Sflorian * Copyright (c) 2008, NLnet Labs. All rights reserved. 5*ae8c6e27Sflorian * 6*ae8c6e27Sflorian * This software is open source. 7*ae8c6e27Sflorian * 8*ae8c6e27Sflorian * Redistribution and use in source and binary forms, with or without 9*ae8c6e27Sflorian * modification, are permitted provided that the following conditions 10*ae8c6e27Sflorian * are met: 11*ae8c6e27Sflorian * 12*ae8c6e27Sflorian * Redistributions of source code must retain the above copyright notice, 13*ae8c6e27Sflorian * this list of conditions and the following disclaimer. 14*ae8c6e27Sflorian * 15*ae8c6e27Sflorian * Redistributions in binary form must reproduce the above copyright notice, 16*ae8c6e27Sflorian * this list of conditions and the following disclaimer in the documentation 17*ae8c6e27Sflorian * and/or other materials provided with the distribution. 18*ae8c6e27Sflorian * 19*ae8c6e27Sflorian * Neither the name of the NLNET LABS nor the names of its contributors may 20*ae8c6e27Sflorian * be used to endorse or promote products derived from this software without 21*ae8c6e27Sflorian * specific prior written permission. 22*ae8c6e27Sflorian * 23*ae8c6e27Sflorian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24*ae8c6e27Sflorian * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25*ae8c6e27Sflorian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26*ae8c6e27Sflorian * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27*ae8c6e27Sflorian * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28*ae8c6e27Sflorian * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29*ae8c6e27Sflorian * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30*ae8c6e27Sflorian * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31*ae8c6e27Sflorian * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32*ae8c6e27Sflorian * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33*ae8c6e27Sflorian * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34*ae8c6e27Sflorian */ 35*ae8c6e27Sflorian 36*ae8c6e27Sflorian /** 37*ae8c6e27Sflorian * \file 38*ae8c6e27Sflorian * 39*ae8c6e27Sflorian * This file contains interface functions with the WinSock2 API on Windows. 40*ae8c6e27Sflorian * It uses the winsock WSAWaitForMultipleEvents interface on a number of 41*ae8c6e27Sflorian * sockets. 42*ae8c6e27Sflorian * 43*ae8c6e27Sflorian * Note that windows can only wait for max 64 events at one time. 44*ae8c6e27Sflorian * 45*ae8c6e27Sflorian * Also, file descriptors cannot be waited for. 46*ae8c6e27Sflorian * 47*ae8c6e27Sflorian * Named pipes are not easily available (and are not usable in select() ). 48*ae8c6e27Sflorian * For interprocess communication, it is possible to wait for a hEvent to 49*ae8c6e27Sflorian * be signaled by another thread. 50*ae8c6e27Sflorian * 51*ae8c6e27Sflorian * When a socket becomes readable, then it will not be flagged as 52*ae8c6e27Sflorian * readable again until you have gotten WOULDBLOCK from a recv routine. 53*ae8c6e27Sflorian * That means the event handler must store the readability (edge notify) 54*ae8c6e27Sflorian * and process the incoming data until it blocks. 55*ae8c6e27Sflorian * The function performing recv then has to inform the event handler that 56*ae8c6e27Sflorian * the socket has blocked, and the event handler can mark it as such. 57*ae8c6e27Sflorian * Thus, this file transforms the edge notify from windows to a level notify 58*ae8c6e27Sflorian * that is compatible with UNIX. 59*ae8c6e27Sflorian * The WSAEventSelect page says that it does do level notify, as long 60*ae8c6e27Sflorian * as you call a recv/write/accept at least once when it is signalled. 61*ae8c6e27Sflorian * This last bit is not true, even though documented in server2008 api docs 62*ae8c6e27Sflorian * from microsoft, it does not happen at all. Instead you have to test for 63*ae8c6e27Sflorian * WSAEWOULDBLOCK on a tcp stream, and only then retest the socket. 64*ae8c6e27Sflorian * And before that remember the previous result as still valid. 65*ae8c6e27Sflorian * 66*ae8c6e27Sflorian * To stay 'fair', instead of emptying a socket completely, the event handler 67*ae8c6e27Sflorian * can test the other (marked as blocking) sockets for new events. 68*ae8c6e27Sflorian * 69*ae8c6e27Sflorian * Additionally, TCP accept sockets get special event support. 70*ae8c6e27Sflorian * 71*ae8c6e27Sflorian * Socket numbers are not starting small, they can be any number (say 33060). 72*ae8c6e27Sflorian * Therefore, bitmaps are not used, but arrays. 73*ae8c6e27Sflorian * 74*ae8c6e27Sflorian * on winsock, you must use recv() and send() for TCP reads and writes, 75*ae8c6e27Sflorian * not read() and write(), those work only on files. 76*ae8c6e27Sflorian * 77*ae8c6e27Sflorian * Also fseek and fseeko do not work if a FILE is not fopen-ed in binary mode. 78*ae8c6e27Sflorian * 79*ae8c6e27Sflorian * When under a high load windows gives out lots of errors, from recvfrom 80*ae8c6e27Sflorian * on udp sockets for example (WSAECONNRESET). Even though the udp socket 81*ae8c6e27Sflorian * has no connection per se. 82*ae8c6e27Sflorian */ 83*ae8c6e27Sflorian 84*ae8c6e27Sflorian #ifndef UTIL_WINSOCK_EVENT_H 85*ae8c6e27Sflorian #define UTIL_WINSOCK_EVENT_H 86*ae8c6e27Sflorian 87*ae8c6e27Sflorian #ifdef USE_WINSOCK 88*ae8c6e27Sflorian 89*ae8c6e27Sflorian #ifndef HAVE_EVENT_BASE_FREE 90*ae8c6e27Sflorian #define HAVE_EVENT_BASE_FREE 91*ae8c6e27Sflorian #endif 92*ae8c6e27Sflorian 93*ae8c6e27Sflorian /* redefine the calls to different names so that there is no name 94*ae8c6e27Sflorian * collision with other code that uses libevent names. (that uses libunbound)*/ 95*ae8c6e27Sflorian #define event_init winsockevent_init 96*ae8c6e27Sflorian #define event_get_version winsockevent_get_version 97*ae8c6e27Sflorian #define event_get_method winsockevent_get_method 98*ae8c6e27Sflorian #define event_base_dispatch winsockevent_base_dispatch 99*ae8c6e27Sflorian #define event_base_loopexit winsockevent_base_loopexit 100*ae8c6e27Sflorian #define event_base_free winsockevent_base_free 101*ae8c6e27Sflorian #define event_set winsockevent_set 102*ae8c6e27Sflorian #define event_base_set winsockevent_base_set 103*ae8c6e27Sflorian #define event_add winsockevent_add 104*ae8c6e27Sflorian #define event_del winsockevent_del 105*ae8c6e27Sflorian #define signal_add winsocksignal_add 106*ae8c6e27Sflorian #define signal_del winsocksignal_del 107*ae8c6e27Sflorian 108*ae8c6e27Sflorian /** event timeout */ 109*ae8c6e27Sflorian #define EV_TIMEOUT 0x01 110*ae8c6e27Sflorian /** event fd readable */ 111*ae8c6e27Sflorian #define EV_READ 0x02 112*ae8c6e27Sflorian /** event fd writable */ 113*ae8c6e27Sflorian #define EV_WRITE 0x04 114*ae8c6e27Sflorian /** event signal */ 115*ae8c6e27Sflorian #define EV_SIGNAL 0x08 116*ae8c6e27Sflorian /** event must persist */ 117*ae8c6e27Sflorian #define EV_PERSIST 0x10 118*ae8c6e27Sflorian 119*ae8c6e27Sflorian /* needs our redblack tree */ 120*ae8c6e27Sflorian #include "rbtree.h" 121*ae8c6e27Sflorian 122*ae8c6e27Sflorian /** max number of signals to support */ 123*ae8c6e27Sflorian #define MAX_SIG 32 124*ae8c6e27Sflorian 125*ae8c6e27Sflorian /** The number of items that the winsock event handler can service. 126*ae8c6e27Sflorian * Windows cannot handle more anyway */ 127*ae8c6e27Sflorian #define WSK_MAX_ITEMS 64 128*ae8c6e27Sflorian 129*ae8c6e27Sflorian /** 130*ae8c6e27Sflorian * event base for winsock event handler 131*ae8c6e27Sflorian */ 132*ae8c6e27Sflorian struct event_base 133*ae8c6e27Sflorian { 134*ae8c6e27Sflorian /** sorted by timeout (absolute), ptr */ 135*ae8c6e27Sflorian rbtree_type* times; 136*ae8c6e27Sflorian /** array (first part in use) of handles to work on */ 137*ae8c6e27Sflorian struct event** items; 138*ae8c6e27Sflorian /** number of items in use in array */ 139*ae8c6e27Sflorian int max; 140*ae8c6e27Sflorian /** capacity of array, size of array in items */ 141*ae8c6e27Sflorian int cap; 142*ae8c6e27Sflorian /** array of 0 - maxsig of ptr to event for it */ 143*ae8c6e27Sflorian struct event** signals; 144*ae8c6e27Sflorian /** if we need to exit */ 145*ae8c6e27Sflorian int need_to_exit; 146*ae8c6e27Sflorian /** where to store time in seconds */ 147*ae8c6e27Sflorian time_t* time_secs; 148*ae8c6e27Sflorian /** where to store time in microseconds */ 149*ae8c6e27Sflorian struct timeval* time_tv; 150*ae8c6e27Sflorian /** 151*ae8c6e27Sflorian * TCP streams have sticky events to them, these are not 152*ae8c6e27Sflorian * reported by the windows event system anymore, we have to 153*ae8c6e27Sflorian * keep reporting those events as present until wouldblock() is 154*ae8c6e27Sflorian * signalled by the handler back to use. 155*ae8c6e27Sflorian */ 156*ae8c6e27Sflorian int tcp_stickies; 157*ae8c6e27Sflorian /** 158*ae8c6e27Sflorian * should next cycle process reinvigorated stickies, 159*ae8c6e27Sflorian * these are stickies that have been stored, but due to a new 160*ae8c6e27Sflorian * event_add a sudden interest in the event has incepted. 161*ae8c6e27Sflorian */ 162*ae8c6e27Sflorian int tcp_reinvigorated; 163*ae8c6e27Sflorian /** The list of events that is currently being processed. */ 164*ae8c6e27Sflorian WSAEVENT waitfor[WSK_MAX_ITEMS]; 165*ae8c6e27Sflorian }; 166*ae8c6e27Sflorian 167*ae8c6e27Sflorian /** 168*ae8c6e27Sflorian * Event structure. Has some of the event elements. 169*ae8c6e27Sflorian */ 170*ae8c6e27Sflorian struct event { 171*ae8c6e27Sflorian /** node in timeout rbtree */ 172*ae8c6e27Sflorian rbnode_type node; 173*ae8c6e27Sflorian /** is event already added */ 174*ae8c6e27Sflorian int added; 175*ae8c6e27Sflorian 176*ae8c6e27Sflorian /** event base it belongs to */ 177*ae8c6e27Sflorian struct event_base *ev_base; 178*ae8c6e27Sflorian /** fd to poll or -1 for timeouts. signal number for sigs. */ 179*ae8c6e27Sflorian int ev_fd; 180*ae8c6e27Sflorian /** what events this event is interested in, see EV_.. above. */ 181*ae8c6e27Sflorian short ev_events; 182*ae8c6e27Sflorian /** timeout value */ 183*ae8c6e27Sflorian struct timeval ev_timeout; 184*ae8c6e27Sflorian 185*ae8c6e27Sflorian /** callback to call: fd, eventbits, userarg */ 186*ae8c6e27Sflorian void (*ev_callback)(int, short, void *); 187*ae8c6e27Sflorian /** callback user arg */ 188*ae8c6e27Sflorian void *ev_arg; 189*ae8c6e27Sflorian 190*ae8c6e27Sflorian /* ----- nonpublic part, for winsock_event only ----- */ 191*ae8c6e27Sflorian /** index of this event in the items array (if added) */ 192*ae8c6e27Sflorian int idx; 193*ae8c6e27Sflorian /** the event handle to wait for new events to become ready */ 194*ae8c6e27Sflorian WSAEVENT hEvent; 195*ae8c6e27Sflorian /** true if this filedes is a TCP socket and needs special attention */ 196*ae8c6e27Sflorian int is_tcp; 197*ae8c6e27Sflorian /** remembered EV_ values */ 198*ae8c6e27Sflorian short old_events; 199*ae8c6e27Sflorian /** should remembered EV_ values be used for TCP streams. 200*ae8c6e27Sflorian * Reset after WOULDBLOCK is signaled using the function. */ 201*ae8c6e27Sflorian int stick_events; 202*ae8c6e27Sflorian 203*ae8c6e27Sflorian /** true if this event is a signaling WSAEvent by the user. 204*ae8c6e27Sflorian * User created and user closed WSAEvent. Only signaled/unsignaled, 205*ae8c6e27Sflorian * no read/write/distinctions needed. */ 206*ae8c6e27Sflorian int is_signal; 207*ae8c6e27Sflorian /** used during callbacks to see which events were just checked */ 208*ae8c6e27Sflorian int just_checked; 209*ae8c6e27Sflorian }; 210*ae8c6e27Sflorian 211*ae8c6e27Sflorian /** create event base */ 212*ae8c6e27Sflorian void *event_init(time_t* time_secs, struct timeval* time_tv); 213*ae8c6e27Sflorian /** get version */ 214*ae8c6e27Sflorian const char *event_get_version(void); 215*ae8c6e27Sflorian /** get polling method (select,epoll) */ 216*ae8c6e27Sflorian const char *event_get_method(void); 217*ae8c6e27Sflorian /** run select in a loop */ 218*ae8c6e27Sflorian int event_base_dispatch(struct event_base *); 219*ae8c6e27Sflorian /** exit that loop */ 220*ae8c6e27Sflorian int event_base_loopexit(struct event_base *, struct timeval *); 221*ae8c6e27Sflorian /** free event base. Free events yourself */ 222*ae8c6e27Sflorian void event_base_free(struct event_base *); 223*ae8c6e27Sflorian /** set content of event */ 224*ae8c6e27Sflorian void event_set(struct event *, int, short, void (*)(int, short, void *), void *); 225*ae8c6e27Sflorian 226*ae8c6e27Sflorian /** add event to a base. You *must* call this for every event. */ 227*ae8c6e27Sflorian int event_base_set(struct event_base *, struct event *); 228*ae8c6e27Sflorian /** add event to make it active. You may not change it with event_set anymore */ 229*ae8c6e27Sflorian int event_add(struct event *, struct timeval *); 230*ae8c6e27Sflorian /** remove event. You may change it again */ 231*ae8c6e27Sflorian int event_del(struct event *); 232*ae8c6e27Sflorian 233*ae8c6e27Sflorian #define evtimer_add(ev, tv) event_add(ev, tv) 234*ae8c6e27Sflorian #define evtimer_del(ev) event_del(ev) 235*ae8c6e27Sflorian 236*ae8c6e27Sflorian /* uses different implementation. Cannot mix fd/timeouts and signals inside 237*ae8c6e27Sflorian * the same struct event. create several event structs for that. */ 238*ae8c6e27Sflorian /** install signal handler */ 239*ae8c6e27Sflorian int signal_add(struct event *, struct timeval *); 240*ae8c6e27Sflorian /** set signal event contents */ 241*ae8c6e27Sflorian #define signal_set(ev, x, cb, arg) \ 242*ae8c6e27Sflorian event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) 243*ae8c6e27Sflorian /** remove signal handler */ 244*ae8c6e27Sflorian int signal_del(struct event *); 245*ae8c6e27Sflorian 246*ae8c6e27Sflorian /** compare events in tree, based on timevalue, ptr for uniqueness */ 247*ae8c6e27Sflorian int mini_ev_cmp(const void* a, const void* b); 248*ae8c6e27Sflorian 249*ae8c6e27Sflorian /** 250*ae8c6e27Sflorian * Routine for windows only, where the handling layer can signal that 251*ae8c6e27Sflorian * a TCP stream encountered WSAEWOULDBLOCK for a stream and thus needs 252*ae8c6e27Sflorian * retesting the event. 253*ae8c6e27Sflorian * Pass if EV_READ or EV_WRITE gave wouldblock. 254*ae8c6e27Sflorian */ 255*ae8c6e27Sflorian void winsock_tcp_wouldblock(struct event* ev, int eventbit); 256*ae8c6e27Sflorian 257*ae8c6e27Sflorian /** 258*ae8c6e27Sflorian * Routine for windows only. where you pass a signal WSAEvent that 259*ae8c6e27Sflorian * you wait for. When the event is signaled, the callback gets called. 260*ae8c6e27Sflorian * The callback has to WSAResetEvent to disable the signal. 261*ae8c6e27Sflorian * @param base: the event base. 262*ae8c6e27Sflorian * @param ev: the event structure for data storage 263*ae8c6e27Sflorian * can be passed uninitialised. 264*ae8c6e27Sflorian * @param wsaevent: the WSAEvent that gets signaled. 265*ae8c6e27Sflorian * @param cb: callback routine. 266*ae8c6e27Sflorian * @param arg: user argument to callback routine. 267*ae8c6e27Sflorian * @return false on error. 268*ae8c6e27Sflorian */ 269*ae8c6e27Sflorian int winsock_register_wsaevent(struct event_base* base, struct event* ev, 270*ae8c6e27Sflorian WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg); 271*ae8c6e27Sflorian 272*ae8c6e27Sflorian /** 273*ae8c6e27Sflorian * Unregister a wsaevent. User has to close the WSAEVENT itself. 274*ae8c6e27Sflorian * @param ev: event data storage. 275*ae8c6e27Sflorian */ 276*ae8c6e27Sflorian void winsock_unregister_wsaevent(struct event* ev); 277*ae8c6e27Sflorian 278*ae8c6e27Sflorian #endif /* USE_WINSOCK */ 279*ae8c6e27Sflorian #endif /* UTIL_WINSOCK_EVENT_H */ 280