1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2009 InspIRCd Development Team
6 * See: http://wiki.inspircd.org/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
14 #ifndef __SOCKETENGINE_IOCP__
15 #define __SOCKETENGINE_IOCP__
17 #define READ_BUFFER_SIZE 600
20 #include "inspircd_config.h"
21 #include "inspircd_win32wrapper.h"
23 #include "socketengine.h"
25 /** Socket overlapped event types
30 SOCKET_IO_EVENT_READ_READY = 0,
32 SOCKET_IO_EVENT_WRITE_READY = 1,
34 SOCKET_IO_EVENT_ACCEPT = 2,
36 SOCKET_IO_EVENT_ERROR = 3,
37 /** Number of events */
38 NUM_SOCKET_IO_EVENTS = 4,
41 /** Represents a windows overlapped IO event
49 SocketIOEvent m_event;
52 unsigned __int64 m_params;
55 unsigned long m_params;
57 /** Create an overlapped event
59 Overlapped(SocketIOEvent ev, int params) : m_event(ev), m_params(params)
61 memset(&m_overlap, 0, sizeof(OVERLAPPED));
65 /** Specific to UDP sockets with overlapped IO
69 unsigned char udp_buffer[600];
70 unsigned long udp_len;
71 sockaddr udp_sockaddr[2];
72 unsigned long udp_sockaddr_len;
75 /** Specific to accepting sockets with overlapped IO
83 /** Implementation of SocketEngine that implements windows IO Completion Ports
85 class IOCPEngine : public SocketEngine
87 /** Creates a "fake" file descriptor for use with an IOCP socket.
88 * This is a little slow, but it isnt called too much. We'll fix it
89 * in a future release.
90 * @return -1 if there are no free slots, and an integer if it finds one.
92 __inline int GenerateFd(int RealFd)
94 int index_hash = RealFd % MAX_DESCRIPTORS;
95 if(ref[index_hash] == 0)
100 for(; i < MAX_DESCRIPTORS; ++i)
107 /** Global I/O completion port that sockets attach to.
109 HANDLE m_completionPort;
111 /** This is kinda shitty... :/ for getting an address from a real fd.
113 std::map<int, EventHandler*> m_binding;
116 /** Holds the preallocated buffer passed to WSARecvFrom
117 * function. Yes, I know, it's a dirty hack.
119 udp_overlap * udp_ov;
121 /** Creates an IOCP Socket Engine
122 * @param Instance The creator of this object
126 /** Deletes an IOCP socket engine and all the attached sockets
130 /** Adds an event handler to the completion port, and sets up initial events.
131 * @param eh EventHandler to add
132 * @return True if success, false if no room
134 bool AddFd(EventHandler* eh, int event_mask);
136 /** Gets the maximum number of file descriptors that this engine can handle.
137 * @return The number of file descriptors
139 __inline int GetMaxFds() { return MAX_DESCRIPTORS; }
141 /** Gets the number of free/remaining file descriptors under this engine.
142 * @return Remaining count
144 __inline int GetRemainingFds()
146 register int count = 0;
148 for(; i < MAX_DESCRIPTORS; ++i)
154 /** Removes a file descriptor from the set, preventing it from receiving any more events
155 * @return True if remove was successful, false otherwise
157 bool DelFd(EventHandler* eh, bool force = false);
159 /** Called every loop to handle input/output events for all sockets under this engine
160 * @return The number of "changed" sockets.
162 int DispatchEvents();
164 /** Gets the name of this socket engine as a string.
165 * @return string of socket engine name
167 std::string GetName();
169 void OnSetEvent(EventHandler* eh, int old_mask, int new_mask);
171 /** Posts a completion event on the specified socket.
172 * @param eh EventHandler for message
173 * @param type Event Type
174 * @param param Event Parameter
175 * @return True if added, false if not
177 bool PostCompletionEvent(EventHandler* eh, SocketIOEvent type, int param);
179 /** Posts a read event on the specified socket
180 * @param eh EventHandler (socket)
182 void PostReadEvent(EventHandler* eh);
184 /** Posts an accept event on the specified socket
185 * @param eh EventHandler (socket)
187 void PostAcceptEvent(EventHandler* eh);
189 /** Returns the EventHandler attached to a specific fd.
190 * If the fd isnt in the socketengine, returns NULL.
191 * @param fd The event handler to look for
192 * @return A pointer to the event handler, or NULL
194 EventHandler* GetRef(int fd);
196 /** Returns true if a file descriptor exists in
197 * the socket engine's list.
198 * @param fd The event handler to look for
199 * @return True if this fd has an event handler
203 /** Returns the EventHandler attached to a specific fd.
204 * If the fd isnt in the socketengine, returns NULL.
205 * @param fd The event handler to look for
206 * @return A pointer to the event handler, or NULL
208 EventHandler* GetIntRef(int fd);
210 bool BoundsCheckFd(EventHandler* eh);
212 virtual int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen);
214 virtual int RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
216 virtual int Blocking(int fd);
218 virtual int NonBlocking(int fd);
220 virtual int GetSockName(EventHandler* fd, sockaddr *name, socklen_t* namelen);
222 virtual int Close(int fd);
224 virtual int Close(EventHandler* fd);
227 /** Creates a SocketEngine
229 class SocketEngineFactory
232 /** Create a new instance of SocketEngine based on IOCPEngine
234 SocketEngine* Create() { return new IOCPEngine; }