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