Author: Ghostwolf <foxxe@wtfs.net>
[ircu2.10.12-pk.git] / include / ircd_events.h
1 #ifndef INCLUDED_ircd_events_h
2 #define INCLUDED_ircd_events_h
3 /*
4  * IRC - Internet Relay Chat, include/ircd_events.h
5  * Copyright (C) 2001 Kevin L. Mitchell <klmitch@mit.edu>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * $Id$
22  */
23
24 #ifndef INCLUDED_config_h
25 #include "config.h"
26 #endif
27 #ifndef INCLUDED_sys_types_h
28 #include <sys/types.h>  /* time_t */
29 #define INCLUDED_sys_types_h
30 #endif
31
32 struct Event;
33
34 typedef void (*EventCallBack)(struct Event*);
35
36 enum SocketState {
37   SS_CONNECTING,        /* Connection in progress on socket */
38   SS_LISTENING,         /* Socket is a listening socket */
39   SS_CONNECTED,         /* Socket is a connected socket */
40   SS_DATAGRAM,          /* Socket is a datagram socket */
41   SS_CONNECTDG,         /* Socket is a connected datagram socket */
42   SS_NOTSOCK            /* Socket isn't a socket at all */
43 };
44
45 enum TimerType {
46   TT_ABSOLUTE,          /* timer that runs at a specific time */
47   TT_RELATIVE,          /* timer that runs so many seconds in the future */
48   TT_PERIODIC           /* timer that runs periodically */
49 };
50
51 enum EventType {
52   ET_READ,              /* Readable event detected */
53   ET_WRITE,             /* Writable event detected */
54   ET_ACCEPT,            /* Connection can be accepted */
55   ET_CONNECT,           /* Connection completed */
56   ET_EOF,               /* End-of-file on connection */
57   ET_ERROR,             /* Error condition detected */
58   ET_SIGNAL,            /* A signal was received */
59   ET_EXPIRE,            /* A timer expired */
60   ET_DESTROY            /* The generator is being destroyed */
61 };
62
63 struct GenHeader {
64   struct GenHeader*  gh_next;   /* linked list of generators */
65   struct GenHeader** gh_prev_p;
66 #ifdef IRCD_THREADED
67   struct GenHeader*  gh_qnext;  /* linked list of generators in queue */
68   struct GenHeader** gh_qprev_p;
69   struct Event*      gh_head;   /* head of event queue */
70   struct Event*      gh_tail;   /* tail of event queue */
71 #endif
72   unsigned int       gh_flags;  /* generator flags */
73   unsigned int       gh_ref;    /* reference count */
74   EventCallBack      gh_call;   /* generator callback function */
75   void*              gh_data;   /* extra data */
76   union {
77     void*            ed_ptr;    /* engine data == pointer */
78     int              ed_int;    /* engine data == integer */
79   }                  gh_engdata;/* engine data */
80 };
81
82 #define GEN_DESTROY     0x0001  /* generator is to be destroyed */
83 #define GEN_MARKED      0x0002  /* generator is marked for destruction */
84 #define GEN_ACTIVE      0x0004  /* generator is active */
85 #define GEN_READD       0x0008  /* generator (timer) must be re-added */
86 #define GEN_ERROR       0x0010  /* an error occurred on the generator */
87
88 struct Socket {
89   struct GenHeader s_header;    /* generator information */
90   enum SocketState s_state;     /* state socket's in */
91   unsigned int     s_events;    /* events socket is interested in */
92   int              s_fd;        /* file descriptor for socket */
93 };
94
95 #define SOCK_EVENT_READABLE     0x0001  /* interested in readable */
96 #define SOCK_EVENT_WRITABLE     0x0002  /* interested in writable */
97
98 #define SOCK_EVENT_MASK         (SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE)
99
100 #define SOCK_ACTION_SET         0x0000  /* set interest set as follows */
101 #define SOCK_ACTION_ADD         0x1000  /* add to interest set */
102 #define SOCK_ACTION_DEL         0x2000  /* remove from interest set */
103
104 #define SOCK_ACTION_MASK        0x3000  /* mask out the actions */
105
106 #define s_state(sock)   ((sock)->s_state)
107 #define s_events(sock)  ((sock)->s_events)
108 #define s_fd(sock)      ((sock)->s_fd)
109 #define s_data(sock)    ((sock)->s_header.gh_data)
110 #define s_ed_int(sock)  ((sock)->s_header.gh_engdata.ed_int)
111 #define s_ed_ptr(sock)  ((sock)->s_header.gh_engdata.ed_ptr)
112 #define s_active(sock)  ((sock)->s_header.gh_flags & GEN_ACTIVE)
113
114 /* Note: The socket state overrides the socket event mask; that is, if
115  * it's an SS_CONNECTING socket, the engine selects its own definition
116  * of what that looks like and ignores s_events.  s_events is meaningful
117  * only for SS_CONNECTED, SS_DATAGRAM, and SS_CONNECTDG, but may be set
118  * prior to the state transition, if desired.
119  */
120
121 struct Signal {
122   struct GenHeader sig_header;  /* generator information */
123   int              sig_signal;  /* signal number */
124 };
125
126 #define sig_signal(sig) ((sig)->sig_signal)
127 #define sig_data(sig)   ((sig)->sig_header.gh_data)
128 #define sig_ed_int(sig) ((sig)->sig_header.gh_engdata.ed_int)
129 #define sig_ed_ptr(sig) ((sig)->sig_header.gh_engdata.ed_ptr)
130 #define sig_active(sig) ((sig)->sig_header.gh_flags & GEN_ACTIVE)
131
132 struct Timer {
133   struct GenHeader t_header;    /* generator information */
134   enum TimerType   t_type;      /* what type of timer this is */
135   time_t           t_value;     /* value timer was added with */
136   time_t           t_expire;    /* time at which timer expires */
137 };
138
139 #define t_type(tim)     ((tim)->t_type)
140 #define t_value(tim)    ((tim)->t_value)
141 #define t_expire(tim)   ((tim)->t_expire)
142 #define t_data(tim)     ((tim)->t_header.gh_data)
143 #define t_ed_int(tim)   ((tim)->t_header.gh_engdata.ed_int)
144 #define t_ed_ptr(tim)   ((tim)->t_header.gh_engdata.ed_ptr)
145 #define t_active(tim)   ((tim)->t_header.gh_flags & GEN_ACTIVE)
146 #define t_onqueue(tim)  ((tim)->t_header.gh_prev_p)
147
148 struct Event {
149   struct Event*  ev_next;       /* linked list of events on queue */
150   struct Event** ev_prev_p;
151   enum EventType ev_type;       /* Event type */
152   int            ev_data;       /* extra data, like errno value */
153   union {
154     struct GenHeader* gen_header;       /* Generator header */
155     struct Socket*    gen_socket;       /* Socket generating event */
156     struct Signal*    gen_signal;       /* Signal generating event */
157     struct Timer*     gen_timer;        /* Timer generating event */
158   }              ev_gen;        /* object generating event */
159 };
160
161 #define ev_type(ev)     ((ev)->ev_type)
162 #define ev_data(ev)     ((ev)->ev_data)
163 #define ev_socket(ev)   ((ev)->ev_gen.gen_socket)
164 #define ev_signal(ev)   ((ev)->ev_gen.gen_signal)
165 #define ev_timer(ev)    ((ev)->ev_gen.gen_timer)
166
167 struct Generators {
168   struct Socket* g_socket;      /* list of socket generators */
169   struct Signal* g_signal;      /* list of signal generators */
170   struct Timer*  g_timer;       /* list of timer generators */
171 };
172
173 /* returns 1 if successfully initialized, 0 if not */
174 typedef int (*EngineInit)(int);
175
176 /* Tell engine about new signal; set to 0 if engine doesn't know signals */
177 typedef void (*EngineSignal)(struct Signal*);
178
179 /* Tell engine about new socket */
180 typedef int (*EngineAdd)(struct Socket*);
181
182 /* Tell engine about socket's new_state */
183 typedef void (*EngineState)(struct Socket*, enum SocketState new_state);
184
185 /* Tell engine about socket's new_events */
186 typedef void (*EngineEvents)(struct Socket*, unsigned int new_events);
187
188 /* Tell engine a socket's going away */
189 typedef void (*EngineDelete)(struct Socket*);
190
191 /* The actual event loop */
192 typedef void (*EngineLoop)(struct Generators*);
193
194 struct Engine {
195   const char*   eng_name;       /* a name for the engine */
196   EngineInit    eng_init;       /* initialize engine */
197   EngineSignal  eng_signal;     /* express interest in a signal */
198   EngineAdd     eng_add;        /* express interest in a socket */
199   EngineState   eng_state;      /* mention a change in state to engine */
200   EngineEvents  eng_events;     /* express interest in socket events */
201   EngineDelete  eng_closing;    /* socket is being closed */
202   EngineLoop    eng_loop;       /* actual event loop */
203 };
204
205 #define gen_ref_inc(gen)        (((struct GenHeader*) (gen))->gh_ref++)
206 #define gen_ref_dec(gen)                                                      \
207 do {                                                                          \
208   struct GenHeader* _gen = (struct GenHeader*) (gen);                         \
209   if (!--_gen->gh_ref && (_gen->gh_flags & GEN_DESTROY)) {                    \
210     gen_dequeue(_gen);                                                        \
211     event_generate(ET_DESTROY, _gen, 0);                                      \
212   }                                                                           \
213 } while (0)
214 #define gen_clear_error(gen)                                                  \
215         (((struct GenHeader*) (gen))->gh_flags &= ~GEN_ERROR)
216
217 void gen_dequeue(void* arg);
218
219 void event_init(int max_sockets);
220 void event_loop(void);
221 void event_generate(enum EventType type, void* arg, int data);
222
223 struct Timer* timer_init(struct Timer* timer);
224 void timer_add(struct Timer* timer, EventCallBack call, void* data,
225                enum TimerType type, time_t value);
226 void timer_del(struct Timer* timer);
227 void timer_chg(struct Timer* timer, enum TimerType type, time_t value);
228 void timer_run(void);
229 #define timer_next(gen) ((gen)->g_timer ? (gen)->g_timer->t_expire : 0)
230
231 void signal_add(struct Signal* signal, EventCallBack call, void* data,
232                 int sig);
233
234 int socket_add(struct Socket* sock, EventCallBack call, void* data,
235                enum SocketState state, unsigned int events, int fd);
236 void socket_del(struct Socket* sock);
237 void socket_state(struct Socket* sock, enum SocketState state);
238 void socket_events(struct Socket* sock, unsigned int events);
239
240 const char* engine_name(void);
241
242 #ifdef DEBUGMODE
243 /* These routines pretty-print names for states and types for debug printing */
244
245 const char* state_to_name(enum SocketState state);
246 const char* timer_to_name(enum TimerType type);
247 const char* event_to_name(enum EventType type);
248 const char* gen_flags(unsigned int flags);
249 const char* sock_flags(unsigned int flags);
250
251 #endif /* DEBUGMODE */
252
253 #endif /* INCLUDED_ircd_events_h */