xref: /openbsd-src/usr.sbin/nsd/netio.h (revision 3efee2e132f9af6db74577d714f3304be2b3af74)
162ac0c33Sjakob /*
262ac0c33Sjakob  * netio.h -- network I/O support.
362ac0c33Sjakob  *
4d3fecca9Ssthen  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
562ac0c33Sjakob  *
662ac0c33Sjakob  * See LICENSE for the license.
762ac0c33Sjakob  *
862ac0c33Sjakob  *
962ac0c33Sjakob  * The netio module implements event based I/O handling using
1062ac0c33Sjakob  * pselect(2).  Multiple event handlers can wait for a certain event
1162ac0c33Sjakob  * to occur simultaneously.  Each event handler is called when an
1262ac0c33Sjakob  * event occurs that the event handler has indicated that it is
1362ac0c33Sjakob  * willing to handle.
1462ac0c33Sjakob  *
1562ac0c33Sjakob  * There are four types of events that can be handled:
1662ac0c33Sjakob  *
1762ac0c33Sjakob  *   NETIO_EVENT_READ: reading will not block.
1862ac0c33Sjakob  *   NETIO_EVENT_WRITE: writing will not block.
1962ac0c33Sjakob  *   NETIO_EVENT_TIMEOUT: the timeout expired.
2062ac0c33Sjakob  *
2162ac0c33Sjakob  * A file descriptor must be specified if the handler is interested in
2262ac0c33Sjakob  * the first three event types.  A timeout must be specified if the
2362ac0c33Sjakob  * event handler is interested in timeouts.  These event types can be
2462ac0c33Sjakob  * OR'ed together if the handler is willing to handle multiple types
2562ac0c33Sjakob  * of events.
2662ac0c33Sjakob  *
2762ac0c33Sjakob  * The special event type NETIO_EVENT_NONE is available if you wish to
2862ac0c33Sjakob  * temporarily disable the event handler without removing and adding
2962ac0c33Sjakob  * the handler to the netio structure.
3062ac0c33Sjakob  *
3162ac0c33Sjakob  * The event callbacks are free to modify the netio_handler_type
3262ac0c33Sjakob  * structure to change the file descriptor, timeout, event types, user
3362ac0c33Sjakob  * data, or handler functions.
3462ac0c33Sjakob  *
3562ac0c33Sjakob  * The main loop of the program must call netio_dispatch to check for
3662ac0c33Sjakob  * events and dispatch them to the handlers.  An additional timeout
3762ac0c33Sjakob  * can be specified as well as the signal mask to install while
3862ac0c33Sjakob  * blocked in pselect(2).
3962ac0c33Sjakob  */
4062ac0c33Sjakob 
41*3efee2e1Sflorian #ifndef NETIO_H
42*3efee2e1Sflorian #define NETIO_H
4362ac0c33Sjakob 
4462ac0c33Sjakob #ifdef	HAVE_SYS_SELECT_H
4562ac0c33Sjakob #include <sys/select.h>
4662ac0c33Sjakob #endif
4762ac0c33Sjakob 
4862ac0c33Sjakob #include <signal.h>
4962ac0c33Sjakob 
5062ac0c33Sjakob #include "region-allocator.h"
5162ac0c33Sjakob 
5262ac0c33Sjakob /*
5362ac0c33Sjakob  * The type of events a handler is interested in.  These can be OR'ed
5462ac0c33Sjakob  * together to specify multiple event types.
5562ac0c33Sjakob  */
5662ac0c33Sjakob enum netio_event_types {
5762ac0c33Sjakob 	NETIO_EVENT_NONE    = 0,
5862ac0c33Sjakob 	NETIO_EVENT_READ    = 1,
5962ac0c33Sjakob 	NETIO_EVENT_WRITE   = 2,
603126abd5Ssthen 	NETIO_EVENT_TIMEOUT = 4,
6162ac0c33Sjakob };
6262ac0c33Sjakob typedef enum netio_event_types netio_event_types_type;
6362ac0c33Sjakob 
6462ac0c33Sjakob typedef struct netio netio_type;
6562ac0c33Sjakob typedef struct netio_handler netio_handler_type;
6662ac0c33Sjakob typedef struct netio_handler_list netio_handler_list_type;
6762ac0c33Sjakob 
6862ac0c33Sjakob struct netio
6962ac0c33Sjakob {
7062ac0c33Sjakob 	region_type             *region;
7162ac0c33Sjakob 	netio_handler_list_type *handlers;
7262ac0c33Sjakob 	netio_handler_list_type *deallocated;
7362ac0c33Sjakob 
7462ac0c33Sjakob 	/*
7562ac0c33Sjakob 	 * Cached value of the current time.  The cached value is
7662ac0c33Sjakob 	 * cleared at the start of netio_dispatch to calculate the
7762ac0c33Sjakob 	 * relative timeouts of the event handlers and after calling
7862ac0c33Sjakob 	 * pselect(2) so handlers can use it to calculate a new
7962ac0c33Sjakob 	 * absolute timeout.
8062ac0c33Sjakob 	 *
8162ac0c33Sjakob 	 * Use netio_current_time() to read the current time.
8262ac0c33Sjakob 	 */
8362ac0c33Sjakob 	int have_current_time;
8462ac0c33Sjakob 	struct timespec cached_current_time;
8562ac0c33Sjakob 
8662ac0c33Sjakob 	/*
8762ac0c33Sjakob 	 * Next handler in the dispatch. Only valid during callbacks.
8862ac0c33Sjakob 	 * To make sure that deletes respect the state of the iterator.
8962ac0c33Sjakob 	 */
9062ac0c33Sjakob 	netio_handler_list_type *dispatch_next;
9162ac0c33Sjakob };
9262ac0c33Sjakob 
9362ac0c33Sjakob typedef void (*netio_event_handler_type)(netio_type *netio,
9462ac0c33Sjakob 					 netio_handler_type *handler,
9562ac0c33Sjakob 					 netio_event_types_type event_types);
9662ac0c33Sjakob 
9762ac0c33Sjakob struct netio_handler
9862ac0c33Sjakob {
9962ac0c33Sjakob 	/*
10062ac0c33Sjakob 	 * The file descriptor that should be checked for events.  If
10162ac0c33Sjakob 	 * the file descriptor is negative only timeout events are
10262ac0c33Sjakob 	 * checked for.
10362ac0c33Sjakob 	 */
10462ac0c33Sjakob 	int fd;
10562ac0c33Sjakob 
1063126abd5Ssthen 	/** index of the pollfd array for this handler */
1073126abd5Ssthen 	int pfd;
1083126abd5Ssthen 
10962ac0c33Sjakob 	/*
11062ac0c33Sjakob 	 * The time when no events should be checked for and the
11162ac0c33Sjakob 	 * handler should be called with the NETIO_EVENT_TIMEOUT
11262ac0c33Sjakob 	 * event type.  Unlike most timeout parameters the time should
11362ac0c33Sjakob 	 * be absolute, not relative!
11462ac0c33Sjakob 	 */
11562ac0c33Sjakob 	struct timespec *timeout;
11662ac0c33Sjakob 
11762ac0c33Sjakob 	/*
11862ac0c33Sjakob 	 * Additional user data.
11962ac0c33Sjakob 	 */
12062ac0c33Sjakob 	void *user_data;
12162ac0c33Sjakob 
12262ac0c33Sjakob 	/*
12362ac0c33Sjakob 	 * The type of events that should be checked for.  These types
12462ac0c33Sjakob 	 * can be OR'ed together to wait for multiple types of events.
12562ac0c33Sjakob 	 */
12662ac0c33Sjakob 	netio_event_types_type event_types;
12762ac0c33Sjakob 
12862ac0c33Sjakob 	/*
12962ac0c33Sjakob 	 * The event handler.  The event_types parameter contains the
13062ac0c33Sjakob 	 * OR'ed set of event types that actually triggered.  The
13162ac0c33Sjakob 	 * event handler is allowed to modify this handler object.
13262ac0c33Sjakob 	 * The event handler SHOULD NOT block.
13362ac0c33Sjakob 	 */
13462ac0c33Sjakob 	netio_event_handler_type event_handler;
13562ac0c33Sjakob };
13662ac0c33Sjakob 
13762ac0c33Sjakob 
13812455795Ssthen struct netio_handler_list
13912455795Ssthen {
14012455795Ssthen 	netio_handler_list_type *next;
14112455795Ssthen 	netio_handler_type      *handler;
14212455795Ssthen };
14312455795Ssthen 
14412455795Ssthen 
14562ac0c33Sjakob /*
14662ac0c33Sjakob  * Create a new netio instance using the specified REGION.  The netio
14762ac0c33Sjakob  * instance is cleaned up when the REGION is deallocated.
14862ac0c33Sjakob  */
14962ac0c33Sjakob netio_type *netio_create(region_type *region);
15062ac0c33Sjakob 
15162ac0c33Sjakob /*
15262ac0c33Sjakob  * Add a new HANDLER to NETIO.
15362ac0c33Sjakob  */
15462ac0c33Sjakob void netio_add_handler(netio_type *netio, netio_handler_type *handler);
15562ac0c33Sjakob 
15662ac0c33Sjakob /*
15762ac0c33Sjakob  * Remove the HANDLER from NETIO.
15862ac0c33Sjakob  */
15962ac0c33Sjakob void netio_remove_handler(netio_type *netio, netio_handler_type *handler);
16062ac0c33Sjakob 
16162ac0c33Sjakob /*
16262ac0c33Sjakob  * Retrieve the current time (using gettimeofday(2).
16362ac0c33Sjakob  */
16462ac0c33Sjakob const struct timespec *netio_current_time(netio_type *netio);
16562ac0c33Sjakob 
16662ac0c33Sjakob /*
16762ac0c33Sjakob  * Check for events and dispatch them to the handlers.  If TIMEOUT is
16862ac0c33Sjakob  * specified it specifies the maximum time to wait for an event to
16962ac0c33Sjakob  * arrive.  SIGMASK is passed to the underlying pselect(2) call.
17062ac0c33Sjakob  * Returns the number of non-timeout events dispatched, 0 on timeout,
17162ac0c33Sjakob  * and -1 on error (with errno set appropriately).
17262ac0c33Sjakob  */
17362ac0c33Sjakob int netio_dispatch(netio_type *netio,
17462ac0c33Sjakob 		   const struct timespec *timeout,
17562ac0c33Sjakob 		   const sigset_t *sigmask);
17662ac0c33Sjakob 
17762ac0c33Sjakob 
17862ac0c33Sjakob #ifdef __cplusplus
17962ac0c33Sjakob inline netio_event_types_type
18062ac0c33Sjakob operator | (netio_event_types_type lhs, netio_event_types_type rhs) {
18162ac0c33Sjakob 	return (netio_event_types_type) (lhs | rhs);
18262ac0c33Sjakob }
18362ac0c33Sjakob inline netio_event_types_type
18462ac0c33Sjakob operator |= (netio_event_types_type &lhs, netio_event_types_type rhs) {
18562ac0c33Sjakob 	lhs = (netio_event_types_type) (lhs | rhs);
18662ac0c33Sjakob 	return lhs;
18762ac0c33Sjakob }
18862ac0c33Sjakob #endif /* __cplusplus */
18962ac0c33Sjakob 
190*3efee2e1Sflorian #endif /* NETIO_H */
191