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