diff --git a/core/libs/prx/libSceNetCtl/Export.cpp b/core/libs/prx/libSceNetCtl/Export.cpp index 592ab29a8..5f0ab11e2 100644 --- a/core/libs/prx/libSceNetCtl/Export.cpp +++ b/core/libs/prx/libSceNetCtl/Export.cpp @@ -8,7 +8,6 @@ #include #include #ifdef __linux__ -#include #include #endif #endif @@ -16,8 +15,10 @@ #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" +#include #include #include +#include #ifdef _WIN32 #include #endif @@ -83,6 +84,13 @@ static bool HostHasAddress(int family) { #endif } +extern "C" std::uint64_t NetCtlReadByteCounter_nid_no_patch(const char* path) { + std::ifstream file(path); + std::uint64_t value = 0; + if (!(file >> value)) throw std::runtime_error(std::string("sceNetCtlGetIfStat: no byte counter in ") + path); + return value; +} + static void HostTraffic(std::uint64_t& sent, std::uint64_t& received) { sent = 0; received = 0; @@ -100,11 +108,11 @@ static void HostTraffic(std::uint64_t& sent, std::uint64_t& received) { ifaddrs* interfaces = nullptr; if (getifaddrs(&interfaces) != 0) throw std::runtime_error("sceNetCtlGetIfStat: the host interface list is unavailable"); for (auto* item = interfaces; item; item = item->ifa_next) { - if (!item->ifa_addr || item->ifa_addr->sa_family != AF_PACKET || !item->ifa_data) continue; + if (!item->ifa_addr || item->ifa_addr->sa_family != AF_PACKET) continue; if (!(item->ifa_flags & IFF_UP) || (item->ifa_flags & IFF_LOOPBACK)) continue; - const auto* stats = static_cast(item->ifa_data); - sent += stats->tx_bytes; - received += stats->rx_bytes; + const std::string statistics = std::string("/sys/class/net/") + item->ifa_name + "/statistics/"; + sent += NetCtlReadByteCounter_nid_no_patch((statistics + "tx_bytes").c_str()); + received += NetCtlReadByteCounter_nid_no_patch((statistics + "rx_bytes").c_str()); } freeifaddrs(interfaces); #else diff --git a/core/libs/tests/GuestSceNet.cpp b/core/libs/tests/GuestSceNet.cpp index eab87d58b..712ef8d36 100644 --- a/core/libs/tests/GuestSceNet.cpp +++ b/core/libs/tests/GuestSceNet.cpp @@ -58,6 +58,7 @@ int APS5_VABI sceNetResolverDestroy(int); int APS5_VABI sceNetResolverGetError(int, int*); int APS5_VABI sceNetCtlGetState(int*); int APS5_VABI sceNetCtlGetIfStat(NetCtlIfStat*); +std::uint64_t NetCtlReadByteCounter_nid_no_patch(const char*); int APS5_VABI select_nid_postfix(int, void*, void*, void*, const void*); int APS5_VABI open_nid_postfix(const char*, int, int); int APS5_VABI close_nid_postfix(int); @@ -766,6 +767,22 @@ int main() { Require(sceNetCtlGetState(&state) == 0); Require(state == 0 || state == 3); Require(sceNetCtlGetIfStat(nullptr) == static_cast(0x80412107)); + { + const char* counterPath = "guest_sce_net_byte_counter.txt"; + std::FILE* counter = std::fopen(counterPath, "w"); + Require(counter != nullptr); + Require(std::fputs("1099511627776", counter) >= 0); + Require(std::fclose(counter) == 0); + Require(NetCtlReadByteCounter_nid_no_patch(counterPath) == 1099511627776ull); + Require(std::remove(counterPath) == 0); + bool missing = false; + try { + NetCtlReadByteCounter_nid_no_patch(counterPath); + } catch (const std::runtime_error&) { + missing = true; + } + Require(missing); + } NetCtlIfStat first{}; first.device = 7; first.reserved[7] = 7;