Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sys_net: Implement sys_net_bnet_sendmsg for native sockets #12687

Merged
merged 1 commit into from Sep 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
75 changes: 73 additions & 2 deletions rpcs3/Emu/Cell/lv2/sys_net.cpp
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.h
Expand Up @@ -94,6 +94,7 @@ class lv2_socket

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;
Expand Down
44 changes: 44 additions & 0 deletions rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h
Expand Up @@ -48,6 +48,7 @@ class lv2_socket_native final : public lv2_socket
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;
Expand Down
6 changes: 6 additions & 0 deletions rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.h
Expand Up @@ -25,6 +25,7 @@ class lv2_socket_p2p : public lv2_socket

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;
Expand Down
6 changes: 6 additions & 0 deletions rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.h
Expand Up @@ -79,6 +79,7 @@ class lv2_socket_p2ps final : public lv2_socket_p2p

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;
Expand Down
6 changes: 6 additions & 0 deletions rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.cpp
Expand Up @@ -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");
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_raw.h
Expand Up @@ -25,6 +25,7 @@ class lv2_socket_raw final : public lv2_socket

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;
Expand Down