X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ba14d9861d043d53cc53ea70a2fab4146f7be9f3..df4ac4c7e93cfc6a6253331285c0f8a50b0e22b2:/src/msw/gsocket.c diff --git a/src/msw/gsocket.c b/src/msw/gsocket.c index 4490c43ada..dbdbe90fe6 100644 --- a/src/msw/gsocket.c +++ b/src/msw/gsocket.c @@ -26,7 +26,6 @@ # pragma warning(disable:4100) #endif /* _MSC_VER */ - #ifndef __GSOCKET_STANDALONE__ # include "wx/defs.h" # include "wx/setup.h" @@ -50,7 +49,6 @@ # define _GSocket_Disable_Events(socket) #endif /* wxUSE_GUI */ - #include #include #include @@ -103,6 +101,13 @@ GSocket *GSocket_new(void) return socket; } +void GSocket_close(GSocket *socket) +{ + _GSocket_Disable_Events(socket); + closesocket(socket->m_fd); + socket->m_fd = INVALID_SOCKET; +} + void GSocket_destroy(GSocket *socket) { assert(socket != NULL); @@ -139,8 +144,7 @@ void GSocket_Shutdown(GSocket *socket) if (socket->m_fd != INVALID_SOCKET) { shutdown(socket->m_fd, 2); - closesocket(socket->m_fd); - socket->m_fd = INVALID_SOCKET; + GSocket_close(socket); } /* Disable GUI callbacks */ @@ -148,7 +152,6 @@ void GSocket_Shutdown(GSocket *socket) socket->m_cbacks[evt] = NULL; socket->m_detected = GSOCK_LOST_FLAG; - _GSocket_Disable_Events(socket); } /* Address handling */ @@ -325,8 +328,7 @@ GSocketError GSocket_SetServer(GSocket *sck) (SOCKLEN_T *)&sck->m_local->m_len) != 0) || (listen(sck->m_fd, 5) != 0)) { - closesocket(sck->m_fd); - sck->m_fd = INVALID_SOCKET; + GSocket_close(sck); sck->m_error = GSOCK_IOERR; return GSOCK_IOERR; } @@ -508,8 +510,7 @@ GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream) if (err != GSOCK_NOERROR) { - closesocket(sck->m_fd); - sck->m_fd = INVALID_SOCKET; + GSocket_close(sck); /* sck->m_error is set in _GSocket_Connect_Timeout */ } @@ -532,8 +533,7 @@ GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream) /* If connect failed with an error other than EWOULDBLOCK, * then the call to GSocket_Connect() has failed. */ - closesocket(sck->m_fd); - sck->m_fd = INVALID_SOCKET; + GSocket_close(sck); sck->m_error = GSOCK_IOERR; return GSOCK_IOERR; } @@ -597,8 +597,7 @@ GSocketError GSocket_SetNonOriented(GSocket *sck) sck->m_local->m_addr, (SOCKLEN_T *)&sck->m_local->m_len) != 0)) { - closesocket(sck->m_fd); - sck->m_fd = INVALID_SOCKET; + GSocket_close(sck); sck->m_error = GSOCK_IOERR; return GSOCK_IOERR; } @@ -713,22 +712,51 @@ GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags) FD_SET(socket->m_fd, &writefds); FD_SET(socket->m_fd, &exceptfds); - /* Check known state first */ - result |= (GSOCK_CONNECTION_FLAG & socket->m_detected & flags); - result |= (GSOCK_LOST_FLAG & socket->m_detected & flags); + /* Check 'sticky' CONNECTION flag first */ + result |= (GSOCK_CONNECTION_FLAG & socket->m_detected); + + /* If we have already detected a LOST event, then don't try + * to do any further processing. + */ + if ((socket->m_detected & GSOCK_LOST_FLAG) != 0) + { + socket->m_establishing = FALSE; + + return (GSOCK_LOST_FLAG & flags); + } /* Try select now */ if (select(socket->m_fd + 1, &readfds, &writefds, &exceptfds, &tv) <= 0) - return result; + { + /* What to do here? */ + return (result & flags); + } /* Check for readability */ if (FD_ISSET(socket->m_fd, &readfds)) { - /* Assume that closure of the socket is always reported via exceptfds */ - if (socket->m_server && socket->m_stream) - result |= (GSOCK_CONNECTION_FLAG & flags); + char c; + + if (recv(socket->m_fd, &c, 1, MSG_PEEK) > 0) + { + result |= GSOCK_INPUT_FLAG; + } else - result |= (GSOCK_INPUT_FLAG & flags); + { + if (socket->m_server && socket->m_stream) + { + result |= GSOCK_CONNECTION_FLAG; + socket->m_detected |= GSOCK_CONNECTION_FLAG; + } + else + { + socket->m_detected = GSOCK_LOST_FLAG; + socket->m_establishing = FALSE; + + /* LOST event: Abort any further processing */ + return (GSOCK_LOST_FLAG & flags); + } + } } /* Check for writability */ @@ -736,23 +764,43 @@ GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags) { if (socket->m_establishing && !socket->m_server) { - result |= (GSOCK_CONNECTION_FLAG & flags); + int error; + SOCKLEN_T len = sizeof(error); + socket->m_establishing = FALSE; - socket->m_detected |= GSOCK_CONNECTION_FLAG; + + getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len); + + if (error) + { + socket->m_detected = GSOCK_LOST_FLAG; + + /* LOST event: Abort any further processing */ + return (GSOCK_LOST_FLAG & flags); + } + else + { + result |= GSOCK_CONNECTION_FLAG; + socket->m_detected |= GSOCK_CONNECTION_FLAG; + } } else - result |= (GSOCK_OUTPUT_FLAG & flags); + { + result |= GSOCK_OUTPUT_FLAG; + } } - /* Check for exceptions and errors */ + /* Check for exceptions and errors (is this useful in Unices?) */ if (FD_ISSET(socket->m_fd, &exceptfds)) { - result |= (GSOCK_LOST_FLAG & flags); socket->m_establishing = FALSE; socket->m_detected = GSOCK_LOST_FLAG; + + /* LOST event: Abort any further processing */ + return (GSOCK_LOST_FLAG & flags); } - return result; + return (result & flags); #else @@ -1380,3 +1428,4 @@ GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf) typedef void (*wxDummy)(); #endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */ +