1933707f3Ssthen /* 2933707f3Ssthen * mini-event.h - micro implementation of libevent api, using select() only. 3933707f3Ssthen * 4933707f3Ssthen * Copyright (c) 2007, NLnet Labs. All rights reserved. 5933707f3Ssthen * 6933707f3Ssthen * This software is open source. 7933707f3Ssthen * 8933707f3Ssthen * Redistribution and use in source and binary forms, with or without 9933707f3Ssthen * modification, are permitted provided that the following conditions 10933707f3Ssthen * are met: 11933707f3Ssthen * 12933707f3Ssthen * Redistributions of source code must retain the above copyright notice, 13933707f3Ssthen * this list of conditions and the following disclaimer. 14933707f3Ssthen * 15933707f3Ssthen * Redistributions in binary form must reproduce the above copyright notice, 16933707f3Ssthen * this list of conditions and the following disclaimer in the documentation 17933707f3Ssthen * and/or other materials provided with the distribution. 18933707f3Ssthen * 19933707f3Ssthen * Neither the name of the NLNET LABS nor the names of its contributors may 20933707f3Ssthen * be used to endorse or promote products derived from this software without 21933707f3Ssthen * specific prior written permission. 22933707f3Ssthen * 23933707f3Ssthen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24933707f3Ssthen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25933707f3Ssthen * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26933707f3Ssthen * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 27933707f3Ssthen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28933707f3Ssthen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29933707f3Ssthen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30933707f3Ssthen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31933707f3Ssthen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32933707f3Ssthen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33933707f3Ssthen * POSSIBILITY OF SUCH DAMAGE. 34933707f3Ssthen */ 35933707f3Ssthen 36933707f3Ssthen /** 37933707f3Ssthen * \file 38933707f3Ssthen * This file implements part of the event(3) libevent api. 39933707f3Ssthen * The back end is only select. Max number of fds is limited. 40933707f3Ssthen * Max number of signals is limited, one handler per signal only. 41933707f3Ssthen * And one handler per fd. 42933707f3Ssthen * 43933707f3Ssthen * Although limited to select() and a max (1024) open fds, it 44933707f3Ssthen * is efficient: 45933707f3Ssthen * o dispatch call caches fd_sets to use. 46933707f3Ssthen * o handler calling takes time ~ to the number of fds. 47933707f3Ssthen * o timeouts are stored in a redblack tree, sorted, so take log(n). 48933707f3Ssthen * Timeouts are only accurate to the second (no subsecond accuracy). 49933707f3Ssthen * To avoid cpu hogging, fractional timeouts are rounded up to a whole second. 50933707f3Ssthen */ 51933707f3Ssthen 52933707f3Ssthen #ifndef MINI_EVENT_H 53933707f3Ssthen #define MINI_EVENT_H 54933707f3Ssthen 55933707f3Ssthen #if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK) 56933707f3Ssthen 57933707f3Ssthen #ifndef HAVE_EVENT_BASE_FREE 58933707f3Ssthen #define HAVE_EVENT_BASE_FREE 59933707f3Ssthen #endif 60933707f3Ssthen 61933707f3Ssthen /** event timeout */ 62933707f3Ssthen #define EV_TIMEOUT 0x01 63933707f3Ssthen /** event fd readable */ 64933707f3Ssthen #define EV_READ 0x02 65933707f3Ssthen /** event fd writable */ 66933707f3Ssthen #define EV_WRITE 0x04 67933707f3Ssthen /** event signal */ 68933707f3Ssthen #define EV_SIGNAL 0x08 69933707f3Ssthen /** event must persist */ 70933707f3Ssthen #define EV_PERSIST 0x10 71933707f3Ssthen 72933707f3Ssthen /* needs our redblack tree */ 73933707f3Ssthen #include "rbtree.h" 74933707f3Ssthen 75933707f3Ssthen /** max number of file descriptors to support */ 76933707f3Ssthen #define MAX_FDS 1024 77933707f3Ssthen /** max number of signals to support */ 78933707f3Ssthen #define MAX_SIG 32 79933707f3Ssthen 80933707f3Ssthen /** event base */ 81933707f3Ssthen struct event_base 82933707f3Ssthen { 83933707f3Ssthen /** sorted by timeout (absolute), ptr */ 84933707f3Ssthen rbtree_t* times; 85933707f3Ssthen /** array of 0 - maxfd of ptr to event for it */ 86933707f3Ssthen struct event** fds; 87933707f3Ssthen /** max fd in use */ 88933707f3Ssthen int maxfd; 89933707f3Ssthen /** capacity - size of the fds array */ 90933707f3Ssthen int capfd; 91933707f3Ssthen /* fdset for read write, for fds ready, and added */ 92933707f3Ssthen fd_set 93933707f3Ssthen /** fds for reading */ 94933707f3Ssthen reads, 95933707f3Ssthen /** fds for writing */ 96933707f3Ssthen writes, 97933707f3Ssthen /** fds determined ready for use */ 98933707f3Ssthen ready, 99933707f3Ssthen /** ready plus newly added events. */ 100933707f3Ssthen content; 101933707f3Ssthen /** array of 0 - maxsig of ptr to event for it */ 102933707f3Ssthen struct event** signals; 103933707f3Ssthen /** if we need to exit */ 104933707f3Ssthen int need_to_exit; 105933707f3Ssthen /** where to store time in seconds */ 106*229e174cSsthen time_t* time_secs; 107933707f3Ssthen /** where to store time in microseconds */ 108933707f3Ssthen struct timeval* time_tv; 109933707f3Ssthen }; 110933707f3Ssthen 111933707f3Ssthen /** 112933707f3Ssthen * Event structure. Has some of the event elements. 113933707f3Ssthen */ 114933707f3Ssthen struct event { 115933707f3Ssthen /** node in timeout rbtree */ 116933707f3Ssthen rbnode_t node; 117933707f3Ssthen /** is event already added */ 118933707f3Ssthen int added; 119933707f3Ssthen 120933707f3Ssthen /** event base it belongs to */ 121933707f3Ssthen struct event_base *ev_base; 122933707f3Ssthen /** fd to poll or -1 for timeouts. signal number for sigs. */ 123933707f3Ssthen int ev_fd; 124933707f3Ssthen /** what events this event is interested in, see EV_.. above. */ 125933707f3Ssthen short ev_events; 126933707f3Ssthen /** timeout value */ 127933707f3Ssthen struct timeval ev_timeout; 128933707f3Ssthen 129933707f3Ssthen /** callback to call: fd, eventbits, userarg */ 130933707f3Ssthen void (*ev_callback)(int, short, void *arg); 131933707f3Ssthen /** callback user arg */ 132933707f3Ssthen void *ev_arg; 133933707f3Ssthen }; 134933707f3Ssthen 135933707f3Ssthen /* function prototypes (some are as they appear in event.h) */ 136933707f3Ssthen /** create event base */ 137*229e174cSsthen void *event_init(time_t* time_secs, struct timeval* time_tv); 138933707f3Ssthen /** get version */ 139933707f3Ssthen const char *event_get_version(void); 140933707f3Ssthen /** get polling method, select */ 141933707f3Ssthen const char *event_get_method(void); 142933707f3Ssthen /** run select in a loop */ 143933707f3Ssthen int event_base_dispatch(struct event_base *); 144933707f3Ssthen /** exit that loop */ 145933707f3Ssthen int event_base_loopexit(struct event_base *, struct timeval *); 146933707f3Ssthen /** free event base. Free events yourself */ 147933707f3Ssthen void event_base_free(struct event_base *); 148933707f3Ssthen /** set content of event */ 149933707f3Ssthen void event_set(struct event *, int, short, void (*)(int, short, void *), void *); 150933707f3Ssthen /** add event to a base. You *must* call this for every event. */ 151933707f3Ssthen int event_base_set(struct event_base *, struct event *); 152933707f3Ssthen /** add event to make it active. You may not change it with event_set anymore */ 153933707f3Ssthen int event_add(struct event *, struct timeval *); 154933707f3Ssthen /** remove event. You may change it again */ 155933707f3Ssthen int event_del(struct event *); 156933707f3Ssthen 157933707f3Ssthen /** add a timer */ 158933707f3Ssthen #define evtimer_add(ev, tv) event_add(ev, tv) 159933707f3Ssthen /** remove a timer */ 160933707f3Ssthen #define evtimer_del(ev) event_del(ev) 161933707f3Ssthen 162933707f3Ssthen /* uses different implementation. Cannot mix fd/timeouts and signals inside 163933707f3Ssthen * the same struct event. create several event structs for that. */ 164933707f3Ssthen /** install signal handler */ 165933707f3Ssthen int signal_add(struct event *, struct timeval *); 166933707f3Ssthen /** set signal event contents */ 167933707f3Ssthen #define signal_set(ev, x, cb, arg) \ 168933707f3Ssthen event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) 169933707f3Ssthen /** remove signal handler */ 170933707f3Ssthen int signal_del(struct event *); 171933707f3Ssthen 172933707f3Ssthen #endif /* USE_MINI_EVENT and not USE_WINSOCK */ 173933707f3Ssthen 174933707f3Ssthen /** compare events in tree, based on timevalue, ptr for uniqueness */ 175933707f3Ssthen int mini_ev_cmp(const void* a, const void* b); 176933707f3Ssthen 177933707f3Ssthen #endif /* MINI_EVENT_H */ 178