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