diff --git a/GUSI/MacDistr b/GUSI/MacDistr index 57a2c33..61fdb25 100755 Binary files a/GUSI/MacDistr and b/GUSI/MacDistr differ diff --git a/GUSI/README b/GUSI/README index cdf059e..65cef6d 100755 Binary files a/GUSI/README and b/GUSI/README differ diff --git a/GUSI/include/GUSIContext.h b/GUSI/include/GUSIContext.h index 8709b33..dfb0c2f 100755 --- a/GUSI/include/GUSIContext.h +++ b/GUSI/include/GUSIContext.h @@ -5,6 +5,9 @@ // % Language : C++ // % // % $Log$ +// % Revision 1.1.1.1 2001/03/07 09:50:40 chombier +// % First Imported. +// % // % Revision 1.1.1.1 2001/03/03 21:50:10 chombier // % Initial import // % @@ -337,8 +340,7 @@ protected: GUSIContext(ThreadID id); GUSIContext( ThreadEntryProcPtr threadEntry, void *threadParam, - Size stackSize, ThreadOptions options = kCreateIfNeeded, - void **threadResult = nil, ThreadID *threadMade = nil); + Size stackSize, ThreadOptions options, void **threadResult, ThreadID *threadMade); virtual void SwitchIn(); virtual void SwitchOut(); @@ -398,6 +400,7 @@ protected: static Queue sContexts; static GUSIContext * sCurrentContext; + static bool sCreatingCurrentContext; static bool sHasThreading; static OSErr sError; // The [[GUSIContext]] constructor links the context into the queue of existing @@ -411,7 +414,7 @@ protected: // Destruction of a [[GUSIContext]] requires some cleanup. // // = - ~GUSIContext(); + virtual ~GUSIContext(); }; // [[GUSIContext]] instances are created by instances of [[GUSIContextFactory]]. // @@ -420,6 +423,7 @@ class GUSIContextFactory { public: static GUSIContextFactory * Instance(); static void SetInstance(GUSIContextFactory * instance); + static void DeleteInstance(); virtual GUSIContext * CreateContext(ThreadID id); virtual GUSIContext * CreateContext( @@ -431,6 +435,11 @@ public: protected: GUSIContextFactory(); }; +// To make it possible to install an alternative [[GUSIContextFactory]], we provide the +// [[GUSISetupContextFactory()]] hook for overriding; +// +// = +extern "C" void GUSISetupContextFactory(); // 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 diff --git a/GUSI/include/GUSIDescriptor.h b/GUSI/include/GUSIDescriptor.h index 7c947b4..69aabfe 100755 --- a/GUSI/include/GUSIDescriptor.h +++ b/GUSI/include/GUSIDescriptor.h @@ -5,6 +5,9 @@ // % Language : C++ // % // % $Log$ +// % Revision 1.1.1.1 2001/03/07 09:50:41 chombier +// % First Imported. +// % // % Revision 1.1.1.1 2001/03/03 21:50:10 chombier // % Initial import // % @@ -114,6 +117,7 @@ public: static void SetInstance(GUSIDescriptorTable * table); + GUSIDescriptorTable(); GUSIDescriptorTable(const GUSIDescriptorTable & parent); private: // \section{Implementation of [[GUSIDescriptorTable]]} @@ -123,7 +127,6 @@ private: // = GUSISocket * fSocket[SIZE]; int fInvalidDescriptor; - GUSIDescriptorTable(); // = static GUSIDescriptorTable * sGUSIDescriptorTable; }; @@ -141,6 +144,7 @@ private: // // = extern "C" { +void GUSISetupDescriptorTable(); void GUSISetupConsole(); void GUSIDefaultSetupConsole(); void GUSISetupConsoleDescriptors(); diff --git a/GUSI/include/GUSIFileSpec.h b/GUSI/include/GUSIFileSpec.h index e9507b5..b4bf8b9 100755 --- a/GUSI/include/GUSIFileSpec.h +++ b/GUSI/include/GUSIFileSpec.h @@ -5,6 +5,9 @@ // % Language : C++ // % // % $Log$ +// % Revision 1.1.1.1 2001/03/07 09:50:44 chombier +// % First Imported. +// % // % Revision 1.1.1.1 2001/03/03 21:50:11 chombier // % Initial import // % @@ -333,8 +336,11 @@ public: // [[operator+]] provides a non-destructive variant of [[operator+=]]. // // = - friend GUSIFileSpec operator+(const FSSpec & spec, ConstStr31Param name); - friend GUSIFileSpec operator+(const FSSpec & spec, const char * name); + // + // These don't need access to the GUSIFileSpec internals + // + // 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). diff --git a/GUSI/include/GUSIOpenTransport.h b/GUSI/include/GUSIOpenTransport.h index 4b97e90..e47560a 100755 --- a/GUSI/include/GUSIOpenTransport.h +++ b/GUSI/include/GUSIOpenTransport.h @@ -4,9 +4,15 @@ // % Author : Matthias Neeracher // % Language : C++ // % -// % $Log$ -// % Revision 1.1.1.1 2001/03/03 21:50:13 chombier -// % Initial import +// % $Log$ +// % Revision 1.21 2001/03/20 08:12:55 neeri +// % Further select repairs +// % +// % Revision 1.20 2001/03/20 02:35:21 neeri +// % Refined new select() implementation +// % +// % Revision 1.19 2001/03/09 09:25:21 neeri +// % Fixed select logic bugs, listener queue // % // % Revision 1.18 2001/01/17 08:58:06 neeri // % Releasing 2.1.4 @@ -231,6 +237,11 @@ public: // // = virtual int ioctl(unsigned int request, va_list arg); + // Before we call [[select]], we check whether there is data currently available and turn + // off the data flags otherwise. + // + // = + virtual bool pre_select(bool wantRead, bool wantWrite, bool wantExcept); // [[getsockopt]] and [[setsockopt]] are available for a variety of options. // // = diff --git a/GUSI/include/fcntl.h b/GUSI/include/fcntl.h index dcdb95b..ca7f0d2 100755 --- a/GUSI/include/fcntl.h +++ b/GUSI/include/fcntl.h @@ -122,7 +122,7 @@ int fcntl __P((int, int, ...)); /* This properly belongs into stdio.h, but that header is outside of GUSI's control */ -#ifdef __MWERKS__ +#if defined(__MWERKS__) && !defined(_SFSTDIO_H) FILE * fdopen(int fildes, char *type); #else FILE * fdopen(int fildes, const char *type); diff --git a/GUSI/include/unistd.h b/GUSI/include/unistd.h index 6daead1..4410edc 100755 --- a/GUSI/include/unistd.h +++ b/GUSI/include/unistd.h @@ -58,6 +58,12 @@ int close __P((int)); size_t confstr __P((int, char *, size_t)); int dup __P((int)); int dup2 __P((int, int)); +int execl __P((const char *, const char *, ...)); +int execle __P((const char *, const char *, ...)); +int execlp __P((const char *, const char *, ...)); +int execv __P((const char *, char * const *)); +int execve __P((const char *, char * const *, char * const *)); +int execvp __P((const char *, char * const *)); long fpathconf __P((int, int)); char *getcwd __P((char *, size_t)); gid_t getegid __P((void)); @@ -142,7 +148,7 @@ int sethostname __P((const char *, int)); int setkey __P((const char *)); int setlogin __P((const char *)); void *setmode __P((const char *)); -int setpgrp __P((pid_t pid, pid_t pgrp)); /* obsoleted by setpgid() */ +int setpgrp __P((void)); int setregid __P((gid_t, gid_t)); int setreuid __P((uid_t, uid_t)); int setrgid __P((gid_t)); diff --git a/GUSI/src/GUSIContext.nw b/GUSI/src/GUSIContext.nw index e1e8ea9..5f33b1d 100755 Binary files a/GUSI/src/GUSIContext.nw and b/GUSI/src/GUSIContext.nw differ diff --git a/GUSI/src/GUSIDescriptor.nw b/GUSI/src/GUSIDescriptor.nw index 3dcf496..33fa1f5 100755 Binary files a/GUSI/src/GUSIDescriptor.nw and b/GUSI/src/GUSIDescriptor.nw differ diff --git a/GUSI/src/GUSIFileSpec.nw b/GUSI/src/GUSIFileSpec.nw index 1965362..64ee0c9 100755 Binary files a/GUSI/src/GUSIFileSpec.nw and b/GUSI/src/GUSIFileSpec.nw differ diff --git a/GUSI/src/GUSIMPW.nw b/GUSI/src/GUSIMPW.nw index 8785b82..b25d7d5 100755 Binary files a/GUSI/src/GUSIMPW.nw and b/GUSI/src/GUSIMPW.nw differ diff --git a/GUSI/src/GUSINetDB.nw b/GUSI/src/GUSINetDB.nw index 95594c5..654b56b 100755 Binary files a/GUSI/src/GUSINetDB.nw and b/GUSI/src/GUSINetDB.nw differ diff --git a/GUSI/src/GUSIOTInet.nw b/GUSI/src/GUSIOTInet.nw index bb90800..c9b789d 100755 Binary files a/GUSI/src/GUSIOTInet.nw and b/GUSI/src/GUSIOTInet.nw differ diff --git a/GUSI/src/GUSIOTNetDB.nw b/GUSI/src/GUSIOTNetDB.nw index 9878e03..ccedfa4 100755 Binary files a/GUSI/src/GUSIOTNetDB.nw and b/GUSI/src/GUSIOTNetDB.nw differ diff --git a/GUSI/src/GUSIOpenTransport.nw b/GUSI/src/GUSIOpenTransport.nw index 6abe42e..6c11660 100755 Binary files a/GUSI/src/GUSIOpenTransport.nw and b/GUSI/src/GUSIOpenTransport.nw differ diff --git a/GUSI/src/tangled/GUSIContext.cp b/GUSI/src/tangled/GUSIContext.cp index 2b67d6b..d790e69 100755 --- a/GUSI/src/tangled/GUSIContext.cp +++ b/GUSI/src/tangled/GUSIContext.cp @@ -67,7 +67,8 @@ GUSIProcess::~GUSIProcess() now += 300; // Accelerate } } -// [[GUSIContext::Setup]] initializes the default context. +// [[GUSIContext::Setup]] initializes the default context. We have to employ +// [[sCreatingCurrentContext]] to avoid nasty recursions. // // = void GUSIContext::Setup(bool threading) @@ -75,11 +76,13 @@ void GUSIContext::Setup(bool threading) bool wasThreading = sHasThreading; if (threading) sHasThreading = true; - if (!sCurrentContext) { + if (!sCurrentContext && !sCreatingCurrentContext) { MaxApplZone(); // It's about time, too! + sCreatingCurrentContext = true; sCurrentContext = - new GUSIContext(kApplicationThreadID); + GUSIContextFactory::Instance()->CreateContext(kApplicationThreadID); + sCreatingCurrentContext = false; } else if (!wasThreading && threading) { // Sometimes we only recognize that we need threading after the application context // has already been created. Assuming a disciplined use of threads, we can assume @@ -97,6 +100,7 @@ void GUSIContext::Setup(bool threading) // = GUSIContext::Queue GUSIContext::sContexts; GUSIContext * GUSIContext::sCurrentContext; +bool GUSIContext::sCreatingCurrentContext; bool GUSIContext::sHasThreading; OSErr GUSIContext::sError; // = @@ -187,6 +191,7 @@ GUSIContext::~GUSIContext() // = void GUSIContext::Queue::LiquidateAll() { + GUSIContextFactory::DeleteInstance(); GUSIDescriptorTable::CloseAllDescriptors(); while (!empty()) front()->Liquidate(); @@ -277,19 +282,46 @@ OSErr GUSINewThread( return err; } // = -static auto_ptr sGUSIContextFactory; +#ifdef __MRC__ +#pragma noinline_func GUSISetupContextFactory +#endif +#ifdef __MWERKS__ +#pragma dont_inline on +#endif + +void GUSISetupContextFactory() +{ +} + +#ifdef __MWERKS__ +#pragma dont_inline reset +#endif +// = +static GUSIContextFactory * sGUSIContextFactory; +static bool sGUSIContextFactorySetup; GUSIContextFactory * GUSIContextFactory::Instance() { - if (!sGUSIContextFactory.get()) + if (!sGUSIContextFactorySetup) { + sGUSIContextFactorySetup = true; + GUSISetupContextFactory(); + } + + if (!sGUSIContextFactory) SetInstance(new GUSIContextFactory()); - return sGUSIContextFactory.get(); + return sGUSIContextFactory; } void GUSIContextFactory::SetInstance(GUSIContextFactory * instance) { - sGUSIContextFactory = auto_ptr(instance); + sGUSIContextFactory = instance; +} + +void GUSIContextFactory::DeleteInstance() +{ + delete sGUSIContextFactory; + sGUSIContextFactory = 0; } GUSIContextFactory::GUSIContextFactory() diff --git a/GUSI/src/tangled/GUSIDescriptor.cp b/GUSI/src/tangled/GUSIDescriptor.cp index 2252b23..c61967c 100755 --- a/GUSI/src/tangled/GUSIDescriptor.cp +++ b/GUSI/src/tangled/GUSIDescriptor.cp @@ -20,7 +20,7 @@ GUSIDescriptorTable::GUSIDescriptorTable() // = #ifdef __MRC__ #pragma noinline_func GUSISetupConsole, GUSISetupConsoleDescriptors, GUSISetupConsoleStdio -#pragma noinline_func GUSIStdioClose, GUSIStdioFlush +#pragma noinline_func GUSIStdioClose, GUSIStdioFlush, GUSISetupDescriptorTable #endif // = GUSIDescriptorTable * GUSIDescriptorTable::sGUSIDescriptorTable; @@ -82,6 +82,24 @@ void GUSISetupConsoleDescriptors() table->InstallSocket(null->open()); } +#ifdef __MWERKS__ +#pragma dont_inline reset +#endif +// If, for any reason, the default descriptor table does not do the job for you, override +// [[GUSISetupDescriptorTable]]. +// +// = +// +// Prevent inlining to allow override +// +#ifdef __MWERKS__ +#pragma dont_inline on +#endif + +void GUSISetupDescriptorTable() +{ +} + #ifdef __MWERKS__ #pragma dont_inline reset #endif @@ -91,11 +109,14 @@ GUSIDescriptorTable * GUSIDescriptorTable::Instance() static bool sNeedConsoleSetup = true; if (!sGUSIDescriptorTable) { - sGUSIDescriptorTable = new GUSIDescriptorTable(); - if (sNeedConsoleSetup) { - sNeedConsoleSetup = false; - GUSISetupConsole(); - } + GUSISetupDescriptorTable(); + + if (!sGUSIDescriptorTable) + sGUSIDescriptorTable = new GUSIDescriptorTable(); + } + if (sNeedConsoleSetup) { + sNeedConsoleSetup = false; + GUSISetupConsole(); } return sGUSIDescriptorTable; } diff --git a/GUSI/src/tangled/GUSIFileSpec.cp b/GUSI/src/tangled/GUSIFileSpec.cp index c0f2e6a..9f87a61 100755 --- a/GUSI/src/tangled/GUSIFileSpec.cp +++ b/GUSI/src/tangled/GUSIFileSpec.cp @@ -460,10 +460,12 @@ OSErr GUSIFileSpec::PrependPathComponent(char *&path, ConstStr63Param component, char * GUSIFileSpec::RelativePath(const FSSpec & dir) const { GUSIFileSpec current(dir); + if (current.fSpec.name[0]) + ++current; + long relDirID= current.fSpec.parID; if (current.GetVolume(0)) return FullPath(); short relVRef = current.fSpec.vRefNum; - long relDirID= dir.parID; current = *this; if (current.GetVolume(0) || current.fSpec.vRefNum != relVRef) return FullPath(); diff --git a/GUSI/src/tangled/GUSIMPW.cp b/GUSI/src/tangled/GUSIMPW.cp index 196e73a..8b051ee 100755 --- a/GUSI/src/tangled/GUSIMPW.cp +++ b/GUSI/src/tangled/GUSIMPW.cp @@ -184,7 +184,8 @@ class GUSIMPWDevice : public GUSIDevice { public: static GUSIMPWDevice * Instance(); - // [[GUSIMPWDevice]] is prepared to handle an [[open]] on a limited set of names. + // [[GUSIMPWDevice]] is prepared to handle an [[open]] on a limited set of device names + // and on all files. // // = virtual bool Want(GUSIFileToken & file); @@ -285,7 +286,7 @@ bool GUSIMPWDevice::Want(GUSIFileToken & file) { switch (file.WhichRequest()) { case GUSIFileToken::kWillOpen: - return file.IsDevice() && (file.StrStdStream(file.Path()) > -1); + return !file.IsDevice() || (file.StrStdStream(file.Path()) > -1); default: return false; } @@ -338,6 +339,8 @@ static int TranslateOpenFlags(int mode) return mpwMode; } // = +extern int StandAlone; + GUSISocket * GUSIMPWDevice::open(GUSIFileToken & file, int flags) { if (!ConnectToMPWLibrary()) @@ -345,16 +348,17 @@ GUSISocket * GUSIMPWDevice::open(GUSIFileToken & file, int flags) int fd = MPW_open(file.Path(), TranslateOpenFlags(flags)); - if (fd == -1) + if (fd == -1) { return static_cast(nil); - else + } else if (!file.IsDevice() && !StandAlone && MPW_ioctl(fd, FIOINTERACTIVE, nil) == -1) { + MPW_close(fd); + return GUSIMacFileDevice::Instance()->open(file, flags); + } else return stdopen(fd, flags); } // [[stdopen]] handles the GUSI side of the opening. // // = -extern int StandAlone; - GUSISocket * GUSIMPWDevice::stdopen(int fd, int flags) { if (!ConnectToMPWLibrary()) diff --git a/GUSI/src/tangled/GUSINetDB.cp b/GUSI/src/tangled/GUSINetDB.cp index 2cd01c4..4fa3e78 100755 --- a/GUSI/src/tangled/GUSINetDB.cp +++ b/GUSI/src/tangled/GUSINetDB.cp @@ -380,7 +380,7 @@ void GUSIhostent::Alloc(size_t size) { if (size > fAlloc) { if (fName) - delete fName; + delete[] fName; h_name = fName = new char[fAlloc = size]; } } diff --git a/GUSI/src/tangled/GUSIOTInet.cp b/GUSI/src/tangled/GUSIOTInet.cp index f847658..7f9b94a 100755 --- a/GUSI/src/tangled/GUSIOTInet.cp +++ b/GUSI/src/tangled/GUSIOTInet.cp @@ -444,7 +444,7 @@ static int GetInterfaceList(ifconf * conf) if (++interface == maxInterfaces) goto bufferFull; } - delete secondaries; + delete[] secondaries; } ++numInterfaces; } @@ -472,7 +472,7 @@ static int GetInterfaceParam(ifreq * ifr, unsigned int request) InetHost * secondaries = new InetHost[info.fIPSecondaryCount]; OTInetGetSecondaryAddresses(secondaries, &info.fIPSecondaryCount, ifnum); info.fAddress = secondaries[ifalias-1]; - delete secondaries; + delete[] secondaries; } switch (request) { case SIOCGIFADDR: diff --git a/GUSI/src/tangled/GUSIOTNetDB.cp b/GUSI/src/tangled/GUSIOTNetDB.cp index c5db7c9..c98d26d 100755 --- a/GUSI/src/tangled/GUSIOTNetDB.cp +++ b/GUSI/src/tangled/GUSIOTNetDB.cp @@ -55,6 +55,8 @@ pascal void GUSIOTNetDBNotify( default: if (code != kOTProviderWillClose) result = 0; + else + netdb->fCreationContext = nil; // Close & reopen break; } if (result) @@ -84,6 +86,10 @@ void GUSIOTNetDB::Instantiate() bool GUSIOTNetDB::Resolver() { if (!fCreationContext) { + if (fSvc) { + OTCloseProvider(fSvc); + fSvc = nil; + } fCreationContext = GUSIContext::Current(); if (!GUSIOTFactory::Initialize()) return false; diff --git a/GUSI/src/tangled/GUSIOpenTransport.cp b/GUSI/src/tangled/GUSIOpenTransport.cp index 6891ec4..5e1090e 100755 --- a/GUSI/src/tangled/GUSIOpenTransport.cp +++ b/GUSI/src/tangled/GUSIOpenTransport.cp @@ -111,7 +111,7 @@ void GUSIOTSocket::MopupEvents() delete udErr; } - if (fCurEvent & (T_DISCONNECT | T_ORDREL)) { + if ((fCurEvent & (T_DISCONNECT | T_ORDREL)) && !(fEvent & T_LISTEN)) { fReadShutdown = true; } } @@ -170,6 +170,7 @@ void GUSIOTSocket::close() Unbind(); OTCloseProvider(fEndpoint); + fEvent = 0; GUSISocket::close(); } @@ -317,6 +318,16 @@ int GUSIOTSocket::ioctl(unsigned int request, va_list arg) return GUSISetPosixError(EOPNOTSUPP); } // = +bool GUSIOTSocket::pre_select(bool wantRead, bool wantWrite, bool wantExcept) +{ + size_t sz; + + if (wantRead && OTCountDataBytes(fEndpoint, &sz) == kOTNoDataErr) + fEvent &= ~(T_DATA|T_EXDATA); + + return true; +} +// = int GUSIOTSocket::getsockopt(int level, int optname, void *optval, socklen_t * optlen) { int result; @@ -560,6 +571,7 @@ void GUSIOTStreamSocket::MopupEvents() if (fCurEvent & T_CONNECT) { GUSI_MESSAGE(("Connect\n")); OTRcvConnect(fEndpoint, fPeerName); + fEvent |= T_GODATA; } if (fCurEvent & T_ORDREL) { OTRcvOrderlyDisconnect(fEndpoint); @@ -658,9 +670,9 @@ if (err) { } if (fNextListener) { // = - GUSIOTSocket * sock = fNextListener; + GUSIOTStreamSocket * sock = fNextListener; fCompletion &= ~(CompleteMask(T_ACCEPTCOMPLETE)); - SetAsyncMacError(OTAccept(fEndpoint, fNextListener->fEndpoint, fNextListener->fPeerName)); + SetAsyncMacError(OTAccept(fEndpoint, sock->fEndpoint, sock->fPeerName)); AddContext(); MopupEvents(); while (!fAsyncError && !(fCompletion & CompleteMask(T_ACCEPTCOMPLETE))) { @@ -681,11 +693,13 @@ if (err) { } break; case 0: - GUSI_MESSAGE(("GUSIOTStreamSocket::accept accepted %08x\n", fNextListener)); - fNextListener = fNextListener->fNextListener; + GUSI_MESSAGE(("GUSIOTStreamSocket::accept accepted %08x\n", sock)); + fNextListener = sock->fNextListener; + sock->fNextListener = nil; sock->getpeername(address, addrlen); sock->fSockName = new (fEndpoint) GUSIOTTBind; + sock->fEvent |= T_GODATA; /* Ready to write */ if (sock->fSockName && !fSockName->Copy(fStrategy, sock->fSockName)) return sock; else @@ -694,7 +708,7 @@ if (err) { default: deleteCandidate: GUSI_MESSAGE(("GUSIOTStreamSocket::accept async error %d\n", error)); - fNextListener = fNextListener->fNextListener; + fNextListener = sock->fNextListener; delete sock; } @@ -772,6 +786,7 @@ ssize_t GUSIOTStreamSocket::recvfrom( if (res == kOTNoDataErr) { if (GUSISetPosixError(GetAsyncError())) return -1; + fEvent &= ~(T_DATA|T_EXDATA); if (!fBlocking) return GUSISetPosixError(EWOULDBLOCK); bool signal = false; @@ -792,9 +807,15 @@ ssize_t GUSIOTStreamSocket::recvfrom( buffer.SetLength(res); if (from) fPeerName->Unpack(fStrategy, from, fromlen); - if (exp && (otflags & (T_EXPEDITED|T_MORE)) != T_EXPEDITED) { + // When the [[T_EXDATA]] event arrives, we might first get some non-expedited data + // [[!(otflags & T_EXPEDITED)]] and then a packet of expedited data [[otflags & T_EXPEDITED]], + // possibly with the [[T_MORE]] flag set (although that should not happen in TCP/IP). We + // therefore don't reset [[T_EXDATA]] until we have seen a packet with [[T_EXPEDITED]] set + // and [[T_MORE]] not set. + // + // = + if (exp && (otflags & (T_EXPEDITED|T_MORE)) != T_EXPEDITED) fEvent |= exp; - } return res; } // = @@ -814,6 +835,7 @@ ssize_t GUSIOTStreamSocket::sendto( OTResult res = OTSnd(fEndpoint, buf, len, 0); if (res <= 0) if (res == kOTFlowErr) { + fEvent &= ~T_GODATA; if (!fBlocking) return done ? done : GUSISetPosixError(EWOULDBLOCK); bool signal = GUSIContext::Yield(kGUSIBlock); @@ -839,32 +861,34 @@ bool GUSIOTStreamSocket::select(bool * canRead, bool * canWrite, bool * except) OTResult state = OTGetEndpointState(fEndpoint); if (canRead) { - size_t sz; if (*canRead = fReadShutdown // EOF || fAsyncError // Asynchronous error - || OTCountDataBytes(fEndpoint, &sz) != kOTNoDataErr // Data available + || fEvent & T_DATA // Data available || state == T_INCON // Connection pending || fNextListener // Connection pending ) res = true; } - if (canWrite) - if (fWriteShutdown || fAsyncError) + if (canWrite) { + if (fWriteShutdown || fAsyncError) { res = *canWrite = true; - else + } else { switch (state) { case T_DATAXFER: case T_INREL: - *canWrite = true; - res = true; + if (*canWrite = (fEvent & T_GODATA) != 0) + res = true; break; default: *canWrite = false; } - if (except) + } + } + if (except) { if (*except = (fEvent & T_EXDATA) != 0) res = true; + } return res; } // = @@ -1057,8 +1081,7 @@ bool GUSIOTDatagramSocket::select(bool * canRead, bool * canWrite, bool * except OTResult state = OTGetEndpointState(fEndpoint); if (canRead) { - size_t sz; - if (*canRead = fAsyncError || OTCountDataBytes(fEndpoint, &sz) != kOTNoDataErr) + if (*canRead = fAsyncError || fEvent & T_DATA) res = true; } if (canWrite) diff --git a/lsh/MacOS/src/GUSIPatches.cp b/lsh/MacOS/src/GUSIPatches.cp index d467878..1ce8c6c 100755 --- a/lsh/MacOS/src/GUSIPatches.cp +++ b/lsh/MacOS/src/GUSIPatches.cp @@ -148,12 +148,15 @@ done: return interrupt; } + /* * The fSvc field of the GUSIOTNetDB instance is no longer valid after * an interface switch in the TCP/IP control panel. * Let's clear it upon kOTProviderWillClose message. */ +/* no longer needed: GUSI 2.1.6b2 fixes this */ +/* // = inline uint32_t CompleteMask(OTEventCode code) { @@ -199,8 +202,7 @@ pascal void GUSIOTNetDBNotify( netdb->fAsyncError = result; context->Wakeup(); } - - +*/ diff --git a/macssh/source/ssh/GUSIPatch2.cp b/macssh/source/ssh/GUSIPatch2.cp index 1e3c724..69c755b 100755 --- a/macssh/source/ssh/GUSIPatch2.cp +++ b/macssh/source/ssh/GUSIPatch2.cp @@ -19,6 +19,7 @@ #include #include +#include #include @@ -46,3 +47,79 @@ GUSIFileServiceDB * GUSIFileServiceDB::Instance() return static_cast(nil); } +/* + * The fSvc field of the GUSIOTNetDB instance is no longer valid after + * an interface switch in the TCP/IP control panel. + * Let's clear it upon kOTProviderWillClose message. + */ + +/* no longer needed: GUSI 2.1.6b2 fixes this */ +/* +// = +inline uint32_t CompleteMask(OTEventCode code) +{ + return 1 << (code & 0x1F); +} + +pascal void GUSIOTNetDBNotify( + GUSIOTNetDB * netdb, OTEventCode code, OTResult result, void *cookie) +{ + GUSI_MESSAGE(("GUSIOTNetDBNotify %08x %d\n", code, result)); + GUSIContext * context = netdb->fCreationContext; + + switch (code & 0x7F000000L) { + case 0: + netdb->fEvent |= code; + result = 0; + break; + case kPRIVATEEVENT: + case kCOMPLETEEVENT: + if (!(code & 0x00FFFFE0)) + netdb->fCompletion |= CompleteMask(code); + switch (code) { + case T_OPENCOMPLETE: + netdb->fSvc = static_cast(cookie); + break; + case T_DNRSTRINGTOADDRCOMPLETE: + case T_DNRADDRTONAMECOMPLETE: + context = static_cast(cookie)[-1]; + break; + } + break; + default: + if (code != kOTProviderWillClose) { + result = 0; + } else { + netdb->fCreationContext = static_cast(NULL); + } + break; + } + if (result) + netdb->fAsyncError = result; + context->Wakeup(); +} + +// = +bool GUSIOTNetDB::Resolver() +{ + if (!fCreationContext) { + fCreationContext = GUSIContext::Current(); + if (!GUSIOTFactory::Initialize()) + return false; + if (fSvc) { + OTCloseProvider(fSvc); + fSvc = static_cast(NULL); + } + fAsyncError = 0; + OSStatus syncError = OTAsyncOpenInternetServices( + kDefaultInternetServicesPath, + 0, + reinterpret_cast(GUSIOTNetDBNotify), + this); + if (!syncError) + while (!fAsyncError && !(fCompletion & CompleteMask(T_OPENCOMPLETE))) + GUSIContext::Yield(kGUSIBlock); + } + return fSvc != 0; +} +*/ diff --git a/macssh/www/download/ChangeLog b/macssh/www/download/ChangeLog index 4fd32bd..c2ca3d0 100755 Binary files a/macssh/www/download/ChangeLog and b/macssh/www/download/ChangeLog differ