-/* GSocket_Select:
- * Polls the socket to determine its status. This function will
- * check for the events specified in the 'flags' parameter, and
- * it will return a mask indicating which operations can be
- * performed. This function won't block, regardless of the
- * mode (blocking | nonblocking) of the socket.
- */
-GSocketEventFlags GSocket::Select(GSocketEventFlags flags)
-{
- if (!gs_gui_functions->CanUseEventLoop())
- {
- GSocketEventFlags result = 0;
- fd_set readfds;
- fd_set writefds;
- fd_set exceptfds;
-
- assert(this);
-
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
- FD_ZERO(&exceptfds);
- FD_SET(m_fd, &readfds);
- if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG)
- FD_SET(m_fd, &writefds);
- FD_SET(m_fd, &exceptfds);
-
- /* Check 'sticky' CONNECTION flag first */
- result |= (GSOCK_CONNECTION_FLAG & m_detected);
-
- /* If we have already detected a LOST event, then don't try
- * to do any further processing.
- */
- if ((m_detected & GSOCK_LOST_FLAG) != 0)
- {
- m_establishing = FALSE;
-
- return (GSOCK_LOST_FLAG & flags);
- }
-
- /* Try select now */
- if (select(m_fd + 1, &readfds, &writefds, &exceptfds,
- &m_timeout) <= 0)
- {
- /* What to do here? */
- return (result & flags);
- }
-
- /* Check for readability */
- if (FD_ISSET(m_fd, &readfds))
- {
- char c;
-
- if (!m_stream || recv(m_fd, &c, 1, MSG_PEEK) > 0)
- {
- result |= GSOCK_INPUT_FLAG;
- }
- else
- {
- if (m_server && m_stream)
- {
- result |= GSOCK_CONNECTION_FLAG;
- m_detected |= GSOCK_CONNECTION_FLAG;
- }
- else
- {
- m_detected = GSOCK_LOST_FLAG;
- m_establishing = FALSE;
-
- /* LOST event: Abort any further processing */
- return (GSOCK_LOST_FLAG & flags);
- }
- }
- }
-
- /* Check for writability */
- if (FD_ISSET(m_fd, &writefds))
- {
- if (m_establishing && !m_server)
- {
- int error;
- SOCKLEN_T len = sizeof(error);
-
- m_establishing = FALSE;
-
- getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
-
- if (error)
- {
- m_detected = GSOCK_LOST_FLAG;
-
- /* LOST event: Abort any further processing */
- return (GSOCK_LOST_FLAG & flags);
- }
- else
- {
- result |= GSOCK_CONNECTION_FLAG;
- m_detected |= GSOCK_CONNECTION_FLAG;
- }
- }
- else
- {
- result |= GSOCK_OUTPUT_FLAG;
- }
- }
-
- /* Check for exceptions and errors (is this useful in Unices?) */
- if (FD_ISSET(m_fd, &exceptfds))
- {
- m_establishing = FALSE;
- m_detected = GSOCK_LOST_FLAG;
-
- /* LOST event: Abort any further processing */
- return (GSOCK_LOST_FLAG & flags);
- }
-
- return (result & flags);
- }
- else /* USE_GUI() */
- {
- assert(this);
- return flags & m_detected;
- }
-}
-
-/* Attributes */
-
-/* GSocket_SetNonBlocking:
- * Sets the socket to non-blocking mode. All IO calls will return
- * immediately.
- */
-void GSocket::SetNonBlocking(bool non_block)
-{
- assert(this);
-
- m_non_blocking = non_block;
-}
-
-/* GSocket_SetTimeout:
- * Sets the timeout for blocking calls. Time is expressed in
- * milliseconds.
- */
-void GSocket::SetTimeout(unsigned long millis)
-{
- assert(this);
-
- m_timeout.tv_sec = (millis / 1000);
- m_timeout.tv_usec = (millis % 1000) * 1000;
-}
-
-/* GSocket_GetError:
- * Returns the last error occured for this socket. Note that successful
- * operations do not clear this back to GSOCK_NOERROR, so use it only
- * after an error.
- */
-GSocketError WXDLLIMPEXP_NET GSocket::GetError()
-{
- assert(this);
-
- return m_error;
-}
-
-/* Callbacks */
-
-/* GSOCK_INPUT:
- * There is data to be read in the input buffer. If, after a read
- * 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
- * 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
- * assume that it can write since the first OUTPUT event, and no more
- * OUTPUT events will be generated unless an error occurs.
- * GSOCK_CONNECTION:
- * Connection succesfully established, for client sockets, or incoming
- * client connection, for server sockets. Wait for this event (also watch
- * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
- * GSOCK_LOST:
- * The connection is lost (or a connection request failed); this could
- * be due to a failure, or due to the peer closing it gracefully.
- */
-
-/* GSocket_SetCallback:
- * Enables the callbacks specified by 'flags'. Note that 'flags'
- * may be a combination of flags OR'ed toghether, so the same
- * callback function can be made to accept different events.
- * The callback function must have the following prototype:
- *
- * void function(GSocket *socket, GSocketEvent event, char *cdata)
- */
-void GSocket::SetCallback(GSocketEventFlags flags,
- GSocketCallback callback, char *cdata)
-{
- int count;
-
- assert(this);
-
- for (count = 0; count < GSOCK_MAX_EVENT; count++)
- {
- if ((flags & (1 << count)) != 0)
- {
- m_cbacks[count] = callback;
- m_data[count] = cdata;
- }
- }
-}
-
-/* GSocket_UnsetCallback:
- * Disables all callbacks specified by 'flags', which may be a
- * combination of flags OR'ed toghether.
- */
-void GSocket::UnsetCallback(GSocketEventFlags flags)
-{
- int count;
-
- assert(this);
-
- for (count = 0; count < GSOCK_MAX_EVENT; count++)
- {
- if ((flags & (1 << count)) != 0)
- {
- m_cbacks[count] = NULL;
- m_data[count] = NULL;
- }
- }
-}
-
-GSocketError GSocket::GetSockOpt(int level, int optname,
- void *optval, int *optlen)
-{
- if (getsockopt(m_fd, level, optname, (char*)optval, optlen) == 0)
- {
- return GSOCK_NOERROR;
- }
- return GSOCK_OPTERR;
-}
-
-GSocketError GSocket::SetSockOpt(int level, int optname,
- const void *optval, int optlen)
-{
- if (setsockopt(m_fd, level, optname, (char*)optval, optlen) == 0)
- {
- return GSOCK_NOERROR;
- }
- return GSOCK_OPTERR;
-}
-