// no modified.. waiting for a MAC! int my_recv(TCPsocket sock, void *data, int maxlen) { int len = 0; OSStatus res; /* Server sockets are for accepting connections only */ if ( sock->sflag ) { SDLNet_SetError("Server sockets cannot receive"); return(-1); } do { res = OTRcv(sock->channel, data, maxlen-len, 0); if (res > 0) { len = res; } AsyncTCPPopEvent(sock); if( res == kOTLookErr ) { res = OTLook(sock->channel ); continue; } } while ( (len == 0) && (res == kOTNoDataErr) ); sock->ready = 0; if ( len == 0 ) { /* Open Transport error */ return(-1); } return(len); }
/* Receive up to 'maxlen' bytes of data over the non-server socket 'sock', and store them in the buffer pointed to by 'data'. This function returns the actual amount of data received. If the return value is less than or equal to zero, then either the remote connection was closed, or an unknown socket error occurred. */ int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen) { int len = 0; OSStatus res; /* Server sockets are for accepting connections only */ if ( sock->sflag ) { SDLNet_SetError("Server sockets cannot receive"); return(-1); } do { res = OTRcv(sock->channel, data, maxlen-len, 0); if (res > 0) { len = res; } #ifdef DEBUG_NET if ( res != kOTNoDataErr ) printf("SDLNet_TCP_Recv received ; %d\n", res ); #endif AsyncTCPPopEvent(sock); if( res == kOTLookErr ) { res = OTLook(sock->channel ); continue; } } while ( (len == 0) && (res == kOTNoDataErr) ); sock->ready = 0; if ( len == 0 ) { /* Open Transport error */ #ifdef DEBUG_NET printf("Open Transport error: %d\n", res); #endif return(-1); } return(len); }
/* 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); } }
/* Open a TCP network socket If 'remote' is NULL, this creates a local server socket on the given port, otherwise a TCP connection to the remote host and port is attempted. The newly created socket is returned, or NULL if there was an error. ( re-written by masahiro minami<*****@*****.**> Now endpoint is created in Async mode. 01/02/20 ) */ TCPsocket SDLNet_TCP_Open(IPaddress *ip) { EndpointRef dummy = NULL; TCPsocket sock = AsyncTCPNewSocket(); if( ! sock) return NULL; // Determin whether bind locally, or connect to remote if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) ) { // ######## Connect to remote OTResult stat; InetAddress inAddr; TBind bindReq; // Open endpoint sock->error = OTAsyncOpenEndpoint( OTCreateConfiguration(kTCPName), NULL, &(sock->info), (OTNotifyProcPtr)(AsyncTCPNotifier), sock ); AsyncTCPPopEvent( sock ); while( !sock->error && !( sock->completion & CompleteMask(T_OPENCOMPLETE))) { //SetThreadState( kCurrentThreadID, kReadyThreadState, kNoThreadID ); //YieldToAnyThread(); //WaitNextEvent(everyEvent, &macEvent, 1, NULL); AsyncTCPPopEvent( sock ); } if( !sock->channel ) { SDLNet_SetError("OTAsyncOpenEndpoint failed --- client socket could not be opened"); goto error_return; } // Set blocking mode // I'm not sure if this is a good solution.... // Check out Apple's sample code, OT Virtual Server // ( 010314 masahiro minami<*****@*****.**>) sock->error = OTSetBlocking( sock->channel ); if( sock->error != kOTNoError ) { SDLNet_SetError("OTSetBlocking() returned an error"); goto error_return; } // Bind the socket OTInitInetAddress(&inAddr, 0, 0 ); bindReq.addr.len = sizeof( InetAddress ); bindReq.addr.buf = (unsigned char*)&inAddr; bindReq.qlen = 0; sock->error = OTBind( sock->channel, &bindReq, NULL ); AsyncTCPPopEvent(sock); while( !sock->error && !( sock->completion & CompleteMask(T_BINDCOMPLETE))) { //YieldToAnyThread(); //WaitNextEvent(everyEvent, &macEvent, 1, NULL); AsyncTCPPopEvent(sock); } switch( stat = OTGetEndpointState( sock->channel )) { InetAddress inAddr; TCall sndCall; OTResult res; case T_OUTCON: SDLNet_SetError("SDLNet_Open() failed -- T_OUTCON"); goto error_return; break; case T_IDLE: sock->readShutdown = false; sock->writeShutdown = false; sock->event &=~T_CONNECT; OTMemzero(&sndCall, sizeof(TCall)); OTInitInetAddress(&inAddr, ip->port, ip->host ); sndCall.addr.len = sizeof(InetAddress); sndCall.addr.buf = (unsigned char*)&inAddr; sock->connected = 0; res = OTConnect( sock->channel, &sndCall, NULL ); AsyncTCPPopEvent(sock); while( sock->error == kOTNoDataErr || !sock->connected ) AsyncTCPPopEvent(sock); break; default: // What's to be done ? (TODO) SDLNet_SetError("SDLNet_TCP_Open() failed -- EndpointState not good"); goto error_return; } if( !(sock->event & (T_CONNECT|T_DISCONNECT))) goto error_return; AsyncTCPPopEvent( sock ); while( !(sock->event & (T_CONNECT|T_DISCONNECT))) { AsyncTCPPopEvent( sock ); } // OTConnect successfull if( sock->event & T_CONNECT) { sock->remoteAddress.host = inAddr.fHost; sock->remoteAddress.port = inAddr.fPort; sock->sflag = false; } else { // OTConnect failed sock->event &= ~T_DISCONNECT; goto error_return; } } else { // ######## Bind locally TBind bindReq; InetAddress inAddr; // First, get InetInterfaceInfo. // I don't search for all of them. // Does that matter ? sock->error = OTAsyncOpenEndpoint( OTCreateConfiguration("tilisten, tcp"), NULL, &(sock->info), (OTNotifyProcPtr)(AsyncTCPNotifier), sock); AsyncTCPPopEvent( sock ); while( !sock->error && !( sock->completion & CompleteMask( T_OPENCOMPLETE))) { AsyncTCPPopEvent( sock ); } if( ! sock->channel ) { SDLNet_SetError("OTAsyncOpenEndpoint failed --- server socket could not be opened"); goto error_return; } // Create a master OTConfiguration sock->config = OTCreateConfiguration(kTCPName); if( ! sock->config ) { SDLNet_SetError("Could not create master OTConfiguration"); goto error_return; } // Bind the socket OTInitInetAddress(&inAddr, ip->port, 0 ); inAddr.fAddressType = AF_INET; bindReq.addr.len = sizeof( InetAddress ); bindReq.addr.buf = (unsigned char*)&inAddr; bindReq.qlen = 35; // This number is NOT well considered. (TODO) sock->localAddress.host = inAddr.fHost; sock->localAddress.port = inAddr.fPort; sock->sflag = true; sock->error = OTBind( sock->channel, &bindReq, NULL ); AsyncTCPPopEvent(sock); while( !sock->error && !( sock->completion & CompleteMask(T_BINDCOMPLETE))) { AsyncTCPPopEvent(sock); } if( sock->error != kOTNoError ) { SDLNet_SetError("Could not bind server socket"); goto error_return; } if( dummy ) OTCloseProvider( dummy ); } sock->ready = 0; return sock; error_return: if( dummy ) OTCloseProvider( dummy ); SDLNet_TCP_Close( sock ); return NULL; }