fixed some more examples

fixed the ResolveHost method
added more network specific defines
This commit is contained in:
Jak Barnes 2019-03-17 20:33:22 +00:00
parent 867e29b6a4
commit 7c2f816852
10 changed files with 270 additions and 147 deletions

View File

@ -36,8 +36,8 @@ bool client_connected = false;
const char * pingmsg = "Ping!"; const char * pingmsg = "Ping!";
const char * pongmsg = "Pong!"; const char * pongmsg = "Pong!";
int msglen = 0; int msglen = 0;
SocketConfig server_cfg = {.host = "127.0.0.1", .port = "8080", .type = SOCKET_TCP, .server = true, .nonblocking = true}; SocketConfig server_cfg = {.host = "127.0.0.1", .port = "4950", .type = SOCKET_TCP, .server = true, .nonblocking = true};
SocketConfig client_cfg = {.host = "127.0.0.1", .port = "8080", .type = SOCKET_TCP, .nonblocking = true}; SocketConfig client_cfg = {.host = "127.0.0.1", .port = "4950", .type = SOCKET_TCP, .nonblocking = true};
SocketConfig connection_cfg = {.nonblocking = true}; SocketConfig connection_cfg = {.nonblocking = true};
SocketResult *server_res = NULL; SocketResult *server_res = NULL;
SocketResult *client_res = NULL; SocketResult *client_res = NULL;
@ -100,14 +100,14 @@ void NetworkUpdate()
int bytesRecv = 0; int bytesRecv = 0;
if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) { if (server_cfg.type == SOCKET_UDP && client_cfg.type == SOCKET_UDP) {
if (IsSocketReady(client_res->socket)) { if (IsSocketReady(client_res->socket)) {
bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen, 0); bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen);
} }
if (IsSocketReady(server_res->socket)) { if (IsSocketReady(server_res->socket)) {
bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen, 0); bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen);
} }
} else { } else {
if (IsSocketReady(connection)) { if (IsSocketReady(connection)) {
bytesRecv = SocketReceive(connection, recvBuffer, msglen, 0); bytesRecv = SocketReceive(connection, recvBuffer, msglen);
} }
} }

View File

@ -36,9 +36,22 @@ int main()
// Networking // Networking
InitNetwork(); InitNetwork();
ResolveHost("www.google.com", "80"); AddressInformation* addr = NULL;
ResolveIP("8.8.8.8", NULL, NAME_INFO_DEFAULT); int count = ResolveHost(
ResolveIP("2001:4860:4860::8888", "80", NAME_INFO_NUMERICSERV); NULL,
"5210",
ADDRESS_TYPE_IPV4,
0 // Uncomment any of these flags
// ADDRESS_INFO_NUMERICHOST // or try them in conjunction to
// ADDRESS_INFO_NUMERICSERV // specify custom behaviour from
// ADDRESS_INFO_DNS_ONLY // the function getaddrinfo()
// ADDRESS_INFO_ALL //
// ADDRESS_INFO_FQDN // e.g. ADDRESS_INFO_CANONNAME | ADDRESS_INFO_NUMERICSERV
,
addr
);
ResolveIP("8.8.8.8", NULL, NAME_INFO_DEFAULT, NULL, NULL);
ResolveIP("2001:4860:4860::8888", "80", NAME_INFO_NUMERICSERV, NULL, NULL);
// Main game loop // Main game loop
while (!WindowShouldClose()) while (!WindowShouldClose())

View File

@ -13,7 +13,7 @@ bool connected = false;
const char * pingmsg = "Ping!"; const char * pingmsg = "Ping!";
const char * pongmsg = "Pong!"; const char * pongmsg = "Pong!";
int msglen = 0; int msglen = 0;
SocketConfig client_cfg = {.host = "127.0.0.1", .port = "8080", .type = SOCKET_TCP, .nonblocking = true}; SocketConfig client_cfg = {.host = "127.0.0.1", .port = "4950", .type = SOCKET_TCP, .nonblocking = true};
SocketResult *client_res = NULL; SocketResult *client_res = NULL;
SocketSet * socket_set = NULL; SocketSet * socket_set = NULL;
char recvBuffer[512]; char recvBuffer[512];
@ -48,7 +48,7 @@ void NetworkUpdate()
// If the socket is ready, attempt to receive data from the socket // If the socket is ready, attempt to receive data from the socket
int bytesRecv = 0; int bytesRecv = 0;
if (IsSocketReady(client_res->socket)) { if (IsSocketReady(client_res->socket)) {
bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen, 0); bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen);
} }
// If we received data, was that data a "Ping!" or a "Pong!" // If we received data, was that data a "Ping!" or a "Pong!"
@ -77,7 +77,7 @@ int main()
int screenWidth = 800; int screenWidth = 800;
int screenHeight = 450; int screenHeight = 450;
InitWindow( InitWindow(
screenWidth, screenHeight, "raylib [network] example - ping pong"); screenWidth, screenHeight, "raylib [network] example - tcp client");
SetTargetFPS(60); SetTargetFPS(60);
SetTraceLogLevel(LOG_DEBUG); SetTraceLogLevel(LOG_DEBUG);

View File

