: m_wxsocket(&wxsocket)
{
m_fd = INVALID_SOCKET;
- m_detected = 0;
m_local = NULL;
m_peer = NULL;
m_error = wxSOCKET_NOERROR;
{
wxSockAddr from;
WX_SOCKLEN_T fromlen = sizeof(from);
- const int fd = accept(m_fd, &from, &fromlen);
+ const SOCKET fd = accept(m_fd, &from, &fromlen);
if ( fd == INVALID_SOCKET )
return NULL;
shutdown(m_fd, 1 /* SD_SEND */);
Close();
}
-
- m_detected = wxSOCKET_LOST_FLAG;
}
/*
wxSocketEventFlags wxSocketImpl::Select(wxSocketEventFlags flags,
const timeval *timeout)
{
- wxSocketEventFlags result = 0;
+ if ( m_fd == INVALID_SOCKET )
+ return (wxSOCKET_LOST_FLAG & flags);
- if (m_fd == INVALID_SOCKET)
- return (wxSOCKET_LOST_FLAG & flags);
-
- struct timeval tv;
- if ( timeout )
- tv = *timeout;
- else
- tv.tv_sec = tv.tv_usec = 0;
-
- fd_set readfds;
- fd_set writefds;
- fd_set exceptfds;
- wxFD_ZERO(&readfds);
- wxFD_ZERO(&writefds);
- wxFD_ZERO(&exceptfds);
- wxFD_SET(m_fd, &readfds);
- if (flags & wxSOCKET_OUTPUT_FLAG || flags & wxSOCKET_CONNECTION_FLAG)
- wxFD_SET(m_fd, &writefds);
- wxFD_SET(m_fd, &exceptfds);
-
- /* Check 'sticky' CONNECTION flag first */
- result |= wxSOCKET_CONNECTION_FLAG & m_detected;
-
- /* If we have already detected a LOST event, then don't try
- * to do any further processing.
- */
- if ((m_detected & wxSOCKET_LOST_FLAG) != 0)
- {
- m_establishing = false;
- return (wxSOCKET_LOST_FLAG & flags);
- }
+ struct timeval tv;
+ if ( timeout )
+ tv = *timeout;
+ else
+ tv.tv_sec = tv.tv_usec = 0;
- /* Try select now */
- if (select(m_fd + 1, &readfds, &writefds, &exceptfds, &tv) < 0)
- {
- /* What to do here? */
- return (result & flags);
- }
+ // prepare the FD sets, passing NULL for the one(s) we don't use
+ fd_set
+ readfds, *preadfds = NULL,
+ writefds, *pwritefds = NULL,
+ exceptfds; // always want to know about errors
- /* Check for exceptions and errors */
- if (wxFD_ISSET(m_fd, &exceptfds))
- {
- m_establishing = false;
- m_detected = wxSOCKET_LOST_FLAG;
+ if ( flags & wxSOCKET_INPUT_FLAG )
+ {
+ preadfds = &readfds;
+ wxFD_ZERO(preadfds);
+ wxFD_SET(m_fd, preadfds);
+ }
- /* LOST event: Abort any further processing */
- return (wxSOCKET_LOST_FLAG & flags);
- }
+ // when using non-blocking connect() the socket becomes connected
+ // (successfully or not) when it becomes writable
+ if ( flags & (wxSOCKET_OUTPUT_FLAG | wxSOCKET_CONNECTION_FLAG) )
+ {
+ pwritefds = &writefds;
+ wxFD_ZERO(pwritefds);
+ wxFD_SET(m_fd, pwritefds);
+ }
- /* Check for readability */
- if (wxFD_ISSET(m_fd, &readfds))
- {
- result |= wxSOCKET_INPUT_FLAG;
+ wxFD_ZERO(&exceptfds);
+ wxFD_SET(m_fd, &exceptfds);
- if (m_server && m_stream)
+ const int rc = select(m_fd + 1, preadfds, pwritefds, &exceptfds, &tv);
+
+ // check for errors first
+ if ( rc == -1 || wxFD_ISSET(m_fd, &exceptfds) )
{
- /* This is a TCP server socket that detected a connection.
- While the INPUT_FLAG is also set, it doesn't matter on
- this kind of sockets, as we can only Accept() from them. */
- m_detected |= wxSOCKET_CONNECTION_FLAG;
+ m_establishing = false;
+
+ return wxSOCKET_LOST_FLAG & flags;
}
- }
- /* Check for writability */
- if (wxFD_ISSET(m_fd, &writefds))
- {
- if (m_establishing && !m_server)
- {
- int error;
- SOCKOPTLEN_T len = sizeof(error);
- m_establishing = false;
- getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
+ if ( rc == 0 )
+ return 0;
- if (error)
- {
- m_detected = wxSOCKET_LOST_FLAG;
+ wxASSERT_MSG( rc == 1, "unexpected select() return value" );
- /* LOST event: Abort any further processing */
- return (wxSOCKET_LOST_FLAG & flags);
- }
- else
- {
- m_detected |= wxSOCKET_CONNECTION_FLAG;
- }
- }
- else
+ wxSocketEventFlags detected = 0;
+ if ( preadfds && wxFD_ISSET(m_fd, preadfds) )
+ detected |= wxSOCKET_INPUT_FLAG;
+
+ if ( pwritefds && wxFD_ISSET(m_fd, pwritefds) )
{
- result |= wxSOCKET_OUTPUT_FLAG;
+ // check for the case of non-blocking connect()
+ if ( m_establishing && !m_server )
+ {
+ int error;
+ SOCKOPTLEN_T len = sizeof(error);
+ m_establishing = false;
+ getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
+
+ if ( error )
+ detected = wxSOCKET_LOST_FLAG;
+ else
+ detected |= wxSOCKET_CONNECTION_FLAG;
+ }
+ else // not called to get non-blocking connect() status
+ {
+ detected |= wxSOCKET_OUTPUT_FLAG;
+ }
}
- }
- return (result | m_detected) & flags;
+ return detected & flags;
}
bool
return DefWindowProc(hWnd, uMsg, wParam, lParam);
wxSocketImplMSW *socket;
- wxSocketNotify event;
+ wxSocketNotify event = (wxSocketNotify)-1;
{
wxCRIT_SECT_LOCKER(lock, gs_critical);
socket = socketList[(uMsg - WM_USER)];
- event = (wxSocketNotify) -1;
+ if ( !socket )
+ return 0;
+
+ wxASSERT_MSG( socket->m_fd == (SOCKET)wParam,
+ "mismatch between message and socket?" );
- /* Check that the socket still exists (it has not been
- * destroyed) and for safety, check that the m_fd field
- * is what we expect it to be.
- */
- if ((socket != NULL) && ((WPARAM)socket->m_fd == wParam))
+ switch WSAGETSELECTEVENT(lParam)
{
- switch WSAGETSELECTEVENT(lParam)
- {
- case FD_READ: event = wxSOCKET_INPUT; break;
- case FD_WRITE: event = wxSOCKET_OUTPUT; break;
- case FD_ACCEPT: event = wxSOCKET_CONNECTION; break;
- case FD_CONNECT:
- {
- if (WSAGETSELECTERROR(lParam) != 0)
- event = wxSOCKET_LOST;
- else
- event = wxSOCKET_CONNECTION;
- break;
- }
- case FD_CLOSE: event = wxSOCKET_LOST; break;
- }
-
- if (event != -1)
- {
- if (event == wxSOCKET_LOST)
- socket->m_detected = wxSOCKET_LOST_FLAG;
- else
- socket->m_detected |= (1 << event);
- }
+ case FD_READ:
+ event = wxSOCKET_INPUT;
+ break;
+
+ case FD_WRITE:
+ event = wxSOCKET_OUTPUT;
+ break;
+
+ case FD_ACCEPT:
+ event = wxSOCKET_CONNECTION;
+ break;
+
+ case FD_CONNECT:
+ event = WSAGETSELECTERROR(lParam) ? wxSOCKET_LOST
+ : wxSOCKET_CONNECTION;
+ break;
+
+ case FD_CLOSE:
+ event = wxSOCKET_LOST;
+ break;
+
+ default:
+ wxFAIL_MSG( "unexpected socket notification" );
+ return 0;
}
} // unlock gs_critical
- if ( socket )
- socket->NotifyOnStateChange(event);
+ socket->NotifyOnStateChange(event);
- return (LRESULT) 0;
+ return 0;
}
/*
{
int ret;
- /* Reenable INPUT events */
- m_detected &= ~wxSOCKET_INPUT_FLAG;
-
if (m_fd == INVALID_SOCKET || m_server)
{
m_error = wxSOCKET_INVSOCK;
else
m_error = wxSOCKET_WOULDBLOCK;
- /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
- * does). Once the first OUTPUT event is received, users can assume
- * that the socket is writable until a read operation fails. Only then
- * will further OUTPUT events be posted.
- */
- m_detected &= ~wxSOCKET_OUTPUT_FLAG;
return -1;
}
*/
if ((ret == 0) && m_stream)
{
- /* Make sure wxSOCKET_LOST event gets sent and shut down the socket */
- m_detected = wxSOCKET_LOST_FLAG;
- OnReadWaiting();
+ m_establishing = false;
+ OnStateChange(wxSOCKET_LOST);
return 0;
}
else if (ret == -1)
void wxSocketImplUnix::EnableEvent(wxSocketNotify event)
{
- m_detected &= ~(1 << event);
wxSocketManager::Get()->Install_Callback(this, event);
}
void wxSocketImplUnix::DisableEvent(wxSocketNotify event)
{
- m_detected |= (1 << event);
wxSocketManager::Get()->Uninstall_Callback(this, event);
}
return;
}
- /* If we have already detected a LOST event, then don't try
- * to do any further processing.
- */
- if ((m_detected & wxSOCKET_LOST_FLAG) != 0)
- {
- m_establishing = false;
-
- OnStateChange(wxSOCKET_LOST);
- return;
- }
-
int num = recv(m_fd, &c, 1, MSG_PEEK | GSOCKET_MSG_NOSIGNAL);
if (num > 0)
void wxSocketImplUnix::OnWriteWaiting()
{
- /* If we have already detected a LOST event, then don't try
- * to do any further processing.
- */
- if ((m_detected & wxSOCKET_LOST_FLAG) != 0)
- {
- m_establishing = false;
-
- OnStateChange(wxSOCKET_LOST);
- return;
- }
-
if (m_establishing && !m_server)
{
int error;