mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 12:12:50 +01:00
Savestates/Network: Feign connection failure on startup
This commit is contained in:
parent
72ad1abd39
commit
8effbf7e4d
@ -22,6 +22,8 @@ lv2_socket_native::lv2_socket_native(lv2_socket_family family, lv2_socket_type t
|
||||
lv2_socket_native::lv2_socket_native(utils::serial& ar, lv2_socket_type type)
|
||||
: lv2_socket(stx::make_exact(ar), type)
|
||||
{
|
||||
[[maybe_unused]] const s32 version = GET_SERIALIZATION_VERSION(lv2_net);
|
||||
|
||||
#ifdef _WIN32
|
||||
ar(so_reuseaddr, so_reuseport);
|
||||
#else
|
||||
@ -33,16 +35,26 @@ lv2_socket_native::lv2_socket_native(utils::serial& ar, lv2_socket_type type)
|
||||
sys_net.error("[Native] Savestate tried to load Win32 specific data, compatibility may be affected");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (version >= 2)
|
||||
{
|
||||
// Flag to signal failure of TCP connection on socket start
|
||||
ar(feign_tcp_conn_failure);
|
||||
}
|
||||
}
|
||||
|
||||
void lv2_socket_native::save(utils::serial& ar)
|
||||
{
|
||||
USING_SERIALIZATION_VERSION(lv2_net);
|
||||
|
||||
lv2_socket::save(ar, true);
|
||||
#ifdef _WIN32
|
||||
ar(so_reuseaddr, so_reuseport);
|
||||
#else
|
||||
ar(std::array<char, 8>{});
|
||||
#endif
|
||||
|
||||
ar(is_socket_connected());
|
||||
}
|
||||
|
||||
lv2_socket_native::~lv2_socket_native()
|
||||
@ -106,6 +118,11 @@ std::tuple<bool, s32, std::shared_ptr<lv2_socket>, sys_net_sockaddr> lv2_socket_
|
||||
::sockaddr_storage native_addr;
|
||||
::socklen_t native_addrlen = sizeof(native_addr);
|
||||
|
||||
if (feign_tcp_conn_failure)
|
||||
{
|
||||
sys_net.error("Calling socket::accpet() from a previously connected socket!");
|
||||
}
|
||||
|
||||
socket_type native_socket = ::accept(socket, reinterpret_cast<struct sockaddr*>(&native_addr), &native_addrlen);
|
||||
|
||||
if (native_socket != invalid_socket)
|
||||
@ -143,6 +160,11 @@ s32 lv2_socket_native::bind(const sys_net_sockaddr& addr)
|
||||
saddr = std::bit_cast<u32>(psa_in->sin_addr);
|
||||
}
|
||||
|
||||
if (feign_tcp_conn_failure)
|
||||
{
|
||||
sys_net.error("Calling socket::bind() from a previously connected socket!");
|
||||
}
|
||||
|
||||
::sockaddr_in native_addr{};
|
||||
native_addr.sin_family = AF_INET;
|
||||
native_addr.sin_port = std::bit_cast<u16>(psa_in->sin_port);
|
||||
@ -225,6 +247,12 @@ std::optional<s32> lv2_socket_native::connect(const sys_net_sockaddr& addr)
|
||||
bool was_connecting = connecting;
|
||||
#endif
|
||||
|
||||
if (feign_tcp_conn_failure)
|
||||
{
|
||||
// As if still connected
|
||||
return -SYS_NET_EALREADY;
|
||||
}
|
||||
|
||||
if (::connect(socket, reinterpret_cast<struct sockaddr*>(&native_addr), native_addr_len) == 0)
|
||||
{
|
||||
return CELL_OK;
|
||||
@ -873,6 +901,13 @@ std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> lv2_socket_nat
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
if (feign_tcp_conn_failure)
|
||||
{
|
||||
// As if just lost the connection
|
||||
feign_tcp_conn_failure = false;
|
||||
return {{-SYS_NET_ECONNRESET, {},{}}};
|
||||
}
|
||||
|
||||
int native_flags = 0;
|
||||
::sockaddr_storage native_addr{};
|
||||
::socklen_t native_addrlen = sizeof(native_addr);
|
||||
@ -963,6 +998,12 @@ std::optional<s32> lv2_socket_native::sendto(s32 flags, const std::vector<u8>& b
|
||||
return -SYS_NET_EADDRNOTAVAIL;
|
||||
}
|
||||
}
|
||||
else if (feign_tcp_conn_failure)
|
||||
{
|
||||
// As if just lost the connection
|
||||
feign_tcp_conn_failure = false;
|
||||
return -SYS_NET_ECONNRESET;
|
||||
}
|
||||
|
||||
sys_net_error result{};
|
||||
|
||||
@ -1029,6 +1070,12 @@ std::optional<s32> lv2_socket_native::sendmsg(s32 flags, const sys_net_msghdr& m
|
||||
native_flags |= MSG_WAITALL;
|
||||
}
|
||||
|
||||
if (feign_tcp_conn_failure)
|
||||
{
|
||||
// As if just lost the connection
|
||||
feign_tcp_conn_failure = false;
|
||||
return {-SYS_NET_ECONNRESET};
|
||||
}
|
||||
|
||||
for (int i = 0; i < msg.msg_iovlen; i++)
|
||||
{
|
||||
@ -1082,6 +1129,12 @@ s32 lv2_socket_native::shutdown(s32 how)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
if (feign_tcp_conn_failure)
|
||||
{
|
||||
// As if still connected
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
const int native_how =
|
||||
how == SYS_NET_SHUT_RD ? SD_RECEIVE :
|
||||
@ -1172,3 +1225,47 @@ void lv2_socket_native::set_non_blocking()
|
||||
::fcntl(socket, F_SETFL, ::fcntl(socket, F_GETFL, 0) | O_NONBLOCK);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool lv2_socket_native::is_socket_connected()
|
||||
{
|
||||
if (type != SYS_NET_SOCK_STREAM)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
int listening = 0;
|
||||
socklen_t len = sizeof(listening);
|
||||
|
||||
if (::getsockopt(socket, SOL_SOCKET, SO_ACCEPTCONN, reinterpret_cast<char*>(&listening), &len) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (listening)
|
||||
{
|
||||
// Would be handled in other ways
|
||||
return false;
|
||||
}
|
||||
|
||||
fd_set readfds, writefds;
|
||||
struct timeval timeout{0, 0}; // Zero timeout
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_ZERO(&writefds);
|
||||
FD_SET(socket, &readfds);
|
||||
FD_SET(socket, &writefds);
|
||||
|
||||
// Use select to check for readability and writability
|
||||
const int result = ::select(1, &readfds, &writefds, NULL, &timeout);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
// Error occurred
|
||||
return false;
|
||||
}
|
||||
|
||||
// Socket is connected if it's readable or writable
|
||||
return FD_ISSET(socket, &readfds) || FD_ISSET(socket, &writefds);
|
||||
}
|
||||
|
@ -53,6 +53,8 @@ public:
|
||||
s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override;
|
||||
std::tuple<bool, bool, bool> select(bs_t<poll_t> selected, pollfd& native_pfd) override;
|
||||
|
||||
bool is_socket_connected();
|
||||
|
||||
s32 listen(s32 backlog) override;
|
||||
void close() override;
|
||||
s32 shutdown(s32 how) override;
|
||||
@ -69,4 +71,5 @@ private:
|
||||
s32 so_reuseport = 0;
|
||||
#endif
|
||||
u16 bound_port = 0;
|
||||
bool feign_tcp_conn_failure = false; // Savestate load related
|
||||
};
|
||||
|
@ -46,7 +46,7 @@ SERIALIZATION_VER(ppu, 1, 1, 2/*PPU sleep
|
||||
SERIALIZATION_VER(spu, 2, 1)
|
||||
SERIALIZATION_VER(lv2_sync, 3, 1)
|
||||
SERIALIZATION_VER(lv2_vm, 4, 1)
|
||||
SERIALIZATION_VER(lv2_net, 5, 1)
|
||||
SERIALIZATION_VER(lv2_net, 5, 1, 2/*TCP Feign conection loss*/)
|
||||
SERIALIZATION_VER(lv2_fs, 6, 1, 2/*NPDRM key saving*/)
|
||||
SERIALIZATION_VER(lv2_prx_overlay, 7, 1)
|
||||
SERIALIZATION_VER(lv2_memory, 8, 1)
|
||||
|
Loading…
Reference in New Issue
Block a user