summaryrefslogtreecommitdiff
path: root/include/socketengine_iocp.h
blob: 615c44fd7ae7a706611cc4ac8befc88e7018d4d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*       +------------------------------------+
 *       | 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 500
#define USING_IOCP 1

#include "inspircd_config.h"
#include "inspircd_win32wrapper.h"
#include "globals.h"
#include "inspircd.h"
#include "socketengine.h"

enum SocketIOEvent
{
	SOCKET_IO_EVENT_READ_READY			= 0,
	SOCKET_IO_EVENT_WRITE_READY			= 1,
	SOCKET_IO_EVENT_ACCEPT				= 2,
	SOCKET_IO_EVENT_ERROR				= 3,
	NUM_SOCKET_IO_EVENTS				= 4,
};

class Overlapped
{
 public:
	OVERLAPPED m_overlap;
	SocketIOEvent m_event;
	int m_params;

	Overlapped(SocketIOEvent ev, int params) : m_event(ev), m_params(params)
	{
		memset(&m_overlap, 0, sizeof(OVERLAPPED));
	}
};

struct accept_overlap
{
	int socket;
	char buf[1024];
};

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:
	/** 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);
};

//typedef void(*OpHandler)(EventHandler)
/** Event Handler Array
 */

/** Creates a SocketEngine
 */
class SocketEngineFactory
{
public:
	/** Create a new instance of SocketEngine based on IOCPEngine
	 */
	SocketEngine* Create(InspIRCd* Instance) { return new IOCPEngine(Instance); }
};

#endif