]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - include/socketengine.h
Deduplicate mode unregistering code in ModuleManager::DoSafeUnload() and extract...
[user/henk/code/inspircd.git] / include / socketengine.h
index 305d389d4bac610e33dd83789b99c95afd7d63ae..c0026bfc6f2513335b0af7ba3853a12d017cff6b 100644 (file)
 #include "socket.h"
 #include "base.h"
 
-/** 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,
-       /** Write event */
-       EVENT_WRITE     =       1,
-       /** Error event */
-       EVENT_ERROR     =       2
-};
+#ifndef _WIN32
+#include <sys/uio.h>
+#endif
+
+#ifndef IOV_MAX
+#define IOV_MAX 1024
+#endif
 
 /**
  * Event mask for SocketEngine events
@@ -93,7 +84,7 @@ enum EventMask
         * EINPROGRESS. An event MAY be sent at any time that writes will not
         * block.
         *
-        * Before calling HandleEvent, a socket engine MAY change the state of
+        * Before calling OnEventHandler*(), a socket engine MAY change the state of
         * the FD back to FD_WANT_EDGE_WRITE if it is simpler (for example, if a
         * one-shot notification was registered). If further writes are needed,
         * it is the responsibility of the event handler to change the state to
@@ -107,7 +98,7 @@ enum EventMask
         */
        FD_WANT_EDGE_WRITE = 0x80,
        /** Request a one-shot poll-style write notification. The socket will
-        * return to the FD_WANT_NO_WRITE state before HandleEvent is called.
+        * return to the FD_WANT_NO_WRITE state before OnEventHandler*() is called.
         */
        FD_WANT_SINGLE_WRITE = 0x100,
 
@@ -115,17 +106,17 @@ enum EventMask
        FD_WANT_WRITE_MASK = 0x1F0,
 
        /** Add a trial read. During the next DispatchEvents invocation, this
-        * will call HandleEvent with EVENT_READ unless reads are known to be
+        * will call OnEventHandlerRead() unless reads are known to be
         * blocking.
         */
        FD_ADD_TRIAL_READ  = 0x1000,
        /** Assert that reads are known to block. This cancels FD_ADD_TRIAL_READ.
-        * Reset by SE before running EVENT_READ
+        * Reset by SE before running OnEventHandlerRead().
         */
        FD_READ_WILL_BLOCK = 0x2000,
 
        /** Add a trial write. During the next DispatchEvents invocation, this
-        * will call HandleEvent with EVENT_WRITE unless writes are known to be
+        * will call OnEventHandlerWrite() unless writes are known to be
         * blocking.
         *
         * This could be used to group several writes together into a single
@@ -134,7 +125,7 @@ enum EventMask
         */
        FD_ADD_TRIAL_WRITE = 0x4000,
        /** Assert that writes are known to block. This cancels FD_ADD_TRIAL_WRITE.
-        * Reset by SE before running EVENT_WRITE
+        * Reset by SE before running OnEventHandlerWrite().
         */
        FD_WRITE_WILL_BLOCK = 0x8000,
 
@@ -145,17 +136,14 @@ enum EventMask
 /** This class is a basic I/O handler class.
  * Any object which wishes to receive basic I/O events
  * from the socketengine must derive from this class and
- * implement the HandleEvent() method. The derived class
+ * implement the OnEventHandler*() methods. The derived class
  * must then be added to SocketEngine using the method
  * SocketEngine::AddFd(), after which point the derived
- * class will receive events to its HandleEvent() method.
- * The derived class should also implement one of Readable()
- * and Writeable(). In the current implementation, only
- * Readable() is used. If this returns true, the socketengine
- * inserts a readable socket. If it is false, the socketengine
- * inserts a writeable socket. The derived class should never
- * change the value this function returns without first
- * deleting the socket from the socket engine. The only
+ * class will receive events to its OnEventHandler*() methods.
+ * The event mask passed to SocketEngine::AddFd() determines
+ * what events the EventHandler gets notified about and with
+ * what semantics. SocketEngine::ChangeEventMask() can be
+ * called to update the event mask later. The only
  * requirement beyond this for an event handler is that it
  * must have a file descriptor. What this file descriptor
  * is actually attached to is completely up to you.
@@ -199,16 +187,20 @@ class CoreExport EventHandler : public classbase
         */
        virtual ~EventHandler() {}
 
