Author: Kev <klmitch@mit.edu>
[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
86 struct Socket {
87   struct GenHeader s_header;    /* generator information */
88   enum SocketState s_state;     /* state socket's in */
89   unsigned int     s_events;    /* events socket is interested in */
90   int              s_fd;        /* file descriptor for socket */
91 };
92
93 #define SOCK_EVENT_READABLE     0x0001  /* interested in readable */
94 #define SOCK_EVENT_WRITABLE     0x0002  /* interested in writable */
95
96 #define SOCK_EVENT_MASK         (SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE)
97
98 #define SOCK_ACTION_SET         0x0000  /* set interest set as follows */
99 #define SOCK_ACTION_ADD         0x1000  /* add to interest set */
100 #define SOCK_ACTION_DEL         0x2000  /* remove from interest set */
101
102 #define SOCK_ACTION_MASK        0x3000  /* mask out the actions */
103
104 #define s_state(sock)   ((sock)->s_state)
105 #define s_events(sock)  ((sock)->s_events)
106 #define s_fd(sock)      ((sock)->s_fd)
107 #define s_data(sock)    ((sock)->s_header.gh_data)
108 #define s_ed_int(sock)  ((sock)->s_header.gh_engdata.ed_int)
109 #define s_ed_ptr(sock)  ((sock)->s_header.gh_engdata.ed_ptr)
110 #define s_active(sock)  ((sock)->s_header.gh_flags & GEN_ACTIVE)
111
112 /* Note: The socket state overrides the socket event mask; that is, if
113  * it's an SS_CONNECTING socket, the engine selects its own definition
114  * of what that looks like and ignores s_events.  s_events is meaningful
115  * only for SS_CONNECTED, SS_DATAGRAM, and SS_CONNECTDG, but may be set
116  * prior to the state transition, if desired.
117  */
118
119 struct Signal {
120   struct GenHeader sig_header;  /* generator information */
121   int              sig_signal;  /* signal number */
122 };
123
124 #define sig_signal(sig) ((sig)->sig_signal)
125 #define sig_data(sig)   ((sig)->sig_header.gh_data)
126 #define sig_ed_int(sig) ((sig)->sig_header.gh_engdata.ed_int)
127 #define sig_ed_ptr(sig) ((sig)->sig_header.gh_engdata.ed_ptr)
128 #define sig_active(sig) ((sig)->sig_header.gh_flags & GEN_ACTIVE)
129
130 struct Timer {
131   struct GenHeader t_header;    /* generator information */
132   enum TimerType   t_type;      /* what type of timer this is */
133   time_t           t_value;     /* value timer was added with */
134   time_t           t_expire;    /* time at which timer expires */
135 };
136
137 #define t_type(tim)     ((tim)->t_type)
138 #define t_value(tim)    ((tim)->t_value)
139 #define t_expire(tim)   ((tim)->t_expire)
140 #define t_data(tim)     ((tim)->t_header.gh_data)
141 #define t_ed_int(tim)   ((tim)->t_header.gh_engdata.ed_int)
142 #define t_ed_ptr(tim)   ((tim)->t_header.gh_engdata.ed_ptr)
143 #define t_active(tim)   ((tim)->t_header.gh_flags & GEN_ACTIVE)
144
145 struct Event {
146   struct Event*  ev_next;       /* linked list of events on queue */
147   struct Event** ev_prev_p;
148   enum EventType ev_type;       /* Event type */
149   int            ev_data;       /* extra data, like errno value */
150   union {
151     struct GenHeader* gen_header;       /* Generator header */
152     struct Socket*    gen_socket;       /* Socket generating event */
153     struct Signal*    gen_signal;       /* Signal generating event */
154     struct Timer*     gen_timer;        /* Timer generating event */
155   }              ev_gen;        /* object generating event */
156 };
157
158 #define ev_type(ev)     ((ev)->ev_type)
159 #define ev_data(ev)     ((ev)->ev_data)
160 #define ev_socket(ev)   ((ev)->ev_gen.gen_socket)
161 #define ev_signal(ev)   ((ev)->ev_gen.gen_signal)
162 #define ev_timer(ev)    ((ev)->ev_gen.gen_timer)
163
164 struct Generators {
165   struct Socket* g_socket;      /* list of socket generators */
166   struct Signal* g_signal;      /* list of signal generators */
167   struct Timer*  g_timer;       /* list of timer generators */
168 };
169
170 /* returns 1 if successfully initialized, 0 if not */
171 typedef int (*EngineInit)(int);
172
173 /* Tell engine about new signal; set to 0 if engine doesn't know signals */
174 typedef void (*EngineSignal)(struct Signal*);
175
176 /* Tell engine about new socket */
177 typedef int (*EngineAdd)(struct Socket*);
178
179 /* Tell engine about socket's new_state */
180 typedef void (*EngineState)(struct Socket*, enum SocketState new_state);
181
182 /* Tell engine about socket's new_events */
183 typedef void (*EngineEvents)(struct Socket*, unsigned int new_events);
184
185 /* Tell engine a socket's going away */
186 typedef void (*EngineDelete)(struct Socket*);
187
188 /* The actual event loop */
189 typedef void (*EngineLoop)(struct Generators*);
190
191 struct Engine {
192   const char*   eng_name;       /* a name for the engine */
193   EngineInit    eng_init;       /* initialize engine */
194   EngineSignal  eng_signal;     /* express interest in a signal */
195   EngineAdd     eng_add;        /* express interest in a socket */
196   EngineState   eng_state;      /* mention a change in state to engine */
197   EngineEvents  eng_events;     /* express interest in socket events */
198   EngineDelete  eng_closing;    /* socket is being closed */
199   EngineLoop    eng_loop;       /* actual event loop */
200 };
201
202 #define gen_ref_inc(gen)        (((struct GenHeader*) (gen))->gh_ref++)
203 #define gen_ref_dec(gen)                                                      \
204 do {                                                                          \
205   struct GenHeader* _gen = (struct GenHeader*) (gen);                         \
206   if (!--_gen->gh_ref && (_gen->gh_flags & GEN_DESTROY)) {                    \
207     gen_dequeue(_gen);                                                        \
208     event_generate(ET_DESTROY, _gen, 0);                                      \
209   }                                                                           \
210 } while (0)
211
212 void gen_dequeue(void* arg);
213
214 void event_init(int max_sockets);
215 void event_loop(void);
216 void event_generate(enum EventType type, void* arg, int data);
217
218 void timer_add(struct Timer* timer, EventCallBack call, void* data,
219                enum TimerType type, time_t value);
220 void timer_del(struct Timer* timer);
221 void timer_chg(struct Timer* timer, enum TimerType type, time_t value);
222 void timer_run(void);
223 #define timer_next(gen) ((gen)->g_timer ? (gen)->g_timer->t_expire : 0)
224
225 void signal_add(struct Signal* signal, EventCallBack call, void* data,
226                 int sig);
227
228 int socket_add(struct Socket* sock, EventCallBack call, void* data,
229                enum SocketState state, unsigned int events, int fd);
230 void socket_del(struct Socket* sock);
231 void socket_state(struct Socket* sock, enum SocketState state);
232 void socket_events(struct Socket* sock, unsigned int events);
233
234 const char* engine_name(void);
235
236 #ifdef DEBUGMODE
237 /* These routines pretty-print names for states and types for debug printing */
238
239 const char* state_to_name(enum SocketState state);
240 const char* timer_to_name(enum TimerType type);
241 const char* event_to_name(enum EventType type);
242 const char* gen_flags(unsigned int flags);
243 const char* sock_flags(unsigned int flags);
244
245 #endif /* DEBUGMODE */
246
247 #endif /* INCLUDED_ircd_events_h */