int TCPLow_PutPacket(TCPINSTANCE* tcp, TCPPEER* pPeer,void* bufptr,ULONG len) { TUnitData udata; OSStatus err; OTResult theResult; InetAddress destAddr; unsigned char *pt; OTInitInetAddress(&destAddr,pPeer->port,pPeer->addr); udata.addr.maxlen = sizeof(InetAddress); udata.addr.len = sizeof(InetAddress); udata.addr.buf = (unsigned char *) &destAddr; udata.opt.maxlen = 0; udata.opt.len = 0; udata.opt.buf = nil; udata.udata.maxlen = len; udata.udata.len = len; udata.udata.buf = (unsigned char *)bufptr; do { err = OTSndUData(tcp->udpEndpoint, &udata); if (err == kOTLookErr) { theResult = OTLook(tcp->udpEndpoint); if (theResult == T_UDERR) { HandleErrorUDERR(); err = 666; } } } while (err == 666); return err; }
// 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); }
void OTIPEnumerator::HandleLookErr(void) { DEBUG_ENTRY_EXIT("IPEnumerator::HandleLookErr"); OTResult result; OSStatus status; TUDErr udErr; InetAddress addr; udErr.addr.buf = (NMUInt8 *) &addr; udErr.addr.len = udErr.addr.maxlen = sizeof(InetAddress); udErr.opt.maxlen = 0; result = OTLook(mEP); DEBUG_PRINT("OTLook returned %ld", result); switch (result) { case T_DATA: ReceiveDatagram(); break; case T_UDERR: status = OTRcvUDErr(mEP, &udErr); DEBUG_PRINT("OTRcvUDErr returned %ld", status); break; default: DEBUG_PRINT("Unhandled look error!"); break; } }
int tcpabi_udp_send( unsigned handle, void *buf, unsigned len, unsigned ttltos, unsigned id, unsigned char flags ) { TUnitData udata; OSStatus err; OTResult theResult; udata.addr.maxlen = sizeof(gDests[handle].dest_addr); udata.addr.len = sizeof(gDests[handle].dest_addr); udata.addr.buf = (unsigned char *) &gDests[handle].dest_addr; udata.opt.maxlen = 0; udata.opt.len = 0; udata.opt.buf = nil; udata.udata.maxlen = len; udata.udata.len = len; udata.udata.buf = (unsigned char *)buf; do { err = OTSndUData(gUDPEndpoint, &udata); if (err == kOTLookErr) { theResult = OTLook(gUDPEndpoint); if (theResult == T_UDERR) { HandleErrorUDERR(); err = 666; } } } while (err == 666); return err; }
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); }
/* Returns true if a socket is has data available for reading right now */ static int SocketReady(SOCKET sock) { int retval = 0; #ifdef MACOS_OPENTRANSPORT OTResult status; #else struct timeval tv; fd_set mask; #endif #ifdef MACOS_OPENTRANSPORT //status = OTGetEndpointState(sock); status = OTLook(sock); if( status > 0 ) retval = 1; /* switch( status ) { // case T_IDLE: case T_DATAXFER: // case T_INREL: retval = 1; break; default: OTCountDataBytes( sock, &numBytes ); if( numBytes ) retval = 1; }*/ #else /* Check the file descriptors for available data */ do { errno = 0; /* Set up the mask of file descriptors */ FD_ZERO(&mask); FD_SET(sock, &mask); /* Set up the timeout */ tv.tv_sec = 0; tv.tv_usec = 0; /* Look! */ retval = select(sock+1, &mask, NULL, NULL, &tv); } while ( errno == EINTR ); #endif /* MACOS_OPENTRANSPORT */ return(retval == 1); }
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; }
int tcpabi_udp_broadcast(void *buf, unsigned len) { OSStatus err = noErr; TUnitData udata; OTResult theResult; short i; InetAddress currentAddress; // this method sends the specified packet to our list of // IP addreses. We return noErr if they were all sent // without any trouble (we should ignore errors which // indicate that the other end is not there since we // really don't care if all of these packets are delivered) // we don't broadcast to the first address because it's our own for (i = 1; i < gAddressList.addressCount; i++) { OTInitInetAddress(¤tAddress, SOCKET_MW2, gAddressList.addressList[i]); udata.addr.maxlen = sizeof(InetAddress); udata.addr.len = sizeof(InetAddress); udata.addr.buf = (unsigned char *) ¤tAddress; udata.opt.maxlen = 0; udata.opt.len = 0; udata.opt.buf = nil; udata.udata.maxlen = len; udata.udata.len = len; udata.udata.buf = (unsigned char *)buf; do { err = OTSndUData(gUDPEndpoint, &udata); if (err == kOTLookErr) { theResult = OTLook(gUDPEndpoint); if (theResult == T_UDERR) { HandleErrorUDERR(); err = 666; } } } while (err == 666); } return err; }
void PostUDERR(char *source, EndpointRef ep) { OSStatus err; TUDErr errBlock; struct InetAddress addr; #define OPTIONS_LENGTH 2048 unsigned char RoomForStupidOptions[OPTIONS_LENGTH]; errBlock.addr.buf = (void *) &addr; errBlock.addr.maxlen = sizeof(addr); #ifdef IGNORE_OPTIONS errBlock.opt.len = 0; errBlock.opt.maxlen = 0; errBlock.opt.buf = 0; #else errBlock.opt.len = 0; errBlock.opt.maxlen = OPTIONS_LENGTH; errBlock.opt.buf = RoomForStupidOptions; #endif err = OTRcvUDErr(ep, &errBlock); post("OTUDP: %s \"protocol-dependent\" error code %ld", source, errBlock.error); { char hostNameString[255]; OTInetHostToString(addr.fHost, hostNameString); post(" Addr. assoc w/ error is %s, port %d.", hostNameString, addr.fPort); } if (errBlock.error == 49) { post("Error 49 seems to mean that you're sending to a machine that's listening to"); post("UDP but not on the port you're sending to."); } if (err == kOTNoError ) { // No further error; don't worry about it } else if (err == kOTLookErr) { OTResult r = OTLook(ep); post("Got kOTLookErr; OTLook returned %d", r); } else if (err == kOTFlowErr) { post("Flow control error."); } else if (err == kOTBufferOverflowErr) { post("Lame Open Transport says it doesn't have enough memory0 to tell me what my problem is."); } else { post("OTRcvUDErr returned %ld", err); } }
int atalk_ddp_broadcast(void *buf, unsigned len) { OSStatus err = noErr; TUnitData udata; OTResult theResult; short i; extern short gLookupCount; extern DDPAddress gLookupResults[]; // this method sends the specified packet to our list of // DDP addreses. We return noErr if they were all sent // without any trouble (we should ignore errors which // indicate that the other end is not there since we // really don't care if all of these packets are delivered) for (i = 0; i < gLookupCount; i++) { udata.addr.len = sizeof(DDPAddress); udata.addr.buf = (unsigned char *) &gLookupResults[i]; udata.opt.len = 0; udata.opt.buf = nil; udata.udata.len = len; udata.udata.buf = (unsigned char *)buf; do { err = OTSndUData(gDDPEndpoint, &udata); if (err == kOTLookErr) { theResult = OTLook(gDDPEndpoint); if (theResult == T_UDERR) { HandleErrorUDERR(); err = 666; } } } while (err == 666); } return err; }
/* 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); }
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; }
int tcpabi_udp_send_to_address(InetAddress* theAddress, void *buf, unsigned len) { TUnitData udata; OSStatus err; OTResult theResult; // send our list of addresses to the destination address udata.addr.maxlen = sizeof(InetAddress); udata.addr.len = sizeof(InetAddress); udata.addr.buf = (unsigned char *) theAddress; udata.opt.maxlen = 0; udata.opt.len = 0; udata.opt.buf = nil; udata.udata.maxlen = len; udata.udata.len = len; udata.udata.buf = (unsigned char *)buf; do { err = OTSndUData(gUDPEndpoint, &udata); if (err == kOTLookErr) { theResult = OTLook(gUDPEndpoint); if (theResult == T_UDERR) { HandleErrorUDERR(); err = 666; } } } while (err == 666); // add the destination address to our list of addresses AddAddressToList(theAddress->fHost); return err; }
void ottcp_handleIncomingData(OTTCP *x) { /* Here's where we actually do the read. This is called by our notifier, so it will run at "deferred task time", i.e., interrupt level. */ OTFlags flags; OTResult r; short oldLockout; EnterCallback(); // post("** Entering ottcp_handleIncomingData"); // Are we in a state where we want to read data that comes in? if (x->o_state == SETTING_UP) { post("е OTTCP: How could ottcp_handleIncomingData() be called in state SETTING_UP?"); } else if (x->o_state == NO_REQUEST) { // The rest of this Max program hasn't asked us for any data yet, so // we won't read it out of OpenTransport. That way, when OT's buffers // fill up, TCP flow control will happen correctly. x->o_datawaiting = 1; } else if (x->o_state == OUTPUTTING) { // We're still busy trying to output the last chunk of data, so again // we just leave the new data in OT's buffers so flow control will work. x->o_datawaiting = 1; } else if (x->o_state == GET_NBYTES) { // Try to read N bytes long numLeftToRead = x->o_numBytesWeWant - x->o_bytesRead; if (numLeftToRead <= 0) { post("е OTTCP: internal error: read too much."); } else { oldLockout = AcquireLock(x); r = OTRcv(x->o_tcp_ep, x->o_currentReadBuf+x->o_bytesRead, numLeftToRead, &flags); ReleaseLock(x,oldLockout); if (r == numLeftToRead) { // We read everything we wanted, so output the darn buffer x->o_bytesRead += r; ChangeState(x, OUTPUTTING); x->o_whatToOutput = GET_NBYTES; clock_delay(x->o_clock, 0); // Maybe there's more data to be read x->o_datawaiting = 1; } else if (r > 0) { // We read some, but not all, of our N bytes. x->o_bytesRead += r; x->o_datawaiting = 0; } else if (r == kOTNoDataErr) { // We didn't read squat, but that's supposed to be OK. x->o_datawaiting = 0; } else if (r == kOTLookErr) { OTResult lookr = OTLook(x->o_tcp_ep); post("OTTCP: OTRcv returned kOTLookErr; OTLook returned %ld", lookr); } else { post("е OTTCP: warning: OTRcv returned %ld", r); } } } else if (x->o_state == GET_DELIM) { long capacity = x->o_ReadBufSize - x->o_bytesRead; long numToRead; if (capacity > MAX_TO_READ_LOOKING_FOR_DELIMITER) { numToRead = MAX_TO_READ_LOOKING_FOR_DELIMITER; } else { numToRead = capacity; } readagain: oldLockout = AcquireLock(x); r = OTRcv(x->o_tcp_ep, x->o_currentReadBuf+x->o_bytesRead, numToRead, &flags); ReleaseLock(x,oldLockout); if (r == numToRead) { // We read everything we asked for char *afterDelimiter; x->o_datawaiting = 1; // Maybe there's more data to be read x->o_bytesRead += r; if (FoundDelimiter(x, &afterDelimiter)) { ChangeState(x, OUTPUTTING); x->o_whatToOutput = GET_DELIM; CopyAfterDelimiterToOtherBuffer(x, afterDelimiter); clock_delay(x->o_clock, 0); } else if (x->o_bytesRead == x->o_ReadBufSize) { post("е OTTCP: error: filled %ld byte read buffer but never found delimiter string \"%s\"", x->o_ReadBufSize, x->o_delimiterBytes); post("Discarding buffer and calling off the search. You probably want to reconnect."); ChangeState(x, NO_REQUEST); x->o_bytesRead = 0; } else { // We didn't find the delimiter in the MAX_TO_READ_LOOKING_FOR_DELIMITER bytes // we read, but we've got more room in our buffer and there may be more // data in the OT buffer, so let's do another read. goto readagain; } } else if (r > 0) { // We read everything that was available char *afterDelimiter; x->o_datawaiting = 0; x->o_bytesRead += r; if (FoundDelimiter(x, &afterDelimiter)) { ChangeState(x, OUTPUTTING); x->o_whatToOutput = GET_DELIM; CopyAfterDelimiterToOtherBuffer(x, afterDelimiter); clock_delay(x->o_clock, 0); } else { // We didn't see the delimiter, TCP's buffer is empty, and our buffer // still has room, so there's nothing else to do until the next T_DATA event. } } else if (r == kOTNoDataErr) { // We didn't read squat, but that's supposed to be OK. x->o_datawaiting = 0; } else if (r == kOTLookErr) { OTResult lookr = OTLook(x->o_tcp_ep); post("OTTCP: OTRcv returned kOTLookErr; OTLook returned %ld", lookr); } else { post("е OTTCP: warning: OTRcv returned %ld", r); } } else { post("е OTTCP: error: unrecognized state %ld", x->o_state); } bag: ExitCallback(); }
void do_write(OTTCP *x, long length, void *bytes) { OTResult r; if (x->o_WBReadPos == x->o_WBWritePos) { // Nothing in the circular buffer, so try to write the new stuff if (length == 0) return; r = OTSnd(x->o_tcp_ep, bytes, length, (OTFlags) 0); if (r == length) { // Great; everything was accepted } else if (r > 0) { // Partial flow control: some was accepted; the rest was not AddToWriteBuffer(x, length-r, ((void *) (((char *) bytes) + r))); } else if (r == kOTFlowErr) { // Full flow control situation: nothing was accepted AddToWriteBuffer(x, length, bytes); } else if (r == kOTLookErr) { // Maybe we got a disconnect or something OTResult lookr = OTLook(x->o_tcp_ep); post("е OTTCP: OTSnd returned kOTLookErr; OTLook returned %ld", lookr); } else { post("е OTTCP: OTSnd returned %ld", r); } } else { // We already have some flow-controlled bytes in the write buffer; they have to // go out before the new ones. We'll try to write the old ones again, just in case // they go out, and the new ones go out, without copying the new ones into the buffer if (x->o_WBReadPos > x->o_WBWritePos) { // Data in the buffer wraps around, so first we try to OTSnd the contiguous // part up to the end of the buffer r = OTSnd(x->o_tcp_ep, x->o_WriteBuf + x->o_WBReadPos, x->o_WriteBufSize - x->o_WBReadPos, (OTFlags) 0); if (r == length) { // Great; the latter part of the write buffer was accepted // Adjust the read position of the write buffer and make a recursive // call to try to write some more x->o_WBReadPos = 0; do_write(x, length, bytes); } else if (r > 0) { // Partial flow control: some was accepted; the rest was not x->o_WBReadPos += r; AddToWriteBuffer(x, length, bytes); } else if (r == kOTFlowErr) { // Full flow control situation: nothing was accepted AddToWriteBuffer(x, length, bytes); } else if (r == kOTLookErr) { // Maybe we got a disconnect or something OTResult lookr = OTLook(x->o_tcp_ep); post("е OTTCP: OTSnd returned kOTLookErr; OTLook returned %ld", lookr); } else { post("е OTTCP: OTSnd returned %ld", r); } } else { // Data in the write buffer is all in one contiguous chunk, so try writing it r = OTSnd(x->o_tcp_ep, x->o_WriteBuf+x->o_WBReadPos, x->o_WBWritePos - x->o_WBReadPos, (OTFlags) 0); if (r == length) { // Great; the entire write buffer was accepted. Mark it empty // and make a recursive call to try to write the new stuff x->o_WBReadPos = x->o_WBWritePos = 0; do_write(x, length, bytes); } else if (r > 0) { // Partial flow control: some was accepted; the rest was not x->o_WBReadPos += r; AddToWriteBuffer(x, length, bytes); } else if (r == kOTFlowErr) { // Full flow control situation: nothing was accepted AddToWriteBuffer(x, length, bytes); } else if (r == kOTLookErr) { // Maybe we got a disconnect or something OTResult lookr = OTLook(x->o_tcp_ep); post("е OTTCP: OTSnd returned kOTLookErr; OTLook returned %ld", lookr); } else { post("е OTTCP: OTSnd returned %ld", r); } } } }
/* 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); } }