fixup commit for tag 'NSPRPUB_RELEASE_3_1' NSPRPUB_RELEASE_3_1
authorcvs2hg
Wed, 17 Mar 1999 21:25:09 +0000
changeset 496 44521a18e26e8b8385d0b7acfd6f10b3a72e911c
parent 495 ea776f3d0d2549007ebc65f546eeeba6340e2134
child 499 bb614fdbf1c9adc96b017a0fa3bc29f40433494a
push idunknown
push userunknown
push dateunknown
fixup commit for tag 'NSPRPUB_RELEASE_3_1'
pr/include/md/_macos.h
pr/include/private/primpl.h
pr/src/io/prio.c
pr/src/md/mac/macsockotpt.c
--- a/pr/include/md/_macos.h
+++ b/pr/include/md/_macos.h
@@ -46,21 +46,22 @@
 #include <setjmp.h>
 #include <Errors.h>
 
 struct _MDProcess {
     PRInt8 notused;
 };
 
 struct _MDThread {
-    jmp_buf      jb;
-    int          osErrCode;
-	PRLock *     asyncIOLock;
-	PRCondVar *  asyncIOCVar;
-    PRBool       notifyPending;
+    jmp_buf jb;
+    int osErrCode;
+	PRLock		*asyncIOLock;
+	PRCondVar	*asyncIOCVar;
+    void *cookie;
+    PRBool notifyPending;
 };
 
 struct _MDThreadStack {
     PRInt8 notused;
 };
 
 struct _MDLock {
     PRInt8 notused;
@@ -77,31 +78,18 @@ struct _MDSemaphore {
 struct _MDSegment {
     PRInt8 notused;
 };
 
 struct _MDCPU {
     PRInt8 notused;
 };
 
-typedef struct _MDSocketCallerInfo {
-	PRThread *	thread;
-	void *		cookie;
-} _MDSocketCallerInfo;
-
 struct _MDFileDesc {
-    PRInt32     osfd;
-	PRBool      connectionOpen;
-	PRBool      readReady;
-	PRBool      writeReady;
-	PRBool      exceptReady;
-	PRLock *    miscLock;
-	_MDSocketCallerInfo  misc;
-	_MDSocketCallerInfo  read;
-	_MDSocketCallerInfo  write;
+    PRInt32 osfd;
 };
 
 /*
 ** Iinitialization Related definitions
 */
 
 #define _MD_EARLY_INIT		_MD_EarlyInit
 #define _MD_FINAL_INIT		_MD_FinalInit
@@ -384,18 +372,17 @@ extern PRStatus _MD_setsockopt(PRFileDes
 #define _MD_ACCEPT			_MD_accept
 #define _MD_CONNECT			_MD_connect
 #define _MD_SEND			_MD_send
 #define _MD_RECV			_MD_recv
 #define _MD_CLOSE_SOCKET	_MD_closesocket
 #define _MD_SENDTO			_MD_sendto
 #define _MD_RECVFROM		_MD_recvfrom
 #define _MD_PR_POLL			_MD_poll
-#define _MD_INIT_FILEDESC	_MD_initfiledesc
-#define _MD_FREE_FILEDESC	_MD_freefiledesc
+#define _MD_INIT_FILEDESC(fd)
 #define _MD_MAKE_NONBLOCK	_MD_makenonblock
 
 #define _MD_GET_SOCKET_ERROR() 		_PR_MD_CURRENT_THREAD()->md.osErrCode
 
 #define _PR_MD_MAP_SELECT_ERROR(x) 	(x)
 /*
 ** Netdb Related definitions
 */
--- a/pr/include/private/primpl.h
+++ b/pr/include/private/primpl.h
@@ -972,21 +972,16 @@ extern char * _PR_MD_READ_DIR(_MDDir *md
 
 extern PRInt32 _PR_MD_CLOSE_DIR(_MDDir *md);
 #define    _PR_MD_CLOSE_DIR _MD_CLOSE_DIR
 
 /* I/O related */
 extern void _PR_MD_INIT_FILEDESC(PRFileDesc *fd);
 #define    _PR_MD_INIT_FILEDESC _MD_INIT_FILEDESC
 
-#ifdef XP_MAC
-extern void _PR_MD_FREE_FILEDESC(PRFileDesc *fd);
-#define    _PR_MD_FREE_FILEDESC _MD_FREE_FILEDESC
-#endif
-
 extern void _PR_MD_MAKE_NONBLOCK(PRFileDesc *fd);
 #define    _PR_MD_MAKE_NONBLOCK _MD_MAKE_NONBLOCK
 
 /* File I/O related */
 extern PRInt32 _PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode);
 #define    _PR_MD_OPEN _MD_OPEN
 
 extern PRInt32 _PR_MD_CLOSE_FILE(PRInt32 osfd);
--- a/pr/src/io/prio.c
+++ b/pr/src/io/prio.c
@@ -96,19 +96,16 @@ PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDe
     }
 
     return fd;
 }
 
 PR_IMPLEMENT(void) PR_FreeFileDesc(PRFileDesc *fd)
 {
     PR_ASSERT(fd);
-#ifdef XP_MAC
-	_PR_MD_FREE_FILEDESC(fd);
-#endif
     _PR_Putfd(fd);
 }
 
 /*
 ** Wait for some i/o to finish on one or more more poll descriptors.
 */
 PR_IMPLEMENT(PRInt32) PR_Poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
 {
--- a/pr/src/md/mac/macsockotpt.c
+++ b/pr/src/md/mac/macsockotpt.c
@@ -15,112 +15,92 @@
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
 /* This turns on UNIX style errors in OT 1.1 headers */
 #define OTUNIXERRORS 1
 
 #include <Gestalt.h>
+
+/*
+    Since Apple put out new headers without
+    putting in a way to test for them, we found some random symbol which
+    isn't defined in the "1.1" headers.
+*/
 #include <OpenTransport.h>
-
+#ifdef kOTInvalidStreamRef
+/* old */
+#define GESTALT_OPEN_TPT_PRESENT        gestaltOpenTptPresent
+#define GESTALT_OPEN_TPT_TCP_PRESENT    gestaltOpenTptTCPPresent
+#else
+/* new */
 #define GESTALT_OPEN_TPT_PRESENT        gestaltOpenTptPresentMask
 #define GESTALT_OPEN_TPT_TCP_PRESENT    gestaltOpenTptTCPPresentMask
+#endif
 
 #include <OpenTptInternet.h>    // All the internet typedefs
 #include "primpl.h"
 
 typedef enum SndRcvOpCode {
     kSTREAM_SEND,
-    kSTREAM_RECEIVE,
+    kSTREAM_RECEIVE    ,
     kDGRAM_SEND,
     kDGRAM_RECEIVE
 } SndRcvOpCode;
 
-static struct {
-	PRLock *    lock;
-	InetSvcRef  serviceRef;
-	PRThread *  thread;
-	void *      cookie;
-} dnsContext;
 
+static InetSvcRef sSvcRef;
 
-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 PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady);
+static PRBool GetState(EndpointRef endpoint, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady);
 
 extern void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout);
 extern void DoneWaitingOnThisThread(PRThread *thread);
 
