diff options
Diffstat (limited to 'pr/src/md/mac/macsockotpt.c')
-rw-r--r-- | pr/src/md/mac/macsockotpt.c | 153 |
1 files changed, 87 insertions, 66 deletions
diff --git a/pr/src/md/mac/macsockotpt.c b/pr/src/md/mac/macsockotpt.c index 7b6e4441..1c9b7d19 100644 --- a/pr/src/md/mac/macsockotpt.c +++ b/pr/src/md/mac/macsockotpt.c @@ -29,6 +29,12 @@ #define GESTALT_OPEN_TPT_TCP_PRESENT gestaltOpenTptTCPPresentMask #include <OpenTptInternet.h> // All the internet typedefs + +#if (UNIVERSAL_INTERFACES_VERSION >= 0x0330) +// for some reason Apple removed this typedef. +typedef struct OTConfiguration OTConfiguration; +#endif + #include "primpl.h" typedef enum SndRcvOpCode { @@ -45,11 +51,10 @@ static struct { void * cookie; } dnsContext; -static PRBool gOTInitialized; static pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie); -static pascal void NotifierRoutine(void * contextPtr, OTEventCode code, - OTResult result, void * cookie); +static pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie); +static pascal void RawEndpointNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie); static PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady); @@ -59,24 +64,20 @@ extern void DoneWaitingOnThisThread(PRThread *thread); #if TARGET_CARBON OTClientContextPtr clientContext = NULL; -OTNotifyUPP DNSNotifierRoutineUPP; -OTNotifyUPP notifierRoutineUPP; - -#define DNS_NOTIFIER_ROUTINE DNSNotifierRoutineUPP -#define NOTIFIER_ROUTINE notifierRoutineUPP -#define INIT_OPEN_TRANSPORT() InitOpenTransport(clientContext, kInitOTForExtensionMask) -#define OT_OPEN_INTERNET_SERVICES(config, flags, err) OTOpenInternetServices(config, flags, err, clientContext) -#define OT_OPEN_ENDPOINT(config, flags, info, err) OTOpenEndpoint(config, flags, info, err, clientContext) +#define INIT_OPEN_TRANSPORT() InitOpenTransportInContext(kInitOTForExtensionMask, &clientContext) +#define OT_OPEN_INTERNET_SERVICES(config, flags, err) OTOpenInternetServicesInContext(config, flags, err, clientContext) +#define OT_OPEN_ENDPOINT(config, flags, info, err) OTOpenEndpointInContext(config, flags, info, err, clientContext) #else -#define DNS_NOTIFIER_ROUTINE DNSNotifierRoutine -#define NOTIFIER_ROUTINE NotifierRoutine #define INIT_OPEN_TRANSPORT() InitOpenTransport() #define OT_OPEN_INTERNET_SERVICES(config, flags, err) OTOpenInternetServices(config, flags, err) #define OT_OPEN_ENDPOINT(config, flags, info, err) OTOpenEndpoint(config, flags, info, err) #endif /* TARGET_CARBON */ +static OTNotifyUPP DNSNotifierRoutineUPP; +static OTNotifyUPP NotifierRoutineUPP; +static OTNotifyUPP RawEndpointNotifierRoutineUPP; void _MD_InitNetAccess() { @@ -97,26 +98,20 @@ void _MD_InitNetAccess() PR_ASSERT(hasOTTCPIP == PR_TRUE); -#if TARGET_CARBON DNSNotifierRoutineUPP = NewOTNotifyUPP(DNSNotifierRoutine); - notifierRoutineUPP = NewOTNotifyUPP(NotifierRoutine); - - errOT = OTAllocClientContext((UInt32)0, &clientContext); - PR_ASSERT(err == kOTNoError); -#endif - + NotifierRoutineUPP = NewOTNotifyUPP(NotifierRoutine); + RawEndpointNotifierRoutineUPP = NewOTNotifyUPP(RawEndpointNotifierRoutine); errOT = INIT_OPEN_TRANSPORT(); PR_ASSERT(err == kOTNoError); + dnsContext.serviceRef = NULL; dnsContext.lock = PR_NewLock(); PR_ASSERT(dnsContext.lock != NULL); dnsContext.thread = _PR_MD_CURRENT_THREAD(); dnsContext.cookie = NULL; - - gOTInitialized = PR_FALSE; - + /* XXX Does not handle absence of open tpt and tcp yet! */ } @@ -124,36 +119,65 @@ static void _MD_FinishInitNetAccess() { OSStatus errOT; + if (dnsContext.serviceRef) + return; + dnsContext.serviceRef = OT_OPEN_INTERNET_SERVICES(kDefaultInternetServicesPath, NULL, &errOT); - if (errOT != kOTNoError) return; /* no network -- oh well */ + if (errOT != kOTNoError) { + dnsContext.serviceRef = NULL; + return; /* no network -- oh well */ + } + PR_ASSERT((dnsContext.serviceRef != NULL) && (errOT == kOTNoError)); /* Install notify function for DNR Address To String completion */ - errOT = OTInstallNotifier(dnsContext.serviceRef, DNS_NOTIFIER_ROUTINE, &dnsContext); + errOT = OTInstallNotifier(dnsContext.serviceRef, DNSNotifierRoutineUPP, &dnsContext); PR_ASSERT(errOT == kOTNoError); /* Put us into async mode */ errOT = OTSetAsynchronous(dnsContext.serviceRef); PR_ASSERT(errOT == kOTNoError); - - gOTInitialized = PR_TRUE; } -pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie) +static pascal void DNSNotifierRoutine(void * contextPtr, OTEventCode otEvent, OTResult result, void * cookie) { #pragma unused(contextPtr) _PRCPU * cpu = _PR_MD_CURRENT_CPU(); + OSStatus errOT; + + dnsContext.thread->md.osErrCode = result; + dnsContext.cookie = cookie; - if (code == T_DNRSTRINGTOADDRCOMPLETE) { - dnsContext.thread->md.osErrCode = result; - dnsContext.cookie = cookie; - if (_PR_MD_GET_INTSOFF()) { - cpu->u.missed[cpu->where] |= _PR_MISSED_IO; - dnsContext.thread->md.missedIONotify = PR_TRUE; - return; - } - DoneWaitingOnThisThread(dnsContext.thread); + switch (otEvent) { + case T_DNRSTRINGTOADDRCOMPLETE: + if (_PR_MD_GET_INTSOFF()) { + cpu->u.missed[cpu->where] |= _PR_MISSED_IO; + dnsContext.thread->md.missedIONotify = PR_TRUE; + return; + } + DoneWaitingOnThisThread(dnsContext.thread); + break; + + case kOTProviderWillClose: + errOT = OTSetSynchronous(dnsContext.serviceRef); + // fall through to kOTProviderIsClosed case + + case kOTProviderIsClosed: + errOT = OTCloseProvider((ProviderRef)dnsContext.serviceRef); + dnsContext.serviceRef = nil; + + if (_PR_MD_GET_INTSOFF()) { + cpu->u.missed[cpu->where] |= _PR_MISSED_IO; + dnsContext.thread->md.missedIONotify = PR_TRUE; + return; + } + DoneWaitingOnThisThread(dnsContext.thread); + break; + + default: // or else we don't handle the event + PR_ASSERT(otEvent==NULL); + } // or else we don't handle the event } @@ -262,7 +286,7 @@ WakeUpNotifiedThread(PRThread *thread, OTResult result) // Notification routine // Async callback routine. // A5 is OK. Cannot allocate memory here -pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie) +static pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie) { PRFilePrivate *secret = (PRFilePrivate *) contextPtr; _MDFileDesc * md = &(secret->md); @@ -301,7 +325,6 @@ pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult resul thread = secret->md.write.thread; secret->md.write.thread = NULL; secret->md.write.cookie = cookie; - secret->md.connectionOpen = PR_TRUE; break; case T_DATA: // Standard data is available @@ -323,7 +346,6 @@ pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult resul err = OTRcvDisconnect(endpoint, &discon); PR_ASSERT(err == kOTNoError); secret->md.exceptReady = PR_TRUE; - secret->md.connectionOpen = PR_FALSE; // wake up waiting threads, if any result = -3199 - discon.reason; // obtain the negative error code @@ -356,7 +378,7 @@ pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult resul PR_ASSERT(err == kOTNoError); secret->md.readReady = PR_TRUE; // mark readable (to emulate bsd sockets) // remember connection is closed, so we can return 0 on read or receive - secret->md.connectionOpen = PR_FALSE; + secret->md.orderlyDisconnect = PR_TRUE; thread = secret->md.read.thread; secret->md.read.thread = NULL; @@ -473,8 +495,7 @@ PRInt32 _MD_socket(int domain, int type, int protocol) OSStatus err; EndpointRef endpoint; - if (!gOTInitialized) - _MD_FinishInitNetAccess(); + _MD_FinishInitNetAccess(); // We only deal with internet domain if (domain != AF_INET) { @@ -1037,7 +1058,7 @@ typedef struct RawEndpointAndThread // Notification routine for raw endpoints not yet attached to a PRFileDesc. // Async callback routine. // A5 is OK. Cannot allocate memory here -pascal void RawEndpointNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie) +static pascal void RawEndpointNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie) { RawEndpointAndThread *endthr = (RawEndpointAndThread *) contextPtr; PRThread * thread = endthr->thread; @@ -1194,7 +1215,7 @@ PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRInterva endthr->thread = me; endthr->endpoint = (EndpointRef) newosfd; - err = OTInstallNotifier((ProviderRef) newosfd, RawEndpointNotifierRoutine, endthr); + err = OTInstallNotifier((ProviderRef) newosfd, RawEndpointNotifierRoutineUPP, endthr); PR_ASSERT(err == kOTNoError); err = OTSetAsynchronous((EndpointRef) newosfd); @@ -1350,6 +1371,7 @@ static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 bytesLeft = amount; PR_ASSERT(flags == 0); + PR_ASSERT(opCode == kSTREAM_SEND || opCode == kSTREAM_RECEIVE); if (endpoint == NULL) { err = kEBADFErr; @@ -1361,11 +1383,6 @@ static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount, goto ErrorExit; } - if (opCode != kSTREAM_SEND && opCode != kSTREAM_RECEIVE) { - err = kEINVALErr; - goto ErrorExit; - } - while (bytesLeft > 0) { PrepareForAsyncCompletion(me, fd->secret->md.osfd); @@ -1434,6 +1451,10 @@ static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount, } me->io_pending = PR_FALSE; + if (opCode == kSTREAM_SEND) + fd->secret->md.write.thread = nil; + else + fd->secret->md.read.thread = nil; if (result > 0) { buf = (void *) ( (UInt32) buf + (UInt32)result ); @@ -1442,9 +1463,6 @@ static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount, return result; } else { switch (result) { - case kOTOutStateErr: // it has been closed - return 0; - case kOTLookErr: PR_ASSERT(!"call to OTLook() required after all."); break; @@ -1464,6 +1482,9 @@ static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount, goto ErrorExit; break; + case kOTOutStateErr: // if provider already closed, fall through to handle error + if (fd->secret->md.orderlyDisconnect) + return 0; default: err = result; goto ErrorExit; @@ -1471,9 +1492,13 @@ static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount, } } + PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == nil : + fd->secret->md.read.thread == nil); return amount; ErrorExit: + PR_ASSERT(opCode == kSTREAM_SEND ? fd->secret->md.write.thread == nil : + fd->secret->md.read.thread == nil); macsock_map_error(err); return -1; } @@ -1752,7 +1777,7 @@ void _MD_initfiledesc(PRFileDesc *fd) PR_ASSERT(fd->secret->md.miscLock == NULL); fd->secret->md.miscLock = PR_NewLock(); PR_ASSERT(fd->secret->md.miscLock != NULL); - fd->secret->md.connectionOpen = PR_FALSE; // starts out closed + fd->secret->md.orderlyDisconnect = PR_FALSE; fd->secret->md.readReady = PR_FALSE; // let's not presume we have data ready to read fd->secret->md.writeReady = PR_TRUE; // let's presume we can write unless we hear otherwise fd->secret->md.exceptReady = PR_FALSE; @@ -1789,7 +1814,7 @@ void _MD_makenonblock(PRFileDesc *fd) // fd changes, but the secret structure does not; // (b) the notifier func refers only to the secret data structure // anyway. - err = OTInstallNotifier(endpointRef, NOTIFIER_ROUTINE, fd->secret); + err = OTInstallNotifier(endpointRef, NotifierRoutineUPP, fd->secret); PR_ASSERT(err == kOTNoError); // Now that we have a NotifierRoutine installed, we can make the endpoint asynchronous @@ -1862,11 +1887,11 @@ PR_IMPLEMENT(unsigned long) inet_addr(const char *cp) OSStatus err; InetHost host; - if (!gOTInitialized) - _MD_FinishInitNetAccess(); + _MD_FinishInitNetAccess(); err = OTInetStringToHost((char*) cp, &host); - PR_ASSERT(err == kOTNoError); + if (err != kOTNoError) + return -1; return host; } @@ -1884,8 +1909,7 @@ PR_IMPLEMENT(struct hostent *) gethostbyname(const char * name) PRUint32 index; PRThread *me = _PR_MD_CURRENT_THREAD(); - if (!gOTInitialized) - _MD_FinishInitNetAccess(); + _MD_FinishInitNetAccess(); me->io_pending = PR_TRUE; me->io_fd = NULL; @@ -1925,8 +1949,7 @@ PR_IMPLEMENT(struct hostent *) gethostbyaddr(const void *addr, int addrlen, int PR_ASSERT(type == AF_INET); PR_ASSERT(addrlen == sizeof(struct in_addr)); - if (!gOTInitialized) - _MD_FinishInitNetAccess(); + _MD_FinishInitNetAccess(); OTInetHostToString((InetHost)addr, sHostInfo.name); @@ -1936,8 +1959,7 @@ PR_IMPLEMENT(struct hostent *) gethostbyaddr(const void *addr, int addrlen, int PR_IMPLEMENT(char *) inet_ntoa(struct in_addr addr) { - if (!gOTInitialized) - _MD_FinishInitNetAccess(); + _MD_FinishInitNetAccess(); OTInetHostToString((InetHost)addr.s_addr, sHostInfo.name); @@ -1950,8 +1972,7 @@ PRStatus _MD_gethostname(char *name, int namelen) OSStatus err; InetInterfaceInfo info; - if (!gOTInitialized) - _MD_FinishInitNetAccess(); + _MD_FinishInitNetAccess(); /* * On a Macintosh, we don't have the concept of a local host name. |