diff --git a/examples/network/network_ping_pong.c b/examples/network/network_ping_pong.c index 7f557c8b6..d2e6f12c0 100644 --- a/examples/network/network_ping_pong.c +++ b/examples/network/network_ping_pong.c @@ -21,10 +21,96 @@ ********************************************************************************************/ #include "raylib.h" +#include "rnet.c" +#include #include #include +char recvBuffer[512]; +float elapsed = 0.0f; +float delay = 1.0f; +bool ping = false; +bool pong = false; +bool connected = false; +const char* pingmsg = "Ping!"; +const char* pongmsg = "Pong!"; +int msglen = 0; +SocketConfig server_cfg = {.host = "127.0.0.1", .port = "8080", .server = true, .nonblocking = true}; +SocketConfig client_cfg = {.host = "127.0.0.1", .port = "8080", .nonblocking = true}; +SocketConfig connection_cfg = {.nonblocking = true}; +SocketResult* server_res = NULL; +SocketResult* client_res = NULL; +SocketSet* socket_set = NULL; +Socket* connection = NULL; + +/* +** 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); +} + +void NetworkConnect() +{ + if (server_cfg.datagram) { + ping = true; + connected = true; + } else { + if ((connection = SocketAccept(server_res->socket, &connection_cfg)) != NULL) { + AddSocket(socket_set, connection); + ping = true; + connected = true; + } + } +} + +void NetworkUpdate() +{ + int active = CheckSockets(socket_set, 0); + if (active != 0) { + TraceLog(LOG_DEBUG, + "There are currently %d socket(s) with data to be processed.", active); + } + + int bytesRecv = 0; + if (server_cfg.datagram) { + if (IsSocketReady(server_res->socket)) { + bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen, 0); + } + } else { + if (IsSocketReady(connection)) { + bytesRecv = SocketReceive(connection, recvBuffer, msglen, 0); + } + } + if (bytesRecv > 0) { + if (strcmp(recvBuffer, pingmsg) == 0) { pong = true; } + if (strcmp(recvBuffer, pongmsg) == 0) { ping = true; } + } + + elapsed += GetFrameTime(); + if (elapsed > delay) { + if (ping) { + ping = false; + SocketSend(client_res->socket, pingmsg, msglen); + } else if (pong) { + pong = false; + SocketSend(client_res->socket, pongmsg, msglen); + } + elapsed = 0.0f; + } +} + +#define VALUE_TO_STRING(x) #x +#define VALUE(x) VALUE_TO_STRING(x) +#define VAR_NAME_VALUE(var) #var "=" VALUE(var) + int main() { // Setup @@ -33,134 +119,40 @@ int main() InitWindow( screenWidth, screenHeight, "raylib [network] example - ping pong"); SetTargetFPS(60); - SetTraceLogLevel(LOG_DEBUG); // Networking - InitNetwork(); + InitNetwork(); // Create the server - SocketConfig server_cfg = {.host = "127.0.0.1", .port = "8080", .server = true, .datagram = true, .nonblocking = true}; - SocketResult* server_res = AllocSocketResult(); - if (!SocketOpen(&server_cfg, server_res)) - { + server_res = AllocSocketResult(); + if (!SocketOpen(&server_cfg, server_res)) { TraceLog(LOG_WARNING, "Failed to open server: status %d, errno %d\n", server_res->status, server_res->socket->status); } // Create the client - SocketConfig client_cfg = {.host = "127.0.0.1", .port = "8080", .datagram = true, .nonblocking = true}; - SocketResult* client_res = AllocSocketResult(); - { - if (!SocketOpen(&client_cfg, client_res)) - { - TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d\n", - client_res->status, client_res->socket->status); - } + client_res = AllocSocketResult(); + if (!SocketOpen(&client_cfg, client_res)) { + TraceLog(LOG_WARNING, "Failed to open client: status %d, errno %d\n", + client_res->status, client_res->socket->status); } - char recvBuffer[512]; + socket_set = CreateSocketSet(3); + msglen = strlen(pingmsg) + 1; memset(recvBuffer, '\0', sizeof(recvBuffer)); - Socket* connection = NULL; - SocketConfig connection_cfg = { .nonblocking = true,.datagram = true }; - float elapsed = 0.0f; - float delay = 1.0f; - bool ping = false; - bool pong = false; - bool connected = false; - const char* pingmsg = "Ping!"; - const char* pongmsg = "Pong!"; - const int msglen = strlen(pingmsg) + 1; - SocketSet* socket_set = CreateSocketSet(3); AddSocket(socket_set, server_res->socket); AddSocket(socket_set, client_res->socket); // Main game loop - while (!WindowShouldClose()) - { - // Draw + while (!WindowShouldClose()) { BeginDrawing(); - - // Clear ClearBackground(RAYWHITE); - - int active = CheckSockets(socket_set, 0); - if (active != 0) - { - TraceLog(LOG_DEBUG, - "There are currently %d socket(s) with data to be processed.", active); + if (connected) { + NetworkUpdate(); + } else { + NetworkConnect(); } - - // A valid connection will != -1 - if (!connected) - { - if (server_cfg.datagram) - { - ping = true; - connected = true; - } - else - { - if ((connection = SocketAccept(server_res->socket, &connection_cfg)) != NULL) - { - AddSocket(socket_set, connection); - ping = true; - connected = true; - } - } - } - - // Connected - if (connected) - { - int bytesRecv = 0; - - if (server_cfg.datagram) - { - if (IsSocketReady(server_res->socket)) - { - bytesRecv = SocketReceive(server_res->socket, recvBuffer, msglen, 0); - } - } - else - { - if (IsSocketReady(connection)) - { - bytesRecv = SocketReceive(connection, recvBuffer, msglen, 0); - } - } - if (bytesRecv > 0) - { - if (strcmp(recvBuffer, pingmsg) == 0) - { - pong = true; - printf("%s\n", pingmsg); - } - if (strcmp(recvBuffer, pongmsg) == 0) - { - ping = true; - printf("%s\n", pongmsg); - } - } - - elapsed += GetFrameTime(); - if (elapsed > delay) - { - if (ping) - { - ping = false; - SocketSend(client_res->socket, pingmsg, msglen); - } - else if (pong) - { - pong = false; - SocketSend(client_res->socket, pongmsg, msglen); - } - elapsed = 0.0f; - } - } - - // End draw EndDrawing(); } diff --git a/examples/network/network_tcp_client.c b/examples/network/network_tcp_client.c index 7a424d933..8fc6f6c40 100644 --- a/examples/network/network_tcp_client.c +++ b/examples/network/network_tcp_client.c @@ -21,6 +21,44 @@ #include "raylib.h" +#define MAX_BUFFER_SIZE 512 + +char buffer[MAX_BUFFER_SIZE]; +float elapsed = 0.0f; +float delay = 1.0f; +bool connected = false; +SocketConfig client_cfg = {.host = "127.0.0.1", .port = "8080", .nonblocking = true}; +SocketResult* client_res = NULL; +SocketSet* socket_set = NULL; + +void NetworkConnect() +{ + if (!SocketConnect(&client_cfg, client_res)) { + TraceLog(LOG_WARNING, + "Failed to connect socket to server: status %d, errno %d", + client_res->status, client_res->socket->status); + } else { + connected = true; + } +} + +void NetworkUpdate() +{ + int active = CheckSockets(socket_set, 0); + if (active != 0) { + TraceLog(LOG_DEBUG, + "There are currently %d socket(s) with data to be processed.", active); + } + + if (active > 0) { + int bytesRecv = 0; + if (IsSocketReady(client_res->socket)) { + bytesRecv = SocketReceive(client_res->socket, buffer, MAX_BUFFER_SIZE, 0); + } + if (bytesRecv > 0) { TraceLog(LOG_INFO, "%s", buffer); } + } +} + int main() { int screenWidth = 800; @@ -29,12 +67,35 @@ int main() screenWidth, screenHeight, "raylib [core] example - basic window"); SetTargetFPS(60); + // Set log type + SetTraceLogLevel(LOG_DEBUG); + + // Init the network layer + InitNetwork(); + + // Create the server + client_res = AllocSocketResult(); + socket_set = AllocSocketSet(1); + if (!SocketCreate(&client_cfg, client_res)) { + TraceLog(LOG_WARNING, "Failed to create socket: status %d, errno %d", + client_res->status, client_res->socket->status); + } else { + AddSocket(socket_set, client_res->socket); + } + // Main game loop - while (!WindowShouldClose()) - { + while (!WindowShouldClose()) { BeginDrawing(); - ClearBackground(RAYWHITE); - DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); + ClearBackground(RAYWHITE); + if (connected) { + NetworkUpdate(); + } else { + elapsed += GetFrameTime(); + if (elapsed > delay) { + NetworkConnect(); + elapsed = 0.0f; + } + } EndDrawing(); } CloseWindow(); diff --git a/examples/network/network_tcp_server.c b/examples/network/network_tcp_server.c index 7a424d933..349c3a3a6 100644 --- a/examples/network/network_tcp_server.c +++ b/examples/network/network_tcp_server.c @@ -21,6 +21,44 @@ #include "raylib.h" +bool connected = false; +bool sent = false; +float elapsed = 0.0f; +float delay = 1.0f; +SocketConfig server_cfg = {.host = "127.0.0.1", .port = "8080", .server = true, .nonblocking = true}; +SocketConfig connection_cfg = {.nonblocking = true}; +SocketResult* server_res = NULL; +Socket* connection = NULL; +SocketSet* socket_set = NULL; + +void NetworkSend() +{ + if (!sent) { + sent = true; + SocketSend(connection, "Hello, world!", 13); + } +} + +void NetworkListen() +{ + int active = CheckSockets(socket_set, 0); + if (active != 0) { + TraceLog(LOG_DEBUG, + "There are currently %d socket(s) with data to be processed.", active); + } + + if (active > 0) { + connection = SocketAccept(server_res->socket, &connection_cfg); + if (connection != NULL) { + AddSocket(socket_set, connection); + connected = true; + } else { + TraceLog(LOG_WARNING, "Failed to accept socket: status %d, errno %d", + server_res->status, server_res->socket->status); + } + } +} + int main() { int screenWidth = 800; @@ -29,12 +67,40 @@ int main() screenWidth, screenHeight, "raylib [core] example - basic window"); SetTargetFPS(60); + // Set log type + SetTraceLogLevel(LOG_DEBUG); + + // Init the network layer + InitNetwork(); + + // Create the server + server_res = AllocSocketResult(); + socket_set = AllocSocketSet(2); + if (!SocketCreate(&server_cfg, server_res)) { + TraceLog(LOG_WARNING, "Failed to create socket: status %d, errno %d", + server_res->status, server_res->socket->status); + } else { + AddSocket(socket_set, server_res->socket); + if (!SocketListen(&server_cfg, server_res)) { + TraceLog(LOG_WARNING, + "Failed to listen on socket: status %d, errno %d", + server_res->status, server_res->socket->status); + } + } + // Main game loop - while (!WindowShouldClose()) - { + while (!WindowShouldClose()) { BeginDrawing(); ClearBackground(RAYWHITE); - DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); + if (connected) { + NetworkSend(); + } else { + elapsed += GetFrameTime(); + if (elapsed > delay) { + NetworkListen(); + elapsed = 0.0f; + } + } EndDrawing(); } CloseWindow(); diff --git a/projects/VS2017/examples/core_basic_window.vcxproj b/projects/VS2017/examples/core_basic_window.vcxproj index ad6e050e7..f49ced0fb 100644 --- a/projects/VS2017/examples/core_basic_window.vcxproj +++ b/projects/VS2017/examples/core_basic_window.vcxproj @@ -73,7 +73,7 @@ true $(ProjectDir)$(ProjectName)\$(Configuration)\ - $(ProjectDir)$(ProjectName)\$(Configuration)\temp + $(ProjectDir)$(ProjectName)\$(Configuration)\temp\ true diff --git a/src/raylib.h b/src/raylib.h index 93aa15434..7aea46cee 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -72,6 +72,7 @@ #define RAYLIB_H #include // Required for: va_list - Only used by TraceLogCallback +#include // Required for rnet #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) # define RLAPI \ @@ -203,7 +204,7 @@ typedef enum #endif // Network typedefs -typedef unsigned int SocketChannel; +typedef int32_t SocketChannel; // Vector2 type typedef struct Vector2 @@ -567,15 +568,24 @@ typedef struct SocketConfig bool nonblocking; // non-blocking operation? int backlog_size; // set a custom backlog size SocketOpt sockopts[SOCKET_MAX_SOCK_OPTS]; -} SocketConfig; +} SocketConfig; // Result from calling open with a given config. typedef struct SocketResult { int status; - Socket *socket; + Socket *socket; } SocketResult; +// +typedef struct Packet +{ + uint32_t size; // The total size of bytes in data + uint32_t offs; // The offset to data access + uint32_t maxs; // The max size of data + uint8_t* data; // Data stored in network byte order +} Packet; + //---------------------------------------------------------------------------------- // Enumerators Definition //---------------------------------------------------------------------------------- @@ -1573,7 +1583,9 @@ extern "C" RLAPI char *ResolveHost(const char *address, const char *port); // Socket API - RLAPI bool SocketOpen(SocketConfig *cfg, SocketResult *res); + RLAPI bool SocketCreate(SocketConfig *cfg, SocketResult *res); + RLAPI bool SocketListen(SocketConfig *cfg, SocketResult *res); + RLAPI bool SocketConnect(SocketConfig *cfg, SocketResult *res); RLAPI void SocketClose(SocketChannel socket); RLAPI Socket *SocketAccept(Socket *server, SocketConfig *cfg); RLAPI int SocketSend(Socket *socket, const void *datap, int len); @@ -1581,15 +1593,33 @@ extern "C" // Socket set methods for async i/o RLAPI bool IsSocketReady(Socket* sock); - RLAPI SocketSet* CreateSocketSet(int max); - RLAPI void CleanupSocketSet(SocketSet* sockset); + RLAPI SocketSet* AllocSocketSet(int max); + RLAPI void FreeSocketSet(SocketSet* sockset); RLAPI int AddSocket(SocketSet* set, Socket* sock); RLAPI int RemoveSocket(SocketSet* set, Socket* sock); RLAPI int CheckSockets(SocketSet* set, unsigned int timeout); // Creation and allocation RLAPI SocketResult *AllocSocketResult(); - RLAPI Socket *AllocSocket(); + RLAPI void FreeSocketResult(SocketResult *result); + RLAPI Socket *AllocSocket(); + RLAPI void FreeSocket(Socket *sock); + + + // Data packets and helpers + Packet* AllocPacket(int size); + void FreePacket(Packet* packet); + void PacketSend(Packet* packet); + void PacketReceive(Packet* packet); + void PacketWrite8(Packet* packet, uint16_t value); + void PacketWrite16(Packet* packet, uint16_t value); + void PacketWrite32(Packet* packet, uint32_t value); + void PacketWrite64(Packet* packet, uint64_t value); + uint16_t PacketRead8(Packet* packet); + uint16_t PacketRead16(Packet* packet); + uint32_t PacketRead32(Packet* packet); + uint64_t PacketRead64(Packet* packet); + #if defined(__cplusplus) } diff --git a/src/rnet.c b/src/rnet.c index bede18dcc..700a34645 100644 --- a/src/rnet.c +++ b/src/rnet.c @@ -60,7 +60,7 @@ //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- -// Module methods +// Global module forward declarations //---------------------------------------------------------------------------------- static bool IsSocketValid(Socket* sock); @@ -71,8 +71,6 @@ static char* SocketErrorCodeToString(int err); static bool SocketSetDefaults(SocketConfig* config); static bool InitSocket(Socket* outsock, struct addrinfo* addr); static bool CreateSocket(SocketConfig* config, SocketResult* outresult); -static int BindSocket(Socket* sock, SocketConfig* config, struct addrinfo* iterator); -static int ConnectSocket(Socket* channel, SocketConfig* config, struct addrinfo* iterator); static bool SocketSetBlocking(Socket* out); static bool SocketSetNonBlocking(Socket* out); static bool SocketSetOptions(SocketConfig* config, Socket* channel); @@ -83,6 +81,40 @@ static bool IsIPv4Address(const char* ip); static bool IsIPv6Address(const char* ip); static char* SocketAddressToString(struct sockaddr* sockaddr, char buffer[], int* port); static void PrintSocket(struct sockaddr* 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 FillIPv6SockAddress(struct sockaddr_in6* sa, const char* host, unsigned short port); + +//---------------------------------------------------------------------------------- +// Global module implementationd +//---------------------------------------------------------------------------------- + +static bool FillIPv4SockAddress(struct sockaddr_in* sa, const char* host, unsigned short port) +{ + sa->sin_family = AF_INET; + sa->sin_port = htons(port); + int result = inet_pton(AF_INET, host, &(sa->sin_addr)); + if (result <= 0) { + if (result == 0) { + TraceLog(LOG_WARNING, "Input not provided in presentation format."); + return false; + } + } + return true; +} + +static bool FillIPv6SockAddress(struct sockaddr_in6* sa, const char* host, unsigned short port) +{ + sa->sin6_family = AF_INET6; + sa->sin6_port = htons(port); + int result = inet_pton(AF_INET6, host, &(sa->sin6_addr)); + if (result <= 0) { + if (result == 0) { + TraceLog(LOG_WARNING, "Input not provided in presentation format."); + return false; + } + } + return true; +} // Print socket information static void PrintSocket(struct sockaddr* addr, const int family, const int socktype, const int protocol) @@ -90,103 +122,68 @@ static void PrintSocket(struct sockaddr* addr, const int family, const int sockt struct sockaddr* sockaddr_ip; char ip[INET6_ADDRSTRLEN]; // Enough pace to hold a IPv6 string int port; - switch (family) - { - case AF_UNSPEC: - { + switch (family) { + case AF_UNSPEC: { TraceLog(LOG_DEBUG, "\tFamily: Unspecified"); - } - break; - case AF_INET: - { + } break; + case AF_INET: { TraceLog(LOG_DEBUG, "\tFamily: AF_INET (IPv4)"); TraceLog(LOG_INFO, "\t- IPv4 address %s", SocketAddressToString(addr, ip, &port)); - } - break; - case AF_INET6: - { + } break; + case AF_INET6: { TraceLog(LOG_DEBUG, "\tFamily: AF_INET6 (IPv6)"); TraceLog(LOG_INFO, "\t- IPv6 address %s", SocketAddressToString(addr, ip, &port)); - } - break; - case AF_NETBIOS: - { + } break; + case AF_NETBIOS: { TraceLog(LOG_DEBUG, "\tFamily: AF_NETBIOS (NetBIOS)"); - } - break; - default: - { + } break; + default: { TraceLog(LOG_DEBUG, "\tFamily: Other %ld", family); - } - break; + } break; } TraceLog(LOG_DEBUG, "\tSocket type:"); - switch (socktype) - { - case 0: - TraceLog(LOG_DEBUG, "\t- Unspecified"); - break; + switch (socktype) { + case 0: TraceLog(LOG_DEBUG, "\t- Unspecified"); break; case SOCK_STREAM: TraceLog(LOG_DEBUG, "\t- SOCK_STREAM (stream)"); break; case SOCK_DGRAM: TraceLog(LOG_DEBUG, "\t- SOCK_DGRAM (datagram)"); break; - case SOCK_RAW: - TraceLog(LOG_DEBUG, "\t- SOCK_RAW (raw)"); - break; + case SOCK_RAW: TraceLog(LOG_DEBUG, "\t- SOCK_RAW (raw)"); break; case SOCK_RDM: TraceLog(LOG_DEBUG, "\t- SOCK_RDM (reliable message datagram)"); break; case SOCK_SEQPACKET: TraceLog(LOG_DEBUG, "\t- SOCK_SEQPACKET (pseudo-stream packet)"); break; - default: - TraceLog(LOG_DEBUG, "\t- Other %ld", socktype); - break; + default: TraceLog(LOG_DEBUG, "\t- Other %ld", socktype); break; } TraceLog(LOG_DEBUG, "\tProtocol:"); - switch (protocol) - { - case 0: - TraceLog(LOG_DEBUG, "\t- Unspecified"); - break; - case IPPROTO_TCP: - TraceLog(LOG_DEBUG, "\t- IPPROTO_TCP (TCP)"); - break; - case IPPROTO_UDP: - TraceLog(LOG_DEBUG, "\t- IPPROTO_UDP (UDP)"); - break; - default: - TraceLog(LOG_DEBUG, "\t- Other %ld", protocol); - break; + switch (protocol) { + case 0: TraceLog(LOG_DEBUG, "\t- Unspecified"); break; + case IPPROTO_TCP: TraceLog(LOG_DEBUG, "\t- IPPROTO_TCP (TCP)"); break; + case IPPROTO_UDP: TraceLog(LOG_DEBUG, "\t- IPPROTO_UDP (UDP)"); break; + default: TraceLog(LOG_DEBUG, "\t- Other %ld", protocol); break; } } // Convert network ordered socket address to human readable string (127.0.0.1) -static char* SocketAddressToString(struct sockaddr* sockaddr, char buffer[], int* port) +static char* SocketAddressToString(struct sockaddr* sockaddr) { - switch (sockaddr->sa_family) - { - case AF_INET: - { + static ipv6[INET6_ADDRSTRLEN]; + switch (sockaddr->sa_family) { + case AF_INET: { struct sockaddr_in* s = ((struct sockaddr_in*) sockaddr); - *port = ntohs(s->sin_port); - return inet_ntop(AF_INET, &s->sin_addr, buffer, INET_ADDRSTRLEN); - } - break; - case AF_INET6: - { + return inet_ntop(AF_INET, &s->sin_addr, ipv6, INET_ADDRSTRLEN); + } break; + case AF_INET6: { struct sockaddr_in6* s = ((struct sockaddr_in6*) sockaddr); - *port = ntohs(s->sin6_port); - return inet_ntop(AF_INET6, &s->sin6_addr, buffer, INET6_ADDRSTRLEN); - } - break; - default: - { + return inet_ntop(AF_INET6, &s->sin6_addr, ipv6, INET6_ADDRSTRLEN); + } break; + default: { return NULL; - } - break; + } break; } } @@ -209,8 +206,7 @@ static bool IsIPv6Address(const char* ip) // void* GetSocketPortPtr(struct sockaddr* sa) { - if (sa->sa_family == AF_INET) - { + if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*) sa)->sin_port); } @@ -220,8 +216,7 @@ void* GetSocketPortPtr(struct sockaddr* sa) // void* GetSocketAddressPtr(struct sockaddr* sa) { - if (sa->sa_family == AF_INET) - { + if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*) sa)->sin_addr); } @@ -231,10 +226,7 @@ void* GetSocketAddressPtr(struct sockaddr* sa) // static bool IsSocketValid(Socket* sock) { - if (sock != NULL) - { - return (sock->channel != INVALID_SOCKET); - } + if (sock != NULL) { return (sock->channel != INVALID_SOCKET); } return false; } @@ -279,8 +271,7 @@ static char* SocketErrorCodeToString(int err) // static bool SocketSetDefaults(SocketConfig* config) { - if (config->backlog_size == 0) - { + if (config->backlog_size == 0) { config->backlog_size = SOCKET_BACKLOG_SIZE; } @@ -290,16 +281,10 @@ static bool SocketSetDefaults(SocketConfig* config) // Create the socket channel static bool InitSocket(Socket* sock, struct addrinfo* addr) { - switch (sock->type) - { - case SOCKET_TCP: - sock->channel = socket(AF_INET, SOCK_STREAM, 0); - break; - case SOCKET_UDP: - sock->channel = socket(AF_INET, SOCK_DGRAM, 0); - break; - default: - break; + switch (sock->type) { + case SOCKET_TCP: sock->channel = socket(AF_INET, SOCK_STREAM, 0); break; + case SOCKET_UDP: sock->channel = socket(AF_INET, SOCK_DGRAM, 0); break; + default: break; } return IsSocketValid(sock); } @@ -322,9 +307,10 @@ static bool InitSocket(Socket* sock, struct addrinfo* addr) // SocketResult server_res; SocketResult client_res; static bool CreateSocket(SocketConfig* config, SocketResult* outresult) { - int status; // Status value to return (0) is success - struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) - struct addrinfo* res; // A pointer to the resulting address list + bool success = true; + int addrstatus; + struct addrinfo hints; // Address flags (IPV4, IPV6, UDP?) + struct addrinfo* res; // A pointer to the resulting address list outresult->socket->channel = INVALID_SOCKET; outresult->status = RESULT_FAILURE; @@ -341,17 +327,16 @@ static bool CreateSocket(SocketConfig* config, SocketResult* outresult) SocketSetHints(config, &hints); // Populate address information - status = getaddrinfo(config->host, // e.g. "www.example.com" or IP (Can be null if AI_PASSIVE flag is set - config->port, // e.g. "http" or port number - &hints, // e.g. SOCK_STREAM/SOCK_DGRAM - &res // The struct to populate + addrstatus = getaddrinfo(config->host, // e.g. "www.example.com" or IP (Can be null if AI_PASSIVE flag is set + config->port, // e.g. "http" or port number + &hints, // e.g. SOCK_STREAM/SOCK_DGRAM + &res // The struct to populate ); // Did we succeed? - if (status != 0) - { + if (addrstatus != 0) { outresult->socket->status = SocketGetLastError(); - TraceLog(LOG_DEBUG, + TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->socket->status)); SocketSetLastError(0); @@ -360,24 +345,19 @@ static bool CreateSocket(SocketConfig* config, SocketResult* outresult) config->host, config->port, SocketGetLastErrorString()); - freeaddrinfo(res); - return false; - } - else - { + return (success = false); + } else { TraceLog( LOG_INFO, "Successfully resolved host %s:%s", config->host, config->port); } - // Walk the addrinfo struct + // Walk the address information linked-list struct addrinfo* it; - for (it = res; it != NULL; it = it->ai_next) - { + for (it = res; it != NULL; it = it->ai_next) { // Initialise the socket - if (!InitSocket(outresult->socket, it)) - { + if (!InitSocket(outresult->socket, it)) { outresult->socket->status = SocketGetLastError(); - TraceLog(LOG_DEBUG, + TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->socket->status)); SocketSetLastError(0); @@ -385,163 +365,93 @@ static bool CreateSocket(SocketConfig* config, SocketResult* outresult) } // Set socket options - if (!SocketSetOptions(config, outresult->socket->channel)) - { + if (!SocketSetOptions(config, outresult->socket->channel)) { outresult->socket->status = SocketGetLastError(); - TraceLog(LOG_DEBUG, + TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->socket->status)); SocketSetLastError(0); freeaddrinfo(res); - return false; - } - - // Only bind to sockets marked as server - if (config->server) - { - if (BindSocket(outresult->socket, config, it)) - { - TraceLog(LOG_INFO, "Successfully bound socket."); - } - else - { - outresult->socket->status = SocketGetLastError(); - TraceLog(LOG_DEBUG, - "Socket Error: %s", - SocketErrorCodeToString(outresult->socket->status)); - SocketSetLastError(0); - freeaddrinfo(res); - return false; - } - } - else - { - if (ConnectSocket(outresult->socket, config, it)) - { - TraceLog(LOG_INFO, "Successfully connected to socket."); - break; - } - else - { - outresult->socket->status = SocketGetLastError(); - TraceLog(LOG_DEBUG, - "Socket Error: %s", - SocketErrorCodeToString(outresult->socket->status)); - SocketSetLastError(0); - SocketClose(outresult->socket); - continue; - } + return (success = false); } } - if (!IsSocketValid(outresult->socket)) - { + if (!IsSocketValid(outresult->socket)) { outresult->socket->status = SocketGetLastError(); TraceLog( - LOG_DEBUG, "Socket Error: %s", SocketErrorCodeToString(outresult->status)); + LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(outresult->status)); SocketSetLastError(0); freeaddrinfo(res); - return false; + return (success = false); } - outresult->status = RESULT_SUCCESS; - outresult->socket->ready = 0; - outresult->socket->status = 0; - outresult->socket->isServer = config->server; - outresult->socket->address.host = (char*) malloc(INET6_ADDRSTRLEN); - SocketAddressToString(res->ai_addr, - outresult->socket->address.host, - &outresult->socket->address.port); + if (success) { + outresult->status = RESULT_SUCCESS; + outresult->socket->ready = 0; + outresult->socket->status = 0; + outresult->socket->isServer = config->server; + switch (res->ai_addr->sa_family) { + case AF_INET: { + struct sockaddr_in* s = ((struct sockaddr_in*) res->ai_addr); + outresult->socket->address.host = s->sin_addr.s_addr; + outresult->socket->address.port = s->sin_port; + } break; + case AF_INET6: { + struct sockaddr_in6* s = ((struct sockaddr_in6*) res->ai_addr); + outresult->socket->address.host = s->sin6_addr.s6_addr; + outresult->socket->address.port = s->sin6_port; + } break; + } + } freeaddrinfo(res); - return true; -} - -// -static bool BindSocket(Socket* sock, SocketConfig* config, struct addrinfo* iterator) -{ - // Attempt to bind the socket - if (bind(sock->channel, iterator->ai_addr, iterator->ai_addrlen) == SOCKET_ERROR) - { - sock->status = SocketGetLastError(); - TraceLog(LOG_DEBUG, "Socket Error: %s", SocketErrorCodeToString(sock->status)); - SocketSetLastError(0); - SocketClose(sock); - return false; - } - - // Don't listen on UDP sockets - if (!config->datagram) - { - if (listen(sock->channel, config->backlog_size) != 0) - { - return false; - } - else - { - TraceLog(LOG_INFO, "Started listening on socket..."); - } - } - - return true; -} - -// -static bool ConnectSocket(Socket* sock, SocketConfig* config, struct addrinfo* iterator) -{ - // Don't connect datagram sockets - if (config->datagram) - { - return true; - } - - // Did we connect successfully? - if (connect(sock->channel, iterator->ai_addr, iterator->ai_addrlen) != SOCKET_ERROR) - { - return true; - } - else - { - return false; - } + return success; } // static bool SocketSetBlocking(Socket* sock) { + bool ret = true; #if PLATFORM == PLATFORM_WINDOWS unsigned long mode = 0; - ioctlsocket(sock->channel, FIONBIO, &mode); + ret = ioctlsocket(sock->channel, FIONBIO, &mode); #else - int flags = fcntl(sock->channel, F_GETFL, 0); - fcntl(sock->channel, F_SETFL, flags & ~O_NONBLOCK); + const int flags = fcntl(sock->channel, F_GETFL, 0); + if (!(flags & O_NONBLOCK)) { + TraceLog(LOG_DEBUG, "Socket was already in blocking mode"); + return ret; + } + + ret = (0 == fcntl(sock->channel, F_SETFL, (flags ^ O_NONBLOCK))); #endif + return ret; } // static bool SocketSetNonBlocking(Socket* sock) { + bool ret = true; #if PLATFORM == PLATFORM_WINDOWS unsigned long mode = 1; - ioctlsocket(sock->channel, FIONBIO, &mode); + ret = ioctlsocket(sock->channel, FIONBIO, &mode); #else - fcntl(sock->channel, F_SETFL, O_NONBLOCK); + const int flags = fcntl(sock->channel, F_GETFL, 0); + if ((flags & O_NONBLOCK)) { + TraceLog(LOG_DEBUG, "Socket was already in non-blocking mode"); + return ret; + } + ret = (0 == fcntl(sock->channel, F_SETFL, (flags | O_NONBLOCK))); #endif - return true; + return ret; } // static bool SocketSetOptions(SocketConfig* config, Socket* sock) { - for (int i = 0; i < SOCKET_MAX_SOCK_OPTS; i++) - { + for (int i = 0; i < SOCKET_MAX_SOCK_OPTS; i++) { SocketOpt* opt = &config->sockopts[i]; - if (opt->id == 0) - { - break; - } + if (opt->id == 0) { break; } - if (setsockopt(sock->channel, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0) - { + if (setsockopt(sock->channel, SOL_SOCKET, opt->id, opt->value, opt->valueLen) < 0) { return false; } } @@ -552,45 +462,30 @@ static bool SocketSetOptions(SocketConfig* config, Socket* sock) // Set "hints" in an addrinfo struct, to be passed to getaddrinfo. static void SocketSetHints(SocketConfig* cfg, struct addrinfo* hints) { - if (cfg == NULL || hints == NULL) - { - return; - } + if (cfg == NULL || hints == NULL) { return; } memset(hints, 0, sizeof(*hints)); // Check if the ip supplied in the config is a valid ipv4 ip ipv6 address - if (IsIPv4Address(cfg->host)) - { + if (IsIPv4Address(cfg->host)) { hints->ai_family = AF_INET; hints->ai_flags |= AI_NUMERICHOST; - } - else - { - if (IsIPv6Address(cfg->host)) - { + } else { + if (IsIPv6Address(cfg->host)) { hints->ai_family = AF_INET6; hints->ai_flags |= AI_NUMERICHOST; - } - else - { + } else { hints->ai_family = AF_UNSPEC; } } - if (cfg->datagram) - { + if (cfg->datagram) { hints->ai_socktype = SOCK_DGRAM; - } - else - { + } else { hints->ai_socktype = SOCK_STREAM; } // Set passive unless UDP client - if (!cfg->datagram || cfg->server) - { - hints->ai_flags = AI_PASSIVE; - } + if (!cfg->datagram || cfg->server) { hints->ai_flags = AI_PASSIVE; } } //---------------------------------------------------------------------------------- @@ -607,18 +502,14 @@ bool InitNetwork() wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); - if (err != 0) - { + if (err != 0) { TraceLog(LOG_WARNING, "WinSock failed to initialise."); return false; - } - else - { + } else { TraceLog(LOG_INFO, "WinSock initialised."); } - if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) - { + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { TraceLog(LOG_WARNING, "WinSock failed to initialise."); WSACleanup(); return false; @@ -634,10 +525,8 @@ bool InitNetwork() void CloseNetwork() { #if PLATFORM == PLATFORM_WINDOWS - if (WSACleanup() == SOCKET_ERROR) - { - if (WSAGetLastError() == WSAEINPROGRESS) - { + if (WSACleanup() == SOCKET_ERROR) { + if (WSAGetLastError() == WSAEINPROGRESS) { WSACancelBlockingCall(); WSACleanup(); } @@ -684,18 +573,14 @@ char* ResolveIP(const char* ip, const char* port, int flags) ); // Did we succeed? - if (status != 0) - { + if (status != 0) { TraceLog(LOG_WARNING, "Failed to get resolve host %s:%s: %s", ip, port, gai_strerror(errno)); - } - else - { + } else { TraceLog(LOG_DEBUG, "Resolving... %s::%s", ip, port); } // Attempt to resolve network byte order ip to hostname - switch (results->ai_family) - { + switch (results->ai_family) { case AF_INET: status = getnameinfo(&*((struct sockaddr*) results->ai_addr), sizeof(*((struct sockaddr_in*) results->ai_addr)), @@ -714,17 +599,13 @@ char* ResolveIP(const char* ip, const char* port, int flags) NI_MAXSERV, flags); 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()); - } - else - { + } else { TraceLog(LOG_INFO, "Successfully resolved %s::%s to %s", ip, port, host); } @@ -755,10 +636,7 @@ char* ResolveHost(const char* address, const char* port) hints.ai_protocol = 0; // Automatically select correct protocol (IPPROTO_TCP), (IPPROTO_UDP) // When the address is NULL, populate the IP for me - if (address == NULL) - { - hints.ai_flags = AI_PASSIVE; - } + if (address == NULL) { hints.ai_flags = AI_PASSIVE; } // Populate address information status = getaddrinfo(address, // e.g. "www.example.com" or IP @@ -768,18 +646,14 @@ char* ResolveHost(const char* address, const char* port) ); // Did we succeed? - if (status != 0) - { + if (status != 0) { TraceLog(LOG_WARNING, "Failed to get resolve host %s:%s: %s", address, port, gai_strerror(errno)); - } - else - { + } else { TraceLog(LOG_INFO, "Successfully resolved host %s:%s", address, port); } struct addrinfo* iterator; - for (iterator = results; iterator != NULL; iterator = iterator->ai_next) - { + for (iterator = results; iterator != NULL; iterator = iterator->ai_next) { TraceLog(LOG_DEBUG, "GetAddressInformation"); TraceLog(LOG_DEBUG, "\tFlags: 0x%x", iterator->ai_flags); PrintSocket(iterator->ai_addr, @@ -811,37 +685,123 @@ char* ResolveHost(const char* address, const char* port) // .nonblocking = true, // }; // SocketResult server_res; SocketResult client_res; -bool SocketOpen(SocketConfig* config, SocketResult* result) +bool SocketCreate(SocketConfig* config, SocketResult* result) { + // Socket creation result + bool success = true; + // Make sure we've not received a null config or result pointer - if (config == NULL || result == NULL) - { - return false; - } + if (config == NULL || result == NULL) { return (success = false); } // Set the defaults based on the config - if (!SocketSetDefaults(config)) - { - TraceLog(LOG_DEBUG, "Configuration Error."); - return false; + if (!SocketSetDefaults(config)) { + TraceLog(LOG_WARNING, "Configuration Error."); + success = false; + } else { + // Create the socket + if (CreateSocket(config, result)) { + if (config->nonblocking) { + SocketSetNonBlocking(result->socket); + } else { + SocketSetBlocking(result->socket); + } + } else { + success = false; + } + } + return success; +} + +// +bool SocketListen(SocketConfig* config, SocketResult* result) +{ + bool success = true; + result->status = RESULT_FAILURE; + + // Only bind to sockets marked as server + if (config->server) { + // The sockaddr_in structure specifies the address family, + // IP address, and port of the server to be connected to. + struct sockaddr_in clientService; + clientService.sin_family = AF_INET; + clientService.sin_addr.s_addr = inet_addr("127.0.0.1"); + clientService.sin_port = htons(8080); + + // Attempt to bind the socket + if (bind(result->socket->channel, (SOCKADDR*) &clientService, sizeof(clientService)) != SOCKET_ERROR) { + TraceLog(LOG_INFO, "Successfully bound socket."); + } else { + 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; + } + } + + } else { + TraceLog(LOG_WARNING, + "Cannot listen on socket marked as \"Client\" in SocketConfig."); + success = false; } - // Create the socket - if (!CreateSocket(config, result)) - { - return false; + if (success) { + result->status = RESULT_SUCCESS; + result->socket->ready = 0; + result->socket->status = 0; } - // If the config states non-blocking, set the socket to non-blocking - if (config->nonblocking) - { - if (!SocketSetNonBlocking(result)) - { - return false; + return success; +} + +// +bool SocketConnect(SocketConfig* config, SocketResult* result) +{ + bool success = true; + result->status = RESULT_FAILURE; + + // Only bind to sockets marked as server + if (config->server) { + TraceLog(LOG_WARNING, + "Cannot connect to socket marked as \"Server\" in SocketConfig."); + success = false; + } else { + // The sockaddr_in structure specifies the address family, + // IP address, and port of the server to be connected to. + struct sockaddr_in clientService; + clientService.sin_family = AF_INET; + clientService.sin_addr.s_addr = inet_addr("127.0.0.1"); + clientService.sin_port = htons(8080); + + // Did we connect successfully? + if (connect(result->socket->channel, (SOCKADDR*) &clientService, sizeof(clientService)) != SOCKET_ERROR) { + TraceLog(LOG_INFO, "Successfully connected to socket."); + } else { + result->socket->status = SocketGetLastError(); + TraceLog(LOG_WARNING, + "Socket Error: %s", + SocketErrorCodeToString(result->socket->status)); + SocketSetLastError(0); + success = false; } } - return true; + if (success) { + result->status = RESULT_SUCCESS; + result->socket->ready = 0; + result->socket->status = 0; + } + + return success; } // Closes an existing socket @@ -849,13 +809,8 @@ bool SocketOpen(SocketConfig* config, SocketResult* result) // SocketChannel socket - The id of the socket to close void SocketClose(Socket* sock) { - if (sock != NULL) - { - if (sock->channel != INVALID_SOCKET) - { - closesocket(sock->channel); - } - free(sock); + if (sock != NULL) { + if (sock->channel != INVALID_SOCKET) { closesocket(sock->channel); } } } @@ -877,23 +832,18 @@ void SocketClose(Socket* sock) // } Socket* SocketAccept(Socket* server, SocketConfig* config) { + if (!server->isServer || server->type == SOCKET_UDP) { return NULL; } struct sockaddr_storage sock_addr; - Socket* sock; socklen_t sock_alen; + Socket* sock; int sock_port; - static char ip[INET6_ADDRSTRLEN]; - if (!server->isServer || server->type == SOCKET_UDP) - { - return NULL; - } - server->ready = 0; sock = AllocSocket(); + server->ready = 0; sock_alen = sizeof(sock_addr); sock->channel = accept(server->channel, (struct sockaddr*) &sock_addr, &sock_alen); - if (sock->channel == INVALID_SOCKET) - { + if (sock->channel == INVALID_SOCKET) { sock->status = SocketGetLastError(); - TraceLog(LOG_DEBUG, "Socket Error: %s", SocketErrorCodeToString(sock->status)); + TraceLog(LOG_WARNING, "Socket Error: %s", SocketErrorCodeToString(sock->status)); SocketSetLastError(0); SocketClose(sock); return NULL; @@ -902,20 +852,21 @@ Socket* SocketAccept(Socket* server, SocketConfig* config) sock->isServer = false; sock->ready = 0; sock->type = server->type; - switch (sock_addr.ss_family) - { - case AF_INET: - sock->address.host = ((struct sockaddr_in*) &sock_addr)->sin_addr.s_addr; - sock->address.port = ((struct sockaddr_in*) &sock_addr)->sin_port; - TraceLog(LOG_DEBUG, "Server: Got connection from %s", SocketAddressToString(((struct sockaddr_in*) &sock_addr), ip, &sock_port)); - break; - case AF_INET6: - sock->address.host = ((struct sockaddr_in6*) &sock_addr)->sin6_addr.s6_addr; - sock->address.port = ((struct sockaddr_in6*) &sock_addr)->sin6_port; - TraceLog(LOG_DEBUG, "Server: Got connection from %s", SocketAddressToString(((struct sockaddr_in6*) &sock_addr), ip, &sock_port)); - break; - default: - break; + switch (sock_addr.ss_family) { + case AF_INET: { + struct sockaddr_in* s = ((struct sockaddr_in*) &sock_addr); + sock->address.host = s->sin_addr.s_addr; + sock->address.port = s->sin_port; + TraceLog(LOG_INFO, "Server: Got connection from %s::%hu", SocketAddressToString(s), + ntohs(sock->address.port)); + } break; + case AF_INET6: { + struct sockaddr_in6* s = ((struct sockaddr_in6*) &sock_addr); + sock->address.host = s->sin6_addr.s6_addr; + sock->address.port = s->sin6_port; + TraceLog(LOG_INFO, "Server: Got connection from %s::%hu", SocketAddressToString(s), + ntohs(sock->address.port)); + } break; } return sock; } @@ -925,36 +876,25 @@ Socket* SocketAccept(Socket* server, SocketConfig* config) // Example int SocketSend(Socket* sock, const void* datap, int length) { - struct sockaddr_in sock_addr; - int sock_len; - int sent = 0; - int left = length; - int status = -1; - int numsent = 0; - sock_len = sizeof(sock_addr); - sock_addr.sin_family = AF_INET; - sock_addr.sin_port = htons(sock->address.port); - inet_pton(AF_INET, sock->address.host, &sock_addr.sin_addr); - const unsigned char* data = (const unsigned char*) datap; + int sent = 0; + int left = length; + int status = -1; + int numsent = 0; + const unsigned char* data = (const unsigned char*) datap; // Server sockets are for accepting connections only - if (sock->isServer) - { + if (sock->isServer) { TraceLog(LOG_WARNING, "Cannot send information on a server socket"); return -1; } // Which socket are we trying to send data on - switch (sock->type) - { - case SOCKET_TCP: - { + switch (sock->type) { + case SOCKET_TCP: { SocketSetLastError(0); - do - { + do { length = send(sock->channel, (const char*) data, left, 0); - if (length > 0) - { + if (length > 0) { sent += length; left -= length; data += length; @@ -964,41 +904,35 @@ int SocketSend(Socket* sock, const void* datap, int length) (SocketGetLastError() == WSAEINTR)) // The socket was interupted ); - if (length == SOCKET_ERROR) - { + if (length == SOCKET_ERROR) { sock->status = SocketGetLastError(); TraceLog(LOG_DEBUG, "Socket Error: %s", SocketErrorCodeToString(sock->status)); SocketSetLastError(0); - } - else - { + } else { TraceLog(LOG_DEBUG, "Successfully sent \"%s\" (%d bytes)", datap, sent); } return sent; - } - break; - case SOCKET_UDP: - { + } break; + case SOCKET_UDP: { + struct sockaddr_in dest; + dest.sin_family = AF_INET; + dest.sin_port = sock->address.port; + dest.sin_addr.s_addr = sock->address.host; SocketSetLastError(0); - status = sendto(sock->channel, (const char*) data, left, 0, (struct sockaddr*) &sock_addr, sock_len); - if (sent >= 0) - { + status = sendto(sock->channel, (const char*) data, left, 0, (struct sockaddr*) &dest, sizeof(dest)); + if (sent >= 0) { sock->status = status; ++numsent; - } - else - { + } else { sock->status = SocketGetLastError(); TraceLog(LOG_DEBUG, "Socket Error: %s", SocketGetLastErrorString(sock->status)); SocketSetLastError(0); return 0; } return numsent; - } - break; - default: - break; + } break; + default: break; } return -1; } @@ -1018,8 +952,7 @@ int SocketReceive(Socket* sock, void* data, int maxlen, int timeout) char ip[INET6_ADDRSTRLEN]; // Server sockets are for accepting connections only - if (sock->isServer && sock->type == SOCKET_TCP) - { + if (sock->isServer && sock->type == SOCKET_TCP) { sock->status = SocketGetLastError(); TraceLog(LOG_DEBUG, "Socket Error: %s", "Server sockets cannot be used to receive data"); @@ -1028,21 +961,16 @@ int SocketReceive(Socket* sock, void* data, int maxlen, int timeout) } // Which socket are we trying to send data on - switch (sock->type) - { - case SOCKET_TCP: - { + switch (sock->type) { + case SOCKET_TCP: { SocketSetLastError(0); - do - { + do { len = recv(sock->channel, (char*) data, maxlen, 0); } while (SocketGetLastError() == WSAEINTR); - if (len > 0) - { + if (len > 0) { // Who sent the packet? - if (sock->type == SOCKET_UDP) - { + if (sock->type == SOCKET_UDP) { TraceLog( LOG_DEBUG, "Received data from: %s", inet_ntop(sock_addr.ss_family, GetSocketAddressPtr((struct sockaddr*) &sock_addr), ip, sizeof(ip))); } @@ -1051,10 +979,8 @@ int SocketReceive(Socket* sock, void* data, int maxlen, int timeout) } sock->ready = 0; return len; - } - break; - case SOCKET_UDP: - { + } break; + case SOCKET_UDP: { SocketSetLastError(0); sock_len = sizeof(sock_addr); status = recvfrom(sock->channel, // The receving channel @@ -1064,12 +990,9 @@ int SocketReceive(Socket* sock, void* data, int maxlen, int timeout) (struct sockaddr*) &sock_addr, // The address of the recevied data &sock_len // The length of the received data address ); - if (status >= 0) - { + if (status >= 0) { ++numrecv; - } - else - { + } else { sock->status = SocketGetLastError(); TraceLog(LOG_DEBUG, "Socket Error: %s", SocketGetLastErrorString(sock->status)); SocketSetLastError(0); @@ -1077,8 +1000,7 @@ int SocketReceive(Socket* sock, void* data, int maxlen, int timeout) } sock->ready = 0; return numrecv; - } - break; + } break; } return -1; } @@ -1094,11 +1016,9 @@ SocketResult* AllocSocketResult() { struct SocketResult* res; res = (struct SocketResult*) malloc(sizeof(*res)); - if (res != NULL) - { + if (res != NULL) { memset(res, 0, sizeof(*res)); - if ((res->socket = AllocSocket()) == NULL) - { + if ((res->socket = AllocSocket()) == NULL) { free(res); res = NULL; } @@ -1106,18 +1026,21 @@ SocketResult* AllocSocketResult() return res; } +// +void FreeSocketResult(SocketResult* result) +{ + if (result != NULL) { free(result); } +} + // Socket* AllocSocket() { // Allocate a socket if one already hasn't been struct Socket* sock; sock = (Socket*) malloc(sizeof(*sock)); - if (socket != NULL) - { + if (socket != NULL) { memset(sock, 0, sizeof(*sock)); - } - else - { + } else { TraceLog( LOG_WARNING, "Ran out of memory attempting to allocate a socket"); SocketClose(sock); @@ -1128,23 +1051,26 @@ Socket* AllocSocket() } // -SocketSet* CreateSocketSet(int max) +void FreeSocket(Socket* sock) +{ + SocketClose(sock); + free(sock); +} + +// +SocketSet* AllocSocketSet(int max) { struct SocketSet* set; int i; set = (struct SocketSet*) malloc(sizeof(*set)); - if (set != NULL) - { + if (set != NULL) { set->numsockets = 0; set->maxsockets = max; set->sockets = (struct Socket**) malloc(max * sizeof(*set->sockets)); - if (set->sockets != NULL) - { + if (set->sockets != NULL) { for (i = 0; i < max; ++i) { set->sockets[i] = NULL; } - } - else - { + } else { free(set); set = NULL; } @@ -1153,10 +1079,9 @@ SocketSet* CreateSocketSet(int max) } // -void CleanupSocketSet(SocketSet* set) +void FreeSocketSet(SocketSet* set) { - if (set) - { + if (set) { free(set->sockets); free(set); } @@ -1165,18 +1090,14 @@ void CleanupSocketSet(SocketSet* set) // int AddSocket(SocketSet* set, Socket* sock) { - if (sock != NULL) - { - if (set->numsockets == set->maxsockets) - { + if (sock != NULL) { + if (set->numsockets == set->maxsockets) { TraceLog(LOG_DEBUG, "Socket Error: %s", "SocketSet is full"); SocketSetLastError(0); return (-1); } set->sockets[set->numsockets++] = (struct Socket*) sock; - } - else - { + } else { TraceLog(LOG_DEBUG, "Socket Error: %s", "Socket was null"); SocketSetLastError(0); return (-1); @@ -1189,24 +1110,20 @@ int RemoveSocket(SocketSet* set, Socket* sock) { int i; - if (sock != NULL) - { - for (i = 0; i < set->numsockets; ++i) - { - if (set->sockets[i] == (struct Socket*) sock) - { - break; - } + if (sock != NULL) { + for (i = 0; i < set->numsockets; ++i) { + if (set->sockets[i] == (struct Socket*) sock) { break; } } - if (i == set->numsockets) - { + if (i == set->numsockets) { TraceLog(LOG_DEBUG, "Socket Error: %s", "Socket not found"); SocketSetLastError(0); return (-1); } --set->numsockets; - for (; i < set->numsockets; ++i) - { set->sockets[i] = set->sockets[i + 1]; } } + for (; i < set->numsockets; ++i) { + set->sockets[i] = set->sockets[i + 1]; + } + } return (set->numsockets); } @@ -1221,23 +1138,22 @@ int CheckSockets(SocketSet* set, unsigned int timeout) /* Find the largest file descriptor */ maxfd = 0; - for (i = set->numsockets - 1; i >= 0; --i) - { - if (set->sockets[i]->channel > maxfd) - { + for (i = set->numsockets - 1; i >= 0; --i) { + if (set->sockets[i]->channel > maxfd) { maxfd = set->sockets[i]->channel; } } /* Check the file descriptors for available data */ - do - { + do { SocketSetLastError(0); /* Set up the mask of file descriptors */ FD_ZERO(&mask); - for (i = set->numsockets - 1; i >= 0; --i) - { FD_SET(set->sockets[i]->channel, &mask); } /* Set up the timeout */ tv.tv_sec = timeout / 1000; + for (i = set->numsockets - 1; i >= 0; --i) { + FD_SET(set->sockets[i]->channel, &mask); + } /* Set up the timeout */ + tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; /* Look! */ @@ -1245,15 +1161,141 @@ int CheckSockets(SocketSet* set, unsigned int timeout) } while (SocketGetLastError() == WSAEINTR); /* Mark all file descriptors ready that have data available */ - if (retval > 0) - { - for (i = set->numsockets - 1; i >= 0; --i) - { - if (FD_ISSET(set->sockets[i]->channel, &mask)) - { + if (retval > 0) { + for (i = set->numsockets - 1; i >= 0; --i) { + if (FD_ISSET(set->sockets[i]->channel, &mask)) { set->sockets[i]->ready = 1; } } } return (retval); -} \ No newline at end of file +} + +// +Packet* AllocPacket(int size) +{ + struct Packet* packet; + packet = (struct Packet*) malloc(sizeof(*packet)); + if (packet != NULL) { + memset(packet, 0, sizeof(*packet)); + packet->size = 0; + packet->offs = 0; + packet->maxs = size; + packet->data = (uint8_t*) malloc(size * sizeof(uint8_t)); + memset(packet->data, '\0', size); + if (packet->data == NULL) { + free(packet); + packet = NULL; + } + } else { + free(packet); + packet = NULL; + } + return packet; +} + +// +void FreePacket(Packet* packet) +{ + if (packet != NULL) { + if (packet->data != NULL) { + free(packet->data); + packet->data = NULL; + } + free(packet); + packet = NULL; + } +} + +// +void PacketSend(Packet* packet) +{ + printf("Sending packet (%s) with size %d\n", packet->data, packet->size); +} + +// +void PacketReceive(Packet* packet) +{ + printf("Receiving packet (%s) with size %d\n", packet->data, packet->size); +} + +// +void PacketWrite16(Packet* packet, uint16_t value) +{ + printf("Original: 0x%04" PRIX16 " - %" PRIu16 "\n", value, value); + uint8_t* data = packet->data + packet->offs; + *data++ = (uint8_t)(value >> 8); + *data++ = (uint8_t)(value); + packet->size += sizeof(uint16_t); + packet->offs += sizeof(uint16_t); + printf("Network: 0x%04" PRIX16 " - %" PRIu16 "\n", (uint16_t) *data, (uint16_t) *data); +} + +// +void PacketWrite32(Packet* packet, uint32_t value) +{ + printf("Original: 0x%08" PRIX32 " - %" PRIu32 "\n", value, value); + uint8_t* data = packet->data + packet->offs; + *data++ = (uint8_t)(value >> 24); + *data++ = (uint8_t)(value >> 16); + *data++ = (uint8_t)(value >> 8); + *data++ = (uint8_t)(value); + packet->size += sizeof(uint32_t); + packet->offs += sizeof(uint32_t); + printf("Network: 0x%08" PRIX32 " - %" PRIu32 "\n", + (uint32_t)(((intptr_t) packet->data) - packet->offs), + (uint32_t)(((intptr_t) packet->data) - packet->offs)); +} + +// +void PacketWrite64(Packet* packet, uint64_t value) +{ + printf("Original: 0x%016" PRIX64 " - %" PRIu64 "\n", value, value); + uint8_t* data = packet->data + packet->offs; + *data++ = (uint8_t)(value >> 56); + *data++ = (uint8_t)(value >> 48); + *data++ = (uint8_t)(value >> 40); + *data++ = (uint8_t)(value >> 32); + *data++ = (uint8_t)(value >> 24); + *data++ = (uint8_t)(value >> 16); + *data++ = (uint8_t)(value >> 8); + *data++ = (uint8_t)(value); + packet->size += sizeof(uint64_t); + packet->offs += sizeof(uint64_t); + printf("Network: 0x%016" PRIX64 " - %" PRIu64 "\n", + (uint64_t)(packet->data - packet->offs), + (uint64_t)(packet->data - packet->offs)); +} + +// +uint16_t PacketRead16(Packet* packet) +{ + uint8_t* data = packet->data + packet->offs; + packet->size += sizeof(uint16_t); + packet->offs += sizeof(uint16_t); + uint16_t value = ((uint16_t) data[0] << 8) | data[1]; + printf("Original: 0x%04" PRIX16 " - %" PRIu16 "\n", value, value); + return value; +} + +// +uint32_t PacketRead32(Packet* packet) +{ + uint8_t* data = packet->data + packet->offs; + packet->size += sizeof(uint32_t); + packet->offs += sizeof(uint32_t); + uint32_t value = ((uint32_t) data[0] << 24) | ((uint32_t) data[1] << 16) | ((uint32_t) data[2] << 8) | data[3]; + printf("Original: 0x%08" PRIX32 " - %" PRIu32 "\n", value, value); + return value; +} + +// +uint64_t PacketRead64(Packet* packet) +{ + uint8_t* data = packet->data + packet->offs; + packet->size += sizeof(uint64_t); + packet->offs += sizeof(uint64_t); + uint64_t value = ((uint64_t) data[0] << 56) | ((uint64_t) data[1] << 48) | ((uint64_t) data[2] << 40) | ((uint64_t) data[3] << 32) | ((uint64_t) data[4] << 24) | ((uint64_t) data[5] << 16) | ((uint64_t) data[6] << 8) | data[7]; + printf("Original: 0x%016" PRIX64 " - %" PRIu64 "\n", value, value); + return value; +} diff --git a/src/sysnet.h b/src/sysnet.h index ff171c25a..7d1aa005b 100644 --- a/src/sysnet.h +++ b/src/sysnet.h @@ -185,7 +185,7 @@ typedef long int int64; #ifndef RESULT_FAILURE # define RESULT_FAILURE 1 #endif // RESULT_FAILURE - + #ifndef INADDR_ANY # define INADDR_ANY 0x00000000 #endif // INADDR_ANY @@ -219,6 +219,7 @@ typedef long int int64; #ifdef _WIN32 # pragma comment(lib, "ws2_32.lib") # define __USE_W32_SOCKETS +# define WIN32_LEAN_AND_MEAN # include # include # include