Applied patch [ 1119239 ] Adds socket support for Windows CE platforms

by 'upcase'


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31894 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart
2005-02-10 14:55:27 +00:00
parent e47570f11c
commit dbfb61b3a4
3 changed files with 152 additions and 8 deletions

View File

@@ -23,6 +23,10 @@
#include "wx/msw/wrapwin.h" #include "wx/msw/wrapwin.h"
#ifdef __WXWINCE__
#include <winsock.h>
#endif
class GSocketGUIFunctionsTableConcrete: public GSocketGUIFunctionsTable class GSocketGUIFunctionsTableConcrete: public GSocketGUIFunctionsTable
{ {
public: public:

View File

@@ -371,7 +371,7 @@
#define wxUSE_DYNAMIC_LOADER 0 #define wxUSE_DYNAMIC_LOADER 0
// Set to 1 to use socket classes // Set to 1 to use socket classes
#define wxUSE_SOCKETS 0 #define wxUSE_SOCKETS 1
// Set to 1 to enable virtual file systems (required by wxHTML) // Set to 1 to enable virtual file systems (required by wxHTML)
#define wxUSE_FILESYSTEM 1 #define wxUSE_FILESYSTEM 1

View File

@@ -15,11 +15,13 @@
#endif #endif
/* /*
* TODO: for WinCE we need to replace WSAAsyncSelect * DONE: for WinCE we need to replace WSAAsyncSelect
* (Windows message-based notification of network events for a socket) * (Windows message-based notification of network events for a socket)
* with another mechanism. * with another mechanism.
* We may need to have a separate thread that polls for socket events * As WSAAsyncSelect is not present on WinCE, it now uses
* using select() and sends a message to the main thread. * WSACreateEvent, WSAEventSelect, WSAWaitForMultipleEvents and WSAEnumNetworkEvents.
* When enabling eventhandling for a socket a new thread it created that keeps track of the events
* and posts a messageto the hidden window to use the standard message loop.
*/ */
/* including rasasync.h (included from windows.h itself included from /* including rasasync.h (included from windows.h itself included from
@@ -70,7 +72,7 @@ extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance(void);
* be available and it must contain the app's instance * be available and it must contain the app's instance
* handle. * handle.
*/ */
extern HINSTANCE hInst; extern HINSTANCE hInst;
#define INSTANCE hInst #define INSTANCE hInst
#endif /* __GSOCKET_STANDALONE__ */ #endif /* __GSOCKET_STANDALONE__ */
@@ -111,19 +113,104 @@ wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
#error "MAXSOCKETS is too big!" #error "MAXSOCKETS is too big!"
#endif #endif
#ifndef __WXWINCE__
typedef int (PASCAL *WSAAsyncSelectFunc)(SOCKET,HWND,u_int,long); typedef int (PASCAL *WSAAsyncSelectFunc)(SOCKET,HWND,u_int,long);
#else
/* Typedef the needed function prototypes and the WSANETWORKEVENTS structure
*/
typedef struct _WSANETWORKEVENTS {
long lNetworkEvents;
int iErrorCode[10];
} WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS;
typedef HANDLE (PASCAL *WSACreateEventFunc)(void);
typedef int (PASCAL *WSAEventSelectFunc)(SOCKET,HANDLE,long);
typedef int (PASCAL *WSAWaitForMultipleEventsFunc)(long,HANDLE,BOOL,long,BOOL);
typedef int (PASCAL *WSAEnumNetworkEventsFunc)(SOCKET,HANDLE,LPWSANETWORKEVENTS);
#endif //__WXWINCE__
LRESULT CALLBACK _GSocket_Internal_WinProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK _GSocket_Internal_WinProc(HWND, UINT, WPARAM, LPARAM);
/* Global variables */ /* Global variables */
extern HINSTANCE INSTANCE;
static HWND hWin; static HWND hWin;
static CRITICAL_SECTION critical; static CRITICAL_SECTION critical;
static GSocket* socketList[MAXSOCKETS]; static GSocket* socketList[MAXSOCKETS];
static int firstAvailable; static int firstAvailable;
#ifndef __WXWINCE__
static WSAAsyncSelectFunc gs_WSAAsyncSelect = NULL; static WSAAsyncSelectFunc gs_WSAAsyncSelect = NULL;
#else
/* Setup WinCE specific stuff
*/
static socket_running;
static unsigned int currSocket;
HANDLE hThread[MAXSOCKETS];
static WSACreateEventFunc gs_WSACreateEvent = NULL;
static WSAEventSelectFunc gs_WSAEventSelect = NULL;
static WSAWaitForMultipleEventsFunc gs_WSAWaitForMultipleEvents = NULL;
static WSAEnumNetworkEventsFunc gs_WSAEnumNetworkEvents = NULL;
/* This structure will be used to pass data on to the thread that handles socket events.
*/
typedef struct thread_data{
HWND hEvtWin;
unsigned long msgnumber;
unsigned long fd;
unsigned long lEvent;
}thread_data;
#endif
static HMODULE gs_wsock32dll = 0; static HMODULE gs_wsock32dll = 0;
#ifdef __WXWINCE__
/* This thread handles socket events on WinCE using WSAEventSelect() as WSAAsyncSelect is not supported.
* When an event occures for the socket, it is checked what kind of event happend and the correct message gets posted
* so that the hidden window can handle it as it would in other MSW builds.
*/
DWORD WINAPI SocketThread(LPVOID data)
{
WSANETWORKEVENTS NetworkEvents;
thread_data* d = (thread_data *)data;
HANDLE NetworkEvent = gs_WSACreateEvent();
gs_WSAEventSelect(d->fd, NetworkEvent, d->lEvent);
while(socket_running)
{
if ((gs_WSAWaitForMultipleEvents(1, &NetworkEvent, FALSE,INFINITE, FALSE)) == WAIT_FAILED)
{
printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
return 0;
}
if (gs_WSAEnumNetworkEvents(d->fd ,NetworkEvent, &NetworkEvents) == SOCKET_ERROR)
{
printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
return 0;
}
long flags = NetworkEvents.lNetworkEvents;
if (flags & FD_READ)
::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_READ);
if (flags & FD_WRITE)
::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_WRITE);
if (flags & FD_OOB)
::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_OOB);
if (flags & FD_ACCEPT)
::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_ACCEPT);
if (flags & FD_CONNECT)
::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_CONNECT);
if (flags & FD_CLOSE)
::PostMessage(d->hEvtWin, d->msgnumber,d->fd, FD_CLOSE);
}
gs_WSAEventSelect(d->fd, NetworkEvent, 0);
ExitThread(0);
return 0;
}
#endif
bool GSocketGUIFunctionsTableConcrete::CanUseEventLoop() bool GSocketGUIFunctionsTableConcrete::CanUseEventLoop()
{ return true; } { return true; }
@@ -151,19 +238,53 @@ bool GSocketGUIFunctionsTableConcrete::OnInit()
/* Load WSAAsyncSelect from wsock32.dll (we don't link against it /* Load WSAAsyncSelect from wsock32.dll (we don't link against it
statically to avoid dependency on wsock32.dll for apps that don't use statically to avoid dependency on wsock32.dll for apps that don't use
sockets): */ sockets): */
gs_wsock32dll = LoadLibraryA("wsock32.dll"); #ifndef __WXWINCE__
gs_wsock32dll = LoadLibrary(wxT("wsock32.dll"));
if (!gs_wsock32dll) if (!gs_wsock32dll)
return false; return false;
gs_WSAAsyncSelect =(WSAAsyncSelectFunc)GetProcAddress(gs_wsock32dll, gs_WSAAsyncSelect =(WSAAsyncSelectFunc)GetProcAddress(gs_wsock32dll,
"WSAAsyncSelect"); wxT("WSAAsyncSelect"));
if (!gs_WSAAsyncSelect) if (!gs_WSAAsyncSelect)
return false; return false;
#else
/* On WinCE we load ws2.dll which will provide the needed functions.
*/
gs_wsock32dll = LoadLibrary(wxT("ws2.dll"));
if (!gs_wsock32dll)
return false;
gs_WSAEventSelect =(WSAEventSelectFunc)GetProcAddress(gs_wsock32dll,
wxT("WSAEventSelect"));
if (!gs_WSAEventSelect)
return false;
gs_WSACreateEvent =(WSACreateEventFunc)GetProcAddress(gs_wsock32dll,
wxT("WSACreateEvent"));
if (!gs_WSACreateEvent)
return false;
gs_WSAWaitForMultipleEvents =(WSAWaitForMultipleEventsFunc)GetProcAddress(gs_wsock32dll,
wxT("WSAWaitForMultipleEvents"));
if (!gs_WSAWaitForMultipleEvents)
return false;
gs_WSAEnumNetworkEvents =(WSAEnumNetworkEventsFunc)GetProcAddress(gs_wsock32dll,
wxT("WSAEnumNetworkEvents"));
if (!gs_WSAEnumNetworkEvents)
return false;
currSocket = 0;
#endif
return true; return true;
} }
void GSocketGUIFunctionsTableConcrete::OnExit() void GSocketGUIFunctionsTableConcrete::OnExit()
{ {
#ifdef __WXWINCE__
/* Delete the threads here */
for(unsigned int i=0; i < currSocket; i++)
CloseHandle(hThread[i]);
#endif
/* Destroy internal window */ /* Destroy internal window */
DestroyWindow(hWin); DestroyWindow(hWin);
UnregisterClass(CLASSNAME, INSTANCE); UnregisterClass(CLASSNAME, INSTANCE);
@@ -303,8 +424,21 @@ void GSocketGUIFunctionsTableConcrete::Enable_Events(GSocket *socket)
*/ */
long lEvent = socket->m_server? long lEvent = socket->m_server?
FD_ACCEPT : (FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE); FD_ACCEPT : (FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
#ifndef __WXWINCE__
gs_WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, lEvent); gs_WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, lEvent);
#else
/*
* WinCE creates a thread for socket event handling.
* All needed parameters get passed through the thread_data structure.
*/
socket_running = true;
thread_data* d = new thread_data;
d->lEvent = lEvent;
d->hEvtWin = hWin;
d->msgnumber = socket->m_msgnumber;
d->fd = socket->m_fd;
hThread[currSocket++] = CreateThread(NULL, 0, &SocketThread,(LPVOID)d, 0, NULL);
#endif
} }
} }
@@ -317,7 +451,13 @@ void GSocketGUIFunctionsTableConcrete::Disable_Events(GSocket *socket)
if (socket->m_fd != INVALID_SOCKET) if (socket->m_fd != INVALID_SOCKET)
{ {
#ifndef __WXWINCE__
gs_WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, 0); gs_WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, 0);
#else
//Destroy the thread
//TODO: This needs to be changed, maybe using another global event that could be triggered.
socket_running = false;
#endif
} }
} }