project_files/Android-build/SDL-android-project/jni/sdl_net/SDLnetUDP.c
branchhedgeroid
changeset 5317 86984c1034a5
equal deleted inserted replaced
5314:09bcdcd78379 5317:86984c1034a5
       
     1 /*
       
     2     SDL_net:  An example cross-platform network library for use with SDL
       
     3     Copyright (C) 1997-2004 Sam Lantinga
       
     4 
       
     5     This library is free software; you can redistribute it and/or
       
     6     modify it under the terms of the GNU Library General Public
       
     7     License as published by the Free Software Foundation; either
       
     8     version 2 of the License, or (at your option) any later version.
       
     9 
       
    10     This library is distributed in the hope that it will be useful,
       
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13     Library General Public License for more details.
       
    14 
       
    15     You should have received a copy of the GNU Library General Public
       
    16     License along with this library; if not, write to the Free
       
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    18 
       
    19     Sam Lantinga
       
    20     slouken@libsdl.org
       
    21 */
       
    22 
       
    23 /* $Id: SDLnetUDP.c 1192 2004-01-04 17:41:55Z slouken $ */
       
    24 
       
    25 #include "SDLnetsys.h"
       
    26 #include "SDL_net.h"
       
    27 #ifdef MACOS_OPENTRANSPORT
       
    28 #include <Events.h>
       
    29 #endif
       
    30 
       
    31 struct _UDPsocket {
       
    32 	int ready;
       
    33 	SOCKET channel;
       
    34 	IPaddress address;
       
    35 
       
    36 #ifdef MACOS_OPENTRANSPORT
       
    37 	OTEventCode newEvent;
       
    38 	OTEventCode event;
       
    39 	OTEventCode curEvent;
       
    40 	OTEventCode newCompletion;
       
    41 	OTEventCode completion;
       
    42 	OTEventCode curCompletion;
       
    43 	TEndpointInfo info;
       
    44 	Boolean		readShutdown;
       
    45 	Boolean		writeShutdown;
       
    46 	OSStatus	error;
       
    47 	OTConfigurationRef	config;		// Master configuration. you can clone this.
       
    48 #endif /* MACOS_OPENTRANSPORT */
       
    49 
       
    50 	struct UDP_channel {
       
    51 		int numbound;
       
    52 		IPaddress address[SDLNET_MAX_UDPADDRESSES];
       
    53 	} binding[SDLNET_MAX_UDPCHANNELS];
       
    54 };
       
    55 
       
    56 #ifdef MACOS_OPENTRANSPORT
       
    57 
       
    58 /* A helper function for Mac OpenTransport support*/
       
    59 // This function is a complete copy from GUSI
       
    60 // ( masahiro minami<elsur@aaa.letter.co.jp> )
       
    61 // ( 01/02/19 )
       
    62 //
       
    63 // I guess this function should be put in SDLnet.c
       
    64 // ( 010315 masahiro minami<elsur@aaa.letter.co.jp>)
       
    65 // (TODO)
       
    66 static __inline__ Uint32 CompleteMask(OTEventCode code)	
       
    67 { 	
       
    68 	return 1 << (code & 0x1F); 
       
    69 }
       
    70 
       
    71 /* Notifier for async OT calls */
       
    72 // This function is completely same as AsyncTCPNotifier,
       
    73 // except for the argument, UDPsocket / TCPsocket
       
    74 // ( 010315 masahiro minami<elsur@aaa.letter.co.jp>)
       
    75 static pascal void AsyncUDPNotifier( UDPsocket sock, OTEventCode code,
       
    76 					OTResult result, void* cookie )
       
    77 {
       
    78 	switch( code & 0x7f000000L)
       
    79 	{
       
    80 		case 0:
       
    81 			sock->newEvent |= code;
       
    82 			result = 0;
       
    83 			break;
       
    84 		case kCOMPLETEEVENT:
       
    85 			if(!(code & 0x00FFFFE0 ))
       
    86 				sock->newCompletion |= CompleteMask( code );
       
    87 			if( code == T_OPENCOMPLETE )
       
    88 				sock->channel = (SOCKET)(cookie);
       
    89 			break;
       
    90 		default:
       
    91 			if( code != kOTProviderWillClose )
       
    92 				result = 0;
       
    93 	}
       
    94 	// Do we need these ???? TODO
       
    95 	// sock->SetAsyncMacError( result );
       
    96 	// sock->Wakeup();
       
    97 	
       
    98 	// Do we need to ?
       
    99 	//YieldToAnyThread();
       
   100 }
       
   101 
       
   102 /* Retrieve OT event */
       
   103 // This function is completely same as AsyncTCPPopEvent,
       
   104 // except for the argument, UDPsocket / TCPsocket
       
   105 // ( 010315 masahiro minami<elsur@aaa.letter.co.jp>)
       
   106 static void AsyncUDPPopEvent( UDPsocket sock )
       
   107 {
       
   108 	// Make sure OT calls are not interrupted
       
   109 	// Not sure if we really need this.
       
   110 	OTEnterNotifier( sock->channel );
       
   111 	
       
   112 	sock->event |= (sock->curEvent = sock->newEvent );
       
   113 	sock->completion |= ( sock->curCompletion = sock->newCompletion );
       
   114 	sock->newEvent = sock->newCompletion = 0;
       
   115 	
       
   116 	OTLeaveNotifier( sock->channel );
       
   117 	
       
   118 	if( sock->curEvent & T_UDERR)
       
   119 	{
       
   120 		// We just clear the error.
       
   121 		// Should we feed this back to users ?
       
   122 		// (TODO )
       
   123 		OTRcvUDErr( sock->channel, NULL );	
       
   124 	}
       
   125 	
       
   126 	// Remote is disconnecting...
       
   127 	if( sock->curEvent & ( T_DISCONNECT | T_ORDREL ))
       
   128 	{
       
   129 		sock->readShutdown = true;
       
   130 	}
       
   131 	
       
   132 	if( sock->curEvent &T_CONNECT)
       
   133 	{
       
   134 		// Ignore the info of remote (second parameter).
       
   135 		// Shoule we care ?
       
   136 		// (TODO)
       
   137 		OTRcvConnect( sock->channel, NULL );	
       
   138 	}
       
   139 	
       
   140 	if( sock->curEvent & T_ORDREL )
       
   141 	{
       
   142 		OTRcvOrderlyDisconnect( sock->channel );
       
   143 	}
       
   144 	
       
   145 	if( sock->curEvent & T_DISCONNECT )
       
   146 	{
       
   147 		OTRcvDisconnect( sock->channel, NULL );
       
   148 	}
       
   149 	
       
   150 	// Should we ??
       
   151 	// (010318 masahiro minami<elsur@aaa.letter.co.jp>
       
   152 	//YieldToAnyThread();
       
   153 }
       
   154 
       
   155 /* Create a new UDPsocket */
       
   156 // Because TCPsocket structure gets bigger and bigger,
       
   157 // I think we'd better have a constructor function and delete function.
       
   158 // ( 01/02/25 masahiro minami<elsur@aaa.letter.co.jp> )
       
   159 /*static*/ UDPsocket AsyncUDPNewSocket()
       
   160 {
       
   161 	UDPsocket sock;
       
   162 	
       
   163 	sock = (UDPsocket)malloc(sizeof(*sock));
       
   164 	if ( sock == NULL ) {
       
   165 		SDLNet_SetError("Out of memory");
       
   166 		return NULL;
       
   167 	}
       
   168 	
       
   169 	sock->newEvent = 0;
       
   170 	sock->event = 0;
       
   171 	sock->curEvent = 0;
       
   172 	sock->newCompletion = 0;
       
   173 	sock->completion = 0;
       
   174 	sock->curCompletion = 0;
       
   175 	//sock->info = NULL;
       
   176 	sock->readShutdown = sock->writeShutdown = false;
       
   177 	sock->error = 0;
       
   178 	sock->config = NULL;
       
   179 	
       
   180 	return sock;	
       
   181 }
       
   182 
       
   183 #endif /* MACOS_OPENTRANSPORT */
       
   184 
       
   185 /* Allocate/free a single UDP packet 'size' bytes long.
       
   186    The new packet is returned, or NULL if the function ran out of memory.
       
   187  */
       
   188 extern UDPpacket *SDLNet_AllocPacket(int size)
       
   189 {
       
   190 	UDPpacket *packet;
       
   191 	int error;
       
   192 
       
   193 
       
   194 	error = 1;
       
   195 	packet = (UDPpacket *)malloc(sizeof(*packet));
       
   196 	if ( packet != NULL ) {
       
   197 		packet->maxlen = size;
       
   198 		packet->data = (Uint8 *)malloc(size);
       
   199 		if ( packet->data != NULL ) {
       
   200 			error = 0;
       
   201 		}
       
   202 	}
       
   203 	if ( error ) {
       
   204 		SDLNet_FreePacket(packet);
       
   205 		packet = NULL;
       
   206 	}
       
   207 	return(packet);
       
   208 }
       
   209 int SDLNet_ResizePacket(UDPpacket *packet, int newsize)
       
   210 {
       
   211 	Uint8 *newdata;
       
   212 
       
   213 	newdata = (Uint8 *)malloc(newsize);
       
   214 	if ( newdata != NULL ) {
       
   215 		free(packet->data);
       
   216 		packet->data = newdata;
       
   217 		packet->maxlen = newsize;
       
   218 	}
       
   219 	return(packet->maxlen);
       
   220 }
       
   221 extern void SDLNet_FreePacket(UDPpacket *packet)
       
   222 {
       
   223 	if ( packet ) {
       
   224 		if ( packet->data )
       
   225 			free(packet->data);
       
   226 		free(packet);
       
   227 	}
       
   228 }
       
   229 
       
   230 /* Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets,
       
   231    each 'size' bytes long.
       
   232    A pointer to the packet array is returned, or NULL if the function ran out
       
   233    of memory.
       
   234  */
       
   235 UDPpacket **SDLNet_AllocPacketV(int howmany, int size)
       
   236 {
       
   237 	UDPpacket **packetV;
       
   238 
       
   239 	packetV = (UDPpacket **)malloc((howmany+1)*sizeof(*packetV));
       
   240 	if ( packetV != NULL ) {
       
   241 		int i;
       
   242 		for ( i=0; i<howmany; ++i ) {
       
   243 			packetV[i] = SDLNet_AllocPacket(size);
       
   244 			if ( packetV[i] == NULL ) {
       
   245 				break;
       
   246 			}
       
   247 		}
       
   248 		packetV[i] = NULL;
       
   249 
       
   250 		if ( i != howmany ) {
       
   251 			SDLNet_FreePacketV(packetV);
       
   252 			packetV = NULL;
       
   253 		}
       
   254 	}
       
   255 	return(packetV);
       
   256 }
       
   257 void SDLNet_FreePacketV(UDPpacket **packetV)
       
   258 {
       
   259 	if ( packetV ) {
       
   260 		int i;
       
   261 		for ( i=0; packetV[i]; ++i ) {
       
   262 			SDLNet_FreePacket(packetV[i]);
       
   263 		}
       
   264 		free(packetV);
       
   265 	}
       
   266 }
       
   267 
       
   268 /* Since the UNIX/Win32/BeOS code is so different from MacOS,
       
   269    we'll just have two completely different sections here.
       
   270 */
       
   271 
       
   272 /* Open a UDP network socket
       
   273    If 'port' is non-zero, the UDP socket is bound to a fixed local port.
       
   274 */
       
   275 extern UDPsocket SDLNet_UDP_Open(Uint16 port)
       
   276 {
       
   277 	UDPsocket sock;
       
   278 #ifdef MACOS_OPENTRANSPORT
       
   279 	EndpointRef dummy = NULL;
       
   280 #endif
       
   281 
       
   282 	/* Allocate a UDP socket structure */
       
   283 	sock = (UDPsocket)malloc(sizeof(*sock));
       
   284 	if ( sock == NULL ) {
       
   285 		SDLNet_SetError("Out of memory");
       
   286 		goto error_return;
       
   287 	}
       
   288 	memset(sock, 0, sizeof(*sock));
       
   289 	
       
   290 	/* Open the socket */
       
   291 #ifdef MACOS_OPENTRANSPORT
       
   292 	{
       
   293 		sock->error = OTAsyncOpenEndpoint(
       
   294 			OTCreateConfiguration(kUDPName),0, &(sock->info),
       
   295 			(OTNotifyProcPtr)AsyncUDPNotifier, sock );
       
   296 		AsyncUDPPopEvent( sock );
       
   297 		while( !sock->error && !( sock->completion & CompleteMask(T_OPENCOMPLETE)))
       
   298 		{
       
   299 			AsyncUDPPopEvent( sock );
       
   300 		}
       
   301 		if( sock->error )
       
   302 		{
       
   303 			SDLNet_SetError("Could not open UDP socket");
       
   304 			goto error_return;
       
   305 		}
       
   306 		// Should we ??
       
   307 		// (01/05/03 minami<elsur@aaa.letter.co.jp>
       
   308 		OTSetBlocking( sock->channel );
       
   309 	}
       
   310 #else
       
   311 	sock->channel = socket(AF_INET, SOCK_DGRAM, 0);
       
   312 #endif /* MACOS_OPENTRANSPORT */
       
   313 
       
   314 	if ( sock->channel == INVALID_SOCKET ) 
       
   315 	{
       
   316 		SDLNet_SetError("Couldn't create socket");
       
   317 		goto error_return;
       
   318 	}
       
   319 
       
   320 #ifdef MACOS_OPENTRANSPORT
       
   321 	{
       
   322 	InetAddress required, assigned;
       
   323 	TBind req_addr, assigned_addr;
       
   324 	OSStatus status;
       
   325 	InetInterfaceInfo info;
       
   326 		
       
   327 		memset(&assigned_addr, 0, sizeof(assigned_addr));
       
   328 		assigned_addr.addr.maxlen = sizeof(assigned);
       
   329 		assigned_addr.addr.len = sizeof(assigned);
       
   330 		assigned_addr.addr.buf = (UInt8 *) &assigned;
       
   331 		
       
   332 		if ( port ) {
       
   333 			status = OTInetGetInterfaceInfo( &info, kDefaultInetInterface );
       
   334 			if( status != kOTNoError )
       
   335 				goto error_return;
       
   336 			OTInitInetAddress(&required, port, info.fAddress );
       
   337 			req_addr.addr.maxlen = sizeof( required );
       
   338 			req_addr.addr.len = sizeof( required );
       
   339 			req_addr.addr.buf = (UInt8 *) &required;
       
   340 		
       
   341 			sock->error = OTBind(sock->channel, &req_addr, &assigned_addr);
       
   342 		} else {
       
   343 			sock->error = OTBind(sock->channel, nil, &assigned_addr );
       
   344 		}
       
   345 		AsyncUDPPopEvent(sock);
       
   346 
       
   347 		while( !sock->error && !(sock->completion & CompleteMask(T_BINDCOMPLETE)))
       
   348 		{
       
   349 			AsyncUDPPopEvent(sock);
       
   350 		}	
       
   351 		if (sock->error != noErr)
       
   352 		{
       
   353 			SDLNet_SetError("Couldn't bind to local port, OTBind() = %d",(int) status);
       
   354 			goto error_return;
       
   355 		}
       
   356 
       
   357 		sock->address.host = assigned.fHost;
       
   358 		sock->address.port = assigned.fPort;
       
   359 		
       
   360 #ifdef DEBUG_NET
       
   361 		printf("UDP open host = %d, port = %d\n", assigned.fHost, assigned.fPort );
       
   362 #endif
       
   363 	}
       
   364 #else
       
   365 	/* Bind locally, if appropriate */
       
   366 	if ( port )
       
   367 	{
       
   368 		struct sockaddr_in sock_addr;
       
   369 		memset(&sock_addr, 0, sizeof(sock_addr));
       
   370 		sock_addr.sin_family = AF_INET;
       
   371 		sock_addr.sin_addr.s_addr = INADDR_ANY;
       
   372 		sock_addr.sin_port = SDL_SwapBE16(port);
       
   373 
       
   374 		/* Bind the socket for listening */
       
   375 		if ( bind(sock->channel, (struct sockaddr *)&sock_addr,
       
   376 				sizeof(sock_addr)) == SOCKET_ERROR ) {
       
   377 			SDLNet_SetError("Couldn't bind to local port");
       
   378 			goto error_return;
       
   379 		}
       
   380 		/* Fill in the channel host address */
       
   381 		sock->address.host = sock_addr.sin_addr.s_addr;
       
   382 		sock->address.port = sock_addr.sin_port;
       
   383 	}
       
   384 
       
   385 #ifdef SO_BROADCAST
       
   386 	/* Allow LAN broadcasts with the socket */
       
   387 	{ int yes = 1;
       
   388 		setsockopt(sock->channel, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes));
       
   389 	}
       
   390 #endif
       
   391 #endif /* MACOS_OPENTRANSPORT */
       
   392 
       
   393 	/* The socket is ready */
       
   394 	
       
   395 	return(sock);
       
   396 
       
   397 error_return:
       
   398 #ifdef MACOS_OPENTRANSPORT
       
   399 	if( dummy )
       
   400 		OTCloseProvider( dummy );
       
   401 #endif
       
   402 	SDLNet_UDP_Close(sock);
       
   403 	
       
   404 	return(NULL);
       
   405 }
       
   406 
       
   407 /* Verify that the channel is in the valid range */
       
   408 static int ValidChannel(int channel)
       
   409 {
       
   410 	if ( (channel < 0) || (channel >= SDLNET_MAX_UDPCHANNELS) ) {
       
   411 		SDLNet_SetError("Invalid channel");
       
   412 		return(0);
       
   413 	}
       
   414 	return(1);
       
   415 }
       
   416 
       
   417 /* Bind the address 'address' to the requested channel on the UDP socket.
       
   418    If the channel is -1, then the first unbound channel will be bound with
       
   419    the given address as it's primary address.
       
   420    If the channel is already bound, this new address will be added to the
       
   421    list of valid source addresses for packets arriving on the channel.
       
   422    If the channel is not already bound, then the address becomes the primary
       
   423    address, to which all outbound packets on the channel are sent.
       
   424    This function returns the channel which was bound, or -1 on error.
       
   425 */
       
   426 int SDLNet_UDP_Bind(UDPsocket sock, int channel, IPaddress *address)
       
   427 {
       
   428 	struct UDP_channel *binding;
       
   429 
       
   430 	if ( channel == -1 ) {
       
   431 		for ( channel=0; channel < SDLNET_MAX_UDPCHANNELS; ++channel ) {
       
   432 			binding = &sock->binding[channel];
       
   433 			if ( binding->numbound < SDLNET_MAX_UDPADDRESSES ) {
       
   434 				break;
       
   435 			}
       
   436 		}
       
   437 	} else {
       
   438 		if ( ! ValidChannel(channel) ) {
       
   439 			return(-1);
       
   440 		}
       
   441 		binding = &sock->binding[channel];
       
   442 	}
       
   443 	if ( binding->numbound == SDLNET_MAX_UDPADDRESSES ) {
       
   444 		SDLNet_SetError("No room for new addresses");
       
   445 		return(-1);
       
   446 	}
       
   447 	binding->address[binding->numbound++] = *address;
       
   448 	return(channel);
       
   449 }
       
   450 
       
   451 /* Unbind all addresses from the given channel */
       
   452 void SDLNet_UDP_Unbind(UDPsocket sock, int channel)
       
   453 {
       
   454 	if ( (channel >= 0) && (channel < SDLNET_MAX_UDPCHANNELS) ) {
       
   455 		sock->binding[channel].numbound = 0;
       
   456 	}
       
   457 }
       
   458 
       
   459 /* Get the primary IP address of the remote system associated with the
       
   460    socket and channel.
       
   461    If the channel is not bound, this function returns NULL.
       
   462  */
       
   463 IPaddress *SDLNet_UDP_GetPeerAddress(UDPsocket sock, int channel)
       
   464 {
       
   465 	IPaddress *address;
       
   466 
       
   467 	address = NULL;
       
   468 	switch (channel) {
       
   469 		case -1:
       
   470 			/* Return the actual address of the socket */
       
   471 			address = &sock->address;
       
   472 			break;
       
   473 		default:
       
   474 			/* Return the address of the bound channel */
       
   475 			if ( ValidChannel(channel) &&
       
   476 				(sock->binding[channel].numbound > 0) ) {
       
   477 				address = &sock->binding[channel].address[0];
       
   478 			}
       
   479 			break;
       
   480 	}
       
   481 	return(address);
       
   482 }
       
   483 
       
   484 /* Send a vector of packets to the the channels specified within the packet.
       
   485    If the channel specified in the packet is -1, the packet will be sent to
       
   486    the address in the 'src' member of the packet.
       
   487    Each packet will be updated with the status of the packet after it has 
       
   488    been sent, -1 if the packet send failed.
       
   489    This function returns the number of packets sent.
       
   490 */
       
   491 int SDLNet_UDP_SendV(UDPsocket sock, UDPpacket **packets, int npackets)
       
   492 {
       
   493 	int numsent, i, j;
       
   494 	struct UDP_channel *binding;
       
   495 	int status;
       
   496 #ifndef MACOS_OPENTRANSPORT
       
   497 	int sock_len;
       
   498 	struct sockaddr_in sock_addr;
       
   499 
       
   500 	/* Set up the variables to send packets */
       
   501 	sock_len = sizeof(sock_addr);
       
   502 #endif
       
   503 
       
   504 	numsent = 0;
       
   505 	for ( i=0; i<npackets; ++i ) 
       
   506 	{
       
   507 		/* if channel is < 0, then use channel specified in sock */
       
   508 		
       
   509 		if ( packets[i]->channel < 0 ) 
       
   510 		{
       
   511 #ifdef MACOS_OPENTRANSPORT
       
   512 		TUnitData OTpacket;
       
   513 		InetAddress address;
       
   514 
       
   515 			memset(&OTpacket, 0, sizeof(OTpacket));
       
   516 			OTpacket.addr.buf = (Uint8 *)&address;
       
   517 			OTpacket.addr.len = (sizeof address);
       
   518 			OTpacket.udata.buf = packets[i]->data;
       
   519 			OTpacket.udata.len = packets[i]->len;
       
   520 			OTInitInetAddress(&address, packets[i]->address.port, packets[i]->address.host);
       
   521 #ifdef DEBUG_NET
       
   522 			printf("Packet send address: 0x%8.8x:%d, length = %d\n", packets[i]->address.host, packets[i]->address.port, packets[i]->len);
       
   523 #endif
       
   524 			
       
   525 			status = OTSndUData(sock->channel, &OTpacket);
       
   526 #ifdef DEBUG_NET
       
   527 			printf("SDLNet_UDP_SendV   OTSndUData return value is ;%d\n", status );
       
   528 #endif
       
   529 
       
   530 			AsyncUDPPopEvent( sock );
       
   531 			packets[i]->status = status;
       
   532 			
       
   533 			if (status == noErr)
       
   534 			{
       
   535 				++numsent;
       
   536 			}
       
   537 #else
       
   538 			sock_addr.sin_addr.s_addr = packets[i]->address.host;
       
   539 			sock_addr.sin_port = packets[i]->address.port;
       
   540 			sock_addr.sin_family = AF_INET;
       
   541 			status = sendto(sock->channel, 
       
   542 					packets[i]->data, packets[i]->len, 0,
       
   543 					(struct sockaddr *)&sock_addr,sock_len);
       
   544 			if ( status >= 0 )
       
   545 			{
       
   546 				packets[i]->status = status;
       
   547 				++numsent;
       
   548 			}
       
   549 #endif /* MACOS_OPENTRANSPORT */
       
   550 		}
       
   551 		else 
       
   552 		{
       
   553 			/* Send to each of the bound addresses on the channel */
       
   554 #ifdef DEBUG_NET
       
   555 			printf("SDLNet_UDP_SendV sending packet to channel = %d\n", packets[i]->channel );
       
   556 #endif
       
   557 			
       
   558 			binding = &sock->binding[packets[i]->channel];
       
   559 			
       
   560 			for ( j=binding->numbound-1; j>=0; --j ) 
       
   561 			{
       
   562 #ifdef MACOS_OPENTRANSPORT
       
   563 			TUnitData OTpacket;
       
   564 			InetAddress address;
       
   565 
       
   566 				OTInitInetAddress(&address, binding->address[j].port,binding->address[j].host);
       
   567 #ifdef DEBUG_NET
       
   568 				printf("Packet send address: 0x%8.8x:%d, length = %d\n", binding->address[j].host, binding->address[j].port, packets[i]->len);
       
   569 #endif
       
   570 				memset(&OTpacket, 0, sizeof(OTpacket));
       
   571 				OTpacket.addr.buf = (Uint8 *)&address;
       
   572 				OTpacket.addr.len = (sizeof address);
       
   573 				OTpacket.udata.buf = packets[i]->data;
       
   574 				OTpacket.udata.len = packets[i]->len;
       
   575 			                              
       
   576 				status = OTSndUData(sock->channel, &OTpacket);
       
   577 #ifdef DEBUG_NET
       
   578 				printf("SDLNet_UDP_SendV   OTSndUData returne value is;%d\n", status );
       
   579 #endif
       
   580 				AsyncUDPPopEvent(sock);
       
   581 				packets[i]->status = status;
       
   582 				
       
   583 				if (status == noErr)
       
   584 				{
       
   585 					++numsent;
       
   586 				}
       
   587 
       
   588 #else
       
   589 				sock_addr.sin_addr.s_addr = binding->address[j].host;
       
   590 				sock_addr.sin_port = binding->address[j].port;
       
   591 				sock_addr.sin_family = AF_INET;
       
   592 				status = sendto(sock->channel, 
       
   593 						packets[i]->data, packets[i]->len, 0,
       
   594 						(struct sockaddr *)&sock_addr,sock_len);
       
   595 				if ( status >= 0 )
       
   596 				{
       
   597 					packets[i]->status = status;
       
   598 					++numsent;
       
   599 				}
       
   600 #endif /* MACOS_OPENTRANSPORT */
       
   601 			}
       
   602 		}
       
   603 	}
       
   604 	
       
   605 	return(numsent);
       
   606 }
       
   607 
       
   608 int SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket *packet)
       
   609 {
       
   610 	/* This is silly, but... */
       
   611 	packet->channel = channel;
       
   612 	return(SDLNet_UDP_SendV(sock, &packet, 1));
       
   613 }
       
   614 
       
   615 /* Returns true if a socket is has data available for reading right now */
       
   616 static int SocketReady(SOCKET sock)
       
   617 {
       
   618 	int retval = 0;
       
   619 #ifdef MACOS_OPENTRANSPORT
       
   620 	OTResult status;
       
   621 #else
       
   622 	struct timeval tv;
       
   623 	fd_set mask;
       
   624 #endif
       
   625 
       
   626 #ifdef MACOS_OPENTRANSPORT
       
   627 	//status = OTGetEndpointState(sock);
       
   628 	status = OTLook(sock);
       
   629 	if( status > 0 )
       
   630 		retval = 1;
       
   631 		
       
   632 /*	switch( status )
       
   633 	{
       
   634 //		case T_IDLE:
       
   635 		case T_DATAXFER:
       
   636 //		case T_INREL:
       
   637 			retval = 1;
       
   638 			break;
       
   639 		default:
       
   640 			OTCountDataBytes( sock, &numBytes );
       
   641 			if( numBytes )
       
   642 				retval = 1;
       
   643 	}*/
       
   644 #else
       
   645 	/* Check the file descriptors for available data */
       
   646 	do {
       
   647 		errno = 0;
       
   648 
       
   649 		/* Set up the mask of file descriptors */
       
   650 		FD_ZERO(&mask);
       
   651 		FD_SET(sock, &mask);
       
   652 
       
   653 		/* Set up the timeout */
       
   654 		tv.tv_sec = 0;
       
   655 		tv.tv_usec = 0;
       
   656 
       
   657 		/* Look! */
       
   658 		retval = select(sock+1, &mask, NULL, NULL, &tv);
       
   659 	} while ( errno == EINTR );
       
   660 #endif /* MACOS_OPENTRANSPORT */
       
   661 
       
   662 	return(retval == 1);
       
   663 }
       
   664 
       
   665 /* Receive a vector of pending packets from the UDP socket.
       
   666    The returned packets contain the source address and the channel they arrived
       
   667    on.  If they did not arrive on a bound channel, the the channel will be set
       
   668    to -1.
       
   669    This function returns the number of packets read from the network, or -1
       
   670    on error.  This function does not block, so can return 0 packets pending.
       
   671 */
       
   672 extern int SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets)
       
   673 {
       
   674 	int numrecv, i, j;
       
   675 	struct UDP_channel *binding;
       
   676 #ifdef MACOS_OPENTRANSPORT
       
   677 	TUnitData OTpacket;
       
   678 	OTFlags flags;
       
   679 	InetAddress address;
       
   680 #else
       
   681 	int sock_len;
       
   682 	struct sockaddr_in sock_addr;
       
   683 #endif
       
   684 
       
   685 	numrecv = 0;
       
   686 	while ( packets[numrecv] && SocketReady(sock->channel) ) 
       
   687 	{
       
   688 	UDPpacket *packet;
       
   689 
       
   690 		packet = packets[numrecv];
       
   691 		
       
   692 #ifdef MACOS_OPENTRANSPORT
       
   693 		memset(&OTpacket, 0, sizeof(OTpacket));
       
   694 		OTpacket.addr.buf = (Uint8 *)&address;
       
   695 		OTpacket.addr.maxlen = (sizeof address);
       
   696 		OTpacket.udata.buf = packet->data;
       
   697 		OTpacket.udata.maxlen = packet->maxlen;
       
   698 		
       
   699 		packet->status = OTRcvUData(sock->channel, &OTpacket, &flags);
       
   700 #ifdef DEBUG_NET
       
   701 		printf("Packet status: %d\n", packet->status);
       
   702 #endif
       
   703 		AsyncUDPPopEvent(sock);
       
   704 		if (packet->status == noErr)
       
   705 		{
       
   706 			packet->len = OTpacket.udata.len;
       
   707 			packet->address.host = address.fHost;
       
   708 			packet->address.port = address.fPort;
       
   709 #ifdef DEBUG_NET
       
   710 			printf("Packet address: 0x%8.8x:%d, length = %d\n", packet->address.host, packet->address.port, packet->len);
       
   711 #endif
       
   712 		}
       
   713 #else
       
   714 		sock_len = sizeof(sock_addr);
       
   715 		packet->status = recvfrom(sock->channel,
       
   716 				packet->data, packet->maxlen, 0,
       
   717 				(struct sockaddr *)&sock_addr,
       
   718 #ifdef USE_GUSI_SOCKETS
       
   719 				(unsigned int *)&sock_len);
       
   720 #else
       
   721 						&sock_len);
       
   722 #endif
       
   723 		if ( packet->status >= 0 ) {
       
   724 			packet->len = packet->status;
       
   725 			packet->address.host = sock_addr.sin_addr.s_addr;
       
   726 			packet->address.port = sock_addr.sin_port;
       
   727 		}
       
   728 #endif
       
   729 		if (packet->status >= 0)
       
   730 		{
       
   731 			packet->channel = -1;
       
   732 			
       
   733 			for (i=(SDLNET_MAX_UDPCHANNELS-1); i>=0; --i ) 
       
   734 			{
       
   735 				binding = &sock->binding[i];
       
   736 				
       
   737 				for ( j=binding->numbound-1; j>=0; --j ) 
       
   738 				{
       
   739 					if ( (packet->address.host == binding->address[j].host) &&
       
   740 					     (packet->address.port == binding->address[j].port) ) 
       
   741 					{
       
   742 						packet->channel = i;
       
   743 						goto foundit; /* break twice */
       
   744 					}
       
   745 				}
       
   746 			}
       
   747 foundit:
       
   748 			++numrecv;
       
   749 		} 
       
   750 		
       
   751 		else 
       
   752 		{
       
   753 			packet->len = 0;
       
   754 		}
       
   755 	}
       
   756 	
       
   757 	sock->ready = 0;
       
   758 	
       
   759 	return(numrecv);
       
   760 }
       
   761 
       
   762 /* Receive a single packet from the UDP socket.
       
   763    The returned packet contains the source address and the channel it arrived
       
   764    on.  If it did not arrive on a bound channel, the the channel will be set
       
   765    to -1.
       
   766    This function returns the number of packets read from the network, or -1
       
   767    on error.  This function does not block, so can return 0 packets pending.
       
   768 */
       
   769 int SDLNet_UDP_Recv(UDPsocket sock, UDPpacket *packet)
       
   770 {
       
   771 	UDPpacket *packets[2];
       
   772 
       
   773 	/* Receive a packet array of 1 */
       
   774 	packets[0] = packet;
       
   775 	packets[1] = NULL;
       
   776 	return(SDLNet_UDP_RecvV(sock, packets));
       
   777 }
       
   778 
       
   779 /* Close a UDP network socket */
       
   780 extern void SDLNet_UDP_Close(UDPsocket sock)
       
   781 {
       
   782 	if ( sock != NULL ) 
       
   783 	{
       
   784 		if ( sock->channel != INVALID_SOCKET ) 
       
   785 		{
       
   786 #ifdef MACOS_OPENTRANSPORT
       
   787 			OTUnbind(sock->channel);
       
   788 			OTCloseProvider(sock->channel);
       
   789 #else
       
   790 			closesocket(sock->channel);
       
   791 #endif /* MACOS_OPENTRANSPORT */
       
   792 		}
       
   793 		
       
   794 		free(sock);
       
   795 	}
       
   796 }
       
   797