-       /** Process an I/O event.
-        * You MUST implement this function in your derived
-        * class, and it will be called whenever read or write
-        * events are received.
-        * @param et either one of EVENT_READ for read events,
-        * EVENT_WRITE for write events and EVENT_ERROR for
-        * error events.
-        * @param errornum The error code which goes with an EVENT_ERROR.
+       /** Called by the socket engine in case of a read event
         */
-       virtual void HandleEvent(EventType et, int errornum = 0) = 0;
+       virtual void OnEventHandlerRead() = 0;
+
+       /** Called by the socket engine in case of a write event.
+        * The default implementation does nothing.
+        */
+       virtual void OnEventHandlerWrite();
+
+       /** Called by the socket engine in case of an error event.
+        * The default implementation does nothing.
+        * @param errornum Error code
+        */
+       virtual void OnEventHandlerError(int errornum);
 
        friend class SocketEngine;
 };
@@ -306,6 +298,12 @@ class CoreExport SocketEngine
        }
 
 public:
+#ifndef _WIN32
+       typedef iovec IOVector;
+#else
+       typedef WindowsIOVec IOVector;
+#endif
+
        /** Constructor.
         * The constructor transparently initializes
         * the socket engine which the ircd is using.
@@ -327,7 +325,7 @@ public:
        /** Add an EventHandler object to the engine.  Use AddFd to add a file
         * descriptor to the engine and have the socket engine monitor it. You
         * must provide an object derived from EventHandler which implements
-        * HandleEvent().
+        * the required OnEventHandler*() methods.
         * @param eh An event handling object to add
         * @param event_mask The initial event mask for the object
         */
@@ -346,8 +344,10 @@ public:
         */
        static void ChangeEventMask(EventHandler* eh, int event_mask);
 
-       /** Returns the highest file descriptor you may store in the socket engine
-        * @return The maximum fd value
+       /** Returns the number of file descriptors reported by the system this program may use
+        * when it was started.
+        * @return If positive, the number of file descriptors that the system reported that we
+        * may use. Otherwise (<= 0) this number could not be determined.
         */
        static int GetMaxFds() { return MAX_DESCRIPTORS; }
 
@@ -384,8 +384,7 @@ public:
         * this doesn't wait long, only a couple of milliseconds. It returns the
         * number of events which occurred during this call.  This method will
         * dispatch events to their handlers by calling their
-        * EventHandler::HandleEvent() methods with the necessary EventType
-        * value.
+        * EventHandler::OnEventHandler*() methods.
         * @return The number of events which have occured.
         */
        static int DispatchEvents();
@@ -409,12 +408,11 @@ public:
         */
        static 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.
+       /** Close the underlying fd of an event handler, remove it from the socket engine and set the fd to -1.
+        * @param eh The EventHandler to close.
+        * @return 0 on success, a negative value on error
         */
-       static int Close(EventHandler* fd);
+       static int Close(EventHandler* eh);
 
        /** Abstraction for BSD sockets close(2).
         * This function should emulate its namesake system call exactly.
@@ -433,6 +431,27 @@ public:
         */
        static int Send(EventHandler* fd, const void *buf, size_t len, int flags);
 
+       /** Abstraction for vector write function writev().
+        * This function should emulate its namesake system call exactly.
+        * @param fd EventHandler to send data with
+        * @param iov Array of IOVectors containing the buffers to send and their lengths in the platform's
+        * native format.
+        * @param count Number of elements in iov.
+        * @return This method should return exactly the same values as the system call it emulates.
+        */
+       static int WriteV(EventHandler* fd, const IOVector* iov, int count);
+
+#ifdef _WIN32
+       /** Abstraction for vector write function writev() that accepts a POSIX format iovec.
+        * This function should emulate its namesake system call exactly.
+        * @param fd EventHandler to send data with
+        * @param iov Array of iovecs containing the buffers to send and their lengths in POSIX format.
+        * @param count Number of elements in iov.
+        * @return This method should return exactly the same values as the system call it emulates.
+        */
+       static int WriteV(EventHandler* fd, const iovec* iov, int count);
+#endif
+
        /** 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.