]> git.saurik.com Git - wxWidgets.git/commitdiff
Copied gsockmsw.c revision 1.20
authorDavid Elliott <dfe@tgwbd.org>
Sun, 18 Jan 2004 22:42:07 +0000 (22:42 +0000)
committerDavid Elliott <dfe@tgwbd.org>
Sun, 18 Jan 2004 22:42:07 +0000 (22:42 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@25244 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/msw/gsockmsw.cpp [new file with mode: 0644]

diff --git a/src/msw/gsockmsw.cpp b/src/msw/gsockmsw.cpp
new file mode 100644 (file)
index 0000000..a51169e
--- /dev/null
@@ -0,0 +1,295 @@
+/* -------------------------------------------------------------------------
+ * Project: GSocket (Generic Socket)
+ * Name:    gsockmsw.c
+ * Author:  Guillermo Rodriguez Garcia <guille@iies.es>
+ * Purpose: GSocket GUI-specific MSW code
+ * CVSID:   $Id$
+ * -------------------------------------------------------------------------
+ */
+
+/*
+ * TODO: for WinCE we need to replace WSAAsyncSelect
+ * (Windows message-based notification of network events for a socket)
+ * with another mechanism.
+ * We may need to have a separate thread that polls for socket events
+ * using select() and sends a message to the main thread.
+ */
+
+/*
+ * PLEASE don't put C++ comments here - this is a C source file.
+ */
+
+/* including rasasync.h (included from windows.h itself included from
+ * wx/setup.h and/or winsock.h results in this warning for
+ * RPCNOTIFICATION_ROUTINE
+ */
+#ifdef _MSC_VER
+#  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__
+#include <windows.h>
+#endif
+
+#ifndef __GSOCKET_STANDALONE__
+#   include "wx/platform.h"
+#   include "wx/setup.h"
+#endif
+
+#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
+
+#ifndef __GSOCKET_STANDALONE__
+
+#include "wx/msw/gsockmsw.h"
+#include "wx/gsocket.h"
+
+HINSTANCE wxGetInstance(void);
+#define INSTANCE wxGetInstance()
+
+#else
+
+#include "gsockmsw.h"
+#include "gsocket.h"
+
+/* If not using wxWindows, a global var called hInst must
+ * be available and it must contain the app's instance
+ * handle.
+ */
+#define INSTANCE hInst
+
+#endif /* __GSOCKET_STANDALONE__ */
+
+#ifndef __WXWINCE__
+#include <assert.h>
+#else
+#define assert(x)
+#include <winsock.h>
+#include "wx/msw/wince/net.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+
+#include <winsock.h>
+
+#ifdef _MSC_VER
+#  pragma warning(default:4115) /* named type definition in parentheses */
+#endif
+
+#define CLASSNAME  TEXT("_GSocket_Internal_Window_Class")
+
+/* implemented in utils.cpp */
+extern WXDLLIMPEXP_BASE HWND
+wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
+
+/* Maximum number of different GSocket objects at a given time.
+ * This value can be modified at will, but it CANNOT be greater
+ * than (0x7FFF - WM_USER + 1)
+ */
+#define MAXSOCKETS 1024
+
+#if (MAXSOCKETS > (0x7FFF - WM_USER + 1))
+#error "MAXSOCKETS is too big!"
+#endif
+
+
+/* Global variables */
+
+extern HINSTANCE INSTANCE;
+static HWND hWin;
+static CRITICAL_SECTION critical;
+static GSocket* socketList[MAXSOCKETS];
+static int firstAvailable;
+
+/* Global initializers */
+
+int _GSocket_GUI_Init(void)
+{
+  static LPCTSTR pclassname = NULL;
+  int i;
+
+  /* Create internal window for event notifications */
+  hWin = wxCreateHiddenWindow(&pclassname, CLASSNAME, _GSocket_Internal_WinProc);
+  if (!hWin)
+      return FALSE;
+
+  /* Initialize socket list */
+  InitializeCriticalSection(&critical);
+
+  for (i = 0; i < MAXSOCKETS; i++)
+  {
+    socketList[i] = NULL;
+  }
+  firstAvailable = 0;
+
+  return TRUE;
+}
+
+void _GSocket_GUI_Cleanup(void)
+{
+  /* Destroy internal window */
+  DestroyWindow(hWin);
+  UnregisterClass(CLASSNAME, INSTANCE);
+
+  /* Delete critical section */
+  DeleteCriticalSection(&critical);
+}
+
+/* Per-socket GUI initialization / cleanup */
+
+int _GSocket_GUI_Init_Socket(GSocket *socket)
+{
+  int i;
+
+  /* Allocate a new message number for this socket */
+  EnterCriticalSection(&critical);
+
+  i = firstAvailable;
+  while (socketList[i] != NULL)
+  {
+    i = (i + 1) % MAXSOCKETS;
+
+    if (i == firstAvailable)    /* abort! */
+    {
+      LeaveCriticalSection(&critical);
+      return FALSE;
+    }
+  }
+  socketList[i] = socket;
+  firstAvailable = (i + 1) % MAXSOCKETS;
+  socket->m_msgnumber = (i + WM_USER);
+
+  LeaveCriticalSection(&critical);
+
+  return TRUE;
+}
+
+void _GSocket_GUI_Destroy_Socket(GSocket *socket)
+{
+  /* Remove the socket from the list */
+  EnterCriticalSection(&critical);
+  socketList[(socket->m_msgnumber - WM_USER)] = NULL;
+  LeaveCriticalSection(&critical);
+}
+
+/* Windows proc for asynchronous event handling */
+
+LRESULT CALLBACK _GSocket_Internal_WinProc(HWND hWnd,
+                                           UINT uMsg,
+                                           WPARAM wParam,
+                                           LPARAM lParam)
+{
+  GSocket *socket;
+  GSocketEvent event;
+  GSocketCallback cback;
+  char *data;
+
+  if (uMsg >= WM_USER && uMsg <= (WM_USER + MAXSOCKETS - 1))
+  {
+    EnterCriticalSection(&critical);
+    socket = socketList[(uMsg - WM_USER)];
+    event = (GSocketEvent) -1;
+    cback = NULL;
+    data = NULL;
+
+    /* 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))
+    {
+      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_CONNECT:
+        {
+          if (WSAGETSELECTERROR(lParam) != 0)
+            event = GSOCK_LOST;
+          else
+            event = GSOCK_CONNECTION;
+          break;
+        }
+        case FD_CLOSE:   event = GSOCK_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;
+        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);
+
+    return (LRESULT) 0;
+  }
+  else
+    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.
+ */
+void _GSocket_Enable_Events(GSocket *socket)
+{
+  assert (socket != NULL);
+
+  if (socket->m_fd != INVALID_SOCKET)
+  {
+    /* We could probably just subscribe to all events regardless
+     * of the socket type, but MS recommends to do it this way.
+     */
+    long lEvent = socket->m_server?
+                  FD_ACCEPT : (FD_READ | FD_WRITE | FD_CONNECT | FD_CLOSE);
+
+    WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, lEvent);
+  }
+}
+
+/* _GSocket_Disable_Events:
+ *  Disable event notifications (when shutdowning the socket)
+ */
+void _GSocket_Disable_Events(GSocket *socket)
+{
+  assert (socket != NULL);
+
+  if (socket->m_fd != INVALID_SOCKET)
+  {
+    WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber, 0);
+  }
+}
+
+#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)();
+
+#endif  /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */