added opaque data types

added stubs and started tests
This commit is contained in:
Jak Barnes 2019-03-03 23:37:44 +00:00
parent 082a0c85ce
commit 9cc0f80909
6 changed files with 653 additions and 213 deletions

View File

@ -27,9 +27,9 @@ char buffer[MAX_BUFFER_SIZE];
float elapsed = 0.0f; float elapsed = 0.0f;
float delay = 1.0f; float delay = 1.0f;
bool connected = false; bool connected = false;
SocketConfig client_cfg = {.host = "127.0.0.1", .port = "8080", .nonblocking = true};
SocketResult* client_res = NULL; SocketResult* client_res = NULL;
SocketSet* socket_set = NULL; SocketSet* socket_set = NULL;
SocketConfig client_cfg = {.host = "127.0.0.1", .port = "8080", .nonblocking = true};
void NetworkConnect() void NetworkConnect()
{ {

View File

@ -0,0 +1,114 @@
#include "raylib.h"
#include <assert.h>
void test_network_initialise()
{
assert(InitNetwork() == true);
}
void test_socket_result()
{
SocketResult *result = AllocSocketResult();
assert(result != NULL);
FreeSocketResult(&result);
assert(result == NULL);
}
void test_socket()
{
Socket *socket = AllocSocket();
assert(socket != NULL);
FreeSocket(&socket);
assert(socket == NULL);
}
void test_resolve_ip()
{
const char *host = "8.8.8.8";
const char *port = "8080";
char ip[ADDRESS_IPV6_ADDRSTRLEN];
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_NUMERICHOST, ip);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "8.8.8.8") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_DEFAULT, ip);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "google-public-dns-a.google.com") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_NOFQDN, ip);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "google-public-dns-a") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_NUMERICHOST, ip);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "8.8.8.8") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_NAMEREQD, ip);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "google-public-dns-a.google.com") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_NUMERICSERV, ip);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "google-public-dns-a.google.com") == 0);
memset(ip, '\0', ADDRESS_IPV6_ADDRSTRLEN);
ResolveIP(host, port, NAME_INFO_DGRAM, ip);
TraceLog(LOG_INFO, "Resolved %s to %s", host, ip);
assert(strcmp(ip, "google-public-dns-a.google.com") == 0);
}
void test_resolve_host()
{
const char * address = "localhost";
const char * port = "80";
struct _AddressInformation **addr = AllocAddressList(3);
int count = ResolveHost(address, port, addr);
assert(GetAddressFamily(addr[0]) == ADDRESS_TYPE_IPV6);
assert(GetAddressFamily(addr[1]) == ADDRESS_TYPE_IPV4);
for (size_t i = 0; i < count; i++) { PrintAddressInfo(addr[i]); }
}
void test_address()
{
}
void test_address_list()
{
}
int main()
{
int screenWidth = 800;
int screenHeight = 450;
InitWindow(
screenWidth, screenHeight, "raylib [network] example - network test");
SetTargetFPS(60);
// Run the tests
test_network_initialise();
// test_socket_result();
// test_socket();
// test_resolve_ip();
test_resolve_host();
// Main game loop
while (!WindowShouldClose()) {
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
EndDrawing();
}
CloseWindow();
return 0;
}

