Fix for bug 49990 "Networking fails after sleep/wake cycle" on Mac. rtm+, r=pinkerton, wtc, sr =sfraser. Added support for provide will/has closed OT events. NSPRPUB_CLIENT_BRANCH XBL_FORMS_20001011_BASE
authorgordon%netscape.com
Tue, 10 Oct 2000 20:52:17 +0000
branchNSPRPUB_CLIENT_BRANCH
changeset 1587 2fbe4001654d9f8a40e6bad921381c4c79d6dbba
parent 1586 46ee0b6276e55dd443e14335edd37d0148c53a48
child 1588 11a3be25abee3139a88cf55f978c5eec10fa9652
child 1594 bb886030d3b05af0762a80f084bc654f50e9d02d
push idunknown
push userunknown
push dateunknown
reviewerspinkerton, wtc, sr
bugs49990
Fix for bug 49990 "Networking fails after sleep/wake cycle" on Mac. rtm+, r=pinkerton, wtc, sr =sfraser. Added support for provide will/has closed OT events.
pr/src/md/mac/macsockotpt.c
--- a/pr/src/md/mac/macsockotpt.c
+++ b/pr/src/md/mac/macsockotpt.c
@@ -46,17 +46,16 @@ typedef enum SndRcvOpCode {
 
 static struct {
 	PRLock *    lock;
 	InetSvcRef  serviceRef;
 	PRThread *  thread;
 	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  RawEndpointNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie);
 
 static PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady);
 
 extern void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout);
@@ -101,61 +100,89 @@ void _MD_InitNetAccess()
 
     DNSNotifierRoutineUPP	=  NewOTNotifyUPP(DNSNotifierRoutine);
     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! */
 }
 
 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, DNSNotifierRoutineUPP, &dnsContext);
     PR_ASSERT(errOT == kOTNoError);
 
     /* Put us into async mode */
     errOT = OTSetAsynchronous(dnsContext.serviceRef);
     PR_ASSERT(errOT == kOTNoError);
-    
-    gOTInitialized = PR_TRUE;
 }
 
 
-static 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(); 
-	
-	if (code == T_DNRSTRINGTOADDRCOMPLETE) {
+	OSStatus    errOT;
+
 		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
 }
 
 
 static void macsock_map_error(OSStatus err)
 {
     _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
@@ -465,17 +492,16 @@ ErrorExit:
 // kOTXXXX - OT returned error
 // EPROTONOSUPPORT - bad socket type/protocol
 // ENOBUFS - not enough space for another socket, or failure in socket creation routine
 PRInt32 _MD_socket(int domain, int type, int protocol)
 {
     OSStatus    err;
     EndpointRef endpoint;
     
-    if (!gOTInitialized)
     	_MD_FinishInitNetAccess();
 
     // We only deal with internet domain
     if (domain != AF_INET) {
         err = kEPROTONOSUPPORTErr;
         goto ErrorExit;
     }
     
@@ -1858,17 +1884,16 @@ ErrorExit:
 }                               
 
 
 PR_IMPLEMENT(unsigned long) inet_addr(const char *cp)
 {
     OSStatus err;
     InetHost host;    
 
-    if (!gOTInitialized)
     	_MD_FinishInitNetAccess();
 
     err = OTInetStringToHost((char*) cp, &host);
     if (err != kOTNoError)
         return -1;
     
     return host;
 }
@@ -1881,17 +1906,16 @@ static InetHost *sAddresses[kMaxHostAddr
 
 
 PR_IMPLEMENT(struct hostent *) gethostbyname(const char * name)
 {
     OSStatus err;
     PRUint32 index;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
-    if (!gOTInitialized)
     	_MD_FinishInitNetAccess();
 
     me->io_pending       = PR_TRUE;
     me->io_fd            = NULL;
     me->md.osErrCode     = noErr;
 	
 	PR_Lock(dnsContext.lock);	// so we can safely store our thread ptr in dnsContext
 	dnsContext.thread = me;		// so we know what thread to wake up when OTInetStringToAddress completes
@@ -1922,42 +1946,39 @@ ErrorExit:
 }
 
 
 PR_IMPLEMENT(struct hostent *) gethostbyaddr(const void *addr, int addrlen, int type)
 {
     PR_ASSERT(type == AF_INET);
     PR_ASSERT(addrlen == sizeof(struct in_addr));
 
-    if (!gOTInitialized)
     	_MD_FinishInitNetAccess();
 
     OTInetHostToString((InetHost)addr, sHostInfo.name);
     
     return (gethostbyname(sHostInfo.name));
 }
 
 
 PR_IMPLEMENT(char *) inet_ntoa(struct in_addr addr)
 {
-    if (!gOTInitialized)
     	_MD_FinishInitNetAccess();
 
     OTInetHostToString((InetHost)addr.s_addr, sHostInfo.name);
     
     return sHostInfo.name;
 }
 
 
 PRStatus _MD_gethostname(char *name, int namelen)
 {
     OSStatus err;
     InetInterfaceInfo info;
 
-    if (!gOTInitialized)
     	_MD_FinishInitNetAccess();
 
     /*
      *    On a Macintosh, we don't have the concept of a local host name.
      *    We do though have an IP address & everyone should be happy with
      *     a string version of that for a name.
      *    The alternative here is to ping a local DNS for our name, they
      *    will often know it.  This is the cheap, easiest, and safest way out.