1 /* ------------------------------------------------------------------------- 
   2  * Project: GSocket (Generic Socket) 
   4  * Author:  Guillermo Rodriguez Garcia <guille@iies.es> 
   5  * Purpose: GSocket GUI-specific MSW code 
   7  * ------------------------------------------------------------------------- 
  11  * TODO: for WinCE we need to replace WSAAsyncSelect 
  12  * (Windows message-based notification of network events for a socket) 
  13  * with another mechanism. 
  14  * We may need to have a separate thread that polls for socket events 
  15  * using select() and sends a message to the main thread. 
  19  * PLEASE don't put C++ comments here - this is a C source file. 
  22 /* including rasasync.h (included from windows.h itself included from 
  23  * wx/setup.h and/or winsock.h results in this warning for 
  24  * RPCNOTIFICATION_ROUTINE 
  27 #  pragma warning(disable:4115) /* named type definition in parentheses */ 
  30 /* This needs to be before the wx/defs/h inclusion 
  38 #ifndef __GSOCKET_STANDALONE__ 
  39 #   include "wx/platform.h" 
  40 #   include "wx/setup.h" 
  43 #if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) 
  45 #ifndef __GSOCKET_STANDALONE__ 
  47 #include "wx/msw/gsockmsw.h" 
  48 #include "wx/gsocket.h" 
  50 HINSTANCE 
wxGetInstance(void); 
  51 #define INSTANCE wxGetInstance() 
  58 /* If not using wxWindows, a global var called hInst must 
  59  * be available and it must contain the app's instance 
  62 #define INSTANCE hInst 
  64 #endif /* __GSOCKET_STANDALONE__ */ 
  71 #include "wx/msw/wince/net.h" 
  83 #  pragma warning(default:4115) /* named type definition in parentheses */ 
  86 #define CLASSNAME  TEXT("_GSocket_Internal_Window_Class") 
  88 /* implemented in utils.cpp */ 
  89 extern WXDLLIMPEXP_BASE HWND
 
  90 wxCreateHiddenWindow(LPCTSTR 
*pclassname
, LPCTSTR classname
, WNDPROC wndproc
); 
  92 /* Maximum number of different GSocket objects at a given time. 
  93  * This value can be modified at will, but it CANNOT be greater 
  94  * than (0x7FFF - WM_USER + 1) 
  96 #define MAXSOCKETS 1024 
  98 #if (MAXSOCKETS > (0x7FFF - WM_USER + 1)) 
  99 #error "MAXSOCKETS is too big!" 
 103 /* Global variables */ 
 105 extern HINSTANCE INSTANCE
; 
 107 static CRITICAL_SECTION critical
; 
 108 static GSocket
* socketList
[MAXSOCKETS
]; 
 109 static int firstAvailable
; 
 111 /* Global initializers */ 
 113 int _GSocket_GUI_Init(void) 
 115   static LPCTSTR pclassname 
= NULL
; 
 118   /* Create internal window for event notifications */ 
 119   hWin 
= wxCreateHiddenWindow(&pclassname
, CLASSNAME
, _GSocket_Internal_WinProc
); 
 123   /* Initialize socket list */ 
 124   InitializeCriticalSection(&critical
); 
 126   for (i 
= 0; i 
< MAXSOCKETS
; i
++) 
 128     socketList
[i
] = NULL
; 
 135 void _GSocket_GUI_Cleanup(void) 
 137   /* Destroy internal window */ 
 139   UnregisterClass(CLASSNAME
, INSTANCE
); 
 141   /* Delete critical section */ 
 142   DeleteCriticalSection(&critical
); 
 145 /* Per-socket GUI initialization / cleanup */ 
 147 int _GSocket_GUI_Init_Socket(GSocket 
*socket
) 
 151   /* Allocate a new message number for this socket */ 
 152   EnterCriticalSection(&critical
); 
 155   while (socketList
[i
] != NULL
) 
 157     i 
= (i 
+ 1) % MAXSOCKETS
; 
 159     if (i 
== firstAvailable
)    /* abort! */ 
 161       LeaveCriticalSection(&critical
); 
 165   socketList
