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