]>
Commit | Line | Data |
---|---|---|
7407ac7f BB |
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 | 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 <SDL2/SDL.h> | |
43 | #include <SDL2/SDL_endian.h> | |
44 | #include <SDL2/SDL_version.h> | |
45 | ||
46 | typedef SDL_version SDLNet_version; | |
47 | ||
48 | #endif /* WITHOUT_SDL */ | |
49 | ||
50 | #include <SDL2/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 0 | |
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); | |
313 | static __inline__ int SDLNet_TCP_AddSocket(SDLNet_SocketSet set, TCPsocket sock) | |
314 | { | |
315 | return SDLNet_AddSocket(set, (SDLNet_GenericSocket)sock); | |
316 | } | |
317 | static __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); | |
325 | static __inline__ int SDLNet_TCP_DelSocket(SDLNet_SocketSet set, TCPsocket sock) | |
326 | { | |
327 | return SDLNet_DelSocket(set, (SDLNet_GenericSocket)sock); | |
328 | } | |
329 | static __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)) | |
348 | static __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 | ||
385 | static __inline__ void _SDLNet_Write16(Uint16 value, void *areap) | |
386 | { | |
387 | *(Uint16 *)areap = SDL_SwapBE16(value); | |
388 | } | |
389 | ||
390 | static __inline__ void _SDLNet_Write32(Uint32 value, void *areap) | |
391 | { | |
392 | *(Uint32 *)areap = SDL_SwapBE32(value); | |
393 | } | |
394 | ||
395 | static __inline__ Uint16 _SDLNet_Read16(const void *areap) | |
396 | { | |
397 | return SDL_SwapBE16(*(const Uint16 *)areap); | |
398 | } | |
399 | ||
400 | static __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 | ||
407 | static __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 | ||
414 | static __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 | ||
423 | static __inline__ Uint16 _SDLNet_Read16(void *areap) | |
424 | { | |
425 | Uint8 *area = (Uint8*)areap; | |
426 | return ((Uint16)area[0]) << 8 | ((Uint16)area[1]); | |
427 | } | |
428 | ||
429 | static __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 <SDL2/close_code.h> | |
442 | ||
443 | #endif /* _SDL_NET_H */ |