]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/gsocket.c
Revert original UNIX C->C++ conversion and instead make it work exactly
[wxWidgets.git] / src / msw / gsocket.c
index 2ca87dd3055fc53a2d035647e9fc4050e0cca0cd..74783e0b1b9310bc4e4d77d0028ea58ed340bba6 100644 (file)
@@ -3,7 +3,7 @@
  * Name:    gsocket.c
  * Author:  Guillermo Rodriguez Garcia <guille@iies.es>
  * Purpose: GSocket main MSW file
- * Licence: The wxWindows licence
+ * Licence: The wxWidgets licence
  * CVSID:   $Id$
  * -------------------------------------------------------------------------
  */
     * warning: unreferenced formal parameter.
     */
 #  pragma warning(disable:4100)
+
+#ifdef __WXWINCE__
+    /* windows.h results in tons of warnings at max warning level */
+#   ifdef _MSC_VER
+#       pragma warning(push, 1)
+#   endif
+#   include <windows.h>
+#   ifdef _MSC_VER
+#       pragma warning(pop)
+#       pragma warning(disable:4514)
+#   endif
+#endif
+
 #endif /* _MSC_VER */
 
 #include <winsock.h>
 
 #ifndef __GSOCKET_STANDALONE__
-#  include "wx/defs.h"
-#  include "wx/setup.h"
+#   include "wx/platform.h"
+#   include "wx/setup.h"
 #endif
 
 #if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
@@ -96,11 +109,11 @@ void GSocket_SetGUIFunctions(struct GSocketGUIFunctionsTable *guifunc)
 {
   gs_gui_functions = guifunc;
 }
-         
+
 int GSocket_Init(void)
 {
   WSADATA wsaData;
-  
+
   if (gs_gui_functions)
   {
       if ( !gs_gui_functions->GUI_Init() )
@@ -117,7 +130,7 @@ void GSocket_Cleanup(void)
   {
       gs_gui_functions->GUI_Cleanup();
   }
-  
+
   /* Cleanup WinSocket */
   WSACleanup();
 }
@@ -147,6 +160,7 @@ GSocket *GSocket_new(void)
   socket->m_timeout.tv_sec  = 10 * 60;  /* 10 minutes */
   socket->m_timeout.tv_usec = 0;
   socket->m_establishing    = FALSE;
+  socket->m_reusable        = FALSE;
 
   /* Per-socket GUI-specific initialization */
   success = _GSocket_GUI_Init_Socket(socket);
@@ -362,7 +376,6 @@ GSocketError GSocket_SetServer(GSocket *sck)
   /* Initialize all fields */
   sck->m_server   = TRUE;
   sck->m_stream   = TRUE;
-  sck->m_oriented = TRUE;
 
   /* Create the socket */
   sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0);
@@ -376,6 +389,13 @@ GSocketError GSocket_SetServer(GSocket *sck)
   ioctlsocket(sck->m_fd, FIONBIO, (u_long FAR *) &arg);
   _GSocket_Enable_Events(sck);
 
+  /* allow a socket to re-bind if the socket is in the TIME_WAIT
+     state after being previously closed.
+   */
+  if (sck->m_reusable) {
+    setsockopt(sck->m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(u_long));
+  }
+
   /* Bind to the local address,
    * retrieve the actual address bound,
    * and listen up to 5 connections.
@@ -459,7 +479,6 @@ GSocket *GSocket_WaitConnection(GSocket *sck)
   /* Initialize all fields */
   connection->m_server   = FALSE;
   connection->m_stream   = TRUE;
-  connection->m_oriented = TRUE;
 
   /* Setup the peer address field */
   connection->m_peer = GAddress_new();
@@ -484,6 +503,24 @@ GSocket *GSocket_WaitConnection(GSocket *sck)
   return connection;
 }
 
+/* GSocket_SetReusable:
+*  Simply sets the m_resuable flag on the socket. GSocket_SetServer will
+*  make the appropriate setsockopt() call.
+*  Implemented as a GSocket function because clients (ie, wxSocketServer)
+*  don't have access to the GSocket struct information.
+*  Returns TRUE if the flag was set correctly, FALSE if an error occured
+*  (ie, if the parameter was NULL)
+*/
+int GSocket_SetReusable(GSocket *socket)
+{
+    /* socket must not be null, and must not be in use/already bound */
+    if (NULL != socket && socket->m_fd == INVALID_SOCKET) {
+        socket->m_reusable = TRUE;
+        return TRUE;
+    }
+    return FALSE;
+}
+
 /* Client specific parts */
 
 /* GSocket_Connect:
@@ -533,7 +570,6 @@ GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
 
   /* Streamed or dgram socket? */
   sck->m_stream   = (stream == GSOCK_STREAMED);
