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