-
 void _MD_InitNetAccess()
 {
-    OSErr       err;
+    OSErr        err;
     OSStatus    errOT;
-    PRBool      hasOTTCPIP = PR_FALSE;
-    PRBool      hasOT = PR_FALSE;
-    long        gestaltResult;
+    PRBool         hasOTTCPIP = PR_FALSE;
+    PRBool         hasOT = PR_FALSE;
+    long         gestaltResult;
+    PRThread *me = _PR_MD_CURRENT_THREAD();
     
     err = Gestalt(gestaltOpenTpt, &gestaltResult);
     if (err == noErr)
         if (gestaltResult & GESTALT_OPEN_TPT_PRESENT)
             hasOT = PR_TRUE;
     
     if (hasOT)
         if (gestaltResult & GESTALT_OPEN_TPT_TCP_PRESENT)
             hasOTTCPIP = PR_TRUE;
         
     PR_ASSERT(hasOTTCPIP == PR_TRUE);
 
     errOT = InitOpenTransport();
     PR_ASSERT(err == kOTNoError);
-	
-	dnsContext.lock = PR_NewLock();
-	PR_ASSERT(dnsContext.lock != NULL);
 
-	dnsContext.thread = _PR_MD_CURRENT_THREAD();
-	dnsContext.cookie = NULL;
-	
-    dnsContext.serviceRef = OTOpenInternetServices(kDefaultInternetServicesPath, NULL, &errOT);
+    sSvcRef = OTOpenInternetServices(kDefaultInternetServicesPath, NULL, &errOT);
     if (errOT != kOTNoError) return;    /* no network -- oh well */
-    PR_ASSERT((dnsContext.serviceRef != NULL) && (errOT == kOTNoError));
+    PR_ASSERT((sSvcRef != NULL) && (errOT == kOTNoError));
 
     /* Install notify function for DNR Address To String completion */
-    errOT = OTInstallNotifier(dnsContext.serviceRef, DNSNotifierRoutine, &dnsContext);
+    errOT = OTInstallNotifier(sSvcRef, NotifierRoutine, me);
     PR_ASSERT(errOT == kOTNoError);
 
     /* Put us into async mode */
-    errOT = OTSetAsynchronous(dnsContext.serviceRef);
+    errOT = OTSetAsynchronous(sSvcRef);
     PR_ASSERT(errOT == kOTNoError);
 
 /* XXX Does not handle absence of open tpt and tcp yet! */
 }
 
