mirror of https://github.com/macssh/macssh.git
204 lines
11 KiB
C++
Executable File
204 lines
11 KiB
C++
Executable File
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
// % Project : GUSI - Grand Unified Socket Interface
|
|
// % File : GUSIFactory.nw - Socket factories
|
|
// % Author : Matthias Neeracher
|
|
// % Language : C++
|
|
// %
|
|
// % $Log$
|
|
// % Revision 1.1.1.1 2001/03/03 21:50:10 chombier
|
|
// % Initial import
|
|
// %
|
|
// % Revision 1.10 2000/05/23 07:00:00 neeri
|
|
// % Improve formatting
|
|
// %
|
|
// % Revision 1.9 2000/03/15 07:22:07 neeri
|
|
// % Enforce alignment choices
|
|
// %
|
|
// % Revision 1.8 1999/11/15 07:27:18 neeri
|
|
// % Getting ready for GUSI 2.0.1
|
|
// %
|
|
// % Revision 1.7 1999/08/26 05:45:02 neeri
|
|
// % Fixes for literate edition of source code
|
|
// %
|
|
// % Revision 1.6 1999/05/29 06:26:43 neeri
|
|
// % Fixed header guards
|
|
// %
|
|
// % Revision 1.5 1998/11/22 23:06:53 neeri
|
|
// % Releasing 2.0a4 in a hurry
|
|
// %
|
|
// % Revision 1.4 1998/10/25 11:37:37 neeri
|
|
// % More configuration hooks
|
|
// %
|
|
// % Revision 1.3 1998/08/02 11:20:08 neeri
|
|
// % Fixed some typos
|
|
// %
|
|
// % Revision 1.2 1998/01/25 20:53:54 neeri
|
|
// % Engine implemented, except for signals & scheduling
|
|
// %
|
|
// % Revision 1.1 1996/12/16 02:12:40 neeri
|
|
// % TCP Sockets sort of work
|
|
// %
|
|
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
//
|
|
// \chapter{Socket Factories}
|
|
//
|
|
// Instead of creating sockets of some specific subtype of [[GUSISocket]],
|
|
// directly, we choose the more flexible approach of creating them in
|
|
// some instance of a subtype of the abstract factory class [[GUSISocketFactory]].
|
|
// For even more flexibility and a direct mapping to BSD socket domains,
|
|
// [[GUSISocketFactory]] instances are collected in a [[GUSISocketDomainRegistry]].
|
|
// If several types and or protocols in a domain are implemented, they are collected
|
|
// in a [[GUSISocketTypeRegistry]].
|
|
//
|
|
// <GUSIFactory.h>=
|
|
#ifndef _GUSIFactory_
|
|
#define _GUSIFactory_
|
|
|
|
#ifdef GUSI_SOURCE
|
|
|
|
#include "GUSISocket.h"
|
|
|
|
#include <ConditionalMacros.h>
|
|
|
|
#if PRAGMA_STRUCT_ALIGN
|
|
#pragma options align=native
|
|
#endif
|
|
|
|
// \section{Definition of [[GUSISocketFactory]]}
|
|
//
|
|
// [[GUSISocketFactory]] consists of a few maintenance functions and the socket
|
|
// operations.
|
|
//
|
|
// <Definition of class [[GUSISocketFactory]]>=
|
|
class GUSISocketFactory {
|
|
public:
|
|
virtual int socketpair(int domain, int type, int protocol, GUSISocket * s[2]);
|
|
virtual GUSISocket * socket(int domain, int type, int protocol) = 0;
|
|
protected:
|
|
GUSISocketFactory() {}
|
|
virtual ~GUSISocketFactory() {}
|
|
};
|
|
// \section{Definition of [[GUSISocketDomainRegistry]]}
|
|
//
|
|
// The [[GUSISocketDomainRegistry]] is a singleton class registering all socket
|
|
// domains.
|
|
//
|
|
// <Definition of class [[GUSISocketDomainRegistry]]>=
|
|
class GUSISocketDomainRegistry : public GUSISocketFactory {
|
|
public:
|
|
// The only instance of [[GUSISocketDomainRegistry]] is, as usual, obtained by calling
|
|
// [[Instance]]. Calling [[socket]] on this instance will then create a socket.
|
|
//
|
|
// <Socket creation interface of [[GUSISocketDomainRegistry]]>=
|
|
virtual GUSISocket * socket(int domain, int type, int protocol);
|
|
virtual int socketpair(int domain, int type, int protocol, GUSISocket * s[2]);
|
|
static GUSISocketDomainRegistry * Instance();
|
|
// [[AddFactory]] and [[RemoveFactory]] add and remove a [[GUSISocketFactory]]
|
|
// for a given domain number. Both return the previous registrant.
|
|
//
|
|
// <Registration interface of [[GUSISocketDomainRegistry]]>=
|
|
GUSISocketFactory * AddFactory(int domain, GUSISocketFactory * factory);
|
|
GUSISocketFactory * RemoveFactory(int domain);
|
|
private:
|
|
// <Privatissima of [[GUSISocketDomainRegistry]]>=
|
|
static GUSISocketDomainRegistry * sInstance;
|
|
// We store domain factories in a table that is quite comfortably sized.
|
|
//
|
|
// <Privatissima of [[GUSISocketDomainRegistry]]>=
|
|
GUSISocketFactory * factory[AF_MAX];
|
|
GUSISocketDomainRegistry();
|
|
};
|
|
// \section{Definition of [[GUSISocketTypeRegistry]]}
|
|
//
|
|
// A [[GUSISocketTypeRegistry]] registers factories for some domain by type and
|
|
// protocol.
|
|
//
|
|
// <Definition of class [[GUSISocketTypeRegistry]]>=
|
|
class GUSISocketTypeRegistry : public GUSISocketFactory {
|
|
public:
|
|
// [[GUSISocketTypeRegistry]] is not a singleton, but each instance is somewhat
|
|
// singletonish in that it does some delayed initialization only when it's used
|
|
// and at that point registers itself with the [[GUSISocketDomainRegistry]].
|
|
// Calling [[socket]] on these instances will then create a socket.
|
|
//
|
|
// <Socket creation interface of [[GUSISocketTypeRegistry]]>=
|
|
GUSISocketTypeRegistry(int domain, int maxfactory);
|
|
virtual GUSISocket * socket(int domain, int type, int protocol);
|
|
virtual int socketpair(int domain, int type, int protocol, GUSISocket * s[2]);
|
|
// [[AddFactory]] and [[RemoveFactory]] add and remove a [[GUSISocketFactory]]
|
|
// for a given type and protocol (both of which can be specified as 0 to match any
|
|
// value). Both return the previous registrant.
|
|
//
|
|
// <Registration interface of [[GUSISocketTypeRegistry]]>=
|
|
GUSISocketFactory * AddFactory(int type, int protocol, GUSISocketFactory * factory);
|
|
GUSISocketFactory * RemoveFactory(int type, int protocol);
|
|
private:
|
|
// \section{Implementation of [[GUSISocketTypeRegistry]]}
|
|
//
|
|
// We store type factories in a fixed size table. This table is only
|
|
// initialized when any non-constructor public member is called.
|
|
//
|
|
// <Privatissima of [[GUSISocketTypeRegistry]]>=
|
|
struct Entry {
|
|
int type;
|
|
int protocol;
|
|
GUSISocketFactory * factory;
|
|
Entry() : type(0), protocol(0), factory(nil) {}
|
|
};
|
|
Entry * factory;
|
|
int domain;
|
|
int maxfactory;
|
|
// [[Initialize]] initializes the table and registers the object with the
|
|
// [[GUSISocketDomainRegistry]] the first time it's called.
|
|
//
|
|
// <Privatissima of [[GUSISocketTypeRegistry]]>=
|
|
void Initialize();
|
|
// Unlike for a [[GUSISocketDomainRegistry]], match identification for a
|
|
// [[GUSISocketTypeRegistry]] takes a linear search. [[Find]] stops
|
|
// when it has found either a match or an empty slot.
|
|
//
|
|
// <Privatissima of [[GUSISocketTypeRegistry]]>=
|
|
bool Find(int type, int protocol, bool exact, Entry *&found);
|
|
};
|
|
|
|
#if PRAGMA_STRUCT_ALIGN
|
|
#pragma options align=reset
|
|
#endif
|
|
|
|
// \section{Implementation of [[GUSISocketDomainRegistry]]}
|
|
//
|
|
// By now, you should know how singletons are created. Could it be that the
|
|
// combination of Design Patterns and Literate Programming leads to a
|
|
// proliferation of cliches?
|
|
//
|
|
// <Definition of [[GUSISetupFactories]] hook>=
|
|
extern "C" void GUSISetupFactories();
|
|
|
|
// <Inline member functions for class [[GUSISocketDomainRegistry]]>=
|
|
inline GUSISocketDomainRegistry * GUSISocketDomainRegistry::Instance()
|
|
{
|
|
if (!sInstance) {
|
|
sInstance = new GUSISocketDomainRegistry();
|
|
GUSISetupFactories();
|
|
}
|
|
|
|
return sInstance;
|
|
}
|
|
// [[RemoveFactory]] can actually be implemented in terms of [[AddFactory]] but
|
|
// that might confuse readers.
|
|
//
|
|
// <Inline member functions for class [[GUSISocketDomainRegistry]]>=
|
|
inline GUSISocketFactory * GUSISocketDomainRegistry::RemoveFactory(int domain)
|
|
{
|
|
return AddFactory(domain, nil);
|
|
}
|
|
// <Inline member functions for class [[GUSISocketTypeRegistry]]>=
|
|
inline GUSISocketTypeRegistry::GUSISocketTypeRegistry(int domain, int maxfactory)
|
|
: domain(domain), maxfactory(maxfactory), factory(nil)
|
|
{
|
|
}
|
|
|
|
#endif /* GUSI_SOURCE */
|
|
|
|
#endif /* _GUSIFactory_ */
|