mirror of https://github.com/macssh/macssh.git
218 lines
9.9 KiB
C++
Executable File
218 lines
9.9 KiB
C++
Executable File
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
// % Project : GUSI - Grand Unified Socket Interface
|
|
// % File : GUSIDescriptor.nw - Descriptor Table
|
|
// % Author : Matthias Neeracher
|
|
// % Language : C++
|
|
// %
|
|
// % $Log$
|
|
// % Revision 1.2 2001/03/28 14:03:59 chombier
|
|
// % GUSI 2.1.6b2 update
|
|
// %
|
|
// % Revision 1.1.1.1 2001/03/07 09:50:41 chombier
|
|
// % First Imported.
|
|
// %
|
|
// % Revision 1.1.1.1 2001/03/03 21:50:10 chombier
|
|
// % Initial import
|
|
// %
|
|
// % Revision 1.15 2001/01/22 04:31:11 neeri
|
|
// % Last minute changes for 2.1.5
|
|
// %
|
|
// % Revision 1.14 2001/01/17 08:40:17 neeri
|
|
// % Prevent inlining of overridable functions
|
|
// %
|
|
// % Revision 1.13 2000/06/12 04:23:43 neeri
|
|
// % Return values, not references; Introduce support for multiple descriptor tables
|
|
// %
|
|
// % Revision 1.12 2000/05/23 06:58:03 neeri
|
|
// % Improve formatting
|
|
// %
|
|
// % Revision 1.11 2000/03/15 07:14:26 neeri
|
|
// % Prevent double destruction of descriptor table
|
|
// %
|
|
// % Revision 1.10 2000/03/06 06:26:57 neeri
|
|
// % Introduce (and call) CloseAllDescriptors()
|
|
// %
|
|
// % Revision 1.9 1999/08/26 05:45:01 neeri
|
|
// % Fixes for literate edition of source code
|
|
// %
|
|
// % Revision 1.8 1999/08/02 07:02:43 neeri
|
|
// % Support for asynchronous errors and other socket options
|
|
// %
|
|
// % Revision 1.7 1999/06/30 07:42:05 neeri
|
|
// % Getting ready to release 2.0b3
|
|
// %
|
|
// % Revision 1.6 1999/05/29 06:26:42 neeri
|
|
// % Fixed header guards
|
|
// %
|
|
// % Revision 1.5 1999/04/29 05:00:48 neeri
|
|
// % Fix bug with bizarre uses of dup2
|
|
// %
|
|
// % Revision 1.4 1999/03/17 09:05:06 neeri
|
|
// % Added GUSITimer, expanded docs
|
|
// %
|
|
// % Revision 1.3 1998/10/11 16:45:12 neeri
|
|
// % Ready to release 2.0a2
|
|
// %
|
|
// % Revision 1.2 1998/08/01 21:32:03 neeri
|
|
// % About ready for 2.0a1
|
|
// %
|
|
// % Revision 1.1 1998/01/25 21:02:44 neeri
|
|
// % Engine implemented, except for signals & scheduling
|
|
// %
|
|
// % Revision 1.1 1996/12/16 02:12:40 neeri
|
|
// % TCP Sockets sort of work
|
|
// %
|
|
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
//
|
|
// \chapter{Mapping descriptors to sockets}
|
|
//
|
|
// POSIX routines do not, of course, operate on [[GUSISockets]] but on
|
|
// numerical descriptors. The [[GUSIDescriptorTable]] singleton maps between
|
|
// descriptors and their [[GUSISockets]].
|
|
//
|
|
// <GUSIDescriptor.h>=
|
|
#ifndef _GUSIDescriptor_
|
|
#define _GUSIDescriptor_
|
|
|
|
#ifdef GUSI_SOURCE
|
|
|
|
#include "GUSISocket.h"
|
|
|
|
#include <ConditionalMacros.h>
|
|
|
|
#if PRAGMA_STRUCT_ALIGN
|
|
#pragma options align=native
|
|
#endif
|
|
|
|
// \section{Definition of [[GUSIDescriptorTable]]}
|
|
//
|
|
// A [[GUSIDescriptorTable]] is another singleton class, behaving in many aspects
|
|
// like an array of [[GUSISocket]] pointers. [[InstallSocket]] installs a new socket
|
|
// into the table, picking the first available slot with a descriptor greater than
|
|
// or equal to [[start]]. [[RemoveSocket]] empties one slot.
|
|
// [[GUSIDescriptorTable::LookupSocket]] is a shorthand for
|
|
// [[ (*GUSIDescriptorTable::Instance())[fd] ]].
|
|
//
|
|
// To allow for light-weight processes, we provide a copy constructor and
|
|
// the [[SetInstance]] member.
|
|
//
|
|
// <Definition of class [[GUSIDescriptorTable]]>=
|
|
class GUSIDescriptorTable {
|
|
public:
|
|
// enum { SIZE = 64 };
|
|
enum { SIZE = 256 };
|
|
|
|
static GUSIDescriptorTable * Instance();
|
|
|
|
int InstallSocket(GUSISocket * sock, int start = 0);
|
|
int RemoveSocket(int fd);
|
|
GUSISocket * operator[](int fd);
|
|
static GUSISocket * LookupSocket(int fd);
|
|
|
|
class iterator;
|
|
friend class iterator;
|
|
|
|
iterator begin();
|
|
iterator end();
|
|
|
|
~GUSIDescriptorTable();
|
|
|
|
static void CloseAllDescriptors();
|
|
|
|
static void SetInstance(GUSIDescriptorTable * table);
|
|
|
|
GUSIDescriptorTable();
|
|
GUSIDescriptorTable(const GUSIDescriptorTable & parent);
|
|
private:
|
|
// \section{Implementation of [[GUSIDescriptorTable]]}
|
|
//
|
|
// On creation, a [[GUSIDescriptorTable]] clears all descriptors.
|
|
//
|
|
// <Privatissima of [[GUSIDescriptorTable]]>=
|
|
GUSISocket * fSocket[SIZE];
|
|
int fInvalidDescriptor;
|
|
// <Privatissima of [[GUSIDescriptorTable]]>=
|
|
static GUSIDescriptorTable * sGUSIDescriptorTable;
|
|
};
|
|
|
|
#if PRAGMA_STRUCT_ALIGN
|
|
#pragma options align=reset
|
|
#endif
|
|
|
|
// If no instance exists yet, [[GUSIDescriptorTable::Instance]] creates one and
|
|
// calls [[GUSISetupConsole]] if the [[setupConsole]] parameter is true.
|
|
// [[GUSISetupConsole]] calls [[GUSIDefaultSetupConsole]], which first calls
|
|
// [[GUSISetupConsoleDescriptors]] to set up file descriptors 0, 1, and 2, and
|
|
// then calls [[GUSISetupConsoleStdio]] to deal with the necessary initializations
|
|
// on the stdio level.
|
|
//
|
|
// <Hooks for ANSI library interfaces>=
|
|
extern "C" {
|
|
void GUSISetupDescriptorTable();
|
|
void GUSISetupConsole();
|
|
void GUSIDefaultSetupConsole();
|
|
void GUSISetupConsoleDescriptors();
|
|
void GUSISetupConsoleStdio();
|
|
}
|
|
// Destructing a [[GUSIDescriptorTable]] may be a bit problematic, as this
|
|
// may have effects reaching up into the stdio layer. We therefore factor
|
|
// out the stdio aspects into the procedures [[StdioClose]] and [[StdioFlush]]
|
|
// which we then can redefine in other, stdio library specific, libraries.
|
|
//
|
|
// <Hooks for ANSI library interfaces>=
|
|
extern "C" {
|
|
void GUSIStdioClose();
|
|
void GUSIStdioFlush();
|
|
}
|
|
|
|
// <Inline member functions for class [[GUSIDescriptorTable]]>=
|
|
class GUSIDescriptorTable::iterator {
|
|
public:
|
|
iterator(GUSIDescriptorTable * table, int fd = 0) : fTable(table), fFd(fd) {}
|
|
GUSIDescriptorTable::iterator & operator++();
|
|
GUSIDescriptorTable::iterator operator++(int);
|
|
int operator*() { return fFd; }
|
|
bool operator==(const GUSIDescriptorTable::iterator & other) const;
|
|
private:
|
|
GUSIDescriptorTable * fTable;
|
|
int fFd;
|
|
};
|
|
|
|
inline GUSIDescriptorTable::iterator & GUSIDescriptorTable::iterator::operator++()
|
|
{
|
|
while (++fFd < fTable->fInvalidDescriptor && !fTable->fSocket[fFd])
|
|
;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline GUSIDescriptorTable::iterator GUSIDescriptorTable::iterator::operator++(int)
|
|
{
|
|
int oldFD = fFd;
|
|
|
|
while (++fFd < fTable->fInvalidDescriptor && !fTable->fSocket[fFd])
|
|
;
|
|
|
|
return GUSIDescriptorTable::iterator(fTable, oldFD);
|
|
}
|
|
|
|
inline bool GUSIDescriptorTable::iterator::operator==(
|
|
const GUSIDescriptorTable::iterator & other) const
|
|
{
|
|
return fFd == other.fFd;
|
|
}
|
|
|
|
inline GUSIDescriptorTable::iterator GUSIDescriptorTable::begin()
|
|
{
|
|
return iterator(this);
|
|
}
|
|
|
|
inline GUSIDescriptorTable::iterator GUSIDescriptorTable::end()
|
|
{
|
|
return iterator(this, fInvalidDescriptor);
|
|
}
|
|
|
|
#endif /* GUSI_SOURCE */
|
|
|
|
#endif /* _GUSIDescriptor_ */
|