continuation of GSocket/wxSocket merge: always create GSocket associated to a wxSocke...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 23 Nov 2008 13:12:46 +0000 (13:12 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 23 Nov 2008 13:12:46 +0000 (13:12 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@56934 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/gsocket.h
include/wx/msw/gsockmsw.h
include/wx/unix/gsockunx.h
src/common/socket.cpp
src/msw/gsocket.cpp
src/unix/gsocket.cpp

index 5786aa65f0c8c390dc3b1c06435456e2f77e8e87..4d1c6215965b0bdcc7ea09a8d282094d712a831a 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "wx/dlimpexp.h" /* for WXDLLIMPEXP_NET */
 
+class WXDLLIMPEXP_FWD_NET wxSocketBase;
+
 #include <stddef.h>
 
 /*
@@ -163,13 +165,17 @@ private:
 class GSocketBase
 {
 public:
-    // static factory function
-    static GSocket *Create();
+    // static factory function: creates the low-level socket associated with
+    // the given wxSocket (and inherits its attributes such as timeout)
+    static GSocket *Create(wxSocketBase& wxsocket);
 
+    void SetTimeout(unsigned long millisec);
     virtual ~GSocketBase();
 
     GSocketEventFlags Select(GSocketEventFlags flags);
 
+    virtual GSocket *WaitConnection(wxSocketBase& wxsocket) = 0;
+
     virtual void Close() = 0;
     virtual void Shutdown();
 
@@ -200,11 +206,19 @@ public:
 #endif
 
     GSocketEventFlags m_detected;
-    GSocketCallback m_cbacks[GSOCK_MAX_EVENT];
-    char *m_data[GSOCK_MAX_EVENT];
 
 protected:
-    GSocketBase();
+    GSocketBase(wxSocketBase& wxsocket);
+
+    // notify m_wxsocket
+    void NotifyOnStateChange(GSocketEvent event);
+
+private:
+    // set in ctor and never changed except that it's reset to NULL when the
+    // socket is shut down
+    wxSocketBase *m_wxsocket;
+
+    DECLARE_NO_COPY_CLASS(GSocketBase)
 };
 
 #if defined(__WINDOWS__)
index 94f622064b93d59e42d27bb244686d1e34881213..50fd92c1381b98030661f39d4a96ecbf506fe3ca 100644 (file)
 class GSocket : public GSocketBase
 {
 public:
-  GSocket() : GSocketBase() { m_msgnumber = 0; }
+    GSocket::GSocket(wxSocketBase& wxsocket)
+        : GSocketBase(wxsocket)
+    {
+        m_msgnumber = 0;
+    }
+
+    virtual void Close();
+
+    virtual GSocket *WaitConnection(wxSocketBase& wxsocket);
 
-  virtual void Close();
 
   GSocketError SetLocal(GAddress *address);
   GSocketError SetPeer(GAddress *address);
   GAddress *GetLocal();
   GAddress *GetPeer();
   GSocketError SetServer();
-  GSocket *WaitConnection();
+
   // not used under MSW
   void Notify(bool) { }
   bool SetReusable();
@@ -47,11 +54,7 @@ public:
   int Read(char *buffer, int size);
   int Write(const char *buffer, int size);
   void SetNonBlocking(bool non_block);
-  void SetTimeout(unsigned long millis);
   GSocketError WXDLLIMPEXP_NET GetError();
-  void SetCallback(GSocketEventFlags flags,
-    GSocketCallback callback, char *cdata);
-  void UnsetCallback(GSocketEventFlags flags);
   GSocketError GetSockOpt(int level, int optname,
     void *optval, int *optlen);
   GSocketError SetSockOpt(int level, int optname,
index 3741595542d60a91db04378650bd3f2a9b8cf6bc..8bf15cad8978cd7a6f41e48328ed01104698dbc5 100644 (file)
@@ -16,16 +16,18 @@ class wxGSocketIOHandler;
 class GSocket : public GSocketBase
 {
 public:
-    GSocket();
-    ~GSocket();
+    GSocket(wxSocketBase& wxsocket);
+    virtual ~GSocket();
+
     virtual void Close();
     virtual void Shutdown();
+    virtual GSocket *WaitConnection(wxSocketBase& wxsocket);
+
     GSocketError SetLocal(GAddress *address);
     GSocketError SetPeer(GAddress *address);
     GAddress *GetLocal();
     GAddress *GetPeer();
     GSocketError SetServer();
-    GSocket *WaitConnection();
     bool SetReusable();
     bool SetBroadcast();
     bool DontDoBind();
@@ -34,11 +36,7 @@ public:
     int Read(char *buffer, int size);
     int Write(const char *buffer, int size);
     void SetNonBlocking(bool non_block);
-    void SetTimeout(unsigned long millisec);
     GSocketError WXDLLIMPEXP_NET GetError();
-    void SetCallback(GSocketEventFlags flags,
-        GSocketCallback callback, char *cdata);
-    void UnsetCallback(GSocketEventFlags flags);
     GSocketError GetSockOpt(int level, int optname, void *optval, int *optlen);
     GSocketError SetSockOpt(int level, int optname,
         const void *optval, int optlen);
@@ -74,6 +72,11 @@ public:
 
   // pointer for storing extra (usually GUI-specific) data
   void *m_gui_dependent;
+
+private:
+    // notify the associated wxSocket about a change in socket state and shut
+    // down the socket if the event is GSOCK_LOST
+    void OnStateChange(GSocketEvent event);
 };
 
 // A version of GSocketManager which uses FDs for socket IO
index 9273719a2888484d107c801917faef229d325da2..95ce875344f5643b72262ff190ee73c9f9c03075 100644 (file)
@@ -158,9 +158,9 @@ void GSocketManager::Init()
 // ==========================================================================
 
 /* static */
-GSocket *GSocketBase::Create()
+GSocket *GSocketBase::Create(wxSocketBase& wxsocket)
 {
-    GSocket * const newsocket = new GSocket();
+    GSocket * const newsocket = new GSocket(wxsocket);
     if ( !GSocketManager::Get()->Init_Socket(newsocket) )
     {
         delete newsocket;
@@ -170,7 +170,8 @@ GSocket *GSocketBase::Create()
     return newsocket;
 }
 
-GSocketBase::GSocketBase()
+GSocketBase::GSocketBase(wxSocketBase& wxsocket)
+    : m_wxsocket(&wxsocket)
 {
     m_fd              = INVALID_SOCKET;
     m_detected        = 0;
@@ -180,12 +181,8 @@ GSocketBase::GSocketBase()
     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
+
+    SetTimeout(wxsocket.GetTimeout() * 1000);
 
     m_establishing    = false;
     m_reusable        = false;
@@ -193,9 +190,6 @@ GSocketBase::GSocketBase()
     m_dobind          = true;
     m_initialRecvBufferSize = -1;
     m_initialSendBufferSize = -1;
-
-    for ( int i = 0; i < GSOCK_MAX_EVENT; i++ )
-        m_cbacks[i] = NULL;
 }
 
 GSocketBase::~GSocketBase()
@@ -226,13 +220,30 @@ void GSocketBase::Shutdown()
         Close();
     }
 
-    /* Disable GUI callbacks */
-    for ( int evt = 0; evt < GSOCK_MAX_EVENT; evt++ )
-        m_cbacks[evt] = NULL;
-
     m_detected = GSOCK_LOST_FLAG;
 }
 
+/* GSocket_SetTimeout:
+ *  Sets the timeout for blocking calls. Time is expressed in
+ *  milliseconds.
+ */
+void GSocketBase::SetTimeout(unsigned long millis)
+{
+#ifdef __WXMSW__
+    m_timeout.tv_sec  = (millis / 1000);
+    m_timeout.tv_usec = (millis % 1000) * 1000;
+#else
+    m_timeout = millis;
+#endif
+}
+
+void GSocketBase::NotifyOnStateChange(GSocketEvent event)
+{
+    // GSocketEvent and wxSocketNotify enums have the same elements with the
+    // same values
+    m_wxsocket->OnRequest(static_cast<wxSocketNotify>(event));
+}
+
 // ==========================================================================
 // wxSocketBase
 // ==========================================================================
@@ -395,18 +406,7 @@ bool wxSocketBase::Close()
     InterruptWait();
 
     if (m_socket)
-    {
-        // Disable callbacks
-        m_socket->UnsetCallback(
-            GSOCK_INPUT_FLAG |
-            GSOCK_OUTPUT_FLAG |
-            GSOCK_LOST_FLAG |
-            GSOCK_CONNECTION_FLAG
-        );
-
-        // Shutdown the connection
         m_socket->Shutdown();
-    }
 
     m_connected = false;
     m_establishing = false;
@@ -1324,7 +1324,7 @@ wxSocketServer::wxSocketServer(const wxSockAddress& addr_man,
 {
     wxLogTrace( wxTRACE_Socket, _T("Opening wxSocketServer") );
 
-    m_socket = GSocket::Create();
+    m_socket = GSocket::Create(*this);
 
     if (!m_socket)
     {
@@ -1355,11 +1355,6 @@ wxSocketServer::wxSocketServer(const wxSockAddress& addr_man,
         return;
     }
 
-    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);
-
     wxLogTrace( wxTRACE_Socket, _T("wxSocketServer on fd %d"), m_socket->m_fd );
 }
 
@@ -1376,20 +1371,14 @@ bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
     // When we are finished, we put the socket to blocking mode
     // again.
     wxSocketUnblocker unblock(m_socket, !wait);
-    GSocket * const child_socket = m_socket->WaitConnection();
+    sock.m_socket = m_socket->WaitConnection(sock);
 
-    if (!child_socket)
+    if ( !sock.m_socket )
         return false;
 
     sock.m_type = wxSOCKET_BASE;
-    sock.m_socket = child_socket;
     sock.m_connected = true;
 
-    sock.m_socket->SetTimeout(sock.m_timeout * 1000);
-    sock.m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
-            GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
-            wx_socket_callback, (char *)&sock);
-
     return true;
 }
 
