Compare commits

...

8 Commits

Author SHA1 Message Date
heyimalaap 6388365306
Merge 0d03ddfae9 into 1ba8541da9 2024-12-22 11:32:53 +01:00
JMC47 1ba8541da9
Merge pull request #13091 from mitaclaw/ranges-modernization-2-returns
Ranges Algorithms Modernization - Return
2024-12-20 12:50:19 -05:00
Alaap Surendran 0d03ddfae9 Swap out enet with a fork that supports IPv6 2024-11-28 05:49:20 +05:30
mitaclaw 3d0d03b871 Modernize `std::partition` with ranges
The new return value is `std::ranges::subrange`.
2024-10-17 18:39:13 -07:00
mitaclaw 5f3a8ff0de Modernize `std::unique` with ranges
The new return value is `std::ranges::subrange`.
2024-10-17 18:39:12 -07:00
mitaclaw be0b13da97 Simplify `std::remove` with `std::erase`
`std::erase` is a replacement for the remove-erase idiom.

Changes to `OpenModeToAndroid` inadvertently revealed that the prior implementation had UB (potentially deleting the end iterator). This is now fixed.
2024-10-17 18:38:34 -07:00
mitaclaw 4fde0f2868 Modernize `std::search` with ranges
The new return value is `std::ranges::subrange`.
2024-10-17 18:38:34 -07:00
mitaclaw 0352f24a8e Modernize `std::mismatch` with ranges
The new return value is `std::ranges::mismatch_result`, an alias for the pair-like type `std::ranges::in_in_result`.
2024-10-17 18:38:34 -07:00
17 changed files with 84 additions and 44 deletions

6
.gitmodules vendored
View File

@ -69,9 +69,6 @@
[submodule "Externals/xxhash/xxHash"] [submodule "Externals/xxhash/xxHash"]
path = Externals/xxhash/xxHash path = Externals/xxhash/xxHash
url = https://github.com/Cyan4973/xxHash.git url = https://github.com/Cyan4973/xxHash.git
[submodule "Externals/enet/enet"]
path = Externals/enet/enet
url = https://github.com/lsalzman/enet.git
[submodule "hidapi-src"] [submodule "hidapi-src"]
path = Externals/hidapi/hidapi-src path = Externals/hidapi/hidapi-src
url = https://github.com/libusb/hidapi url = https://github.com/libusb/hidapi
@ -84,3 +81,6 @@
[submodule "Externals/Vulkan-Headers"] [submodule "Externals/Vulkan-Headers"]
path = Externals/Vulkan-Headers path = Externals/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git url = https://github.com/KhronosGroup/Vulkan-Headers.git
[submodule "enet"]
path = Externals/enet/enet
url = https://github.com/freeminer/enet.git

View File

@ -660,7 +660,10 @@ endif()
dolphin_find_optional_system_library(pugixml Externals/pugixml) dolphin_find_optional_system_library(pugixml Externals/pugixml)
dolphin_find_optional_system_library_pkgconfig(ENET libenet>=1.3.18 enet::enet Externals/enet) # Using static enet from Externals since we are using a fork that supports
# IPv6 (freeminers/enet)
message(STATUS "Using static enet from Externals (freeminer/enet)")
add_subdirectory(Externals/enet)
dolphin_find_optional_system_library_pkgconfig(xxhash libxxhash>=0.8.2 xxhash::xxhash Externals/xxhash) dolphin_find_optional_system_library_pkgconfig(xxhash libxxhash>=0.8.2 xxhash::xxhash Externals/xxhash)

2
Externals/enet/enet vendored

@ -1 +1 @@
Subproject commit 2a85cd64459f6ba038d233a634d9440490dbba12 Subproject commit 9a74b511091a172cd78bf57f0d4a440f41600de1

View File

