GUSI 2.1.6b2 update

This commit is contained in:
chombier 2001-03-28 14:05:07 +00:00
parent 314207e840
commit 49269292b0
27 changed files with 257 additions and 54 deletions

Binary file not shown.

Binary file not shown.

View File

@ -5,6 +5,9 @@
// % Language : C++ // % Language : C++
// % // %
// % $Log$ // % $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 // % Revision 1.1.1.1 2001/03/03 21:50:10 chombier
// % Initial import // % Initial import
// % // %
@ -337,8 +340,7 @@ protected:
GUSIContext(ThreadID id); GUSIContext(ThreadID id);
GUSIContext( GUSIContext(
ThreadEntryProcPtr threadEntry, void *threadParam, ThreadEntryProcPtr threadEntry, void *threadParam,
Size stackSize, ThreadOptions options = kCreateIfNeeded, Size stackSize, ThreadOptions options, void **threadResult, ThreadID *threadMade);
void **threadResult = nil, ThreadID *threadMade = nil);
virtual void SwitchIn(); virtual void SwitchIn();
virtual void SwitchOut(); virtual void SwitchOut();
@ -398,6 +400,7 @@ protected:
static Queue sContexts; static Queue sContexts;
static GUSIContext * sCurrentContext; static GUSIContext * sCurrentContext;
static bool sCreatingCurrentContext;
static bool sHasThreading; static bool sHasThreading;
static OSErr sError; static OSErr sError;
// The [[GUSIContext]] constructor links the context into the queue of existing // The [[GUSIContext]] constructor links the context into the queue of existing
@ -411,7 +414,7 @@ protected:
// Destruction of a [[GUSIContext]] requires some cleanup. // Destruction of a [[GUSIContext]] requires some cleanup.
// //
// <Privatissima of [[GUSIContext]]>= // <Privatissima of [[GUSIContext]]>=
~GUSIContext(); virtual ~GUSIContext();
}; };
// [[GUSIContext]] instances are created by instances of [[GUSIContextFactory]]. // [[GUSIContext]] instances are created by instances of [[GUSIContextFactory]].
// //
@ -420,6 +423,7 @@ class GUSIContextFactory {
public: public:
static GUSIContextFactory * Instance(); static GUSIContextFactory * Instance();
static void SetInstance(GUSIContextFactory * instance); static void SetInstance(GUSIContextFactory * instance);
static void DeleteInstance();
virtual GUSIContext * CreateContext(ThreadID id); virtual GUSIContext * CreateContext(ThreadID id);
virtual GUSIContext * CreateContext( virtual GUSIContext * CreateContext(
@ -431,6 +435,11 @@ public:
protected: protected:
GUSIContextFactory(); GUSIContextFactory();
}; };
// To make it possible to install an alternative [[GUSIContextFactory]], we provide the
// [[GUSISetupContextFactory()]] hook for overriding;
//
// <Definition of class [[GUSIContextFactory]]>=
extern "C" void GUSISetupContextFactory();
// Many asynchronous calls take the same style of I/O parameter block and thus // Many asynchronous calls take the same style of I/O parameter block and thus
// can be handled by the same completion procedure. [[StartIO]] prepares // can be handled by the same completion procedure. [[StartIO]] prepares
// a parameter block for asynchronous I/O; [[FinishIO]] waits for the I/O // a parameter block for asynchronous I/O; [[FinishIO]] waits for the I/O

View File

@ -5,6 +5,9 @@
// % Language : C++ // % Language : C++
// % // %
// % $Log$ // % $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 // % Revision 1.1.1.1 2001/03/03 21:50:10 chombier
// % Initial import // % Initial import
// % // %
@ -114,6 +117,7 @@ public:
static void SetInstance(GUSIDescriptorTable * table); static void SetInstance(GUSIDescriptorTable * table);
GUSIDescriptorTable();
GUSIDescriptorTable(const GUSIDescriptorTable & parent); GUSIDescriptorTable(const GUSIDescriptorTable & parent);
private: private:
// \section{Implementation of [[GUSIDescriptorTable]]} // \section{Implementation of [[GUSIDescriptorTable]]}
@ -123,7 +127,6 @@ private:
// <Privatissima of [[GUSIDescriptorTable]]>= // <Privatissima of [[GUSIDescriptorTable]]>=
GUSISocket * fSocket[SIZE]; GUSISocket * fSocket[SIZE];
int fInvalidDescriptor; int fInvalidDescriptor;
GUSIDescriptorTable();
// <Privatissima of [[GUSIDescriptorTable]]>= // <Privatissima of [[GUSIDescriptorTable]]>=
static GUSIDescriptorTable * sGUSIDescriptorTable; static GUSIDescriptorTable * sGUSIDescriptorTable;
}; };
@ -141,6 +144,7 @@ private:
// //
// <Hooks for ANSI library interfaces>= // <Hooks for ANSI library interfaces>=
extern "C" { extern "C" {
void GUSISetupDescriptorTable();
void GUSISetupConsole(); void GUSISetupConsole();
void GUSIDefaultSetupConsole(); void GUSIDefaultSetupConsole();
void GUSISetupConsoleDescriptors(); void GUSISetupConsoleDescriptors();

View File

@ -5,6 +5,9 @@
// % Language : C++ // % Language : C++
// % // %
// % $Log$ // % $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 // % Revision 1.1.1.1 2001/03/03 21:50:11 chombier
// % Initial import // % Initial import
// % // %
@ -333,8 +336,11 @@ public:
// [[operator+]] provides a non-destructive variant of [[operator+=]]. // [[operator+]] provides a non-destructive variant of [[operator+=]].
// //
// <Manipulating a [[GUSIFileSpec]]>= // <Manipulating a [[GUSIFileSpec]]>=
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 // Array access replaces the file specification with the [[index]]th object in the
// {\em parent directory} of the specification (allowing the same specification to // {\em parent directory} of the specification (allowing the same specification to
// be reused for reading a directory). // be reused for reading a directory).

View File

@ -4,9 +4,15 @@
// % Author : Matthias Neeracher // % Author : Matthias Neeracher
// % Language : C++ // % Language : C++
// % // %
// % $Log$ // % $Log$
// % Revision 1.1.1.1 2001/03/03 21:50:13 chombier // % Revision 1.21 2001/03/20 08:12:55 neeri
// % Initial import // % 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 // % Revision 1.18 2001/01/17 08:58:06 neeri
// % Releasing 2.1.4 // % Releasing 2.1.4
@ -231,6 +237,11 @@ public:
// //
// <Overridden member functions for [[GUSIOTSocket]]>= // <Overridden member functions for [[GUSIOTSocket]]>=
virtual int ioctl(unsigned int request, va_list arg); 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.
//
// <Overridden member functions for [[GUSIOTSocket]]>=
virtual bool pre_select(bool wantRead, bool wantWrite, bool wantExcept);
// [[getsockopt]] and [[setsockopt]] are available for a variety of options. // [[getsockopt]] and [[setsockopt]] are available for a variety of options.
// //
// <Overridden member functions for [[GUSIOTSocket]]>= // <Overridden member functions for [[GUSIOTSocket]]>=

View File

@ -122,7 +122,7 @@ int fcntl __P((int, int, ...));
/* This properly belongs into stdio.h, but that header is outside of /* This properly belongs into stdio.h, but that header is outside of
GUSI's control GUSI's control
*/ */
#ifdef __MWERKS__ #if defined(__MWERKS__) && !defined(_SFSTDIO_H)
FILE * fdopen(int fildes, char *type); FILE * fdopen(int fildes, char *type);
#else #else
FILE * fdopen(int fildes, const char *type); FILE * fdopen(int fildes, const char *type);

View File

@ -58,6 +58,12 @@ int close __P((int));
size_t confstr __P((int, char *, size_t)); size_t confstr __P((int, char *, size_t));
int dup __P((int)); int dup __P((int));
int dup2 __P((int, 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)); long fpathconf __P((int, int));
char *getcwd __P((char *, size_t)); char *getcwd __P((char *, size_t));
gid_t getegid __P((void)); gid_t getegid __P((void));
@ -142,7 +148,7 @@ int sethostname __P((const char *, int));
int setkey __P((const char *)); int setkey __P((const char *));
int setlogin __P((const char *)); int setlogin __P((const char *));
void *setmode __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 setregid __P((gid_t, gid_t));
int setreuid __P((uid_t, uid_t)); int setreuid __P((uid_t, uid_t));
int setrgid __P((gid_t)); int setrgid __P((gid_t));

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -67,7 +67,8 @@ GUSIProcess::~GUSIProcess()
now += 300; // Accelerate now += 300; // Accelerate
} }
} }
// [[GUSIContext::Setup]] initializes the default context. // [[GUSIContext::Setup]] initializes the default context. We have to employ
// [[sCreatingCurrentContext]] to avoid nasty recursions.
// //
// <Implementation of completion handling>= // <Implementation of completion handling>=
void GUSIContext::Setup(bool threading) void GUSIContext::Setup(bool threading)
@ -75,11 +76,13 @@ void GUSIContext::Setup(bool threading)
bool wasThreading = sHasThreading; bool wasThreading = sHasThreading;
if (threading) if (threading)
sHasThreading = true; sHasThreading = true;
if (!sCurrentContext) { if (!sCurrentContext && !sCreatingCurrentContext) {
MaxApplZone(); // It's about time, too! MaxApplZone(); // It's about time, too!
sCreatingCurrentContext = true;
sCurrentContext = sCurrentContext =
new GUSIContext(kApplicationThreadID); GUSIContextFactory::Instance()->CreateContext(kApplicationThreadID);
sCreatingCurrentContext = false;
} else if (!wasThreading && threading) { } else if (!wasThreading && threading) {
// Sometimes we only recognize that we need threading after the application context // 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 // has already been created. Assuming a disciplined use of threads, we can assume
@ -97,6 +100,7 @@ void GUSIContext::Setup(bool threading)
// <Implementation of completion handling>= // <Implementation of completion handling>=
GUSIContext::Queue GUSIContext::sContexts; GUSIContext::Queue GUSIContext::sContexts;
GUSIContext * GUSIContext::sCurrentContext; GUSIContext * GUSIContext::sCurrentContext;
bool GUSIContext::sCreatingCurrentContext;
bool GUSIContext::sHasThreading; bool GUSIContext::sHasThreading;
OSErr GUSIContext::sError; OSErr GUSIContext::sError;
// <Implementation of completion handling>= // <Implementation of completion handling>=
@ -187,6 +191,7 @@ GUSIContext::~GUSIContext()
// <Implementation of completion handling>= // <Implementation of completion handling>=
void GUSIContext::Queue::LiquidateAll() void GUSIContext::Queue::LiquidateAll()
{ {
GUSIContextFactory::DeleteInstance();
GUSIDescriptorTable::CloseAllDescriptors(); GUSIDescriptorTable::CloseAllDescriptors();
while (!empty()) while (!empty())
front()->Liquidate(); front()->Liquidate();
@ -277,19 +282,46 @@ OSErr GUSINewThread(
return err; return err;
} }
// <Implementation of completion handling>= // <Implementation of completion handling>=
static auto_ptr<GUSIContextFactory> sGUSIContextFactory; #ifdef __MRC__
#pragma noinline_func GUSISetupContextFactory
#endif
#ifdef __MWERKS__
#pragma dont_inline on
#endif
void GUSISetupContextFactory()
{
}
#ifdef __MWERKS__
#pragma dont_inline reset
#endif
// <Implementation of completion handling>=
static GUSIContextFactory * sGUSIContextFactory;
static bool sGUSIContextFactorySetup;
GUSIContextFactory * GUSIContextFactory::Instance() GUSIContextFactory * GUSIContextFactory::Instance()
{ {
if (!sGUSIContextFactory.get()) if (!sGUSIContextFactorySetup) {
sGUSIContextFactorySetup = true;
GUSISetupContextFactory();
}
if (!sGUSIContextFactory)
SetInstance(new GUSIContextFactory()); SetInstance(new GUSIContextFactory());
return sGUSIContextFactory.get(); return sGUSIContextFactory;
} }
void GUSIContextFactory::SetInstance(GUSIContextFactory * instance) void GUSIContextFactory::SetInstance(GUSIContextFactory * instance)
{ {
sGUSIContextFactory = auto_ptr<GUSIContextFactory>(instance); sGUSIContextFactory = instance;
}
void GUSIContextFactory::DeleteInstance()
{
delete sGUSIContextFactory;
sGUSIContextFactory = 0;
} }
GUSIContextFactory::GUSIContextFactory() GUSIContextFactory::GUSIContextFactory()

View File

@ -20,7 +20,7 @@ GUSIDescriptorTable::GUSIDescriptorTable()
// <Member functions for class [[GUSIDescriptorTable]]>= // <Member functions for class [[GUSIDescriptorTable]]>=
#ifdef __MRC__ #ifdef __MRC__
#pragma noinline_func GUSISetupConsole, GUSISetupConsoleDescriptors, GUSISetupConsoleStdio #pragma noinline_func GUSISetupConsole, GUSISetupConsoleDescriptors, GUSISetupConsoleStdio
#pragma noinline_func GUSIStdioClose, GUSIStdioFlush #pragma noinline_func GUSIStdioClose, GUSIStdioFlush, GUSISetupDescriptorTable
#endif #endif
// <Member functions for class [[GUSIDescriptorTable]]>= // <Member functions for class [[GUSIDescriptorTable]]>=
GUSIDescriptorTable * GUSIDescriptorTable::sGUSIDescriptorTable; GUSIDescriptorTable * GUSIDescriptorTable::sGUSIDescriptorTable;
@ -82,6 +82,24 @@ void GUSISetupConsoleDescriptors()
table->InstallSocket(null->open()); 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]].
//
// <Default implementation of [[GUSISetupDescriptorTable]]>=
//
// Prevent inlining to allow override
//
#ifdef __MWERKS__
#pragma dont_inline on
#endif
void GUSISetupDescriptorTable()
{
}
#ifdef __MWERKS__ #ifdef __MWERKS__
#pragma dont_inline reset #pragma dont_inline reset
#endif #endif
@ -91,11 +109,14 @@ GUSIDescriptorTable * GUSIDescriptorTable::Instance()
static bool sNeedConsoleSetup = true; static bool sNeedConsoleSetup = true;
if (!sGUSIDescriptorTable) { if (!sGUSIDescriptorTable) {
sGUSIDescriptorTable = new GUSIDescriptorTable(); GUSISetupDescriptorTable();
if (sNeedConsoleSetup) {
sNeedConsoleSetup = false; if (!sGUSIDescriptorTable)
GUSISetupConsole(); sGUSIDescriptorTable = new GUSIDescriptorTable();
} }
if (sNeedConsoleSetup) {
sNeedConsoleSetup = false;
GUSISetupConsole();
} }
return sGUSIDescriptorTable; return sGUSIDescriptorTable;
} }

