+wxUint32 wxSocketBase::DoRead(void* buffer_, wxUint32 nbytes)
+{
+ wxCHECK_MSG( m_impl, 0, "socket must be valid" );
+
+ // We use pointer arithmetic here which doesn't work with void pointers.
+ char *buffer = static_cast<char *>(buffer_);
+ wxCHECK_MSG( buffer, 0, "NULL buffer" );
+
+ // Try the push back buffer first, even before checking whether the socket
+ // is valid to allow reading previously pushed back data from an already
+ // closed socket.
+ wxUint32 total = GetPushback(buffer, nbytes, false);
+ nbytes -= total;
+ buffer += total;
+
+ while ( nbytes )
+ {
+ // our socket is non-blocking so Read() will return immediately if
+ // there is nothing to read yet and it's more efficient to try it first
+ // before entering DoWait() which is going to start dispatching GUI
+ // events and, even more importantly, we must do this under Windows
+ // where we're not going to get notifications about socket being ready
+ // for reading before we read all the existing data from it
+ const int ret = !m_impl->m_stream || m_connected
+ ? m_impl->Read(buffer, nbytes)
+ : 0;
+ if ( ret == -1 )
+ {
+ if ( m_impl->GetLastError() == wxSOCKET_WOULDBLOCK )
+ {
+ // if we don't want to wait, just return immediately
+ if ( m_flags & wxSOCKET_NOWAIT )
+ {
+ // this shouldn't be counted as an error in this case
+ SetError(wxSOCKET_NOERROR);
+ break;
+ }
+
+ // otherwise wait until the socket becomes ready for reading or
+ // an error occurs on it
+ if ( !DoWaitWithTimeout(wxSOCKET_INPUT_FLAG) )
+ {
+ // and exit if the timeout elapsed before it did
+ SetError(wxSOCKET_TIMEDOUT);
+ break;
+ }
+
+ // retry reading
+ continue;
+ }
+ else // "real" error
+ {
+ SetError(wxSOCKET_IOERR);
+ break;
+ }
+ }
+ else 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;
+
+ // we're not going to read anything else and so if we haven't read
+ // anything (or not everything in wxSOCKET_WAITALL case) already,
+ // signal an error
+ if ( (m_flags & wxSOCKET_WAITALL) || !total )
+ SetError(wxSOCKET_IOERR);
+ break;
+ }
+
+ total += ret;
+
+ // if we are happy to read something and not the entire nbytes bytes,
+ // then we're done
+ if ( !(m_flags & wxSOCKET_WAITALL) )
+ break;
+
+ nbytes -= ret;
+ buffer += ret;
+ }
+
+ return total;
+}
+
+wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
+{
+ struct
+ {
+ unsigned char sig[4];
+ unsigned char len[4];
+ } msg;
+
+ wxSocketReadGuard read(this);
+
+ wxSocketWaitModeChanger changeFlags(this, wxSOCKET_WAITALL);
+
+ bool ok = false;
+ if ( DoRead(&msg, sizeof(msg)) == sizeof(msg) )
+ {
+ wxUint32 sig = (wxUint32)msg.sig[0];
+ sig |= (wxUint32)(msg.sig[1] << 8);
+ sig |= (wxUint32)(msg.sig[2] << 16);
+ sig |= (wxUint32)(msg.sig[3] << 24);
+
+ if ( sig == 0xfeeddead )
+ {
+ wxUint32 len = (wxUint32)msg.len[0];
+ len |= (wxUint32)(msg.len[1] << 8);
+ len |= (wxUint32)(msg.len[2] << 16);
+ len |= (wxUint32)(msg.len[3] << 24);
+
+ wxUint32 len2;
+ if (len > nbytes)
+ {
+ len2 = len - nbytes;
+ len = nbytes;
+ }
+ else
+ len2 = 0;
+
+ // Don't attempt to read if the msg was zero bytes long.
+ m_lcount = len ? DoRead(buffer, len) : 0;
+
+ if ( len2 )
+ {
+ char discard_buffer[MAX_DISCARD_SIZE];
+ long discard_len;
+
+ // NOTE: discarded bytes don't add to m_lcount.
+ do
+ {
+ discard_len = len2 > MAX_DISCARD_SIZE
+ ? MAX_DISCARD_SIZE
+ : len2;
+ discard_len = DoRead(discard_buffer, (wxUint32)discard_len);
+ len2 -= (wxUint32)discard_len;
+ }
+ while ((discard_len > 0) && len2);
+ }
+
+ if ( !len2 && DoRead(&msg, sizeof(msg)) == sizeof(msg) )
+ {
+ sig = (wxUint32)msg.sig[0];
+ sig |= (wxUint32)(msg.sig[1] << 8);
+ sig |= (wxUint32)(msg.sig[2] << 16);
+ sig |= (wxUint32)(msg.sig[3] << 24);
+
+ if ( sig == 0xdeadfeed )
+ ok = true;
+ }
+ }
+ }
+
+ if ( !ok )
+ SetError(wxSOCKET_IOERR);
+
+ return *this;
+}
+
+wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)