6d12e746e1
The refactoring in the commit 51ea713826
(Extend and rename
wxSocketImpl::UnblockAndRegisterWithEventLoop(), 2019-11-20)
accidentally inverted the test for wxSOCKET_BLOCK, restore the correct
logic to make non-blocking sockets work again.
Closes #18834.
152 lines
5.0 KiB
C++
152 lines
5.0 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: wx/unix/private/sockunix.h
|
|
// Purpose: wxSocketImpl implementation for Unix systems
|
|
// Authors: Guilhem Lavaux, Vadim Zeitlin
|
|
// Created: April 1997
|
|
// Copyright: (c) 1997 Guilhem Lavaux
|
|
// (c) 2008 Vadim Zeitlin
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef _WX_UNIX_GSOCKUNX_H_
|
|
#define _WX_UNIX_GSOCKUNX_H_
|
|
|
|
#include <unistd.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
// Under older (Open)Solaris versions FIONBIO is declared in this header only.
|
|
// In the newer versions it's included by sys/ioctl.h but it's simpler to just
|
|
// include it always instead of testing for whether it is or not.
|
|
#ifdef __SOLARIS__
|
|
#include <sys/filio.h>
|
|
#endif
|
|
|
|
#include "wx/private/fdiomanager.h"
|
|
|
|
#define wxCloseSocket close
|
|
|
|
class wxSocketImplUnix : public wxSocketImpl,
|
|
public wxFDIOHandler
|
|
{
|
|
public:
|
|
wxSocketImplUnix(wxSocketBase& wxsocket)
|
|
: wxSocketImpl(wxsocket)
|
|
{
|
|
m_fds[0] =
|
|
m_fds[1] = -1;
|
|
}
|
|
|
|
virtual wxSocketError GetLastError() const wxOVERRIDE;
|
|
|
|
virtual void ReenableEvents(wxSocketEventFlags flags) wxOVERRIDE
|
|
{
|
|
// Events are only ever used for non-blocking sockets.
|
|
if ( GetSocketFlags() & wxSOCKET_BLOCK )
|
|
return;
|
|
|
|
// enable the notifications about input/output being available again in
|
|
// case they were disabled by OnRead/WriteWaiting()
|
|
//
|
|
// notice that we'd like to enable the events here only if there is
|
|
// nothing more left on the socket right now as otherwise we're going
|
|
// to get a "ready for whatever" notification immediately (well, during
|
|
// the next event loop iteration) and disable the event back again
|
|
// which is rather inefficient but unfortunately doing it like this
|
|
// doesn't work because the existing code (e.g. src/common/sckipc.cpp)
|
|
// expects to keep getting notifications about the data available from
|
|
// the socket even if it didn't read all the data the last time, so we
|
|
// absolutely have to continue generating them
|
|
EnableEvents(flags);
|
|
}
|
|
|
|
virtual void UpdateBlockingState() wxOVERRIDE
|
|
{
|
|
// Make this int and not bool to allow passing it to ioctl().
|
|
int isNonBlocking = (GetSocketFlags() & wxSOCKET_BLOCK) == 0;
|
|
ioctl(m_fd, FIONBIO, &isNonBlocking);
|
|
|
|
DoEnableEvents(wxSOCKET_INPUT_FLAG | wxSOCKET_OUTPUT_FLAG, isNonBlocking);
|
|
}
|
|
|
|
// wxFDIOHandler methods
|
|
virtual void OnReadWaiting() wxOVERRIDE;
|
|
virtual void OnWriteWaiting() wxOVERRIDE;
|
|
virtual void OnExceptionWaiting() wxOVERRIDE;
|
|
virtual bool IsOk() const wxOVERRIDE { return m_fd != INVALID_SOCKET; }
|
|
|
|
private:
|
|
virtual void DoClose() wxOVERRIDE
|
|
{
|
|
DisableEvents();
|
|
|
|
wxCloseSocket(m_fd);
|
|
}
|
|
|
|
// enable or disable notifications for socket input/output events
|
|
void EnableEvents(int flags = wxSOCKET_INPUT_FLAG | wxSOCKET_OUTPUT_FLAG)
|
|
{ DoEnableEvents(flags, true); }
|
|
void DisableEvents(int flags = wxSOCKET_INPUT_FLAG | wxSOCKET_OUTPUT_FLAG)
|
|
{ DoEnableEvents(flags, false); }
|
|
|
|
// really enable or disable socket input/output events
|
|
void DoEnableEvents(int flags, bool enable);
|
|
|
|
protected:
|
|
// descriptors for input and output event notification channels associated
|
|
// with the socket
|
|
int m_fds[2];
|
|
|
|
private:
|
|
// notify the associated wxSocket about a change in socket state and shut
|
|
// down the socket if the event is wxSOCKET_LOST
|
|
void OnStateChange(wxSocketNotify event);
|
|
|
|
// check if there is any input available, return 1 if yes, 0 if no or -1 on
|
|
// error
|
|
int CheckForInput();
|
|
|
|
|
|
// give it access to our m_fds
|
|
friend class wxSocketFDBasedManager;
|
|
};
|
|
|
|
// A version of wxSocketManager which uses FDs for socket IO: it is used by
|
|
// Unix console applications and some X11-like ports (wxGTK and wxMotif but not
|
|
// wxX11 currently) which implement their own port-specific wxFDIOManagers
|
|
class wxSocketFDBasedManager : public wxSocketManager
|
|
{
|
|
public:
|
|
wxSocketFDBasedManager()
|
|
{
|
|
m_fdioManager = NULL;
|
|
}
|
|
|
|
virtual bool OnInit() wxOVERRIDE;
|
|
virtual void OnExit() wxOVERRIDE { }
|
|
|
|
virtual wxSocketImpl *CreateSocket(wxSocketBase& wxsocket) wxOVERRIDE
|
|
{
|
|
return new wxSocketImplUnix(wxsocket);
|
|
}
|
|
|
|
virtual void Install_Callback(wxSocketImpl *socket_, wxSocketNotify event) wxOVERRIDE;
|
|
virtual void Uninstall_Callback(wxSocketImpl *socket_, wxSocketNotify event) wxOVERRIDE;
|
|
|
|
protected:
|
|
// get the FD index corresponding to the given wxSocketNotify
|
|
wxFDIOManager::Direction
|
|
GetDirForEvent(wxSocketImpl *socket, wxSocketNotify event);
|
|
|
|
// access the FDs we store
|
|
int& FD(wxSocketImplUnix *socket, wxFDIOManager::Direction d)
|
|
{
|
|
return socket->m_fds[d];
|
|
}
|
|
|
|
wxFDIOManager *m_fdioManager;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxSocketFDBasedManager);
|
|
};
|
|
|
|
#endif /* _WX_UNIX_GSOCKUNX_H_ */
|