@ -62,7 +62,7 @@ bool IsPathAndroidContent(std::string_view uri)
std::string OpenModeToAndroid(std::string mode) std::string OpenModeToAndroid(std::string mode)
{ {
// The 'b' specifier is not supported by Android. Since we're on POSIX, it's fine to just skip it. // The 'b' specifier is not supported by Android. Since we're on POSIX, it's fine to just skip it.
mode.erase(std::remove(mode.begin(), mode.end(), 'b')); std::erase(mode, 'b');
if (mode == "r") if (mode == "r")
return "r"; return "r";

View File

@ -18,7 +18,7 @@ void WakeupThread(ENetHost* host)
address.port = host->address.port; address.port = host->address.port;
else else
enet_socket_get_address(host->socket, &address); enet_socket_get_address(host->socket, &address);
address.host = 0x0100007f; // localhost address.host = in6addr_loopback; // localhost or ::1
u8 byte = 0; u8 byte = 0;
ENetBuffer buf; ENetBuffer buf;
buf.data = &byte; buf.data = &byte;
@ -62,4 +62,22 @@ bool SendPacket(ENetPeer* socket, const sf::Packet& packet, u8 channel_id)
return true; return true;
} }
std::optional<in6_addr> AddressFromString(const std::string& addr_str)
{
in6_addr addr;
memset(&addr, 0, sizeof(in6_addr));
if (!inet_pton(AF_INET6, addr_str.c_str(), &addr))
{
in_addr addr_v4;
if (!inet_pton(AF_INET, addr_str.c_str(), &addr_v4)) {
return {};
}
u32 v6_mapped_addr[4] = {0, 0, htonl(0x0000ffff), *reinterpret_cast<u32*>(&addr_v4)};
memcpy(&addr, v6_mapped_addr, sizeof(in6_addr));
}
return addr;
}
} // namespace Common::ENet } // namespace Common::ENet

View File

@ -7,6 +7,7 @@
#include <SFML/Network/Packet.hpp> #include <SFML/Network/Packet.hpp>
#include <enet/enet.h> #include <enet/enet.h>
#include <optional>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
@ -21,6 +22,7 @@ using ENetHostPtr = std::unique_ptr<ENetHost, ENetHostDeleter>;
void WakeupThread(ENetHost* host); void WakeupThread(ENetHost* host);
int ENET_CALLBACK InterceptCallback(ENetHost* host, ENetEvent* event); int ENET_CALLBACK InterceptCallback(ENetHost* host, ENetEvent* event);
bool SendPacket(ENetPeer* socket, const sf::Packet& packet, u8 channel_id); bool SendPacket(ENetPeer* socket, const sf::Packet& packet, u8 channel_id);
std::optional<in6_addr> AddressFromString(const std::string& addr);
// used for traversal packets and wake-up packets // used for traversal packets and wake-up packets
constexpr int SKIPPABLE_EVENT = 42; constexpr int SKIPPABLE_EVENT = 42;

View File