-  sck->m_oriented = TRUE;
   sck->m_server   = FALSE;
   sck->m_establishing = FALSE;
 
@@ -633,7 +669,6 @@ GSocketError GSocket_SetNonOriented(GSocket *sck)
   /* Initialize all fields */
   sck->m_stream   = FALSE;
   sck->m_server   = FALSE;
-  sck->m_oriented = FALSE;
 
   /* Create the socket */
   sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0);
@@ -759,7 +794,6 @@ GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
     fd_set readfds;
     fd_set writefds;
     fd_set exceptfds;
-    static const struct timeval tv = { 0, 0 };
 
     assert(socket != NULL);
 
@@ -767,7 +801,8 @@ GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
     FD_ZERO(&writefds);
     FD_ZERO(&exceptfds);
     FD_SET(socket->m_fd, &readfds);
-    FD_SET(socket->m_fd, &writefds);
+    if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG)
+      FD_SET(socket->m_fd, &writefds);
     FD_SET(socket->m_fd, &exceptfds);
 
     /* Check 'sticky' CONNECTION flag first */
@@ -784,7 +819,8 @@ GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
     }
 
     /* Try select now */
-    if (select(socket->m_fd + 1, &readfds, &writefds, &exceptfds, &tv) <= 0)
+    if (select(socket->m_fd + 1, &readfds, &writefds, &exceptfds,
+        &socket->m_timeout) <= 0)
     {
       /* What to do here? */
       return (result & flags);
@@ -795,7 +831,7 @@ GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
     {
       char c;
 
-      if (recv(socket->m_fd, &c, 1, MSG_PEEK) > 0)
+      if (!socket->m_stream || recv(socket->m_fd, &c, 1, MSG_PEEK) > 0)
       {
         result |= GSOCK_INPUT_FLAG;
       }
@@ -810,7 +846,7 @@ GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
         {
           socket->m_detected = GSOCK_LOST_FLAG;
           socket->m_establishing = FALSE;
-      
+
           /* LOST event: Abort any further processing */
           return (GSOCK_LOST_FLAG & flags);
         }
@@ -971,6 +1007,26 @@ void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags)
   }
 }
 
+GSocketError GSocket_GetSockOpt(GSocket *socket, int level, int optname,
+                                void *optval, int *optlen)
+{
+    if (getsockopt(socket->m_fd, level, optname, optval, optlen) == 0)
+    {
+        return GSOCK_NOERROR;
+    }
+    return GSOCK_OPTERR;
+}
+
+GSocketError GSocket_SetSockOpt(GSocket *socket, int level, int optname,
+                                const void *optval, int optlen)
+{
+    if (setsockopt(socket->m_fd, level, optname, optval, optlen) == 0)
+    {
+        return GSOCK_NOERROR;
+    }
+    return GSOCK_OPTERR;
+}
+
 /* Internals (IO) */
 
 /* _GSocket_Input_Timeout:
@@ -1293,7 +1349,7 @@ GSocketError _GAddress_Init_INET(GAddress *address)
   }
 
   address->m_family = GSOCK_INET;
-  address->m_realfamily = PF_INET;
+  address->m_realfamily = AF_INET;
   ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
   ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
 
@@ -1346,7 +1402,7 @@ GSocketError GAddress_INET_SetHostAddress(GAddress *address,
   CHECK_ADDRESS(address, INET);
 
   addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
-  addr->s_addr = hostaddr;
+  addr->s_addr = htonl(hostaddr);;
 
   return GSOCK_NOERROR;
 }
@@ -1435,7 +1491,7 @@ unsigned long GAddress_INET_GetHostAddress(GAddress *address)
 
   addr = (struct sockaddr_in *)address->m_addr;
 
-  return addr->sin_addr.s_addr;
+  return ntohl(addr->sin_addr.s_addr);
 }
 
 unsigned short GAddress_INET_GetPort(GAddress *address)
@@ -1464,6 +1520,10 @@ GSocketError _GAddress_Init_UNIX(GAddress *address)
 
 GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
 {
+#if defined(__BORLANDC__)
+  /* prevents unused variable message in Borland */
+  (void)path;
+#endif
   assert (address != NULL);
   address->m_error = GSOCK_INVADDR;
   return GSOCK_INVADDR;
@@ -1471,6 +1531,11 @@ GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
 
 GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
 {
+#if defined(__BORLANDC__)
+  /* prevents unused variable message in Borland */
+  (void)path;
+  (void)sbuf;
+#endif
   assert (address != NULL);
   address->m_error = GSOCK_INVADDR;
   return GSOCK_INVADDR;