int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout) { Uint32 stop; int numReady; /* Loop, polling the network devices */ stop = SDL_GetTicks() + timeout; do { OTResult status; size_t numBytes; int i; numReady = 0; for (i = set->numsockets-1;i >= 0;--i) { status = OTLook( set->sockets[i]->channel ); if( status > 0 ) { switch( status ) { case T_UDERR: OTRcvUDErr( set->sockets[i]->channel , nil); break; case T_DISCONNECT: OTRcvDisconnect( set->sockets[i]->channel, nil ); break; case T_ORDREL: OTRcvOrderlyDisconnect(set->sockets[i]->channel ); break; case T_CONNECT: OTRcvConnect( set->sockets[i]->channel, nil ); break; default: set->sockets[i]->ready = 1; ++numReady; } } else if( OTCountDataBytes(set->sockets[i]->channel, &numBytes ) != kOTNoDataErr ) { set->sockets[i]->ready = 1; ++numReady; } else set->sockets[i]->ready = 0; } } while (!numReady && (SDL_GetTicks() < stop)); return(numReady); }
// This function is taken from GUSI interface. // ( 01/02/19 masahiro minami<*****@*****.**> ) static void AsyncTCPPopEvent( TCPsocket sock ) { // Make sure OT calls are not interrupted // Not sure if we really need this. OTEnterNotifier( sock->channel ); sock->event |= (sock->curEvent = sock->newEvent ); sock->completion |= ( sock->curCompletion = sock->newCompletion ); sock->newEvent = sock->newCompletion = 0; OTLeaveNotifier( sock->channel ); if( sock->curEvent & T_UDERR) { // We just clear the error. // Should we feed this back to users ? // (TODO ) OTRcvUDErr( sock->channel, NULL ); #ifdef DEBUG_NET printf("AsyncTCPPopEvent T_UDERR recognized"); #endif } // Remote is disconnecting... if( sock->curEvent & ( T_DISCONNECT | T_ORDREL )) { sock->readShutdown = true; } if( sock->curEvent &T_CONNECT ) { // Ignore the info of remote (second parameter). // Shoule we care ? // (TODO) OTRcvConnect( sock->channel, NULL ); sock->connected = 1; } if( sock->curEvent & T_ORDREL ) { OTRcvOrderlyDisconnect( sock->channel ); } if( sock->curEvent & T_DISCONNECT ) { OTRcvDisconnect( sock->channel, NULL ); } // Do we need to ? // (masahiro minami<*****@*****.**>) //YieldToAnyThread(); }
static PRBool GetState(EndpointRef endpoint, PRBool *readReady, PRBool *writeReady, PRBool *exceptReady) { OSStatus err; OTResult resultOT; TDiscon discon; PRBool result = PR_FALSE; *readReady = *writeReady = *exceptReady = PR_FALSE; 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; } if ((*readReady == PR_TRUE) || (*writeReady==PR_TRUE) || (*exceptReady==PR_TRUE)) result = PR_TRUE; return result; }
PRInt32 _MD_connect(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(); TCall sndCall; TBind bindReq; PRNetAddr bindAddr; if (endpoint == NULL) { err = kEBADFErr; goto ErrorExit; } if (addr == NULL) { err = kEFAULTErr; goto ErrorExit; } // 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, endpoint, osfd); err = OTBind(endpoint, &bindReq, NULL); if (err != kOTNoError) goto ErrorExit; WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT); 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); err = OTConnect (endpoint, &sndCall, NULL); 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; }
pascal void OTTCPNotifier(void* vobj, OTEventCode code, OTResult result, void* cookie) { OTTCP *x = (OTTCP *) vobj; long oldA5; OSStatus s; EnterCallback(); oldA5 = SetA5(x->o_a5); post("*** OTTCPNotifier(code %x, result %ld)", (long) code, (long) result); if (code == T_OPENCOMPLETE) { if (result != noErr) { post("OTTCPNotifier got a T_OPENCOMPLETE code with error %ld", result); } // Even if we got an error, we'll use the endpoint. x->o_tcp_ep = (EndpointRef) cookie; if (x->o_inetHostName != 0) { BindTheEndpoint(x); // Now we expect a T_BINDCOMPLETE message. } } else if (code == T_BINDCOMPLETE) { TCall sndCall; InetAddress inAddr; // See what ephemeral port number OT gave us x->o_receiveInetPort = x->o_addrWeActuallyGot.fPort; // Now the endpoint has been bound; next trick is connecting OTInitInetAddress(&inAddr, x->o_inetPort, x->o_inetHost); OTMemzero(&sndCall, sizeof(TCall)); sndCall.addr.buf = (void *) &inAddr; sndCall.addr.len = sizeof(InetAddress); post("** About to OTConnect"); s = OTConnect(x->o_tcp_ep, &sndCall, NULL); if (s == kOTNoDataErr) { // No problem; that means connection is in progress post("** OTConnect returned kOTNoDataErr - good"); } else { post("е OTTCP: error: OTConnect returned %ld; not connecting.", s); } // Now we expect T_CONNECT } else if (code == T_CONNECT) { if (result == kOTBadAddressErr) { post("е OTTCP: error: bad address. Disconnecting"); x->o_inetHost = 0; change_connection(x); } else { post("** Got T_CONNECT"); post("** Result passed to notifier: %ld", (long) result); post("** Endpoint state before OTRcvConnect: %ld", (long) OTGetEndpointState(x->o_tcp_ep)); // We could pass in buffers to find out the actual address we connected to, etc. s = OTRcvConnect(x->o_tcp_ep, nil); if (s != kOTNoError) { post("е OTTCP: error: RcvConnect returned %ld", s); } post("** Endpoint state after OTRcvConnect: %ld", (long) OTGetEndpointState(x->o_tcp_ep)); ChangeState(x, NO_REQUEST); x->o_connectionSymbol = ps_connected; clock_delay(x->o_connectedclock, 0); } } else if (code == T_UNBINDCOMPLETE) { // If we have a new inetHost, try to bind it if (x->o_inetHost != 0) { BindTheEndpoint(x); // Now we expect T_BINDCOMPLETE } else { // No inetHost, so we're disonnected x->o_connectionSymbol = ps_disconnected; clock_delay(x->o_connectedclock, 0); } } else if (code == T_DISCONNECTCOMPLETE) { // We always want to rebind when we reconnect, so after disconnecting we unbind s = OTUnbind(x->o_tcp_ep); if (s != kOTNoError) { post("OTTCP: warning: OTUnbind returned %ld", s); } } else if (code == T_DATA) { ottcp_handleIncomingData(x); } else if (code == T_UDERR) { if (x->o_errorreporting) { PostUDERR("OTTCPNotifier was called for a T_UDERR code", x->o_tcp_ep); } else { /* We still have to receive the error to clear the condition */ OTRcvUDErr(x->o_tcp_ep, 0); } } else if (code == T_GODATA) { // Flow control restriction has lifted; now it's OK to send more data. do_write(x, 0, 0); } else if (code == T_DISCONNECT) { // The other dude wants to disconnect post("OTTCP: peer wants to disconnect"); s = OTRcvDisconnect(x->o_tcp_ep, NULL); if (s == kOTNoError) { x->o_inetHost = 0; change_connection(x); } else if (s == kOTNoDisconnectErr) { // false alarm } else { post("е OTTCP: error: OTRcvDisconnect returned %ld", s); } } else if (code == T_ORDREL) { post("*** Got T_ORDREL"); s = OTRcvOrderlyDisconnect(x->o_tcp_ep); if (s == kOTNoReleaseErr) { post("...false alarm!"); } else if (s == kOTNoError) { x->o_inetHost = 0; change_connection(x); } else { post("е OTTCP: error: OTRcvOrderlyDisconnect returned %ld", s); } } else { if (x->o_errorreporting) { post("OTTCP: Unrecognized OTEventCode %ld in event handler. Oh well.", (long) code); } } done: SetA5(oldA5); ExitCallback(); }
void _GSocket_Internal_Proc(unsigned long e , void* d ) { GSocket * socket = (GSocket*) d ; OTEventCode ev = (OTEventCode) e ; GSocketEvent event; GSocketEvent event2; GSocketCallback cback; char *data; GSocketCallback cback2; char *data2; if ( !socket ) return ; event = GSOCK_MAX_EVENT ; event2 = GSOCK_MAX_EVENT ; cback = NULL; data = NULL; cback2 = NULL; data2 = NULL; /* Check that the socket still exists (it has not been * destroyed) and for safety, check that the m_endpoint field * is what we expect it to be. */ if ((socket != NULL) && (socket->m_takesEvents)) { switch (ev) { case T_LISTEN : event = GSOCK_CONNECTION ; break ; case T_CONNECT : event = GSOCK_CONNECTION ; event2 = GSOCK_OUTPUT ; { TCall retCall; retCall.addr.buf = NULL; retCall.addr.maxlen = 0; retCall.opt.buf = NULL; retCall.opt.maxlen = 0; retCall.udata.buf = NULL; retCall.udata.maxlen= 0; OTRcvConnect( socket->m_endpoint , &retCall ) ; } break ; case T_DISCONNECT : event = GSOCK_LOST ; break ; case T_GODATA : case T_GOEXDATA : event = GSOCK_OUTPUT ; break ; case T_DATA : event = GSOCK_INPUT ; break ; case T_EXDATA : event = GSOCK_INPUT ; break ; } if (event != GSOCK_MAX_EVENT) { cback = socket->m_cbacks[event]; data = socket->m_data[event]; if (event == GSOCK_LOST) socket->m_detected = GSOCK_LOST_FLAG; else socket->m_detected |= (1 << event); } if (event2 != GSOCK_MAX_EVENT) { cback2 = socket->m_cbacks[event2]; data2 = socket->m_data[event2]; if (event2 == GSOCK_LOST) socket->m_detected = GSOCK_LOST_FLAG; else socket->m_detected |= (1 << event2); } } /* OK, we can now leave the critical section because we have * already obtained the callback address (we make no further * accesses to socket->whatever). However, the app should * be prepared to handle events from a socket that has just * been closed! */ if (cback != NULL) (cback)(socket, event, data); if (cback2 != NULL) (cback2)(socket, event2, data2); }