zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDLnetselect.c
Go to the documentation of this file.
1 /*
2  SDL_net: An example cross-platform network library for use with SDL
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 /* $Id$ */
23 
24 #include "SDLnetsys.h"
25 #include "SDL_net.h"
26 
27 /* The select() API for network sockets */
28 
29 struct SDLNet_Socket {
30  int ready;
31  SOCKET channel;
32 };
33 
34 struct _SDLNet_SocketSet {
35  int numsockets;
36  int maxsockets;
37  struct SDLNet_Socket **sockets;
38 };
39 
40 /* Allocate a socket set for use with SDLNet_CheckSockets()
41  This returns a socket set for up to 'maxsockets' sockets, or NULL if
42  the function ran out of memory.
43  */
45 {
46  struct _SDLNet_SocketSet *set;
47  int i;
48 
49  set = (struct _SDLNet_SocketSet *)malloc(sizeof(*set));
50  if ( set != NULL ) {
51  set->numsockets = 0;
52  set->maxsockets = maxsockets;
53  set->sockets = (struct SDLNet_Socket **)malloc
54  (maxsockets*sizeof(*set->sockets));
55  if ( set->sockets != NULL ) {
56  for ( i=0; i<maxsockets; ++i ) {
57  set->sockets[i] = NULL;
58  }
59  } else {
60  free(set);
61  set = NULL;
62  }
63  }
64  return(set);
65 }
66 
67 /* Add a socket to a set of sockets to be checked for available data */
69 {
70  if ( sock != NULL ) {
71  if ( set->numsockets == set->maxsockets ) {
72  SDLNet_SetError("socketset is full");
73  return(-1);
74  }
75  set->sockets[set->numsockets++] = (struct SDLNet_Socket *)sock;
76  }
77  return(set->numsockets);
78 }
79 
80 /* Remove a socket from a set of sockets to be checked for available data */
82 {
83  int i;
84 
85  if ( sock != NULL ) {
86  for ( i=0; i<set->numsockets; ++i ) {
87  if ( set->sockets[i] == (struct SDLNet_Socket *)sock ) {
88  break;
89  }
90  }
91  if ( i == set->numsockets ) {
92  SDLNet_SetError("socket not found in socketset");
93  return(-1);
94  }
95  --set->numsockets;
96  for ( ; i<set->numsockets; ++i ) {
97  set->sockets[i] = set->sockets[i+1];
98  }
99  }
100  return(set->numsockets);
101 }
102 
103 /* This function checks to see if data is available for reading on the
104  given set of sockets. If 'timeout' is 0, it performs a quick poll,
105  otherwise the function returns when either data is available for
106  reading, or the timeout in milliseconds has elapsed, which ever occurs
107  first. This function returns the number of sockets ready for reading,
108  or -1 if there was an error with the select() system call.
109 */
111 {
112  int i;
113  SOCKET maxfd;
114  int retval;
115  struct timeval tv;
116  fd_set mask;
117 
118  /* Find the largest file descriptor */
119  maxfd = 0;
120  for ( i=set->numsockets-1; i>=0; --i ) {
121  if ( set->sockets[i]->channel > maxfd ) {
122  maxfd = set->sockets[i]->channel;
123  }
124  }
125 
126  /* Check the file descriptors for available data */
127  do {
129 
130  /* Set up the mask of file descriptors */
131  FD_ZERO(&mask);
132  for ( i=set->numsockets-1; i>=0; --i ) {
133  FD_SET(set->sockets[i]->channel, &mask);
134  }
135 
136  /* Set up the timeout */
137  tv.tv_sec = timeout/1000;
138  tv.tv_usec = (timeout%1000)*1000;
139 
140  /* Look! */
141  retval = select(maxfd+1, &mask, NULL, NULL, &tv);
142  } while ( SDLNet_GetLastError() == EINTR );
143 
144  /* Mark all file descriptors ready that have data available */
145  if ( retval > 0 ) {
146  for ( i=set->numsockets-1; i>=0; --i ) {
147  if ( FD_ISSET(set->sockets[i]->channel, &mask) ) {
148  set->sockets[i]->ready = 1;
149  }
150  }
151  }
152  return(retval);
153 }
154 
155 /* Free a set of sockets allocated by SDL_NetAllocSocketSet() */
157 {
158  if ( set ) {
159  free(set->sockets);
160  free(set);
161  }
162 }
163 
DECLSPEC void SDLCALL SDLNet_SetError(const char *fmt,...)
Definition: SDLnet.c:65
#define SOCKET
Definition: SDLnetsys.h:78
DECLSPEC int SDLCALL SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout)
Definition: SDLnetselect.c:110
DECLSPEC int SDLCALL SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
Definition: SDLnetselect.c:81
#define NULL
Definition: ftobjs.h:61
DECLSPEC void SDLCALL SDLNet_FreeSocketSet(SDLNet_SocketSet set)
Definition: SDLnetselect.c:156
SDL_EventEntry * free
Definition: SDL_events.c:80
int SDLNet_GetLastError(void)
Definition: SDLnet.c:51
DECLSPEC int SDLCALL SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock)
Definition: SDLnetselect.c:68
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:145
struct _SDLNet_SocketSet * SDLNet_SocketSet
Definition: SDL_net.h:298
GLbitfield GLuint64 timeout
Definition: glew.h:5938
#define malloc
Definition: SDL_malloc.c:635
TCPsocket sock
Definition: chatd.c:41
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
Definition: gl2ext.h:961
DECLSPEC SDLNet_SocketSet SDLCALL SDLNet_AllocSocketSet(int maxsockets)
Definition: SDLnetselect.c:44
void SDLNet_SetLastError(int err)
Definition: SDLnet.c:56
int i
Definition: pngrutil.c:1377