blob: 6d1980cc1b48824e6906cfe01d8b33eefc009e8e [file] [log] [blame]
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19// -=- SocketManager.cxx
20
21#define WIN32_LEAN_AND_MEAN
22#include <winsock2.h>
23#include <assert.h>
24
25#include <rfb/LogWriter.h>
26#include <rfb_win32/SocketManager.h>
27
28using namespace rfb;
29using namespace rfb::win32;
30
31static LogWriter vlog("SocketManager");
32
33
34// -=- SocketManager
35
36SocketManager::SocketManager() : sockets(0), events(0), nSockets(0), nAvail(0) {
37}
38
39SocketManager::~SocketManager() {
40 for (int i=0; i<nSockets; i++) {
41 if (!sockets[i].is_event)
42 WSACloseEvent(events[i]);
43 }
44 delete [] events;
45 delete [] sockets;
46}
47
48
49void SocketManager::addListener(network::SocketListener* sock_, network::SocketServer* srvr) {
50 WSAEVENT event = WSACreateEvent();
51 assert(event != WSA_INVALID_EVENT);
52 addListener(sock_, event, srvr);
53}
54
55void SocketManager::addSocket(network::Socket* sock_, network::SocketServer* srvr) {
56 WSAEVENT event = WSACreateEvent();
57 assert(event != WSA_INVALID_EVENT);
58 addSocket(sock_, event, srvr);
59}
60
61
62BOOL SocketManager::getMessage(MSG* msg, HWND hwnd, UINT minMsg, UINT maxMsg) {
63 while (true) {
64 // First check for idle timeout
65
66 network::SocketServer* server = 0;
67 int timeout = 0;
68 for (int i=0; i<nSockets; i++) {
69 if (!sockets[i].is_event &&
70 sockets[i].server != server) {
71 server = sockets[i].server;
72 int t = server->checkTimeouts();
73 if (t > 0 && (timeout == 0 || t < timeout))
74 timeout = t;
75 }
76 }
77 if (timeout == 0)
78 timeout = INFINITE;
79
80 // - Network IO is less common than messages - process it first
81 DWORD result;
82 if (nSockets) {
83 result = WaitForMultipleObjects(nSockets, events, FALSE, 0);
84 if (result == WAIT_TIMEOUT) {
85 if (PeekMessage(msg, hwnd, minMsg, maxMsg, PM_REMOVE))
86 return msg->message != WM_QUIT;
87
88 result = MsgWaitForMultipleObjects(nSockets, events, FALSE, timeout,
89 QS_ALLINPUT);
90 if (result == WAIT_OBJECT_0 + nSockets) {
91 if (PeekMessage(msg, hwnd, minMsg, maxMsg, PM_REMOVE))
92 return msg->message != WM_QUIT;
93 continue;
94 }
95 }
96 } else
97 return GetMessage(msg, hwnd, minMsg, maxMsg);
98
99 if ((result >= WAIT_OBJECT_0) && (result < (WAIT_OBJECT_0 + nSockets))) {
100 int index = result - WAIT_OBJECT_0;
101
102 // - Process a socket event
103
104 if (sockets[index].is_event) {
105 // Process a general Win32 event
106 // NB: The handler must reset the event!
107
108 if (!sockets[index].handler->processEvent(events[index])) {
109 removeSocket(index);
110 continue;
111 }
112 } else if (sockets[index].is_conn) {
113 // Process data from an active connection
114
115 // Cancel event notification for this socket
116 if (WSAEventSelect(sockets[index].fd, events[index], 0) == SOCKET_ERROR)
117 vlog.info("unable to disable WSAEventSelect:%u", WSAGetLastError());
118
119 // Reset the event object
120 WSAResetEvent(events[index]);
121
122 // Call the socket server to process the event
123 if (!sockets[index].server->processSocketEvent(sockets[index].sock.conn)) {
124 removeSocket(index);
125 continue;
126 }
127
128 // Re-instate the required socket event
129 // If the read event is still valid, the event object gets set here
130 if (WSAEventSelect(sockets[index].fd, events[index], FD_READ | FD_CLOSE) == SOCKET_ERROR)
131 throw rdr::SystemException("unable to re-enable WSAEventSelect:%u", WSAGetLastError());
132
133 } else {
134 // Accept an incoming connection
135 vlog.debug("accepting incoming connection");
136
137 // What kind of event is this?
138 WSANETWORKEVENTS network_events;
139 WSAEnumNetworkEvents(sockets[index].fd, events[index], &network_events);
140 if (network_events.lNetworkEvents & FD_ACCEPT) {
141 network::Socket* new_sock = sockets[index].sock.listener->accept();
Oleg Sheikin5c642e92005-12-22 20:57:58 +0000142 if ((sockets[index].server)->getDisable()) {
143 delete new_sock;
144 new_sock = 0;
145 }
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +0000146 if (new_sock) {
147 sockets[index].server->addClient(new_sock);
148 addSocket(new_sock, sockets[index].server);
149 }
150 } else if (network_events.lNetworkEvents & FD_CLOSE) {
151 vlog.info("deleting listening socket");
152 network::SocketListener* s = sockets[index].sock.listener;
153 removeSocket(index);
154 delete s;
155 } else {
156 vlog.error("unknown network event for listener");
157 }
158
159 }
160 } else if (result == WAIT_FAILED) {
161 throw rdr::SystemException("unable to wait for events", GetLastError());
162 }
163 }
164}
165
166
167void SocketManager::resizeArrays(int numSockets) {
168 if (nAvail >= numSockets) return;
169 while (nAvail < numSockets)
170 nAvail = max(16, nAvail*2);
171
172 SocketInfo* newinfo = new SocketInfo[nAvail];
173 HANDLE* newevents = new HANDLE[nAvail];
174 for (int i=0; i<nSockets; i++) {
175 newinfo[i] = sockets[i];
176 newevents[i] = events[i];
177 }
178 delete [] sockets;
179 delete [] events;
180 sockets = newinfo;
181 events = newevents;
182}
183
184void SocketManager::addSocket(network::Socket* sock, HANDLE event, network::SocketServer* server) {
185 resizeArrays(nSockets+1);
186
187 sockets[nSockets].sock.conn = sock;
188 sockets[nSockets].fd = sock->getFd();
189 sockets[nSockets].server = server;
190 events[nSockets] = event;
191 sockets[nSockets].is_conn = true;
192 sockets[nSockets].is_event = false;
193
194 if (WSAEventSelect(sock->getFd(), event, FD_READ | FD_CLOSE) == SOCKET_ERROR)
195 throw rdr::SystemException("unable to select on socket", WSAGetLastError());
196 nSockets++;
197}
198
199void SocketManager::addListener(network::SocketListener* sock, HANDLE event, network::SocketServer* server) {
200 resizeArrays(nSockets+1);
201
202 sockets[nSockets].sock.listener = sock;
203 sockets[nSockets].fd = sock->getFd();
204 sockets[nSockets].server = server;
205 events[nSockets] = event;
206 sockets[nSockets].is_conn = false;
207 sockets[nSockets].is_event = false;
208
209 if (WSAEventSelect(sock->getFd(), event, FD_ACCEPT | FD_CLOSE) == SOCKET_ERROR)
210 throw rdr::SystemException("unable to select on listener", WSAGetLastError());
211 nSockets++;
212}
213
214void SocketManager::remListener(network::SocketListener* sock) {
215 for (int index=0; index<nSockets; index++) {
216 if (!sockets[index].is_conn &&
217 !sockets[index].is_event) {
218 vlog.debug("removing listening socket");
219 removeSocket(index);
220 delete sock;
221 }
222 }
223}
224
225void SocketManager::addEvent(HANDLE event, EventHandler* ecb) {
226 resizeArrays(nSockets+1);
227
228 sockets[nSockets].handler = ecb;
229 events[nSockets] = event;
230 sockets[nSockets].is_conn = false;
231 sockets[nSockets].is_event = true;
232
233 nSockets++;
234}
235
236void SocketManager::removeSocket(int index) {
237 if (index >= nSockets)
238 throw rdr::Exception("attempting to remove unregistered socket");
239
240 if (!sockets[index].is_event)
241 WSACloseEvent(events[index]);
242
243 for (int i=index; i<nSockets-1; i++) {
244 sockets[i] = sockets[i+1];
245 events[i] = events[i+1];
246 }
247
248 nSockets--;
249}
250