From 8f2f1fd4969bf9f763853fc4546867ad38873682 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 17 Apr 2026 17:00:03 -0500 Subject: [PATCH] Added network info --- cmake/targets/linux.cmake | 1 + src/dusk/engine/engine.c | 20 ++++++++ src/dusk/network/CMakeLists.txt | 1 + src/dusk/network/networkinfo.c | 24 +++++++++ src/dusk/network/networkinfo.h | 57 +++++++++++++++++++++ src/dusklinux/network/networklinux.c | 68 +++++++++++++++++++++++++ src/dusklinux/network/networklinux.h | 12 ++++- src/dusklinux/network/networkplatform.h | 1 + src/duskpsp/network/networkplatform.h | 1 + src/duskpsp/network/networkpsp.c | 24 +++++++++ src/duskpsp/network/networkpsp.h | 10 +++- 11 files changed, 216 insertions(+), 3 deletions(-) create mode 100644 src/dusk/network/networkinfo.c create mode 100644 src/dusk/network/networkinfo.h diff --git a/cmake/targets/linux.cmake b/cmake/targets/linux.cmake index 6b7ee984..c7ab2361 100644 --- a/cmake/targets/linux.cmake +++ b/cmake/targets/linux.cmake @@ -40,5 +40,6 @@ target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC DUSK_INPUT_POINTER DUSK_INPUT_GAMEPAD DUSK_TIME_DYNAMIC + DUSK_NETWORK_IPV6 THREAD_PTHREAD=1 ) \ No newline at end of file diff --git a/src/dusk/engine/engine.c b/src/dusk/engine/engine.c index 447b35ce..b0cb047a 100644 --- a/src/dusk/engine/engine.c +++ b/src/dusk/engine/engine.c @@ -21,6 +21,7 @@ #include "game/game.h" #include "physics/physicsmanager.h" #include "network/network.h" +#include "network/networkinfo.h" #include "system/system.h" #include "display/mesh/cube.h" @@ -37,6 +38,25 @@ void goOffline(); void onNetworkConnected(void *user) { onlineSwapTime = TIME.time + 3.0f; + + networkinfo_t info = networkGetInfo(); + if(info.type == NETWORK_TYPE_IPV4) { + printf( + "Connected to network with IPv4 address: " NETWORK_INFO_FORMAT_IPV4 "\n", + info.ipv4.ip[0], info.ipv4.ip[1], info.ipv4.ip[2], info.ipv4.ip[3] + ); + #ifdef DUSK_NETWORK_IPV6 + } else if(info.type == NETWORK_TYPE_IPV6) { + printf( + "Connected to network with IPv6 address: " NETWORK_INFO_FORMAT_IPV6 "\n", + info.ipv6.ip[0], info.ipv6.ip[1], info.ipv6.ip[2], info.ipv6.ip[3], + info.ipv6.ip[4], info.ipv6.ip[5], info.ipv6.ip[6], info.ipv6.ip[7], + info.ipv6.ip[8], info.ipv6.ip[9], info.ipv6.ip[10], info.ipv6.ip[11], + info.ipv6.ip[12], info.ipv6.ip[13], info.ipv6.ip[14], info.ipv6.ip[15] + ); + #endif + } + printf("Network connected, I will disconnect at: %.2f1.\n", onlineSwapTime); } diff --git a/src/dusk/network/CMakeLists.txt b/src/dusk/network/CMakeLists.txt index 6680fc6d..6926e0b1 100644 --- a/src/dusk/network/CMakeLists.txt +++ b/src/dusk/network/CMakeLists.txt @@ -6,4 +6,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC network.c + networkinfo.c ) diff --git a/src/dusk/network/networkinfo.c b/src/dusk/network/networkinfo.c new file mode 100644 index 00000000..d60980be --- /dev/null +++ b/src/dusk/network/networkinfo.c @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "network.h" +#include "networkinfo.h" +#include "network/networkplatform.h" +#include "assert/assert.h" + +#ifndef networkPlatformGetInfo + #error "networkPlatformGetInfo must be defined" +#endif + +networkinfo_t networkGetInfo() { + assertTrue( + NETWORK.state == NETWORK_STATE_CONNECTED, + "networkGetInfo called when not connected" + ); + + return networkPlatformGetInfo(); +} \ No newline at end of file diff --git a/src/dusk/network/networkinfo.h b/src/dusk/network/networkinfo.h new file mode 100644 index 00000000..06c33c9a --- /dev/null +++ b/src/dusk/network/networkinfo.h @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +#define NETWORK_INFO_IPV4_DNS_COUNT_MAX 2 +#define NETWORK_INFO_IPV4_OCTET_COUNT 4 +#define NETWORK_INFO_IPV6_OCTET_COUNT 16 +#define NETWORK_INFO_IPV6_DNS_COUNT_MAX 2 +#define NETWORK_INFO_FORMAT_IPV4 "%u.%u.%u.%u" +#define NETWORK_INFO_FORMAT_IPV6 \ + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x" + +typedef enum { + NETWORK_TYPE_IPV4, + #ifdef DUSK_NETWORK_IPV6 + NETWORK_TYPE_IPV6, + #endif +} networktype_t; + +typedef struct { + uint8_t ip[NETWORK_INFO_IPV4_OCTET_COUNT]; + // uint8_t subnet[NETWORK_INFO_IPV4_OCTET_COUNT]; + // uint8_t gateway[NETWORK_INFO_IPV4_OCTET_COUNT]; + // uint8_t dns[NETWORK_INFO_IPV4_OCTET_COUNT][NETWORK_INFO_IPV4_DNS_COUNT_MAX]; +} networkinfoipv4_t; + +#ifdef DUSK_NETWORK_IPV6 + typedef struct { + uint8_t ip[NETWORK_INFO_IPV6_OCTET_COUNT]; + // uint8_t subnet[NETWORK_INFO_IPV6_OCTET_COUNT]; + // uint8_t gateway[NETWORK_INFO_IPV6_OCTET_COUNT]; + // uint8_t dns[NETWORK_INFO_IPV6_OCTET_COUNT][NETWORK_INFO_IPV6_DNS_COUNT_MAX]; + } networkinfoipv6_t; +#endif + +typedef struct { + networktype_t type; + union { + networkinfoipv4_t ipv4; + #ifdef DUSK_NETWORK_IPV6 + networkinfoipv6_t ipv6; + #endif + }; +} networkinfo_t; + +/** + * Returns the network information for the currently active network connection. + * + * @return Network information for the currently active network connection. + */ +networkinfo_t networkGetInfo(); \ No newline at end of file diff --git a/src/dusklinux/network/networklinux.c b/src/dusklinux/network/networklinux.c index 1a9e20ed..2a0b5eb1 100644 --- a/src/dusklinux/network/networklinux.c +++ b/src/dusklinux/network/networklinux.c @@ -54,4 +54,72 @@ bool_t networkLinuxIsConnected() { errorret_t networkLinuxDispose() { curl_global_cleanup(); errorOk(); +} + +networkinfo_t networkLinuxGetInfo() { + networkinfo_t info; + memset(&info, 0, sizeof(networkinfo_t)); + + bool_t found = false; + + struct ifaddrs *ifaddr, *ifa; + if(getifaddrs(&ifaddr) == -1) { + assertUnreachable("getifaddrs failed"); + } + + // Find the first non-loopback interface with an IP address + for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_name || !ifa->ifa_flags) continue; + + // Skip loopback (localhost) + if(ifa->ifa_flags & IFF_LOOPBACK) continue; + + // Is interface up and running? + if(!(ifa->ifa_flags & IFF_UP)) continue; + if(!(ifa->ifa_flags & IFF_RUNNING)) continue; + if(ifa->ifa_addr == NULL) continue; + + // Check for IPv4 address + if(ifa->ifa_addr->sa_family == AF_INET) { + info.type = NETWORK_TYPE_IPV4; + + struct sockaddr_in *sa = (struct sockaddr_in *)ifa->ifa_addr; + memoryCopy( + info.ipv4.ip, + &sa->sin_addr, + NETWORK_INFO_IPV4_OCTET_COUNT + ); + + found = true; + + // sa = (struct sockaddr_in *)ifa->ifa_netmask; + // memoryCopy( + // info.ipv4.subnet, + // &sa->sin_addr, + // NETWORK_INFO_IPV4_OCTET_COUNT + // ); + break; + } + + // Check for IPv6 address + #ifdef DUSK_NETWORK_IPV6 + if(ifa->ifa_addr->sa_family == AF_INET6) { + info.type = NETWORK_TYPE_IPV6; + + struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ifa->ifa_addr; + memoryCopy( + info.ipv6.ip, + &sa->sin6_addr, + NETWORK_INFO_IPV6_OCTET_COUNT + ); + found = true; + break; + } + #endif + } + + freeifaddrs(ifaddr); + + assertTrue(found, "No active network interface found?"); + return info; } \ No newline at end of file diff --git a/src/dusklinux/network/networklinux.h b/src/dusklinux/network/networklinux.h index 508085f3..df0e1d1a 100644 --- a/src/dusklinux/network/networklinux.h +++ b/src/dusklinux/network/networklinux.h @@ -7,10 +7,11 @@ #pragma once #include "error/error.h" +#include "network/networkinfo.h" #include #include #include - +#include typedef struct { void *nothing; @@ -44,4 +45,11 @@ bool_t networkLinuxIsConnected(); * * @return Any error that occurs. */ -errorret_t networkLinuxDispose(); \ No newline at end of file +errorret_t networkLinuxDispose(); + +/** + * Gets the network information for the currently active network connection. + * + * @return Network information for the currently active network connection. + */ +networkinfo_t networkLinuxGetInfo(); \ No newline at end of file diff --git a/src/dusklinux/network/networkplatform.h b/src/dusklinux/network/networkplatform.h index 120e5ad8..0fc02849 100644 --- a/src/dusklinux/network/networkplatform.h +++ b/src/dusklinux/network/networkplatform.h @@ -12,5 +12,6 @@ #define networkPlatformUpdate networkLinuxUpdate #define networkPlatformDispose networkLinuxDispose #define networkPlatformIsConnected networkLinuxIsConnected +#define networkPlatformGetInfo networkLinuxGetInfo typedef networklinux_t networkplatform_t; \ No newline at end of file diff --git a/src/duskpsp/network/networkplatform.h b/src/duskpsp/network/networkplatform.h index 4fe84754..1645d141 100644 --- a/src/duskpsp/network/networkplatform.h +++ b/src/duskpsp/network/networkplatform.h @@ -14,5 +14,6 @@ #define networkPlatformIsConnected networkPSPIsConnected #define networkPlatformRequestConnection networkPSPRequestConnection #define networkPlatformRequestDisconnection networkPSPRequestDisconnection +#define networkPlatformGetInfo networkPSPGetInfo typedef networkpsp_t networkplatform_t; \ No newline at end of file diff --git a/src/duskpsp/network/networkpsp.c b/src/duskpsp/network/networkpsp.c index a05ce54f..73c12b80 100644 --- a/src/duskpsp/network/networkpsp.c +++ b/src/duskpsp/network/networkpsp.c @@ -232,4 +232,28 @@ errorret_t networkPSPTerm() { } errorOk(); +} + +networkinfo_t networkPSPGetInfo() { + networkinfo_t netInfo; + memoryZero(&netInfo, sizeof(networkinfo_t)); + + // Get the IP address of the current connection. + union SceNetApctlInfo info; + int ret = sceNetApctlGetInfo(PSP_NET_APCTL_INFO_IP, &info); + assertTrue(ret >= 0, "Failed to get IP address"); + + // Parse the IP address string into octets. + netInfo.type = NETWORK_TYPE_IPV4; + ret = sscanf( + info.ip, + "%hhu.%hhu.%hhu.%hhu", + &netInfo.ipv4.ip[0], + &netInfo.ipv4.ip[1], + &netInfo.ipv4.ip[2], + &netInfo.ipv4.ip[3] + ); + assertTrue(ret == 4, "Failed to parse IP address"); + + return netInfo; } \ No newline at end of file diff --git a/src/duskpsp/network/networkpsp.h b/src/duskpsp/network/networkpsp.h index f6bcd4ad..fc3a400f 100644 --- a/src/duskpsp/network/networkpsp.h +++ b/src/duskpsp/network/networkpsp.h @@ -7,6 +7,7 @@ #pragma once #include "error/error.h" +#include "network/networkinfo.h" #include "system/systempsp.h" #include #include @@ -99,4 +100,11 @@ void networkPSPRequestDisconnection( * * @return Error state (if any). */ -errorret_t networkPSPTerm(); \ No newline at end of file +errorret_t networkPSPTerm(); + +/** + * Gets the network information for the currently active network connection. + * + * @return Network information for the currently active network connection. + */ +networkinfo_t networkPSPGetInfo(); \ No newline at end of file