// Purpose: wxSocketImpl implementation for Unix systems
// Authors: Guilhem Lavaux, Vadim Zeitlin
// Created: April 1997
-// RCS-ID: $Id$
// Copyright: (c) 1997 Guilhem Lavaux
// (c) 2008 Vadim Zeitlin
// Licence: wxWindows licence
#include <unistd.h>
#include <sys/ioctl.h>
-class wxSocketIOHandler;
+// 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
-class wxSocketImplUnix : public wxSocketImpl
+#include "wx/private/fdiomanager.h"
+
+class wxSocketImplUnix : public wxSocketImpl,
+ public wxFDIOHandler
{
public:
- wxSocketImplUnix(wxSocketBase& wxsocket);
+ wxSocketImplUnix(wxSocketBase& wxsocket)
+ : wxSocketImpl(wxsocket)
+ {
+ m_fds[0] =
+ m_fds[1] = -1;
+ }
- virtual void Shutdown();
- virtual wxSocketImpl *WaitConnection(wxSocketBase& wxsocket);
+ virtual wxSocketError GetLastError() const;
+
+ virtual void ReenableEvents(wxSocketEventFlags flags)
+ {
+ // 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);
+ }
- int Read(char *buffer, int size);
- int Write(const char *buffer, int size);
- //attach or detach from main loop
- void Notify(bool flag);
- void Detected_Read();
- void Detected_Write();
+ // wxFDIOHandler methods
+ virtual void OnReadWaiting();
+ virtual void OnWriteWaiting();
+ virtual void OnExceptionWaiting();
+ virtual bool IsOk() const { return m_fd != INVALID_SOCKET; }
private:
- virtual wxSocketError DoHandleConnect(int ret);
virtual void DoClose()
{
- wxSocketManager * const manager = wxSocketManager::Get();
- if ( manager )
- {
- manager->Uninstall_Callback(this, wxSOCKET_INPUT);
- manager->Uninstall_Callback(this, wxSOCKET_OUTPUT);
- }
+ DisableEvents();
close(m_fd);
}
EnableEvents();
}
- // enable or disable notifications for socket input/output events but only
- // if m_use_events is true; do nothing otherwise
- virtual void EnableEvents()
- {
- if ( m_use_events )
- DoEnableEvents(true);
- }
-
- void DisableEvents()
- {
- if ( m_use_events )
- DoEnableEvents(false);
- }
+ // 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, regardless of
- // m_use_events value
- void DoEnableEvents(bool enable);
-
-
- // enable or disable events for the given event if m_use_events; do nothing
- // otherwise
- //
- // notice that these functions also update m_detected: EnableEvent() clears
- // the corresponding bit in it and DisableEvent() sets it
- void EnableEvent(wxSocketNotify event);
- void DisableEvent(wxSocketNotify event);
-
-
- wxSocketError Input_Timeout();
- wxSocketError Output_Timeout();
- int Recv_Stream(char *buffer, int size);
- int Recv_Dgram(char *buffer, int size);
- int Send_Stream(const char *buffer, int size);
- int Send_Dgram(const char *buffer, int size);
+ // really enable or disable socket input/output events
+ void DoEnableEvents(int flags, bool enable);
protected:
- // true if socket should fire events
- bool m_use_events;
-
// descriptors for input and output event notification channels associated
// with the socket
int m_fds[2];
// 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
+// 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:
- // no special initialization/cleanup needed when using FDs
- virtual bool OnInit() { return true; }
+ wxSocketFDBasedManager()
+ {
+ m_fdioManager = NULL;
+ }
+
+ virtual bool OnInit();
virtual void OnExit() { }
- // allocate/free the storage we need
virtual wxSocketImpl *CreateSocket(wxSocketBase& wxsocket)
{
return new wxSocketImplUnix(wxsocket);
}
-protected:
- // identifies either input or output direction
- //
- // NB: the values of this enum shouldn't change
- enum SocketDir
- {
- FD_INPUT,
- FD_OUTPUT
- };
+ virtual void Install_Callback(wxSocketImpl *socket_, wxSocketNotify event);
+ virtual void Uninstall_Callback(wxSocketImpl *socket_, wxSocketNotify event);
+protected:
// get the FD index corresponding to the given wxSocketNotify
- SocketDir GetDirForEvent(wxSocketImpl *socket, wxSocketNotify event)
- {
- switch ( event )
- {
- default:
- wxFAIL_MSG( "unexpected socket event" );
- // fall through
-
- case wxSOCKET_LOST:
- // fall through
-
- case wxSOCKET_INPUT:
- return FD_INPUT;
-
- case wxSOCKET_OUTPUT:
- return FD_OUTPUT;
-
- case wxSOCKET_CONNECTION:
- // FIXME: explain this?
- return socket->m_server ? FD_INPUT : FD_OUTPUT;
- }
- }
+ wxFDIOManager::Direction
+ GetDirForEvent(wxSocketImpl *socket, wxSocketNotify event);
// access the FDs we store
- int& FD(wxSocketImpl *socket, SocketDir d)
+ int& FD(wxSocketImplUnix *socket, wxFDIOManager::Direction d)
{
- return static_cast<wxSocketImplUnix *>(socket)->m_fds[d];
+ return socket->m_fds[d];
}
-};
-// Common base class for all ports using X11-like (and hence implemented in
-// X11, Motif and GTK) AddInput() and RemoveInput() functions
-class wxSocketInputBasedManager : public wxSocketFDBasedManager
-{
-public:
- virtual void Install_Callback(wxSocketImpl *socket, wxSocketNotify event)
- {
- wxCHECK_RET( socket->m_fd != -1,
- "shouldn't be called on invalid socket" );
-
- const SocketDir d = GetDirForEvent(socket, event);
-
- int& fd = FD(socket, d);
- if ( fd != -1 )
- RemoveInput(fd);
-
- fd = AddInput(socket, d);
- }
+ wxFDIOManager *m_fdioManager;
- virtual void Uninstall_Callback(wxSocketImpl *socket, wxSocketNotify event)
- {
- const SocketDir d = GetDirForEvent(socket, event);
-
- int& fd = FD(socket, d);
- if ( fd != -1 )
- {
- RemoveInput(fd);
- fd = -1;
- }
- }
-
-private:
- // these functions map directly to XtAdd/RemoveInput() or
- // gdk_input_add/remove()
- virtual int AddInput(wxSocketImpl *socket, SocketDir d) = 0;
- virtual void RemoveInput(int fd) = 0;
+ wxDECLARE_NO_COPY_CLASS(wxSocketFDBasedManager);
};
#endif /* _WX_UNIX_GSOCKUNX_H_ */