This commit is contained in:
sgehani%netscape.com 2001-03-11 22:48:35 +00:00
Родитель 3972e66a0f
Коммит bff4894c69
81 изменённых файлов: 7604 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,398 @@
GUSI 2 -- A multithreaded POSIX library
INTRODUCTION
GUSI is an extension and partial replacement of the standard C runtime library
supplied with your compiler. The main objective of GUSI is to faciliate the
porting of software written for UNIX systems by implementing a substantial subset
of the Single Unix Specification library routines:
- BSD style sockets.
- Pthreads.
- Many other POSIX facilities such as diropen().
REQUIREMENTS
To use GUSI with Metrowerks CodeWarrior, you need one of the following compilers:
- Metrowerks CodeWarrior Pro 5 or later.
- SC/SCpp 8.8.4d1c1 or later.
- MrC/MrCpp 4.1.0a6c1 or later.
GETTING STARTED
If you're new to GUSI, start by reading the manual in :doc:GUSI.pdf.
If you're using GUSI with the Metrowerks CodeWarrior IDE, also read
:doc:GUSI_CW_Guide.pdf if you haver any difficulties getting your first GUSI
project to compile/link.
If you're using GUSI in combination with the MPW shell and/or the MPW compilers,
please run GUSI_Install.MPW. For more details, please consider reading the
documentation in the doc folder.
To recompile GUSI with the MPW compilers, you need an STL library. I've found
STLport, available at http://www.stlport.org/download.shtml, to work perfectly
for my purposes. To install it, put it anywhere on your disk and run
STLport_Install.MPW.
GUSI USER LICENSE
My primary objective in distributing GUSI is to have it used as widely as
possible, while protecting my moral rights of authorship and limiting my
exposure to liability.
Copyright (C) 1992-2000 Matthias Neeracher
Permission is granted to anyone to use this software for any purpose on any
computer system, and to redistribute it freely, subject to the following
restrictions:
- The author is not responsible for the consequences of use of this software,
no matter how awful, even if they arise from defects in it.
- The origin of this software must not be misrepresented, either by explicit
claim or by omission.
- You are allowed to distributed modified copies of the software, in source
and binary form, provided they are marked plainly as altered versions, and
are not misrepresented as being the original software.
While I am giving GUSI away for free, that does not mean that I don't like
getting appreciation for it. If you want to do something for me beyond your
obligations outlined above, you can
- Acknowledge the use of GUSI in the about box of your application and/or
your documentation.
- Send me a CD as described in
http://www.iis.ee.ethz.ch/~neeri/macintosh/donations.html
BUGS, QUESTIONS, SUGGESTIONS
Please report any problems you experience with the code or the documentation to
me. I'd also be interested in hearing about your success stories, if you have
any.
GUSI ON WWW
An online version of the GUSI manual and a GUSI FAQ are available at
http://www.iis.ee.ethz.ch/~neeri/macintosh.html
MAILING LIST
There is a mailing list for announcing new releases and discussions about
how to make GUSI change your life. To subscribe, send a mail:
----------------------------------
To: gusi-request@iis.ee.ethz.ch
Subject: (is ignored)
subscribe
----------------------------------
Mail is now processed by a daemon, so please follow the above format.
Matthias Neeracher <neeri@iis.ee.ethz.ch>
20875 Valley Green Dr. #50
Cupertino, CA 95014
e-Mail: <neeracher@mac.com>
Fax: +1 (408) 514-2605 ext. 0023
KNOWN BUGS
- MSG_PEEK does not yet work for for native OpenTransport sockets, only for MacTCP
sockets [John Cargill-Ek].
- hstrerror() is not yet implemented [Darrell Walisser].
RELEASE NOTES
Version 2.1.5 21Jan01
- Make literate programming tools configurable to some extent [Jack Jansen].
- Made countless tweaks to scheduling and wakeups [Andreas Grosam, Keith Stattenfield].
- Prevent inlining of overridable functions [Andreas Grosam].
- Socket options did not work properly for OT sockets created by accept [Andreas Grosam].
- pthread_cond_timedwait never returned ETIMEDOUT [Andreas Grosam].
Version 2.1.4 22Dec00
- Using a GUSIFSxxx call before any POSIX calls could cause programs to hang
because the default context was not initialized yet.
- GUSIForeignThreads was unable to open ThreadsLib [Max Horn].
- GUSI diagnostic messages were sometimes emitted at A5 unsafe times
[Jean-Pierre Stierlin].
- Added ssh entry in hard coded services table [Jean-Pierre Stierlin].
Version 2.1.3 29Oct00
- More CW 6 fixes, especially for massive problems with time related functions
[Richard Wesley].
- Nonstandard macros defined in sys/cdefs.h conflicted with CW macros [David Willis].
- PPC sockets were totally broken; they seemed to have slipped entirely through any
sort of acceptance testing [David Willis].
- Deal with CW's non-standard signature for fdopen.
- Include two new tests (GUSIThreadTest, GUSIPPCTest) in interactive test suite.
- Switched to distributing XML versions of the CW projects for space savings and
portability.
Version 2.1.2 16Oct00
- Fixes for CodeWarrior 6 [Jack Jansen, Jeff Shulman].
- SC would always use A5 relative addresses, with disastrous consequences in
completion routines [Jean-Pierre Stierlin].
- The OpenTransport code for dealing with multiple incoming connections had
severe bugs [Gordon McMillan].
- Accommodate the fact that CodeWarrior internally uses a different numbering
scheme for SIGINT [Jack Jansen].
Version 2.1.1 05Jun00
- Some functions were returning references to stack values [Alexandre Parenteau].
- Fixed a shocking amount of bugs in time(), localtime(), and gmtime()
[Jack Jansen, Alexandre Parenteau].
- Keep DCon support from crashing under Sfio.
- Introduced preliminary support for multiple descriptor tables.
Version 2.1.0 29May00
- Improved formatting of the woven documentation [Peter Teeson].
- Updated to Universal Headers 3.3.1 [Tom Bayley].
- Tuned scheduling again [Jack Jansen].
- Implemented proper linger model, closing sockets immediately (while
actually putting them into a background queue to allow pending data to
be transmitted) [Rich Cook, Oebele Dijkstra].
- MacTCP sockets would hang on close with pending data [Jack Jansen].
- Fixed bugs in lseek for read-only files [Jack Jansen].
- Failed OpenTransport DNS lookups would return garbage data instead of
error [Karl Armstrong, Mike Johnson].
- Repeatedly calling a connect on a nonblocking socket could cause an infinite
loop [Mike Johnson].
- Fixed leak in OT UDP sendto [Tom Bayley].
- (Hopefully) fixed a problem that could cause select() not to return a
ready to read status [Mike Johnson].
Version 2.0.6 14Mar00
- Fixed several race conditions causing hangs in OpenTransport code
[Alexandre Parenteau].
- Console would get initialized twice [Steven Gillispie].
- Suffix finding code was broken [Alexandre Parenteau].
- open(":x:y", O_RDWR) would create x as a file if it didn't exist [Alexandre Parenteau].
- Temporary name creation would crash horribly [Alexandre Parenteau].
- rename() was broken [Alexandre Parenteau].
- Try to enforce alignment of struct and class fields when GUSI headers are
included by clients with arbitrary default alignments [Alexandre Parenteau].
- Custom thread switchers were not getting correctly reinstalled upon destruction
of a thread [Andre Radke].
- GUSIFileSpec::Resolve needed to clear fValidInfo [Alexandre Parenteau].
- Accidentally had reversed the logic for my "fix" of the double destruction of detached
threads [Stephen Coy].
- getservbyname would crash if /etc/services did not exist
[Christopher Stern, Alexandre Parenteau].
Version 2.0.5 06Mar00
- Added a visual manual for first time CodeWarrior GUSI users [Rich Cook].
- Forgot include guard in inttypes.h
- Device families did not check that the paths passed to them were device paths
[Christopher Stern]
- Sped up thread switching by a factor of up to 1000 [Jack Jansen].
- Called InitGraf in one location without checking configuration flag
[Alexandre Parenteau].
- Used a flaky plausibility test for automatic InitGraf.
- Detached threads were deleted twice [Stephen Coy].
- Force order of static destructors by closing descriptors before deleting threads
[Christopher Stern].
- Checked for nonexistent devices in file calls [Alexandre Parenteau].
- readdir() would always return an error at the end of the directory, which is against
the specification [Alexandre Parenteau].
- sleep() from the main thread didn't [Darrell Walisser].
- Renamed CodeWarrior projects to .mcp for cross platform compilability [Chris Brown].
Version 2.0.4 16Jan00
- Updated to CodeWarrior 5.3 compilers (this shouldn't affect any existing CW 5 users
negatively, I think. If it does, please alert me.).
- Some of the macros in pthread.h had PTHREAD_ misspelled as PTHREADS_ [Mike Davis]
- GUSI's version of rename() was incorrectly mangled, so clients would link with
the standard rename() [Matthew Nolan].
- Removing an open file in the temporary items folder would fail [Jack Jansen].
Version 2.0.3 13Dec99
- Closing a OpenTransport TCP socket with data pending would hang
[Oebele Dijkstra, Darrell Walisser].
- Calling gethostbyname() before any sockets were opened would malfunction.
Version 2.0.2 12Dec99
- Attempting to set SO_LINGER would crash [Keith Rollin].
- Passing a null timezone argument to gettimeofday() would misbehave [Christopher Stern].
- GUSISetThreadSwitcher would get the wrong linkage [Bruno Litman].
- read() on OpenTransport TCP/IP sockets had wrong results on disconnected sockets
[Keith Rollin].
- select() would return a wrong result if any descriptors were ready for both reading
and writing [Keith Rollin].
- Added pause() call.
Version 2.0.1 14Nov99
- select() would sometimes unecessarily poll [David Lawrence].
- Added GUSIwithPPCSockets, GUSIwithLocalSockets, which I had forgotten
[Darrell Walisser].
- GUSI would generate SIGINT for background applications if Command-. was
pressed in the foreground application [Darrell Walisser].
- Calling signal() before any sockets were created would crash [Darrell Walisser].
- gethostname() would garble the name if running with TCP/IP off
[Christopher Stern].
- stat() would not return an error for nonexistent files [Christopher Stern].
Version 2.0 23Oct99
- Removed the advertising clause from the BSD headers, as UCB no longer
requires it. Thanks!
- Included DCon.h in the distribution so GUSI compiles even if you
don't have DCon. Thanks to Ed Wynne, Phasic Interware, Inc.,
for his permission to do so. [Steven Gillispie]
Version 2.0fc2 14Oct99
- Open Transport sockets didn't close their connections in an orderly way
[Steven Gillispie].
Version 2.0fc1 25Sep99
- The number and severity of bug reports has decreased sufficiently to
convince me to declare final candidate status on GUSI 2. Please report
all bugs immediately.
- Added sanity checks on A5 before attempting to call InitGraf [Brian Pink].
- Renamed the socket option IPPROTO_IP/IP_BROADCAST to its correct name
SOL_SOCKET/SO_BROADCAST [Chris Brown].
Version 2.0b10 08Sep99
- I found several bugs in GUSI when trying to port the Darwin Streaming Server
to MacOS.
- Attempted to deal with threads created outside GUSI (e.g. in PowerPlant)
[Eli Bishop].
- File manager sockets would misbehave when switching off read-ahead.
- Implemented the interface detection ioctl calls for OpenTransport TCP/IP.
- getsockname would not work on sockets returned fropm accept under
OpenTransport.
- recvfrom would not correctly return the sorce socket address under
OpenTransport except for a connected datagram socket [Philippe Lang].
- Nonblocking reads on OpenTransport stream sockets did in fact block.
- Nonblocking reads on OpenTransport datagram sockets leaked memory.
- Implemented inet_aton and minimal pthread_condattr and pthread_mutexattr
support.
- Fixed bugs in the documentation [Chris Brown]. Added warning about
interaction between GUSIConfig and precompiled headers [Steven Gillispie].
Version 2.0b9 02Sep99
- OpenTransport operations in threads sometimes would hang
[Brian Pink, David Catmull].
Version 2.0b8 25Aug99
- Fixed problems with nonblocking connects in MacTCP [Philippe Lang].
- Open transport sockets needed to have an explicit unbind [Steven Gillispie].
- Work on literate edition of the source code.
Version 2.0b7 04Aug99
- Adapted to CodeWarrior Pro 5.
- Updated documentation.
- Tried to clarify license and added pointer to donations page.
Version 2.0b6 01Aug99 (Happy 708th birthday, Switzerland!)
- Philippe Lang convinced me to support the SO_ERROR socket option, and while
I was at it, I supported as many socket options as I reasonably could
(mostly on Open Transport).
- Found out that the member fields of a struct timespec are named tv_xxx, not
ts_xxx, thanks to W. Richard Stevens' sample code.
- Fixed conditional macros in sys/un.h [Michel Rabozee].
- Calling MSL __close_all() turned out not to have been such a hot idea.
Version 2.0b5 19Jul99
- Rick Waits correctly pointed out that most of the new files
promised in b4 were actually missing.
- Fixed bug in MacTCP UDP code [Philippe Lang].
- Specified bool support in Example project so it would compile again [Rick Waits].
Version 2.0b4 18Jul99
- Added support for SIOW based programs.
- Added mkdir/rmdir.
- Fixed Open Transport nonblocking connects [Philippe Lang].
- Fixed long standing inability to give new files the right type and
creator [Chris Jacobson].
- Add MPW makefile and examples to :Examples [Rick Waits].
Version 2.0b3 30Jun99
- Added support for Standard C and UNIX 98 style signal handling.
- Added support for using sfio with SC and MrC.
- Improved performance of file I/O.
- Tried to improve documentation for SC and MrC [Rick Waits].
- Added GUSI_Install.MPW installation script.
- Eradicated dependences on STL from GUSI headers.
Version 2.0b2 07Jun99
- Added support for SC[pp] and MrC[pp] compilers. I compiled with SCpp 8.8.4d1c1
and MrCpp 4.1.0a5c3, and intend to maintain the code for newer, but not older
versions of these compilers. Unfortunately, Stdio does not work yet when
using GUSI with MrCpp due to shared library conflicts. I intend to support
sfio for SC and MrC in the near future, though.
- Added back STDIN_FILENO & co. Fixed various bad comments in header guards
[Chris Jacobson].
- select for OpenTransport datagram (UDP) sockets was broken [Philippe Lang].
- Allow recursive locks for mutexes.
- Added a CodeWarrior project files to simplify rebuilds.
- Some more work on PPC sockets.
Version 2.0b1 14Apr99
- Added support for broadcast and multicast options [Tom Bayley, Quinn].
- Rewrote GUSIConfig in C++.
- Brought documentation up to date.
- Event handling for AppleEvents was broken [Chris Jacobson].
- Changed auto-spin default to off, as this feature has less importance in
GUSI II and can easier be turned on with configuration files.
- Introduced GUSIContextFactory to add more flexibility to GUSIContext
creation. Made switching in and out fully virtualized.
- Massively improved and simplified the handling of race conditions
in wakeups [George Warner & Quinn]
- Added support for the DCon debugging console, and also switched to DCon
for our own debugging output.
- Added support for the PPC (Program-to-program communications) toolbox.
- Fixed several bugs in Open Transport support.
- Removed GUSIwithThreading, which is no longer necessary.
Version 2.0a4 22Nov98
- Since my Mac is getting packed up, a hasty and somewhat incomplete, but
interesting release.
- Changed configuration system to explicit configuration files created with
GUSI_Configurator. This change is not reflected in the examples yet.
- Added OpenTransport TCP/IP support (finally!)
Version 2.0a3 25Oct98
- Added MacTCP UDP support, SIOUX support, MSG_PEEK support.
- Fixed many bugs.
- Started adapting old test programs in Examples
Version 2.0a2 11Oct98
- Much more feature complete version: Added most file routines and domain name
support.
- Incorporated as much as I could of Michel Rabozee's excellent feedback.
Version 2.0a1 02Aug98
- A sneak peek to give an impression of the flavor of the new facilities
in GUSI2. This version is far from feature complete, lacking most file
routines, UDP support, support for AppleTalk, OpenTransport support,
and support of the domain name resolver.

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,409 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIBuffer.nw - Buffering for GUSI
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIBuffer.h,v $
// % Revision 1.1 2001-03-11 22:33:31 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.20 2001/01/17 08:33:14 neeri
// % Need to set fOldBuffer to nil after deleting
// %
// % Revision 1.19 2000/10/16 04:34:22 neeri
// % Releasing 2.1.2
// %
// % Revision 1.18 2000/05/23 06:53:14 neeri
// % Improve formatting
// %
// % Revision 1.17 2000/03/15 07:22:06 neeri
// % Enforce alignment choices
// %
// % Revision 1.16 1999/09/09 07:19:18 neeri
// % Fix read-ahead switch-off
// %
// % Revision 1.15 1999/08/26 05:44:59 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.14 1999/06/30 07:42:05 neeri
// % Getting ready to release 2.0b3
// %
// % Revision 1.13 1999/05/30 03:09:29 neeri
// % Added support for MPW compilers
// %
// % Revision 1.12 1999/03/17 09:05:05 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.11 1998/11/22 23:06:50 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.10 1998/10/25 11:28:43 neeri
// % Added MSG_PEEK support, recursive locks.
// %
// % Revision 1.9 1998/08/02 12:31:36 neeri
// % Another typo
// %
// % Revision 1.8 1998/08/02 11:20:06 neeri
// % Fixed some typos
// %
// % Revision 1.7 1998/01/25 20:53:51 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.6 1997/11/13 21:12:08 neeri
// % Fall 1997
// %
// % Revision 1.5 1996/12/22 19:57:55 neeri
// % TCP streams work
// %
// % Revision 1.4 1996/12/16 02:16:02 neeri
// % Add Size(), make inlines inline, use BlockMoveData
// %
// % Revision 1.3 1996/11/24 13:00:26 neeri
// % Fix comment leaders
// %
// % Revision 1.2 1996/11/24 12:52:05 neeri
// % Added GUSIPipeSockets
// %
// % Revision 1.1.1.1 1996/11/03 02:43:32 neeri
// % Imported into CVS
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Buffering for GUSI}
//
// This section defines four classes that handle buffering for GUSI:
// [[GUSIScatterer]], [[GUSIGatherer]], and their common ancestor
// [[GUSIScattGath]] convert between [[iovecs]] and simple buffers in the
// absence of specialized communications routines. A [[GUSIRingBuffer]]
// mediates between a producer and a consumer, one of which is typically
// normal code and the other interrupt level code.
//
//
// <GUSIBuffer.h>=
#ifndef _GUSIBuffer_
#define _GUSIBuffer_
#ifdef GUSI_SOURCE
#include <sys/types.h>
#include <sys/uio.h>
#include <MacTypes.h>
#include "GUSIDiag.h"
#include "GUSIBasics.h"
#include <ConditionalMacros.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// \section{Definition of scattering/gathering}
//
// A [[GUSIScattGath]] translates between an array of [[iovecs]] and a simple buffer,
// allocating scratch space if necessary.
//
// <Definition of class [[GUSIScattGath]]>=
class GUSIScattGath {
protected:
// On constructing a [[GUSIScattGath]], we pass an array of [[iovecs]]. For the
// simpler functions, a variant with a single [[buffer]] and [[length]] is also
// available.
//
// <Constructor and destructor for [[GUSIScattGath]]>=
GUSIScattGath(const iovec *iov, int count, bool gather);
GUSIScattGath(void * buffer, size_t length, bool gather);
virtual ~GUSIScattGath();
public:
// The [[iovec]], the buffer and its length are then available for public scrutinity.
// Copy constructor and assignment both are a bit nontrivial.
//
// <Public interface to [[GUSIScattGath]]>=
const iovec * IOVec() const;
int Count() const;
void * Buffer() const;
operator void *() const;
int Length() const;
int SetLength(int len) const;
void operator=(const GUSIScattGath & other);
GUSIScattGath(const GUSIScattGath & other);
private:
// \section{Implementation of scattering/gathering}
//
// A [[GUSIScattGath]] always consists of [[fIo]], an array of [[iovecs]], [[fCount]],
// the number of sections in the array, and [[fLen]], the total size of the data area.
// If [[fCount]] is 1, [[fBuf]] will be a copy of the pointer to the single section. If
// [[fCount]] is greater than 1, [[fScratch]] will contain a [[Handle]] to a scratch
// area of size [[len]] and [[fBuf]] will contain [[*scratch]]. If the object was
// constructed without providing an [[iovec]] array, [[fTrivialIo]] will be set up
// to hold one.
//
// <Privatissima of [[GUSIScattGath]]>=
const iovec * fIo;
iovec fTrivialIo;
mutable int fCount;
mutable Handle fScratch;
mutable void * fBuf;
mutable int fLen;
bool fGather;
};
// A [[GUSIScatterer]] distributes the contents of a buffer over an array of
// [[iovecs]].
//
// <Definition of class [[GUSIScatterer]]>=
class GUSIScatterer : public GUSIScattGath {
public:
GUSIScatterer(const iovec *iov, int count)
: GUSIScattGath(iov, count, false) {}
GUSIScatterer(void * buffer, size_t length)
: GUSIScattGath(buffer, length, false) {}
GUSIScatterer & operator=(const GUSIScatterer & other)
{ *static_cast<GUSIScattGath *>(this) = other; return *this; }
};
// A [[GUSIGatherer]] collects the contents of an array of [[iovecs]] into a single
// buffer.
//
// <Definition of class [[GUSIGatherer]]>=
class GUSIGatherer : public GUSIScattGath {
public:
GUSIGatherer(const struct iovec *iov, int count)
: GUSIScattGath(iov, count, true) {}
GUSIGatherer(const void * buffer, size_t length)
: GUSIScattGath(const_cast<void *>(buffer), length, true) {}
GUSIGatherer & operator=(const GUSIGatherer & other)
{ *static_cast<GUSIScattGath *>(this) = other; return *this; }
};
// \section{Definition of ring buffering}
//
// A [[GUSIRingBuffer]] typically has on one side a non-preeemptive piece of code
// and on the other side a piece of interrupt code. To transfer data from and to
// the buffer, two interfaces are available: A direct interface that transfers
// memory, and an indirect interface that allocates memory regions and then
// has OS routines transfer data from or to them
//
// <Definition of class [[GUSIRingBuffer]]>=
class GUSIRingBuffer {
public:
// On construction of a [[GUSIRingBuffer]], a buffer of the specified size is
// allocated and not released until destruction. [[operator void*]] may be used
// to determine whether construction was successful.
//
// <Constructor and destructor for [[GUSIRingBuffer]]>=
GUSIRingBuffer(size_t bufsiz);
~GUSIRingBuffer();
operator void*();
// The direct interface to [[GUSIRingBuffer]] is straightforward: [[Produce]] copies
// memory into the buffer, [[Consume]] copies memory from the buffer, [[Free]]
// determines how much space there is for [[Produce]] and [[Valid]] determines
// how much space there is for [[Consume]].
//
// <Direct interface for [[GUSIRingBuffer]]>=
void Produce(void * from, size_t & len);
void Produce(const GUSIGatherer & gather, size_t & len, size_t & offset);
void Produce(const GUSIGatherer & gather, size_t & len);
void Consume(void * to, size_t & len);
void Consume(const GUSIScatterer & scatter, size_t & len, size_t & offset);
void Consume(const GUSIScatterer & scatter, size_t & len);
size_t Free();
size_t Valid();
// [[ProduceBuffer]] tries to find in the ring buffer a contiguous free block of
// memory of the specified size [[len]] or otherwise the biggest available free
// block, returns a pointer to it and sets [[len]] to its length. [[ValidBuffer]]
// specifies that the next [[len]] bytes of the ring buffer now contain valid data.
//
// [[ConsumeBuffer]] returns a pointer to the next valid byte and sets [[len]] to
// the minimum of the number of contiguous valid bytes and the value of len on
// entry. [[FreeBuffer]] specifies that the next [[len]] bytes of the ring
// buffer were consumed and are no longer needed.
//
// <Indirect interface for [[GUSIRingBuffer]]>=
void * ProduceBuffer(size_t & len);
void * ConsumeBuffer(size_t & len);
void ValidBuffer(void * buffer, size_t len);
void FreeBuffer(void * buffer, size_t len);
// Before the nonpreemptive partner changes any of the buffer's data structures,
// the [[GUSIRingBuffer]] member functions call [[Lock]], and after the change is
// complete, they call [[Release]]. An interrupt level piece of code before
// changing any data structures has to determine whether the buffer is locked by
// calling [[Locked]]. If the buffer is locked or otherwise in an unsuitable state,
// the code can specify a procedure to be called during the next [[Release]] by
// calling [[Defer]]. A deferred procedure should call [[ClearDefer]] to avoid
// getting activated again at the next opportunity.
//
// <Synchronization support for [[GUSIRingBuffer]]>=
void Lock();
void Release();
bool Locked();
typedef void (*Deferred)(void *);
void Defer(Deferred def, void * ar);
void ClearDefer();
// It is possible to switch buffer sizes during the existence of a buffer, but we
// have to be somewhat careful, since some asynchronous call may still be writing
// into the old buffer. [[PurgeBuffers]], called at safe times, cleans up old
// buffers.
//
// <Buffer switching for [[GUSIRingBuffer]]>=
void SwitchBuffer(size_t bufsiz);
size_t Size();
void PurgeBuffers();
// Sometimes, it's necessary to do nondestructive reads, a task complex enough to
// warrant its own class.
//
// <Definition of class [[GUSIRingBuffer::Peeker]]>=
class Peeker {
public:
Peeker(GUSIRingBuffer & buffer);
~Peeker();
void Peek(void * to, size_t & len);
void Peek(const GUSIScatterer & scatter, size_t & len);
private:
// A [[GUSIRingBuffer::Peeker]] has to keep its associated [[GUSIRingBuffer]] locked during
// its entire existence.
//
// <Privatissima of [[GUSIRingBuffer::Peeker]]>=
GUSIRingBuffer & fTopBuffer;
GUSIRingBuffer * fCurBuffer;
Ptr fPeek;
// The core routine for reading is [[PeekBuffer]] which automatically advances the
// peeker as well.
//
// <Privatissima of [[GUSIRingBuffer::Peeker]]>=
void * PeekBuffer(size_t & len);
};
friend class Peeker;
void Peek(void * to, size_t & len);
void Peek(const GUSIScatterer & scatter, size_t & len);
private:
// \section{Implementation of ring buffering}
//
// The buffer area of a ring buffer extends between [[fBuffer]] and [[fEnd]]. [[fValid]]
// contains the number of valid bytes, while [[fFree]] and [[fSpare]] (Whose purpose
// will be explained later) sum up to the number of free bytes. [[fProduce]] points at the
// next free byte, while [[fConsume]] points at the next valid byte. [[fInUse]]
// indicates that an asynchronous call might be writing into the buffer.
//
// <Privatissima of [[GUSIRingBuffer]]>=
Ptr fBuffer;
Ptr fEnd;
Ptr fConsume;
Ptr fProduce;
size_t fFree;
size_t fValid;
size_t fSpare;
bool fInUse;
// The relationships between the various pointers are captured by [[Invariant]] which
// uses the auxiliary function [[Distance]] to determine the distance between two
// pointers in the presence of wrap around areas.
//
// <Privatissima of [[GUSIRingBuffer]]>=
bool Invariant();
size_t Distance(Ptr from, Ptr to);
// The lock mechanism relies on [[fLocked]], and the deferred procedure and its argument
// are stored in [[fDeferred]] and [[fDeferredArg]].
//
// <Privatissima of [[GUSIRingBuffer]]>=
int fLocked;
Deferred fDeferred;
void * fDeferredArg;
// We only switch the next time the buffer is empty, so we are prepared to create
// the new buffer dynamically and forward requests to it for a while.
//
// <Privatissima of [[GUSIRingBuffer]]>=
GUSIRingBuffer * fNewBuffer;
GUSIRingBuffer * fOldBuffer;
void ObsoleteBuffer();
// The scatter/gather variants of [[Produce]] and [[Consume]] rely on a common
// strategy.
//
// <Privatissima of [[GUSIRingBuffer]]>=
void IterateIOVec(const GUSIScattGath & sg, size_t & len, size_t & offset, bool produce);
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
// Clients need readonly access to the buffer address and read/write access to the length.
// [[operator void*]] server to check whether the [[GUSIScattGath]] was constructed
// successfully.
//
// <Inline member functions for class [[GUSIScattGath]]>=
inline const iovec * GUSIScattGath::IOVec() const
{ return fIo; }
inline int GUSIScattGath::Count() const
{ return fCount; }
inline GUSIScattGath::operator void *() const
{ return Buffer(); }
inline int GUSIScattGath::Length() const
{ return fLen; }
inline int GUSIScattGath::SetLength(int len) const
{ return GUSI_MUTABLE(GUSIScattGath, fLen) = len; }
// <Inline member functions for class [[GUSIRingBuffer]]>=
inline void GUSIRingBuffer::Produce(const GUSIGatherer & gather, size_t & len, size_t & offset)
{
IterateIOVec(gather, len, offset, true);
}
inline void GUSIRingBuffer::Consume(const GUSIScatterer & scatter, size_t & len, size_t & offset)
{
IterateIOVec(scatter, len, offset, false);
}
inline void GUSIRingBuffer::Produce(const GUSIGatherer & gather, size_t & len)
{
size_t offset = 0;
IterateIOVec(gather, len, offset, true);
}
inline void GUSIRingBuffer::Consume(const GUSIScatterer & scatter, size_t & len)
{
size_t offset = 0;
IterateIOVec(scatter, len, offset, false);
}
// The lock support is rather straightforward.
//
// <Inline member functions for class [[GUSIRingBuffer]]>=
inline void GUSIRingBuffer::Lock() { ++fLocked; }
inline bool GUSIRingBuffer::Locked() { return (fLocked!=0); }
inline void GUSIRingBuffer::ClearDefer() { fDeferred = nil; }
inline void GUSIRingBuffer::Release()
{
GUSI_CASSERT_INTERNAL(fLocked > 0);
if (--fLocked <= 0 && fDeferred)
fDeferred(fDeferredArg);
}
inline void GUSIRingBuffer::Defer(Deferred def, void * ar)
{
fDeferred = def;
fDeferredArg = ar;
}
// The size is stored only implicitely.
//
// <Inline member functions for class [[GUSIRingBuffer]]>=
inline size_t GUSIRingBuffer::Size() { return fEnd - fBuffer; }
// <Inline member functions for class [[GUSIRingBuffer]]>=
inline void GUSIRingBuffer::Peek(void * to, size_t & len)
{
Peeker peeker(*this);
peeker.Peek(to, len);
}
inline void GUSIRingBuffer::Peek(const GUSIScatterer & scatter, size_t & len)
{
Peeker peeker(*this);
peeker.Peek(scatter, len);
}
#endif /* GUSI_SOURCE */
#endif /* _GUSIBuffer_ */

Просмотреть файл

@ -0,0 +1,289 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIConfig.nw - Configuration settings
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIConfig.h,v $
// % Revision 1.1 2001-03-11 22:33:34 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.18 2001/01/22 04:31:11 neeri
// % Last minute changes for 2.1.5
// %
// % Revision 1.17 2001/01/17 08:40:17 neeri
// % Prevent inlining of overridable functions
// %
// % Revision 1.16 2000/05/23 06:54:39 neeri
// % Improve formatting, update to latest universal headers
// %
// % Revision 1.15 2000/03/15 07:10:29 neeri
// % Fix suffix searching code
// %
// % Revision 1.14 2000/03/06 06:24:34 neeri
// % Fix plausibility tests for A5
// %
// % Revision 1.13 1999/09/26 03:56:44 neeri
// % Sanity check for A5
// %
// % Revision 1.12 1999/08/26 05:44:59 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.11 1999/06/28 05:57:03 neeri
// % Support SIGINT generation
// %
// % Revision 1.10 1999/05/29 06:26:41 neeri
// % Fixed header guards
// %
// % Revision 1.9 1999/03/29 09:51:28 neeri
// % New configuration system with support for hardcoded configurations.
// %
// % Revision 1.8 1999/03/17 09:05:05 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.7 1998/10/11 16:45:10 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.6 1998/08/01 21:32:01 neeri
// % About ready for 2.0a1
// %
// % Revision 1.5 1998/01/25 20:53:52 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.4 1997/11/13 21:12:10 neeri
// % Fall 1997
// %
// % Revision 1.3 1996/11/24 13:00:27 neeri
// % Fix comment leaders
// %
// % Revision 1.2 1996/11/24 12:52:06 neeri
// % Added GUSIPipeSockets
// %
// % Revision 1.1.1.1 1996/11/03 02:43:32 neeri
// % Imported into CVS
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{GUSI Configuration settings}
//
// GUSI stores its global configuration settings in the [[GUSIConfiguration]]
// singleton class. To create the instance, GUSI calls the [[GUSISetupConfig]]
// hook.
//
// <GUSIConfig.h>=
#ifndef _GUSIConfig_
#define _GUSIConfig_
#ifdef GUSI_SOURCE
#include "GUSIFileSpec.h"
#include <ConditionalMacros.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// \section{Definition of configuration settings}
//
// The GUSIConfiguration has a single instance with read only access, accessible
// with the static [[Instance]] member function.
//
// <Definition of class [[GUSIConfiguration]]>=
class GUSIConfiguration {
public:
enum { kNoResource = -1, kDefaultResourceID = 10240 };
static GUSIConfiguration * Instance();
static GUSIConfiguration * CreateInstance(short resourceID = kDefaultResourceID);
// To determine the file type and creator of a newly created file, we first try
// to match one of the [[FileSuffix]] suffices.
//
// <Type and creator rules for newly created files>=
struct FileSuffix {
char suffix[4];
OSType suffType;
OSType suffCreator;
};
short fNumSuffices;
FileSuffix * fSuffices;
void ConfigureSuffices(short numSuffices, FileSuffix * suffices);
// If none of the suffices matches, we apply the default type and creator. These
// rules are applied with [[SetDefaultFType]].
//
// <Type and creator rules for newly created files>=
OSType fDefaultType;
OSType fDefaultCreator;
void ConfigureDefaultTypeCreator(OSType defaultType, OSType defaultCreator);
void SetDefaultFType(const GUSIFileSpec & name) const;
// To simplify Macintosh friendly ports of simple, I/O bound programs it is
// possible to specify automatic yielding on read() and write() calls.
// [[AutoSpin]] will spin a cursor and/or yield the CPU if desired.
//
// <Automatic cursor spin>=
bool fAutoSpin;
void ConfigureAutoSpin(bool autoSpin);
void AutoSpin() const;
// GUSI applications can crash hard if QuickDraw is not initialized. Therefore, we
// offer to initialize it automatically with the [[fAutoInitGraf]] feature.
//
// <Automatic initialization of QuickDraw>=
bool fAutoInitGraf;
void ConfigureAutoInitGraf(bool autoInitGraf);
void AutoInitGraf();
// Due to the organization of a UNIX filesystem, it is fairly easy to find
// out how many subdirectories a given directory has, since the [[nlink]] field of
// its inode will automatically contain the number of subdirectories[[+2]]. Therefore,
// some UNIX derived code depends on this behaviour. When [[fAccurateStat]] is set,
// GUSI emulates this behaviour, but be warned that this makes [[stat]] on
// directories a much more expensive operation. If [[fAccurateStat]] is not set,
// stat() gives the total number of entries in the directory[[+2]] as a conservative
// estimate.
//
// <Various flags>=
bool fAccurateStat;
void ConfigureAccurateStat(bool accurateState);
// The [[fSigPipe]] feature causes a signal [[SIGPIPE]] to be raised if an attempt
// is made to write to a broken pipe.
//
// <Various flags>=
bool fSigPipe;
void ConfigureSigPipe(bool sigPipe);
void BrokenPipe();
// The [[fSigInt]] feature causes a signal [[SIGINT]] to be raised if the user presses
// command-period.
//
// <Various flags>=
bool fSigInt;
void ConfigureSigInt(bool sigInt);
void CheckInterrupt();
// If [[fSharedOpen]] is set, open() opens files with shared read/write permission.
//
// <Various flags>=
bool fSharedOpen;
void ConfigureSharedOpen(bool sharedOpen);
// If [[fHandleAppleEvents]] is set, GUSI automatically handles AppleEvents in its
// event handling routine.
//
// <Various flags>=
bool fHandleAppleEvents;
void ConfigureHandleAppleEvents(bool handleAppleEvents);
protected:
GUSIConfiguration(short resourceID = kDefaultResourceID);
private:
// \section{Implementation of configuration settings}
//
// The sole instance of [[GUSIConfiguration]] is created on demand.
//
// <Privatissima of [[GUSIConfiguration]]>=
static GUSIConfiguration * sInstance;
// [[ConfigureSuffices]] sets up the suffix table.
//
// <Privatissima of [[GUSIConfiguration]]>=
bool fWeOwnSuffices;
// [[AutoSpin]] tests the flag inline, but performs the actual spinning out of
// line.
//
// <Privatissima of [[GUSIConfiguration]]>=
void DoAutoSpin() const;
// [[AutoInitGraf]] works rather similarly to [[AutoSpin]].
//
// <Privatissima of [[GUSIConfiguration]]>=
void DoAutoInitGraf();
// [[CheckInterrupt]] raises a [[SIGINT]] signal if desired.
//
// <Privatissima of [[GUSIConfiguration]]>=
bool CmdPeriod(const EventRecord * event);
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
// To create the sole instance of [[GUSIConfiguration]], we call [[GUSISetupConfig]]
// which has to call [[GUSIConfiguration::CreateInstance]].
//
// <Definition of [[GUSISetupConfig]] hook>=
#ifdef __MRC__
#pragma noinline_func GUSISetupConfig
#endif
extern "C" void GUSISetupConfig();
// <Inline member functions for class [[GUSIConfiguration]]>=
inline GUSIConfiguration * GUSIConfiguration::Instance()
{
if (!sInstance)
GUSISetupConfig();
if (!sInstance)
sInstance = new GUSIConfiguration();
return sInstance;
}
inline GUSIConfiguration * GUSIConfiguration::CreateInstance(short resourceID)
{
if (!sInstance)
sInstance = new GUSIConfiguration(resourceID);
return sInstance;
}
// <Inline member functions for class [[GUSIConfiguration]]>=
inline void GUSIConfiguration::ConfigureDefaultTypeCreator(OSType defaultType, OSType defaultCreator)
{
fDefaultType = defaultType;
fDefaultCreator = defaultCreator;
}
// <Inline member functions for class [[GUSIConfiguration]]>=
inline void GUSIConfiguration::ConfigureAutoSpin(bool autoSpin)
{
fAutoSpin = autoSpin;
}
// <Inline member functions for class [[GUSIConfiguration]]>=
inline void GUSIConfiguration::AutoSpin() const
{
if (fAutoSpin)
DoAutoSpin();
}
// <Inline member functions for class [[GUSIConfiguration]]>=
inline void GUSIConfiguration::ConfigureAutoInitGraf(bool autoInitGraf)
{
fAutoInitGraf = autoInitGraf;
}
// <Inline member functions for class [[GUSIConfiguration]]>=
inline void GUSIConfiguration::AutoInitGraf()
{
if (fAutoInitGraf)
DoAutoInitGraf();
}
// <Inline member functions for class [[GUSIConfiguration]]>=
inline void GUSIConfiguration::ConfigureSigPipe(bool sigPipe)
{
fSigPipe = sigPipe;
}
// <Inline member functions for class [[GUSIConfiguration]]>=
inline void GUSIConfiguration::ConfigureSigInt(bool sigInt)
{
fSigInt = sigInt;
}
// <Inline member functions for class [[GUSIConfiguration]]>=
inline void GUSIConfiguration::ConfigureAccurateStat(bool accurateStat)
{
fAccurateStat = accurateStat;
}
inline void GUSIConfiguration::ConfigureSharedOpen(bool sharedOpen)
{
fSharedOpen = sharedOpen;
}
#endif /* GUSI_SOURCE */
#endif /* _GUSIConfig_ */

Просмотреть файл

@ -0,0 +1,497 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIContext.nw - Thread and Process structures
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIContext.h,v $
// % Revision 1.1 2001-03-11 22:33:38 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.22 2001/01/22 04:31:11 neeri
// % Last minute changes for 2.1.5
// %
// % Revision 1.21 2001/01/17 08:43:42 neeri
// % Tweak scheduling
// %
// % Revision 1.20 2000/12/23 06:09:21 neeri
// % May need to create context for IO completions
// %
// % Revision 1.19 2000/10/16 04:34:22 neeri
// % Releasing 2.1.2
// %
// % Revision 1.18 2000/06/01 06:31:09 neeri
// % Delete SigContext
// %
// % Revision 1.17 2000/05/23 06:56:19 neeri
// % Improve formatting, add socket closing queue, tune scheduling
// %
// % Revision 1.16 2000/03/15 07:11:50 neeri
// % Fix detached delete (again), switcher restore
// %
// % Revision 1.15 2000/03/06 08:10:09 neeri
// % Fix sleep in main thread
// %
// % Revision 1.14 2000/03/06 06:13:46 neeri
// % Speed up thread/process switching through minimal quotas
// %
// % Revision 1.13 1999/12/13 02:40:50 neeri
// % GUSISetThreadSwitcher had Boolean <-> bool inconsistency
// %
// % Revision 1.12 1999/11/15 07:25:32 neeri
// % Safe context setup. Check interrupts only in foreground.
// %
// % Revision 1.11 1999/09/09 07:18:06 neeri
// % Added support for foreign threads
// %
// % Revision 1.10 1999/08/26 05:44:59 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.9 1999/06/28 05:59:02 neeri
// % Add signal handling support
// %
// % Revision 1.8 1999/05/30 03:09:29 neeri
// % Added support for MPW compilers
// %
// % Revision 1.7 1999/03/17 09:05:05 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.6 1999/02/25 03:34:24 neeri
// % Introduced GUSIContextFactory, simplified wakeup
// %
// % Revision 1.5 1998/11/22 23:06:51 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.4 1998/10/11 16:45:11 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.3 1998/08/01 21:26:18 neeri
// % Switch dynamically to threading model
// %
// % Revision 1.2 1998/02/11 12:57:11 neeri
// % PowerPC Build
// %
// % Revision 1.1 1998/01/25 21:02:41 neeri
// % Engine implemented, except for signals & scheduling
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Thread and Process structures}
//
// This section defines the process and thread switching engine of GUSI.
//
// In some execution environments, completion routines execute at interrupt level.
// GUSI therefore is designed so all information needed to operate from interrupt
// level is accessible from a [[GUSISocket]]. This information is separated into
// per-process data, collected in [[GUSIProcess]], and per-thread data, collected
// in [[GUSIContext]]. [[GUSIProcess]] is always a singleton, while [[GUSIContext]]
// is a singleton if threading is disabled, and has multiple instances if threading
// is enabled. By delegating the [[GUSIContext]] creation process to an instance
// of a [[GUSIContextFactory]], we gain some extra flexibility.
//
// As soon as GUSI has started an asynchronous call, it calls the [[Wait]] member
// function of its context. [[msec]] will set a time limit after which the call will
// return in any case. Exceptional events may also cause [[GUSIWait]] to return, so
// it is not safe to assume that the call will have completed upon return.
//
//
// <GUSIContext.h>=
#ifndef _GUSIContext_
#define _GUSIContext_
#include <errno.h>
#include <sys/cdefs.h>
#include <sys/signal.h>
#include <MacTypes.h>
#include <Threads.h>
__BEGIN_DECLS
// To maintain correct state, we have to remain informed which thread is active, so
// we install all sorts of hooks. Clients have to use the C++ interface or call
// [[GUSINewThread]], [[GUSISetThreadSwitcher]], and [[GUSISetThreadTerminator]].
// instead of the thread manager routines.
//
// <Definition of thread manager hooks>=
OSErr GUSINewThread(
ThreadStyle threadStyle, ThreadEntryProcPtr threadEntry, void *threadParam,
Size stackSize, ThreadOptions options,
void **threadResult, ThreadID *threadMade);
OSErr GUSISetThreadSwitcher(ThreadID thread,
ThreadSwitchProcPtr threadSwitcher, void *switchProcParam, Boolean inOrOut);
OSErr GUSISetThreadTerminator(ThreadID thread,
ThreadTerminationProcPtr threadTerminator, void *terminationProcParam);
__END_DECLS
#ifndef GUSI_SOURCE
typedef struct GUSIContext GUSIContext;
#else
#include "GUSISpecific.h"
#include "GUSIBasics.h"
#include "GUSIContextQueue.h"
#include <Files.h>
#include <Processes.h>
#include <OSUtils.h>
// \section{Definition of completion handling}
//
// {\tt GUSIContext} is heavily circular both with classes declared herein and
// in other files. Therefore, we start by declaring a few class names.
//
// <Name dropping for file GUSIContext>=
class GUSISocket;
class GUSIContext;
class GUSIProcess;
class GUSISigProcess;
class GUSISigContext;
class GUSITimer;
#include <ConditionalMacros.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// Ultimately, we will call through to the thread manager, but if an application uses foreign
// sources of threads, we might have to go through indirections.
//
// <Definition of class [[GUSIThreadManagerProxy]]>=
class GUSIThreadManagerProxy {
public:
virtual OSErr NewThread(
ThreadStyle threadStyle, ThreadEntryProcPtr threadEntry, void *threadParam,
Size stackSize, ThreadOptions options, void **threadResult, ThreadID *threadMade);
virtual OSErr SetThreadSwitcher(
ThreadID thread, ThreadSwitchProcPtr threadSwitcher, void *switchProcParam,
Boolean inOrOut);
virtual OSErr SetThreadTerminator(
ThreadID thread, ThreadTerminationProcPtr threadTerminator, void *terminatorParam);
virtual ~GUSIThreadManagerProxy() {}
static GUSIThreadManagerProxy * Instance();
protected:
GUSIThreadManagerProxy() {}
static GUSIThreadManagerProxy * MakeInstance();
};
// A [[GUSIProcess]] contains all the data needed to wake up a process:
//
// \begin{itemize}
// \item The [[ProcessSerialNumber]] of the process.
// \item The [[ThreadTaskRef]] if threads are enabled.
// \item The contents of the A5 register.
// \end{itemize}
//
// The sole instance of [[GUSIProcess]] is obtained by calling the [[GUSIProcess::Instance]] static member
// function, which will create the instance if necessary. Interrupt level prcedures may access the application's
// A5 register either manually by calling [[GetA5]] or simply by declaring a [[GUSIProcess::A5Saver]] in a scope.
//
// <Definition of class [[GUSIProcess]]>=
enum GUSIYieldMode {
kGUSIPoll, // Busy wait for some unblockable condition
kGUSIBlock, // Wait for some blockable condition
kGUSIYield // Yield to some other eligible thread
};
class GUSIProcess {
public:
static GUSIProcess * Instance();
static void DeleteInstance();
void GetPSN(ProcessSerialNumber * psn);
void AcquireTaskRef();
ThreadTaskRef GetTaskRef();
long GetA5();
bool Threading();
void Yield(GUSIYieldMode wait);
void Wakeup();
GUSISigProcess * SigProcess() { return fSigProcess; }
void QueueForClose(GUSISocket * sock);
// A [[GUSIProcess::A5Saver]] is a class designed to restore the process A5
// register for the scope of its declaration.
//
// <Definition of class [[GUSIProcess::A5Saver]]>=
class A5Saver {
public:
A5Saver(long processA5);
A5Saver(GUSIContext * context);
A5Saver(GUSIProcess * process);
~A5Saver();
private:
long fSavedA5;
};
protected:
friend class GUSIContext;
GUSIProcess(bool threading);
~GUSIProcess();
int fReadyThreads;
int fExistingThreads;
GUSISigProcess * fSigProcess;
private:
// \section{Implementation of completion handling}
//
// [[Instance]] returns the sole instance of [[GUSIProcess]], creating it if
// necessary.
//
// <Privatissima of [[GUSIProcess]]>=
static GUSIProcess * sInstance;
// Much of the information stored in a [[GUSIProcess]] is static and read-only.
//
// <Privatissima of [[GUSIProcess]]>=
ProcessSerialNumber fProcess;
ThreadTaskRef fTaskRef;
long fA5;
// The exception is the [[fClosing]] socket queue and some yielding related flags.
//
// <Privatissima of [[GUSIProcess]]>=
GUSISocket * fClosing;
UInt32 fResumeTicks;
bool fWillSleep;
bool fDontSleep;
};
// A [[GUSIContext]] gathers thread related data. The central operation on a
// [[GUSIContext]] is [[Wakeup]]. If the process is not asleep when [[Wakeup]]
// is called, it is marked for deferred wakeup.
//
// A [[GUSIContext]] can either be created from an existing thread manager
// [[ThreadID]] or by specifying the parameters for a [[NewThread]] call.
//
// [[Current]] returns the current [[GUSIContext]]. [[Setup]] initializes the
// default context for either the threading or the non-threading model.
//
// [[Yield]] suspends the current process or thread until something interesting
// happens if [[wait]] is [[kGUSIBlock]. Otherwise, [[Yield]] switches,
// but does not suspend. For an ordinary thread context, [[Yield]] simply yields
// the thread. For the context in a non-threading application, [[Yield]] does a
// [[WaitNextEvent]]. For the main thread context, [[Yield]] does both.
//
// [[Done]] tests whether the thread has terminated yet. If [[join]] is set,
// the caller is willing to wait. [[Result]] returns the default location to store
// the thread result if no other is specified.
//
// By default, a context is joinable. Calling [[Detach]] will cause the context to
// be destroyed automatically upon thread termination, and joins are no longer allowed.
// A joinable context will not be destroyed automatically before the end of the
// program, so you will have to call [[Liquidate]] to do that.
//
// [[SetSwitchIn]], [[SetSwitchOut]], and [[SetTerminator]] set per-thread user
// switch and termination procedures. [[SwitchIn]], [[SwitchOut]], and [[Terminate]]
// call the user defined procedures then perform their own actions.
//
// <Definition of class [[GUSIContext]]>=
class GUSIContext : public GUSISpecificTable {
public:
friend class GUSIProcess;
friend class GUSIContextFactory;
ThreadID ID() { return fThreadID; }
virtual void Wakeup();
void ClearWakeups() { fWakeup = false; }
GUSIProcess * Process() { return fProcess; }
void Detach() { fFlags |= detached; }
void Liquidate();
OSErr Error() { return sError; }
bool Done(bool join);
void * Result() { return fResult; }
GUSISigContext * SigContext() { return fSigContext; }
static GUSIContext * Current() { return sCurrentContext; }
static GUSIContext * CreateCurrent(bool threading = false)
{ if (!sCurrentContext) Setup(threading); return sCurrentContext; }
static GUSIContext * Lookup(ThreadID id);
static void Setup(bool threading);
static bool Yield(GUSIYieldMode wait);
static void SigWait(sigset_t sigs);
static void SigSuspend();
static bool Raise(bool allSigs = false);
static sigset_t Pending();
static sigset_t Blocked();
void SetSwitchIn(ThreadSwitchProcPtr switcher, void *switchParam);
void SetSwitchOut(ThreadSwitchProcPtr switcher, void *switchParam);
void SetTerminator(ThreadTerminationProcPtr terminator, void *terminationParam);
static GUSIContextQueue::iterator begin() { return sContexts.begin(); }
static GUSIContextQueue::iterator end() { return sContexts.end(); }
static void LiquidateAll() { sContexts.LiquidateAll(); }
protected:
// <Friends of [[GUSIContext]]>=
friend class GUSIContextFactory;
// The thread switcher updates the pointer to the current context and switches
// the global error variables.
//
// <Friends of [[GUSIContext]]>=
friend pascal void GUSIThreadSwitchIn(ThreadID thread, GUSIContext * context);
friend pascal void GUSIThreadSwitchOut(ThreadID thread, GUSIContext * context);
// The terminator wakes up the joining thread if a join is pending.
//
// <Friends of [[GUSIContext]]>=
friend pascal void GUSIThreadTerminator(ThreadID thread, GUSIContext * context);
GUSIContext(ThreadID id);
GUSIContext(
ThreadEntryProcPtr threadEntry, void *threadParam,
Size stackSize, ThreadOptions options = kCreateIfNeeded,
void **threadResult = nil, ThreadID *threadMade = nil);
virtual void SwitchIn();
virtual void SwitchOut();
virtual void Terminate();
// At this point, we need to introduce all the private data of a [[GUSIContext]].
//
// \begin{itemize}
// \item [[fThreadID]] stores the thread manager thread ID.
// \item [[fProcess]] keeps a pointer to the process structure, so completion
// routines can get at it.
// \item [[sCurrentContext]] always points at the current context.
// \item [[sContexts]] contains a queue of all contexts.
// \item [[sHasThreads]] reminds us whether we are threading or not.
// \item We define our own switch-in and termination procedures. If the user specifies procedures
// we store them in [[fSwitchInProc]], [[fSwitchOutProc]], and [[fTerminateProc]] and their parameters
// in [[fSwitchInParam]], [[fSwitchOutParam]], and [[fTerminateParam]] so we can call through to them
// from our procedures.
// \item [[fJoin]] contains the context waiting for us to die;
// \item [[done]] reminds us if the thread is still alive. [[detached]] guarantees
// that we will never wait for that thread anymore.
// \item Last of all, we keep the global error variables [[errno]] and [[h_errno]]
// for each context in the [[fErrno]] and [[fHostErrno]] fields.
// \end{itemize}
//
//
// <Privatissima of [[GUSIContext]]>=
ThreadID fThreadID;
GUSIProcess * fProcess;
GUSIContext * fNext;
GUSISigContext * fSigContext;
ThreadSwitchProcPtr fSwitchInProc;
ThreadSwitchProcPtr fSwitchOutProc;
ThreadTerminationProcPtr fTerminateProc;
void * fSwitchInParam;
void * fSwitchOutParam;
void * fTerminateParam;
void * fResult;
GUSIContext * fJoin;
enum {
done = 1 << 0,
detached= 1 << 1,
asleep = 1 << 2
};
char fFlags;
bool fWakeup;
UInt32 fEntryTicks;
int fErrno;
int fHostErrno;
class Queue : public GUSIContextQueue {
public:
void LiquidateAll();
~Queue() { LiquidateAll(); }
};
static Queue sContexts;
static GUSIContext * sCurrentContext;
static bool sHasThreading;
static OSErr sError;
// The [[GUSIContext]] constructor links the context into the queue of existing
// contexts and installs the appropriate thread hooks. We split this into two
// routines: [[StartSetup]] does static setup before the thread id is determined,
// [[FinishSetup]] does the queueing.
//
// <Privatissima of [[GUSIContext]]>=
void StartSetup();
void FinishSetup();
// Destruction of a [[GUSIContext]] requires some cleanup.
//
// <Privatissima of [[GUSIContext]]>=
~GUSIContext();
};
// [[GUSIContext]] instances are created by instances of [[GUSIContextFactory]].
//
// <Definition of class [[GUSIContextFactory]]>=
class GUSIContextFactory {
public:
static GUSIContextFactory * Instance();
static void SetInstance(GUSIContextFactory * instance);
virtual GUSIContext * CreateContext(ThreadID id);
virtual GUSIContext * CreateContext(
ThreadEntryProcPtr threadEntry, void *threadParam,
Size stackSize, ThreadOptions options = kCreateIfNeeded,
void **threadResult = nil, ThreadID *threadMade = nil);
virtual ~GUSIContextFactory();
protected:
GUSIContextFactory();
};
// Many asynchronous calls take the same style of I/O parameter block and thus
// can be handled by the same completion procedure. [[StartIO]] prepares
// a parameter block for asynchronous I/O; [[FinishIO]] waits for the I/O
// to complete. The parameter block has to be wrapped in a [[GUSIIOPBWrapper]].
//
// <Definition of IO wrappers>=
void GUSIStartIO(IOParam * pb);
OSErr GUSIFinishIO(IOParam * pb);
OSErr GUSIControl(IOParam * pb);
template <class PB> struct GUSIIOPBWrapper {
GUSIContext * fContext;
PB fPB;
GUSIIOPBWrapper() {}
GUSIIOPBWrapper(const PB & pb) { memcpy(&fPB, &pb, sizeof(PB)); }
PB * operator->(){ return &fPB; }
void StartIO() { GUSIStartIO(reinterpret_cast<IOParam *>(&fPB)); }
OSErr FinishIO() { return GUSIFinishIO(reinterpret_cast<IOParam *>(&fPB)); }
OSErr Control() { return GUSIControl(reinterpret_cast<IOParam *>(&fPB)); }
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
// <Inline member functions for file GUSIContext>=
inline GUSIProcess * GUSIProcess::Instance()
{
if (!sInstance)
sInstance = new GUSIProcess(GUSIContext::sHasThreading);
return sInstance;
}
inline void GUSIProcess::DeleteInstance()
{
delete sInstance;
sInstance = 0;
}
// <Inline member functions for file GUSIContext>=
inline void GUSIProcess::GetPSN(ProcessSerialNumber * psn)
{ *psn = fProcess; }
inline void GUSIProcess::AcquireTaskRef()
{ GetThreadCurrentTaskRef(&fTaskRef); }
inline ThreadTaskRef GUSIProcess::GetTaskRef()
{ return fTaskRef; }
inline long GUSIProcess::GetA5()
{ return fA5; }
inline bool GUSIProcess::Threading()
{ return fTaskRef!=0;}
// An [[A5Saver]] is trivially implemented but it simplifies bookkeeping.
//
// <Inline member functions for file GUSIContext>=
inline GUSIProcess::A5Saver::A5Saver(long processA5)
{ fSavedA5 = SetA5(processA5); }
inline GUSIProcess::A5Saver::A5Saver(GUSIProcess * process)
{ fSavedA5 = SetA5(process->GetA5()); }
inline GUSIProcess::A5Saver::A5Saver(GUSIContext * context)
{ fSavedA5 = SetA5(context->Process()->GetA5()); }
inline GUSIProcess::A5Saver::~A5Saver()
{ SetA5(fSavedA5); }
#endif /* GUSI_SOURCE */
#endif /* _GUSIContext_ */

Просмотреть файл

@ -0,0 +1,237 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIContext.nw - Thread and Process structures
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIContextQueue.h,v $
// % Revision 1.1 2001-03-11 22:33:41 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.9 2001/01/17 08:45:13 neeri
// % Improve memory allocation safety somewhat
// %
// % Revision 1.8 2000/05/23 06:58:03 neeri
// % Improve formatting
// %
// % Revision 1.7 2000/03/15 07:22:06 neeri
// % Enforce alignment choices
// %
// % Revision 1.6 1999/08/26 05:45:00 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.5 1999/05/30 03:09:29 neeri
// % Added support for MPW compilers
// %
// % Revision 1.4 1999/03/17 09:05:06 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.3 1998/08/02 11:20:07 neeri
// % Fixed some typos
// %
// % Revision 1.2 1998/08/01 21:32:02 neeri
// % About ready for 2.0a1
// %
// % Revision 1.1 1998/01/25 21:02:43 neeri
// % Engine implemented, except for signals & scheduling
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Context Queues}
//
// At all times through its existence, a [[GUSIContext]] will exist in various
// queues: A queue of all contexts, queues of contexts waiting on a socket
// event, a mutex, or a condition variable, and so on. Since a context is often
// in several queues simultaneously, it's better to define queues non-intrusively.
//
// <GUSIContextQueue.h>=
#ifndef _GUSIContextQueue_
#define _GUSIContextQueue_
#ifndef GUSI_SOURCE
typedef struct GUSIContextQueue GUSIContextQueue;
#else
#include <stdlib.h>
// \section{Definition of context queues}
//
// We'd like to avoid having to include \texttt{GUSIContext} here, for reasons that
// should be rather obvious.
//
// <Name dropping for file GUSIContextQueue>=
class GUSIContext;
#include <ConditionalMacros.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// The class [[GUSIContextQueue]] tries to present an interface that is a subset of
// what C++ standard library list template classes offer.
//
// <Definition of class [[GUSIContextQueue]]>=
class GUSIContextQueue {
public:
GUSIContextQueue();
~GUSIContextQueue();
bool empty();
GUSIContext * front() const;
GUSIContext * back() const;
void push_front(GUSIContext * context);
void push_back(GUSIContext * context);
void push(GUSIContext * context) { push_back(context); }
void pop_front();
void pop() { pop_front(); }
void remove(GUSIContext * context);
void Wakeup();
// We define a forward iterator, but no reverse iterator.
//
// <Define [[iterator]] for [[GUSIContextQueue]]>=
struct element;
class iterator {
friend class GUSIContextQueue;
public:
iterator & operator++();
iterator operator++(int);
bool operator==(const iterator other) const;
GUSIContext * operator*();
GUSIContext * operator->();
private:
// A [[GUSIContextQueue::iterator]] is just a wrapper for a
// [[GUSIContextQueue::element]].
//
// <Privatissima of [[GUSIContextQueue::iterator]]>=
element * fCurrent;
iterator(element * elt) : fCurrent(elt) {}
iterator() : fCurrent(0) {}
};
iterator begin();
iterator end();
private:
// \section{Implementation of context queues}
//
// Efficiency of context queues is quite important, so we provide a custom
// allocator for queue elements.
//
// <Privatissima of [[GUSIContextQueue]]>=
struct element {
GUSIContext * fContext;
element * fNext;
element(GUSIContext * context, element * next = 0)
: fContext(context), fNext(next) {}
void * operator new(size_t);
void operator delete(void *, size_t);
private:
// Elements are allocated in blocks of increasing size.
//
// <Privatissima of [[GUSIContextQueue::element]]>=
struct header {
short fFree;
short fMax;
header *fNext;
};
static header * sBlocks;
};
// A [[GUSIContextQueue]] is a single linked list with a separate back pointer.
//
// <Privatissima of [[GUSIContextQueue]]>=
element * fFirst;
element * fLast;
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
// <Inline member functions for class [[GUSIContextQueue]]>=
inline GUSIContextQueue::GUSIContextQueue()
: fFirst(0), fLast(0)
{
}
// None of the member functions are very large, so we'll inline them.
//
// <Inline member functions for class [[GUSIContextQueue]]>=
inline bool GUSIContextQueue::empty()
{
return !fFirst;
}
inline GUSIContext * GUSIContextQueue::front() const
{
return fFirst ? fFirst->fContext : reinterpret_cast<GUSIContext *>(0);
}
inline GUSIContext * GUSIContextQueue::back() const
{
return fLast ? fLast->fContext : reinterpret_cast<GUSIContext *>(0);
}
inline void GUSIContextQueue::push_front(GUSIContext * context)
{
fFirst = new element(context, fFirst);
if (!fLast)
fLast = fFirst;
}
inline void GUSIContextQueue::pop_front()
{
if (element * e = fFirst) {
if (!(fFirst = fFirst->fNext))
fLast = 0;
delete e;
}
}
// The constructors are not public, so only [[begin]] and [[end]] call them.
//
// <Inline member functions for class [[GUSIContextQueue]]>=
inline GUSIContextQueue::iterator GUSIContextQueue::begin()
{
return iterator(fFirst);
}
inline GUSIContextQueue::iterator GUSIContextQueue::end()
{
return iterator();
}
// <Inline member functions for class [[GUSIContextQueue]]>=
inline GUSIContextQueue::iterator & GUSIContextQueue::iterator::operator++()
{
fCurrent = fCurrent->fNext;
return *this;
}
inline GUSIContextQueue::iterator GUSIContextQueue::iterator::operator++(int)
{
GUSIContextQueue::iterator it(*this);
fCurrent = fCurrent->fNext;
return it;
}
inline bool GUSIContextQueue::iterator::operator==(const iterator other) const
{
return fCurrent == other.fCurrent;
}
inline GUSIContext * GUSIContextQueue::iterator::operator*()
{
return fCurrent->fContext;
}
inline GUSIContext * GUSIContextQueue::iterator::operator->()
{
return fCurrent->fContext;
}
#endif /* GUSI_SOURCE */
#endif /* _GUSIContextQueue_ */

Просмотреть файл

@ -0,0 +1,69 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIDCon.nw - DCon interface
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIDCon.h,v $
// % Revision 1.1 2001-03-11 22:33:45 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.4 2000/03/06 06:03:30 neeri
// % Check device families for file paths
// %
// % Revision 1.3 1999/08/26 05:45:00 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.2 1999/05/29 06:26:41 neeri
// % Fixed header guards
// %
// % Revision 1.1 1999/03/17 09:05:06 neeri
// % Added GUSITimer, expanded docs
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{DCon interface}
//
// A [[GUSIDConSocket]] implements an interface to DCon, Cache Computing's
// debugging console. For more information about DCon, see
// \href{http://www.cache-computing.com/products/dcon/}{Cache Computing's site}
// at \verb|http://www.cache-computing.com/products/dcon/|.
//
// All instances of [[GUSIDConSocket]] are created by the [[GUSIDConDevice]]
// singleton, so
// there is no point in exporting the class itself.
//
// <GUSIDCon.h>=
#ifndef _GUSIDCon_
#define _GUSIDCon_
#ifdef GUSI_INTERNAL
#include "GUSIDevice.h"
// \section{Definition of [[GUSIDConDevice]]}
//
// [[GUSIDConDevice]] is a singleton subclass of [[GUSIDevice]].
//
// <Definition of class [[GUSIDConDevice]]>=
class GUSIDConDevice : public GUSIDevice {
public:
static GUSIDConDevice * Instance();
virtual bool Want(GUSIFileToken & file);
virtual GUSISocket * open(GUSIFileToken & file, int flags);
protected:
GUSIDConDevice() {}
static GUSIDConDevice * sInstance;
};
// <Inline member functions for class [[GUSIDConDevice]]>=
inline GUSIDConDevice * GUSIDConDevice::Instance()
{
if (!sInstance)
sInstance = new GUSIDConDevice;
return sInstance;
}
#endif /* GUSI_INTERNAL */
#endif /* _GUSIDCon_ */

Просмотреть файл

@ -0,0 +1,209 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIDescriptor.nw - Descriptor Table
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIDescriptor.h,v $
// % Revision 1.1 2001-03-11 22:33:48 sgehani%netscape.com
// % First Checked In.
// %
// % 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 };
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(const GUSIDescriptorTable & parent);
private:
// \section{Implementation of [[GUSIDescriptorTable]]}
//
// On creation, a [[GUSIDescriptorTable]] clears all descriptors.
//
// <Privatissima of [[GUSIDescriptorTable]]>=
GUSISocket * fSocket[SIZE];
int fInvalidDescriptor;
GUSIDescriptorTable();
// <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 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_ */

Просмотреть файл

@ -0,0 +1,381 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIDevice.nw - Devices
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIDevice.h,v $
// % Revision 1.1 2001-03-11 22:34:48 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.13 2000/06/12 04:22:30 neeri
// % Return values, not references
// %
// % Revision 1.12 2000/05/23 06:58:03 neeri
// % Improve formatting
// %
// % Revision 1.11 2000/03/15 07:22:06 neeri
// % Enforce alignment choices
// %
// % Revision 1.10 2000/03/06 06:30:30 neeri
// % Check for nonexistent device
// %
// % Revision 1.9 1999/08/26 05:45:01 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.8 1999/07/19 06:21:02 neeri
// % Add mkdir/rmdir, fix various file manager related bugs
// %
// % Revision 1.7 1999/05/29 06:26:42 neeri
// % Fixed header guards
// %
// % Revision 1.6 1999/03/17 09:05:07 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.5 1998/11/22 23:06:52 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.4 1998/10/25 11:37:38 neeri
// % More configuration hooks
// %
// % Revision 1.3 1998/10/11 16:45:13 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.2 1998/08/01 21:28:57 neeri
// % Add directory operations
// %
// % Revision 1.1 1998/01/25 21:02:45 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.1 1996/12/16 02:12:40 neeri
// % TCP Sockets sort of work
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Devices}
//
// Similar to the creation of sockets, operations on files like opening or
// renaming them need to be dispatched to a variety of special cases (Most of
// them of the form "Dev:" preceded by a device name). Analogous to the
// [[GUSISocketFactory]] subclasses registered in a [[GUSISocketDomainRegistry]],
// we therefore have subclasses of [[GUSIDevice]] registered in a
// [[GUSIDeviceRegistry]], although the details of the two registries are
// quite different.
//
// During resolution of a file name, the name and information about it is passed
// around in a [[GUSIFileToken]].
//
// <GUSIDevice.h>=
#ifndef _GUSIDevice_
#define _GUSIDevice_
#ifdef GUSI_SOURCE
#include "GUSISocket.h"
#include "GUSIFileSpec.h"
#include <dirent.h>
#include <utime.h>
#include <ConditionalMacros.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// \section{Definition of [[GUSIFileToken]]}
//
// A [[GUSIFileToken]] consists of a pointer to the name as a C string, of a pointer
// to the [[GUSIDevice]] the token resolves to, and, if the token refers to a
// file name rather than a device name, a pointer to a [[GUSIFileSpec]]. Since
// depending on the call, different [[GUSIDevice]] subclasses may handle it, a
// request code has to be passed to the constructor, too.
//
// <Definition of class [[GUSIFileToken]]>=
class GUSIDevice;
class GUSIFileToken : public GUSIFileSpec {
public:
enum Request {
// \section{Operations on Devices}
//
// The [[open]] operation creates a new socket for the specified path or file
// specification.
//
// <Requests for [[GUSIFileToken]]>=
kWillOpen,
// [[remove]] deletes a path or file specification.
//
// <Requests for [[GUSIFileToken]]>=
kWillRemove,
// [[rename]] renames a path or file specification.
//
// <Requests for [[GUSIFileToken]]>=
kWillRename,
// [[stat]] gathers statistical data about a file or directory.
//
// <Requests for [[GUSIFileToken]]>=
kWillStat,
// [[chmod]] changes file modes, to the extent that this is meaningful on MacOS.
//
// <Requests for [[GUSIFileToken]]>=
kWillChmod,
// [[utime]] bumps a file's modification time.
//
// <Requests for [[GUSIFileToken]]>=
kWillUtime,
// [[access]] checks access permissions for a file.
//
// <Requests for [[GUSIFileToken]]>=
kWillAccess,
// [[mkdir]] creates a directory.
//
// <Requests for [[GUSIFileToken]]>=
kWillMkdir,
// [[rmdir]] deletes a directory.
//
// <Requests for [[GUSIFileToken]]>=
kWillRmdir,
// [[opendir]] opens a directory handle on the given directory.
//
// <Requests for [[GUSIFileToken]]>=
kWillOpendir,
// [[symlink]] creates a symbolic link to a file.
//
// <Requests for [[GUSIFileToken]]>=
kWillSymlink,
// [[readlink]] reads the contents of a symbolic link.
//
// <Requests for [[GUSIFileToken]]>=
kWillReadlink,
// [[fgetfileinfo]] and [[fsetfileinfo]] reads and set the type and creator
// code of a file.
//
// <Requests for [[GUSIFileToken]]>=
kWillGetfileinfo,
kWillSetfileinfo,
// [[faccess]] manipulates MPW properties of files.
//
// <Requests for [[GUSIFileToken]]>=
kWillFaccess,
kNoRequest
};
GUSIFileToken(const char * path, Request request, bool useAlias = false);
GUSIFileToken(const GUSIFileSpec & spec, Request request);
GUSIFileToken(short fRefNum, Request request);
bool IsFile() const { return fIsFile; }
bool IsDevice() const { return !fIsFile; }
Request WhichRequest() const { return fRequest; }
GUSIDevice * Device() const { return fDevice; }
const char * Path() const { return fPath; }
static bool StrFragEqual(const char * name, const char * frag);
enum StdStream {
kStdin,
kStdout,
kStderr,
kConsole,
kNoStdStream = -2
};
static StdStream StrStdStream(const char * name);
private:
GUSIDevice * fDevice;
const char * fPath;
bool fIsFile;
Request fRequest;
};
// \section{Definition of [[GUSIDirectory]]}
//
// [[GUSIDirectory]] is a directory handle to iterate over all entries in a
// directory.
//
// <Definition of class [[GUSIDirectory]]>=
class GUSIDirectory {
public:
virtual ~GUSIDirectory() {}
virtual dirent * readdir() = 0;
virtual long telldir() = 0;
virtual void seekdir(long pos) = 0;
virtual void rewinddir() = 0;
protected:
friend class GUSIDevice;
GUSIDirectory() {}
};
// \section{Definition of [[GUSIDeviceRegistry]]}
//
// The [[GUSIDeviceRegistry]] is a singleton class registering all socket
// domains.
//
// <Definition of class [[GUSIDeviceRegistry]]>=
class GUSIDeviceRegistry {
public:
// The only instance of [[GUSIDeviceRegistry]] is, as usual, obtained by calling
// [[Instance]].
//
// <Creation of [[GUSIDeviceRegistry]]>=
static GUSIDeviceRegistry * Instance();
// <Operations for [[GUSIDeviceRegistry]]>=
GUSISocket * open(const char * path, int flags);
// <Operations for [[GUSIDeviceRegistry]]>=
int remove(const char * path);
// <Operations for [[GUSIDeviceRegistry]]>=
int rename(const char * oldname, const char * newname);
// <Operations for [[GUSIDeviceRegistry]]>=
int stat(const char * path, struct stat * buf, bool useAlias);
// <Operations for [[GUSIDeviceRegistry]]>=
int chmod(const char * path, mode_t mode);
// <Operations for [[GUSIDeviceRegistry]]>=
int utime(const char * path, const utimbuf * times);
// <Operations for [[GUSIDeviceRegistry]]>=
int access(const char * path, int mode);
// <Operations for [[GUSIDeviceRegistry]]>=
int mkdir(const char * path);
// <Operations for [[GUSIDeviceRegistry]]>=
int rmdir(const char * path);
// <Operations for [[GUSIDeviceRegistry]]>=
GUSIDirectory * opendir(const char * path);
// <Operations for [[GUSIDeviceRegistry]]>=
int symlink(const char * target, const char * newlink);
// <Operations for [[GUSIDeviceRegistry]]>=
int readlink(const char * path, char * buf, int bufsize);
// <Operations for [[GUSIDeviceRegistry]]>=
int fgetfileinfo(const char * path, OSType * creator, OSType * type);
int fsetfileinfo(const char * path, OSType creator, OSType type);
// <Operations for [[GUSIDeviceRegistry]]>=
int faccess(const char * path, unsigned * cmd, void * arg);
// [[AddDevice]] and [[RemoveDevice]] add and remove a [[GUSIDevice]].
//
// <Registration interface of [[GUSIDeviceRegistry]]>=
void AddDevice(GUSIDevice * device);
void RemoveDevice(GUSIDevice * device);
// It is convenient to define iterators to iterate across all devices.
//
// <Iterator on [[GUSIDeviceRegistry]]>=
class iterator;
iterator begin();
iterator end();
protected:
// On construction, a [[GUSIFileToken]] looks up the appropriate device in the
// [[GUSIDeviceRegistry]].
//
// <Looking up a device in the [[GUSIDeviceRegistry]]>=
friend class GUSIFileToken;
GUSIDevice * Lookup(GUSIFileToken & file);
private:
// <Privatissima of [[GUSIDeviceRegistry]]>=
static GUSIDeviceRegistry * sInstance;
// Devices are stored in a linked list. On creation of the registry, it immediately
// registers the instance for plain Macintosh file sockets, to which pretty much all
// operations default. This device will never refuse any request.
//
// <Privatissima of [[GUSIDeviceRegistry]]>=
GUSIDevice * fFirstDevice;
GUSIDeviceRegistry();
};
// \section{Definition of [[GUSIDevice]]}
//
// [[GUSIDevice]] consists of a few maintenance functions and the
// device operations. The request dispatcher first calls [[Want]] for
// each candidate device and as soon as it's successful, calls the specific
// operation. Devices are kept in a linked list by the [[GUSIDeviceRegistry]].
//
// <Definition of class [[GUSIDevice]]>=
class GUSIDevice {
public:
virtual bool Want(GUSIFileToken & file);
// <Operations for [[GUSIDevice]]>=
virtual GUSISocket * open(GUSIFileToken & file, int flags);
// <Operations for [[GUSIDevice]]>=
virtual int remove(GUSIFileToken & file);
// <Operations for [[GUSIDevice]]>=
virtual int rename(GUSIFileToken & from, const char * newname);
// <Operations for [[GUSIDevice]]>=
virtual int stat(GUSIFileToken & file, struct stat * buf);
// <Operations for [[GUSIDevice]]>=
virtual int chmod(GUSIFileToken & file, mode_t mode);
// <Operations for [[GUSIDevice]]>=
virtual int utime(GUSIFileToken & file, const utimbuf * times);
// <Operations for [[GUSIDevice]]>=
virtual int access(GUSIFileToken & file, int mode);
// <Operations for [[GUSIDevice]]>=
virtual int mkdir(GUSIFileToken & file);
// <Operations for [[GUSIDevice]]>=
virtual int rmdir(GUSIFileToken & file);
// <Operations for [[GUSIDevice]]>=
virtual GUSIDirectory * opendir(GUSIFileToken & file);
// <Operations for [[GUSIDevice]]>=
virtual int symlink(GUSIFileToken & to, const char * newlink);
// <Operations for [[GUSIDevice]]>=
virtual int readlink(GUSIFileToken & link, char * buf, int bufsize);
// <Operations for [[GUSIDevice]]>=
virtual int fgetfileinfo(GUSIFileToken & file, OSType * creator, OSType * type);
virtual int fsetfileinfo(GUSIFileToken & file, OSType creator, OSType type);
// <Operations for [[GUSIDevice]]>=
virtual int faccess(GUSIFileToken & file, unsigned * cmd, void * arg);
protected:
friend class GUSIDeviceRegistry;
friend class GUSIDeviceRegistry::iterator;
GUSIDevice() : fNextDevice(nil) {}
virtual ~GUSIDevice() {}
GUSIDevice * fNextDevice;
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
// \section{Implementation of [[GUSIDeviceRegistry]]}
//
//
// <Definition of [[GUSISetupDevices]] hook>=
extern "C" void GUSISetupDevices();
// <Inline member functions for class [[GUSIDeviceRegistry]]>=
inline GUSIDeviceRegistry * GUSIDeviceRegistry::Instance()
{
if (!sInstance) {
sInstance = new GUSIDeviceRegistry();
GUSISetupDevices();
}
return sInstance;
}
// The [[GUSIDeviceRegistry]] forward iterator is simple.
//
// <Inline member functions for class [[GUSIDeviceRegistry]]>=
class GUSIDeviceRegistry::iterator {
public:
iterator(GUSIDevice * device = 0) : fDevice(device) {}
GUSIDeviceRegistry::iterator & operator++()
{ fDevice = fDevice->fNextDevice; return *this; }
GUSIDeviceRegistry::iterator operator++(int)
{ GUSIDeviceRegistry::iterator old(*this); fDevice = fDevice->fNextDevice; return old; }
bool operator==(const GUSIDeviceRegistry::iterator other) const
{ return fDevice==other.fDevice; }
GUSIDevice & operator*() { return *fDevice; }
GUSIDevice * operator->() { return fDevice; }
private:
GUSIDevice * fDevice;
};
inline GUSIDeviceRegistry::iterator GUSIDeviceRegistry::begin()
{
return GUSIDeviceRegistry::iterator(fFirstDevice);
}
inline GUSIDeviceRegistry::iterator GUSIDeviceRegistry::end()
{
return GUSIDeviceRegistry::iterator();
}
#endif /* GUSI_SOURCE */
#endif /* _GUSIDevice_ */

Просмотреть файл

@ -0,0 +1,222 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIDiag.nw - Assertions and diagnostics
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIDiag.h,v $
// % Revision 1.1 2001-03-11 22:35:00 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.12 2000/06/12 04:20:58 neeri
// % Introduce GUSI_*printf
// %
// % Revision 1.11 2000/05/23 06:58:04 neeri
// % Improve formatting
// %
// % Revision 1.10 1999/08/26 05:45:01 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.9 1999/08/02 07:02:43 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.8 1999/05/29 06:26:42 neeri
// % Fixed header guards
// %
// % Revision 1.7 1999/04/10 04:45:47 neeri
// % Add DCon stubs
// %
// % Revision 1.6 1999/03/17 09:05:07 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.5 1999/02/25 03:49:00 neeri
// % Switched to DCon for logging
// %
// % Revision 1.4 1998/01/25 20:53:53 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.3 1996/12/16 02:17:20 neeri
// % Tune messages
// %
// % Revision 1.2 1996/11/24 12:52:07 neeri
// % Added GUSIPipeSockets
// %
// % Revision 1.1.1.1 1996/11/03 02:43:32 neeri
// % Imported into CVS
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Assertions and diagnostic messages}
//
// GUSI reports on three kinds of error conditions:
//
// \begin{itemize}
// \item {\bf Internal} errors are usually caused by bugs in GUSI. They should be
// considered fatal.
// \item {\bf Client} errors are caused by calling GUSI routines with bad
// parameters. They are typically handled by returning an appropriate error
// code.
// \item {\bf External} errors are caused by various OS and Network related
// problems. Typically, they are also handled by returning an appropriate
// error code.
// \end{itemize}
//
// If you feel lucky, you can turn off the checking for internal and client errors,
// but external errors will always be checked.
//
// <GUSIDiag.h>=
#ifndef _GUSIDiag_
#define _GUSIDiag_
#include <sys/cdefs.h>
#include <stdarg.h>
#include <string.h>
#include <MacTypes.h>
__BEGIN_DECLS
// \section{Definition of diagnostics}
//
// Depending on the diagnostic level, messages get printed to the DCon console.
//
// <Definition of diagnostic logfile>=
extern char * GUSI_diag_log;
// Printing is done by passing an argument list to [[GUSI_log]]. To simplify the job
// for the diagnostic macros, [[GUSI_log]] returns a [[bool]] value which is
// always [[false]]. [[GUSI_break]] stops with a [[DebugStr]] call. [[GUSI_pos]]
// establishes the source code position for diagnostic messages.
// instead of logging.
//
// <Definition of diagnostic logfile>=
bool GUSI_pos(const char * file, int line);
bool GUSI_log(const char * format, ...);
bool GUSI_break(const char * format, ...);
// There are four levels of diagnostic handling:
// \begin{itemize}
// \item [[GUSI_DIAG_RECKLESS]] totally ignores all internal and client errors. This
// setting is not recommended.
// \item [[GUSI_DIAG_RELAXED]] ignores internal errors, but checks client errors. This
// setting is probably the best for production code.
// \item [[GUSI_DIAG_CAUTIOUS]] checks and logs internal and client errors. This
// setting is best for GUSI client development.
// \item [[GUSI_DIAG_PARANOID]] immediately stops at internal errors, checks and
// logs client and external errors. This is the preferred setting for GUSI
// internal development.
// \end{itemize}
//
//
// <Definition of diagnostic levels>=
#define GUSI_DIAG_RECKLESS 0
#define GUSI_DIAG_RELAXED 1
#define GUSI_DIAG_CAUTIOUS 2
#define GUSI_DIAG_PARANOID 3
// [[GUSI_DIAG]] is defined to the diagnostic level. It can be overridden on a
// module by module basis, or by changing the default setting here.
// [[GUSI_MESSAGE_LEVEL]] determines how important a message has to be to print it.
// [[GUSI_LOG_POS]] determines whether we want to log the code position.
//
// <Definition of diagnostic levels>=
#ifndef GUSI_DIAG
#define GUSI_DIAG GUSI_DIAG_PARANOID
#endif
#ifndef GUSI_LOG_POS
#define GUSI_LOG_POS 0
#endif
#ifndef GUSI_MESSAGE_LEVEL
#define GUSI_MESSAGE_LEVEL 3
#endif
// <Definition of diagnostics>=
#if GUSI_LOG_POS
#define GUSI_POS GUSI_pos(__FILE__, __LINE__)
#define GUSI_LOG GUSI_POS || GUSI_log
#else
#define GUSI_LOG GUSI_log
#endif
#define GUSI_BREAK GUSI_break
// <Definition of diagnostics>=
#if GUSI_DIAG == GUSI_DIAG_RECKLESS
// [[GUSI_DIAG_RECKLESS]] only checks for external errors.
//
// <Diagnostics for [[GUSI_DIAG_RECKLESS]]>=
#define GUSI_ASSERT_INTERNAL(COND, ARGLIST) true
#define GUSI_ASSERT_CLIENT(COND, ARGLIST) true
#define GUSI_ASSERT_EXTERNAL(COND, ARGLIST) (COND)
#define GUSI_SASSERT_INTERNAL(COND, MSG) true
#define GUSI_SASSERT_CLIENT(COND, MSG) true
#define GUSI_SASSERT_EXTERNAL(COND, MSG) (COND)
#elif GUSI_DIAG == GUSI_DIAG_RELAXED
// [[GUSI_DIAG_RELAXED]] ignores internal errors, but checks client errors.
//
// <Diagnostics for [[GUSI_DIAG_RELAXED]]>=
#define GUSI_ASSERT_INTERNAL(COND, ARGLIST) true
#define GUSI_ASSERT_CLIENT(COND, ARGLIST) (COND)
#define GUSI_ASSERT_EXTERNAL(COND, ARGLIST) (COND)
#define GUSI_SASSERT_INTERNAL(COND, MSG) true
#define GUSI_SASSERT_CLIENT(COND, MSG) (COND)
#define GUSI_SASSERT_EXTERNAL(COND, MSG) (COND)
#elif GUSI_DIAG == GUSI_DIAG_CAUTIOUS
// [[GUSI_DIAG_CAUTIOUS]] checks and logs internal and client errors.
//
// <Diagnostics for [[GUSI_DIAG_CAUTIOUS]]>=
#define GUSI_ASSERT_INTERNAL(COND, ARGLIST) ((COND) || GUSI_LOG ARGLIST)
#define GUSI_ASSERT_CLIENT(COND, ARGLIST) ((COND) || GUSI_LOG ARGLIST)
#define GUSI_ASSERT_EXTERNAL(COND, ARGLIST) (COND)
#define GUSI_SASSERT_INTERNAL(COND, MSG) ((COND) || GUSI_LOG ("%s", MSG))
#define GUSI_SASSERT_CLIENT(COND, MSG) ((COND) || GUSI_LOG ("%s", MSG))
#define GUSI_SASSERT_EXTERNAL(COND, MSG) (COND)
#elif GUSI_DIAG == GUSI_DIAG_PARANOID
// [[GUSI_DIAG_PARANOID]] immediately stops at internal errors, checks and
// logs client and external errors.
//
// <Diagnostics for [[GUSI_DIAG_PARANOID]]>=
#define GUSI_ASSERT_INTERNAL(COND, ARGLIST) ((COND) || GUSI_BREAK ARGLIST)
#define GUSI_ASSERT_CLIENT(COND, ARGLIST) ((COND) || GUSI_LOG ARGLIST)
#define GUSI_ASSERT_EXTERNAL(COND, ARGLIST) ((COND) || GUSI_LOG ARGLIST)
#define GUSI_SASSERT_INTERNAL(COND, MSG) ((COND) || GUSI_BREAK ("%s", (MSG)))
#define GUSI_SASSERT_CLIENT(COND, MSG) ((COND) || GUSI_LOG ("%s", MSG))
#define GUSI_SASSERT_EXTERNAL(COND, MSG) ((COND) || GUSI_LOG ("%s", MSG))
#else
#error "GUSI_DIAG defined to illegal value: " GUSI_DIAG
#endif
// There are 11 different diagnostic macros. [[GUSI_ASSERT_INTERNAL]],
// [[GUSI_ASSERT_CLIENT]] and [[GUSI_ASSERT_EXTERNAL]] check for internal,
// client, and external errors, respectively. Their first argument is a
// conditional expression which when [[false]] indicates that an error
// happened. [[GUSI_MESSAGE]] has the same logging status as
// [[GUSI_ASSERT_EXTERNAL]], but does not check any conditions. The [[SASSERT]]
// and [[SMESSAGE]] variants do the same checking, but only take a simple
// message instead of an argument list. The [[CASSERT]] variants simply output
// the condition as the message.
//
// <Definition of diagnostics>=
#define GUSI_CASSERT_INTERNAL(COND) \
GUSI_SASSERT_INTERNAL(COND, "(" #COND ") -- assertion failed.\n" )
#define GUSI_CASSERT_CLIENT(COND) \
GUSI_SASSERT_CLIENT(COND, "(" #COND ") -- assertion failed.\n" )
#define GUSI_CASSERT_EXTERNAL(COND) \
GUSI_SASSERT_EXTERNAL(COND, "(" #COND ") -- assertion failed.\n" )
#define GUSI_MESSAGE1(ARGLIST) \
GUSI_ASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>1, ARGLIST)
#define GUSI_SMESSAGE1(MSG) \
GUSI_SASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>1, MSG)
#define GUSI_MESSAGE2(ARGLIST) \
GUSI_ASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>2, ARGLIST)
#define GUSI_SMESSAGE2(MSG) \
GUSI_SASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>2, MSG)
#define GUSI_MESSAGE3(ARGLIST) \
GUSI_ASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>3, ARGLIST)
#define GUSI_SMESSAGE3(MSG) \
GUSI_SASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>3, MSG)
#define GUSI_MESSAGE4(ARGLIST) \
GUSI_ASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>4, ARGLIST)
#define GUSI_SMESSAGE4(MSG) \
GUSI_SASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>4, MSG)
#define GUSI_MESSAGE5(ARGLIST) \
GUSI_ASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>5, ARGLIST)
#define GUSI_SMESSAGE5(MSG) \
GUSI_SASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>5, MSG)
#define GUSI_MESSAGE(ARGLIST) GUSI_MESSAGE3(ARGLIST)
#define GUSI_SMESSAGE(MSG) GUSI_SMESSAGE3(MSG)
__END_DECLS
#endif /* _GUSIDiag_ */

