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