View File

@ -460,10 +460,12 @@ OSErr GUSIFileSpec::PrependPathComponent(char *&path, ConstStr63Param component,
char * GUSIFileSpec::RelativePath(const FSSpec & dir) const char * GUSIFileSpec::RelativePath(const FSSpec & dir) const
{ {
GUSIFileSpec current(dir); GUSIFileSpec current(dir);
if (current.fSpec.name[0])
++current;
long relDirID= current.fSpec.parID;
if (current.GetVolume(0)) if (current.GetVolume(0))
return FullPath(); return FullPath();
short relVRef = current.fSpec.vRefNum; short relVRef = current.fSpec.vRefNum;
long relDirID= dir.parID;
current = *this; current = *this;
if (current.GetVolume(0) || current.fSpec.vRefNum != relVRef) if (current.GetVolume(0) || current.fSpec.vRefNum != relVRef)
return FullPath(); return FullPath();

View File

@ -184,7 +184,8 @@ class GUSIMPWDevice : public GUSIDevice {
public: public:
static GUSIMPWDevice * Instance(); 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.
// //
// <Overridden member functions for class [[GUSIMPWDevice]]>= // <Overridden member functions for class [[GUSIMPWDevice]]>=
virtual bool Want(GUSIFileToken & file); virtual bool Want(GUSIFileToken & file);
@ -285,7 +286,7 @@ bool GUSIMPWDevice::Want(GUSIFileToken & file)
{ {
switch (file.WhichRequest()) { switch (file.WhichRequest()) {
case GUSIFileToken::kWillOpen: case GUSIFileToken::kWillOpen:
return file.IsDevice() && (file.StrStdStream(file.Path()) > -1); return !file.IsDevice() || (file.StrStdStream(file.Path()) > -1);
default: default:
return false; return false;
} }
@ -338,6 +339,8 @@ static int TranslateOpenFlags(int mode)
return mpwMode; return mpwMode;
} }
// <Member functions for class [[GUSIMPWDevice]]>= // <Member functions for class [[GUSIMPWDevice]]>=
extern int StandAlone;
GUSISocket * GUSIMPWDevice::open(GUSIFileToken & file, int flags) GUSISocket * GUSIMPWDevice::open(GUSIFileToken & file, int flags)
{ {
if (!ConnectToMPWLibrary()) if (!ConnectToMPWLibrary())
@ -345,16 +348,17 @@ GUSISocket * GUSIMPWDevice::open(GUSIFileToken & file, int flags)
int fd = MPW_open(file.Path(), TranslateOpenFlags(flags)); int fd = MPW_open(file.Path(), TranslateOpenFlags(flags));
if (fd == -1) if (fd == -1) {
return static_cast<GUSISocket *>(nil); return static_cast<GUSISocket *>(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); return stdopen(fd, flags);
} }
// [[stdopen]] handles the GUSI side of the opening. // [[stdopen]] handles the GUSI side of the opening.
// //
// <Member functions for class [[GUSIMPWDevice]]>= // <Member functions for class [[GUSIMPWDevice]]>=
extern int StandAlone;
GUSISocket * GUSIMPWDevice::stdopen(int fd, int flags) GUSISocket * GUSIMPWDevice::stdopen(int fd, int flags)
{ {
if (!ConnectToMPWLibrary()) if (!ConnectToMPWLibrary())

View File

@ -380,7 +380,7 @@ void GUSIhostent::Alloc(size_t size)
{ {
if (size > fAlloc) { if (size > fAlloc) {
if (fName) if (fName)
delete fName; delete[] fName;
h_name = fName = new char[fAlloc = size]; h_name = fName = new char[fAlloc = size];
} }
} }

View File

@ -444,7 +444,7 @@ static int GetInterfaceList(ifconf * conf)
if (++interface == maxInterfaces) if (++interface == maxInterfaces)
goto bufferFull; goto bufferFull;
} }
delete secondaries; delete[] secondaries;
} }
++numInterfaces; ++numInterfaces;
} }
@ -472,7 +472,7 @@ static int GetInterfaceParam(ifreq * ifr, unsigned int request)
InetHost * secondaries = new InetHost[info.fIPSecondaryCount]; InetHost * secondaries = new InetHost[info.fIPSecondaryCount];
OTInetGetSecondaryAddresses(secondaries, &info.fIPSecondaryCount, ifnum); OTInetGetSecondaryAddresses(secondaries, &info.fIPSecondaryCount, ifnum);
info.fAddress = secondaries[ifalias-1]; info.fAddress = secondaries[ifalias-1];
delete secondaries; delete[] secondaries;
} }
switch (request) { switch (request) {
case SIOCGIFADDR: case SIOCGIFADDR:

View File

@ -55,6 +55,8 @@ pascal void GUSIOTNetDBNotify(
default: default:
if (code != kOTProviderWillClose) if (code != kOTProviderWillClose)
result = 0; result = 0;
else
netdb->fCreationContext = nil; // Close & reopen
break; break;
} }
if (result) if (result)
@ -84,6 +86,10 @@ void GUSIOTNetDB::Instantiate()
bool GUSIOTNetDB::Resolver() bool GUSIOTNetDB::Resolver()
{ {
if (!fCreationContext) { if (!fCreationContext) {
if (fSvc) {
OTCloseProvider(fSvc);
fSvc = nil;
}
fCreationContext = GUSIContext::Current(); fCreationContext = GUSIContext::Current();
if (!GUSIOTFactory::Initialize()) if (!GUSIOTFactory::Initialize())
return false; return false;

View File

@ -111,7 +111,7 @@ void GUSIOTSocket::MopupEvents()
delete udErr; delete udErr;
} }
if (fCurEvent & (T_DISCONNECT | T_ORDREL)) { if ((fCurEvent & (T_DISCONNECT | T_ORDREL)) && !(fEvent & T_LISTEN)) {
fReadShutdown = true; fReadShutdown = true;
} }
} }
@ -170,6 +170,7 @@ void GUSIOTSocket::close()
Unbind(); Unbind();
OTCloseProvider(fEndpoint); OTCloseProvider(fEndpoint);
fEvent = 0;
GUSISocket::close(); GUSISocket::close();
} }
@ -317,6 +318,16 @@ int GUSIOTSocket::ioctl(unsigned int request, va_list arg)
return GUSISetPosixError(EOPNOTSUPP); return GUSISetPosixError(EOPNOTSUPP);
} }
// <Member functions for class [[GUSIOTSocket]]>= // <Member functions for class [[GUSIOTSocket]]>=
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;
}
// <Member functions for class [[GUSIOTSocket]]>=
int GUSIOTSocket::getsockopt(int level, int optname, void *optval, socklen_t * optlen) int GUSIOTSocket::getsockopt(int level, int optname, void *optval, socklen_t * optlen)
{ {
int result; int result;
@ -560,6 +571,7 @@ void GUSIOTStreamSocket::MopupEvents()
if (fCurEvent & T_CONNECT) { if (fCurEvent & T_CONNECT) {
GUSI_MESSAGE(("Connect\n")); GUSI_MESSAGE(("Connect\n"));
OTRcvConnect(fEndpoint, fPeerName); OTRcvConnect(fEndpoint, fPeerName);
fEvent |= T_GODATA;
} }
if (fCurEvent & T_ORDREL) { if (fCurEvent & T_ORDREL) {
OTRcvOrderlyDisconnect(fEndpoint); OTRcvOrderlyDisconnect(fEndpoint);
@ -658,9 +670,9 @@ if (err) {
} }
if (fNextListener) { if (fNextListener) {
// <Call [[OTAccept]] and [[return]] if successful>= // <Call [[OTAccept]] and [[return]] if successful>=
GUSIOTSocket * sock = fNextListener; GUSIOTStreamSocket * sock = fNextListener;
fCompletion &= ~(CompleteMask(T_ACCEPTCOMPLETE)); fCompletion &= ~(CompleteMask(T_ACCEPTCOMPLETE));
SetAsyncMacError(OTAccept(fEndpoint, fNextListener->fEndpoint, fNextListener->fPeerName)); SetAsyncMacError(OTAccept(fEndpoint, sock->fEndpoint, sock->fPeerName));
AddContext(); AddContext();
MopupEvents(); MopupEvents();
while (!fAsyncError && !(fCompletion & CompleteMask(T_ACCEPTCOMPLETE))) { while (!fAsyncError && !(fCompletion & CompleteMask(T_ACCEPTCOMPLETE))) {
@ -681,11 +693,13 @@ if (err) {
} }
break; break;
case 0: case 0:
GUSI_MESSAGE(("GUSIOTStreamSocket::accept accepted %08x\n", fNextListener)); GUSI_MESSAGE(("GUSIOTStreamSocket::accept accepted %08x\n", sock));
fNextListener = fNextListener->fNextListener; fNextListener = sock->fNextListener;
sock->fNextListener = nil;
sock->getpeername(address, addrlen); sock->getpeername(address, addrlen);
sock->fSockName = new (fEndpoint) GUSIOTTBind; sock->fSockName = new (fEndpoint) GUSIOTTBind;
sock->fEvent |= T_GODATA; /* Ready to write */
if (sock->fSockName && !fSockName->Copy(fStrategy, sock->fSockName)) if (sock->fSockName && !fSockName->Copy(fStrategy, sock->fSockName))
return sock; return sock;
else else
@ -694,7 +708,7 @@ if (err) {
default: default:
deleteCandidate: deleteCandidate:
GUSI_MESSAGE(("GUSIOTStreamSocket::accept async error %d\n", error)); GUSI_MESSAGE(("GUSIOTStreamSocket::accept async error %d\n", error));
fNextListener = fNextListener->fNextListener; fNextListener = sock->fNextListener;
delete sock; delete sock;
} }
@ -772,6 +786,7 @@ ssize_t GUSIOTStreamSocket::recvfrom(
if (res == kOTNoDataErr) { if (res == kOTNoDataErr) {
if (GUSISetPosixError(GetAsyncError())) if (GUSISetPosixError(GetAsyncError()))
return -1; return -1;
fEvent &= ~(T_DATA|T_EXDATA);
if (!fBlocking) if (!fBlocking)
return GUSISetPosixError(EWOULDBLOCK); return GUSISetPosixError(EWOULDBLOCK);
bool signal = false; bool signal = false;
@ -792,9 +807,15 @@ ssize_t GUSIOTStreamSocket::recvfrom(
buffer.SetLength(res); buffer.SetLength(res);
if (from) if (from)
fPeerName->Unpack(fStrategy, from, fromlen); 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.
//
// <Keep [[T_EXDATA]] flag set until we finish reading expedited data>=
if (exp && (otflags & (T_EXPEDITED|T_MORE)) != T_EXPEDITED)
fEvent |= exp; fEvent |= exp;
}
return res; return res;
} }
// <Member functions for class [[GUSIOTStreamSocket]]>= // <Member functions for class [[GUSIOTStreamSocket]]>=
@ -814,6 +835,7 @@ ssize_t GUSIOTStreamSocket::sendto(
OTResult res = OTSnd(fEndpoint, buf, len, 0); OTResult res = OTSnd(fEndpoint, buf, len, 0);
if (res <= 0) if (res <= 0)
if (res == kOTFlowErr) { if (res == kOTFlowErr) {
fEvent &= ~T_GODATA;
if (!fBlocking) if (!fBlocking)
return done ? done : GUSISetPosixError(EWOULDBLOCK); return done ? done : GUSISetPosixError(EWOULDBLOCK);
bool signal = GUSIContext::Yield(kGUSIBlock); bool signal = GUSIContext::Yield(kGUSIBlock);
@ -839,32 +861,34 @@ bool GUSIOTStreamSocket::select(bool * canRead, bool * canWrite, bool * except)
OTResult state = OTGetEndpointState(fEndpoint); OTResult state = OTGetEndpointState(fEndpoint);
if (canRead) { if (canRead) {
size_t sz;
if (*canRead = if (*canRead =
fReadShutdown // EOF fReadShutdown // EOF
|| fAsyncError // Asynchronous error || fAsyncError // Asynchronous error
|| OTCountDataBytes(fEndpoint, &sz) != kOTNoDataErr // Data available || fEvent & T_DATA // Data available
|| state == T_INCON // Connection pending || state == T_INCON // Connection pending
|| fNextListener // Connection pending || fNextListener // Connection pending
) )
res = true; res = true;
} }
if (canWrite) if (canWrite) {
if (fWriteShutdown || fAsyncError) if (fWriteShutdown || fAsyncError) {
res = *canWrite = true; res = *canWrite = true;
else } else {
switch (state) { switch (state) {
case T_DATAXFER: case T_DATAXFER:
case T_INREL: case T_INREL:
*canWrite = true; if (*canWrite = (fEvent & T_GODATA) != 0)
res = true; res = true;
break; break;
default: default:
*canWrite = false; *canWrite = false;
} }
if (except) }
}
if (except) {
if (*except = (fEvent & T_EXDATA) != 0) if (*except = (fEvent & T_EXDATA) != 0)
res = true; res = true;
}
return res; return res;
} }
// <Member functions for class [[GUSIOTStreamSocket]]>= // <Member functions for class [[GUSIOTStreamSocket]]>=
@ -1057,8 +1081,7 @@ bool GUSIOTDatagramSocket::select(bool * canRead, bool * canWrite, bool * except
OTResult state = OTGetEndpointState(fEndpoint); OTResult state = OTGetEndpointState(fEndpoint);
if (canRead) { if (canRead) {
size_t sz; if (*canRead = fAsyncError || fEvent & T_DATA)
if (*canRead = fAsyncError || OTCountDataBytes(fEndpoint, &sz) != kOTNoDataErr)
res = true; res = true;
} }
if (canWrite) if (canWrite)

View File

@ -148,12 +148,15 @@ done:
return interrupt; return interrupt;
} }
/* /*
* The fSvc field of the GUSIOTNetDB instance is no longer valid after * The fSvc field of the GUSIOTNetDB instance is no longer valid after
* an interface switch in the TCP/IP control panel. * an interface switch in the TCP/IP control panel.
* Let's clear it upon kOTProviderWillClose message. * Let's clear it upon kOTProviderWillClose message.
*/ */
/* no longer needed: GUSI 2.1.6b2 fixes this */
/*
// <Asynchronous notifier function for [[GUSIOTNetDB]]>= // <Asynchronous notifier function for [[GUSIOTNetDB]]>=
inline uint32_t CompleteMask(OTEventCode code) inline uint32_t CompleteMask(OTEventCode code)
{ {
@ -199,8 +202,7 @@ pascal void GUSIOTNetDBNotify(
netdb->fAsyncError = result; netdb->fAsyncError = result;
context->Wakeup(); context->Wakeup();
} }
*/

View File

@ -19,6 +19,7 @@
#include <GUSIInternal.h> #include <GUSIInternal.h>
#include <GUSINetDB.h> #include <GUSINetDB.h>
#include <GUSIOTNetDB.h>
#include <pthread.h> #include <pthread.h>
@ -46,3 +47,79 @@ GUSIFileServiceDB * GUSIFileServiceDB::Instance()
return static_cast<GUSIFileServiceDB *>(nil); return static_cast<GUSIFileServiceDB *>(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 */
/*
// <Asynchronous notifier function for [[GUSIOTNetDB]]>=
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<InetSvcRef>(cookie);
break;
case T_DNRSTRINGTOADDRCOMPLETE:
case T_DNRADDRTONAMECOMPLETE:
context = static_cast<GUSIContext **>(cookie)[-1];
break;
}
break;
default:
if (code != kOTProviderWillClose) {
result = 0;
} else {
netdb->fCreationContext = static_cast<GUSIContext *>(NULL);
}
break;
}
if (result)
netdb->fAsyncError = result;
context->Wakeup();
}
// <Member functions for class [[GUSIOTNetDB]]>=
bool GUSIOTNetDB::Resolver()
{
if (!fCreationContext) {
fCreationContext = GUSIContext::Current();
if (!GUSIOTFactory::Initialize())
return false;
if (fSvc) {
OTCloseProvider(fSvc);
fSvc = static_cast<InetSvcRef>(NULL);
}
fAsyncError = 0;
OSStatus syncError = OTAsyncOpenInternetServices(
kDefaultInternetServicesPath,
0,
reinterpret_cast<OTNotifyProcPtr>(GUSIOTNetDBNotify),
this);
if (!syncError)
while (!fAsyncError && !(fCompletion & CompleteMask(T_OPENCOMPLETE)))
GUSIContext::Yield(kGUSIBlock);
}
return fSvc != 0;
}
*/

Binary file not shown.