-
-pascal void  DNSNotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie)
-{
-#pragma unused(contextPtr)
-    _PRCPU *    cpu    = _PR_MD_CURRENT_CPU(); 
-	
-	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.notifyPending = PR_TRUE;
-			return;
-		}
-		DoneWaitingOnThisThread(dnsContext.thread);
-	}
-	// or else we don't handle the event
-}
-
-
 static void macsock_map_error(OSStatus err)
 {
     _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
 
     if (IsEError(err) || (err >= EPERM && err <= ELASTERRNO)) {
     switch (IsEError(err) ? OSStatus2E(err) : err) {
         case EBADF:
             PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
@@ -188,195 +168,118 @@ static void macsock_map_error(OSStatus e
         default:
             PR_ASSERT(0);
             PR_SetError(PR_UNKNOWN_ERROR, err);
             break;
         }
     }
 }
 
-
-
-static void PrepareForAsyncCompletion(PRThread * thread, PRFileDesc * fd)
+static void PrepareThreadForAsyncIO(PRThread *thread, EndpointRef endpoint, PRInt32 osfd)
 {
-    thread->io_pending       = PR_TRUE;
-    thread->io_fd            = fd->secret->md.osfd;
-    thread->md.osErrCode     = noErr;
+    OSStatus err;
+
+    thread->io_pending = PR_TRUE;
+    thread->io_fd = osfd;
+    thread->md.osErrCode = noErr;
+
+    OTRemoveNotifier(endpoint);
+    err = OTInstallNotifier(endpoint, NotifierRoutine, thread);
+    PR_ASSERT(err == kOTNoError);
 }
 
-
 // Notification routine
 // Async callback routine.
 // A5 is OK. Cannot allocate memory here
 pascal void  NotifierRoutine(void * contextPtr, OTEventCode code, OTResult result, void * cookie)
 {
-	PRFileDesc *  fd       = (PRFileDesc *) contextPtr;
-	EndpointRef   endpoint = (EndpointRef)fd->secret->md.osfd;
-    PRThread *    thread   = NULL;
-    _PRCPU *      cpu      = _PR_MD_CURRENT_CPU(); 
-	OSStatus      err;
-    TDiscon       discon;
-	OTResult	  resultOT;
-
+    PRThread * thread = (PRThread *) contextPtr;
+    _PRCPU *cpu = _PR_MD_CURRENT_CPU();    
+    
     switch (code)
     {
-// OTLook Events - 
-        case T_LISTEN:        // A connection request is available
-            PR_ASSERT(!"T_LISTEN Not implemented");  // listen or reject?
-            break;
-			
-        case T_CONNECT:      // Confirmation of a connect request
-			// cookie = sndCall parameter from OTConnect()
-            err = OTRcvConnect(endpoint, NULL);
-            PR_ASSERT(err == kOTNoError);
-
-			// wake up waiting thread, if any
-            thread = fd->secret->md.write.thread;
-            fd->secret->md.write.thread    = NULL;
-            fd->secret->md.write.cookie    = cookie;
-            fd->secret->md.connectionOpen  = PR_TRUE;
-            break;
-
-        case T_DATA:        // Standard data is available
-			fd->secret->md.readReady = PR_TRUE;
-
-			// wake up waiting thread, if any
-            thread = fd->secret->md.read.thread;
-            fd->secret->md.read.thread    = NULL;
-            fd->secret->md.read.cookie    = cookie;
-			break;
-
-        case T_EXDATA:      // Expedited data is available
-            PR_ASSERT(!"T_EXDATA Not implemented");
-			return;
-
-        case T_DISCONNECT:  // A disconnect is available
-            memset(&discon, 0 , sizeof(discon));
-            err = OTRcvDisconnect(endpoint, &discon);
-            PR_ASSERT(err == kOTNoError);
-            macsock_map_error(discon.reason);
-            fd->secret->md.exceptReady     = PR_TRUE;
-            fd->secret->md.connectionOpen  = PR_FALSE;
-            break;
-		
-        case T_ERROR:       // obsolete/unused in library
-            PR_ASSERT(!"T_ERROR Not implemented");
-			return;		
-		
-        case T_UDERR:       // UDP Send error; clear the error
-			(void) OTRcvUDErr((EndpointRef) cookie, NULL);
+// Async Completion Event
+        case T_OPENCOMPLETE:
+        case T_BINDCOMPLETE:
+        case T_UNBINDCOMPLETE:
+        case T_GETPROTADDRCOMPLETE:
+        case T_ACCEPTCOMPLETE:
+// Connect callback
+        case T_CONNECT:
+// Standard or expedited data is available
+        case T_DATA:
+        case T_EXDATA:
+// Standard or expedited data Flow control lifted
+        case T_GODATA:
+        case T_GOEXDATA:
+// Asynchronous Listen Event
+        case T_LISTEN:
+// DNR String To Address Complete Event
+        case T_DNRSTRINGTOADDRCOMPLETE:
+// Option Management Request Complete Event
+        case T_OPTMGMTCOMPLETE:
+            thread->md.osErrCode = result;
+            thread->md.cookie = cookie;
+            if (_PR_MD_GET_INTSOFF()) {
+                cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
+                thread->md.notifyPending = PR_TRUE;
+                return;
+            }
+            DoneWaitingOnThisThread(thread);
             break;
 
-        case T_ORDREL:      // An orderly release is available
-            err = OTRcvOrderlyDisconnect(endpoint);
-            PR_ASSERT(err == kOTNoError);
-            fd->secret->md.readReady      = PR_TRUE;   // mark readable (to emulate bsd sockets)
-            // remember connection is closed, so we can return 0 on read or receive
-			fd->secret->md.connectionOpen = PR_FALSE;
-            break;		
+// T_ORDREL orderly release is available;  nothing to do
+        case T_ORDREL:
+            break;
 
-        case T_GODATA:   // Flow control lifted on standard data
-            fd->secret->md.writeReady = PR_TRUE;
-			resultOT = OTLook(endpoint);		// clear T_GODATA event
-			PR_ASSERT(resultOT == T_GODATA);
-			
-			// wake up waiting thread, if any
-            thread = fd->secret->md.write.thread;
-            fd->secret->md.write.thread    = NULL;
-            fd->secret->md.write.cookie    = cookie;
+// T_PASSCON; nothing to do
+        case T_PASSCON:
             break;
 
-        case T_GOEXDATA: // Flow control lifted on expedited data
-            PR_ASSERT(!"T_GOEXDATA Not implemented");
-			return;
-
-        case T_REQUEST:  // An Incoming request is available
-            PR_ASSERT(!"T_REQUEST Not implemented");
-            return;
-
-        case T_REPLY:    // An Incoming reply is available
-            PR_ASSERT(!"T_REPLY Not implemented");
-            return;
-
-        case T_PASSCON:  // State is now T_DATAXFER
-			// OTAccept() complete, receiving endpoint in T_DATAXFER state
-			// cookie = OTAccept() resRef parameter
-			break;
-
-        case T_RESET:    // Protocol has been reset
-            PR_ASSERT(!"T_RESET Not implemented");
-			return;
-            
-// Async Completion Events
-        case T_BINDCOMPLETE:
-        case T_UNBINDCOMPLETE:
-        case T_ACCEPTCOMPLETE:
-        case T_OPTMGMTCOMPLETE:
-        case T_GETPROTADDRCOMPLETE:
-			thread = fd->secret->md.misc.thread;
-            fd->secret->md.misc.thread    = NULL;
-            fd->secret->md.misc.cookie    = cookie;
+// T_DISCONNECT; disconnect is available; nothing to do
+        case T_DISCONNECT:
             break;
 
-//      case T_OPENCOMPLETE:			// we open endpoints in synchronous mode
-//      case T_REPLYCOMPLETE:
-//      case T_DISCONNECTCOMPLETE:		// we don't call OTSndDisconnect()
-//      case T_RESOLVEADDRCOMPLETE:
-//      case T_GETINFOCOMPLETE:
-//      case T_SYNCCOMPLETE:
-//      case T_MEMORYRELEASED:			// only if OTAckSends() called on endpoint
-//      case T_REGNAMECOMPLETE:
-//      case T_DELNAMECOMPLETE:
-//      case T_LKUPNAMECOMPLETE:
-//      case T_LKUPNAMERESULT:
-		// OpenTptInternet.h
-//      case T_DNRSTRINGTOADDRCOMPLETE:	// DNS is handled by dnsContext in DNSNotifierRoutine()
-//      case T_DNRADDRTONAMECOMPLETE:
-//      case T_DNRSYSINFOCOMPLETE:
-//      case T_DNRMAILEXCHANGECOMPLETE:
-//      case T_DNRQUERYCOMPLETE:
+// UDP Send error; clear the error
+        case T_UDERR:
+            (void) OTRcvUDErr((EndpointRef) cookie, NULL);
+            break;
+            
         default:
-        	// we should probably have a bit more sophisticated handling of kOTSystemSleep, etc.
-			// PR_ASSERT(code != 0);
-            return;
+            PR_ASSERT(0);
+            break;
     }
-
-	if (thread) {
-		thread->md.osErrCode = result;
-		if (_PR_MD_GET_INTSOFF()) {
-			cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
-			thread->md.notifyPending = PR_TRUE;
-			return;
-		}
-		DoneWaitingOnThisThread(thread);
-	}
 }
 
 
 static OSErr CreateSocket(int type, EndpointRef *endpoint)
 {
     OSStatus err;
     PRThread *me = _PR_MD_CURRENT_THREAD();
-    char *  configName;
-    OTConfiguration *config;
-    EndpointRef ep;
-
-	// for now we just create the endpoint
-	// we'll make it asynchronous and give it a notifier routine in _MD_makenonblock()
 
     switch (type){
-        case SOCK_STREAM:   configName = kTCPName;  break;
-        case SOCK_DGRAM:    configName = kUDPName;  break;
+        case SOCK_STREAM:
+            err = OTAsyncOpenEndpoint(OTCreateConfiguration(kTCPName), 0, NULL, 
+                    NotifierRoutine, me);
+            break;
+        case SOCK_DGRAM:
+            err = OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName), 0, NULL,
+                    NotifierRoutine, me);
+            break;
     }
-    config = OTCreateConfiguration(configName);
-    ep = OTOpenEndpoint(config, 0, NULL, &err);
     if (err != kOTNoError)
         goto ErrorExit;
 
-    *endpoint = ep;
+    WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
+
+    err = me->md.osErrCode;
+    if (err != kOTNoError)
+        goto ErrorExit;
+
+    *endpoint = me->md.cookie;
     PR_ASSERT(*endpoint != NULL);
 
     return kOTNoError;
 
 ErrorExit:
     return err;
 }
 
@@ -431,84 +334,84 @@ PRInt32 _MD_socket(int domain, int type,
 
     return ((PRInt32)endpoint);
 
 ErrorExit:
     macsock_map_error(err);
     return -1;
 }
 
-
 // Errors:
