diff --git a/rpcs3/Emu/Cell/lv2/sys_net.cpp b/rpcs3/Emu/Cell/lv2/sys_net.cpp index 57a1803d10..118a1808c7 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net.cpp @@ -1279,10 +1279,26 @@ error_code sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr<sys_net_fd_set if (auto sock = idm::check_unlocked<lv2_socket>((lv2_socket::id_base & -1024) + i)) { - if (sock->select(selected, _fds[i])) + auto [read_set, write_set, except_set] = sock->select(selected, _fds[i]); + + if (read_set || write_set || except_set) + { + signaled++; + } + + if (read_set) { rread.set(i); - signaled++; + } + + if (write_set) + { + rwrite.set(i); + } + + if (except_set) + { + rexcept.set(i); } #ifdef _WIN32 diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.h index a787147e83..d96ca0f0ed 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.h @@ -21,11 +21,10 @@ #endif #endif - #ifdef _WIN32 - using socket_type = uptr; +using socket_type = uptr; #else - using socket_type = int; +using socket_type = int; #endif class lv2_socket @@ -73,34 +72,33 @@ public: #endif public: - virtual std::tuple<bool, s32, sys_net_sockaddr> accept(bool is_lock = true) = 0; - virtual s32 bind(const sys_net_sockaddr &addr, s32 ps3_id) = 0; - - virtual std::optional<s32> connect(const sys_net_sockaddr &addr) = 0; - virtual s32 connect_followup() = 0; + virtual s32 bind(const sys_net_sockaddr& addr, s32 ps3_id) = 0; + + virtual std::optional<s32> connect(const sys_net_sockaddr& addr) = 0; + virtual s32 connect_followup() = 0; virtual std::pair<s32, sys_net_sockaddr> getpeername() = 0; virtual std::pair<s32, sys_net_sockaddr> getsockname() = 0; virtual std::tuple<s32, sockopt_data, u32> getsockopt(s32 level, s32 optname, u32 len) = 0; - virtual s32 setsockopt(s32 level, s32 optname, const std::vector<u8>& optval) = 0; + virtual s32 setsockopt(s32 level, s32 optname, const std::vector<u8>& optval) = 0; virtual s32 listen(s32 backlog) = 0; - virtual std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> recvfrom(s32 flags, u32 len, bool is_lock = true) = 0; + virtual std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> recvfrom(s32 flags, u32 len, bool is_lock = true) = 0; virtual std::optional<s32> sendto(s32 flags, const std::vector<u8>& buf, std::optional<sys_net_sockaddr> opt_sn_addr, bool is_lock = true) = 0; - virtual void close() = 0; + virtual void close() = 0; virtual s32 shutdown(s32 how) = 0; - virtual s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) = 0; - virtual s32 select(bs_t<poll_t> selected, pollfd& native_pfd) = 0; + virtual s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) = 0; + virtual std::tuple<bool, bool, bool> select(bs_t<poll_t> selected, pollfd& native_pfd) = 0; public: // IDM data - static const u32 id_base = 24; - static const u32 id_step = 1; + static const u32 id_base = 24; + static const u32 id_step = 1; static const u32 id_count = 1000; protected: 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 4568d853c2..b2e7c8e92e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp @@ -969,7 +969,7 @@ s32 lv2_socket_native::poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) return 0; } -s32 lv2_socket_native::select(bs_t<lv2_socket::poll_t> selected, pollfd& native_pfd) +std::tuple<bool, bool, bool> lv2_socket_native::select(bs_t<lv2_socket::poll_t> selected, pollfd& native_pfd) { native_pfd.fd = socket; if (selected & lv2_socket::poll_t::read) @@ -981,7 +981,7 @@ s32 lv2_socket_native::select(bs_t<lv2_socket::poll_t> selected, pollfd& native_ native_pfd.events |= POLLOUT; } - return 0; + return {}; } void lv2_socket_native::set_default_buffers() diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h index 3ad3a0dedc..9917cbf92b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h @@ -48,7 +48,7 @@ public: std::optional<s32> sendto(s32 flags, const std::vector<u8>& buf, std::optional<sys_net_sockaddr> opt_sn_addr, bool is_lock = true) override; s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; - s32 select(bs_t<poll_t> selected, pollfd& native_pfd) override; + std::tuple<bool, bool, bool> select(bs_t<poll_t> selected, pollfd& native_pfd) override; s32 listen(s32 backlog) override; void close() override; diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp index 0f5724c434..7d9e2c415a 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp @@ -221,7 +221,7 @@ std::optional<s32> lv2_socket_p2p::sendto(s32 flags, const std::vector<u8>& buf, if (native_result >= 0) { - return {native_result}; + return {std::max<s32>(native_result - sizeof(u16), 0l)}; } s32 result = get_last_error(!so_nbio && (flags & SYS_NET_MSG_DONTWAIT) == 0); @@ -281,15 +281,25 @@ s32 lv2_socket_p2p::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& native return sn_pfd.revents ? 1 : 0; } -s32 lv2_socket_p2p::select(bs_t<lv2_socket::poll_t> selected, [[maybe_unused]] pollfd& native_pfd) +std::tuple<bool, bool, bool> lv2_socket_p2p::select(bs_t<lv2_socket::poll_t> selected, [[maybe_unused]] pollfd& native_pfd) { std::lock_guard lock(mutex); + + bool read_set = false; + bool write_set = false; + // Check if it's a bound P2P socket if ((selected & lv2_socket::poll_t::read) && vport && !data.empty()) { sys_net.trace("[P2P] p2p_data for vport %d contains %d elements", vport, data.size()); - return 1; + read_set = true; } - return 0; + if (selected & lv2_socket::poll_t::write) + { + sys_net.trace("[P2P] p2p_data for vport %d contains %d elements", vport, data.size()); + write_set = true; + } + + return {read_set, write_set, false}; } diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.h index a256e9fa81..dbcf18040b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.h @@ -4,13 +4,13 @@ class lv2_socket_p2p : public lv2_socket { - public: +public: lv2_socket_p2p(lv2_socket_family family, lv2_socket_type type, lv2_ip_protocol protocol); std::tuple<bool, s32, sys_net_sockaddr> accept(bool is_lock = true) override; - s32 bind(const sys_net_sockaddr &addr, s32 ps3_id) override; + s32 bind(const sys_net_sockaddr& addr, s32 ps3_id) override; - std::optional<s32> connect(const sys_net_sockaddr &addr) override; + std::optional<s32> connect(const sys_net_sockaddr& addr) override; s32 connect_followup() override; std::pair<s32, sys_net_sockaddr> getpeername() override; @@ -28,11 +28,11 @@ class lv2_socket_p2p : public lv2_socket s32 shutdown(s32 how) override; s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; - s32 select(bs_t<poll_t> selected, pollfd& native_pfd) override; + std::tuple<bool, bool, bool> select(bs_t<poll_t> selected, pollfd& native_pfd) override; void handle_new_data(sys_net_sockaddr_in_p2p p2p_addr, std::vector<u8> p2p_data); - protected: +protected: // Port(actual bound port) and Virtual Port(indicated by u16 at the start of the packet) u16 port = 3658, vport = 0; u32 bound_addr = 0; diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp index f0023b11d1..f588ec58b1 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp @@ -796,3 +796,37 @@ s32 lv2_socket_p2ps::poll(sys_net_pollfd& sn_pfd, [[maybe_unused]] pollfd& nativ return 0; } + +std::tuple<bool, bool, bool> lv2_socket_p2ps::select(bs_t<lv2_socket::poll_t> selected, [[maybe_unused]] pollfd& native_pfd) +{ + std::lock_guard lock(mutex); + + bool read_set = false; + bool write_set = false; + + if (status == p2ps_stream_status::stream_connected) + { + if ((selected & lv2_socket::poll_t::read) && data_available) + { + sys_net.trace("[P2PS] socket has %d bytes available", data_available); + read_set = true; + } + + if (selected & lv2_socket::poll_t::write) + { + sys_net.trace("[P2PS] socket is writeable"); + write_set = true; + } + } + else if (status == p2ps_stream_status::stream_listening) + { + const auto bsize = backlog.size(); + if ((selected & lv2_socket::poll_t::read) && bsize) + { + sys_net.trace("[P2PS] socket has %d clients available", bsize); + read_set = true; + } + } + + return {read_set, write_set, false}; +} diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.h index 9893f37db1..5b10d561d6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.h @@ -21,8 +21,8 @@ constexpr be_t<u32> P2PS_U2S_SIG = (static_cast<u32>('U') << 24 | static_cast<u3 struct p2ps_encapsulated_tcp { be_t<u32> signature = P2PS_U2S_SIG; // Signature to verify it's P2P Stream data - be_t<u32> length = 0; // Length of data - be_t<u64> seq = 0; // This should be u32 but changed to u64 for simplicity + be_t<u32> length = 0; // Length of data + be_t<u64> seq = 0; // This should be u32 but changed to u64 for simplicity be_t<u64> ack = 0; be_t<u16> src_port = 0; // fake source tcp port be_t<u16> dst_port = 0; // fake dest tcp port(should be == vport) @@ -71,7 +71,7 @@ public: std::optional<s32> connect(const sys_net_sockaddr& addr) override; - //std::pair<s32, sys_net_sockaddr> getsockname() override; + // std::pair<s32, sys_net_sockaddr> getsockname() override; s32 listen(s32 backlog) override; @@ -82,6 +82,7 @@ public: s32 shutdown(s32 how) override; 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; protected: static constexpr usz MAX_RECEIVED_BUFFER = (1024 * 1024 * 10); diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.cpp index 2a1be4b4c9..c44e51dadb 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.cpp @@ -91,7 +91,7 @@ s32 lv2_socket_raw::poll([[maybe_unused]] sys_net_pollfd& sn_pfd, [[maybe_unused return {}; } -s32 lv2_socket_raw::select([[maybe_unused]] bs_t<lv2_socket::poll_t> selected, [[maybe_unused]] pollfd& native_pfd) +std::tuple<bool, bool, bool> lv2_socket_raw::select([[maybe_unused]] bs_t<lv2_socket::poll_t> selected, [[maybe_unused]] pollfd& native_pfd) { sys_net.todo("lv2_socket_raw::select"); return {}; diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.h index c20a6d8194..abab1a3e5d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.h @@ -28,5 +28,5 @@ public: s32 shutdown(s32 how) override; s32 poll(sys_net_pollfd& sn_pfd, pollfd& native_pfd) override; - s32 select(bs_t<poll_t> selected, pollfd& native_pfd) override; + std::tuple<bool, bool, bool> select(bs_t<poll_t> selected, pollfd& native_pfd) override; }; diff --git a/rpcs3/Emu/Cell/lv2/sys_net/nt_p2p_port.h b/rpcs3/Emu/Cell/lv2/sys_net/nt_p2p_port.h index b17f7c2531..4115a0462e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/nt_p2p_port.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/nt_p2p_port.h @@ -22,7 +22,7 @@ struct nt_p2p_port { // Real socket where P2P packets are received/sent socket_type p2p_socket = 0; - u16 port = 0; + u16 port = 0; shared_mutex bound_p2p_vports_mutex; // For DGRAM_P2P sockets(vport, sock_id) 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 fb081baff0..54b9e5417b 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/sys_net_helpers.h @@ -15,7 +15,6 @@ #endif #endif - #include "Emu/Cell/lv2/sys_net.h" int get_native_error();