Просмотреть файл

@ -0,0 +1,107 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIFSWrappers.nw - Pseudo-synchronous file calls
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIFSWrappers.h,v $
// % Revision 1.1 2001-03-11 22:35:14 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.7 2001/01/17 08:45:49 neeri
// % Make open calls synchronous
// %
// % Revision 1.6 2000/05/23 06:58:04 neeri
// % Improve formatting
// %
// % Revision 1.5 2000/01/17 01:41:52 neeri
// % Handle special cases in FSMoveRename
// %
// % Revision 1.4 1999/08/26 05:45:01 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.3 1999/07/19 06:21:02 neeri
// % Add mkdir/rmdir, fix various file manager related bugs
// %
// % Revision 1.2 1999/05/30 02:16:54 neeri
// % Cleaner definition of GUSICatInfo
// %
// % Revision 1.1 1998/10/11 16:45:14 neeri
// % Ready to release 2.0a2
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Pseudo-synchronous File System Calls}
//
// MacOS offers a wide variety of file system APIs, but the most convenient
// of them--the [[FSpXXX]] calls only works synchronously. The routines defined
// here offer a version of these calls, executed asynchronously and embedded
// into the [[GUSIContext]] switching model.
//
// <GUSIFSWrappers.h>=
#ifndef _GUSIFSWrappers_
#define _GUSIFSWrappers_
#ifdef GUSI_SOURCE
#include <Files.h>
#include <sys/cdefs.h>
#include "GUSIFileSpec.h"
__BEGIN_DECLS
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSOpenDriver(StringPtr name, short * refNum);
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSGetFInfo(const FSSpec * spec, FInfo * info);
OSErr GUSIFSSetFInfo(const FSSpec * spec, const FInfo * info);
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSOpenDF(const FSSpec * spec, char permission, short * refNum);
OSErr GUSIFSOpenRF(const FSSpec * spec, char permission, short * refNum);
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSGetVolParms(short vRefNum, GetVolParmsInfoBuffer * volParms);
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSCreate(const FSSpec * spec, OSType creator, OSType type, ScriptCode script);
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSDelete(const FSSpec * spec);
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSDirCreate(const FSSpec * spec);
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSSetFLock(const FSSpec * spec);
OSErr GUSIFSRstFLock(const FSSpec * spec);
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSRename(const FSSpec * spec, ConstStr255Param newname);
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSCatMove(const FSSpec * spec, const FSSpec * dest);
// <Declarations of C [[GUSIFSWrappers]]>=
OSErr GUSIFSMoveRename(const FSSpec * spec, const FSSpec * dest);
__END_DECLS
#ifdef __cplusplus
// <Declarations of C++ [[GUSIFSWrappers]]>=
OSErr GUSIFSGetCatInfo(GUSIIOPBWrapper<GUSICatInfo> * info);
OSErr GUSIFSSetCatInfo(GUSIIOPBWrapper<GUSICatInfo> * info);
// <Declarations of C++ [[GUSIFSWrappers]]>=
OSErr GUSIFSGetFCBInfo(GUSIIOPBWrapper<FCBPBRec> * fcb);
// <Declarations of C++ [[GUSIFSWrappers]]>=
OSErr GUSIFSGetVInfo(GUSIIOPBWrapper<ParamBlockRec> * pb);
OSErr GUSIFSHGetVInfo(GUSIIOPBWrapper<HParamBlockRec> * pb);
// According to Andreas Grosam, [[PBOpenAsync]] may cause the file not to be closed properly when the
// process quits, so we call that call synchronously.
//
// <Declarations of C++ [[GUSIFSWrappers]]>=
OSErr GUSIFSOpen(GUSIIOPBWrapper<ParamBlockRec> * pb);
// <Declarations of C++ [[GUSIFSWrappers]]>=
OSErr GUSIFSHGetFInfo(GUSIIOPBWrapper<HParamBlockRec> * pb);
OSErr GUSIFSHSetFInfo(GUSIIOPBWrapper<HParamBlockRec> * pb);
// <Declarations of C++ [[GUSIFSWrappers]]>=
OSErr GUSIFSHGetVolParms(GUSIIOPBWrapper<HParamBlockRec> * pb);
// <Declarations of C++ [[GUSIFSWrappers]]>=
OSErr GUSIFSCreate(const FSSpec * spec);
// <Declarations of C++ [[GUSIFSWrappers]]>=
OSErr GUSIFSCatMove(const FSSpec * spec, long dest);
#endif
#endif /* GUSI_SOURCE */
#endif /* GUSIFSWrappers */

