1 /* 2 * netio.h -- network I/O support. 3 * 4 * Copyright (c) 2001-2011, 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 #define NETIO_SLOW_ACCEPT_TIMEOUT 2 /* in seconds */ 54 55 /* 56 * The type of events a handler is interested in. These can be OR'ed 57 * together to specify multiple event types. 58 */ 59 enum netio_event_types { 60 NETIO_EVENT_NONE = 0, 61 NETIO_EVENT_READ = 1, 62 NETIO_EVENT_WRITE = 2, 63 NETIO_EVENT_EXCEPT = 4, 64 NETIO_EVENT_TIMEOUT = 8, 65 NETIO_EVENT_ACCEPT = 16 66 }; 67 typedef enum netio_event_types netio_event_types_type; 68 69 typedef struct netio netio_type; 70 typedef struct netio_handler netio_handler_type; 71 typedef struct netio_handler_list netio_handler_list_type; 72 73 struct netio 74 { 75 region_type *region; 76 netio_handler_list_type *handlers; 77 netio_handler_list_type *deallocated; 78 79 /* 80 * Cached value of the current time. The cached value is 81 * cleared at the start of netio_dispatch to calculate the 82 * relative timeouts of the event handlers and after calling 83 * pselect(2) so handlers can use it to calculate a new 84 * absolute timeout. 85 * 86 * Use netio_current_time() to read the current time. 87 */ 88 int have_current_time; 89 struct timespec cached_current_time; 90 91 /* 92 * Next handler in the dispatch. Only valid during callbacks. 93 * To make sure that deletes respect the state of the iterator. 94 */ 95 netio_handler_list_type *dispatch_next; 96 }; 97 98 typedef void (*netio_event_handler_type)(netio_type *netio, 99 netio_handler_type *handler, 100 netio_event_types_type event_types); 101 102 struct netio_handler 103 { 104 /* 105 * The file descriptor that should be checked for events. If 106 * the file descriptor is negative only timeout events are 107 * checked for. 108 */ 109 int fd; 110 111 /* 112 * The time when no events should be checked for and the 113 * handler should be called with the NETIO_EVENT_TIMEOUT 114 * event type. Unlike most timeout parameters the time should 115 * be absolute, not relative! 116 */ 117 struct timespec *timeout; 118 119 /* 120 * Additional user data. 121 */ 122 void *user_data; 123 124 /* 125 * The type of events that should be checked for. These types 126 * can be OR'ed together to wait for multiple types of events. 127 */ 128 netio_event_types_type event_types; 129 130 /* 131 * The event handler. The event_types parameter contains the 132 * OR'ed set of event types that actually triggered. The 133 * event handler is allowed to modify this handler object. 134 * The event handler SHOULD NOT block. 135 */ 136 netio_event_handler_type event_handler; 137 }; 138 139 140 /* 141 * Create a new netio instance using the specified REGION. The netio 142 * instance is cleaned up when the REGION is deallocated. 143 */ 144 netio_type *netio_create(region_type *region); 145 146 /* 147 * Add a new HANDLER to NETIO. 148 */ 149 void netio_add_handler(netio_type *netio, netio_handler_type *handler); 150 151 /* 152 * Remove the HANDLER from NETIO. 153 */ 154 void netio_remove_handler(netio_type *netio, netio_handler_type *handler); 155 156 /* 157 * Retrieve the current time (using gettimeofday(2). 158 */ 159 const struct timespec *netio_current_time(netio_type *netio); 160 161 /* 162 * Check for events and dispatch them to the handlers. If TIMEOUT is 163 * specified it specifies the maximum time to wait for an event to 164 * arrive. SIGMASK is passed to the underlying pselect(2) call. 165 * Returns the number of non-timeout events dispatched, 0 on timeout, 166 * and -1 on error (with errno set appropriately). 167 */ 168 int netio_dispatch(netio_type *netio, 169 const struct timespec *timeout, 170 const sigset_t *sigmask); 171 172 173 #ifdef __cplusplus 174 inline netio_event_types_type 175 operator | (netio_event_types_type lhs, netio_event_types_type rhs) { 176 return (netio_event_types_type) (lhs | rhs); 177 } 178 inline netio_event_types_type 179 operator |= (netio_event_types_type &lhs, netio_event_types_type rhs) { 180 lhs = (netio_event_types_type) (lhs | rhs); 181 return lhs; 182 } 183 #endif /* __cplusplus */ 184 185 #endif /* _NETIO_H_ */ 186