@@ -1487,23 +1476,13 @@ bool wxSocketClient::DoConnect(const wxSockAddress& addr_man,
         delete m_socket;
     }
 
-    m_socket = GSocket::Create();
+    m_socket = GSocket::Create(*this);
     m_connected = false;
     m_establishing = false;
 
     if (!m_socket)
         return false;
 
-    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
-    );
-
     // If wait == false, then the call should be nonblocking. When we are
     // finished, we put the socket to blocking mode again.
     wxSocketUnblocker unblock(m_socket, !wait);
@@ -1602,13 +1581,11 @@ wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
                 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
 {
     // Create the socket
-    m_socket = GSocket::Create();
+    m_socket = GSocket::Create(*this);
 
     if (!m_socket)
-    {
-        wxFAIL_MSG( _T("datagram socket not new'd") );
         return;
-    }
+
     m_socket->Notify(m_notify);
     // Setup the socket as non connection oriented
     m_socket->SetLocal(addr.GetAddress());
@@ -1634,10 +1611,6 @@ wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
     // Initialize all stuff
     m_connected = false;
     m_establishing = false;
-    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 );
 }
 
 wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
index 5730a6cf187e31a741922f66ed50f0a046d0d29a..c973bbd9deb6bf64c8faf89044cc293cb32f9036 100644 (file)
@@ -308,7 +308,7 @@ GSocketError GSocket::SetServer()
  *    GSOCK_MEMERR     - couldn't allocate memory.
  *    GSOCK_IOERR      - low-level error.
  */
