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