1 /**********************************************************************************************
3 * rnet - A simple and easy-to-use network module for raylib
6 * - Provides a simple and (hopefully) easy to use wrapper around the Berkeley socket API
9 * SFML Sockets - https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Socket.php
10 * SDL_net - https://www.libsdl.org/projects/SDL_net/
11 * BSD Sockets - https://www.gnu.org/software/libc/manual/html_node/Sockets.html
12 * BEEJ - https://beej.us/guide/bgnet/html/single/bgnet.html
13 * Winsock2 - https://docs.microsoft.com/en-us/windows/desktop/api/winsock2
16 * Jak Barnes (github: @syphonx) (Feb. 2019) - Initial version
19 * LICENSE: zlib/libpng
21 * Copyright (c) 2019-2020 Jak Barnes (@syphonx) and Ramon Santamaria (@raysan5)
23 * This software is provided "as-is", without any express or implied warranty. In no event
24 * will the authors be held liable for any damages arising from the use of this software.
26 * Permission is granted to anyone to use this software for any purpose, including commercial
27 * applications, and to alter it and redistribute it freely, subject to the following restrictions:
29 * 1. The origin of this software must not be misrepresented; you must not claim that you
30 * wrote the original software. If you use this software in a product, an acknowledgment
31 * in the product documentation would be appreciated but is not required.
33 * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
34 * as being the original software.
36 * 3. This notice may not be removed or altered from any source distribution.
38 **********************************************************************************************/
43 #include <limits.h> // Required for limits
44 #include <inttypes.h> // Required for platform type sizes
46 //----------------------------------------------------------------------------------
48 //----------------------------------------------------------------------------------
50 // Undefine any conflicting windows.h symbols
51 // If defined, the following flags inhibit definition of the indicated items.
52 #define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_
53 #define NOVIRTUALKEYCODES // VK_*
54 #define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_*
55 #define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
56 #define NOSYSMETRICS // SM_*
57 #define NOMENUS // MF_*
58 #define NOICONS // IDI_*
59 #define NOKEYSTATES // MK_*
60 #define NOSYSCOMMANDS // SC_*
61 #define NORASTEROPS // Binary and Tertiary raster ops
62 #define NOSHOWWINDOW // SW_*
63 #define OEMRESOURCE // OEM Resource values
64 #define NOATOM // Atom Manager routines
65 #define NOCLIPBOARD // Clipboard routines
66 #define NOCOLOR // Screen colors
67 #define NOCTLMGR // Control and Dialog routines
68 #define NODRAWTEXT // DrawText() and DT_*
69 #define NOGDI // All GDI defines and routines
70 #define NOKERNEL // All KERNEL defines and routines
71 #define NOUSER // All USER defines and routines
72 #define NONLS // All NLS defines and routines
73 #define NOMB // MB_* and MessageBox()
74 #define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines
75 #define NOMETAFILE // typedef METAFILEPICT
76 #define NOMINMAX // Macros min(a,b) and max(a,b)
77 #define NOMSG // typedef MSG and associated routines
78 #define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_*
79 #define NOSCROLL // SB_* and scrolling routines
80 #define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc.
81 #define NOSOUND // Sound driver routines
82 #define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines
83 #define NOWH // SetWindowsHook and WH_*
84 #define NOWINOFFSETS // GWL_*, GCL_*, associated routines
85 #define NOCOMM // COMM driver routines
86 #define NOKANJI // Kanji support stuff.
87 #define NOHELP // Help engine interface.
88 #define NOPROFILER // Profiler interface.
89 #define NODEFERWINDOWPOS // DeferWindowPos routines
90 #define NOMCX // Modem Configuration Extensions
93 // Allow custom memory allocators
95 #define RNET_MALLOC(sz) malloc(sz)
98 #define RNET_CALLOC(n,sz) calloc(n,sz)
101 #define RNET_FREE(p) free(p)
104 //----------------------------------------------------------------------------------
105 // Platform type definitions
106 // From: https://github.com/DFHack/clsocket/blob/master/src/Host.h
107 //----------------------------------------------------------------------------------
110 typedef int socklen_t;
113 #ifndef RESULT_SUCCESS
114 # define RESULT_SUCCESS 0
115 #endif // RESULT_SUCCESS
117 #ifndef RESULT_FAILURE
118 # define RESULT_FAILURE 1
119 #endif // RESULT_FAILURE
123 # define htonll(x) (x)
124 # define ntohll(x) (x)
126 # define htonll(x) ((((uint64) htonl(x)) << 32) + htonl(x >> 32))
127 # define ntohll(x) ((((uint64) ntohl(x)) << 32) + ntohl(x >> 32))
128 # endif // _BIG_ENDIAN
131 //----------------------------------------------------------------------------------
132 // Platform specific network includes
133 // From: https://github.com/SDL-mirror/SDL_net/blob/master/SDLnetsys.h
134 //----------------------------------------------------------------------------------
136 // Include system network headers
137 #if defined(_WIN32) // Windows
138 #define __USE_W32_SOCKETS
139 #define WIN32_LEAN_AND_MEAN
140 #include <winsock2.h>
141 #include <ws2tcpip.h>
143 #define IPTOS_LOWDELAY 0x10
145 #include <sys/types.h>
147 #include <netinet/in.h>
148 #include <sys/ioctl.h>
149 #include <sys/time.h>
153 #include <netinet/tcp.h>
154 #include <sys/socket.h>
155 #include <arpa/inet.h>
158 #ifndef INVALID_SOCKET
159 #define INVALID_SOCKET ~(0)
162 #ifndef __USE_W32_SOCKETS
163 #define closesocket close
165 #define INVALID_SOCKET -1
166 #define SOCKET_ERROR -1
169 #ifdef __USE_W32_SOCKETS
171 #define EINTR WSAEINTR
175 //----------------------------------------------------------------------------------
177 //----------------------------------------------------------------------------------
179 // Network connection related defines
180 #define SOCKET_MAX_SET_SIZE 32 // Maximum sockets in a set
181 #define SOCKET_MAX_QUEUE_SIZE 16 // Maximum socket queue size
182 #define SOCKET_MAX_SOCK_OPTS 4 // Maximum socket options
183 #define SOCKET_MAX_UDPCHANNELS 32 // Maximum UDP channels
184 #define SOCKET_MAX_UDPADDRESSES 4 // Maximum bound UDP addresses
186 // Network address related defines
187 #define ADDRESS_IPV4_ADDRSTRLEN 22 // IPv4 string length
188 #define ADDRESS_IPV6_ADDRSTRLEN 65 // IPv6 string length
189 #define ADDRESS_TYPE_ANY 0 // AF_UNSPEC
190 #define ADDRESS_TYPE_IPV4 2 // AF_INET
191 #define ADDRESS_TYPE_IPV6 23 // AF_INET6
192 #define ADDRESS_MAXHOST 1025 // Max size of a fully-qualified domain name
193 #define ADDRESS_MAXSERV 32 // Max size of a service name
195 // Network address related defines
196 #define ADDRESS_ANY (unsigned long)0x00000000
197 #define ADDRESS_LOOPBACK 0x7f000001
198 #define ADDRESS_BROADCAST (unsigned long)0xffffffff
199 #define ADDRESS_NONE 0xffffffff
201 // Network resolution related defines
202 #define NAME_INFO_DEFAULT 0x00 // No flags set
203 #define NAME_INFO_NOFQDN 0x01 // Only return nodename portion for local hosts
204 #define NAME_INFO_NUMERICHOST 0x02 // Return numeric form of the host's address
205 #define NAME_INFO_NAMEREQD 0x04 // Error if the host's name not in DNS
206 #define NAME_INFO_NUMERICSERV 0x08 // Return numeric form of the service (port #)
207 #define NAME_INFO_DGRAM 0x10 // Service is a datagram service
209 // Address resolution related defines
211 #define ADDRESS_INFO_PASSIVE (0x00000001) // Socket address will be used in bind() call
212 #define ADDRESS_INFO_CANONNAME (0x00000002) // Return canonical name in first ai_canonname
213 #define ADDRESS_INFO_NUMERICHOST (0x00000004) // Nodename must be a numeric address string
214 #define ADDRESS_INFO_NUMERICSERV (0x00000008) // Servicename must be a numeric port number
215 #define ADDRESS_INFO_DNS_ONLY (0x00000010) // Restrict queries to unicast DNS only (no LLMNR, netbios, etc.)
216 #define ADDRESS_INFO_ALL (0x00000100) // Query both IP6 and IP4 with AI_V4MAPPED
217 #define ADDRESS_INFO_ADDRCONFIG (0x00000400) // Resolution only if global address configured
218 #define ADDRESS_INFO_V4MAPPED (0x00000800) // On v6 failure, query v4 and convert to V4MAPPED format
219 #define ADDRESS_INFO_NON_AUTHORITATIVE (0x00004000) // LUP_NON_AUTHORITATIVE
220 #define ADDRESS_INFO_SECURE (0x00008000) // LUP_SECURE
221 #define ADDRESS_INFO_RETURN_PREFERRED_NAMES (0x00010000) // LUP_RETURN_PREFERRED_NAMES
222 #define ADDRESS_INFO_FQDN (0x00020000) // Return the FQDN in ai_canonname
223 #define ADDRESS_INFO_FILESERVER (0x00040000) // Resolving fileserver name resolution
224 #define ADDRESS_INFO_DISABLE_IDN_ENCODING (0x00080000) // Disable Internationalized Domain Names handling
225 #define ADDRESS_INFO_EXTENDED (0x80000000) // Indicates this is extended ADDRINFOEX(2/..) struct
226 #define ADDRESS_INFO_RESOLUTION_HANDLE (0x40000000) // Request resolution handle
229 //----------------------------------------------------------------------------------
230 // Types and Structures Definition
231 //----------------------------------------------------------------------------------
237 #if defined(__STDC__) && __STDC_VERSION__ >= 199901L
239 #elif !defined(__cplusplus) && !defined(bool)
240 typedef enum { false, true } bool;
245 SOCKET_TCP = 0, // SOCK_STREAM
246 SOCKET_UDP = 1 // SOCK_DGRAM
250 typedef uint32_t SocketChannel;
251 typedef struct _AddressInformation *AddressInformation;
252 typedef struct _SocketAddress *SocketAddress;
253 typedef struct _SocketAddressIPv4 *SocketAddressIPv4;
254 typedef struct _SocketAddressIPv6 *SocketAddressIPv6;
255 typedef struct _SocketAddressStorage *SocketAddressStorage;
257 // IPAddress definition (in network byte order)
258 typedef struct IPAddress {
259 unsigned long host; // 32-bit IPv4 host address
260 unsigned short port; // 16-bit protocol port
263 typedef struct UDPChannel {
264 int numbound; // The total number of addresses this channel is bound to
265 IPAddress address[SOCKET_MAX_UDPADDRESSES]; // The list of remote addresses this channel is bound to
268 // An option ID, value, sizeof(value) tuple for setsockopt(2).
269 typedef struct SocketOpt {
270 int id; // Socked option id
271 int valueLen; // Socked option value len
272 void *value; // Socked option value data
275 typedef struct Socket {
276 int ready; // Is the socket ready? i.e. has information
277 int status; // The last status code to have occured using this socket
278 bool isServer; // Is this socket a server socket (i.e. TCP/UDP Listen Server)
279 SocketChannel channel; // The socket handle id
280 SocketType type; // Is this socket a TCP or UDP socket?
282 bool isIPv6; // Is this socket address an ipv6 address?
283 SocketAddressIPv4 addripv4; // The host/target IPv4 for this socket (in network byte order)
284 SocketAddressIPv6 addripv6; // The host/target IPv6 for this socket (in network byte order)
286 struct UDPChannel binding[SOCKET_MAX_UDPCHANNELS]; // The amount of channels (if UDP) this socket is bound to
289 // Configuration for a socket
290 typedef struct SocketConfig {
291 SocketType type; // The type of socket, TCP/UDP
292 char *host; // The host address in xxx.xxx.xxx.xxx form
293 char *port; // The target port/service in the form "http" or "25565"
294 bool server; // Listen for incoming clients?
295 bool nonblocking; // non-blocking operation?
296 int backlog_size; // set a custom backlog size
297 SocketOpt sockopts[SOCKET_MAX_SOCK_OPTS];
300 typedef struct SocketDataPacket {
301 IPAddress address; // The source/dest address of an incoming/outgoing packet
302 int channel; // The src/dst channel of the packet
303 int maxlen; // The size of the data buffer
304 int status; // Packet status after sending
305 unsigned int len; // The length of the packet data
306 unsigned char *data; // The packet data
309 // Result from calling open with a given config
310 typedef struct SocketResult {
311 int status; // Socket result state
312 Socket *socket; // Socket ref
315 typedef struct SocketSet {
316 int numsockets; // Socket set count
317 int maxsockets; // Socket set max
318 struct Socket **sockets; // Sockets array
322 typedef struct Packet {
323 uint32_t size; // The total size of bytes in data
324 uint32_t offs; // The offset to data access
325 uint32_t maxs; // The max size of data
326 uint8_t *data; // Data stored in network byte order
331 extern "C" { // Prevents name mangling of functions
334 //----------------------------------------------------------------------------------
335 // Global Variables Definition
336 //----------------------------------------------------------------------------------
339 //----------------------------------------------------------------------------------
340 // Module Functions Declaration
341 //----------------------------------------------------------------------------------
343 // Initialisation and cleanup
344 bool InitNetworkDevice(void);
345 void CloseNetworkDevice(void);
348 void ResolveIP(const char *ip, const char *service, int flags, char *outhost, char *outserv);
349 int ResolveHost(const char *address, const char *service, int addressType, int flags, AddressInformation *outAddr);
350 int GetAddressFamily(AddressInformation address);
351 int GetAddressSocketType(AddressInformation address);
352 int GetAddressProtocol(AddressInformation address);
353 char *GetAddressCanonName(AddressInformation address);
354 char *GetAddressHostAndPort(AddressInformation address, char *outhost, unsigned short *outport);
356 // Address Memory API
357 AddressInformation LoadAddress(void);
358 void UnloadAddress(AddressInformation *addressInfo);
359 AddressInformation *LoadAddressList(int size);
362 bool SocketCreate(SocketConfig *config, SocketResult *result);
363 bool SocketBind(SocketConfig *config, SocketResult *result);
364 bool SocketListen(SocketConfig *config, SocketResult *result);
365 bool SocketConnect(SocketConfig *config, SocketResult *result);
366 Socket *SocketAccept(Socket *server, SocketConfig *config);
368 // General Socket API
369 int SocketSend(Socket *sock, const void *datap, int len);
370 int SocketReceive(Socket *sock, void *data, int maxlen);
371 SocketAddressStorage SocketGetPeerAddress(Socket *sock);
372 const char *GetSocketAddressHost(SocketAddressStorage storage);
373 short GetSocketAddressPort(SocketAddressStorage storage);
374 void SocketClose(Socket *sock);
377 int SocketSetChannel(Socket *socket, int channel, const IPAddress *address);
378 void SocketUnsetChannel(Socket *socket, int channel);
380 // UDP DataPacket API
381 SocketDataPacket *AllocPacket(int size);
382 int ResizePacket(SocketDataPacket *packet, int newsize);
383 void FreePacket(SocketDataPacket *packet);
384 SocketDataPacket **AllocPacketList(int count, int size);
385 void FreePacketList(SocketDataPacket **packets);
388 Socket *LoadSocket(void);
389 void UnloadSocket(Socket **sock);
390 SocketResult *LoadSocketResult(void);
391 void UnloadSocketResult(SocketResult **result);
392 SocketSet *LoadSocketSet(int max);
393 void UnloadSocketSet(SocketSet *sockset);
396 bool IsSocketReady(Socket *sock);
397 bool IsSocketConnected(Socket *sock);
398 int AddSocket(SocketSet *set, Socket *sock);
399 int RemoveSocket(SocketSet *set, Socket *sock);
400 int CheckSockets(SocketSet *set, unsigned int timeout);
403 void PacketSend(Packet *packet);
404 void PacketReceive(Packet *packet);
405 void PacketWrite8(Packet *packet, uint16_t value);
406 void PacketWrite16(Packet *packet, uint16_t value);
407 void PacketWrite32(Packet *packet, uint32_t value);
408 void PacketWrite64(Packet *packet, uint64_t value);
409 uint16_t PacketRead8(Packet *packet);
410 uint16_t PacketRead16(Packet *packet);
411 uint32_t PacketRead32(Packet *packet);
412 uint64_t PacketRead64(Packet *packet);
420 /***********************************************************************************
422 * RNET IMPLEMENTATION
424 ************************************************************************************/
426 #if defined(RNET_IMPLEMENTATION)
428 #include <assert.h> // Required for: assert()
429 #include <stdio.h> // Required for: FILE, fopen(), fclose(), fread()
430 #include <stdlib.h> // Required for: malloc(), free()
431 #include <string.h> // Required for: strcmp(), strncmp()
433 #define NET_DEBUG_ENABLED 1
435 #if defined(SUPPORT_TRACELOG)
436 #define TRACELOG(level, ...) TraceLog(level, __VA_ARGS__)
438 #if defined(SUPPORT_TRACELOG_DEBUG)
439 #define TRACELOGD(...) TraceLog(LOG_DEBUG, __VA_ARGS__)
441 #define TRACELOGD(...) (void)0
444 #define TRACELOG(level, ...) (void)0
445 #define TRACELOGD(...) (void)0
448 //----------------------------------------------------------------------------------
449 // Types and Structures Definition
450 //----------------------------------------------------------------------------------
452 typedef struct _SocketAddress
454 struct sockaddr address;
457 typedef struct _SocketAddressIPv4
459 struct sockaddr_in address;
460 } _SocketAddressIPv4;
462 typedef struct _SocketAddressIPv6
464 struct sockaddr_in6 address;
465 } _SocketAddressIPv6;
467 typedef struct _SocketAddressStorage
469 struct sockaddr_storage address;
470 } _SocketAddressStorage;
472 typedef struct _AddressInformation
474 struct addrinfo addr;
475 } _AddressInformation;
477 //----------------------------------------------------------------------------------
478 // Local module Functions Declarations
479 //----------------------------------------------------------------------------------
480 static void PrintSocket(struct sockaddr_storage *addr, const int family, const int socktype, const int protocol);
481 static const char *SocketAddressToString(struct sockaddr_storage *sockaddr);
482 static bool IsIPv4Address(const char *ip);
483 static bool IsIPv6Address(const char *ip);
484 static void *GetSocketPortPtr(struct sockaddr_storage *sa);
485 static void *GetSocketAddressPtr(struct sockaddr_storage *sa);
486 static bool IsSocketValid(Socket *sock);
487 static void SocketSetLastError(int err);
488 static int SocketGetLastError();
489 static char *SocketGetLastErrorString();
490 static char *SocketErrorCodeToString(int err);
491 static bool SocketSetDefaults(SocketConfig *config);
492 static bool InitSocket(Socket *sock, struct addrinfo *addr);
493 static bool CreateSocket(SocketConfig *config, SocketResult *outresult);
494 static bool SocketSetBlocking(Socket *sock);
495 static bool SocketSetNonBlocking(Socket *sock);
496 static bool SocketSetOptions(SocketConfig *config, Socket *sock);
497 static void SocketSetHints(SocketConfig *config, struct addrinfo *hints);
499 //----------------------------------------------------------------------------------
500 // Local module Functions Definition
501 //----------------------------------------------------------------------------------
502 // Print socket information
503 static void PrintSocket(struct sockaddr_storage *addr, const int family, const int socktype, const int protocol)
507 case AF_UNSPEC: TRACELOG(LOG_DEBUG, "\tFamily: Unspecified"); break;
510 TRACELOG(LOG_DEBUG, "\tFamily: AF_INET (IPv4)");
511 TRACELOG(LOG_INFO, "\t- IPv4 address %s", SocketAddressToString(addr));
515 TRACELOG(LOG_DEBUG, "\tFamily: AF_INET6 (IPv6)");
516 TRACELOG(LOG_INFO, "\t- IPv6 address %s", SocketAddressToString(addr));
520 TRACELOG(LOG_DEBUG, "\tFamily: AF_NETBIOS (NetBIOS)");
522 default: TRACELOG(LOG_DEBUG, "\tFamily: Other %ld", family); break;
525 TRACELOG(LOG_DEBUG, "\tSocket type:");
528 case 0: TRACELOG(LOG_DEBUG, "\t- Unspecified"); break;
529 case SOCK_STREAM: TRACELOG(LOG_DEBUG, "\t- SOCK_STREAM (stream)"); break;
530 case SOCK_DGRAM: TRACELOG(LOG_DEBUG, "\t- SOCK_DGRAM (datagram)"); break;
531 case SOCK_RAW: TRACELOG(LOG_DEBUG, "\t- SOCK_RAW (raw)"); break;
532 case SOCK_RDM: TRACELOG(LOG_DEBUG, "\t- SOCK_RDM (reliable message datagram)"); break;
533 case SOCK_SEQPACKET: TRACELOG(LOG_DEBUG, "\t- SOCK_SEQPACKET (pseudo-stream packet)"); break;
534 default: TRACELOG(LOG_DEBUG, "\t- Other %ld", socktype); break;
537 TRACELOG(LOG_DEBUG, "\tProtocol:");
540 case 0: TRACELOG(LOG_DEBUG, "\t- Unspecified"); break;
541 case IPPROTO_TCP: TRACELOG(LOG_DEBUG, "\t- IPPROTO_TCP (TCP)"); break;
542 case IPPROTO_UDP: TRACELOG(LOG_DEBUG, "\t- IPPROTO_UDP (UDP)"); break;
543 default: TRACELOG(LOG_DEBUG, "\t- Other %ld", protocol); break;
547 // Convert network ordered socket address to human readable string (127.0.0.1)
548 static const char *SocketAddressToString(struct sockaddr_storage *sockaddr)
550 //static const char* ipv6[INET6_ADDRSTRLEN];
551 assert(sockaddr != NULL);
552 assert(sockaddr->ss_family == AF_INET || sockaddr->ss_family == AF_INET6);
554 switch (sockaddr->ss_family)
558 //struct sockaddr_in *s = ((struct sockaddr_in *)sockaddr);
559 //return inet_ntop(AF_INET, &s->sin_addr, ipv6, INET_ADDRSTRLEN); // TODO.
564 //struct sockaddr_in6 *s = ((struct sockaddr_in6 *)sockaddr);
565 //return inet_ntop(AF_INET6, &s->sin6_addr, ipv6, INET6_ADDRSTRLEN); // TODO.
573 // Check if the null terminated string ip is a valid IPv4 address
574 static bool IsIPv4Address(const char *ip)
577 struct sockaddr_in sa;
578 int result = inet_pton(AF_INET, ip, &(sa.sin_addr)); // TODO.
579 return (result != 0);
584 // Check if the null terminated string ip is a valid IPv6 address
585 static bool IsIPv6Address(const char *ip)
588 struct sockaddr_in6 sa;
589 int result = inet_pton(AF_INET6, ip, &(sa.sin6_addr)); // TODO.
595 // Return a pointer to the port from the correct address family (IPv4, or IPv6)
596 static void *GetSocketPortPtr(struct sockaddr_storage *sa)
598 if (sa->ss_family == AF_INET)
600 return &(((struct sockaddr_in *)sa)->sin_port);
603 return &(((struct sockaddr_in6 *)sa)->sin6_port);
606 // Return a pointer to the address from the correct address family (IPv4, or IPv6)
607 static void *GetSocketAddressPtr(struct sockaddr_storage *sa)
609 if (sa->ss_family == AF_INET)
611 return &(((struct sockaddr_in *)sa)->sin_addr);
614 return &(((struct sockaddr_in6 *)sa)->sin6_addr);
617 // Is the socket in a valid state?
618 static bool IsSocketValid(Socket *sock)
622 return (sock->channel != INVALID_SOCKET);
628 // Sets the error code that can be retrieved through the WSAGetLastError function.
629 static void SocketSetLastError(int err)
632 WSASetLastError(err);
638 // Returns the error status for the last Sockets operation that failed
639 static int SocketGetLastError(void)
642 return WSAGetLastError();
648 // Returns a human-readable string representing the last error message
649 static char *SocketGetLastErrorString(void)
651 return SocketErrorCodeToString(SocketGetLastError());
654 // Returns a human-readable string representing the error message (err)
655 static char *SocketErrorCodeToString(int err)
658 static char gaiStrErrorBuffer[GAI_STRERROR_BUFFER_SIZE];
659 TRACELOG(LOG_INFO, gaiStrErrorBuffer, "%s", gai_strerror(err));
660 return gaiStrErrorBuffer;
662 return gai_strerror(err);
666 // Set the defaults in the supplied SocketConfig if they're not already set
667 static bool SocketSetDefaults(SocketConfig *config)
669 if (config->backlog_size == 0) config->backlog_size = SOCKET_MAX_QUEUE_SIZE;
674 // Create the socket channel
675 static bool InitSocket(Socket *sckt, struct addrinfo *address)
681 if (address->ai_family == AF_INET) sckt->channel = socket(AF_INET, SOCK_STREAM, 0);
682 else sckt->channel = socket(AF_INET6, SOCK_STREAM, 0);
686 if (address->ai_family == AF_INET) sckt->channel = socket(AF_INET, SOCK_DGRAM, 0);
687 else sckt->channel = socket(AF_INET6, SOCK_DGRAM, 0);
689 default: TRACELOG(LOG_WARNING, "Invalid socket type specified."); break;
692 return IsSocketValid(sckt);
695 // CreateSocket() - Interally called by CreateSocket()
697 // This here is the bread and butter of the socket API, This function will
698 // attempt to open a socket, bind and listen to it based on the config passed in
700 // SocketConfig* config - Configuration for which socket to open
701 // SocketResult* result - The results of this function (if any, including errors)
704 // SocketConfig server_config = { SocketConfig client_config = {
705 // .host = "127.0.0.1", .host = "127.0.0.1",
706 // .port = 8080, .port = 8080,
707 // .server = true, };
708 // .nonblocking = true,
710 // SocketResult server_res; SocketResult client_res;
711 static bool CreateSocket(SocketConfig *config, SocketResult *outresult)
715 struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
716 struct addrinfo *res; // A pointer to the resulting address list
718 outresult->socket->channel = INVALID_SOCKET;
719 outresult->status = RESULT_FAILURE;
721 // Set the socket type
722 outresult->socket->type = config->type;
724 // Set the hints based on information in the config
726 // AI_CANONNAME Causes the ai_canonname of the result to the filled out with the host's canonical (real) name.
727 // AI_PASSIVE: Causes the result's IP address to be filled out with INADDR_ANY (IPv4)or in6addr_any (IPv6);
728 // Note: This causes a subsequent call to bind() to auto-fill the IP address
729 // of the struct sockaddr with the address of the current host.
731 SocketSetHints(config, &hints);
733 // Populate address information
734 addrstatus = getaddrinfo(config->host, // e.g. "www.example.com" or IP (Can be null if AI_PASSIVE flag is set
735 config->port, // e.g. "http" or port number
736 &hints, // e.g. SOCK_STREAM/SOCK_DGRAM
737 &res // The struct to populate
743 outresult->socket->status = SocketGetLastError();
744 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->socket->status));
745 SocketSetLastError(0);
746 TRACELOG(LOG_WARNING, "Failed to get resolve host %s:%s: %s", config->host, config->port, SocketGetLastErrorString());
748 return (success = false);
752 char hoststr[NI_MAXHOST];
753 char portstr[NI_MAXSERV];
754 //socklen_t client_len = sizeof(struct sockaddr_storage);
755 //int rc = getnameinfo((struct sockaddr *)res->ai_addr, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
756 TRACELOG(LOG_INFO, "Successfully resolved host %s:%s", hoststr, portstr);
759 // Walk the address information linked-list
761 for (it = res; it != NULL; it = it->ai_next)
763 // Initialise the socket
764 if (!InitSocket(outresult->socket, it))
766 outresult->socket->status = SocketGetLastError();
767 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->socket->status));
768 SocketSetLastError(0);
772 // Set socket options
773 if (!SocketSetOptions(config, outresult->socket))
775 outresult->socket->status = SocketGetLastError();
776 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->socket->status));
777 SocketSetLastError(0);
780 return (success = false);
784 if (!IsSocketValid(outresult->socket))
786 outresult->socket->status = SocketGetLastError();
787 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->status));
788 SocketSetLastError(0);
791 return (success = false);
796 outresult->status = RESULT_SUCCESS;
797 outresult->socket->ready = 0;
798 outresult->socket->status = 0;
800 if (!(config->type == SOCKET_UDP)) outresult->socket->isServer = config->server;
802 switch (res->ai_addr->sa_family)
806 outresult->socket->addripv4 = (struct _SocketAddressIPv4 *)RNET_MALLOC(sizeof(*outresult->socket->addripv4));
808 if (outresult->socket->addripv4 != NULL)
810 memset(outresult->socket->addripv4, 0, sizeof(*outresult->socket->addripv4));
812 if (outresult->socket->addripv4 != NULL)
814 memcpy(&outresult->socket->addripv4->address, (struct sockaddr_in *)res->ai_addr, sizeof(struct sockaddr_in));
816 outresult->socket->isIPv6 = false;
817 char hoststr[NI_MAXHOST];
818 char portstr[NI_MAXSERV];
820 socklen_t client_len = sizeof(struct sockaddr_storage);
821 getnameinfo((struct sockaddr *)&outresult->socket->addripv4->address, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
823 TRACELOG(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr);
829 outresult->socket->addripv6 = (struct _SocketAddressIPv6 *)RNET_MALLOC(
830 sizeof(*outresult->socket->addripv6));
831 if (outresult->socket->addripv6 != NULL)
833 memset(outresult->socket->addripv6, 0,
834 sizeof(*outresult->socket->addripv6));
835 if (outresult->socket->addripv6 != NULL)
837 memcpy(&outresult->socket->addripv6->address,
838 (struct sockaddr_in6 *)res->ai_addr, sizeof(struct sockaddr_in6));
839 outresult->socket->isIPv6 = true;
840 char hoststr[NI_MAXHOST];
841 char portstr[NI_MAXSERV];
842 socklen_t client_len = sizeof(struct sockaddr_storage);
844 (struct sockaddr *)&outresult->socket->addripv6->address, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
845 TRACELOG(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr);
857 // Set the state of the Socket sock to blocking
858 static bool SocketSetBlocking(Socket *sock)
862 unsigned long mode = 0;
863 ret = ioctlsocket(sock->channel, FIONBIO, &mode);
865 const int flags = fcntl(sock->channel, F_GETFL, 0);
866 if (!(flags & O_NONBLOCK))
868 TRACELOG(LOG_DEBUG, "Socket was already in blocking mode");
872 ret = (0 == fcntl(sock->channel, F_SETFL, (flags ^ O_NONBLOCK)));
877 // Set the state of the Socket sock to non-blocking
878 static bool SocketSetNonBlocking(Socket *sock)
882 unsigned long mode = 1;
883 ret = ioctlsocket(sock->channel, FIONBIO, &mode);
885 const int flags = fcntl(sock->channel, F_GETFL, 0);
887 if ((flags & O_NONBLOCK))
889 TRACELOG(LOG_DEBUG, "Socket was already in non-blocking mode");
893 ret = (0 == fcntl(sock->channel, F_SETFL, (flags | O_NONBLOCK)));
898 // Set options specified in SocketConfig to Socket sock
899 static bool SocketSetOptions(SocketConfig *config, Socket *sock)
901 for (int i = 0; i < SOCKET_MAX_SOCK_OPTS; i++)
903 SocketOpt *opt = &config->sockopts[i];
905 if (opt->id == 0) break;
907 if (setsockopt(sock->channel, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0) return false;
913 // Set "hints" in an addrinfo struct, to be passed to getaddrinfo.
914 static void SocketSetHints(SocketConfig *config, struct addrinfo *hints)
916 if (config == NULL || hints == NULL) return;
918 memset(hints, 0, sizeof(*hints));
920 // Check if the ip supplied in the config is a valid ipv4 ip ipv6 address
921 if (IsIPv4Address(config->host))
923 hints->ai_family = AF_INET;
924 hints->ai_flags |= AI_NUMERICHOST;
928 if (IsIPv6Address(config->host))
930 hints->ai_family = AF_INET6;
931 hints->ai_flags |= AI_NUMERICHOST;
933 else hints->ai_family = AF_UNSPEC;
936 if (config->type == SOCKET_UDP) hints->ai_socktype = SOCK_DGRAM;
937 else hints->ai_socktype = SOCK_STREAM;
940 // Set passive unless UDP client
941 if (!(config->type == SOCKET_UDP) || config->server) hints->ai_flags = AI_PASSIVE;
944 //----------------------------------------------------------------------------------
945 // Module implementation
946 //----------------------------------------------------------------------------------
948 // Initialise the network (requires for windows platforms only)
949 bool InitNetworkDevice(void)
952 WORD wVersionRequested;
955 wVersionRequested = MAKEWORD(2, 2);
956 int err = WSAStartup(wVersionRequested, &wsaData);
960 TRACELOG(LOG_WARNING, "WinSock failed to initialise.");
963 else TRACELOG(LOG_INFO, "WinSock initialised.");
965 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
967 TRACELOG(LOG_WARNING, "WinSock failed to initialise.");
978 // Cleanup, and close the network
979 void CloseNetworkDevice(void)
986 // Protocol-independent name resolution from an address to an ANSI host name
987 // and from a port number to the ANSI service name.
989 // The flags parameter can be used to customize processing of the getnameinfo function
991 // The following flags are available:
993 // NAME_INFO_DEFAULT 0x00 // No flags set
994 // NAME_INFO_NOFQDN 0x01 // Only return nodename portion for local hosts
995 // NAME_INFO_NUMERICHOST 0x02 // Return numeric form of the host's address
996 // NAME_INFO_NAMEREQD 0x04 // Error if the host's name not in DNS
997 // NAME_INFO_NUMERICSERV 0x08 // Return numeric form of the service (port #)
998 // NAME_INFO_DGRAM 0x10 // Service is a datagram service
999 void ResolveIP(const char *ip, const char *port, int flags, char *host, char *serv)
1002 int status; // Status value to return (0) is success
1003 struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
1004 struct addrinfo *res; // A pointer to the resulting address list
1007 memset(&hints, 0, sizeof hints);
1008 hints.ai_family = AF_UNSPEC; // Either IPv4 or IPv6 (AF_INET, AF_INET6)
1009 hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP)
1011 // Populate address information
1012 status = getaddrinfo(ip, // e.g. "www.example.com" or IP
1013 port, // e.g. "http" or port number
1014 &hints, // e.g. SOCK_STREAM/SOCK_DGRAM
1015 &res // The struct to populate
1019 if (status != 0) TRACELOG(LOG_WARNING, "Failed to get resolve host %s:%s: %s", ip, port, gai_strerror(errno));
1020 else TRACELOG(LOG_DEBUG, "Resolving... %s::%s", ip, port);
1022 // Attempt to resolve network byte order ip to hostname
1023 switch (res->ai_family)
1027 status = getnameinfo(&*((struct sockaddr *)res->ai_addr),
1028 sizeof(*((struct sockaddr_in *)res->ai_addr)),
1029 host, NI_MAXHOST, serv, NI_MAXSERV, flags);
1034 status = getnameinfo(&*((struct sockaddr_in6 *)res->ai_addr), // TODO.
1035 sizeof(*((struct sockaddr_in6 *)res->ai_addr)),
1036 host, NI_MAXHOST, serv, NI_MAXSERV, flags);
1042 if (status != 0) TRACELOG(LOG_WARNING, "Failed to resolve ip %s: %s", ip, SocketGetLastErrorString());
1043 else TRACELOG(LOG_DEBUG, "Successfully resolved %s::%s to %s", ip, port, host);
1045 // Free the pointer to the data returned by addrinfo
1049 // Protocol-independent translation from an ANSI host name to an address
1052 // const char* address = "127.0.0.1" (local address)
1053 // const char* port = "80"
1056 // const char* address - A pointer to a NULL-terminated ANSI string that contains a host (node) name or a numeric host address string.
1057 // const char* service - A pointer to a NULL-terminated ANSI string that contains either a service name or port number represented as a string.
1060 // The total amount of addresses found, -1 on error
1062 int ResolveHost(const char *address, const char *service, int addressType, int flags, AddressInformation *outAddr)
1065 int status; // Status value to return (0) is success
1066 struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
1067 struct addrinfo *res; // will point to the results
1068 struct addrinfo *iterator;
1069 assert(((address != NULL || address != 0) || (service != NULL || service != 0)));
1070 assert(((addressType == AF_INET) || (addressType == AF_INET6) || (addressType == AF_UNSPEC)));
1073 memset(&hints, 0, sizeof hints);
1074 hints.ai_family = addressType; // Either IPv4 or IPv6 (ADDRESS_TYPE_IPV4, ADDRESS_TYPE_IPV6)
1075 hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP)
1076 hints.ai_flags = flags;
1077 assert((hints.ai_addrlen == 0) || (hints.ai_addrlen == 0));
1078 assert((hints.ai_canonname == 0) || (hints.ai_canonname == 0));
1079 assert((hints.ai_addr == 0) || (hints.ai_addr == 0));
1080 assert((hints.ai_next == 0) || (hints.ai_next == 0));
1082 // When the address is NULL, populate the IP for me
1083 if (address == NULL)
1085 if ((hints.ai_flags & AI_PASSIVE) == 0) hints.ai_flags |= AI_PASSIVE;
1088 TRACELOG(LOG_INFO, "Resolving host...");
1090 // Populate address information
1091 status = getaddrinfo(address, // e.g. "www.example.com" or IP
1092 service, // e.g. "http" or port number
1093 &hints, // e.g. SOCK_STREAM/SOCK_DGRAM
1094 &res // The struct to populate
1100 int error = SocketGetLastError();
1101 SocketSetLastError(0);
1102 TRACELOG(LOG_WARNING, "Failed to get resolve host: %s", SocketErrorCodeToString(error));
1105 else TRACELOG(LOG_INFO, "Successfully resolved host %s:%s", address, service);
1107 // Calculate the size of the address information list
1109 for (iterator = res; iterator != NULL; iterator = iterator->ai_next) size++;
1111 // Validate the size is > 0, otherwise return
1114 TRACELOG(LOG_WARNING, "Error, no addresses found.");
1118 // If not address list was allocated, allocate it dynamically with the known address size
1119 if (outAddr == NULL) outAddr = (AddressInformation *)RNET_MALLOC(size * sizeof(AddressInformation));
1121 // Dynamically allocate an array of address information structs
1122 if (outAddr != NULL)
1125 for (i = 0; i < size; ++i)
1127 outAddr[i] = LoadAddress();
1128 if (outAddr[i] == NULL)
1135 if (i != size) outAddr = NULL;
1139 TRACELOG(LOG_WARNING, "Error, failed to dynamically allocate memory for the address list");
1143 // Copy all the address information from res into outAddrList
1145 for (iterator = res; iterator != NULL; iterator = iterator->ai_next)
1149 outAddr[i]->addr.ai_flags = iterator->ai_flags;
1150 outAddr[i]->addr.ai_family = iterator->ai_family;
1151 outAddr[i]->addr.ai_socktype = iterator->ai_socktype;
1152 outAddr[i]->addr.ai_protocol = iterator->ai_protocol;
1153 outAddr[i]->addr.ai_addrlen = iterator->ai_addrlen;
1154 *outAddr[i]->addr.ai_addr = *iterator->ai_addr;
1155 #if NET_DEBUG_ENABLED
1156 TRACELOG(LOG_DEBUG, "GetAddressInformation");
1157 TRACELOG(LOG_DEBUG, "\tFlags: 0x%x", iterator->ai_flags);
1158 //PrintSocket(outAddr[i]->addr.ai_addr, outAddr[i]->addr.ai_family, outAddr[i]->addr.ai_socktype, outAddr[i]->addr.ai_protocol);
1159 TRACELOG(LOG_DEBUG, "Length of this sockaddr: %d", outAddr[i]->addr.ai_addrlen);
1160 TRACELOG(LOG_DEBUG, "Canonical name: %s", iterator->ai_canonname);
1166 // Free the pointer to the data returned by addrinfo
1169 // Return the total count of addresses found
1173 // This here is the bread and butter of the socket API, This function will
1174 // attempt to open a socket, bind and listen to it based on the config passed in
1176 // SocketConfig* config - Configuration for which socket to open
1177 // SocketResult* result - The results of this function (if any, including errors)
1180 // SocketConfig server_config = { SocketConfig client_config = {
1181 // .host = "127.0.0.1", .host = "127.0.0.1",
1182 // .port = 8080, .port = 8080,
1183 // .server = true, };
1184 // .nonblocking = true,
1186 // SocketResult server_res; SocketResult client_res;
1187 bool SocketCreate(SocketConfig *config, SocketResult *result)
1189 // Socket creation result
1190 bool success = true;
1192 // Make sure we've not received a null config or result pointer
1193 if (config == NULL || result == NULL) return (success = false);
1195 // Set the defaults based on the config
1196 if (!SocketSetDefaults(config))
1198 TRACELOG(LOG_WARNING, "Configuration Error.");
1203 // Create the socket
1204 if (CreateSocket(config, result))
1206 if (config->nonblocking) SocketSetNonBlocking(result->socket);
1207 else SocketSetBlocking(result->socket);
1209 else success = false;
1215 // Bind a socket to a local address
1216 // Note: The bind function is required on an unconnected socket before subsequent calls to the listen function.
1217 bool SocketBind(SocketConfig *config, SocketResult *result)
1219 bool success = false;
1220 result->status = RESULT_FAILURE;
1221 struct sockaddr_storage *sock_addr = NULL;
1223 // Don't bind to a socket that isn't configured as a server
1224 if (!IsSocketValid(result->socket) || !config->server)
1226 TRACELOG(LOG_WARNING, Cannot bind to socket marked as \"Client\" in SocketConfig.");
1231 if (result->socket->isIPv6) sock_addr = (struct sockaddr_storage *)&result->socket->addripv6->address;
1232 else sock_addr = (struct sockaddr_storage *)&result->socket->addripv4->address;
1234 if (sock_addr != NULL)
1236 if (bind(result->socket->channel, (struct sockaddr *)sock_addr, sizeof(*sock_addr)) != SOCKET_ERROR)
1238 TRACELOG(LOG_INFO, "Successfully bound socket.");
1243 result->socket->status = SocketGetLastError();
1244 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status));
1245 SocketSetLastError(0);
1251 // Was the bind a success?
1254 result->status = RESULT_SUCCESS;
1255 result->socket->ready = 0;
1256 result->socket->status = 0;
1257 socklen_t sock_len = sizeof(*sock_addr);
1259 if (getsockname(result->socket->channel, (struct sockaddr *)sock_addr, &sock_len) < 0)
1261 TRACELOG(LOG_WARNING, "Couldn't get socket address");
1265 struct sockaddr_in *s = (struct sockaddr_in *)sock_addr;
1266 // result->socket->address.host = s->sin_addr.s_addr;
1267 // result->socket->address.port = s->sin_port;
1269 result->socket->addripv4 = (struct _SocketAddressIPv4 *)RNET_MALLOC(sizeof(*result->socket->addripv4));
1271 if (result->socket->addripv4 != NULL) memset(result->socket->addripv4, 0, sizeof(*result->socket->addripv4));
1273 memcpy(&result->socket->addripv4->address, (struct sockaddr_in *)&s->sin_addr, sizeof(struct sockaddr_in));
1279 // Listens (and queues) incoming connections requests for a bound port.
1280 bool SocketListen(SocketConfig *config, SocketResult *result)
1282 bool success = false;
1283 result->status = RESULT_FAILURE;
1285 // Don't bind to a socket that isn't configured as a server
1286 if (!IsSocketValid(result->socket) || !config->server)
1288 TRACELOG(LOG_WARNING, "Cannot listen on socket marked as \"Client\" in SocketConfig.");
1293 // Don't listen on UDP sockets
1294 if (!(config->type == SOCKET_UDP))
1296 if (listen(result->socket->channel, config->backlog_size) != SOCKET_ERROR)
1298 TRACELOG(LOG_INFO, "Started listening on socket...");
1304 result->socket->status = SocketGetLastError();
1305 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status));
1306 SocketSetLastError(0);
1311 TRACELOG(LOG_WARNING, "Cannot listen on socket marked as \"UDP\" (datagram) in SocketConfig.");
1316 // Was the listen a success?
1319 result->status = RESULT_SUCCESS;
1320 result->socket->ready = 0;
1321 result->socket->status = 0;
1327 // Connect the socket to the destination specified by "host" and "port" in SocketConfig
1328 bool SocketConnect(SocketConfig *config, SocketResult *result)
1330 bool success = true;
1331 result->status = RESULT_FAILURE;
1333 // Only bind to sockets marked as server
1336 TRACELOG(LOG_WARNING, "Cannot connect to socket marked as \"Server\" in SocketConfig.");
1341 if (IsIPv4Address(config->host))
1343 struct sockaddr_in ip4addr;
1344 ip4addr.sin_family = AF_INET;
1345 unsigned long hport;
1346 hport = strtoul(config->port, NULL, 0);
1347 ip4addr.sin_port = (unsigned short)(hport);
1349 // TODO: Changed the code to avoid the usage of inet_pton and inet_ntop replacing them with getnameinfo (that should have a better support on windows).
1351 //inet_pton(AF_INET, config->host, &ip4addr.sin_addr);
1352 int connect_result = connect(result->socket->channel, (struct sockaddr *)&ip4addr, sizeof(ip4addr));
1354 if (connect_result == SOCKET_ERROR)
1356 result->socket->status = SocketGetLastError();
1357 SocketSetLastError(0);
1359 switch (result->socket->status)
1361 case WSAEWOULDBLOCK: success = true; break;
1364 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status));
1371 TRACELOG(LOG_INFO, "Successfully connected to socket.");
1377 if (IsIPv6Address(config->host))
1379 struct sockaddr_in6 ip6addr;
1380 ip6addr.sin6_family = AF_INET6;
1381 unsigned long hport;
1382 hport = strtoul(config->port, NULL, 0);
1383 ip6addr.sin6_port = htons((unsigned short)hport);
1384 //inet_pton(AF_INET6, config->host, &ip6addr.sin6_addr); // TODO.
1385 int connect_result = connect(result->socket->channel, (struct sockaddr *)&ip6addr, sizeof(ip6addr));
1387 if (connect_result == SOCKET_ERROR)
1389 result->socket->status = SocketGetLastError();
1390 SocketSetLastError(0);
1392 switch (result->socket->status)
1394 case WSAEWOULDBLOCK: success = true; break;
1397 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status));
1404 TRACELOG(LOG_INFO, "Successfully connected to socket.");
1413 result->status = RESULT_SUCCESS;
1414 result->socket->ready = 0;
1415 result->socket->status = 0;
1421 // Closes an existing socket
1423 // SocketChannel socket - The id of the socket to close
1424 void SocketClose(Socket *sock)
1428 if (sock->channel != INVALID_SOCKET) closesocket(sock->channel);
1432 // Returns the sockaddress for a specific socket in a generic storage struct
1433 SocketAddressStorage SocketGetPeerAddress(Socket *sock)
1437 if (sock->isServer) return NULL;
1438 if (sock->isIPv6) return sock->addripv6;
1439 else return sock->addripv4;
1445 // Return the address-type appropriate host portion of a socket address
1446 const char *GetSocketAddressHost(SocketAddressStorage storage)
1448 assert(storage->address.ss_family == AF_INET || storage->address.ss_family == AF_INET6);
1449 return SocketAddressToString((struct sockaddr_storage *)storage);
1452 // Return the address-type appropriate port(service) portion of a socket address
1453 short GetSocketAddressPort(SocketAddressStorage storage)
1455 //return ntohs(GetSocketPortPtr(storage)); // TODO.
1460 // The accept function permits an incoming connection attempt on a socket.
1462 // SocketChannel listener - The socket to listen for incoming connections on (i.e. server)
1463 // SocketResult* out - The result of this function (if any, including errors)
1467 // SocketResult connection;
1468 // bool connected = false;
1471 // if (SocketAccept(server_res.socket.channel, &connection))
1473 // connected = true;
1476 Socket *SocketAccept(Socket *server, SocketConfig *config)
1478 if (!server->isServer || server->type == SOCKET_UDP) return NULL;
1480 struct sockaddr_storage sock_addr;
1481 socklen_t sock_alen;
1482 Socket *sock = LoadSocket();
1484 sock_alen = sizeof(sock_addr);
1485 sock->channel = accept(server->channel, (struct sockaddr *)&sock_addr, &sock_alen);
1487 if (sock->channel == INVALID_SOCKET)
1489 sock->status = SocketGetLastError();
1490 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status));
1491 SocketSetLastError(0);
1497 (config->nonblocking) ? SocketSetNonBlocking(sock) : SocketSetBlocking(sock);
1498 sock->isServer = false;
1500 sock->type = server->type;
1502 switch (sock_addr.ss_family)
1506 struct sockaddr_in *s = ((struct sockaddr_in *)&sock_addr);
1507 sock->addripv4 = (struct _SocketAddressIPv4 *)RNET_MALLOC(sizeof(*sock->addripv4));
1509 if (sock->addripv4 != NULL)
1511 memset(sock->addripv4, 0, sizeof(*sock->addripv4));
1512 memcpy(&sock->addripv4->address, (struct sockaddr_in *)&s->sin_addr, sizeof(struct sockaddr_in));
1513 TRACELOG(LOG_INFO, "Server: Got connection from %s::%hu", SocketAddressToString((struct sockaddr_storage *)s), ntohs(sock->addripv4->address.sin_port));
1518 struct sockaddr_in6 *s = ((struct sockaddr_in6 *)&sock_addr);
1519 sock->addripv6 = (struct _SocketAddressIPv6 *)RNET_MALLOC(sizeof(*sock->addripv6));
1521 if (sock->addripv6 != NULL)
1523 memset(sock->addripv6, 0, sizeof(*sock->addripv6));
1524 memcpy(&sock->addripv6->address, (struct sockaddr_in6 *)&s->sin6_addr, sizeof(struct sockaddr_in6));
1525 TRACELOG(LOG_INFO, "Server: Got connection from %s::%hu", SocketAddressToString((struct sockaddr_storage *)s), ntohs(sock->addripv6->address.sin6_port));
1533 // Verify that the channel is in the valid range
1534 static int ValidChannel(int channel)
1536 if ((channel < 0) || (channel >= SOCKET_MAX_UDPCHANNELS))
1538 TRACELOG(LOG_WARNING, "Invalid channel");
1545 // Set the socket channel
1546 int SocketSetChannel(Socket *socket, int channel, const IPAddress *address)
1548 struct UDPChannel *binding;
1552 TRACELOG(LOG_WARNING, "Passed a NULL socket");
1558 for (channel = 0; channel < SOCKET_MAX_UDPCHANNELS; ++channel)
1560 binding = &socket->binding[channel];
1561 if (binding->numbound < SOCKET_MAX_UDPADDRESSES) break;
1566 if (!ValidChannel(channel)) return (-1);
1568 binding = &socket->binding[channel];
1571 if (binding->numbound == SOCKET_MAX_UDPADDRESSES)
1573 TRACELOG(LOG_WARNING, "No room for new addresses");
1577 binding->address[binding->numbound++] = *address;
1582 // Remove the socket channel
1583 void SocketUnsetChannel(Socket *socket, int channel)
1585 if ((channel >= 0) && (channel < SOCKET_MAX_UDPCHANNELS)) socket->binding[channel].numbound = 0;
1588 /* Allocate/free a single UDP packet 'size' bytes long.
1589 The new packet is returned, or NULL if the function ran out of memory.
1591 SocketDataPacket *AllocPacket(int size)
1593 SocketDataPacket *packet = (SocketDataPacket *)RNET_MALLOC(sizeof(*packet));
1598 packet->maxlen = size;
1599 packet->data = (uint8_t *)RNET_MALLOC(size);
1600 if (packet->data != NULL)
1615 int ResizePacket(SocketDataPacket *packet, int newsize)
1617 uint8_t *newdata = (uint8_t *)RNET_MALLOC(newsize);
1619 if (newdata != NULL)
1621 RNET_FREE(packet->data);
1622 packet->data = newdata;
1623 packet->maxlen = newsize;
1626 return (packet->maxlen);
1629 void FreePacket(SocketDataPacket *packet)
1633 RNET_FREE(packet->data);
1638 // Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets, each 'size' bytes long.
1639 // A pointer to the packet array is returned, or NULL if the function ran out of memory.
1640 SocketDataPacket **AllocPacketList(int howmany, int size)
1642 SocketDataPacket **packetV = (SocketDataPacket **)RNET_MALLOC((howmany + 1) * sizeof(*packetV));
1644 if (packetV != NULL)
1647 for (i = 0; i < howmany; ++i)
1649 packetV[i] = AllocPacket(size);
1650 if (packetV[i] == NULL)
1659 FreePacketList(packetV);
1667 void FreePacketList(SocketDataPacket **packetV)
1671 for (int i = 0; packetV[i]; ++i) FreePacket(packetV[i]);
1676 // Send 'len' bytes of 'data' over the non-server socket 'sock'
1677 int SocketSend(Socket *sock, const void *datap, int length)
1683 const unsigned char *data = (const unsigned char *)datap;
1685 // Server sockets are for accepting connections only
1688 TRACELOG(LOG_WARNING, "Cannot send information on a server socket");
1692 // Which socket are we trying to send data on
1697 SocketSetLastError(0);
1700 length = send(sock->channel, (const char *)data, left, 0);
1707 } while ((left > 0) && // While we still have bytes left to send
1708 ((length > 0) || // The amount of bytes we actually sent is > 0
1709 (SocketGetLastError() == WSAEINTR)) // The socket was interupted
1712 if (length == SOCKET_ERROR)
1714 sock->status = SocketGetLastError();
1715 TRACELOG(LOG_DEBUG, "Socket Error: %s", SocketErrorCodeToString(sock->status));
1716 SocketSetLastError(0);
1718 else TRACELOG(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, sent);
1724 SocketSetLastError(0);
1726 if (sock->isIPv6) status = sendto(sock->channel, (const char *)data, left, 0, (struct sockaddr *)&sock->addripv6->address, sizeof(sock->addripv6->address));
1727 else status = sendto(sock->channel, (const char *)data, left, 0, (struct sockaddr *)&sock->addripv4->address, sizeof(sock->addripv4->address));
1733 TRACELOG(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, status);
1737 sock->status = SocketGetLastError();
1738 TRACELOG(LOG_DEBUG, "Socket Error: %s", SocketGetLastErrorString(sock->status));
1739 SocketSetLastError(0);
1751 // Receive up to 'maxlen' bytes of data over the non-server socket 'sock',
1752 // and store them in the buffer pointed to by 'data'.
1753 // This function returns the actual amount of data received. If the return
1754 // value is less than or equal to zero, then either the remote connection was
1755 // closed, or an unknown socket error occurred.
1756 int SocketReceive(Socket *sock, void *data, int maxlen)
1762 struct sockaddr_storage sock_addr;
1763 //char ip[INET6_ADDRSTRLEN];
1765 // Server sockets are for accepting connections only
1766 if (sock->isServer && (sock->type == SOCKET_TCP))
1768 sock->status = SocketGetLastError();
1769 TRACELOG(LOG_DEBUG, "Socket Error: %s", "Server sockets cannot be used to receive data");
1770 SocketSetLastError(0);
1774 // Which socket are we trying to send data on
1779 SocketSetLastError(0);
1782 len = recv(sock->channel, (char *)data, maxlen, 0);
1783 } while (SocketGetLastError() == WSAEINTR);
1787 // Who sent the packet?
1788 if (sock->type == SOCKET_UDP)
1790 //TRACELOG(LOG_DEBUG, "Received data from: %s", inet_ntop(sock_addr.ss_family, GetSocketAddressPtr((struct sockaddr *)&sock_addr), ip, sizeof(ip)));
1793 ((unsigned char *)data)[len] = '\0'; // Add null terminating character to the end of the stream
1794 TRACELOG(LOG_DEBUG, "Received \"%s\" (%d bytes)", data, len);
1802 SocketSetLastError(0);
1803 sock_len = sizeof(sock_addr);
1804 status = recvfrom(sock->channel, // The receving channel
1805 data, // A pointer to the data buffer to fill
1806 maxlen, // The max length of the data to fill
1808 (struct sockaddr *)&sock_addr, // The address of the recevied data
1809 &sock_len // The length of the received data address
1812 if (status >= 0) ++numrecv;
1815 sock->status = SocketGetLastError();
1817 switch (sock->status)
1819 case WSAEWOULDBLOCK: break;
1820 default: TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); break;
1823 SocketSetLastError(0);
1836 // Does the socket have it's 'ready' flag set?
1837 bool IsSocketReady(Socket *sock)
1839 return (sock != NULL) && (sock->ready);
1842 // Check if the socket is considered connected
1843 bool IsSocketConnected(Socket *sock)
1848 FD_SET(sock->channel, &writefds);
1849 struct timeval timeout;
1851 timeout.tv_usec = 1000000000UL;
1852 int total = select(0, NULL, &writefds, NULL, &timeout);
1856 sock->status = SocketGetLastError();
1857 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status));
1858 SocketSetLastError(0);
1860 else if (total == 0) return false; // Timeout
1861 else if (FD_ISSET(sock->channel, &writefds)) return true;
1869 // Allocate and return a SocketResult struct
1870 SocketResult *LoadSocketResult(void)
1872 struct SocketResult *res = (struct SocketResult *)RNET_MALLOC(sizeof(*res));
1876 memset(res, 0, sizeof(*res));
1877 if ((res->socket = LoadSocket()) == NULL)
1887 // Free an allocated SocketResult
1888 void UnloadSocketResult(SocketResult **result)
1890 if (*result != NULL)
1892 if ((*result)->socket != NULL) UnloadSocket(&((*result)->socket));
1899 // Allocate a Socket
1900 Socket *LoadSocket(void)
1902 struct Socket *sock;
1903 sock = (Socket *)RNET_MALLOC(sizeof(*sock));
1905 if (sock != NULL) memset(sock, 0, sizeof(*sock));
1908 TRACELOG(LOG_WARNING, "Ran out of memory attempting to allocate a socket");
1917 // Free an allocated Socket
1918 void UnloadSocket(Socket **sock)
1927 // Allocate a SocketSet
1928 SocketSet *LoadSocketSet(int max)
1930 struct SocketSet *set = (struct SocketSet *)RNET_MALLOC(sizeof(*set));
1934 set->numsockets = 0;
1935 set->maxsockets = max;
1936 set->sockets = (struct Socket **)RNET_MALLOC(max * sizeof(*set->sockets));
1937 if (set->sockets != NULL)
1939 for (int i = 0; i < max; ++i) set->sockets[i] = NULL;
1951 // Free an allocated SocketSet
1952 void UnloadSocketSet(SocketSet *set)
1956 RNET_FREE(set->sockets);
1961 // Add a Socket "sock" to the SocketSet "set"
1962 int AddSocket(SocketSet *set, Socket *sock)
1966 if (set->numsockets == set->maxsockets)
1968 TRACELOG(LOG_DEBUG, "Socket Error: %s", "SocketSet is full");
1969 SocketSetLastError(0);
1972 set->sockets[set->numsockets++] = (struct Socket *)sock;
1976 TRACELOG(LOG_DEBUG, "Socket Error: %s", "Socket was null");
1977 SocketSetLastError(0);
1981 return (set->numsockets);
1984 // Remove a Socket "sock" to the SocketSet "set"
1985 int RemoveSocket(SocketSet *set, Socket *sock)
1990 for (i = 0; i < set->numsockets; ++i)
1992 if (set->sockets[i] == (struct Socket *)sock) break;
1995 if (i == set->numsockets)
1997 TRACELOG(LOG_DEBUG, "Socket Error: %s", "Socket not found");
1998 SocketSetLastError(0);
2003 for (; i < set->numsockets; ++i) set->sockets[i] = set->sockets[i + 1];
2006 return (set->numsockets);
2009 // Check the sockets in the socket set for pending information
2010 int CheckSockets(SocketSet *set, unsigned int timeout)
2018 /* Find the largest file descriptor */
2020 for (i = set->numsockets - 1; i >= 0; --i)
2022 if (set->sockets[i]->channel > maxfd)
2024 maxfd = set->sockets[i]->channel;
2028 // Check the file descriptors for available data
2031 SocketSetLastError(0);
2033 // Set up the mask of file descriptors
2035 for (i = set->numsockets - 1; i >= 0; --i)
2037 FD_SET(set->sockets[i]->channel, &mask);
2038 } // Set up the timeout
2040 tv.tv_sec = timeout / 1000;
2041 tv.tv_usec = (timeout % 1000) * 1000;
2044 retval = select(maxfd + 1, &mask, NULL, NULL, &tv);
2045 } while (SocketGetLastError() == WSAEINTR);
2047 // Mark all file descriptors ready that have data available
2050 for (i = set->numsockets - 1; i >= 0; --i)
2052 if (FD_ISSET(set->sockets[i]->channel, &mask)) set->sockets[i]->ready = 1;
2059 // Allocate an AddressInformation
2060 AddressInformation LoadAddress(void)
2062 AddressInformation addressInfo = NULL;
2063 addressInfo = (AddressInformation)RNET_CALLOC(1, sizeof(*addressInfo));
2065 if (addressInfo != NULL)
2067 addressInfo->addr.ai_addr = (struct sockaddr *)RNET_CALLOC(1, sizeof(struct sockaddr));
2068 if (addressInfo->addr.ai_addr == NULL) TRACELOG(LOG_WARNING, "Failed to allocate memory for \"struct sockaddr\"");
2070 else TRACELOG(LOG_WARNING, "Failed to allocate memory for \"struct AddressInformation\"");
2075 // Free an AddressInformation struct
2076 void UnloadAddress(AddressInformation *addressInfo)
2078 if (*addressInfo != NULL)
2080 if ((*addressInfo)->addr.ai_addr != NULL)
2082 RNET_FREE((*addressInfo)->addr.ai_addr);
2083 (*addressInfo)->addr.ai_addr = NULL;
2086 RNET_FREE(*addressInfo);
2087 *addressInfo = NULL;
2091 // Allocate a list of AddressInformation
2092 AddressInformation *LoadAddressList(int size)
2094 AddressInformation *addr;
2095 addr = (AddressInformation *)RNET_MALLOC(size * sizeof(AddressInformation));
2099 // Opaque datatype accessor addrinfo->ai_family
2100 int GetAddressFamily(AddressInformation address)
2102 return address->addr.ai_family;
2105 // Opaque datatype accessor addrinfo->ai_socktype
2106 int GetAddressSocketType(AddressInformation address)
2108 return address->addr.ai_socktype;
2111 // Opaque datatype accessor addrinfo->ai_protocol
2112 int GetAddressProtocol(AddressInformation address)
2114 return address->addr.ai_protocol;
2117 // Opaque datatype accessor addrinfo->ai_canonname
2118 char *GetAddressCanonName(AddressInformation address)
2120 return address->addr.ai_canonname;
2123 // Opaque datatype accessor addrinfo->ai_addr
2124 char *GetAddressHostAndPort(AddressInformation address, char *outhost, unsigned short *outport)
2126 //char *ip[INET6_ADDRSTRLEN];
2127 char *result = NULL;
2128 struct sockaddr_storage *storage = (struct sockaddr_storage *)address->addr.ai_addr;
2130 switch (storage->ss_family)
2134 struct sockaddr_in *s = ((struct sockaddr_in *)address->addr.ai_addr);
2135 //result = inet_ntop(AF_INET, &s->sin_addr, ip, INET_ADDRSTRLEN); // TODO.
2136 *outport = ntohs(s->sin_port);
2140 struct sockaddr_in6 *s = ((struct sockaddr_in6 *)address->addr.ai_addr);
2141 //result = inet_ntop(AF_INET6, &s->sin6_addr, ip, INET6_ADDRSTRLEN); // TODO.
2142 *outport = ntohs(s->sin6_port);
2149 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(SocketGetLastError()));
2150 SocketSetLastError(0);
2154 strcpy(outhost, result);
2160 void PacketSend(Packet *packet)
2162 TRACELOG(LOG_INFO, "Sending packet (%s) with size %d\n", packet->data, packet->size);
2166 void PacketReceive(Packet *packet)
2168 TRACELOG(LOG_INFO, "Receiving packet (%s) with size %d\n", packet->data, packet->size);
2172 void PacketWrite16(Packet *packet, uint16_t value)
2174 TRACELOG(LOG_INFO, "Original: 0x%04" PRIX16 " - %" PRIu16 "\n", value, value);
2175 uint8_t *data = packet->data + packet->offs;
2176 *data++ = (uint8_t)(value >> 8);
2177 *data++ = (uint8_t)(value);
2178 packet->size += sizeof(uint16_t);
2179 packet->offs += sizeof(uint16_t);
2180 TRACELOG(LOG_INFO, "Network: 0x%04" PRIX16 " - %" PRIu16 "\n", (uint16_t) *data, (uint16_t) *data);
2184 void PacketWrite32(Packet *packet, uint32_t value)
2186 TRACELOG(LOG_INFO, "Original: 0x%08" PRIX32 " - %" PRIu32 "\n", value, value);
2187 uint8_t *data = packet->data + packet->offs;
2188 *data++ = (uint8_t)(value >> 24);
2189 *data++ = (uint8_t)(value >> 16);
2190 *data++ = (uint8_t)(value >> 8);
2191 *data++ = (uint8_t)(value);
2192 packet->size += sizeof(uint32_t);
2193 packet->offs += sizeof(uint32_t);
2195 TRACELOG(LOG_INFO, "Network: 0x%08" PRIX32 " - %" PRIu32 "\n",
2196 (uint32_t)(((intptr_t) packet->data) - packet->offs),
2197 (uint32_t)(((intptr_t) packet->data) - packet->offs));
2201 void PacketWrite64(Packet *packet, uint64_t value)
2203 TRACELOG(LOG_INFO, "Original: 0x%016" PRIX64 " - %" PRIu64 "\n", value, value);
2205 uint8_t *data = packet->data + packet->offs;
2206 *data++ = (uint8_t)(value >> 56);
2207 *data++ = (uint8_t)(value >> 48);
2208 *data++ = (uint8_t)(value >> 40);
2209 *data++ = (uint8_t)(value >> 32);
2210 *data++ = (uint8_t)(value >> 24);
2211 *data++ = (uint8_t)(value >> 16);
2212 *data++ = (uint8_t)(value >> 8);
2213 *data++ = (uint8_t)(value);
2214 packet->size += sizeof(uint64_t);
2215 packet->offs += sizeof(uint64_t);
2217 TRACELOG(LOG_INFO, "Network: 0x%016" PRIX64 " - %" PRIu64 "\n", (uint64_t)(packet->data - packet->offs), (uint64_t)(packet->data - packet->offs));
2221 uint16_t PacketRead16(Packet *packet)
2223 uint8_t *data = packet->data + packet->offs;
2224 packet->size += sizeof(uint16_t);
2225 packet->offs += sizeof(uint16_t);
2226 uint16_t value = ((uint16_t) data[0] << 8) | data[1];
2227 TRACELOG(LOG_INFO, "Original: 0x%04" PRIX16 " - %" PRIu16 "\n", value, value);
2233 uint32_t PacketRead32(Packet *packet)
2235 uint8_t *data = packet->data + packet->offs;
2236 packet->size += sizeof(uint32_t);
2237 packet->offs += sizeof(uint32_t);
2238 uint32_t value = ((uint32_t) data[0] << 24) | ((uint32_t) data[1] << 16) | ((uint32_t) data[2] << 8) | data[3];
2239 TRACELOG(LOG_INFO, "Original: 0x%08" PRIX32 " - %" PRIu32 "\n", value, value);
2245 uint64_t PacketRead64(Packet *packet)
2247 uint8_t *data = packet->data + packet->offs;
2248 packet->size += sizeof(uint64_t);
2249 packet->offs += sizeof(uint64_t);
2250 uint64_t value = ((uint64_t) data[0] << 56) | ((uint64_t) data[1] << 48) | ((uint64_t) data[2] << 40) | ((uint64_t) data[3] << 32) | ((uint64_t) data[4] << 24) | ((uint64_t) data[5] << 16) | ((uint64_t) data[6] << 8) | data[7];
2251 TRACELOG(LOG_INFO, "Original: 0x%016" PRIX64 " - %" PRIu64 "\n", value, value);
2256 #endif // RNET_IMPLEMENTATION