зеркало из https://github.com/mozilla/pjs.git
First Checked In.
This commit is contained in:
Родитель
3972e66a0f
Коммит
bff4894c69
|
@ -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;
|
||||
};
|
Загрузка…
Ссылка в новой задаче