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