Просмотреть файл

@ -0,0 +1,203 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIFactory.nw - Socket factories
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIFactory.h,v $
// % Revision 1.1 2001-03-11 22:35:04 sgehani%netscape.com
// % First Checked In.
// %
// % 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_ */

Просмотреть файл

@ -0,0 +1,587 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIFileSpec.nw - File specifications
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIFileSpec.h,v $
// % Revision 1.1 2001-03-11 22:35:07 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.15 2001/01/17 08:46:45 neeri
// % Get rid of excess directory seperators when name is empty
// %
// % Revision 1.14 2000/12/23 06:10:17 neeri
// % Add GUSIFSpTouchFolder, GUSIFSpGetCatInfo; copy error in copy constructor
// %
// % Revision 1.13 2000/10/16 03:59:36 neeri
// % Make FSSpec a member of GUSIFileSpec instead of a base class
// %
// % Revision 1.12 2000/06/12 04:20:58 neeri
// % Introduce GUSI_*printf
// %
// % Revision 1.11 2000/05/23 07:00:00 neeri
// % Improve formatting
// %
// % Revision 1.10 2000/03/15 07:16:08 neeri
// % Fix path construction, temp name bugs
// %
// % Revision 1.9 2000/03/06 06:34:11 neeri
// % Added C FSSpec convenience calls
// %
// % Revision 1.8 1999/08/26 05:45:02 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.7 1999/07/19 06:21:02 neeri
// % Add mkdir/rmdir, fix various file manager related bugs
// %
// % Revision 1.6 1999/06/28 06:00:53 neeri
// % add support for generating temp names from basename
// %
// % Revision 1.5 1999/05/30 02:16:53 neeri
// % Cleaner definition of GUSICatInfo
// %
// % Revision 1.4 1999/03/17 09:05:07 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.3 1998/10/11 16:45:15 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.2 1998/08/01 21:32:04 neeri
// % About ready for 2.0a1
// %
// % Revision 1.1 1998/01/25 21:02:46 neeri
// % Engine implemented, except for signals & scheduling
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{File specifications}
//
// While the Macintosh toolbox has a convenient type [[FSSpec]] to pass to
// file system routines, it lacks manipulation functions. We provide them here.
// This module has been known under a different name and with different data types
// in GUSI 1.
//
// <GUSIFileSpec.h>=
#ifndef _GUSIFileSpec_
#define _GUSIFileSpec_
#include <MacTypes.h>
#include <Files.h>
#include <Folders.h>
#include <string.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
// \section{C Interfaces to [[GUSIFileSpec]]}
//
// Many of the API routines defined here are useful to C code and not too hard to make accessible,
// even though I prefer the C++ versions. As opposed to GUSI 1, we stick to our namespace now.
//
// <Plain C interfaces to [[GUSIFileSpec]]>=
/*
* Construct a FSSpec from...
*/
/* ... the refNum of an open file. */
OSErr GUSIFRefNum2FSp(short fRefNum, FSSpec * desc);
/* ... a working directory & file name. */
OSErr GUSIWD2FSp(short wd, ConstStr31Param name, FSSpec * desc);
/* ... a path name. */
OSErr GUSIPath2FSp(const char * path, FSSpec * desc);
/* ... a special object. */
OSErr GUSISpecial2FSp(OSType object, short vol, FSSpec * desc);
/* ... a temporary file path. */
OSErr GUSIMakeTempFSp(short vol, long dirID, FSSpec * desc);
/*
* Convert a FSSpec into...
*/
/* ... a full path name. */
char * GUSIFSp2FullPath(const FSSpec * desc);
/* ... a relative path name if possible, full if not */
char * GUSIFSp2RelPath(const FSSpec * desc);
/* ... a path relative to the specified directory */
char * GUSIFSp2DirRelPath(const FSSpec * desc, const FSSpec * dir);
/* ... an GUSI-=specific ASCII encoding. */
char * GUSIFSp2Encoding(const FSSpec * desc);
/*
* Construct FSSpec of...
*/
/* ... (vRefNum, parID) */
OSErr GUSIFSpUp(FSSpec * desc);
/* ... file (name) in directory denoted by desc */
OSErr GUSIFSpDown(FSSpec * desc, ConstStr31Param name);
/* ... of nth file in directory denoted by (vRefNum, parID) */
OSErr GUSIFSpIndex(FSSpec * desc, short n);
/* Resolve if alias file */
OSErr GUSIFSpResolve(FSSpec * spec);
/* Touch folder containing the object */
OSErr GUSIFSpTouchFolder(const FSSpec * spec);
/* Get catalog information */
OSErr GUSIFSpGetCatInfo(const FSSpec * spec, CInfoPBRec * info);
__END_DECLS
#ifdef GUSI_SOURCE
#include "GUSIBasics.h"
#include "GUSIContext.h"
#include <ConditionalMacros.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// \section{Definition of [[GUSICatInfo]]}
//
// [[GUSICatInfo]] is a wrapper for [[CInfoPBRec]]. Since the latter is a [[union]], we cannot
// inherit from it.
//
// <Definition of class [[GUSICatInfo]]>=
class GUSICatInfo {
CInfoPBRec fInfo;
public:
bool IsFile() const;
bool IsAlias() const;
bool DirIsExported() const;
bool DirIsMounted() const;
bool DirIsShared() const;
bool HasRdPerm() const;
bool HasWrPerm() const;
bool Locked() const;
CInfoPBRec & Info() { return fInfo; }
operator CInfoPBRec &() { return fInfo; }
struct HFileInfo & FileInfo() { return fInfo.hFileInfo; }
struct DirInfo & DirInfo() { return fInfo.dirInfo; }
struct FInfo & FInfo() { return fInfo.hFileInfo.ioFlFndrInfo; }
struct FXInfo & FXInfo() { return fInfo.hFileInfo.ioFlXFndrInfo; }
const CInfoPBRec & Info() const { return fInfo; }
operator const CInfoPBRec &() const { return fInfo; }
const struct HFileInfo & FileInfo() const{ return fInfo.hFileInfo; }
const struct DirInfo & DirInfo() const { return fInfo.dirInfo; }
const struct FInfo & FInfo() const { return fInfo.hFileInfo.ioFlFndrInfo; }
const struct FXInfo & FXInfo() const { return fInfo.hFileInfo.ioFlXFndrInfo; }
};
// \section{Definition of [[GUSIFileSpec]]}
//
// A [[GUSIFileSpec]] is a manipulation friendly version of an [[FSSpec]]. Due to
// conversion operators, a [[GUSIFileSpec]] can be used whereever a [[const FSSpec]]
// is specified. For any long term storage, [[FSSpec]] should be used rather than the
// much bulkier [[GUSIFileSpec]].
//
// <Definition of class [[GUSIFileSpec]]>=
class GUSIFileSpec {
public:
// A [[GUSIFileSpec]] can be constructed in lots of different ways. Most of the
// constructors have a final argument [[useAlias]] that, when [[true]], suppresses
// resolution of leaf aliases.
//
// First, two trivial cases: The default constructor and the copy constructor, which
// do exactly what you'd expect them to do.
//
// <Constructors for [[GUSIFileSpec]]>=
GUSIFileSpec() {}
GUSIFileSpec(const GUSIFileSpec & spec);
// The [[FSSpec]] conversion is almost a copy constructor, but by default resolves
// leaf aliases.
//
// <Constructors for [[GUSIFileSpec]]>=
GUSIFileSpec(const FSSpec & spec, bool useAlias = false);
// A number of convenience constructors let you construct a [[GUSIFileSpec]] from
// various components.
//
// <Constructors for [[GUSIFileSpec]]>=
// Construct from volume reference number, directory ID & file name
GUSIFileSpec(short vRefNum, long parID, ConstStr31Param name, bool useAlias = false);
// Construct from working directory & file name
GUSIFileSpec(short wd, ConstStr31Param name, bool useAlias = false);
// Construct from full or relative path
GUSIFileSpec(const char * path, bool useAlias = false);
// Construct from open file reference number
explicit GUSIFileSpec(short fRefNum);
// Finally, there is a constructor for constructing a [[GUSIFileSpec]] for one of
// the folders obtainable with [[FindFolder]].
//
// <Constructors for [[GUSIFileSpec]]>=
GUSIFileSpec(OSType object, short vol = kOnSystemDisk);
// All [[GUSIFileSpecs]] have an error variable from which the last error
// is available.
//
// <Error handling in [[GUSIFileSpec]]>=
OSErr Error() const;
operator void*() const;
bool operator!() const;
// While earlier versions of GUSI maintained a notion of "current directory" that
// was independent of the HFS default directory, there is no such distinction anymore
// in GUSI 2. [[SetDefaultDirectory]] sets the default directory to [[vRefNum, dirID]].
// [[GetDefaultDirectory]] sets [[vRefNum,dirID]] to the default directory. Neither
// routine affects the [[name]]. [[GetVolume]] gets the named or indexed volume.
//
// <Default directory handling in [[GUSIFileSpec]]>=
OSErr SetDefaultDirectory();
OSErr GetDefaultDirectory();
OSErr GetVolume(short index = -1);
// Conversions of [[GUSIFileSpec]] to [[FSSpec]] values and references is, of course,
// simple. Pointers are a bit trickier; we define an custom [[operator&]] and two
// smart pointer classes. [[operator->]], however, is simpler.
//
// <Converting a [[GUSIFileSpec]] to a [[FSSpec]]>=
operator const FSSpec &() const;
class pointer {
public:
pointer(GUSIFileSpec * ptr);
operator GUSIFileSpec *() const;
operator const FSSpec *() const;
private:
GUSIFileSpec * ptr;
};
pointer operator&();
class const_pointer {
public:
const_pointer(const GUSIFileSpec * ptr);
operator const GUSIFileSpec *() const;
operator const FSSpec *() const;
private:
const GUSIFileSpec * ptr;
};
const_pointer operator&() const;
const FSSpec * operator->() const;
friend class pointer;
friend class const_pointer;
// Each [[GUSIFileSpec]] has an implicit [[GUSICatInfo]] record associated with it.
// [[CatInfo]] calls [[GetCatInfo]] if the record is not already valid and
// returns a pointer to the record. [[DirInfo]] replaces the [[GUSIFileSpec]] by
// the specification of its parent directory and returns a pointer to information
// about the parent. Both calls return a [[nil]] pointer if the object does not exist.
// If all you are interested in is whether the object exists, call [[Exists]].
//
// <Getting the [[GUSICatInfo]] for a [[GUSIFileSpec]]>=
const GUSICatInfo * CatInfo(short index);
const GUSICatInfo * DirInfo();
const GUSICatInfo * CatInfo() const;
bool Exists() const;
// In many POSIXish contexts, it's necessary to specify path names with C string.
// Although this practice is dangerous on a Mac, we of course have to conform to
// it. The basic operations are getting a full path and getting a path relative to
// a directory (the current directory by default).
//
// <Getting path names from a [[GUSIFileSpec]]>=
char * FullPath() const;
char * RelativePath() const;
char * RelativePath(const FSSpec & dir) const;
// If the path ultimately is going to flow back into a GUSI routine again, it is
// possible to simply encode the [[GUSIFileSpec]] in ASCII. This is fast and reliable,
// but you should of course not employ it with any non-GUSI destination routine and
// should never store such a part across a reboot. The standard [[GUSIFileSpec]]
// constructors for paths will accept encoded paths.
//
// The encoding is defined as:
//
// \begin{itemize}
// \item 1 byte: DC1 (ASCII 0x11)
// \item 4 bytes: Volume reference number in zero-padded hex
// \item 8 bytes: Directory ID in zero-padded hex
// \item n bytes: Partial pathname, starting with ':'
// \end{itemize}
//
// <Getting path names from a [[GUSIFileSpec]]>=
char * EncodedPath() const;
// Most aliases are resolved implicitly, but occasionally you may want to do
// explicit resolution. [[Resolve]] resolves an alias. If [[gently]] is set,
// nonexistent target files of aliases don't cause an error to be returned.
//
// <Alias resolution for a [[GUSIFileSpec]]>=
OSErr Resolve(bool gently = true);
// [[AliasPath]] returns the path an alias points to without mounting any volumes.
//
// <Alias resolution for a [[GUSIFileSpec]]>=
char * AliasPath() const;
// A major feature of the [[GUSIFileSpec]] class is the set of operators for
// manipulating a file specification.
//
// [[operator--]] replaces a file specification with the directory specification of
// its parent.
//
// <Manipulating a [[GUSIFileSpec]]>=
GUSIFileSpec & operator--();
// [[operator++]] sets the [[dirID]] of a directory specification to the ID of the
// directory.
//
// <Manipulating a [[GUSIFileSpec]]>=
GUSIFileSpec & operator++();
// The two versions of [[operator+=]], which internally both call [[AddPathComponent]],
// replace a directory specification with the specification
//
// <Manipulating a [[GUSIFileSpec]]>=
GUSIFileSpec & AddPathComponent(const char * name, int length, bool fullSpec);
GUSIFileSpec & operator+=(ConstStr31Param name);
GUSIFileSpec & operator+=(const char * name);
// [[operator+]] provides a non-destructive variant of [[operator+=]].
//
// <Manipulating a [[GUSIFileSpec]]>=
friend GUSIFileSpec operator+(const FSSpec & spec, ConstStr31Param name);
friend GUSIFileSpec operator+(const FSSpec & spec, const char * name);
// Array access replaces the file specification with the [[index]]th object in the
// {\em parent directory} of the specification (allowing the same specification to
// be reused for reading a directory).
//
// <Manipulating a [[GUSIFileSpec]]>=
GUSIFileSpec & operator[](short index);
// To manipulate the fields of the file specification directly, there is a procedural
// interface.
//
// <Manipulating a [[GUSIFileSpec]]>=
void SetVRef(short vref);
void SetParID(long parid);
void SetName(ConstStr63Param nam);
void SetName(const char * nam);
// For some modifications to propagate quickly, the surrounding folder needs to
// have its date modified.
//
// <Manipulating a [[GUSIFileSpec]]>=
OSErr TouchFolder();
// Two [[GUSIFileSpecs]] can be compared for (in)equality.
//
// <Comparing two [[GUSIFileSpec]] objects>=
friend bool operator==(const GUSIFileSpec & one, const GUSIFileSpec & other);
// [[IsParentOf]] determines whether the object specifies a parent directory of
// [[other]].
//
// <Comparing two [[GUSIFileSpec]] objects>=
bool IsParentOf(const GUSIFileSpec & other) const;
protected:
// \section{Implementation of [[GUSIFileSpec]]}
//
// [[sError]] contains the error code for failed calls. [[Error]] returns the value.
//
// <Privatissima of [[GUSIFileSpec]]>=
mutable OSErr fError;
// For path name constructions, a sometimes large scratch area is needed which is
// maintained in [[sScratch]]. A scratch request preserves a preexisting scratch area
// at the {\em end} of the new area if [[extend]] is nonzero.
//
// <Privatissima of [[GUSIFileSpec]]>=
static char * sScratch;
static long sScratchSize;
static char * CScratch(bool extend = false);
static StringPtr PScratch();
// A [[GUSIFileSpec]] has a [[GUSICatInfo]] embedded and a flag [[fValidInfo]] indicating
// that it is valid.
//
// <Privatissima of [[GUSIFileSpec]]>=
FSSpec fSpec;
GUSIIOPBWrapper<GUSICatInfo> fInfo;
bool fValidInfo;
// For convenience, we define a fictivous parent directory of all volumes.
//
// <Privatissima of [[GUSIFileSpec]]>=
enum { ROOT_MAGIC_COOKIE = 666 };
// Each accumulation step is preformed in [[PrependPathComponent]].
//
// <Privatissima of [[GUSIFileSpec]]>=
OSErr PrependPathComponent(char *&path, ConstStr63Param component, bool colon) const;
};
// A [[GUSITempFileSpec]] is just a [[GUSIFileSpec]] with constructors to construct
// filenames for temporary files.
//
// <Definition of class [[GUSIFileSpec]]>=
class GUSITempFileSpec : public GUSIFileSpec {
public:
GUSITempFileSpec(short vRefNum = kOnSystemDisk);
GUSITempFileSpec(short vRefNum, long parID);
GUSITempFileSpec(ConstStr31Param basename);
GUSITempFileSpec(short vRefNum, ConstStr31Param basename);
GUSITempFileSpec(short vRefNum, long parID, ConstStr31Param basename);
private:
void TempName();
void TempName(ConstStr31Param basename);
static int sID;
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
// \section{Implementation of [[GUSICatInfo]]}
//
// All of the member functions for [[GUSICatInfo]] are inline.
//
// <Inline member functions for class [[GUSICatInfo]]>=
inline bool GUSICatInfo::IsFile() const
{
return !(DirInfo().ioFlAttrib & 0x10);
}
inline bool GUSICatInfo::IsAlias() const
{
return
!(FileInfo().ioFlAttrib & 0x10) &&
(FInfo().fdFlags & (1 << 15));
}
inline bool GUSICatInfo::DirIsExported() const
{
return (FileInfo().ioFlAttrib & 0x20) != 0;
}
inline bool GUSICatInfo::DirIsMounted() const
{
return (FileInfo().ioFlAttrib & 0x08) != 0;
}
inline bool GUSICatInfo::DirIsShared() const
{
return (FileInfo().ioFlAttrib & 0x04) != 0;
}
inline bool GUSICatInfo::HasRdPerm() const
{
return !(DirInfo().ioACUser & 0x02) != 0;
}
inline bool GUSICatInfo::HasWrPerm() const
{
return !(DirInfo().ioACUser & 0x04) != 0;
}
inline bool GUSICatInfo::Locked() const
{
return (FileInfo().ioFlAttrib & 0x11) == 0x01;
}
// <Inline member functions for class [[GUSIFileSpec]]>=
inline OSErr GUSIFileSpec::Error() const
{
return fError;
}
inline GUSIFileSpec::operator void*() const
{
return (void *)!fError;
}
inline bool GUSIFileSpec::operator!() const
{
return fError!=0;
}
// <Inline member functions for class [[GUSIFileSpec]]>=
inline StringPtr GUSIFileSpec::PScratch()
{
return (StringPtr) CScratch();
}
// <Inline member functions for class [[GUSIFileSpec]]>=
inline OSErr GUSIFileSpec::SetDefaultDirectory()
{
return fError = HSetVol(nil, fSpec.vRefNum, fSpec.parID);
}
inline OSErr GUSIFileSpec::GetDefaultDirectory()
{
fSpec.name[0] = 0;
fValidInfo = false;
return fError = HGetVol(nil, &fSpec.vRefNum, &fSpec.parID);
}
// [[operator+=]] and [[operator+]] are merely wrappers around [[AddPathComponent]].
//
// <Inline member functions for class [[GUSIFileSpec]]>=
inline GUSIFileSpec & GUSIFileSpec::operator+=(ConstStr31Param name)
{
return AddPathComponent((char *) name+1, name[0], true);
}
inline GUSIFileSpec & GUSIFileSpec::operator+=(const char * name)
{
return AddPathComponent(name, strlen(name), true);
}
// The other variations of the call are simple.
//
// <Inline member functions for class [[GUSIFileSpec]]>=
inline const GUSICatInfo * GUSIFileSpec::CatInfo() const
{
return const_cast<GUSIFileSpec *>(this)->CatInfo(0);
}
inline const GUSICatInfo * GUSIFileSpec::DirInfo()
{
if (CatInfo(-1)) {
fSpec.parID = fInfo->DirInfo().ioDrParID;
fValidInfo = true;
return &fInfo.fPB;
} else
return nil;
}
inline bool GUSIFileSpec::Exists() const
{
return CatInfo() != nil;
}
// Reference conversion is straightforward, as is [[operator->]].
//
// <Inline member functions for class [[GUSIFileSpec]]>=
inline GUSIFileSpec::operator const FSSpec &() const
{
return fSpec;
}
inline const FSSpec * GUSIFileSpec::operator->() const
{
return &fSpec;
}
// Pointers, however, are a trickier issue, as they might be used either as a
// [[GUSIFileSpec *]] or as an [[FSSpec *]].
//
// <Inline member functions for class [[GUSIFileSpec]]>=
inline GUSIFileSpec::const_pointer::const_pointer(const GUSIFileSpec * ptr)
: ptr(ptr)
{
}
inline GUSIFileSpec::const_pointer::operator const GUSIFileSpec *() const
{
return ptr;
}
inline GUSIFileSpec::const_pointer::operator const FSSpec *() const
{
return &ptr->fSpec;
}
inline GUSIFileSpec::const_pointer GUSIFileSpec::operator&() const
{
return const_pointer(this);
}
// [[GUSIFileSpec::pointer]] is the non-constant equivalent to [[GUSIFileSpec::const_pointer]].
//
// <Inline member functions for class [[GUSIFileSpec]]>=
inline GUSIFileSpec::pointer::pointer(GUSIFileSpec * ptr)
: ptr(ptr)
{
}
inline GUSIFileSpec::pointer::operator GUSIFileSpec *() const
{
return ptr;
}
inline GUSIFileSpec::pointer::operator const FSSpec *() const
{
return &ptr->fSpec;
}
inline GUSIFileSpec::pointer GUSIFileSpec::operator&()
{
return pointer(this);
}
#endif /* GUSI_SOURCE */
#endif /* GUSIFileSpec */

Просмотреть файл

@ -0,0 +1,52 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIForeignThreads.nw - Foreign thread support
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIForeignThreads.h,v $
// % Revision 1.1 2001-03-11 22:35:11 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.4 2000/12/23 06:10:48 neeri
// % Use kPowerPCCFragArch, NOT GetCurrentArchitecture()
// %
// % Revision 1.3 2000/05/23 07:00:00 neeri
// % Improve formatting
// %
// % Revision 1.2 2000/03/06 08:28:32 neeri
// % Releasing 2.0.5
// %
// % Revision 1.1 1999/09/09 07:18:06 neeri
// % Added support for foreign threads
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Supporting threads made outside of GUSI}
//
// As convenient as the pthreads interface is, some applications may link to other
// libraries which create thread manager threads directly, such as the PowerPlant
// thread classes.
//
// Unfortunately, there is no really elegant way to welcome these lost sheep into the
// pthread flock, since the thread manager offers no way to retrieve thread switching
// and termination procedures. We therefore have to resort to a violent technique used
// already successfully for MPW support: On CFM, we override the default entry point and
// use the CFM manager to find the real implementation.
//
// For non-CFM, we unfortunately don't have such an effective technique, since the
// thread manager is called through traps (and no, I'm not going to patch any traps
// for this). You will therefore have to recompile your foreign libraries with
// a precompiled header that includes \texttt{GUSIForeignThreads.h}.
//
// <GUSIForeignThreads.h>=
#ifndef _GUSIForeignThreads_
#define _GUSIForeignThreads_
#define NewThread(style, entry, param, stack, options, result, made) \
GUSINewThread((style), (entry), (param), (stack), (options), (result), (made))
#define SetThreadSwitcher(thread, switcher, param, inOrOut) \
GUSISetThreadSwitcher((thread), (switcher), (param), (inOrOut))
#define SetThreadTerminator(thread, threadTerminator, terminationProcParam) \
GUSISetThreadTerminator((thread), (threadTerminator), (terminationProcParam))
#endif /* _GUSIForeignThreads_ */

