git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28494
c3d73ce0-8a6f-49c7-b76d-
6d57e0e08775
\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.
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.
{\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.
+
*/
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);
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);
int m_stream;
int m_oriented;
int m_establishing;
int m_stream;
int m_oriented;
int m_establishing;
struct timeval m_timeout;
/* Callbacks */
struct timeval m_timeout;
/* Callbacks */
wxSOCKET_NONE = 0,
wxSOCKET_NOWAIT = 1,
wxSOCKET_WAITALL = 2,
wxSOCKET_NONE = 0,
wxSOCKET_NOWAIT = 1,
wxSOCKET_WAITALL = 2,
+ wxSOCKET_BLOCK = 4,
+ wxSOCKET_REUSEADDR = 8
// 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);
{
gs_gui_functions = guifunc;
}
{
gs_gui_functions = guifunc;
}
int GSocket_Init(void)
{
if (gs_gui_functions)
int GSocket_Init(void)
{
if (gs_gui_functions)
* 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)
{
#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.
* 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)
{
+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:
* 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)
{
/* 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! */
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)
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)
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)
_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;
{
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);
}
* 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
-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)
{
-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;
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)
{
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);
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;
{
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;
{
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);
{
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);