diff options
author | Fernando S <fsahmkow27@gmail.com> | 2021-08-16 17:10:00 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-16 17:10:00 +0200 |
commit | 521e6ac17483e975e2fc731fed879e9f3edf7547 (patch) | |
tree | ca5a9b7559f475de1d461885f3df9ee2282bccdf /src | |
parent | Merge pull request #6861 from yzct12345/const-mempy-is-all-the-speed (diff) | |
parent | network_interface: correct formatting (diff) | |
download | yuzu-521e6ac17483e975e2fc731fed879e9f3edf7547.tar yuzu-521e6ac17483e975e2fc731fed879e9f3edf7547.tar.gz yuzu-521e6ac17483e975e2fc731fed879e9f3edf7547.tar.bz2 yuzu-521e6ac17483e975e2fc731fed879e9f3edf7547.tar.lz yuzu-521e6ac17483e975e2fc731fed879e9f3edf7547.tar.xz yuzu-521e6ac17483e975e2fc731fed879e9f3edf7547.tar.zst yuzu-521e6ac17483e975e2fc731fed879e9f3edf7547.zip |
Diffstat (limited to 'src')
-rw-r--r-- | src/common/settings.h | 3 | ||||
-rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/core/hle/service/nifm/nifm.cpp | 45 | ||||
-rw-r--r-- | src/core/network/network.cpp | 64 | ||||
-rw-r--r-- | src/core/network/network.h | 24 | ||||
-rw-r--r-- | src/core/network/network_interface.cpp | 203 | ||||
-rw-r--r-- | src/core/network/network_interface.h | 29 | ||||
-rw-r--r-- | src/yuzu/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/yuzu/configuration/config.cpp | 6 | ||||
-rw-r--r-- | src/yuzu/configuration/config.h | 2 | ||||
-rw-r--r-- | src/yuzu/configuration/configure.ui | 10 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_dialog.cpp | 4 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_network.cpp (renamed from src/yuzu/configuration/configure_service.cpp) | 39 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_network.h (renamed from src/yuzu/configuration/configure_service.h) | 10 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_network.ui (renamed from src/yuzu/configuration/configure_service.ui) | 63 |
15 files changed, 408 insertions, 102 deletions
diff --git a/src/common/settings.h b/src/common/settings.h index 1ba9b606c..c65746749 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -558,9 +558,10 @@ struct Values { BasicSetting<std::string> log_filter{"*:Info", "log_filter"}; BasicSetting<bool> use_dev_keys{false, "use_dev_keys"}; - // Services + // Network BasicSetting<std::string> bcat_backend{"none", "bcat_backend"}; BasicSetting<bool> bcat_boxcat_local{false, "bcat_boxcat_local"}; + BasicSetting<std::string> network_interface{std::string(), "network_interface"}; // WebService BasicSetting<bool> enable_telemetry{true, "enable_telemetry"}; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5c99c00f5..f5cf5c16a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -636,6 +636,8 @@ add_library(core STATIC memory.h network/network.cpp network/network.h + network/network_interface.cpp + network/network_interface.h network/sockets.h perf_stats.cpp perf_stats.h diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index e742db48f..0a53c0c81 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -11,6 +11,7 @@ #include "core/hle/service/nifm/nifm.h" #include "core/hle/service/service.h" #include "core/network/network.h" +#include "core/network/network_interface.h" namespace Service::NIFM { @@ -179,10 +180,10 @@ private: IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - if (Settings::values.bcat_backend.GetValue() == "none") { - rb.PushEnum(RequestState::NotSubmitted); - } else { + if (Network::GetHostIPv4Address().has_value()) { rb.PushEnum(RequestState::Connected); + } else { + rb.PushEnum(RequestState::NotSubmitted); } } @@ -322,12 +323,15 @@ private: void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); - const auto [ipv4, error] = Network::GetHostIPv4Address(); - UNIMPLEMENTED_IF(error != Network::Errno::SUCCESS); + auto ipv4 = Network::GetHostIPv4Address(); + if (!ipv4) { + LOG_ERROR(Service_NIFM, "Couldn't get host IPv4 address, defaulting to 0.0.0.0"); + ipv4.emplace(Network::IPv4Address{0, 0, 0, 0}); + } IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.PushRaw(ipv4); + rb.PushRaw(*ipv4); } void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_NIFM, "called"); @@ -354,10 +358,10 @@ private: static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting), "IpConfigInfo has incorrect size."); - const IpConfigInfo ip_config_info{ + IpConfigInfo ip_config_info{ .ip_address_setting{ .is_automatic{true}, - .current_address{192, 168, 1, 100}, + .current_address{0, 0, 0, 0}, .subnet_mask{255, 255, 255, 0}, .gateway{192, 168, 1, 1}, }, @@ -368,6 +372,19 @@ private: }, }; + const auto iface = Network::GetSelectedNetworkInterface(); + if (iface) { + ip_config_info.ip_address_setting = + IpAddressSetting{.is_automatic{true}, + .current_address{Network::TranslateIPv4(iface->ip_address)}, + .subnet_mask{Network::TranslateIPv4(iface->subnet_mask)}, + .gateway{Network::TranslateIPv4(iface->gateway)}}; + + } else { + LOG_ERROR(Service_NIFM, + "Couldn't get host network configuration info, using default values"); + } + IPC::ResponseBuilder rb{ctx, 2 + (sizeof(IpConfigInfo) + 3) / sizeof(u32)}; rb.Push(ResultSuccess); rb.PushRaw<IpConfigInfo>(ip_config_info); @@ -384,10 +401,10 @@ private: IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - if (Settings::values.bcat_backend.GetValue() == "none") { - rb.Push<u8>(0); - } else { + if (Network::GetHostIPv4Address().has_value()) { rb.Push<u8>(1); + } else { + rb.Push<u8>(0); } } void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) { @@ -395,10 +412,10 @@ private: IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - if (Settings::values.bcat_backend.GetValue() == "none") { - rb.Push<u8>(0); - } else { + if (Network::GetHostIPv4Address().has_value()) { rb.Push<u8>(1); + } else { + rb.Push<u8>(0); } } }; diff --git a/src/core/network/network.cpp b/src/core/network/network.cpp index 375bc79ec..4732d4485 100644 --- a/src/core/network/network.cpp +++ b/src/core/network/network.cpp @@ -10,9 +10,10 @@ #include "common/common_funcs.h" #ifdef _WIN32 -#define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname #include <winsock2.h> +#include <ws2tcpip.h> #elif YUZU_UNIX +#include <arpa/inet.h> #include <errno.h> #include <fcntl.h> #include <netdb.h> @@ -27,7 +28,9 @@ #include "common/assert.h" #include "common/common_types.h" #include "common/logging/log.h" +#include "common/settings.h" #include "core/network/network.h" +#include "core/network/network_interface.h" #include "core/network/sockets.h" namespace Network { @@ -47,11 +50,6 @@ void Finalize() { WSACleanup(); } -constexpr IPv4Address TranslateIPv4(in_addr addr) { - auto& bytes = addr.S_un.S_un_b; - return IPv4Address{bytes.s_b1, bytes.s_b2, bytes.s_b3, bytes.s_b4}; -} - sockaddr TranslateFromSockAddrIn(SockAddrIn input) { sockaddr_in result; @@ -138,12 +136,6 @@ void Initialize() {} void Finalize() {} -constexpr IPv4Address TranslateIPv4(in_addr addr) { - const u32 bytes = addr.s_addr; - return IPv4Address{static_cast<u8>(bytes), static_cast<u8>(bytes >> 8), - static_cast<u8>(bytes >> 16), static_cast<u8>(bytes >> 24)}; -} - sockaddr TranslateFromSockAddrIn(SockAddrIn input) { sockaddr_in result; @@ -182,7 +174,7 @@ linger MakeLinger(bool enable, u32 linger_value) { } bool EnableNonBlock(int fd, bool enable) { - int flags = fcntl(fd, F_GETFD); + int flags = fcntl(fd, F_GETFL); if (flags == -1) { return false; } @@ -191,7 +183,7 @@ bool EnableNonBlock(int fd, bool enable) { } else { flags &= ~O_NONBLOCK; } - return fcntl(fd, F_SETFD, flags) == 0; + return fcntl(fd, F_SETFL, flags) == 0; } Errno TranslateNativeError(int e) { @@ -227,8 +219,12 @@ Errno GetAndLogLastError() { #else int e = errno; #endif + const Errno err = TranslateNativeError(e); + if (err == Errno::AGAIN) { + return err; + } LOG_ERROR(Network, "Socket operation error: {}", NativeErrorToString(e)); - return TranslateNativeError(e); + return err; } int TranslateDomain(Domain domain) { @@ -353,27 +349,29 @@ NetworkInstance::~NetworkInstance() { Finalize(); } -std::pair<IPv4Address, Errno> GetHostIPv4Address() { - std::array<char, 256> name{}; - if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) { - return {IPv4Address{}, GetAndLogLastError()}; +std::optional<IPv4Address> GetHostIPv4Address() { + const std::string& selected_network_interface = Settings::values.network_interface.GetValue(); + const auto network_interfaces = Network::GetAvailableNetworkInterfaces(); + if (network_interfaces.size() == 0) { + LOG_ERROR(Network, "GetAvailableNetworkInterfaces returned no interfaces"); + return {}; } - hostent* const ent = gethostbyname(name.data()); - if (!ent) { - return {IPv4Address{}, GetAndLogLastError()}; - } - if (ent->h_addr_list == nullptr) { - UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list"); - return {IPv4Address{}, Errno::SUCCESS}; - } - if (ent->h_length != sizeof(in_addr)) { - UNIMPLEMENTED_MSG("Unexpected size={} in hostent->h_length", ent->h_length); - } + const auto res = + std::ranges::find_if(network_interfaces, [&selected_network_interface](const auto& iface) { + return iface.name == selected_network_interface; + }); + + if (res != network_interfaces.end()) { + char ip_addr[16] = {}; + ASSERT(inet_ntop(AF_INET, &res->ip_address, ip_addr, sizeof(ip_addr)) != nullptr); + LOG_INFO(Network, "IP address: {}", ip_addr); - in_addr addr; - std::memcpy(&addr, ent->h_addr_list[0], sizeof(addr)); - return {TranslateIPv4(addr), Errno::SUCCESS}; + return TranslateIPv4(res->ip_address); + } else { + LOG_ERROR(Network, "Couldn't find selected interface \"{}\"", selected_network_interface); + return {}; + } } std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { diff --git a/src/core/network/network.h b/src/core/network/network.h index bd30f1899..fdd3e4655 100644 --- a/src/core/network/network.h +++ b/src/core/network/network.h @@ -5,11 +5,18 @@ #pragma once #include <array> +#include <optional> #include <utility> #include "common/common_funcs.h" #include "common/common_types.h" +#ifdef _WIN32 +#include <winsock2.h> +#elif YUZU_UNIX +#include <netinet/in.h> +#endif + namespace Network { class Socket; @@ -92,8 +99,21 @@ public: ~NetworkInstance(); }; +#ifdef _WIN32 +constexpr IPv4Address TranslateIPv4(in_addr addr) { + auto& bytes = addr.S_un.S_un_b; + return IPv4Address{bytes.s_b1, bytes.s_b2, bytes.s_b3, bytes.s_b4}; +} +#elif YUZU_UNIX +constexpr IPv4Address TranslateIPv4(in_addr addr) { + const u32 bytes = addr.s_addr; + return IPv4Address{static_cast<u8>(bytes), static_cast<u8>(bytes >> 8), + static_cast<u8>(bytes >> 16), static_cast<u8>(bytes >> 24)}; +} +#endif + /// @brief Returns host's IPv4 address -/// @return Pair of an array of human ordered IPv4 address (e.g. 192.168.0.1) and an error code -std::pair<IPv4Address, Errno> GetHostIPv4Address(); +/// @return human ordered IPv4 address (e.g. 192.168.0.1) as an array +std::optional<IPv4Address> GetHostIPv4Address(); } // namespace Network diff --git a/src/core/network/network_interface.cpp b/src/core/network/network_interface.cpp new file mode 100644 index 000000000..cecc9aa11 --- /dev/null +++ b/src/core/network/network_interface.cpp @@ -0,0 +1,203 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <algorithm> +#include <fstream> +#include <sstream> +#include <vector> + +#include "common/bit_cast.h" +#include "common/common_types.h" +#include "common/logging/log.h" +#include "common/settings.h" +#include "common/string_util.h" +#include "core/network/network_interface.h" + +#ifdef _WIN32 +#include <iphlpapi.h> +#else +#include <cerrno> +#include <ifaddrs.h> +#include <net/if.h> +#endif + +namespace Network { + +#ifdef _WIN32 + +std::vector<NetworkInterface> GetAvailableNetworkInterfaces() { + std::vector<IP_ADAPTER_ADDRESSES> adapter_addresses; + DWORD ret = ERROR_BUFFER_OVERFLOW; + DWORD buf_size = 0; + + // retry up to 5 times + for (int i = 0; i < 5 && ret == ERROR_BUFFER_OVERFLOW; i++) { + ret = GetAdaptersAddresses( + AF_INET, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_GATEWAYS, + nullptr, adapter_addresses.data(), &buf_size); + + if (ret == ERROR_BUFFER_OVERFLOW) { + adapter_addresses.resize((buf_size / sizeof(IP_ADAPTER_ADDRESSES)) + 1); + } else { + break; + } + } + + if (ret == NO_ERROR) { + std::vector<NetworkInterface> result; + + for (auto current_address = adapter_addresses.data(); current_address != nullptr; + current_address = current_address->Next) { + if (current_address->FirstUnicastAddress == nullptr || + current_address->FirstUnicastAddress->Address.lpSockaddr == nullptr) { + continue; + } + + if (current_address->OperStatus != IfOperStatusUp) { + continue; + } + + const auto ip_addr = Common::BitCast<struct sockaddr_in>( + *current_address->FirstUnicastAddress->Address.lpSockaddr) + .sin_addr; + + ULONG mask = 0; + if (ConvertLengthToIpv4Mask(current_address->FirstUnicastAddress->OnLinkPrefixLength, + &mask) != NO_ERROR) { + LOG_ERROR(Network, "Failed to convert IPv4 prefix length to subnet mask"); + continue; + } + + struct in_addr gateway = {.S_un{.S_addr{0}}}; + if (current_address->FirstGatewayAddress != nullptr && + current_address->FirstGatewayAddress->Address.lpSockaddr != nullptr) { + gateway = Common::BitCast<struct sockaddr_in>( + *current_address->FirstGatewayAddress->Address.lpSockaddr) + .sin_addr; + } + + result.push_back(NetworkInterface{ + .name{Common::UTF16ToUTF8(std::wstring{current_address->FriendlyName})}, + .ip_address{ip_addr}, + .subnet_mask = in_addr{.S_un{.S_addr{mask}}}, + .gateway = gateway}); + } + + return result; + } else { + LOG_ERROR(Network, "Failed to get network interfaces with GetAdaptersAddresses"); + return {}; + } +} + +#else + +std::vector<NetworkInterface> GetAvailableNetworkInterfaces() { + std::vector<NetworkInterface> result; + + struct ifaddrs* ifaddr = nullptr; + + if (getifaddrs(&ifaddr) != 0) { + LOG_ERROR(Network, "Failed to get network interfaces with getifaddrs: {}", + std::strerror(errno)); + return result; + } + + for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr) { + continue; + } + + if (ifa->ifa_addr->sa_family != AF_INET) { + continue; + } + + if ((ifa->ifa_flags & IFF_UP) == 0 || (ifa->ifa_flags & IFF_LOOPBACK) != 0) { + continue; + } + + std::uint32_t gateway{0}; + std::ifstream file{"/proc/net/route"}; + if (file.is_open()) { + + // ignore header + file.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); + + bool gateway_found = false; + + for (std::string line; std::getline(file, line);) { + std::istringstream iss{line}; + + std::string iface_name{}; + iss >> iface_name; + if (iface_name != ifa->ifa_name) { + continue; + } + + iss >> std::hex; + + std::uint32_t dest{0}; + iss >> dest; + if (dest != 0) { + // not the default route + continue; + } + + iss >> gateway; + + std::uint16_t flags{0}; + iss >> flags; + + // flag RTF_GATEWAY (defined in <linux/route.h>) + if ((flags & 0x2) == 0) { + continue; + } + + gateway_found = true; + break; + } + + if (!gateway_found) { + gateway = 0; + } + } else { + LOG_ERROR(Network, "Failed to open \"/proc/net/route\""); + } + + result.push_back(NetworkInterface{ + .name{ifa->ifa_name}, + .ip_address{Common::BitCast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr}, + .subnet_mask{Common::BitCast<struct sockaddr_in>(*ifa->ifa_netmask).sin_addr}, + .gateway{in_addr{.s_addr = gateway}}}); + } + + freeifaddrs(ifaddr); + + return result; +} + +#endif + +std::optional<NetworkInterface> GetSelectedNetworkInterface() { + const std::string& selected_network_interface = Settings::values.network_interface.GetValue(); + const auto network_interfaces = Network::GetAvailableNetworkInterfaces(); + if (network_interfaces.size() == 0) { + LOG_ERROR(Network, "GetAvailableNetworkInterfaces returned no interfaces"); + return {}; + } + + const auto res = + std::ranges::find_if(network_interfaces, [&selected_network_interface](const auto& iface) { + return iface.name == selected_network_interface; + }); + + if (res != network_interfaces.end()) { + return *res; + } else { + LOG_ERROR(Network, "Couldn't find selected interface \"{}\"", selected_network_interface); + return {}; + } +} + +} // namespace Network diff --git a/src/core/network/network_interface.h b/src/core/network/network_interface.h new file mode 100644 index 000000000..980edb2f5 --- /dev/null +++ b/src/core/network/network_interface.h @@ -0,0 +1,29 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <optional> +#include <string> +#include <vector> + +#ifdef _WIN32 +#include <winsock2.h> +#else +#include <netinet/in.h> +#endif + +namespace Network { + +struct NetworkInterface { + std::string name; + struct in_addr ip_address; + struct in_addr subnet_mask; + struct in_addr gateway; +}; + +std::vector<NetworkInterface> GetAvailableNetworkInterfaces(); +std::optional<NetworkInterface> GetSelectedNetworkInterface(); + +} // namespace Network diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index cb4bdcc7e..cf68a95b5 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -102,9 +102,9 @@ add_executable(yuzu configuration/configure_profile_manager.cpp configuration/configure_profile_manager.h configuration/configure_profile_manager.ui - configuration/configure_service.cpp - configuration/configure_service.h - configuration/configure_service.ui + configuration/configure_network.cpp + configuration/configure_network.h + configuration/configure_network.ui configuration/configure_system.cpp configuration/configure_system.h configuration/configure_system.ui diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 380379eb4..377795326 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -692,6 +692,7 @@ void Config::ReadServiceValues() { qt_config->beginGroup(QStringLiteral("Services")); ReadBasicSetting(Settings::values.bcat_backend); ReadBasicSetting(Settings::values.bcat_boxcat_local); + ReadBasicSetting(Settings::values.network_interface); qt_config->endGroup(); } @@ -1144,7 +1145,7 @@ void Config::SaveValues() { SaveDataStorageValues(); SaveDebuggingValues(); SaveDisabledAddOnValues(); - SaveServiceValues(); + SaveNetworkValues(); SaveUIValues(); SaveWebServiceValues(); SaveMiscellaneousValues(); @@ -1238,11 +1239,12 @@ void Config::SaveDebuggingValues() { qt_config->endGroup(); } -void Config::SaveServiceValues() { +void Config::SaveNetworkValues() { qt_config->beginGroup(QStringLiteral("Services")); WriteBasicSetting(Settings::values.bcat_backend); WriteBasicSetting(Settings::values.bcat_boxcat_local); + WriteBasicSetting(Settings::values.network_interface); qt_config->endGroup(); } diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index c1d7feb9f..9555f4498 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -88,7 +88,7 @@ private: void SaveCoreValues(); void SaveDataStorageValues(); void SaveDebuggingValues(); - void SaveServiceValues(); + void SaveNetworkValues(); void SaveDisabledAddOnValues(); void SaveMiscellaneousValues(); void SavePathValues(); diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui index fca9aed5f..6258dcf20 100644 --- a/src/yuzu/configuration/configure.ui +++ b/src/yuzu/configuration/configure.ui @@ -147,12 +147,12 @@ <string>Web</string> </attribute> </widget> - <widget class="ConfigureService" name="serviceTab"> + <widget class="ConfigureNetwork" name="networkTab"> <property name="accessibleName"> - <string>Services</string> + <string>Network</string> </property> <attribute name="title"> - <string>Services</string> + <string>Network</string> </attribute> </widget> </widget> @@ -242,9 +242,9 @@ <container>1</container> </customwidget> <customwidget> - <class>ConfigureService</class> + <class>ConfigureNetwork</class> <extends>QWidget</extends> - <header>configuration/configure_service.h</header> + <header>configuration/configure_network.h</header> <container>1</container> </customwidget> <customwidget> diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index bc009b6b3..fe4186157 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -67,7 +67,7 @@ void ConfigureDialog::ApplyConfiguration() { ui->audioTab->ApplyConfiguration(); ui->debugTab->ApplyConfiguration(); ui->webTab->ApplyConfiguration(); - ui->serviceTab->ApplyConfiguration(); + ui->networkTab->ApplyConfiguration(); Core::System::GetInstance().ApplySettings(); Settings::LogSettings(); } @@ -103,7 +103,7 @@ Q_DECLARE_METATYPE(QList<QWidget*>); void ConfigureDialog::PopulateSelectionList() { const std::array<std::pair<QString, QList<QWidget*>>, 6> items{ {{tr("General"), {ui->generalTab, ui->hotkeysTab, ui->uiTab, ui->webTab, ui->debugTab}}, - {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}}, + {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->networkTab, ui->filesystemTab}}, {tr("CPU"), {ui->cpuTab}}, {tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}}, {tr("Audio"), {ui->audioTab}}, diff --git a/src/yuzu/configuration/configure_service.cpp b/src/yuzu/configuration/configure_network.cpp index 4aa424803..ae22f1018 100644 --- a/src/yuzu/configuration/configure_service.cpp +++ b/src/yuzu/configuration/configure_network.cpp @@ -5,9 +5,11 @@ #include <QGraphicsItem> #include <QtConcurrent/QtConcurrent> #include "common/settings.h" +#include "core/core.h" #include "core/hle/service/bcat/backend/boxcat.h" -#include "ui_configure_service.h" -#include "yuzu/configuration/configure_service.h" +#include "core/network/network_interface.h" +#include "ui_configure_network.h" +#include "yuzu/configuration/configure_network.h" #ifdef YUZU_ENABLE_BOXCAT namespace { @@ -35,8 +37,8 @@ QString FormatEventStatusString(const Service::BCAT::EventStatus& status) { } // Anonymous namespace #endif -ConfigureService::ConfigureService(QWidget* parent) - : QWidget(parent), ui(std::make_unique<Ui::ConfigureService>()) { +ConfigureNetwork::ConfigureNetwork(QWidget* parent) + : QWidget(parent), ui(std::make_unique<Ui::ConfigureNetwork>()) { ui->setupUi(this); ui->bcat_source->addItem(QStringLiteral("None")); @@ -47,29 +49,42 @@ ConfigureService::ConfigureService(QWidget* parent) ui->bcat_source->addItem(QStringLiteral("Boxcat"), QStringLiteral("boxcat")); #endif + ui->network_interface->addItem(tr("None")); + for (const auto& iface : Network::GetAvailableNetworkInterfaces()) { + ui->network_interface->addItem(QString::fromStdString(iface.name)); + } + connect(ui->bcat_source, QOverload<int>::of(&QComboBox::currentIndexChanged), this, - &ConfigureService::OnBCATImplChanged); + &ConfigureNetwork::OnBCATImplChanged); this->SetConfiguration(); } -ConfigureService::~ConfigureService() = default; +ConfigureNetwork::~ConfigureNetwork() = default; -void ConfigureService::ApplyConfiguration() { +void ConfigureNetwork::ApplyConfiguration() { Settings::values.bcat_backend = ui->bcat_source->currentText().toLower().toStdString(); + Settings::values.network_interface = ui->network_interface->currentText().toStdString(); } -void ConfigureService::RetranslateUi() { +void ConfigureNetwork::RetranslateUi() { ui->retranslateUi(this); } -void ConfigureService::SetConfiguration() { +void ConfigureNetwork::SetConfiguration() { + const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); + const int index = ui->bcat_source->findData(QString::fromStdString(Settings::values.bcat_backend.GetValue())); ui->bcat_source->setCurrentIndex(index == -1 ? 0 : index); + + const std::string& network_interface = Settings::values.network_interface.GetValue(); + + ui->network_interface->setCurrentText(QString::fromStdString(network_interface)); + ui->network_interface->setEnabled(runtime_lock); } -std::pair<QString, QString> ConfigureService::BCATDownloadEvents() { +std::pair<QString, QString> ConfigureNetwork::BCATDownloadEvents() { #ifdef YUZU_ENABLE_BOXCAT std::optional<std::string> global; std::map<std::string, Service::BCAT::EventStatus> map; @@ -114,7 +129,7 @@ std::pair<QString, QString> ConfigureService::BCATDownloadEvents() { #endif } -void ConfigureService::OnBCATImplChanged() { +void ConfigureNetwork::OnBCATImplChanged() { #ifdef YUZU_ENABLE_BOXCAT const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat"); ui->bcat_empty_header->setHidden(!boxcat); @@ -133,7 +148,7 @@ void ConfigureService::OnBCATImplChanged() { #endif } -void ConfigureService::OnUpdateBCATEmptyLabel(std::pair<QString, QString> string) { +void ConfigureNetwork::OnUpdateBCATEmptyLabel(std::pair<QString, QString> string) { #ifdef YUZU_ENABLE_BOXCAT const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat"); if (boxcat) { diff --git a/src/yuzu/configuration/configure_service.h b/src/yuzu/configuration/configure_network.h index f5c1b703a..442b68e6b 100644 --- a/src/yuzu/configuration/configure_service.h +++ b/src/yuzu/configuration/configure_network.h @@ -9,15 +9,15 @@ #include <QWidget> namespace Ui { -class ConfigureService; +class ConfigureNetwork; } -class ConfigureService : public QWidget { +class ConfigureNetwork : public QWidget { Q_OBJECT public: - explicit ConfigureService(QWidget* parent = nullptr); - ~ConfigureService() override; + explicit ConfigureNetwork(QWidget* parent = nullptr); + ~ConfigureNetwork() override; void ApplyConfiguration(); void RetranslateUi(); @@ -29,6 +29,6 @@ private: void OnBCATImplChanged(); void OnUpdateBCATEmptyLabel(std::pair<QString, QString> string); - std::unique_ptr<Ui::ConfigureService> ui; + std::unique_ptr<Ui::ConfigureNetwork> ui; QFutureWatcher<std::pair<QString, QString>> watcher{this}; }; diff --git a/src/yuzu/configuration/configure_service.ui b/src/yuzu/configuration/configure_network.ui index 9668dd557..5f9b7e97b 100644 --- a/src/yuzu/configuration/configure_service.ui +++ b/src/yuzu/configuration/configure_network.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>ConfigureService</class> - <widget class="QWidget" name="ConfigureService"> + <class>ConfigureNetwork</class> + <widget class="QWidget" name="ConfigureNetwork"> <property name="geometry"> <rect> <x>0</x> @@ -17,21 +17,37 @@ <item> <layout class="QVBoxLayout" name="verticalLayout_3"> <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>General</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="1"> + <widget class="QComboBox" name="network_interface"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Network Interface</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> <widget class="QGroupBox" name="groupBox"> <property name="title"> <string>BCAT</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="1" colspan="2"> - <widget class="QLabel" name="label_2"> - <property name="maximumSize"> - <size> - <width>260</width> - <height>16777215</height> - </size> - </property> + <item row="3" column="0"> + <widget class="QLabel" name="bcat_empty_header"> <property name="text"> - <string>BCAT is Nintendo's way of sending data to games to engage its community and unlock additional content.</string> + <string/> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> </property> <property name="wordWrap"> <bool>true</bool> @@ -51,11 +67,8 @@ </property> </widget> </item> - <item row="3" column="1" colspan="2"> - <widget class="QLabel" name="bcat_empty_label"> - <property name="enabled"> - <bool>true</bool> - </property> + <item row="1" column="1" colspan="2"> + <widget class="QLabel" name="label_2"> <property name="maximumSize"> <size> <width>260</width> @@ -63,10 +76,7 @@ </size> </property> <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + <string>BCAT is Nintendo's way of sending data to games to engage its community and unlock additional content.</string> </property> <property name="wordWrap"> <bool>true</bool> @@ -86,8 +96,17 @@ <item row="0" column="1" colspan="2"> <widget class="QComboBox" name="bcat_source"/> </item> - <item row="3" column="0"> - <widget class="QLabel" name="bcat_empty_header"> + <item row="3" column="1" colspan="2"> + <widget class="QLabel" name="bcat_empty_label"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="maximumSize"> + <size> + <width>260</width> + <height>16777215</height> + </size> + </property> <property name="text"> <string/> </property> |