View File

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug.DLL|Win32">
<Configuration>Debug.DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release.DLL|Win32">
<Configuration>Release.DLL</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4297B501-7D79-4192-BC79-C6A8121B6C83}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>network_test</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<ProjectName>network_test</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)$(ProjectName)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(ProjectName)\$(Configuration)\temp\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(ProjectDir)$(ProjectName)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(ProjectName)\$(Configuration)\temp</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)$(ProjectName)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(ProjectName)\$(Configuration)\temp</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)$(ProjectName)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)$(ProjectName)\$(Configuration)\temp</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAs>CompileAsC</CompileAs>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug.DLL|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CompileAs>CompileAsC</CompileAs>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release.DLL|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<RemoveUnreferencedCodeData>true</RemoveUnreferencedCodeData>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\examples\network\network_test.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\raylib\raylib.vcxproj">
<Project>{e89d61ac-55de-4482-afd4-df7242ebc859}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -29,6 +29,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "network_udp_client", "examp
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "network_udp_server", "examples\network_udp_server.vcxproj", "{C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "network_udp_server", "examples\network_udp_server.vcxproj", "{C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "network_test", "examples\network_test.vcxproj", "{4297B501-7D79-4192-BC79-C6A8121B6C83}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug.DLL|x64 = Debug.DLL|x64 Debug.DLL|x64 = Debug.DLL|x64
@ -221,6 +223,18 @@ Global
{C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A}.Release|x64.Build.0 = Release|x64 {C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A}.Release|x64.Build.0 = Release|x64
{C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A}.Release|x86.ActiveCfg = Release|Win32 {C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A}.Release|x86.ActiveCfg = Release|Win32
{C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A}.Release|x86.Build.0 = Release|Win32 {C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A}.Release|x86.Build.0 = Release|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Debug.DLL|x64.ActiveCfg = Debug.DLL|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Debug|x64.ActiveCfg = Debug|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Debug|x86.ActiveCfg = Debug|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Debug|x86.Build.0 = Debug|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Release.DLL|x64.ActiveCfg = Release.DLL|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Release.DLL|x86.Build.0 = Release.DLL|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Release|x64.ActiveCfg = Release|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Release|x86.ActiveCfg = Release|Win32
{4297B501-7D79-4192-BC79-C6A8121B6C83}.Release|x86.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -237,6 +251,7 @@ Global
{B7AA867E-AA24-4CD6-A61E-5A0B9A068131} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} {B7AA867E-AA24-4CD6-A61E-5A0B9A068131} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
{0207D9BA-25E0-44A0-9B54-952FFDA3D58D} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} {0207D9BA-25E0-44A0-9B54-952FFDA3D58D} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
{C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} {C8C754B7-E53D-4D7D-A3F7-F52F5B55FA2A} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
{4297B501-7D79-4192-BC79-C6A8121B6C83} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}

View File

