]> git.saurik.com Git - wxWidgets.git/commitdiff
replaced my recent GSocket_SetReuseAddr() addition with GSocket_SetReusable() from...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 25 Jul 2004 17:06:01 +0000 (17:06 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 25 Jul 2004 17:06:01 +0000 (17:06 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28494 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/latex/wx/socket.tex
include/wx/gsocket.h
include/wx/msw/gsockmsw.h
include/wx/socket.h
src/common/socket.cpp
src/unix/gsocket.c

index 1c8d64aa7386d9cedfcfa059eeebf83b73af3467..e8741147d0ed59590e85fda89480c0e09b2bad71 100644 (file)
@@ -593,6 +593,7 @@ The following flags can be used:
 \twocolitem{{\bf wxSOCKET\_NOWAIT}}{Read/write as much data as possible and return immediately.}
 \twocolitem{{\bf wxSOCKET\_WAITALL}}{Wait for all required data to be read/written unless an error occurs.}
 \twocolitem{{\bf wxSOCKET\_BLOCK}}{Block the GUI (do not yield) while reading/writing data.}
 \twocolitem{{\bf wxSOCKET\_NOWAIT}}{Read/write as much data as possible and return immediately.}
 \twocolitem{{\bf wxSOCKET\_WAITALL}}{Wait for all required data to be read/written unless an error occurs.}
 \twocolitem{{\bf wxSOCKET\_BLOCK}}{Block the GUI (do not yield) while reading/writing data.}
+\twocolitem{{\bf wxSOCKET\_REUSEADDR}}{Allows the use of an in-use port (wxServerSocket only)}
 \end{twocollist}
 
 A brief overview on how to use these flags follows.
 \end{twocollist}
 
 A brief overview on how to use these flags follows.
@@ -626,6 +627,13 @@ during IO calls, so the GUI will remain blocked until the operation
 completes. If it is not used, then the application must take extra
 care to avoid unwanted reentrance.
 
 completes. If it is not used, then the application must take extra
 care to avoid unwanted reentrance.
 
+The {\bf wxSOCKET\_REUSEADDR} flag controls the use of the SO_REUSEADDR standard
+setsockopt() flag. This flag allows the socket to bind to a port that is already in use.
+This is mostly used on UNIX-based systems to allow rapid starting and stopping of a server - 
+otherwise you may have to wait several minutes for the port to become available.
+This option can have suprising platform dependent behavior, check the documentation for
+your platforms implementation of setsockopt().
+
 So:
 
 {\bf wxSOCKET\_NONE} will try to read at least SOME data, no matter how much.
 So:
 
 {\bf wxSOCKET\_NONE} will try to read at least SOME data, no matter how much.
@@ -639,6 +647,8 @@ the data.
 {\bf wxSOCKET\_BLOCK} has nothing to do with the previous flags and
 it controls whether the GUI blocks.
 
 {\bf wxSOCKET\_BLOCK} has nothing to do with the previous flags and
 it controls whether the GUI blocks.
 
+(\bf wxSOCKET\_REUSEADDR} controls special platform-specific behavior for wxServerSocket.
+
 %
 % SetNotify
 %
 %
 % SetNotify
 %
index 3b0faf040bbb65201f68223473415044d461c566..3301e79511c71024cace07955bc218b5cc6f3a3a 100644 (file)
@@ -235,6 +235,15 @@ GSocket *GSocket_WaitConnection(GSocket *socket);
  */
 GSocketError GSocket_Connect(GSocket *socket, GSocketStream stream);
 
  */
 GSocketError GSocket_Connect(GSocket *socket, GSocketStream stream);
 
+/* 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);
 
 /* Datagram sockets */
 
 
 /* Datagram sockets */
 
@@ -277,7 +286,6 @@ GSocketError GSocket_GetSockOpt(GSocket *socket, int level, int optname,
 
 GSocketError GSocket_SetSockOpt(GSocket *socket, int level, int optname, 
                                 const void *optval, int optlen);
 
 GSocketError GSocket_SetSockOpt(GSocket *socket, int level, int optname, 
                                 const void *optval, int optlen);
-GSocketError GSocket_SetReuseAddr(GSocket *socket);
 
 void GSocket_Streamed(GSocket *socket);
 void GSocket_Unstreamed(GSocket *socket);
 
 void GSocket_Streamed(GSocket *socket);
 void GSocket_Unstreamed(GSocket *socket);
index a000ababea62464627de6c9761f83050627598b2..3961fc942905377b563142d42e099234a15b30ad 100644 (file)
@@ -50,6 +50,7 @@ struct _GSocket
   int m_stream;
   int m_oriented;
   int m_establishing;
   int m_stream;
   int m_oriented;
   int m_establishing;
+  int m_reusable;
   struct timeval m_timeout;
 
   /* Callbacks */
   struct timeval m_timeout;
 
   /* Callbacks */
index 90e99f7f623dc23dbd7e558ca1dc2170b7a02046..03cc2fb1bddc2eb032504f184f0d8f9c8c7f7f39 100644 (file)
@@ -74,7 +74,8 @@ enum
   wxSOCKET_NONE = 0,
   wxSOCKET_NOWAIT = 1,
   wxSOCKET_WAITALL = 2,
   wxSOCKET_NONE = 0,
   wxSOCKET_NOWAIT = 1,
   wxSOCKET_WAITALL = 2,
-  wxSOCKET_BLOCK = 4
+  wxSOCKET_BLOCK = 4,
+  wxSOCKET_REUSEADDR = 8
 };
 
 enum wxSocketType
 };
 
 enum wxSocketType
index 848e383c4b1449ddf9317ddf7944f903776f652b..043eb9a07d176ea2836f2bfe855ab851f3668a3f 100644 (file)
@@ -1068,6 +1068,11 @@ wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
         // Setup the socket as server
 
     GSocket_SetLocal(m_socket, addr_man.GetAddress());
         // Setup the socket as server
 
     GSocket_SetLocal(m_socket, addr_man.GetAddress());
+    
+    if (GetFlags() & wxSOCKET_REUSEADDR) {
+        GSocket_SetReusable(m_socket);
+    }
+
     if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
     {
         GSocket_destroy(m_socket);
     if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
     {
         GSocket_destroy(m_socket);
index 28b5f54307b88a2f2f2ff7056ce8d036fc5b8e7e..6de6e941a81a7edb03f79a9cb6e4bc89f6590883 100644 (file)
@@ -197,7 +197,7 @@ void GSocket_SetGUIFunctions(struct GSocketGUIFunctionsTable *guifunc)
 {
   gs_gui_functions = guifunc;
 }
 {
   gs_gui_functions = guifunc;
 }
-         
+
 int GSocket_Init(void)
 {
   if (gs_gui_functions)
 int GSocket_Init(void)
 {
   if (gs_gui_functions)
@@ -437,11 +437,11 @@ GAddress *GSocket_GetPeer(GSocket *socket)
  *  Sets up this socket as a server. The local address must have been
  *  set with GSocket_SetLocal() before GSocket_SetServer() is called.
  *  Returns GSOCK_NOERROR on success, one of the following otherwise:
  *  Sets up this socket as a server. The local address must have been
  *  set with GSocket_SetLocal() before GSocket_SetServer() is called.
  *  Returns GSOCK_NOERROR on success, one of the following otherwise:
- * 
+ *
  *  Error codes:
  *    GSOCK_INVSOCK - the socket is in use.
  *    GSOCK_INVADDR - the local address has not been set.
  *  Error codes:
  *    GSOCK_INVSOCK - the socket is in use.
  *    GSOCK_INVADDR - the local address has not been set.
- *    GSOCK_IOERR   - low-level error. 
+ *    GSOCK_IOERR   - low-level error.
  */
 GSocketError GSocket_SetServer(GSocket *sck)
 {
  */
 GSocketError GSocket_SetServer(GSocket *sck)
 {
@@ -483,6 +483,12 @@ GSocketError GSocket_SetServer(GSocket *sck)
 #endif
   _GSocket_Enable_Events(sck);
 
 #endif
   _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(socket->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.
   /* Bind to the local address,
    * retrieve the actual address bound,
    * and listen up to 5 connections.
@@ -511,7 +517,7 @@ GSocketError GSocket_SetServer(GSocket *sck)
  *    GSOCK_TIMEDOUT   - timeout, no incoming connections.
  *    GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking.
  *    GSOCK_MEMERR     - couldn't allocate memory.
  *    GSOCK_TIMEDOUT   - timeout, no incoming connections.
  *    GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking.
  *    GSOCK_MEMERR     - couldn't allocate memory.
- *    GSOCK_IOERR      - low-level error. 
+ *    GSOCK_IOERR      - low-level error.
  */
 GSocket *GSocket_WaitConnection(GSocket *socket)
 {
  */
 GSocket *GSocket_WaitConnection(GSocket *socket)
 {
@@ -594,6 +600,16 @@ GSocket *GSocket_WaitConnection(GSocket *socket)
   return connection;
 }
 
   return connection;
 }
 
+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:
 /* Client specific parts */
 
 /* GSocket_Connect:
@@ -617,7 +633,7 @@ GSocket *GSocket_WaitConnection(GSocket *socket)
  *    GSOCK_TIMEDOUT   - timeout, the connection failed.
  *    GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only)
  *    GSOCK_MEMERR     - couldn't allocate memory.
  *    GSOCK_TIMEDOUT   - timeout, the connection failed.
  *    GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only)
  *    GSOCK_MEMERR     - couldn't allocate memory.
- *    GSOCK_IOERR      - low-level error. 
+ *    GSOCK_IOERR      - low-level error.
  */
 GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
 {
  */
 GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
 {
@@ -803,7 +819,7 @@ int GSocket_Read(GSocket *socket, char *buffer, int size)
 
   /* Disable events during query of socket status */
   _GSocket_Disable(socket, GSOCK_INPUT);
 
   /* Disable events during query of socket status */
   _GSocket_Disable(socket, GSOCK_INPUT);
-    
+
   /* If the socket is blocking, wait for data (with a timeout) */
   if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
     /* We no longer return here immediately, otherwise socket events would not be re-enabled! */
   /* If the socket is blocking, wait for data (with a timeout) */
   if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
     /* We no longer return here immediately, otherwise socket events would not be re-enabled! */
@@ -815,7 +831,7 @@ int GSocket_Read(GSocket *socket, char *buffer, int size)
     else
       ret = _GSocket_Recv_Dgram(socket, buffer, size);
   }
     else
       ret = _GSocket_Recv_Dgram(socket, buffer, size);
   }
-    
+
   if (ret == -1)
   {
     if (errno == EWOULDBLOCK)
   if (ret == -1)
   {
     if (errno == EWOULDBLOCK)
@@ -823,19 +839,19 @@ int GSocket_Read(GSocket *socket, char *buffer, int size)
     else
       socket->m_error = GSOCK_IOERR;
   }
     else
       socket->m_error = GSOCK_IOERR;
   }
-  
+
   /* Enable events again now that we are done processing */
   _GSocket_Enable(socket, GSOCK_INPUT);
   /* Enable events again now that we are done processing */
   _GSocket_Enable(socket, GSOCK_INPUT);
-  
+
   return ret;
 }
 
 int GSocket_Write(GSocket *socket, const char *buffer, int size)
   return ret;
 }
 
 int GSocket_Write(GSocket *socket, const char *buffer, int size)
-{                        
+{
   int ret;
 
   assert(socket != NULL);
   int ret;
 
   assert(socket != NULL);
-  
+
   GSocket_Debug(( "GSocket_Write #1, size %d\n", size ));
 
   if (socket->m_fd == INVALID_SOCKET || socket->m_server)
   GSocket_Debug(( "GSocket_Write #1, size %d\n", size ));
 
   if (socket->m_fd == INVALID_SOCKET || socket->m_server)
@@ -857,7 +873,7 @@ int GSocket_Write(GSocket *socket, const char *buffer, int size)
     ret = _GSocket_Send_Stream(socket, buffer, size);
   else
     ret = _GSocket_Send_Dgram(socket, buffer, size);
     ret = _GSocket_Send_Stream(socket, buffer, size);
   else
     ret = _GSocket_Send_Dgram(socket, buffer, size);
-    
+
   GSocket_Debug(( "GSocket_Write #4, size %d\n", size ));
 
   if (ret == -1)
   GSocket_Debug(( "GSocket_Write #4, size %d\n", size ));
 
   if (ret == -1)
@@ -881,7 +897,7 @@ int GSocket_Write(GSocket *socket, const char *buffer, int size)
     _GSocket_Enable(socket, GSOCK_OUTPUT);
     return -1;
   }
     _GSocket_Enable(socket, GSOCK_OUTPUT);
     return -1;
   }
-  
+
   GSocket_Debug(( "GSocket_Write #5, size %d ret %d\n", size, ret ));
 
   return ret;
   GSocket_Debug(( "GSocket_Write #5, size %d ret %d\n", size, ret ));
 
   return ret;
@@ -959,7 +975,7 @@ GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
         {
           socket->m_detected = GSOCK_LOST_FLAG;
           socket->m_establishing = FALSE;
         {
           socket->m_detected = GSOCK_LOST_FLAG;
           socket->m_establishing = FALSE;
-      
+
           /* LOST event: Abort any further processing */
           return (GSOCK_LOST_FLAG & flags);
         }
           /* LOST event: Abort any further processing */
           return (GSOCK_LOST_FLAG & flags);
         }
@@ -1064,7 +1080,7 @@ GSocketError GSocket_GetError(GSocket *socket)
  *   operation, there is still data available, the callback function will
  *   be called again.
  * GSOCK_OUTPUT:
  *   operation, there is still data available, the callback function will
  *   be called again.
  * GSOCK_OUTPUT:
- *   The socket is available for writing. That is, the next write call 
+ *   The socket is available for writing. That is, the next write call
  *   won't block. This event is generated only once, when the connection is
  *   first established, and then only if a call failed with GSOCK_WOULDBLOCK,
  *   when the output buffer empties again. This means that the app should
  *   won't block. This event is generated only once, when the connection is
  *   first established, and then only if a call failed with GSOCK_WOULDBLOCK,
  *   when the output buffer empties again. This means that the app should
@@ -1134,25 +1150,16 @@ GSocketError GSocket_GetSockOpt(GSocket *socket, int level, int optname,
     return GSOCK_OPTERR;
 }
 
     return GSOCK_OPTERR;
 }
 
-GSocketError GSocket_SetSockOpt(GSocket *socket, int level, int optname, 
+GSocketError GSocket_SetSockOpt(GSocket *socket, int level, int optname,
                                 const void *optval, int optlen)
 {
     if (setsockopt(socket->m_fd, level, optname, optval, optlen) == 0)
     {
                                 const void *optval, int optlen)
 {
     if (setsockopt(socket->m_fd, level, optname, optval, optlen) == 0)
     {
-        return GSOCK_NOERROR;       
+        return GSOCK_NOERROR;
     }
     return GSOCK_OPTERR;
 }
 
     }
     return GSOCK_OPTERR;
 }
 
-GSocketError GSocket_SetReuseAddr(GSocket *socket)
-{
-  /* allow a socket to re-bind if the socket is in the TIME_WAIT
-     state after being previously closed.
-   */
-  u_long arg = 1;
-  setsockopt(socket->m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(u_long));
-}
-
 void GSocket_Streamed(GSocket *socket)
 {
     socket->m_stream = TRUE;
 void GSocket_Streamed(GSocket *socket)
 {
     socket->m_stream = TRUE;
@@ -1702,7 +1709,7 @@ GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
     address->m_error = GSOCK_INVPORT;
     return GSOCK_INVPORT;
   }
     address->m_error = GSOCK_INVPORT;
     return GSOCK_INVPORT;
   }
+
   se = getservbyname(port, protocol);
   if (!se)
   {
   se = getservbyname(port, protocol);
   if (!se)
   {
@@ -1734,7 +1741,7 @@ GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
 
   assert(address != NULL);
   CHECK_ADDRESS(address, INET);
 
   assert(address != NULL);
   CHECK_ADDRESS(address, INET);
+
   addr = (struct sockaddr_in *)address->m_addr;
   addr->sin_port = htons(port);
 
   addr = (struct sockaddr_in *)address->m_addr;
   addr->sin_port = htons(port);
 
@@ -1747,7 +1754,7 @@ GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t
   char *addr_buf;
   struct sockaddr_in *addr;
 
   char *addr_buf;
   struct sockaddr_in *addr;
 
-  assert(address != NULL); 
+  assert(address != NULL);
   CHECK_ADDRESS(address, INET);
 
   addr = (struct sockaddr_in *)address->m_addr;
   CHECK_ADDRESS(address, INET);
 
   addr = (struct sockaddr_in *)address->m_addr;
@@ -1769,8 +1776,8 @@ unsigned long GAddress_INET_GetHostAddress(GAddress *address)
 {
   struct sockaddr_in *addr;
 
 {
   struct sockaddr_in *addr;
 
-  assert(address != NULL); 
-  CHECK_ADDRESS_RETVAL(address, INET, 0); 
+  assert(address != NULL);
+  CHECK_ADDRESS_RETVAL(address, INET, 0);
 
   addr = (struct sockaddr_in *)address->m_addr;
 
 
   addr = (struct sockaddr_in *)address->m_addr;
 
@@ -1781,8 +1788,8 @@ unsigned short GAddress_INET_GetPort(GAddress *address)
 {
   struct sockaddr_in *addr;
 
 {
   struct sockaddr_in *addr;
 
-  assert(address != NULL); 
-  CHECK_ADDRESS_RETVAL(address, INET, 0); 
+  assert(address != NULL);
+  CHECK_ADDRESS_RETVAL(address, INET, 0);
 
   addr = (struct sockaddr_in *)address->m_addr;
   return ntohs(addr->sin_port);
 
   addr = (struct sockaddr_in *)address->m_addr;
   return ntohs(addr->sin_port);
@@ -1819,9 +1826,9 @@ GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
 {
   struct sockaddr_un *addr;
 
 {
   struct sockaddr_un *addr;
 
-  assert(address != NULL); 
+  assert(address != NULL);
 
 
-  CHECK_ADDRESS(address, UNIX); 
+  CHECK_ADDRESS(address, UNIX);
 
   addr = ((struct sockaddr_un *)address->m_addr);
   strncpy(addr->sun_path, path, UNIX_SOCK_PATHLEN);
 
   addr = ((struct sockaddr_un *)address->m_addr);
   strncpy(addr->sun_path, path, UNIX_SOCK_PATHLEN);