Просмотреть файл

@ -0,0 +1,68 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIMTInet.nw - Common routines for MacTCP
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIInet.h,v $
// % Revision 1.1 2001-03-11 22:35:17 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.5 1999/08/26 05:45:02 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.4 1999/05/29 06:26:43 neeri
// % Fixed header guards
// %
// % Revision 1.3 1998/11/22 23:06:53 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.2 1998/10/25 11:57:34 neeri
// % Ready to release 2.0a3
// %
// % Revision 1.1 1998/08/01 21:32:05 neeri
// % About ready for 2.0a1
// %
// % Revision 1.4 1998/02/11 12:57:12 neeri
// % PowerPC Build
// %
// % Revision 1.3 1998/01/25 20:53:55 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.2 1996/12/22 19:57:56 neeri
// % TCP streams work
// %
// % Revision 1.1 1996/12/16 02:12:40 neeri
// % TCP Sockets sort of work
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{TCP/IP shared infrastructure}
//
// Both the MacTCP and the forthcoming open transport implementation of TCP/IP
// sockets share a common registry.
//
// <GUSIInet.h>=
#ifndef _GUSIInet_
#define _GUSIInet_
#ifdef GUSI_SOURCE
#include <sys/cdefs.h>
__BEGIN_DECLS
// <Definition of [[GUSIwithInetSockets]]>=
void GUSIwithInetSockets();
__END_DECLS
#ifdef GUSI_INTERNAL
#include "GUSIFactory.h"
extern GUSISocketTypeRegistry gGUSIInetFactories;
#endif /* GUSI_INTERNAL */
#endif /* GUSI_SOURCE */
#endif /* _GUSIInet_ */

Просмотреть файл

