]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - include/socketengine_iocp.h
Windows specific data types in EventHandler are now Extensible items
[user/henk/code/inspircd.git] / include / socketengine_iocp.h
index ac27c86e3e093d5482dcef2267c9f82a5aac90f1..ad3e581574015c13b2d30a0bd3027bafd710d563 100644 (file)
@@ -1 +1,228 @@
-/*       +------------------------------------+\r *       | Inspire Internet Relay Chat Daemon |\r *       +------------------------------------+\r *\r *  InspIRCd: (C) 2002-2007 InspIRCd Development Team\r * See: http://www.inspircd.org/wiki/index.php/Credits\r *\r * This program is free but copyrighted software; see\r *            the file COPYING for details.\r *\r * ---------------------------------------------------\r */\r\r#ifndef __SOCKETENGINE_IOCP__\r#define __SOCKETENGINE_IOCP__\r\r#define READ_BUFFER_SIZE 600\r#define USING_IOCP 1\r\r#include "inspircd_config.h"\r#include "inspircd_win32wrapper.h"\r#include "globals.h"\r#include "inspircd.h"\r#include "socketengine.h"\r\r/** Socket overlapped event types\r */\renum SocketIOEvent\r{\r  /** Read ready */\r      SOCKET_IO_EVENT_READ_READY                      = 0,\r   /** Write ready */\r     SOCKET_IO_EVENT_WRITE_READY                     = 1,\r   /** Accept ready */\r    SOCKET_IO_EVENT_ACCEPT                          = 2,\r   /** Error occured */\r   SOCKET_IO_EVENT_ERROR                           = 3,\r   /** Number of events */\r        NUM_SOCKET_IO_EVENTS                            = 4,\r};\r\r/** Represents a windows overlapped IO event\r */\rclass Overlapped\r{\r public:\r  /** Overlap event */\r   OVERLAPPED m_overlap;\r  /** Type of event */\r   SocketIOEvent m_event;\r#ifdef WIN64\r    /** Parameters */\r      unsigned __int64 m_params;\r#else\r       /** Parameters */\r      unsigned long m_params;\r#endif\r /** Create an overlapped event\r  */\r    Overlapped(SocketIOEvent ev, int params) : m_event(ev), m_params(params)\r       {\r              memset(&m_overlap, 0, sizeof(OVERLAPPED));\r     }\r};\r\r/** Specific to UDP sockets with overlapped IO\r */\rstruct udp_overlap\r{\r  unsigned char udp_buffer[600];\r unsigned long udp_len;\r sockaddr udp_sockaddr[2];\r      unsigned long udp_sockaddr_len;\r};\r\r/** Specific to accepting sockets with overlapped IO\r */\rstruct accept_overlap\r{\r   int socket;\r    char buf[1024];\r};\r\r/** Implementation of SocketEngine that implements windows IO Completion Ports\r */\rclass IOCPEngine : public SocketEngine\r{\r        /** Creates a "fake" file descriptor for use with an IOCP socket.\r       * This is a little slow, but it isnt called too much. We'll fix it\r     * in a future release.\r         * @return -1 if there are no free slots, and an integer if it finds one.\r       */\r    __inline int GenerateFd(int RealFd)\r    {\r              int index_hash = RealFd % MAX_DESCRIPTORS;\r             if(ref[index_hash] == 0)\r                       return index_hash;\r             else\r           {\r                      register int i = 0;\r                    for(; i < MAX_DESCRIPTORS; ++i)\r                                if(ref[i] == 0)\r                                        return i;\r              }\r              return -1;\r     }\r      \r       /** Global I/O completion port that sockets attach to.\r  */\r    HANDLE m_completionPort;\r\r      /** This is kinda shitty... :/ for getting an address from a real fd. \r  */\r    map<int, EventHandler*> m_binding;\r\rpublic:\r    /** Creates an IOCP Socket Engine\r       * @param Instance The creator of this object\r   */\r    IOCPEngine(InspIRCd* Instance);\r\r       /** Deletes an IOCP socket engine and all the attached sockets\r  */\r    ~IOCPEngine();\r\r        /** Adds an event handler to the completion port, and sets up initial events.\r   * @param eh EventHandler to add\r        * @return True if success, false if no room\r    */\r    bool AddFd(EventHandler* eh);\r\r /** Gets the maximum number of file descriptors that this engine can handle.\r    * @return The number of file descriptors\r       */\r    __inline int GetMaxFds() { return MAX_DESCRIPTORS; }\r\r  /** Gets the number of free/remaining file descriptors under this engine.\r       * @return Remaining count\r      */\r    __inline int GetRemainingFds()\r {\r              register int count = 0;\r                register int i = 0;                     \r               for(; i < MAX_DESCRIPTORS; ++i)\r                        if(ref[i] == 0)\r                                ++count;\r               return count;\r  }\r\r     /** Removes a file descriptor from the set, preventing it from receiving any more events\r        * @return True if remove was successful, false otherwise\r       */\r    bool DelFd(EventHandler* eh, bool force = false);\r\r     /** Called every loop to handle input/output events for all sockets under this engine\r   * @return The number of "changed" sockets.\r     */\r    int DispatchEvents();\r\r /** Gets the name of this socket engine as a string.\r    * @return string of socket engine name\r         */\r    std::string GetName();\r\r        /** Queues a Write event on the specified event handler.\r        * @param eh EventHandler that needs data sent on\r       */\r    void WantWrite(EventHandler* eh);\r\r     /** Posts a completion event on the specified socket.\r   * @param eh EventHandler for message\r   * @param type Event Type\r       * @param param Event Parameter\r         * @return True if added, false if not\r  */\r    bool PostCompletionEvent(EventHandler* eh, SocketIOEvent type, int param);\r\r    /** Posts a read event on the specified socket\r  * @param eh EventHandler (socket)\r      */\r    void PostReadEvent(EventHandler* eh);\r\r /** Posts an accept event on the specified socket\r       * @param eh EventHandler (socket)\r      */\r    void PostAcceptEvent(EventHandler* eh);\r\r       /** Returns the EventHandler attached to a specific fd.\r         * If the fd isnt in the socketengine, returns NULL.\r    * @param fd The event handler to look for\r      * @return A pointer to the event handler, or NULL\r      */\r    EventHandler* GetRef(int fd);\r\r /** Returns true if a file descriptor exists in\r         * the socket engine's list.\r    * @param fd The event handler to look for\r      * @return True if this fd has an event handler\r         */\r    bool HasFd(int fd);\r\r   /** Returns the EventHandler attached to a specific fd.\r         * If the fd isnt in the socketengine, returns NULL.\r    * @param fd The event handler to look for\r      * @return A pointer to the event handler, or NULL\r      */\r    EventHandler* GetIntRef(int fd);\r\r      /** Holds the preallocated buffer passed to WSARecvFrom\r         * function. Yes, I know, it's a dirty hack.\r    */\r    udp_overlap * udp_ov;\r};\r\r/** Creates a SocketEngine\r */\rclass SocketEngineFactory\r{\rpublic:\r   /** Create a new instance of SocketEngine based on IOCPEngine\r   */\r    SocketEngine* Create(InspIRCd* Instance) { return new IOCPEngine(Instance); }\r};\r\r#endif\r\r
\ No newline at end of file
+/*       +------------------------------------+
+ *       | Inspire Internet Relay Chat Daemon |
+ *       +------------------------------------+
+ *
+ *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ *            the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#ifndef __SOCKETENGINE_IOCP__
+#define __SOCKETENGINE_IOCP__
+
+#define READ_BUFFER_SIZE 600
+#define USING_IOCP 1
+
+#include "inspircd_config.h"
+#include "inspircd_win32wrapper.h"
+#include "globals.h"
+#include "inspircd.h"
+#include "socketengine.h"
+
+/** Socket overlapped event types
+ */
+enum SocketIOEvent
+{
+       /** Read ready */
+       SOCKET_IO_EVENT_READ_READY                      = 0,
+       /** Write ready */
+       SOCKET_IO_EVENT_WRITE_READY                     = 1,
+       /** Accept ready */
+       SOCKET_IO_EVENT_ACCEPT                          = 2,
+       /** Error occured */
+       SOCKET_IO_EVENT_ERROR                           = 3,
+       /** Number of events */
+       NUM_SOCKET_IO_EVENTS                            = 4,
+};
+
+/** Represents a windows overlapped IO event
+ */
+class Overlapped
+{
+ public:
+       /** Overlap event */
+       OVERLAPPED m_overlap;
+       /** Type of event */
+       SocketIOEvent m_event;
+#ifdef WIN64
+       /** Parameters */
+       unsigned __int64 m_params;
+#else
+       /** Parameters */
+       unsigned long m_params;
+#endif
+       /** Create an overlapped event
+        */
+       Overlapped(SocketIOEvent ev, int params) : m_event(ev), m_params(params)
+       {
+               memset(&m_overlap, 0, sizeof(OVERLAPPED));
+       }
+};
+
+/** Specific to UDP sockets with overlapped IO
+ */
+struct udp_overlap
+{
+       unsigned char udp_buffer[600];
+       unsigned long udp_len;
+       sockaddr udp_sockaddr[2];
+       unsigned long udp_sockaddr_len;
+};
+
+/** Specific to accepting sockets with overlapped IO
+ */
+struct accept_overlap
+{
+       int socket;
+       char buf[1024];
+};
+
+/** Implementation of SocketEngine that implements windows IO Completion Ports
+ */
+class IOCPEngine : public SocketEngine
+{
+       /** Creates a "fake" file descriptor for use with an IOCP socket.
+        * This is a little slow, but it isnt called too much. We'll fix it
+        * in a future release.
+        * @return -1 if there are no free slots, and an integer if it finds one.
+        */
+       __inline int GenerateFd(int RealFd)
+       {
+               int index_hash = RealFd % MAX_DESCRIPTORS;
+               if(ref[index_hash] == 0)
+                       return index_hash;
+               else
+               {
+                       register int i = 0;
+                       for(; i < MAX_DESCRIPTORS; ++i)
+                               if(ref[i] == 0)
+                                       return i;
+               }
+               return -1;
+       }
+       
+       /** Global I/O completion port that sockets attach to.
+        */
+       HANDLE m_completionPort;
+
+       /** This is kinda shitty... :/ for getting an address from a real fd. 
+        */
+       map<int, EventHandler*> m_binding;
+
+public:
+       /** Holds the preallocated buffer passed to WSARecvFrom
+        * function. Yes, I know, it's a dirty hack.
+        */
+       udp_overlap * udp_ov;
+
+       /** Creates an IOCP Socket Engine
+        * @param Instance The creator of this object
+        */
+       IOCPEngine(InspIRCd* Instance);
+
+       /** Deletes an IOCP socket engine and all the attached sockets
+        */
+       ~IOCPEngine();
+
+       /** Adds an event handler to the completion port, and sets up initial events.
+        * @param eh EventHandler to add
+        * @return True if success, false if no room
+        */
+       bool AddFd(EventHandler* eh);
+
+       /** Gets the maximum number of file descriptors that this engine can handle.
+        * @return The number of file descriptors
+        */
+       __inline int GetMaxFds() { return MAX_DESCRIPTORS; }
+
+       /** Gets the number of free/remaining file descriptors under this engine.
+        * @return Remaining count
+        */
+       __inline int GetRemainingFds()
+       {
+               register int count = 0;
+               register int i = 0;                     
+               for(; i < MAX_DESCRIPTORS; ++i)
+                       if(ref[i] == 0)
+                               ++count;
+               return count;
+       }
+
+       /** Removes a file descriptor from the set, preventing it from receiving any more events
+        * @return True if remove was successful, false otherwise
+        */
+       bool DelFd(EventHandler* eh, bool force = false);
+
+       /** Called every loop to handle input/output events for all sockets under this engine
+        * @return The number of "changed" sockets.
+        */
+       int DispatchEvents();
+
+       /** Gets the name of this socket engine as a string.
+        * @return string of socket engine name
+        */
+       std::string GetName();
+
+       /** Queues a Write event on the specified event handler.
+        * @param eh EventHandler that needs data sent on
+        */
+       void WantWrite(EventHandler* eh);
+
+       /** Posts a completion event on the specified socket.
+        * @param eh EventHandler for message
+        * @param type Event Type
+        * @param param Event Parameter
+        * @return True if added, false if not
+        */
+       bool PostCompletionEvent(EventHandler* eh, SocketIOEvent type, int param);
+
+       /** Posts a read event on the specified socket
+        * @param eh EventHandler (socket)
+        */
+       void PostReadEvent(EventHandler* eh);
+
+       /** Posts an accept event on the specified socket
+        * @param eh EventHandler (socket)
+        */
+       void PostAcceptEvent(EventHandler* eh);
+
+       /** 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);
+
+       /** 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);
+
+       /** 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* GetIntRef(int fd);
+
+       bool BoundsCheckFd(EventHandler* eh);
+};
+
+/** Creates a SocketEngine
+ */
+class SocketEngineFactory
+{
+public:
+       /** Create a new instance of SocketEngine based on IOCPEngine
+        */
+       SocketEngine* Create(InspIRCd* Instance) { return new IOCPEngine(Instance); }
+};
+
+#endif
+