mirror of
https://github.com/DrBeef/DVR.git
synced 2024-12-21 10:01:47 +00:00
227 lines
5.4 KiB
Text
227 lines
5.4 KiB
Text
|
/*
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
|