@ -0,0 +1,104 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIBasics.nw - Common routines for GUSI
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIInternal.h,v $
// % Revision 1.1 2001-03-11 22:35:21 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.20 2001/01/17 08:32:30 neeri
// % Atomic locks turned out not to be necessary after all
// %
// % Revision 1.19 2001/01/17 08:31:10 neeri
// % Added PPC error codes, tweaked nullEvent handling, added atomic locks
// %
// % Revision 1.18 2000/10/16 04:34:22 neeri
// % Releasing 2.1.2
// %
// % Revision 1.17 2000/06/12 04:20:58 neeri
// % Introduce GUSI_*printf
// %
// % Revision 1.16 2000/05/23 06:51:55 neeri
// % Reorganize errors to improve formatting
// %
// % Revision 1.15 2000/03/15 07:22:05 neeri
// % Enforce alignment choices
// %
// % Revision 1.14 1999/08/26 05:44:58 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.13 1999/08/02 07:02:42 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.12 1999/06/28 05:56:01 neeri
// % Get rid of STL includes in header
// %
// % Revision 1.11 1999/06/08 04:31:29 neeri
// % Getting ready for 2.0b2
// %
// % Revision 1.10 1999/05/30 03:09:28 neeri
// % Added support for MPW compilers
// %
// % Revision 1.9 1999/04/10 04:45:05 neeri
// % Handle MacTCP errors correctly
// %
// % Revision 1.8 1999/03/17 09:05:04 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.7 1998/10/25 11:57:33 neeri
// % Ready to release 2.0a3
// %
// % Revision 1.6 1998/10/11 16:45:09 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.5 1998/01/25 20:53:50 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.4 1996/12/22 19:57:54 neeri
// % TCP streams work
// %
// % Revision 1.3 1996/11/24 12:52:04 neeri
// % Added GUSIPipeSockets
// %
// % Revision 1.2 1996/11/18 00:53:46 neeri
// % TestTimers (basic threading/timer test) works
// %
// % Revision 1.1.1.1 1996/11/03 02:43:32 neeri
// % Imported into CVS
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Common routines for GUSI}
//
// This section defines various services used by all parts of GUSI:
//
// \begin{itemize}
// \item Various hooks to customize GUSI.
// \item The propagation of {\bf errors} to the [[errno]] and [[h_errno]]
// global variables.
// \item Waiting for completion of asynchronous calls.
// \item Event handling.
// \item Compiler features.
// \end{itemize}
//
// To protect our name space further, we maintain a strict C interface unless
// [[GUSI_SOURCE]] is defined, and may avoid defining some stuff unless
// [[GUSI_INTERNAL]] is defined. The following header is therefore included
// first by all GUSI source files.
//
// <GUSIInternal.h>=
#ifndef _GUSIInternal_
#define _GUSIInternal_
#include <ConditionalMacros.h>
#define GUSI_SOURCE
#define GUSI_INTERNAL
#if !TARGET_RT_MAC_CFM
#pragma segment GUSI
#endif
#endif /* _GUSIInternal_ */

Просмотреть файл

@ -0,0 +1,65 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIMPW.nw - MPW Interface
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIMPW.h,v $
// % Revision 1.1 2001-03-11 22:35:49 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.13 2001/01/17 08:48:04 neeri
// % Introduce Expired(), Reset()
// %
// % Revision 1.12 2000/05/23 07:01:53 neeri
// % Improve formatting
// %
// % Revision 1.11 1999/08/26 05:45:03 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.10 1999/07/19 06:17:08 neeri
// % Add SIOW support
// %
// % Revision 1.9 1999/07/07 04:17:41 neeri
// % Final tweaks for 2.0b3
// %
// % Revision 1.8 1999/06/08 04:31:29 neeri
// % Getting ready for 2.0b2
// %
// % Revision 1.7 1999/05/29 06:26:43 neeri
// % Fixed header guards
// %
// % Revision 1.6 1999/04/29 05:33:20 neeri
// % Fix fcntl prototype
// %
// % Revision 1.5 1999/03/29 09:51:28 neeri
// % New configuration system with support for hardcoded configurations.
// %
// % Revision 1.4 1999/03/17 09:05:08 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.3 1998/11/22 23:06:54 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.2 1998/10/25 11:57:35 neeri
// % Ready to release 2.0a3
// %
// % Revision 1.1 1998/08/01 21:32:06 neeri
// % About ready for 2.0a1
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{MPW Support}
//
// In MPW tools, we have to direct some of the I/O operations to the standard
// library functions, which we otherwise try to avoid as much as possible.
// Getting at those library calls is a bit tricky: For 68K, we rename entries
// in the MPW glue library, while for PowerPC, we look up the symbols dynamically.
//
// MPW support is installed implicitly through [[GUSISetupConsoleDescriptors]]
//
// <GUSIMPW.h>=
#ifndef _GUSIMPW_
#define _GUSIMPW_
#endif /* _GUSIMPW_ */

Просмотреть файл

@ -0,0 +1,56 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIMSL.nw - Interface to the MSL
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIMSL.h,v $
// % Revision 1.1 2001-03-11 22:35:53 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.8 2000/10/29 19:17:04 neeri
// % Accommodate MSL's non-compliant fopen signature
// %
// % Revision 1.7 2000/10/16 04:34:22 neeri
// % Releasing 2.1.2
// %
// % Revision 1.6 2000/05/23 07:03:25 neeri
// % Improve formatting
// %
// % Revision 1.5 1999/08/26 05:45:03 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.4 1999/08/02 07:02:43 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.3 1999/04/14 04:20:21 neeri
// % Override console hooks
// %
// % Revision 1.2 1999/04/10 04:53:58 neeri
// % Use simpler internal MSL routines
// %
// % Revision 1.1 1998/08/01 21:32:07 neeri
// % About ready for 2.0a1
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{The Interface to the MSL}
//
// This section interfaces GUSI to the Metrowerks Standard Library (MSL)
// by reimplementing various internal MSL routines. Consequently, some of
// the code used here is borrowed from the MSL code itself. The routines
// here are in three different categories:
//
// \begin{itemize}
// \item Overrides of MSL functions (all internal, as it happens).
// \item Implementations of ANSI library specific public GUSI functions like
// [[fdopen]].
// \item Implementations of ANSI library specific internal GUSI functions.
// \end{itemize}
//
//
// <GUSIMSL.h>=
#ifndef _GUSIMSL_
#define _GUSIMSL_
#endif /* _GUSIMSL_ */

Просмотреть файл

@ -0,0 +1,194 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIMTInet.nw - Common routines for MacTCP
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIMTInet.h,v $
// % Revision 1.1 2001-03-11 22:35:57 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.14 2000/10/16 04:34:23 neeri
// % Releasing 2.1.2
// %
// % Revision 1.13 2000/05/23 07:03:25 neeri
// % Improve formatting
// %
// % Revision 1.12 1999/08/26 05:45:04 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.11 1999/08/02 07:02:43 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.10 1999/06/30 07:42:06 neeri
// % Getting ready to release 2.0b3
// %
// % Revision 1.9 1999/05/29 06:26:43 neeri
// % Fixed header guards
// %
// % Revision 1.8 1999/04/29 05:33:19 neeri
// % Fix fcntl prototype
// %
// % Revision 1.7 1999/03/17 09:05:08 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.6 1998/10/25 11:57:35 neeri
// % Ready to release 2.0a3
// %
// % Revision 1.5 1998/10/11 16:45:16 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.4 1998/02/11 12:57:12 neeri
// % PowerPC Build
// %
// % Revision 1.3 1998/01/25 20:53:55 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.2 1996/12/22 19:57:56 neeri
// % TCP streams work
// %
// % Revision 1.1 1996/12/16 02:12:40 neeri
// % TCP Sockets sort of work
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Basic MacTCP code}
//
// A [[GUSIMTInetSocket]] defines the infrastructure shared between
// MacTCP TCP and UDP sockets.
//
// <GUSIMTInet.h>=
#ifndef _GUSIMTInet_
#define _GUSIMTInet_
#ifdef GUSI_SOURCE
#include <sys/cdefs.h>
__BEGIN_DECLS
// <Definition of [[GUSIwithMTInetSockets]]>=
void GUSIwithMTInetSockets();
__END_DECLS
#ifdef GUSI_INTERNAL
#include "GUSISocket.h"
#include "GUSISocketMixins.h"
#include <netinet/in.h>
#include <MacTCP.h>
// \section{Definition of [[GUSIMTInetSocket]]}
//
// MacTCP related sockets are buffered, have a standard state model, and can be
// nonblocking.
//
// <Definition of class [[GUSIMTInetSocket]]>=
class GUSIMTInetSocket :
public GUSISocket,
protected GUSISMBlocking,
protected GUSISMState,
protected GUSISMInputBuffer,
protected GUSISMOutputBuffer,
protected GUSISMAsyncError
{
public:
GUSIMTInetSocket();
// [[bind]] for MacTCP sockets has the fatal flaw that it is totally unable to
// reserve a socket.
//
// <Overridden member functions for [[GUSIMTInetSocket]]>=
virtual int bind(void * addr, socklen_t namelen);
// [[getsockname]] and [[getpeername]] return the stored values.
//
// <Overridden member functions for [[GUSIMTInetSocket]]>=
virtual int getsockname(void * addr, socklen_t * namelen);
virtual int getpeername(void * addr, socklen_t * namelen);
// [[shutdown]] just delegates to [[GUSISMState]].
//
// <Overridden member functions for [[GUSIMTInetSocket]]>=
virtual int shutdown(int how);
// [[fcntl]] handles the blocking support.
//
// <Overridden member functions for [[GUSIMTInetSocket]]>=
virtual int fcntl(int cmd, va_list arg);
// [[ioctl]] deals with blocking support and with [[FIONREAD]].
//
// <Overridden member functions for [[GUSIMTInetSocket]]>=
virtual int ioctl(unsigned int request, va_list arg);
// [[getsockopt]] and [[setsockopt]] are available for setting buffer sizes and
// getting asynchronous errors.
//
// <Overridden member functions for [[GUSIMTInetSocket]]>=
virtual int getsockopt(int level, int optname, void *optval, socklen_t * optlen);
// <Overridden member functions for [[GUSIMTInetSocket]]>=
virtual int setsockopt(int level, int optname, void *optval, socklen_t optlen);
// MacTCP sockets implement socket style calls.
//
// <Overridden member functions for [[GUSIMTInetSocket]]>=
virtual bool Supports(ConfigOption config);
// MacTCP I/O calls communicate by means of read and write data structures,
// of which we need only the most primitive variants.
//
// <Definition of classes [[MiniWDS]] and [[MidiWDS]]>=
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#endif
class MiniWDS {
public:
u_short fLength;
char * fDataPtr;
u_short fZero;
MiniWDS() : fZero(0) {}
Ptr operator &() { return (Ptr)this; }
};
class MidiWDS {
public:
u_short fLength;
char * fDataPtr;
u_short fLength2;
char * fDataPtr2;
u_short fZero;
MidiWDS() : fZero(0) {}
Ptr operator &() { return (Ptr)this; }
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
// The only other interesting bit in the interface is the driver management, which
// arranges to open the MacTCP driver and domain name resolver at most once,
// as late as possible in the program (If you open some SLIP or PPP drivers
// before the Toolbox is initialized, you'll wish you'd curled up by the fireside
// with a nice Lovecraft novel instead). [[Driver]] returns the driver reference
// number of the MacTCP driver. [[HostAddr]] returns our host's IP address.
//
// <MacTCP driver management>=
static short Driver();
static u_long HostAddr();
protected:
// All MacTCP related sockets need a [[StreamPtr]]; they store their own and
// their peer's address away, and the save errors reported at interrupt time
// in an [[fAsyncError]] field.
//
// <Data members for [[GUSIMTInetSocket]]>=
StreamPtr fStream;
sockaddr_in fSockAddr;
sockaddr_in fPeerAddr;
// \section{Implementation of [[GUSIMTInetSocket]]}
//
// [[Driver]] preserves error status in an [[OSErr]]
// variable, initially [[1]] to convey unresolvedness.
//
// <Data members for [[GUSIMTInetSocket]]>=
static short sDrvrRefNum;
static OSErr sDrvrState;
static u_long sHostAddress;
};
#endif /* GUSI_INTERNAL */
#endif /* GUSI_SOURCE */
#endif /* _GUSIMTInet_ */

Просмотреть файл

@ -0,0 +1,69 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSINetDB.nw - Convert between names and adresses
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIMTNetDB.h,v $
// % Revision 1.1 2001-03-11 22:36:01 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.7 2000/06/12 04:20:59 neeri
// % Introduce GUSI_*printf
// %
// % Revision 1.6 2000/03/06 06:10:02 neeri
// % Reorganize Yield()
// %
// % Revision 1.5 1999/08/26 05:45:04 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.4 1999/05/30 03:09:30 neeri
// % Added support for MPW compilers
// %
// % Revision 1.3 1999/03/17 09:05:08 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.2 1998/10/25 11:57:36 neeri
// % Ready to release 2.0a3
// %
// % Revision 1.1 1998/10/11 16:45:17 neeri
// % Ready to release 2.0a2
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{IP Name Lookup in MacTCP}
//
//
// <GUSIMTNetDB.h>=
#ifndef _GUSIMTNetDB_
#define _GUSIMTNetDB_
#ifdef GUSI_INTERNAL
#include "GUSINetDB.h"
// \section{Definition of [[GUSIMTNetDB]]}
//
//
// <Definition of class [[GUSIMTNetDB]]>=
class GUSIMTNetDB : public GUSINetDB {
public:
static void Instantiate();
static bool Resolver();
// <Overridden member functions for [[GUSIMTNetDB]]>=
virtual hostent * gethostbyname(const char * name);
// <Overridden member functions for [[GUSIMTNetDB]]>=
virtual hostent * gethostbyaddr(const void * addr, size_t len, int type);
// <Overridden member functions for [[GUSIMTNetDB]]>=
virtual char * inet_ntoa(in_addr inaddr);
// <Overridden member functions for [[GUSIMTNetDB]]>=
virtual long gethostid();
private:
GUSIMTNetDB() {}
GUSISpecificData<GUSIhostent,GUSIKillHostEnt> fHost;
static OSErr sResolverState;
};
#endif /* GUSI_INTERNAL */
#endif /* _GUSIMTNetDB_ */

Просмотреть файл

@ -0,0 +1,113 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIMTTcp.nw - TCP code for MacTCP
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIMTTcp.h,v $
// % Revision 1.1 2001-03-11 22:36:04 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.17 2000/10/16 04:01:59 neeri
// % Save A5 in completion routines
// %
// % Revision 1.16 2000/05/23 07:04:20 neeri
// % Improve formatting, fix hang on close
// %
// % Revision 1.15 2000/03/06 06:10:02 neeri
// % Reorganize Yield()
// %
// % Revision 1.14 1999/08/26 05:42:13 neeri
// % Fix nonblocking connects
// %
// % Revision 1.13 1999/08/02 07:02:44 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.12 1999/06/28 06:04:58 neeri
// % Support interrupted calls
// %
// % Revision 1.11 1999/06/08 04:31:29 neeri
// % Getting ready for 2.0b2
// %
// % Revision 1.10 1999/05/30 03:09:30 neeri
// % Added support for MPW compilers
// %
// % Revision 1.9 1999/03/17 09:05:08 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.8 1998/11/22 23:06:55 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.7 1998/10/25 11:31:42 neeri
// % Add MSG_PEEK support, make releases more orderly.
// %
// % Revision 1.6 1998/10/11 16:45:18 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.5 1998/08/01 21:32:07 neeri
// % About ready for 2.0a1
// %
// % Revision 1.4 1998/01/25 20:53:56 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.3 1997/11/13 21:12:11 neeri
// % Fall 1997
// %
// % Revision 1.2 1996/12/22 19:57:57 neeri
// % TCP streams work
// %
// % Revision 1.1 1996/12/16 02:12:41 neeri
// % TCP Sockets sort of work
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{MacTCP TCP sockets}
//
// A [[GUSIMTTcpSocket]] implements the TCP socket class for MacTCP. All instances
// of [[GUSIMTTcpSocket]] are created by the [[GUSIMTTcpFactory]] singleton, so
// there is no point in exporting the class itself.
//
// <GUSIMTTcp.h>=
#ifndef _GUSIMTTcp_
#define _GUSIMTTcp_
#ifdef GUSI_SOURCE
#include <sys/cdefs.h>
__BEGIN_DECLS
// \section{Definition of [[GUSIMTTcpFactory]]}
//
// [[GUSIMTTcpFactory]] is a singleton subclass of [[GUSISocketFactory]].
//
// <Definition of [[GUSIwithMTTcpSockets]]>=
void GUSIwithMTTcpSockets();
__END_DECLS
#ifdef GUSI_INTERNAL
#include "GUSIFactory.h"
// <Definition of class [[GUSIMTTcpFactory]]>=
class GUSIMTTcpFactory : public GUSISocketFactory {
public:
static GUSISocketFactory * Instance();
virtual GUSISocket * socket(int domain, int type, int protocol);
private:
GUSIMTTcpFactory() {}
static GUSISocketFactory * instance;
};
// <Inline member functions for class [[GUSIMTTcpFactory]]>=
inline GUSISocketFactory * GUSIMTTcpFactory::Instance()
{
if (!instance)
instance = new GUSIMTTcpFactory;
return instance;
}
#endif /* GUSI_INTERNAL */
#endif /* GUSI_SOURCE */
#endif /* _GUSIMTTcp_ */

Просмотреть файл

@ -0,0 +1,95 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIMTUdp.nw - UDP code for MacTCP
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIMTUdp.h,v $
// % Revision 1.1 2001-03-11 22:36:08 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.11 2000/10/16 04:02:00 neeri
// % Save A5 in completion routines
// %
// % Revision 1.10 2000/05/23 07:05:16 neeri
// % Improve formatting
// %
// % Revision 1.9 2000/03/06 06:10:01 neeri
// % Reorganize Yield()
// %
// % Revision 1.8 1999/08/26 05:45:04 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.7 1999/08/02 07:02:44 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.6 1999/07/20 04:25:53 neeri
// % Fixed race condition in sendto()
// %
// % Revision 1.5 1999/06/28 06:04:59 neeri
// % Support interrupted calls
// %
// % Revision 1.4 1999/05/29 06:26:44 neeri
// % Fixed header guards
// %
// % Revision 1.3 1999/03/17 09:05:09 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.2 1998/11/22 23:06:57 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.1 1998/10/25 11:57:37 neeri
// % Ready to release 2.0a3
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{MacTCP UDP sockets}
//
// A [[GUSIMTUdpSocket]] implements the UDP socket class for MacTCP. All instances
// of [[GUSIMTUdpSocket]] are created by the [[GUSIMTUdpFactory]] singleton, so
// there is no point in exporting the class itself.
//
// <GUSIMTUdp.h>=
#ifndef _GUSIMTUdp_
#define _GUSIMTUdp_
#ifdef GUSI_SOURCE
#include <sys/cdefs.h>
__BEGIN_DECLS
// \section{Definition of [[GUSIMTUdpFactory]]}
//
// [[GUSIMTUdpFactory]] is a singleton subclass of [[GUSISocketFactory]].
//
// <Definition of [[GUSIwithMTUdpSockets]]>=
void GUSIwithMTUdpSockets();
__END_DECLS
#ifdef GUSI_INTERNAL
#include "GUSIFactory.h"
// <Definition of class [[GUSIMTUdpFactory]]>=
class GUSIMTUdpFactory : public GUSISocketFactory {
public:
static GUSISocketFactory * Instance();
virtual GUSISocket * socket(int domain, int type, int protocol);
private:
GUSIMTUdpFactory() {}
static GUSISocketFactory * instance;
};
// <Inline member functions for class [[GUSIMTUdpFactory]]>=
inline GUSISocketFactory * GUSIMTUdpFactory::Instance()
{
if (!instance)
instance = new GUSIMTUdpFactory;
return instance;
}
#endif /* GUSI_INTERNAL */
#endif /* GUSI_SOURCE */
#endif /* _GUSIMTUdp_ */

Просмотреть файл

@ -0,0 +1,178 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIMacFile.nw - Disk files
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIMacFile.h,v $
// % Revision 1.1 2001-03-11 22:35:45 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.24 2001/01/17 08:58:06 neeri
// % Releasing 2.1.4
// %
// % Revision 1.23 2000/12/23 06:11:36 neeri
// % Move diagnostics to A5 safe time
// %
// % Revision 1.22 2000/10/16 04:02:00 neeri
// % Save A5 in completion routines
// %
// % Revision 1.21 2000/05/23 07:07:05 neeri
// % Improve formatting, fix lseek for readonly files
// %
// % Revision 1.20 2000/03/15 07:17:11 neeri
// % Fix rename for existing targets
// %
// % Revision 1.19 2000/03/06 08:12:27 neeri
// % New Yield system; fix readdir at end of directory
// %
// % Revision 1.18 1999/11/15 07:24:32 neeri
// % Return error for stat() of nonexistent files.
// %
// % Revision 1.17 1999/09/09 07:19:19 neeri
// % Fix read-ahead switch-off
// %
// % Revision 1.16 1999/08/26 05:45:05 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.15 1999/08/05 05:55:35 neeri
// % Updated for CW Pro 5
// %
// % Revision 1.14 1999/08/02 07:02:45 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.13 1999/07/19 06:21:03 neeri
// % Add mkdir/rmdir, fix various file manager related bugs
// %
// % Revision 1.12 1999/07/07 04:17:41 neeri
// % Final tweaks for 2.0b3
// %
// % Revision 1.11 1999/06/28 06:07:15 neeri
// % Support I/O alignment, more effective writeback strategy
// %
// % Revision 1.10 1999/05/30 02:18:05 neeri
// % Cleaner definition of GUSICatInfo
// %
// % Revision 1.9 1999/04/29 05:33:19 neeri
// % Fix fcntl prototype
// %
// % Revision 1.8 1999/04/10 04:54:39 neeri
// % stat() was broken for directories
// %
// % Revision 1.7 1999/03/29 09:51:28 neeri
// % New configuration system with support for hardcoded configurations.
// %
// % Revision 1.6 1999/03/17 09:05:09 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.5 1998/11/22 23:06:57 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.4 1998/10/11 16:45:19 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.3 1998/08/01 21:28:58 neeri
// % Add directory operations
// %
// % Revision 1.2 1998/02/11 12:57:14 neeri
// % PowerPC Build
// %
// % Revision 1.1 1998/01/25 21:02:48 neeri
// % Engine implemented, except for signals & scheduling
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Disk files}
//
// A [[GUSIMacFileSocket]] implements the operations on mac files. All instances
// of [[GUSIMacFileSocket]] are created by the [[GUSIMacFileDevice]] singleton, so
// there is no point in exporting the class itself.
//
// A [[GUSIMacDirectory]] implements directory handles on mac directories.
//
// <GUSIMacFile.h>=
#ifndef _GUSIMacFile_
#define _GUSIMacFile_
#ifdef GUSI_INTERNAL
#include "GUSIDevice.h"
// \section{Definition of [[GUSIMacFileDevice]]}
//
// [[GUSIMacFileDevice]] is a singleton subclass of [[GUSIDevice]].
//
// <Definition of class [[GUSIMacFileDevice]]>=
class GUSIMacFileDevice : public GUSIDevice {
public:
static GUSIMacFileDevice * Instance();
virtual bool Want(GUSIFileToken & file);
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual GUSISocket * open(GUSIFileToken & file, int flags);
// The normal case of [[remove]] is straightforward, but we also want to support
// the removing of open files, which is frequently used in POSIX code, as much
// as possible.
//
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int remove(GUSIFileToken & file);
// [[rename]] can be a surprisingly difficult operation.
//
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int rename(GUSIFileToken & file, const char * newname);
// [[stat]] is a rather intimidating function which needs to pull together
// information from various sources.
//
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int stat(GUSIFileToken & file, struct stat * buf);
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int chmod(GUSIFileToken & file, mode_t mode);
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int utime(GUSIFileToken & file, const utimbuf * times);
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int access(GUSIFileToken & file, int mode);
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int mkdir(GUSIFileToken & file);
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int rmdir(GUSIFileToken & file);
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual GUSIDirectory * opendir(GUSIFileToken & file);
// [[symlink]] has to reproduce the Finder's alias creation process, which is
// quite complex.
//
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int symlink(GUSIFileToken & to, const char * newlink);
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int readlink(GUSIFileToken & link, char * buf, int bufsize);
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int fgetfileinfo(GUSIFileToken & file, OSType * creator, OSType * type);
virtual int fsetfileinfo(GUSIFileToken & file, OSType creator, OSType type);
// [[faccess]] is a somewhat curious case in that [[GUSIMacFileDevice]]
// accepts responsibility for handling it, but then does not, in fact, handle
// it.
//
// <Overridden member functions for [[GUSIMacFileDevice]]>=
virtual int faccess(GUSIFileToken & file, unsigned * cmd, void * arg);
GUSISocket * open(short fileRef, int flags);
int MarkTemporary(const FSSpec & file);
void CleanupTemporaries(bool giveup);
~GUSIMacFileDevice();
protected:
GUSIMacFileDevice() : fTemporaries(0) {}
// [[MarkTemporary]] moves the file to the temporary folder and puts it on a list
// of death candidates.
//
// <Privatissima of [[GUSIMacFileDevice]]>=
struct TempQueue {
TempQueue * fNext;
FSSpec fSpec;
} * fTemporaries;
};
#endif /* GUSI_INTERNAL */
#endif /* _GUSIMacFile_ */

Просмотреть файл