@ -13,7 +13,7 @@ bool connected = false;
const char * pingmsg = "Ping!"; const char * pingmsg = "Ping!";
const char * pongmsg = "Pong!"; const char * pongmsg = "Pong!";
int msglen = 0; int msglen = 0;
SocketConfig server_cfg = {.host = "127.0.0.1", .port = "8080", .type = SOCKET_TCP, .server = true, .nonblocking = true}; SocketConfig server_cfg = {.host = "127.0.0.1", .port = "4950", .type = SOCKET_TCP, .server = true, .nonblocking = true};
SocketConfig connection_cfg = {.nonblocking = true}; SocketConfig connection_cfg = {.nonblocking = true};
SocketResult *server_res = NULL; SocketResult *server_res = NULL;
SocketSet * socket_set = NULL; SocketSet * socket_set = NULL;
@ -56,7 +56,7 @@ void NetworkUpdate()
// If the socket is ready, attempt to receive data from the socket // If the socket is ready, attempt to receive data from the socket
int bytesRecv = 0; int bytesRecv = 0;
if (IsSocketReady(connection)) { if (IsSocketReady(connection)) {
bytesRecv = SocketReceive(connection, recvBuffer, msglen, 0); bytesRecv = SocketReceive(connection, recvBuffer, msglen);
} }
// If we received data, was that data a "Ping!" or a "Pong!" // If we received data, was that data a "Ping!" or a "Pong!"
@ -85,7 +85,7 @@ int main()
int screenWidth = 800; int screenWidth = 800;
int screenHeight = 450; int screenHeight = 450;
InitWindow( InitWindow(
screenWidth, screenHeight, "raylib [network] example - ping pong"); screenWidth, screenHeight, "raylib [network] example - tcp server");
SetTargetFPS(60); SetTargetFPS(60);
SetTraceLogLevel(LOG_DEBUG); SetTraceLogLevel(LOG_DEBUG);

View File

@ -28,39 +28,40 @@ void test_resolve_ip()
const char *host = "8.8.8.8"; const char *host = "8.8.8.8";
const char *port = "8080"; const char *port = "8080";
char ip[ADDRESS_IPV6_ADDRSTRLEN]; char ip[ADDRESS_IPV6_ADDRSTRLEN];
char service[ADDRESS_MAXSERV];
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_NUMERICHOST, ip); ResolveIP(host, port, NAME_INFO_NUMERICHOST, ip, service);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "8.8.8.8") == 0); assert(strcmp(ip, "8.8.8.8") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_DEFAULT, ip); ResolveIP(host, port, NAME_INFO_DEFAULT, ip, service);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "google-public-dns-a.google.com") == 0); assert(strcmp(ip, "google-public-dns-a.google.com") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_NOFQDN, ip); ResolveIP(host, port, NAME_INFO_NOFQDN, ip, service);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "google-public-dns-a") == 0); assert(strcmp(ip, "google-public-dns-a") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_NUMERICHOST, ip); ResolveIP(host, port, NAME_INFO_NUMERICHOST, ip, service);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "8.8.8.8") == 0); assert(strcmp(ip, "8.8.8.8") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_NAMEREQD, ip); ResolveIP(host, port, NAME_INFO_NAMEREQD, ip, service);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "google-public-dns-a.google.com") == 0); assert(strcmp(ip, "google-public-dns-a.google.com") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_NUMERICSERV, ip); ResolveIP(host, port, NAME_INFO_NUMERICSERV, ip, service);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "google-public-dns-a.google.com") == 0); assert(strcmp(ip, "google-public-dns-a.google.com") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN); memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_DGRAM, ip); ResolveIP(host, port, NAME_INFO_DGRAM, ip, service);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip); TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "google-public-dns-a.google.com") == 0); assert(strcmp(ip, "google-public-dns-a.google.com") == 0);
} }
@ -75,7 +76,7 @@ void test_resolve_host()
assert(GetAddressFamily(addr[1]) == ADDRESS_TYPE_IPV4); assert(GetAddressFamily(addr[1]) == ADDRESS_TYPE_IPV4);
assert(GetAddressSocketType(addr[0]) == 0); assert(GetAddressSocketType(addr[0]) == 0);
assert(GetAddressProtocol(addr[0]) == 0); assert(GetAddressProtocol(addr[0]) == 0);
for (size_t i = 0; i < count; i++) { PrintAddressInfo(addr[i]); } // for (size_t i = 0; i < count; i++) { PrintAddressInfo(addr[i]); }
} }
void test_address() void test_address()

View File

@ -35,7 +35,7 @@ void NetworkUpdate()
// If the socket is ready, attempt to receive data from the socket // If the socket is ready, attempt to receive data from the socket
int bytesRecv = 0; int bytesRecv = 0;
if (IsSocketReady(client_res->socket)) { if (IsSocketReady(client_res->socket)) {
bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen, 0); bytesRecv = SocketReceive(client_res->socket, recvBuffer, msglen);
} }
// If we received data, was that data a "Ping!" or a "Pong!" // If we received data, was that data a "Ping!" or a "Pong!"

View File

