From 8ceecf6259820a4e495352e5e99e782e1c2a036c Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 15 Aug 2026 06:01:36 +0000 Subject: [PATCH] don't murder me for this change --- src/core/hle/service/sockets/bsd.cpp | 11 +++-- src/core/internal_network/network.cpp | 38 ++++++++------- src/core/internal_network/socket_icmp.cpp | 56 ++++++++++++++++------- src/core/internal_network/socket_icmp.h | 2 + 4 files changed, 69 insertions(+), 38 deletions(-) diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 4eff91a2d3..05756b5929 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -550,13 +550,14 @@ std::pair BSD::SocketImpl(Network::Domain domain, Network:: // ENONMEM might be thrown here LOG_INFO(Service, "New socket fd={},domain={},type={},prot={}", fd, domain, type, protocol); + // While room is important -- we need to remember ICMP takes priority over **everything else** + // TODO: rework this so proxy sockets can be done transparently? -- like what if i need + // to browse the internet while playing LDN or something stupid like that? auto room_member = Network::GetRoomMember().lock(); - if (room_member && room_member->IsConnected()) { - descriptor.socket = std::make_shared(); - } else if ((type == Network::Type::RAW || type == Network::Type::DGRAM) - && (domain == Network::Domain::INET && protocol == Network::Protocol::ICMP) - && (domain == Network::Domain::INET6 && protocol == Network::Protocol::ICMPV6)) { + if (protocol == Network::Protocol::ICMP || protocol == Network::Protocol::ICMPV6) { descriptor.socket = std::make_shared(); + } else if (room_member && room_member->IsConnected()) { + descriptor.socket = std::make_shared(); } else { descriptor.socket = std::make_shared(); } diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index 5d6efc1928..6c0cab391f 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -250,7 +250,7 @@ Errno TranslateNativeError(int e, CallType call_type = CallType::Other) { #endif -Errno GetAndLogLastError(CallType call_type = CallType::Other) { +Errno GetAndLogLastError(CallType call_type) { #ifdef _WIN32 int e = WSAGetLastError(); #else @@ -262,6 +262,12 @@ Errno GetAndLogLastError(CallType call_type = CallType::Other) { LOG_DEBUG(Network, "Socket operation error: {}", Common::NativeErrorToString(e)); return err; } + if (call_type == CallType::Send) { + // ISCONN + PIPE occur when send()/recv() is spammed on a socket which + // hasnt been properly initialized. + LOG_DEBUG(Network, "Socket operation error: {}", Common::NativeErrorToString(e)); + return err; + } LOG_ERROR(Network, "Socket operation error: {}", Common::NativeErrorToString(e)); return err; } @@ -907,7 +913,7 @@ std::pair Poll(std::span pollfds, s32 timeout) { if (res <= 0) { ASSERT(res == SOCKET_ERROR); - return {-1, GetAndLogLastError()}; + return {-1, GetAndLogLastError(CallType::Other)}; } return {res, Errno::SUCCESS}; } @@ -1027,7 +1033,7 @@ Errno Socket::GetSockOpt(Network::SocketLevel level, Network::OptName optname, s ASSERT(len == socklen_t(value.size())); return Errno::SUCCESS; } - return GetAndLogLastError(); + return GetAndLogLastError(CallType::Other); } Errno Socket::SetNonBlock(bool enable) { @@ -1035,7 +1041,7 @@ Errno Socket::SetNonBlock(bool enable) { is_non_blocking = enable; return Errno::SUCCESS; } - return GetAndLogLastError(); + return GetAndLogLastError(CallType::Other); } Errno Socket::SetSockOpt(Network::SocketLevel level, Network::OptName optname, std::span optval) { @@ -1050,20 +1056,20 @@ Errno Socket::SetSockOpt(Network::SocketLevel level, Network::OptName optname, s auto const linger_optval = MakeLinger(bool(linger.onoff), linger.linger); if (setsockopt(fd, native_level, native_optname, reinterpret_cast(&linger_optval), sizeof(linger_optval)) != SOCKET_ERROR) return Errno::SUCCESS; - return GetAndLogLastError(); + return GetAndLogLastError(CallType::Other); } return Errno::INVAL; } if (setsockopt(fd, native_level, native_optname, reinterpret_cast(optval.data()), socklen_t(optval.size())) != SOCKET_ERROR) return Errno::SUCCESS; - return GetAndLogLastError(); + return GetAndLogLastError(CallType::Other); } Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) { fd = socket(TranslateDomainToNative(domain), TranslateTypeToNative(type), TranslateProtocolToNative(protocol)); if (fd != INVALID_SOCKET) return Errno::SUCCESS; - return GetAndLogLastError(); + return GetAndLogLastError(CallType::Other); } std::pair Socket::Accept() { @@ -1086,7 +1092,7 @@ std::pair Socket::Accept() { const SOCKET new_socket = accept(fd, reinterpret_cast(&addr), &addrlen); if (new_socket == INVALID_SOCKET) { - return {AcceptResult{}, GetAndLogLastError()}; + return {AcceptResult{}, GetAndLogLastError(CallType::Other)}; } AcceptResult result{ @@ -1106,14 +1112,14 @@ Errno Socket::Connect(Network::SockAddrIn addr_in) { } } } - return GetAndLogLastError(); + return GetAndLogLastError(CallType::Other); } std::pair Socket::GetPeerName() { sockaddr_in addr; socklen_t addrlen = sizeof(addr); if (getpeername(fd, reinterpret_cast(&addr), &addrlen) == SOCKET_ERROR) - return {Network::SockAddrIn{}, GetAndLogLastError()}; + return {Network::SockAddrIn{}, GetAndLogLastError(CallType::Other)}; return {TranslateToSockAddrIn(addr), Errno::SUCCESS}; } @@ -1121,7 +1127,7 @@ std::pair Socket::GetSockName() { sockaddr_in addr; socklen_t addrlen = sizeof(addr); if (getsockname(fd, reinterpret_cast(&addr), &addrlen) == SOCKET_ERROR) { - return {Network::SockAddrIn{}, GetAndLogLastError()}; + return {Network::SockAddrIn{}, GetAndLogLastError(CallType::Other)}; } return {TranslateToSockAddrIn(addr), Errno::SUCCESS}; @@ -1131,13 +1137,13 @@ Errno Socket::Bind(Network::SockAddrIn addr) { auto const addr_in = TranslateFromSockAddrIn(addr); if (bind(fd, reinterpret_cast(&addr_in), sizeof(addr_in)) != SOCKET_ERROR) return Errno::SUCCESS; - return GetAndLogLastError(); + return GetAndLogLastError(CallType::Other); } Errno Socket::Listen(s32 backlog) { if (listen(fd, backlog) != SOCKET_ERROR) return Errno::SUCCESS; - return GetAndLogLastError(); + return GetAndLogLastError(CallType::Other); } Errno Socket::Shutdown(ShutdownHow how) { @@ -1160,7 +1166,7 @@ Errno Socket::Shutdown(ShutdownHow how) { return Errno::SUCCESS; } - return GetAndLogLastError(); + return GetAndLogLastError(CallType::Other); } s32 TranslateMsgOptToNative(s32 flags) { @@ -1203,7 +1209,7 @@ std::pair Socket::Recv(int flags, std::span message) { auto const result = recv(fd, reinterpret_cast(message.data()), int(message.size()), native_flags); if (result != SOCKET_ERROR) return {s32(result), Errno::SUCCESS}; - return {-1, GetAndLogLastError()}; + return {-1, GetAndLogLastError(CallType::Other)}; } std::pair Socket::RecvFrom(int flags, std::span message, Network::SockAddrIn* addr) { @@ -1223,7 +1229,7 @@ std::pair Socket::RecvFrom(int flags, std::span message, Network } return {s32(result), Errno::SUCCESS}; } - return {-1, GetAndLogLastError()}; + return {-1, GetAndLogLastError(CallType::Other)}; } std::pair Socket::Send(std::span message, int flags) { diff --git a/src/core/internal_network/socket_icmp.cpp b/src/core/internal_network/socket_icmp.cpp index 724625cfae..6ff3811262 100644 --- a/src/core/internal_network/socket_icmp.cpp +++ b/src/core/internal_network/socket_icmp.cpp @@ -1,11 +1,13 @@ // SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include #include "common/assert.h" #include "common/logging.h" #include "core/internal_network/socket_icmp.h" #ifdef __unix__ +#include #include #endif @@ -91,25 +93,46 @@ std::pair IcmpSocket::RecvFrom(int flags, std::span message, Net LOG_DEBUG(Network, "(stubbed) called"); ASSERT(flags == 0); ASSERT(message.size() < std::size_t((std::numeric_limits::max)())); - std::vector data; - data.push_back(8); - data.push_back(0); - data.push_back(0); //checksum (placeholder 0) - data.push_back(0); - data.push_back(message[4]); //ident - data.push_back(message[5]); - data.push_back(message[6]); //seq - data.push_back(message[7]); - auto const csum = ComputeChecksum(std::span{data.begin(), data.end()}); - data[2] = u8(csum >> 8); //hi - data[3] = u8(csum); //lo - auto const n = (std::max)(data.size(), message.size()); - std::copy(data.begin(), data.begin() + n, message.begin()); - return {n, Errno::SUCCESS}; +#ifdef __unix__ + if (addr) { + if (seq_ident.empty()) + return {0, Errno::SUCCESS}; + // PLEASE DON'T KILL ME, I SWEAR THIS IS LEGITIMATELY THE BEST WAY TO DO IT + // IF YOU OPEN socket() GOOGLE WILL STRAIGHT UP IP BAN YOU AFTER 2 HOURS + auto const cmd = fmt::format("ping -o {}.{}.{}.{}", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3]); + if (::system(cmd.c_str()) == 0) { + std::vector data{ + 8, + 0, + 0, //checksum + 0, + u8(seq_ident.front() >> 24), //ident + u8(seq_ident.front() >> 16), + u8(seq_ident.front() >> 8), // seq + u8(seq_ident.front() >> 0), + }; + seq_ident.pop_back(); + auto const csum = ComputeChecksum(std::span{data.begin(), data.end()}); + data[2] = u8(csum >> 8); //hi + data[3] = u8(csum); //lo + auto const n = (std::max)(data.size(), message.size()); + std::copy(data.begin(), data.begin() + n, message.begin()); + return {n, Errno::SUCCESS}; + } + return {-1, Errno::TIMEDOUT}; + } +#endif + return {-1, Errno::INVAL}; } std::pair IcmpSocket::Send(std::span message, int flags) { LOG_DEBUG(Network, "(stubbed) called"); + seq_ident.push_back( + (u32(message[4]) << 24) + | (u32(message[5]) << 16) + | (u32(message[6]) << 8) + | (u32(message[7]) << 0) + ); return {s32(0), Errno::NOTCONN}; } @@ -123,7 +146,7 @@ std::pair IcmpSocket::SendTo(u32 flags, std::span message, // 6..8 -> seq if (!message.empty()) return {s32(message.size()), Errno::SUCCESS}; - return {s32(0), Errno::NETDOWN}; + return {-1, Errno::INVAL}; } Errno IcmpSocket::Close() { @@ -145,7 +168,6 @@ void IcmpSocket::HandleProxyPacket(const ProxyPacket& packet) { LOG_WARNING(Network, "(stubbed) called"); } Errno IcmpSocket::SetNonBlock(bool enable) { - LOG_WARNING(Network, "(stubbed) called"); return Errno::SUCCESS; } diff --git a/src/core/internal_network/socket_icmp.h b/src/core/internal_network/socket_icmp.h index 3126e718b3..0ba72c456a 100644 --- a/src/core/internal_network/socket_icmp.h +++ b/src/core/internal_network/socket_icmp.h @@ -30,6 +30,8 @@ public: bool IsOpened() const override; void HandleProxyPacket(const ProxyPacket& packet) override; Errno SetNonBlock(bool enable) override; + + std::vector seq_ident; }; } // namespace Network