project_files/Android-build/SDL-android-project/jni/sdl_net/SDLnetselect.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: SDLnetselect.c 1192 2004-01-04 17:41:55Z slouken $ */
       
    24 
       
    25 #include "SDLnetsys.h"
       
    26 #include "SDL_net.h"
       
    27 
       
    28 /* The select() API for network sockets */
       
    29 
       
    30 struct SDLNet_Socket {
       
    31 	int ready;
       
    32 	SOCKET channel;
       
    33 #ifdef MACOS_OPENTRANSPORT
       
    34 	OTEventCode curEvent;
       
    35 #endif
       
    36 };
       
    37 
       
    38 struct _SDLNet_SocketSet {
       
    39 	int numsockets;
       
    40 	int maxsockets;
       
    41 	struct SDLNet_Socket **sockets;
       
    42 };
       
    43 
       
    44 /* Allocate a socket set for use with SDLNet_CheckSockets() 
       
    45    This returns a socket set for up to 'maxsockets' sockets, or NULL if 
       
    46    the function ran out of memory. 
       
    47  */
       
    48 SDLNet_SocketSet SDLNet_AllocSocketSet(int maxsockets)
       
    49 {
       
    50 	struct _SDLNet_SocketSet *set;
       
    51 	int i;
       
    52 
       
    53 	set = (struct _SDLNet_SocketSet *)malloc(sizeof(*set));
       
    54 	if ( set != NULL ) {
       
    55 		set->numsockets = 0;
       
    56 		set->maxsockets = maxsockets;
       
    57 		set->sockets = (struct SDLNet_Socket **)malloc
       
    58 					(maxsockets*sizeof(*set->sockets));
       
    59 		if ( set->sockets != NULL ) {
       
    60 			for ( i=0; i<maxsockets; ++i ) {
       
    61 				set->sockets[i] = NULL;
       
    62 			}
       
    63 		} else {
       
    64 			free(set);
       
    65 			set = NULL;
       
    66 		}
       
    67 	}
       
    68 	return(set);
       
    69 }
       
    70 
       
    71 /* Add a socket to a set of sockets to be checked for available data */
       
    72 int SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
       
    73 {
       
    74 	if ( sock != NULL ) {
       
    75 		if ( set->numsockets == set->maxsockets ) {
       
    76 			SDLNet_SetError("socketset is full");
       
    77 			return(-1);
       
    78 		}
       
    79 		set->sockets[set->numsockets++] = (struct SDLNet_Socket *)sock;
       
    80 	}
       
    81 	return(set->numsockets);
       
    82 }
       
    83 
       
    84 /* Remove a socket from a set of sockets to be checked for available data */
       
    85 int SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
       
    86 {
       
    87 	int i;
       
    88 
       
    89 	if ( sock != NULL ) {
       
    90 		for ( i=0; i<set->numsockets; ++i ) {
       
    91 			if ( set->sockets[i] == (struct SDLNet_Socket *)sock ) {
       
    92 				break;
       
    93 			}
       
    94 		}
       
    95 		if ( i == set->numsockets ) {
       
    96 			SDLNet_SetError("socket not found in socketset");
       
    97 			return(-1);
       
    98 		}
       
    99 		--set->numsockets;
       
   100 		for ( ; i<set->numsockets; ++i ) {
       
   101 			set->sockets[i] = set->sockets[i+1];
       
   102 		}
       
   103 	}
       
   104 	return(set->numsockets);
       
   105 }
       
   106 
       
   107 /* This function checks to see if data is available for reading on the
       
   108    given set of sockets.  If 'timeout' is 0, it performs a quick poll,
       
   109    otherwise the function returns when either data is available for
       
   110    reading, or the timeout in milliseconds has elapsed, which ever occurs
       
   111    first.  This function returns the number of sockets ready for reading,
       
   112    or -1 if there was an error with the select() system call.
       
   113 */
       
   114 #ifdef MACOS_OPENTRANSPORT
       
   115 int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout)
       
   116 {
       
   117 Uint32	stop;
       
   118 int 	numReady;
       
   119 
       
   120 	/* Loop, polling the network devices */
       
   121 	
       
   122 	stop = SDL_GetTicks() + timeout;
       
   123 	
       
   124 	do 
       
   125 	{
       
   126 	OTResult status;
       
   127 	size_t	numBytes;
       
   128 	int 	i;
       
   129 		
       
   130 		numReady = 0;
       
   131 	
       
   132 		for (i = set->numsockets-1;i >= 0;--i) 
       
   133 		{
       
   134 			status = OTLook( set->sockets[i]->channel );
       
   135 			if( status > 0 )
       
   136 			{
       
   137 				switch( status )
       
   138 				{
       
   139 					case T_UDERR:
       
   140 						OTRcvUDErr( set->sockets[i]->channel , nil);
       
   141 						break;
       
   142 					case T_DISCONNECT:
       
   143 						OTRcvDisconnect( set->sockets[i]->channel, nil );
       
   144 						break;
       
   145 					case T_ORDREL:
       
   146 						OTRcvOrderlyDisconnect(set->sockets[i]->channel );
       
   147 						break;
       
   148 					case T_CONNECT:
       
   149 						OTRcvConnect( set->sockets[i]->channel, nil );
       
   150 						break;
       
   151 					
       
   152 				
       
   153 					default:
       
   154 						set->sockets[i]->ready = 1;
       
   155 						++numReady;
       
   156 				}
       
   157 			}
       
   158 			else if( OTCountDataBytes(set->sockets[i]->channel, &numBytes ) != kOTNoDataErr )
       
   159 			{
       
   160 				set->sockets[i]->ready = 1;
       
   161 				++numReady;
       
   162 			}
       
   163 			else
       
   164 				set->sockets[i]->ready = 0;
       
   165 		}
       
   166 		
       
   167 	} while (!numReady && (SDL_GetTicks() < stop));
       
   168 
       
   169 	return(numReady);
       
   170 }
       
   171 #else
       
   172 int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout)
       
   173 {
       
   174 	int i;
       
   175 	SOCKET maxfd;
       
   176 	int retval;
       
   177 	struct timeval tv;
       
   178 	fd_set mask;
       
   179 
       
   180 	/* Find the largest file descriptor */
       
   181 	maxfd = 0;
       
   182 	for ( i=set->numsockets-1; i>=0; --i ) {
       
   183 		if ( set->sockets[i]->channel > maxfd ) {
       
   184 			maxfd = set->sockets[i]->channel;
       
   185 		}
       
   186 	}
       
   187 
       
   188 	/* Check the file descriptors for available data */
       
   189 	do {
       
   190 		errno = 0;
       
   191 
       
   192 		/* Set up the mask of file descriptors */
       
   193 		FD_ZERO(&mask);
       
   194 		for ( i=set->numsockets-1; i>=0; --i ) {
       
   195 			FD_SET(set->sockets[i]->channel, &mask);
       
   196 		}
       
   197 
       
   198 		/* Set up the timeout */
       
   199 		tv.tv_sec = timeout/1000;
       
   200 		tv.tv_usec = (timeout%1000)*1000;
       
   201 
       
   202 		/* Look! */
       
   203 		retval = select(maxfd+1, &mask, NULL, NULL, &tv);
       
   204 	} while ( errno == EINTR );
       
   205 
       
   206 	/* Mark all file descriptors ready that have data available */
       
   207 	if ( retval > 0 ) {
       
   208 		for ( i=set->numsockets-1; i>=0; --i ) {
       
   209 			if ( FD_ISSET(set->sockets[i]->channel, &mask) ) {
       
   210 				set->sockets[i]->ready = 1;
       
   211 			}
       
   212 		}
       
   213 	}
       
   214 	return(retval);
       
   215 }
       
   216 #endif /* MACOS_OPENTRANSPORT */
       
   217    
       
   218 /* Free a set of sockets allocated by SDL_NetAllocSocketSet() */
       
   219 extern void SDLNet_FreeSocketSet(SDLNet_SocketSet set)
       
   220 {
       
   221 	if ( set ) {
       
   222 		free(set->sockets);
       
   223 		free(set);
       
   224 	}
       
   225 }
       
   226