]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/private/socket.h
Add RunScript and implement on all backends. Document and add a very simple unit...
[wxWidgets.git] / include / wx / private / socket.h
index 9b20bf60ccc3563e2f75bc22f3fa981ecb46bcf8..89a5bd00043f313f453ce1b90e6a133b851ce243 100644 (file)
@@ -1,16 +1,72 @@
-///////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
 // Name:        wx/private/socket.h
-// Purpose:     various wxSocket-related private declarations
-// Author:      Vadim Zeitlin
-// Created:     2008-11-23
+// Purpose:     wxSocketImpl and related declarations
+// Authors:     Guilhem Lavaux, Vadim Zeitlin
+// Created:     April 1997
 // RCS-ID:      $Id$
-// Copyright:   (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
+// Copyright:   (c) 1997 Guilhem Lavaux
+//              (c) 2008 Vadim Zeitlin
 // Licence:     wxWindows licence
-///////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+/*
+    Brief overview of different socket classes:
+
+    - wxSocketBase is the public class representing a socket ("Base" here
+      refers to the fact that wxSocketClient and wxSocketServer are derived
+      from it and predates the convention of using "Base" for common base
+      classes for platform-specific classes in wxWidgets) with implementation
+      common to all platforms and forwarding methods whose implementation
+      differs between platforms to wxSocketImpl which it contains.
+
+    - wxSocketImpl is actually just an abstract base class having only code
+      common to all platforms, the concrete implementation classes derive from
+      it and are created by wxSocketImpl::Create().
+
+    - Some socket operations have different implementations in console-mode and
+      GUI applications. wxSocketManager class exists to abstract this in such
+      way that console applications (using wxBase) don't depend on wxNet. An
+      object of this class is made available via wxApp and GUI applications set
+      up a different kind of global socket manager from console ones.
+
+      TODO: it looks like wxSocketManager could be eliminated by providing
+            methods for registering/unregistering sockets directly in
+            wxEventLoop.
+ */
 
 #ifndef _WX_PRIVATE_SOCKET_H_
 #define _WX_PRIVATE_SOCKET_H_
 
+#include "wx/defs.h"
+
+#if wxUSE_SOCKETS
+
+#include "wx/socket.h"
+#include "wx/private/sckaddr.h"
+
+#include <stddef.h>
+
+/*
+   Including sys/types.h under Cygwin results in the warnings about "fd_set
+   having been defined in sys/types.h" when winsock.h is included later and
+   doesn't seem to be necessary anyhow. It's not needed under Mac neither.
+ */
+#if !defined(__WXMAC__) && !defined(__CYGWIN__) && !defined(__WXWINCE__)
+#include <sys/types.h>
+#endif
+
+#ifdef __WXWINCE__
+#include <stdlib.h>
+#endif
+
+// include the header defining timeval: under Windows this struct is used only
+// with sockets so we need to include winsock.h which we do via windows.h
+#ifdef __WXMSW__
+    #include "wx/msw/wrapwin.h"
+#else
+    #include <sys/time.h>   // for timeval
+#endif
+
 // these definitions are for MSW when we don't use configure, otherwise these
 // symbols are defined by configure
 #ifndef WX_SOCKLEN_T
 
 // define some symbols which winsock.h defines but traditional BSD headers
 // don't
+#ifndef __WXMSW__
+    #define SOCKET int
+#endif
+
 #ifndef INVALID_SOCKET
     #define INVALID_SOCKET (-1)
 #endif
     #define SOCKET_ERROR (-1)
 #endif
 