@ -0,0 +1,266 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSINetDB.nw - Convert between names and adresses
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSINetDB.h,v $
// % Revision 1.1 2001-03-11 22:37:15 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.10 2000/12/23 06:11:55 neeri
// % Add SSH service
// %
// % Revision 1.9 2000/05/23 07:10:35 neeri
// % Improve formatting
// %
// % Revision 1.8 2000/03/15 07:18:43 neeri
// % Fix GUSIBuiltinServiceDB::sServices
// %
// % Revision 1.7 1999/11/15 07:23:23 neeri
// % Fix gethostname for non-TCP/IP case
// %
// % Revision 1.6 1999/08/26 05:45:05 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.5 1999/05/30 03:09:30 neeri
// % Added support for MPW compilers
// %
// % Revision 1.4 1999/03/17 09:05:10 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.3 1998/11/22 23:06:58 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.2 1998/10/25 11:33:38 neeri
// % Fixed disastrous bug in inet_addr, support alternative NL conventions
// %
// % Revision 1.1 1998/10/11 16:45:20 neeri
// % Ready to release 2.0a2
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Converting Between Names and IP Addresses}
//
// The [[GUSINetDB]] class coordinates access to the domain name server database.
//
// The [[GUSIServiceDB]] class is responsible for a database of TCP/IP service
// name to port number mappings.
//
// The [[hostent]] and [[servent]] classes are somewhat inconvenient to set up as
// they reference extra chunks of memory, so we define the wrapper classes
// [[GUSIhostent]] and [[GUSIservent]].
//
// <GUSINetDB.h>=
#ifndef _GUSINetDB_
#define _GUSINetDB_
#ifdef GUSI_SOURCE
#include "GUSISpecific.h"
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ConditionalMacros.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// \section{Definition of [[GUSIhostent]] and [[GUSIservent]]}
//
// A [[GUSIhostent]] may need a lot of data, so we allocate the name data
// dynamically.
//
// <Definition of class [[GUSIhostent]]>=
class GUSIhostent : public hostent {
public:
GUSIhostent();
void Alloc(size_t size);
char * fAlias[16];
char * fAddressList[16];
char * fName;
size_t fAlloc;
char fAddrString[16];
};
extern "C" void GUSIKillHostEnt(void * hostent);
// A [[GUSIservent]] typically will remain more modest in its needs, so the
// data is allocated statically.
//
// <Definition of class [[GUSIservent]]>=
class GUSIservent : public servent {
public:
GUSIservent();
char * fAlias[8];
char fName[256];
};
// \section{Definition of [[GUSIServiceDB]]}
//
// [[GUSIServiceDB]] is a singleton, used as a primitive iterator. The semantics of
// these iterators conform only very superficially to real iterators:
//
// \begin{itemize}
// \item Only a single instance of the iterator is supported.
// \item Comparison operators all compare against [[end]], no matter what
// arguments are passed.
// \end{itemize}
//
// <Definition of class [[GUSIServiceDB]]>=
extern "C" void GUSIKillServiceDBData(void * entry);
class GUSIServiceDB {
public:
static GUSIServiceDB * Instance();
// Iterating is accomplished by a public interface conforming to STL iterator
// protocols.
//
// <Iterating over the [[GUSIServiceDB]]>=
class iterator {
public:
inline bool operator==(const iterator & other);
inline bool operator!=(const iterator & other);
inline iterator & operator++();
inline servent * operator*();
};
inline static iterator begin();
inline static iterator end();
protected:
static GUSIServiceDB * sInstance;
GUSIServiceDB() {}
virtual ~GUSIServiceDB() {}
friend void GUSIKillServiceDBData(void * entry);
// This interface does not access any data elements in the iterator, but directly
// calls through to a private interface in the [[GUSIServiceDB]], which explains
// the limitations in the iterator implementation.
//
// <Internal iterator protocol of [[GUSIServiceDB]]>=
friend class iterator;
class Data {
public:
Data() : fCurrent(0) {}
servent * fCurrent;
GUSIservent fServent;
};
typedef GUSISpecificData<Data, GUSIKillServiceDBData> SpecificData;
static SpecificData sData;
virtual void Reset() = 0;
virtual void Next() = 0;
};
// \section{Definition of [[GUSINetDB]]}
//
//
// <Definition of class [[GUSINetDB]]>=
class GUSINetDB {
public:
// [[GUSINetDB]] is a singleton, but usually instantiated by an instance of a
// derived class.
//
// <Constructing instances of [[GUSINetDB]]>=
static GUSINetDB * Instance();
// The public interface of [[GUSINetDB]] consists of three areas. The first set of
// calls is concerned with host names and IP numbers.
//
// <[[GUSINetDB]] host database>=
virtual hostent * gethostbyname(const char * name);
virtual hostent * gethostbyaddr(const void * addr, size_t len, int type);
virtual char * inet_ntoa(in_addr inaddr);
virtual in_addr_t inet_addr(const char *address);
virtual long gethostid();
virtual int gethostname(char *machname, int buflen);
// The next set of calls is concerned with TCP and UDP services.
//
// <[[GUSINetDB]] service database>=
virtual servent * getservbyname(const char * name, const char * proto);
virtual servent * getservbyport(int port, const char * proto);
virtual servent * getservent();
virtual void setservent(int stayopen);
virtual void endservent();
// Finally, there is a set of calls concerned with protocols.
//
// <[[GUSINetDB]] protocol database>=
virtual protoent * getprotobyname(const char * name);
virtual protoent * getprotobynumber(int proto);
virtual protoent * getprotoent();
virtual void setprotoent(int stayopen);
virtual void endprotoent();
protected:
GUSINetDB();
virtual ~GUSINetDB() {}
// \section{Implementation of [[GUSINetDB]]}
//
// [[GUSINetDB]] is a singleton, but typically implemented by an instance
// of a subclass (stored into [[fInstance]] by that subclass) rather than the
// base class.
//
// <Privatissima of [[GUSINetDB]]>=
static GUSINetDB * sInstance;
// The service database is implemented in terms of [[GUSIServiceDB]]. Only
// [[getservent]] and [[setservent]] accesse [[GUSIServiceDB]] directly, however.
//
// <Privatissima of [[GUSINetDB]]>=
bool fServiceOpen;
GUSIServiceDB::iterator fServiceIter;
// The protocol database is similar, in principle, to the service database, but it
// lends itself naturally to a much simpler implementation.
//
// <Privatissima of [[GUSINetDB]]>=
int fNextProtocol;
static protoent sProtocols[2];
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
#ifdef GUSI_INTERNAL
// Iterators can be defined without regard to the implementation of the
// [[GUSIServiceDB]] currently used.
//
// <Inline member functions for class [[GUSIServiceDB]]>=
GUSIServiceDB::iterator GUSIServiceDB::begin()
{
Instance()->Reset();
Instance()->Next();
return iterator();
}
GUSIServiceDB::iterator GUSIServiceDB::end()
{
return iterator();
}
bool GUSIServiceDB::iterator::operator==(const GUSIServiceDB::iterator &)
{
return !GUSIServiceDB::sData->fCurrent;
}
bool GUSIServiceDB::iterator::operator!=(const GUSIServiceDB::iterator &)
{
return GUSIServiceDB::sData->fCurrent
== static_cast<servent *>(nil);
}
GUSIServiceDB::iterator & GUSIServiceDB::iterator::operator++()
{
GUSIServiceDB::Instance()->Next();
return *this;
}
servent * GUSIServiceDB::iterator::operator*()
{
return GUSIServiceDB::sData->fCurrent;
}
#endif /* GUSI_INTERNAL */
#endif /* GUSI_SOURCE */
#endif /* _GUSINetDB_ */

Просмотреть файл

@ -0,0 +1,75 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSINull.nw - Null device
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSINull.h,v $
// % Revision 1.1 2001-03-11 22:37:20 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.7 2000/03/06 06:03:29 neeri
// % Check device families for file paths
// %
// % Revision 1.6 1999/08/26 05:45:05 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.5 1999/05/29 06:26:44 neeri
// % Fixed header guards
// %
// % Revision 1.4 1999/04/29 05:34:22 neeri
// % Support stat/fstat
// %
// % Revision 1.3 1999/03/17 09:05:10 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.2 1998/11/22 23:06:59 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.1 1998/08/01 21:32:09 neeri
// % About ready for 2.0a1
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Null device}
//
// A [[GUSINullSocket]] implements the null socket class for MacTCP. All instances
// of [[GUSINullSocket]] are created by the [[GUSINullDevice]] singleton, so
// there is no point in exporting the class itself.
//
// <GUSINull.h>=
#ifndef _GUSINull_
#define _GUSINull_
#ifdef GUSI_INTERNAL
#include "GUSIDevice.h"
// \section{Definition of [[GUSINullDevice]]}
//
// [[GUSINullDevice]] is a singleton subclass of [[GUSIDevice]].
//
// <Definition of class [[GUSINullDevice]]>=
class GUSINullDevice : public GUSIDevice {
public:
static GUSINullDevice * Instance();
virtual bool Want(GUSIFileToken & file);
virtual GUSISocket * open(GUSIFileToken & file, int flags);
virtual int stat(GUSIFileToken & file, struct stat * buf);
GUSISocket * open();
protected:
GUSINullDevice() {}
static GUSINullDevice * sInstance;
};
// <Inline member functions for class [[GUSINullDevice]]>=
inline GUSINullDevice * GUSINullDevice::Instance()
{
if (!sInstance)
sInstance = new GUSINullDevice;
return sInstance;
}
#endif /* GUSI_INTERNAL */
#endif /* _GUSINull_ */

Просмотреть файл

@ -0,0 +1,71 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIOpenTransport.nw- OpenTransport sockets
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIOTInet.h,v $
// % Revision 1.1 2001-03-11 22:37:27 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.11 2001/01/17 08:54:12 neeri
// % Add Clone() implementations
// %
// % Revision 1.10 2000/06/12 04:20:59 neeri
// % Introduce GUSI_*printf
// %
// % Revision 1.9 2000/05/23 09:05:27 neeri
// % Improve formatting
// %
// % Revision 1.8 1999/09/26 03:57:12 neeri
// % Renamed broadcast option
// %
// % Revision 1.7 1999/09/09 07:20:29 neeri
// % Fix numerous bugs, add support for interface ioctls
// %
// % Revision 1.6 1999/08/26 05:45:06 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.5 1999/08/02 07:02:45 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.4 1999/05/29 06:26:44 neeri
// % Fixed header guards
// %
// % Revision 1.3 1999/04/14 04:21:19 neeri
// % Correct option sizes
// %
// % Revision 1.2 1999/04/10 05:17:51 neeri
// % Implement broadcast/multicast options
// %
// % Revision 1.1 1999/03/17 09:05:10 neeri
// % Added GUSITimer, expanded docs
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Open Transport TCP/IP sockets}
//
// For TCP and UDP, the strategy classes do most of the work, the derived socket
// classes only have to do option management.
//
// <GUSIOTInet.h>=
#ifndef _GUSIOTInet_
#define _GUSIOTInet_
#ifdef GUSI_SOURCE
#include <sys/cdefs.h>
__BEGIN_DECLS
// \section{Definition of Open Transport Internet hooks}
//
//
// <Definition of [[GUSIwithOTInetSockets]]>=
void GUSIwithOTInetSockets();
void GUSIwithOTTcpSockets();
void GUSIwithOTUdpSockets();
__END_DECLS
#endif /* GUSI_SOURCE */
#endif /* _GUSIOTInet_ */

Просмотреть файл

@ -0,0 +1,93 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIOTNetDB.nw - Open Transport DNS lookups
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIOTNetDB.h,v $
// % Revision 1.1 2001-03-11 22:37:31 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.8 2000/06/12 04:20:59 neeri
// % Introduce GUSI_*printf
// %
// % Revision 1.7 2000/05/23 07:11:45 neeri
// % Improve formatting, handle failed lookups correctly
// %
// % Revision 1.6 2000/03/06 06:10:01 neeri
// % Reorganize Yield()
// %
// % Revision 1.5 1999/12/14 06:27:47 neeri
// % initialize OT before opening resolver
// %
// % Revision 1.4 1999/08/26 05:45:06 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.3 1999/06/30 07:42:06 neeri
// % Getting ready to release 2.0b3
// %
// % Revision 1.2 1999/05/30 03:09:31 neeri
// % Added support for MPW compilers
// %
// % Revision 1.1 1999/03/17 09:05:10 neeri
// % Added GUSITimer, expanded docs
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{IP Name Lookup in Open Transport}
//
//
// <GUSIOTNetDB.h>=
#ifndef _GUSIOTNetDB_
#define _GUSIOTNetDB_
#ifdef GUSI_INTERNAL
#include "GUSINetDB.h"
#include "GUSIContext.h"
#include "GUSIOpenTransport.h"
// \section{Definition of [[GUSIOTNetDB]]}
//
// We don't want to open the Open Transport headers files in our public header, but we
// need [[InetSvcRef]].
//
// <Name dropping for file GUSIOTNetDB>=
class TInternetServices;
typedef TInternetServices* InetSvcRef;
// <Definition of class [[GUSIOTNetDB]]>=
class GUSIOTNetDB : public GUSINetDB {
public:
static void Instantiate();
bool Resolver();
// <Overridden member functions for [[GUSIOTNetDB]]>=
virtual hostent * gethostbyname(const char * name);
// <Overridden member functions for [[GUSIOTNetDB]]>=
virtual hostent * gethostbyaddr(const void * addr, size_t len, int type);
// <Overridden member functions for [[GUSIOTNetDB]]>=
virtual char * inet_ntoa(in_addr inaddr);
// <Overridden member functions for [[GUSIOTNetDB]]>=
virtual long gethostid();
private:
GUSISpecificData<GUSIhostent, GUSIKillHostEnt> fHost;
// \section{Implementation of [[GUSIOTNetDB]]}
//
//
// <Privatissima of [[GUSIOTNetDB]]>=
GUSIOTNetDB();
// The [[GUSIOTNetDB]] notifier operates similarly to the [[GUSIOTSocket]] notifier,
// but it has to get the context to wake up somehow from its parameters.
//
// <Privatissima of [[GUSIOTNetDB]]>=
uint16_t fEvent;
uint32_t fCompletion;
OSStatus fAsyncError;
InetSvcRef fSvc;
GUSIContext * fCreationContext;
friend pascal void GUSIOTNetDBNotify(GUSIOTNetDB *, OTEventCode, OTResult, void *);
};
#endif /* GUSI_INTERNAL */
#endif /* _GUSIOTNetDB_ */

Просмотреть файл

@ -0,0 +1,422 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIOpenTransport.nw- OpenTransport sockets
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIOpenTransport.h,v $
// % Revision 1.1 2001-03-11 22:37:24 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.18 2001/01/17 08:58:06 neeri
// % Releasing 2.1.4
// %
// % Revision 1.17 2000/10/16 04:07:23 neeri
// % Fix accept code
// %
// % Revision 1.16 2000/06/01 06:31:10 neeri
// % Reset shutdown flags on connect, refine test for data available, fix memory leak in UDP sendto
// %
// % Revision 1.15 2000/05/23 07:13:19 neeri
// % Improve formatting, implement immediate close and sorrect linger handling
// %
// % Revision 1.14 2000/03/15 07:19:53 neeri
// % Fix numerous race conditions
// %
// % Revision 1.13 2000/03/06 06:10:01 neeri
// % Reorganize Yield()
// %
// % Revision 1.12 1999/12/14 06:28:29 neeri
// % Read pending data while closing
// %
// % Revision 1.11 1999/12/13 02:44:19 neeri
// % Fix SO_LINGER, read results for disconnected sockets
// %
// % Revision 1.10 1999/10/15 02:48:50 neeri
// % Make disconnects orderly
// %
// % Revision 1.9 1999/09/09 07:20:29 neeri
// % Fix numerous bugs, add support for interface ioctls
// %
// % Revision 1.8 1999/09/03 06:31:36 neeri
// % Needed more mopups
// %
// % Revision 1.7 1999/08/26 05:43:09 neeri
// % Supply missing Unbind
// %
// % Revision 1.6 1999/08/02 07:02:45 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.5 1999/07/19 06:17:44 neeri
// % Fix nonblocking connect
// %
// % Revision 1.4 1999/06/28 06:04:59 neeri
// % Support interrupted calls
// %
// % Revision 1.3 1999/05/30 03:06:41 neeri
// % MPW compiler compatibility, fix select for datagram sockets
// %
// % Revision 1.2 1999/04/29 05:33:19 neeri
// % Fix fcntl prototype
// %
// % Revision 1.1 1999/03/17 09:05:11 neeri
// % Added GUSITimer, expanded docs
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Open Transport socket infrastructure}
//
// A [[GUSIOTSocket]] defines a class of Open Transport sockets. Since most
// families differ only in a few details, like address representation, we
// abstract the typical differences in a strategy class [[GUSIOTStrategy]].
//
// <GUSIOpenTransport.h>=
#ifndef _GUSIOpenTransport_
#define _GUSIOpenTransport_
#ifdef GUSI_INTERNAL
#include "GUSISocket.h"
#include "GUSISocketMixins.h"
#include "GUSIFactory.h"
#include <netinet/in.h>
#include <netinet/tcp.h>
#undef O_ASYNC
#undef O_NDELAY
#undef O_NONBLOCK
#undef SIGHUP
#undef SIGURG
#undef AF_INET
#undef TCP_KEEPALIVE
#undef TCP_NODELAY
#undef TCP_MAXSEG
#include <OpenTransport.h>
#include <OpenTptInternet.h>
// \section{Definition of [[GUSIOTStrategy]]}
//
// A [[GUSIOTStrategy]] contains all the tricky parts of each Open Transport
// family.
//
// <Definition of class [[GUSIOTStrategy]]>=
class GUSIOTStrategy {
public:
// [[CreateConfiguration]] creates an appropriate [[OTConfiguration]]. This
// method is not virtual, as it relies on the strategy method
// [[ConfigPath]].
//
// <Strategic interfaces for [[GUSIOTStrategy]]>=
OTConfiguration * CreateConfiguration();
// [[PackAddress]] converts a socket address into an OT address, and
// [[UnpackAddress]] performs the reverse step. [[CopyAddress]] copies an address.
//
// <Strategic interfaces for [[GUSIOTStrategy]]>=
virtual int PackAddress(
const void * address, socklen_t len, TNetbuf & addr, bool non_null = false) = 0;
virtual int UnpackAddress(const TNetbuf & addr, void * address, socklen_t * len) = 0;
virtual int CopyAddress(const TNetbuf & from, TNetbuf & to);
// [[EndpointInfo]] returns a data structure storing endpoint parameters. We only
// need one copy per socket type.
//
// <Strategic interfaces for [[GUSIOTStrategy]]>=
TEndpointInfo * EndpointInfo() { return &fEndpointInfo; }
protected:
// <Privatissima of [[GUSIOTStrategy]]>=
virtual const char * ConfigPath() = 0;
// <Privatissima of [[GUSIOTStrategy]]>=
TEndpointInfo fEndpointInfo;
// \section{Implementation of [[GUSIOTStrategy]]}
//
// [[GUSIOTStrategy]] is mostly abstract, except for the [[CreateConfiguration]]
// and [[CopyAddress]] methods.
//
// <Privatissima of [[GUSIOTStrategy]]>=
OTConfiguration * fConfig;
GUSIOTStrategy() : fConfig(nil) {}
virtual ~GUSIOTStrategy();
};
// \section{Definition of [[GUSIOTFactory]] and descendants}
//
// A [[GUSIOTFactory]] is an abstract class combining a socket creation
// mechanism with a strategy instance. To clarify our intent, we isolate
// the latter in [[GUSIOTStrategy]].
//
// <Definition of class [[GUSIOTFactory]]>=
class GUSIOTFactory : public GUSISocketFactory {
public:
static bool Initialize();
protected:
virtual GUSIOTStrategy *Strategy(int domain, int type, int protocol) = 0;
private:
// \section{Implementation of [[GUSIOTFactory]] and descendants}
//
//
// <Privatissima of [[GUSIOTFactory]]>=
static bool sOK;
};
// <Definition of class [[GUSIOTStreamFactory]]>=
class GUSIOTStreamFactory : public GUSIOTFactory {
public:
GUSISocket * socket(int domain, int type, int protocol);
};
// <Definition of class [[GUSIOTDatagramFactory]]>=
class GUSIOTDatagramFactory : public GUSIOTFactory {
public:
GUSISocket * socket(int domain, int type, int protocol);
};
// \section{Definition of [[GUSIOT]]}
//
// Open Transport allocates and deallocates many data structures, which we
// simplify with a smart template. Allocation works via class allocation
// operators, which is a bit weird admittedly.
//
// <Definition of template [[GUSIOT]]>=
template <class T, int tag> class GUSIOT : public T {
public:
void * operator new(size_t, EndpointRef ref)
{ OSStatus err; return OTAlloc(ref, tag, T_ALL, &err); }
void * operator new(size_t, EndpointRef ref, int fields)
{ OSStatus err; return OTAlloc(ref, tag, fields, &err); }
void operator delete(void * o)
{ if (o) OTFree(o, tag); }
};
template <class T, int tag> class GUSIOTAddr : public GUSIOT<T, tag> {
public:
int Pack(GUSIOTStrategy * strategy, const void * address, socklen_t len, bool non_null=false)
{ return strategy->PackAddress(address, len, addr, non_null); }
int Unpack(GUSIOTStrategy * strategy, void * address, socklen_t * len)
{ return strategy->UnpackAddress(addr, address, len); }
int Copy(GUSIOTStrategy * strategy, GUSIOTAddr<T, tag> * to)
{ return strategy->CopyAddress(addr, to->addr); }
};
typedef GUSIOTAddr<TBind, T_BIND> GUSIOTTBind;
typedef GUSIOTAddr<TCall, T_CALL> GUSIOTTCall;
typedef GUSIOTAddr<TUnitData, T_UNITDATA> GUSIOTTUnitData;
typedef GUSIOTAddr<TUDErr, T_UDERROR> GUSIOTTUDErr;
typedef GUSIOT<TDiscon, T_DIS> GUSIOTTDiscon;
typedef GUSIOT<TOptMgmt, T_OPTMGMT> GUSIOTTOptMgmt;
// \section{Definition of [[GUSIOTSocket]] and descendants}
//
// Open Transport sockets are rather lightweight, since OT is rather similar
// to sockets already.
//
// <Definition of class [[GUSIOTSocket]]>=
class GUSIOTSocket :
public GUSISocket,
protected GUSISMBlocking,
protected GUSISMState,
protected GUSISMAsyncError
{
public:
// <Overridden member functions for [[GUSIOTSocket]]>=
virtual int bind(void * name, socklen_t namelen);
// [[getsockname]] and [[getpeername]] unpack the stored addresses.
// Note that the reaction to [[nil]] addresses is a bit different.
//
// <Overridden member functions for [[GUSIOTSocket]]>=
virtual int getsockname(void * name, socklen_t * namelen);
// [[shutdown]] just delegates to [[GUSISMState]].
//
// <Overridden member functions for [[GUSIOTSocket]]>=
virtual int shutdown(int how);
// [[fcntl]] handles the blocking support.
//
// <Overridden member functions for [[GUSIOTSocket]]>=
virtual int fcntl(int cmd, va_list arg);
// [[ioctl]] deals with blocking support and with [[FIONREAD]].
//
// <Overridden member functions for [[GUSIOTSocket]]>=
virtual int ioctl(unsigned int request, va_list arg);
// [[getsockopt]] and [[setsockopt]] are available for a variety of options.
//
// <Overridden member functions for [[GUSIOTSocket]]>=
virtual int getsockopt(int level, int optname, void *optval, socklen_t * optlen);
// <Overridden member functions for [[GUSIOTSocket]]>=
virtual int setsockopt(int level, int optname, void *optval, socklen_t optlen);
// Open Transport sockets implement socket style calls.
//
// <Overridden member functions for [[GUSIOTSocket]]>=
virtual bool Supports(ConfigOption config);
protected:
GUSIOTSocket(GUSIOTStrategy * strategy);
// \section{Implementation of [[GUSIOTSocket]]}
//
// Open Transport may call this routine for dozens and dozens of different
// reasons. Pretty much every call results in a wakeup of the threads attached
// to the socket. We save some of the more interesting events in bitsets.
// in [[MopupEvents]].
//
// <Privatissima of [[GUSIOTSocket]]>=
uint16_t fNewEvent;
uint16_t fCurEvent;
uint16_t fEvent;
uint32_t fNewCompletion;
uint32_t fCurCompletion;
uint32_t fCompletion;
friend pascal void GUSIOTNotify(GUSIOTSocket *, OTEventCode, OTResult, void *);
// To avoid race conditions with the notifier, we sometimes need a lock.
//
// <Privatissima of [[GUSIOTSocket]]>=
class Lock {
public:
Lock(EndpointRef end) : fEndpoint(end) { OTEnterNotifier(fEndpoint); }
~Lock() { OTLeaveNotifier(fEndpoint); }
private:
EndpointRef fEndpoint;
};
// For some events, we have to take a followup action at a more convenient time.
//
// <Privatissima of [[GUSIOTSocket]]>=
virtual void MopupEvents();
// [[GUSIOTSocket]] creates an asynchronous endpoint for the appropriate
// provider.
//
// <Privatissima of [[GUSIOTSocket]]>=
GUSIOTStrategy * fStrategy;
EndpointRef fEndpoint;
linger fLinger;
UInt32 fDeadline;
// The destructor tears down the connection as gracefully as possible. It also respects
// the linger settings.
//
// <Privatissima of [[GUSIOTSocket]]>=
virtual void close();
virtual ~GUSIOTSocket();
// [[Clone]] creates another socket of the same class.
//
// <Privatissima of [[GUSIOTSocket]]>=
virtual GUSIOTSocket * Clone() = 0;
// At the time the socket function [[bind]] is called, we are not really ready
// yet to call [[OTBind]], but if we don't call it, we can't report whether the
// address was free.
//
// <Privatissima of [[GUSIOTSocket]]>=
GUSIOTTBind * fSockName;
int BindToAddress(GUSIOTTBind * addr);
// Open Transport takes unbinding a lot more serious than MacTCP.
//
// <Privatissima of [[GUSIOTSocket]]>=
void Unbind();
friend class GUSIOTStreamSocket;
friend class GUSIOTDatagramSocket;
};
// <Definition of class [[GUSIOTStreamSocket]]>=
class GUSIOTStreamSocket : public GUSIOTSocket {
public:
// [[Clone]] creates another socket of the same class.
//
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual GUSIOTSocket * Clone();
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual void close();
virtual bool Close(UInt32 now);
~GUSIOTStreamSocket();
// Stream sockets include a mopup action for connect and disconnect.
//
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual void MopupEvents();
// [[listen]] is a bit embarassing, because we already committed ourselves
// to a queue length of [[0]], so we have to unbind and rebind ourselves.
//
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual int listen(int qlen);
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual int getpeername(void * name, socklen_t * namelen);
// [[accept]] may become quite complex, because connections could nest. The
// listening socket calls [[OTListen]], queues candidates by their
// [[fNextListener]] field, and then trys calling [[OTAccept]] on the first
// candidate.
//
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual GUSISocket * accept(void * address, socklen_t * addrlen);
// [[connect]] is comparatively simple.
//
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual int connect(void * address, socklen_t addrlen);
// Data transfer is simple as well. Here is the version for stream protocols.
//
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual ssize_t recvfrom(const GUSIScatterer & buffer, int flags, void * from, socklen_t * fromlen);
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual ssize_t sendto(const GUSIGatherer & buffer, int flags, const void * to, socklen_t tolen);
// [[select]] for stream sockets intermingles data information and connection
// information as usual.
//
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual bool select(bool * canRead, bool * canWrite, bool * except);
// [[shutdown]] for stream sockets has to send an orderly disconnect.
//
// <Overridden member functions for [[GUSIOTStreamSocket]]>=
virtual int shutdown(int how);
protected:
GUSIOTStreamSocket(GUSIOTStrategy * strategy);
// Since all we need to know is in the [[GUSIOTStrategy]], it often suffices
// simply to create a [[GUSIOTSocket]]. Stream and datagram sockets differ
// merely in the descendant they create.
//
// <Privatissima of [[GUSIOTStreamSocket]]>=
friend class GUSIOTStreamFactory;
// <Privatissima of [[GUSIOTStreamSocket]]>=
friend pascal void GUSIOTNotify(GUSIOTSocket *, OTEventCode, OTResult, void *);
// The peer address for a [[GUSIOTStreamSocket]] is stored in a [[GUSIOTTCall]]
// structure.
//
// <Privatissima of [[GUSIOTStreamSocket]]>=
GUSIOTTCall * fPeerName;
// <Privatissima of [[GUSIOTStreamSocket]]>=
GUSIOTStreamSocket * fNextListener;
};
// <Definition of class [[GUSIOTDatagramSocket]]>=
class GUSIOTDatagramSocket : public GUSIOTSocket {
public:
// [[Clone]] creates another socket of the same class.
//
// <Overridden member functions for [[GUSIOTDatagramSocket]]>=
virtual GUSIOTSocket * Clone();
// <Overridden member functions for [[GUSIOTDatagramSocket]]>=
~GUSIOTDatagramSocket();
// <Overridden member functions for [[GUSIOTDatagramSocket]]>=
virtual int getpeername(void * name, socklen_t * namelen);
// A datagram socket can [[connect]] as many times as it wants.
//
// <Overridden member functions for [[GUSIOTDatagramSocket]]>=
virtual int connect(void * address, socklen_t addrlen);
// Datagram protocols use slightly different calls for data transfers.
//
// <Overridden member functions for [[GUSIOTDatagramSocket]]>=
virtual ssize_t recvfrom(const GUSIScatterer & buffer, int flags, void * from, socklen_t * fromlen);
// [[sendto]] needs either a valid [[to]] address or a stored peer address set by
// [[connect]].
//
// <Overridden member functions for [[GUSIOTDatagramSocket]]>=
virtual ssize_t sendto(const GUSIGatherer & buffer, int flags, const void * to, socklen_t tolen);
// [[select]] for datagram sockets returns data information only.
//
// <Overridden member functions for [[GUSIOTDatagramSocket]]>=
virtual bool select(bool * canRead, bool * canWrite, bool * except);
protected:
GUSIOTDatagramSocket(GUSIOTStrategy * strategy);
// <Privatissima of [[GUSIOTDatagramSocket]]>=
friend class GUSIOTDatagramFactory;
// Datagram sockets might be bound at rather arbitrary times.
//
// <Privatissima of [[GUSIOTDatagramSocket]]>=
int BindIfUnbound();
// The peer address for a [[GUSIOTDatagramSocket]] is stored in a [[GUSIOTTBind]]
// structure.
//
// <Privatissima of [[GUSIOTDatagramSocket]]>=
GUSIOTTBind * fPeerName;
};
#endif /* GUSI_INTERNAL */
#endif /* _GUSIOpenTransport_ */

Просмотреть файл

@ -0,0 +1,115 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIPOSIX.nw - POSIX/Socket wrappers
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIPOSIX.h,v $
// % Revision 1.1 2001-03-11 22:37:38 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.22 2001/01/17 08:58:06 neeri
// % Releasing 2.1.4
// %
// % Revision 1.21 2000/10/29 18:36:32 neeri
// % Fix time_t signedness issues
// %
// % Revision 1.20 2000/10/16 04:34:23 neeri
// % Releasing 2.1.2
// %
// % Revision 1.19 2000/06/12 04:24:50 neeri
// % Fix time, localtime, gmtime
// %
// % Revision 1.18 2000/05/23 07:15:30 neeri
// % Improve formatting
// %
// % Revision 1.17 2000/03/06 08:18:25 neeri
// % Fix sleep, usleep, chdir; new Yield system
// %
// % Revision 1.16 2000/01/17 01:41:21 neeri
// % Fix rename() mangling
// %
// % Revision 1.15 1999/12/13 03:01:48 neeri
// % Another select() fix
// %
// % Revision 1.14 1999/11/15 07:22:34 neeri
// % Safe context setup. Fix sleep checking.
// %
// % Revision 1.13 1999/09/09 07:21:22 neeri
// % Add support for inet_aton
// %
// % Revision 1.12 1999/08/26 05:45:06 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.11 1999/07/19 06:21:03 neeri
// % Add mkdir/rmdir, fix various file manager related bugs
// %
// % Revision 1.10 1999/07/07 04:17:42 neeri
// % Final tweaks for 2.0b3
// %
// % Revision 1.9 1999/06/28 06:04:59 neeri
// % Support interrupted calls
// %
// % Revision 1.8 1999/05/30 03:09:31 neeri
// % Added support for MPW compilers
// %
// % Revision 1.7 1999/04/29 05:33:18 neeri
// % Fix fcntl prototype
// %
// % Revision 1.6 1999/03/29 09:51:29 neeri
// % New configuration system with support for hardcoded configurations.
// %
// % Revision 1.5 1999/03/17 09:05:11 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.4 1998/10/25 11:35:19 neeri
// % chdir, getcwd, setxxxent
// %
// % Revision 1.3 1998/10/11 16:45:22 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.2 1998/08/01 21:32:09 neeri
// % About ready for 2.0a1
// %
// % Revision 1.1 1998/01/25 21:02:49 neeri
// % Engine implemented, except for signals & scheduling
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{POSIX/Socket Wrappers}
//
// Now everything is in place to define the POSIX and socket routines
// themselves. As opposed to our usual practice, we don't declare the
// exported routines here, as they all have been declared in [[unistd.h]]
// or [[sys/socket.h]] already. The exceptions are [[remove]] and [[rename]],
// which are declared in [[stdio.h]], which we'd rather not include, and
// various calls which are not consistently declared.
//
// <GUSIPOSIX.h>=
#ifndef _GUSIPOSIX_
#define _GUSIPOSIX_
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <utime.h>
#include <netdb.h>
#include <arpa/inet.h>
__BEGIN_DECLS
int remove(const char * path);
int rename(const char *oldname, const char *newname);
int fgetfileinfo(const char * path, OSType * creator, OSType * type);
void fsetfileinfo(const char * path, OSType creator, OSType type);
time_t time(time_t * timer);
struct tm * localtime(const time_t * timer);
struct tm * gmtime(const time_t * timer);
time_t mktime(struct tm *timeptr);
__END_DECLS
#endif /* _GUSIPOSIX_ */

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,88 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIPipe.nw - Pipes
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSIPipe.h,v $
// % Revision 1.1 2001-03-11 22:37:35 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.12 2000/05/23 07:18:03 neeri
// % Improve formatting
// %
// % Revision 1.11 2000/03/06 06:09:59 neeri
// % Reorganize Yield()
// %
// % Revision 1.10 1999/11/15 07:20:59 neeri
// % Add GUSIwithLocalSockets
// %
// % Revision 1.9 1999/08/26 05:45:07 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.8 1999/06/28 06:05:00 neeri
// % Support interrupted calls
// %
// % Revision 1.7 1999/05/29 06:26:45 neeri
// % Fixed header guards
// %
// % Revision 1.6 1999/03/17 09:05:12 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.5 1998/11/22 23:07:00 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.4 1998/10/25 11:57:38 neeri
// % Ready to release 2.0a3
// %
// % Revision 1.3 1998/01/25 20:53:57 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.2 1996/12/22 19:57:58 neeri
// % TCP streams work
// %
// % Revision 1.1 1996/11/24 12:52:08 neeri
// % Added GUSIPipeSockets
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{The GUSI Pipe Socket Class}
//
// Pipes and socket pairs are implemented with the [[GUSIPipeSocket]] class.
// The [[GUSIPipeFactory]] singleton creates pairs of [[GUSIPipeSockets]].
//
// <GUSIPipe.h>=
#ifndef _GUSIPipe_
#define _GUSIPipe_
#ifdef GUSI_INTERNAL
#include "GUSISocket.h"
#include "GUSIFactory.h"
// \section{Definition of [[GUSIPipeFactory]]}
//
// [[GUSIPipeFactory]] is a singleton subclass of [[GUSISocketFactory]].
//
// <Definition of class [[GUSIPipeFactory]]>=
class GUSIPipeFactory : public GUSISocketFactory {
public:
static GUSISocketFactory * Instance();
virtual GUSISocket * socket(int domain, int type, int protocol);
virtual int socketpair(int domain, int type, int protocol, GUSISocket * s[2]);
private:
GUSIPipeFactory() {}
static GUSISocketFactory * sInstance;
};
// <Inline member functions for class [[GUSIPipeFactory]]>=
inline GUSISocketFactory * GUSIPipeFactory::Instance()
{
if (!sInstance)
sInstance = new GUSIPipeFactory;
return sInstance;
}
#endif /* GUSI_INTERNAL */
#endif /* _GUSIPipe_ */

