diff options
author | Jakob Schlyter <jakob@cvs.openbsd.org> | 2010-01-15 19:25:09 +0000 |
---|---|---|
committer | Jakob Schlyter <jakob@cvs.openbsd.org> | 2010-01-15 19:25:09 +0000 |
commit | d2081ac134d2d350ed92374b12613330132619c9 (patch) | |
tree | 511f9a412b24160516c7d3d29111801f9fa1bf35 /usr.sbin/nsd/netio.h | |
parent | efe15de128add506fb4055690c47221eb73d6346 (diff) |
NSD v3.2.4
Diffstat (limited to 'usr.sbin/nsd/netio.h')
-rw-r--r-- | usr.sbin/nsd/netio.h | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/usr.sbin/nsd/netio.h b/usr.sbin/nsd/netio.h new file mode 100644 index 00000000000..99d9c316aa3 --- /dev/null +++ b/usr.sbin/nsd/netio.h @@ -0,0 +1,182 @@ +/* + * 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_EXCEPT: an exception occurred. + * 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_EXCEPT = 4, + NETIO_EVENT_TIMEOUT = 8 +}; +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; + + /* + * 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; +}; + + +/* + * 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_ */ |