-GSocket *GSocket::WaitConnection()
+GSocket *GSocket::WaitConnection(wxSocketBase& wxsocket)
 {
   GSocket *connection;
   wxSockAddr from;
@@ -327,7 +327,7 @@ GSocket *GSocket::WaitConnection()
   }
 
   /* Create a GSocket object for the new connection */
-  connection = GSocket::Create();
+  connection = GSocket::Create(wxsocket);
 
   if (!connection)
   {
@@ -721,16 +721,6 @@ void GSocket::SetNonBlocking(bool non_block)
   m_non_blocking = non_block;
 }
 
-/* GSocket_SetTimeout:
- *  Sets the timeout for blocking calls. Time is expressed in
- *  milliseconds.
- */
-void GSocket::SetTimeout(unsigned long millis)
-{
-  m_timeout.tv_sec  = (millis / 1000);
-  m_timeout.tv_usec = (millis % 1000) * 1000;
-}
-
 /* GSocket_GetError:
  *  Returns the last error occurred for this socket. Note that successful
  *  operations do not clear this back to GSOCK_NOERROR, so use it only
@@ -741,69 +731,6 @@ GSocketError WXDLLIMPEXP_NET GSocket::GetError()
   return m_error;
 }
 
-/* Callbacks */
-
-/* GSOCK_INPUT:
- *   There is data to be read in the input buffer. If, after a read
- *   operation, there is still data available, the callback function will
- *   be called again.
- * GSOCK_OUTPUT:
- *   The socket is available for writing. That is, the next write call
- *   won't block. This event is generated only once, when the connection is
- *   first established, and then only if a call failed with GSOCK_WOULDBLOCK,
- *   when the output buffer empties again. This means that the app should
- *   assume that it can write since the first OUTPUT event, and no more
- *   OUTPUT events will be generated unless an error occurs.
- * GSOCK_CONNECTION:
- *   Connection successfully established, for client sockets, or incoming
- *   client connection, for server sockets. Wait for this event (also watch
- *   out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
- * GSOCK_LOST:
- *   The connection is lost (or a connection request failed); this could
- *   be due to a failure, or due to the peer closing it gracefully.
- */
-
-/* GSocket_SetCallback:
- *  Enables the callbacks specified by 'flags'. Note that 'flags'
- *  may be a combination of flags OR'ed toghether, so the same
- *  callback function can be made to accept different events.
- *  The callback function must have the following prototype:
- *
- *  void function(GSocket *socket, GSocketEvent event, char *cdata)
- */
-void GSocket::SetCallback(GSocketEventFlags flags,
-                         GSocketCallback callback, char *cdata)
-{
-  int count;
-
-  for (count = 0; count < GSOCK_MAX_EVENT; count++)
-  {
-    if ((flags & (1 << count)) != 0)
-    {
-      m_cbacks[count] = callback;
-      m_data[count] = cdata;
-    }
-  }
-}
-
-/* GSocket_UnsetCallback:
- *  Disables all callbacks specified by 'flags', which may be a
- *  combination of flags OR'ed toghether.
- */
-void GSocket::UnsetCallback(GSocketEventFlags flags)
-{
-  int count;
-
-  for (count = 0; count < GSOCK_MAX_EVENT; count++)
-  {
-    if ((flags & (1 << count)) != 0)
-    {
-      m_cbacks[count] = NULL;
-      m_data[count] = NULL;
-    }
-  }
-}
-
 GSocketError GSocket::GetSockOpt(int level, int optname,
                                 void *optval, int *optlen)
 {
index 226f46ad0da8b6110742790d34295b35a67e768c..a7e54ff58b4b0da7710b4613e67fe76762dfdcdc 100644 (file)
@@ -467,7 +467,8 @@ void GSocket_Cleanup()
 
 /* Constructors / Destructors for GSocket */
 
-GSocket::GSocket()
+GSocket::GSocket(wxSocketBase& wxsocket)
+    : GSocketBase(wxsocket)
 {
   m_handler             = NULL;
 
@@ -723,7 +724,7 @@ GSocketError GSocket::SetServer()
  *    GSOCK_MEMERR     - couldn't allocate memory.
  *    GSOCK_IOERR      - low-level error.
  */
-GSocket *GSocket::WaitConnection()
+GSocket *GSocket::WaitConnection(wxSocketBase& wxsocket)
 {
   wxSockAddr from;
   WX_SOCKLEN_T fromlen = sizeof(from);
@@ -741,7 +742,7 @@ GSocket *GSocket::WaitConnection()
   }
 
   /* Create a GSocket object for the new connection */
-  connection = GSocket::Create();
+  connection = GSocket::Create(wxsocket);
 
   if (!connection)
   {
@@ -1238,17 +1239,6 @@ void GSocket::SetNonBlocking(bool non_block)
   m_non_blocking = non_block;
 }
 
-/* GSocket_SetTimeout:
- *  Sets the timeout for blocking calls. Time is expressed in
- *  milliseconds.
- */
-void GSocket::SetTimeout(unsigned long millisec)
-{
-  assert(this);
-
-  m_timeout = millisec;
-}
-
 /* GSocket_GetError:
  *  Returns the last error occurred for this socket. Note that successful
  *  operations do not clear this back to GSOCK_NOERROR, so use it only
@@ -1261,73 +1251,6 @@ GSocketError WXDLLIMPEXP_NET GSocket::GetError()
   return m_error;
 }
 
-/* Callbacks */
-
-/* GSOCK_INPUT:
- *   There is data to be read in the input buffer. If, after a read
- *   operation, there is still data available, the callback function will
- *   be called again.
- * GSOCK_OUTPUT:
- *   The socket is available for writing. That is, the next write call
- *   won't block. This event is generated only once, when the connection is
- *   first established, and then only if a call failed with GSOCK_WOULDBLOCK,
- *   when the output buffer empties again. This means that the app should
- *   assume that it can write since the first OUTPUT event, and no more
- *   OUTPUT events will be generated unless an error occurs.
- * GSOCK_CONNECTION:
- *   Connection successfully established, for client sockets, or incoming
- *   client connection, for server sockets. Wait for this event (also watch
- *   out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
- * GSOCK_LOST:
- *   The connection is lost (or a connection request failed); this could
- *   be due to a failure, or due to the peer closing it gracefully.
- */
-
-/* GSocket_SetCallback:
- *  Enables the callbacks specified by 'flags'. Note that 'flags'
- *  may be a combination of flags OR'ed toghether, so the same
- *  callback function can be made to accept different events.
- *  The callback function must have the following prototype:
- *
- *  void function(GSocket *socket, GSocketEvent event, char *cdata)
- */
-void GSocket::SetCallback(GSocketEventFlags flags,
-                         GSocketCallback callback, char *cdata)
-{
-  int count;
-
-  assert(this);
-
-  for (count = 0; count < GSOCK_MAX_EVENT; count++)
-  {
-    if ((flags & (1 << count)) != 0)
-    {
-      m_cbacks[count] = callback;
-      m_data[count] = cdata;
-    }
-  }
-}
-
-/* GSocket_UnsetCallback:
- *  Disables all callbacks specified by 'flags', which may be a
- *  combination of flags OR'ed toghether.
- */
-void GSocket::UnsetCallback(GSocketEventFlags flags)
-{
-  int count;
-
-  assert(this);
-
-  for (count = 0; count < GSOCK_MAX_EVENT; count++)
-  {
-    if ((flags & (1 << count)) != 0)
-    {
-      m_cbacks[count] = NULL;
-      m_data[count] = NULL;
-    }
-  }
-}
-
 GSocketError GSocket::GetSockOpt(int level, int optname,
                                 void *optval, int *optlen)
 {
@@ -1346,13 +1269,6 @@ GSocketError GSocket::SetSockOpt(int level, int optname,
     return GSOCK_OPTERR;
 }
 
-#define CALL_CALLBACK(socket, event) {                                  \
-  socket->Disable(event);                                               \
-  if (socket->m_cbacks[event])                                          \
-    socket->m_cbacks[event](socket, event, socket->m_data[event]);      \
-}
-
-
 void GSocket::Enable(GSocketEvent event)
 {
     if (m_use_events)
@@ -1573,6 +1489,15 @@ int GSocket::Send_Dgram(const char *buffer, int size)
   return ret;
 }
 
+void GSocket::OnStateChange(GSocketEvent event)
+{
+    Disable(event);
+    NotifyOnStateChange(event);
+
+    if ( event == GSOCK_LOST )
+        Shutdown();
+}
+
 void GSocket::Detected_Read()
 {
   char c;
@@ -1590,8 +1515,7 @@ void GSocket::Detected_Read()
   {
     m_establishing = false;
 
-    CALL_CALLBACK(this, GSOCK_LOST);
-    Shutdown();
+    OnStateChange(GSOCK_LOST);
     return;
   }
 
@@ -1599,26 +1523,25 @@ void GSocket::Detected_Read()
 
   if (num > 0)
   {
-    CALL_CALLBACK(this, GSOCK_INPUT);
+    OnStateChange(GSOCK_INPUT);
   }
   else
   {
     if (m_server && m_stream)
     {
-      CALL_CALLBACK(this, GSOCK_CONNECTION);
+      OnStateChange(GSOCK_CONNECTION);
     }
     else if (num == 0)
     {
       if (m_stream)
       {
         /* graceful shutdown */
-        CALL_CALLBACK(this, GSOCK_LOST);
-        Shutdown();
+        OnStateChange(GSOCK_LOST);
       }
       else
       {
         /* Empty datagram received */
-        CALL_CALLBACK(this, GSOCK_INPUT);
+        OnStateChange(GSOCK_INPUT);
       }
     }
     else
@@ -1626,12 +1549,11 @@ void GSocket::Detected_Read()
       /* Do not throw a lost event in cases where the socket isn't really lost */
       if ((errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINTR))
       {
-        CALL_CALLBACK(this, GSOCK_INPUT);
+        OnStateChange(GSOCK_INPUT);
       }
       else
       {
-        CALL_CALLBACK(this, GSOCK_LOST);
-        Shutdown();
+        OnStateChange(GSOCK_LOST);
       }
     }
   }
@@ -1646,8 +1568,7 @@ void GSocket::Detected_Write()
   {
     m_establishing = false;
 
-    CALL_CALLBACK(this, GSOCK_LOST);
-    Shutdown();
+    OnStateChange(GSOCK_LOST);
     return;
   }
 
@@ -1662,22 +1583,21 @@ void GSocket::Detected_Write()
 
     if (error)
     {
-      CALL_CALLBACK(this, GSOCK_LOST);
-      Shutdown();
+      OnStateChange(GSOCK_LOST);
     }
     else
     {
-      CALL_CALLBACK(this, GSOCK_CONNECTION);
+      OnStateChange(GSOCK_CONNECTION);
       /* We have to fire this event by hand because CONNECTION (for clients)
        * and OUTPUT are internally the same and we just disabled CONNECTION
        * events with the above macro.
        */
-      CALL_CALLBACK(this, GSOCK_OUTPUT);
+      OnStateChange(GSOCK_OUTPUT);
     }
   }
   else
   {
-    CALL_CALLBACK(this, GSOCK_OUTPUT);
+    OnStateChange(GSOCK_OUTPUT);
   }
 }