]> 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\_REUSEADDR}}{Allows the use of an in-use port (wxServerSocket only)}
 \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.
 
+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.
@@ -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\_REUSEADDR} controls special platform-specific behavior for wxServerSocket.
+
 %
 % SetNotify
 %
index 3b0faf040bbb65201f68223473415044d461c566..3301e79511c71024cace07955bc218b5cc6f3a3a 100644 (file)
@@ -235,6 +235,15 @@ GSocket *GSocket_WaitConnection(GSocket *socket);
  */
 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 */
 
@@ -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_SetReuseAddr(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_reusable;
   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_BLOCK = 4
+  wxSOCKET_BLOCK = 4,
+  wxSOCKET_REUSEADDR = 8
 };
 
 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());
+    
+    if (GetFlags() & wxSOCKET_REUSEADDR) {
+        GSocket_SetReusable(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;
 }
-         
+
 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:
- * 
+ *
  *  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)
 {
@@ -483,6 +483,12 @@ GSocketError GSocket_SetServer(GSocket *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.
@@ -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_IOERR      - low-level error. 
+ *    GSOCK_IOERR      - low-level error.
  */
 GSocket *GSocket_WaitConnection(GSocket *socket)
 {
@@ -594,6 +600,16 @@ GSocket *GSocket_WaitConnection(GSocket *socket)
   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:
@@ -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_IOERR      - low-level error. 
+ *    GSOCK_IOERR      - low-level error.
  */
 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);
-    
+
   /* 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);
   }
-    
+
   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;
   }
-  
+
   /* 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)
-{                        
+{
   int ret;
 
   assert(socket != NULL);
-  
+
   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);
-    
+
   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_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;
-      
+
           /* 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:
- *   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
@@ -1134,25 +1150,16 @@ GSocketError GSocket_GetSockOpt(GSocket *socket, int level, int optname,
     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)
     {
-        return GSOCK_NOERROR;       
+        return GSOCK_NOERROR;
     }
     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;
@@ -1702,7 +1709,7 @@ GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
     address->m_error = GSOCK_INVPORT;
     return GSOCK_INVPORT;
   }
+
   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);
+
   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;
 
-  assert(address != NULL); 
+  assert(address != NULL);
   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;
 
-  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;
 
@@ -1781,8 +1788,8 @@ unsigned short GAddress_INET_GetPort(GAddress *address)
 {
   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);
@@ -1819,9 +1826,9 @@ GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
 {
   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);