@ -98,7 +98,8 @@ std::vector<std::string> DoFileSearch(const std::vector<std::string>& directorie
// not because std::filesystem returns duplicates). Also note that this pathname-based uniqueness // not because std::filesystem returns duplicates). Also note that this pathname-based uniqueness
// isn't as thorough as std::filesystem::equivalent. // isn't as thorough as std::filesystem::equivalent.
std::ranges::sort(result); std::ranges::sort(result);
result.erase(std::unique(result.begin(), result.end()), result.end()); const auto unique_result = std::ranges::unique(result);
result.erase(unique_result.begin(), unique_result.end());
// Dolphin expects to be able to use "/" (DIR_SEP) everywhere. // Dolphin expects to be able to use "/" (DIR_SEP) everywhere.
// std::filesystem uses the OS separator. // std::filesystem uses the OS separator.

View File

@ -20,13 +20,13 @@ QoSSession::QoSSession(ENetPeer* peer, int tos_val) : m_peer(peer)
if (!QOSCreateHandle(&ver, &m_qos_handle)) if (!QOSCreateHandle(&ver, &m_qos_handle))
return; return;
sockaddr_in sin = {}; sockaddr_in6 sin6 = {};
sin.sin_family = AF_INET; sin6.sin6_family = AF_INET6;
sin.sin_port = ENET_HOST_TO_NET_16(peer->host->address.port); sin6.sin6_port = ENET_HOST_TO_NET_16(peer->host->address.port);
sin.sin_addr.s_addr = peer->host->address.host; memcpy(&sin6.sin6_addr, &peer->host->address.host, sizeof(struct in6_addr));
if (QOSAddSocketToFlow(m_qos_handle, peer->host->socket, reinterpret_cast<PSOCKADDR>(&sin), if (QOSAddSocketToFlow(m_qos_handle, peer->host->socket, reinterpret_cast<PSOCKADDR>(&sin6),
QOSTrafficTypeControl, QOS_NON_ADAPTIVE_FLOW, &m_qos_flow_id)) QOSTrafficTypeControl, QOS_NON_ADAPTIVE_FLOW, &m_qos_flow_id))
{ {
// We shift the complete ToS value by 3 to get rid of the 3 bit ECN field // We shift the complete ToS value by 3 to get rid of the 3 bit ECN field

View File

@ -49,12 +49,17 @@ TraversalClient::FailureReason TraversalClient::GetFailureReason() const
void TraversalClient::ReconnectToServer() void TraversalClient::ReconnectToServer()
{ {
if (enet_address_set_host(&m_ServerAddress, m_Server.c_str())) if (auto addr = Common::ENet::AddressFromString(m_Server))
{
m_ServerAddress.host = *addr;
}
else
{ {
OnFailure(FailureReason::BadHost); OnFailure(FailureReason::BadHost);
return; return;
} }
m_ServerAddress.port = m_port; m_ServerAddress.port = m_port;
m_ServerAddress.sin6_scope_id = 0;
m_State = State::Connecting; m_State = State::Connecting;
@ -71,12 +76,16 @@ static ENetAddress MakeENetAddress(const TraversalInetAddress& address)
ENetAddress eaddr{}; ENetAddress eaddr{};
if (address.isIPV6) if (address.isIPV6)
{ {
eaddr.port = 0; // no support yet :( memcpy(&eaddr.host, &address.address, sizeof(address.address));
eaddr.port = ntohs(address.port);
eaddr.sin6_scope_id = 0;
} }
else else
{ {
eaddr.host = address.address[0]; u32 ipv4_mapped_addr[4] = {0, 0, 0xffff0000, address.address[0]};
memcpy(&eaddr.host, &ipv4_mapped_addr, sizeof(ipv4_mapped_addr));
eaddr.port = ntohs(address.port); eaddr.port = ntohs(address.port);
eaddr.sin6_scope_id = 0;
} }
return eaddr; return eaddr;
} }
@ -97,7 +106,7 @@ void TraversalClient::ConnectToClient(std::string_view host)
bool TraversalClient::TestPacket(u8* data, size_t size, ENetAddress* from) bool TraversalClient::TestPacket(u8* data, size_t size, ENetAddress* from)
{ {
if (from->host == m_ServerAddress.host && from->port == m_ServerAddress.port) if (in6_equal(from->host, m_ServerAddress.host) && from->port == m_ServerAddress.port)
{ {
if (size < sizeof(TraversalPacket)) if (size < sizeof(TraversalPacket))
{ {
@ -299,7 +308,7 @@ void TraversalClient::NewTraversalTest()
if (m_TestSocket != ENET_SOCKET_NULL) if (m_TestSocket != ENET_SOCKET_NULL)
enet_socket_destroy(m_TestSocket); enet_socket_destroy(m_TestSocket);
m_TestSocket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); m_TestSocket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
ENetAddress addr = {ENET_HOST_ANY, 0}; ENetAddress addr = {in6addr_any, 0, 0};
if (m_TestSocket == ENET_SOCKET_NULL || enet_socket_bind(m_TestSocket, &addr) < 0) if (m_TestSocket == ENET_SOCKET_NULL || enet_socket_bind(m_TestSocket, &addr) < 0)
{ {
// error, abort // error, abort
@ -373,8 +382,8 @@ void TraversalClient::HandleTraversalTest()
waitCondition = 0; waitCondition = 0;
break; break;
} }
else if (rv < int(sizeof(packet)) || raddr.host != m_ServerAddress.host || else if (rv < int(sizeof(packet)) || !in6_equal(raddr.host, m_ServerAddress.host) ||
raddr.host != m_portAlt || packet.requestId != m_TestRequestId) raddr.port != m_portAlt || packet.requestId != m_TestRequestId)
{ {
// irrelevant packet, ignore // irrelevant packet, ignore
continue; continue;
@ -452,7 +461,7 @@ bool EnsureTraversalClient(const std::string& server, u16 server_port, u16 serve
g_OldServerPortAlt = server_port_alt; g_OldServerPortAlt = server_port_alt;
g_OldListenPort = listen_port; g_OldListenPort = listen_port;
ENetAddress addr = {ENET_HOST_ANY, listen_port}; ENetAddress addr = {in6addr_any, listen_port, 0};
auto host = Common::ENet::ENetHostPtr{enet_host_create(&addr, // address auto host = Common::ENet::ENetHostPtr{enet_host_create(&addr, // address
50, // peerCount 50, // peerCount
NetPlay::CHANNEL_COUNT, // channelLimit NetPlay::CHANNEL_COUNT, // channelLimit

View File

@ -1085,10 +1085,10 @@ void WiiSockMan::UpdatePollCommands()
std::vector<int> original_order(pfds.size()); std::vector<int> original_order(pfds.size());
std::iota(original_order.begin(), original_order.end(), 0); std::iota(original_order.begin(), original_order.end(), 0);
// Select indices with valid fds // Select indices with valid fds
auto mid = std::partition(original_order.begin(), original_order.end(), [&](auto i) { const auto partition_result = std::ranges::partition(original_order, [&](auto i) {
return GetHostSocket(memory.Read_U32(pcmd.buffer_out + 0xc * i)) >= 0; return GetHostSocket(memory.Read_U32(pcmd.buffer_out + 0xc * i)) >= 0;
}); });
const auto n_valid = std::distance(original_order.begin(), mid); const auto n_valid = std::distance(original_order.begin(), partition_result.begin());
// Move all the valid pollfds to the front of the vector // Move all the valid pollfds to the front of the vector
for (auto i = 0; i < n_valid; ++i) for (auto i = 0; i < n_valid; ++i)

View File

@ -1081,11 +1081,11 @@ void MovieManager::LoadInput(const std::string& movie_path)
std::vector<u8> movInput(m_current_byte); std::vector<u8> movInput(m_current_byte);
t_record.ReadArray(movInput.data(), movInput.size()); t_record.ReadArray(movInput.data(), movInput.size());
const auto result = std::mismatch(movInput.begin(), movInput.end(), m_temp_input.begin()); const auto mismatch_result = std::ranges::mismatch(movInput, m_temp_input);
if (result.first != movInput.end()) if (mismatch_result.in1 != movInput.end())
{ {
const ptrdiff_t mismatch_index = std::distance(movInput.begin(), result.first); const ptrdiff_t mismatch_index = std::distance(movInput.begin(), mismatch_result.in1);
// this is a "you did something wrong" alert for the user's benefit. // this is a "you did something wrong" alert for the user's benefit.
// we'll try to say what's going on in excruciating detail, otherwise the user might not // we'll try to say what's going on in excruciating detail, otherwise the user might not

View File

@ -147,8 +147,12 @@ NetPlayClient::NetPlayClient(const std::string& address, const u16 port, NetPlay
m_client->mtu = std::min(m_client->mtu, NetPlay::MAX_ENET_MTU); m_client->mtu = std::min(m_client->mtu, NetPlay::MAX_ENET_MTU);
ENetAddress addr; ENetAddress addr;
enet_address_set_host(&addr, address.c_str()); if (auto parsed_addr = Common::ENet::AddressFromString(address))
{
addr.host = *parsed_addr;
}
addr.port = port; addr.port = port;
addr.sin6_scope_id = 0;
m_server = enet_host_connect(m_client, &addr, CHANNEL_COUNT, 0); m_server = enet_host_connect(m_client, &addr, CHANNEL_COUNT, 0);

View File

@ -152,8 +152,9 @@ NetPlayServer::NetPlayServer(const u16 port, const bool forward_port, NetPlayUI*
else else
{ {
ENetAddress serverAddr; ENetAddress serverAddr;
serverAddr.host = ENET_HOST_ANY; serverAddr.host = in6addr_any;
serverAddr.port = port; serverAddr.port = port;
serverAddr.sin6_scope_id = 0;
m_server = enet_host_create(&serverAddr, 10, CHANNEL_COUNT, 0, 0); m_server = enet_host_create(&serverAddr, 10, CHANNEL_COUNT, 0, 0);
if (m_server != nullptr) if (m_server != nullptr)
{ {
@ -304,8 +305,9 @@ void NetPlayServer::ThreadFunc()
{ {
// Actual client initialization is deferred to the receive event, so here // Actual client initialization is deferred to the receive event, so here
// we'll just log the new connection. // we'll just log the new connection.
INFO_LOG_FMT(NETPLAY, "Peer connected from: {:x}:{}", netEvent.peer->address.host, char host_str[48];
netEvent.peer->address.port); enet_address_get_host_ip(&netEvent.peer->address, host_str, 48);
INFO_LOG_FMT(NETPLAY, "Peer connected from: {}:{}", host_str, netEvent.peer->address.port);
} }
break; break;
case ENET_EVENT_TYPE_RECEIVE: case ENET_EVENT_TYPE_RECEIVE:
@ -320,16 +322,19 @@ void NetPlayServer::ThreadFunc()
// uninitialized client, we'll assume this is their initialization packet // uninitialized client, we'll assume this is their initialization packet
ConnectionError error; ConnectionError error;
{ {
INFO_LOG_FMT(NETPLAY, "Initializing peer {:x}:{}", netEvent.peer->address.host, char host_str[48];
netEvent.peer->address.port); enet_address_get_host_ip(&netEvent.peer->address, host_str, 48);
INFO_LOG_FMT(NETPLAY, "Initializing peer {}:{}", host_str, netEvent.peer->address.port);
std::lock_guard lkg(m_crit.game); std::lock_guard lkg(m_crit.game);
error = OnConnect(netEvent.peer, rpac); error = OnConnect(netEvent.peer, rpac);
} }
if (error != ConnectionError::NoError) if (error != ConnectionError::NoError)
{ {
INFO_LOG_FMT(NETPLAY, "Error {} initializing peer {:x}:{}", u8(error), char host_str[48];
netEvent.peer->address.host, netEvent.peer->address.port); enet_address_get_host_ip(&netEvent.peer->address, host_str, 48);
INFO_LOG_FMT(NETPLAY, "Error {} initializing peer {}:{}", u8(error), host_str,
netEvent.peer->address.port);
sf::Packet spac; sf::Packet spac;
spac << error; spac << error;

View File

@ -240,11 +240,9 @@ bool NANDImporter::ExtractCertificates()
for (const PEMCertificate& certificate : certificates) for (const PEMCertificate& certificate : certificates)
{ {
const auto search_result = const auto search_result = std::ranges::search(content_bytes, certificate.search_bytes);
std::search(content_bytes.begin(), content_bytes.end(), certificate.search_bytes.begin(),
certificate.search_bytes.end());
if (search_result == content_bytes.end()) if (search_result.empty())
{ {
ERROR_LOG_FMT(DISCIO, "ExtractCertificates: Could not find offset for certficate '{}'", ERROR_LOG_FMT(DISCIO, "ExtractCertificates: Could not find offset for certficate '{}'",
certificate.filename); certificate.filename);
@ -252,7 +250,8 @@ bool NANDImporter::ExtractCertificates()
} }
const std::string pem_file_path = m_nand_root + std::string(certificate.filename); const std::string pem_file_path = m_nand_root + std::string(certificate.filename);
const ptrdiff_t certificate_offset = std::distance(content_bytes.begin(), search_result); const ptrdiff_t certificate_offset =
std::distance(content_bytes.begin(), search_result.begin());
constexpr int min_offset = 2; constexpr int min_offset = 2;
if (certificate_offset < min_offset) if (certificate_offset < min_offset)
{ {

View File

@ -1570,7 +1570,7 @@ bool MainWindow::NetPlayJoin()
u16 host_port; u16 host_port;
if (server) if (server)
{ {
host_ip = "127.0.0.1"; host_ip = "::1";
host_port = server->GetPort(); host_port = server->GetPort();
} }
else else

View File

@ -309,11 +309,9 @@ void Settings::RemovePath(const QString& qpath)
std::string path = qpath.toStdString(); std::string path = qpath.toStdString();
std::vector<std::string> paths = Config::GetIsoPaths(); std::vector<std::string> paths = Config::GetIsoPaths();
auto new_end = std::remove(paths.begin(), paths.end(), path); if (std::erase(paths, path) == 0)
if (new_end == paths.end())
return; return;
paths.erase(new_end, paths.end());
Config::SetIsoPaths(paths); Config::SetIsoPaths(paths);
emit PathRemoved(qpath); emit PathRemoved(qpath);
} }

View File

@ -129,7 +129,8 @@ BuildExpression(const std::vector<ciface::Core::DeviceContainer::InputDetection>
// Remove duplicates // Remove duplicates
std::ranges::sort(alternations); std::ranges::sort(alternations);
alternations.erase(std::unique(alternations.begin(), alternations.end()), alternations.end()); const auto unique_result = std::ranges::unique(alternations);
alternations.erase(unique_result.begin(), unique_result.end());
return fmt::to_string(fmt::join(alternations, "|")); return fmt::to_string(fmt::join(alternations, "|"));
} }