From de447e7bf4bbb5f26aa298305e89a50f46e94c18 Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 2 Jul 2026 00:39:20 +0000 Subject: [PATCH] we love when cURL has bugs? --- src/core/hle/service/sockets/bsd.cpp | 22 ++++------ src/core/internal_network/network.cpp | 49 +++++++++++++++------- src/core/internal_network/socket_proxy.cpp | 8 ++-- src/core/internal_network/socket_types.h | 11 +++-- 4 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 32cd481bd6..2fc35ccf4b 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -717,7 +717,7 @@ std::pair BSD::FcntlImpl(s32 fd, Network::FcntlCmd cmd, s32 ASSERT(arg == 0); return {descriptor.flags, Network::Errno::SUCCESS}; case Network::FcntlCmd::SETFL: { - const bool enable = (arg & Network::FLAG_O_NONBLOCK) != 0; + const bool enable = (arg & u32(Network::FcntlFlags::NONBLOCK_ANY)) != 0; const Network::Errno bsd_errno = descriptor.socket->SetNonBlock(enable); if (bsd_errno != Network::Errno::SUCCESS) { return {-1, bsd_errno}; @@ -800,18 +800,16 @@ std::pair BSD::RecvImpl(s32 fd, u32 flags, std::vector& FileDescriptor& descriptor = *file_descriptors[fd]; // Apply flags - using Network::FLAG_MSG_DONTWAIT; - using Network::FLAG_O_NONBLOCK; - if ((flags & FLAG_MSG_DONTWAIT) != 0) { - flags &= ~FLAG_MSG_DONTWAIT; - if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) { + if ((flags & u32(Network::MsgOpt::DONTWAIT)) != 0) { + flags &= ~u32(Network::MsgOpt::DONTWAIT); + if ((descriptor.flags & u32(Network::FcntlFlags::NONBLOCK_ANY)) == 0) { descriptor.socket->SetNonBlock(true); } } const auto [ret, bsd_errno] = descriptor.socket->Recv(flags, message); // Restore original state - if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) + if ((descriptor.flags & u32(Network::FcntlFlags::NONBLOCK_ANY)) == 0) descriptor.socket->SetNonBlock(false); return {ret, bsd_errno}; } @@ -834,11 +832,9 @@ std::pair BSD::RecvFromImpl(s32 fd, u32 flags, std::vector< } // Apply flags - using Network::FLAG_MSG_DONTWAIT; - using Network::FLAG_O_NONBLOCK; - if ((flags & FLAG_MSG_DONTWAIT) != 0) { - flags &= ~FLAG_MSG_DONTWAIT; - if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) { + if ((flags & u32(Network::MsgOpt::DONTWAIT)) != 0) { + flags &= ~u32(Network::MsgOpt::DONTWAIT); + if ((descriptor.flags & u32(Network::FcntlFlags::NONBLOCK_ANY)) == 0) { descriptor.socket->SetNonBlock(true); } } @@ -846,7 +842,7 @@ std::pair BSD::RecvFromImpl(s32 fd, u32 flags, std::vector< const auto [ret, bsd_errno] = descriptor.socket->RecvFrom(flags, message, p_addr_in); // Restore original state - if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) { + if ((descriptor.flags & u32(Network::FcntlFlags::NONBLOCK_ANY)) == 0) { descriptor.socket->SetNonBlock(false); } diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index 8ff2abe9ca..b15d583f6a 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -845,22 +845,43 @@ std::variant, GetAddrInfoError> GetAddressInfo(const std:: return TranslateGetAddrInfoErrorFromNative(gai_err); } std::vector ret{}; - for (auto* current = addrinfo; current; current = current->ai_next) { - LOG_DEBUG(Network, "- entry prot={},socktype={},family={},len={}", current->ai_protocol, current->ai_socktype, current->ai_family, current->ai_addrlen); - // We should only get AF_INET results due to the hints value. - if (current->ai_family == AF_INET && current->ai_addrlen == sizeof(sockaddr_in)) { - auto& out = ret.emplace_back(); - out.family = TranslateDomainFromNative(current->ai_family); - out.socket_type = TranslateTypeFromNative(current->ai_socktype); - out.protocol = TranslateProtocolFromNative(current->ai_protocol); - out.addr = TranslateToSockAddrIn(*reinterpret_cast(current->ai_addr), current->ai_addrlen); - if (current->ai_canonname != nullptr) { - out.canon_name = current->ai_canonname; + + auto const add_entries = [&](auto const&& filter_fn) { + for (auto* current = addrinfo; current; current = current->ai_next) { + if (filter_fn(current)) { + LOG_DEBUG(Network, "- entry prot={},socktype={},family={},len={}", current->ai_protocol, current->ai_socktype, current->ai_family, current->ai_addrlen); + // We should only get AF_INET results due to the hints value. + if (current->ai_family == AF_INET && current->ai_addrlen == sizeof(sockaddr_in)) { + auto& out = ret.emplace_back(); + out.family = TranslateDomainFromNative(current->ai_family); + out.socket_type = TranslateTypeFromNative(current->ai_socktype); + out.protocol = TranslateProtocolFromNative(current->ai_protocol); + out.addr = TranslateToSockAddrIn(*reinterpret_cast(current->ai_addr), current->ai_addrlen); + if (current->ai_canonname != nullptr) { + out.canon_name = current->ai_canonname; + } + } else { + LOG_ERROR(Network, "invalid entry family={},len={}", current->ai_family, current->ai_addrlen); + } } - } else { - LOG_ERROR(Network, "invalid entry family={},len={}", current->ai_family, current->ai_addrlen); } - } + }; + + // Let me explain slowly, so HB app store depends ENTIRELY on the switch returning + // getaddrinfo stuff in a particular order, right? + // cURL is used by hb app store, which uses a tiny library called "get"; the + // specific version that 99% of users run has a bug with DNS cache queries... + // unfortunely we can only do what we do best: emulate the issue away. + // + // Please see this fuckery here -> https://github.com/curl/curl/issues/9274 + // Place fucking UDP last + add_entries([](auto* current) { + return current->ai_protocol != IPPROTO_UDP; + }); + // Off to the shitter you go! + add_entries([](auto* current) { + return current->ai_protocol == IPPROTO_UDP; + }); freeaddrinfo(addrinfo); return ret; } diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp index 0dae5ad0c9..bbfb4a5420 100644 --- a/src/core/internal_network/socket_proxy.cpp +++ b/src/core/internal_network/socket_proxy.cpp @@ -156,8 +156,7 @@ std::pair ProxySocket::RecvFrom(int flags, std::span message, Ne } } -std::pair ProxySocket::ReceivePacket(int flags, std::span message, Network::SockAddrIn* addr, - std::size_t max_length) { +std::pair ProxySocket::ReceivePacket(int flags, std::span message, Network::SockAddrIn* addr, std::size_t max_length) { ProxyPacket& packet = received_packets.front(); if (addr) { addr->len = 16; @@ -167,7 +166,7 @@ std::pair ProxySocket::ReceivePacket(int flags, std::span messag addr->zeroes = {}; } - bool peek = (flags & FLAG_MSG_PEEK) != 0; + bool peek = (flags & u32(Network::MsgOpt::PEEK)) != 0; std::size_t read_bytes; if (packet.data.size() > max_length) { read_bytes = max_length; @@ -180,8 +179,7 @@ std::pair ProxySocket::ReceivePacket(int flags, std::span messag return {-1, Errno::MSGSIZE}; } else if (protocol == Protocol::TCP) { std::vector numArray(packet.data.size() - max_length); - std::copy(packet.data.begin() + max_length, packet.data.end(), - std::back_inserter(numArray)); + std::copy(packet.data.begin() + max_length, packet.data.end(), std::back_inserter(numArray)); packet.data = numArray; } } else { diff --git a/src/core/internal_network/socket_types.h b/src/core/internal_network/socket_types.h index 3db114f80c..1d43a2c643 100644 --- a/src/core/internal_network/socket_types.h +++ b/src/core/internal_network/socket_types.h @@ -291,6 +291,13 @@ enum class FcntlCmd : s32 { SETFL = 4, }; +enum class FcntlFlags : u32 { + NONBLOCK = 0x004, + NONBLOCK_NX = 0x800, + // Provided for convenience + NONBLOCK_ANY = u32(NONBLOCK) | u32(NONBLOCK_NX), +}; + /// Array of IPv4 address using IPv4Address = std::array; @@ -331,10 +338,6 @@ struct Linger { }; static_assert(sizeof(Linger) == 8); -constexpr u32 FLAG_MSG_PEEK = 0x2; -constexpr u32 FLAG_MSG_DONTWAIT = 0x80; -constexpr u32 FLAG_O_NONBLOCK = 0x800; - /// @brief Cross-platform addrinfo structure (not guest) struct AddrInfo { Domain family;