From: Guillermo Rodriguez Garcia Date: Fri, 17 Sep 1999 01:51:06 +0000 (+0000) Subject: - NOWAIT flag now implemented X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/af2fd9613a810695f63db0246df4fc2aff6026f2 - NOWAIT flag now implemented - WaitForXXX are now correct (will not report readability / writability if in the middle of a defered read / write operation) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3688 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/src/common/socket.cpp b/src/common/socket.cpp index cc5c83e84f..a5cf4047a7 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -3,8 +3,9 @@ // Purpose: Socket handler classes // Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia // Created: April 1997 -// Updated: July 1999 +// Updated: September 1999 // Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux +// (C) 1999, Guillermo Rodriguez Garcia // RCS_ID: $Id$ // License: see wxWindows license ///////////////////////////////////////////////////////////////////////////// @@ -184,7 +185,7 @@ int wxSocketBase::DeferRead(char *buffer, wxUint32 nbytes) if (GSocket_Select(m_socket, GSOCK_INPUT_FLAG)) DoDefer(); - // Wait for buffer completion. + // Wait for buffer completion. while (m_defer_buffer != NULL) wxYield(); @@ -220,11 +221,25 @@ wxSocketBase& wxSocketBase::Read(char* buffer, wxUint32 nbytes) // If we have got the whole needed buffer, return immediately if (!nbytes) - { return *this; - } - if (m_flags & SPEED & WAITALL) // SPEED && WAITALL + // Possible combinations (they are checked in this order) + // NOWAIT + // SPEED | WAITALL + // SPEED + // WAITALL + // NONE + // + if (m_flags & NOWAIT) // NOWAIT + { + GSocket_SetNonBlocking(m_socket, TRUE); + ret = GSocket_Read(m_socket, buffer, nbytes); + GSocket_SetNonBlocking(m_socket, FALSE); + + if (ret > 0) + m_lcount += ret; + } + else if (m_flags & SPEED & WAITALL) // SPEED, WAITALL { while (ret > 0 && nbytes > 0) { @@ -237,14 +252,14 @@ wxSocketBase& wxSocketBase::Read(char* buffer, wxUint32 nbytes) if (ret < 0) m_lcount ++; } - else if (m_flags & SPEED) // SPEED && !WAITALL + else if (m_flags & SPEED) // SPEED, !WAITALL { ret = GSocket_Read(m_socket, buffer, nbytes); if (ret > 0) m_lcount += ret; } - else // !SPEED + else // NONE or WAITALL { ret = DeferRead(buffer, nbytes); @@ -277,7 +292,7 @@ wxSocketBase& wxSocketBase::ReadMsg(char* buffer, wxUint32 nbytes) // compilers in which wxUint32 was actually a 16-bit unsigned integer old_flags = m_flags; - SetFlags(WAITALL | SPEED); + SetFlags(old_flags | WAITALL); Read((char *)&msg, sizeof(msg)); if (m_lcount != sizeof(msg)) @@ -313,7 +328,7 @@ wxSocketBase& wxSocketBase::ReadMsg(char* buffer, wxUint32 nbytes) else len2 = 0; - // The "len &&" in the following statements is necessary so + // The "len &&" in the following statements is necessary so // that we don't attempt to read (and possibly hang the system) // if the message was zero bytes long if (len && Read(buffer, len).LastCount() != len) @@ -400,7 +415,7 @@ int wxSocketBase::DeferWrite(const char *buffer, wxUint32 nbytes) if (GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG)) DoDefer(); - // Wait for buffer completion. + // Wait for buffer completion. while (m_defer_buffer != NULL) wxYield(); @@ -426,7 +441,23 @@ wxSocketBase& wxSocketBase::Write(const char *buffer, wxUint32 nbytes) return *this; } - if (m_flags & SPEED & WAITALL) // SPEED && WAITALL + // Possible combinations (they are checked in this order) + // NOWAIT + // SPEED | WAITALL + // SPEED + // WAITALL + // NONE + // + if (m_flags & NOWAIT) // NOWAIT + { + GSocket_SetNonBlocking(m_socket, TRUE); + ret = GSocket_Write(m_socket, buffer, nbytes); + GSocket_SetNonBlocking(m_socket, FALSE); + + if (ret > 0) + m_lcount += ret; + } + else if (m_flags & SPEED & WAITALL) // SPEED, WAITALL { while (ret > 0 && nbytes > 0) { @@ -439,14 +470,14 @@ wxSocketBase& wxSocketBase::Write(const char *buffer, wxUint32 nbytes) if (ret < 0) m_lcount ++; } - else if (m_flags & SPEED) // SPEED && !WAITALL + else if (m_flags & SPEED) // SPEED, !WAITALL { ret = GSocket_Write(m_socket, buffer, nbytes); if (ret > 0) m_lcount += ret; } - else // !SPEED + else // NONE or WAITALL { ret = DeferWrite(buffer, nbytes); @@ -486,9 +517,8 @@ wxSocketBase& wxSocketBase::WriteMsg(const char *buffer, wxUint32 nbytes) msg.len[2] = (char) (nbytes >> 16) & 0xff; msg.len[3] = (char) (nbytes >> 24) & 0xff; - // GRG: We need WAITALL | SPEED old_flags = m_flags; - SetFlags(WAITALL | SPEED); + SetFlags(old_flags | WAITALL); if (Write((char *)&msg, sizeof(msg)).LastCount() < sizeof(msg)) { @@ -699,7 +729,11 @@ bool wxSocketBase::_Wait(long seconds, long milliseconds, wxSocketEventFlags fla int state = -1; // Check for valid socket - if ((!m_connected && !m_establishing) || !m_socket) + if (!m_socket) + return FALSE; + + // If it is not a server, it must be connected or establishing connection + if ((m_type != SOCK_SERVER) && (!m_connected && !m_establishing)) return FALSE; // Check for valid timeout value @@ -714,17 +748,50 @@ bool wxSocketBase::_Wait(long seconds, long milliseconds, wxSocketEventFlags fla timer.Start(timeout, TRUE); // Active polling (without using events) - result = GSocket_Select(m_socket, flags); - - while ((result == 0) && (state == -1)) + // + // NOTE: this duplicates some of the code in OnRequest (lost + // connection and connection establishment handling) but this + // doesn't hurt. It has to be here because the event might + // be a bit delayed, and it has to be in OnRequest as well + // because maybe the WaitXXX functions are not being used. + // + while (state == -1) { + result = GSocket_Select(m_socket, flags | GSOCK_LOST_FLAG); + + // Connection lost + if (result & GSOCK_LOST_FLAG) + { + timer.Stop(); + m_defer_buffer = NULL; + Close(); + return TRUE; + } + + // Incoming connection (server) or connection established (client) + if (result & GSOCK_CONNECTION_FLAG) + { + timer.Stop(); + m_connected = TRUE; + m_establishing = FALSE; + return TRUE; + } + + // If we are in the middle of a deferred R/W, ignore these. + if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG)) + { + if (m_defer_buffer == NULL) + { + timer.Stop(); + return TRUE; + } + } + wxYield(); - result = GSocket_Select(m_socket, flags); } timer.Stop(); - - return (result != 0); + return FALSE; } bool wxSocketBase::Wait(long seconds, long milliseconds) @@ -737,12 +804,12 @@ bool wxSocketBase::Wait(long seconds, long milliseconds) bool wxSocketBase::WaitForRead(long seconds, long milliseconds) { - return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG); + return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG); } bool wxSocketBase::WaitForWrite(long seconds, long milliseconds) { - return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG | GSOCK_LOST_FLAG); + return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG); } bool wxSocketBase::WaitForLost(long seconds, long milliseconds) @@ -766,7 +833,7 @@ void wxSocketBase::SetFlags(wxSockFlags _flags) { m_flags = _flags; } - + wxSocketBase::wxSockFlags wxSocketBase::GetFlags() const { return m_flags; @@ -830,6 +897,12 @@ void wxSocketBase::OnRequest(wxSocketNotify req_evt) wxSocketEvent event(m_id); wxSocketEventFlags flag = EventToNotify(req_evt); + // NOTE: this duplicates some of the code in _Wait (lost + // connection and connection establishment handling) but + // this doesn't hurt. It has to be here because maybe the + // WaitXXX are not being used, and it has to be in _Wait + // as well because the event might be a bit delayed. + // switch(req_evt) { case wxSOCKET_CONNECTION: @@ -1028,7 +1101,7 @@ wxSocketBase *wxSocketServer::Accept(bool wait) bool wxSocketServer::WaitForAccept(long seconds, long milliseconds) { - return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG | GSOCK_LOST_FLAG); + return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG); } // -------------------------------------------------------------- @@ -1102,33 +1175,15 @@ bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait) bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds) { - bool ret; - - if (m_connected) // Already connected + if (m_connected) // Already connected return TRUE; - if (!m_establishing || !m_socket) // No connection in progress + if (!m_establishing || !m_socket) // No connection in progress return FALSE; - ret = _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG | GSOCK_LOST_FLAG); - - // GRG: m_connected and m_establishing will be updated in - // OnRequest(), but we do it here anyway because sometimes - // the event might be a bit delayed, and if that happens, - // when WaitOnConnect() returns, m_connected will still be - // FALSE. We have to do it as well in OnRequest because - // maybe WaitOnConnect() is not being used... - - if (ret) - { - m_connected = GSocket_Select(m_socket, GSOCK_CONNECTION_FLAG); - m_establishing = FALSE; - } - - return m_connected; + return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG); } - // -------------------------------------------------------------- // wxSocketEvent // --------------------------------------------------------------