-#if wxUSE_IPV6
-    typedef struct sockaddr_storage wxSockAddr;
+typedef int wxSocketEventFlags;
+
+class wxSocketImpl;
+
+/*
+   Class providing hooks abstracting the differences between console and GUI
+   applications for socket code.
+
+   We also have different implementations of this class for different platforms
+   allowing us to keep more things in the common code but the main reason for
+   its existence is that we want the same socket code work differently
+   depending on whether it's used from a console or a GUI program. This is
+   achieved by implementing the virtual methods of this class differently in
+   the objects returned by wxConsoleAppTraits::GetSocketManager() and the same
+   method in wxGUIAppTraits.
+ */
+class wxSocketManager
+{
+public:
+    // set the manager to use, we don't take ownership of it
+    //
+    // this should be called before creating the first wxSocket object,
+    // otherwise the manager returned by wxAppTraits::GetSocketManager() will
+    // be used
+    static void Set(wxSocketManager *manager);
+
+    // return the manager to use
+    //
+    // this initializes the manager at first use
+    static wxSocketManager *Get()
+    {
+        if ( !ms_manager )
+            Init();
+
+        return ms_manager;
+    }
+
+    // called before the first wxSocket is created and should do the
+    // initializations needed in order to use the network
+    //
+    // return true if initialized successfully; if this returns false sockets
+    // can't be used at all
+    virtual bool OnInit() = 0;
+
+    // undo the initializations of OnInit()
+    virtual void OnExit() = 0;
+
+
+    // create the socket implementation object matching this manager
+    virtual wxSocketImpl *CreateSocket(wxSocketBase& wxsocket) = 0;
+
+    // these functions enable or disable monitoring of the given socket for the
+    // specified events inside the currently running event loop (but notice
+    // that both BSD and Winsock implementations actually use socket->m_server
+    // value to determine what exactly should be monitored so it needs to be
+    // set before calling these functions)
+    //
+    // the default event value is used just for the convenience of wxMSW
+    // implementation which doesn't use this parameter anyhow, it doesn't make
+    // sense to pass wxSOCKET_LOST for the Unix implementation which does use
+    // this parameter
+    virtual void Install_Callback(wxSocketImpl *socket,
+                                  wxSocketNotify event = wxSOCKET_LOST) = 0;
+    virtual void Uninstall_Callback(wxSocketImpl *socket,
+                                    wxSocketNotify event = wxSOCKET_LOST) = 0;
+
+    virtual ~wxSocketManager() { }
+
+private:
+    // get the manager to use if we don't have it yet
+    static void Init();
+
+    static wxSocketManager *ms_manager;
+};
+
+/*
+    Base class for all socket implementations providing functionality common to
+    BSD and Winsock sockets.
+
+    Objects of this class are not created directly but only via the factory
+    function wxSocketManager::CreateSocket().
+ */
+class wxSocketImpl
+{
+public:
+    virtual ~wxSocketImpl();
+
+    // set various socket properties: all of those can only be called before
+    // creating the socket
+    void SetTimeout(unsigned long millisec);
+    void SetReusable() { m_reusable = true; }
+    void SetBroadcast() { m_broadcast = true; }
+    void DontDoBind() { m_dobind = false; }
+    void SetInitialSocketBuffers(int recv, int send)
+    {
+        m_initialRecvBufferSize = recv;
+        m_initialSendBufferSize = send;
+    }
+
+    wxSocketError SetLocal(const wxSockAddressImpl& address);
+    wxSocketError SetPeer(const wxSockAddressImpl& address);
+
+    // accessors
+    // ---------
+
+    bool IsServer() const { return m_server; }
+
+    const wxSockAddressImpl& GetLocal(); // non const as may update m_local
+    const wxSockAddressImpl& GetPeer() const { return m_peer; }
+
+    wxSocketError GetError() const { return m_error; }
+    bool IsOk() const { return m_error == wxSOCKET_NOERROR; }
+
+    // get the error code corresponding to the last operation
+    virtual wxSocketError GetLastError() const = 0;
+
+
+    // creating/closing the socket
+    // --------------------------
+
+    // notice that SetLocal() must be called before creating the socket using
+    // any of the functions below
+    //
+    // all of Create() functions return wxSOCKET_NOERROR if the operation
+    // completed successfully or one of:
+    //  wxSOCKET_INVSOCK - the socket is in use.
+    //  wxSOCKET_INVADDR - the local (server) or peer (client) address has not
+    //                     been set.
+    //  wxSOCKET_IOERR   - any other error.
+
+    // create a socket listening on the local address specified by SetLocal()
+    // (notice that DontDoBind() is ignored by this function)
+    wxSocketError CreateServer();
+
+    // create a socket connected to the peer address specified by SetPeer()
+    // (notice that DontDoBind() is ignored by this function)
+    //
+    // this function may return wxSOCKET_WOULDBLOCK in addition to the return
+    // values listed above if wait is false
+    wxSocketError CreateClient(bool wait);
+
+    // create (and bind unless DontDoBind() had been called) an UDP socket
+    // associated with the given local address
+    wxSocketError CreateUDP();
+
+    // may be called whether the socket was created or not, calls DoClose() if
+    // it was indeed created
+    void Close();
+
+    // shuts down the writing end of the socket and closes it, this is a more
+    // graceful way to close
+    //
+    // does nothing if the socket wasn't created
+    void Shutdown();
+
+
+    // IO operations
+    // -------------
+
+    // basic IO, work for both TCP and UDP sockets
+    //
+    // return the number of bytes read/written (possibly 0) or -1 on error
+    int Read(void *buffer, int size);
+    int Write(const void *buffer, int size);
+
+    // basically a wrapper for select(): returns the condition of the socket,
+    // blocking for not longer than timeout if it is specified (otherwise just
+    // poll without blocking at all)
+    //
+    // flags defines what kind of conditions we're interested in, the return
+    // value is composed of a (possibly empty) subset of the bits set in flags
+    wxSocketEventFlags Select(wxSocketEventFlags flags,
+                              const timeval *timeout = NULL);
+
+    // convenient wrapper calling Select() with our default timeout
+    wxSocketEventFlags SelectWithTimeout(wxSocketEventFlags flags)
+    {
+        return Select(flags, &m_timeout);
+    }
+
+    // just a wrapper for accept(): it is called to create a new wxSocketImpl
+    // corresponding to a new server connection represented by the given
+    // wxSocketBase, returns NULL on error (including immediately if there are
+    // no pending connections as our sockets are non-blocking)
+    wxSocketImpl *Accept(wxSocketBase& wxsocket);
+
+
+    // notifications
+    // -------------
+
+    // notify m_wxsocket about the given socket event by calling its (inaptly
+    // named) OnRequest() method
+    void NotifyOnStateChange(wxSocketNotify event);
+
+    // called after reading/writing the data from/to the socket and should
+    // enable back the wxSOCKET_INPUT/OUTPUT_FLAG notifications if they were
+    // turned off when this data was first detected
+    virtual void ReenableEvents(wxSocketEventFlags flags) = 0;
+
+    // TODO: make these fields protected and provide accessors for those of
+    //       them that wxSocketBase really needs
+//protected:
+    SOCKET m_fd;
+
+    int m_initialRecvBufferSize;
+    int m_initialSendBufferSize;
+
+    wxSockAddressImpl m_local,
+                      m_peer;
+    wxSocketError m_error;
+
+    bool m_stream;
+    bool m_establishing;
+    bool m_reusable;
+    bool m_broadcast;
+    bool m_dobind;
+
+    struct timeval m_timeout;
+
+protected:
+    wxSocketImpl(wxSocketBase& wxsocket);
+
+    // true if we're a listening stream socket
+    bool m_server;
+
+private:
+    // called by Close() if we have a valid m_fd
+    virtual void DoClose() = 0;
+
+    // put this socket into non-blocking mode and enable monitoring this socket
+    // as part of the event loop
+    virtual void UnblockAndRegisterWithEventLoop() = 0;
+
+    // check that the socket wasn't created yet and that the given address
+    // (either m_local or m_peer depending on the socket kind) is valid and
+    // set m_error and return false if this is not the case
+    bool PreCreateCheck(const wxSockAddressImpl& addr);
+
+    // set the given socket option: this just wraps setsockopt(SOL_SOCKET)
+    int SetSocketOption(int optname, int optval)
+    {
+        // although modern Unix systems use "const void *" for the 4th
+        // parameter here, old systems and Winsock still use "const char *"
+        return setsockopt(m_fd, SOL_SOCKET, optname,
+                          reinterpret_cast<const char *>(&optval),
+                          sizeof(optval));
+    }
+
+    // set the given socket option to true value: this is an even simpler
+    // wrapper for setsockopt(SOL_SOCKET) for boolean options
+    int EnableSocketOption(int optname)
+    {
+        return SetSocketOption(optname, 1);
+    }
+
+    // apply the options to the (just created) socket and register it with the
+    // event loop by calling UnblockAndRegisterWithEventLoop()
+    void PostCreation();
+
+    // update local address after binding/connecting
+    wxSocketError UpdateLocalAddress();
+
+    // functions used to implement Read/Write()
+    int RecvStream(void *buffer, int size);
+    int RecvDgram(void *buffer, int size);
+    int SendStream(const void *buffer, int size);
+    int SendDgram(const void *buffer, int size);
+
+
+    // set in ctor and never changed except that it's reset to NULL when the
+    // socket is shut down
+    wxSocketBase *m_wxsocket;
+
+    wxDECLARE_NO_COPY_CLASS(wxSocketImpl);
+};
+
+#if defined(__WXMSW__)
+    #include "wx/msw/private/sockmsw.h"
 #else
-    typedef struct sockaddr wxSockAddr;
+    #include "wx/unix/private/sockunix.h"
 #endif
 
-#endif // _WX_PRIVATE_SOCKET_H_
+#endif /* wxUSE_SOCKETS */
 
+#endif /* _WX_PRIVATE_SOCKET_H_ */