NMErr
OTIPEnumerator::ReceiveDatagram(void)
{
	DEBUG_ENTRY_EXIT("IPEnumerator::ReceiveDatagram");

NMErr		status = kNMNoError;
OTResult	result;
OTFlags		flags = 0;
	
	do
	{
		result = OTRcvUData(mEP, &mIncomingData, &flags);

		if (result == kOTLookErr)
			HandleLookErr();
		else if (result == kNMNoError)
			HandleReply(mIncomingData.udata.buf, mIncomingData.udata.len, (InetAddress *) mIncomingData.addr.buf);

	} while (result != kNMNoError && result == kOTLookErr);

	if (result == kOTNoDataErr)
		bDataWaiting = false;
		
	return status;

}
Exemple #2
0
/* Receive a vector of pending packets from the UDP socket.
   The returned packets contain the source address and the channel they arrived
   on.  If they did not arrive on a bound channel, the the channel will be set
   to -1.
   This function returns the number of packets read from the network, or -1
   on error.  This function does not block, so can return 0 packets pending.
*/
extern int SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets)
{
	int numrecv, i, j;
	struct UDP_channel *binding;
#ifdef MACOS_OPENTRANSPORT
	TUnitData OTpacket;
	OTFlags flags;
	InetAddress address;
#else
	int sock_len;
	struct sockaddr_in sock_addr;
#endif

	numrecv = 0;
	while ( packets[numrecv] && SocketReady(sock->channel) ) 
	{
	UDPpacket *packet;

		packet = packets[numrecv];
		
#ifdef MACOS_OPENTRANSPORT
		memset(&OTpacket, 0, sizeof(OTpacket));
		OTpacket.addr.buf = (Uint8 *)&address;
		OTpacket.addr.maxlen = (sizeof address);
		OTpacket.udata.buf = packet->data;
		OTpacket.udata.maxlen = packet->maxlen;
		
		packet->status = OTRcvUData(sock->channel, &OTpacket, &flags);
#ifdef DEBUG_NET
		printf("Packet status: %d\n", packet->status);
#endif
		AsyncUDPPopEvent(sock);
		if (packet->status == noErr)
		{
			packet->len = OTpacket.udata.len;
			packet->address.host = address.fHost;
			packet->address.port = address.fPort;
#ifdef DEBUG_NET
			printf("Packet address: 0x%8.8x:%d, length = %d\n", packet->address.host, packet->address.port, packet->len);
#endif
		}
#else
		sock_len = sizeof(sock_addr);
		packet->status = recvfrom(sock->channel,
				packet->data, packet->maxlen, 0,
				(struct sockaddr *)&sock_addr,
#ifdef USE_GUSI_SOCKETS
				(unsigned int *)&sock_len);
#else
						&sock_len);
#endif
		if ( packet->status >= 0 ) {
			packet->len = packet->status;
			packet->address.host = sock_addr.sin_addr.s_addr;
			packet->address.port = sock_addr.sin_port;
		}
#endif
		if (packet->status >= 0)
		{
			packet->channel = -1;
			
			for (i=(SDLNET_MAX_UDPCHANNELS-1); i>=0; --i ) 
			{
				binding = &sock->binding[i];
				
				for ( j=binding->numbound-1; j>=0; --j ) 
				{
					if ( (packet->address.host == binding->address[j].host) &&
					     (packet->address.port == binding->address[j].port) ) 
					{
						packet->channel = i;
						goto foundit; /* break twice */
					}
				}
			}
foundit:
			++numrecv;
		} 
		
		else 
		{
			packet->len = 0;
		}
	}
	
	sock->ready = 0;
	
	return(numrecv);
}
Exemple #3
0
// 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;
	PRInt32 osfd = fd->secret->md.osfd;
	EndpointRef endpoint = (EndpointRef) osfd;
	PRThread *me = _PR_MD_CURRENT_THREAD();
	PRInt32 bytesLeft = amount;
	TUnitData dgram;

	PR_ASSERT(flags == 0);
	
	if (endpoint == NULL) {
		err = kEBADFErr;
		goto ErrorExit;
	}
		
	if (buf == NULL || addr == NULL) {
		err = kEFAULTErr;
		goto ErrorExit;
	}
		
	memset(&dgram, 0 , sizeof(dgram));
	dgram.addr.maxlen = *addrlen;
	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) {
	
		PrepareThreadForAsyncIO(me, endpoint, osfd);    

		if (opCode == kDGRAM_SEND)
			err = OTSndUData(endpoint, &dgram);
		else if (opCode == kDGRAM_RECEIVE)
			err = OTRcvUData(endpoint, &dgram, NULL);
		else {
			err = kEINVALErr;
			goto ErrorExit;
		}

		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 {
			PR_ASSERT(err == kOTNoDataErr || err == kOTOutStateErr);
			WaitOnThisThread(me, timeout);
			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;
}                               
Exemple #4
0
/* 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.  */
void otudp_read(OTUDP *x) {
	TUnitData	unitdata;
	OTFlags		flags;
	OSStatus	err;
	OTBuffer *theOTBuffer;
	long shouldCheckAgain;
	PacketBuffer myPB;
	UInt8 *bufferToUse;
	int i;
	int numPacketsThisTime;
	short oldLockout;
	
//	post("** Entering otudp_read");
		
	// Set up the data structures OT wants to put the incoming data into
	unitdata.addr.maxlen = sizeof(struct InetAddress);
	unitdata.opt.maxlen = 0;
	unitdata.opt.buf = 0;
	unitdata.udata.maxlen = x->bufsize;

	// Mutual exclusion:  Make sure that neither Max not Open Transport will interrupt
	// this until we've read all there is to read.  That makes it safe to access the global
	// buffer lists in my object.

	oldLockout = AcquireLock(x);

	numPacketsThisTime = 0;
	shouldCheckAgain = 1;		// By default, after we do one read we should do another
	while (shouldCheckAgain) {
	
		// Try to allocate an available PacketBuffer
		myPB = PacketBufferListPop(&(x->freeBuffers));
		if (myPB == 0) {
			// Out of buffers, but we're still going to do the read just so we can
			// drop the packet (gracefully) without Open Transport blowing up.
			if (x->o_errorreporting) {
				if (!(x->o_num_dropped_packets)) {
					error("otudp: Out of packet buffers; have to drop packet(s)");
				}
				++(x->o_num_dropped_packets);
				x->o_ever_dropped_a_packet = 1;
			}
			unitdata.udata.buf = DevNullBuffer;
			unitdata.addr.buf = DevNullBuffer;
		} else {
			unitdata.udata.buf = (UInt8 *) myPB->buf;
			unitdata.addr.buf = (UInt8*) &(myPB->returnAddress);
		}
			
		// post("** About to call OTRcvUData");
		err = OTRcvUData(x->o_udp_ep, &unitdata, &flags);
		
		if (err == kOTNoError ) {
			if (flags == 0) {
				if (myPB != 0) {
	 				myPB->n = unitdata.udata.len;
					PBFIFOEnqueue(myPB, &(x->pendingBuffers));
					++numPacketsThisTime;
					clock_delay(x->o_clock, 0);
				}
			} else if (flags == T_MORE) {
				// Only the beginning of the (large) UDP packet fit in our buffer
				if (x->o_errorreporting) {
					error("OTUDP: packet too big; dropping.");
				}
				
				++numPacketsThisTime;
				while (flags == T_MORE) {
					err = OTRcvUData(x->o_udp_ep, &unitdata, &flags);
				}
				if (myPB) PacketBufferListPush(myPB, &(x->freeBuffers));
			} else {
				if (x->o_errorreporting) {
					error("OTUDP: OTRcvUData returned flags of %ld; dropped packet", (long) flags);
				}
				if (myPB) PacketBufferListPush(myPB, &(x->freeBuffers));
			}
		} else if ( err == kOTNoDataErr ) {
			/* We're supposed to keep trying to read incoming data until we get this
			   "error", so it's not really an error; it just says we've read enough
			   for now. */
			shouldCheckAgain = 0;
			if (myPB) {
				PacketBufferListPush(myPB, &(x->freeBuffers));
			} else {
				// We're out of buffers, but we didn't actually need one, so we need to un-count
				// this as a dropped packet
				--(x->o_num_dropped_packets);
			}
		} else {
			error("OTUDP: OTRcvUData returned error %ld; dropped packet", (long) err);
			if (myPB) PacketBufferListPush(myPB, &(x->freeBuffers));
		}
	}

end:
	
	ReleaseLock(x, oldLockout);

/*
	if (numPacketsThisTime > 1) {
		post("* Read %ld packets in one call to otudp_read", numPacketsThisTime);
	}
*/
}