320 lines
12 KiB
C
320 lines
12 KiB
C
#ifndef INCLUDED_ircd_events_h
|
|
#define INCLUDED_ircd_events_h
|
|
/*
|
|
* IRC - Internet Relay Chat, include/ircd_events.h
|
|
* Copyright (C) 2001 Kevin L. Mitchell <klmitch@mit.edu>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
/** @file
|
|
* @brief Interface and public definitions for event loop.
|
|
* @version $Id: ircd_events.h 1794 2007-04-01 02:11:41Z entrope $
|
|
*/
|
|
|
|
#ifndef INCLUDED_config_h
|
|
#include "config.h"
|
|
#endif
|
|
#ifndef INCLUDED_sys_types_h
|
|
#include <sys/types.h> /* time_t */
|
|
#define INCLUDED_sys_types_h
|
|
#endif
|
|
#ifdef USE_SSL
|
|
#ifndef INCLUDED_ssl_h
|
|
#include "ssl.h"
|
|
#endif
|
|
#endif /* USE_SSL */
|
|
|
|
struct Event;
|
|
|
|
/** Generic callback for event activity. */
|
|
typedef void (*EventCallBack)(struct Event*);
|
|
|
|
/** State of a Socket structure. */
|
|
enum SocketState {
|
|
SS_CONNECTING, /**< Connection in progress on socket */
|
|
SS_LISTENING, /**< Socket is a listening socket */
|
|
SS_CONNECTED, /**< Socket is a connected socket */
|
|
SS_DATAGRAM, /**< Socket is a datagram socket */
|
|
SS_CONNECTDG, /**< Socket is a connected datagram socket */
|
|
SS_NOTSOCK /**< Socket isn't a socket at all */
|
|
};
|
|
|
|
/** Type of a Timer (how its expiration is measured). */
|
|
enum TimerType {
|
|
TT_ABSOLUTE, /**< timer that runs at a specific time */
|
|
TT_RELATIVE, /**< timer that runs so many seconds in the future */
|
|
TT_PERIODIC /**< timer that runs periodically */
|
|
};
|
|
|
|
/** Type of event that generated a callback. */
|
|
enum EventType {
|
|
ET_READ, /**< Readable event detected */
|
|
ET_WRITE, /**< Writable event detected */
|
|
ET_ACCEPT, /**< Connection can be accepted */
|
|
ET_CONNECT, /**< Connection completed */
|
|
ET_EOF, /**< End-of-file on connection */
|
|
ET_ERROR, /**< Error condition detected */
|
|
ET_SIGNAL, /**< A signal was received */
|
|
ET_EXPIRE, /**< A timer expired */
|
|
ET_DESTROY /**< The generator is being destroyed */
|
|
};
|
|
|
|
/** Common header for event generators. */
|
|
struct GenHeader {
|
|
struct GenHeader* gh_next; /**< linked list of generators */
|
|
struct GenHeader** gh_prev_p; /**< previous pointer to this generator */
|
|
#ifdef IRCD_THREADED
|
|
struct GenHeader* gh_qnext; /**< linked list of generators in queue */
|
|
struct GenHeader** gh_qprev_p; /**< previous pointer to this generator */
|
|
struct Event* gh_head; /**< head of event queue */
|
|
struct Event* gh_tail; /**< tail of event queue */
|
|
#endif
|
|
unsigned int gh_flags; /**< generator flags */
|
|
unsigned int gh_ref; /**< reference count */
|
|
EventCallBack gh_call; /**< generator callback function */
|
|
void* gh_data; /**< extra data */
|
|
union {
|
|
void* ed_ptr; /**< engine data as pointer */
|
|
int ed_int; /**< engine data as integer */
|
|
} gh_engdata;/**< engine data */
|
|
};
|
|
|
|
#define GEN_DESTROY 0x0001 /**< generator is to be destroyed */
|
|
#define GEN_MARKED 0x0002 /**< generator is marked for destruction */
|
|
#define GEN_ACTIVE 0x0004 /**< generator is active */
|
|
#define GEN_READD 0x0008 /**< generator (timer) must be re-added */
|
|
#define GEN_ERROR 0x0010 /**< an error occurred on the generator */
|
|
|
|
/** Socket event generator.
|
|
* Note: The socket state overrides the socket event mask; that is, if
|
|
* it's an SS_CONNECTING socket, the engine selects its own definition
|
|
* of what that looks like and ignores s_events. s_events is meaningful
|
|
* only for SS_CONNECTED, SS_DATAGRAM, and SS_CONNECTDG, but may be set
|
|
* prior to the state transition, if desired.
|
|
*/
|
|
struct Socket {
|
|
struct GenHeader s_header; /**< generator information */
|
|
enum SocketState s_state; /**< state socket's in */
|
|
unsigned int s_events; /**< events socket is interested in */
|
|
int s_fd; /**< file descriptor for socket */
|
|
#ifdef USE_SSL
|
|
SSL* ssl; /**< if not NULL, use SSL routines on socket */
|
|
#endif /* USE_SSL */
|
|
};
|
|
|
|
#define SOCK_EVENT_READABLE 0x0001 /**< interested in readable */
|
|
#define SOCK_EVENT_WRITABLE 0x0002 /**< interested in writable */
|
|
|
|
/** Bitmask of possible event interests for a socket. */
|
|
#define SOCK_EVENT_MASK (SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE)
|
|
|
|
#define SOCK_ACTION_SET 0x0000 /**< set interest set as follows */
|
|
#define SOCK_ACTION_ADD 0x1000 /**< add to interest set */
|
|
#define SOCK_ACTION_DEL 0x2000 /**< remove from interest set */
|
|
|
|
#define SOCK_ACTION_MASK 0x3000 /**< mask out the actions */
|
|
|
|
/** Retrieve state of the Socket \a sock. */
|
|
#define s_state(sock) ((sock)->s_state)
|
|
/** Retrieve interest mask of the Socket \a sock. */
|
|
#define s_events(sock) ((sock)->s_events)
|
|
/** Retrieve file descriptor of the Socket \a sock. */
|
|
#define s_fd(sock) ((sock)->s_fd)
|
|
/** Retrieve user data pointer of the Socket \a sock. */
|
|
#define s_data(sock) ((sock)->s_header.gh_data)
|
|
/** Retrieve engine data integer of the Socket \a sock. */
|
|
#define s_ed_int(sock) ((sock)->s_header.gh_engdata.ed_int)
|
|
/** Retrieve engine data pointer of the Socket \a sock. */
|
|
#define s_ed_ptr(sock) ((sock)->s_header.gh_engdata.ed_ptr)
|
|
/** Retrieve whether the Socket \a sock is active. */
|
|
#define s_active(sock) ((sock)->s_header.gh_flags & GEN_ACTIVE)
|
|
|
|
/** Signal event generator. */
|
|
struct Signal {
|
|
struct GenHeader sig_header; /**< generator information */
|
|
int sig_signal; /**< signal number */
|
|
};
|
|
|
|
/** Retrieve signal number of the Signal \a sig. */
|
|
#define sig_signal(sig) ((sig)->sig_signal)
|
|
/** Retrieve user data pointer of the Signal \a sig. */
|
|
#define sig_data(sig) ((sig)->sig_header.gh_data)
|
|
/** Retrieve engine data integer of the Signal \a sig. */
|
|
#define sig_ed_int(sig) ((sig)->sig_header.gh_engdata.ed_int)
|
|
/** Retrieve engine data pointer of the Signal \a sig. */
|
|
#define sig_ed_ptr(sig) ((sig)->sig_header.gh_engdata.ed_ptr)
|
|
/** Retrieve whether the Signal \a sig is active. */
|
|
#define sig_active(sig) ((sig)->sig_header.gh_flags & GEN_ACTIVE)
|
|
|
|
/** Timer event generator. */
|
|
struct Timer {
|
|
struct GenHeader t_header; /**< generator information */
|
|
enum TimerType t_type; /**< what type of timer this is */
|
|
time_t t_value; /**< value timer was added with */
|
|
time_t t_expire; /**< time at which timer expires */
|
|
};
|
|
|
|
/** Retrieve type of the Timer \a tim. */
|
|
#define t_type(tim) ((tim)->t_type)
|
|
/** Retrieve interval of the Timer \a tim. */
|
|
#define t_value(tim) ((tim)->t_value)
|
|
/** Retrieve expiration time of the Timer \a tim. */
|
|
#define t_expire(tim) ((tim)->t_expire)
|
|
/** Retrieve user data pointer of the Timer \a tim. */
|
|
#define t_data(tim) ((tim)->t_header.gh_data)
|
|
/** Retrieve engine data integer of the Timer \a tim. */
|
|
#define t_ed_int(tim) ((tim)->t_header.gh_engdata.ed_int)
|
|
/** Retrieve engine data pointer of the Timer \a tim. */
|
|
#define t_ed_ptr(tim) ((tim)->t_header.gh_engdata.ed_ptr)
|
|
/** Retrieve whether the Timer \a tim is active. */
|
|
#define t_active(tim) ((tim)->t_header.gh_flags & GEN_ACTIVE)
|
|
/** Retrieve whether the Timer \a tim is enqueued. */
|
|
#define t_onqueue(tim) ((tim)->t_header.gh_prev_p)
|
|
|
|
/** Event activity descriptor. */
|
|
struct Event {
|
|
struct Event* ev_next; /**< linked list of events on queue */
|
|
struct Event** ev_prev_p; /**< previous pointer to this event */
|
|
enum EventType ev_type; /**< Event type */
|
|
int ev_data; /**< extra data, like errno value */
|
|
union {
|
|
struct GenHeader* gen_header; /**< Generator header */
|
|
struct Socket* gen_socket; /**< Socket generating event */
|
|
struct Signal* gen_signal; /**< Signal generating event */
|
|
struct Timer* gen_timer; /**< Timer generating event */
|
|
} ev_gen; /**< object generating event */
|
|
};
|
|
|
|
/** Retrieve the type of the Event \a ev. */
|
|
#define ev_type(ev) ((ev)->ev_type)
|
|
/** Retrieve the extra data of the Event \a ev. */
|
|
#define ev_data(ev) ((ev)->ev_data)
|
|
/** Retrieve the Socket that generated the Event \a ev. */
|
|
#define ev_socket(ev) ((ev)->ev_gen.gen_socket)
|
|
/** Retrieve the Signal that generated the Event \a ev. */
|
|
#define ev_signal(ev) ((ev)->ev_gen.gen_signal)
|
|
/** Retrieve the Timer that generated the Event \a ev. */
|
|
#define ev_timer(ev) ((ev)->ev_gen.gen_timer)
|
|
|
|
/** List of all event generators. */
|
|
struct Generators {
|
|
struct GenHeader* g_socket; /**< list of socket generators */
|
|
struct GenHeader* g_signal; /**< list of signal generators */
|
|
struct GenHeader* g_timer; /**< list of timer generators */
|
|
};
|
|
|
|
/** Returns 1 if successfully initialized, 0 if not.
|
|
* @param[in] max_sockets Number of sockets to support.
|
|
*/
|
|
typedef int (*EngineInit)(int max_sockets);
|
|
|
|
/** Tell engine about new signal.
|
|
* @param[in] sig Signal event generator to add.
|
|
*/
|
|
typedef void (*EngineSignal)(struct Signal* sig);
|
|
|
|
/** Tell engine about new socket.
|
|
* @param[in] sock Socket event generator to add.
|
|
*/
|
|
typedef int (*EngineAdd)(struct Socket* sock);
|
|
|
|
/** Tell engine about socket's new_state.
|
|
* @param[in] sock Socket whose state is changing.
|
|
* @param[in] new_state New state for socket.
|
|
*/
|
|
typedef void (*EngineState)(struct Socket* sock, enum SocketState new_state);
|
|
|
|
/** Tell engine about socket's new event interests.
|
|
* @param[in] sock Socket whose interest mask is changing.
|
|
* @param[in] new_events New event mask to set (not SOCK_ACTION_ADD or SOCK_ACTION_DEL).
|
|
*/
|
|
typedef void (*EngineEvents)(struct Socket* sock, unsigned int new_events);
|
|
|
|
/** Tell engine a socket is going away.
|
|
* @param[in] sock Socket being destroyed.
|
|
*/
|
|
typedef void (*EngineDelete)(struct Socket* sock);
|
|
|
|
/** The actual event loop.
|
|
* @param[in] gens List of event generators.
|
|
*/
|
|
typedef void (*EngineLoop)(struct Generators* gens);
|
|
|
|
/** Structure for an event engine to describe itself. */
|
|
struct Engine {
|
|
const char* eng_name; /**< a name for the engine */
|
|
EngineInit eng_init; /**< initialize engine */
|
|
EngineSignal eng_signal; /**< express interest in a signal (may be NULL) */
|
|
EngineAdd eng_add; /**< express interest in a socket */
|
|
EngineState eng_state; /**< mention a change in state to engine */
|
|
EngineEvents eng_events; /**< express interest in socket events */
|
|
EngineDelete eng_closing; /**< socket is being closed */
|
|
EngineLoop eng_loop; /**< actual event loop */
|
|
};
|
|
|
|
/** Increment the reference count of \a gen. */
|
|
#define gen_ref_inc(gen) (((struct GenHeader*) (gen))->gh_ref++)
|
|
/** Decrement the reference count of \a gen. */
|
|
#define gen_ref_dec(gen) \
|
|
do { \
|
|
struct GenHeader* _gen = (struct GenHeader*) (gen); \
|
|
if (!--_gen->gh_ref && (_gen->gh_flags & GEN_DESTROY)) { \
|
|
gen_dequeue(_gen); \
|
|
event_generate(ET_DESTROY, _gen, 0); \
|
|
} \
|
|
} while (0)
|
|
/** Clear the error flag for \a gen. */
|
|
#define gen_clear_error(gen) \
|
|
(((struct GenHeader*) (gen))->gh_flags &= ~GEN_ERROR)
|
|
|
|
void gen_dequeue(void* arg);
|
|
|
|
void event_init(int max_sockets);
|
|
void event_loop(void);
|
|
void event_generate(enum EventType type, void* arg, int data);
|
|
|
|
struct Timer* timer_init(struct Timer* timer);
|
|
void timer_add(struct Timer* timer, EventCallBack call, void* data,
|
|
enum TimerType type, time_t value);
|
|
void timer_del(struct Timer* timer);
|
|
void timer_chg(struct Timer* timer, enum TimerType type, time_t value);
|
|
void timer_run(void);
|
|
/** Retrieve the next timer's expiration time from Generators \a gen. */
|
|
#define timer_next(gen) ((gen)->g_timer ? ((struct Timer*)(gen)->g_timer)->t_expire : 0)
|
|
|
|
void signal_add(struct Signal* signal, EventCallBack call, void* data,
|
|
int sig);
|
|
|
|
int socket_add(struct Socket* sock, EventCallBack call, void* data,
|
|
enum SocketState state, unsigned int events, int fd);
|
|
void socket_del(struct Socket* sock);
|
|
void socket_state(struct Socket* sock, enum SocketState state);
|
|
void socket_events(struct Socket* sock, unsigned int events);
|
|
|
|
const char* engine_name(void);
|
|
|
|
#ifdef DEBUGMODE
|
|
/* These routines pretty-print names for states and types for debug printing */
|
|
|
|
const char* state_to_name(enum SocketState state);
|
|
const char* timer_to_name(enum TimerType type);
|
|
const char* event_to_name(enum EventType type);
|
|
const char* gen_flags(unsigned int flags);
|
|
const char* sock_flags(unsigned int flags);
|
|
|
|
#endif /* DEBUGMODE */
|
|
|
|
#endif /* INCLUDED_ircd_events_h */
|