@ -35,9 +35,9 @@ void NetworkUpdate()
// If the socket is ready, attempt to receive data from the socket // If the socket is ready, attempt to receive data from the socket
// int bytesRecv = 0; // int bytesRecv = 0;
// if (IsSocketReady(server_res->socket)) { // if (IsSocketReady(server_res->socket)) {
// bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen, 0); // bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen);
// } // }
int bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen, 0); int bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen);
// If we received data, was that data a "Ping!" or a "Pong!" // If we received data, was that data a "Ping!" or a "Pong!"
if (bytesRecv > 0) { if (bytesRecv > 0) {

View File

@ -89,6 +89,8 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)$(ProjectName)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(ProjectName)\$(Configuration)\temp</IntDir>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
@ -131,7 +133,7 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile> <ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
@ -140,6 +142,7 @@
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>

View File

@ -98,26 +98,55 @@
#define MAX_SHADER_LOCATIONS 32 // Maximum number of predefined locations stored in shader struct #define MAX_SHADER_LOCATIONS 32 // Maximum number of predefined locations stored in shader struct
#define MAX_MATERIAL_MAPS 12 // Maximum number of texture maps stored in shader struct #define MAX_MATERIAL_MAPS 12 // Maximum number of texture maps stored in shader struct
// Network defines // Network connection related defines
#define SOCKET_MAX_SET_SIZE 32 #define SOCKET_MAX_SET_SIZE (32) // Maximum sockets in a set
#define SOCKET_MAX_QUEUE_SIZE 16 #define SOCKET_MAX_QUEUE_SIZE (16) // Maximum socket queue size
#define SOCKET_MAX_SOCK_OPTS 4 #define SOCKET_MAX_SOCK_OPTS (4) // Maximum socket options
#define SOCKET_MAX_UDPCHANNELS (32) #define SOCKET_MAX_UDPCHANNELS (32) // Maximum UDP channels
#define SOCKET_MAX_UDPADDRESSES (4) #define SOCKET_MAX_UDPADDRESSES (4) // Maximum bound UDP addresses
// // Network address related defines
#define ADDRESS_IPV4_ADDRSTRLEN 22 #define ADDRESS_IPV4_ADDRSTRLEN (22) // IPv4 string length
#define ADDRESS_IPV6_ADDRSTRLEN 65 #define ADDRESS_IPV6_ADDRSTRLEN (65) // IPv6 string length
#define ADDRESS_TYPE_IPV4 2 #define ADDRESS_TYPE_ANY (0) // AF_UNSPEC
#define ADDRESS_TYPE_IPV6 23 #define ADDRESS_TYPE_IPV4 (2) // AF_INET
#define ADDRESS_TYPE_IPV6 (23) // AF_INET6
#define ADDRESS_MAXHOST (1025) // Max size of a fully-qualified domain name
#define ADDRESS_MAXSERV (32) // Max size of a service name
// getnameinfo() defines // Network address related defines
#define NAME_INFO_DEFAULT 0x00 /* No flags set */ #define ADDRESS_ANY ((unsigned long) 0x00000000)
#define NAME_INFO_NOFQDN 0x01 /* Only return nodename portion for local hosts */ #define ADDRESS_LOOPBACK (0x7f000001)
#define NAME_INFO_NUMERICHOST 0x02 /* Return numeric form of the host's address */ #define ADDRESS_BROADCAST ((unsigned long) 0xffffffff)
#define NAME_INFO_NAMEREQD 0x04 /* Error if the host's name not in DNS */ #define ADDRESS_NONE (0xffffffff)
#define NAME_INFO_NUMERICSERV 0x08 /* Return numeric form of the service (port #) */
#define NAME_INFO_DGRAM 0x10 /* Service is a datagram service */ // Address resolution related defines
#if defined(_WIN32)
#define ADDRESS_INFO_PASSIVE (0x00000001) // Socket address will be used in bind() call
#define ADDRESS_INFO_CANONNAME (0x00000002) // Return canonical name in first ai_canonname
#define ADDRESS_INFO_NUMERICHOST (0x00000004) // Nodename must be a numeric address string
#define ADDRESS_INFO_NUMERICSERV (0x00000008) // Servicename must be a numeric port number
#define ADDRESS_INFO_DNS_ONLY (0x00000010) // Restrict queries to unicast DNS only (no LLMNR, netbios, etc.)
#define ADDRESS_INFO_ALL (0x00000100) // Query both IP6 and IP4 with AI_V4MAPPED
#define ADDRESS_INFO_ADDRCONFIG (0x00000400) // Resolution only if global address configured
#define ADDRESS_INFO_V4MAPPED (0x00000800) // On v6 failure, query v4 and convert to V4MAPPED format
#define ADDRESS_INFO_NON_AUTHORITATIVE (0x00004000) // LUP_NON_AUTHORITATIVE
#define ADDRESS_INFO_SECURE (0x00008000) // LUP_SECURE
#define ADDRESS_INFO_RETURN_PREFERRED_NAMES (0x00010000) // LUP_RETURN_PREFERRED_NAMES
#define ADDRESS_INFO_FQDN (0x00020000) // Return the FQDN in ai_canonname
#define ADDRESS_INFO_FILESERVER (0x00040000) // Resolving fileserver name resolution
#define ADDRESS_INFO_DISABLE_IDN_ENCODING (0x00080000) // Disable Internationalized Domain Names handling
#define ADDRESS_INFO_EXTENDED (0x80000000) // Indicates this is extended ADDRINFOEX(2/..) struct
#define ADDRESS_INFO_RESOLUTION_HANDLE (0x40000000) // Request resolution handle
#endif
// Network resolution related defines
#define NAME_INFO_DEFAULT (0x00) // No flags set
#define NAME_INFO_NOFQDN (0x01) // Only return nodename portion for local hosts
#define NAME_INFO_NUMERICHOST (0x02) // Return numeric form of the host's address
#define NAME_INFO_NAMEREQD (0x04) // Error if the host's name not in DNS
#define NAME_INFO_NUMERICSERV (0x08) // Return numeric form of the service (port #)
#define NAME_INFO_DGRAM (0x10) // Service is a datagram service
// NOTE: MSC C++ compiler does not support compound literals (C99 feature) // NOTE: MSC C++ compiler does not support compound literals (C99 feature)
// Plain structures in C++ (without constructors) can be initialized from { } initializers. // Plain structures in C++ (without constructors) can be initialized from { } initializers.
@ -1502,13 +1531,14 @@ RLAPI bool InitNetwork(void);
RLAPI void CloseNetwork(void); RLAPI void CloseNetwork(void);
// Address API // Address API
RLAPI void ResolveIP(const char *host, const char *port, int flags, char *outhost); RLAPI void ResolveIP(const char *ip, const char *service, int flags, char *outhost, char *outserv);
RLAPI int ResolveHost(const char *address, const char *port, struct _AddressInformation *addr); RLAPI int ResolveHost(const char *address, const char *service, int addressType, int flags, AddressInformation* outAddr);
RLAPI int GetAddressFamily(); RLAPI int GetAddressFamily();
RLAPI int GetAddressSocketType(AddressInformation address); RLAPI int GetAddressSocketType(AddressInformation address);
RLAPI int GetAddressProtocol(AddressInformation address); RLAPI int GetAddressProtocol(AddressInformation address);
RLAPI void PrintAddressInfo(AddressInformation address); RLAPI void PrintAddressInfo(AddressInformation address);
RLAPI AddressInformation AllocAddress(); RLAPI AddressInformation AllocAddress();
RLAPI void FreeAddress(AddressInformation* addressInfo);
RLAPI AddressInformation *AllocAddressList(int size); RLAPI AddressInformation *AllocAddressList(int size);
// Socket API // Socket API
@ -1520,12 +1550,12 @@ RLAPI Socket *SocketAccept(Socket *server, SocketConfig *config);
// UDP Socket API // UDP Socket API
RLAPI int SocketSetChannel(Socket *socket, int channel, const IPAddress *address); RLAPI int SocketSetChannel(Socket *socket, int channel, const IPAddress *address);
RLAPI int SocketUnsetChannel(Socket *socket, int channel); RLAPI void SocketUnsetChannel(Socket *socket, int channel);
RLAPI IPAddress* SocketGetPeerAddress(Socket *socket, int channel); RLAPI IPAddress* SocketGetPeerAddress(Socket *socket, int channel);
// General Socket API // General Socket API
RLAPI int SocketSend(Socket *sock, const void *datap, int len); RLAPI int SocketSend(Socket *sock, const void *datap, int len);
RLAPI int SocketReceive(Socket *sock, void *data, int maxlen, int timeout); RLAPI int SocketReceive(Socket *sock, void *data, int maxlen);
RLAPI void SocketClose(Socket* sock); RLAPI void SocketClose(Socket* sock);
RLAPI int SocketReady(Socket* sock); RLAPI int SocketReady(Socket* sock);

View File

@ -43,6 +43,7 @@
#include "raylib.h" #include "raylib.h"
#include <assert.h> // Required for: assert()
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fread() #include <stdio.h> // Required for: FILE, fopen(), fclose(), fread()
#include <stdlib.h> // Required for: malloc(), free() #include <stdlib.h> // Required for: malloc(), free()
#include <string.h> // Required for: strcmp(), strncmp() #include <string.h> // Required for: strcmp(), strncmp()
@ -51,10 +52,7 @@
// Module defines // Module defines
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define NET_SOCKET_BACKLOG_SIZE (20) #define NET_DEBUG_ENABLED (1)
#define NET_MAXHOST (1025) // Max size of a fully-qualified domain name
#define NET_MAXSERV (32) // Max size of a service name
#define NET_DEBUG_ENABLED (0)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
@ -96,7 +94,7 @@ static void *GetSocketPortPtr(struct sockaddr *sa);
static void SocketSetHints(SocketConfig *config, struct addrinfo *hints); static void SocketSetHints(SocketConfig *config, struct addrinfo *hints);
static bool IsIPv4Address(const char *ip); static bool IsIPv4Address(const char *ip);
static bool IsIPv6Address(const char *ip); static bool IsIPv6Address(const char *ip);
static char *SocketAddressToString(struct sockaddr_storage *sockaddr); static const char *SocketAddressToString(struct sockaddr_storage *sockaddr);
static void PrintSocket(struct sockaddr_storage *addr, const int family, const int socktype, const int protocol); static void PrintSocket(struct sockaddr_storage *addr, const int family, const int socktype, const int protocol);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -153,9 +151,11 @@ static void PrintSocket(struct sockaddr_storage *addr, const int family, const i
} }
// Convert network ordered socket address to human readable string (127.0.0.1) // Convert network ordered socket address to human readable string (127.0.0.1)
static char *SocketAddressToString(struct sockaddr_storage *sockaddr) static const char *SocketAddressToString(struct sockaddr_storage *sockaddr)
{ {
static ipv6[INET6_ADDRSTRLEN]; static ipv6[INET6_ADDRSTRLEN];
assert(sockaddr != NULL);
assert(sockaddr->ss_family == AF_INET || sockaddr->ss_family == AF_INET6);
switch (sockaddr->ss_family) { switch (sockaddr->ss_family) {
case AF_INET: { case AF_INET: {
struct sockaddr_in *s = ((struct sockaddr_in *) sockaddr); struct sockaddr_in *s = ((struct sockaddr_in *) sockaddr);
@ -165,10 +165,8 @@ static char *SocketAddressToString(struct sockaddr_storage *sockaddr)
struct sockaddr_in6 *s = ((struct sockaddr_in6 *) sockaddr); struct sockaddr_in6 *s = ((struct sockaddr_in6 *) sockaddr);
return inet_ntop(AF_INET6, &s->sin6_addr, ipv6, INET6_ADDRSTRLEN); return inet_ntop(AF_INET6, &s->sin6_addr, ipv6, INET6_ADDRSTRLEN);
} break; } break;
default: {
return NULL;
} break;
} }
return NULL;
} }
// Check if the null terminated string ip is a valid IPv4 address // Check if the null terminated string ip is a valid IPv4 address
@ -210,7 +208,9 @@ void *GetSocketAddressPtr(struct sockaddr *sa)
// Is the socket in a valid state? // Is the socket in a valid state?
static bool IsSocketValid(Socket *sock) static bool IsSocketValid(Socket *sock)
{ {
if (sock != NULL) { return (sock->channel != INVALID_SOCKET); } if (sock != NULL) {
return (sock->channel != INVALID_SOCKET);
}
return false; return false;
} }
@ -256,7 +256,7 @@ static char *SocketErrorCodeToString(int err)
static bool SocketSetDefaults(SocketConfig *config) static bool SocketSetDefaults(SocketConfig *config)
{ {
if (config->backlog_size == 0) { if (config->backlog_size == 0) {
config->backlog_size = NET_SOCKET_BACKLOG_SIZE; config->backlog_size = SOCKET_MAX_QUEUE_SIZE;
} }
return true; return true;
@ -364,7 +364,7 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult)
} }
// Set socket options // Set socket options
if (!SocketSetOptions(config, outresult->socket->channel)) { if (!SocketSetOptions(config, outresult->socket)) {
outresult->socket->status = SocketGetLastError(); outresult->socket->status = SocketGetLastError();
TraceLog(LOG_WARNING, TraceLog(LOG_WARNING,
"Socket Error: %s", "Socket Error: %s",
@ -398,16 +398,18 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult)
if (outresult->socket->addripv4 != NULL) { if (outresult->socket->addripv4 != NULL) {
memset(outresult->socket->addripv4, 0, memset(outresult->socket->addripv4, 0,
sizeof(*outresult->socket->addripv4)); sizeof(*outresult->socket->addripv4));
} if (outresult->socket->addripv4 != NULL) {
memcpy(&outresult->socket->addripv4->address, memcpy(&outresult->socket->addripv4->address,
(struct sockaddr_in *) res->ai_addr, sizeof(struct sockaddr_in)); (struct sockaddr_in *) res->ai_addr, sizeof(struct sockaddr_in));
outresult->socket->isIPv6 = false; outresult->socket->isIPv6 = false;
char hoststr[NI_MAXHOST]; char hoststr[NI_MAXHOST];
char portstr[NI_MAXSERV]; char portstr[NI_MAXSERV];
socklen_t client_len = sizeof(struct sockaddr_storage); socklen_t client_len = sizeof(struct sockaddr_storage);
int rc = getnameinfo( getnameinfo(
(struct sockaddr *) &outresult->socket->addripv4->address, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); (struct sockaddr *) &outresult->socket->addripv4->address, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
TraceLog(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr); TraceLog(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr);
}
}
} break; } break;
case AF_INET6: { case AF_INET6: {
outresult->socket->addripv6 = (struct _SocketAddressIPv6 *) malloc( outresult->socket->addripv6 = (struct _SocketAddressIPv6 *) malloc(
@ -415,16 +417,18 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult)
if (outresult->socket->addripv6 != NULL) { if (outresult->socket->addripv6 != NULL) {
memset(outresult->socket->addripv6, 0, memset(outresult->socket->addripv6, 0,
sizeof(*outresult->socket->addripv6)); sizeof(*outresult->socket->addripv6));
} if (outresult->socket->addripv6 != NULL) {
memcpy(&outresult->socket->addripv6->address, memcpy(&outresult->socket->addripv6->address,
(struct sockaddr_in6 *) res->ai_addr, sizeof(struct sockaddr_in6)); (struct sockaddr_in6 *) res->ai_addr, sizeof(struct sockaddr_in6));
outresult->socket->isIPv6 = true; outresult->socket->isIPv6 = true;
char hoststr[NI_MAXHOST]; char hoststr[NI_MAXHOST];
char portstr[NI_MAXSERV]; char portstr[NI_MAXSERV];
socklen_t client_len = sizeof(struct sockaddr_storage); socklen_t client_len = sizeof(struct sockaddr_storage);
int rc = getnameinfo( getnameinfo(
(struct sockaddr *) &outresult->socket->addripv6->address, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); (struct sockaddr *) &outresult->socket->addripv6->address, client_len, hoststr, sizeof(hoststr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
TraceLog(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr); TraceLog(LOG_INFO, "Socket address set to %s:%s", hoststr, portstr);
}
}
} break; } break;
} }
} }
@ -474,7 +478,9 @@ static bool SocketSetOptions(SocketConfig *config, Socket *sock)
{ {
for (int i = 0; i < SOCKET_MAX_SOCK_OPTS; i++) { for (int i = 0; i < SOCKET_MAX_SOCK_OPTS; i++) {
SocketOpt *opt = &config->sockopts[i]; SocketOpt *opt = &config->sockopts[i];
if (opt->id == 0) { break; } if (opt->id == 0) {
break;
}
if (setsockopt(sock->channel, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0) { if (setsockopt(sock->channel, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0) {
return false; return false;
@ -487,7 +493,9 @@ static bool SocketSetOptions(SocketConfig *config, Socket *sock)
// Set "hints" in an addrinfo struct, to be passed to getaddrinfo. // Set "hints" in an addrinfo struct, to be passed to getaddrinfo.
static void SocketSetHints(SocketConfig *config, struct addrinfo *hints) static void SocketSetHints(SocketConfig *config, struct addrinfo *hints)
{ {
if (config == NULL || hints == NULL) { return; } if (config == NULL || hints == NULL) {
return;
}
memset(hints, 0, sizeof(*hints)); memset(hints, 0, sizeof(*hints));
// Check if the ip supplied in the config is a valid ipv4 ip ipv6 address // Check if the ip supplied in the config is a valid ipv4 ip ipv6 address
@ -552,12 +560,7 @@ bool InitNetwork()
void CloseNetwork() void CloseNetwork()
{ {
#if PLATFORM == PLATFORM_WINDOWS #if PLATFORM == PLATFORM_WINDOWS
if (WSACleanup() == SOCKET_ERROR) {
if (WSAGetLastError() == WSAEINPROGRESS) {
WSACancelBlockingCall();
WSACleanup(); WSACleanup();
}
}
#endif #endif
} }
@ -606,18 +609,18 @@ void ResolveIP(const char *ip, const char *port, int flags, char *host, char *se
status = getnameinfo(&*((struct sockaddr *) res->ai_addr), status = getnameinfo(&*((struct sockaddr *) res->ai_addr),
sizeof(*((struct sockaddr_in *) res->ai_addr)), sizeof(*((struct sockaddr_in *) res->ai_addr)),
host, host,
NET_MAXHOST, NI_MAXHOST,
serv, serv,
NET_MAXSERV, NI_MAXSERV,
flags); flags);
break; break;
case AF_INET6: case AF_INET6:
status = getnameinfo(&*((struct sockaddr_in6 *) res->ai_addr), status = getnameinfo(&*((struct sockaddr_in6 *) res->ai_addr),
sizeof(*((struct sockaddr_in6 *) res->ai_addr)), sizeof(*((struct sockaddr_in6 *) res->ai_addr)),
host, host,
NET_MAXHOST, NI_MAXHOST,
serv, serv,
NET_MAXSERV, NI_MAXSERV,
flags); flags);
break; break;
default: break; default: break;
@ -639,10 +642,14 @@ void ResolveIP(const char *ip, const char *port, int flags, char *host, char *se
// const char* address = "127.0.0.1" (local address) // const char* address = "127.0.0.1" (local address)
// const char* port = "80" // const char* port = "80"
// //
// Parameters:
// const char* address - A pointer to a NULL-terminated ANSI string that contains a host (node) name or a numeric host address string.
// const char* service - A pointer to a NULL-terminated ANSI string that contains either a service name or port number represented as a string.
//
// Returns: // Returns:
// The total amount of addresses found, -1 on error // The total amount of addresses found, -1 on error
// //
int ResolveHost(const char *address, const char *port, AddressInformation *addrlist) int ResolveHost(const char *address, const char *service, int addressType, int flags, AddressInformation *outAddr)
{ {
// Variables // Variables
int status; // Status value to return (0) is success int status; // Status value to return (0) is success
@ -650,27 +657,41 @@ int ResolveHost(const char *address, const char *port, AddressInformation *addrl
struct addrinfo *res; // will point to the results struct addrinfo *res; // will point to the results
struct addrinfo *iterator; struct addrinfo *iterator;
int portptr; int portptr;
assert(((address != NULL || address != 0) || (service != NULL || service != 0)));
assert(((addressType == AF_INET) || (addressType == AF_INET6) || (addressType == AF_UNSPEC)));
// Set the hints // Set the hints
memset(&hints, 0, sizeof hints); memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // Either IPv4 or IPv6 (AF_INET, AF_INET6) hints.ai_family = addressType; // Either IPv4 or IPv6 (ADDRESS_TYPE_IPV4, ADDRESS_TYPE_IPV6)
hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP) hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP)
hints.ai_flags = flags;
assert(hints.ai_addrlen == NULL || hints.ai_addrlen == 0);
assert(hints.ai_canonname == NULL || hints.ai_canonname == 0);
assert(hints.ai_addr == NULL || hints.ai_addr == 0);
assert(hints.ai_next == NULL || hints.ai_next == 0);
// When the address is NULL, populate the IP for me // When the address is NULL, populate the IP for me
if (address == NULL) { hints.ai_flags = AI_PASSIVE; } if (address == NULL) {
hints.ai_flags |= AI_PASSIVE;
}
TraceLog(LOG_INFO, "Resolving host...");
// Populate address information // Populate address information
status = getaddrinfo(address, // e.g. "www.example.com" or IP status = getaddrinfo(address, // e.g. "www.example.com" or IP
port, // e.g. "http" or port number service, // e.g. "http" or port number
&hints, // e.g. SOCK_STREAM/SOCK_DGRAM &hints, // e.g. SOCK_STREAM/SOCK_DGRAM
&res // The struct to populate &res // The struct to populate
); );
// Did we succeed? // Did we succeed?
if (status != 0) { if (status != 0) {
TraceLog(LOG_WARNING, "Failed to get resolve host %s:%s: %s", address, port, gai_strerror(errno)); int error = SocketGetLastError();
SocketSetLastError(0);
TraceLog(LOG_WARNING, "Failed to get resolve host: %s", SocketErrorCodeToString(error));
return -1;
} else { } else {
TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, port); TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, service);
} }
// Calculate the size of the address information list // Calculate the size of the address information list
@ -685,38 +706,48 @@ int ResolveHost(const char *address, const char *port, AddressInformation *addrl
return -1; return -1;
} }
// If not address list was allocated, allocate it dynamically with the known address size
if (outAddr == NULL) {
outAddr = AllocAddressList(size);
}
// Dynamically allocate an array of address information structs // Dynamically allocate an array of address information structs
if (addrlist != NULL) { if (outAddr != NULL) {
int i; int i;
for (i = 0; i < size; ++i) { for (i = 0; i < size; ++i) {
addrlist[i] = AllocAddress(); outAddr[i] = AllocAddress();
if (addrlist[i] == NULL) { break; } if (outAddr[i] == NULL) {
break;
}
}
outAddr[i] = NULL;
if (i != size) {
outAddr = NULL;
} }
addrlist[i] = NULL;
if (i != size) { addrlist = NULL; }
} else { } else {
TraceLog(LOG_WARNING, TraceLog(LOG_WARNING,
"Error, failed to dynamically allocate memory for the address list"); "Error, failed to dynamically allocate memory for the address list");
return -1;
} }
// Copy all the address information from res into outAddrList // Copy all the address information from res into outAddrList
int i = 0; int i = 0;
for (iterator = res; iterator != NULL; iterator = iterator->ai_next) { for (iterator = res; iterator != NULL; iterator = iterator->ai_next) {
if (i < size) { if (i < size) {
addrlist[i]->addr.ai_flags = iterator->ai_flags; outAddr[i]->addr.ai_flags = iterator->ai_flags;
addrlist[i]->addr.ai_family = iterator->ai_family; outAddr[i]->addr.ai_family = iterator->ai_family;
addrlist[i]->addr.ai_socktype = iterator->ai_socktype; outAddr[i]->addr.ai_socktype = iterator->ai_socktype;
addrlist[i]->addr.ai_protocol = iterator->ai_protocol; outAddr[i]->addr.ai_protocol = iterator->ai_protocol;
addrlist[i]->addr.ai_addrlen = iterator->ai_addrlen; outAddr[i]->addr.ai_addrlen = iterator->ai_addrlen;
memcpy(&addrlist[i]->addr.ai_addr, iterator->ai_addr, iterator->ai_addrlen); *outAddr[i]->addr.ai_addr = *iterator->ai_addr;
#if NET_DEBUG_ENABLED #if NET_DEBUG_ENABLED
TraceLog(LOG_DEBUG, "GetAddressInformation"); TraceLog(LOG_DEBUG, "GetAddressInformation");
TraceLog(LOG_DEBUG, "\tFlags: 0x%x", iterator->ai_flags); TraceLog(LOG_DEBUG, "\tFlags: 0x%x", iterator->ai_flags);
PrintSocket(&addrlist[i]->addr.ai_addr, PrintSocket(outAddr[i]->addr.ai_addr,
addrlist[i]->addr.ai_family, outAddr[i]->addr.ai_family,
addrlist[i]->addr.ai_socktype, outAddr[i]->addr.ai_socktype,
addrlist[i]->addr.ai_protocol); outAddr[i]->addr.ai_protocol);
TraceLog(LOG_DEBUG, "Length of this sockaddr: %d", addrlist[i]->addr.ai_addrlen); TraceLog(LOG_DEBUG, "Length of this sockaddr: %d", outAddr[i]->addr.ai_addrlen);
TraceLog(LOG_DEBUG, "Canonical name: %s", iterator->ai_canonname); TraceLog(LOG_DEBUG, "Canonical name: %s", iterator->ai_canonname);
#endif #endif
i++; i++;
@ -750,7 +781,9 @@ bool SocketCreate(SocketConfig *config, SocketResult *result)
bool success = true; bool success = true;
// Make sure we've not received a null config or result pointer // Make sure we've not received a null config or result pointer
if (config == NULL || result == NULL) { return (success = false); } if (config == NULL || result == NULL) {
return (success = false);
}
// Set the defaults based on the config // Set the defaults based on the config
if (!SocketSetDefaults(config)) { if (!SocketSetDefaults(config)) {
@ -871,7 +904,9 @@ bool SocketConnect(SocketConfig *config, SocketResult *result)
if (IsIPv4Address(config->host)) { if (IsIPv4Address(config->host)) {
struct sockaddr_in ip4addr; struct sockaddr_in ip4addr;
ip4addr.sin_family = AF_INET; ip4addr.sin_family = AF_INET;
ip4addr.sin_port = config->port; unsigned long hport;
hport = strtoul(config->port, NULL, 0);
ip4addr.sin_port = htons(hport);
inet_pton(AF_INET, config->host, &ip4addr.sin_addr); inet_pton(AF_INET, config->host, &ip4addr.sin_addr);
int connect_result = connect(result->socket->channel, (struct sockaddr *) &ip4addr, sizeof(ip4addr)); int connect_result = connect(result->socket->channel, (struct sockaddr *) &ip4addr, sizeof(ip4addr));
if (connect_result == SOCKET_ERROR) { if (connect_result == SOCKET_ERROR) {
@ -897,7 +932,9 @@ bool SocketConnect(SocketConfig *config, SocketResult *result)
if (IsIPv6Address(config->host)) { if (IsIPv6Address(config->host)) {
struct sockaddr_in6 ip6addr; struct sockaddr_in6 ip6addr;
ip6addr.sin6_family = AF_INET6; ip6addr.sin6_family = AF_INET6;
ip6addr.sin6_port = config->port; unsigned long hport;
hport = strtoul(config->port, NULL, 0);
ip6addr.sin6_port = htons(hport);
inet_pton(AF_INET6, config->host, &ip6addr.sin6_addr); inet_pton(AF_INET6, config->host, &ip6addr.sin6_addr);
int connect_result = connect(result->socket->channel, (struct sockaddr *) &ip6addr, sizeof(ip6addr)); int connect_result = connect(result->socket->channel, (struct sockaddr *) &ip6addr, sizeof(ip6addr));
if (connect_result == SOCKET_ERROR) { if (connect_result == SOCKET_ERROR) {
@ -938,7 +975,9 @@ bool SocketConnect(SocketConfig *config, SocketResult *result)
void SocketClose(Socket *sock) void SocketClose(Socket *sock)
{ {
if (sock != NULL) { if (sock != NULL) {
if (sock->channel != INVALID_SOCKET) { closesocket(sock->channel); } if (sock->channel != INVALID_SOCKET) {
closesocket(sock->channel);
}
} }
} }
@ -960,7 +999,9 @@ void SocketClose(Socket *sock)
// } // }
Socket *SocketAccept(Socket *server, SocketConfig *config) Socket *SocketAccept(Socket *server, SocketConfig *config)
{ {
if (!server->isServer || server->type == SOCKET_UDP) { return NULL; } if (!server->isServer || server->type == SOCKET_UDP) {
return NULL;
}
struct sockaddr_storage sock_addr; struct sockaddr_storage sock_addr;
socklen_t sock_alen; socklen_t sock_alen;
Socket * sock; Socket * sock;
@ -1025,10 +1066,14 @@ int SocketSetChannel(Socket *socket, int channel, const IPAddress *address)
if (channel == -1) { if (channel == -1) {
for (channel = 0; channel < SOCKET_MAX_UDPCHANNELS; ++channel) { for (channel = 0; channel < SOCKET_MAX_UDPCHANNELS; ++channel) {
binding = &socket->binding[channel]; binding = &socket->binding[channel];
if (binding->numbound < SOCKET_MAX_UDPADDRESSES) { break; } if (binding->numbound < SOCKET_MAX_UDPADDRESSES) {
break;
}
} }
} else { } else {
if (!ValidChannel(channel)) { return (-1); } if (!ValidChannel(channel)) {
return (-1);
}
binding = &socket->binding[channel]; binding = &socket->binding[channel];
} }
if (binding->numbound == SOCKET_MAX_UDPADDRESSES) { if (binding->numbound == SOCKET_MAX_UDPADDRESSES) {
@ -1040,7 +1085,7 @@ int SocketSetChannel(Socket *socket, int channel, const IPAddress *address)
} }
// Remove the socket channel // Remove the socket channel
int SocketUnsetChannel(Socket *socket, int channel) void SocketUnsetChannel(Socket *socket, int channel)
{ {
if ((channel >= 0) && (channel < SOCKET_MAX_UDPCHANNELS)) { if ((channel >= 0) && (channel < SOCKET_MAX_UDPCHANNELS)) {
socket->binding[channel].numbound = 0; socket->binding[channel].numbound = 0;
@ -1144,7 +1189,7 @@ int SocketSend(Socket *sock, const void *datap, int length)
// This function returns the actual amount of data received. If the return // This function returns the actual amount of data received. If the return
// value is less than or equal to zero, then either the remote connection was // value is less than or equal to zero, then either the remote connection was
// closed, or an unknown socket error occurred. // closed, or an unknown socket error occurred.
int SocketReceive(Socket *sock, void *data, int maxlen, int timeout) int SocketReceive(Socket *sock, void *data, int maxlen)
{ {
int len = 0; int len = 0;
int numrecv = 0; int numrecv = 0;
@ -1260,7 +1305,9 @@ bool IsSocketConnected(Socket *sock)
} else if (total == 0) { // Timeout } else if (total == 0) { // Timeout
return false; return false;
} else { } else {
if (FD_ISSET(sock->channel, &writefds)) { return true; } if (FD_ISSET(sock->channel, &writefds)) {
return true;
}
} }
return false; return false;
#else #else
@ -1287,7 +1334,9 @@ SocketResult *AllocSocketResult()
void FreeSocketResult(SocketResult **result) void FreeSocketResult(SocketResult **result)
{ {
if (*result != NULL) { if (*result != NULL) {
if ((*result)->socket != NULL) { FreeSocket(&((*result)->socket)); } if ((*result)->socket != NULL) {
FreeSocket(&((*result)->socket));
}
free(*result); free(*result);
*result = NULL; *result = NULL;
} }
@ -1332,7 +1381,9 @@ SocketSet *AllocSocketSet(int max)
set->maxsockets = max; set->maxsockets = max;
set->sockets = (struct Socket **) malloc(max * sizeof(*set->sockets)); set->sockets = (struct Socket **) malloc(max * sizeof(*set->sockets));
if (set->sockets != NULL) { if (set->sockets != NULL) {
for (i = 0; i < max; ++i) { set->sockets[i] = NULL; } for (i = 0; i < max; ++i) {
set->sockets[i] = NULL;
}
} else { } else {
free(set); free(set);
set = NULL; set = NULL;
@ -1375,7 +1426,9 @@ int RemoveSocket(SocketSet *set, Socket *sock)
if (sock != NULL) { if (sock != NULL) {
for (i = 0; i < set->numsockets; ++i) { for (i = 0; i < set->numsockets; ++i) {
if (set->sockets[i] == (struct Socket *) sock) { break; } if (set->sockets[i] == (struct Socket *) sock) {
break;
}
} }
if (i == set->numsockets) { if (i == set->numsockets) {
TraceLog(LOG_DEBUG, "Socket Error: %s", "Socket not found"); TraceLog(LOG_DEBUG, "Socket Error: %s", "Socket not found");
@ -1473,9 +1526,32 @@ void FreePacket(Packet *packet)
// Allocate an AddressInformation // Allocate an AddressInformation
AddressInformation AllocAddress() AddressInformation AllocAddress()
{ {
AddressInformation addr; AddressInformation addressInfo = NULL;
addr = (AddressInformation) calloc(1, sizeof(*addr)); addressInfo = (AddressInformation) calloc(1, sizeof(*addressInfo));
return addr; if (addressInfo != NULL) {
addressInfo->addr.ai_addr = (struct sockaddr *) calloc(1, sizeof(struct sockaddr));
if (addressInfo->addr.ai_addr == NULL) {
TraceLog(LOG_WARNING,
"Failed to allocate memory for \"struct sockaddr\"");
}
} else {
TraceLog(LOG_WARNING,
"Failed to allocate memory for \"struct AddressInformation\"");
}
return addressInfo;
}
// Free an AddressInformation struct
void FreeAddress(AddressInformation *addressInfo)
{
if (*addressInfo != NULL) {
if ((*addressInfo)->addr.ai_addr != NULL) {
free((*addressInfo)->addr.ai_addr);
(*addressInfo)->addr.ai_addr = NULL;
}
free(*addressInfo);
*addressInfo = NULL;
}
} }
// Allocate a list of AddressInformation // Allocate a list of AddressInformation