]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/socketengine.h
b411b394a6cbc1e2f5c3af988c86d5b516e779b4
[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 /**
41  * Event mask for SocketEngine events
42  */
43 enum EventMask
44 {
45         /** Do not test this socket for readability
46          */
47         FD_WANT_NO_READ = 0x1,
48         /** Give a read event at all times when reads will not block.
49          */
50         FD_WANT_POLL_READ = 0x2,
51         /** Give a read event when there is new data to read.
52          *
53          * An event MUST be sent if there is new data to be read, and the most
54          * recent read/recv() on this FD returned EAGAIN. An event MAY be sent
55          * at any time there is data to be read on the socket.
56          */
57         FD_WANT_FAST_READ = 0x4,
58         /** Give an optional read event when reads begin to unblock
59          *
60          * This state is useful if you want to leave data in the OS receive
61          * queue but not get continuous event notifications about it, because
62          * it may not require a system call to transition from FD_WANT_FAST_READ
63          */
64         FD_WANT_EDGE_READ = 0x8,
65
66         /** Mask for all read events */
67         FD_WANT_READ_MASK = 0x0F,
68
69         /** Do not test this socket for writeability
70          */
71         FD_WANT_NO_WRITE = 0x10,
72         /** Give a write event at all times when writes will not block.
73          *
74          * You probably shouldn't use this state; if it's likely that the write
75          * will not block, try it first, then use FD_WANT_FAST_WRITE if it
76          * fails. If it's likely to block (or you are using polling-style reads)
77          * then use FD_WANT_SINGLE_WRITE.
78          */
79         FD_WANT_POLL_WRITE = 0x20,
80         /** Give a write event when writes don't block any more
81          *
82          * An event MUST be sent if writes will not block, and the most recent
83          * write/send() on this FD returned EAGAIN, or connect() returned
84          * EINPROGRESS. An event MAY be sent at any time that writes will not
85          * block.
86          *
87          * Before calling HandleEvent, a socket engine MAY change the state of
88          * the FD back to FD_WANT_EDGE_WRITE if it is simpler (for example, if a
89          * one-shot notification was registered). If further writes are needed,
90          * it is the responsibility of the event handler to change the state to
91          * one that will generate the required notifications
92          */
93         FD_WANT_FAST_WRITE = 0x40,
94         /** Give an optional write event on edge-triggered write unblock.
95          *
96          * This state is useful to avoid system calls when moving to/from
97          * FD_WANT_FAST_WRITE when writing data to a mostly-unblocked socket.
98          */
99         FD_WANT_EDGE_WRITE = 0x80,
100         /** Request a one-shot poll-style write notification. The socket will
101          * return to the FD_WANT_NO_WRITE state before HandleEvent is called.
102          */
103         FD_WANT_SINGLE_WRITE = 0x100,
104
105         /** Mask for all write events */
106         FD_WANT_WRITE_MASK = 0x1F0,
107
108         /** Add a trial read. During the next DispatchEvents invocation, this
109          * will call HandleEvent with EVENT_READ unless reads are known to be
110          * blocking.
111          */
112         FD_ADD_TRIAL_READ  = 0x1000,
113         /** Assert that reads are known to block. This cancels FD_ADD_TRIAL_READ.
114          * Reset by SE before running EVENT_READ
115          */
116         FD_READ_WILL_BLOCK = 0x2000,
117
118         /** Add a trial write. During the next DispatchEvents invocation, this
119          * will call HandleEvent with EVENT_WRITE unless writes are known to be
120          * blocking.
121          * 
122          * This could be used to group several writes together into a single
123          * send() syscall, or to ensure that writes are blocking when attempting
124          * to use FD_WANT_FAST_WRITE.
125          */
126         FD_ADD_TRIAL_WRITE = 0x4000,
127         /** Assert that writes are known to block. This cancels FD_ADD_TRIAL_WRITE.
128          * Reset by SE before running EVENT_WRITE
129          */
130         FD_WRITE_WILL_BLOCK = 0x8000, 
131
132         /** Mask for trial read/trial write */
133         FD_TRIAL_NOTE_MASK = 0x5000
134 };
135
136 /** This class is a basic I/O handler class.
137  * Any object which wishes to receive basic I/O events
138  * from the socketengine must derive from this class and
139  * implement the HandleEvent() method. The derived class
140  * must then be added to SocketEngine using the method
141  * SocketEngine::AddFd(), after which point the derived
142  * class will receive events to its HandleEvent() method.
143  * The derived class should also implement one of Readable()
144  * and Writeable(). In the current implementation, only
145  * Readable() is used. If this returns true, the socketengine
146  * inserts a readable socket. If it is false, the socketengine
147  * inserts a writeable socket. The derived class should never
148  * change the value this function returns without first
149  * deleting the socket from the socket engine. The only
150  * requirement beyond this for an event handler is that it
151  * must have a file descriptor. What this file descriptor
152  * is actually attached to is completely up to you.
153  */
154 class CoreExport EventHandler : public classbase
155 {
156  private:
157         /** Private state maintained by socket engine */
158         int event_mask;
159  protected:
160         /** File descriptor.
161          * All events which can be handled must have a file descriptor.  This
162          * allows you to add events for sockets, fifo's, pipes, and various
163          * other forms of IPC.  Do not change this while the object is
164          * registered with the SocketEngine
165          */
166         int fd;
167  public:
168         /** Get the current file descriptor
169          * @return The file descriptor of this handler
170          */
171         inline int GetFd() const { return fd; }
172
173         inline int GetEventMask() const { return event_mask; }
174
175         /** Set a new file desciptor
176          * @param FD The new file descriptor. Do not call this method without
177          * first deleting the object from the SocketEngine if you have
178          * added it to a SocketEngine instance.
179          */
180         void SetFd(int FD);
181
182         /** Constructor
183          */
184         EventHandler();
185
186         /** Destructor
187          */
188         virtual ~EventHandler() {}
189
190         /** Process an I/O event.
191          * You MUST implement this function in your derived
192          * class, and it will be called whenever read or write
193          * events are received.
194          * @param et either one of EVENT_READ for read events,
195          * and EVENT_WRITE for write events.
196          */
197         virtual void HandleEvent(EventType et, int errornum = 0) = 0;
198
199         friend class SocketEngine;
200 };
201
202 /** Provides basic file-descriptor-based I/O support.
203  * The actual socketengine class presents the
204  * same interface on all operating systems, but
205  * its private members and internal behaviour
206  * should be treated as blackboxed, and vary
207  * from system to system and upon the config
208  * settings chosen by the server admin. The current
209  * version supports select, epoll and kqueue.
210  * The configure script will enable a socket engine
211  * based upon what OS is detected, and will derive
212  * a class from SocketEngine based upon what it finds.
213  * The derived classes file will also implement a
214  * classfactory, SocketEngineFactory, which will
215  * create a derived instance of SocketEngine using
216  * polymorphism so that the core and modules do not
217  * have to be aware of which SocketEngine derived
218  * class they are using.
219  */
220 class CoreExport SocketEngine
221 {
222  protected:
223         /** Current number of descriptors in the engine
224          */
225         int CurrentSetSize;
226         /** Reference table, contains all current handlers
227          */
228         EventHandler** ref;
229         /** List of handlers that want a trial read/write
230          */
231         std::set<int> trials;
232
233         int MAX_DESCRIPTORS;
234
235         size_t indata;
236         size_t outdata;
237         time_t lastempty;
238
239         void UpdateStats(size_t len_in, size_t len_out);
240
241         virtual void OnSetEvent(EventHandler* eh, int old_mask, int new_mask) = 0;
242         void SetEventMask(EventHandler* eh, int value);
243 public:
244
245         double TotalEvents;
246         double ReadEvents;
247         double WriteEvents;
248         double ErrorEvents;
249
250         /** Constructor.
251          * The constructor transparently initializes
252          * the socket engine which the ircd is using.
253          * Please note that if there is a catastrophic
254          * failure (for example, you try and enable
255          * epoll on a 2.4 linux kernel) then this
256          * function may bail back to the shell.
257          */
258         SocketEngine();
259
260         /** Destructor.
261          * The destructor transparently tidies up
262          * any resources used by the socket engine.
263          */
264         virtual ~SocketEngine();
265
266         /** Add an EventHandler object to the engine.  Use AddFd to add a file
267          * descriptor to the engine and have the socket engine monitor it. You
268          * must provide an object derived from EventHandler which implements
269          * HandleEvent().
270          * @param eh An event handling object to add
271          * @param event_mask The initial event mask for the object
272          */
273         virtual bool AddFd(EventHandler* eh, int event_mask) = 0;
274
275         /** If you call this function and pass it an
276          * event handler, that event handler will
277          * receive the next available write event,
278          * even if the socket is a readable socket only.
279          * Developers should avoid constantly keeping
280          * an eventhandler in the writeable state,
281          * as this will consume large amounts of
282          * CPU time.
283          * @param eh The event handler to change
284          * @param event_mask The changes to make to the wait state
285          */
286         void ChangeEventMask(EventHandler* eh, int event_mask);
287
288         /** Returns the highest file descriptor you may store in the socket engine
289          * @return The maximum fd value
290          */
291         inline int GetMaxFds() const { return MAX_DESCRIPTORS; }
292
293         /** Returns the number of file descriptors being queried
294          * @return The set size
295          */
296         inline int GetUsedFds() const { return CurrentSetSize; }
297
298         /** Delete an event handler from the engine.
299          * This function call deletes an EventHandler
300          * from the engine, returning true if it succeeded
301          * and false if it failed. This does not free the
302          * EventHandler pointer using delete, if this is
303          * required you must do this yourself.
304          * Note on forcing deletes. DO NOT DO THIS! This is
305          * extremely dangerous and will most likely render the
306          * socketengine dead. This was added only for handling
307          * very rare cases where broken 3rd party libs destroys
308          * the OS socket beyond our control. If you can't explain
309          * in minute details why forcing is absolutely necessary
310          * then you don't need it. That was a NO!
311          * @param eh The event handler object to remove
312          * @param force *DANGEROUS* See method description!
313          * @return True if the event handler was removed
314          */
315         virtual bool DelFd(EventHandler* eh, bool force = false) = 0;
316
317         /** Returns true if a file descriptor exists in
318          * the socket engine's list.
319          * @param fd The event handler to look for
320          * @return True if this fd has an event handler
321          */
322         virtual bool HasFd(int fd);
323
324         /** Returns the EventHandler attached to a specific fd.
325          * If the fd isnt in the socketengine, returns NULL.
326          * @param fd The event handler to look for
327          * @return A pointer to the event handler, or NULL
328          */
329         virtual EventHandler* GetRef(int fd);
330
331         /** Waits for events and dispatches them to handlers.  Please note that
332          * this doesn't wait long, only a couple of milliseconds. It returns the
333          * number of events which occurred during this call.  This method will
334          * dispatch events to their handlers by calling their
335          * EventHandler::HandleEvent() methods with the necessary EventType
336          * value.
337          * @return The number of events which have occured.
338          */
339         virtual int DispatchEvents() = 0;
340
341         /** Dispatch trial reads and writes. This causes the actual socket I/O
342          * to happen when writes have been pre-buffered.
343          */
344         virtual void DispatchTrialWrites();
345
346         /** Returns the socket engines name.  This returns the name of the
347          * engine for use in /VERSION responses.
348          * @return The socket engine name
349          */
350         virtual std::string GetName() = 0;
351
352         /** Returns true if the file descriptors in the given event handler are
353          * within sensible ranges which can be handled by the socket engine.
354          */
355         virtual bool BoundsCheckFd(EventHandler* eh);
356
357         /** Abstraction for BSD sockets accept(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         int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen);
363
364         /** Abstraction for BSD sockets close(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         int Close(EventHandler* fd);
370
371         /** Abstraction for BSD sockets close(2).
372          * This function should emulate its namesake system call exactly.
373          * This function should emulate its namesake system call exactly.
374          * @return This method should return exactly the same values as the system call it emulates.
375          */
376         int Close(int fd);
377
378         /** Abstraction for BSD sockets send(2).
379          * This function should emulate its namesake system call exactly.
380          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
381          * @return This method should return exactly the same values as the system call it emulates.
382          */
383         int Send(EventHandler* fd, const void *buf, size_t len, int flags);
384
385         /** Abstraction for BSD sockets recv(2).
386          * This function should emulate its namesake system call exactly.
387          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
388          * @return This method should return exactly the same values as the system call it emulates.
389          */
390         int Recv(EventHandler* fd, void *buf, size_t len, int flags);
391
392         /** Abstraction for BSD sockets recvfrom(2).
393          * This function should emulate its namesake system call exactly.
394          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
395          * @return This method should return exactly the same values as the system call it emulates.
396          */
397         int RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen);
398
399         /** Abstraction for BSD sockets sendto(2).
400          * This function should emulate its namesake system call exactly.
401          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
402          * @return This method should return exactly the same values as the system call it emulates.
403          */
404         int SendTo(EventHandler* fd, const void *buf, size_t len, int flags, const sockaddr *to, socklen_t tolen);
405
406         /** Abstraction for BSD sockets connect(2).
407          * This function should emulate its namesake system call exactly.
408          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
409          * @return This method should return exactly the same values as the system call it emulates.
410          */
411         int Connect(EventHandler* fd, const sockaddr *serv_addr, socklen_t addrlen);
412
413         /** Make a file descriptor blocking.
414          * @param fd a file descriptor to set to blocking mode
415          * @return 0 on success, -1 on failure, errno is set appropriately.
416          */
417         int Blocking(int fd);
418
419         /** Make a file descriptor nonblocking.
420          * @param fd A file descriptor to set to nonblocking mode
421          * @return 0 on success, -1 on failure, errno is set appropriately.
422          */
423         int NonBlocking(int fd);
424
425         /** Abstraction for BSD sockets shutdown(2).
426          * This function should emulate its namesake system call exactly.
427          * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
428          * @return This method should return exactly the same values as the system call it emulates.
429          */
430         int Shutdown(EventHandler* fd, int how);
431
432         /** Abstraction for BSD sockets shutdown(2).
433          * This function should emulate its namesake system call exactly.
434          * @return This method should return exactly the same values as the system call it emulates.
435          */
436         int Shutdown(int fd, int how);
437
438         /** Abstraction for BSD sockets bind(2).
439          * This function should emulate its namesake system call exactly.
440          * @return This method should return exactly the same values as the system call it emulates.
441          */
442         int Bind(int fd, const sockaddr *my_addr, socklen_t addrlen);
443
444         /** Abstraction for BSD sockets listen(2).
445          * This function should emulate its namesake system call exactly.
446          * @return This method should return exactly the same values as the system call it emulates.
447          */
448         int Listen(int sockfd, int backlog);
449
450         /** Set SO_REUSEADDR and SO_LINGER on this file descriptor
451          */
452         void SetReuse(int sockfd);
453
454         /** This function is called immediately after fork().
455          * Some socket engines (notably kqueue) cannot have their
456          * handles inherited by forked processes. This method
457          * allows for the socket engine to re-create its handle
458          * after the daemon forks as the socket engine is created
459          * long BEFORE the daemon forks.
460          * @return void, but it is acceptable for this function to bail back to
461          * the shell or operating system on fatal error.
462          */
463         virtual void RecoverFromFork();
464
465         /** Get data transfer statistics, kilobits per second in and out and total.
466          */
467         void GetStats(float &kbitpersec_in, float &kbitpersec_out, float &kbitpersec_total);
468 };
469
470 SocketEngine* CreateSocketEngine();
471
472 #endif
473