zenilib: zenilib/jni/external/sdl_net/SDLnetTCP.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDLnetTCP.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 network API for TCP sockets */
28
29 /* Since the UNIX/Win32/BeOS code is so different from MacOS,
30 we'll just have two completely different sections here.
31 */
32
33 struct _TCPsocket {
34 int ready;
35 SOCKET channel;
36 IPaddress remoteAddress;
37 IPaddress localAddress;
38 int sflag;
39 };
40
41 /* Open a TCP network socket
42 If 'remote' is NULL, this creates a local server socket on the given port,
43 otherwise a TCP connection to the remote host and port is attempted.
44 The newly created socket is returned, or NULL if there was an error.
45 */
46 TCPsocket SDLNet_TCP_Open(IPaddress *ip)
47 {
48 TCPsocket sock;
49 struct sockaddr_in sock_addr;
50
51 /* Allocate a TCP socket structure */
52 sock = (TCPsocket)malloc(sizeof(*sock));
53 if ( sock == NULL ) {
54 SDLNet_SetError("Out of memory");
55 goto error_return;
56 }
57
58 /* Open the socket */
59 sock->channel = socket(AF_INET, SOCK_STREAM, 0);
60 if ( sock->channel == INVALID_SOCKET ) {
61 SDLNet_SetError("Couldn't create socket");
62 goto error_return;
63 }
64
65 /* Connect to remote, or bind locally, as appropriate */
66 if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) ) {
67
68 // ######### Connecting to remote
69
70 memset(&sock_addr, 0, sizeof(sock_addr));
71 sock_addr.sin_family = AF_INET;
72 sock_addr.sin_addr.s_addr = ip->host;
73 sock_addr.sin_port = ip->port;
74
75 /* Connect to the remote host */
76 if ( connect(sock->channel, (struct sockaddr *)&sock_addr,
77 sizeof(sock_addr)) == SOCKET_ERROR ) {
78 SDLNet_SetError("Couldn't connect to remote host");
79 goto error_return;
80 }
81 sock->sflag = 0;
82 } else {
83
84 // ########## Binding locally
85
86 memset(&sock_addr, 0, sizeof(sock_addr));
87 sock_addr.sin_family = AF_INET;
88 sock_addr.sin_addr.s_addr = INADDR_ANY;
89 sock_addr.sin_port = ip->port;
90
91 /*
92 * Windows gets bad mojo with SO_REUSEADDR:
93 * http://www.devolution.com/pipermail/sdl/2005-September/070491.html
94 * --ryan.
95 */
96 #ifndef WIN32
97 /* allow local address reuse */
98 { int yes = 1;
99 setsockopt(sock->channel, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes));
100 }
101 #endif
102
103 /* Bind the socket for listening */
104 if ( bind(sock->channel, (struct sockaddr *)&sock_addr,
105 sizeof(sock_addr)) == SOCKET_ERROR ) {
106 SDLNet_SetError("Couldn't bind to local port");
107 goto error_return;
108 }
109 if ( listen(sock->channel, 5) == SOCKET_ERROR ) {
110 SDLNet_SetError("Couldn't listen to local port");
111 goto error_return;
112 }
113
114 /* Set the socket to non-blocking mode for accept() */
115 #if defined(__BEOS__) && defined(SO_NONBLOCK)
116 /* On BeOS r5 there is O_NONBLOCK but it's for files only */
117 {
118 long b = 1;
119 setsockopt(sock->channel, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
120 }
121 #elif defined(O_NONBLOCK)
122 {
123 fcntl(sock->channel, F_SETFL, O_NONBLOCK);
124 }
125 #elif defined(WIN32)
126 {
127 unsigned long mode = 1;
128 ioctlsocket (sock->channel, FIONBIO, &mode);
129 }
130 #elif defined(__OS2__)
131 {
132 int dontblock = 1;
133 ioctl(sock->channel, FIONBIO, &dontblock);
134 }
135 #else
136 #warning How do we set non-blocking mode on other operating systems?
137 #endif
138 sock->sflag = 1;
139 }
140 sock->ready = 0;
141
142 #ifdef TCP_NODELAY
143 /* Set the nodelay TCP option for real-time games */
144 { int yes = 1;
145 setsockopt(sock->channel, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes));
146 }
147 #else
148 #warning Building without TCP_NODELAY
149 #endif /* TCP_NODELAY */
150
151 /* Fill in the channel host address */
152 sock->remoteAddress.host = sock_addr.sin_addr.s_addr;
153 sock->remoteAddress.port = sock_addr.sin_port;
154
155 /* The socket is ready */
156 return(sock);
157
158 error_return:
159 SDLNet_TCP_Close(sock);
160 return(NULL);
161 }
162
163 /* Accept an incoming connection on the given server socket.
164 The newly created socket is returned, or NULL if there was an error.
165 */
166 TCPsocket SDLNet_TCP_Accept(TCPsocket server)
167 {
168 TCPsocket sock;
169 struct sockaddr_in sock_addr;
170 socklen_t sock_alen;
171
172 /* Only server sockets can accept */
173 if ( ! server->sflag ) {
174 SDLNet_SetError("Only server sockets can accept()");
175 return(NULL);
176 }
177 server->ready = 0;
178
179 /* Allocate a TCP socket structure */
180 sock = (TCPsocket)malloc(sizeof(*sock));
181 if ( sock == NULL ) {
182 SDLNet_SetError("Out of memory");
183 goto error_return;
184 }
185
186 /* Accept a new TCP connection on a server socket */
187 sock_alen = sizeof(sock_addr);
188 sock->channel = accept(server->channel, (struct sockaddr *)&sock_addr,
189 &sock_alen);
190 if ( sock->channel == INVALID_SOCKET ) {
191 SDLNet_SetError("accept() failed");
192 goto error_return;
193 }
194 #ifdef WIN32
195 {
196 /* passing a zero value, socket mode set to block on */
197 unsigned long mode = 0;
198 ioctlsocket (sock->channel, FIONBIO, &mode);
199 }
200 #elif defined(O_NONBLOCK)
201 {
202 int flags = fcntl(sock->channel, F_GETFL, 0);
203 fcntl(sock->channel, F_SETFL, flags & ~O_NONBLOCK);
204 }
205 #endif /* WIN32 */
206 sock->remoteAddress.host = sock_addr.sin_addr.s_addr;
207 sock->remoteAddress.port = sock_addr.sin_port;
208
209 sock->sflag = 0;
210 sock->ready = 0;
211
212 /* The socket is ready */
213 return(sock);
214
215 error_return:
216 SDLNet_TCP_Close(sock);
217 return(NULL);
218 }
219
220 /* Get the IP address of the remote system associated with the socket.
221 If the socket is a server socket, this function returns NULL.
222 */
223 IPaddress *SDLNet_TCP_GetPeerAddress(TCPsocket sock)
224 {
225 if ( sock->sflag ) {
226 return(NULL);
227 }
228 return(&sock->remoteAddress);
229 }
230
231 /* Send 'len' bytes of 'data' over the non-server socket 'sock'
232 This function returns the actual amount of data sent. If the return value
233 is less than the amount of data sent, then either the remote connection was
234 closed, or an unknown socket error occurred.
235 */
236 int SDLNet_TCP_Send(TCPsocket sock, const void *datap, int len)
237 {
238 const Uint8 *data = (const Uint8 *)datap; /* For pointer arithmetic */
239 int sent, left;
240
241 /* Server sockets are for accepting connections only */
242 if ( sock->sflag ) {
243 SDLNet_SetError("Server sockets cannot send");
244 return(-1);
245 }
246
247 /* Keep sending data until it's sent or an error occurs */
248 left = len;
249 sent = 0;
250 SDLNet_SetLastError(0);
251 do {
252 len = send(sock->channel, (const char *) data, left, 0);
253 if ( len > 0 ) {
254 sent += len;
255 left -= len;
256 data += len;
257 }
258 } while ( (left > 0) && ((len > 0) || (SDLNet_GetLastError() == EINTR)) );
259
260 return(sent);
261 }
262
263 /* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
264 and store them in the buffer pointed to by 'data'.
265 This function returns the actual amount of data received. If the return
266 value is less than or equal to zero, then either the remote connection was
267 closed, or an unknown socket error occurred.
268 */
269 int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen)
270 {
271 int len;
272
273 /* Server sockets are for accepting connections only */
274 if ( sock->sflag ) {
275 SDLNet_SetError("Server sockets cannot receive");
276 return(-1);
277 }
278
279 SDLNet_SetLastError(0);
280 do {
281 len = recv(sock->channel, (char *) data, maxlen, 0);
282 } while ( SDLNet_GetLastError() == EINTR );
283
284 sock->ready = 0;
285 return(len);
286 }
287
288 /* Close a TCP network socket */
289 void SDLNet_TCP_Close(TCPsocket sock)
290 {
291 if ( sock != NULL ) {
292 if ( sock->channel != INVALID_SOCKET ) {
293 closesocket(sock->channel);
294 }
295 free(sock);
296 }
297 }
SDLNet_TCP_Send
DECLSPEC int SDLCALL SDLNet_TCP_Send(TCPsocket sock, const void *data, int len)
Definition: SDLnetTCP.c:236
SDLNet_SetError
DECLSPEC void SDLCALL SDLNet_SetError(const char *fmt,...)
Definition: SDLnet.c:65
SOCKET
#define SOCKET
Definition: SDLnetsys.h:78
IPaddress::host
Uint32 host
Definition: SDL_net.h:91
closesocket
#define closesocket
Definition: SDLnetsys.h:76
left
GLint left
Definition: glew.h:7291
NULL
#define NULL
Definition: ftobjs.h:61
IPaddress
Definition: SDL_net.h:90
SDLnetsys.h
free
SDL_EventEntry * free
Definition: SDL_events.c:80
memset
#define memset
Definition: SDL_malloc.c:633
SDLNet_GetLastError
int SDLNet_GetLastError(void)
Definition: SDLnet.c:51
len
GLenum GLsizei len
Definition: glew.h:7035
SDLNet_TCP_Accept
DECLSPEC TCPsocket SDLCALL SDLNet_TCP_Accept(TCPsocket server)
Definition: SDLnetTCP.c:166
INADDR_NONE
#define INADDR_NONE
Definition: SDL_net.h:105
SDLNet_TCP_GetPeerAddress
DECLSPEC IPaddress *SDLCALL SDLNet_TCP_GetPeerAddress(TCPsocket sock)
Definition: SDLnetTCP.c:223
INVALID_SOCKET
#define INVALID_SOCKET
Definition: SDLnetsys.h:79
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
SDLNet_TCP_Open
DECLSPEC TCPsocket SDLCALL SDLNet_TCP_Open(IPaddress *ip)
Definition: SDLnetTCP.c:46
IPaddress::port
Uint16 port
Definition: SDL_net.h:92
malloc
#define malloc
Definition: SDL_malloc.c:635
flags
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
TCPsocket
struct _TCPsocket * TCPsocket
Definition: SDL_net.h:131
sock
TCPsocket sock
Definition: chatd.c:41
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
INADDR_ANY
#define INADDR_ANY
Definition: SDL_net.h:102
b
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
SOCKET_ERROR
#define SOCKET_ERROR
Definition: SDLnetsys.h:80
SDLNet_TCP_Recv
DECLSPEC int SDLCALL SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen)
Definition: SDLnetTCP.c:269
SDLNet_SetLastError
void SDLNet_SetLastError(int err)
Definition: SDLnet.c:56
mode
GLenum mode
Definition: glew.h:2394
SDLNet_TCP_Close
DECLSPEC void SDLCALL SDLNet_TCP_Close(TCPsocket sock)
Definition: SDLnetTCP.c:289