+public:
+ int *m_state;
+ unsigned long m_new_val;
+
+ void Notify()
+ {
+ *m_state = m_new_val; // Change the value
+ }
+};
+
+wxUint32 wxSocketBase::DeferRead(char *buffer, wxUint32 nbytes)
+{
+ // Timer for timeout
+ _wxSocketInternalTimer timer;
+
+ //wxLogMessage("Entrando a DeferRead, nbytes = %d", nbytes);
+ wxASSERT(m_defering == NO_DEFER);
+
+ // Set the defering mode to READ.
+ m_defering = DEFER_READ;
+
+ // Set the current buffer.
+ m_defer_buffer = buffer;
+ m_defer_nbytes = nbytes;
+ m_defer_timer = &timer;
+
+ timer.m_state = (int *)&m_defer_buffer;
+ timer.m_new_val = 0;
+
+ timer.Start(m_timeout * 1000, FALSE);
+
+ // If the socket is readable, call DoDefer for the first time
+ if (GSocket_Select(m_socket, GSOCK_INPUT_FLAG))
+ {
+ //wxLogMessage("Llamando al primer DoDefer");
+ DoDefer();
+ }
+
+ // Wait for buffer completion.
+ while (m_defer_buffer != NULL)
+ PROCESS_EVENTS();
+
+ timer.Stop();
+
+ // Disable defering mode.
+ m_defering = NO_DEFER;
+ m_defer_timer = NULL;
+
+ // Return the number of bytes read from the socket.
+ //wxLogMessage("Saliendo de DeferRead: total: %d bytes", nbytes - m_defer_nbytes);
+ return nbytes-m_defer_nbytes;
+}
+
+wxSocketBase& wxSocketBase::Read(char* buffer, wxUint32 nbytes)
+{
+ // Mask read events
+ m_reading = TRUE;
+
+ m_lcount = _Read(buffer, nbytes);
+
+ // If in WAITALL mode, all bytes should have been read.
+ if (m_flags & WAITALL)
+ m_error = (m_lcount != nbytes);
+ else
+ m_error = (m_lcount == 0);
+
+ // Trigger another read event if there is still data available.
+ m_reading = FALSE;
+ // TODO: TriggerRead
+
+ return *this;
+}
+
+wxUint32 wxSocketBase::_Read(char* buffer, wxUint32 nbytes)
+{
+ int total;
+ int ret = 1;
+
+ // we try this even if the connection has already been closed.
+ total = GetPushback(buffer, nbytes, FALSE);
+ nbytes -= total;
+ buffer += total;
+
+ // If the socket is not connected, or we have got the whole
+ // needed buffer, return immedately
+ if (!m_connected || !m_socket || !nbytes)
+ return total;
+
+ // 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)
+ total += ret;
+ }
+ else if ((m_flags & SPEED) && (m_flags & WAITALL)) // SPEED, WAITALL
+ {
+ while (ret > 0 && nbytes > 0)
+ {
+ ret = GSocket_Read(m_socket, buffer, nbytes);
+ total += ret;
+ buffer += ret;
+ nbytes -= ret;
+ }
+ // In case the last call was an error ...
+ if (ret < 0)
+ total++;
+ }
+ else if (m_flags & SPEED) // SPEED, !WAITALL
+ {
+ ret = GSocket_Read(m_socket, buffer, nbytes);
+
+ if (ret > 0)
+ total += ret;
+ }
+ else // NONE or WAITALL
+ {
+ ret = DeferRead(buffer, nbytes);
+
+ if (ret > 0)
+ total += ret;
+ }
+
+ return total;
+}
+
+wxSocketBase& wxSocketBase::ReadMsg(char* buffer, wxUint32 nbytes)
+{
+#define MAX_DISCARD_SIZE (10 * 1024)
+
+ wxUint32 len, len2, sig, total;
+ bool error;
+ int old_flags;
+ struct
+ {
+ unsigned char sig[4];
+ unsigned char len[4];
+ } msg;
+
+ // Mask read events
+ m_reading = TRUE;
+
+ total = 0;
+ error = TRUE;
+ old_flags = m_flags;
+ SetFlags((m_flags & SPEED) | WAITALL);
+
+ if (_Read((char *)&msg, sizeof(msg)) != sizeof(msg))
+ goto exit;
+
+ 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)
+ {
+ wxLogWarning( _("TCP: invalid signature returned to ReadMsg."));
+ goto exit;
+ }
+
+ len = (wxUint32)msg.len[0];
+ len |= (wxUint32)(msg.len[1] << 8);
+ len |= (wxUint32)(msg.len[2] << 16);
+ len |= (wxUint32)(msg.len[3] << 24);
+
+ //wxLogMessage("Readmsg: %d %d %d %d -> len == %d",
+ // msg.len[0], msg.len[1], msg.len[2], msg.len[3], len);
+
+ if (len > nbytes)
+ {
+ len2 = len - nbytes;
+ len = nbytes;
+ }
+ else
+ len2 = 0;
+
+ // This check is necessary so that we don't attemp to read if
+ // the msg was zero bytes long.
+ if (len)
+ {
+ total = _Read(buffer, len);
+
+ if (total != len)
+ goto exit;
+ }
+ if (len2)
+ {
+ char *discard_buffer = new char[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 = _Read(discard_buffer, discard_len);
+ len2 -= discard_len;
+ }
+ while ((discard_len > 0) && len2);
+
+ delete [] discard_buffer;
+
+ if (len2 != 0)
+ goto exit;