mirror of
https://github.com/DrBeef/DVR.git
synced 2024-12-19 17:12:43 +00:00
226 lines
5.4 KiB
C
226 lines
5.4 KiB
C
/*
|
|
SDL_net: An example cross-platform network library for use with SDL
|
|
Copyright (C) 1997-2004 Sam Lantinga
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
Sam Lantinga
|
|
slouken@libsdl.org
|
|
*/
|
|
|
|
/* $Id: SDLnetselect.c 1192 2004-01-04 17:41:55Z slouken $ */
|
|
|
|
#include "SDLnetsys.h"
|
|
#include "SDL_net.h"
|
|
|
|
/* The select() API for network sockets */
|
|
|
|
struct SDLNet_Socket {
|
|
int ready;
|
|
SOCKET channel;
|
|
#ifdef MACOS_OPENTRANSPORT
|
|
OTEventCode curEvent;
|
|
#endif
|
|
};
|
|
|
|
struct _SDLNet_SocketSet {
|
|
int numsockets;
|
|
int maxsockets;
|
|
struct SDLNet_Socket **sockets;
|
|
};
|
|
|
|
/* Allocate a socket set for use with SDLNet_CheckSockets()
|
|
This returns a socket set for up to 'maxsockets' sockets, or NULL if
|
|
the function ran out of memory.
|
|
*/
|
|
SDLNet_SocketSet SDLNet_AllocSocketSet(int maxsockets)
|
|
{
|
|
struct _SDLNet_SocketSet *set;
|
|
int i;
|
|
|
|
set = (struct _SDLNet_SocketSet *)malloc(sizeof(*set));
|
|
if ( set != NULL ) {
|
|
set->numsockets = 0;
|
|
set->maxsockets = maxsockets;
|
|
set->sockets = (struct SDLNet_Socket **)malloc
|
|
(maxsockets*sizeof(*set->sockets));
|
|
if ( set->sockets != NULL ) {
|
|
for ( i=0; i<maxsockets; ++i ) {
|
|
set->sockets[i] = NULL;
|
|
}
|
|
} else {
|
|
free(set);
|
|
set = NULL;
|
|
}
|
|
}
|
|
return(set);
|
|
}
|
|
|
|
/* Add a socket to a set of sockets to be checked for available data */
|
|
int SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
|
|
{
|
|
if ( sock != NULL ) {
|
|
if ( set->numsockets == set->maxsockets ) {
|
|
SDLNet_SetError("socketset is full");
|
|
return(-1);
|
|
}
|
|
set->sockets[set->numsockets++] = (struct SDLNet_Socket *)sock;
|
|
}
|
|
return(set->numsockets);
|
|
}
|
|
|
|
/* Remove a socket from a set of sockets to be checked for available data */
|
|
int SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
|
|
{
|
|
int i;
|
|
|
|
if ( sock != NULL ) {
|
|
for ( i=0; i<set->numsockets; ++i ) {
|
|
if ( set->sockets[i] == (struct SDLNet_Socket *)sock ) {
|
|
break;
|
|
}
|
|
}
|
|
if ( i == set->numsockets ) {
|
|
SDLNet_SetError("socket not found in socketset");
|
|
return(-1);
|
|
}
|
|
--set->numsockets;
|
|
for ( ; i<set->numsockets; ++i ) {
|
|
set->sockets[i] = set->sockets[i+1];
|
|
}
|
|
}
|
|
return(set->numsockets);
|
|
}
|
|
|
|
/* This function checks to see if data is available for reading on the
|
|
given set of sockets. If 'timeout' is 0, it performs a quick poll,
|
|
otherwise the function returns when either data is available for
|
|
reading, or the timeout in milliseconds has elapsed, which ever occurs
|
|
first. This function returns the number of sockets ready for reading,
|
|
or -1 if there was an error with the select() system call.
|
|
*/
|
|
#ifdef MACOS_OPENTRANSPORT
|
|
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);
|
|
}
|
|
#else
|
|
int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout)
|
|
{
|
|
int i;
|
|
SOCKET maxfd;
|
|
int retval;
|
|
struct timeval tv;
|
|
fd_set mask;
|
|
|
|
/* Find the largest file descriptor */
|
|
maxfd = 0;
|
|
for ( i=set->numsockets-1; i>=0; --i ) {
|
|
if ( set->sockets[i]->channel > maxfd ) {
|
|
maxfd = set->sockets[i]->channel;
|
|
}
|
|
}
|
|
|
|
/* Check the file descriptors for available data */
|
|
do {
|
|
errno = 0;
|
|
|
|
/* Set up the mask of file descriptors */
|
|
FD_ZERO(&mask);
|
|
for ( i=set->numsockets-1; i>=0; --i ) {
|
|
FD_SET(set->sockets[i]->channel, &mask);
|
|
}
|
|
|
|
/* Set up the timeout */
|
|
tv.tv_sec = timeout/1000;
|
|
tv.tv_usec = (timeout%1000)*1000;
|
|
|
|
/* Look! */
|
|
retval = select(maxfd+1, &mask, NULL, NULL, &tv);
|
|
} while ( errno == EINTR );
|
|
|
|
/* Mark all file descriptors ready that have data available */
|
|
if ( retval > 0 ) {
|
|
for ( i=set->numsockets-1; i>=0; --i ) {
|
|
if ( FD_ISSET(set->sockets[i]->channel, &mask) ) {
|
|
set->sockets[i]->ready = 1;
|
|
}
|
|
}
|
|
}
|
|
return(retval);
|
|
}
|
|
#endif /* MACOS_OPENTRANSPORT */
|
|
|
|
/* Free a set of sockets allocated by SDL_NetAllocSocketSet() */
|
|
extern void SDLNet_FreeSocketSet(SDLNet_SocketSet set)
|
|
{
|
|
if ( set ) {
|
|
free(set->sockets);
|
|
free(set);
|
|
}
|
|
}
|
|
|