added more api calls to rnet.c, updated examples to support ipv4/6
Signed-off-by: Jak Barnes <contact@jakbarnes.co.uk>
This commit is contained in:
parent
bb01a49398
commit
38dce94577
|
|
@ -31,27 +31,38 @@ int main()
|
||||||
screenWidth, screenHeight, "raylib [network] example - ping pong");
|
screenWidth, screenHeight, "raylib [network] example - ping pong");
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
|
|
||||||
|
SetTraceLogLevel(LOG_INFO);
|
||||||
|
|
||||||
// Networking
|
// Networking
|
||||||
TCPSocket server;
|
|
||||||
TCPSocket client;
|
|
||||||
TCPSocket connection;
|
|
||||||
ResetSocket(&server);
|
|
||||||
ResetSocket(&client);
|
|
||||||
ResetSocket(&connection);
|
|
||||||
|
|
||||||
InitNetwork();
|
InitNetwork();
|
||||||
CreateTCPListenServer(&server, "127.0.0.1", "3490");
|
|
||||||
CreateTCPClient(&client, "127.0.0.1", "3490");
|
|
||||||
|
|
||||||
// Timer
|
// Server socket and address
|
||||||
|
AddressInformation serveraddr;
|
||||||
|
Socket server;
|
||||||
|
server.blocking = false;
|
||||||
|
GetAddressInformation(&serveraddr, "localhost", "3490", SOCKET_TCP, PROTOCOL_TCP);
|
||||||
|
CreateSocket(&server, serveraddr);
|
||||||
|
BindSocket(server, serveraddr);
|
||||||
|
ListenSocket(server);
|
||||||
|
|
||||||
|
// Client socket and address
|
||||||
|
AddressInformation clientaddr;
|
||||||
|
Socket client;
|
||||||
|
client.blocking = false;
|
||||||
|
GetAddressInformation(&clientaddr, "localhost", "3490", SOCKET_TCP, PROTOCOL_TCP);
|
||||||
|
CreateSocket(&client, clientaddr);
|
||||||
|
ConnectSocket(client, clientaddr);
|
||||||
|
|
||||||
|
Socket connection; // The socket connection between server->client
|
||||||
float elapsed = 0.0f, delay = 1.0f; // ms
|
float elapsed = 0.0f, delay = 1.0f; // ms
|
||||||
bool ping = false, pong = false;
|
bool ping = false, pong = false;
|
||||||
char recvBuffer[512];
|
char recvBuffer[512];
|
||||||
|
bool connected = false;
|
||||||
memset(&recvBuffer, 0, 8);
|
memset(&recvBuffer, 0, 8);
|
||||||
|
|
||||||
// Main game loop
|
// Main game loop
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose())
|
||||||
|
{
|
||||||
// Draw
|
// Draw
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
|
|
||||||
|
|
@ -59,34 +70,43 @@ int main()
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
// A valid connection will != -1
|
// A valid connection will != -1
|
||||||
if (!connection.ready) {
|
if (!connected)
|
||||||
AcceptIncomingConnections(&connection, server.sockfd);
|
{
|
||||||
|
AcceptSocket(server, &connection);
|
||||||
ping = true;
|
ping = true;
|
||||||
|
connected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connected
|
// Connected
|
||||||
if (connection.ready) {
|
if (connected)
|
||||||
|
{
|
||||||
int bytesRecv = ReceiveTCP(connection.sockfd, recvBuffer, 5);
|
int bytesRecv = ReceiveTCP(connection.handle, recvBuffer, 5);
|
||||||
if (bytesRecv > 0) {
|
if (bytesRecv > 0)
|
||||||
if (strcmp(recvBuffer, "Ping!") == 0) {
|
{
|
||||||
|
if (strcmp(recvBuffer, "Ping!") == 0)
|
||||||
|
{
|
||||||
pong = true;
|
pong = true;
|
||||||
printf("Ping!\n");
|
printf("Ping!\n");
|
||||||
}
|
}
|
||||||
if (strcmp(recvBuffer, "Pong!") == 0) {
|
if (strcmp(recvBuffer, "Pong!") == 0)
|
||||||
|
{
|
||||||
ping = true;
|
ping = true;
|
||||||
printf("Pong!\n");
|
printf("Pong!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed += GetFrameTime();
|
elapsed += GetFrameTime();
|
||||||
if (elapsed > delay) {
|
if (elapsed > delay)
|
||||||
if (ping) {
|
{
|
||||||
|
if (ping)
|
||||||
|
{
|
||||||
ping = false;
|
ping = false;
|
||||||
SendTCP(client.sockfd, "Ping!", 5);
|
SendTCP(client.handle, "Ping!", 5);
|
||||||
} else if (pong) {
|
}
|
||||||
|
else if (pong)
|
||||||
|
{
|
||||||
pong = false;
|
pong = false;
|
||||||
SendTCP(client.sockfd, "Pong!", 5);
|
SendTCP(client.handle, "Pong!", 5);
|
||||||
}
|
}
|
||||||
elapsed = 0.0f;
|
elapsed = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,13 @@ int main()
|
||||||
|
|
||||||
// Networking
|
// Networking
|
||||||
InitNetwork();
|
InitNetwork();
|
||||||
ResolveHost("www.raylib.com");
|
ResolveHost("www.google.com");
|
||||||
|
ResolveIP("2001:4860:4860::8888");
|
||||||
|
ResolveIP("8.8.8.8");
|
||||||
|
|
||||||
// Main game loop
|
// Main game loop
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose())
|
||||||
|
{
|
||||||
// Draw
|
// Draw
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
<ProjectGuid>{0981CA98-E4A5-4DF1-987F-A41D09131EFC}</ProjectGuid>
|
<ProjectGuid>{0981CA98-E4A5-4DF1-987F-A41D09131EFC}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>core_basic_window</RootNamespace>
|
<RootNamespace>core_basic_window</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||||
<ProjectName>core_basic_window</ProjectName>
|
<ProjectName>core_basic_window</ProjectName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
<ProjectGuid>{B655E850-3322-42F7-941D-6AC18FD66CA1}</ProjectGuid>
|
<ProjectGuid>{B655E850-3322-42F7-941D-6AC18FD66CA1}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
<RootNamespace>raylib_example_cpp</RootNamespace>
|
<RootNamespace>raylib_example_cpp</RootNamespace>
|
||||||
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||||
<ProjectName>core_basic_window_cpp</ProjectName>
|
<ProjectName>core_basic_window_cpp</ProjectName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "network_ping_pong", "exampl
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_basic_window", "examples\core_basic_window.vcxproj", "{0981CA98-E4A5-4DF1-987F-A41D09131EFC}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_basic_window", "examples\core_basic_window.vcxproj", "{0981CA98-E4A5-4DF1-987F-A41D09131EFC}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "network_interfaces", "examples\network_interfaces.vcxproj", "{A16D19CB-6AF4-4D17-8318-EABD8805247C}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "network_resolve_host", "examples\network_interfaces.vcxproj", "{A16D19CB-6AF4-4D17-8318-EABD8805247C}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "network_stream_client", "examples\network_stream_client.vcxproj", "{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
|
@ -95,6 +97,22 @@ Global
|
||||||
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release|x64.Build.0 = Release|x64
|
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release|x64.Build.0 = Release|x64
|
||||||
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release|x86.ActiveCfg = Release|Win32
|
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release|x86.Build.0 = Release|Win32
|
{A16D19CB-6AF4-4D17-8318-EABD8805247C}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Debug.DLL|x64.ActiveCfg = Debug|x64
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Debug.DLL|x64.Build.0 = Debug|x64
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Debug.DLL|x86.ActiveCfg = Debug|Win32
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Debug.DLL|x86.Build.0 = Debug|Win32
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Release.DLL|x64.ActiveCfg = Release|x64
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Release.DLL|x64.Build.0 = Release|x64
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Release.DLL|x86.ActiveCfg = Release|Win32
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Release.DLL|x86.Build.0 = Release|Win32
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Release|x64.Build.0 = Release|x64
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D}.Release|x86.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -104,6 +122,7 @@ Global
|
||||||
{56EB485C-00A9-459E-B758-2E86316EB7FD} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
|
{56EB485C-00A9-459E-B758-2E86316EB7FD} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
|
||||||
{0981CA98-E4A5-4DF1-987F-A41D09131EFC} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
|
{0981CA98-E4A5-4DF1-987F-A41D09131EFC} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
|
||||||
{A16D19CB-6AF4-4D17-8318-EABD8805247C} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
|
{A16D19CB-6AF4-4D17-8318-EABD8805247C} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
|
||||||
|
{BC49AAF0-E8C2-4F94-A60A-C56993023C6D} = {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}
|
||||||
|
|
|
||||||
84
src/raylib.h
84
src/raylib.h
|
|
@ -97,6 +97,10 @@
|
||||||
#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 limits
|
||||||
|
#define MAX_SOCKET_SET_SIZE 32
|
||||||
|
#define MAX_SOCKET_QUEUE_SIZE 16
|
||||||
|
|
||||||
// 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.
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
@ -151,6 +155,9 @@
|
||||||
typedef enum { false, true } bool;
|
typedef enum { false, true } bool;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Network typedefs
|
||||||
|
typedef int SocketHandle;
|
||||||
|
|
||||||
// Vector2 type
|
// Vector2 type
|
||||||
typedef struct Vector2 {
|
typedef struct Vector2 {
|
||||||
float x;
|
float x;
|
||||||
|
|
@ -418,17 +425,56 @@ typedef struct VrStereoConfig {
|
||||||
int eyeViewportLeft[4]; // VR stereo rendering left eye viewport [x, y, w, h]
|
int eyeViewportLeft[4]; // VR stereo rendering left eye viewport [x, y, w, h]
|
||||||
} VrStereoConfig;
|
} VrStereoConfig;
|
||||||
|
|
||||||
// TCP Stream socket
|
typedef struct AddressInformation
|
||||||
typedef struct TCPSocket {
|
{
|
||||||
int sockfd;
|
int flags; // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST
|
||||||
int server;
|
int family; // PF_xxx
|
||||||
bool ready;
|
int socktype; // SOCK_xxx
|
||||||
} TCPSocket;
|
int protocol; // 0 or IPPROTO_xxx for IPv4 and IPv6
|
||||||
|
size_t addrlen; // Length of ai_addr
|
||||||
|
char * canonname; // Canonical name for nodename
|
||||||
|
struct SocketAddress *sockaddr; // Binary address
|
||||||
|
struct AddressInformation *next; // Next structure in linked list
|
||||||
|
} AddressInformation;
|
||||||
|
|
||||||
|
typedef struct SocketAddress
|
||||||
|
{
|
||||||
|
unsigned short family; // Address family.
|
||||||
|
char data[14]; // Up to 14 bytes of direct address.
|
||||||
|
} SocketAddress;
|
||||||
|
|
||||||
|
// Socket
|
||||||
|
typedef struct Socket
|
||||||
|
{
|
||||||
|
SocketHandle handle;
|
||||||
|
bool blocking;
|
||||||
|
} Socket;
|
||||||
|
|
||||||
|
typedef struct SocketSet
|
||||||
|
{
|
||||||
|
Socket sockets[MAX_SOCKET_SET_SIZE];
|
||||||
|
} SocketSet;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Enumerators Definition
|
// Enumerators Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SOCKET_ANY = 0, // ACCEPT_ALL
|
||||||
|
SOCKET_TCP = 1, // SOCK_STREAM
|
||||||
|
SOCKET_UDP = 2 // SOCK_DGRAM
|
||||||
|
} SocketType;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PROTOCOL_ANY = 0, // ACCEPT_ALL
|
||||||
|
PROTOCOL_TCP = 6, // IPPROTO_TCP
|
||||||
|
PROTOCOL_UDP = 17 // IPPROTO_UDP
|
||||||
|
} ProtocolType;
|
||||||
|
|
||||||
// System config flags
|
// System config flags
|
||||||
// NOTE: Used for bit masks
|
// NOTE: Used for bit masks
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -1385,13 +1431,27 @@ RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pit
|
||||||
// Network functions
|
// Network functions
|
||||||
RLAPI bool InitNetwork(void);
|
RLAPI bool InitNetwork(void);
|
||||||
RLAPI void CloseNetwork(void);
|
RLAPI void CloseNetwork(void);
|
||||||
RLAPI void CreateTCPListenServer(TCPSocket* socket, const char* address, const int port);
|
|
||||||
RLAPI void CreateTCPClient(TCPSocket* socket, const char* address, const char* port);
|
RLAPI void GetAddressInformation(AddressInformation* outaddr, const char* address, const char* port, int socketType, int protocolType);
|
||||||
RLAPI void AcceptIncomingConnections(TCPSocket* sock, int sockfd);
|
|
||||||
RLAPI int SendTCP(int sockfd, const char* data, int len);
|
RLAPI bool CreateSocket(Socket *socket, AddressInformation outaddr);
|
||||||
RLAPI int ReceiveTCP(int sockfd, const char* data, int len);
|
RLAPI bool BindSocket(Socket socket, const AddressInformation addr);
|
||||||
RLAPI void ResetSocket(TCPSocket* socket);
|
RLAPI bool ConnectSocket(Socket socket, const AddressInformation addr);
|
||||||
|
RLAPI bool ListenSocket(Socket socket);
|
||||||
|
RLAPI void CloseSocket(Socket* socket);
|
||||||
|
RLAPI void AcceptSocket(Socket listenSock, Socket *newSock);
|
||||||
|
|
||||||
|
RLAPI char* SocketAddressToString(SocketAddress* sockaddr, char buffer[]);
|
||||||
|
RLAPI void PrintSocket(SocketAddress* addr, const int family, const int socktype, const int protocol);
|
||||||
RLAPI void ResolveHost(const char* hostname);
|
RLAPI void ResolveHost(const char* hostname);
|
||||||
|
RLAPI void ResolveIP(const char* ip);
|
||||||
|
|
||||||
|
RLAPI void CreateListenServer(Socket* socket, const char* address, const int port, SocketType socketType);
|
||||||
|
RLAPI void CreateClient(Socket* socket, const char* address, const char* port, SocketType socketType);
|
||||||
|
RLAPI int Send(SocketHandle sockfd, const char* data, int len);
|
||||||
|
RLAPI int Receive(SocketHandle sockfd, const char* data, int len);
|
||||||
|
RLAPI void ResetSocket(Socket* socket);
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
472
src/rnet.c
472
src/rnet.c
|
|
@ -47,14 +47,20 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define errno WSAGetLastError()
|
||||||
|
|
||||||
|
// Initialise the network (requires for windows platforms only)
|
||||||
bool InitNetwork()
|
bool InitNetwork()
|
||||||
{
|
{
|
||||||
#if PLATFORM == PLATFORM_WINDOWS
|
#if PLATFORM == PLATFORM_WINDOWS
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) == NO_ERROR) {
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) == NO_ERROR)
|
||||||
|
{
|
||||||
TraceLog(LOG_INFO, "WinSock initialised.");
|
TraceLog(LOG_INFO, "WinSock initialised.");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TraceLog(LOG_WARNING, "WinSock failed to initialise.");
|
TraceLog(LOG_WARNING, "WinSock failed to initialise.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -63,6 +69,7 @@ bool InitNetwork()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cleanup, and close the network
|
||||||
void CloseNetwork()
|
void CloseNetwork()
|
||||||
{
|
{
|
||||||
#if PLATFORM == PLATFORM_WINDOWS
|
#if PLATFORM == PLATFORM_WINDOWS
|
||||||
|
|
@ -70,7 +77,8 @@ void CloseNetwork()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateTCPListenServer(TCPSocket* tcpsock, const char* address, const char* port)
|
// Get address information
|
||||||
|
void GetAddressInformation(AddressInformation* outaddr, const char* address, const char* port, int socketType, int protocolType)
|
||||||
{
|
{
|
||||||
// Variables
|
// Variables
|
||||||
int status; // Status value to return (0) is success
|
int status; // Status value to return (0) is success
|
||||||
|
|
@ -79,8 +87,166 @@ void CreateTCPListenServer(TCPSocket* tcpsock, const char* address, const char*
|
||||||
|
|
||||||
// Set the hints
|
// Set the hints
|
||||||
memset(&hints, 0, sizeof hints);
|
memset(&hints, 0, sizeof hints);
|
||||||
hints.ai_family = AF_INET; // Either IPv4 or IPv6 (AF_INET, AF_INET6)
|
hints.ai_family = AF_UNSPEC; // Either IPv4 or IPv6 (AF_INET, AF_INET6)
|
||||||
hints.ai_socktype = SOCK_STREAM; // TCP (SOCK_STREAM), UDP (SOCK_DGRAM)
|
hints.ai_socktype = socketType; // TCP (SOCK_STREAM), UDP (SOCK_DGRAM)
|
||||||
|
hints.ai_protocol = protocolType; // TCP (IPPROTO_TCP), UDP (IPPROTO_UDP)
|
||||||
|
|
||||||
|
// Populate address information
|
||||||
|
status = getaddrinfo(address, // e.g. "www.example.com" or IP
|
||||||
|
port, // e.g. "http" or port number
|
||||||
|
&hints, // e.g. SOCK_STREAM/SOCK_DGRAM
|
||||||
|
&results // The struct to populate
|
||||||
|
);
|
||||||
|
|
||||||
|
memcpy(outaddr, results, sizeof(struct addrinfo));
|
||||||
|
|
||||||
|
// Did we succeed?
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to get resolve host %s:%s: %ls", address, port, gai_strerror(status));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct addrinfo* iterator;
|
||||||
|
for (iterator = outaddr; iterator != NULL; iterator = iterator->ai_next)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_DEBUG, "GetAddressInformation");
|
||||||
|
TraceLog(LOG_DEBUG, "Flags: 0x%x", iterator->ai_flags);
|
||||||
|
PrintSocket(iterator->ai_addr,
|
||||||
|
iterator->ai_family,
|
||||||
|
iterator->ai_socktype,
|
||||||
|
iterator->ai_protocol);
|
||||||
|
TraceLog(LOG_DEBUG, "Length of this sockaddr: %d", iterator->ai_addrlen);
|
||||||
|
TraceLog(LOG_DEBUG, "Canonical name: %s", iterator->ai_canonname);
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a socket from information provided by the filled Address information struct
|
||||||
|
bool CreateSocket(Socket* sock, const AddressInformation addr)
|
||||||
|
{
|
||||||
|
// Create a socket from provided address data
|
||||||
|
sock->handle = socket(addr.family, addr.socktype, addr.protocol);
|
||||||
|
|
||||||
|
// Did we succeed?
|
||||||
|
if (sock->handle == INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to get create socket: %ls", gai_strerror(sock->handle));
|
||||||
|
CloseSocket(sock->handle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TraceLog(LOG_INFO, "Successfully created socket");
|
||||||
|
PrintSocket(addr.sockaddr, addr.family, addr.socktype, addr.protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if we've successfully created the socket
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind the socket to a specific port, this is usually used if you're going to listen for incoming connections on a specific port
|
||||||
|
bool BindSocket(Socket sock, const AddressInformation addr)
|
||||||
|
{
|
||||||
|
// Bind the socket handle to the socket address defined in sockaddr
|
||||||
|
int status = bind(sock.handle, addr.sockaddr, addr.addrlen);
|
||||||
|
|
||||||
|
// Did we succeed?
|
||||||
|
if (status == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to get bind socket: %ls", gai_strerror(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buff[INET6_ADDRSTRLEN];
|
||||||
|
TraceLog(LOG_INFO, "Successfully bound socket to address: %s", SocketAddressToString(addr.sockaddr, buff));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if we've successfully bound the socket
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect the socket to an address
|
||||||
|
bool ConnectSocket(Socket socket, AddressInformation addr)
|
||||||
|
{
|
||||||
|
int status = connect(socket.handle, addr.sockaddr, addr.addrlen);
|
||||||
|
|
||||||
|
// Did we succeed?
|
||||||
|
if (status == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to connect socket: %ls", gai_strerror(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buff[INET6_ADDRSTRLEN];
|
||||||
|
TraceLog(LOG_INFO, "Successfully connected socket to address: %s", SocketAddressToString(addr.sockaddr, buff));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if we've successfully connected the socket
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
bool ListenSocket(Socket socket)
|
||||||
|
{
|
||||||
|
int status = listen(socket.handle, MAX_SOCKET_QUEUE_SIZE);
|
||||||
|
|
||||||
|
// Did we succeed?
|
||||||
|
if (status == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to listen to socket: %ls", gai_strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TraceLog(LOG_INFO, "Success, socket now listening");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the socket i/o mode to blocking, or non-blocking
|
||||||
|
unsigned long blocking = socket.blocking ? 0 : 1;
|
||||||
|
status = ioctlsocket(socket.handle, FIONBIO, &blocking);
|
||||||
|
|
||||||
|
if (status != NO_ERROR)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_WARNING, "Failed to set socket io mode to: %s", (blocking ? "non-blocking" : "blocking"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TraceLog(LOG_INFO, "Successfully set socket io mode to: %s", (blocking ? "non-blocking" : "blocking"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if we've successfully connected the socket
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close a socket
|
||||||
|
void CloseSocket(Socket* socket)
|
||||||
|
{
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
closesocket(socket);
|
||||||
|
#elif PLATFORM == PLATFORM_UNIX
|
||||||
|
close(socket);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void CreateListenServer(Socket* tcpsock, const char* address, const char* port, SocketType socketType)
|
||||||
|
{
|
||||||
|
// Variables
|
||||||
|
int status; // Status value to return (0) is success
|
||||||
|
struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?)
|
||||||
|
struct addrinfo* results; // A pointer to the resulting address list
|
||||||
|
|
||||||
|
// Set the hints
|
||||||
|
memset(&hints, 0, sizeof hints);
|
||||||
|
hints.ai_family = AF_UNSPEC; // Either IPv4 or IPv6 (AF_INET, AF_INET6)
|
||||||
|
hints.ai_socktype = socketType; // TCP (SOCK_STREAM), UDP (SOCK_DGRAM)
|
||||||
|
|
||||||
// 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
|
||||||
|
|
@ -90,39 +256,51 @@ void CreateTCPListenServer(TCPSocket* tcpsock, const char* address, const char*
|
||||||
);
|
);
|
||||||
|
|
||||||
// Did we succeed?
|
// Did we succeed?
|
||||||
if (status == -1) {
|
if (status == -1)
|
||||||
TraceLog(LOG_WARNING, "Failed to get resolve host %s:%s: %s", address, port, strerror(status));
|
{
|
||||||
} else {
|
TraceLog(LOG_WARNING, "Failed to get resolve host %s:%s: %ls", address, port, gai_strerror(status));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, port);
|
TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create our server socket
|
// Create our server socket
|
||||||
int sockfd = socket(results->ai_family, results->ai_socktype, results->ai_protocol);
|
int handle = socket(results->ai_family, results->ai_socktype, results->ai_protocol);
|
||||||
|
|
||||||
// Bind it to the port we passed in to getaddrinfo():
|
// Bind it to the port we passed in to getaddrinfo():
|
||||||
status = bind(sockfd, results->ai_addr, results->ai_addrlen);
|
status = bind(handle, results->ai_addr, results->ai_addrlen);
|
||||||
|
|
||||||
// Did we succeed?
|
// Did we succeed?
|
||||||
if (status == -1) {
|
if (status == -1)
|
||||||
TraceLog(LOG_WARNING, "Failed to get bind socket to port (%s): %s", port, strerror(errno));
|
{
|
||||||
} else {
|
TraceLog(LOG_WARNING, "Failed to get bind socket to port (%s): %ls", port, gai_strerror(errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TraceLog(LOG_INFO, "Successfully bound %s to port (%s)", address, port);
|
TraceLog(LOG_INFO, "Successfully bound %s to port (%s)", address, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen on the bound port
|
// Listen on the bound port
|
||||||
status = listen(sockfd, 5);
|
status = listen(handle, 5);
|
||||||
|
|
||||||
// Did we succeed?
|
// Did we succeed?
|
||||||
if (status == -1) {
|
if (status == -1)
|
||||||
TraceLog(LOG_WARNING, "Failed to listen to socket: %s", strerror(errno));
|
{
|
||||||
} else {
|
TraceLog(LOG_WARNING, "Failed to listen to socket: %ls", gai_strerror(errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TraceLog(LOG_INFO, "Successfully started listen server.");
|
TraceLog(LOG_INFO, "Successfully started listen server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD nonBlocking = 1;
|
DWORD nonBlocking = 1;
|
||||||
if (ioctlsocket(sockfd, FIONBIO, &nonBlocking) == -1) {
|
if (ioctlsocket(handle, FIONBIO, &nonBlocking) == -1)
|
||||||
|
{
|
||||||
TraceLog(LOG_WARNING, "Failed to set socket to non-blocking.");
|
TraceLog(LOG_WARNING, "Failed to set socket to non-blocking.");
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TraceLog(LOG_INFO, "Successfully set socket to non-blocking.");
|
TraceLog(LOG_INFO, "Successfully set socket to non-blocking.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,109 +308,128 @@ void CreateTCPListenServer(TCPSocket* tcpsock, const char* address, const char*
|
||||||
freeaddrinfo(results);
|
freeaddrinfo(results);
|
||||||
|
|
||||||
// Finally, return our socket descriptor
|
// Finally, return our socket descriptor
|
||||||
tcpsock->sockfd = sockfd;
|
tcpsock->handle = handle;
|
||||||
tcpsock->server = 1;
|
|
||||||
tcpsock->ready = true;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateTCPClient(TCPSocket* tcpsock, char* address, char* port)
|
//
|
||||||
|
void CreateClient(Socket* tcpsock, char* address, char* port, SocketType socketType)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
int sockfd;
|
int handle;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo* results; // Will point to the results
|
struct addrinfo* results; // Will point to the results
|
||||||
|
|
||||||
memset(&hints, 0, sizeof hints); // Make sure the struct is empty
|
memset(&hints, 0, sizeof hints); // Make sure the struct is empty
|
||||||
hints.ai_family = AF_UNSPEC; // Don't care IPv4 or IPv6
|
hints.ai_family = AF_UNSPEC; // Don't care IPv4 or IPv6
|
||||||
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
|
hints.ai_socktype = socketType; // TCP stream sockets
|
||||||
|
|
||||||
// Get ready to connect
|
// Get ready to connect
|
||||||
status = getaddrinfo(address, port, &hints, &results);
|
status = getaddrinfo(address, port, &hints, &results);
|
||||||
|
|
||||||
// Did we succeed?
|
// Did we succeed?
|
||||||
if (status != 0) {
|
if (status != 0)
|
||||||
TraceLog(LOG_WARNING, "Failed to get address information: %s", strerror(errno));
|
{
|
||||||
} else {
|
TraceLog(LOG_WARNING, "Failed to get address information: %ls", gai_strerror(errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TraceLog(LOG_INFO, "Successfully created TCP client on port (%s)", port);
|
TraceLog(LOG_INFO, "Successfully created TCP client on port (%s)", port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create our socket
|
// Create our socket
|
||||||
sockfd = socket(results->ai_family, results->ai_socktype, results->ai_protocol);
|
handle = socket(results->ai_family, results->ai_socktype, results->ai_protocol);
|
||||||
|
|
||||||
// Did it succeed?
|
// Did it succeed?
|
||||||
if (sockfd == -1) {
|
if (handle == -1)
|
||||||
TraceLog(LOG_WARNING, "Failed to create socket: %s", strerror(errno));
|
{
|
||||||
} else {
|
TraceLog(LOG_WARNING, "Failed to create socket: %ls", gai_strerror(errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TraceLog(LOG_INFO, "Successfully created socket");
|
TraceLog(LOG_INFO, "Successfully created socket");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to the server
|
// Connect to the server
|
||||||
status = connect(sockfd, results->ai_addr, results->ai_addrlen);
|
status = connect(handle, results->ai_addr, results->ai_addrlen);
|
||||||
|
|
||||||
if (status == -1) {
|
if (status == -1)
|
||||||
|
{
|
||||||
TraceLog(LOG_WARNING, "Failed to connect to server %s:%s", address, port);
|
TraceLog(LOG_WARNING, "Failed to connect to server %s:%s", address, port);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TraceLog(LOG_INFO, "Successfully connected to %s:%s", address, port);
|
TraceLog(LOG_INFO, "Successfully connected to %s:%s", address, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(results);
|
freeaddrinfo(results);
|
||||||
|
|
||||||
// Finally, return our socket descriptor
|
// Finally, return our socket descriptor
|
||||||
tcpsock->sockfd = sockfd;
|
tcpsock->handle = handle;
|
||||||
tcpsock->server = 0;
|
|
||||||
tcpsock->ready = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AcceptIncomingConnections(TCPSocket* tcpsock, int sockfd)
|
//
|
||||||
|
void AcceptSocket(Socket listenSock, Socket* newSock)
|
||||||
{
|
{
|
||||||
struct sockaddr_storage their_addr;
|
struct sockaddr_storage their_addr;
|
||||||
socklen_t addr_size;
|
socklen_t addrSize;
|
||||||
int new_fd;
|
int newHandle;
|
||||||
addr_size = sizeof their_addr;
|
addrSize = sizeof their_addr;
|
||||||
new_fd = accept(sockfd, (struct sockaddr*) &their_addr, &addr_size);
|
newHandle = accept(listenSock.handle, (struct sockaddr*) &their_addr, &addrSize);
|
||||||
|
|
||||||
if (new_fd == -1) {
|
if (newHandle == INVALID_SOCKET)
|
||||||
TraceLog(LOG_DEBUG, "Failed to accept incoming connection: %s", strerror(errno));
|
{
|
||||||
} else {
|
TraceLog(LOG_DEBUG, "Failed to accept incoming connection: %ls", gai_strerror(errno));
|
||||||
tcpsock->sockfd = new_fd;
|
}
|
||||||
tcpsock->server = false;
|
else
|
||||||
tcpsock->ready = true;
|
{
|
||||||
|
newSock->handle = newHandle;
|
||||||
TraceLog(LOG_INFO, "Successfully accepted a new connection.");
|
TraceLog(LOG_INFO, "Successfully accepted a new connection.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SendTCP(int sockfd, const char* data, int len)
|
//
|
||||||
|
int SendTCP(SocketHandle handle, const char* data, int len)
|
||||||
{
|
{
|
||||||
int sentBytes = send(sockfd, data, len, 0);
|
int sentBytes = send(handle, data, len, 0);
|
||||||
if (sentBytes == -1) {
|
if (sentBytes == SOCKET_ERROR)
|
||||||
TraceLog(LOG_WARNING, "Failed to send data: %s", strerror(errno));
|
{
|
||||||
} else {
|
TraceLog(LOG_WARNING, "Failed to send data: %ls", gai_strerror(errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
TraceLog(LOG_DEBUG, "Successfully sent %d bytes.", sentBytes);
|
TraceLog(LOG_DEBUG, "Successfully sent %d bytes.", sentBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReceiveTCP(int sockfd, const char* data, int len)
|
//
|
||||||
|
int ReceiveTCP(SocketHandle handle, const char* data, int len)
|
||||||
{
|
{
|
||||||
int receiveBytes = recv(sockfd, data, len, 0);
|
int status = recv(handle, data, len, 0);
|
||||||
if (receiveBytes == -1) {
|
if (status == SOCKET_ERROR && errno == EWOULDBLOCK)
|
||||||
TraceLog(LOG_DEBUG, "Failed to receive data: %s", strerror(errno));
|
{
|
||||||
} else if (receiveBytes == 0) {
|
TraceLog(LOG_DEBUG, "Failed to receive data: %ls", gai_strerror(errno));
|
||||||
TraceLog(LOG_INFO, "Connection closed.");
|
|
||||||
} else {
|
|
||||||
TraceLog(LOG_DEBUG, "Successfully received %d bytes.", receiveBytes);
|
|
||||||
}
|
}
|
||||||
return receiveBytes;
|
else if (status > 0)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_DEBUG, "Successfully received %d bytes.", status);
|
||||||
|
}
|
||||||
|
else if (status == 0)
|
||||||
|
{
|
||||||
|
TraceLog(LOG_INFO, "Connection closed.");
|
||||||
|
}
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetSocket(TCPSocket* socket)
|
// Reset a socket
|
||||||
|
void ResetSocket(Socket* socket)
|
||||||
{
|
{
|
||||||
socket->ready = false;
|
socket->handle = -1;
|
||||||
socket->server = 0;
|
socket->blocking = false;
|
||||||
socket->sockfd = -1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Resolve the hostname
|
||||||
void ResolveHost(const char* hostname)
|
void ResolveHost(const char* hostname)
|
||||||
{
|
{
|
||||||
struct addrinfo hints, *res, *p;
|
struct addrinfo hints, *res, *p;
|
||||||
|
|
@ -240,27 +437,32 @@ void ResolveHost(const char* hostname)
|
||||||
char ipstr[INET6_ADDRSTRLEN];
|
char ipstr[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
memset(&hints, 0, sizeof hints);
|
memset(&hints, 0, sizeof hints);
|
||||||
hints.ai_family = AF_INET; // AF_INET or AF_INET6 to force version
|
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
|
if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0)
|
||||||
TraceLog(LOG_WARNING, "getaddrinfo: %s", strerror(status));
|
{
|
||||||
|
TraceLog(LOG_WARNING, "getaddrinfo: %ls", gai_strerror(status));
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceLog(LOG_INFO, "IP addresses for %s:", hostname);
|
TraceLog(LOG_INFO, "IP addresses for %s:", hostname);
|
||||||
|
|
||||||
for (p = res; p != NULL; p = p->ai_next) {
|
for (p = res; p != NULL; p = p->ai_next)
|
||||||
|
{
|
||||||
void* addr;
|
void* addr;
|
||||||
char* ipver;
|
char* ipver;
|
||||||
|
|
||||||
// get the pointer to the address itself,
|
// get the pointer to the address itself,
|
||||||
// different fields in IPv4 and IPv6:
|
// different fields in IPv4 and IPv6:
|
||||||
if (p->ai_family == AF_INET) { // IPv4
|
if (p->ai_family == AF_INET)
|
||||||
|
{ // IPv4
|
||||||
struct sockaddr_in* ipv4 = (struct sockaddr_in*) p->ai_addr;
|
struct sockaddr_in* ipv4 = (struct sockaddr_in*) p->ai_addr;
|
||||||
addr = &(ipv4->sin_addr);
|
addr = &(ipv4->sin_addr);
|
||||||
ipver = "IPv4";
|
ipver = "IPv4";
|
||||||
} else { // IPv6
|
}
|
||||||
|
else
|
||||||
|
{ // IPv6
|
||||||
struct sockaddr_in6* ipv6 = (struct sockaddr_in6*) p->ai_addr;
|
struct sockaddr_in6* ipv6 = (struct sockaddr_in6*) p->ai_addr;
|
||||||
addr = &(ipv6->sin6_addr);
|
addr = &(ipv6->sin6_addr);
|
||||||
ipver = "IPv6";
|
ipver = "IPv6";
|
||||||
|
|
@ -273,3 +475,127 @@ void ResolveHost(const char* hostname)
|
||||||
|
|
||||||
freeaddrinfo(res); // free the linked list
|
freeaddrinfo(res); // free the linked list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve the hostname
|
||||||
|
void ResolveIP(const char* ip)
|
||||||
|
{
|
||||||
|
struct hostent* he;
|
||||||
|
struct in_addr ipv4addr;
|
||||||
|
struct in6_addr ipv6addr;
|
||||||
|
inet_pton(AF_INET, ip, &ipv4addr);
|
||||||
|
he = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET);
|
||||||
|
if (he != NULL)
|
||||||
|
{
|
||||||
|
printf("Host name: %s\n", he->h_name);
|
||||||
|
}
|
||||||
|
inet_pton(AF_INET6, ip, &ipv6addr);
|
||||||
|
he = gethostbyaddr(&ipv6addr, sizeof ipv6addr, AF_INET6);
|
||||||
|
if (he != NULL)
|
||||||
|
{
|
||||||
|
printf("Host name: %s\n", he->h_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print socket information
|
||||||
|
void PrintSocket(struct SocketAddress* addr, const int family, const int socktype, const int protocol)
|
||||||
|
{
|
||||||
|
struct sockaddr_in* sockaddr_ipv4;
|
||||||
|
struct sockaddr_in6* sockaddr_ipv6;
|
||||||
|
struct sockaddr* sockaddr_ip;
|
||||||
|
char ip4[INET_ADDRSTRLEN]; // space to hold the IPv4 string
|
||||||
|
char ip6[INET6_ADDRSTRLEN]; // space to hold the IPv6 string
|
||||||
|
switch (family)
|
||||||
|
{
|
||||||
|
case AF_UNSPEC:
|
||||||
|
{
|
||||||
|
TraceLog(LOG_DEBUG, "Family: Unspecified");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AF_INET:
|
||||||
|
{
|
||||||
|
TraceLog(LOG_DEBUG, "Family: AF_INET (IPv4)");
|
||||||
|
TraceLog(LOG_INFO, "- IPv4 address %s", SocketAddressToString(addr, ip4));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
{
|
||||||
|
TraceLog(LOG_DEBUG, "Family: AF_INET6 (IPv6)");
|
||||||
|
TraceLog(LOG_INFO, "- IPv6 address %s", SocketAddressToString(addr, ip6));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AF_NETBIOS:
|
||||||
|
{
|
||||||
|
TraceLog(LOG_DEBUG, "Family: AF_NETBIOS (NetBIOS)");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
TraceLog(LOG_DEBUG, "Family: Other %ld", family);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TraceLog(LOG_DEBUG, "Socket type:");
|
||||||
|
switch (socktype)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
TraceLog(LOG_DEBUG, "- Unspecified");
|
||||||
|
break;
|
||||||
|
case SOCK_STREAM:
|
||||||
|
TraceLog(LOG_DEBUG, "- SOCK_STREAM (stream)");
|
||||||
|
break;
|
||||||
|
case SOCK_DGRAM:
|
||||||
|
TraceLog(LOG_DEBUG, "- SOCK_DGRAM (datagram)");
|
||||||
|
break;
|
||||||
|
case SOCK_RAW:
|
||||||
|
TraceLog(LOG_DEBUG, "- SOCK_RAW (raw)");
|
||||||
|
break;
|
||||||
|
case SOCK_RDM:
|
||||||
|
TraceLog(LOG_DEBUG, "- SOCK_RDM (reliable message datagram)");
|
||||||
|
break;
|
||||||
|
case SOCK_SEQPACKET:
|
||||||
|
TraceLog(LOG_DEBUG, "- SOCK_SEQPACKET (pseudo-stream packet)");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TraceLog(LOG_DEBUG, "- Other %ld", socktype);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TraceLog(LOG_DEBUG, "Protocol:");
|
||||||
|
switch (protocol)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
TraceLog(LOG_DEBUG, "- Unspecified");
|
||||||
|
break;
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
TraceLog(LOG_DEBUG, "- IPPROTO_TCP (TCP)");
|
||||||
|
break;
|
||||||
|
case IPPROTO_UDP:
|
||||||
|
TraceLog(LOG_DEBUG, "- IPPROTO_UDP (UDP)");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TraceLog(LOG_DEBUG, "- Other %ld", protocol);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert network ordered socket address to human readable string (127.0.0.1)
|
||||||
|
char* SocketAddressToString(struct SocketAddress* sockaddr, char buffer[])
|
||||||
|
{
|
||||||
|
switch (sockaddr->family)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
{
|
||||||
|
return inet_ntop(AF_INET, &((struct sockaddr_in*) sockaddr)->sin_addr, buffer, INET_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
{
|
||||||
|
return inet_ntop(AF_INET6, &((struct sockaddr_in6*) sockaddr)->sin6_addr, buffer, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user