/********************************************************************* Project : GUSI - Grand Unified Socket Interface File : GUSI_P.h - Private stuff Author : Matthias Neeracher Language : MPW C/C++ $Log$ Revision 1.1 1998/08/18 14:52:33 jack Putting Python-specific GUSI modifications under CVS. Revision 1.3 1994/12/31 01:30:26 neeri Reorganize filename dispatching. Revision 1.2 1994/08/10 00:41:05 neeri Sanitized for universal headers. Revision 1.1 1994/02/25 02:57:01 neeri Initial revision Revision 0.22 1993/07/17 00:00:00 neeri GUSIRingBuffer::proc -> defproc Revision 0.21 1993/07/17 00:00:00 neeri GUSIO_MAX_DOMAIN -> AF_MAX Revision 0.20 1993/06/27 00:00:00 neeri Socket::{pre,post}_select Revision 0.19 1993/06/27 00:00:00 neeri Socket::ftruncate Revision 0.18 1993/02/09 00:00:00 neeri Socket::lurking, Socket::lurkdescr Revision 0.17 1993/01/31 00:00:00 neeri GUSIConfiguration::daemon Revision 0.16 1993/01/17 00:00:00 neeri Destructors for Socketdomain Revision 0.15 1993/01/17 00:00:00 neeri SAFESPIN Revision 0.14 1993/01/03 00:00:00 neeri GUSIConfig Revision 0.13 1992/09/24 00:00:00 neeri Include GUSIRsrc_P.h Revision 0.12 1992/09/13 00:00:00 neeri SPINVOID didn't return Revision 0.11 1992/08/30 00:00:00 neeri AppleTalkIdentity() Revision 0.10 1992/08/03 00:00:00 neeri RingBuffer Revision 0.9 1992/07/30 00:00:00 neeri Initializer Features Revision 0.8 1992/07/26 00:00:00 neeri UnixSockets.choose() Revision 0.7 1992/07/13 00:00:00 neeri Make AppleTalkSockets global Revision 0.6 1992/06/27 00:00:00 neeri choose(), hasNewSF Revision 0.5 1992/06/07 00:00:00 neeri Feature Revision 0.4 1992/05/21 00:00:00 neeri Implemented select() Revision 0.3 1992/04/19 00:00:00 neeri C++ rewrite Revision 0.2 1992/04/18 00:00:00 neeri changed read/write/send/recv dispatchers Revision 0.1 1992/04/18 00:00:00 neeri ppc Domain *********************************************************************/ #ifndef __GUSI_P__ #define __GUSI_P__ #define __useAppleExts__ #include #include #include #include #include #include extern "C" { #include #include int GUSI_error(int err); void * GUSI_error_nil(int err); } #include #include #include #include #include #include #if MSLGUSI using namespace std; #endif #if GENERATING68K #pragma segment GUSI #endif #define GUSI_MAX_DOMAIN AF_MAX #define DEFAULT_BUFFER_SIZE 4096 /* * In use and shutdown status. */ #define SOCK_STATUS_USED 0x1 /* Used socket table entry */ #define SOCK_STATUS_NOREAD 0x2 /* No more reading allowed from socket */ #define SOCK_STATUS_NOWRITE 0x4 /* No more writing allowed to socket */ /* * Socket connection states. */ #define SOCK_STATE_NO_STREAM 0 /* Socket doesn't have a MacTCP stream yet */ #define SOCK_STATE_UNCONNECTED 1 /* Socket is unconnected. */ #define SOCK_STATE_LISTENING 2 /* Socket is listening for connection. */ #define SOCK_STATE_LIS_CON 3 /* Socket is in transition from listen to connected. */ #define SOCK_STATE_CONNECTING 4 /* Socket is initiating a connection. */ #define SOCK_STATE_CONNECTED 5 /* Socket is connected. */ #define SOCK_STATE_CLOSING 6 /* Socket is closing */ #define SOCK_STATE_LIS_CLOSE 7 /* Socket closed while listening */ #define min(a,b) ( (a) < (b) ? (a) : (b)) #define max(a,b) ( (a) > (b) ? (a) : (b)) extern GUSISpinFn GUSISpin; extern "C" int GUSIDefaultSpin(spin_msg, long); extern int GUSICheckAlarm(); #define GUSI_INTERRUPT(mesg,param) (GUSICheckAlarm() || (GUSISpin && (*GUSISpin)(mesg,param))) /* SPIN returns a -1 on user cancel for fn returning integers */ #define SPIN(cond,mesg,param) \ do { \ if (GUSI_INTERRUPT(mesg,param)) \ return GUSI_error(EINTR); \ } while(cond) /* SPINP returns a NULL on user cancel, for fn returning pointers */ #define SPINP(cond,mesg,param) \ do { \ if (GUSI_INTERRUPT(mesg,param)) { \ GUSI_error(EINTR); \ return NULL; \ } \ } while(cond) /* SPINVOID just returns on user cancel, for fn returning void */ #define SPINVOID(cond,mesg,param) \ do { \ if (GUSI_INTERRUPT(mesg,param)) { \ GUSI_error(EINTR); \ return; \ } \ } while(cond) /* SAFESPIN doesn't return, you have to check errno */ #define SAFESPIN(cond,mesg,param) \ do { \ if (GUSI_INTERRUPT(mesg,param)) { \ GUSI_error(EINTR); \ break; \ } else \ errno = 0; \ } while(cond) // // Library functions are never allowed to clear errno, so we have to save // class ErrnoSaver { public: ErrnoSaver() { fSavedErrno = ::errno; ::errno = 0; } ~ErrnoSaver() { if (!::errno) ::errno = fSavedErrno; } private: int fSavedErrno; }; #define SAVE_AND_CLEAR_ERRNO ErrnoSaver saveErrno class SocketTable; #if PRAGMA_ALIGN_SUPPORTED #pragma options align=mac68k #endif class Socket { friend class SocketTable; short refCount; protected: Socket(); public: virtual int bind(void * name, int namelen); virtual int connect(void * address, int addrlen); virtual int listen(int qlen); virtual Socket * accept(void * address, int * addrlen); virtual int read(void * buffer, int buflen); virtual int write(void * buffer, int buflen); virtual int recvfrom(void * buffer, int buflen, int flags, void * from, int * fromlen); virtual int sendto(void * buffer, int buflen, int flags, void * to, int tolen); virtual int getsockname(void * name, int * namelen); virtual int getpeername(void * name, int * namelen); virtual int getsockopt(int level, int optname, void *optval, int * optlen); virtual int setsockopt(int level, int optname, void *optval, int optlen); virtual int fcntl(unsigned int cmd, int arg); virtual int ioctl(unsigned int request, void *argp); virtual int fstat(struct stat * buf); virtual long lseek(long offset, int whence); virtual int ftruncate(long offset); virtual int isatty(); virtual int shutdown(int how); virtual void pre_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept); virtual int select(Boolean * canRead, Boolean * canWrite, Boolean * exception); virtual void post_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept); virtual ~Socket(); void operator++() { ++refCount; } void operator--() { if (!--refCount) delete this; } }; #if PRAGMA_ALIGN_SUPPORTED #pragma options align=reset #endif class SocketDomain { static SocketDomain * domains[GUSI_MAX_DOMAIN]; static ProcessSerialNumber process; protected: SocketDomain(int domain); virtual ~SocketDomain(); public: inline static SocketDomain * Domain(int domain); static void Ready(); // Optionally override the following virtual Socket * socket(int type, short protocol); // Optionally override the following virtual int socketpair(int type, short protocol, Socket * sockets[]); // Optionally define the following virtual int choose( int type, char * prompt, void * constraint, int flags, void * name, int * namelen); // Never override the following void DontStrip(); }; class SocketTable { Socket * sockets[GUSI_MAX_FD]; Boolean needsConsole; public: SocketTable(); ~SocketTable(); void InitConsole(); int Install(Socket * sock, int start = 0); int Remove(int fd); Socket * operator[](int fd); }; struct GUSISuffix { char suffix[4]; OSType suffType; OSType suffCreator; }; #if PRAGMA_ALIGN_SUPPORTED #pragma options align=mac68k #endif // // I learned the hard way not to rely on bit field alignments // struct GUSIConfigRsrc { OSType defaultType; OSType defaultCreator; char autoSpin; unsigned char flags; OSType version; short numSuffices; GUSISuffix suffices[1]; }; #if PRAGMA_ALIGN_SUPPORTED #pragma options align=reset #endif struct GUSIConfiguration { OSType defaultType; OSType defaultCreator; char autoSpin; Boolean noChdir; // Set current directory without chdir() Boolean accurStat; // Return # of subdirectories + 2 in st_nlink Boolean hasConsole; // Do we have our own console ? Boolean noAutoInitGraf; // Never automatically do InitGraf Boolean sharedOpen; // Open files with shared permissions Boolean sigPipe; // raise SIGPIPE on write to closed socket Boolean noAppleEvents; // Don't solicit AppleEvents for MPW tools Boolean delayConsole; // Do not open console until needed OSType version; short numSuffices; GUSISuffix * suffices; GUSIConfiguration(); void GUSILoadConfiguration(Handle config); void SetDefaultFType(const TFileSpec & name) const; void DoAutoSpin() const; void AutoInitGraf() const { if (!noAutoInitGraf) DoAutoInitGraf(); } void DoAutoInitGraf() const; Boolean DelayConsole() const; private: static Boolean firstTime; static short we; }; extern GUSIConfiguration GUSIConfig; extern SocketTable Sockets; typedef pascal OSErr (*OSErrInitializer)(); typedef pascal void (*voidInitializer)(); class Feature { Boolean good; public: Feature(unsigned short trapNum, TrapType tTyp); Feature(OSType type, long value); Feature(OSType type, long mask, long value); Feature(const Feature & precondition, OSErrInitializer init); Feature(OSErrInitializer init); Feature(const Feature & precondition, voidInitializer init); Feature(voidInitializer init); Feature(const Feature & cond1, const Feature & cond2); operator void*() const { return (void *) good; } }; extern Feature hasMakeFSSpec; extern Feature hasAlias; extern Feature hasNewSF; extern Feature hasProcessMgr; extern Feature hasCRM; extern Feature hasCTB; extern Feature hasStdNBP; extern Feature hasCM; extern Feature hasFT; extern Feature hasTM; extern Feature hasPPC; extern Feature hasRevisedTimeMgr; class ScattGath { Handle scratch; protected: void * buf; int len; int count; const struct iovec * io; ScattGath(const struct iovec *iov, int cnt); virtual ~ScattGath(); public: void * buffer() { return buf; } int buflen() { return len; } int length(int l) { return len = l; } operator void *() { return buf; } }; class Scatterer : public ScattGath { public: Scatterer(const struct iovec *iov, int count); virtual ~Scatterer(); }; class Gatherer : public ScattGath { public: Gatherer(const struct iovec *iov, int count); virtual ~Gatherer(); }; typedef pascal void (*Deferred)(void *); class RingBuffer { // Valid bytes are between consume and produce // Free bytes are between produce and consume // bytes between endbuf-spare and endbuf are neither Ptr buffer; Ptr endbuf; Ptr consume; Ptr produce; u_short free; u_short valid; u_short spare; Boolean lock; Deferred defproc; void * arg; public: RingBuffer(u_short bufsiz); ~RingBuffer(); Ptr Producer(long & len); // Find continuous memory for producer Ptr Consumer(long & len); // Find continuous memory for consumer void Validate(long len); // Validate this, unallocate rest void Invalidate(long len); void Produce(Ptr from, long & len);// Allocate, copy & validate void Consume(Ptr to, long & len); // Copy & invalidate long Free() { return free; } long Valid() { return valid; } void Defer() { lock = true; } void Undefer() { lock = false; if (defproc) defproc(arg);} Boolean Locked() { return lock; } void Later(Deferred def, void * ar){ defproc = def; arg = ar; } operator void *() { return buffer; } }; Boolean GUSIInterrupt(); Boolean CopyIconFamily(short srcResFile, short srcID, short dstResFile, short dstID); pascal OSErr PPCInit_P(); OSErr AppleTalkIdentity(short & net, short & node); void CopyC2PStr(const char * cstr, StringPtr pstr); #endif