updated rnet api, fixed ping-pong example
This commit is contained in:
parent
22249b72cf
commit
38b77c7cc0
|
|
@ -27,50 +27,61 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
char recvBuffer[512];
|
float elapsed = 0.0f;
|
||||||
float elapsed = 0.0f;
|
float delay = 1.0f;
|
||||||
float delay = 1.0f;
|
bool ping = false;
|
||||||
bool ping = false;
|
bool pong = false;
|
||||||
bool pong = false;
|
bool connected = false;
|
||||||
bool connected = false;
|
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", .server = true, .nonblocking = true};
|
SocketConfig server_cfg = {.host = "127.0.0.1", .port = "8080", .datagram = true, .server = true, .nonblocking = true};
|
||||||
SocketConfig client_cfg = {.host = "127.0.0.1", .port = "8080", .nonblocking = true};
|
SocketConfig client_cfg = {.host = "127.0.0.1", .port = "8080", .datagram = true, .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;
|
||||||
SocketSet* socket_set = NULL;
|
SocketSet * socket_set = NULL;
|
||||||
Socket* connection = NULL;
|
Socket * connection = NULL;
|
||||||
|
char recvBuffer[512];
|
||||||
/*
|
|
||||||
** packshort() -- store a 16-bit int into a char buffer (like htons())
|
|
||||||
*/
|
|
||||||
void packshort(unsigned short s)
|
|
||||||
{
|
|
||||||
unsigned char* sptr = ((unsigned char*) &(s));
|
|
||||||
printf("before: %02X %02X\n", sptr[0], sptr[1]);
|
|
||||||
unsigned short ns = htons(s);
|
|
||||||
memcpy(packbuf + packlen, (unsigned char*) &(ns), sizeof(short));
|
|
||||||
printf("after: %02X %02X\n", (packbuf + packlen)[0], (packbuf + packlen)[1]);
|
|
||||||
packlen += sizeof(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Attempt to connect to the network (Either TCP, or UDP)
|
||||||
void NetworkConnect()
|
void NetworkConnect()
|
||||||
{
|
{
|
||||||
if (server_cfg.datagram) {
|
// If the server is configured as UDP, ignore connection requests
|
||||||
|
if (server_cfg.datagram == true && client_cfg.datagram == true) {
|
||||||
ping = true;
|
ping = true;
|
||||||
connected = true;
|
connected = true;
|
||||||
} else {
|
} else {
|
||||||
if ((connection = SocketAccept(server_res->socket, &connection_cfg)) != NULL) {
|
// If the client is connected, run the server code to check for a connection
|
||||||
AddSocket(socket_set, connection);
|
if (client_connected) {
|
||||||
ping = true;
|
int active = CheckSockets(socket_set, 0);
|
||||||
connected = true;
|
if (active != 0) {
|
||||||
|
TraceLog(LOG_DEBUG,
|
||||||
|
"There are currently %d socket(s) with data to be processed.", active);
|
||||||
|
}
|
||||||
|
if (active > 0) {
|
||||||
|
if ((connection = SocketAccept(server_res->socket, &connection_cfg)) != NULL) {
|
||||||
|
AddSocket(socket_set, connection);
|
||||||
|
ping = true;
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Check if we're connected every _delay_ seconds
|
||||||
|
elapsed += GetFrameTime();
|
||||||
|
if (elapsed > delay) {
|
||||||
|
if (IsSocketConnected(client_res->socket)) {
|
||||||
|
client_connected = true;
|
||||||
|
}
|
||||||
|
elapsed = 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Once connected to the network, check the sockets for pending information
|
||||||
|
// and when information is ready, send either a Ping or a Pong.
|
||||||
void NetworkUpdate()
|
void NetworkUpdate()
|
||||||
{
|
{
|
||||||
int active = CheckSockets(socket_set, 0);
|
int active = CheckSockets(socket_set, 0);
|
||||||
|
|
@ -81,7 +92,7 @@ void NetworkUpdate()
|
||||||
|
|
||||||
int bytesRecv = 0;
|
int bytesRecv = 0;
|
||||||
if (server_cfg.datagram) {
|
if (server_cfg.datagram) {
|
||||||
if (IsSocketReady(server_res->socket)) {
|
if (IsSocketReady(client_res->socket)) {
|
||||||
bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen, 0);
|
bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -107,10 +118,6 @@ void NetworkUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VALUE_TO_STRING(x) #x
|
|
||||||
#define VALUE(x) VALUE_TO_STRING(x)
|
|
||||||
#define VAR_NAME_VALUE(var) #var "=" VALUE(var)
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// Setup
|
// Setup
|
||||||
|
|
@ -124,21 +131,52 @@ int main()
|
||||||
// Networking
|
// Networking
|
||||||
InitNetwork();
|
InitNetwork();
|
||||||
|
|
||||||
// Create the server
|
// Create the server
|
||||||
|
//
|
||||||
|
// Performs
|
||||||
|
// getaddrinfo
|
||||||
|
// socket
|
||||||
|
// setsockopt
|
||||||
|
// bind
|
||||||
|
// listen
|
||||||
server_res = AllocSocketResult();
|
server_res = AllocSocketResult();
|
||||||
if (!SocketOpen(&server_cfg, server_res)) {
|
if (!SocketCreate(&server_cfg, server_res)) {
|
||||||
TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d\n",
|
TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d",
|
||||||
server_res->status, server_res->socket->status);
|
server_res->status, server_res->socket->status);
|
||||||
|
} else {
|
||||||
|
if (!SocketBind(&server_cfg, server_res)) {
|
||||||
|
TraceLog(LOG_WARNING, "Failed to bind server: status %d, errno %d",
|
||||||
|
server_res->status, server_res->socket->status);
|
||||||
|
} else {
|
||||||
|
if (!SocketListen(&server_cfg, server_res)) {
|
||||||
|
TraceLog(LOG_WARNING,
|
||||||
|
"Failed to start listen server: status %d, errno %d",
|
||||||
|
server_res->status, server_res->socket->status);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the client
|
// Create the client
|
||||||
|
//
|
||||||
|
// Performs
|
||||||
|
// getaddrinfo
|
||||||
|
// socket
|
||||||
|
// setsockopt
|
||||||
|
// connect
|
||||||
client_res = AllocSocketResult();
|
client_res = AllocSocketResult();
|
||||||
if (!SocketOpen(&client_cfg, client_res)) {
|
if (!SocketCreate(&client_cfg, client_res)) {
|
||||||
TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d\n",
|
TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d",
|
||||||
client_res->status, client_res->socket->status);
|
client_res->status, client_res->socket->status);
|
||||||
|
} else {
|
||||||
|
if (!SocketConnect(&client_cfg, client_res)) {
|
||||||
|
TraceLog(LOG_WARNING,
|
||||||
|
"Failed to connect to server: status %d, errno %d",
|
||||||
|
client_res->status, client_res->socket->status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
socket_set = CreateSocketSet(3);
|
// Create & Add sockets to the socket set
|
||||||
|
socket_set = AllocSocketSet(3);
|
||||||
msglen = strlen(pingmsg) + 1;
|
msglen = strlen(pingmsg) + 1;
|
||||||
memset(recvBuffer, '\0', sizeof(recvBuffer));
|
memset(recvBuffer, '\0', sizeof(recvBuffer));
|
||||||
AddSocket(socket_set, server_res->socket);
|
AddSocket(socket_set, server_res->socket);
|
||||||
|
|
|
||||||
|
|
@ -67,23 +67,34 @@ void test_resolve_ip()
|
||||||
|
|
||||||
void test_resolve_host()
|
void test_resolve_host()
|
||||||
{
|
{
|
||||||
const char * address = "localhost";
|
const char * address = "localhost";
|
||||||
const char * port = "80";
|
const char * port = "80";
|
||||||
struct _AddressInformation **addr = AllocAddressList(3);
|
AddressInformation *addr = AllocAddressList(3);
|
||||||
int count = ResolveHost(address, port, addr);
|
int count = ResolveHost(address, port, addr);
|
||||||
assert(GetAddressFamily(addr[0]) == ADDRESS_TYPE_IPV6);
|
assert(GetAddressFamily(addr[0]) == ADDRESS_TYPE_IPV6);
|
||||||
assert(GetAddressFamily(addr[1]) == ADDRESS_TYPE_IPV4);
|
assert(GetAddressFamily(addr[1]) == ADDRESS_TYPE_IPV4);
|
||||||
|
assert(GetAddressSocketType(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()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_address_list()
|
void test_address_list()
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_socket_create()
|
||||||
|
{
|
||||||
|
SocketConfig server_cfg = {.host = "127.0.0.1", .port = "8080", .server = true, .nonblocking = true};
|
||||||
|
Socket * socket = AllocSocket();
|
||||||
|
SocketResult *server_res = AllocSocketResult();
|
||||||
|
SocketSet * socket_set = AllocSocketSet(1);
|
||||||
|
assert(SocketCreate(&server_cfg, server_res));
|
||||||
|
assert(AddSocket(socket_set, server_res->socket));
|
||||||
|
assert(SocketListen(&server_cfg, server_res));
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
|
@ -96,10 +107,8 @@ int main()
|
||||||
|
|
||||||
// Run the tests
|
// Run the tests
|
||||||
test_network_initialise();
|
test_network_initialise();
|
||||||
// test_socket_result();
|
// test_resolve_host();
|
||||||
// test_socket();
|
test_socket_create();
|
||||||
// test_resolve_ip();
|
|
||||||
test_resolve_host();
|
|
||||||
|
|
||||||
// Main game loop
|
// Main game loop
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose()) {
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,3 @@
|
||||||
/*******************************************************************************************
|
|
||||||
*
|
|
||||||
* raylib [core] example - Basic window
|
|
||||||
*
|
|
||||||
* Welcome to raylib!
|
|
||||||
*
|
|
||||||
* To test examples, just press F6 and execute raylib_compile_execute script
|
|
||||||
* Note that compiled executable is placed in the same folder as .c file
|
|
||||||
*
|
|
||||||
* You can find all basic examples on C:\raylib\raylib\examples folder or
|
|
||||||
* raylib official webpage: www.raylib.com
|
|
||||||
*
|
|
||||||
* Enjoy using raylib. :)
|
|
||||||
*
|
|
||||||
* This example has been created using raylib 1.0 (www.raylib.com)
|
|
||||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013-2016 Ramon Santamaria (@raysan5)
|
|
||||||
*
|
|
||||||
********************************************************************************************/
|
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,3 @@
|
||||||
/*******************************************************************************************
|
|
||||||
*
|
|
||||||
* raylib [core] example - Basic window
|
|
||||||
*
|
|
||||||
* Welcome to raylib!
|
|
||||||
*
|
|
||||||
* To test examples, just press F6 and execute raylib_compile_execute script
|
|
||||||
* Note that compiled executable is placed in the same folder as .c file
|
|
||||||
*
|
|
||||||
* You can find all basic examples on C:\raylib\raylib\examples folder or
|
|
||||||
* raylib official webpage: www.raylib.com
|
|
||||||
*
|
|
||||||
* Enjoy using raylib. :)
|
|
||||||
*
|
|
||||||
* This example has been created using raylib 1.0 (www.raylib.com)
|
|
||||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013-2016 Ramon Santamaria (@raysan5)
|
|
||||||
*
|
|
||||||
********************************************************************************************/
|
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
|
@ -29,9 +8,13 @@ int main()
|
||||||
screenWidth, screenHeight, "raylib [core] example - basic window");
|
screenWidth, screenHeight, "raylib [core] example - basic window");
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
|
|
||||||
|
// Initialise networking
|
||||||
|
InitNetwork();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
// Main game loop
|
// Main game loop
|
||||||
while (!WindowShouldClose())
|
while (!WindowShouldClose()) {
|
||||||
{
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
|
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@
|
||||||
<ClInclude Include="..\..\..\src\raylib.h" />
|
<ClInclude Include="..\..\..\src\raylib.h" />
|
||||||
<ClInclude Include="..\..\..\src\raymath.h" />
|
<ClInclude Include="..\..\..\src\raymath.h" />
|
||||||
<ClInclude Include="..\..\..\src\rlgl.h" />
|
<ClInclude Include="..\..\..\src\rlgl.h" />
|
||||||
<ClInclude Include="..\..\..\src\sysnet.h" />
|
<ClInclude Include="..\..\..\src\rnet.h" />
|
||||||
<ClInclude Include="..\..\..\src\utils.h" />
|
<ClInclude Include="..\..\..\src\utils.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
43
src/raylib.h
43
src/raylib.h
|
|
@ -455,10 +455,17 @@ typedef struct VrStereoConfig {
|
||||||
|
|
||||||
|
|
||||||
// IPAddress definition (in network byte order)
|
// IPAddress definition (in network byte order)
|
||||||
typedef struct IPAddress {
|
typedef struct IPv4Address {
|
||||||
unsigned long host; /* 32-bit IPv4 host address */
|
unsigned long host; /* 32-bit IPv4 host address */
|
||||||
unsigned short port; /* 16-bit protocol port */
|
unsigned short port; /* 16-bit protocol port */
|
||||||
} IPAddress;
|
} IPv4Address;
|
||||||
|
|
||||||
|
typedef struct IPv6Address {
|
||||||
|
union {
|
||||||
|
uint8_t byte[16];
|
||||||
|
uint16_t word[8];
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
// An option ID, value, sizeof(value) tuple for setsockopt(2).
|
// An option ID, value, sizeof(value) tuple for setsockopt(2).
|
||||||
typedef struct SocketOpt {
|
typedef struct SocketOpt {
|
||||||
|
|
@ -474,7 +481,7 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct UDPChannel {
|
typedef struct UDPChannel {
|
||||||
int numbound; // The total number of addresses this channel is bound to
|
int numbound; // The total number of addresses this channel is bound to
|
||||||
IPAddress address[SOCKET_MAX_UDPADDRESSES]; // The list of remote addresses this channel is bound to
|
IPv4Address address[SOCKET_MAX_UDPADDRESSES]; // The list of remote addresses this channel is bound to
|
||||||
} UDPChannel;
|
} UDPChannel;
|
||||||
|
|
||||||
typedef struct Socket {
|
typedef struct Socket {
|
||||||
|
|
@ -483,7 +490,7 @@ typedef struct Socket {
|
||||||
bool isServer; // Is this socket a server socket (i.e. TCP/UDP Listen Server)
|
bool isServer; // Is this socket a server socket (i.e. TCP/UDP Listen Server)
|
||||||
SocketChannel channel; // The socket handle id
|
SocketChannel channel; // The socket handle id
|
||||||
SocketType type; // Is this socket a TCP or UDP socket?
|
SocketType type; // Is this socket a TCP or UDP socket?
|
||||||
IPAddress address; // The host/target ip for this socket (in network byte order)
|
IPv4Address address; // The host/target ip for this socket (in network byte order)
|
||||||
struct UDPChannel bindings[SOCKET_MAX_UDPCHANNELS]; // The amount of channels (if UDP) this socket is bound to
|
struct UDPChannel bindings[SOCKET_MAX_UDPCHANNELS]; // The amount of channels (if UDP) this socket is bound to
|
||||||
} Socket;
|
} Socket;
|
||||||
|
|
||||||
|
|
@ -499,14 +506,13 @@ typedef struct SocketDataPacket {
|
||||||
int len; /* The length of the packet data */
|
int len; /* The length of the packet data */
|
||||||
int maxlen; /* The size of the data buffer */
|
int maxlen; /* The size of the data buffer */
|
||||||
int status; /* packet status after sending */
|
int status; /* packet status after sending */
|
||||||
IPAddress address; /* The source/dest address of an incoming/outgoing packet */
|
IPv4Address address; /* The source/dest address of an incoming/outgoing packet */
|
||||||
} SocketDataPacket;
|
} SocketDataPacket;
|
||||||
|
|
||||||
// Configuration for a socket. Not all of these fields need to
|
// Configuration for a socket. Not all of these fields need to
|
||||||
// be set, and ones omitted from a C99-style "designated initializer"
|
// be set, and ones omitted from a C99-style "designated initializer"
|
||||||
// struct literal will be zeroed out and replaced with defaults.
|
// struct literal will be zeroed out and replaced with defaults.
|
||||||
typedef struct SocketConfig {
|
typedef struct SocketConfig {
|
||||||
// Hostname and port, for TCP or UDP sockets. */
|
|
||||||
char * host; // The host address in xxx.xxx.xxx.xxx form
|
char * host; // The host address in xxx.xxx.xxx.xxx form
|
||||||
char * port; // The target port/server in the form "http" or "25565"
|
char * port; // The target port/server in the form "http" or "25565"
|
||||||
bool server; // Listen for incoming clients?
|
bool server; // Listen for incoming clients?
|
||||||
|
|
@ -1510,30 +1516,31 @@ 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 struct _AddressInformation **AllocAddressList(int size);
|
RLAPI 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 SocketBind(SocketConfig *cfg, SocketResult *res);
|
||||||
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 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);
|
||||||
|
RLAPI void SocketClose(SocketChannel socket);
|
||||||
RLAPI Socket *AllocSocket();
|
RLAPI Socket *AllocSocket();
|
||||||
|
RLAPI void FreeSocket(Socket **sock);
|
||||||
RLAPI SocketResult *AllocSocketResult();
|
RLAPI SocketResult *AllocSocketResult();
|
||||||
RLAPI void FreeSocket(Socket **sock);
|
RLAPI void FreeSocketResult(SocketResult **result);
|
||||||
RLAPI void FreeSocketResult(SocketResult **result);
|
RLAPI SocketSet *AllocSocketSet(int max);
|
||||||
|
RLAPI void FreeSocketSet(SocketSet *sockset);
|
||||||
|
|
||||||
// Socket I/O API
|
// Socket I/O API
|
||||||
RLAPI bool IsSocketReady(Socket *sock);
|
RLAPI bool IsSocketReady(Socket *sock);
|
||||||
RLAPI SocketSet *AllocSocketSet(int max);
|
RLAPI bool IsSocketConnected(Socket *sock);
|
||||||
RLAPI void FreeSocketSet(SocketSet *sockset);
|
RLAPI int AddSocket(SocketSet *set, Socket *sock);
|
||||||
RLAPI int AddSocket(SocketSet *set, Socket *sock);
|
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);
|
|
||||||
|
|
||||||
// Packet API
|
// Packet API
|
||||||
Packet * AllocPacket(int size);
|
Packet * AllocPacket(int size);
|
||||||
|
|
|
||||||
349
src/rnet.c
349
src/rnet.c
|
|
@ -39,16 +39,9 @@
|
||||||
// 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 "rnet.h"
|
|
||||||
# include <stdarg.h>
|
#include "raylib.h"
|
||||||
#else
|
|
||||||
# include "raylib.h"
|
|
||||||
# include "rnet.h"
|
|
||||||
# if !defined(EXTERNAL_CONFIG_FLAGS)
|
|
||||||
# include "config.h" // Defines module configuration flags
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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()
|
||||||
|
|
@ -57,6 +50,7 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module defines
|
// Module defines
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
#define NET_SOCKET_BACKLOG_SIZE (20)
|
#define NET_SOCKET_BACKLOG_SIZE (20)
|
||||||
#define NET_MAXHOST (1025) // Max size of a fully-qualified domain name
|
#define NET_MAXHOST (1025) // Max size of a fully-qualified domain name
|
||||||
#define NET_MAXSERV (32) // Max size of a service name
|
#define NET_MAXSERV (32) // Max size of a service name
|
||||||
|
|
@ -66,35 +60,21 @@
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if PLATFORM == PLATFORM_WINDOWS
|
typedef struct _SocketAddress {
|
||||||
typedef socklen_t _SocketLength;
|
struct sockaddr address;
|
||||||
typedef SOCKADDR _SocketAddress;
|
} _SocketAddress;
|
||||||
typedef SOCKADDR_IN _SocketAddressIPv4;
|
typedef struct _SocketAddressIPv4 {
|
||||||
typedef SOCKADDR_IN6 _SocketAddressIPv6;
|
struct sockaddr_in address;
|
||||||
typedef SOCKADDR_STORAGE _SocketAddressStorage;
|
} _SocketAddressIPv4;
|
||||||
|
typedef struct _SocketAddressIPv6 {
|
||||||
|
struct sockaddr_in6 address;
|
||||||
|
} _SocketAddressIPv6;
|
||||||
|
typedef struct _SocketAddressStorage {
|
||||||
|
struct sockaddr_storage address;
|
||||||
|
} _SocketAddressStorage;
|
||||||
typedef struct _AddressInformation {
|
typedef struct _AddressInformation {
|
||||||
int ai_flags; // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST
|
struct addrinfo addr;
|
||||||
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;
|
} _AddressInformation;
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RNET_STANDALONE)
|
|
||||||
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
|
||||||
|
|
@ -120,11 +100,18 @@ static char *SocketAddressToString(struct sockaddr_storage *sockaddr, char buffe
|
||||||
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);
|
||||||
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);
|
||||||
|
static void PrintSocket(AddressInformation addr);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global module implementationd
|
// Global module implementationd
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static void PrintAddressInfo(AddressInformation addr)
|
||||||
|
{
|
||||||
|
PrintSocket(&addr->addr.ai_addr, addr->addr.ai_family, addr->addr.ai_socktype,
|
||||||
|
addr->addr.ai_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)
|
||||||
{
|
{
|
||||||
|
|
@ -226,7 +213,7 @@ static char *SocketAddressToString(struct sockaddr_storage *sockaddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Check if the null terminated string ip is a valid IPv4 address
|
||||||
static bool IsIPv4Address(const char *ip)
|
static bool IsIPv4Address(const char *ip)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
|
|
@ -234,7 +221,7 @@ static bool IsIPv4Address(const char *ip)
|
||||||
return result != 0;
|
return result != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Check if the null terminated string ip is a valid IPv6 address
|
||||||
static bool IsIPv6Address(const char *ip)
|
static bool IsIPv6Address(const char *ip)
|
||||||
{
|
{
|
||||||
struct sockaddr_in6 sa;
|
struct sockaddr_in6 sa;
|
||||||
|
|
@ -328,7 +315,7 @@ static bool InitSocket(Socket *sock, struct addrinfo *addr)
|
||||||
return IsSocketValid(sock);
|
return IsSocketValid(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSocket() - Interally called by OpenSocket()
|
// CreateSocket() - Interally called by CreateSocket()
|
||||||
//
|
//
|
||||||
// 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
|
||||||
// attempt to open a socket, bind and listen to it based on the config passed in
|
// attempt to open a socket, bind and listen to it based on the config passed in
|
||||||
|
|
@ -446,7 +433,7 @@ static bool CreateSocket(SocketConfig *config, SocketResult *outresult)
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Set the state of the Socket sock to blocking
|
||||||
static bool SocketSetBlocking(Socket *sock)
|
static bool SocketSetBlocking(Socket *sock)
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
@ -465,7 +452,7 @@ static bool SocketSetBlocking(Socket *sock)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Set the state of the Socket sock to non-blocking
|
||||||
static bool SocketSetNonBlocking(Socket *sock)
|
static bool SocketSetNonBlocking(Socket *sock)
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
@ -483,7 +470,7 @@ static bool SocketSetNonBlocking(Socket *sock)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Set options specified in SocketConfig to Socket sock
|
||||||
static bool SocketSetOptions(SocketConfig *config, Socket *sock)
|
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++) {
|
||||||
|
|
@ -654,7 +641,7 @@ void ResolveIP(const char *ip, const char *port, int flags, char *host, char *se
|
||||||
// returns:
|
// returns:
|
||||||
// the total amount of addresses found
|
// the total amount of addresses found
|
||||||
//
|
//
|
||||||
int ResolveHost(const char *address, const char *port, AddressInformation *outAddrList)
|
int ResolveHost(const char *address, const char *port, AddressInformation *addrlist)
|
||||||
{
|
{
|
||||||
// Variables
|
// Variables
|
||||||
int status; // Status value to return (0) is success
|
int status; // Status value to return (0) is success
|
||||||
|
|
@ -698,14 +685,14 @@ int ResolveHost(const char *address, const char *port, AddressInformation *outAd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamically allocate an array of address information structs
|
// Dynamically allocate an array of address information structs
|
||||||
if (outAddrList != NULL) {
|
if (addrlist != NULL) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
outAddrList[i] = AllocAddress();
|
addrlist[i] = AllocAddress();
|
||||||
if (outAddrList[i] == NULL) { break; }
|
if (addrlist[i] == NULL) { break; }
|
||||||
}
|
}
|
||||||
outAddrList[i] = NULL;
|
addrlist[i] = NULL;
|
||||||
if (i != size) { outAddrList = 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");
|
||||||
|
|
@ -715,20 +702,20 @@ int ResolveHost(const char *address, const char *port, AddressInformation *outAd
|
||||||
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) {
|
||||||
outAddrList[i]->ai_flags = iterator->ai_flags;
|
addrlist[i]->addr.ai_flags = iterator->ai_flags;
|
||||||
outAddrList[i]->ai_family = iterator->ai_family;
|
addrlist[i]->addr.ai_family = iterator->ai_family;
|
||||||
outAddrList[i]->ai_socktype = iterator->ai_socktype;
|
addrlist[i]->addr.ai_socktype = iterator->ai_socktype;
|
||||||
outAddrList[i]->ai_protocol = iterator->ai_protocol;
|
addrlist[i]->addr.ai_protocol = iterator->ai_protocol;
|
||||||
outAddrList[i]->ai_addrlen = iterator->ai_addrlen;
|
addrlist[i]->addr.ai_addrlen = iterator->ai_addrlen;
|
||||||
memcpy(&outAddrList[i]->ai_addr, iterator->ai_addr, iterator->ai_addrlen);
|
memcpy(&addrlist[i]->addr.ai_addr, iterator->ai_addr, iterator->ai_addrlen);
|
||||||
#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(&outAddrList[i]->ai_addr,
|
PrintSocket(&addrlist[i]->addr.ai_addr,
|
||||||
outAddrList[i]->ai_family,
|
addrlist[i]->addr.ai_family,
|
||||||
outAddrList[i]->ai_socktype,
|
addrlist[i]->addr.ai_socktype,
|
||||||
outAddrList[i]->ai_protocol);
|
addrlist[i]->addr.ai_protocol);
|
||||||
TraceLog(LOG_DEBUG, "Length of this sockaddr: %d", outAddrList[i]->ai_addrlen);
|
TraceLog(LOG_DEBUG, "Length of this sockaddr: %d", addrlist[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++;
|
||||||
|
|
@ -783,54 +770,91 @@ bool SocketCreate(SocketConfig *config, SocketResult *result)
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Bind a socket to a local address
|
||||||
bool SocketListen(SocketConfig *config, SocketResult *result)
|
// Note: The bind function is required on an unconnected socket before subsequent calls to the listen function.
|
||||||
|
bool SocketBind(SocketConfig *config, SocketResult *result)
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = false;
|
||||||
result->status = RESULT_FAILURE;
|
result->status = RESULT_FAILURE;
|
||||||
|
|
||||||
// Only bind to sockets marked as server
|
// Don't bind to a socket that isn't configured as a server
|
||||||
if (config->server) {
|
if (!IsSocketValid(result->socket) || !config->server) {
|
||||||
// The sockaddr_in structure specifies the address family,
|
TraceLog(LOG_WARNING,
|
||||||
// IP address, and port of the server to be connected to.
|
"Cannot bind to socket marked as \"Client\" in SocketConfig.");
|
||||||
struct sockaddr_in clientService;
|
success = false;
|
||||||
clientService.sin_family = AF_INET;
|
} else {
|
||||||
clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
|
if (IsIPv4Address(config->host)) {
|
||||||
clientService.sin_port = htons(8080);
|
struct sockaddr_in ip4addr;
|
||||||
|
ip4addr.sin_family = AF_INET;
|
||||||
// Attempt to bind the socket
|
ip4addr.sin_port = config->port;
|
||||||
if (bind(result->socket->channel, (SOCKADDR *) &clientService, sizeof(clientService)) != SOCKET_ERROR) {
|
inet_pton(AF_INET, config->host, &ip4addr.sin_addr);
|
||||||
TraceLog(LOG_INFO, "Successfully bound socket.");
|
if (bind(result->socket->channel, (struct sockaddr *) &ip4addr, sizeof(ip4addr)) != SOCKET_ERROR) {
|
||||||
} else {
|
TraceLog(LOG_INFO, "Successfully bound socket.");
|
||||||
result->socket->status = SocketGetLastError();
|
|
||||||
TraceLog(LOG_WARNING, "Socket Error: %s",
|
|
||||||
SocketErrorCodeToString(result->socket->status));
|
|
||||||
SocketSetLastError(0);
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't listen on UDP sockets
|
|
||||||
if (!config->datagram) {
|
|
||||||
if (listen(result->socket->channel, config->backlog_size) != 0) {
|
|
||||||
success = false;
|
|
||||||
} else {
|
|
||||||
TraceLog(LOG_INFO, "Started listening on socket...");
|
|
||||||
success = true;
|
success = true;
|
||||||
|
} else {
|
||||||
|
result->socket->status = SocketGetLastError();
|
||||||
|
TraceLog(LOG_WARNING, "Socket Error: %s",
|
||||||
|
SocketErrorCodeToString(result->socket->status));
|
||||||
|
SocketSetLastError(0);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (IsIPv6Address(config->host)) {
|
||||||
|
struct sockaddr_in6 ip6addr;
|
||||||
|
ip6addr.sin6_family = AF_INET6;
|
||||||
|
ip6addr.sin6_port = config->port;
|
||||||
|
inet_pton(AF_INET6, config->host, &ip6addr.sin6_addr);
|
||||||
|
if (bind(result->socket->channel, (struct sockaddr *) &ip6addr, sizeof(ip6addr)) != SOCKET_ERROR) {
|
||||||
|
TraceLog(LOG_INFO, "Successfully bound socket.");
|
||||||
|
success = true;
|
||||||
|
} else {
|
||||||
|
result->socket->status = SocketGetLastError();
|
||||||
|
TraceLog(LOG_WARNING, "Socket Error: %s",
|
||||||
|
SocketErrorCodeToString(result->socket->status));
|
||||||
|
SocketSetLastError(0);
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
TraceLog(LOG_WARNING,
|
|
||||||
"Cannot listen on socket marked as \"Client\" in SocketConfig.");
|
|
||||||
success = false;
|
|
||||||
}
|
}
|
||||||
|
// Was the bind a success?
|
||||||
if (success) {
|
if (success) {
|
||||||
result->status = RESULT_SUCCESS;
|
result->status = RESULT_SUCCESS;
|
||||||
result->socket->ready = 0;
|
result->socket->ready = 0;
|
||||||
result->socket->status = 0;
|
result->socket->status = 0;
|
||||||
}
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listens (and queues) incoming connections requests for a bound port.
|
||||||
|
bool SocketListen(SocketConfig *config, SocketResult *result)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
result->status = RESULT_FAILURE;
|
||||||
|
|
||||||
|
// Don't bind to a socket that isn't configured as a server
|
||||||
|
if (!IsSocketValid(result->socket) || !config->server) {
|
||||||
|
TraceLog(LOG_WARNING,
|
||||||
|
"Cannot listen on socket marked as \"Client\" in SocketConfig.");
|
||||||
|
success = false;
|
||||||
|
} else {
|
||||||
|
// Don't listen on UDP sockets
|
||||||
|
if (!config->datagram) {
|
||||||
|
if (listen(result->socket->channel, config->backlog_size) != SOCKET_ERROR) {
|
||||||
|
TraceLog(LOG_INFO, "Started listening on socket...");
|
||||||
|
success = true;
|
||||||
|
} else {
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Was the listen a success?
|
||||||
|
if (success) {
|
||||||
|
result->status = RESULT_SUCCESS;
|
||||||
|
result->socket->ready = 0;
|
||||||
|
result->socket->status = 0;
|
||||||
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -846,23 +870,58 @@ bool SocketConnect(SocketConfig *config, SocketResult *result)
|
||||||
"Cannot connect to socket marked as \"Server\" in SocketConfig.");
|
"Cannot connect to socket marked as \"Server\" in SocketConfig.");
|
||||||
success = false;
|
success = false;
|
||||||
} else {
|
} else {
|
||||||
// The sockaddr_in structure specifies the address family,
|
if (IsIPv4Address(config->host)) {
|
||||||
// IP address, and port of the server to be connected to.
|
struct sockaddr_in ip4addr;
|
||||||
struct sockaddr_in clientService;
|
ip4addr.sin_family = AF_INET;
|
||||||
clientService.sin_family = AF_INET;
|
ip4addr.sin_port = config->port;
|
||||||
clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
|
inet_pton(AF_INET, config->host, &ip4addr.sin_addr);
|
||||||
clientService.sin_port = htons(8080);
|
int connect_result = connect(result->socket->channel, (struct sockaddr *) &ip4addr, sizeof(ip4addr));
|
||||||
|
if (connect_result == SOCKET_ERROR) {
|
||||||
// Did we connect successfully?
|
result->socket->status = SocketGetLastError();
|
||||||
if (connect(result->socket->channel, (SOCKADDR *) &clientService, sizeof(clientService)) != SOCKET_ERROR) {
|
SocketSetLastError(0);
|
||||||
TraceLog(LOG_INFO, "Successfully connected to socket.");
|
switch (result->socket->status) {
|
||||||
|
case WSAEWOULDBLOCK: {
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
TraceLog(LOG_WARNING, "Socket Error: %s",
|
||||||
|
SocketErrorCodeToString(result->socket->status));
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TraceLog(LOG_INFO, "Successfully connected to socket.");
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
result->socket->status = SocketGetLastError();
|
if (IsIPv6Address(config->host)) {
|
||||||
TraceLog(LOG_WARNING,
|
struct sockaddr_in6 ip6addr;
|
||||||
"Socket Error: %s",
|
ip6addr.sin6_family = AF_INET6;
|
||||||
SocketErrorCodeToString(result->socket->status));
|
ip6addr.sin6_port = config->port;
|
||||||
SocketSetLastError(0);
|
inet_pton(AF_INET6, config->host, &ip6addr.sin6_addr);
|
||||||
success = false;
|
int connect_result = connect(result->socket->channel, (struct sockaddr *) &ip6addr, sizeof(ip6addr));
|
||||||
|
if (connect_result == SOCKET_ERROR) {
|
||||||
|
result->socket->status = SocketGetLastError();
|
||||||
|
SocketSetLastError(0);
|
||||||
|
switch (result->socket->status) {
|
||||||
|
case WSAEWOULDBLOCK: {
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
TraceLog(LOG_WARNING, "Socket Error: %s",
|
||||||
|
SocketErrorCodeToString(result->socket->status));
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TraceLog(LOG_INFO, "Successfully connected to socket.");
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1082,7 +1141,32 @@ bool IsSocketReady(Socket *sock)
|
||||||
return (sock != NULL) && (sock->ready);
|
return (sock != NULL) && (sock->ready);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
bool IsSocketConnected(Socket *sock)
|
||||||
|
{
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
FD_SET writefds;
|
||||||
|
FD_ZERO(&writefds);
|
||||||
|
FD_SET(sock->channel, &writefds);
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 1000000000UL;
|
||||||
|
int total = select(0, NULL, &writefds, NULL, &timeout);
|
||||||
|
if (total == -1) { // Error
|
||||||
|
sock->status = SocketGetLastError();
|
||||||
|
TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status));
|
||||||
|
SocketSetLastError(0);
|
||||||
|
} else if (total == 0) { // Timeout
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (FD_ISSET(sock->channel, &writefds)) { return true; }
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate and return a SocketResult struct
|
||||||
SocketResult *AllocSocketResult()
|
SocketResult *AllocSocketResult()
|
||||||
{
|
{
|
||||||
struct SocketResult *res;
|
struct SocketResult *res;
|
||||||
|
|
@ -1097,7 +1181,7 @@ SocketResult *AllocSocketResult()
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Free an allocated SocketResult
|
||||||
void FreeSocketResult(SocketResult **result)
|
void FreeSocketResult(SocketResult **result)
|
||||||
{
|
{
|
||||||
if (*result != NULL) {
|
if (*result != NULL) {
|
||||||
|
|
@ -1107,13 +1191,13 @@ void FreeSocketResult(SocketResult **result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Allocate a Socket
|
||||||
Socket *AllocSocket()
|
Socket *AllocSocket()
|
||||||
{
|
{
|
||||||
// Allocate a socket if one already hasn't been
|
// Allocate a socket if one already hasn't been
|
||||||
struct Socket *sock;
|
struct Socket *sock;
|
||||||
sock = (Socket *) malloc(sizeof(*sock));
|
sock = (Socket *) malloc(sizeof(*sock));
|
||||||
if (socket != NULL) {
|
if (sock != NULL) {
|
||||||
memset(sock, 0, sizeof(*sock));
|
memset(sock, 0, sizeof(*sock));
|
||||||
} else {
|
} else {
|
||||||
TraceLog(
|
TraceLog(
|
||||||
|
|
@ -1125,7 +1209,7 @@ Socket *AllocSocket()
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Free an allocated Socket
|
||||||
void FreeSocket(Socket **sock)
|
void FreeSocket(Socket **sock)
|
||||||
{
|
{
|
||||||
if (*sock != NULL) {
|
if (*sock != NULL) {
|
||||||
|
|
@ -1134,7 +1218,7 @@ void FreeSocket(Socket **sock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Allocate a SocketSet
|
||||||
SocketSet *AllocSocketSet(int max)
|
SocketSet *AllocSocketSet(int max)
|
||||||
{
|
{
|
||||||
struct SocketSet *set;
|
struct SocketSet *set;
|
||||||
|
|
@ -1155,7 +1239,7 @@ SocketSet *AllocSocketSet(int max)
|
||||||
return (set);
|
return (set);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Free an allocated SocketSet
|
||||||
void FreeSocketSet(SocketSet *set)
|
void FreeSocketSet(SocketSet *set)
|
||||||
{
|
{
|
||||||
if (set) {
|
if (set) {
|
||||||
|
|
@ -1164,7 +1248,7 @@ void FreeSocketSet(SocketSet *set)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Add a Socket "sock" to the SocketSet "set"
|
||||||
int AddSocket(SocketSet *set, Socket *sock)
|
int AddSocket(SocketSet *set, Socket *sock)
|
||||||
{
|
{
|
||||||
if (sock != NULL) {
|
if (sock != NULL) {
|
||||||
|
|
@ -1182,7 +1266,7 @@ int AddSocket(SocketSet *set, Socket *sock)
|
||||||
return (set->numsockets);
|
return (set->numsockets);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Remove a Socket "sock" to the SocketSet "set"
|
||||||
int RemoveSocket(SocketSet *set, Socket *sock)
|
int RemoveSocket(SocketSet *set, Socket *sock)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -1204,7 +1288,7 @@ int RemoveSocket(SocketSet *set, Socket *sock)
|
||||||
return (set->numsockets);
|
return (set->numsockets);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Check the sockets in the socket set for pending information
|
||||||
int CheckSockets(SocketSet *set, unsigned int timeout)
|
int CheckSockets(SocketSet *set, unsigned int timeout)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -1248,7 +1332,7 @@ int CheckSockets(SocketSet *set, unsigned int timeout)
|
||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Allocate a Packet
|
||||||
Packet *AllocPacket(int size)
|
Packet *AllocPacket(int size)
|
||||||
{
|
{
|
||||||
struct Packet *packet;
|
struct Packet *packet;
|
||||||
|
|
@ -1271,7 +1355,7 @@ Packet *AllocPacket(int size)
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Free an allocated Packet
|
||||||
void FreePacket(Packet *packet)
|
void FreePacket(Packet *packet)
|
||||||
{
|
{
|
||||||
if (packet != NULL) {
|
if (packet != NULL) {
|
||||||
|
|
@ -1284,7 +1368,7 @@ void FreePacket(Packet *packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Allocate an AddressInformation
|
||||||
AddressInformation AllocAddress()
|
AddressInformation AllocAddress()
|
||||||
{
|
{
|
||||||
AddressInformation addr;
|
AddressInformation addr;
|
||||||
|
|
@ -1292,7 +1376,7 @@ AddressInformation AllocAddress()
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Allocate a list of AddressInformation
|
||||||
AddressInformation *AllocAddressList(int size)
|
AddressInformation *AllocAddressList(int size)
|
||||||
{
|
{
|
||||||
AddressInformation *addr;
|
AddressInformation *addr;
|
||||||
|
|
@ -1300,25 +1384,22 @@ AddressInformation *AllocAddressList(int size)
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Opaque datatype accessor addrinfo->ai_socktype
|
||||||
int GetAddressSocketType(AddressInformation address)
|
int GetAddressSocketType(AddressInformation address)
|
||||||
{
|
{
|
||||||
return address->ai_socktype;
|
return address->addr.ai_socktype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Opaque datatype accessor addrinfo->ai_protocol
|
||||||
int GetAddressProtocol(AddressInformation address)
|
int GetAddressProtocol(AddressInformation address)
|
||||||
{
|
{
|
||||||
return address->ai_protocol;
|
return address->addr.ai_protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Opaque datatype accessor addrinfo->ai_family
|
||||||
int GetAddressFamily(AddressInformation address)
|
int GetAddressFamily(AddressInformation address)
|
||||||
{
|
{
|
||||||
return address->ai_family;
|
return address->addr.ai_family;
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
void PrintAddressInfo(AddressInformation addr)
|
|
||||||
{
|
|
||||||
PrintSocket(&addr->ai_addr, addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
||||||
22
src/rnet.h
22
src/rnet.h
|
|
@ -88,7 +88,6 @@
|
||||||
#define NOPROFILER // Profiler interface.
|
#define NOPROFILER // Profiler interface.
|
||||||
#define NODEFERWINDOWPOS // DeferWindowPos routines
|
#define NODEFERWINDOWPOS // DeferWindowPos routines
|
||||||
#define NOMCX // Modem Configuration Extensions
|
#define NOMCX // Modem Configuration Extensions
|
||||||
|
|
||||||
#define MMNOSOUND
|
#define MMNOSOUND
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -170,14 +169,6 @@ typedef long int int64;
|
||||||
# define ssize_t size_t
|
# define ssize_t size_t
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
# define TRUE 1
|
|
||||||
#endif // TRUE
|
|
||||||
|
|
||||||
#ifndef FALSE
|
|
||||||
# define FALSE 0
|
|
||||||
#endif // FALSE
|
|
||||||
|
|
||||||
#ifndef RESULT_SUCCESS
|
#ifndef RESULT_SUCCESS
|
||||||
# define RESULT_SUCCESS 0
|
# define RESULT_SUCCESS 0
|
||||||
#endif // RESULT_SUCCESS
|
#endif // RESULT_SUCCESS
|
||||||
|
|
@ -186,19 +177,6 @@ typedef long int int64;
|
||||||
# define RESULT_FAILURE 1
|
# define RESULT_FAILURE 1
|
||||||
#endif // RESULT_FAILURE
|
#endif // RESULT_FAILURE
|
||||||
|
|
||||||
#ifndef INADDR_ANY
|
|
||||||
# define INADDR_ANY 0x00000000
|
|
||||||
#endif // INADDR_ANY
|
|
||||||
#ifndef INADDR_NONE
|
|
||||||
# define INADDR_NONE 0xFFFFFFFF
|
|
||||||
#endif // INADDR_NONE
|
|
||||||
#ifndef INADDR_LOOPBACK
|
|
||||||
# define INADDR_LOOPBACK 0x7f000001
|
|
||||||
#endif // INADDR_LOOPBACK
|
|
||||||
#ifndef INADDR_BROADCAST
|
|
||||||
# define INADDR_BROADCAST 0xFFFFFFFF
|
|
||||||
#endif // INADDR_BROADCAST
|
|
||||||
|
|
||||||
#ifndef htonll
|
#ifndef htonll
|
||||||
# ifdef _BIG_ENDIAN
|
# ifdef _BIG_ENDIAN
|
||||||
# define htonll(x) (x)
|
# define htonll(x) (x)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user