#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
#ifndef __GSOCKET_STANDALONE__
-
-#include "wx/msw/gsockmsw.h"
-#include "wx/gsocket.h"
-
+# include "wx/msw/gsockmsw.h"
+# include "wx/gsocket.h"
#else
+# include "gsockmsw.h"
+# include "gsocket.h"
+#endif /* __GSOCKET_STANDALONE__ */
-#include "gsockmsw.h"
-#include "gsocket.h"
+/* redefine some GUI-only functions to do nothing in console mode */
+#if defined(wxUSE_GUI) && !wxUSE_GUI
+# define _GSocket_GUI_Init(socket) 1
+# define _GSocket_GUI_Destroy(socket)
+# define _GSocket_Enable_Events(socket)
+# define _GSocket_Disable_Events(socket)
+#endif /* wxUSE_GUI */
-#endif /* __GSOCKET_STANDALONE__ */
#include <assert.h>
#include <string.h>
/* if we use configure for MSW SOCKLEN_T will be already defined */
#ifndef SOCKLEN_T
-#define SOCKLEN_T int
+# define SOCKLEN_T int
#endif
+/* using FD_SET results in this warning */
#ifdef _MSC_VER
- /* using FD_SET results in this warning */
- #pragma warning(disable:4127) /* conditional expression is constant */
-#endif /* Visual C++ */
+# pragma warning(disable:4127) /* conditional expression is constant */
+#endif
/* Constructors / Destructors for GSocket */
GSocket *GSocket_new(void)
{
- int i;
+ int i, success;
GSocket *socket;
if ((socket = (GSocket *) malloc(sizeof(GSocket))) == NULL)
{
socket->m_cbacks[i] = NULL;
}
+ socket->m_detected = 0;
socket->m_local = NULL;
socket->m_peer = NULL;
socket->m_error = GSOCK_NOERROR;
socket->m_non_blocking = FALSE;
socket->m_timeout.tv_sec = 10 * 60; /* 10 minutes */
socket->m_timeout.tv_usec = 0;
- socket->m_detected = 0;
+ socket->m_establishing = FALSE;
/* Per-socket GUI-specific initialization */
- if (!_GSocket_GUI_Init(socket))
+ success = _GSocket_GUI_Init(socket);
+ if (!success)
{
free(socket);
return NULL;
sck->m_stream = (stream == GSOCK_STREAMED);
sck->m_oriented = TRUE;
sck->m_server = FALSE;
+ sck->m_establishing = FALSE;
/* Create the socket */
sck->m_fd = socket(sck->m_peer->m_realfamily,
*/
if ((err == WSAEWOULDBLOCK) && (sck->m_non_blocking))
{
+ sck->m_establishing = TRUE;
sck->m_error = GSOCK_WOULDBLOCK;
return GSOCK_WOULDBLOCK;
}
*/
GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
{
+#if defined(wxUSE_GUI) && !wxUSE_GUI
+
+ GSocketEventFlags result = 0;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+ static const struct timeval tv = { 0, 0 };
+
assert(socket != NULL);
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+ FD_SET(socket->m_fd, &readfds);
+ FD_SET(socket->m_fd, &writefds);
+ FD_SET(socket->m_fd, &exceptfds);
+
+ /* Check known state first */
+ result |= (GSOCK_CONNECTION_FLAG & socket->m_detected & flags);
+ result |= (GSOCK_LOST_FLAG & socket->m_detected & flags);
+
+ /* Try select now */
+ if (select(socket->m_fd + 1, &readfds, &writefds, &exceptfds, &tv) <= 0)
+ return result;
+
+ /* Check for readability */
+ if (FD_ISSET(socket->m_fd, &readfds))
+ {
+ /* Assume that closure of the socket is always reported via exceptfds */
+ if (socket->m_server && socket->m_stream)
+ result |= (GSOCK_CONNECTION_FLAG & flags);
+ else
+ result |= (GSOCK_INPUT_FLAG & flags);
+ }
+
+ /* Check for writability */
+ if (FD_ISSET(socket->m_fd, &writefds))
+ {
+ if (socket->m_establishing && !socket->m_server)
+ {
+ result |= (GSOCK_CONNECTION_FLAG & flags);
+ socket->m_establishing = FALSE;
+ socket->m_detected |= GSOCK_CONNECTION_FLAG;
+ }
+ else
+ result |= (GSOCK_OUTPUT_FLAG & flags);
+ }
+
+ /* Check for exceptions and errors */
+ if (FD_ISSET(socket->m_fd, &exceptfds))
+ {
+ result |= (GSOCK_LOST_FLAG & flags);
+ socket->m_establishing = FALSE;
+ socket->m_detected = GSOCK_LOST_FLAG;
+ }
+
+ return result;
+
+#else
+
+ assert(socket != NULL);
return flags & socket->m_detected;
+
+#endif /* !wxUSE_GUI */
}
/* Attributes */
/* Global initializers */
-bool GSocket_Init()
+bool GSocket_Init(void)
{
WSADATA wsaData;
WNDCLASS winClass;
return (WSAStartup((1 << 8) | 1, &wsaData) == 0);
}
-void GSocket_Cleanup()
+void GSocket_Cleanup(void)
{
/* Destroy internal window */
DestroyWindow(hWin);
if (socket->m_fd != INVALID_SOCKET)
{
- WSAAsyncSelect(socket->m_fd, hWin, socket->m_msgnumber,
- FD_READ | FD_WRITE | FD_ACCEPT | FD_CONNECT | FD_CLOSE);
+ /* 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);
}
}