LOST event.
- Elusive bug found and fixed when:
a) there was still data to be read in the input buffer, but
b) the socket had already been closed by the peer, so
c) there was a LOST event before the next INPUT event was generated.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5940
c3d73ce0-8a6f-49c7-b76d-
6d57e0e08775
// Shutdown the connection
GSocket_Shutdown(m_socket);
// Shutdown the connection
GSocket_Shutdown(m_socket);
- m_connected = FALSE;
- m_establishing = FALSE;
+ m_connected = FALSE; // (GRG)
+ m_establishing = FALSE;
- *m_state = (int)m_new_val; // Change the value
+ *m_state = (int)m_new_val; // Change the value
- // we try this even if the connection has already been closed.
+ // Try the pushback buffer first
total = GetPushback(buffer, nbytes, FALSE);
nbytes -= total;
buffer += total;
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_socket || !m_connected || !nbytes)
+ // If the socket is invalid or we got all the data, return now (GRG)
+ if (!m_socket || !nbytes)
return total;
// Possible combinations (they are checked in this order)
return total;
// Possible combinations (they are checked in this order)
if (_Read((char *)&msg, sizeof(msg)) != sizeof(msg))
goto exit;
if (_Read((char *)&msg, sizeof(msg)) != sizeof(msg))
goto exit;
- sig = (wxUint32)msg.sig[0];
+ 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)
{
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."));
+ wxLogWarning( _("wxSocket: invalid signature in ReadMsg."));
len |= (wxUint32)(msg.len[2] << 16);
len |= (wxUint32)(msg.len[3] << 24);
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;
if (len > nbytes)
{
len2 = len - nbytes;
- // This check is necessary so that we don't attemp to read if
- // the msg was zero bytes long.
+ // Don't attemp to read if the msg was zero bytes long.
if (len)
{
total = _Read(buffer, len);
if (len)
{
total = _Read(buffer, len);
- //wxLogMessage(wxT("Warning: invalid signature returned to ReadMsg"));
+ wxLogWarning( _("wxSocket: invalid signature in ReadMsg."));
wxUint32 total = 0;
int ret = 1;
wxUint32 total = 0;
int ret = 1;
- if (!m_connected || !m_socket)
+ // If the socket is invalid, return immediately (GRG)
+ if (!m_socket)
return 0;
// Possible combinations (they are checked in this order)
return 0;
// Possible combinations (they are checked in this order)
old_flags = m_flags;
SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
old_flags = m_flags;
SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
- // warning about 'cast truncates constant value'
-#ifdef __VISUALC__
-# pragma warning(disable: 4310)
-#endif // __VISUALC__
-
msg.sig[0] = (unsigned char) 0xad;
msg.sig[1] = (unsigned char) 0xde;
msg.sig[2] = (unsigned char) 0xed;
msg.sig[3] = (unsigned char) 0xfe;
msg.sig[0] = (unsigned char) 0xad;
msg.sig[1] = (unsigned char) 0xde;
msg.sig[2] = (unsigned char) 0xed;
msg.sig[3] = (unsigned char) 0xfe;
- msg.len[0] = (unsigned char) nbytes & 0xff;
- msg.len[1] = (unsigned char) (nbytes >> 8) & 0xff;
- msg.len[2] = (unsigned char) (nbytes >> 16) & 0xff;
- msg.len[3] = (unsigned char) (nbytes >> 24) & 0xff;
-
- //wxLogMessage("Writemsg: %d %d %d %d -> %d",
- // nbytes & 0xff,
- // (nbytes >> 8) & 0xff,
- // (nbytes >> 16) & 0xff,
- // (nbytes >> 24) & 0xff,
- // nbytes
- // );
+ msg.len[0] = (unsigned char) (nbytes & 0xff);
+ msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
+ msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
+ msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
if (_Write((char *)&msg, sizeof(msg)) < sizeof(msg))
goto exit;
if (_Write((char *)&msg, sizeof(msg)) < sizeof(msg))
goto exit;
m_writing = FALSE;
return *this;
m_writing = FALSE;
return *this;
-
-#ifdef __VISUALC__
-# pragma warning(default: 4310)
-#endif // __VISUALC__
}
wxSocketBase& wxSocketBase::Unread(const char *buffer, wxUint32 nbytes)
}
wxSocketBase& wxSocketBase::Unread(const char *buffer, wxUint32 nbytes)
wxSocketBase& wxSocketBase::Discard()
{
int old_flags;
wxSocketBase& wxSocketBase::Discard()
{
int old_flags;
- char *my_data = new char[MAX_DISCARD_SIZE];
- wxUint32 recv_size = MAX_DISCARD_SIZE;
+ char *buffer = new char[MAX_DISCARD_SIZE];
+ wxUint32 ret;
wxUint32 total = 0;
// Mask read events
wxUint32 total = 0;
// Mask read events
old_flags = m_flags;
SetFlags(wxSOCKET_NOWAIT);
old_flags = m_flags;
SetFlags(wxSOCKET_NOWAIT);
- while (recv_size == MAX_DISCARD_SIZE)
- recv_size = _Read(my_data, MAX_DISCARD_SIZE);
- total += recv_size;
+ ret = _Read(buffer, MAX_DISCARD_SIZE);
+ total += ret;
+ while (ret == MAX_DISCARD_SIZE);
// Allow read events again
m_reading = FALSE;
// Allow read events again
m_reading = FALSE;
// to check for the specified combination of event flags, until
// an event occurs or until the timeout ellapses. The polling
// loop calls PROCESS_EVENTS(), so this won't block the GUI.
// to check for the specified combination of event flags, until
// an event occurs or until the timeout ellapses. The polling
// loop calls PROCESS_EVENTS(), so this won't block the GUI.
-//
-// XXX: Should it honour the wxSOCKET_BLOCK flag ?
-//
bool wxSocketBase::_Wait(long seconds, long milliseconds,
wxSocketEventFlags flags)
{
bool wxSocketBase::_Wait(long seconds, long milliseconds,
wxSocketEventFlags flags)
{
// Set this to TRUE to interrupt ongoing waits
m_interrupt = FALSE;
// Set this to TRUE to interrupt ongoing waits
m_interrupt = FALSE;
- // Check for valid socket
+ // Check for valid socket (GRG)
if (!m_socket)
return FALSE;
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
if (seconds != -1)
timeout = seconds * 1000 + milliseconds;
// Check for valid timeout value
if (seconds != -1)
timeout = seconds * 1000 + milliseconds;
+ // Data available or output buffer ready
if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
{
timer.Stop();
if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
{
timer.Stop();
if (result & GSOCK_LOST_FLAG)
{
timer.Stop();
if (result & GSOCK_LOST_FLAG)
{
timer.Stop();
- return TRUE; // XXX: should be FALSE if !(flags & GSOCK_LOST_FLAG) !
+ m_connected = FALSE; // (GRG)
+ m_establishing = FALSE;
+ return (flags & GSOCK_LOST_FLAG); // (GRG) <--- Maybe here???
wxSocketEvent event(m_id);
wxSocketEventFlags flag = EventToNotify(req_evt);
wxSocketEvent event(m_id);
wxSocketEventFlags flag = EventToNotify(req_evt);
- // dbg("Entering OnRequest (evt %d)\n", req_evt);
-
// This duplicates some code in _Wait(), but this doesn't
// hurt. It has to be here because we don't know whether
// WaitXXX will be used, and it has to be in _Wait as well
// because the event might be a bit delayed.
//
// This duplicates some code in _Wait(), but this doesn't
// hurt. It has to be here because we don't know whether
// WaitXXX will be used, and it has to be in _Wait as well
// because the event might be a bit delayed.
//
- if (req_evt == wxSOCKET_CONNECTION)
- {
- m_establishing = FALSE;
- m_connected = TRUE;
- }
- else if (req_evt == wxSOCKET_INPUT)
+ case wxSOCKET_CONNECTION:
+ m_establishing = FALSE;
+ m_connected = TRUE;
+ break;
+
// If we are in the middle of a R/W operation, do not
// propagate events to users. Also, filter 'late' events
// which are no longer valid.
//
// If we are in the middle of a R/W operation, do not
// propagate events to users. Also, filter 'late' events
// which are no longer valid.
//
- if (m_reading || !GSocket_Select(m_socket, GSOCK_INPUT_FLAG))
- return;
- }
- else if (req_evt == wxSOCKET_OUTPUT)
- {
- if (m_writing || !GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG))
- return;
+ case wxSOCKET_INPUT:
+ if (m_reading || !GSocket_Select(m_socket, GSOCK_INPUT_FLAG))
+ return;
+ break;
+
+ case wxSOCKET_OUTPUT:
+ if (m_writing || !GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG))
+ return;
+ break;
+
+ case wxSOCKET_LOST:
+ m_connected = FALSE;
+ m_establishing = FALSE;
+ break;
+
+ default:
+ break;
}
if (((m_neededreq & flag) == flag) && m_notify_state)
{
}
if (((m_neededreq & flag) == flag) && m_notify_state)
{
- // dbg("Evt %d delivered\n", req_evt);
event.m_socket = this;
event.m_skevt = req_evt;
event.m_socket = this;
event.m_skevt = req_evt;
OldOnNotify(req_evt);
if (m_cbk)
m_cbk(*this, req_evt, m_cdata);
OldOnNotify(req_evt);
if (m_cbk)
m_cbk(*this, req_evt, m_cdata);
-
- // dbg("Exiting OnRequest (evt %d)\n", req_evt);
}
void wxSocketBase::OldOnNotify(wxSocketNotify WXUNUSED(evt))
}
void wxSocketBase::OldOnNotify(wxSocketNotify WXUNUSED(evt))
// --------------------------------------------------------------
wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
// --------------------------------------------------------------
wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
wxSocketBase(flags, SOCK_SERVER)
{
// Create the socket
wxSocketBase(flags, SOCK_SERVER)
{
// Create the socket
if (!m_socket)
return FALSE;
if (!m_socket)
return FALSE;
- // GRG: If wait == FALSE, then the call should be nonblocking.
+ // If wait == FALSE, then the call should be nonblocking.
// When we are finished, we put the socket to blocking mode
// again.
// When we are finished, we put the socket to blocking mode
// again.
if (!wait)
GSocket_SetNonBlocking(m_socket, FALSE);
if (!wait)
GSocket_SetNonBlocking(m_socket, FALSE);
- // GRG: this was not being handled!
- if (child_socket == NULL)
return FALSE;
sock.m_type = SOCK_INTERNAL;
return FALSE;
sock.m_type = SOCK_INTERNAL;
+ if (m_socket) // (GRG)
+ {
+ // Shutdown and destroy the socket
GSocket_destroy(m_socket);
GSocket_destroy(m_socket);
- // Initialize all socket stuff ...
m_socket = GSocket_new();
m_connected = FALSE;
m_establishing = FALSE;
m_socket = GSocket_new();
m_connected = FALSE;
m_establishing = FALSE;
GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
wx_socket_callback, (char *)this);
GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
wx_socket_callback, (char *)this);
- // GRG: If wait == FALSE, then the call should be nonblocking.
+ // If wait == FALSE, then the call should be nonblocking.
// When we are finished, we put the socket to blocking mode
// again.
// When we are finished, we put the socket to blocking mode
// again.
// wxSocketEvent
// --------------------------------------------------------------
// wxSocketEvent
// --------------------------------------------------------------
+// XXX: Should be moved to event.cpp ?
+
wxSocketEvent::wxSocketEvent(int id)
: wxEvent(id)
{
wxSocketEvent::wxSocketEvent(int id)
: wxEvent(id)
{
class WXDLLEXPORT wxSocketModule: public wxModule
{
DECLARE_DYNAMIC_CLASS(wxSocketModule)
class WXDLLEXPORT wxSocketModule: public wxModule
{
DECLARE_DYNAMIC_CLASS(wxSocketModule)
- bool OnInit()
- {
- return GSocket_Init();
- }
- void OnExit()
- {
- GSocket_Cleanup();
- }
+ bool OnInit() { return GSocket_Init(); }
+ void OnExit() { GSocket_Cleanup(); }
};
IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
};
IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
*/
GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
{
*/
GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
{
+ GSocketEventFlags result = 0;
+ char c;
+
- return (flags & socket->m_detected);
+ result = flags & socket->m_detected;
+
+ if ((flags & GSOCK_INPUT_FLAG) &&
+ (recv(socket->m_fd, &c, 1, MSG_PEEK) > 0))
+ {
+ result |= GSOCK_INPUT_FLAG;
+ }
+
+ return result;
#ifndef __GSOCKET_STANDALONE__
#ifndef __GSOCKET_STANDALONE__
#include "wx/unix/gsockunx.h"
#include "wx/unix/gsockunx.h"
#endif /* __GSOCKET_STANDALONE__ */
#endif /* __GSOCKET_STANDALONE__ */
*/
GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
{
*/
GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
{
+ GSocketEventFlags result = 0;
+ char c;
+
- return (flags & socket->m_detected);
+ result = flags & socket->m_detected;
+
+ if ((flags & GSOCK_INPUT_FLAG) &&
+ (recv(socket->m_fd, &c, 1, MSG_PEEK) > 0))
+ {
+ result |= GSOCK_INPUT_FLAG;
+ }
+
+ return result;
int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
{
int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
{
- int ret;
-
- MASK_SIGNAL();
- ret = recv(socket->m_fd, buffer, size, 0);
- UNMASK_SIGNAL();
-
- return ret;
+ return recv(socket->m_fd, buffer, size, 0);
}
int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
}
int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
ret = recvfrom(socket->m_fd, buffer, size, 0, &from, (SOCKLEN_T *) &fromlen);
ret = recvfrom(socket->m_fd, buffer, size, 0, &from, (SOCKLEN_T *) &fromlen);
if (ret == -1)
return -1;
if (ret == -1)
return -1;