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