PCSBSocket * PCSBSocket::Accept(void) { OSStatus err = noErr; if (mWorker == NULL) mWorker = ::OTOpenEndpointInContext( ::OTCreateConfiguration(kTCPName), 0, // Options must be 0 NULL, // Don't care about endpoint info &err, NULL); if (err != noErr) return NULL; while (1) { MopupEvents(); if (!mHasIncoming) return NULL; OSStatus result = OTAccept(mMacSocket, mWorker, &mIncoming); switch(result) { case noErr: EndpointRef newSock = mWorker; mWorker = NULL; return new PCSBSocket(newSock); case kOTLookErr: continue; default: mHasIncoming = false; return NULL; } } }
NMErr EndpointHander::Finish(void) { DEBUG_ENTRY_EXIT("EndpointHander::Finish"); NMErr status; OTRemoveNotifier(mNewEP->mStreamEndpoint->mEP); OTInstallNotifier(mNewEP->mStreamEndpoint->mEP, mNewEP->mNotifier.fUPP, mNewEP->mStreamEndpoint); if (mNewEP->mMode == kNMNormalMode) { OTRemoveNotifier(mNewEP->mDatagramEndpoint->mEP); OTInstallNotifier(mNewEP->mDatagramEndpoint->mEP, mNewEP->mNotifier.fUPP, mNewEP->mDatagramEndpoint); } status = OTAccept(mListenerEP->mStreamEndpoint->mEP, mNewEP->mStreamEndpoint->mEP, mCall); DEBUG_NETWORK_API(mListenerEP->mStreamEndpoint->mEP, "OTAccept", status); if (status == kOTLookErr) { OTResult lookResult = OTLook(mListenerEP->mStreamEndpoint->mEP); if (lookResult == T_DISCONNECT) // the active peer disconnected OTRcvDisconnect(mListenerEP->mStreamEndpoint->mEP, NULL); // fake the accept complete mListenerEP->HandleAcceptComplete(); // kill the new endpoint EndpointDisposer *killer = new EndpointDisposer(mNewEP, true); } if (! ScheduleDelete()) delete this; // this is pretty damn likely to crach [gg] return kNMNoError; }
PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; OSStatus err; EndpointRef endpoint = (EndpointRef) osfd; PRThread *me = _PR_MD_CURRENT_THREAD(); TBind bindReq; PRNetAddr bindAddr; PRInt32 newosfd = -1; EndpointRef newEndpoint; TCall call; PRNetAddr callAddr; if (endpoint == NULL) { err = kEBADFErr; goto ErrorExit; } memset(&call, 0 , sizeof(call)); call.addr.maxlen = PR_NETADDR_SIZE(&callAddr); call.addr.len = PR_NETADDR_SIZE(&callAddr); call.addr.buf = (UInt8*) &callAddr; 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; PrepareThreadForAsyncIO(me, endpoint, osfd); err = OTListen (endpoint, &call); if (err == kOTNoError) break; PR_ASSERT(err == kOTNoDataErr); } newosfd = _MD_socket(AF_INET, SOCK_STREAM, 0); if (newosfd == -1) return -1; newEndpoint = (EndpointRef)newosfd; // Bind to a local port; let the system assign it. 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, 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, 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; }
/* Accept an incoming connection on the given server socket. The newly created socket is returned, or NULL if there was an error. */ TCPsocket SDLNet_TCP_Accept(TCPsocket server) { /* Only server sockets can accept */ if ( ! server->sflag ) { SDLNet_SetError("Only server sockets can accept()"); return(NULL); } server->ready = 0; /* Accept a new TCP connection on a server socket */ { InetAddress peer; TCall peerinfo; TCPsocket sock = NULL; Boolean mustListen = false; OTResult err; memset(&peerinfo, 0, (sizeof peerinfo )); peerinfo.addr.buf = (Uint8 *) &peer; peerinfo.addr.maxlen = sizeof(peer); while( mustListen || !sock ) { // OTListen // We do NOT block ---- right thing ? (TODO) err = OTListen( server->channel, &peerinfo ); if( err ) goto error_return; else { mustListen = false; sock = AsyncTCPNewSocket(); if( ! sock ) goto error_return; } } if( sock ) { // OTAsyncOpenEndpoint server->error = OTAsyncOpenEndpoint( OTCloneConfiguration( server->config ), NULL, &(sock->info), (OTNotifyProcPtr)AsyncTCPNotifier, sock ); AsyncTCPPopEvent( sock ); while( !sock->error && !( sock->completion & CompleteMask( T_OPENCOMPLETE))) { AsyncTCPPopEvent( sock ); } if( ! sock->channel ) { mustListen = false; goto error_return; } // OTAccept server->completion &= ~(CompleteMask(T_ACCEPTCOMPLETE)); server->error = OTAccept( server->channel, sock->channel, &peerinfo ); AsyncTCPPopEvent( server ); while( !(server->completion & CompleteMask(T_ACCEPTCOMPLETE))) { AsyncTCPPopEvent( server ); } switch( server->error ) { case kOTLookErr: switch( OTLook(server->channel )) { case T_LISTEN: mustListen = true; break; case T_DISCONNECT: goto error_return; } break; case 0: sock->nextListener = server->nextListener; server->nextListener = sock; sock->remoteAddress.host = peer.fHost; sock->remoteAddress.port = peer.fPort; return sock; // accept successful break; default: free( sock ); } } sock->remoteAddress.host = peer.fHost; sock->remoteAddress.port = peer.fPort; sock->sflag = 0; sock->ready = 0; /* The socket is ready */ return(sock); // Error; close the socket and return error_return: SDLNet_TCP_Close(sock); return(NULL); } }