X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=include%2Fsocketengine.h;h=16913972d8d578e9cd881beff1e87346a0e6b5af;hb=5d67a5fff127bf95bca69b436ef7f645f2fe3281;hp=9aa651499b647bafad50f46a32ac041ca6c10e75;hpb=dd168c56c95a870de3d178edda48507ca47168fe;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/include/socketengine.h b/include/socketengine.h index 9aa651499..16913972d 100644 --- a/include/socketengine.h +++ b/include/socketengine.h @@ -2,17 +2,14 @@ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * - * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev. - * E-mail: - * - * + * InspIRCd: (C) 2002-2009 InspIRCd Development Team + * See: http://wiki.inspircd.org/Credits * - * Written by Craig Edwards, Craig McLure, and others. * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- -*/ + */ #ifndef __SOCKETENGINE__ #define __SOCKETENGINE__ @@ -26,14 +23,22 @@ /** Types of event an EventHandler may receive. * EVENT_READ is a readable file descriptor, * and EVENT_WRITE is a writeable file descriptor. + * EVENT_ERROR can always occur, and indicates + * a write error or read error on the socket, + * e.g. EOF condition or broken pipe. */ enum EventType { + /** Read event */ EVENT_READ = 0, - EVENT_WRITE = 1 + /** Write event */ + EVENT_WRITE = 1, + /** Error event */ + EVENT_ERROR = 2 }; class InspIRCd; +class Module; /** This class is a basic I/O handler class. * Any object which wishes to receive basic I/O events @@ -53,7 +58,7 @@ class InspIRCd; * must have a file descriptor. What this file descriptor * is actually attached to is completely up to you. */ -class EventHandler : public Extensible +class CoreExport EventHandler : public Extensible { protected: /** File descriptor. @@ -64,7 +69,28 @@ class EventHandler : public Extensible * other forms of IPC. */ int fd; + + /** Pointer to the module which has hooked the given EventHandler for IO events. + */ + Module *IOHook; public: + + /** Return the current hooker of IO events for this socket, or NULL. + * @return Hooker module, if set, or NULL. + */ + Module *GetIOHook(); + + /** Set a module as hooking IO events on this socket. + * @param IOHooker The module hooking IO + * @return True if the hook could be added, false otherwise. + */ + bool AddIOHook(Module *IOHooker); + + /** Remove IO hooking from a module + * @return True if hooking was successfully removed, false otherwise. + */ + bool DelIOHook(); + /** Get the current file descriptor * @return The file descriptor of this handler */ @@ -80,7 +106,7 @@ class EventHandler : public Extensible /** Constructor */ - EventHandler() {} + EventHandler(); /** Destructor */ @@ -93,6 +119,12 @@ class EventHandler : public Extensible * is still added to a SocketEngine instance! * If this function is unimplemented, the base class * will return true. + * + * NOTE: You cannot set both Readable() and + * Writeable() to true. If you wish to receive + * a write event for your object, you must call + * SocketEngine::WantWrite() instead. This will + * trigger your objects next EVENT_WRITE type event. */ virtual bool Readable(); @@ -103,6 +135,12 @@ class EventHandler : public Extensible * is still added to a SocketEngine instance! * If this function is unimplemented, the base class * will return false. + * + * NOTE: You cannot set both Readable() and + * Writeable() to true. If you wish to receive + * a write event for your object, you must call + * SocketEngine::WantWrite() instead. This will + * trigger your objects next EVENT_WRITE type event. */ virtual bool Writeable(); @@ -110,11 +148,12 @@ class EventHandler : public Extensible * You MUST implement this function in your derived * class, and it will be called whenever read or write * events are received, depending on what your functions - * Readable() and Writeable() returns. + * Readable() and Writeable() returns and wether you + * previously made a call to SocketEngine::WantWrite(). * @param et either one of EVENT_READ for read events, * and EVENT_WRITE for write events. */ - virtual void HandleEvent(EventType et) = 0; + virtual void HandleEvent(EventType et, int errornum = 0) = 0; }; /** Provides basic file-descriptor-based I/O support. @@ -135,7 +174,7 @@ class EventHandler : public Extensible * have to be aware of which SocketEngine derived * class they are using. */ -class SocketEngine : public Extensible +class CoreExport SocketEngine : public Extensible { protected: /** Owner/Creator @@ -149,9 +188,22 @@ protected: int CurrentSetSize; /** Reference table, contains all current handlers */ - EventHandler* ref[MAX_DESCRIPTORS]; + EventHandler** ref; + + int MAX_DESCRIPTORS; + + size_t indata; + size_t outdata; + time_t lastempty; + + void UpdateStats(size_t len_in, size_t len_out); public: + double TotalEvents; + double ReadEvents; + double WriteEvents; + double ErrorEvents; + /** Constructor. * The constructor transparently initializes * the socket engine which the ircd is using. @@ -179,6 +231,17 @@ public: */ virtual bool AddFd(EventHandler* eh); + /** If you call this function and pass it an + * event handler, that event handler will + * receive the next available write event, + * even if the socket is a readable socket only. + * Developers should avoid constantly keeping + * an eventhandler in the writeable state, + * as this will consume large amounts of + * CPU time. + * @param eh An event handler which wants to + * receive the next writeability event. + */ virtual void WantWrite(EventHandler* eh); /** Returns the maximum number of file descriptors @@ -199,24 +262,32 @@ public: * and false if it failed. This does not free the * EventHandler pointer using delete, if this is * required you must do this yourself. + * Note on forcing deletes. DO NOT DO THIS! This is + * extremely dangerous and will most likely render the + * socketengine dead. This was added only for handling + * very rare cases where broken 3rd party libs destroys + * the OS socket beyond our control. If you can't explain + * in minute details why forcing is absolutely necessary + * then you don't need it. That was a NO! * @param eh The event handler object to remove + * @param force *DANGEROUS* See method description! * @return True if the event handler was removed */ - virtual bool DelFd(EventHandler* eh); + virtual bool DelFd(EventHandler* eh, bool force = false); /** Returns true if a file descriptor exists in * the socket engine's list. * @param fd The event handler to look for * @return True if this fd has an event handler */ - bool HasFd(int fd); + virtual bool HasFd(int fd); /** Returns the EventHandler attached to a specific fd. * If the fd isnt in the socketengine, returns NULL. * @param fd The event handler to look for * @return A pointer to the event handler, or NULL */ - EventHandler* GetRef(int fd); + virtual EventHandler* GetRef(int fd); /** Waits for events and dispatches them to handlers. * Please note that this doesnt wait long, only @@ -235,6 +306,128 @@ public: * @return The socket engine name */ virtual std::string GetName(); + + /** Returns true if the file descriptors in the + * given event handler are within sensible ranges + * which can be handled by the socket engine. + */ + virtual bool BoundsCheckFd(EventHandler* eh); + + /** Abstraction for BSD sockets accept(2). + * This function should emulate its namesake system call exactly. + * @param fd This version of the call takes an EventHandler instead of a bare file descriptor. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen); + + /** Abstraction for BSD sockets close(2). + * This function should emulate its namesake system call exactly. + * @param fd This version of the call takes an EventHandler instead of a bare file descriptor. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int Close(EventHandler* fd); + + /** Abstraction for BSD sockets close(2). + * This function should emulate its namesake system call exactly. + * This function should emulate its namesake system call exactly. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int Close(int fd); + + /** Abstraction for BSD sockets send(2). + * This function should emulate its namesake system call exactly. + * @param fd This version of the call takes an EventHandler instead of a bare file descriptor. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int Send(EventHandler* fd, const void *buf, size_t len, int flags); + + /** Abstraction for BSD sockets recv(2). + * This function should emulate its namesake system call exactly. + * @param fd This version of the call takes an EventHandler instead of a bare file descriptor. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int Recv(EventHandler* fd, void *buf, size_t len, int flags); + + /** Abstraction for BSD sockets recvfrom(2). + * This function should emulate its namesake system call exactly. + * @param fd This version of the call takes an EventHandler instead of a bare file descriptor. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen); + + /** Abstraction for BSD sockets sendto(2). + * This function should emulate its namesake system call exactly. + * @param fd This version of the call takes an EventHandler instead of a bare file descriptor. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int SendTo(EventHandler* fd, const void *buf, size_t len, int flags, const sockaddr *to, socklen_t tolen); + + /** Abstraction for BSD sockets connect(2). + * This function should emulate its namesake system call exactly. + * @param fd This version of the call takes an EventHandler instead of a bare file descriptor. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int Connect(EventHandler* fd, const sockaddr *serv_addr, socklen_t addrlen); + + /** Make a file descriptor blocking. + * @param fd a file descriptor to set to blocking mode + * @return 0 on success, -1 on failure, errno is set appropriately. + */ + virtual int Blocking(int fd); + + /** Make a file descriptor nonblocking. + * @param fd A file descriptor to set to nonblocking mode + * @return 0 on success, -1 on failure, errno is set appropriately. + */ + virtual int NonBlocking(int fd); + + /** Abstraction for BSD sockets shutdown(2). + * This function should emulate its namesake system call exactly. + * @param fd This version of the call takes an EventHandler instead of a bare file descriptor. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int Shutdown(EventHandler* fd, int how); + + /** Abstraction for BSD sockets shutdown(2). + * This function should emulate its namesake system call exactly. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int Shutdown(int fd, int how); + + /** Abstraction for BSD sockets bind(2). + * This function should emulate its namesake system call exactly. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int Bind(int fd, const sockaddr *my_addr, socklen_t addrlen); + + /** Abstraction for BSD sockets listen(2). + * This function should emulate its namesake system call exactly. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int Listen(int sockfd, int backlog); + + /** Abstraction for BSD sockets getsockname(2). + * This function should emulate its namesake system call exactly. + * @param fd This version of the call takes an EventHandler instead of a bare file descriptor. + * @return This method should return exactly the same values as the system call it emulates. + */ + virtual int GetSockName(EventHandler* fd, sockaddr *name, socklen_t* namelen); + + /** This function is called immediately after fork(). + * Some socket engines (notably kqueue) cannot have their + * handles inherited by forked processes. This method + * allows for the socket engine to re-create its handle + * after the daemon forks as the socket engine is created + * long BEFORE the daemon forks. + * @return void, but it is acceptable for this function to bail back to + * the shell or operating system on fatal error. + */ + virtual void RecoverFromFork(); + + /** Get data transfer statistics, kilobits per second in and out and total. + */ + void GetStats(float &kbitpersec_in, float &kbitpersec_out, float &kbitpersec_total); }; #endif +