2026-09-27 10:33:17

Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
lizzie
2026-09-27 10:33:17 +00:00
parent e9eae6465f
commit ec33801c2b
6 changed files with 46 additions and 83 deletions
+13 -13
View File
@@ -876,9 +876,12 @@ std::pair<s32, Network::Errno> BSD_USA::RecvImpl(s32 fd, u32 flags, std::vector<
std::pair<s32, Network::Errno> BSD_USA::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message, std::vector<u8>& addr) { std::pair<s32, Network::Errno> BSD_USA::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message, std::vector<u8>& addr) {
LOG_DEBUG(Network, "fd={},flags={}", fd, flags); LOG_DEBUG(Network, "fd={},flags={}", fd, flags);
if (!IsFileDescriptorValid(fd)) { if (!IsFileDescriptorValid(fd))
return {-1, Network::Errno::E_BADF}; return {-1, Network::Errno::E_BADF};
} if (message.size() == 0)
return {0, Network::Errno::E_SUCCESS};
if (!std::in_range<u32>(message.size()))
return {0, Network::Errno::E_FAULT};
FileDescriptor& descriptor = *file_descriptors[fd]; FileDescriptor& descriptor = *file_descriptors[fd];
@@ -892,19 +895,16 @@ std::pair<s32, Network::Errno> BSD_USA::RecvFromImpl(s32 fd, u32 flags, std::vec
} }
// Apply flags // Apply flags
if ((flags & u32(Network::MsgOpt::DONTWAIT)) != 0) { auto const is_nonblock = descriptor.socket->GetNonBlock();
flags &= ~u32(Network::MsgOpt::DONTWAIT); auto const f_dontwait = (flags & u32(Network::MsgOpt::DONTWAIT)) != 0;
if ((descriptor.flags & u32(Network::FcntlFlags::NONBLOCK_NX)) == 0) { auto const f_waitall = (flags & u32(Network::MsgOpt::WAITALL)) != 0;
descriptor.socket->SetNonBlock(true); // DONTWAIT set clears WAITALL, if socket is non-blocking it also clears WAITALL
} if (f_dontwait || (f_waitall && is_nonblock))
} flags &= ~u32(Network::MsgOpt::WAITALL);
if (f_dontwait) descriptor.socket->SetNonBlock(true); //set non-block
const auto [ret, bsd_errno] = descriptor.socket->RecvFrom(flags, message, p_addr_in); const auto [ret, bsd_errno] = descriptor.socket->RecvFrom(flags, message, p_addr_in);
if (f_dontwait) descriptor.socket->SetNonBlock(is_nonblock); //restore
// Restore original state
if ((descriptor.flags & u32(Network::FcntlFlags::NONBLOCK_NX)) == 0) {
descriptor.socket->SetNonBlock(false);
}
if (p_addr_in) { if (p_addr_in) {
if (ret < 0) { if (ret < 0) {
+4 -1
View File
@@ -1029,6 +1029,10 @@ Errno Socket::GetSockOpt(Network::SocketLevel level, Network::OptName optname, s
return GetAndLogLastError(CallType::Other); return GetAndLogLastError(CallType::Other);
} }
bool Socket::GetNonBlock() {
return is_non_blocking;
}
Errno Socket::SetNonBlock(bool enable) { Errno Socket::SetNonBlock(bool enable) {
if (EnableNonBlock(fd, enable)) { if (EnableNonBlock(fd, enable)) {
is_non_blocking = enable; is_non_blocking = enable;
@@ -1223,7 +1227,6 @@ std::pair<s32, Errno> Socket::RecvFrom(int flags, std::span<u8> message, Network
socklen_t* const p_addrlen = addr ? &addrlen : nullptr; socklen_t* const p_addrlen = addr ? &addrlen : nullptr;
sockaddr* const p_addr_in = addr ? reinterpret_cast<sockaddr*>(&addr_in) : nullptr; sockaddr* const p_addr_in = addr ? reinterpret_cast<sockaddr*>(&addr_in) : nullptr;
auto const native_flags = TranslateMsgOptToNative(flags);
auto const result = recvfrom(fd, reinterpret_cast<char*>(message.data()), int(message.size()), native_flags, p_addr_in, p_addrlen); auto const result = recvfrom(fd, reinterpret_cast<char*>(message.data()), int(message.size()), native_flags, p_addr_in, p_addrlen);
if (result != SOCKET_ERROR) { if (result != SOCKET_ERROR) {
if (addr) { if (addr) {
@@ -269,6 +269,10 @@ bool IcmpSocket::IsOpened() const {
void IcmpSocket::HandleProxyPacket(const ProxyPacket& packet) { void IcmpSocket::HandleProxyPacket(const ProxyPacket& packet) {
LOG_WARNING(Network, "(stubbed) called"); LOG_WARNING(Network, "(stubbed) called");
} }
bool IcmpSocket::GetNonBlock() {
return !blocking;
}
Errno IcmpSocket::SetNonBlock(bool enable) { Errno IcmpSocket::SetNonBlock(bool enable) {
blocking = !enable; blocking = !enable;
return Errno::E_SUCCESS; return Errno::E_SUCCESS;
+2
View File
@@ -44,6 +44,8 @@ public:
std::pair<Errno, Errno> GetPendingError() override; std::pair<Errno, Errno> GetPendingError() override;
bool IsOpened() const override; bool IsOpened() const override;
void HandleProxyPacket(const ProxyPacket& packet) override; void HandleProxyPacket(const ProxyPacket& packet) override;
bool GetNonBlock() override;
Errno SetNonBlock(bool enable) override; Errno SetNonBlock(bool enable) override;
boost::container::static_vector<PingProcessData, 128> pings; boost::container::static_vector<PingProcessData, 128> pings;
+17 -47
View File
@@ -47,6 +47,10 @@ void ProxySocket::HandleProxyPacket(const ProxyPacket& packet) {
received_packets.push(decompressed); received_packets.push(decompressed);
} }
bool ProxySocket::GetNonBlock() {
return blocking;
}
Errno ProxySocket::SetNonBlock(bool enable) { Errno ProxySocket::SetNonBlock(bool enable) {
blocking = !enable; blocking = !enable;
return Errno::E_SUCCESS; return Errno::E_SUCCESS;
@@ -115,41 +119,19 @@ Errno ProxySocket::Shutdown(ShutdownHow how) {
std::pair<s32, Errno> ProxySocket::Recv(int flags, std::span<u8> message) { std::pair<s32, Errno> ProxySocket::Recv(int flags, std::span<u8> message) {
LOG_WARNING(Network, "(stubbed) called"); LOG_WARNING(Network, "(stubbed) called");
ASSERT(flags == 0); ASSERT(flags == 0 && message.size() < std::size_t((std::numeric_limits<int>::max)()));
ASSERT(message.size() < std::size_t((std::numeric_limits<int>::max)()));
return {s32(0), Errno::E_SUCCESS}; return {s32(0), Errno::E_SUCCESS};
} }
std::pair<s32, Errno> ProxySocket::RecvFrom(int flags, std::span<u8> message, Network::SockAddrIn* addr) { std::pair<s32, Errno> ProxySocket::RecvFrom(int flags, std::span<u8> message, Network::SockAddrIn* addr) {
ASSERT(flags == 0); LOG_DEBUG(Network, "called");
ASSERT(message.size() < std::size_t((std::numeric_limits<int>::max)())); ASSERT(flags == 0 && message.size() < std::size_t((std::numeric_limits<int>::max)()));
do {
// TODO (flTobi): Verify the timeout behavior and break when connection is lost std::unique_lock lk{packets_mutex};
const auto timestamp = std::chrono::steady_clock::now(); if (received_packets.size() > 0)
// When receive_timeout is set to zero, the socket is supposed to wait indefinitely until a
// packet arrives. In order to prevent lost packets from hanging the emulation thread, we set
// the timeout to 5s instead
const auto timeout = receive_timeout == 0 ? 5000 : receive_timeout;
while (true) {
{
std::lock_guard guard(packets_mutex);
if (received_packets.size() > 0) {
return ReceivePacket(flags, message, addr, message.size()); return ReceivePacket(flags, message, addr, message.size());
} } while (blocking);
}
if (!blocking) {
return {-1, Errno::E_AGAIN}; return {-1, Errno::E_AGAIN};
}
std::this_thread::yield();
const auto time_diff = std::chrono::steady_clock::now() - timestamp;
const auto time_diff_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_diff).count();
if (time_diff_ms > timeout) {
return {-1, Errno::E_TIMEDOUT};
}
}
} }
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) {
@@ -164,29 +146,17 @@ std::pair<s32, Errno> ProxySocket::ReceivePacket(int flags, std::span<u8> messag
} }
bool peek = (flags & u32(Network::MsgOpt::PEEK)) != 0; bool peek = (flags & u32(Network::MsgOpt::PEEK)) != 0;
std::size_t read_bytes; std::size_t read_bytes = (std::min)(max_length, packet.data.size());
if (packet.data.size() > max_length) {
read_bytes = max_length;
std::memcpy(message.data(), packet.data.data(), max_length);
if (protocol == Protocol::UDP) {
if (!peek) {
received_packets.pop();
}
return {-1, Errno::E_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));
packet.data = numArray;
}
} else {
read_bytes = packet.data.size();
std::memcpy(message.data(), packet.data.data(), read_bytes); std::memcpy(message.data(), packet.data.data(), read_bytes);
if (!peek) { if (!peek) {
packet.data.erase(packet.data.begin(), packet.data.begin() + read_bytes);
if (packet.data.empty())
received_packets.pop(); received_packets.pop();
} }
if (packet.data.size() > max_length && protocol == Protocol::UDP) {
LOG_ERROR(Network, "Packet size");
return {-1, Errno::E_MSGSIZE};
} }
return {u32(read_bytes), Errno::E_SUCCESS}; return {u32(read_bytes), Errno::E_SUCCESS};
} }
+1 -17
View File
@@ -41,39 +41,23 @@ public:
YUZU_NON_MOVEABLE(SocketBase); YUZU_NON_MOVEABLE(SocketBase);
virtual Errno Initialize(Domain domain, Type type, Protocol protocol) = 0; virtual Errno Initialize(Domain domain, Type type, Protocol protocol) = 0;
virtual Errno Close() = 0; virtual Errno Close() = 0;
virtual std::pair<AcceptResult, Errno> Accept() = 0; virtual std::pair<AcceptResult, Errno> Accept() = 0;
virtual Errno Connect(Network::SockAddrIn addr_in) = 0; virtual Errno Connect(Network::SockAddrIn addr_in) = 0;
virtual std::pair<Network::SockAddrIn, Errno> GetPeerName() = 0; virtual std::pair<Network::SockAddrIn, Errno> GetPeerName() = 0;
virtual std::pair<Network::SockAddrIn, Errno> GetSockName() = 0; virtual std::pair<Network::SockAddrIn, Errno> GetSockName() = 0;
virtual Errno Bind(Network::SockAddrIn addr) = 0; virtual Errno Bind(Network::SockAddrIn addr) = 0;
virtual Errno Listen(s32 backlog) = 0; virtual Errno Listen(s32 backlog) = 0;
virtual Errno Shutdown(ShutdownHow how) = 0; virtual Errno Shutdown(ShutdownHow how) = 0;
virtual std::pair<s32, Errno> Recv(int flags, std::span<u8> message) = 0; virtual std::pair<s32, Errno> Recv(int flags, std::span<u8> message) = 0;
virtual std::pair<s32, Errno> RecvFrom(int flags, std::span<u8> message, Network::SockAddrIn* addr) = 0; virtual std::pair<s32, Errno> RecvFrom(int flags, std::span<u8> message, Network::SockAddrIn* addr) = 0;
virtual std::pair<s32, Errno> Send(std::span<const u8> message, int flags) = 0; virtual std::pair<s32, Errno> Send(std::span<const u8> message, int flags) = 0;
virtual std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> message, const Network::SockAddrIn* addr) = 0; virtual std::pair<s32, Errno> SendTo(u32 flags, std::span<const u8> message, const Network::SockAddrIn* addr) = 0;
virtual bool GetNonBlock() = 0;
virtual Errno SetNonBlock(bool enable) = 0; virtual Errno SetNonBlock(bool enable) = 0;
virtual Errno SetSockOpt(Network::SocketLevel level, Network::OptName option, std::span<const u8> value) = 0; virtual Errno SetSockOpt(Network::SocketLevel level, Network::OptName option, std::span<const u8> value) = 0;
virtual std::pair<Errno, Errno> GetPendingError() = 0; virtual std::pair<Errno, Errno> GetPendingError() = 0;
virtual bool IsOpened() const = 0; virtual bool IsOpened() const = 0;
virtual void HandleProxyPacket(const ProxyPacket& packet) = 0; virtual void HandleProxyPacket(const ProxyPacket& packet) = 0;
[[nodiscard]] SOCKET GetFD() const { [[nodiscard]] SOCKET GetFD() const {