mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-27 11:19:04 +00:00
@@ -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) {
|
||||
LOG_DEBUG(Network, "fd={},flags={}", fd, flags);
|
||||
if (!IsFileDescriptorValid(fd)) {
|
||||
if (!IsFileDescriptorValid(fd))
|
||||
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];
|
||||
|
||||
@@ -892,19 +895,16 @@ std::pair<s32, Network::Errno> BSD_USA::RecvFromImpl(s32 fd, u32 flags, std::vec
|
||||
}
|
||||
|
||||
// Apply flags
|
||||
if ((flags & u32(Network::MsgOpt::DONTWAIT)) != 0) {
|
||||
flags &= ~u32(Network::MsgOpt::DONTWAIT);
|
||||
if ((descriptor.flags & u32(Network::FcntlFlags::NONBLOCK_NX)) == 0) {
|
||||
descriptor.socket->SetNonBlock(true);
|
||||
}
|
||||
}
|
||||
auto const is_nonblock = descriptor.socket->GetNonBlock();
|
||||
auto const f_dontwait = (flags & u32(Network::MsgOpt::DONTWAIT)) != 0;
|
||||
auto const f_waitall = (flags & u32(Network::MsgOpt::WAITALL)) != 0;
|
||||
// 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);
|
||||
|
||||
// Restore original state
|
||||
if ((descriptor.flags & u32(Network::FcntlFlags::NONBLOCK_NX)) == 0) {
|
||||
descriptor.socket->SetNonBlock(false);
|
||||
}
|
||||
if (f_dontwait) descriptor.socket->SetNonBlock(is_nonblock); //restore
|
||||
|
||||
if (p_addr_in) {
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -1029,6 +1029,10 @@ Errno Socket::GetSockOpt(Network::SocketLevel level, Network::OptName optname, s
|
||||
return GetAndLogLastError(CallType::Other);
|
||||
}
|
||||
|
||||
bool Socket::GetNonBlock() {
|
||||
return is_non_blocking;
|
||||
}
|
||||
|
||||
Errno Socket::SetNonBlock(bool enable) {
|
||||
if (EnableNonBlock(fd, 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;
|
||||
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);
|
||||
if (result != SOCKET_ERROR) {
|
||||
if (addr) {
|
||||
|
||||
@@ -269,6 +269,10 @@ bool IcmpSocket::IsOpened() const {
|
||||
void IcmpSocket::HandleProxyPacket(const ProxyPacket& packet) {
|
||||
LOG_WARNING(Network, "(stubbed) called");
|
||||
}
|
||||
|
||||
bool IcmpSocket::GetNonBlock() {
|
||||
return !blocking;
|
||||
}
|
||||
Errno IcmpSocket::SetNonBlock(bool enable) {
|
||||
blocking = !enable;
|
||||
return Errno::E_SUCCESS;
|
||||
|
||||
@@ -44,6 +44,8 @@ public:
|
||||
std::pair<Errno, Errno> GetPendingError() override;
|
||||
bool IsOpened() const override;
|
||||
void HandleProxyPacket(const ProxyPacket& packet) override;
|
||||
|
||||
bool GetNonBlock() override;
|
||||
Errno SetNonBlock(bool enable) override;
|
||||
|
||||
boost::container::static_vector<PingProcessData, 128> pings;
|
||||
|
||||
@@ -47,6 +47,10 @@ void ProxySocket::HandleProxyPacket(const ProxyPacket& packet) {
|
||||
received_packets.push(decompressed);
|
||||
}
|
||||
|
||||
bool ProxySocket::GetNonBlock() {
|
||||
return blocking;
|
||||
}
|
||||
|
||||
Errno ProxySocket::SetNonBlock(bool enable) {
|
||||
blocking = !enable;
|
||||
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) {
|
||||
LOG_WARNING(Network, "(stubbed) called");
|
||||
ASSERT(flags == 0);
|
||||
ASSERT(message.size() < std::size_t((std::numeric_limits<int>::max)()));
|
||||
ASSERT(flags == 0 && message.size() < std::size_t((std::numeric_limits<int>::max)()));
|
||||
return {s32(0), Errno::E_SUCCESS};
|
||||
}
|
||||
|
||||
std::pair<s32, Errno> ProxySocket::RecvFrom(int flags, std::span<u8> message, Network::SockAddrIn* addr) {
|
||||
ASSERT(flags == 0);
|
||||
ASSERT(message.size() < std::size_t((std::numeric_limits<int>::max)()));
|
||||
|
||||
// TODO (flTobi): Verify the timeout behavior and break when connection is lost
|
||||
const auto timestamp = std::chrono::steady_clock::now();
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
if (!blocking) {
|
||||
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};
|
||||
}
|
||||
}
|
||||
LOG_DEBUG(Network, "called");
|
||||
ASSERT(flags == 0 && message.size() < std::size_t((std::numeric_limits<int>::max)()));
|
||||
do {
|
||||
std::unique_lock lk{packets_mutex};
|
||||
if (received_packets.size() > 0)
|
||||
return ReceivePacket(flags, message, addr, message.size());
|
||||
} while (blocking);
|
||||
return {-1, Errno::E_AGAIN};
|
||||
}
|
||||
|
||||
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;
|
||||
std::size_t read_bytes;
|
||||
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);
|
||||
if (!peek) {
|
||||
std::size_t read_bytes = (std::min)(max_length, packet.data.size());
|
||||
std::memcpy(message.data(), packet.data.data(), read_bytes);
|
||||
if (!peek) {
|
||||
packet.data.erase(packet.data.begin(), packet.data.begin() + read_bytes);
|
||||
if (packet.data.empty())
|
||||
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};
|
||||
}
|
||||
|
||||
|
||||
@@ -41,39 +41,23 @@ public:
|
||||
YUZU_NON_MOVEABLE(SocketBase);
|
||||
|
||||
virtual Errno Initialize(Domain domain, Type type, Protocol protocol) = 0;
|
||||
|
||||
virtual Errno Close() = 0;
|
||||
|
||||
virtual std::pair<AcceptResult, Errno> Accept() = 0;
|
||||
|
||||
virtual Errno Connect(Network::SockAddrIn addr_in) = 0;
|
||||
|
||||
virtual std::pair<Network::SockAddrIn, Errno> GetPeerName() = 0;
|
||||
|
||||
virtual std::pair<Network::SockAddrIn, Errno> GetSockName() = 0;
|
||||
|
||||
virtual Errno Bind(Network::SockAddrIn addr) = 0;
|
||||
|
||||
virtual Errno Listen(s32 backlog) = 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> 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> 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 SetSockOpt(Network::SocketLevel level, Network::OptName option, std::span<const u8> value) = 0;
|
||||
|
||||
virtual std::pair<Errno, Errno> GetPendingError() = 0;
|
||||
|
||||
virtual bool IsOpened() const = 0;
|
||||
|
||||
virtual void HandleProxyPacket(const ProxyPacket& packet) = 0;
|
||||
|
||||
[[nodiscard]] SOCKET GetFD() const {
|
||||
|
||||
Reference in New Issue
Block a user