/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/gsockmsw.cpp
ViewVC logotype

Contents of /branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/gsockmsw.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (show annotations) (download)
Tue Sep 7 03:29:01 2010 UTC (9 years, 11 months ago) by william
File size: 14056 byte(s)
branching from upstream revision (http://pcsx2.googlecode.com/svn/trunk
): r3113 to
https://svn.netsolutions.dnsalias.com/websvn/ps2/pcsx2/pcsx2_0.9.7/branch/r3113_0.9.7_beta
1 /* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket)
3 * Name: src/msw/gsockmsw.cpp
4 * Copyright: (c) Guilhem Lavaux
5 * Licence: wxWindows Licence
6 * Author: Guillermo Rodriguez Garcia <guille@iies.es>
7 * Purpose: GSocket GUI-specific MSW code
8 * CVSID: $Id: gsockmsw.cpp 50893 2007-12-22 14:05:25Z VZ $
9 * -------------------------------------------------------------------------
10 */
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 /*
20 * DONE: for WinCE we need to replace WSAAsyncSelect
21 * (Windows message-based notification of network events for a socket)
22 * with another mechanism.
23 * As WSAAsyncSelect is not present on WinCE, it now uses
24 * WSACreateEvent, WSAEventSelect, WSAWaitForMultipleEvents and WSAEnumNetworkEvents.
25 * When enabling eventhandling for a socket a new thread it created that keeps track of the events
26 * and posts a messageto the hidden window to use the standard message loop.
27 */
28
29 /* including rasasync.h (included from windows.h itself included from
30 * wx/setup.h and/or winsock.h results in this warning for
31 * RPCNOTIFICATION_ROUTINE
32 */
33 #ifdef _MSC_VER
34 # pragma warning(disable:4115) /* named type definition in parentheses */
35 #endif
36
37 /* This needs to be before the wx/defs/h inclusion
38 * for some reason
39 */
40
41 #ifdef __WXWINCE__
42 /* windows.h results in tons of warnings at max warning level */
43 # ifdef _MSC_VER
44 # pragma warning(push, 1)
45 # endif
46 # include <windows.h>
47 # ifdef _MSC_VER
48 # pragma warning(pop)
49 # pragma warning(disable:4514)
50 # endif
51 #endif
52
53 #ifndef __GSOCKET_STANDALONE__
54 # include "wx/platform.h"
55 #endif
56
57 #if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
58
59 #ifndef __GSOCKET_STANDALONE__
60
61 #include "wx/msw/gsockmsw.h"
62 #include "wx/gsocket.h"
63
64 extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance(void);
65 #define INSTANCE wxGetInstance()
66
67 #else /* __GSOCKET_STANDALONE__ */
68
69 #include "gsockmsw.h"
70 #include "gsocket.h"
71
72 /* If not using wxWidgets, a global var called hInst must
73 * be available and it must contain the app's instance
74 * handle.
75 */
76 extern HINSTANCE hInst;
77 #define INSTANCE hInst
78
79 #endif /* !__GSOCKET_STANDALONE__/__GSOCKET_STANDALONE__ */
80
81 #ifndef __WXWINCE__
82 #include <assert.h>
83 #else
84 #define assert(x)
85 #include <winsock.h>
86 #include "wx/msw/wince/net.h"
87 #include "wx/hashmap.h"
88 WX_DECLARE_HASH_MAP(int,bool,wxIntegerHash,wxIntegerEqual,SocketHash);
89 #endif
90
91 #include <string.h>
92 #include <stdio.h>
93 #include <stdlib.h>
94 #include <stddef.h>
95 #include <ctype.h>
96
97 #include <winsock.h>
98
99 #ifdef _MSC_VER
100 # pragma warning(default:4115) /* named type definition in parentheses */
101 #endif
102
103 #define CLASSNAME TEXT("_GSocket_Internal_Window_Class")
104
105 /* implemented in utils.cpp */
106 extern "C" WXDLLIMPEXP_BASE HWND
107 wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
108
109 /* Maximum number of different GSocket objects at a given time.
110 * This value can be modified at will, but it CANNOT be greater
111 * than (0x7FFF - WM_USER + 1)
112 */
113 #define MAXSOCKETS 1024
114
115 #if (MAXSOCKETS > (0x7FFF - WM_USER + 1))
116 #error "MAXSOCKETS is too big!"
117 #endif
118
119 #ifndef __WXWINCE__
120 typedef int (PASCAL *WSAAsyncSelectFunc)(SOCKET,HWND,u_int,long);
121 #else
122 /* Typedef the needed function prototypes and the WSANETWORKEVENTS structure
123 */
124 typedef struct _WSANETWORKEVENTS {
125 long lNetworkEvents;
126 int iErrorCode[10];
127 } WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS;
128 typedef HANDLE (PASCAL *WSACreateEventFunc)(void);
129 typedef int (PASCAL *WSAEventSelectFunc)(SOCKET,HANDLE,long);
130 typedef int (PASCAL *WSAWaitForMultipleEventsFunc)(long,HANDLE,BOOL,long,BOOL);
131 typedef int (PASCAL *WSAEnumNetworkEventsFunc)(SOCKET,HANDLE,LPWSANETWORKEVENTS);
132 #endif //__WXWINCE__
133
134 LRESULT CALLBACK _GSocket_Internal_WinProc(HWND, UINT, WPARAM, LPARAM);
135
136 /* Global variables */
137
138 static HWND hWin;
139 static CRITICAL_SECTION critical;
140 static GSocket* socketList[MAXSOCKETS];
141 static int firstAvailable;
142
143 #ifndef __WXWINCE__
144 static WSAAsyncSelectFunc gs_WSAAsyncSelect = NULL;
145 #else
146 static SocketHash socketHash;
147 static unsigned int currSocket;
148 HANDLE hThread[MAXSOCKETS];
149 static WSACreateEventFunc gs_WSACreateEvent = NULL;
150 static WSAEventSelectFunc gs_WSAEventSelect = NULL;
151 static WSAWaitForMultipleEventsFunc gs_WSAWaitForMultipleEvents = NULL;
152 static WSAEnumNetworkEventsFunc gs_WSAEnumNetworkEvents = NULL;
153 /* This structure will be used to pass data on to the thread that handles socket events.
154 */
155 typedef struct thread_data{
156 HWND hEvtWin;
157 unsigned long msgnumber;
158 unsigned long fd;
159 unsigned long lEvent;
160 }thread_data;
161 #endif
162
163 static HMODULE gs_wsock32dll = 0;
164
165
166 #ifdef __WXWINCE__
167 /* This thread handles socket events on WinCE using WSAEventSelect() as WSAAsyncSelect is not supported.
168 * When an event occures for the socket, it is checked what kind of event happend and the correct message gets posted
169 * so that the hidden window can handle it as it would in other MSW builds.
170 */
171 DWORD WINAPI SocketThread(LPVOID data)
172 {
173 WSANETWORKEVENTS NetworkEvents;
174 thread_data* d = (thread_data *)data;
175
176 HANDLE NetworkEvent = gs_WSACreateEvent();
177 gs_WSAEventSelect(d->fd, NetworkEvent, d->lEvent);
178
179 while(socketHash[d->fd] == true)
180 {
181 if ((gs_WSAWaitForMultipleEvents(1, &NetworkEvent, FALSE,INFINITE, FALSE)) == WAIT_FAILED)
182 {
183 printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
184 return 0;
185 }
186 if (gs_WSAEnumNetworkEvents(d->fd ,NetworkEvent, &NetworkEvents) == SOCKET_ERROR)
187 {
188 printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
189 return 0;
190 }
191
192 long flags = NetworkEvents.lNetworkEvents;
193 if (flags & FD_READ)
194 ::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_READ);
195 if (flags & FD_WRITE)
196 ::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_WRITE);
197 if (flags & FD_OOB)
198 ::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_OOB);
199 if (flags & FD_ACCEPT)
200 ::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_ACCEPT);
201 if (flags & FD_CONNECT)
202 ::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_CONNECT);
203 if (flags & FD_CLOSE)
204 ::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_CLOSE);
205
206 }
207 gs_WSAEventSelect(d->fd, NetworkEvent, 0);
208 ExitThread(0);
209 return 0;
210 }
211 #endif
212
213
214 bool GSocketGUIFunctionsTableConcrete::CanUseEventLoop()
215 {
216 return true;
217 }
218
219 /* Global initializers */
220
221 bool GSocketGUIFunctionsTableConcrete::OnInit()
222 {
223 static LPCTSTR pclassname = NULL;
224 int i;
225
226 /* Create internal window for event notifications */
227 hWin = wxCreateHiddenWindow(&pclassname, CLASSNAME, _GSocket_Internal_WinProc);
228 if (!hWin)
229 return false;
230
231 /* Initialize socket list */
232 InitializeCriticalSection(&critical);
233
234 for (i = 0; i < MAXSOCKETS; i++)
235 {
236 socketList[i] = NULL;
237 }
238 firstAvailable = 0;
239
240 /* Load WSAAsyncSelect from wsock32.dll (we don't link against it
241 statically to avoid dependency on wsock32.dll for apps that don't use
242 sockets): */
243 #ifndef __WXWINCE__
244 gs_wsock32dll = LoadLibrary(wxT("wsock32.dll"));
245 if (!gs_wsock32dll)
246 return false;
247 gs_WSAAsyncSelect =(WSAAsyncSelectFunc)GetProcAddress(gs_wsock32dll,
248 "WSAAsyncSelect");
249 if (!gs_WSAAsyncSelect)
250 return false;
251 #else
252 /* On WinCE we load ws2.dll which will provide the needed functions.
253 */
254 gs_wsock32dll = LoadLibrary(wxT("ws2.dll"));
255 if (!gs_wsock32dll)
256 return false;
257 gs_WSAEventSelect =(WSAEventSelectFunc)GetProcAddress(gs_wsock32dll,
258 wxT("WSAEventSelect"));
259 if (!gs_WSAEventSelect)
260 return false;
261
262 gs_WSACreateEvent =(WSACreateEventFunc)GetProcAddress(gs_wsock32dll,
263 wxT("WSACreateEvent"));
264 if (!gs_WSACreateEvent)
265 return false;
266
267 gs_WSAWaitForMultipleEvents =(WSAWaitForMultipleEventsFunc)GetProcAddress(gs_wsock32dll,
268 wxT("WSAWaitForMultipleEvents"));
269 if (!gs_WSAWaitForMultipleEvents)
270 return false;
271
272 gs_WSAEnumNetworkEvents =(WSAEnumNetworkEventsFunc)GetProcAddress(gs_wsock32dll,
273 wxT("WSAEnumNetworkEvents"));
274 if (!gs_WSAEnumNetworkEvents)
275 return false;
276
277 currSocket = 0;
278 #endif
279
280 return true;
281 }
282
283 void GSocketGUIFunctionsTableConcrete::OnExit()
284 {
285 #ifdef __WXWINCE__
286 /* Delete the threads here */
287 for(unsigned int i=0; i < currSocket; i++)
288 CloseHandle(hThread[i]);
289 #endif
290 /* Destroy internal window */
291 DestroyWindow(hWin);
292 UnregisterClass(CLASSNAME, INSTANCE);
293
294 /* Unlock wsock32.dll */
295 if (gs_wsock32dll)
296 {
297 FreeLibrary(gs_wsock32dll);
298 gs_wsock32dll = 0;
299 }
300
301 /* Delete critical section */
302 DeleteCriticalSection(&critical);
303 }
304
305 /* Per-socket GUI initialization / cleanup */
306
307 bool GSocketGUIFunctionsTableConcrete::Init_Socket(GSocket *socket)
308 {
309 int i;
310
311 /* Allocate a new message number for this socket */
312 EnterCriticalSection(&critical);
313
314 i = firstAvailable;
315 while (socketList[i] != NULL)
316 {
317 i = (i + 1) % MAXSOCKETS;
318
319 if (i == firstAvailable) /* abort! */
320 {
321 LeaveCriticalSection(&critical);
322 return false;
323 }
324 }
325 socketList[i] = socket;
326 firstAvailable = (i + 1) % MAXSOCKETS;
327 socket->m_msgnumber = (i + WM_USER);
328
329 LeaveCriticalSection(&critical);
330
331 return true;
332 }
333
334 void GSocketGUIFunctionsTableConcrete::Destroy_Socket(GSocket *socket)
335 {
336 /* Remove the socket from the list */
337 EnterCriticalSection(&critical);
338 if ( socket->IsOk() )
339 {
340 const int msgnum = socket->m_msgnumber;
341
342 // we need to remove any pending messages for this socket to avoid having
343 // them sent to a new socket which could reuse the same message number as
344 // soon as we destroy this one
345 MSG msg;
346 while ( ::PeekMessage(&msg, hWin, msgnum, msgnum, PM_REMOVE) )
347 ;
348
349 socketList[msgnum - WM_USER] = NULL;
350 }
351
352 LeaveCriticalSection(&critical);
353 }
354
355 /* Windows proc for asynchronous event handling */
356
357 LRESULT CALLBACK _GSocket_Internal_WinProc(HWND hWnd,
358 UINT uMsg,
359 WPARAM wParam,
360 LPARAM lParam)
361 {
362 GSocket *socket;
363 GSocketEvent event;
364 GSocketCallback cback;
365 char *data;
366
367 if (uMsg >= WM_USER && uMsg <= (WM_USER + MAXSOCKETS - 1))
368 {
369 EnterCriticalSection(&critical);
370 socket = socketList[(uMsg - WM_USER)];
371 event = (GSocketEvent) -1;
372 cback = NULL;
373 data = NULL;
374
375 /* Check that the socket still exists (it has not been
376 * destroyed) and for safety, check that the m_fd field
377 * is what we expect it to be.
378 */
379 if ((socket != NULL) && (socket->m_fd == wParam))
380 {
381 switch WSAGETSELECTEVENT(lParam)
382 {
383 case FD_READ: event = GSOCK_INPUT; break;
384 case FD_WRITE: event = GSOCK_OUTPUT; break;
385 case FD_ACCEPT: event = GSOCK_CONNECTION; break;
386 case FD_CONNECT:
387 {
388 if (WSAGETSELECTERROR(lParam) != 0)
389 event = GSOCK_LOST;
390 else
391 event = GSOCK_CONNECTION;
392 break;
393 }
394 case FD_CLOSE: event = GSOCK_LOST; break;
395 }
396
397 if (event != -1)
398 {
399 cback = socket->m_cbacks[event];
400 data = socket->m_data[event];
401
402 if (event == GSOCK_LOST)
403 socket->m_detected = GSOCK_LOST_FLAG;
404 else
405 socket->m_detected |= (1 << event);
406 }
407 }
408
409 /* OK, we can now leave the critical section because we have
410 * already obtained the callback address (we make no further
411 * accesses to socket->whatever). However, the app should
412 * be prepared to handle events from a socket that has just
413 * been closed!
414 */
415 LeaveCriticalSection(&critical);
416
417 if (cback != NULL)
418 (cback)(socket, event, data);
419
420 return (LRESULT) 0;
421 }
422 else
423 return DefWindowProc(hWnd, uMsg, wParam, lParam);
424 }
425
426 /* _GSocket_Enable_Events:
427 * Enable all event notifications; we need to be notified of all
428 * events for internal processing, but we will only notify users
429 * when an appropiate callback function has been installed.
430 */
431 void GSocketGUIFunctionsTableConcrete::Enable_Events(GSocket *socket)
432 {
433 assert (socket != NULL);
434
435 if (socket->m_fd != INVALID_SOCKET)
436 {
437 /* We could probably just subscribe to all events regardless
438 * of the socket type, but MS recommends to do it this way.
439 */
440 long lEvent = socket->m_server?
441 FD_ACCEPT : (FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
442 #ifndef __WXWINCE__
443 gs_WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, lEvent);
444 #else
445 /*
446 * WinCE creates a thread for socket event handling.
447 * All needed parameters get passed through the thread_data structure.
448 */
449
450 thread_data* d = new thread_data;
451 d->lEvent = lEvent;
452 d->hEvtWin = hWin;
453 d->msgnumber = socket->m_msgnumber;
454 d->fd = socket->m_fd;
455 socketHash[socket->m_fd] = true;
456 hThread[currSocket++] = CreateThread(NULL, 0, &SocketThread,(LPVOID)d, 0, NULL);
457 #endif
458 }
459 }
460
461 /* _GSocket_Disable_Events:
462 * Disable event notifications (when shutdowning the socket)
463 */
464 void GSocketGUIFunctionsTableConcrete::Disable_Events(GSocket *socket)
465 {
466 assert (socket != NULL);
467
468 if (socket->m_fd != INVALID_SOCKET)
469 {
470 #ifndef __WXWINCE__
471 gs_WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, 0);
472 #else
473 //Destroy the thread
474 socketHash[socket->m_fd] = false;
475 #endif
476 }
477 }
478
479 #else /* !wxUSE_SOCKETS */
480
481 /*
482 * Translation unit shouldn't be empty, so include this typedef to make the
483 * compiler (VC++ 6.0, for example) happy
484 */
485 typedef void (*wxDummy)();
486
487 #endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */

  ViewVC Help
Powered by ViewVC 1.1.22