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) {
|
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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
return ReceivePacket(flags, message, addr, message.size());
|
||||||
// packet arrives. In order to prevent lost packets from hanging the emulation thread, we set
|
} while (blocking);
|
||||||
// the timeout to 5s instead
|
return {-1, Errno::E_AGAIN};
|
||||||
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};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
std::memcpy(message.data(), packet.data.data(), read_bytes);
|
||||||
read_bytes = max_length;
|
if (!peek) {
|
||||||
std::memcpy(message.data(), packet.data.data(), max_length);
|
packet.data.erase(packet.data.begin(), packet.data.begin() + read_bytes);
|
||||||
|
if (packet.data.empty())
|
||||||
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) {
|
|
||||||
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};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user