diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp index cc800a1633..b044a9671e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp @@ -239,7 +239,7 @@ std::optional lv2_socket_native::connect(const sys_net_sockaddr& addr) else { // TODO: check error formats (both native and translated) - so_error = native_error ? get_last_error(false, native_error) : 0; + so_error = native_error ? convert_error(false, native_error) : 0; } return true; @@ -270,7 +270,7 @@ s32 lv2_socket_native::connect_followup() } // TODO: check error formats (both native and translated) - return native_error ? -get_last_error(false, native_error) : 0; + return native_error ? -convert_error(false, native_error) : 0; } std::pair lv2_socket_native::getpeername() @@ -906,9 +906,10 @@ std::optional, sys_net_sockaddr>> lv2_socket_nat return {{0, {}, sn_addr}}; } } -#endif - + const auto result = get_last_error(!so_nbio && (flags & SYS_NET_MSG_DONTWAIT) == 0, connecting); +#else const auto result = get_last_error(!so_nbio && (flags & SYS_NET_MSG_DONTWAIT) == 0); +#endif if (result) { @@ -974,7 +975,11 @@ std::optional lv2_socket_native::sendto(s32 flags, const std::vector& b return {native_result}; } - result = get_last_error(!so_nbio && (flags & SYS_NET_MSG_DONTWAIT) == 0); +#ifdef _WIN32 + get_last_error(!so_nbio && (flags & SYS_NET_MSG_DONTWAIT) == 0, connecting); +#else + get_last_error(!so_nbio && (flags & SYS_NET_MSG_DONTWAIT) == 0); +#endif if (result) { diff --git a/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.cpp b/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.cpp index a0b6e4edd2..ca5e84f33e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.cpp @@ -20,17 +20,12 @@ int get_native_error() return native_error; } -sys_net_error get_last_error(bool is_blocking, int native_error) +sys_net_error convert_error(bool is_blocking, int native_error, [[maybe_unused]] bool is_connecting) { // Convert the error code for socket functions to a one for sys_net sys_net_error result{}; const char* name{}; - if (!native_error) - { - native_error = get_native_error(); - } - #ifdef _WIN32 #define ERROR_CASE(error) \ case WSA##error: \ @@ -92,6 +87,14 @@ sys_net_error get_last_error(bool is_blocking, int native_error) fmt::throw_exception("sys_net get_last_error(is_blocking=%d, native_error=%d): Unknown/illegal socket error", is_blocking, native_error); } +#ifdef _WIN32 + // Windows will return SYS_NET_ENOTCONN when recvfrom/sendto is called on a socket that is connecting but not yet connected + if (is_connecting && result == SYS_NET_ENOTCONN) + { + return SYS_NET_EAGAIN; + } +#endif + if (name && result != SYS_NET_EWOULDBLOCK && result != SYS_NET_EINPROGRESS) { sys_net.error("Socket error %s", name); @@ -111,6 +114,11 @@ sys_net_error get_last_error(bool is_blocking, int native_error) #undef ERROR_CASE } +sys_net_error get_last_error(bool is_blocking, bool is_connecting) +{ + return convert_error(is_blocking, get_native_error(), is_connecting); +} + sys_net_sockaddr native_addr_to_sys_net_addr(const ::sockaddr_storage& native_addr) { ensure(native_addr.ss_family == AF_INET || native_addr.ss_family == AF_UNSPEC); diff --git a/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.h b/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.h index 26745d2b0d..60b5058b90 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.h @@ -18,7 +18,8 @@ #include "Emu/Cell/lv2/sys_net.h" int get_native_error(); -sys_net_error get_last_error(bool is_blocking, int native_error = 0); +sys_net_error convert_error(bool is_blocking, int native_error, bool is_connecting = false); +sys_net_error get_last_error(bool is_blocking, bool is_connecting = false); sys_net_sockaddr native_addr_to_sys_net_addr(const ::sockaddr_storage& native_addr); ::sockaddr_in sys_net_addr_to_native_addr(const sys_net_sockaddr& sn_addr); bool is_ip_public_address(const ::sockaddr_in& addr);