-// EBADF  -- bad socket id
+// EBADF -- bad socket id
 // EFAULT -- bad address format
 PRInt32 _MD_bind(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen)
 {
+    PRInt32 osfd = fd->secret->md.osfd;
     OSStatus err;
-    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+    EndpointRef endpoint = (EndpointRef) osfd;
     TBind bindReq;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     PRUint32 retryCount = 0;
 
     if (endpoint == NULL) {
         err = kEBADFErr;
         goto ErrorExit;
     }
         
     if (addr == NULL) {
         err = kEFAULTErr;
         goto ErrorExit;
     }
         
+    // setup our request
+#if 0
+    if ((addr->inet.port == 0) || (addr->inet.ip == 0))
+        bindReq.addr.len = 0;
+    else
+#endif
 /*
- * There seems to be a bug with OT related to OTBind failing with kOTNoAddressErr even though
+ * There seems to be a bug with OT ralted to OTBind failing with kOTNoAddressErr eventhough
  * a proper legal address was supplied.  This happens very rarely and just retrying the
  * operation after a certain time (less than 1 sec. does not work) seems to succeed.
  */
 
 TryAgain:
-    // setup our request
     bindReq.addr.len = addrlen;
         
     bindReq.addr.maxlen = addrlen;
     bindReq.addr.buf = (UInt8*) addr;
     bindReq.qlen = 1;
-
-	PR_Lock(fd->secret->md.miscLock);
-    PrepareForAsyncCompletion(me, fd);
-	fd->secret->md.misc.thread = me;
+    
+    PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
     err = OTBind(endpoint, &bindReq, NULL);
-    if (err != kOTNoError) {
-	    me->io_pending = PR_FALSE;
-	    PR_Unlock(fd->secret->md.miscLock);
+    if (err != kOTNoError)
         goto ErrorExit;
-	}
 
     WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
-	PR_Unlock(fd->secret->md.miscLock);
 
     err = me->md.osErrCode;
     if (err != kOTNoError)
         goto ErrorExit;
 
+    PR_ASSERT(me->md.cookie == NULL);
+
     return kOTNoError;
 
 ErrorExit:
     if ((err == kOTNoAddressErr) && (++retryCount <= 4)) {
         long finalTicks;
     
         Delay(100,&finalTicks);
         goto TryAgain;
     }
     macsock_map_error(err);
     return -1;
 }
 
