Browse Source

we love when cURL has bugs?

lizzie/refactor-networking-12
lizzie 1 month ago
parent
commit
de447e7bf4
  1. 22
      src/core/hle/service/sockets/bsd.cpp
  2. 49
      src/core/internal_network/network.cpp
  3. 8
      src/core/internal_network/socket_proxy.cpp
  4. 11
      src/core/internal_network/socket_types.h

22
src/core/hle/service/sockets/bsd.cpp

@ -717,7 +717,7 @@ std::pair<s32, Network::Errno> 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<s32, Network::Errno> BSD::RecvImpl(s32 fd, u32 flags, std::vector<u8>&
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<s32, Network::Errno> 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<s32, Network::Errno> 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);
}

49
src/core/internal_network/network.cpp

@ -845,22 +845,43 @@ std::variant<std::vector<AddrInfo>, GetAddrInfoError> GetAddressInfo(const std::
return TranslateGetAddrInfoErrorFromNative(gai_err);
}
std::vector<AddrInfo> 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<sockaddr_in*>(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<sockaddr_in*>(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;
}

8
src/core/internal_network/socket_proxy.cpp

@ -156,8 +156,7 @@ std::pair<s32, Errno> ProxySocket::RecvFrom(int flags, std::span<u8> message, Ne
}
}
std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::span<u8> message, Network::SockAddrIn* addr,
std::size_t max_length) {
std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::span<u8> 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<s32, Errno> ProxySocket::ReceivePacket(int flags, std::span<u8> 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<s32, Errno> ProxySocket::ReceivePacket(int flags, std::span<u8> messag
return {-1, Errno::MSGSIZE};
} else if (protocol == Protocol::TCP) {
std::vector<u8> 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 {

11
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<u8, 4>;
@ -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;

Loading…
Cancel
Save