blob: 6ebd5c0aaaa64e13e3af1fdd716caf8835637552 [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();
142 if (new_sock) {
143 sockets[index].server->addClient(new_sock);
144 addSocket(new_sock, sockets[index].server);
145 }
146 } else if (network_events.lNetworkEvents & FD_CLOSE) {
147 vlog.info("deleting listening socket");
148 network::SocketListener* s = sockets[index].sock.listener;
149 removeSocket(index);
150 delete s;
151 } else {
152 vlog.error("unknown network event for listener");
153 }
154
155 }
156 } else if (result == WAIT_FAILED) {
157 throw rdr::SystemException("unable to wait for events", GetLastError());
158 }
159 }
160}
161
162
163void SocketManager::resizeArrays(int numSockets) {
164 if (nAvail >= numSockets) return;
165 while (nAvail < numSockets)
166 nAvail = max(16, nAvail*2);
167
168 SocketInfo* newinfo = new SocketInfo[nAvail];
169 HANDLE* newevents = new HANDLE[nAvail];
170 for (int i=0; i<nSockets; i++) {
171 newinfo[i] = sockets[i];
172 newevents[i] = events[i];
173 }
174 delete [] sockets;
175 delete [] events;
176 sockets = newinfo;
177 events = newevents;
178}
179
180void SocketManager::addSocket(network::Socket* sock, HANDLE event, network::SocketServer* server) {
181 resizeArrays(nSockets+1);
182
183 sockets[nSockets].sock.conn = sock;
184 sockets[nSockets].fd = sock->getFd();
185 sockets[nSockets].server = server;
186 events[nSockets] = event;
187 sockets[nSockets].is_conn = true;
188 sockets[nSockets].is_event = false;
189
190 if (WSAEventSelect(sock->getFd(), event, FD_READ | FD_CLOSE) == SOCKET_ERROR)
191 throw rdr::SystemException("unable to select on socket", WSAGetLastError());
192 nSockets++;
193}
194
195void SocketManager::addListener(network::SocketListener* sock, HANDLE event, network::SocketServer* server) {
196 resizeArrays(nSockets+1);
197
198 sockets[nSockets].sock.listener = sock;
199 sockets[nSockets].fd = sock->getFd();
200 sockets[nSockets].server = server;
201 events[nSockets] = event;
202 sockets[nSockets].is_conn = false;
203 sockets[nSockets].is_event = false;
204
205 if (WSAEventSelect(sock->getFd(), event, FD_ACCEPT | FD_CLOSE) == SOCKET_ERROR)
206 throw rdr::SystemException("unable to select on listener", WSAGetLastError());
207 nSockets++;
208}
209
210void SocketManager::remListener(network::SocketListener* sock) {
211 for (int index=0; index<nSockets; index++) {
212 if (!sockets[index].is_conn &&
213 !sockets[index].is_event) {
214 vlog.debug("removing listening socket");
215 removeSocket(index);
216 delete sock;
217 }
218 }
219}
220
221void SocketManager::addEvent(HANDLE event, EventHandler* ecb) {
222 resizeArrays(nSockets+1);
223
224 sockets[nSockets].handler = ecb;
225 events[nSockets] = event;
226 sockets[nSockets].is_conn = false;
227 sockets[nSockets].is_event = true;
228
229 nSockets++;
230}
231
232void SocketManager::removeSocket(int index) {
233 if (index >= nSockets)
234 throw rdr::Exception("attempting to remove unregistered socket");
235
236 if (!sockets[index].is_event)
237 WSACloseEvent(events[index]);
238
239 for (int i=index; i<nSockets-1; i++) {
240 sockets[i] = sockets[i+1];
241 events[i] = events[i+1];
242 }
243
244 nSockets--;
245}
246