git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@50831 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			241 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -------------------------------------------------------------------------
 | 
						|
 * Project:     GSocket (Generic Socket) for WX
 | 
						|
 * Name:        gsockunx.h
 | 
						|
 * Copyright:   (c) Guilhem Lavaux
 | 
						|
 * Licence:     wxWindows Licence
 | 
						|
 * Purpose:     GSocket Unix header
 | 
						|
 * CVSID:       $Id$
 | 
						|
 * -------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef _WX_UNIX_GSOCKUNX_H_
 | 
						|
#define _WX_UNIX_GSOCKUNX_H_
 | 
						|
 | 
						|
class wxGSocketIOHandler;
 | 
						|
 | 
						|
class GSocket
 | 
						|
{
 | 
						|
public:
 | 
						|
    GSocket();
 | 
						|
    virtual ~GSocket();
 | 
						|
    bool IsOk() { return m_ok; }
 | 
						|
    void Close();
 | 
						|
    void Shutdown();
 | 
						|
    GSocketError SetLocal(GAddress *address);
 | 
						|
    GSocketError SetPeer(GAddress *address);
 | 
						|
    GAddress *GetLocal();
 | 
						|
    GAddress *GetPeer();
 | 
						|
    GSocketError SetServer();
 | 
						|
    GSocket *WaitConnection();
 | 
						|
    bool SetReusable();
 | 
						|
    bool SetBroadcast();
 | 
						|
    bool DontDoBind();
 | 
						|
    GSocketError Connect(GSocketStream stream);
 | 
						|
    GSocketError SetNonOriented();
 | 
						|
    int Read(char *buffer, int size);
 | 
						|
    int Write(const char *buffer, int size);
 | 
						|
    GSocketEventFlags Select(GSocketEventFlags flags);
 | 
						|
    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);
 | 
						|
    //attach or detach from main loop
 | 
						|
    void Notify(bool flag);
 | 
						|
    virtual void Detected_Read();
 | 
						|
    virtual void Detected_Write();
 | 
						|
    void SetInitialSocketBuffers(int recv, int send)
 | 
						|
    {
 | 
						|
        m_initialRecvBufferSize = recv;
 | 
						|
        m_initialSendBufferSize = send;
 | 
						|
    }
 | 
						|
 | 
						|
protected:
 | 
						|
    //enable or disable event callback using gsocket gui callback table
 | 
						|
    void EnableEvents(bool flag = true);
 | 
						|
    void DisableEvents() { EnableEvents(false); }
 | 
						|
    void Enable(GSocketEvent event);
 | 
						|
    void Disable(GSocketEvent event);
 | 
						|
    GSocketError Input_Timeout();
 | 
						|
    GSocketError 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);
 | 
						|
    bool m_ok;
 | 
						|
    int m_initialRecvBufferSize;
 | 
						|
    int m_initialSendBufferSize;
 | 
						|
public:
 | 
						|
    /* DFE: We can't protect these data member until the GUI code is updated */
 | 
						|
    /* protected: */
 | 
						|
  int m_fd;
 | 
						|
  wxGSocketIOHandler *m_handler;
 | 
						|
  GAddress *m_local;
 | 
						|
  GAddress *m_peer;
 | 
						|
  GSocketError m_error;
 | 
						|
 | 
						|
  bool m_non_blocking;
 | 
						|
  bool m_server;
 | 
						|
  bool m_stream;
 | 
						|
  bool m_establishing;
 | 
						|
  bool m_reusable;
 | 
						|
  bool m_broadcast;
 | 
						|
  bool m_dobind;
 | 
						|
  unsigned long m_timeout;
 | 
						|
 | 
						|
  // true if socket should fire events
 | 
						|
  bool m_use_events;
 | 
						|
 | 
						|
  /* Callbacks */
 | 
						|
  GSocketEventFlags m_detected;
 | 
						|
  GSocketCallback m_cbacks[GSOCK_MAX_EVENT];
 | 
						|
  char *m_data[GSOCK_MAX_EVENT];
 | 
						|
 | 
						|
  // pointer for storing extra (usually GUI-specific) data
 | 
						|
  void *m_gui_dependent;
 | 
						|
};
 | 
						|
 | 
						|
/* Definition of GAddress */
 | 
						|
struct _GAddress
 | 
						|
{
 | 
						|
  struct sockaddr *m_addr;
 | 
						|
  size_t m_len;
 | 
						|
 | 
						|
  GAddressType m_family;
 | 
						|
  int m_realfamily;
 | 
						|
 | 
						|
  GSocketError m_error;
 | 
						|
};
 | 
						|
 | 
						|
