1 /*********************************************************************
2 Project : GUSI - Grand Unified Socket Interface
3 File : GUSI_P.h - Private stuff
4 Author : Matthias Neeracher
8 Revision 1.1 1998/08/18 14:52:33 jack
9 Putting Python-specific GUSI modifications under CVS.
11 Revision 1.3 1994/12/31 01:30:26 neeri
12 Reorganize filename dispatching.
14 Revision 1.2 1994/08/10 00:41:05 neeri
15 Sanitized for universal headers.
17 Revision 1.1 1994/02/25 02:57:01 neeri
20 Revision 0.22 1993/07/17 00:00:00 neeri
21 GUSIRingBuffer::proc -> defproc
23 Revision 0.21 1993/07/17 00:00:00 neeri
24 GUSIO_MAX_DOMAIN -> AF_MAX
26 Revision 0.20 1993/06/27 00:00:00 neeri
27 Socket::{pre,post}_select
29 Revision 0.19 1993/06/27 00:00:00 neeri
32 Revision 0.18 1993/02/09 00:00:00 neeri
33 Socket::lurking, Socket::lurkdescr
35 Revision 0.17 1993/01/31 00:00:00 neeri
36 GUSIConfiguration::daemon
38 Revision 0.16 1993/01/17 00:00:00 neeri
39 Destructors for Socketdomain
41 Revision 0.15 1993/01/17 00:00:00 neeri
44 Revision 0.14 1993/01/03 00:00:00 neeri
47 Revision 0.13 1992/09/24 00:00:00 neeri
50 Revision 0.12 1992/09/13 00:00:00 neeri
51 SPINVOID didn't return
53 Revision 0.11 1992/08/30 00:00:00 neeri
56 Revision 0.10 1992/08/03 00:00:00 neeri
59 Revision 0.9 1992/07/30 00:00:00 neeri
62 Revision 0.8 1992/07/26 00:00:00 neeri
65 Revision 0.7 1992/07/13 00:00:00 neeri
66 Make AppleTalkSockets global
68 Revision 0.6 1992/06/27 00:00:00 neeri
71 Revision 0.5 1992/06/07 00:00:00 neeri
74 Revision 0.4 1992/05/21 00:00:00 neeri
77 Revision 0.3 1992/04/19 00:00:00 neeri
80 Revision 0.2 1992/04/18 00:00:00 neeri
81 changed read/write/send/recv dispatchers
83 Revision 0.1 1992/04/18 00:00:00 neeri
86 *********************************************************************/
91 #define __useAppleExts__
94 #include <GUSIRsrc_P.h>
95 #include <TFileSpec.h>
98 #include <sys/errno.h>
100 #include <sys/socket.h>
107 int GUSI_error(int err
);
108 void * GUSI_error_nil(int err
);
114 #include <AppleEvents.h>
115 #include <Processes.h>
116 #include <MixedMode.h>
126 #define GUSI_MAX_DOMAIN AF_MAX
127 #define DEFAULT_BUFFER_SIZE 4096
130 * In use and shutdown status.
132 #define SOCK_STATUS_USED 0x1 /* Used socket table entry */
133 #define SOCK_STATUS_NOREAD 0x2 /* No more reading allowed from socket */
134 #define SOCK_STATUS_NOWRITE 0x4 /* No more writing allowed to socket */
137 * Socket connection states.
139 #define SOCK_STATE_NO_STREAM 0 /* Socket doesn't have a MacTCP stream yet */
140 #define SOCK_STATE_UNCONNECTED 1 /* Socket is unconnected. */
141 #define SOCK_STATE_LISTENING 2 /* Socket is listening for connection. */
142 #define SOCK_STATE_LIS_CON 3 /* Socket is in transition from listen to connected. */
143 #define SOCK_STATE_CONNECTING 4 /* Socket is initiating a connection. */
144 #define SOCK_STATE_CONNECTED 5 /* Socket is connected. */
145 #define SOCK_STATE_CLOSING 6 /* Socket is closing */
146 #define SOCK_STATE_LIS_CLOSE 7 /* Socket closed while listening */
148 #define min(a,b) ( (a) < (b) ? (a) : (b))
149 #define max(a,b) ( (a) > (b) ? (a) : (b))
151 extern GUSISpinFn GUSISpin
;
152 extern "C" int GUSIDefaultSpin(spin_msg
, long);
153 extern int GUSICheckAlarm();
155 #define GUSI_INTERRUPT(mesg,param) (GUSICheckAlarm() || (GUSISpin && (*GUSISpin)(mesg,param)))
157 /* SPIN returns a -1 on user cancel for fn returning integers */
158 #define SPIN(cond,mesg,param) \
160 if (GUSI_INTERRUPT(mesg,param)) \
161 return GUSI_error(EINTR); \
164 /* SPINP returns a NULL on user cancel, for fn returning pointers */
165 #define SPINP(cond,mesg,param) \
167 if (GUSI_INTERRUPT(mesg,param)) { \
173 /* SPINVOID just returns on user cancel, for fn returning void */
174 #define SPINVOID(cond,mesg,param) \
176 if (GUSI_INTERRUPT(mesg,param)) { \
182 /* SAFESPIN doesn't return, you have to check errno */
183 #define SAFESPIN(cond,mesg,param) \
185 if (GUSI_INTERRUPT(mesg,param)) { \
193 // Library functions are never allowed to clear errno, so we have to save
197 ErrnoSaver() { fSavedErrno
= ::errno
; ::errno
= 0; }
198 ~ErrnoSaver() { if (!::errno
) ::errno
= fSavedErrno
; }
203 #define SAVE_AND_CLEAR_ERRNO ErrnoSaver saveErrno
207 #if PRAGMA_ALIGN_SUPPORTED
208 #pragma options align=mac68k
212 friend class SocketTable
;
218 virtual int bind(void * name
, int namelen
);
219 virtual int connect(void * address
, int addrlen
);
220 virtual int listen(int qlen
);
221 virtual Socket
* accept(void * address
, int * addrlen
);
222 virtual int read(void * buffer
, int buflen
);
223 virtual int write(void * buffer
, int buflen
);
224 virtual int recvfrom(void * buffer
, int buflen
, int flags
, void * from
, int * fromlen
);
225 virtual int sendto(void * buffer
, int buflen
, int flags
, void * to
, int tolen
);
226 virtual int getsockname(void * name
, int * namelen
);
227 virtual int getpeername(void * name
, int * namelen
);
228 virtual int getsockopt(int level
, int optname
, void *optval
, int * optlen
);
229 virtual int setsockopt(int level
, int optname
, void *optval
, int optlen
);
230 virtual int fcntl(unsigned int cmd
, int arg
);
231 virtual int ioctl(unsigned int request
, void *argp
);
232 virtual int fstat(struct stat
* buf
);
233 virtual long lseek(long offset
, int whence
);
234 virtual int ftruncate(long offset
);
235 virtual int isatty();
236 virtual int shutdown(int how
);
237 virtual void pre_select(Boolean wantRead
, Boolean wantWrite
, Boolean wantExcept
);
238 virtual int select(Boolean
* canRead
, Boolean
* canWrite
, Boolean
* exception
);
239 virtual void post_select(Boolean wantRead
, Boolean wantWrite
, Boolean wantExcept
);
242 void operator++() { ++refCount
; }
243 void operator--() { if (!--refCount
) delete this; }
247 #if PRAGMA_ALIGN_SUPPORTED
248 #pragma options align=reset
252 static SocketDomain
* domains
[GUSI_MAX_DOMAIN
];
253 static ProcessSerialNumber process
;
255 SocketDomain(int domain
);
256 virtual ~SocketDomain();
258 inline static SocketDomain
* Domain(int domain
);
261 // Optionally override the following
263 virtual Socket
* socket(int type
, short protocol
);
265 // Optionally override the following
267 virtual int socketpair(int type
, short protocol
, Socket
* sockets
[]);
269 // Optionally define the following
279 // Never override the following
285 Socket
* sockets
[GUSI_MAX_FD
];
286 Boolean needsConsole
;
292 int Install(Socket
* sock
, int start
= 0);
294 Socket
* operator[](int fd
);
303 #if PRAGMA_ALIGN_SUPPORTED
304 #pragma options align=mac68k
308 // I learned the hard way not to rely on bit field alignments
311 struct GUSIConfigRsrc
{
313 OSType defaultCreator
;
320 GUSISuffix suffices
[1];
323 #if PRAGMA_ALIGN_SUPPORTED
324 #pragma options align=reset
327 struct GUSIConfiguration
{
329 OSType defaultCreator
;
333 Boolean noChdir
; // Set current directory without chdir()
334 Boolean accurStat
; // Return # of subdirectories + 2 in st_nlink
335 Boolean hasConsole
; // Do we have our own console ?
336 Boolean noAutoInitGraf
; // Never automatically do InitGraf
337 Boolean sharedOpen
; // Open files with shared permissions
338 Boolean sigPipe
; // raise SIGPIPE on write to closed socket
339 Boolean noAppleEvents
; // Don't solicit AppleEvents for MPW tools
340 Boolean delayConsole
; // Do not open console until needed
344 GUSISuffix
* suffices
;
347 void GUSILoadConfiguration(Handle config
);
349 void SetDefaultFType(const TFileSpec
& name
) const;
350 void DoAutoSpin() const;
351 void AutoInitGraf() const { if (!noAutoInitGraf
) DoAutoInitGraf(); }
352 void DoAutoInitGraf() const;
353 Boolean
DelayConsole() const;
355 static Boolean firstTime
;
359 extern GUSIConfiguration GUSIConfig
;
360 extern SocketTable Sockets
;
362 typedef pascal OSErr (*OSErrInitializer
)();
363 typedef pascal void (*voidInitializer
)();
368 Feature(unsigned short trapNum
, TrapType tTyp
);
369 Feature(OSType type
, long value
);
370 Feature(OSType type
, long mask
, long value
);
371 Feature(const Feature
& precondition
, OSErrInitializer init
);
372 Feature(OSErrInitializer init
);
373 Feature(const Feature
& precondition
, voidInitializer init
);
374 Feature(voidInitializer init
);
375 Feature(const Feature
& cond1
, const Feature
& cond2
);
377 operator void*() const { return (void *) good
; }
380 extern Feature hasMakeFSSpec
;
381 extern Feature hasAlias
;
382 extern Feature hasNewSF
;
383 extern Feature hasProcessMgr
;
384 extern Feature hasCRM
;
385 extern Feature hasCTB
;
386 extern Feature hasStdNBP
;
387 extern Feature hasCM
;
388 extern Feature hasFT
;
389 extern Feature hasTM
;
390 extern Feature hasPPC
;
391 extern Feature hasRevisedTimeMgr
;
399 const struct iovec
* io
;
401 ScattGath(const struct iovec
*iov
, int cnt
);
402 virtual ~ScattGath();
404 void * buffer() { return buf
; }
405 int buflen() { return len
; }
406 int length(int l
) { return len
= l
; }
407 operator void *() { return buf
; }
410 class Scatterer
: public ScattGath
{
412 Scatterer(const struct iovec
*iov
, int count
);
413 virtual ~Scatterer();
416 class Gatherer
: public ScattGath
{
418 Gatherer(const struct iovec
*iov
, int count
);
422 typedef pascal void (*Deferred
)(void *);
425 // Valid bytes are between consume and produce
426 // Free bytes are between produce and consume
427 // bytes between endbuf-spare and endbuf are neither
440 RingBuffer(u_short bufsiz
);
443 Ptr
Producer(long & len
); // Find continuous memory for producer
444 Ptr
Consumer(long & len
); // Find continuous memory for consumer
445 void Validate(long len
); // Validate this, unallocate rest
446 void Invalidate(long len
);
447 void Produce(Ptr from
, long & len
);// Allocate, copy & validate
448 void Consume(Ptr to
, long & len
); // Copy & invalidate
450 long Free() { return free
; }
451 long Valid() { return valid
; }
453 void Defer() { lock
= true; }
454 void Undefer() { lock
= false; if (defproc
) defproc(arg
);}
455 Boolean
Locked() { return lock
; }
456 void Later(Deferred def
, void * ar
){ defproc
= def
; arg
= ar
; }
458 operator void *() { return buffer
; }
461 Boolean
GUSIInterrupt();
463 Boolean
CopyIconFamily(short srcResFile
, short srcID
, short dstResFile
, short dstID
);
465 pascal OSErr
PPCInit_P();
467 OSErr
AppleTalkIdentity(short & net
, short & node
);
469 void CopyC2PStr(const char * cstr
, StringPtr pstr
);