X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7ec698211d5d82a009ac80fb354059e9af497508..fba41cf33a3952077133d387f2cc49d211f3d893:/src/msw/gsockmsw.cpp diff --git a/src/msw/gsockmsw.cpp b/src/msw/gsockmsw.cpp index a9fad98e50..4215428a26 100644 --- a/src/msw/gsockmsw.cpp +++ b/src/msw/gsockmsw.cpp @@ -1,13 +1,15 @@ -/* ------------------------------------------------------------------------- - * Project: GSocket (Generic Socket) - * Name: src/msw/gsockmsw.cpp - * Copyright: (c) Guilhem Lavaux - * Licence: wxWindows Licence - * Author: Guillermo Rodriguez Garcia - * Purpose: GSocket GUI-specific MSW code - * CVSID: $Id$ - * ------------------------------------------------------------------------- - */ +///////////////////////////////////////////////////////////////////////////// +// Name: src/msw/gsockmsw.cpp +// Purpose: MSW-specific socket support +// Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia +// Created: April 1997 +// Copyright: (C) 1999-1997, Guilhem Lavaux +// (C) 1999-2000, Guillermo Rodriguez Garcia +// (C) 2008 Vadim Zeitlin +// RCS_ID: $Id$ +// License: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -16,6 +18,8 @@ #pragma hdrstop #endif +#if wxUSE_SOCKETS + /* * DONE: for WinCE we need to replace WSAAsyncSelect * (Windows message-based notification of network events for a socket) @@ -34,55 +38,16 @@ # pragma warning(disable:4115) /* named type definition in parentheses */ #endif -/* This needs to be before the wx/defs/h inclusion - * for some reason - */ - -#ifdef __WXWINCE__ - /* windows.h results in tons of warnings at max warning level */ -# ifdef _MSC_VER -# pragma warning(push, 1) -# endif -# include -# ifdef _MSC_VER -# pragma warning(pop) -# pragma warning(disable:4514) -# endif -#endif - -#ifndef __GSOCKET_STANDALONE__ -# include "wx/platform.h" -# include "wx/setup.h" -#endif - -#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) - -#ifndef __GSOCKET_STANDALONE__ +#include "wx/private/socket.h" +#include "wx/apptrait.h" +#include "wx/link.h" -#include "wx/msw/gsockmsw.h" -#include "wx/gsocket.h" +wxFORCE_LINK_THIS_MODULE(gsockmsw) -extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance(void); +extern "C" WXDLLIMPEXP_BASE HINSTANCE wxGetInstance(); #define INSTANCE wxGetInstance() -#else /* __GSOCKET_STANDALONE__ */ - -#include "gsockmsw.h" -#include "gsocket.h" - -/* If not using wxWidgets, a global var called hInst must - * be available and it must contain the app's instance - * handle. - */ -extern HINSTANCE hInst; -#define INSTANCE hInst - -#endif /* !__GSOCKET_STANDALONE__/__GSOCKET_STANDALONE__ */ - -#ifndef __WXWINCE__ -#include -#else -#define assert(x) +#ifdef __WXWINCE__ #include #include "wx/msw/wince/net.h" #include "wx/hashmap.h" @@ -101,13 +66,13 @@ WX_DECLARE_HASH_MAP(int,bool,wxIntegerHash,wxIntegerEqual,SocketHash); # pragma warning(default:4115) /* named type definition in parentheses */ #endif -#define CLASSNAME TEXT("_GSocket_Internal_Window_Class") +#define CLASSNAME TEXT("_wxSocket_Internal_Window_Class") /* implemented in utils.cpp */ extern "C" WXDLLIMPEXP_BASE HWND wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc); -/* Maximum number of different GSocket objects at a given time. +/* Maximum number of different wxSocket objects at a given time. * This value can be modified at will, but it CANNOT be greater * than (0x7FFF - WM_USER + 1) */ @@ -126,19 +91,19 @@ typedef struct _WSANETWORKEVENTS { long lNetworkEvents; int iErrorCode[10]; } WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS; -typedef HANDLE (PASCAL *WSACreateEventFunc)(void); +typedef HANDLE (PASCAL *WSACreateEventFunc)(); 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 wxSocket_Internal_WinProc(HWND, UINT, WPARAM, LPARAM); /* Global variables */ static HWND hWin; static CRITICAL_SECTION critical; -static GSocket* socketList[MAXSOCKETS]; +static wxSocketImplMSW *socketList[MAXSOCKETS]; static int firstAvailable; #ifndef __WXWINCE__ @@ -211,21 +176,33 @@ DWORD WINAPI SocketThread(LPVOID data) } #endif +// ---------------------------------------------------------------------------- +// MSW implementation of wxSocketManager +// ---------------------------------------------------------------------------- -bool GSocketGUIFunctionsTableConcrete::CanUseEventLoop() +class wxSocketMSWManager : public wxSocketManager { - return true; -} +public: + virtual bool OnInit(); + virtual void OnExit(); + + virtual wxSocketImpl *CreateSocket(wxSocketBase& wxsocket) + { + return new wxSocketImplMSW(wxsocket); + } + virtual void Install_Callback(wxSocketImpl *socket, wxSocketNotify event); + virtual void Uninstall_Callback(wxSocketImpl *socket, wxSocketNotify event); +}; /* Global initializers */ -bool GSocketGUIFunctionsTableConcrete::OnInit() +bool wxSocketMSWManager::OnInit() { static LPCTSTR pclassname = NULL; int i; /* Create internal window for event notifications */ - hWin = wxCreateHiddenWindow(&pclassname, CLASSNAME, _GSocket_Internal_WinProc); + hWin = wxCreateHiddenWindow(&pclassname, CLASSNAME, wxSocket_Internal_WinProc); if (!hWin) return false; @@ -278,10 +255,12 @@ bool GSocketGUIFunctionsTableConcrete::OnInit() currSocket = 0; #endif - return true; + // finally initialize WinSock + WSADATA wsaData; + return WSAStartup((1 << 8) | 1, &wsaData) == 0; } -void GSocketGUIFunctionsTableConcrete::OnExit() +void wxSocketMSWManager::OnExit() { #ifdef __WXWINCE__ /* Delete the threads here */ @@ -301,18 +280,19 @@ void GSocketGUIFunctionsTableConcrete::OnExit() /* Delete critical section */ DeleteCriticalSection(&critical); + + WSACleanup(); } /* Per-socket GUI initialization / cleanup */ -bool GSocketGUIFunctionsTableConcrete::Init_Socket(GSocket *socket) +wxSocketImplMSW::wxSocketImplMSW(wxSocketBase& wxsocket) + : wxSocketImpl(wxsocket) { - int i; - /* Allocate a new message number for this socket */ EnterCriticalSection(&critical); - i = firstAvailable; + int i = firstAvailable; while (socketList[i] != NULL) { i = (i + 1) % MAXSOCKETS; @@ -320,90 +300,89 @@ bool GSocketGUIFunctionsTableConcrete::Init_Socket(GSocket *socket) if (i == firstAvailable) /* abort! */ { LeaveCriticalSection(&critical); - return false; + m_msgnumber = 0; // invalid + return; } } - socketList[i] = socket; + socketList[i] = this; firstAvailable = (i + 1) % MAXSOCKETS; - socket->m_msgnumber = (i + WM_USER); + m_msgnumber = (i + WM_USER); LeaveCriticalSection(&critical); - - return true; } -void GSocketGUIFunctionsTableConcrete::Destroy_Socket(GSocket *socket) +wxSocketImplMSW::~wxSocketImplMSW() { /* Remove the socket from the list */ EnterCriticalSection(&critical); - socketList[(socket->m_msgnumber - WM_USER)] = NULL; + + if ( m_msgnumber ) + { + // we need to remove any pending messages for this socket to avoid having + // them sent to a new socket which could reuse the same message number as + // soon as we destroy this one + MSG msg; + while ( ::PeekMessage(&msg, hWin, m_msgnumber, m_msgnumber, PM_REMOVE) ) + ; + + socketList[m_msgnumber - WM_USER] = NULL; + } + //else: the socket has never been created successfully + LeaveCriticalSection(&critical); } /* Windows proc for asynchronous event handling */ -LRESULT CALLBACK _GSocket_Internal_WinProc(HWND hWnd, +LRESULT CALLBACK wxSocket_Internal_WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - GSocket *socket; - GSocketEvent event; - GSocketCallback cback; - char *data; + wxSocketImplMSW *socket; + wxSocketNotify event; if (uMsg >= WM_USER && uMsg <= (WM_USER + MAXSOCKETS - 1)) { EnterCriticalSection(&critical); socket = socketList[(uMsg - WM_USER)]; - event = (GSocketEvent) -1; - cback = NULL; - data = NULL; + event = (wxSocketNotify) -1; /* Check that the socket still exists (it has not been * destroyed) and for safety, check that the m_fd field * is what we expect it to be. */ - if ((socket != NULL) && (socket->m_fd == wParam)) + if ((socket != NULL) && ((WPARAM)socket->m_fd == wParam)) { switch WSAGETSELECTEVENT(lParam) { - case FD_READ: event = GSOCK_INPUT; break; - case FD_WRITE: event = GSOCK_OUTPUT; break; - case FD_ACCEPT: event = GSOCK_CONNECTION; break; + case FD_READ: event = wxSOCKET_INPUT; break; + case FD_WRITE: event = wxSOCKET_OUTPUT; break; + case FD_ACCEPT: event = wxSOCKET_CONNECTION; break; case FD_CONNECT: { if (WSAGETSELECTERROR(lParam) != 0) - event = GSOCK_LOST; + event = wxSOCKET_LOST; else - event = GSOCK_CONNECTION; + event = wxSOCKET_CONNECTION; break; } - case FD_CLOSE: event = GSOCK_LOST; break; + case FD_CLOSE: event = wxSOCKET_LOST; break; } if (event != -1) { - cback = socket->m_cbacks[event]; - data = socket->m_data[event]; - - if (event == GSOCK_LOST) - socket->m_detected = GSOCK_LOST_FLAG; + if (event == wxSOCKET_LOST) + socket->m_detected = wxSOCKET_LOST_FLAG; else socket->m_detected |= (1 << event); } } - /* OK, we can now leave the critical section because we have - * already obtained the callback address (we make no further - * accesses to socket->whatever). However, the app should - * be prepared to handle events from a socket that has just - * been closed! - */ LeaveCriticalSection(&critical); - if (cback != NULL) - (cback)(socket, event, data); + if ( socket ) + socket->NotifyOnStateChange(event); return (LRESULT) 0; } @@ -411,14 +390,15 @@ LRESULT CALLBACK _GSocket_Internal_WinProc(HWND hWnd, return DefWindowProc(hWnd, uMsg, wParam, lParam); } -/* _GSocket_Enable_Events: +/* * Enable all event notifications; we need to be notified of all * events for internal processing, but we will only notify users - * when an appropiate callback function has been installed. + * when an appropriate callback function has been installed. */ -void GSocketGUIFunctionsTableConcrete::Enable_Events(GSocket *socket) +void wxSocketMSWManager::Install_Callback(wxSocketImpl *socket_, + wxSocketNotify WXUNUSED(event)) { - assert (socket != NULL); + wxSocketImplMSW * const socket = static_cast(socket_); if (socket->m_fd != INVALID_SOCKET) { @@ -446,12 +426,13 @@ void GSocketGUIFunctionsTableConcrete::Enable_Events(GSocket *socket) } } -/* _GSocket_Disable_Events: - * Disable event notifications (when shutdowning the socket) +/* + * Disable event notifications (used when shutting down the socket) */ -void GSocketGUIFunctionsTableConcrete::Disable_Events(GSocket *socket) +void wxSocketMSWManager::Uninstall_Callback(wxSocketImpl *socket_, + wxSocketNotify WXUNUSED(event)) { - assert (socket != NULL); + wxSocketImplMSW * const socket = static_cast(socket_); if (socket->m_fd != INVALID_SOCKET) { @@ -464,12 +445,17 @@ void GSocketGUIFunctionsTableConcrete::Disable_Events(GSocket *socket) } } -#else /* !wxUSE_SOCKETS */ - -/* - * Translation unit shouldn't be empty, so include this typedef to make the - * compiler (VC++ 6.0, for example) happy - */ -typedef void (*wxDummy)(); +// set the wxBase variable to point to our wxSocketManager implementation +// +// see comments in wx/apptrait.h for the explanation of why do we do it +// like this +static struct ManagerSetter +{ + ManagerSetter() + { + static wxSocketMSWManager s_manager; + wxAppTraits::SetDefaultSocketManager(&s_manager); + } +} gs_managerSetter; -#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */ +#endif // wxUSE_SOCKETS