@ -109,6 +109,12 @@
#define SOCKET_MAX_UDPCHANNELS (32) #define SOCKET_MAX_UDPCHANNELS (32)
#define SOCKET_MAX_UDPADDRESSES (4) #define SOCKET_MAX_UDPADDRESSES (4)
//
#define ADDRESS_IPV4_ADDRSTRLEN 22
#define ADDRESS_IPV6_ADDRSTRLEN 65
#define ADDRESS_TYPE_IPV4 2
#define ADDRESS_TYPE_IPV6 23
// getnameinfo() defines // getnameinfo() defines
#define NAME_INFO_DEFAULT 0x00 /* No flags set */ #define NAME_INFO_DEFAULT 0x00 /* No flags set */
#define NAME_INFO_NOFQDN 0x01 /* Only return nodename portion for local hosts */ #define NAME_INFO_NOFQDN 0x01 /* Only return nodename portion for local hosts */
@ -586,6 +592,13 @@ typedef struct Packet
uint8_t* data; // Data stored in network byte order uint8_t* data; // Data stored in network byte order
} Packet; } Packet;
//
typedef struct _AddressInformation * AddressInformation;
typedef struct _SocketAddress * SocketAddress;
typedef struct _SocketAddressIPv4 * SocketAddressIPv4;
typedef struct _SocketAddressIPv6 * SocketAddressIPv6;
typedef struct _SocketAddressStorage *SocketAddressStorage;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Enumerators Definition // Enumerators Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -1576,22 +1589,31 @@ extern "C"
RLAPI bool InitNetwork(void); RLAPI bool InitNetwork(void);
RLAPI void CloseNetwork(void); RLAPI void CloseNetwork(void);
// Protocol-independent name resolution from an address to an ANSI host name and from a port number to the ANSI service name. // Address API
RLAPI char *ResolveIP(const char *host, const char *port, int flags); RLAPI void ResolveIP(const char *host, const char *port, int flags, char* outhost);
RLAPI int ResolveHost(const char *address, const char *port, struct _AddressInformation* addr);
// Protocol-independent translation from an ANSI host name to an address. RLAPI int GetAddressFamily();
RLAPI char *ResolveHost(const char *address, const char *port); RLAPI int GetAddressSocketType(AddressInformation address);
RLAPI int GetAddressProtocol(AddressInformation address);
RLAPI void PrintAddressInfo(AddressInformation address);
RLAPI AddressInformation AllocAddress();
RLAPI struct _AddressInformation **AllocAddressList(int size);
// Socket API // Socket API
RLAPI bool SocketCreate(SocketConfig *cfg, SocketResult *res); RLAPI bool SocketCreate(SocketConfig *cfg, SocketResult *res);
RLAPI void SocketClose(SocketChannel socket);
RLAPI bool SocketListen(SocketConfig *cfg, SocketResult *res); RLAPI bool SocketListen(SocketConfig *cfg, SocketResult *res);
RLAPI bool SocketConnect(SocketConfig *cfg, SocketResult *res); RLAPI bool SocketConnect(SocketConfig *cfg, SocketResult *res);
RLAPI void SocketClose(SocketChannel socket);
RLAPI Socket *SocketAccept(Socket *server, SocketConfig *cfg); RLAPI Socket *SocketAccept(Socket *server, SocketConfig *cfg);
RLAPI int SocketSend(Socket *socket, const void *datap, int len); RLAPI int SocketSend(Socket *socket, const void *datap, int len);
RLAPI int SocketReceive(Socket *socket, void *data, int maxlen, int timeout); RLAPI int SocketReceive(Socket *socket, void *data, int maxlen, int timeout);
// Socket set methods for async i/o RLAPI Socket *AllocSocket();
RLAPI SocketResult *AllocSocketResult();
RLAPI void FreeSocket(Socket **sock);
RLAPI void FreeSocketResult(SocketResult **result);
// Socket I/O API
RLAPI bool IsSocketReady(Socket* sock); RLAPI bool IsSocketReady(Socket* sock);
RLAPI SocketSet* AllocSocketSet(int max); RLAPI SocketSet* AllocSocketSet(int max);
RLAPI void FreeSocketSet(SocketSet* sockset); RLAPI void FreeSocketSet(SocketSet* sockset);
@ -1599,14 +1621,7 @@ extern "C"
RLAPI int RemoveSocket(SocketSet* set, Socket* sock); RLAPI int RemoveSocket(SocketSet* set, Socket* sock);
RLAPI int CheckSockets(SocketSet* set, unsigned int timeout); RLAPI int CheckSockets(SocketSet* set, unsigned int timeout);
// Creation and allocation // Packet API
RLAPI SocketResult *AllocSocketResult();
RLAPI void FreeSocketResult(SocketResult *result);
RLAPI Socket *AllocSocket();
RLAPI void FreeSocket(Socket *sock);
// Data packets and helpers
Packet * AllocPacket(int size); Packet * AllocPacket(int size);
void FreePacket(Packet *packet); void FreePacket(Packet *packet);
void PacketSend(Packet* packet); void PacketSend(Packet* packet);

View File

