Fix for Windows ENOTCONN on connecting socket

Fixes Windows returns ENOTCONN when using recvfrom/sendto on connecting socket instead of the expected EAGAIN.
This commit is contained in:
RipleyTom 2023-02-24 23:02:18 +01:00 committed by Megamouse
parent c570fd03d1
commit d9e0d016c6
3 changed files with 26 additions and 12 deletions

View File

@ -239,7 +239,7 @@ std::optional<s32> 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<s32, sys_net_sockaddr> lv2_socket_native::getpeername()
@ -906,9 +906,10 @@ std::optional<std::tuple<s32, std::vector<u8>, 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<s32> lv2_socket_native::sendto(s32 flags, const std::vector<u8>& 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)
{

View File

@ -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);

View File

@ -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);