#include "wx/stopwatch.h"
#include "wx/thread.h"
#include "wx/evtloop.h"
+#include "wx/private/fd.h"
// DLL options compatibility check:
#include "wx/build.h"
ms_manager = app->GetTraits()->GetSocketManager();
}
+// ==========================================================================
+// GSocketBase
+// ==========================================================================
+
+/* static */
+GSocket *GSocketBase::Create()
+{
+ GSocket * const newsocket = new GSocket();
+ if ( !GSocketManager::Get()->Init_Socket(newsocket) )
+ {
+ delete newsocket;
+ return NULL;
+ }
+
+ return newsocket;
+}
+
+GSocketBase::GSocketBase()
+{
+ m_fd = INVALID_SOCKET;
+ m_detected = 0;
+ m_local = NULL;
+ m_peer = NULL;
+ m_error = GSOCK_NOERROR;
+ m_server = false;
+ m_stream = true;
+ m_non_blocking = false;
+#ifdef __WINDOWS__
+ m_timeout.tv_sec = 10 * 60; /* 10 minutes */
+ m_timeout.tv_usec = 0;
+#else
+ m_timeout = 10*60*1000; /* 10 minutes * 60 sec * 1000 millisec */
+#endif
+
+ m_establishing = false;
+ m_reusable = false;
+ m_broadcast = false;
+ m_dobind = true;
+ m_initialRecvBufferSize = -1;
+ m_initialSendBufferSize = -1;
+
+ for ( int i = 0; i < GSOCK_MAX_EVENT; i++ )
+ m_cbacks[i] = NULL;
+}
+
+GSocketBase::~GSocketBase()
+{
+ if (m_fd != INVALID_SOCKET)
+ Shutdown();
+
+ if (m_local)
+ GAddress_destroy(m_local);
+
+ if (m_peer)
+ GAddress_destroy(m_peer);
+
+ // cast is ok as all GSocketBase objects we have in our code are really
+ // GSockets
+ GSocketManager::Get()->Destroy_Socket(static_cast<GSocket *>(this));
+}
+
+/* GSocket_Shutdown:
+ * Disallow further read/write operations on this socket, close
+ * the fd and disable all callbacks.
+ */
+void GSocketBase::Shutdown()
+{
+ if ( m_fd != INVALID_SOCKET )
+ {
+ shutdown(m_fd, 1 /* SD_SEND */);
+ Close();
+ }
+
+ /* Disable GUI callbacks */
+ for ( int evt = 0; evt < GSOCK_MAX_EVENT; evt++ )
+ m_cbacks[evt] = NULL;
+
+ m_detected = GSOCK_LOST_FLAG;
+}
+
// ==========================================================================
// wxSocketBase
// ==========================================================================
// Wait functions
// --------------------------------------------------------------------------
+/* GSocket_Select:
+ * Polls the socket to determine its status. This function will
+ * check for the events specified in the 'flags' parameter, and
+ * it will return a mask indicating which operations can be
+ * performed. This function won't block, regardless of the
+ * mode (blocking | nonblocking) of the socket.
+ */
+GSocketEventFlags GSocketBase::Select(GSocketEventFlags flags)
+{
+ assert(this);
+
+ GSocketEventFlags result = 0;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+ struct timeval tv;
+
+ if (m_fd == -1)
+ return (GSOCK_LOST_FLAG & flags);
+
+ /* Do not use a static struct, Linux can garble it */
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ wxFD_ZERO(&readfds);
+ wxFD_ZERO(&writefds);
+ wxFD_ZERO(&exceptfds);
+ wxFD_SET(m_fd, &readfds);
+ if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG)
+ wxFD_SET(m_fd, &writefds);
+ wxFD_SET(m_fd, &exceptfds);
+
+ /* Check 'sticky' CONNECTION flag first */
+ result |= GSOCK_CONNECTION_FLAG & m_detected;
+
+ /* If we have already detected a LOST event, then don't try
+ * to do any further processing.
+ */
+ if ((m_detected & GSOCK_LOST_FLAG) != 0)
+ {
+ m_establishing = false;
+ return (GSOCK_LOST_FLAG & flags);
+ }
+
+ /* Try select now */
+ if (select(m_fd + 1, &readfds, &writefds, &exceptfds, &tv) < 0)
+ {
+ /* What to do here? */
+ return (result & flags);
+ }
+
+ /* Check for exceptions and errors */
+ if (wxFD_ISSET(m_fd, &exceptfds))
+ {
+ m_establishing = false;
+ m_detected = GSOCK_LOST_FLAG;
+
+ /* LOST event: Abort any further processing */
+ return (GSOCK_LOST_FLAG & flags);
+ }
+
+ /* Check for readability */
+ if (wxFD_ISSET(m_fd, &readfds))
+ {
+ result |= GSOCK_INPUT_FLAG;
+
+ if (m_server && m_stream)
+ {
+ /* 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 |= GSOCK_CONNECTION_FLAG;
+ }
+ }
+
+ /* 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 (error)
+ {
+ m_detected = GSOCK_LOST_FLAG;
+
+ /* LOST event: Abort any further processing */
+ return (GSOCK_LOST_FLAG & flags);
+ }
+ else
+ {
+ m_detected |= GSOCK_CONNECTION_FLAG;
+ }
+ }
+ else
+ {
+ result |= GSOCK_OUTPUT_FLAG;
+ }
+ }
+
+ return (result | m_detected) & flags;
+}
+
// All Wait functions poll the socket using GSocket_Select() to
// check for the specified combination of conditions, until one
// of these conditions become true, an error occurs, or the
if ( wxIsMainThread() )
{
eventLoop = wxEventLoop::GetActive();
-
-#ifdef __WXMSW__
- wxASSERT_MSG( eventLoop,
- "Sockets won't work without a running event loop" );
-#endif // __WXMSW__
}
else // in worker thread
{
if ( eventLoop )
{
- // Dispatch the events when we run in the main thread and have an
- // active event loop: without this sockets don't work at all under
- // MSW as socket flags are only updated when socket messages are
- // processed.
+ // This function is only called if wxSOCKET_BLOCK flag was not used
+ // and so we should dispatch the events if there is an event loop
+ // capable of doing it.
if ( eventLoop->Pending() )
eventLoop->Dispatch();
}
{
wxLogTrace( wxTRACE_Socket, _T("Opening wxSocketServer") );
- m_socket = GSocket_new();
+ m_socket = GSocket::Create();
if (!m_socket)
{
delete m_socket;
}
- m_socket = GSocket_new();
+ m_socket = GSocket::Create();
m_connected = false;
m_establishing = false;
: wxSocketBase( flags, wxSOCKET_DATAGRAM )
{
// Create the socket
- m_socket = GSocket_new();
+ m_socket = GSocket::Create();
if (!m_socket)
{
// Initialize all stuff
m_connected = false;
m_establishing = false;
- m_socket->SetTimeout( m_timeout );
+ m_socket->SetTimeout( m_timeout * 1000 );
m_socket->SetCallback( GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
wx_socket_callback, (char*)this );