]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/socketengine.h
ce701beff4a14ac3f510737ecc42bc19c2467987
[user/henk/code/inspircd.git] / include / socketengine.h
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #ifndef __SOCKETENGINE__
15 #define __SOCKETENGINE__
16
17 #include <vector>
18 #include <string>
19 #include <map>
20 #include "inspircd_config.h"
21 #include "base.h"
22
23 /** Types of event an EventHandler may receive.
24  * EVENT_READ is a readable file descriptor,
25  * and EVENT_WRITE is a writeable file descriptor.
26  * EVENT_ERROR can always occur, and indicates
27  * a write error or read error on the socket,
28  * e.g. EOF condition or broken pipe.
29  */
30 enum EventType
31 {
32         /** Read event */
33         EVENT_READ      =       0,
34         /** Write event */
35         EVENT_WRITE     =       1,
36         /** Error event */
37         EVENT_ERROR     =       2
38 };
39
40 class InspIRCd;
41
42 /** This class is a basic I/O handler class.
43  * Any object which wishes to receive basic I/O events
44  * from the socketengine must derive from this class and
45  * implement the HandleEvent() method. The derived class
46  * must then be added to SocketEngine using the method
47  * SocketEngine::AddFd(), after which point the derived
48  * class will receive events to its HandleEvent() method.
49  * The derived class should also implement one of Readable()
50  * and Writeable(). In the current implementation, only
51  * Readable() is used. If this returns true, the socketengine
52  * inserts a readable socket. If it is false, the socketengine
53  * inserts a writeable socket. The derived class should never
54  * change the value this function returns without first
55  * deleting the socket from the socket engine. The only
56  * requirement beyond this for an event handler is that it
57  * must have a file descriptor. What this file descriptor
58  * is actually attached to is completely up to you.
59  */
60 class CoreExport EventHandler : public Extensible
61 {
62  protected:
63         /** File descriptor.
64          * All events which can be handled
65          * must have a file descriptor.
66          * This allows you to add events for
67          * sockets, fifo's, pipes, and various
68          * other forms of IPC.
69          */
70         int fd;
71  public:
72         /** Get the current file descriptor
73          * @return The file descriptor of this handler
74          */
75         int GetFd();
76
77         /** Set a new file desciptor
78          * @param FD The new file descriptor. Do not
79          * call this method without first deleting the
80          * object from the SocketEngine if you have
81          * added it to a SocketEngine instance.
82          */
83         void SetFd(int FD);
84
85         /** Constructor
86          */
87         EventHandler() {}
88
89         /** Destructor
90          */
91         virtual ~EventHandler() {}
92
93         /** Override this function to indicate readability.
94          * @return This should return true if the function
95          * wishes to receive EVENT_READ events. Do not change
96          * what this function returns while the event handler
97          * is still added to a SocketEngine instance!
98          * If this function is unimplemented, the base class
99          * will return true.
100          *
101          * NOTE: You cannot set both Readable() and
102          * Writeable() to true. If you wish to receive
103          * a write event for your object, you must call
104          * SocketEngine::WantWrite() instead. This will
105          * trigger your objects next EVENT_WRITE type event.
106          */
107         virtual bool Readable();
108
109         /** Override this function to indicate writeability.
110          * @return This should return true if the function
111          * wishes to receive EVENT_WRITE events. Do not change
112          * what this function returns while the event handler
113          * is still added to a SocketEngine instance!
114          * If this function is unimplemented, the base class
115          * will return false.
116          *
117          * NOTE: You cannot set both Readable() and
118          * Writeable() to true. If you wish to receive
119          * a write event for your object, you must call
120          * SocketEngine::WantWrite() instead. This will
121          * trigger your objects next EVENT_WRITE type event.
122          */
123         virtual bool Writeable();
124
125         /** Process an I/O event.
126          * You MUST implement this function in your derived
127          * class, and it will be called whenever read or write
128          * events are received, depending on what your functions
129          * Readable() and Writeable() returns and wether you
130          * previously made a call to SocketEngine::WantWrite().
131          * @param et either one of EVENT_READ for read events,
132          * and EVENT_WRITE for write events.
133          */
134         virtual void HandleEvent(EventType et, int errornum = 0) = 0;
135
136 #ifdef WINDOWS
137
138         /** "Fake" file descriptor. This is windows-specific.
139          */
140         int m_internalFd;
141
142         /** Pointer to read event. We delete this so the buffer can't be used
143          * after the socket is deleted, and so it doesn't leak memory
144          */
145         void* m_readEvent;
146         /** Pointer to a write event.
147          */
148         void* m_writeEvent;
149         /** Pointer to an accept event.
150          */
151         void* m_acceptEvent;
152
153 #endif
154 };
155
156 /** Provides basic file-descriptor-based I/O support.
157  * The actual socketengine class presents the
158  * same interface on all operating systems, but
159  * its private members and internal behaviour
160  * should be treated as blackboxed, and vary
161  * from system to system and upon the config
162  * settings chosen by the server admin. The current
163  * version supports select, epoll and kqueue.
164  * The configure script will enable a socket engine
165  * based upon what OS is detected, and will derive
166  * a class from SocketEngine based upon what it finds.
167  * The derived classes file will also implement a
168  * classfactory, SocketEngineFactory, which will
169  * create a derived instance of SocketEngine using
170  * polymorphism so that the core and modules do not
171  * have to be aware of which SocketEngine derived
172  * class they are using.
173  */
174 class CoreExport SocketEngine : public Extensible
175 {
176 protected:
177         /** Owner/Creator
178          */
179         InspIRCd* ServerInstance;
180         /** Handle to socket engine, where needed.
181          */
182         int EngineHandle;
183         /** Current number of descriptors in the engine
184          */
185         int CurrentSetSize;
186         /** Reference table, contains all current handlers
187          */
188         EventHandler* ref[MAX_DESCRIPTORS];
189 public:
190
191         /** Constructor.
192          * The constructor transparently initializes
193          * the socket engine which the ircd is using.
194          * Please note that if there is a catastrophic
195          * failure (for example, you try and enable
196          * epoll on a 2.4 linux kernel) then this
197          * function may bail back to the shell.
198          * @param Instance The creator/owner of this object
199          */
200         SocketEngine(InspIRCd* Instance);
201
202         /** Destructor.
203          * The destructor transparently tidies up
204          * any resources used by the socket engine.
205          */
206         virtual ~SocketEngine();
207
208         /** Add an EventHandler object to the engine.
209          * Use AddFd to add a file descriptor to the
210          * engine and have the socket engine monitor
211          * it. You must provide an object derived from
212          * EventHandler which implements HandleEvent()
213          * and optionally Readable() and Writeable().
214          * @param eh An event handling object to add
215          */
216         virtual bool AddFd(EventHandler* eh);
217
218         /** If you call this function and pass it an
219          * event handler, that event handler will
220          * receive the next available write event,
221          * even if the socket is a readable socket only.
222          * Developers should avoid constantly keeping
223          * an eventhandler in the writeable state,
224          * as this will consume large amounts of
225          * CPU time.
226          * @param eh An event handler which wants to
227          * receive the next writeability event.
228          */
229         virtual void WantWrite(EventHandler* eh);
230
231         /** Returns the maximum number of file descriptors
232          * you may store in the socket engine at any one time.
233          * @return The maximum fd value
234          */
235         virtual int GetMaxFds();
236
237         /** Returns the number of file descriptor slots
238          * which are available for storing fds.
239          * @return The number of remaining fd's
240          */
241         virtual int GetRemainingFds();
242
243         /** Delete an event handler from the engine.
244          * This function call deletes an EventHandler
245          * from the engine, returning true if it succeeded
246          * and false if it failed. This does not free the
247          * EventHandler pointer using delete, if this is
248          * required you must do this yourself.
249          * Note on forcing deletes. DO NOT DO THIS! This is
250          * extremely dangerous and will most likely render the
251          * socketengine dead. This was added only for handling
252          * very rare cases where broken 3rd party libs destroys
253          * the OS socket beyond our control. If you can't explain
254          * in minute details why forcing is absolutely necessary
255          * then you don't need it. That was a NO!
256          * @param eh The event handler object to remove
257          * @param force *DANGEROUS* See method description!
258          * @return True if the event handler was removed
259          */
260         virtual bool DelFd(EventHandler* eh, bool force = false);
261
262         /** Returns true if a file descriptor exists in
263          * the socket engine's list.
264          * @param fd The event handler to look for
265          * @return True if this fd has an event handler
266          */
267         virtual bool HasFd(int fd);
268
269         /** Returns the EventHandler attached to a specific fd.
270          * If the fd isnt in the socketengine, returns NULL.
271          * @param fd The event handler to look for
272          * @return A pointer to the event handler, or NULL
273          */
274         virtual EventHandler* GetRef(int fd);
275
276         /** Waits for events and dispatches them to handlers.
277          * Please note that this doesnt wait long, only
278          * a couple of milliseconds. It returns the number of
279          * events which occured during this call.
280          * This method will dispatch events to their handlers
281          * by calling their EventHandler::HandleEvent()
282          * methods with the neccessary EventType value.
283          * @return The number of events which have occured.
284          */
285         virtual int DispatchEvents();
286
287         /** Returns the socket engines name.
288          * This returns the name of the engine for use
289          * in /VERSION responses.
290          * @return The socket engine name
291          */
292         virtual std::string GetName();
293 };
294
295 #endif
296