1 /*
2   SDL_net:  An example cross-platform network library for use with SDL
3   Copyright (C) 1997-2012 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 #ifndef _SDL_NET_H
25 #define _SDL_NET_H
26 
27 #include "SDL.h"
28 #include "SDL_endian.h"
29 #include "SDL_version.h"
30 #include "begin_code.h"
31 
32 
33 
34 /* Set up for C function definitions, even when using C++ */
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
40 */
41 #define SDL_NET_MAJOR_VERSION	1
42 #define SDL_NET_MINOR_VERSION	2
43 #define SDL_NET_PATCHLEVEL	8
44 
45 /* This macro can be used to fill a version structure with the compile-time
46  * version of the SDL_net library.
47  */
48 #define SDL_NET_VERSION(X)						\
49 {									\
50 	(X)->major = SDL_NET_MAJOR_VERSION;				\
51 	(X)->minor = SDL_NET_MINOR_VERSION;				\
52 	(X)->patch = SDL_NET_PATCHLEVEL;				\
53 }
54 
55 /* This function gets the version of the dynamically linked SDL_net library.
56    it should NOT be used to fill a version structure, instead you should
57    use the SDL_NET_VERSION() macro.
58  */
59 extern DECLSPEC const SDL_version * SDLCALL SDLNet_Linked_Version(void);
60 
61 /* Initialize/Cleanup the network API
62    SDL must be initialized before calls to functions in this library,
63    because this library uses utility functions from the SDL library.
64 */
65 extern DECLSPEC int  SDLCALL SDLNet_Init(void);
66 extern DECLSPEC void SDLCALL SDLNet_Quit(void);
67 
68 /***********************************************************************/
69 /* IPv4 hostname resolution API                                        */
70 /***********************************************************************/
71 
72 typedef struct {
73 	Uint32 host;			/* 32-bit IPv4 host address */
74 	Uint16 port;			/* 16-bit protocol port */
75 } IPaddress;
76 
77 /* Resolve a host name and port to an IP address in network form.
78    If the function succeeds, it will return 0.
79    If the host couldn't be resolved, the host portion of the returned
80    address will be INADDR_NONE, and the function will return -1.
81    If 'host' is NULL, the resolved host will be set to INADDR_ANY.
82  */
83 #ifndef INADDR_ANY
84 #define INADDR_ANY		0x00000000
85 #endif
86 #ifndef INADDR_NONE
87 #define INADDR_NONE		0xFFFFFFFF
88 #endif
89 #ifndef INADDR_LOOPBACK
90 #define INADDR_LOOPBACK		0x7f000001
91 #endif
92 #ifndef INADDR_BROADCAST
93 #define INADDR_BROADCAST	0xFFFFFFFF
94 #endif
95 extern DECLSPEC int SDLCALL SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port);
96 
97 /* Resolve an ip address to a host name in canonical form.
98    If the ip couldn't be resolved, this function returns NULL,
99    otherwise a pointer to a static buffer containing the hostname
100    is returned.  Note that this function is not thread-safe.
101 */
102 extern DECLSPEC const char * SDLCALL SDLNet_ResolveIP(const IPaddress *ip);
103 
104 /* Get the addresses of network interfaces on this system.
105    This returns the number of addresses saved in 'addresses'
106  */
107 extern DECLSPEC int SDLCALL SDLNet_GetLocalAddresses(IPaddress *addresses, int maxcount);
108 
109 /***********************************************************************/
110 /* TCP network API                                                     */
111 /***********************************************************************/
112 
113 typedef struct _TCPsocket *TCPsocket;
114 
115 /* Open a TCP network socket
116    If ip.host is INADDR_NONE or INADDR_ANY, this creates a local server
117    socket on the given port, otherwise a TCP connection to the remote
118    host and port is attempted. The address passed in should already be
119    swapped to network byte order (addresses returned from
120    SDLNet_ResolveHost() are already in the correct form).
121    The newly created socket is returned, or NULL if there was an error.
122 */
123 extern DECLSPEC TCPsocket SDLCALL SDLNet_TCP_Open(IPaddress *ip);
124 
125 /* Accept an incoming connection on the given server socket.
126    The newly created socket is returned, or NULL if there was an error.
127 */
128 extern DECLSPEC TCPsocket SDLCALL SDLNet_TCP_Accept(TCPsocket server);
129 
130 /* Get the IP address of the remote system associated with the socket.
131    If the socket is a server socket, this function returns NULL.
132 */
133 extern DECLSPEC IPaddress * SDLCALL SDLNet_TCP_GetPeerAddress(TCPsocket sock);
134 
135 /* Send 'len' bytes of 'data' over the non-server socket 'sock'
136    This function returns the actual amount of data sent.  If the return value
137    is less than the amount of data sent, then either the remote connection was
138    closed, or an unknown socket error occurred.
139 */
140 extern DECLSPEC int SDLCALL SDLNet_TCP_Send(TCPsocket sock, const void *data,
141 		int len);
142 
143 /* Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
144    and store them in the buffer pointed to by 'data'.
145    This function returns the actual amount of data received.  If the return
146    value is less than or equal to zero, then either the remote connection was
147    closed, or an unknown socket error occurred.
148 */
149 extern DECLSPEC int SDLCALL SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen);
150 
151 /* Close a TCP network socket */
152 extern DECLSPEC void SDLCALL SDLNet_TCP_Close(TCPsocket sock);
153 
154 
155 /***********************************************************************/
156 /* UDP network API                                                     */
157 /***********************************************************************/
158 
159 /* The maximum channels on a a UDP socket */
160 #define SDLNET_MAX_UDPCHANNELS	32
161 /* The maximum addresses bound to a single UDP socket channel */
162 #define SDLNET_MAX_UDPADDRESSES	4
163 
164 typedef struct _UDPsocket *UDPsocket;
165 typedef struct {
166 	int channel;		/* The src/dst channel of the packet */
167 	Uint8 *data;		/* The packet data */
168 	int len;		/* The length of the packet data */
169 	int maxlen;		/* The size of the data buffer */
170 	int status;		/* packet status after sending */
171 	IPaddress address;		/* The source/dest address of an incoming/outgoing packet */
172 } UDPpacket;
173 
174 /* Allocate/resize/free a single UDP packet 'size' bytes long.
175    The new packet is returned, or NULL if the function ran out of memory.
176  */
177 extern DECLSPEC UDPpacket * SDLCALL SDLNet_AllocPacket(int size);
178 extern DECLSPEC int SDLCALL SDLNet_ResizePacket(UDPpacket *packet, int newsize);
179 extern DECLSPEC void SDLCALL SDLNet_FreePacket(UDPpacket *packet);
180 
181 /* Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets,
182    each 'size' bytes long.
183    A pointer to the first packet in the array is returned, or NULL if the
184    function ran out of memory.
185  */
186 extern DECLSPEC UDPpacket ** SDLCALL SDLNet_AllocPacketV(int howmany, int size);
187 extern DECLSPEC void SDLCALL SDLNet_FreePacketV(UDPpacket **packetV);
188 
189 
190 /* Open a UDP network socket
191    If 'port' is non-zero, the UDP socket is bound to a local port.
192    The 'port' should be given in native byte order, but is used
193    internally in network (big endian) byte order, in addresses, etc.
194    This allows other systems to send to this socket via a known port.
195 */
196 extern DECLSPEC UDPsocket SDLCALL SDLNet_UDP_Open(Uint16 port);
197 
198 /* Set the percentage of simulated packet loss for packets sent on the socket.
199 */
200 extern DECLSPEC void SDLCALL SDLNet_UDP_SetPacketLoss(UDPsocket sock, int percent);
201 
202 /* Bind the address 'address' to the requested channel on the UDP socket.
203    If the channel is -1, then the first unbound channel will be bound with
204    the given address as it's primary address.
205    If the channel is already bound, this new address will be added to the
206    list of valid source addresses for packets arriving on the channel.
207    If the channel is not already bound, then the address becomes the primary
208    address, to which all outbound packets on the channel are sent.
209    This function returns the channel which was bound, or -1 on error.
210 */
211 extern DECLSPEC int SDLCALL SDLNet_UDP_Bind(UDPsocket sock, int channel, const IPaddress *address);
212 
213 /* Unbind all addresses from the given channel */
214 extern DECLSPEC void SDLCALL SDLNet_UDP_Unbind(UDPsocket sock, int channel);
215 
216 /* Get the primary IP address of the remote system associated with the
217    socket and channel.  If the channel is -1, then the primary IP port
218    of the UDP socket is returned -- this is only meaningful for sockets
219    opened with a specific port.
220    If the channel is not bound and not -1, this function returns NULL.
221  */
222 extern DECLSPEC IPaddress * SDLCALL SDLNet_UDP_GetPeerAddress(UDPsocket sock, int channel);
223 
224 /* Send a vector of packets to the the channels specified within the packet.
225    If the channel specified in the packet is -1, the packet will be sent to
226    the address in the 'src' member of the packet.
227    Each packet will be updated with the status of the packet after it has
228    been sent, -1 if the packet send failed.
229    This function returns the number of packets sent.
230 */
231 extern DECLSPEC int SDLCALL SDLNet_UDP_SendV(UDPsocket sock, UDPpacket **packets, int npackets);
232 
233 /* Send a single packet to the specified channel.
234    If the channel specified in the packet is -1, the packet will be sent to
235    the address in the 'src' member of the packet.
236    The packet will be updated with the status of the packet after it has
237    been sent.
238    This function returns 1 if the packet was sent, or 0 on error.
239 
240    NOTE:
241    The maximum size of the packet is limited by the MTU (Maximum Transfer Unit)
242    of the transport medium.  It can be as low as 250 bytes for some PPP links,
243    and as high as 1500 bytes for ethernet.
244 */
245 extern DECLSPEC int SDLCALL SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket *packet);
246 
247 /* Receive a vector of pending packets from the UDP socket.
248    The returned packets contain the source address and the channel they arrived
249    on.  If they did not arrive on a bound channel, the the channel will be set
250    to -1.
251    The channels are checked in highest to lowest order, so if an address is
252    bound to multiple channels, the highest channel with the source address
253    bound will be returned.
254    This function returns the number of packets read from the network, or -1
255    on error.  This function does not block, so can return 0 packets pending.
256 */
257 extern DECLSPEC int SDLCALL SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packets);
258 
259 /* Receive a single packet from the UDP socket.
260    The returned packet contains the source address and the channel it arrived
261    on.  If it did not arrive on a bound channel, the the channel will be set
262    to -1.
263    The channels are checked in highest to lowest order, so if an address is
264    bound to multiple channels, the highest channel with the source address
265    bound will be returned.
266    This function returns the number of packets read from the network, or -1
267    on error.  This function does not block, so can return 0 packets pending.
268 */
269 extern DECLSPEC int SDLCALL SDLNet_UDP_Recv(UDPsocket sock, UDPpacket *packet);
270 
271 /* Close a UDP network socket */
272 extern DECLSPEC void SDLCALL SDLNet_UDP_Close(UDPsocket sock);
273 
274 
275 /***********************************************************************/
276 /* Hooks for checking sockets for available data                       */
277 /***********************************************************************/
278 
279 typedef struct _SDLNet_SocketSet *SDLNet_SocketSet;
280 
281 /* Any network socket can be safely cast to this socket type */
282 typedef struct _SDLNet_GenericSocket {
283 	int ready;
284 } *SDLNet_GenericSocket;
285 
286 /* Allocate a socket set for use with SDLNet_CheckSockets()
287    This returns a socket set for up to 'maxsockets' sockets, or NULL if
288    the function ran out of memory.
289  */
290 extern DECLSPEC SDLNet_SocketSet SDLCALL SDLNet_AllocSocketSet(int maxsockets);
291 
292 /* Add a socket to a set of sockets to be checked for available data */
293 #define SDLNet_TCP_AddSocket(set, sock) \
294 			SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
295 #define SDLNet_UDP_AddSocket(set, sock) \
296 			SDLNet_AddSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
297 extern DECLSPEC int SDLCALL SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock);
298 
299 /* Remove a socket from a set of sockets to be checked for available data */
300 #define SDLNet_TCP_DelSocket(set, sock) \
301 			SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
302 #define SDLNet_UDP_DelSocket(set, sock) \
303 			SDLNet_DelSocket(set, SDL_reinterpret_cast(SDLNet_GenericSocket, sock))
304 extern DECLSPEC int SDLCALL SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock);
305 
306 /* This function checks to see if data is available for reading on the
307    given set of sockets.  If 'timeout' is 0, it performs a quick poll,
308    otherwise the function returns when either data is available for
309    reading, or the timeout in milliseconds has elapsed, which ever occurs
310    first.  This function returns the number of sockets ready for reading,
311    or -1 if there was an error with the select() system call.
312 */
313 extern DECLSPEC int SDLCALL SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout);
314 
315 /* After calling SDLNet_CheckSockets(), you can use this function on a
316    socket that was in the socket set, to find out if data is available
317    for reading.
318 */
319 #define SDLNet_SocketReady(sock) \
320 		((sock != NULL) && SDL_reinterpret_cast(SDLNet_GenericSocket, sock)->ready)
321 
322 /* Free a set of sockets allocated by SDL_NetAllocSocketSet() */
323 extern DECLSPEC void SDLCALL SDLNet_FreeSocketSet(SDLNet_SocketSet set);
324 
325 
326 /***********************************************************************/
327 /* Platform-independent data conversion functions                      */
328 /***********************************************************************/
329 
330 /* Write a 16/32 bit value to network packet buffer */
331 extern DECLSPEC void SDLCALL SDLNet_Write16(Uint16 value, void *area);
332 extern DECLSPEC void SDLCALL SDLNet_Write32(Uint32 value, void *area);
333 
334 /* Read a 16/32 bit value from network packet buffer */
335 extern DECLSPEC Uint16 SDLCALL SDLNet_Read16(void *area);
336 extern DECLSPEC Uint32 SDLCALL SDLNet_Read32(void *area);
337 
338 /***********************************************************************/
339 /* Error reporting functions                                           */
340 /***********************************************************************/
341 
342 /* We'll use SDL's functions for error reporting */
343 #define SDLNet_SetError	SDL_SetError
344 #define SDLNet_GetError	SDL_GetError
345 
346 /* I'm eventually going to try to disentangle SDL_net from SDL, thus making
347    SDL_net an independent X-platform networking toolkit.  Not today though....
348 
349 extern no_parse_DECLSPEC void SDLCALL SDLNet_SetError(const char *fmt, ...);
350 extern no_parse_DECLSPEC char * SDLCALL SDLNet_GetError(void);
351 */
352 
353 
354 /* Inline macro functions to read/write network data */
355 
356 /* Warning, some systems have data access alignment restrictions */
357 #if defined(sparc) || defined(mips)
358 #define SDL_DATA_ALIGNED	1
359 #endif
360 #ifndef SDL_DATA_ALIGNED
361 #define SDL_DATA_ALIGNED	0
362 #endif
363 
364 /* Write a 16 bit value to network packet buffer */
365 #if !SDL_DATA_ALIGNED
366 #define SDLNet_Write16(value, areap)	\
367 	(*SDL_reinterpret_cast(Uint16 *, areap) = SDL_SwapBE16(value))
368 #else
369 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
370 #define SDLNet_Write16(value, areap)	\
371 do 					\
372 {					\
373 	Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap);	\
374 	area[0] = (value >>  8) & 0xFF;	\
375 	area[1] =  value        & 0xFF;	\
376 } while ( 0 )
377 #else
378 #define SDLNet_Write16(value, areap)	\
379 do 					\
380 {					\
381 	Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap);	\
382 	area[1] = (value >>  8) & 0xFF;	\
383 	area[0] =  value        & 0xFF;	\
384 } while ( 0 )
385 #endif
386 #endif /* !SDL_DATA_ALIGNED */
387 
388 /* Write a 32 bit value to network packet buffer */
389 #if !SDL_DATA_ALIGNED
390 #define SDLNet_Write32(value, areap) 	\
391 	*SDL_reinterpret_cast(Uint32 *, areap) = SDL_SwapBE32(value);
392 #else
393 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
394 #define SDLNet_Write32(value, areap) 	\
395 do					\
396 {					\
397 	Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap);	\
398 	area[0] = (value >> 24) & 0xFF;	\
399 	area[1] = (value >> 16) & 0xFF;	\
400 	area[2] = (value >>  8) & 0xFF;	\
401 	area[3] =  value       & 0xFF;	\
402 } while ( 0 )
403 #else
404 #define SDLNet_Write32(value, areap) 	\
405 do					\
406 {					\
407 	Uint8 *area = SDL_reinterpret_cast(Uint8 *, areap);	\
408 	area[3] = (value >> 24) & 0xFF;	\
409 	area[2] = (value >> 16) & 0xFF;	\
410 	area[1] = (value >>  8) & 0xFF;	\
411 	area[0] =  value       & 0xFF;	\
412 } while ( 0 )
413 #endif
414 #endif /* !SDL_DATA_ALIGNED */
415 
416 /* Read a 16 bit value from network packet buffer */
417 #if !SDL_DATA_ALIGNED
418 #define SDLNet_Read16(areap) 		\
419 	(SDL_SwapBE16(*SDL_reinterpret_cast(Uint16 *, areap)))
420 #else
421 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
422 #define SDLNet_Read16(areap) 		\
423 	(((SDL_reinterpret_cast(Uint8 *, areap))[0] <<  8) | (SDL_reinterpret_cast(Uint8 *, areap))[1] <<  0)
424 #else
425 #define SDLNet_Read16(areap) 		\
426 	(((SDL_reinterpret_cast(Uint8 *, areap))[1] <<  8) | (SDL_reinterpret_cast(Uint8 *, areap))[0] <<  0)
427 #endif
428 #endif /* !SDL_DATA_ALIGNED */
429 
430 /* Read a 32 bit value from network packet buffer */
431 #if !SDL_DATA_ALIGNED
432 #define SDLNet_Read32(areap) 		\
433 	(SDL_SwapBE32(*SDL_reinterpret_cast(Uint32 *, areap)))
434 #else
435 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
436 #define SDLNet_Read32(areap) 		\
437 	(((SDL_reinterpret_cast(Uint8 *, areap))[0] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[1] << 16) | \
438 	 ((SDL_reinterpret_cast(Uint8 *, areap))[2] <<  8) |  (SDL_reinterpret_cast(Uint8 *, areap))[3] <<  0)
439 #else
440 #define SDLNet_Read32(areap) 		\
441 	(((SDL_reinterpret_cast(Uint8 *, areap))[3] << 24) | ((SDL_reinterpret_cast(Uint8 *, areap))[2] << 16) | \
442 	 ((SDL_reinterpret_cast(Uint8 *, areap))[1] <<  8) |  (SDL_reinterpret_cast(Uint8 *, areap))[0] <<  0)
443 #endif
444 #endif /* !SDL_DATA_ALIGNED */
445 
446 /* Ends C function definitions when using C++ */
447 #ifdef __cplusplus
448 }
449 #endif
450 #include "close_code.h"
451 
452 #endif /* _SDL_NET_H */
453