/* GAddress */
 | 
						|
 | 
						|
GSocketError _GAddress_translate_from(GAddress *address,
 | 
						|
                                      struct sockaddr *addr, int len);
 | 
						|
GSocketError _GAddress_translate_to  (GAddress *address,
 | 
						|
                                      struct sockaddr **addr, int *len);
 | 
						|
GSocketError _GAddress_Init_INET(GAddress *address);
 | 
						|
GSocketError _GAddress_Init_UNIX(GAddress *address);
 | 
						|
 | 
						|
// A version of GSocketManager which uses FDs for socket IO
 | 
						|
//
 | 
						|
// This class uses GSocket::m_gui_dependent field to store the 2 (for input and
 | 
						|
// output) FDs associated with the socket.
 | 
						|
class GSocketFDBasedManager : public GSocketManager
 | 
						|
{
 | 
						|
public:
 | 
						|
    // no special initialization/cleanup needed when using FDs
 | 
						|
    virtual bool OnInit() { return true; }
 | 
						|
    virtual void OnExit() { }
 | 
						|
 | 
						|
    // allocate/free the storage we need
 | 
						|
    virtual bool Init_Socket(GSocket *socket)
 | 
						|
    {
 | 
						|
        socket->m_gui_dependent = malloc(sizeof(int)*2);
 | 
						|
        int * const fds = wx_static_cast(int *, socket->m_gui_dependent);
 | 
						|
 | 
						|
        fds[0] = -1;
 | 
						|
        fds[1] = -1;
 | 
						|
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
    virtual void Destroy_Socket(GSocket *socket)
 | 
						|
    {
 | 
						|
        free(socket->m_gui_dependent);
 | 
						|
    }
 | 
						|
 | 
						|
    virtual void Enable_Events(GSocket *socket)
 | 
						|
    {
 | 
						|
        Install_Callback(socket, GSOCK_INPUT);
 | 
						|
        Install_Callback(socket, GSOCK_OUTPUT);
 | 
						|
    }
 | 
						|
    virtual void Disable_Events(GSocket *socket)
 | 
						|
    {
 | 
						|
        Uninstall_Callback(socket, GSOCK_INPUT);
 | 
						|
        Uninstall_Callback(socket, GSOCK_OUTPUT);
 | 
						|
    }
 | 
						|
 | 
						|
protected:
 | 
						|
    // identifies either input or output direction
 | 
						|
    //
 | 
						|
    // NB: the values of this enum shouldn't change
 | 
						|
    enum SocketDir
 | 
						|
    {
 | 
						|
        FD_INPUT,
 | 
						|
        FD_OUTPUT
 | 
						|
    };
 | 
						|
 | 
						|
    // get the FD index corresponding to the given GSocketEvent
 | 
						|
    SocketDir GetDirForEvent(GSocket *socket, GSocketEvent event)
 | 
						|
    {
 | 
						|
        switch ( event )
 | 
						|
        {
 | 
						|
            default:
 | 
						|
                wxFAIL_MSG( "unexpected socket event" );
 | 
						|
                // fall through
 | 
						|
 | 
						|
            case GSOCK_LOST:
 | 
						|
                // fall through
 | 
						|
 | 
						|
            case GSOCK_INPUT:
 | 
						|
                return FD_INPUT;
 | 
						|
 | 
						|
            case GSOCK_OUTPUT:
 | 
						|
                return FD_OUTPUT;
 | 
						|
 | 
						|
            case GSOCK_CONNECTION:
 | 
						|
                // FIXME: explain this?
 | 
						|
                return socket->m_server ? FD_INPUT : FD_OUTPUT;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // access the FDs we store
 | 
						|
    int& FD(GSocket *socket, SocketDir d)
 | 
						|
    {
 | 
						|
        return wx_static_cast(int *, socket->m_gui_dependent)[d];
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
// Common base class for all ports using X11-like (and hence implemented in
 | 
						|
// X11, Motif and GTK) AddInput() and RemoveInput() functions
 | 
						|
class GSocketInputBasedManager : public GSocketFDBasedManager
 | 
						|
{
 | 
						|
public:
 | 
						|
    virtual void Install_Callback(GSocket *socket, GSocketEvent 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);
 | 
						|
    }
 | 
						|
 | 
						|
    virtual void Uninstall_Callback(GSocket *socket, GSocketEvent 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(GSocket *socket, SocketDir d) = 0;
 | 
						|
    virtual void RemoveInput(int fd) = 0;
 | 
						|
};
 | 
						|
 | 
						|
#endif  /* _WX_UNIX_GSOCKUNX_H_ */
 |