[i
] = socket
; 
 166   firstAvailable 
= (i 
+ 1) % MAXSOCKETS
; 
 167   socket
->m_msgnumber 
= (i 
+ WM_USER
); 
 169   LeaveCriticalSection(&critical
); 
 174 void _GSocket_GUI_Destroy_Socket(GSocket 
*socket
) 
 176   /* Remove the socket from the list */ 
 177   EnterCriticalSection(&critical
); 
 178   socketList
[(socket
->m_msgnumber 
- WM_USER
)] = NULL
; 
 179   LeaveCriticalSection(&critical
); 
 182 /* Windows proc for asynchronous event handling */ 
 184 LRESULT CALLBACK 
_GSocket_Internal_WinProc(HWND hWnd
, 
 191   GSocketCallback cback
; 
 194   if (uMsg 
>= WM_USER 
&& uMsg 
<= (WM_USER 
+ MAXSOCKETS 
- 1)) 
 196     EnterCriticalSection(&critical
); 
 197     socket 
= socketList
[(uMsg 
- WM_USER
)]; 
 198     event 
= (GSocketEvent
) -1; 
 202     /* Check that the socket still exists (it has not been 
 203      * destroyed) and for safety, check that the m_fd field 
 204      * is what we expect it to be. 
 206     if ((socket 
!= NULL
) && (socket
->m_fd 
== wParam
)) 
 208       switch WSAGETSELECTEVENT(lParam
) 
 210         case FD_READ
:    event 
= GSOCK_INPUT
; break; 
 211         case FD_WRITE
:   event 
= GSOCK_OUTPUT
; break; 
 212         case FD_ACCEPT
:  event 
= GSOCK_CONNECTION
; break; 
 215           if (WSAGETSELECTERROR(lParam
) != 0) 
 218             event 
= GSOCK_CONNECTION
; 
 221         case FD_CLOSE
:   event 
= GSOCK_LOST
; break; 
 226         cback 
= socket
->m_cbacks
[event
]; 
 227         data 
= socket
->m_data
[event
]; 
 229         if (event 
== GSOCK_LOST
) 
 230           socket
->m_detected 
= GSOCK_LOST_FLAG
; 
 232           socket
->m_detected 
|= (1 << event
); 
 236     /* OK, we can now leave the critical section because we have 
 237      * already obtained the callback address (we make no further 
 238      * accesses to socket->whatever). However, the app should 
 239      * be prepared to handle events from a socket that has just 
 242     LeaveCriticalSection(&critical
); 
 245       (cback
)(socket
, event
, data
); 
 250     return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
); 
 253 /* _GSocket_Enable_Events: 
 254  *  Enable all event notifications; we need to be notified of all 
 255  *  events for internal processing, but we will only notify users 
 256  *  when an appropiate callback function has been installed. 
 258 void _GSocket_Enable_Events(GSocket 
*socket
) 
 260   assert (socket 
!= NULL
); 
 262   if (socket
->m_fd 
!= INVALID_SOCKET
) 
 264     /* We could probably just subscribe to all events regardless 
 265      * of the socket type, but MS recommends to do it this way. 
 267     long lEvent 
= socket
->m_server
? 
 268                   FD_ACCEPT 
: (FD_READ 
| FD_WRITE 
| FD_CONNECT 
| FD_CLOSE
); 
 270     WSAAsyncSelect(socket
->m_fd
, hWin
, socket
->m_msgnumber
, lEvent
); 
 274 /* _GSocket_Disable_Events: 
 275  *  Disable event notifications (when shutdowning the socket) 
 277 void _GSocket_Disable_Events(GSocket 
*socket
) 
 279   assert (socket 
!= NULL
); 
 281   if (socket
->m_fd 
!= INVALID_SOCKET
) 
 283     WSAAsyncSelect(socket
->m_fd
, hWin
, socket
->m_msgnumber
, 0); 
 287 #else /* !wxUSE_SOCKETS */ 
 290  * Translation unit shouldn't be empty, so include this typedef to make the 
 291  * compiler (VC++ 6.0, for example) happy 
 293 typedef void (*wxDummy
)(); 
 295 #endif  /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */