more socket cleanup to allow using wxSocket from both wxBase and wxCore (replaces patch 1756260)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@50831 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2007-12-19 16:45:08 +00:00
parent 4813bb8d72
commit 2804f77d88
54 changed files with 3817 additions and 1933 deletions

View File

@@ -30,7 +30,7 @@ class WXDLLIMPEXP_FWD_BASE wxString;
class WXDLLIMPEXP_FWD_BASE wxTimer;
class WXDLLIMPEXP_FWD_BASE wxTimerImpl;
class GSocketGUIFunctionsTable;
class GSocketManager;
// ----------------------------------------------------------------------------
@@ -116,13 +116,9 @@ public:
virtual void RemoveFromPendingDelete(wxObject *object) = 0;
#if wxUSE_SOCKETS
// return table of GUI callbacks for GSocket code or NULL in wxBase. This
// is needed because networking classes are in their own library and so
// they can't directly call GUI functions (the same net library can be
// used in both GUI and base apps). To complicate it further, GUI library
// ("wxCore") doesn't depend on networking library and so only a functions
// table can be passed around
virtual GSocketGUIFunctionsTable* GetSocketGUIFunctionsTable() = 0;
// return socket manager: this is usually different for console and GUI
// applications (although some ports use the same implementation for both)
virtual GSocketManager *GetSocketManager() = 0;
#endif
// create a new, port specific, instance of the event loop used by wxApp
@@ -220,9 +216,6 @@ public:
virtual wxFontMapper *CreateFontMapper();
#endif // wxUSE_FONTMAP
virtual wxRendererNative *CreateRenderer();
#if wxUSE_SOCKETS
virtual GSocketGUIFunctionsTable* GetSocketGUIFunctionsTable();
#endif
#ifdef __WXDEBUG__
virtual bool ShowAssertDialog(const wxString& msg);
@@ -264,9 +257,6 @@ public:
virtual wxFontMapper *CreateFontMapper();
#endif // wxUSE_FONTMAP
virtual wxRendererNative *CreateRenderer();
#if wxUSE_SOCKETS
virtual GSocketGUIFunctionsTable* GetSocketGUIFunctionsTable();
#endif
#ifdef __WXDEBUG__
virtual bool ShowAssertDialog(const wxString& msg);

View File

@@ -2,26 +2,24 @@
* Project: GSocket (Generic Socket)
* Name: gsocket.h
* Author: Guilhem Lavaux
* Guillermo Rodriguez Garcia <guille@iies.es> (maintainer)
* Guillermo Rodriguez Garcia <guille@iies.es>
* Copyright: (c) Guilhem Lavaux
* (c) 2007 Vadim Zeitlin <vadim@wxwidgets.org>
* Licence: wxWindows Licence
* Purpose: GSocket include file (system independent)
* CVSID: $Id$
* -------------------------------------------------------------------------
*/
#ifndef __GSOCKET_H
#define __GSOCKET_H
#ifndef _WX_GSOCKET_H_
#define _WX_GSOCKET_H_
#ifndef __GSOCKET_STANDALONE__
#include "wx/defs.h"
#if wxUSE_SOCKETS
#include "wx/dlimpexp.h" /* for WXDLLIMPEXP_NET */
#endif
#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
#include <stddef.h>
/*
@@ -37,27 +35,24 @@
#include <stdlib.h>
#endif
class GSocket;
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _GAddress GAddress;
typedef enum {
enum GAddressType
{
GSOCK_NOFAMILY = 0,
GSOCK_INET,
GSOCK_INET6,
GSOCK_UNIX
} GAddressType;
};
typedef enum {
enum GSocketStream
{
GSOCK_STREAMED,
GSOCK_UNSTREAMED
} GSocketStream;
};
typedef enum {
enum GSocketError
{
GSOCK_NOERROR = 0,
GSOCK_INVOP,
GSOCK_IOERR,
@@ -69,19 +64,21 @@ typedef enum {
GSOCK_TIMEDOUT,
GSOCK_MEMERR,
GSOCK_OPTERR
} GSocketError;
};
/* See below for an explanation on how events work.
*/
typedef enum {
enum GSocketEvent
{
GSOCK_INPUT = 0,
GSOCK_OUTPUT = 1,
GSOCK_CONNECTION = 2,
GSOCK_LOST = 3,
GSOCK_MAX_EVENT = 4
} GSocketEvent;
};
enum {
enum
{
GSOCK_INPUT_FLAG = 1 << GSOCK_INPUT,
GSOCK_OUTPUT_FLAG = 1 << GSOCK_OUTPUT,
GSOCK_CONNECTION_FLAG = 1 << GSOCK_CONNECTION,
@@ -90,54 +87,99 @@ enum {
typedef int GSocketEventFlags;
class GSocket;
typedef void (*GSocketCallback)(GSocket *socket, GSocketEvent event,
char *cdata);
/*
Class providing hooks abstracting the differences between console and GUI
applications for socket code.
/* Functions tables for internal use by GSocket code: */
/* Actually this is a misnomer now, but reusing this name means I don't
have to ifdef app traits or common socket code */
class GSocketGUIFunctionsTable
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::GetSocketFunctionsTable() and
the same method in wxGUIAppTraits.
*/
class GSocketManager
{
public:
// needed since this class declares virtual members
virtual ~GSocketGUIFunctionsTable() { }
// set the manager to use, we don't take ownership of it
//
// this should be called before GSocket_Init(), i.e. before the first
// wxSocket object is created, otherwise the manager returned by
// wxAppTraits::GetSocketManager() will be used
static void Set(GSocketManager *manager);
// return the manager to use
//
// this initializes the manager at first use
static GSocketManager *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
virtual bool OnInit() = 0;
// undo the initializations of OnInit()
virtual void OnExit() = 0;
virtual bool CanUseEventLoop() = 0;
// do manager-specific socket initializations (and undo it): this is called
// in the beginning/end of the socket initialization/destruction
virtual bool Init_Socket(GSocket *socket) = 0;
virtual void Destroy_Socket(GSocket *socket) = 0;
#ifndef __WINDOWS__
virtual void Install_Callback(GSocket *socket, GSocketEvent event) = 0;
virtual void Uninstall_Callback(GSocket *socket, GSocketEvent event) = 0;
#endif
virtual void Enable_Events(GSocket *socket) = 0;
virtual void Disable_Events(GSocket *socket) = 0;
virtual ~GSocketManager() { }
private:
// get the manager to use if we don't have it yet
static void Init();
static GSocketManager *ms_manager;
};
#if defined(__WINDOWS__)
#include "wx/msw/gsockmsw.h"
#else
#include "wx/unix/gsockunx.h"
#endif
/* Global initializers */
/* Sets GUI functions callbacks. Must be called *before* GSocket_Init
if the app uses async sockets. */
void GSocket_SetGUIFunctions(GSocketGUIFunctionsTable *guifunc);
/* GSocket_Init() must be called at the beginning */
int GSocket_Init(void);
/* GSocket_Init() must be called at the beginning (but after calling
* GSocketManager::Set() if a custom manager should be used) */
bool GSocket_Init();
/* GSocket_Cleanup() must be called at the end */
void GSocket_Cleanup(void);
void GSocket_Cleanup();
/* Constructors / Destructors */
GSocket *GSocket_new(void);
GSocket *GSocket_new();
/* GAddress */
GAddress *GAddress_new(void);
GAddress *GAddress_new();
GAddress *GAddress_copy(GAddress *address);
void GAddress_destroy(GAddress *address);
@@ -185,16 +227,6 @@ unsigned short GAddress_INET6_GetPort(GAddress *address);
GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path);
GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* wxUSE_SOCKETS */
# if defined(__WINDOWS__)
# include "wx/msw/gsockmsw.h"
# else
# include "wx/unix/gsockunx.h"
# endif
#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */
#endif /* __GSOCKET_H */
#endif /* _WX_GSOCKET_H_ */

View File

@@ -13,7 +13,8 @@
#define _WX_PRIVATE_H_
#include "wx/defs.h"
#include "X11/Xlib.h"
#include <X11/Xlib.h>
#include <Xm/Xm.h>
#include "wx/evtloop.h"
class WXDLLIMPEXP_FWD_CORE wxFont;

View File

@@ -45,10 +45,32 @@ public:
// the GUI code, WAIT_OBJECT_0 + 1 if a Windows message arrived
virtual WXDWORD WaitForThread(WXHANDLE hThread) = 0;
// wxSocket support
// ----------------
#if wxUSE_SOCKETS
// this function is used by wxNet library to set the default socket manager
// to use: doing it like this allows us to keep all socket-related code in
// wxNet instead of having to pull it in wxBase itself as we'd have to do
// if we really implemented GSocketManager here
//
// we don't take ownership of this pointer, it should have a lifetime
// greater than that of any socket (e.g. be a pointer to a static object)
static void SetDefaultSocketManager(GSocketManager *manager)
{
ms_manager = manager;
}
virtual GSocketManager *GetSocketManager() { return ms_manager; }
#endif // wxUSE_SOCKETS
protected:
// implementation of WaitForThread() for the console applications which is
// also used by the GUI code if it doesn't [yet|already} dispatch events
WXDWORD DoSimpleWaitForThread(WXHANDLE hThread);
static GSocketManager *ms_manager;
};
#endif // _WX_MSW_APPTBASE_H_

View File

@@ -8,20 +8,8 @@
* -------------------------------------------------------------------------
*/
#ifndef __GSOCK_MSW_H
#define __GSOCK_MSW_H
#ifndef __GSOCKET_STANDALONE__
#include "wx/setup.h"
#endif
#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
#ifndef __GSOCKET_STANDALONE__
#include "wx/gsocket.h"
#else
#include "gsocket.h"
#endif
#ifndef _WX_MSW_GSOCKMSW_H_
#define _WX_MSW_GSOCKMSW_H_
#include "wx/msw/wrapwin.h"
@@ -35,18 +23,6 @@
#include <winsock.h>
#endif
class GSocketGUIFunctionsTableConcrete: public GSocketGUIFunctionsTable
{
public:
virtual bool OnInit();
virtual void OnExit();
virtual bool CanUseEventLoop();
virtual bool Init_Socket(GSocket *socket);
virtual void Destroy_Socket(GSocket *socket);
virtual void Enable_Events(GSocket *socket);
virtual void Disable_Events(GSocket *socket);
};
/* Definition of GSocket */
class GSocket
{
@@ -62,6 +38,8 @@ public:
GAddress *GetPeer();
GSocketError SetServer();
GSocket *WaitConnection();
// not used under MSW
void Notify(bool) { }
bool SetReusable();
bool SetBroadcast();
bool DontDoBind();
@@ -123,10 +101,6 @@ public:
int m_msgnumber;
};
#ifdef __cplusplus
extern "C" {
#endif
/* Definition of GAddress */
struct _GAddress
{
@@ -149,10 +123,4 @@ GSocketError _GAddress_translate_to (GAddress *address,
GSocketError _GAddress_Init_INET(GAddress *address);
GSocketError _GAddress_Init_UNIX(GAddress *address);
#ifdef __cplusplus
}
#endif
#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */
#endif /* __GSOCK_MSW_H */
#endif /* _WX_MSW_GSOCKMSW_H_ */

View File

@@ -2,7 +2,6 @@
// Name: wx/private/gsocketiohandler.h
// Purpose: class for registering GSocket in wxSelectDispatcher
// Authors: Lukasz Michalski
// Modified by:
// Created: December 2006
// Copyright: (c) Lukasz Michalski
// RCS-ID: $Id$
@@ -13,30 +12,34 @@
#define _WX_PRIVATE_GSOCKETIOHANDLER_H_
#include "wx/defs.h"
#if wxUSE_SOCKETS && wxUSE_SELECT_DISPATCHER
#include "wx/private/selectdispatcher.h"
#include "wx/gsocket.h"
#if wxUSE_SOCKETS
// forward declarations
class GSocket;
class WXDLLIMPEXP_CORE wxGSocketIOHandler : public wxFDIOHandler
class WXDLLIMPEXP_BASE wxGSocketIOHandler : public wxFDIOHandler
{
public:
wxGSocketIOHandler(GSocket* socket);
int GetFlags() const;
void RemoveFlag(wxFDIODispatcherEntryFlags flag);
void AddFlag(wxFDIODispatcherEntryFlags flag);
wxGSocketIOHandler(GSocket* socket)
{
m_socket = socket;
m_flags = 0;
}
virtual void OnReadWaiting();
virtual void OnWriteWaiting();
virtual void OnExceptionWaiting();
int GetFlags() const { return m_flags; }
void RemoveFlag(wxFDIODispatcherEntryFlags flag) { m_flags &= ~flag; }
void AddFlag(wxFDIODispatcherEntryFlags flag) { m_flags |= flag; }
virtual void OnReadWaiting() { m_socket->Detected_Read(); }
virtual void OnWriteWaiting() { m_socket->Detected_Write(); }
virtual void OnExceptionWaiting() { m_socket->Detected_Read(); }
private:
GSocket* m_socket;
int m_flags;
};
#endif // wxUSE_SOCKETS
#endif // wxUSE_SOCKETS && wxUSE_SELECT_DISPATCHER
#endif // _WX_PRIVATE_SOCKETEVTDISPATCH_H_

View File

@@ -48,6 +48,13 @@ public:
// ----------------
// TODO
#if wxUSE_SOCKETS
// returns the select()-based socket manager for console applications which
// is also used by some ports (wxX11, wxDFB) in the GUI build (hence it is
// here and not in wxConsoleAppTraits)
virtual GSocketManager *GetSocketManager();
#endif
};
#endif // _WX_UNIX_APPTBASE_H_

View File

@@ -67,6 +67,17 @@ public:
#if defined(__WXDEBUG__) && defined(__WXGTK20__)
virtual bool ShowAssertDialog(const wxString& msg);
#endif
// GTK+ and Motif integrate sockets directly in their main loop, the other
// Unix ports do it at wxEventLoop level
//
// TODO: Should we use XtAddInput() for wxX11 too? Or, vice versa, if there
// is no advantage in doing this compared to the generic way
// currently used by wxX11, should we continue to use GTK/Motif-
// specific stuff?
#if wxUSE_SOCKETS && (defined(__WXGTK__) || defined(__WXMOTIF__))
virtual GSocketManager *GetSocketManager();
#endif
};
#endif // wxUSE_GUI

View File

@@ -8,37 +8,11 @@
* -------------------------------------------------------------------------
*/
#ifndef __GSOCK_UNX_H
#define __GSOCK_UNX_H
#ifndef __GSOCKET_STANDALONE__
#include "wx/setup.h"
#endif
#ifndef _WX_UNIX_GSOCKUNX_H_
#define _WX_UNIX_GSOCKUNX_H_
class wxGSocketIOHandler;
#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
#ifndef __GSOCKET_STANDALONE__
#include "wx/gsocket.h"
#else
#include "gsocket.h"
#endif
class GSocketGUIFunctionsTableConcrete : public GSocketGUIFunctionsTable
{
public:
virtual bool OnInit();
virtual void OnExit();
virtual bool CanUseEventLoop();
virtual bool Init_Socket(GSocket *socket);
virtual void Destroy_Socket(GSocket *socket);
virtual void Install_Callback(GSocket *socket, GSocketEvent event);
virtual void Uninstall_Callback(GSocket *socket, GSocketEvent event);
virtual void Enable_Events(GSocket *socket);
virtual void Disable_Events(GSocket *socket);
};
class GSocket
{
public:
@@ -70,6 +44,8 @@ public:
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)
@@ -79,6 +55,9 @@ public:
}
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();
@@ -108,18 +87,18 @@ public:
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];
char *m_gui_dependent;
// pointer for storing extra (usually GUI-specific) data
void *m_gui_dependent;
};
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Definition of GAddress */
struct _GAddress
{
@@ -131,15 +110,6 @@ struct _GAddress
GSocketError m_error;
};
#ifdef __cplusplus
}
#endif /* __cplusplus */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* GAddress */
@@ -150,11 +120,121 @@ GSocketError _GAddress_translate_to (GAddress *address,
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() { }
#ifdef __cplusplus
}
#endif /* __cplusplus */
// 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);
#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */
fds[0] = -1;
fds[1] = -1;
#endif /* __GSOCK_UNX_H */
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_ */