Просмотреть файл

@ -0,0 +1,48 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSISIOUX.nw - SIOUX Support
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSISIOUX.h,v $
// % Revision 1.1 2001-03-11 22:38:08 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.8 2000/05/23 07:18:03 neeri
// % Improve formatting
// %
// % Revision 1.7 2000/03/06 06:03:29 neeri
// % Check device families for file paths
// %
// % Revision 1.6 1999/08/26 05:45:08 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.5 1999/06/08 04:31:30 neeri
// % Getting ready for 2.0b2
// %
// % Revision 1.4 1999/05/29 06:26:45 neeri
// % Fixed header guards
// %
// % Revision 1.3 1999/03/17 09:05:12 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.2 1998/11/22 23:07:01 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.1 1998/10/25 11:57:39 neeri
// % Ready to release 2.0a3
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{SIOUX Support}
//
// To combine GUSI with SIOUX, terminal I/O needs to interface with the SIOUX
// event handling.
//
// SIOUX support is installed implicitly through [[GUSISetupConsoleDescriptors]]
//
// <GUSISIOUX.h>=
#ifndef _GUSISIOUX_
#define _GUSISIOUX_
#endif /* _GUSISIOUX_ */

Просмотреть файл

@ -0,0 +1,27 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSISIOW.nw - SIOW Interface
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSISIOW.h,v $
// % Revision 1.1 2001-03-11 22:38:11 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.2 1999/08/26 05:45:08 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.1 1999/07/19 06:17:08 neeri
// % Add SIOW support
// %
//
// \chapter{SIOW Support}
//
// SIOW support is based on MPW support, adding a few event hooks so update and activate events
// get handled during blocking calls. SIOW support is installed implecitly through [[GUSIDefaultSetupConsole]].
//
// <GUSISIOW.h>=
#ifndef _GUSISIOW_
#define _GUSISIOW_
#endif /* _GUSISIOW_ */

Просмотреть файл

@ -0,0 +1,149 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSISignal.nw - Signal engine
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSISignal.h,v $
// % Revision 1.1 2001-03-11 22:38:04 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.7 2000/10/16 04:08:51 neeri
// % Add binary compatibility for CW SIGINT
// %
// % Revision 1.6 2000/05/23 07:18:03 neeri
// % Improve formatting
// %
// % Revision 1.5 2000/03/15 07:22:07 neeri
// % Enforce alignment choices
// %
// % Revision 1.4 1999/12/13 03:07:25 neeri
// % Releasing 2.0.2
// %
// % Revision 1.3 1999/11/15 07:20:18 neeri
// % Safe context setup
// %
// % Revision 1.2 1999/08/26 05:45:09 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.1 1999/06/30 07:42:07 neeri
// % Getting ready to release 2.0b3
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Signal support}
//
// We support signals in the half assed way characteristic for GUSI's approach to
// asynchronous issues: Delivery is very much synchronous, basically within [[Yield]]
// calls. Signal handling behavior is encapsulated in the classes [[GUSISigContext]] and
// [[GUSISigProcess]] whose instances are manufactured by a [[GUSISigFactory]].
//
// <GUSISignal.h>=
#ifndef _GUSISIGNAL_
#define _GUSISIGNAL_
#include <signal.h>
#ifdef GUSI_SOURCE
#include <ConditionalMacros.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// \section{Definition of the signal handling engine}
//
// A [[GUSISigProcess]] contains the per-process signal state. [[GetAction]] and [[SetAction]] manipulate the
// action associated with a signal, [[Pending]] returns the set of pending signals, [[Post]] marks a signal
// as pending (but possibly blocked), and [[Raise]] executes a signal (which we have determined is not
// blocked).
//
// <Definition of class [[GUSISigProcess]]>=
class GUSISigContext;
class GUSISigProcess {
public:
virtual struct sigaction & GetAction(int sig);
virtual int SetAction(int sig, const struct sigaction & act);
virtual sigset_t Pending() const;
virtual void ClearPending(sigset_t clear);
virtual void Post(int sig);
virtual bool Raise(int sig, GUSISigContext * context);
virtual ~GUSISigProcess();
protected:
// [[GUSISigProcess]] stores the signal handlers and the set of signals pending against the process.
//
// <Privatissima of [[GUSISigProcess]]>=
sigset_t fPending;
struct sigaction fAction[NSIG-1];
// Some actions can't be caught and/or ignored. [[CantCatch]] and [[CantIgnore]] report those.
//
// <Privatissima of [[GUSISigProcess]]>=
virtual bool CantCatch(int sig);
virtual bool CantIgnore(int sig);
// The default behavior for many signals is to abort the process.
//
// <Privatissima of [[GUSISigProcess]]>=
virtual bool DefaultAction(int sig, const struct sigaction & act);
friend class GUSISigFactory;
GUSISigProcess();
};
// A [[GUSISigContext]] contains the per-thread signal state, primarily blocking info. To support
// [[pthread_kill]], we have out own set of pending signals. [[GetBlocked]] and [[SetBlocked]] manipulate
// the set of blocking signals, [[Pending]] returns the set of pending signals, [[Post]] marks a
// signal as pending (but possibly blocked), and [[Raise]] executes all eligible signals.
//
// <Definition of class [[GUSISigContext]]>=
class GUSISigContext {
public:
virtual sigset_t GetBlocked() const;
virtual void SetBlocked(sigset_t sigs);
virtual sigset_t Pending() const;
virtual sigset_t Pending(GUSISigProcess * proc) const;
virtual void ClearPending(sigset_t clear);
virtual void Post(int sig);
virtual sigset_t Ready(GUSISigProcess * proc);
virtual bool Raise(GUSISigProcess * proc, bool allSigs = false);
virtual ~GUSISigContext();
protected:
// [[GUSISigContext]] mainly deals with a set of blocked signals, which it inherits from its parent.
//
// <Privatissima of [[GUSISigContext]]>=
sigset_t fPending;
sigset_t fBlocked;
// Many signals cannot be blocked. [[CantBlock]] defines those.
//
// <Privatissima of [[GUSISigContext]]>=
virtual sigset_t CantBlock();
friend class GUSISigFactory;
GUSISigContext(const GUSISigContext * parent);
};
// The [[GUSISigFactory]] singleton creates the above two classes, allowing a future extension to
// handle more signals.
//
// <Definition of class [[GUSISigFactory]]>=
class GUSISigFactory {
public:
virtual GUSISigProcess * CreateSigProcess();
virtual GUSISigContext * CreateSigContext(const GUSISigContext * parent);
virtual ~GUSISigFactory();
static GUSISigFactory * Instance();
static void SetInstance(GUSISigFactory * instance);
protected:
GUSISigFactory() {}
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
#endif
#endif /* _GUSISIGNAL_ */

Просмотреть файл

@ -0,0 +1,362 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSISocket.nw - The socket class
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSISocket.h,v $
// % Revision 1.1 2001-03-11 22:38:15 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.18 2000/10/16 04:34:23 neeri
// % Releasing 2.1.2
// %
// % Revision 1.17 2000/05/23 07:19:34 neeri
// % Improve formatting, add close queue
// %
// % Revision 1.16 2000/03/15 07:20:53 neeri
// % Add GUSISocket::AddContextInScope
// %
// % Revision 1.15 1999/10/15 02:48:51 neeri
// % Make disconnects orderly
// %
// % Revision 1.14 1999/09/26 03:59:26 neeri
// % Releasing 2.0fc1
// %
// % Revision 1.13 1999/08/26 05:45:09 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.12 1999/06/08 04:31:31 neeri
// % Getting ready for 2.0b2
// %
// % Revision 1.11 1999/05/29 06:26:45 neeri
// % Fixed header guards
// %
// % Revision 1.10 1999/04/29 05:33:18 neeri
// % Fix fcntl prototype
// %
// % Revision 1.9 1999/03/17 09:05:13 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.8 1998/11/22 23:07:01 neeri
// % Releasing 2.0a4 in a hurry
// %
// % Revision 1.7 1998/10/11 16:45:23 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.6 1998/08/01 21:29:53 neeri
// % Use context queues
// %
// % Revision 1.5 1998/01/25 20:53:58 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.4 1997/11/13 21:12:12 neeri
// % Fall 1997
// %
// % Revision 1.3 1996/11/24 13:00:28 neeri
// % Fix comment leaders
// %
// % Revision 1.2 1996/11/24 12:52:09 neeri
// % Added GUSIPipeSockets
// %
// % Revision 1.1.1.1 1996/11/03 02:43:32 neeri
// % Imported into CVS
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{The GUSI Socket Class}
//
// GUSI is constructed around the [[GUSISocket]] class. This class is
// mostly an abstract superclass, but all virtual procedures are implemented
// to return sensible error codes.
//
// <GUSISocket.h>=
#ifndef _GUSISocket_
#define _GUSISocket_
#ifdef GUSI_SOURCE
#include "GUSIBasics.h"
#include "GUSIContext.h"
#include "GUSIContextQueue.h"
#include "GUSIBuffer.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <stdarg.h>
#include <ConditionalMacros.h>
#include <LowMem.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// \section{Definition of [[GUSISocket]]}
//
// [[GUSISocket]] consists of a few maintenance functions and the socket operations.
// Each operation consists to a POSIX/BSD function with the file descriptor operand
// left out.
//
// <Definition of class [[GUSISocket]]>=
class GUSISocket {
// Since a single [[GUSISocket]] may (through [[dup]]) be installed multiply
// in a descriptor table or even in multiple descriptor tables, [[GUSISocket]]s
// are not destroyed directly, but by manipulating a reference count. As soon
// as the reference count hits zero, the destructor (which, of course, should
// probably be overridden) is called.
//
// Since destructors cannot call virtual functions, we call [[close]] which
// eventually calls the destructor. Some socket types can take quite long to close
// under unfavorable circumstances. To speed up the process, we have the option of
// queueing the socket up and regularly having [[Close]] called on it.
//
// <Reference counting for [[GUSISocket]]>=
public:
void AddReference();
void RemoveReference();
virtual void close();
void CheckClose(UInt32 now = LMGetTicks());
protected:
GUSISocket();
virtual ~GUSISocket();
virtual bool Close(UInt32 now = LMGetTicks());
private:
u_long fRefCount;
// [[GUSIContext]]s are defined in {\tt GUSIBasics}. A context references all
// information you need in a completion procedure: The contents of [[A5]],
// the process ID, and thread information. [[Wakeup]] wakes up the threads
// and/or processes associated with the socket and is guaranteed to work even
// at interrupt level. [[AddContext]] adds another context. [[RemoveContext]]
// indicates that this context no longer should be woken up when something happens.
// To keep a context added inside a scope, declare an automatic object of class
// [[AddContextInScope]].
//
// <Context links for [[GUSISocket]]>=
public:
void Wakeup();
void AddContext(GUSIContext * context = nil);
void RemoveContext(GUSIContext * context = nil);
class AddContextInScope {
public:
AddContextInScope(GUSISocket * sock, GUSIContext * context = nil)
: fSocket(sock), fContext(context)
{ fSocket->AddContext(fContext); }
~AddContextInScope() { fSocket->RemoveContext(fContext); }
private:
GUSISocket * fSocket;
GUSIContext * fContext;
};
private:
GUSIContextQueue fContexts;
// There may be various reasons to keep sockets in queue. Currently the
// only reason is to queue up dying sockets.
//
// <Queue management for [[GUSISocket]]>=
public:
void Enqueue(GUSISocket ** queue);
void Dequeue();
private:
GUSISocket ** fQueue;
GUSISocket * fNextSocket;
GUSISocket * fPrevSocket;
// Both read and write calls on sockets come in five different variants:
//
// \begin{enumerate}
// \item [[read]] and [[write]]
// \item [[recv]] and [[send]]
// \item [[readv]] and [[writev]]
// \item [[recvfrom]] and [[sendto]]
// \item [[recvmsg]] and [[sendmsg]]
// \end{enumerate}
//
// GUSI initially maps variants 3 and 5 of these calls to the [[recvmsg]] and
// [[sendmsg]] member functions, variants 2 and 4 to the [[recvfrom]] and
// [[sendto]] member functions, and variant 1 to the [[read]] and
// [[write]] member functions.
//
// The simpler member functions can always be translated into the complex member
// functions, and under some circumstances, the opposite is also possible.
// To avoid translation loops, the translation routines (i.e., the default
// implementation of [[GUSISocket::read]] and [[GUSISocket::recvmsg]]
// check for the availablility of the other function by calling [[Supports]].
// This member function must be overridden for any reasonable socket class.
//
// <Configuration options for [[GUSISocket]]>=
protected:
enum ConfigOption {
kSimpleCalls, // [[read]], [[write]]
kSocketCalls, // [[recvfrom]], [[sendto]]
kMsgCalls // [[recvmsg]], [[sendmsg]]
};
virtual bool Supports(ConfigOption config);
public:
// Most sockets have names, which to [[GUSISocket]] are just opaque blocks of
// memory. A name for a socket is established (before the socket is actually
// used, of course) through [[bind]]. The name may be queried with
// [[getsockname]] and once the socket is connected, the name of the peer
// endpoint may be queried with [[getpeername]].
//
// <Socket name management for [[GUSISocket]]>=
virtual int bind(void * name, socklen_t namelen);
virtual int getsockname(void * name, socklen_t * namelen);
virtual int getpeername(void * name, socklen_t * namelen);
// Sockets follow either a virtual circuit model where all data is exchanged
// with the same peer throughout the lifetime of the connection, or a datagram
// model where potentially every message is exchanged with a different peer.
//
// The vast majority of protocols follow the virtual circuit model. The server
// end, typically after calling [[bind]] to attach the socket to a well known
// address, calls [[listen]] to establish its willingness to accept connections.
// [[listen]] takes a queue length parameter, which however is ignored for many
// types of sockets.
//
// Incoming connections are then accepted by calling [[accept]]. When [[accept]]
// is successful, it always returns a new [[GUSISocket]], while the original socket
// remains available for further connections. To avoid blocking on [[accept]], you may poll for connections with an
// [[accept()] call in nonblocking mode or query the result of [[select]] whether
// the socket is ready for reading.
//
// The client end in the virtual circuit model connects itself to the well known
// address by calling [[connect]]. To avoid blocking on [[connect]], you may
// call it in nonblocking mode and then query the result of [[select]] whether
// the socket is ready for writing.
//
// In the datagram model, you don't need to establish connections. You may call
// [[connect]] anyway to temporarily establish a virtual circuit.
//
// <Connection establishment for [[GUSISocket]]>=
virtual int listen(int qlen);
virtual GUSISocket * accept(void * address, socklen_t * addrlen);
virtual int connect(void * address, socklen_t addrlen);
// As mentioned before, there are three variants each for reading and writing.
// The socket variants provide a means to pass a peer address for the datagram
// model, while the msg variants also provides fields for passing access rights,
// which is, however not currently supported in GUSI. As syntactic sugar, the more
// traditional flavors with [[buffer]]/[[length]] buffers are also supported.
//
// <Sending and receiving data for [[GUSISocket]]>=
virtual ssize_t read(const GUSIScatterer & buffer);
virtual ssize_t write(const GUSIGatherer & buffer);
virtual ssize_t recvfrom(
const GUSIScatterer & buffer, int flags, void * from, socklen_t * fromlen);
virtual ssize_t sendto(
const GUSIGatherer & buffer, int flags, const void * to, socklen_t tolen);
virtual ssize_t recvmsg(msghdr * msg, int flags);
virtual ssize_t sendmsg(const msghdr * msg, int flags);
ssize_t read(void * buffer, size_t length);
ssize_t write(const void * buffer, size_t length);
ssize_t recvfrom(
void * buffer, size_t length, int flags, void * from, socklen_t * fromlen);
ssize_t sendto(
const void * buffer, size_t length, int flags, const void * to, socklen_t tolen);
// A multitude of parameters can be manipulated for a [[GUSISocket]] through
// the socket oriented calls [[getsockopt]], [[setsockopt]], the file oriented
// call [[fcntl]], and the device oriented call [[ioctl]].
//
// [[isatty]] returns whether the socket should be considered an interactive
// console.
//
// <Maintaining properties for [[GUSISocket]]>=
virtual int getsockopt(int level, int optname, void *optval, socklen_t * optlen);
virtual int setsockopt(int level, int optname, void *optval, socklen_t optlen);
virtual int fcntl(int cmd, va_list arg);
virtual int ioctl(unsigned int request, va_list arg);
virtual int isatty();
// Three of the operations make sense primarily for files, and most other socket
// types accept the default implementations. [[fstat]] returns information about
// an open file, [[lseek]] repositions the read/write pointer, and [[ftruncate]]
// cuts off an open file at a certain point.
//
// <File oriented operations for [[GUSISocket]]>=
virtual int fstat(struct stat * buf);
virtual off_t lseek(off_t offset, int whence);
virtual int ftruncate(off_t offset);
// [[select]] polls or waits for one of a group of [[GUSISocket]] to become
// ready for reading, writing, or for an exceptional condition to occur.
// First, [[pre_select]] is called once for all [[GUSISocket]]s in the group.
// It returns [[true]] is the socket will wake up as soon as one of the events
// occurs and [[false]] if GUSI needs to poll.
// Next, [[select]] is called for all [[GUSISocket]]s once or multiple times,
// until a condition becomes true or the call times out. Finally, [[post_select]]
// is called for all members of the group.
//
// <Multiplexing for [[GUSISocket]]>=
virtual bool pre_select(bool wantRead, bool wantWrite, bool wantExcept);
virtual bool select(bool * canRead, bool * canWrite, bool * exception);
virtual void post_select(bool wantRead, bool wantWrite, bool wantExcept);
// A socket connection is usually full duplex. By calling [[shutdown(1)]], you
// indicate that you won't write any more data on this socket. The values 0 (no
// more reads) and 2 (no more read/write) are used less frequently.
//
// <Miscellaneous operations for [[GUSISocket]]>=
virtual int shutdown(int how);
// Some socket types do not write out data immediately. Calling [[fsync]] guarantees
// that all data is written.
//
// <Miscellaneous operations for [[GUSISocket]]>=
virtual int fsync();
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
// \section{Implementation of [[GUSISocket]]}
//
// \subsection{General socket management}
//
//
// <Inline member functions for class [[GUSISocket]]>=
inline void GUSISocket::AddReference()
{
++fRefCount;
}
inline void GUSISocket::RemoveReference()
{
if (!--fRefCount)
close();
}
// \subsection{Context management}
//
//
// <Inline member functions for class [[GUSISocket]]>=
inline void GUSISocket::Wakeup()
{
fContexts.Wakeup();
}
// The traditional flavors of the I/O calls are translated to the scatterer/gatherer
// variants.
//
// <Inline member functions for class [[GUSISocket]]>=
inline ssize_t GUSISocket::read(void * buffer, size_t length)
{
return read(GUSIScatterer(buffer, length));
}
inline ssize_t GUSISocket::write(const void * buffer, size_t length)
{
return write(GUSIGatherer(buffer, length));
}
inline ssize_t GUSISocket::recvfrom(
void * buffer, size_t length, int flags, void * from, socklen_t * fromlen)
{
return recvfrom(GUSIScatterer(buffer, length), flags, from, fromlen);
}
inline ssize_t GUSISocket::sendto(
const void * buffer, size_t length, int flags, const void * to, socklen_t tolen)
{
return sendto(GUSIGatherer(buffer, length), flags, to, tolen);
}
#endif /* GUSI_SOURCE */
#endif /* _GUSISocket_ */

Просмотреть файл

@ -0,0 +1,360 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSISocketMixins.nw - Useful building blocks
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSISocketMixins.h,v $
// % Revision 1.1 2001-03-11 22:38:21 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.11 2000/10/16 04:10:12 neeri
// % Add GUSISMProcess
// %
// % Revision 1.10 2000/05/23 07:24:58 neeri
// % Improve formatting
// %
// % Revision 1.9 1999/08/26 05:45:09 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.8 1999/08/02 07:02:46 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.7 1999/05/29 06:26:45 neeri
// % Fixed header guards
// %
// % Revision 1.6 1999/04/29 05:33:18 neeri
// % Fix fcntl prototype
// %
// % Revision 1.5 1999/03/17 09:05:13 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.4 1998/10/11 16:45:24 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.3 1998/01/25 20:53:59 neeri
// % Engine implemented, except for signals & scheduling
// %
// % Revision 1.2 1997/11/13 21:12:13 neeri
// % Fall 1997
// %
// % Revision 1.1 1996/12/16 02:12:42 neeri
// % TCP Sockets sort of work
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Mixin Classes for Sockets}
//
// This section contains some building block classes for sockets:
//
// \begin{itemize}
// \item [[GUSISMBlocking]] implements the blocking/nonblocking flag.
// \item [[GUSISMState]] implements a state variable.
// \item [[GUSISMInputBuffer]] provides a [[GUSIBuffer]] for input.
// \item [[GUSISMOutputBuffer]] provides a [[GUSIBuffer]] for output.
// \item [[GUSISMAsyncError]] provides storage for asynchronous errors.
// \item [[GUSISMProcess]] maintains a link to the process instance.
// \end{itemize}
//
//
// <GUSISocketMixins.h>=
#ifndef _GUSISocketMixins_
#define _GUSISocketMixins_
#ifdef GUSI_INTERNAL
#include "GUSISocket.h"
#include "GUSIBuffer.h"
#include <fcntl.h>
#include <sys/ioctl.h>
// \section{Definition of [[GUSISocketMixins]]}
//
// [[GUSISMBlocking]] implements the [[fBlocking]] flags and the [[DoIoctl]] and
// [[DoFcntl]] variants to manipulate it. These two functions work like their
// [[GUSISocket]] member function counterparts, but handle the return value
// differently: The POSIX function result is stored in [[*result]], while the
// return value indicates whether the request was handled.
//
// <Definition of class [[GUSISMBlocking]]>=
class GUSISMBlocking {
public:
GUSISMBlocking();
bool fBlocking;
bool DoFcntl(int * result, int cmd, va_list arg);
bool DoIoctl(int * result, unsigned int request, va_list arg);
};
// [[GUSISMState]] captures the state of a socket over its lifetime. It starts out
// as [[Unbound]]. [[bind]] will put it into [[Unconnected]] state, though few
// socket classes care about this distinction. [[listen]] will put it into
// [[Listening]] state. [[accept]] starts a [[Connected]] new socket.
// [[connect]] puts an [[Unconnected]] socket into [[Connecting]] state from
// where it emerges [[Connected]]. [[fReadShutdown]] and [[fWriteShutdown]] record
// shutdown promises.
//
// <Definition of class [[GUSISMState]]>=
class GUSISMState {
public:
enum State {
Unbound,
Unconnected,
Listening,
Connecting,
Connected,
Closing
};
GUSISMState();
State fState;
bool fReadShutdown;
bool fWriteShutdown;
void Shutdown(int how);
};
// [[GUSISMInputBuffer]] defines the input buffer and some socket options that go
// with it. [[DoGetSockOpt]] and [[DoSetSockOpt]] work the same way as
// [[DoFcntl]] and [[DoIoctl]] above.
//
// <Definition of class [[GUSISMInputBuffer]]>=
class GUSISMInputBuffer {
public:
GUSIRingBuffer fInputBuffer;
GUSISMInputBuffer();
bool DoGetSockOpt(
int * result, int level, int optname,
void *optval, socklen_t * optlen);
bool DoSetSockOpt(
int * result, int level, int optname,
void *optval, socklen_t optlen);
bool DoIoctl(int * result, unsigned int request, va_list arg);
};
// [[GUSISMOutputBuffer]] defines the output buffer and some socket options that go
// with it.
//
// <Definition of class [[GUSISMOutputBuffer]]>=
class GUSISMOutputBuffer {
public:
GUSIRingBuffer fOutputBuffer;
GUSISMOutputBuffer();
bool DoGetSockOpt(
int * result, int level, int optname,
void *optval, socklen_t * optlen);
bool DoSetSockOpt(
int * result, int level, int optname,
void *optval, socklen_t optlen);
};
// [[GUSISMAsyncError]] stores asynchronous errors and makes them available via
// [[getsockopt]]. [[GetAsyncError]] returns the error and resets the stored value.
//
// <Definition of class [[GUSISMAsyncError]]>=
class GUSISMAsyncError {
public:
GUSISMAsyncError();
int fAsyncError;
int SetAsyncPosixError(int error);
int SetAsyncMacError(OSErr error);
int GetAsyncError();
bool DoGetSockOpt(
int * result, int level, int optname,
void *optval, socklen_t * optlen);
};
// [[GUSISMProcess]] stores a link to the global [[GUSIProcess]] instance, which is useful for completion routines.
//
// <Definition of class [[GUSISMProcess]]>=
class GUSISMProcess {
public:
GUSISMProcess();
GUSIProcess * Process();
private:
GUSIProcess * fProcess;
};
// \section{Implementation of [[GUSISocketMixins]]}
//
// Because all the member functions are simple and called in few places, it
// makes sense to inline them.
//
// All sockets start out blocking.
//
// <Inline member functions for class [[GUSISMBlocking]]>=
inline GUSISMBlocking::GUSISMBlocking() : fBlocking(true) {}
// For historical reasons, there is both an [[ioctl]] and a [[fcntl]] interface
// to the blocking flag.
//
// <Inline member functions for class [[GUSISMBlocking]]>=
inline bool GUSISMBlocking::DoFcntl(int * result, int cmd, va_list arg)
{
switch(cmd) {
case F_GETFL :
return (*result = fBlocking ? 0: FNDELAY), true;
case F_SETFL :
fBlocking = !(va_arg(arg, int) & FNDELAY);
return (*result = 0), true;
}
return false;
}
inline bool GUSISMBlocking::DoIoctl(int * result, unsigned int request, va_list arg)
{
if (request == FIONBIO) {
fBlocking = !*va_arg(arg, int *);
return (*result = 0), true;
}
return false;
}
// Sockets start out as unconnected.
//
// <Inline member functions for class [[GUSISMState]]>=
inline GUSISMState::GUSISMState() :
fState(Unbound), fReadShutdown(false), fWriteShutdown(false) {}
// <Inline member functions for class [[GUSISMState]]>=
inline void GUSISMState::Shutdown(int how)
{
if (!(how & 1))
fReadShutdown = true;
if (how > 0)
fWriteShutdown = true;
}
// Buffers initially are 8K.
//
// <Inline member functions for class [[GUSISMInputBuffer]]>=
inline GUSISMInputBuffer::GUSISMInputBuffer() : fInputBuffer(8192) {}
// [[getsockopt]] is used to obtain the buffer size.
//
// <Inline member functions for class [[GUSISMInputBuffer]]>=
inline bool GUSISMInputBuffer::DoGetSockOpt(
int * result, int level, int optname,
void *optval, socklen_t *)
{
if (level == SOL_SOCKET && optname == SO_RCVBUF) {
*(int *)optval = (int)fInputBuffer.Size();
return (*result = 0), true;
}
return false;
}
// [[setsockopt]] modifies the buffer size.
//
// <Inline member functions for class [[GUSISMInputBuffer]]>=
inline bool GUSISMInputBuffer::DoSetSockOpt(
int * result, int level, int optname,
void *optval, socklen_t)
{
if (level == SOL_SOCKET && optname == SO_RCVBUF) {
fInputBuffer.SwitchBuffer(*(int *)optval);
return (*result = 0), true;
}
return false;
}
// [[ioctl]] returns the number of available bytes.
//
// <Inline member functions for class [[GUSISMInputBuffer]]>=
inline bool GUSISMInputBuffer::DoIoctl(int * result, unsigned int request, va_list arg)
{
if (request == FIONREAD) {
*va_arg(arg, long *) = fInputBuffer.Valid();
return (*result = 0), true;
}
return false;
}
// [[GUSISMOutputBuffer]] works identically to the input buffer.
//
// <Inline member functions for class [[GUSISMOutputBuffer]]>=
inline GUSISMOutputBuffer::GUSISMOutputBuffer() : fOutputBuffer(8192) {}
// [[getsockopt]] is used to obtain the buffer size.
//
// <Inline member functions for class [[GUSISMOutputBuffer]]>=
inline bool GUSISMOutputBuffer::DoGetSockOpt(
int * result, int level, int optname,
void *optval, socklen_t *)
{
if (level == SOL_SOCKET && optname == SO_SNDBUF) {
*(int *)optval = (int)fOutputBuffer.Size();
return (*result = 0), true;
}
return false;
}
// [[setsockopt]] is modifies the buffer size.
//
// <Inline member functions for class [[GUSISMOutputBuffer]]>=
inline bool GUSISMOutputBuffer::DoSetSockOpt(
int * result, int level, int optname,
void *optval, socklen_t)
{
if (level == SOL_SOCKET && optname == SO_SNDBUF) {
fOutputBuffer.SwitchBuffer(*(int *)optval);
return (*result = 0), true;
}
return false;
}
// <Inline member functions for class [[GUSISMAsyncError]]>=
inline GUSISMAsyncError::GUSISMAsyncError()
: fAsyncError(0)
{
}
// The central member functions of [[GUSISMAsyncError]] are [[SetAsyncXXXError]] and
// [[GetAsyncError]].
//
// <Inline member functions for class [[GUSISMAsyncError]]>=
inline int GUSISMAsyncError::SetAsyncPosixError(int error)
{
if (error) {
fAsyncError = error;
GUSI_MESSAGE(("GUSISMAsyncError::SetAsyncPosixError %d\n", fAsyncError));
return -1;
}
return 0;
}
inline int GUSISMAsyncError::GetAsyncError()
{
int err = fAsyncError;
fAsyncError = 0;
return err;
}
// For some reason, the CW Pro 4 compilers generated bad code for this in some combination, so
// we make it out of line.
//
// <Inline member functions for class [[GUSISMAsyncError]]>=
inline int GUSISMAsyncError::SetAsyncMacError(OSErr error)
{
if (error) {
fAsyncError = GUSIMapMacError(error);
GUSI_MESSAGE(("GUSISMAsyncError::SetAsyncMacError %d -> %d\n", error, fAsyncError));
return -1;
}
return 0;
}
// [[DoGetSockOpt]] only handles [[SO_ERROR]] (hi Philippe!).
//
// <Inline member functions for class [[GUSISMAsyncError]]>=
inline bool GUSISMAsyncError::DoGetSockOpt(
int * result, int level, int optname,
void *optval, socklen_t * optlen)
{
if (level == SOL_SOCKET && optname == SO_ERROR) {
*(int *)optval = GetAsyncError();
*optlen = sizeof(int);
return (*result = 0), true;
}
return false;
}
// <Inline member functions for class [[GUSISMProcess]]>=
inline GUSISMProcess::GUSISMProcess()
: fProcess(GUSIProcess::Instance())
{
}
inline GUSIProcess * GUSISMProcess::Process()
{
return fProcess;
}
#endif /* GUSI_INTERNAL */
#endif /* _GUSISocketMixins_ */

Просмотреть файл

@ -0,0 +1,186 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSISpecific.nw - Thread specific variables
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSISpecific.h,v $
// % Revision 1.1 2001-03-11 22:38:39 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.9 2000/10/16 04:11:21 neeri
// % Plug memory leak
// %
// % Revision 1.8 2000/03/15 07:22:07 neeri
// % Enforce alignment choices
// %
// % Revision 1.7 1999/08/26 05:45:10 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.6 1999/05/30 03:09:31 neeri
// % Added support for MPW compilers
// %
// % Revision 1.5 1999/04/29 04:58:20 neeri
// % Fix key destruction bug
// %
// % Revision 1.4 1999/03/17 09:05:13 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.3 1998/10/11 16:45:25 neeri
// % Ready to release 2.0a2
// %
// % Revision 1.2 1998/08/01 21:32:11 neeri
// % About ready for 2.0a1
// %
// % Revision 1.1 1998/01/25 21:02:52 neeri
// % Engine implemented, except for signals & scheduling
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Thread Specific Variables}
//
// It is often useful to have variables which maintain a different value
// for each process. The [[GUSISpecific]] class implements such a mechanism
// in a way that is easily mappable to pthreads.
//
//
// <GUSISpecific.h>=
#ifndef _GUSISpecific_
#define _GUSISpecific_
#ifndef GUSI_SOURCE
typedef struct GUSISpecific GUSISpecific;
#else
#include <Types.h>
#include <ConditionalMacros.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// \section{Definition of Thread Specific Variables}
//
// A [[GUSISpecific]] instance contains a variable ID and a per-process
// destructor.
//
// <Definition of class [[GUSISpecific]]>=
extern "C" {
typedef void (*GUSISpecificDestructor)(void *);
}
class GUSISpecific {
friend class GUSISpecificTable;
public:
GUSISpecific(GUSISpecificDestructor destructor = nil);
~GUSISpecific();
void Destruct(void * data);
private:
GUSISpecificDestructor fDestructor;
unsigned fID;
static unsigned sNextID;
};
// A [[GUSIContext]] contains a [[GUSISpecificTable]] storing the values of all
// thread specific variables defined for this thread.
//
// <Definition of class [[GUSISpecificTable]]>=
class GUSISpecificTable {
friend class GUSISpecific;
public:
GUSISpecificTable();
~GUSISpecificTable();
void * GetSpecific(const GUSISpecific * key) const;
void SetSpecific(const GUSISpecific * key, void * value);
void DeleteSpecific(const GUSISpecific * key);
private:
static void Register(GUSISpecific * key);
static void Destruct(GUSISpecific * key);
// We store a [[GUSISpecificTable]] as a contiguous range of IDs.
//
// <Privatissima of [[GUSISpecificTable]]>=
void *** fValues;
unsigned fAlloc;
bool Valid(const GUSISpecific * key) const;
// All keys are registered in a global table.
//
// <Privatissima of [[GUSISpecificTable]]>=
static GUSISpecific *** sKeys;
static unsigned sKeyAlloc;
};
// To simplify having a particular variable assume a different instance in every
// thread, we define the [[GUSISpecificData]] template.
//
// <Definition of template [[GUSISpecificData]]>=
template <class T, GUSISpecificDestructor D>
class GUSISpecificData {
public:
GUSISpecificData() : fKey(D) { }
T & operator*() { return *get(); }
T * operator->() { return get(); }
const GUSISpecific * Key() const { return &fKey; }
T * get(GUSISpecificTable * table);
T * get() { return get(GUSIContext::Current()); }
protected:
GUSISpecific fKey;
};
template <class T, GUSISpecificDestructor D>
T * GUSISpecificData<T,D>::get(GUSISpecificTable * table)
{
void * data = table->GetSpecific(&fKey);
if (!data)
table->SetSpecific(&fKey, data = new T);
return static_cast<T *>(data);
}
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
// <Inline member functions for class [[GUSISpecific]]>=
inline GUSISpecific::GUSISpecific(GUSISpecificDestructor destructor)
: fDestructor(destructor), fID(sNextID++)
{
GUSISpecificTable::Register(this);
}
inline GUSISpecific::~GUSISpecific()
{
GUSISpecificTable::Destruct(this);
}
inline void GUSISpecific::Destruct(void * data)
{
if (fDestructor)
fDestructor(data);
}
// <Inline member functions for class [[GUSISpecificTable]]>=
inline bool GUSISpecificTable::Valid(const GUSISpecific * key) const
{
return key && key->fID < fAlloc;
}
// <Inline member functions for class [[GUSISpecificTable]]>=
inline GUSISpecificTable::GUSISpecificTable()
: fValues(nil), fAlloc(0)
{
}
// <Inline member functions for class [[GUSISpecificTable]]>=
inline void * GUSISpecificTable::GetSpecific(const GUSISpecific * key) const
{
if (Valid(key))
return fValues[0][key->fID];
else
return nil;
}
#endif /* GUSI_SOURCE */
#endif /* _GUSISpecific_ */