-
 // Errors:
 // EBADF -- bad socket id
 PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog)
 {
 #if 0
     PRInt32 osfd = fd->secret->md.osfd;
     OSStatus err;
     EndpointRef endpoint = (EndpointRef) osfd;
@@ -526,43 +429,43 @@ PRInt32 _MD_listen(PRFileDesc *fd, PRInt
         
     addr.inet.port = addr.inet.ip = 0;
 
     bindReq.addr.maxlen = PR_NETADDR_SIZE (&addr);
     bindReq.addr.len = 0;
     bindReq.addr.buf = (UInt8*) &addr;
     bindReq.qlen = 0;
     
-    PrepareForAsyncCompletion(me, osfd);    
+    PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
     err = OTGetProtAddress(endpoint, &bindReq, NULL);
     if (err != kOTNoError)
         goto ErrorExit;
 
     WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
 
     err = me->md.osErrCode;
     if (err != kOTNoError)
         goto ErrorExit;
 
-    PrepareForAsyncCompletion(me, osfd);    
+    PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
     err = OTUnbind(endpoint);
     if (err != kOTNoError)
         goto ErrorExit;
 
     WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
 
     err = me->md.osErrCode;
     if (err != kOTNoError)
         goto ErrorExit;
 
     bindReq.qlen = backlog;
     
-    PrepareForAsyncCompletion(me, osfd);    
+    PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
     err = OTBind(endpoint, &bindReq, NULL);
     if (err != kOTNoError)
         goto ErrorExit;
 
     WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
 
     err = me->md.osErrCode;
@@ -578,23 +481,23 @@ ErrorExit:
     return -1;
 #endif
 
 #pragma unused (fd, backlog)    
     return kOTNoError;
 
 }
 
-
 // Errors:
 // EBADF -- bad socket id
 PRInt32 _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
 {
+    PRInt32 osfd = fd->secret->md.osfd;
     OSStatus err;
-    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+    EndpointRef endpoint = (EndpointRef) osfd;
     TBind bindReq;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
     if (endpoint == NULL) {
         err = kEBADFErr;
         goto ErrorExit;
     }
         
@@ -609,46 +512,42 @@ PRInt32 _MD_getsockname(PRFileDesc *fd, 
     
     PR_ASSERT(PR_NETADDR_SIZE(addr) >= (*addrlen));
 
     bindReq.addr.len = *addrlen;
     bindReq.addr.maxlen = *addrlen;
     bindReq.addr.buf = (UInt8*) addr;
     bindReq.qlen = 0;
     
-	PR_Lock(fd->secret->md.miscLock);
-    PrepareForAsyncCompletion(me, fd);    
-	fd->secret->md.misc.thread = me;
+    PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
     err = OTGetProtAddress(endpoint, &bindReq, NULL);
-    if (err != kOTNoError) {
-	    me->io_pending = PR_FALSE;
-	    PR_Unlock(fd->secret->md.miscLock);
+    if (err != kOTNoError)
         goto ErrorExit;
-	}
 
     WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
-	PR_Unlock(fd->secret->md.miscLock);
 
     err = me->md.osErrCode;
     if (err != kOTNoError)
         goto ErrorExit;
 
+    PR_ASSERT(me->md.cookie == &bindReq);
+
     return kOTNoError;
 
 ErrorExit:
     macsock_map_error(err);
     return -1;
 }
 
-
 PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen)
 {
     OSStatus err;
-    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+    PRInt32 osfd = fd->secret->md.osfd;
+    EndpointRef endpoint = (EndpointRef) osfd;
     TOptMgmt cmd;
     TOption *opt;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData)];
     
     if (endpoint == NULL) {
         err = kEBADFErr;
         goto ErrorExit;
@@ -672,29 +571,23 @@ PRStatus _MD_getsockopt(PRFileDesc *fd, 
     opt->name = optname;
     opt->status = 0;
     
     cmd.opt.len = sizeof(TOption);
     cmd.opt.maxlen = sizeof(optionBuffer);
     cmd.opt.buf = (UInt8*)optionBuffer;
     cmd.flags = T_CURRENT;
 
-	PR_Lock(fd->secret->md.miscLock);
-    PrepareForAsyncCompletion(me, fd);    
-	fd->secret->md.misc.thread = me;
+    PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
     err = OTOptionManagement(endpoint, &cmd, &cmd);
-    if (err != kOTNoError) {
-	    me->io_pending = PR_FALSE;
-	    PR_Unlock(fd->secret->md.miscLock);
+    if (err != kOTNoError)
         goto ErrorExit;
-	}
 
     WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
-	PR_Unlock(fd->secret->md.miscLock);
 
     err = me->md.osErrCode;
     if (err != kOTNoError)
         goto ErrorExit;
 
     if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
         err = kEOPNOTSUPPErr;
         goto ErrorExit;
@@ -759,21 +652,21 @@ PRStatus _MD_getsockopt(PRFileDesc *fd, 
     
     return PR_SUCCESS;
 
 ErrorExit:
     macsock_map_error(err);
     return PR_FAILURE;
 }
 
-
 PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen)
 {
     OSStatus err;
-    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+    PRInt32 osfd = fd->secret->md.osfd;
+    EndpointRef endpoint = (EndpointRef) osfd;
     TOptMgmt cmd;
     TOption *opt;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     unsigned char optionBuffer[kOTOptionHeaderSize + sizeof(PRSocketOptionData) + 1];
     
     if (endpoint == NULL) {
         err = kEBADFErr;
         goto ErrorExit;
@@ -865,29 +758,23 @@ PRStatus _MD_setsockopt(PRFileDesc *fd, 
                 *((unsigned char*)&opt->value) = *((PRUintn*)optval);
             }
             break;
         default:
             PR_ASSERT(0);
             break;    
     }
     
-	PR_Lock(fd->secret->md.miscLock);
-    PrepareForAsyncCompletion(me, fd);    
-	fd->secret->md.misc.thread = me;
+    PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
     err = OTOptionManagement(endpoint, &cmd, &cmd);
-    if (err != kOTNoError) {
-	    me->io_pending = PR_FALSE;
-	    PR_Unlock(fd->secret->md.miscLock);
+    if (err != kOTNoError)
         goto ErrorExit;
-	}
 
     WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
-	PR_Unlock(fd->secret->md.miscLock);
 
     err = me->md.osErrCode;
     if (err != kOTNoError)
         goto ErrorExit;
 
     if (opt->status == T_FAILURE || opt->status == T_NOTSUPPORT){
         err = kEOPNOTSUPPErr;
         goto ErrorExit;
@@ -902,17 +789,16 @@ PRStatus _MD_setsockopt(PRFileDesc *fd, 
 
     return PR_SUCCESS;
 
 ErrorExit:
     macsock_map_error(err);
     return PR_FAILURE;
 }
 
-
 PRInt32 _MD_socketavailable(PRFileDesc *fd)
 {
     PRInt32 osfd = fd->secret->md.osfd;
     OSStatus err;
     EndpointRef endpoint = (EndpointRef) osfd;
     size_t bytes;
 
     if (endpoint == NULL) {
@@ -932,27 +818,21 @@ PRInt32 _MD_socketavailable(PRFileDesc *
         
     return bytes;
 
 ErrorExit:
     macsock_map_error(err);
     return -1;
 }
 
-
 PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
 {
-#pragma unused (fd, addr, addrlen, timeout)
-
-    PR_ASSERT(!"_MD_accept Not implemented");
-	return -1;
-
-#if 0
+    PRInt32 osfd = fd->secret->md.osfd;
     OSStatus err;
-    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+    EndpointRef endpoint = (EndpointRef) osfd;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     TBind bindReq;
     PRNetAddr bindAddr;
     PRInt32 newosfd = -1;
     EndpointRef newEndpoint;
     TCall call;
     PRNetAddr callAddr;
 
@@ -962,31 +842,31 @@ PRInt32 _MD_accept(PRFileDesc *fd, PRNet
     }
         
     memset(&call, 0 , sizeof(call));
 
     call.addr.maxlen = PR_NETADDR_SIZE(&callAddr);
     call.addr.len = PR_NETADDR_SIZE(&callAddr);
     call.addr.buf = (UInt8*) &callAddr;
     
-    PrepareForAsyncCompletion(me, fd);    
+    PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
     err = OTListen (endpoint, &call);
     if (err != kOTNoError && (err != kOTNoDataErr || fd->secret->nonblocking)) {
         me->io_pending = PR_FALSE;
         goto ErrorExit;
     }
 
     while (err == kOTNoDataErr) {
         WaitOnThisThread(me, timeout);
         err = me->md.osErrCode;
         if (err != kOTNoError)
             goto ErrorExit;
 
-        PrepareForAsyncCompletion(me, fd);    
+        PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
         err = OTListen (endpoint, &call);
         if (err == kOTNoError)
             break;
 
         PR_ASSERT(err == kOTNoDataErr);
     }        
 
@@ -1000,60 +880,61 @@ PRInt32 _MD_accept(PRFileDesc *fd, PRNet
 
     bindAddr.inet.port = bindAddr.inet.ip = 0;
 
     bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);
     bindReq.addr.len = 0;
     bindReq.addr.buf = (UInt8*) &bindAddr;
     bindReq.qlen = 0;
     
-    PrepareThreadForAsyncIO(me, newosfd);    
+    PrepareThreadForAsyncIO(me, newEndpoint, newosfd);    
 
     err = OTBind(newEndpoint, &bindReq, NULL);
     if (err != kOTNoError)
         goto ErrorExit;
 
     WaitOnThisThread(me, timeout);
 
     err = me->md.osErrCode;
     if (err != kOTNoError)
         goto ErrorExit;
 
-    PrepareThreadForAsyncIO(me, newosfd);    
+    PrepareThreadForAsyncIO(me, endpoint, newosfd);    
 
     err = OTAccept (endpoint, newEndpoint, &call);
     if (err != kOTNoError)
         goto ErrorExit;
 
     WaitOnThisThread(me, timeout);
 
     err = me->md.osErrCode;
     if (err != kOTNoError)
         goto ErrorExit;
 
+    PR_ASSERT(me->md.cookie != NULL);
+
     if (addr != NULL)
         *addr = callAddr;
     if (addrlen != NULL)
         *addrlen = call.addr.len;
 
     return newosfd;
 
 ErrorExit:
     if (newosfd != -1)
         _MD_closesocket(newosfd);
     macsock_map_error(err);
     return -1;
-#endif
 }
 
-
 PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
 {
+    PRInt32 osfd = fd->secret->md.osfd;
     OSStatus err;
-    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+    EndpointRef endpoint = (EndpointRef) osfd;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     TCall sndCall;
     TBind bindReq;
     PRNetAddr bindAddr;
 
     if (endpoint == NULL) {
         err = kEBADFErr;
         goto ErrorExit;
@@ -1068,83 +949,73 @@ PRInt32 _MD_connect(PRFileDesc *fd, PRNe
 
     bindAddr.inet.port = bindAddr.inet.ip = 0;
 
     bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr);
     bindReq.addr.len = 0;
     bindReq.addr.buf = (UInt8*) &bindAddr;
     bindReq.qlen = 0;
     
-	PR_Lock(fd->secret->md.miscLock);
-    PrepareForAsyncCompletion(me, fd);    
-	fd->secret->md.misc.thread = me;
+    PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
     err = OTBind(endpoint, &bindReq, NULL);
-    if (err != kOTNoError) {
-	    me->io_pending = PR_FALSE;
-	    PR_Unlock(fd->secret->md.miscLock);
+    if (err != kOTNoError)
         goto ErrorExit;
-	}
 
     WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
-	PR_Unlock(fd->secret->md.miscLock);
 
     err = me->md.osErrCode;
     if (err != kOTNoError)
         goto ErrorExit;
 
     memset(&sndCall, 0 , sizeof(sndCall));
 
     sndCall.addr.maxlen = addrlen;
     sndCall.addr.len = addrlen;
     sndCall.addr.buf = (UInt8*) addr;
+    
+    PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
-	if (!fd->secret->nonblocking) {    
-        PrepareForAsyncCompletion(me, fd);    
-	    fd->secret->md.write.thread = me;
-    }
-	
     err = OTConnect (endpoint, &sndCall, NULL);
-	if (err == kOTNoError) {
-        PR_ASSERT(!"OTConnect returned kOTNoError in async mode!?!");	
-	}
-	if (fd->secret->nonblocking) {
-		if (err == kOTNoDataErr)
-			err = EINPROGRESS;
-		goto ErrorExit;
-	} else {
-		if (err != kOTNoError && err != kOTNoDataErr) {
-            me->io_pending = PR_FALSE;
-            goto ErrorExit;
-		}
-	}
-	
+    if (err != kOTNoError && err != kOTNoDataErr)
+        goto ErrorExit;
+    if (err == kOTNoDataErr && fd->secret->nonblocking) {
+        err = kEINPROGRESSErr;
+        me->io_pending = PR_FALSE;
+        goto ErrorExit;
+    }
+
     WaitOnThisThread(me, timeout);
 
     err = me->md.osErrCode;
     if (err != kOTNoError)
         goto ErrorExit;
 
+    PR_ASSERT(me->md.cookie != NULL);
+
+    err = OTRcvConnect(endpoint, NULL);
+    PR_ASSERT(err == kOTNoError);
+
     return kOTNoError;
 
 ErrorExit:
     macsock_map_error(err);
     return -1;
 }
 
-
 // Errors:
 // EBADF -- bad socket id
 // EFAULT -- bad buffer
 static PRInt32 SendReceiveStream(PRFileDesc *fd, void *buf, PRInt32 amount, 
                                PRIntn flags, PRIntervalTime timeout, SndRcvOpCode opCode)
 {
     OSStatus err;
     OTResult result;
-    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+    PRInt32 osfd = fd->secret->md.osfd;
+    EndpointRef endpoint = (EndpointRef) osfd;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     PRInt32 bytesLeft = amount;
 
     PR_ASSERT(flags == 0);
     
     if (endpoint == NULL) {
         err = kEBADFErr;
         goto ErrorExit;
@@ -1157,104 +1028,93 @@ static PRInt32 SendReceiveStream(PRFileD
     
     if (opCode != kSTREAM_SEND && opCode != kSTREAM_RECEIVE) {
         err = kEINVALErr;
         goto ErrorExit;
     }
         
     while (bytesLeft > 0) {
     
-        PrepareForAsyncCompletion(me, fd);    
+        PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
-        if (opCode == kSTREAM_SEND) {
-			fd->secret->md.write.thread = me;
-			fd->secret->md.writeReady = PR_FALSE;				// expect the worst
+        if (opCode == kSTREAM_SEND)
             result = OTSnd(endpoint, buf, bytesLeft, NULL);
-			if (result != kOTFlowErr)							// hope for the best
-				fd->secret->md.writeReady = PR_TRUE;
-        } else {
-			fd->secret->md.read.thread = me;
-			fd->secret->md.readReady = PR_FALSE;				// expect the worst			
+        else
             result = OTRcv(endpoint, buf, bytesLeft, NULL);
-			if (result != kOTNoDataErr)							// hope for the best
-				fd->secret->md.readReady = PR_TRUE;
-        }
-		me->io_pending = PR_FALSE;
 
         if (result > 0) {
             buf = (void *) ( (UInt32) buf + (UInt32)result );
             bytesLeft -= result;
+            me->io_pending = PR_FALSE;
             if (opCode == kSTREAM_RECEIVE)
                 return result;
         } else {
-			switch (result) {
-				case kOTOutStateErr:			// it has been closed
-                    return 0;
-				
-				case kOTLookErr:
-				    PR_ASSERT(!"call to OTLook() required after all.");
-					break;
-				
-				case kOTFlowErr:
-				case kOTNoDataErr:
-				case kEAGAINErr:
-				case kEWOULDBLOCKErr:
-					if (fd->secret->nonblocking) {
-						err = result;
-						goto ErrorExit;
-					}
+            if (result == kOTOutStateErr) { /* it has been closed */
+                me->io_pending = PR_FALSE;
+                return 0;
+            }
+            if (result == kOTLookErr) {
+                PRBool readReady,writeReady,exceptReady;
+                /* process the event and then continue the operation */
+                (void) GetState(endpoint, &readReady, &writeReady, &exceptReady);
+                continue;
+            }
+            if (result != kOTNoDataErr && result != kOTFlowErr && 
+                result != kEAGAINErr && result != kEWOULDBLOCKErr) {
+                me->io_pending = PR_FALSE;
+                err = result;
+                goto ErrorExit;
+            } else if (fd->secret->nonblocking) {
+                me->io_pending = PR_FALSE;
+                err = result;
+                goto ErrorExit;
+            }
+            WaitOnThisThread(me, timeout);
+            me->io_pending = PR_FALSE;
+            err = me->md.osErrCode;
+            if (err != kOTNoError)
+                goto ErrorExit;
 
-					WaitOnThisThread(me, timeout);
-					err = me->md.osErrCode;
-					if (err != kOTNoError)
-						goto ErrorExit;				
-					break;
-					
-				default:
-					err = result;
-					goto ErrorExit;
-			}
-		}
+            PR_ASSERT(me->md.cookie != NULL);
+        }
     }
 
     return amount;
 
 ErrorExit:
     macsock_map_error(err);
     return -1;
 }                               
 
-
 PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount, 
                                PRIntn flags, PRIntervalTime timeout)
 {
     return (SendReceiveStream(fd, buf, amount, flags, timeout, kSTREAM_RECEIVE));
 }                               
 
-
 PRInt32 _MD_send(PRFileDesc *fd,const void *buf, PRInt32 amount, 
                                PRIntn flags, PRIntervalTime timeout)
 {
     return (SendReceiveStream(fd, (void *)buf, amount, flags, timeout, kSTREAM_SEND));
 }                               
 
 
 // Errors:
 // EBADF -- bad socket id
 // EFAULT -- bad buffer
 static PRInt32 SendReceiveDgram(PRFileDesc *fd, void *buf, PRInt32 amount, 
                                PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, 
                                PRIntervalTime timeout, SndRcvOpCode opCode)
 {
     OSStatus err;
-    EndpointRef endpoint = (EndpointRef) fd->secret->md.osfd;
+    PRInt32 osfd = fd->secret->md.osfd;
+    EndpointRef endpoint = (EndpointRef) osfd;
     PRThread *me = _PR_MD_CURRENT_THREAD();
     PRInt32 bytesLeft = amount;
     TUnitData dgram;
-    OTResult	result;
 
     PR_ASSERT(flags == 0);
     
     if (endpoint == NULL) {
         err = kEBADFErr;
         goto ErrorExit;
     }
         
@@ -1273,133 +1133,178 @@ static PRInt32 SendReceiveDgram(PRFileDe
     dgram.addr.len = *addrlen;
     dgram.addr.buf = (UInt8*) addr;
     dgram.udata.maxlen = amount;
     dgram.udata.len = amount;
     dgram.udata.buf = (UInt8*) buf;    
 
     while (bytesLeft > 0) {
     
-        PrepareForAsyncCompletion(me, fd);    
+        PrepareThreadForAsyncIO(me, endpoint, osfd);    
 
-        if (opCode == kDGRAM_SEND) {
-			fd->secret->md.write.thread = me;
-			fd->secret->md.writeReady = PR_FALSE;				// expect the worst
+        if (opCode == kDGRAM_SEND)
             err = OTSndUData(endpoint, &dgram);
-			if (result != kOTFlowErr)							// hope for the best
-				fd->secret->md.writeReady = PR_TRUE;
-		} else {
-			fd->secret->md.read.thread = me;
-			fd->secret->md.readReady = PR_FALSE;				// expect the worst			
+        else
             err = OTRcvUData(endpoint, &dgram, NULL);
-			if (result != kOTNoDataErr)							// hope for the best
-				fd->secret->md.readReady = PR_TRUE;
-		}
 
         if (err == kOTNoError) {
             buf = (void *) ( (UInt32) buf + (UInt32)dgram.udata.len );
             bytesLeft -= dgram.udata.len;
             dgram.udata.buf = (UInt8*) buf;    
             me->io_pending = PR_FALSE;
-        } else {
+        }
+        else {
             PR_ASSERT(err == kOTNoDataErr || err == kOTOutStateErr);
             WaitOnThisThread(me, timeout);
+            me->io_pending = PR_FALSE;
             err = me->md.osErrCode;
             if (err != kOTNoError)
                 goto ErrorExit;
+
+            PR_ASSERT(me->md.cookie != NULL);
         }
     }
 
     if (opCode == kDGRAM_RECEIVE)
         *addrlen = dgram.addr.len;
 
     return amount;
 
 ErrorExit:
     macsock_map_error(err);
     return -1;
 }                               
 
-
 PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, 
                                PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen,
                                PRIntervalTime timeout)
 {
     return (SendReceiveDgram(fd, buf, amount, flags, addr, addrlen,
                             timeout, kDGRAM_RECEIVE));
 }                               
 
-
 PRInt32 _MD_sendto(PRFileDesc *fd,const void *buf, PRInt32 amount, 
                                PRIntn flags, PRNetAddr *addr, PRUint32 addrlen,
                                PRIntervalTime timeout)
 {
     return (SendReceiveDgram(fd, (void *)buf, amount, flags, addr, &addrlen,
                             timeout, kDGRAM_SEND));
 }                               
 
-
 PRInt32 _MD_closesocket(PRInt32 osfd)
 {
     OSStatus err;
     EndpointRef endpoint = (EndpointRef) osfd;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
     if (endpoint == NULL) {
         err = kEBADFErr;
         goto ErrorExit;
     }
         
     if (me->io_pending && me->io_fd == osfd)
         me->io_pending = PR_FALSE;
 
+#if 0
+    {
+    OTResult state;
+    state = OTGetEndpointState(endpoint);
+    
+    err = OTSndOrderlyDisconnect(endpoint);
+    if (err != kOTNoError && err != kOTOutStateErr)
+        goto ErrorExit;
+
+    state = OTGetEndpointState(endpoint);
+    
+    err = OTUnbind(endpoint);
+    if (err != kOTNoError && err != kOTOutStateErr)
+        goto ErrorExit;
+
+    state = OTGetEndpointState(endpoint);
+
+    err = OTSetSynchronous(endpoint);
+    if (err != kOTNoError)
+        goto ErrorExit;
+
+    err = OTSetBlocking(endpoint);
+    if (err != kOTNoError)
+        goto ErrorExit;
+    }
+#endif
+
     (void) OTSndOrderlyDisconnect(endpoint);
+
     err = OTCloseProvider(endpoint);
     if (err != kOTNoError)
         goto ErrorExit;
 
     return kOTNoError;
 
 ErrorExit:
     macsock_map_error(err);
     return -1;
 }                               
 
-
 PRInt32 _MD_writev(PRFileDesc *fd, const struct PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)
 {
 #pragma unused (fd, iov, iov_size, timeout)
 
     PR_ASSERT(0);
     _PR_MD_CURRENT_THREAD()->md.osErrCode = unimpErr;
     return -1;
 }                               
 
-
-static PRBool GetState(PRFileDesc *fd, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady)
+static PRBool GetState(EndpointRef endpoint, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady)
 {
+    OSStatus err;
     OTResult resultOT;
+    TDiscon discon;
+    PRBool result = PR_FALSE;
     
-	*readReady = fd->secret->md.readReady;
-	*exceptReady = fd->secret->md.exceptReady;
+    *readReady = *writeReady = *exceptReady = PR_FALSE;
 
-    resultOT = OTGetEndpointState((EndpointRef)fd->secret->md.osfd);
+    resultOT = OTLook(endpoint);
+    switch (resultOT) {
+        case T_DATA:
+        case T_LISTEN:
+            *readReady = PR_TRUE;
+            break;
+        case T_CONNECT:
+            err = OTRcvConnect(endpoint, NULL);
+            PR_ASSERT(err == kOTNoError);
+            break;        
+        case T_DISCONNECT:
+            memset(&discon, 0 , sizeof(discon));
+            err = OTRcvDisconnect(endpoint, &discon);
+            PR_ASSERT(err == kOTNoError);
+            macsock_map_error(discon.reason);
+            *exceptReady = PR_TRUE;
+            break;        
+        case T_ORDREL:
+            *readReady = PR_TRUE;
+            err = OTRcvOrderlyDisconnect(endpoint);
+            PR_ASSERT(err == kOTNoError);
+            break;
+    }
+    resultOT = OTGetEndpointState(endpoint);
     switch (resultOT)    {
         case T_DATAXFER:
         case T_INREL:
             *writeReady = PR_TRUE;
             break;
         default:
             *writeReady = PR_FALSE;
     }
     
-    return  *readReady || *writeReady || *exceptReady;
+    if ((*readReady == PR_TRUE) || (*writeReady==PR_TRUE) || (*exceptReady==PR_TRUE))
+        result = PR_TRUE;
+
+    return result;
 }
 
-
 PRInt32 _MD_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
 {
     PRInt32 ready = 0;
     PRPollDesc *pd, *epd;
     PRIntervalTime sleepTime, timein;
     
     sleepTime = PR_MillisecondsToInterval(5UL);
     if (PR_INTERVAL_NO_TIMEOUT != timeout)
@@ -1407,17 +1312,17 @@ PRInt32 _MD_poll(PRPollDesc *pds, PRIntn
         if (sleepTime > timeout) sleepTime = timeout;
         timein = PR_IntervalNow();
     }
 
     do
     {
         for (pd = pds, epd = pd + npds; pd < epd; pd++)
         {
-            PRInt16  in_flags_read = 0,  in_flags_write = 0;
+            PRInt16 in_flags_read = 0, in_flags_write = 0;
             PRInt16 out_flags_read = 0, out_flags_write = 0;
 
             if (NULL == pd->fd || pd->in_flags == 0) continue;
 
             if (pd->in_flags & PR_POLL_READ)
             {
                 in_flags_read = (pd->fd->methods->poll)(
                     pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
@@ -1430,25 +1335,30 @@ PRInt32 _MD_poll(PRPollDesc *pds, PRIntn
             if ((0 != (in_flags_read & out_flags_read))
             || (0 != (in_flags_write & out_flags_write)))
             {
                 ready += 1;  /* some layer has buffer input */
                 pd->out_flags = out_flags_read | out_flags_write;
             }
             else
             {
-                PRFileDesc *bottomFD;
+                PRFileDesc *bottom;
+                EndpointRef endpoint;
                 PRBool readReady, writeReady, exceptReady;
 
                 pd->out_flags = 0;  /* pre-condition */
-                bottomFD = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
-                PR_ASSERT(NULL != bottomFD);
-                if ((NULL != bottomFD) && (_PR_FILEDESC_OPEN == bottomFD->secret->state))
+                bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
+                PR_ASSERT(NULL != bottom);
+                if ((NULL != bottom)
+                && (_PR_FILEDESC_OPEN == bottom->secret->state))
                 {
-                    if (GetState(bottomFD, &readReady, &writeReady, &exceptReady))
+                    endpoint = (EndpointRef)bottom->secret->md.osfd;
+
+                    if (GetState(endpoint,
+                    &readReady, &writeReady, &exceptReady))
                     {
                         if (readReady)
                         {
                             if (in_flags_read & PR_POLL_READ)
                                 pd->out_flags |= PR_POLL_READ;
                             if (in_flags_write & PR_POLL_READ)
                                 pd->out_flags |= PR_POLL_WRITE;
                         }
@@ -1479,76 +1389,34 @@ PRInt32 _MD_poll(PRPollDesc *pds, PRIntn
         (void) PR_Sleep(sleepTime);
 
     } while ((timeout == PR_INTERVAL_NO_TIMEOUT) ||
            (((PRIntervalTime)(PR_IntervalNow() - timein)) < timeout));
 
     return 0; /* timed out */
 }
 
-
-void _MD_initfiledesc(PRFileDesc *fd)
-{
-	// Allocate a PR_Lock to arbitrate miscellaneous OT calls for this endpoint between threads
-	// We presume that only one thread will be making Read calls (Recv/Accept) and that only
-	// one thread will be making Write calls (Send/Connect) on the endpoint at a time.
-	if (fd->methods->file_type == PR_DESC_SOCKET_TCP ||
-		fd->methods->file_type == PR_DESC_SOCKET_UDP )
-	{
-		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.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;
-	}
-}
-
-
-void _MD_freefiledesc(PRFileDesc *fd)
-{
-	if (fd->secret->md.miscLock)
-	{
-		PR_ASSERT(fd->methods->file_type == PR_DESC_SOCKET_TCP || fd->methods->file_type == PR_DESC_SOCKET_UDP);
-		PR_DestroyLock(fd->secret->md.miscLock);
-		fd->secret->md.miscLock = NULL;
-	} else {
-		PR_ASSERT(fd->methods->file_type != PR_DESC_SOCKET_TCP && PR_DESC_SOCKET_TCP != PR_DESC_SOCKET_UDP);
-	}
-}
-
 void _MD_makenonblock(PRFileDesc *fd)
 {
-	// We simulate non-blocking mode using async mode rather
-	// than put the endpoint in non-blocking mode.
-	// We need to install the PRFileDesc as the contextPtr for the NotifierRoutine, but it
-	// didn't exist at the time the endpoint was created.  It does now though...
-	ProviderRef	endpointRef = (ProviderRef)fd->secret->md.osfd;
-	OSStatus	err;
-	
-	// Install the PRFileDesc as the contextPtr for the Notifier function associated with this Endpoint.
-	err = OTInstallNotifier(endpointRef, NotifierRoutine, fd);
-	PR_ASSERT(err == kOTNoError);
-	
-	// Now that we have a NotifierRoutine installed, we can make the endpoint asynchronous
-	err = OTSetAsynchronous(endpointRef);
-	PR_ASSERT(err == kOTNoError);
+    OSStatus err;
+    PRInt32 osfd = fd->secret->md.osfd;
+    EndpointRef endpoint = (EndpointRef) osfd;
+
+    err = OTSetNonBlocking(endpoint);
+    PR_ASSERT(err == kOTNoError || err == kOTOutStateErr);
 }
 
-
 PR_IMPLEMENT(PRInt32) _MD_shutdown(PRFileDesc *fd, PRIntn how)
 {
 #pragma unused (fd, how)
 
 /* Just succeed silently!!! */
 return (0);
 }                               
 
-
 PR_IMPLEMENT(PRStatus) _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
 {
 #pragma unused (fd, addr, addrlen)
 
     PR_ASSERT(0);
     _PR_MD_CURRENT_THREAD()->md.osErrCode = unimpErr;
     return PR_FAILURE;
 }                               
@@ -1566,39 +1434,32 @@ PR_IMPLEMENT(unsigned long) inet_addr(co
 }
 
 
 static char *sAliases[1] = {NULL};
 static struct hostent sHostEnt = {NULL, &sAliases[0], AF_INET, sizeof (long), NULL};
 static InetHostInfo sHostInfo;
 static InetHost *sAddresses[kMaxHostAddrs+1];
 
-
 PR_IMPLEMENT(struct hostent *) gethostbyname(const char * name)
 {
     OSStatus err;
     PRUint32 index;
     PRThread *me = _PR_MD_CURRENT_THREAD();
 
-    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
+    PrepareThreadForAsyncIO(me, sSvcRef, NULL);    
 
-    err = OTInetStringToAddress(dnsContext.serviceRef, (char *)name, &sHostInfo);
+    err = OTInetStringToAddress(sSvcRef, (char *)name, &sHostInfo);
     if (err != kOTNoError) {
         me->io_pending = PR_FALSE;
         me->md.osErrCode = err;
         goto ErrorExit;
     }
 
     WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
-	PR_Unlock(dnsContext.lock);
 
     if (me->md.osErrCode != kOTNoError)
         goto ErrorExit;
 
     sHostEnt.h_name = sHostInfo.name;
     for (index=0; index<kMaxHostAddrs && sHostInfo.addrs[index] != NULL; index++)
         sAddresses[index] = &sHostInfo.addrs[index];
     sAddresses[index] = NULL;    
@@ -1631,17 +1492,17 @@ PR_IMPLEMENT(char *) inet_ntoa(struct in
 
 
 PRStatus _MD_gethostname(char *name, int namelen)
 {
     OSStatus err;
     InetInterfaceInfo info;
 
     /*
-     *    On a Macintosh, we don't have the concept of a local host name.
+     *    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.
      */
 
     /* Make sure the string is as long as the longest possible address */
     if (namelen < strlen("123.123.123.123")) {
@@ -1705,17 +1566,17 @@ ErrorExit:
 int _MD_mac_get_nonblocking_connect_error(PRInt32 osfd)
 {
     OTResult resultOT;
     EndpointRef endpoint = (EndpointRef) osfd;
 
     resultOT = OTGetEndpointState(endpoint);
     switch (resultOT)    {
         case T_OUTCON:
-            macsock_map_error(EINPROGRESS);
+            macsock_map_error(kEINPROGRESSErr);
             return -1;
         case T_DATAXFER:
             return 0;
         case T_IDLE:
             return -1;
         default:
             PR_ASSERT(0);
             return -1;