]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/socketengine.h
Start moving IO hooking from being bufferedsocket based to residing in EventHandler...
[user/henk/code/inspircd.git] / include / socketengine.h
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2008 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
72         /** Pointer to the module which has hooked the given EventHandler for IO events.
73          */
74         Module *IOHook;
75  public:
76
77         /** Return the current hooker of IO events for this socket, or NULL.
78          * @return Hooker module, if set, or NULL.
79          */
80         Module *GetIOHook();
81
82         /** Set a module as hooking IO events on this socket.
83          * @param IOHooker The module hooking IO
84          * @return True if the hook could be added, false otherwise.
85          */
86         bool AddIOHook(Module *IOHooker);
87
88         /** Remove IO hooking from a module
89          * @return True if hooking was successfully removed, false otherwise.
90          */
91         bool DelIOHook();
92
93         /** Get the current file descriptor
94          * @return The file descriptor of this handler
95          */
96         int GetFd();
97
98         /** Set a new file desciptor
99          * @param FD The new file descriptor. Do not
100          * call this method without first deleting the
101          * object from the SocketEngine if you have
102          * added it to a SocketEngine instance.
103          */
104         void SetFd(int FD);
105
106         /** Constructor
107          */
108         EventHandler() {}
109
110         /** Destructor
111          */
112         virtual ~EventHandler() {}
113
114         /** Override this function to indicate readability.
115          * @return This should return true if the function
116          * wishes to receive EVENT_READ events. Do not change
117          * what this function returns while the event handler
118          * is still added to a SocketEngine instance!
119          * If this function is unimplemented, the base class
120          * will return true.
121          *
122          * NOTE: You cannot set both Readable() and
123          * Writeable() to true. If you wish to receive
124          * a write event for your object, you must call
125          * SocketEngine::WantWrite() instead. This will
126          * trigger your objects next EVENT_WRITE type event.
127          */
128         virtual bool Readable();
129
130         /** Override this function to indicate writeability.
131          * @return This should return true if the function
132          * wishes to receive EVENT_WRITE events. Do not change
133          * what this function returns while the event handler
134          * is still added to a SocketEngine instance!
135          * If this function is unimplemented, the base class
136          * will return false.
137          *
138          * NOTE: You cannot set both Readable() and
139          * Writeable() to true. If you wish to receive
140          * a write event for your object, you must call
141          * SocketEngine::WantWrite() instead. This will
142          * trigger your objects next EVENT_WRITE type event.
143          */
144         virtual bool Writeable();
145
146         /** Process an I/O event.
147          * You MUST implement this function in your derived
148          * class, and it will be called whenever read or write
149          * events are received, depending on what your functions
150          * Readable() and Writeable() returns and wether you
151          * previously made a call to SocketEngine::WantWrite().
152          * @param et either one of EVENT_READ for read events,
153          * and EVENT_WRITE for write events.
154          */
155         virtual void HandleEvent(EventType et, int errornum = 0) = 0;
156 };
157
158 /** Provides basic file-descriptor-based I/O support.
159  * The actual socketengine class presents the
160  * same interface on all operating systems, but
161  * its private members and internal behaviour
162  * should be treated as blackboxed, and vary
163  * from system to system and upon the config
164  * settings chosen by the server admin. The current
165  * version supports select, epoll and kqueue.
166  * The configure script will enable a socket engine
167  * based upon what OS is detected, and will derive
168  * a class from SocketEngine based upon what it finds.
169  * The derived classes file will also implement a
170  * classfactory, SocketEngineFactory, which will
171  * create a derived instance of SocketEngine using
172  * polymorphism so that the core and modules do not
173  * have to be aware of which SocketEngine derived
174  * class they are using.
175  */
176 class CoreExport SocketEngine : public Extensible
177 {
178 protected:
179         /** Owner/Creator
180          */
181         InspIRCd* ServerInstance;
182         /** Handle to socket engine, where needed.
183          */
184         int EngineHandle;
185         /** Current number of descriptors in the engine
186          */
187         int CurrentSetSize;
188         /** Reference table, contains all current handlers
189          */
190         EventHandler** ref;
191
192         int MAX_DESCRIPTORS;
193
194         size_t indata;
195         size_t outdata;
196         time_t lastempty;
197
198         void UpdateStats(size_t len_in, size_t len_out);
199 public:
200
201         double TotalEvents;
202         double ReadEvents;
203         double WriteEvents;
204         double ErrorEvents;
205
206         /** Constructor.
207          * The constructor transparently initializes
208          * the socket engine which the ircd is using.
209          * Please note that if there is a catastrophic
210          * failure (for example, you try and enable
211          * epoll on a 2.4 linux kernel) then this
212          * function may bail back to the shell.
213          * @param Instance The creator/owner of this object
214          */
215         SocketEngine(InspIRCd* Instance);
216
217         /** Destructor.
218          * The destructor transparently tidies up
219          * any resources used by the socket engine.
220          */
221         virtual ~SocketEngine();
222
223         /** Add an EventHandler object to the engine.
224          * Use AddFd to add a file descriptor to the
225          * engine and have the socket engine monitor
226          * it. You must provide an object derived from
227          * EventHandler which implements HandleEvent()
228          * and optionally Readable() and Writeable().
229          * @param eh An event handling object to add
230          */
231         virtual bool AddFd(EventHandler* eh);
232
233         /** If you call this function and pass it an
234          * event handler, that event handler will
235          * receive the next available write event,
236          * even if the socket is a readable socket only.
237          * Developers should avoid constantly keeping
238          * an eventhandler in the writeable state,
239          * as this will consume large amounts of
240          * CPU time.
241          * @param eh An event handler which wants to
242          * receive the next writeability event.
243          */
244         virtual void WantWrite(EventHandler* eh);
245
246         /** Returns the maximum number of file descriptors
247          * you may store in the socket engine at any one time.
248          * @return The maximum fd value
249          */
250         virtual int GetMaxFds();
251
252         /** Returns the number of file descriptor slots
253          * which are available for storing fds.
254          * @return The number of remaining fd's
255          */
256         virtual int GetRemainingFds();
257
258         /** Delete an event handler from the engine.
259          * This function call deletes an EventHandler
260          * from the engine, returning true if it succeeded
261          * and false if it failed. This does not free the
262          * EventHandler pointer using delete, if this is
263          * required you must do this yourself.
264          * Note on forcing deletes. DO NOT DO THIS! This is
265          * extremely dangerous and will most likely render the
266          * socketengine dead. This was added only for handling
267          * very rare cases where broken 3rd party libs destroys
268          * the OS socket beyond our control. If you can't explain
269          * in minute details why forcing is absolutely necessary
270          * then you don't need it. That was a NO!
271          * @param eh The event handler object to remove
272          * @param force *DANGEROUS* See method description!
273          * @return True if the event handler was removed
274          */
275         virtual bool DelFd(EventHandler* eh, bool force = false);
276
277         /** Returns true if a file descriptor exists in
278          * the socket engine's list.
279          * @param fd The event handler to look for
280          * @return True if this fd has an event handler
281          */
282         virtual bool HasFd(int fd);
283
284         /** Returns the EventHandler attached to a specific fd.
285          * If the fd isnt in the socketengine, returns NULL.
286          * @param fd The event handler to look for
287          * @return A pointer to the event handler, or NULL
288          */
289         virtual EventHandler* GetRef(int fd);
290
291         /** Waits for events and dispatches them to handlers.
292          * Please note that this doesnt wait long, only
293          * a couple of milliseconds. It returns the number of
294          * events which occured during this call.
295          * This method will dispatch events to their handlers
296          * by calling their EventHandler::HandleEvent()
297          * methods with the neccessary EventType value.
298          * @return The number of events which have occured.
299          */
300         virtual int DispatchEvents();
301
302         /** Returns the socket engines name.
303          * This returns the name of the engine for use
304          * in /VERSION responses.
305          * @return The socket engine name
306          */
307         virtual std::string GetName();
308
309         /** Returns true if the file descriptors in the
310          * given event handler are within sensible ranges
311          * which can be handled by the socket engine.
312          */
313         virtual bool BoundsCheckFd(EventHandler* eh);
314
315         /** Abstraction for BSD sockets accept(2).
316          * This function should emulate its namesake system call exactly.
317          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
318          * @return This method should return exactly the same values as the system call it emulates.
319          */
320         virtual int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen);
321
322         /** Abstraction for BSD sockets close(2).
323          * This function should emulate its namesake system call exactly.
324          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
325          * @return This method should return exactly the same values as the system call it emulates.
326          */
327         virtual int Close(EventHandler* fd);
328
329         /** Abstraction for BSD sockets close(2).
330          * This function should emulate its namesake system call exactly.
331          * This function should emulate its namesake system call exactly.
332          * @return This method should return exactly the same values as the system call it emulates.
333          */
334         virtual int Close(int fd);
335
336         /** Abstraction for BSD sockets send(2).
337          * This function should emulate its namesake system call exactly.
338          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
339          * @return This method should return exactly the same values as the system call it emulates.
340          */
341         virtual int Send(EventHandler* fd, const void *buf, size_t len, int flags);
342
343         /** Abstraction for BSD sockets recv(2).
344          * This function should emulate its namesake system call exactly.
345          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
346          * @return This method should return exactly the same values as the system call it emulates.
347          */
348         virtual int Recv(EventHandler* fd, void *buf, size_t len, int flags);
349
350         /** Abstraction for BSD sockets recvfrom(2).
351          * This function should emulate its namesake system call exactly.
352          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
353          * @return This method should return exactly the same values as the system call it emulates.
354          */
355         virtual int RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen);
356
357         /** Abstraction for BSD sockets sendto(2).
358          * This function should emulate its namesake system call exactly.
359          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
360          * @return This method should return exactly the same values as the system call it emulates.
361          */
362         virtual int SendTo(EventHandler* fd, const void *buf, size_t len, int flags, const sockaddr *to, socklen_t tolen);
363
364         /** Abstraction for BSD sockets connect(2).
365          * This function should emulate its namesake system call exactly.
366          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
367          * @return This method should return exactly the same values as the system call it emulates.
368          */
369         virtual int Connect(EventHandler* fd, const sockaddr *serv_addr, socklen_t addrlen);
370
371         /** Make a file descriptor blocking.
372          * @param fd a file descriptor to set to blocking mode
373          * @return 0 on success, -1 on failure, errno is set appropriately.
374          */
375         virtual int Blocking(int fd);
376
377         /** Make a file descriptor nonblocking.
378          * @param fd A file descriptor to set to nonblocking mode
379          * @return 0 on success, -1 on failure, errno is set appropriately.
380          */
381         virtual int NonBlocking(int fd);
382
383         /** Abstraction for BSD sockets shutdown(2).
384          * This function should emulate its namesake system call exactly.
385          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
386          * @return This method should return exactly the same values as the system call it emulates.
387          */
388         virtual int Shutdown(EventHandler* fd, int how);
389
390         /** Abstraction for BSD sockets shutdown(2).
391          * This function should emulate its namesake system call exactly.
392          * @return This method should return exactly the same values as the system call it emulates.
393          */
394         virtual int Shutdown(int fd, int how);
395
396         /** Abstraction for BSD sockets bind(2).
397          * This function should emulate its namesake system call exactly.
398          * @return This method should return exactly the same values as the system call it emulates.
399          */
400         virtual int Bind(int fd, const sockaddr *my_addr, socklen_t addrlen);
401
402         /** Abstraction for BSD sockets listen(2).
403          * This function should emulate its namesake system call exactly.
404          * @return This method should return exactly the same values as the system call it emulates.
405          */
406         virtual int Listen(int sockfd, int backlog);
407
408         /** Abstraction for BSD sockets getsockname(2).
409          * This function should emulate its namesake system call exactly.
410          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
411          * @return This method should return exactly the same values as the system call it emulates.
412          */
413         virtual int GetSockName(EventHandler* fd, sockaddr *name, socklen_t* namelen);
414
415         /** This function is called immediately after fork().
416          * Some socket engines (notably kqueue) cannot have their
417          * handles inherited by forked processes. This method
418          * allows for the socket engine to re-create its handle
419          * after the daemon forks as the socket engine is created
420          * long BEFORE the daemon forks.
421          * @return void, but it is acceptable for this function to bail back to
422          * the shell or operating system on fatal error.
423          */
424         virtual void RecoverFromFork();
425
426         /** Get data transfer statistics, kilobits per second in and out and total.
427          */
428         void GetStats(float &kbitpersec_in, float &kbitpersec_out, float &kbitpersec_total);
429 };
430
431 #endif
432