]> git.saurik.com Git - wxWidgets.git/commitdiff
add wxSocket::IsClosed(), use it to implement Eof() in wxSocketStream
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 12 Jul 2008 02:28:12 +0000 (02:28 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 12 Jul 2008 02:28:12 +0000 (02:28 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54590 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/socket.h
interface/wx/socket.h
src/common/sckstrm.cpp
src/common/socket.cpp

index a07c7bf6fbf4bc37b39b5325e1cf2c0a77fca67b..056de5ee5a1581599694bf5084e7beaaba7e5b46 100644 (file)
@@ -113,6 +113,7 @@ public:
   bool Ok() const { return IsOk(); }
   bool IsOk() const { return (m_socket != NULL); }
   bool Error() const { return m_error; }
+  bool IsClosed() const { return m_closed; }
   bool IsConnected() const { return m_connected; }
   bool IsData() { return WaitForRead(0, 0); }
   bool IsDisconnected() const { return !IsConnected(); }
@@ -199,6 +200,8 @@ private:
   bool          m_reading;          // busy reading?
   bool          m_writing;          // busy writing?
   bool          m_error;            // did last IO call fail?
+  bool          m_closed;           // was the other end closed?
+                                    // (notice that m_error is also set then)
   wxUint32      m_lcount;           // last IO transaction size
   unsigned long m_timeout;          // IO timeout value
   wxList        m_states;           // stack of states
index 4248752b6db11d0d49e680c78a5109eaecf20659..5edc0cf3063958d158091fed91dbe19989411fc6 100644 (file)
@@ -499,6 +499,10 @@ public:
         Returns @true if an error occurred in the last IO operation.
         Use this function to check for an error condition after one of the
         following calls: Discard, Peek, Read, ReadMsg, Unread, Write, WriteMsg.
+
+        Notice that this function will return @true even if the other end of a
+        (connected, i.e. TCP) socket was orderly closed by the peer. Use
+        IsClosed() to check for this.
     */
     bool Error() const;
 
@@ -567,6 +571,13 @@ public:
     */
     bool IsConnected() const;
 
+    /**
+        Return @true if the other end of the socket was closed by the peer.
+
+        Notice that Error() will return @true as well when this happens.
+     */
+    bool IsClosed() const;
+
     /**
         This function waits until the socket is readable. This might mean that
         queued data is available for reading or, for streamed sockets, that
index cb3d65b13bd87aa61dc7a5be59fde1f2318e253a..f060b3fd1f0c3662c8e6f8effd446e785c839b71 100644 (file)
@@ -41,8 +41,11 @@ wxSocketOutputStream::~wxSocketOutputStream()
 
 size_t wxSocketOutputStream::OnSysWrite(const void *buffer, size_t size)
 {
-    size_t ret = m_o_socket->Write((const char *)buffer, size).LastCount();
-    m_lasterror = m_o_socket->Error() ? wxSTREAM_WRITE_ERROR : wxSTREAM_NO_ERROR;
+    const size_t ret = m_o_socket->Write(buffer, size).LastCount();
+    m_lasterror = m_o_socket->Error()
+                    ? m_o_socket->IsClosed() ? wxSTREAM_EOF
+                                             : wxSTREAM_WRITE_ERROR
+                    : wxSTREAM_NO_ERROR;
     return ret;
 }
 
@@ -61,8 +64,11 @@ wxSocketInputStream::~wxSocketInputStream()
 
 size_t wxSocketInputStream::OnSysRead(void *buffer, size_t size)
 {
-    size_t ret = m_i_socket->Read((char *)buffer, size).LastCount();
-    m_lasterror = m_i_socket->Error() ? wxSTREAM_READ_ERROR : wxSTREAM_NO_ERROR;
+    const size_t ret = m_i_socket->Read(buffer, size).LastCount();
+    m_lasterror = m_i_socket->Error()
+                    ? m_i_socket->IsClosed() ? wxSTREAM_EOF
+                                             : wxSTREAM_READ_ERROR
+                    : wxSTREAM_NO_ERROR;
     return ret;
 }
 
index 70a788017c2a686223b064accd99377fda6748d1..a4f8583376c5a679db752e9ae5c353c03cb63d90 100644 (file)
@@ -203,7 +203,8 @@ void wxSocketBase::Init()
   m_establishing =
   m_reading      =
   m_writing      =
-  m_error        = false;
+  m_error        =
+  m_closed       = false;
   m_lcount       = 0;
   m_timeout      = 600;
   m_beingDeleted = false;
@@ -339,8 +340,10 @@ wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
   return *this;
 }
 
-wxUint32 wxSocketBase::_Read(void* buffer, wxUint32 nbytes)
+wxUint32 wxSocketBase::_Read(void* buffer_, wxUint32 nbytes)
 {
+  char *buffer = (char *)buffer_;
+
   int total;
 
   // Try the pushback buffer first
@@ -365,35 +368,53 @@ wxUint32 wxSocketBase::_Read(void* buffer, wxUint32 nbytes)
   if (m_flags & wxSOCKET_NOWAIT)
   {
     m_socket->SetNonBlocking(1);
-    ret = m_socket->Read((char *)buffer, nbytes);
+    ret = m_socket->Read(buffer, nbytes);
     m_socket->SetNonBlocking(0);
 
-    if (ret > 0)
-      total += ret;
+    if ( ret < 0 )
+        return 0;
+
+    total += ret;
   }
-  else
+  else // blocking socket
   {
-    bool more = true;
-
-    while (more)
+    for ( ;; )
     {
+      // dispatch events unless disabled
       if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
         break;
 
-      ret = m_socket->Read((char *)buffer, nbytes);
+      ret = m_socket->Read(buffer, nbytes);
+      if ( ret == 0 )
+      {
+          // for connection-oriented (e.g. TCP) sockets we can only read 0
+          // bytes if the other end has been closed, and for connectionless
+          // ones (UDP) this flag doesn't make sense anyhow so we can set it to
+          // true too without doing any harm
+          m_closed = true;
+          break;
+      }
 
-      if (ret > 0)
+      if ( ret < 0 )
       {
-        total  += ret;
-        nbytes -= ret;
-        buffer  = (char *)buffer + ret;
+          // this will be always interpreted as error by Read()
+          return 0;
       }
 
-      // If we got here and wxSOCKET_WAITALL is not set, we can leave
-      // now. Otherwise, wait until we recv all the data or until there
-      // is an error.
-      //
-      more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
+      total += ret;
+
+      // if wxSOCKET_WAITALL is not set, we can leave now as we did read
+      // something
+      if ( !(m_flags & wxSOCKET_WAITALL) )
+          break;
+
+      // otherwise check if read the maximal requested amount of data
+      nbytes -= ret;
+      if ( !nbytes )
+          break;
+
+      // we didn't, so continue reading
+      buffer  = (char *)buffer + ret;
     }
   }
 
@@ -538,8 +559,10 @@ wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
   return *this;
 }
 
-wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes)
+wxUint32 wxSocketBase::_Write(const void *buffer_, wxUint32 nbytes)
 {
+  const char *buffer = (const char *)buffer_;
+
   wxUint32 total = 0;
 
   // If the socket is invalid or parameters are ill, return immediately
@@ -556,35 +579,42 @@ wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes)
   if (m_flags & wxSOCKET_NOWAIT)
   {
     m_socket->SetNonBlocking(1);
-    ret = m_socket->Write((const char *)buffer, nbytes);
+    ret = m_socket->Write(buffer, nbytes);
     m_socket->SetNonBlocking(0);
 
     if (ret > 0)
       total = ret;
   }
-  else
+  else // blocking socket
   {
-    bool more = true;
-
-    while (more)
+    for ( ;; )
     {
       if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
         break;
 
-      ret = m_socket->Write((const char *)buffer, nbytes);
+      ret = m_socket->Write(buffer, nbytes);
 
-      if (ret > 0)
+      // see comments for similar logic for ret handling in _Read()
+      if ( ret == 0 )
       {
-        total  += ret;
-        nbytes -= ret;
-        buffer  = (const char *)buffer + ret;
+          m_closed = true;
+          break;
       }
 
-      // If we got here and wxSOCKET_WAITALL is not set, we can leave
-      // now. Otherwise, wait until we send all the data or until there
-      // is an error.
-      //
-      more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
+      if ( ret < 0 )
+      {
+          return 0;
+      }
+
+      total += ret;
+      if ( !(m_flags & wxSOCKET_WAITALL) )
+          break;
+
+      nbytes -= ret;
+      if ( !nbytes )
+          break;
+
+      buffer = (const char *)buffer + ret;
     }
   }