From: Vadim Zeitlin Date: Sun, 23 Nov 2008 13:12:46 +0000 (+0000) Subject: continuation of GSocket/wxSocket merge: always create GSocket associated to a wxSocke... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/53a161e10152bc5ff7d4a4c7257f64db13f81ddb?ds=inline continuation of GSocket/wxSocket merge: always create GSocket associated to a wxSocket instead of (always) doing it using a separate call later; remove support for user callbacks which wasn't implemented in Windows version and deprecated since 10 years or so git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56934 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/gsocket.h b/include/wx/gsocket.h index 5786aa65f0..4d1c621596 100644 --- a/include/wx/gsocket.h +++ b/include/wx/gsocket.h @@ -20,6 +20,8 @@ #include "wx/dlimpexp.h" /* for WXDLLIMPEXP_NET */ +class WXDLLIMPEXP_FWD_NET wxSocketBase; + #include /* @@ -163,13 +165,17 @@ private: class GSocketBase { public: - // static factory function - static GSocket *Create(); + // static factory function: creates the low-level socket associated with + // the given wxSocket (and inherits its attributes such as timeout) + static GSocket *Create(wxSocketBase& wxsocket); + void SetTimeout(unsigned long millisec); virtual ~GSocketBase(); GSocketEventFlags Select(GSocketEventFlags flags); + virtual GSocket *WaitConnection(wxSocketBase& wxsocket) = 0; + virtual void Close() = 0; virtual void Shutdown(); @@ -200,11 +206,19 @@ public: #endif GSocketEventFlags m_detected; - GSocketCallback m_cbacks[GSOCK_MAX_EVENT]; - char *m_data[GSOCK_MAX_EVENT]; protected: - GSocketBase(); + GSocketBase(wxSocketBase& wxsocket); + + // notify m_wxsocket + void NotifyOnStateChange(GSocketEvent event); + +private: + // set in ctor and never changed except that it's reset to NULL when the + // socket is shut down + wxSocketBase *m_wxsocket; + + DECLARE_NO_COPY_CLASS(GSocketBase) }; #if defined(__WINDOWS__) diff --git a/include/wx/msw/gsockmsw.h b/include/wx/msw/gsockmsw.h index 94f622064b..50fd92c138 100644 --- a/include/wx/msw/gsockmsw.h +++ b/include/wx/msw/gsockmsw.h @@ -27,16 +27,23 @@ class GSocket : public GSocketBase { public: - GSocket() : GSocketBase() { m_msgnumber = 0; } + GSocket::GSocket(wxSocketBase& wxsocket) + : GSocketBase(wxsocket) + { + m_msgnumber = 0; + } + + virtual void Close(); + + virtual GSocket *WaitConnection(wxSocketBase& wxsocket); - virtual void Close(); GSocketError SetLocal(GAddress *address); GSocketError SetPeer(GAddress *address); GAddress *GetLocal(); GAddress *GetPeer(); GSocketError SetServer(); - GSocket *WaitConnection(); + // not used under MSW void Notify(bool) { } bool SetReusable(); @@ -47,11 +54,7 @@ public: int Read(char *buffer, int size); int Write(const char *buffer, int size); void SetNonBlocking(bool non_block); - void SetTimeout(unsigned long millis); GSocketError WXDLLIMPEXP_NET GetError(); - void SetCallback(GSocketEventFlags flags, - GSocketCallback callback, char *cdata); - void UnsetCallback(GSocketEventFlags flags); GSocketError GetSockOpt(int level, int optname, void *optval, int *optlen); GSocketError SetSockOpt(int level, int optname, diff --git a/include/wx/unix/gsockunx.h b/include/wx/unix/gsockunx.h index 3741595542..8bf15cad89 100644 --- a/include/wx/unix/gsockunx.h +++ b/include/wx/unix/gsockunx.h @@ -16,16 +16,18 @@ class wxGSocketIOHandler; class GSocket : public GSocketBase { public: - GSocket(); - ~GSocket(); + GSocket(wxSocketBase& wxsocket); + virtual ~GSocket(); + virtual void Close(); virtual void Shutdown(); + virtual GSocket *WaitConnection(wxSocketBase& wxsocket); + GSocketError SetLocal(GAddress *address); GSocketError SetPeer(GAddress *address); GAddress *GetLocal(); GAddress *GetPeer(); GSocketError SetServer(); - GSocket *WaitConnection(); bool SetReusable(); bool SetBroadcast(); bool DontDoBind(); @@ -34,11 +36,7 @@ public: int Read(char *buffer, int size); int Write(const char *buffer, int size); void SetNonBlocking(bool non_block); - void SetTimeout(unsigned long millisec); GSocketError WXDLLIMPEXP_NET GetError(); - void SetCallback(GSocketEventFlags flags, - GSocketCallback callback, char *cdata); - void UnsetCallback(GSocketEventFlags flags); GSocketError GetSockOpt(int level, int optname, void *optval, int *optlen); GSocketError SetSockOpt(int level, int optname, const void *optval, int optlen); @@ -74,6 +72,11 @@ public: // pointer for storing extra (usually GUI-specific) data void *m_gui_dependent; + +private: + // notify the associated wxSocket about a change in socket state and shut + // down the socket if the event is GSOCK_LOST + void OnStateChange(GSocketEvent event); }; // A version of GSocketManager which uses FDs for socket IO diff --git a/src/common/socket.cpp b/src/common/socket.cpp index 9273719a28..95ce875344 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -158,9 +158,9 @@ void GSocketManager::Init() // ========================================================================== /* static */ -GSocket *GSocketBase::Create() +GSocket *GSocketBase::Create(wxSocketBase& wxsocket) { - GSocket * const newsocket = new GSocket(); + GSocket * const newsocket = new GSocket(wxsocket); if ( !GSocketManager::Get()->Init_Socket(newsocket) ) { delete newsocket; @@ -170,7 +170,8 @@ GSocket *GSocketBase::Create() return newsocket; } -GSocketBase::GSocketBase() +GSocketBase::GSocketBase(wxSocketBase& wxsocket) + : m_wxsocket(&wxsocket) { m_fd = INVALID_SOCKET; m_detected = 0; @@ -180,12 +181,8 @@ GSocketBase::GSocketBase() m_server = false; m_stream = true; m_non_blocking = false; -#ifdef __WINDOWS__ - m_timeout.tv_sec = 10 * 60; /* 10 minutes */ - m_timeout.tv_usec = 0; -#else - m_timeout = 10*60*1000; /* 10 minutes * 60 sec * 1000 millisec */ -#endif + + SetTimeout(wxsocket.GetTimeout() * 1000); m_establishing = false; m_reusable = false; @@ -193,9 +190,6 @@ GSocketBase::GSocketBase() m_dobind = true; m_initialRecvBufferSize = -1; m_initialSendBufferSize = -1; - - for ( int i = 0; i < GSOCK_MAX_EVENT; i++ ) - m_cbacks[i] = NULL; } GSocketBase::~GSocketBase() @@ -226,13 +220,30 @@ void GSocketBase::Shutdown() Close(); } - /* Disable GUI callbacks */ - for ( int evt = 0; evt < GSOCK_MAX_EVENT; evt++ ) - m_cbacks[evt] = NULL; - m_detected = GSOCK_LOST_FLAG; } +/* GSocket_SetTimeout: + * Sets the timeout for blocking calls. Time is expressed in + * milliseconds. + */ +void GSocketBase::SetTimeout(unsigned long millis) +{ +#ifdef __WXMSW__ + m_timeout.tv_sec = (millis / 1000); + m_timeout.tv_usec = (millis % 1000) * 1000; +#else + m_timeout = millis; +#endif +} + +void GSocketBase::NotifyOnStateChange(GSocketEvent event) +{ + // GSocketEvent and wxSocketNotify enums have the same elements with the + // same values + m_wxsocket->OnRequest(static_cast(event)); +} + // ========================================================================== // wxSocketBase // ========================================================================== @@ -395,18 +406,7 @@ bool wxSocketBase::Close() InterruptWait(); if (m_socket) - { - // Disable callbacks - m_socket->UnsetCallback( - GSOCK_INPUT_FLAG | - GSOCK_OUTPUT_FLAG | - GSOCK_LOST_FLAG | - GSOCK_CONNECTION_FLAG - ); - - // Shutdown the connection m_socket->Shutdown(); - } m_connected = false; m_establishing = false; @@ -1324,7 +1324,7 @@ wxSocketServer::wxSocketServer(const wxSockAddress& addr_man, { wxLogTrace( wxTRACE_Socket, _T("Opening wxSocketServer") ); - m_socket = GSocket::Create(); + m_socket = GSocket::Create(*this); if (!m_socket) { @@ -1355,11 +1355,6 @@ wxSocketServer::wxSocketServer(const wxSockAddress& addr_man, return; } - m_socket->SetTimeout(m_timeout * 1000); - m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG | - GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG, - wx_socket_callback, (char *)this); - wxLogTrace( wxTRACE_Socket, _T("wxSocketServer on fd %d"), m_socket->m_fd ); } @@ -1376,20 +1371,14 @@ bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait) // When we are finished, we put the socket to blocking mode // again. wxSocketUnblocker unblock(m_socket, !wait); - GSocket * const child_socket = m_socket->WaitConnection(); + sock.m_socket = m_socket->WaitConnection(sock); - if (!child_socket) + if ( !sock.m_socket ) return false; sock.m_type = wxSOCKET_BASE; - sock.m_socket = child_socket; sock.m_connected = true; - sock.m_socket->SetTimeout(sock.m_timeout * 1000); - sock.m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG | - GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG, - wx_socket_callback, (char *)&sock); - return true; } @@ -1487,23 +1476,13 @@ bool wxSocketClient::DoConnect(const wxSockAddress& addr_man, delete m_socket; } - m_socket = GSocket::Create(); + m_socket = GSocket::Create(*this); m_connected = false; m_establishing = false; if (!m_socket) return false; - m_socket->SetTimeout(m_timeout * 1000); - m_socket->SetCallback( - GSOCK_INPUT_FLAG | - GSOCK_OUTPUT_FLAG | - GSOCK_LOST_FLAG | - GSOCK_CONNECTION_FLAG, - wx_socket_callback, - (char *)this - ); - // If wait == false, then the call should be nonblocking. When we are // finished, we put the socket to blocking mode again. wxSocketUnblocker unblock(m_socket, !wait); @@ -1602,13 +1581,11 @@ wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr, : wxSocketBase( flags, wxSOCKET_DATAGRAM ) { // Create the socket - m_socket = GSocket::Create(); + m_socket = GSocket::Create(*this); if (!m_socket) - { - wxFAIL_MSG( _T("datagram socket not new'd") ); return; - } + m_socket->Notify(m_notify); // Setup the socket as non connection oriented m_socket->SetLocal(addr.GetAddress()); @@ -1634,10 +1611,6 @@ wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr, // Initialize all stuff m_connected = false; m_establishing = false; - m_socket->SetTimeout( m_timeout * 1000 ); - m_socket->SetCallback( GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG | - GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG, - wx_socket_callback, (char*)this ); } wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr, diff --git a/src/msw/gsocket.cpp b/src/msw/gsocket.cpp index 5730a6cf18..c973bbd9de 100644 --- a/src/msw/gsocket.cpp +++ b/src/msw/gsocket.cpp @@ -308,7 +308,7 @@ GSocketError GSocket::SetServer() * GSOCK_MEMERR - couldn't allocate memory. * GSOCK_IOERR - low-level error. */ -GSocket *GSocket::WaitConnection() +GSocket *GSocket::WaitConnection(wxSocketBase& wxsocket) { GSocket *connection; wxSockAddr from; @@ -327,7 +327,7 @@ GSocket *GSocket::WaitConnection() } /* Create a GSocket object for the new connection */ - connection = GSocket::Create(); + connection = GSocket::Create(wxsocket); if (!connection) { @@ -721,16 +721,6 @@ void GSocket::SetNonBlocking(bool non_block) m_non_blocking = non_block; } -/* GSocket_SetTimeout: - * Sets the timeout for blocking calls. Time is expressed in - * milliseconds. - */ -void GSocket::SetTimeout(unsigned long millis) -{ - m_timeout.tv_sec = (millis / 1000); - m_timeout.tv_usec = (millis % 1000) * 1000; -} - /* GSocket_GetError: * Returns the last error occurred for this socket. Note that successful * operations do not clear this back to GSOCK_NOERROR, so use it only @@ -741,69 +731,6 @@ GSocketError WXDLLIMPEXP_NET GSocket::GetError() 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 successfully 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; - - 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; - - 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) { diff --git a/src/unix/gsocket.cpp b/src/unix/gsocket.cpp index 226f46ad0d..a7e54ff58b 100644 --- a/src/unix/gsocket.cpp +++ b/src/unix/gsocket.cpp @@ -467,7 +467,8 @@ void GSocket_Cleanup() /* Constructors / Destructors for GSocket */ -GSocket::GSocket() +GSocket::GSocket(wxSocketBase& wxsocket) + : GSocketBase(wxsocket) { m_handler = NULL; @@ -723,7 +724,7 @@ GSocketError GSocket::SetServer() * GSOCK_MEMERR - couldn't allocate memory. * GSOCK_IOERR - low-level error. */ -GSocket *GSocket::WaitConnection() +GSocket *GSocket::WaitConnection(wxSocketBase& wxsocket) { wxSockAddr from; WX_SOCKLEN_T fromlen = sizeof(from); @@ -741,7 +742,7 @@ GSocket *GSocket::WaitConnection() } /* Create a GSocket object for the new connection */ - connection = GSocket::Create(); + connection = GSocket::Create(wxsocket); if (!connection) { @@ -1238,17 +1239,6 @@ void GSocket::SetNonBlocking(bool non_block) m_non_blocking = non_block; } -/* GSocket_SetTimeout: - * Sets the timeout for blocking calls. Time is expressed in - * milliseconds. - */ -void GSocket::SetTimeout(unsigned long millisec) -{ - assert(this); - - m_timeout = millisec; -} - /* GSocket_GetError: * Returns the last error occurred for this socket. Note that successful * operations do not clear this back to GSOCK_NOERROR, so use it only @@ -1261,73 +1251,6 @@ GSocketError WXDLLIMPEXP_NET GSocket::GetError() 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 successfully 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) { @@ -1346,13 +1269,6 @@ GSocketError GSocket::SetSockOpt(int level, int optname, return GSOCK_OPTERR; } -#define CALL_CALLBACK(socket, event) { \ - socket->Disable(event); \ - if (socket->m_cbacks[event]) \ - socket->m_cbacks[event](socket, event, socket->m_data[event]); \ -} - - void GSocket::Enable(GSocketEvent event) { if (m_use_events) @@ -1573,6 +1489,15 @@ int GSocket::Send_Dgram(const char *buffer, int size) return ret; } +void GSocket::OnStateChange(GSocketEvent event) +{ + Disable(event); + NotifyOnStateChange(event); + + if ( event == GSOCK_LOST ) + Shutdown(); +} + void GSocket::Detected_Read() { char c; @@ -1590,8 +1515,7 @@ void GSocket::Detected_Read() { m_establishing = false; - CALL_CALLBACK(this, GSOCK_LOST); - Shutdown(); + OnStateChange(GSOCK_LOST); return; } @@ -1599,26 +1523,25 @@ void GSocket::Detected_Read() if (num > 0) { - CALL_CALLBACK(this, GSOCK_INPUT); + OnStateChange(GSOCK_INPUT); } else { if (m_server && m_stream) { - CALL_CALLBACK(this, GSOCK_CONNECTION); + OnStateChange(GSOCK_CONNECTION); } else if (num == 0) { if (m_stream) { /* graceful shutdown */ - CALL_CALLBACK(this, GSOCK_LOST); - Shutdown(); + OnStateChange(GSOCK_LOST); } else { /* Empty datagram received */ - CALL_CALLBACK(this, GSOCK_INPUT); + OnStateChange(GSOCK_INPUT); } } else @@ -1626,12 +1549,11 @@ void GSocket::Detected_Read() /* Do not throw a lost event in cases where the socket isn't really lost */ if ((errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINTR)) { - CALL_CALLBACK(this, GSOCK_INPUT); + OnStateChange(GSOCK_INPUT); } else { - CALL_CALLBACK(this, GSOCK_LOST); - Shutdown(); + OnStateChange(GSOCK_LOST); } } } @@ -1646,8 +1568,7 @@ void GSocket::Detected_Write() { m_establishing = false; - CALL_CALLBACK(this, GSOCK_LOST); - Shutdown(); + OnStateChange(GSOCK_LOST); return; } @@ -1662,22 +1583,21 @@ void GSocket::Detected_Write() if (error) { - CALL_CALLBACK(this, GSOCK_LOST); - Shutdown(); + OnStateChange(GSOCK_LOST); } else { - CALL_CALLBACK(this, GSOCK_CONNECTION); + OnStateChange(GSOCK_CONNECTION); /* We have to fire this event by hand because CONNECTION (for clients) * and OUTPUT are internally the same and we just disabled CONNECTION * events with the above macro. */ - CALL_CALLBACK(this, GSOCK_OUTPUT); + OnStateChange(GSOCK_OUTPUT); } } else { - CALL_CALLBACK(this, GSOCK_OUTPUT); + OnStateChange(GSOCK_OUTPUT); } }