From f0db5d75878e4a4bd8b4d8f0c8e7991b60cced69 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 23 Nov 2008 00:11:09 +0000 Subject: [PATCH] do not require a running event loop, even under MSW, for the sockets to work: if the user code doesn't use events there is no reason for it to run the event loop, especially as it's not needed under the other platforms; instead use the same Select() implementation as under Unix under MSW too and, to avoid duplicating it, put it into the new GSocketBase class git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56923 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/gsocket.h | 88 +++++++++++++++++++++++++++ include/wx/msw/gsockmsw.h | 24 +------- include/wx/unix/gsockunx.h | 24 +------- include/wx/unix/private.h | 42 +------------ src/common/socket.cpp | 118 ++++++++++++++++++++++++++++++++++--- src/msw/gsocket.cpp | 12 ---- src/unix/gsocket.cpp | 106 --------------------------------- 7 files changed, 202 insertions(+), 212 deletions(-) diff --git a/include/wx/gsocket.h b/include/wx/gsocket.h index a97ef10439..a587ece8c0 100644 --- a/include/wx/gsocket.h +++ b/include/wx/gsocket.h @@ -154,6 +154,50 @@ private: static GSocketManager *ms_manager; }; +/* + Base class providing functionality common to BSD and Winsock sockets. + + TODO: merge this in wxSocket itself, there is no reason to maintain the + separation between wxSocket and GSocket. + */ +class GSocketBase +{ +public: + GSocketEventFlags Select(GSocketEventFlags flags); + +#ifdef __WINDOWS__ + SOCKET m_fd; +#else + int m_fd; +#endif + + bool m_ok; + int m_initialRecvBufferSize; + int m_initialSendBufferSize; + + GAddress *m_local; + GAddress *m_peer; + GSocketError m_error; + + bool m_non_blocking; + bool m_server; + bool m_stream; + bool m_establishing; + bool m_reusable; + bool m_broadcast; + bool m_dobind; + +#ifdef __WINDOWS__ + struct timeval m_timeout; +#else + unsigned long m_timeout; +#endif + + GSocketEventFlags m_detected; + GSocketCallback m_cbacks[GSOCK_MAX_EVENT]; + char *m_data[GSOCK_MAX_EVENT]; +}; + #if defined(__WINDOWS__) #include "wx/msw/gsockmsw.h" #else @@ -246,6 +290,50 @@ GSocketError _GAddress_Init_UNIX(GAddress *address); GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path); GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf); +// standard linux headers produce many warnings when used with icc +#if defined(__INTELC__) && defined(__LINUX__) + inline void wxFD_ZERO(fd_set *fds) + { + #pragma warning(push) + #pragma warning(disable:593) + FD_ZERO(fds); + #pragma warning(pop) + } + + inline void wxFD_SET(int fd, fd_set *fds) + { + #pragma warning(push, 1) + #pragma warning(disable:1469) + FD_SET(fd, fds); + #pragma warning(pop) + } + + inline bool wxFD_ISSET(int fd, fd_set *fds) + { + #pragma warning(push, 1) + #pragma warning(disable:1469) + return FD_ISSET(fd, fds); + #pragma warning(pop) + } + inline bool wxFD_CLR(int fd, fd_set *fds) + { + #pragma warning(push, 1) + #pragma warning(disable:1469) + return FD_CLR(fd, fds); + #pragma warning(pop) + } +#else // !__INTELC__ + #define wxFD_ZERO(fds) FD_ZERO(fds) + #define wxFD_SET(fd, fds) FD_SET(fd, fds) + #define wxFD_ISSET(fd, fds) FD_ISSET(fd, fds) + #define wxFD_CLR(fd, fds) FD_CLR(fd, fds) +#endif // __INTELC__/!__INTELC__ + +// this is for Windows where configure doesn't define this +#ifndef SOCKOPTLEN_T + #define SOCKOPTLEN_T int +#endif + #endif /* wxUSE_SOCKETS */ #endif /* _WX_GSOCKET_H_ */ diff --git a/include/wx/msw/gsockmsw.h b/include/wx/msw/gsockmsw.h index ea5fc11fe4..36e7bfbb87 100644 --- a/include/wx/msw/gsockmsw.h +++ b/include/wx/msw/gsockmsw.h @@ -24,7 +24,7 @@ #endif /* Definition of GSocket */ -class GSocket +class GSocket : public GSocketBase { public: GSocket(); @@ -47,7 +47,6 @@ public: GSocketError SetNonOriented(); int Read(char *buffer, int size); int Write(const char *buffer, int size); - GSocketEventFlags Select(GSocketEventFlags flags); void SetNonBlocking(bool non_block); void SetTimeout(unsigned long millis); GSocketError WXDLLIMPEXP_NET GetError(); @@ -73,31 +72,10 @@ protected: int Recv_Dgram(char *buffer, int size); int Send_Stream(const char *buffer, int size); int Send_Dgram(const char *buffer, int size); - bool m_ok; - int m_initialRecvBufferSize; - int m_initialSendBufferSize; /* TODO: Make these protected */ public: - SOCKET m_fd; - GAddress *m_local; - GAddress *m_peer; - GSocketError m_error; - /* Attributes */ - bool m_non_blocking; - bool m_server; - bool m_stream; - bool m_establishing; - bool m_reusable; - bool m_broadcast; - bool m_dobind; - struct timeval m_timeout; - - /* Callbacks */ - GSocketEventFlags m_detected; - GSocketCallback m_cbacks[GSOCK_MAX_EVENT]; - char *m_data[GSOCK_MAX_EVENT]; int m_msgnumber; }; diff --git a/include/wx/unix/gsockunx.h b/include/wx/unix/gsockunx.h index dfbf94e918..c6459aab09 100644 --- a/include/wx/unix/gsockunx.h +++ b/include/wx/unix/gsockunx.h @@ -13,7 +13,7 @@ class wxGSocketIOHandler; -class GSocket +class GSocket : public GSocketBase { public: GSocket(); @@ -34,7 +34,6 @@ public: GSocketError SetNonOriented(); int Read(char *buffer, int size); int Write(const char *buffer, int size); - GSocketEventFlags Select(GSocketEventFlags flags); void SetNonBlocking(bool non_block); void SetTimeout(unsigned long millisec); GSocketError WXDLLIMPEXP_NET GetError(); @@ -66,35 +65,14 @@ protected: int Recv_Dgram(char *buffer, int size); int Send_Stream(const char *buffer, int size); int Send_Dgram(const char *buffer, int size); - bool m_ok; - int m_initialRecvBufferSize; - int m_initialSendBufferSize; public: /* DFE: We can't protect these data member until the GUI code is updated */ /* protected: */ - int m_fd; wxGSocketIOHandler *m_handler; - GAddress *m_local; - GAddress *m_peer; - GSocketError m_error; - - bool m_non_blocking; - bool m_server; - bool m_stream; - bool m_establishing; - bool m_reusable; - bool m_broadcast; - bool m_dobind; - unsigned long m_timeout; // true if socket should fire events bool m_use_events; - /* Callbacks */ - GSocketEventFlags m_detected; - GSocketCallback m_cbacks[GSOCK_MAX_EVENT]; - char *m_data[GSOCK_MAX_EVENT]; - // pointer for storing extra (usually GUI-specific) data void *m_gui_dependent; }; diff --git a/include/wx/unix/private.h b/include/wx/unix/private.h index 3995e70772..627cdb6414 100644 --- a/include/wx/unix/private.h +++ b/include/wx/unix/private.h @@ -11,45 +11,9 @@ #ifndef _WX_UNIX_PRIVATE_H_ #define _WX_UNIX_PRIVATE_H_ -// standard linux headers produce many warnings when used with icc -#if defined(__INTELC__) && defined(__LINUX__) - inline void wxFD_ZERO(fd_set *fds) - { - #pragma warning(push) - #pragma warning(disable:593) - FD_ZERO(fds); - #pragma warning(pop) - } - - inline void wxFD_SET(int fd, fd_set *fds) - { - #pragma warning(push, 1) - #pragma warning(disable:1469) - FD_SET(fd, fds); - #pragma warning(pop) - } - - inline bool wxFD_ISSET(int fd, fd_set *fds) - { - #pragma warning(push, 1) - #pragma warning(disable:1469) - return FD_ISSET(fd, fds); - #pragma warning(pop) - } - inline bool wxFD_CLR(int fd, fd_set *fds) - { - #pragma warning(push, 1) - #pragma warning(disable:1469) - return FD_CLR(fd, fds); - #pragma warning(pop) - } -#else // !__INTELC__ - #define wxFD_ZERO(fds) FD_ZERO(fds) - #define wxFD_SET(fd, fds) FD_SET(fd, fds) - #define wxFD_ISSET(fd, fds) FD_ISSET(fd, fds) - #define wxFD_CLR(fd, fds) FD_CLR(fd, fds) -#endif // __INTELC__/!__INTELC__ - +// this file is currently empty as its original contents was moved to +// include/wx/gsocket.h but let's keep it for now in case we need it for +// something again in the future #endif // _WX_UNIX_PRIVATE_H_ diff --git a/src/common/socket.cpp b/src/common/socket.cpp index 88ad1f1548..6de0020de0 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -720,6 +720,112 @@ wxSocketBase& wxSocketBase::Discard() // Wait functions // -------------------------------------------------------------------------- +/* 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 GSocketBase::Select(GSocketEventFlags flags) +{ + assert(this); + + GSocketEventFlags result = 0; + fd_set readfds; + fd_set writefds; + fd_set exceptfds; + struct timeval tv; + + if (m_fd == -1) + return (GSOCK_LOST_FLAG & flags); + + /* Do not use a static struct, Linux can garble it */ + tv.tv_sec = 0; + tv.tv_usec = 0; + + wxFD_ZERO(&readfds); + wxFD_ZERO(&writefds); + wxFD_ZERO(&exceptfds); + wxFD_SET(m_fd, &readfds); + if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG) + wxFD_SET(m_fd, &writefds); + wxFD_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, &tv) < 0) + { + /* What to do here? */ + return (result & flags); + } + + /* Check for exceptions and errors */ + if (wxFD_ISSET(m_fd, &exceptfds)) + { + m_establishing = false; + m_detected = GSOCK_LOST_FLAG; + + /* LOST event: Abort any further processing */ + return (GSOCK_LOST_FLAG & flags); + } + + /* Check for readability */ + if (wxFD_ISSET(m_fd, &readfds)) + { + result |= GSOCK_INPUT_FLAG; + + if (m_server && m_stream) + { + /* This is a TCP server socket that detected a connection. + While the INPUT_FLAG is also set, it doesn't matter on + this kind of sockets, as we can only Accept() from them. */ + m_detected |= GSOCK_CONNECTION_FLAG; + } + } + + /* Check for writability */ + if (wxFD_ISSET(m_fd, &writefds)) + { + if (m_establishing && !m_server) + { + int error; + SOCKOPTLEN_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 + { + m_detected |= GSOCK_CONNECTION_FLAG; + } + } + else + { + result |= GSOCK_OUTPUT_FLAG; + } + } + + return (result | m_detected) & flags; +} + // All Wait functions poll the socket using GSocket_Select() to // check for the specified combination of conditions, until one // of these conditions become true, an error occurs, or the @@ -749,11 +855,6 @@ wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags) if ( wxIsMainThread() ) { eventLoop = wxEventLoop::GetActive(); - -#ifdef __WXMSW__ - wxASSERT_MSG( eventLoop, - "Sockets won't work without a running event loop" ); -#endif // __WXMSW__ } else // in worker thread { @@ -808,10 +909,9 @@ wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags) if ( eventLoop ) { - // Dispatch the events when we run in the main thread and have an - // active event loop: without this sockets don't work at all under - // MSW as socket flags are only updated when socket messages are - // processed. + // This function is only called if wxSOCKET_BLOCK flag was not used + // and so we should dispatch the events if there is an event loop + // capable of doing it. if ( eventLoop->Pending() ) eventLoop->Dispatch(); } diff --git a/src/msw/gsocket.cpp b/src/msw/gsocket.cpp index 8cc501a98e..1730fc7fc7 100644 --- a/src/msw/gsocket.cpp +++ b/src/msw/gsocket.cpp @@ -776,18 +776,6 @@ int GSocket::Write(const char *buffer, int size) return ret; } -/* 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) -{ - return flags & m_detected; -} - /* Attributes */ /* GSocket_SetNonBlocking: diff --git a/src/unix/gsocket.cpp b/src/unix/gsocket.cpp index 5cb9783b71..97105ca534 100644 --- a/src/unix/gsocket.cpp +++ b/src/unix/gsocket.cpp @@ -1285,112 +1285,6 @@ int GSocket::Write(const char *buffer, int size) return ret; } -/* 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) -{ - assert(this); - - GSocketEventFlags result = 0; - fd_set readfds; - fd_set writefds; - fd_set exceptfds; - struct timeval tv; - - if (m_fd == -1) - return (GSOCK_LOST_FLAG & flags); - - /* Do not use a static struct, Linux can garble it */ - tv.tv_sec = 0; - tv.tv_usec = 0; - - wxFD_ZERO(&readfds); - wxFD_ZERO(&writefds); - wxFD_ZERO(&exceptfds); - wxFD_SET(m_fd, &readfds); - if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG) - wxFD_SET(m_fd, &writefds); - wxFD_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, &tv) < 0) - { - /* What to do here? */ - return (result & flags); - } - - /* Check for exceptions and errors */ - if (wxFD_ISSET(m_fd, &exceptfds)) - { - m_establishing = false; - m_detected = GSOCK_LOST_FLAG; - - /* LOST event: Abort any further processing */ - return (GSOCK_LOST_FLAG & flags); - } - - /* Check for readability */ - if (wxFD_ISSET(m_fd, &readfds)) - { - result |= GSOCK_INPUT_FLAG; - - if (m_server && m_stream) - { - /* This is a TCP server socket that detected a connection. - While the INPUT_FLAG is also set, it doesn't matter on - this kind of sockets, as we can only Accept() from them. */ - m_detected |= GSOCK_CONNECTION_FLAG; - } - } - - /* Check for writability */ - if (wxFD_ISSET(m_fd, &writefds)) - { - if (m_establishing && !m_server) - { - int error; - SOCKOPTLEN_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 - { - m_detected |= GSOCK_CONNECTION_FLAG; - } - } - else - { - result |= GSOCK_OUTPUT_FLAG; - } - } - - return (result | m_detected) & flags; -} - /* Flags */ /* GSocket_SetNonBlocking: -- 2.45.2