]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/socketengines/socketengine_iocp.h
302fdbd2ce24e0c85e8c073d9614e8f79a7a46d5
[user/henk/code/inspircd.git] / include / socketengines / socketengine_iocp.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_IOCP__
15 #define __SOCKETENGINE_IOCP__
16
17 #define READ_BUFFER_SIZE 600
18 #define USING_IOCP 1
19
20 #include "inspircd_config.h"
21 #include "inspircd_win32wrapper.h"
22 #include "inspircd.h"
23 #include "socketengine.h"
24
25 /** Socket overlapped event types
26  */
27 enum SocketIOEvent
28 {
29         /** Read ready */
30         SOCKET_IO_EVENT_READ_READY                      = 0,
31         /** Write ready */
32         SOCKET_IO_EVENT_WRITE_READY                     = 1,
33         /** Accept ready */
34         SOCKET_IO_EVENT_ACCEPT                          = 2,
35         /** Error occured */
36         SOCKET_IO_EVENT_ERROR                           = 3,
37         /** Number of events */
38         NUM_SOCKET_IO_EVENTS                            = 4,
39 };
40
41 /** Represents a windows overlapped IO event
42  */
43 class Overlapped
44 {
45  public:
46         /** Overlap event */
47         OVERLAPPED m_overlap;
48         /** Type of event */
49         SocketIOEvent m_event;
50 #ifdef WIN64
51         /** Parameters */
52         unsigned __int64 m_params;
53 #else
54         /** Parameters */
55         unsigned long m_params;
56 #endif
57         /** Create an overlapped event
58          */
59         Overlapped(SocketIOEvent ev, int params) : m_event(ev), m_params(params)
60         {
61                 memset(&m_overlap, 0, sizeof(OVERLAPPED));
62         }
63 };
64
65 /** Specific to UDP sockets with overlapped IO
66  */
67 struct udp_overlap
68 {
69         unsigned char udp_buffer[600];
70         unsigned long udp_len;
71         sockaddr udp_sockaddr[2];
72         unsigned long udp_sockaddr_len;
73 };
74
75 /** Specific to accepting sockets with overlapped IO
76  */
77 struct accept_overlap
78 {
79         int socket;
80         char buf[1024];
81 };
82
83 /** Implementation of SocketEngine that implements windows IO Completion Ports
84  */
85 class IOCPEngine : public SocketEngine
86 {
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.
91          */
92         __inline int GenerateFd(int RealFd)
93         {
94                 int index_hash = RealFd % MAX_DESCRIPTORS;
95                 if(ref[index_hash] == 0)
96                         return index_hash;
97                 else
98                 {
99                         register int i = 0;
100                         for(; i < MAX_DESCRIPTORS; ++i)
101                                 if(ref[i] == 0)
102                                         return i;
103                 }
104                 return -1;
105         }
106
107         /** Global I/O completion port that sockets attach to.
108          */
109         HANDLE m_completionPort;
110
111         /** This is kinda shitty... :/ for getting an address from a real fd.
112          */
113         std::map<int, EventHandler*> m_binding;
114
115 public:
116         /** Holds the preallocated buffer passed to WSARecvFrom
117          * function. Yes, I know, it's a dirty hack.
118          */
119         udp_overlap * udp_ov;
120
121         /** Creates an IOCP Socket Engine
122          * @param Instance The creator of this object
123          */
124         IOCPEngine(InspIRCd* Instance);
125
126         /** Deletes an IOCP socket engine and all the attached sockets
127          */
128         ~IOCPEngine();
129
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
133          */
134         bool AddFd(EventHandler* eh);
135
136         /** Gets the maximum number of file descriptors that this engine can handle.
137          * @return The number of file descriptors
138          */
139         __inline int GetMaxFds() { return MAX_DESCRIPTORS; }
140
141         /** Gets the number of free/remaining file descriptors under this engine.
142          * @return Remaining count
143          */
144         __inline int GetRemainingFds()
145         {
146                 register int count = 0;
147                 register int i = 0;
148                 for(; i < MAX_DESCRIPTORS; ++i)
149                         if(ref[i] == 0)
150                                 ++count;
151                 return count;
152         }
153
154         /** Removes a file descriptor from the set, preventing it from receiving any more events
155          * @return True if remove was successful, false otherwise
156          */
157         bool DelFd(EventHandler* eh, bool force = false);
158
159         /** Called every loop to handle input/output events for all sockets under this engine
160          * @return The number of "changed" sockets.
161          */
162         int DispatchEvents();
163
164         /** Gets the name of this socket engine as a string.
165          * @return string of socket engine name
166          */
167         std::string GetName();
168
169         /** Queues a Write event on the specified event handler.
170          * @param eh EventHandler that needs data sent on
171          */
172         void WantWrite(EventHandler* eh);
173
174         /** Posts a completion event on the specified socket.
175          * @param eh EventHandler for message
176          * @param type Event Type
177          * @param param Event Parameter
178          * @return True if added, false if not
179          */
180         bool PostCompletionEvent(EventHandler* eh, SocketIOEvent type, int param);
181
182         /** Posts a read event on the specified socket
183          * @param eh EventHandler (socket)
184          */
185         void PostReadEvent(EventHandler* eh);
186
187         /** Posts an accept event on the specified socket
188          * @param eh EventHandler (socket)
189          */
190         void PostAcceptEvent(EventHandler* eh);
191
192         /** Returns the EventHandler attached to a specific fd.
193          * If the fd isnt in the socketengine, returns NULL.
194          * @param fd The event handler to look for
195          * @return A pointer to the event handler, or NULL
196          */
197         EventHandler* GetRef(int fd);
198
199         /** Returns true if a file descriptor exists in
200          * the socket engine's list.
201          * @param fd The event handler to look for
202          * @return True if this fd has an event handler
203          */
204         bool HasFd(int fd);
205
206         /** Returns the EventHandler attached to a specific fd.
207          * If the fd isnt in the socketengine, returns NULL.
208          * @param fd The event handler to look for
209          * @return A pointer to the event handler, or NULL
210          */
211         EventHandler* GetIntRef(int fd);
212
213         bool BoundsCheckFd(EventHandler* eh);
214
215         virtual int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen);
216
217         virtual int RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
218
219         virtual int Blocking(int fd);
220
221         virtual int NonBlocking(int fd);
222
223         virtual int GetSockName(EventHandler* fd, sockaddr *name, socklen_t* namelen);
224
225         virtual int Close(int fd);
226
227         virtual int Close(EventHandler* fd);
228 };
229
230 /** Creates a SocketEngine
231  */
232 class SocketEngineFactory
233 {
234 public:
235         /** Create a new instance of SocketEngine based on IOCPEngine
236          */
237         SocketEngine* Create(InspIRCd* Instance) { return new IOCPEngine(Instance); }
238 };
239
240 #endif