@ -39,25 +39,62 @@
// Check if config flags have been externally provided on compilation line // Check if config flags have been externally provided on compilation line
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(RNET_STANDALONE)
# include "rnet.h"
# include <stdarg.h>
#else
# include "raylib.h"
# include "sysnet.h"
# if !defined(EXTERNAL_CONFIG_FLAGS) # if !defined(EXTERNAL_CONFIG_FLAGS)
# include "config.h" // Defines module configuration flags # include "config.h" // Defines module configuration flags
# endif # endif
#endif
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fread()
#include <stdlib.h> // Required for: malloc(), free()
#include <string.h> // Required for: strcmp(), strncmp()
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module defines // Module defines
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define SOCKET_BACKLOG_SIZE (20) #define NET_SOCKET_BACKLOG_SIZE (20)
#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)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module dependencies // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#include "raylib.h" #if PLATFORM == PLATFORM_WINDOWS
#include "sysnet.h" typedef socklen_t _SocketLength;
typedef SOCKADDR _SocketAddress;
typedef SOCKADDR_IN _SocketAddressIPv4;
typedef SOCKADDR_IN6 _SocketAddressIPv6;
typedef SOCKADDR_STORAGE _SocketAddressStorage;
typedef struct _AddressInformation {
int ai_flags; // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST
int ai_family; // PF_xxx
int ai_socktype; // SOCK_xxx
int ai_protocol; // 0 or IPPROTO_xxx for IPv4 and IPv6
size_t ai_addrlen; // Length of ai_addr
struct sockaddr_storage ai_addr; // Binary address
} _AddressInformation;
#else
#endif
//---------------------------------------------------------------------------------- #if defined(RNET_STANDALONE)
// Module variables typedef enum {
//---------------------------------------------------------------------------------- LOG_ALL,
LOG_TRACE,
LOG_DEBUG,
LOG_INFO,
LOG_WARNING,
LOG_ERROR,
LOG_FATAL,
LOG_NONE
} TraceLogType;
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global module forward declarations // Global module forward declarations
@ -79,8 +116,8 @@ static void* GetSocketPortPtr(struct sockaddr* sa);
static void SocketSetHints(SocketConfig *cfg, struct addrinfo *hints); static void SocketSetHints(SocketConfig *cfg, 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* sockaddr, char buffer[], int* port); static char *SocketAddressToString(struct sockaddr_storage *sockaddr, char buffer[], int *port);
static void PrintSocket(struct sockaddr* 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);
static bool FillIPv4SockAddress(struct sockaddr_in *sa, const char *host, unsigned short port); static bool FillIPv4SockAddress(struct sockaddr_in *sa, const char *host, unsigned short port);
static bool FillIPv6SockAddress(struct sockaddr_in6 *sa, const char *host, unsigned short port); static bool FillIPv6SockAddress(struct sockaddr_in6 *sa, const char *host, unsigned short port);
@ -88,6 +125,7 @@ static bool FillIPv6SockAddress(struct sockaddr_in6* sa, const char* host, unsig
// Global module implementationd // Global module implementationd
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
//
static bool FillIPv4SockAddress(struct sockaddr_in *sa, const char *host, unsigned short port) static bool FillIPv4SockAddress(struct sockaddr_in *sa, const char *host, unsigned short port)
{ {
sa->sin_family = AF_INET; sa->sin_family = AF_INET;
@ -102,6 +140,7 @@ static bool FillIPv4SockAddress(struct sockaddr_in* sa, const char* host, unsign
return true; return true;
} }
//
static bool FillIPv6SockAddress(struct sockaddr_in6 *sa, const char *host, unsigned short port) static bool FillIPv6SockAddress(struct sockaddr_in6 *sa, const char *host, unsigned short port)
{ {
sa->sin6_family = AF_INET6; sa->sin6_family = AF_INET6;
@ -117,7 +156,7 @@ static bool FillIPv6SockAddress(struct sockaddr_in6* sa, const char* host, unsig
} }
// Print socket information // Print socket information
static void PrintSocket(struct sockaddr* 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)
{ {
struct sockaddr *sockaddr_ip; struct sockaddr *sockaddr_ip;
char ip[INET6_ADDRSTRLEN]; // Enough pace to hold a IPv6 string char ip[INET6_ADDRSTRLEN]; // Enough pace to hold a IPv6 string
@ -169,10 +208,10 @@ static void PrintSocket(struct sockaddr* addr, const int family, const int sockt
} }
// 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* sockaddr) static char *SocketAddressToString(struct sockaddr_storage *sockaddr)
{ {
static ipv6[INET6_ADDRSTRLEN]; static ipv6[INET6_ADDRSTRLEN];
switch (sockaddr->sa_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);
return inet_ntop(AF_INET, &s->sin_addr, ipv6, INET_ADDRSTRLEN); return inet_ntop(AF_INET, &s->sin_addr, ipv6, INET_ADDRSTRLEN);
@ -272,7 +311,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 = SOCKET_BACKLOG_SIZE; config->backlog_size = NET_SOCKET_BACKLOG_SIZE;
} }
return true; return true;
@ -547,18 +586,12 @@ void CloseNetwork()
// NAME_INFO_NAMEREQD 0x04 // Error if the host's name not in DNS // NAME_INFO_NAMEREQD 0x04 // Error if the host's name not in DNS
// NAME_INFO_NUMERICSERV 0x08 // Return numeric form of the service (port #) // NAME_INFO_NUMERICSERV 0x08 // Return numeric form of the service (port #)
// NAME_INFO_DGRAM 0x10 // Service is a datagram service // NAME_INFO_DGRAM 0x10 // Service is a datagram service
char* ResolveIP(const char* ip, const char* port, int flags) void ResolveIP(const char *ip, const char *port, int flags, char *host, char *serv)
{ {
// Variables // Variables
char host[NI_MAXHOST];
char service[NI_MAXSERV];
int status; // Status value to return (0) is success int status; // Status value to return (0) is success
struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
struct addrinfo* results; // A pointer to the resulting address list struct addrinfo *res; // A pointer to the resulting address list
// Zero out the host buffer
memset(&host, '\0', sizeof(host));
memset(&service, '\0', sizeof(service));
// Set the hints // Set the hints
memset(&hints, 0, sizeof hints); memset(&hints, 0, sizeof hints);
@ -569,7 +602,7 @@ char* ResolveIP(const char* ip, const char* port, int flags)
status = getaddrinfo(ip, // e.g. "www.example.com" or IP status = getaddrinfo(ip, // e.g. "www.example.com" or IP
port, // e.g. "http" or port number port, // e.g. "http" or port number
&hints, // e.g. SOCK_STREAM/SOCK_DGRAM &hints, // e.g. SOCK_STREAM/SOCK_DGRAM
&results // The struct to populate &res // The struct to populate
); );
// Did we succeed? // Did we succeed?
@ -580,40 +613,36 @@ char* ResolveIP(const char* ip, const char* port, int flags)
} }
// Attempt to resolve network byte order ip to hostname // Attempt to resolve network byte order ip to hostname
switch (results->ai_family) { switch (res->ai_family) {
case AF_INET: case AF_INET:
status = getnameinfo(&*((struct sockaddr*) results->ai_addr), status = getnameinfo(&*((struct sockaddr *) res->ai_addr),
sizeof(*((struct sockaddr_in*) results->ai_addr)), sizeof(*((struct sockaddr_in *) res->ai_addr)),
host, host,
sizeof(host), NET_MAXHOST,
service, serv,
NI_MAXSERV, NET_MAXSERV,
flags); flags);
break; break;
case AF_INET6: case AF_INET6:
status = getnameinfo(&*((struct sockaddr_in6*) results->ai_addr), status = getnameinfo(&*((struct sockaddr_in6 *) res->ai_addr),
sizeof(*((struct sockaddr_in6*) results->ai_addr)), sizeof(*((struct sockaddr_in6 *) res->ai_addr)),
host, host,
sizeof(host), NET_MAXHOST,
service, serv,
NI_MAXSERV, NET_MAXSERV,
flags); flags);
break; break;
default: break; default: break;
} }
// Did we succeed?
if (status != 0) { if (status != 0) {
TraceLog(LOG_WARNING, "Failed to resolve ip %s: %s", ip, SocketGetLastErrorString()); TraceLog(LOG_WARNING, "Failed to resolve ip %s: %s", ip, SocketGetLastErrorString());
} else { } else {
TraceLog(LOG_INFO, "Successfully resolved %s::%s to %s", ip, port, host); TraceLog(LOG_DEBUG, "Successfully resolved %s::%s to %s", ip, port, host);
} }
// Free the pointer to the data returned by addrinfo // Free the pointer to the data returned by addrinfo
freeaddrinfo(results); freeaddrinfo(res);
// Return the resulting hostname
return host;
} }
// Protocol-independent translation from an ANSI host name to an address // Protocol-independent translation from an ANSI host name to an address
@ -621,13 +650,17 @@ char* ResolveIP(const char* ip, const char* port, int flags)
// e.g. // e.g.
// 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"
char* ResolveHost(const char* address, const char* port) //
// returns:
// the total amount of addresses found
//
int ResolveHost(const char *address, const char *port, AddressInformation *outAddrList)
{ {
// Variables // Variables
int status; // Status value to return (0) is success int status; // Status value to return (0) is success
struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
struct addrinfo* results; // A pointer to the resulting address list struct addrinfo *res; // will point to the results
char ip[INET6_ADDRSTRLEN]; // Enough pace to hold a IPv6 string struct addrinfo *iterator;
int portptr; int portptr;
// Set the hints // Set the hints
@ -642,7 +675,7 @@ char* ResolveHost(const char* address, const char* port)
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 port, // e.g. "http" or port number
&hints, // e.g. SOCK_STREAM/SOCK_DGRAM &hints, // e.g. SOCK_STREAM/SOCK_DGRAM
&results // The struct to populate &res // The struct to populate
); );
// Did we succeed? // Did we succeed?
@ -652,23 +685,61 @@ char* ResolveHost(const char* address, const char* port)
TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, port); TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, port);
} }
struct addrinfo* iterator; // Calculate the size of the address information list
for (iterator = results; iterator != NULL; iterator = iterator->ai_next) { int size = 0;
for (iterator = res; iterator != NULL; iterator = iterator->ai_next) {
size++;
}
// Validate the size is > 0, otherwise return
if (size <= 0) {
TraceLog(LOG_WARNING, "Error, no addresses found.");
return;
}
// Dynamically allocate an array of address information structs
if (outAddrList != NULL) {
int i;
for (i = 0; i < size; ++i) {
outAddrList[i] = AllocAddress();
if (outAddrList[i] == NULL) { break; }
}
outAddrList[i] = NULL;
if (i != size) { outAddrList = NULL; }
} else {
TraceLog(LOG_WARNING,
"Error, failed to dynamically allocate memory for the address list");
}
// Copy all the address information from res into outAddrList
int i = 0;
for (iterator = res; iterator != NULL; iterator = iterator->ai_next) {
if (i < size) {
outAddrList[i]->ai_flags = iterator->ai_flags;
outAddrList[i]->ai_family = iterator->ai_family;
outAddrList[i]->ai_socktype = iterator->ai_socktype;
outAddrList[i]->ai_protocol = iterator->ai_protocol;
outAddrList[i]->ai_addrlen = iterator->ai_addrlen;
memcpy(&outAddrList[i]->ai_addr, iterator->ai_addr, iterator->ai_addrlen);
#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(iterator->ai_addr, PrintSocket(&outAddrList[i]->ai_addr,
iterator->ai_family, outAddrList[i]->ai_family,
iterator->ai_socktype, outAddrList[i]->ai_socktype,
iterator->ai_protocol); outAddrList[i]->ai_protocol);
TraceLog(LOG_DEBUG, "Length of this sockaddr: %d", iterator->ai_addrlen); TraceLog(LOG_DEBUG, "Length of this sockaddr: %d", outAddrList[i]->ai_addrlen);
TraceLog(LOG_DEBUG, "Canonical name: %s", iterator->ai_canonname); TraceLog(LOG_DEBUG, "Canonical name: %s", iterator->ai_canonname);
#endif
i++;
}
} }
// Free the pointer to the data returned by addrinfo // Free the pointer to the data returned by addrinfo
freeaddrinfo(results); freeaddrinfo(res);
// Return the resulting hostname // Return the total count of addresses found
return SocketAddressToString(results->ai_addr, ip, &portptr); return size;
} }
// This here is the bread and butter of the socket API, This function will // This here is the bread and butter of the socket API, This function will
@ -1027,9 +1098,13 @@ SocketResult* AllocSocketResult()
} }
// //
void FreeSocketResult(SocketResult* result) void FreeSocketResult(SocketResult **result)
{ {
if (result != NULL) { free(result); } if (*result != NULL) {
if ((*result)->socket != NULL) { FreeSocket(&((*result)->socket)); }
free(*result);
*result = NULL;
}
} }
// //
@ -1051,10 +1126,12 @@ Socket* AllocSocket()
} }
// //
void FreeSocket(Socket* sock) void FreeSocket(Socket **sock)
{ {
SocketClose(sock); if (*sock != NULL) {
free(sock); free(*sock);
*sock = NULL;
}
} }
// //
@ -1207,6 +1284,43 @@ void FreePacket(Packet* packet)
} }
} }
//
AddressInformation AllocAddress()
{
AddressInformation addr;
addr = (AddressInformation) calloc(1, sizeof(*addr));
return addr;
}
//
AddressInformation *AllocAddressList(int size)
{
AddressInformation *addr;
addr = (AddressInformation *) malloc(size * sizeof(AddressInformation));
return addr;
}
int GetAddressSocketType(AddressInformation address)
{
return address->ai_socktype;
}
int GetAddressProtocol(AddressInformation address)
{
return address->ai_protocol;
}
int GetAddressFamily(AddressInformation address)
{
return address->ai_family;
}
//
void PrintAddressInfo(AddressInformation addr)
{
PrintSocket(&addr->ai_addr, addr->ai_family, addr->ai_socktype, addr->ai_protocol);
}
// //
void PacketSend(Packet *packet) void PacketSend(Packet *packet)
{ {