mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-21 18:22:33 +01:00
sys_net: Implement sys_net_bnet_sendmsg for native sockets
This commit is contained in:
parent
8485afa3a5
commit
2655255d4d
@ -900,8 +900,79 @@ error_code sys_net_bnet_sendmsg(ppu_thread& ppu, s32 s, vm::cptr<sys_net_msghdr>
|
||||
{
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
sys_net.todo("sys_net_bnet_sendmsg(s=%d, msg=*0x%x, flags=0x%x)", s, msg, flags);
|
||||
return CELL_OK;
|
||||
sys_net.warning("sys_net_bnet_sendmsg(s=%d, msg=*0x%x, flags=0x%x)", s, msg, flags);
|
||||
|
||||
if (flags & ~(SYS_NET_MSG_DONTWAIT | SYS_NET_MSG_WAITALL | SYS_NET_MSG_USECRYPTO | SYS_NET_MSG_USESIGNATURE))
|
||||
{
|
||||
fmt::throw_exception("sys_net_bnet_sendmsg(s=%d): unknown flags (0x%x)", flags);
|
||||
}
|
||||
|
||||
s32 result{};
|
||||
|
||||
const auto sock = idm::check<lv2_socket>(s, [&](lv2_socket& sock)
|
||||
{
|
||||
auto netmsg = msg.get_ptr();
|
||||
const auto success = sock.sendmsg(flags, *netmsg);
|
||||
|
||||
if (success)
|
||||
{
|
||||
result = *success;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
sock.poll_queue(idm::get_unlocked<named_thread<ppu_thread>>(ppu.id), lv2_socket::poll_t::write, [&](bs_t<lv2_socket::poll_t> events) -> bool
|
||||
{
|
||||
if (events & lv2_socket::poll_t::write)
|
||||
{
|
||||
const auto success = sock.sendmsg(flags, *netmsg, false);
|
||||
|
||||
if (success)
|
||||
{
|
||||
result = *success;
|
||||
lv2_obj::awake(&ppu);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
sock.set_poll_event(lv2_socket::poll_t::write);
|
||||
return false;
|
||||
});
|
||||
|
||||
lv2_obj::sleep(ppu);
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!sock)
|
||||
{
|
||||
return -SYS_NET_EBADF;
|
||||
}
|
||||
|
||||
if (!sock.ret)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
const auto state = ppu.state.fetch_sub(cpu_flag::signal);
|
||||
if (is_stopped(state) || state & cpu_flag::signal)
|
||||
{
|
||||
break;
|
||||
}
|
||||
thread_ctrl::wait_on(ppu.state, state);
|
||||
}
|
||||
|
||||
if (ppu.gpr[3] == static_cast<u64>(-SYS_NET_EINTR))
|
||||
{
|
||||
return -SYS_NET_EINTR;
|
||||
}
|
||||
}
|
||||
|
||||
if (result >= 0 || result == -SYS_NET_EWOULDBLOCK)
|
||||
{
|
||||
return not_an_error(result);
|
||||
}
|
||||
|
||||
|
||||
return sys_net_error{result};
|
||||
}
|
||||
|
||||
error_code sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr<void> buf, u32 len, s32 flags, vm::cptr<sys_net_sockaddr> addr, u32 addrlen)
|
||||
|
@ -94,6 +94,7 @@ public:
|
||||
|
||||
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 std::optional<s32> sendmsg(s32 flags, const sys_net_msghdr& msg, bool is_lock = true) = 0;
|
||||
|
||||
virtual void close() = 0;
|
||||
virtual s32 shutdown(s32 how) = 0;
|
||||
|
@ -931,6 +931,50 @@ std::optional<s32> lv2_socket_native::sendto(s32 flags, const std::vector<u8>& b
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<s32> lv2_socket_native::sendmsg(s32 flags, const sys_net_msghdr& msg, bool is_lock)
|
||||
{
|
||||
std::unique_lock<shared_mutex> lock(mutex, std::defer_lock);
|
||||
|
||||
if (is_lock)
|
||||
{
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
int native_flags = 0;
|
||||
int native_result = -1;
|
||||
|
||||
sys_net_error result{};
|
||||
|
||||
if (flags & SYS_NET_MSG_WAITALL)
|
||||
{
|
||||
native_flags |= MSG_WAITALL;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < msg.msg_iovlen; i++)
|
||||
{
|
||||
auto iov_base = msg.msg_iov[i].iov_base;
|
||||
const u32 len = msg.msg_iov[i].iov_len;
|
||||
const std::vector<u8> buf_copy(vm::_ptr<const char>(iov_base.addr()), vm::_ptr<const char>(iov_base.addr()) + len);
|
||||
|
||||
native_result = ::send(socket, reinterpret_cast<const char*>(buf_copy.data()), buf_copy.size(), native_flags);
|
||||
|
||||
if (native_result >= 0)
|
||||
{
|
||||
return {native_result};
|
||||
}
|
||||
}
|
||||
|
||||
result = get_last_error(!so_nbio && (flags & SYS_NET_MSG_DONTWAIT) == 0);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return {-result};
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void lv2_socket_native::close()
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
|
@ -48,6 +48,7 @@ public:
|
||||
s32 setsockopt(s32 level, s32 optname, const std::vector<u8>& optval) override;
|
||||
std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> recvfrom(s32 flags, u32 len, bool is_lock = true) override;
|
||||
std::optional<s32> sendto(s32 flags, const std::vector<u8>& buf, std::optional<sys_net_sockaddr> opt_sn_addr, bool is_lock = true) override;
|
||||
std::optional<s32> sendmsg(s32 flags, const sys_net_msghdr& msg, bool is_lock = true) 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;
|
||||
|
@ -284,6 +284,12 @@ std::optional<s32> lv2_socket_p2p::sendto(s32 flags, const std::vector<u8>& buf,
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<s32> lv2_socket_p2p::sendmsg([[maybe_unused]] s32 flags, [[maybe_unused]] const sys_net_msghdr& msg, [[maybe_unused]] bool is_lock)
|
||||
{
|
||||
sys_net.todo("lv2_socket_p2p::sendmsg");
|
||||
return {};
|
||||
}
|
||||
|
||||
void lv2_socket_p2p::close()
|
||||
{
|
||||
if (!port || !vport)
|
||||
|
@ -25,6 +25,7 @@ public:
|
||||
|
||||
std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> recvfrom(s32 flags, u32 len, bool is_lock = true) override;
|
||||
std::optional<s32> sendto(s32 flags, const std::vector<u8>& buf, std::optional<sys_net_sockaddr> opt_sn_addr, bool is_lock = true) override;
|
||||
std::optional<s32> sendmsg(s32 flags, const sys_net_msghdr& msg, bool is_lock = true) override;
|
||||
|
||||
void close() override;
|
||||
s32 shutdown(s32 how) override;
|
||||
|
@ -795,6 +795,12 @@ std::optional<s32> lv2_socket_p2ps::sendto([[maybe_unused]] s32 flags, const std
|
||||
return {buf.size()};
|
||||
}
|
||||
|
||||
std::optional<s32> lv2_socket_p2ps::sendmsg([[maybe_unused]] s32 flags, [[maybe_unused]] const sys_net_msghdr& msg, [[maybe_unused]] bool is_lock)
|
||||
{
|
||||
sys_net.todo("lv2_socket_p2ps::sendmsg");
|
||||
return {};
|
||||
}
|
||||
|
||||
void lv2_socket_p2ps::close()
|
||||
{
|
||||
if (!port || !vport)
|
||||
|
@ -79,6 +79,7 @@ public:
|
||||
|
||||
std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> recvfrom(s32 flags, u32 len, bool is_lock = true) override;
|
||||
std::optional<s32> sendto(s32 flags, const std::vector<u8>& buf, std::optional<sys_net_sockaddr> opt_sn_addr, bool is_lock = true) override;
|
||||
std::optional<s32> sendmsg(s32 flags, const sys_net_msghdr& msg, bool is_lock = true) override;
|
||||
|
||||
void close() override;
|
||||
s32 shutdown(s32 how) override;
|
||||
|
@ -84,6 +84,12 @@ std::optional<s32> lv2_socket_raw::sendto([[maybe_unused]] s32 flags, [[maybe_un
|
||||
return buf.size();
|
||||
}
|
||||
|
||||
std::optional<s32> lv2_socket_raw::sendmsg([[maybe_unused]] s32 flags, [[maybe_unused]] const sys_net_msghdr& msg, [[maybe_unused]] bool is_lock)
|
||||
{
|
||||
sys_net.todo("lv2_socket_raw::sendmsg");
|
||||
return {};
|
||||
}
|
||||
|
||||
void lv2_socket_raw::close()
|
||||
{
|
||||
sys_net.todo("lv2_socket_raw::close");
|
||||
|
@ -25,6 +25,7 @@ public:
|
||||
|
||||
std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> recvfrom(s32 flags, u32 len, bool is_lock = true) override;
|
||||
std::optional<s32> sendto(s32 flags, const std::vector<u8>& buf, std::optional<sys_net_sockaddr> opt_sn_addr, bool is_lock = true) override;
|
||||
std::optional<s32> sendmsg(s32 flags, const sys_net_msghdr& msg, bool is_lock = true) override;
|
||||
|
||||
void close() override;
|
||||
s32 shutdown(s32 how) override;
|
||||
|
Loading…
Reference in New Issue
Block a user