diff --git a/src/dusk/CMakeLists.txt b/src/dusk/CMakeLists.txt index a4192a65..03a75469 100644 --- a/src/dusk/CMakeLists.txt +++ b/src/dusk/CMakeLists.txt @@ -77,4 +77,4 @@ add_subdirectory(time) add_subdirectory(ui) add_subdirectory(network) add_subdirectory(util) -# add_subdirectory(thread) \ No newline at end of file +add_subdirectory(thread) \ No newline at end of file diff --git a/src/dusk/engine/engine.c b/src/dusk/engine/engine.c index af8ba34d..2434c9cd 100644 --- a/src/dusk/engine/engine.c +++ b/src/dusk/engine/engine.c @@ -22,6 +22,7 @@ #include "physics/physicsmanager.h" #include "network/network.h" #include "network/networkinfo.h" +#include "network/networksocketclient.h" #include "system/system.h" #include "display/mesh/cube.h" @@ -30,14 +31,28 @@ engine_t ENGINE; entityid_t phBoxEnt; componentid_t phBoxPhys; +networksocketclient_t sockClient; float_t onlineSwapTime = FLT_MAX; void goOnline(); void goOffline(); +void onSocketConnected(void *user) { + sceneLog("Socket connected.\n"); +} + +void onSocketError(errorret_t error, void *user) { + sceneLog("Socket error: %s\n", error.state->message); + errorCatch(errorPrint(error)); +} + +void onSocketDisconnected(void *user) { + sceneLog("Socket disconnected.\n"); +} + void onNetworkConnected(void *user) { - onlineSwapTime = TIME.time + 3.0f; + onlineSwapTime = TIME.time + 1.5f; networkinfo_t info = networkGetInfo(); if(info.type == NETWORK_TYPE_IPV4) { @@ -57,7 +72,19 @@ void onNetworkConnected(void *user) { #endif } - sceneLog("Network connected, I will disconnect at: %.2f1.\n", onlineSwapTime); + sceneLog("Network connected, opening socket: %.2f1.\n", onlineSwapTime); + networkSocketClientInit( + &sockClient, + "google.com", + 443, + NULL, + onSocketConnected, + onSocketError, + onSocketDisconnected + ); + onlineSwapTime = FLT_MAX; + + // sceneLog("Network connected, I will disconnect at: %.2f1.\n", onlineSwapTime); } void onNetworkFailed(errorret_t error, void *user) { @@ -113,8 +140,8 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { // errorChain(networkInit()); errorChain(gameInit()); - sceneLog("Init done, going to queue online in 3 seconds...\n"); - onlineSwapTime = TIME.time + 3.0f; + onlineSwapTime = TIME.time + 1.0f; + sceneLog("Init done, going to queue online at %.2f1.\n", onlineSwapTime); // Camera entityid_t cam = entityManagerAdd(); diff --git a/src/dusk/network/CMakeLists.txt b/src/dusk/network/CMakeLists.txt index 6926e0b1..010907ec 100644 --- a/src/dusk/network/CMakeLists.txt +++ b/src/dusk/network/CMakeLists.txt @@ -7,4 +7,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC network.c networkinfo.c + networksocketclient.c ) diff --git a/src/dusk/network/networkhttp.h b/src/dusk/network/networkhttp.h new file mode 100644 index 00000000..4216775e --- /dev/null +++ b/src/dusk/network/networkhttp.h @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once + +typedef struct { + const char_t *key; + const char_t *value; +} networkhttpheader_t; + +typedef struct { + +} networkhttprequest_t; + +void networkHTTP( + const char_t *url, + const char_t *method, + void *user, + void (*onComplete)(void *user), + void (*onError)(errorret_t error, void *user) +); \ No newline at end of file diff --git a/src/dusk/network/networksocketclient.c b/src/dusk/network/networksocketclient.c new file mode 100644 index 00000000..1d99e69d --- /dev/null +++ b/src/dusk/network/networksocketclient.c @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "networksocketclient.h" +#include "assert/assert.h" +#include "util/memory.h" + +void networkSocketClientInit( + networksocketclient_t *client, + const char_t *host, + uint16_t port, + void *user, + void (*onConnect)(void *user), + void (*onError)(errorret_t error, void *user), + void (*onDisconnect)(void *user) +) { + assertNotNull(client, "Client cannot be NULL"); + assertStrLenMin(host, 1, "Host cannot be empty"); + assertNotNull(onConnect, "onConnect callback cannot be NULL"); + assertNotNull(onError, "onError callback cannot be NULL"); + assertNotNull(onDisconnect, "onDisconnect callback cannot be NULL"); + + memoryZero(client, sizeof(networksocketclient_t)); + client->user = user; + client->onConnect = onConnect; + client->onError = onError; + client->onDisconnect = onDisconnect; + client->state = NETWORK_SOCKET_CLIENT_STATE_CONNECTING; + + // Pass to platform for implementation. + networkSocketClientPlatformInit( + client, + host, + port, + user, + onConnect, + onError, + onDisconnect + ); +} \ No newline at end of file diff --git a/src/dusk/network/networksocketclient.h b/src/dusk/network/networksocketclient.h new file mode 100644 index 00000000..8126eaff --- /dev/null +++ b/src/dusk/network/networksocketclient.h @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "error/error.h" +#include "network/networksocketclientplatform.h" + +#ifndef networkSocketClientPlatformInit + #error "Define networkSocketClientPlatformInit" +#endif + +typedef enum { + NETWORK_SOCKET_CLIENT_STATE_DISCONNECTED, + NETWORK_SOCKET_CLIENT_STATE_CONNECTING, +} networksocketclientstate_t; + +typedef struct networksocketclient_s { + void *user; + void (*onConnect)(void *user); + void (*onError)(errorret_t error, void *user); + void (*onDisconnect)(void *user); + networksocketclientstate_t state; + networksocketclientplatform_t platform; + errorstate_t errorState; +} networksocketclient_t; + +/** + * Initializes a network socket client connection. + * + * @param client The client struct to initialize. + * @param host The hostname or IP address to connect to. + * @param port The port number to connect to. + * @param user User data to pass to callbacks. + * @param onConnect Callback for when the connection is established. + * @param onError Callback for when an error occurs. + * @param onDisconnect Callback for when the connection is disconnected. + */ +void networkSocketClientInit( + networksocketclient_t *client, + const char_t *host, + uint16_t port, + void *user, + void (*onConnect)(void *user), + void (*onError)(errorret_t error, void *user), + void (*onDisconnect)(void *user) +); \ No newline at end of file diff --git a/src/dusklinux/network/CMakeLists.txt b/src/dusklinux/network/CMakeLists.txt index c1322dc3..53b35a3b 100644 --- a/src/dusklinux/network/CMakeLists.txt +++ b/src/dusklinux/network/CMakeLists.txt @@ -6,4 +6,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC networklinux.c + networksocketclientlinux.c ) diff --git a/src/dusklinux/network/networksocketclientlinux.c b/src/dusklinux/network/networksocketclientlinux.c new file mode 100644 index 00000000..919779ca --- /dev/null +++ b/src/dusklinux/network/networksocketclientlinux.c @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "network/networksocketclient.h" +#include "assert/assert.h" +#include "util/memory.h" + +#include +#include +#include +#include +#include +#include + +void networkSocketClientLinuxInit( + networksocketclient_t *client, + const char_t *host, + uint16_t port, + void *user, + void (*onConnect)(void *user), + void (*onError)(errorret_t error, void *user), + void (*onDisconnect)(void *user) +) { + assertTrue(client->user == user, "Net client init mismatch?"); + assertTrue(client->onConnect == onConnect, "Net client init mismatch?"); + assertTrue(client->onError == onError, "Net client init mismatch?"); + assertTrue(client->onDisconnect == onDisconnect, "Net client init mismatch?"); + + // Create the thread. + threadInit(&client->platform.thread, networkSocketClientLinuxThread); + client->platform.thread.data = client; + + threadStart(&client->platform.thread); +} + +void networkSocketClientLinuxThread(thread_t *thread) { + assertNotNull(thread, "Thread cannot be NULL."); + assertNotNull(thread->data, "Thread data cannot be NULL."); + + networksocketclient_t *client = (networksocketclient_t *)thread->data; + + // Setup socket FD + client->platform.sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(client->platform.sockfd < 0) { + errorret_t ret = errorThrowImpl( + &client->errorState, ERROR_NOT_OK, + __FILE__, __func__, __LINE__, + "Failed to create socket." + ); + client->onError(ret, client->user); + return; + } + + // Configure server address. + char_t *host = "google.com"; + int port = 443; + + struct sockaddr_in serverAddr; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(port); + struct hostent *server = gethostbyname(host); + if(server == NULL) { + errorret_t ret = errorThrowImpl( + &client->errorState, ERROR_NOT_OK, + __FILE__, __func__, __LINE__, + "Failed to resolve host." + ); + client->onError(ret, client->user); + return; + } + + memoryCopy(&serverAddr.sin_addr.s_addr, server->h_addr, server->h_length); + + // Connect to server. + if(connect( + client->platform.sockfd, + (struct sockaddr *)&serverAddr, + sizeof(serverAddr) + ) < 0) { + errorret_t ret = errorThrowImpl( + &client->errorState, ERROR_NOT_OK, + __FILE__, __func__, __LINE__, + "Failed to connect to server." + ); + client->onError(ret, client->user); + return; + } + + // At this point we are connected. + client->onConnect(client->user); + + // Hangup for now. + close(client->platform.sockfd); + client->onDisconnect(client->user); +} \ No newline at end of file diff --git a/src/dusklinux/network/networksocketclientlinux.h b/src/dusklinux/network/networksocketclientlinux.h new file mode 100644 index 00000000..a37b26b1 --- /dev/null +++ b/src/dusklinux/network/networksocketclientlinux.h @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "error/error.h" +#include "thread/thread.h" + +typedef struct { + int sockfd; + thread_t thread; +} networksocketclientlinux_t; + +typedef struct networksocketclient_s networksocketclient_t; + +/** + * Refer to networkSocketClientInit for documentation. + */ +void networkSocketClientLinuxInit( + networksocketclient_t *client, + const char_t *host, + uint16_t port, + void *user, + void (*onConnect)(void *user), + void (*onError)(errorret_t error, void *user), + void (*onDisconnect)(void *user) +); + +/** + * Async thread for handling the socket connection. + * + * @param thread Thread structure passed. + */ +void networkSocketClientLinuxThread(thread_t *thread); \ No newline at end of file diff --git a/src/dusklinux/network/networksocketclientplatform.h b/src/dusklinux/network/networksocketclientplatform.h new file mode 100644 index 00000000..83e8c677 --- /dev/null +++ b/src/dusklinux/network/networksocketclientplatform.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "networksocketclientlinux.h" + +#define networkSocketClientPlatformInit networkSocketClientLinuxInit + +typedef networksocketclientlinux_t networksocketclientplatform_t; \ No newline at end of file