]> git.sesse.net Git - pistorm/blob - raylib/rnet.h
Add Meson build files.
[pistorm] / raylib / rnet.h
1 /**********************************************************************************************
2 *
3 *   rnet - A simple and easy-to-use network module for raylib
4 *
5 *   FEATURES:
6 *       - Provides a simple and (hopefully) easy to use wrapper around the Berkeley socket API
7 *
8 *   INSPIRED BY:
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
14 *
15 *   CONTRIBUTORS:
16 *       Jak Barnes (github: @syphonx) (Feb. 2019) - Initial version
17 *
18 *
19 *   LICENSE: zlib/libpng
20 *
21 *   Copyright (c) 2019-2020 Jak Barnes (@syphonx) and Ramon Santamaria (@raysan5)
22 *
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.
25 *
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:
28 *
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.
32 *
33 *     2. Altered source versions must be plainly marked as such, and must not be misrepresented
34 *     as being the original software.
35 *
36 *     3. This notice may not be removed or altered from any source distribution.
37 *
38 **********************************************************************************************/
39
40 #ifndef RNET_H
41 #define RNET_H
42
43 #include <limits.h>         // Required for limits
44 #include <inttypes.h>       // Required for platform type sizes
45
46 //----------------------------------------------------------------------------------
47 // Defines and Macros
48 //----------------------------------------------------------------------------------
49
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
91 #define MMNOSOUND
92
93 // Allow custom memory allocators
94 #ifndef RNET_MALLOC
95     #define RNET_MALLOC(sz)       malloc(sz)
96 #endif
97 #ifndef RNET_CALLOC
98     #define RNET_CALLOC(n,sz)     calloc(n,sz)
99 #endif
100 #ifndef RNET_FREE
101     #define RNET_FREE(p)          free(p)
102 #endif
103
104 //----------------------------------------------------------------------------------
105 // Platform type definitions
106 // From: https://github.com/DFHack/clsocket/blob/master/src/Host.h
107 //----------------------------------------------------------------------------------
108
109 #ifdef WIN32
110 typedef int socklen_t;
111 #endif
112
113 #ifndef RESULT_SUCCESS
114 #    define RESULT_SUCCESS 0
115 #endif // RESULT_SUCCESS
116
117 #ifndef RESULT_FAILURE
118 #    define RESULT_FAILURE 1
119 #endif // RESULT_FAILURE
120
121 #ifndef htonll
122 #    ifdef _BIG_ENDIAN
123 #        define htonll(x) (x)
124 #        define ntohll(x) (x)
125 #    else
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
129 #endif     // htonll
130
131 //----------------------------------------------------------------------------------
132 // Platform specific network includes
133 // From: https://github.com/SDL-mirror/SDL_net/blob/master/SDLnetsys.h
134 //----------------------------------------------------------------------------------
135
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>
142     #include <io.h>
143     #define IPTOS_LOWDELAY 0x10
144 #else               // Unix
145     #include <sys/types.h>
146     #include <fcntl.h>
147     #include <netinet/in.h>
148     #include <sys/ioctl.h>
149     #include <sys/time.h>
150     #include <unistd.h>
151     #include <net/if.h>
152     #include <netdb.h>
153     #include <netinet/tcp.h>
154     #include <sys/socket.h>
155     #include <arpa/inet.h>
156 #endif
157
158 #ifndef INVALID_SOCKET
159     #define INVALID_SOCKET ~(0)
160 #endif
161
162 #ifndef __USE_W32_SOCKETS
163     #define closesocket close
164     #define SOCKET int
165     #define INVALID_SOCKET -1
166     #define SOCKET_ERROR -1
167 #endif
168
169 #ifdef __USE_W32_SOCKETS
170     #ifndef EINTR
171         #define EINTR WSAEINTR
172     #endif
173 #endif
174
175 //----------------------------------------------------------------------------------
176 // Module defines
177 //----------------------------------------------------------------------------------
178
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
185
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
194
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
200
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
208
209 // Address resolution related defines
210 #if defined(_WIN32)
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
227 #endif
228
229 //----------------------------------------------------------------------------------
230 // Types and Structures Definition
231 //----------------------------------------------------------------------------------
232
233 // Boolean type
234 #ifdef _WIN32
235     #include <stdbool.h>
236 #else
237 #if defined(__STDC__) && __STDC_VERSION__ >= 199901L
238     #include <stdbool.h>
239 #elif !defined(__cplusplus) && !defined(bool)
240     typedef enum { false, true } bool;
241 #endif
242 #endif
243
244 typedef enum {
245     SOCKET_TCP = 0,             // SOCK_STREAM
246     SOCKET_UDP = 1              // SOCK_DGRAM
247 } SocketType;
248
249 // Network typedefs
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;
256
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
261 } IPAddress;
262
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
266 } UDPChannel;
267
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
273 } SocketOpt;
274
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?
281     
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)
285
286     struct UDPChannel binding[SOCKET_MAX_UDPCHANNELS]; // The amount of channels (if UDP) this socket is bound to
287 } Socket;
288
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];
298 } SocketConfig;
299
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
307 } SocketDataPacket;
308
309 // Result from calling open with a given config
310 typedef struct SocketResult {
311     int status;                 // Socket result state
312     Socket *socket;             // Socket ref
313 } SocketResult;
314
315 typedef struct SocketSet {
316     int numsockets;             // Socket set count
317     int maxsockets;             // Socket set max
318     struct Socket **sockets;    // Sockets array
319 } SocketSet;
320
321 // Packet type
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
327 } Packet;
328
329
330 #ifdef __cplusplus
331 extern "C" {        // Prevents name mangling of functions
332 #endif
333
334 //----------------------------------------------------------------------------------
335 // Global Variables Definition
336 //----------------------------------------------------------------------------------
337 //...
338
339 //----------------------------------------------------------------------------------
340 // Module Functions Declaration
341 //----------------------------------------------------------------------------------
342
343 // Initialisation and cleanup
344 bool InitNetworkDevice(void);
345 void CloseNetworkDevice(void);
346
347 // Address API
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);
355
356 // Address Memory API
357 AddressInformation LoadAddress(void);
358 void UnloadAddress(AddressInformation *addressInfo);
359 AddressInformation *LoadAddressList(int size);
360
361 // Socket API
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);
367
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);
375
376 // UDP Socket API
377 int SocketSetChannel(Socket *socket, int channel, const IPAddress *address);
378 void SocketUnsetChannel(Socket *socket, int channel);
379
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);
386
387 // Socket Memory API
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);
394
395 // Socket I/O API
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);
401
402 // Packet API
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);
413
414 #ifdef __cplusplus
415 }
416 #endif
417
418 #endif  // RNET_H
419
420 /***********************************************************************************
421 *
422 *   RNET IMPLEMENTATION
423 *
424 ************************************************************************************/
425
426 #if defined(RNET_IMPLEMENTATION)
427
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()
432
433 #define NET_DEBUG_ENABLED   1
434
435 #if defined(SUPPORT_TRACELOG)
436     #define TRACELOG(level, ...) TraceLog(level, __VA_ARGS__)
437
438     #if defined(SUPPORT_TRACELOG_DEBUG)
439         #define TRACELOGD(...) TraceLog(LOG_DEBUG, __VA_ARGS__)
440     #else
441         #define TRACELOGD(...) (void)0
442     #endif
443 #else
444     #define TRACELOG(level, ...) (void)0
445     #define TRACELOGD(...) (void)0
446 #endif
447
448 //----------------------------------------------------------------------------------
449 // Types and Structures Definition
450 //----------------------------------------------------------------------------------
451
452 typedef struct _SocketAddress
453 {
454     struct sockaddr address;
455 } _SocketAddress;
456
457 typedef struct _SocketAddressIPv4
458 {
459     struct sockaddr_in address;
460 } _SocketAddressIPv4;
461
462 typedef struct _SocketAddressIPv6
463 {
464     struct sockaddr_in6 address;
465 } _SocketAddressIPv6;
466
467 typedef struct _SocketAddressStorage
468 {
469     struct sockaddr_storage address;
470 } _SocketAddressStorage;
471
472 typedef struct _AddressInformation
473 {
474     struct addrinfo addr;
475 } _AddressInformation;
476
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);
498
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)
504 {
505     switch (family)
506     {
507         case AF_UNSPEC: TRACELOG(LOG_DEBUG, "\tFamily: Unspecified"); break;
508         case AF_INET:
509         {
510             TRACELOG(LOG_DEBUG, "\tFamily: AF_INET (IPv4)");
511             TRACELOG(LOG_INFO, "\t- IPv4 address %s", SocketAddressToString(addr));
512         } break;
513         case AF_INET6:
514         {
515             TRACELOG(LOG_DEBUG, "\tFamily: AF_INET6 (IPv6)");
516             TRACELOG(LOG_INFO, "\t- IPv6 address %s", SocketAddressToString(addr));
517         } break;
518         case AF_NETBIOS:
519         {
520             TRACELOG(LOG_DEBUG, "\tFamily: AF_NETBIOS (NetBIOS)");
521         } break;
522         default: TRACELOG(LOG_DEBUG, "\tFamily: Other %ld", family); break;
523     }
524
525     TRACELOG(LOG_DEBUG, "\tSocket type:");
526     switch (socktype)
527     {
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;
535     }
536
537     TRACELOG(LOG_DEBUG, "\tProtocol:");
538     switch (protocol)
539     {
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;
544     }
545 }
546
547 // Convert network ordered socket address to human readable string (127.0.0.1)
548 static const char *SocketAddressToString(struct sockaddr_storage *sockaddr)
549 {
550     //static const char* ipv6[INET6_ADDRSTRLEN];
551     assert(sockaddr != NULL);
552     assert(sockaddr->ss_family == AF_INET || sockaddr->ss_family == AF_INET6);
553
554     switch (sockaddr->ss_family)
555     {
556         case AF_INET:
557         {
558             //struct sockaddr_in *s = ((struct sockaddr_in *)sockaddr);
559             //return inet_ntop(AF_INET, &s->sin_addr, ipv6, INET_ADDRSTRLEN);       // TODO.
560         }
561         break;
562         case AF_INET6:
563         {
564             //struct sockaddr_in6 *s = ((struct sockaddr_in6 *)sockaddr);
565             //return inet_ntop(AF_INET6, &s->sin6_addr, ipv6, INET6_ADDRSTRLEN);    // TODO.
566         }
567         break;
568     }
569
570     return NULL;
571 }
572
573 // Check if the null terminated string ip is a valid IPv4 address
574 static bool IsIPv4Address(const char *ip)
575 {
576     /*
577     struct sockaddr_in sa;
578     int result = inet_pton(AF_INET, ip, &(sa.sin_addr));    // TODO.
579     return (result != 0);
580     */
581     return false;
582 }
583
584 // Check if the null terminated string ip is a valid IPv6 address
585 static bool IsIPv6Address(const char *ip)
586 {
587     /*
588     struct sockaddr_in6 sa;
589     int result = inet_pton(AF_INET6, ip, &(sa.sin6_addr));    // TODO.
590     return result != 0;
591     */
592     return false;
593 }
594
595 // Return a pointer to the port from the correct address family (IPv4, or IPv6)
596 static void *GetSocketPortPtr(struct sockaddr_storage *sa)
597 {
598     if (sa->ss_family == AF_INET)
599     {
600         return &(((struct sockaddr_in *)sa)->sin_port);
601     }
602
603     return &(((struct sockaddr_in6 *)sa)->sin6_port);
604 }
605
606 // Return a pointer to the address from the correct address family (IPv4, or IPv6)
607 static void *GetSocketAddressPtr(struct sockaddr_storage *sa)
608 {
609     if (sa->ss_family == AF_INET)
610     {
611         return &(((struct sockaddr_in *)sa)->sin_addr);
612     }
613
614     return &(((struct sockaddr_in6 *)sa)->sin6_addr);
615 }
616
617 // Is the socket in a valid state?
618 static bool IsSocketValid(Socket *sock)
619 {
620     if (sock != NULL)
621     {
622         return (sock->channel != INVALID_SOCKET);
623     }
624
625     return false;
626 }
627
628 // Sets the error code that can be retrieved through the WSAGetLastError function.
629 static void SocketSetLastError(int err)
630 {
631 #if defined(_WIN32)
632     WSASetLastError(err);
633 #else
634     errno = err;
635 #endif
636 }
637
638 // Returns the error status for the last Sockets operation that failed
639 static int SocketGetLastError(void)
640 {
641 #if defined(_WIN32)
642     return WSAGetLastError();
643 #else
644     return errno;
645 #endif
646 }
647
648 // Returns a human-readable string representing the last error message
649 static char *SocketGetLastErrorString(void)
650 {
651     return SocketErrorCodeToString(SocketGetLastError());
652 }
653
654 // Returns a human-readable string representing the error message (err)
655 static char *SocketErrorCodeToString(int err)
656 {
657 #if defined(_WIN32)
658     static char gaiStrErrorBuffer[GAI_STRERROR_BUFFER_SIZE];
659     TRACELOG(LOG_INFO, gaiStrErrorBuffer, "%s", gai_strerror(err));
660     return gaiStrErrorBuffer;
661 #else
662     return gai_strerror(err);
663 #endif
664 }
665
666 // Set the defaults in the supplied SocketConfig if they're not already set
667 static bool SocketSetDefaults(SocketConfig *config)
668 {
669     if (config->backlog_size == 0) config->backlog_size = SOCKET_MAX_QUEUE_SIZE;
670
671     return true;
672 }
673
674 // Create the socket channel
675 static bool InitSocket(Socket *sckt, struct addrinfo *address)
676 {
677     switch (sckt->type)
678     {
679         case SOCKET_TCP:
680         {
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);
683         } break;
684         case SOCKET_UDP:
685         {
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);
688         } break;
689         default: TRACELOG(LOG_WARNING, "Invalid socket type specified."); break;
690     }
691
692     return IsSocketValid(sckt);
693 }
694
695 //    CreateSocket() - Interally called by CreateSocket()
696 //
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
699 //
700 //    SocketConfig* config - Configuration for which socket to open
701 //    SocketResult* result - The results of this function (if any, including errors)
702 //
703 //    e.g.
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,
709 //    };
710 //    SocketResult server_res;                SocketResult client_res;
711 static bool CreateSocket(SocketConfig *config, SocketResult *outresult)
712 {
713     bool success = true;
714     int addrstatus;
715     struct addrinfo hints;      // Address flags (IPV4, IPV6, UDP?)
716     struct addrinfo *res;       // A pointer to the resulting address list
717
718     outresult->socket->channel = INVALID_SOCKET;
719     outresult->status = RESULT_FAILURE;
720
721     // Set the socket type
722     outresult->socket->type = config->type;
723
724     //    Set the hints based on information in the config
725     //
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.
730     //
731     SocketSetHints(config, &hints);
732
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
738     );
739
740     // Did we succeed?
741     if (addrstatus != 0)
742     {
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());
747
748         return (success = false);
749     }
750     else
751     {
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);
757     }
758
759     // Walk the address information linked-list
760     struct addrinfo *it;
761     for (it = res; it != NULL; it = it->ai_next)
762     {
763         // Initialise the socket
764         if (!InitSocket(outresult->socket, it))
765         {
766             outresult->socket->status = SocketGetLastError();
767             TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->socket->status));
768             SocketSetLastError(0);
769             continue;
770         }
771
772         // Set socket options
773         if (!SocketSetOptions(config, outresult->socket))
774         {
775             outresult->socket->status = SocketGetLastError();
776             TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->socket->status));
777             SocketSetLastError(0);
778             freeaddrinfo(res);
779
780             return (success = false);
781         }
782     }
783
784     if (!IsSocketValid(outresult->socket))
785     {
786         outresult->socket->status = SocketGetLastError();
787         TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->status));
788         SocketSetLastError(0);
789         freeaddrinfo(res);
790
791         return (success = false);
792     }
793
794     if (success)
795     {
796         outresult->status = RESULT_SUCCESS;
797         outresult->socket->ready = 0;
798         outresult->socket->status = 0;
799
800         if (!(config->type == SOCKET_UDP)) outresult->socket->isServer = config->server;
801
802         switch (res->ai_addr->sa_family)
803         {
804             case AF_INET:
805             {
806                 outresult->socket->addripv4 = (struct _SocketAddressIPv4 *)RNET_MALLOC(sizeof(*outresult->socket->addripv4));
807
808                 if (outresult->socket->addripv4 != NULL)
809                 {
810                     memset(outresult->socket->addripv4, 0, sizeof(*outresult->socket->addripv4));
811
812                     if (outresult->socket->addripv4 != NULL)
813                     {
814                         memcpy(&outresult->socket->addripv4->address, (struct sockaddr_in *)res->ai_addr, sizeof(struct sockaddr_in));
815
816                         outresult->socket->isIPv6 = false;
817                         char hoststr[NI_MAXHOST];
818                         char portstr[NI_MAXSERV];
819
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);
822
823                         TRACELOG(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr);
824                     }
825                 }
826             } break;
827             case AF_INET6:
828             {
829                 outresult->socket->addripv6 = (struct _SocketAddressIPv6 *)RNET_MALLOC(
830                     sizeof(*outresult->socket->addripv6));
831                 if (outresult->socket->addripv6 != NULL)
832                 {
833                     memset(outresult->socket->addripv6, 0,
834                            sizeof(*outresult->socket->addripv6));
835                     if (outresult->socket->addripv6 != NULL)
836                     {
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);
843                         getnameinfo(
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);
846                     }
847                 }
848             } break;
849             default: break;
850         }
851     }
852
853     freeaddrinfo(res);
854     return success;
855 }
856
857 // Set the state of the Socket sock to blocking
858 static bool SocketSetBlocking(Socket *sock)
859 {
860     bool ret = true;
861 #if defined(_WIN32)
862     unsigned long mode = 0;
863     ret = ioctlsocket(sock->channel, FIONBIO, &mode);
864 #else
865     const int flags = fcntl(sock->channel, F_GETFL, 0);
866     if (!(flags & O_NONBLOCK))
867     {
868         TRACELOG(LOG_DEBUG, "Socket was already in blocking mode");
869         return ret;
870     }
871
872     ret = (0 == fcntl(sock->channel, F_SETFL, (flags ^ O_NONBLOCK)));
873 #endif
874     return ret;
875 }
876
877 // Set the state of the Socket sock to non-blocking
878 static bool SocketSetNonBlocking(Socket *sock)
879 {
880     bool ret = true;
881 #if defined(_WIN32)
882     unsigned long mode = 1;
883     ret = ioctlsocket(sock->channel, FIONBIO, &mode);
884 #else
885     const int flags = fcntl(sock->channel, F_GETFL, 0);
886
887     if ((flags & O_NONBLOCK))
888     {
889         TRACELOG(LOG_DEBUG, "Socket was already in non-blocking mode");
890         return ret;
891     }
892
893     ret = (0 == fcntl(sock->channel, F_SETFL, (flags | O_NONBLOCK)));
894 #endif
895     return ret;
896 }
897
898 // Set options specified in SocketConfig to Socket sock
899 static bool SocketSetOptions(SocketConfig *config, Socket *sock)
900 {
901     for (int i = 0; i < SOCKET_MAX_SOCK_OPTS; i++)
902     {
903         SocketOpt *opt = &config->sockopts[i];
904
905         if (opt->id == 0) break;
906
907         if (setsockopt(sock->channel, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0) return false;
908     }
909
910     return true;
911 }
912
913 // Set "hints" in an addrinfo struct, to be passed to getaddrinfo.
914 static void SocketSetHints(SocketConfig *config, struct addrinfo *hints)
915 {
916     if (config == NULL || hints == NULL) return;
917
918     memset(hints, 0, sizeof(*hints));
919
920     // Check if the ip supplied in the config is a valid ipv4 ip ipv6 address
921     if (IsIPv4Address(config->host))
922     {
923         hints->ai_family = AF_INET;
924         hints->ai_flags |= AI_NUMERICHOST;
925     }
926     else
927     {
928         if (IsIPv6Address(config->host))
929         {
930             hints->ai_family = AF_INET6;
931             hints->ai_flags |= AI_NUMERICHOST;
932         }
933         else hints->ai_family = AF_UNSPEC;
934     }
935
936     if (config->type == SOCKET_UDP) hints->ai_socktype = SOCK_DGRAM;
937     else hints->ai_socktype = SOCK_STREAM;
938
939
940     // Set passive unless UDP client
941     if (!(config->type == SOCKET_UDP) || config->server) hints->ai_flags = AI_PASSIVE;
942 }
943
944 //----------------------------------------------------------------------------------
945 // Module implementation
946 //----------------------------------------------------------------------------------
947
948 //    Initialise the network (requires for windows platforms only)
949 bool InitNetworkDevice(void)
950 {
951 #if defined(_WIN32)
952     WORD wVersionRequested;
953     WSADATA wsaData;
954
955     wVersionRequested = MAKEWORD(2, 2);
956     int err = WSAStartup(wVersionRequested, &wsaData);
957
958     if (err != 0)
959     {
960         TRACELOG(LOG_WARNING, "WinSock failed to initialise.");
961         return false;
962     }
963     else TRACELOG(LOG_INFO, "WinSock initialised.");
964
965     if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
966     {
967         TRACELOG(LOG_WARNING, "WinSock failed to initialise.");
968         WSACleanup();
969         return false;
970     }
971
972     return true;
973 #else
974     return true;
975 #endif
976 }
977
978 //    Cleanup, and close the network
979 void CloseNetworkDevice(void)
980 {
981 #if defined(_WIN32)
982     WSACleanup();
983 #endif
984 }
985
986 //    Protocol-independent name resolution from an address to an ANSI host name
987 //    and from a port number to the ANSI service name.
988 //
989 //    The flags parameter can be used to customize processing of the getnameinfo function
990 //
991 //    The following flags are available:
992 //
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)
1000 {
1001     // Variables
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
1005
1006     // Set the hints
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)
1010
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
1016     );
1017
1018     // Did we succeed?
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);
1021
1022     // Attempt to resolve network byte order ip to hostname
1023     switch (res->ai_family)
1024     {
1025         case AF_INET:
1026         {
1027             status = getnameinfo(&*((struct sockaddr *)res->ai_addr),
1028                                  sizeof(*((struct sockaddr_in *)res->ai_addr)),
1029                                  host, NI_MAXHOST, serv, NI_MAXSERV, flags);
1030         } break;
1031         case AF_INET6:
1032         {
1033         /*
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);
1037         */
1038         } break;
1039         default: break;
1040     }
1041
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);
1044
1045     // Free the pointer to the data returned by addrinfo
1046     freeaddrinfo(res);
1047 }
1048
1049 //    Protocol-independent translation from an ANSI host name to an address
1050 //
1051 //    e.g.
1052 //    const char* address = "127.0.0.1" (local address)
1053 //    const char* port = "80"
1054 //
1055 //  Parameters:
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.
1058 //
1059 //    Returns:
1060 //        The total amount of addresses found, -1 on error
1061 //
1062 int ResolveHost(const char *address, const char *service, int addressType, int flags, AddressInformation *outAddr)
1063 {
1064     // Variables
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)));
1071
1072     // Set the hints
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));
1081
1082     // When the address is NULL, populate the IP for me
1083     if (address == NULL)
1084     {
1085         if ((hints.ai_flags & AI_PASSIVE) == 0) hints.ai_flags |= AI_PASSIVE;
1086     }
1087
1088     TRACELOG(LOG_INFO, "Resolving host...");
1089
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
1095     );
1096
1097     // Did we succeed?
1098     if (status != 0)
1099     {
1100         int error = SocketGetLastError();
1101         SocketSetLastError(0);
1102         TRACELOG(LOG_WARNING, "Failed to get resolve host: %s", SocketErrorCodeToString(error));
1103         return -1;
1104     }
1105     else TRACELOG(LOG_INFO, "Successfully resolved host %s:%s", address, service);
1106
1107     // Calculate the size of the address information list
1108     int size = 0;
1109     for (iterator = res; iterator != NULL; iterator = iterator->ai_next) size++;
1110
1111     // Validate the size is > 0, otherwise return
1112     if (size <= 0)
1113     {
1114         TRACELOG(LOG_WARNING, "Error, no addresses found.");
1115         return -1;
1116     }
1117
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));
1120
1121     // Dynamically allocate an array of address information structs
1122     if (outAddr != NULL)
1123     {
1124         int i;
1125         for (i = 0; i < size; ++i)
1126         {
1127             outAddr[i] = LoadAddress();
1128             if (outAddr[i] == NULL)
1129             {
1130                 break;
1131             }
1132         }
1133
1134         outAddr[i] = NULL;
1135         if (i != size) outAddr = NULL;
1136     }
1137     else
1138     {
1139         TRACELOG(LOG_WARNING, "Error, failed to dynamically allocate memory for the address list");
1140         return -1;
1141     }
1142
1143     // Copy all the address information from res into outAddrList
1144     int i = 0;
1145     for (iterator = res; iterator != NULL; iterator = iterator->ai_next)
1146     {
1147         if (i < size)
1148         {
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);
1161 #endif
1162             i++;
1163         }
1164     }
1165
1166     // Free the pointer to the data returned by addrinfo
1167     freeaddrinfo(res);
1168
1169     // Return the total count of addresses found
1170     return size;
1171 }
1172
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
1175 //
1176 //    SocketConfig* config - Configuration for which socket to open
1177 //    SocketResult* result - The results of this function (if any, including errors)
1178 //
1179 //    e.g.
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,
1185 //    };
1186 //    SocketResult server_res;                SocketResult client_res;
1187 bool SocketCreate(SocketConfig *config, SocketResult *result)
1188 {
1189     // Socket creation result
1190     bool success = true;
1191
1192     // Make sure we've not received a null config or result pointer
1193     if (config == NULL || result == NULL) return (success = false);
1194
1195     // Set the defaults based on the config
1196     if (!SocketSetDefaults(config))
1197     {
1198         TRACELOG(LOG_WARNING, "Configuration Error.");
1199         success = false;
1200     }
1201     else
1202     {
1203         // Create the socket
1204         if (CreateSocket(config, result))
1205         {
1206             if (config->nonblocking) SocketSetNonBlocking(result->socket);
1207             else SocketSetBlocking(result->socket);
1208         }
1209         else success = false;
1210     }
1211
1212     return success;
1213 }
1214
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)
1218 {
1219     bool success = false;
1220     result->status = RESULT_FAILURE;
1221     struct sockaddr_storage *sock_addr = NULL;
1222
1223     // Don't bind to a socket that isn't configured as a server
1224     if (!IsSocketValid(result->socket) || !config->server)
1225     {
1226         TRACELOG(LOG_WARNING, Cannot bind to socket marked as \"Client\" in SocketConfig.");
1227         success = false;
1228     }
1229     else
1230     {
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;
1233
1234         if (sock_addr != NULL)
1235         {
1236             if (bind(result->socket->channel, (struct sockaddr *)sock_addr, sizeof(*sock_addr)) != SOCKET_ERROR)
1237             {
1238                 TRACELOG(LOG_INFO, "Successfully bound socket.");
1239                 success = true;
1240             }
1241             else
1242             {
1243                 result->socket->status = SocketGetLastError();
1244                 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status));
1245                 SocketSetLastError(0);
1246                 success = false;
1247             }
1248         }
1249     }
1250
1251     // Was the bind a success?
1252     if (success)
1253     {
1254         result->status = RESULT_SUCCESS;
1255         result->socket->ready = 0;
1256         result->socket->status = 0;
1257         socklen_t sock_len = sizeof(*sock_addr);
1258
1259         if (getsockname(result->socket->channel, (struct sockaddr *)sock_addr, &sock_len) < 0)
1260         {
1261             TRACELOG(LOG_WARNING, "Couldn't get socket address");
1262         }
1263         else
1264         {
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;
1268
1269             result->socket->addripv4 = (struct _SocketAddressIPv4 *)RNET_MALLOC(sizeof(*result->socket->addripv4));
1270
1271             if (result->socket->addripv4 != NULL) memset(result->socket->addripv4, 0, sizeof(*result->socket->addripv4));
1272
1273             memcpy(&result->socket->addripv4->address, (struct sockaddr_in *)&s->sin_addr, sizeof(struct sockaddr_in));
1274         }
1275     }
1276     return success;
1277 }
1278
1279 // Listens (and queues) incoming connections requests for a bound port.
1280 bool SocketListen(SocketConfig *config, SocketResult *result)
1281 {
1282     bool success = false;
1283     result->status = RESULT_FAILURE;
1284
1285     // Don't bind to a socket that isn't configured as a server
1286     if (!IsSocketValid(result->socket) || !config->server)
1287     {
1288         TRACELOG(LOG_WARNING, "Cannot listen on socket marked as \"Client\" in SocketConfig.");
1289         success = false;
1290     }
1291     else
1292     {
1293         // Don't listen on UDP sockets
1294         if (!(config->type == SOCKET_UDP))
1295         {
1296             if (listen(result->socket->channel, config->backlog_size) != SOCKET_ERROR)
1297             {
1298                 TRACELOG(LOG_INFO, "Started listening on socket...");
1299                 success = true;
1300             }
1301             else
1302             {
1303                 success = false;
1304                 result->socket->status = SocketGetLastError();
1305                 TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status));
1306                 SocketSetLastError(0);
1307             }
1308         }
1309         else
1310         {
1311             TRACELOG(LOG_WARNING, "Cannot listen on socket marked as \"UDP\" (datagram) in SocketConfig.");
1312             success = false;
1313         }
1314     }
1315
1316     // Was the listen a success?
1317     if (success)
1318     {
1319         result->status = RESULT_SUCCESS;
1320         result->socket->ready = 0;
1321         result->socket->status = 0;
1322     }
1323
1324     return success;
1325 }
1326
1327 // Connect the socket to the destination specified by "host" and "port" in SocketConfig
1328 bool SocketConnect(SocketConfig *config, SocketResult *result)
1329 {
1330     bool success = true;
1331     result->status = RESULT_FAILURE;
1332
1333     // Only bind to sockets marked as server
1334     if (config->server)
1335     {
1336         TRACELOG(LOG_WARNING, "Cannot connect to socket marked as \"Server\" in SocketConfig.");
1337         success = false;
1338     }
1339     else
1340     {
1341         if (IsIPv4Address(config->host))
1342         {
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);
1348
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).
1350
1351             //inet_pton(AF_INET, config->host, &ip4addr.sin_addr);
1352             int connect_result = connect(result->socket->channel, (struct sockaddr *)&ip4addr, sizeof(ip4addr));
1353
1354             if (connect_result == SOCKET_ERROR)
1355             {
1356                 result->socket->status = SocketGetLastError();
1357                 SocketSetLastError(0);
1358
1359                 switch (result->socket->status)
1360                 {
1361                     case WSAEWOULDBLOCK: success = true; break;
1362                     default:
1363                     {
1364                         TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status));
1365                         success = false;
1366                     } break;
1367                 }
1368             }
1369             else
1370             {
1371                 TRACELOG(LOG_INFO, "Successfully connected to socket.");
1372                 success = true;
1373             }
1374         }
1375         else
1376         {
1377             if (IsIPv6Address(config->host))
1378             {
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));
1386
1387                 if (connect_result == SOCKET_ERROR)
1388                 {
1389                     result->socket->status = SocketGetLastError();
1390                     SocketSetLastError(0);
1391
1392                     switch (result->socket->status)
1393                     {
1394                         case WSAEWOULDBLOCK: success = true; break;
1395                         default:
1396                         {
1397                             TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(result->socket->status));
1398                             success = false;
1399                         } break;
1400                     }
1401                 }
1402                 else
1403                 {
1404                     TRACELOG(LOG_INFO, "Successfully connected to socket.");
1405                     success = true;
1406                 }
1407             }
1408         }
1409     }
1410
1411     if (success)
1412     {
1413         result->status = RESULT_SUCCESS;
1414         result->socket->ready = 0;
1415         result->socket->status = 0;
1416     }
1417
1418     return success;
1419 }
1420
1421 //    Closes an existing socket
1422 //
1423 //    SocketChannel socket - The id of the socket to close
1424 void SocketClose(Socket *sock)
1425 {
1426     if (sock != NULL)
1427     {
1428         if (sock->channel != INVALID_SOCKET) closesocket(sock->channel);
1429     }
1430 }
1431
1432 // Returns the sockaddress for a specific socket in a generic storage struct
1433 SocketAddressStorage SocketGetPeerAddress(Socket *sock)
1434 {
1435     // TODO.
1436     /*
1437     if (sock->isServer) return NULL;
1438     if (sock->isIPv6) return sock->addripv6;
1439     else return sock->addripv4;
1440     */
1441
1442     return NULL;
1443 }
1444
1445 // Return the address-type appropriate host portion of a socket address
1446 const char *GetSocketAddressHost(SocketAddressStorage storage)
1447 {
1448     assert(storage->address.ss_family == AF_INET || storage->address.ss_family == AF_INET6);
1449     return SocketAddressToString((struct sockaddr_storage *)storage);
1450 }
1451
1452 // Return the address-type appropriate port(service) portion of a socket address
1453 short GetSocketAddressPort(SocketAddressStorage storage)
1454 {
1455     //return ntohs(GetSocketPortPtr(storage));      // TODO.
1456
1457     return 0;
1458 }
1459
1460 //    The accept function permits an incoming connection attempt on a socket.
1461 //
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)
1464 //
1465 //    e.g.
1466 //
1467 //    SocketResult connection;
1468 //    bool         connected = false;
1469 //    if (!connected)
1470 //    {
1471 //        if (SocketAccept(server_res.socket.channel, &connection))
1472 //        {
1473 //            connected = true;
1474 //        }
1475 //    }
1476 Socket *SocketAccept(Socket *server, SocketConfig *config)
1477 {
1478     if (!server->isServer || server->type == SOCKET_UDP) return NULL;
1479
1480     struct sockaddr_storage sock_addr;
1481     socklen_t sock_alen;
1482     Socket *sock = LoadSocket();
1483     server->ready = 0;
1484     sock_alen = sizeof(sock_addr);
1485     sock->channel = accept(server->channel, (struct sockaddr *)&sock_addr, &sock_alen);
1486
1487     if (sock->channel == INVALID_SOCKET)
1488     {
1489         sock->status = SocketGetLastError();
1490         TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status));
1491         SocketSetLastError(0);
1492         SocketClose(sock);
1493
1494         return NULL;
1495     }
1496
1497     (config->nonblocking) ? SocketSetNonBlocking(sock) : SocketSetBlocking(sock);
1498     sock->isServer = false;
1499     sock->ready = 0;
1500     sock->type = server->type;
1501
1502     switch (sock_addr.ss_family)
1503     {
1504         case AF_INET:
1505         {
1506             struct sockaddr_in *s = ((struct sockaddr_in *)&sock_addr);
1507             sock->addripv4 = (struct _SocketAddressIPv4 *)RNET_MALLOC(sizeof(*sock->addripv4));
1508
1509             if (sock->addripv4 != NULL)
1510             {
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));
1514             }
1515         } break;
1516         case AF_INET6:
1517         {
1518             struct sockaddr_in6 *s = ((struct sockaddr_in6 *)&sock_addr);
1519             sock->addripv6 = (struct _SocketAddressIPv6 *)RNET_MALLOC(sizeof(*sock->addripv6));
1520
1521             if (sock->addripv6 != NULL)
1522             {
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));
1526             }
1527         } break;
1528     }
1529
1530     return sock;
1531 }
1532
1533 // Verify that the channel is in the valid range
1534 static int ValidChannel(int channel)
1535 {
1536     if ((channel < 0) || (channel >= SOCKET_MAX_UDPCHANNELS))
1537     {
1538         TRACELOG(LOG_WARNING, "Invalid channel");
1539         return 0;
1540     }
1541
1542     return 1;
1543 }
1544
1545 // Set the socket channel
1546 int SocketSetChannel(Socket *socket, int channel, const IPAddress *address)
1547 {
1548     struct UDPChannel *binding;
1549
1550     if (socket == NULL)
1551     {
1552         TRACELOG(LOG_WARNING, "Passed a NULL socket");
1553         return (-1);
1554     }
1555
1556     if (channel == -1)
1557     {
1558         for (channel = 0; channel < SOCKET_MAX_UDPCHANNELS; ++channel)
1559         {
1560             binding = &socket->binding[channel];
1561             if (binding->numbound < SOCKET_MAX_UDPADDRESSES) break;
1562         }
1563     }
1564     else
1565     {
1566         if (!ValidChannel(channel)) return (-1);
1567
1568         binding = &socket->binding[channel];
1569     }
1570
1571     if (binding->numbound == SOCKET_MAX_UDPADDRESSES)
1572     {
1573         TRACELOG(LOG_WARNING, "No room for new addresses");
1574         return (-1);
1575     }
1576
1577     binding->address[binding->numbound++] = *address;
1578
1579     return (channel);
1580 }
1581
1582 // Remove the socket channel
1583 void SocketUnsetChannel(Socket *socket, int channel)
1584 {
1585     if ((channel >= 0) && (channel < SOCKET_MAX_UDPCHANNELS)) socket->binding[channel].numbound = 0;
1586 }
1587
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.
1590  */
1591 SocketDataPacket *AllocPacket(int size)
1592 {
1593     SocketDataPacket *packet = (SocketDataPacket *)RNET_MALLOC(sizeof(*packet));
1594     int error = 1;
1595
1596     if (packet != NULL)
1597     {
1598         packet->maxlen = size;
1599         packet->data = (uint8_t *)RNET_MALLOC(size);
1600         if (packet->data != NULL)
1601         {
1602             error = 0;
1603         }
1604     }
1605
1606     if (error)
1607     {
1608         FreePacket(packet);
1609         packet = NULL;
1610     }
1611
1612     return (packet);
1613 }
1614
1615 int ResizePacket(SocketDataPacket *packet, int newsize)
1616 {
1617     uint8_t *newdata = (uint8_t *)RNET_MALLOC(newsize);
1618
1619     if (newdata != NULL)
1620     {
1621         RNET_FREE(packet->data);
1622         packet->data = newdata;
1623         packet->maxlen = newsize;
1624     }
1625
1626     return (packet->maxlen);
1627 }
1628
1629 void FreePacket(SocketDataPacket *packet)
1630 {
1631     if (packet)
1632     {
1633         RNET_FREE(packet->data);
1634         RNET_FREE(packet);
1635     }
1636 }
1637
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)
1641 {
1642     SocketDataPacket **packetV = (SocketDataPacket **)RNET_MALLOC((howmany + 1) * sizeof(*packetV));
1643
1644     if (packetV != NULL)
1645     {
1646         int i;
1647         for (i = 0; i < howmany; ++i)
1648         {
1649             packetV[i] = AllocPacket(size);
1650             if (packetV[i] == NULL)
1651             {
1652                 break;
1653             }
1654         }
1655         packetV[i] = NULL;
1656
1657         if (i != howmany)
1658         {
1659             FreePacketList(packetV);
1660             packetV = NULL;
1661         }
1662     }
1663
1664     return (packetV);
1665 }
1666
1667 void FreePacketList(SocketDataPacket **packetV)
1668 {
1669     if (packetV)
1670     {
1671         for (int i = 0; packetV[i]; ++i) FreePacket(packetV[i]);
1672         RNET_FREE(packetV);
1673     }
1674 }
1675
1676 // Send 'len' bytes of 'data' over the non-server socket 'sock'
1677 int SocketSend(Socket *sock, const void *datap, int length)
1678 {
1679     int sent = 0;
1680     int left = length;
1681     int status = -1;
1682     int numsent = 0;
1683     const unsigned char *data = (const unsigned char *)datap;
1684
1685     // Server sockets are for accepting connections only
1686     if (sock->isServer)
1687     {
1688         TRACELOG(LOG_WARNING, "Cannot send information on a server socket");
1689         return -1;
1690     }
1691
1692     // Which socket are we trying to send data on
1693     switch (sock->type)
1694     {
1695         case SOCKET_TCP:
1696         {
1697             SocketSetLastError(0);
1698             do
1699             {
1700                 length = send(sock->channel, (const char *)data, left, 0);
1701                 if (length > 0)
1702                 {
1703                     sent += length;
1704                     left -= length;
1705                     data += length;
1706                 }
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
1710             );
1711
1712             if (length == SOCKET_ERROR)
1713             {
1714                 sock->status = SocketGetLastError();
1715                 TRACELOG(LOG_DEBUG, "Socket Error: %s", SocketErrorCodeToString(sock->status));
1716                 SocketSetLastError(0);
1717             }
1718             else TRACELOG(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, sent);
1719
1720             return sent;
1721         } break;
1722         case SOCKET_UDP:
1723         {
1724             SocketSetLastError(0);
1725
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));
1728
1729             if (sent >= 0)
1730             {
1731                 sock->status = 0;
1732                 ++numsent;
1733                 TRACELOG(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, status);
1734             }
1735             else
1736             {
1737                 sock->status = SocketGetLastError();
1738                 TRACELOG(LOG_DEBUG, "Socket Error: %s", SocketGetLastErrorString(sock->status));
1739                 SocketSetLastError(0);
1740                 return 0;
1741             }
1742
1743             return numsent;
1744         } break;
1745         default: break;
1746     }
1747
1748     return -1;
1749 }
1750
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)
1757 {
1758     int len = 0;
1759     int numrecv = 0;
1760     int status = 0;
1761     socklen_t sock_len;
1762     struct sockaddr_storage sock_addr;
1763     //char ip[INET6_ADDRSTRLEN];
1764
1765     // Server sockets are for accepting connections only
1766     if (sock->isServer && (sock->type == SOCKET_TCP))
1767     {
1768         sock->status = SocketGetLastError();
1769         TRACELOG(LOG_DEBUG, "Socket Error: %s", "Server sockets cannot be used to receive data");
1770         SocketSetLastError(0);
1771         return 0;
1772     }
1773
1774     // Which socket are we trying to send data on
1775     switch (sock->type)
1776     {
1777         case SOCKET_TCP:
1778         {
1779             SocketSetLastError(0);
1780             do
1781             {
1782                 len = recv(sock->channel, (char *)data, maxlen, 0);
1783             } while (SocketGetLastError() == WSAEINTR);
1784
1785             if (len > 0)
1786             {
1787                 // Who sent the packet?
1788                 if (sock->type == SOCKET_UDP)
1789                 {
1790                     //TRACELOG(LOG_DEBUG, "Received data from: %s", inet_ntop(sock_addr.ss_family, GetSocketAddressPtr((struct sockaddr *)&sock_addr), ip, sizeof(ip)));
1791                 }
1792
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);
1795             }
1796
1797             sock->ready = 0;
1798             return len;
1799         } break;
1800         case SOCKET_UDP:
1801         {
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
1807                               0,                // Flags
1808                               (struct sockaddr *)&sock_addr, // The address of the recevied data
1809                               &sock_len         // The length of the received data address
1810             );
1811
1812             if (status >= 0) ++numrecv;
1813             else
1814             {
1815                 sock->status = SocketGetLastError();
1816
1817                 switch (sock->status)
1818                 {
1819                     case WSAEWOULDBLOCK: break;
1820                     default: TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); break;
1821                 }
1822
1823                 SocketSetLastError(0);
1824                 return 0;
1825             }
1826
1827             sock->ready = 0;
1828             return numrecv;
1829         } break;
1830         default: break;
1831     }
1832
1833     return -1;
1834 }
1835
1836 // Does the socket have it's 'ready' flag set?
1837 bool IsSocketReady(Socket *sock)
1838 {
1839     return (sock != NULL) && (sock->ready);
1840 }
1841
1842 // Check if the socket is considered connected
1843 bool IsSocketConnected(Socket *sock)
1844 {
1845 #if defined(_WIN32)
1846     FD_SET writefds;
1847     FD_ZERO(&writefds);
1848     FD_SET(sock->channel, &writefds);
1849     struct timeval timeout;
1850     timeout.tv_sec = 1;
1851     timeout.tv_usec = 1000000000UL;
1852     int total = select(0, NULL, &writefds, NULL, &timeout);
1853
1854     if (total == -1)
1855     { // Error
1856         sock->status = SocketGetLastError();
1857         TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status));
1858         SocketSetLastError(0);
1859     }
1860     else if (total == 0) return false;   // Timeout
1861     else if (FD_ISSET(sock->channel, &writefds)) return true;
1862
1863     return false;
1864 #else
1865     return true;
1866 #endif
1867 }
1868
1869 // Allocate and return a SocketResult struct
1870 SocketResult *LoadSocketResult(void)
1871 {
1872     struct SocketResult *res = (struct SocketResult *)RNET_MALLOC(sizeof(*res));
1873
1874     if (res != NULL)
1875     {
1876         memset(res, 0, sizeof(*res));
1877         if ((res->socket = LoadSocket()) == NULL)
1878         {
1879             RNET_FREE(res);
1880             res = NULL;
1881         }
1882     }
1883
1884     return res;
1885 }
1886
1887 // Free an allocated SocketResult
1888 void UnloadSocketResult(SocketResult **result)
1889 {
1890     if (*result != NULL)
1891     {
1892         if ((*result)->socket != NULL) UnloadSocket(&((*result)->socket));
1893
1894         RNET_FREE(*result);
1895         *result = NULL;
1896     }
1897 }
1898
1899 // Allocate a Socket
1900 Socket *LoadSocket(void)
1901 {
1902     struct Socket *sock;
1903     sock = (Socket *)RNET_MALLOC(sizeof(*sock));
1904
1905     if (sock != NULL) memset(sock, 0, sizeof(*sock));
1906     else
1907     {
1908         TRACELOG(LOG_WARNING, "Ran out of memory attempting to allocate a socket");
1909         SocketClose(sock);
1910         RNET_FREE(sock);
1911         sock = NULL;
1912     }
1913
1914     return sock;
1915 }
1916
1917 // Free an allocated Socket
1918 void UnloadSocket(Socket **sock)
1919 {
1920     if (*sock != NULL)
1921     {
1922         RNET_FREE(*sock);
1923         *sock = NULL;
1924     }
1925 }
1926
1927 // Allocate a SocketSet
1928 SocketSet *LoadSocketSet(int max)
1929 {
1930     struct SocketSet *set = (struct SocketSet *)RNET_MALLOC(sizeof(*set));
1931
1932     if (set != NULL)
1933     {
1934         set->numsockets = 0;
1935         set->maxsockets = max;
1936         set->sockets = (struct Socket **)RNET_MALLOC(max * sizeof(*set->sockets));
1937         if (set->sockets != NULL)
1938         {
1939             for (int i = 0; i < max; ++i) set->sockets[i] = NULL;
1940         }
1941         else
1942         {
1943             RNET_FREE(set);
1944             set = NULL;
1945         }
1946     }
1947
1948     return (set);
1949 }
1950
1951 // Free an allocated SocketSet
1952 void UnloadSocketSet(SocketSet *set)
1953 {
1954     if (set)
1955     {
1956         RNET_FREE(set->sockets);
1957         RNET_FREE(set);
1958     }
1959 }
1960
1961 // Add a Socket "sock" to the SocketSet "set"
1962 int AddSocket(SocketSet *set, Socket *sock)
1963 {
1964     if (sock != NULL)
1965     {
1966         if (set->numsockets == set->maxsockets)
1967         {
1968             TRACELOG(LOG_DEBUG, "Socket Error: %s", "SocketSet is full");
1969             SocketSetLastError(0);
1970             return (-1);
1971         }
1972         set->sockets[set->numsockets++] = (struct Socket *)sock;
1973     }
1974     else
1975     {
1976         TRACELOG(LOG_DEBUG, "Socket Error: %s", "Socket was null");
1977         SocketSetLastError(0);
1978         return (-1);
1979     }
1980
1981     return (set->numsockets);
1982 }
1983
1984 // Remove a Socket "sock" to the SocketSet "set"
1985 int RemoveSocket(SocketSet *set, Socket *sock)
1986 {
1987     if (sock != NULL)
1988     {
1989         int i = 0;
1990         for (i = 0; i < set->numsockets; ++i)
1991         {
1992             if (set->sockets[i] == (struct Socket *)sock) break;
1993         }
1994
1995         if (i == set->numsockets)
1996         {
1997             TRACELOG(LOG_DEBUG, "Socket Error: %s", "Socket not found");
1998             SocketSetLastError(0);
1999             return (-1);
2000         }
2001
2002         --set->numsockets;
2003         for (; i < set->numsockets; ++i) set->sockets[i] = set->sockets[i + 1];
2004     }
2005
2006     return (set->numsockets);
2007 }
2008
2009 // Check the sockets in the socket set for pending information
2010 int CheckSockets(SocketSet *set, unsigned int timeout)
2011 {
2012     int i;
2013     SOCKET maxfd;
2014     int retval;
2015     struct timeval tv;
2016     fd_set mask;
2017
2018     /* Find the largest file descriptor */
2019     maxfd = 0;
2020     for (i = set->numsockets - 1; i >= 0; --i)
2021     {
2022         if (set->sockets[i]->channel > maxfd)
2023         {
2024             maxfd = set->sockets[i]->channel;
2025         }
2026     }
2027
2028     // Check the file descriptors for available data
2029     do
2030     {
2031         SocketSetLastError(0);
2032
2033         // Set up the mask of file descriptors
2034         FD_ZERO(&mask);
2035         for (i = set->numsockets - 1; i >= 0; --i)
2036         {
2037             FD_SET(set->sockets[i]->channel, &mask);
2038         } // Set up the timeout
2039
2040         tv.tv_sec = timeout / 1000;
2041         tv.tv_usec = (timeout % 1000) * 1000;
2042
2043         /* Look! */
2044         retval = select(maxfd + 1, &mask, NULL, NULL, &tv);
2045     } while (SocketGetLastError() == WSAEINTR);
2046
2047     // Mark all file descriptors ready that have data available
2048     if (retval > 0)
2049     {
2050         for (i = set->numsockets - 1; i >= 0; --i)
2051         {
2052             if (FD_ISSET(set->sockets[i]->channel, &mask)) set->sockets[i]->ready = 1;
2053         }
2054     }
2055
2056     return retval;
2057 }
2058
2059 // Allocate an AddressInformation
2060 AddressInformation LoadAddress(void)
2061 {
2062     AddressInformation addressInfo = NULL;
2063     addressInfo = (AddressInformation)RNET_CALLOC(1, sizeof(*addressInfo));
2064
2065     if (addressInfo != NULL)
2066     {
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\"");
2069     }
2070     else TRACELOG(LOG_WARNING, "Failed to allocate memory for \"struct AddressInformation\"");
2071
2072     return addressInfo;
2073 }
2074
2075 // Free an AddressInformation struct
2076 void UnloadAddress(AddressInformation *addressInfo)
2077 {
2078     if (*addressInfo != NULL)
2079     {
2080         if ((*addressInfo)->addr.ai_addr != NULL)
2081         {
2082             RNET_FREE((*addressInfo)->addr.ai_addr);
2083             (*addressInfo)->addr.ai_addr = NULL;
2084         }
2085
2086         RNET_FREE(*addressInfo);
2087         *addressInfo = NULL;
2088     }
2089 }
2090
2091 // Allocate a list of AddressInformation
2092 AddressInformation *LoadAddressList(int size)
2093 {
2094     AddressInformation *addr;
2095     addr = (AddressInformation *)RNET_MALLOC(size * sizeof(AddressInformation));
2096     return addr;
2097 }
2098
2099 // Opaque datatype accessor addrinfo->ai_family
2100 int GetAddressFamily(AddressInformation address)
2101 {
2102     return address->addr.ai_family;
2103 }
2104
2105 // Opaque datatype accessor addrinfo->ai_socktype
2106 int GetAddressSocketType(AddressInformation address)
2107 {
2108     return address->addr.ai_socktype;
2109 }
2110
2111 // Opaque datatype accessor addrinfo->ai_protocol
2112 int GetAddressProtocol(AddressInformation address)
2113 {
2114     return address->addr.ai_protocol;
2115 }
2116
2117 // Opaque datatype accessor addrinfo->ai_canonname
2118 char *GetAddressCanonName(AddressInformation address)
2119 {
2120     return address->addr.ai_canonname;
2121 }
2122
2123 // Opaque datatype accessor addrinfo->ai_addr
2124 char *GetAddressHostAndPort(AddressInformation address, char *outhost, unsigned short *outport)
2125 {
2126     //char *ip[INET6_ADDRSTRLEN];
2127     char *result = NULL;
2128     struct sockaddr_storage *storage = (struct sockaddr_storage *)address->addr.ai_addr;
2129
2130     switch (storage->ss_family)
2131     {
2132         case AF_INET:
2133         {
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);
2137         } break;
2138         case AF_INET6:
2139         {
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);
2143         } break;
2144         default: break;
2145     }
2146
2147     if (result == NULL)
2148     {
2149         TRACELOG(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(SocketGetLastError()));
2150         SocketSetLastError(0);
2151     }
2152     else
2153     {
2154         strcpy(outhost, result);
2155     }
2156     return result;
2157 }
2158
2159 //
2160 void PacketSend(Packet *packet)
2161 {
2162     TRACELOG(LOG_INFO, "Sending packet (%s) with size %d\n", packet->data, packet->size);
2163 }
2164
2165 //
2166 void PacketReceive(Packet *packet)
2167 {
2168     TRACELOG(LOG_INFO, "Receiving packet (%s) with size %d\n", packet->data, packet->size);
2169 }
2170
2171 //
2172 void PacketWrite16(Packet *packet, uint16_t value)
2173 {
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);
2181 }
2182
2183 //
2184 void PacketWrite32(Packet *packet, uint32_t value)
2185 {
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);
2194
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));
2198 }
2199
2200 //
2201 void PacketWrite64(Packet *packet, uint64_t value)
2202 {
2203     TRACELOG(LOG_INFO, "Original: 0x%016" PRIX64 " - %" PRIu64 "\n", value, value);
2204
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);
2216
2217     TRACELOG(LOG_INFO, "Network: 0x%016" PRIX64 " - %" PRIu64 "\n", (uint64_t)(packet->data - packet->offs), (uint64_t)(packet->data - packet->offs));
2218 }
2219
2220 //
2221 uint16_t PacketRead16(Packet *packet)
2222 {
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);
2228
2229     return value;
2230 }
2231
2232 //
2233 uint32_t PacketRead32(Packet *packet)
2234 {
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);
2240
2241     return value;
2242 }
2243
2244 //
2245 uint64_t PacketRead64(Packet *packet)
2246 {
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);
2252
2253     return value;
2254 }
2255
2256 #endif  // RNET_IMPLEMENTATION