blob: 66ee3a76c80798426beff35b5e1d1c62a87f5f1b [file] [log] [blame]
Jack Jansen1d6a6ea1998-08-18 14:52:38 +00001/*********************************************************************
2Project : GUSI - Grand Unified Socket Interface
3File : GUSI_P.h - Private stuff
4Author : Matthias Neeracher
5Language : MPW C/C++
6
7$Log$
Jack Jansen9c940ca2000-09-12 20:24:50 +00008Revision 1.1 2000/09/12 20:24:46 jack
9Moved to Unsupported.
10
Jack Jansen1d6a6ea1998-08-18 14:52:38 +000011Revision 1.1 1998/08/18 14:52:33 jack
12Putting Python-specific GUSI modifications under CVS.
13
14Revision 1.3 1994/12/31 01:30:26 neeri
15Reorganize filename dispatching.
16
17Revision 1.2 1994/08/10 00:41:05 neeri
18Sanitized for universal headers.
19
20Revision 1.1 1994/02/25 02:57:01 neeri
21Initial revision
22
23Revision 0.22 1993/07/17 00:00:00 neeri
24GUSIRingBuffer::proc -> defproc
25
26Revision 0.21 1993/07/17 00:00:00 neeri
27GUSIO_MAX_DOMAIN -> AF_MAX
28
29Revision 0.20 1993/06/27 00:00:00 neeri
30Socket::{pre,post}_select
31
32Revision 0.19 1993/06/27 00:00:00 neeri
33Socket::ftruncate
34
35Revision 0.18 1993/02/09 00:00:00 neeri
36Socket::lurking, Socket::lurkdescr
37
38Revision 0.17 1993/01/31 00:00:00 neeri
39GUSIConfiguration::daemon
40
41Revision 0.16 1993/01/17 00:00:00 neeri
42Destructors for Socketdomain
43
44Revision 0.15 1993/01/17 00:00:00 neeri
45SAFESPIN
46
47Revision 0.14 1993/01/03 00:00:00 neeri
48GUSIConfig
49
50Revision 0.13 1992/09/24 00:00:00 neeri
51Include GUSIRsrc_P.h
52
53Revision 0.12 1992/09/13 00:00:00 neeri
54SPINVOID didn't return
55
56Revision 0.11 1992/08/30 00:00:00 neeri
57AppleTalkIdentity()
58
59Revision 0.10 1992/08/03 00:00:00 neeri
60RingBuffer
61
62Revision 0.9 1992/07/30 00:00:00 neeri
63Initializer Features
64
65Revision 0.8 1992/07/26 00:00:00 neeri
66UnixSockets.choose()
67
68Revision 0.7 1992/07/13 00:00:00 neeri
69Make AppleTalkSockets global
70
71Revision 0.6 1992/06/27 00:00:00 neeri
72choose(), hasNewSF
73
74Revision 0.5 1992/06/07 00:00:00 neeri
75Feature
76
77Revision 0.4 1992/05/21 00:00:00 neeri
78Implemented select()
79
80Revision 0.3 1992/04/19 00:00:00 neeri
81C++ rewrite
82
83Revision 0.2 1992/04/18 00:00:00 neeri
84changed read/write/send/recv dispatchers
85
86Revision 0.1 1992/04/18 00:00:00 neeri
87ppc Domain
88
89*********************************************************************/
90
91#ifndef __GUSI_P__
92#define __GUSI_P__
93
94#define __useAppleExts__
95
96#include <GUSI.h>
97#include <GUSIRsrc_P.h>
98#include <TFileSpec.h>
99
100
101#include <sys/errno.h>
102#include <sys/uio.h>
103#include <sys/socket.h>
104
105extern "C" {
106
107#include <stdio.h>
108#include <string.h>
109
110int GUSI_error(int err);
111void * GUSI_error_nil(int err);
112}
113
114#include <Memory.h>
115#include <Gestalt.h>
116#include <Traps.h>
117#include <AppleEvents.h>
118#include <Processes.h>
119#include <MixedMode.h>
120
121#if MSLGUSI
122using namespace std;
123#endif
124
125#if GENERATING68K
126#pragma segment GUSI
127#endif
128
129#define GUSI_MAX_DOMAIN AF_MAX
130#define DEFAULT_BUFFER_SIZE 4096
131
132/*
133 * In use and shutdown status.
134 */
135#define SOCK_STATUS_USED 0x1 /* Used socket table entry */
136#define SOCK_STATUS_NOREAD 0x2 /* No more reading allowed from socket */
137#define SOCK_STATUS_NOWRITE 0x4 /* No more writing allowed to socket */
138
139/*
140 * Socket connection states.
141 */
142#define SOCK_STATE_NO_STREAM 0 /* Socket doesn't have a MacTCP stream yet */
143#define SOCK_STATE_UNCONNECTED 1 /* Socket is unconnected. */
144#define SOCK_STATE_LISTENING 2 /* Socket is listening for connection. */
145#define SOCK_STATE_LIS_CON 3 /* Socket is in transition from listen to connected. */
146#define SOCK_STATE_CONNECTING 4 /* Socket is initiating a connection. */
147#define SOCK_STATE_CONNECTED 5 /* Socket is connected. */
148#define SOCK_STATE_CLOSING 6 /* Socket is closing */
149#define SOCK_STATE_LIS_CLOSE 7 /* Socket closed while listening */
150
151#define min(a,b) ( (a) < (b) ? (a) : (b))
152#define max(a,b) ( (a) > (b) ? (a) : (b))
153
154extern GUSISpinFn GUSISpin;
155extern "C" int GUSIDefaultSpin(spin_msg, long);
156extern int GUSICheckAlarm();
157
158#define GUSI_INTERRUPT(mesg,param) (GUSICheckAlarm() || (GUSISpin && (*GUSISpin)(mesg,param)))
159
160/* SPIN returns a -1 on user cancel for fn returning integers */
161#define SPIN(cond,mesg,param) \
162 do { \
163 if (GUSI_INTERRUPT(mesg,param)) \
164 return GUSI_error(EINTR); \
165 } while(cond)
166
167/* SPINP returns a NULL on user cancel, for fn returning pointers */
168#define SPINP(cond,mesg,param) \
169 do { \
170 if (GUSI_INTERRUPT(mesg,param)) { \
171 GUSI_error(EINTR); \
172 return NULL; \
173 } \
174 } while(cond)
175
176/* SPINVOID just returns on user cancel, for fn returning void */
177#define SPINVOID(cond,mesg,param) \
178 do { \
179 if (GUSI_INTERRUPT(mesg,param)) { \
180 GUSI_error(EINTR); \
181 return; \
182 } \
183 } while(cond)
184
185/* SAFESPIN doesn't return, you have to check errno */
186#define SAFESPIN(cond,mesg,param) \
187 do { \
188 if (GUSI_INTERRUPT(mesg,param)) { \
189 GUSI_error(EINTR); \
190 break; \
191 } else \
192 errno = 0; \
193 } while(cond)
194
195//
196// Library functions are never allowed to clear errno, so we have to save
197//
198class ErrnoSaver {
199public:
200 ErrnoSaver() { fSavedErrno = ::errno; ::errno = 0; }
201 ~ErrnoSaver() { if (!::errno) ::errno = fSavedErrno; }
202private:
203 int fSavedErrno;
204};
205
206#define SAVE_AND_CLEAR_ERRNO ErrnoSaver saveErrno
207
208class SocketTable;
209
210#if PRAGMA_ALIGN_SUPPORTED
211#pragma options align=mac68k
212#endif
213
214class Socket {
215 friend class SocketTable;
216
217 short refCount;
218protected:
219 Socket();
220public:
221 virtual int bind(void * name, int namelen);
222 virtual int connect(void * address, int addrlen);
223 virtual int listen(int qlen);
224 virtual Socket * accept(void * address, int * addrlen);
225 virtual int read(void * buffer, int buflen);
226 virtual int write(void * buffer, int buflen);
227 virtual int recvfrom(void * buffer, int buflen, int flags, void * from, int * fromlen);
228 virtual int sendto(void * buffer, int buflen, int flags, void * to, int tolen);
229 virtual int getsockname(void * name, int * namelen);
230 virtual int getpeername(void * name, int * namelen);
231 virtual int getsockopt(int level, int optname, void *optval, int * optlen);
232 virtual int setsockopt(int level, int optname, void *optval, int optlen);
233 virtual int fcntl(unsigned int cmd, int arg);
234 virtual int ioctl(unsigned int request, void *argp);
235 virtual int fstat(struct stat * buf);
236 virtual long lseek(long offset, int whence);
237 virtual int ftruncate(long offset);
238 virtual int isatty();
239 virtual int shutdown(int how);
240 virtual void pre_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept);
241 virtual int select(Boolean * canRead, Boolean * canWrite, Boolean * exception);
242 virtual void post_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept);
243 virtual ~Socket();
244
245 void operator++() { ++refCount; }
246 void operator--() { if (!--refCount) delete this; }
247};
248
249
250#if PRAGMA_ALIGN_SUPPORTED
251#pragma options align=reset
252#endif
253
254class SocketDomain {
255 static SocketDomain * domains[GUSI_MAX_DOMAIN];
256 static ProcessSerialNumber process;
257protected:
258 SocketDomain(int domain);
259 virtual ~SocketDomain();
260public:
261 inline static SocketDomain * Domain(int domain);
262 static void Ready();
263
264 // Optionally override the following
265
266 virtual Socket * socket(int type, short protocol);
267
268 // Optionally override the following
269
270 virtual int socketpair(int type, short protocol, Socket * sockets[]);
271
272 // Optionally define the following
273
274 virtual int choose(
275 int type,
276 char * prompt,
277 void * constraint,
278 int flags,
279 void * name,
280 int * namelen);
281
282 // Never override the following
283
284 void DontStrip();
285};
286
287class SocketTable {
288 Socket * sockets[GUSI_MAX_FD];
289 Boolean needsConsole;
290public:
291 SocketTable();
292 ~SocketTable();
293
294 void InitConsole();
295 int Install(Socket * sock, int start = 0);
296 int Remove(int fd);
297 Socket * operator[](int fd);
298};
299
300struct GUSISuffix {
301 char suffix[4];
302 OSType suffType;
303 OSType suffCreator;
304};
305
306#if PRAGMA_ALIGN_SUPPORTED
307#pragma options align=mac68k
308#endif
309
310//
311// I learned the hard way not to rely on bit field alignments
312//
313
314struct GUSIConfigRsrc {
315 OSType defaultType;
316 OSType defaultCreator;
317
318 char autoSpin;
319 unsigned char flags;
320
321 OSType version;
322 short numSuffices;
323 GUSISuffix suffices[1];
324};
325
326#if PRAGMA_ALIGN_SUPPORTED
327#pragma options align=reset
328#endif
329
330struct GUSIConfiguration {
331 OSType defaultType;
332 OSType defaultCreator;
333
334 char autoSpin;
335
336 Boolean noChdir; // Set current directory without chdir()
337 Boolean accurStat; // Return # of subdirectories + 2 in st_nlink
338 Boolean hasConsole; // Do we have our own console ?
339 Boolean noAutoInitGraf; // Never automatically do InitGraf
340 Boolean sharedOpen; // Open files with shared permissions
341 Boolean sigPipe; // raise SIGPIPE on write to closed socket
342 Boolean noAppleEvents; // Don't solicit AppleEvents for MPW tools
343 Boolean delayConsole; // Do not open console until needed
344
345 OSType version;
346 short numSuffices;
347 GUSISuffix * suffices;
348
349 GUSIConfiguration();
350 void GUSILoadConfiguration(Handle config);
351
352 void SetDefaultFType(const TFileSpec & name) const;
353 void DoAutoSpin() const;
354 void AutoInitGraf() const { if (!noAutoInitGraf) DoAutoInitGraf(); }
355 void DoAutoInitGraf() const;
356 Boolean DelayConsole() const;
357private:
358 static Boolean firstTime;
359 static short we;
360};
361
362extern GUSIConfiguration GUSIConfig;
363extern SocketTable Sockets;
364
365typedef pascal OSErr (*OSErrInitializer)();
366typedef pascal void (*voidInitializer)();
367
368class Feature {
369 Boolean good;
370public:
371 Feature(unsigned short trapNum, TrapType tTyp);
372 Feature(OSType type, long value);
373 Feature(OSType type, long mask, long value);
374 Feature(const Feature & precondition, OSErrInitializer init);
375 Feature(OSErrInitializer init);
376 Feature(const Feature & precondition, voidInitializer init);
377 Feature(voidInitializer init);
378 Feature(const Feature & cond1, const Feature & cond2);
379
380 operator void*() const { return (void *) good; }
381};
382
383extern Feature hasMakeFSSpec;
384extern Feature hasAlias;
385extern Feature hasNewSF;
386extern Feature hasProcessMgr;
387extern Feature hasCRM;
388extern Feature hasCTB;
389extern Feature hasStdNBP;
390extern Feature hasCM;
391extern Feature hasFT;
392extern Feature hasTM;
393extern Feature hasPPC;
394extern Feature hasRevisedTimeMgr;
395
396class ScattGath {
397 Handle scratch;
398protected:
399 void * buf;
400 int len;
401 int count;
402 const struct iovec * io;
403
404 ScattGath(const struct iovec *iov, int cnt);
405 virtual ~ScattGath();
406public:
407 void * buffer() { return buf; }
408 int buflen() { return len; }
409 int length(int l) { return len = l; }
410 operator void *() { return buf; }
411};
412
413class Scatterer : public ScattGath {
414public:
415 Scatterer(const struct iovec *iov, int count);
416 virtual ~Scatterer();
417};
418
419class Gatherer : public ScattGath {
420public:
421 Gatherer(const struct iovec *iov, int count);
422 virtual ~Gatherer();
423};
424
425typedef pascal void (*Deferred)(void *);
426
427class RingBuffer {
428 // Valid bytes are between consume and produce
429 // Free bytes are between produce and consume
430 // bytes between endbuf-spare and endbuf are neither
431 Ptr buffer;
432 Ptr endbuf;
433 Ptr consume;
434 Ptr produce;
435 u_short free;
436 u_short valid;
437 u_short spare;
438 Boolean lock;
439 Deferred defproc;
440 void * arg;
441
442public:
443 RingBuffer(u_short bufsiz);
444 ~RingBuffer();
445
446 Ptr Producer(long & len); // Find continuous memory for producer
447 Ptr Consumer(long & len); // Find continuous memory for consumer
448 void Validate(long len); // Validate this, unallocate rest
449 void Invalidate(long len);
450 void Produce(Ptr from, long & len);// Allocate, copy & validate
451 void Consume(Ptr to, long & len); // Copy & invalidate
452
453 long Free() { return free; }
454 long Valid() { return valid; }
455
456 void Defer() { lock = true; }
457 void Undefer() { lock = false; if (defproc) defproc(arg);}
458 Boolean Locked() { return lock; }
459 void Later(Deferred def, void * ar){ defproc = def; arg = ar; }
460
461 operator void *() { return buffer; }
462};
463
464Boolean GUSIInterrupt();
465
466Boolean CopyIconFamily(short srcResFile, short srcID, short dstResFile, short dstID);
467
468pascal OSErr PPCInit_P();
469
470OSErr AppleTalkIdentity(short & net, short & node);
471
472void CopyC2PStr(const char * cstr, StringPtr pstr);
473
474#endif