Просмотреть файл

@ -0,0 +1,192 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSITimer.nw - Timing functions
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: GUSITimer.h,v $
// % Revision 1.1 2001-03-11 22:38:42 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.12 2001/01/17 08:48:04 neeri
// % Introduce Expired(), Reset()
// %
// % Revision 1.11 2000/10/29 18:36:32 neeri
// % Fix time_t signedness issues
// %
// % Revision 1.10 2000/06/12 04:24:50 neeri
// % Fix time, localtime, gmtime
// %
// % Revision 1.9 2000/05/23 07:24:58 neeri
// % Improve formatting
// %
// % Revision 1.8 2000/03/15 07:22:07 neeri
// % Enforce alignment choices
// %
// % Revision 1.7 1999/11/15 07:20:18 neeri
// % Safe context setup
// %
// % Revision 1.6 1999/08/26 05:45:10 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.5 1999/08/02 07:02:46 neeri
// % Support for asynchronous errors and other socket options
// %
// % Revision 1.4 1999/07/07 04:17:43 neeri
// % Final tweaks for 2.0b3
// %
// % Revision 1.3 1999/06/28 06:08:46 neeri
// % Support flexible timer classes
// %
// % Revision 1.2 1999/05/30 03:06:21 neeri
// % Fixed various bugs in cleanup and wakeup
// %
// % Revision 1.1 1999/03/17 09:05:14 neeri
// % Added GUSITimer, expanded docs
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Timing functions}
//
// This section defines mechanisms to measure time. The basic mechanism is
// [[GUSITimer]] which can wake up a [[GUSIContext]] at some later time.
//
// <GUSITimer.h>=
#ifndef _GUSITimer_
#define _GUSITimer_
#ifndef GUSI_SOURCE
typedef struct GUSITimer GUSITimer;
#else
#include "GUSISpecific.h"
#include <errno.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/time.h>
#include <inttypes.h>
#include <MacTypes.h>
#include <Timer.h>
#include <Math64.h>
#include <ConditionalMacros.h>
#if PRAGMA_STRUCT_ALIGN
#pragma options align=native
#endif
// \section{Definition of timing}
//
// [[GUSITime]] is an universal (if somewhat costly) format for
// the large variety of timing formats used in MacOS and POSIX.
//
// <Definition of class [[GUSITime]]>=
class GUSITime {
public:
enum Format {seconds, ticks, msecs, usecs, nsecs};
#if !TYPE_LONGLONG
GUSITime(int32_t val, Format format);
GUSITime(uint32_t val, Format format);
#endif
GUSITime(int64_t val, Format format=nsecs) { Construct(val, format); }
GUSITime(const timeval & tv);
GUSITime(const timespec & ts);
GUSITime(const tm & t);
GUSITime() {}
int32_t Get(Format format) { return S32Set(Get64(format)); }
uint32_t UGet(Format format)
{ return U32SetU(SInt64ToUInt64(Get64(format))); }
int64_t Get64(Format format);
operator int64_t() { return fTime; }
operator timeval();
operator timespec();
operator tm();
GUSITime GM2LocalTime();
GUSITime Local2GMTime();
GUSITime & operator +=(const GUSITime & other)
{ fTime = S64Add(fTime, other.fTime); return *this; }
GUSITime & operator -=(const GUSITime & other)
{ fTime = S64Subtract(fTime, other.fTime); return *this; }
static GUSITime Now();
static timezone & Zone();
private:
void Construct(int64_t val, Format format);
time_t Deconstruct(int64_t & remainder);
int64_t fTime;
static int64_t sTimeOffset;
static timezone sTimeZone;
};
inline GUSITime operator+(const GUSITime & a, const GUSITime & b)
{ GUSITime t(a); return t+=b; }
inline GUSITime operator-(const GUSITime & a, const GUSITime & b)
{ GUSITime t(a); return t-=b; }
// A [[GUSITimer]] is a time manager task that wakes up a [[GUSIContext]].
//
// <Definition of class [[GUSITimer]]>=
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#endif
class GUSIContext;
extern "C" void GUSIKillTimers(void * timers);
class GUSITimer : public TMTask {
public:
GUSITimer(bool wakeup = true, GUSIContext * context = 0);
virtual ~GUSITimer();
void Sleep(long ms, bool driftFree = false);
void MicroSleep(long us, bool driftFree = false)
{ Sleep(-us, driftFree); }
GUSIContext * Context() { return fQueue->fContext; }
GUSITimer * Next() { return fNext; }
bool Primed() { return (qType&kTMTaskActive) != 0; }
bool Expired() { return !(qType&kTMTaskActive); }
virtual void Wakeup();
void Kill();
void Reset();
struct Queue {
GUSITimer * fTimer;
GUSIContext * fContext;
Queue() : fTimer(0) {}
};
QElem * Elem() { return reinterpret_cast<QElem *>(&this->qLink); }
protected:
Queue * fQueue;
GUSITimer * fNext;
class TimerQueue : public GUSISpecificData<Queue,GUSIKillTimers> {
public:
~TimerQueue();
};
static TimerQueue sTimerQueue;
static TimerUPP sTimerProc;
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#endif
#endif /* GUSI_SOURCE */
#endif /* _GUSITimer_ */

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,44 @@
/* Metrowerks Standard Library Version 2.4 1998 March 10 */
/*
* errno.h
*/
/* Adapted for GUSI by Matthias Neeracher <neeri@iis.ee.ethz.ch> */
#ifndef _ERRNO_H
#define _ERRNO_H
#ifdef __MWERKS__
#include <cerrno>
/*
* Undef error codes defined by MSL. We are overriding the MSL implementations, so
* these versions of the codes should never be generated anyway.
*/
#undef EEXIST
#undef ENOTEMPTY
#undef EISDIR
#undef EPERM
#undef EACCES
#undef EBADF
#undef EDEADLOCK
#undef EMFILE
#undef ENOENT
#undef ENFILE
#undef ENOSPC
#undef EINVAL
#undef EIO
#undef ENOMEM
#undef ENOSYS
#undef ENAMETOOLONG
#else
#include <mpw/errno.h>
#endif
#include <sys/errno.h>
#if defined(__cplusplus) && defined(_MSL_USING_NAMESPACE) && (__MSL__ < 0x5000)
using namespace std;
#endif
#endif

Просмотреть файл

Просмотреть файл

@ -0,0 +1,22 @@
/* Written for GUSI by Matthias Neeracher <neeri@iis.ee.ethz.ch> */
#ifndef _INTTYPES_H_
#define _INTTYPES_H_
/*
* Regrettably, this is needed for *int64_t
*/
#include <MacTypes.h>
typedef char int8_t;
typedef short int16_t;
typedef long int32_t;
typedef SInt64 int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
typedef UInt64 uint64_t;
typedef long intptr_t;
typedef unsigned long uintptr_t;
#endif /* _INTTYPES_H_ */

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,128 @@
/*-
* Copyright (c) 1980, 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* [¤3 Deleted as of 22Jul99, see
* ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
* for details]
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)netdb.h 8.1 (Berkeley) 6/2/93
* $Id: netdb.h,v 1.1 2001-03-11 22:39:01 sgehani%netscape.com Exp $
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
* --Copyright--
*/
/* Adapted for GUSI by Matthias Neeracher <neeri@iis.ee.ethz.ch> */
#ifndef _NETDB_H_
#define _NETDB_H_
#define _PATH_HEQUIV "/etc/hosts.equiv"
#define _PATH_HOSTS "/etc/hosts"
#define _PATH_NETWORKS "/etc/networks"
#define _PATH_PROTOCOLS "/etc/protocols"
#define _PATH_SERVICES "/etc/services"
/*
* Structures returned by network data base library. All addresses are
* supplied in host order, and returned in network order (suitable for
* use in system calls).
*/
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
#define h_addr h_addr_list[0] /* address, for backward compatiblity */
};
struct servent {
char *s_name; /* official service name */
char **s_aliases; /* alias list */
int s_port; /* port # */
char *s_proto; /* protocol to use */
};
struct protoent {
char *p_name; /* official protocol name */
char **p_aliases; /* alias list */
int p_proto; /* protocol # */
};
/*
* Error return codes from gethostbyname() and gethostbyaddr()
* (left in h_errno).
*/
extern int h_errno;
#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */
#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
#define NO_DATA 4 /* Valid name, no data record of requested type */
#define NO_ADDRESS NO_DATA /* no address, look for MX record */
#include <sys/cdefs.h>
__BEGIN_DECLS
void endhostent __P((void));
void endprotoent __P((void));
void endservent __P((void));
struct hostent *gethostbyaddr __P((const void *, size_t, int));
struct hostent *gethostbyname __P((const char *));
struct hostent *gethostent __P((void));
struct protoent *getprotobyname __P((const char *));
struct protoent *getprotobynumber __P((int));
struct protoent *getprotoent __P((void));
struct servent *getservbyname __P((const char *, const char *));
struct servent *getservbyport __P((int, const char *));
struct servent *getservent __P((void));
void herror __P((const char *));
char *hstrerror __P((int));
void setprotoent __P((int));
void setservent __P((int));
__END_DECLS
#endif /* !_NETDB_H_ */

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,299 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIPThread.nw - Pthreads wrappers
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: pthread.h,v $
// % Revision 1.1 2001-03-11 22:39:05 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.14 2001/01/17 08:55:16 neeri
// % Detect and return ETIMEDOUT condition
// %
// % Revision 1.13 2000/10/29 20:31:53 neeri
// % Releasing 2.1.3
// %
// % Revision 1.12 2000/05/23 07:16:35 neeri
// % Improve formatting, make data types opaque, tune mutexes
// %
// % Revision 1.11 2000/03/06 06:10:00 neeri
// % Reorganize Yield()
// %
// % Revision 1.10 2000/01/17 01:40:31 neeri
// % Correct macro spelling, update references
// %
// % Revision 1.9 1999/11/15 07:20:19 neeri
// % Safe context setup
// %
// % Revision 1.8 1999/09/09 07:22:15 neeri
// % Add support for mutex and cond attribute creation/destruction
// %
// % Revision 1.7 1999/08/26 05:45:07 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.6 1999/07/07 04:17:42 neeri
// % Final tweaks for 2.0b3
// %
// % Revision 1.5 1999/06/30 07:42:07 neeri
// % Getting ready to release 2.0b3
// %
// % Revision 1.4 1999/05/30 03:06:55 neeri
// % MPW compiler compatibility, recursive mutex locks
// %
// % Revision 1.3 1999/03/17 09:05:12 neeri
// % Added GUSITimer, expanded docs
// %
// % Revision 1.2 1998/08/01 21:32:10 neeri
// % About ready for 2.0a1
// %
// % Revision 1.1 1998/01/25 21:02:51 neeri
// % Engine implemented, except for signals & scheduling
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{Pthreads Wrappers}
//
// As opposed to POSIX.1, with which I think I'm reasonable competent by now,
// I have little practical experience, let alone in-depth familiarity with
// Pthreads, so I'm going by what I learned from
//
// \begin{itemize}
// \item Reading \emph{B.~Nicols, D.~Buttlar, and J.~Proulx Farrell,
// ``Pthreads Programming'', O'Reilly \& Associates} and
// \emph{D.~Butenhof, ``Programming with POSIX Threads'', Addison Wesley}.
//
// \item Taking a few glimpses at Chris Provenzano's pthreads implementation.
// \item Reading the news:comp.programming.threads newsgroup.
// \end{itemize}
//
// If you believe that I've misunderstood Pthreads in my implementation, feel free
// to contact me.
//
// As opposed to most other modules, the header files we're generating here don't
// have GUSI in its name.
//
// <pthread.h>=
#ifndef _PTHREAD_H_
#define _PTHREAD_H_
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/time.h>
__BEGIN_DECLS
// \section{Definition of Pthread data types}
//
// I used to be fairly cavalier about exposing internal GUSI data structures,
// on second thought this was not a good idea. To keep C happy, we define
// [[struct]] wrappers for what ultimately will mostly be classes.
//
// <Pthread data types>=
typedef struct GUSIPThread * pthread_t;
// A [[pthread_attr_t]] collects thread creation attributes. This is implemented
// as a pointer so it's easier to change the size of the underlying data structure.
//
// <Pthread data types>=
typedef struct GUSIPThreadAttr * pthread_attr_t;
// A [[pthread_key_t]] is a key to look up thread specific data.
//
// <Pthread data types>=
typedef struct GUSIPThreadKey * pthread_key_t;
// A [[pthread_once_t]] registers whether some routine has run once. It must always
// be statically initialized to [[PTHREAD_ONCE_INIT]] (Although in our implementation,
// it doesn't matter).
//
// <Pthread data types>=
typedef char pthread_once_t;
enum {
PTHREAD_ONCE_INIT = 0
};
// A [[pthread_mutex_t]] is a mutual exclusion variable, implemented as a pointer
// to a [[GUSIContextQueue]]. For initialization convenience, a 0 value means
// an unlocked mutex. No attributes are supported so far.
//
// <Pthread data types>=
typedef struct GUSIPThreadMutex * pthread_mutex_t;
typedef void * pthread_mutexattr_t;
#define PTHREAD_MUTEX_INITIALIZER 0
// A [[pthread_cond_t]] is a condition variable, which looks rather similar
// to a mutex, but has different semantics. No attributes are supported so far.
//
// <Pthread data types>=
typedef struct GUSIPThreadCond * pthread_cond_t;
typedef void * pthread_condattr_t;
#define PTHREAD_COND_INITIALIZER 0
// [[pthread_attr_init]] initializes an attribute object with the
// default values.
//
// <Pthread function declarations>=
int pthread_attr_init(pthread_attr_t * attr);
// [[pthread_attr_destroy]] destroys an attribute object.
//
// <Pthread function declarations>=
int pthread_attr_destroy(pthread_attr_t * attr);
// The detach state defines whether a thread will be defined joinable or
// detached.
//
// <Pthread function declarations>=
enum {
PTHREAD_CREATE_JOINABLE,
PTHREAD_CREATE_DETACHED
};
int pthread_attr_getdetachstate(const pthread_attr_t * attr, int * state);
int pthread_attr_setdetachstate(pthread_attr_t * attr, int state);
// The stack size defines how much stack space will be allocated. Stack overflows
// typically lead to utterly nasty crashes.
//
// <Pthread function declarations>=
int pthread_attr_getstacksize(const pthread_attr_t * attr, size_t * size);
int pthread_attr_setstacksize(pthread_attr_t * attr, size_t size);
// \section{Creation and Destruction of PThreads}
//
// First, we define wrapper to map the different calling conventions of Pthreads
// and Macintosh threads.
//
// <Pthread function declarations>=
__BEGIN_DECLS
typedef void * (*GUSIPThreadProc)(void *);
__END_DECLS
// [[pthread_create]] stuffs the arguments in a [[CreateArg]] and creates the
// context.
//
// <Pthread function declarations>=
int pthread_create(
pthread_t * thread,
const pthread_attr_t * attr, GUSIPThreadProc proc, void * arg);
// A thread can either be detached, in which case it will just go away after it's
// done, or it can be joinable, in which case it will wait for [[pthread_join]]
// to be called.
//
// <Pthread function declarations>=
int pthread_detach(pthread_t thread);
// [[pthread_join]] waits for the thread to die and optionally returns its last
// words.
//
// <Pthread function declarations>=
int pthread_join(pthread_t thread, void **value);
// [[pthread_exit]] ends the existence of a thread.
//
// <Pthread function declarations>=
int pthread_exit(void *value);
// \section{Pthread thread specific data}
//
// Thread specific data offers a possibility to quickly look up a value that may be
// different for every thread.
//
// [[pthread_key_create]] creates an unique key visible to all threads in a
// process.
//
// <Pthread function declarations>=
__BEGIN_DECLS
typedef void (*GUSIPThreadKeyDestructor)(void *);
__END_DECLS
int pthread_key_create(pthread_key_t * key, GUSIPThreadKeyDestructor destructor);
// [[pthread_key_delete]] deletes a key, but does not call any destructors.
//
// <Pthread function declarations>=
int pthread_key_delete(pthread_key_t key);
// [[pthread_getspecific]] returns the thread specific value for a key.
//
// <Pthread function declarations>=
void * pthread_getspecific(pthread_key_t key);
// [[pthread_setspecific]] sets a new thread specific value for a key.
//
// <Pthread function declarations>=
int pthread_setspecific(pthread_key_t key, void * value);
// \section{Synchronization mechanisms of PThreads}
//
// Since we're only dealing with cooperative threads, all synchronization
// mechanisms can be implemented using means that might look naive to a student
// of computer science, but that actually work perfectly well in our case.
//
// We currently don't support mutex and condition variable attributes. To minimize
// the amount of code changes necessary inclients, we support creating and destroying
// them, at least.
//
// <Pthread function declarations>=
int pthread_mutexattr_init(pthread_mutexattr_t * attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t * attr);
// <Pthread function declarations>=
int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t *);
int pthread_mutex_destroy(pthread_mutex_t * mutex);
// Lock may create the queue if it was allocated statically. Mutexes are implemented
// as a queue of context, with the frontmost context holding the lock. Simple enough,
// isn't it?
//
// <Pthread function declarations>=
int pthread_mutex_lock(pthread_mutex_t * mutex);
// Strangely enough, [[pthread_mutex_trylock]] is much more of a problem if we want
// to maintain a semblance of scheduling fairness. In particular, we need the [[Yield]]
// in case somebody checks a mutex in a loop with no other yield point.
//
// <Pthread function declarations>=
int pthread_mutex_trylock(pthread_mutex_t * mutex);
// Unlocking pops us off the queue and wakes up the new lock owner.
//
// <Pthread function declarations>=
int pthread_mutex_unlock(pthread_mutex_t * mutex);
// On to condition variable attributes, which we don't really support either.
//
// <Pthread function declarations>=
int pthread_condattr_init(pthread_condattr_t * attr);
int pthread_condattr_destroy(pthread_condattr_t * attr);
// Condition variables in some respects work very similar to mutexes.
//
// <Pthread function declarations>=
int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t *);
int pthread_cond_destroy(pthread_cond_t * cond);
// [[pthread_cond_wait]] releases the mutex, sleeps on the condition variable,
// and reacquires the mutex.
//
// <Pthread function declarations>=
int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex);
// [[pthread_cond_timedwait]] adds a timeout value (But it still could block
// indefinitely trying to reacquire the mutex). Note that the timeout specifies
// an absolute wakeup time, not an interval.
//
// <Pthread function declarations>=
int pthread_cond_timedwait(
pthread_cond_t * cond, pthread_mutex_t * mutex,
const struct timespec * patience);
// [[pthread_cond_signal]] wakes up a context from the queue. Since we typically
// still hold the associated mutex, it would be a bad idea (though not a disastrous
// one) to put a yield in here.
//
// <Pthread function declarations>=
int pthread_cond_signal(pthread_cond_t * cond);
// [[pthread_cond_broadcast]] wakes up a the entire queue (but only one context
// will get the mutex).
//
// <Pthread function declarations>=
int pthread_cond_broadcast(pthread_cond_t * cond);
// \section{Pthread varia}
//
// [[pthread_self]] returns the current thread.
//
// <Pthread function declarations>=
pthread_t pthread_self(void);
// [[pthread_equal]] compares two thread handles.
//
// <Pthread function declarations>=
int pthread_equal(pthread_t t1, pthread_t t2);
// [[pthread_once]] calls a routines, guaranteeing that it will be called exactly
// once per process.
//
// <Pthread function declarations>=
__BEGIN_DECLS
typedef void (*GUSIPThreadOnceProc)(void);
__END_DECLS
int pthread_once(pthread_once_t * once_block, GUSIPThreadOnceProc proc);
__END_DECLS
#endif /* _PTHREAD_H_ */

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,55 @@
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Project : GUSI - Grand Unified Socket Interface
// % File : GUSIPPC.nw - Program-Program Communications
// % Author : Matthias Neeracher
// % Language : C++
// %
// % $Log: ppc.h,v $
// % Revision 1.1 2001-03-11 22:41:01 sgehani%netscape.com
// % First Checked In.
// %
// % Revision 1.9 2000/10/29 19:13:57 neeri
// % Numerous fixes to make it actually work
// %
// % Revision 1.8 2000/10/16 04:34:23 neeri
// % Releasing 2.1.2
// %
// % Revision 1.7 2000/05/23 07:15:31 neeri
// % Improve formatting
// %
// % Revision 1.6 2000/03/06 06:10:00 neeri
// % Reorganize Yield()
// %
// % Revision 1.5 1999/11/15 07:21:36 neeri
// % Add GUSIwithPPCSockets
// %
// % Revision 1.4 1999/08/26 05:45:07 neeri
// % Fixes for literate edition of source code
// %
// % Revision 1.3 1999/06/28 06:05:00 neeri
// % Support interrupted calls
// %
// % Revision 1.2 1999/06/08 04:31:30 neeri
// % Getting ready for 2.0b2
// %
// % Revision 1.1 1999/03/17 09:05:12 neeri
// % Added GUSITimer, expanded docs
// %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// \chapter{The GUSI PPC Socket Class}
//
// The [[GUSIPPCSocket]] class implements communication via the Program-Program
// Communications Toolbox (For a change, the PPC does not stand for ``PowerPC''
// here).
//
// We give PPC sockets their own official looking header.
//
// <sys/ppc.h>=
#include <PPCToolbox.h>
struct sockaddr_ppc {
sa_family_t sppc_family; /* AF_PPC */
LocationNameRec sppc_location;
PPCPortRec sppc_port;
};

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл