1 /* 2 * netio.h -- network I/O support. 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 * 9 * The netio module implements event based I/O handling using 10 * pselect(2). Multiple event handlers can wait for a certain event 11 * to occur simultaneously. Each event handler is called when an 12 * event occurs that the event handler has indicated that it is 13 * willing to handle. 14 * 15 * There are four types of events that can be handled: 16 * 17 * NETIO_EVENT_READ: reading will not block. 18 * NETIO_EVENT_WRITE: writing will not block. 19 * NETIO_EVENT_TIMEOUT: the timeout expired. 20 * 21 * A file descriptor must be specified if the handler is interested in 22 * the first three event types. A timeout must be specified if the 23 * event handler is interested in timeouts. These event types can be 24 * OR'ed together if the handler is willing to handle multiple types 25 * of events. 26 * 27 * The special event type NETIO_EVENT_NONE is available if you wish to 28 * temporarily disable the event handler without removing and adding 29 * the handler to the netio structure. 30 * 31 * The event callbacks are free to modify the netio_handler_type 32 * structure to change the file descriptor, timeout, event types, user 33 * data, or handler functions. 34 * 35 * The main loop of the program must call netio_dispatch to check for 36 * events and dispatch them to the handlers. An additional timeout 37 * can be specified as well as the signal mask to install while 38 * blocked in pselect(2). 39 */ 40 41 #ifndef NETIO_H 42 #define NETIO_H 43 44 #ifdef HAVE_SYS_SELECT_H 45 #include <sys/select.h> 46 #endif 47 48 #include <signal.h> 49 50 #include "region-allocator.h" 51 52 /* 53 * The type of events a handler is interested in. These can be OR'ed 54 * together to specify multiple event types. 55 */ 56 enum netio_event_types { 57 NETIO_EVENT_NONE = 0, 58 NETIO_EVENT_READ = 1, 59 NETIO_EVENT_WRITE = 2, 60 NETIO_EVENT_TIMEOUT = 4, 61 }; 62 typedef enum netio_event_types netio_event_types_type; 63 64 typedef struct netio netio_type; 65 typedef struct netio_handler netio_handler_type; 66 typedef struct netio_handler_list netio_handler_list_type; 67 68 struct netio 69 { 70 region_type *region; 71 netio_handler_list_type *handlers; 72 netio_handler_list_type *deallocated; 73 74 /* 75 * Cached value of the current time. The cached value is 76 * cleared at the start of netio_dispatch to calculate the 77 * relative timeouts of the event handlers and after calling 78 * pselect(2) so handlers can use it to calculate a new 79 * absolute timeout. 80 * 81 * Use netio_current_time() to read the current time. 82 */ 83 int have_current_time; 84 struct timespec cached_current_time; 85 86 /* 87 * Next handler in the dispatch. Only valid during callbacks. 88 * To make sure that deletes respect the state of the iterator. 89 */ 90 netio_handler_list_type *dispatch_next; 91 }; 92 93 typedef void (*netio_event_handler_type)(netio_type *netio, 94 netio_handler_type *handler, 95 netio_event_types_type event_types); 96 97 struct netio_handler 98 { 99 /* 100 * The file descriptor that should be checked for events. If 101 * the file descriptor is negative only timeout events are 102 * checked for. 103 */ 104 int fd; 105 106 /** index of the pollfd array for this handler */ 107 int pfd; 108 109 /* 110 * The time when no events should be checked for and the 111 * handler should be called with the NETIO_EVENT_TIMEOUT 112 * event type. Unlike most timeout parameters the time should 113 * be absolute, not relative! 114 */ 115 struct timespec *timeout; 116 117 /* 118 * Additional user data. 119 */ 120 void *user_data; 121 122 /* 123 * The type of events that should be checked for. These types 124 * can be OR'ed together to wait for multiple types of events. 125 */ 126 netio_event_types_type event_types; 127 128 /* 129 * The event handler. The event_types parameter contains the 130 * OR'ed set of event types that actually triggered. The 131 * event handler is allowed to modify this handler object. 132 * The event handler SHOULD NOT block. 133 */ 134 netio_event_handler_type event_handler; 135 }; 136 137 138 struct netio_handler_list 139 { 140 netio_handler_list_type *next; 141 netio_handler_type *handler; 142 }; 143 144 145 /* 146 * Create a new netio instance using the specified REGION. The netio 147 * instance is cleaned up when the REGION is deallocated. 148 */ 149 netio_type *netio_create(region_type *region); 150 151 /* 152 * Add a new HANDLER to NETIO. 153 */ 154 void netio_add_handler(netio_type *netio, netio_handler_type *handler); 155 156 /* 157 * Remove the HANDLER from NETIO. 158 */ 159 void netio_remove_handler(netio_type *netio, netio_handler_type *handler); 160 161 /* 162 * Retrieve the current time (using gettimeofday(2). 163 */ 164 const struct timespec *netio_current_time(netio_type *netio); 165 166 /* 167 * Check for events and dispatch them to the handlers. If TIMEOUT is 168 * specified it specifies the maximum time to wait for an event to 169 * arrive. SIGMASK is passed to the underlying pselect(2) call. 170 * Returns the number of non-timeout events dispatched, 0 on timeout, 171 * and -1 on error (with errno set appropriately). 172 */ 173 int netio_dispatch(netio_type *netio, 174 const struct timespec *timeout, 175 const sigset_t *sigmask); 176 177 178 #ifdef __cplusplus 179 inline netio_event_types_type 180 operator | (netio_event_types_type lhs, netio_event_types_type rhs) { 181 return (netio_event_types_type) (lhs | rhs); 182 } 183 inline netio_event_types_type 184 operator |= (netio_event_types_type &lhs, netio_event_types_type rhs) { 185 lhs = (netio_event_types_type) (lhs | rhs); 186 return lhs; 187 } 188 #endif /* __cplusplus */ 189 190 #endif /* NETIO_H */ 191