mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-03 15:20:27 +01:00
Simplify signaling by making Matching2 a layer over normal signaling. Implements UPNP port forwarding Implement sceNpMatching2AbortRequest Fix reported bw in sceNpUtil Hack for Fat Princess binding udp on 3658 Reenable CB for sceNpBasicAddPlayersHistoryAsync Misc fixes
210 lines
5.1 KiB
C++
210 lines
5.1 KiB
C++
#include "stdafx.h"
|
|
#include "Emu/Cell/lv2/sys_sync.h"
|
|
#include "Emu/Cell/Modules/sceNp.h" // for SCE_NP_PORT
|
|
|
|
#include "network_context.h"
|
|
#include "Emu/system_config.h"
|
|
#include "sys_net_helpers.h"
|
|
|
|
LOG_CHANNEL(sys_net);
|
|
|
|
// Used by RPCN to send signaling packets to RPCN server(for UDP hole punching)
|
|
s32 send_packet_from_p2p_port(const std::vector<u8>& data, const sockaddr_in& addr)
|
|
{
|
|
s32 res{};
|
|
auto& nc = g_fxo->get<network_context>();
|
|
{
|
|
std::lock_guard list_lock(nc.list_p2p_ports_mutex);
|
|
if (nc.list_p2p_ports.contains(SCE_NP_PORT))
|
|
{
|
|
auto& def_port = ::at32(nc.list_p2p_ports, SCE_NP_PORT);
|
|
res = ::sendto(def_port.p2p_socket, reinterpret_cast<const char*>(data.data()), data.size(), 0, reinterpret_cast<const sockaddr*>(&addr), sizeof(sockaddr_in));
|
|
}
|
|
else
|
|
{
|
|
sys_net.error("send_packet_from_p2p_port: port %d not present", +SCE_NP_PORT);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
std::vector<std::vector<u8>> get_rpcn_msgs()
|
|
{
|
|
std::vector<std::vector<u8>> msgs;
|
|
auto& nc = g_fxo->get<network_context>();
|
|
{
|
|
std::lock_guard list_lock(nc.list_p2p_ports_mutex);
|
|
if (nc.list_p2p_ports.contains(SCE_NP_PORT))
|
|
{
|
|
auto& def_port = ::at32(nc.list_p2p_ports, SCE_NP_PORT);
|
|
{
|
|
std::lock_guard lock(def_port.s_rpcn_mutex);
|
|
msgs = std::move(def_port.rpcn_msgs);
|
|
def_port.rpcn_msgs.clear();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sys_net.error("get_rpcn_msgs: port %d not present", +SCE_NP_PORT);
|
|
}
|
|
}
|
|
|
|
return msgs;
|
|
}
|
|
|
|
std::vector<signaling_message> get_sign_msgs()
|
|
{
|
|
std::vector<signaling_message> msgs;
|
|
auto& nc = g_fxo->get<network_context>();
|
|
{
|
|
std::lock_guard list_lock(nc.list_p2p_ports_mutex);
|
|
if (nc.list_p2p_ports.contains(SCE_NP_PORT))
|
|
{
|
|
auto& def_port = ::at32(nc.list_p2p_ports, SCE_NP_PORT);
|
|
{
|
|
std::lock_guard lock(def_port.s_sign_mutex);
|
|
msgs = std::move(def_port.sign_msgs);
|
|
def_port.sign_msgs.clear();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sys_net.error("get_sign_msgs: port %d not present", +SCE_NP_PORT);
|
|
}
|
|
}
|
|
|
|
return msgs;
|
|
}
|
|
|
|
void need_network()
|
|
{
|
|
g_fxo->need<network_context>();
|
|
initialize_tcp_timeout_monitor();
|
|
}
|
|
|
|
void network_thread::bind_sce_np_port()
|
|
{
|
|
std::lock_guard list_lock(list_p2p_ports_mutex);
|
|
list_p2p_ports.emplace(std::piecewise_construct, std::forward_as_tuple(SCE_NP_PORT), std::forward_as_tuple(SCE_NP_PORT));
|
|
}
|
|
|
|
void network_thread::operator()()
|
|
{
|
|
std::vector<std::shared_ptr<lv2_socket>> socklist;
|
|
socklist.reserve(lv2_socket::id_count);
|
|
|
|
s_to_awake.clear();
|
|
|
|
::pollfd fds[lv2_socket::id_count]{};
|
|
#ifdef _WIN32
|
|
bool connecting[lv2_socket::id_count]{};
|
|
bool was_connecting[lv2_socket::id_count]{};
|
|
#endif
|
|
|
|
::pollfd p2p_fd[lv2_socket::id_count]{};
|
|
|
|
while (thread_ctrl::state() != thread_state::aborting)
|
|
{
|
|
// Wait with 1ms timeout
|
|
#ifdef _WIN32
|
|
windows_poll(fds, ::size32(socklist), 1, connecting);
|
|
#else
|
|
::poll(fds, socklist.size(), 1);
|
|
#endif
|
|
|
|
// Check P2P sockets for incoming packets(timeout could probably be set at 0)
|
|
{
|
|
std::lock_guard lock(list_p2p_ports_mutex);
|
|
std::memset(p2p_fd, 0, sizeof(p2p_fd));
|
|
auto num_p2p_sockets = 0;
|
|
for (const auto& p2p_port : list_p2p_ports)
|
|
{
|
|
p2p_fd[num_p2p_sockets].events = POLLIN;
|
|
p2p_fd[num_p2p_sockets].revents = 0;
|
|
p2p_fd[num_p2p_sockets].fd = p2p_port.second.p2p_socket;
|
|
num_p2p_sockets++;
|
|
}
|
|
|
|
if (num_p2p_sockets)
|
|
{
|
|
#ifdef _WIN32
|
|
const auto ret_p2p = WSAPoll(p2p_fd, num_p2p_sockets, 1);
|
|
#else
|
|
const auto ret_p2p = ::poll(p2p_fd, num_p2p_sockets, 1);
|
|
#endif
|
|
if (ret_p2p > 0)
|
|
{
|
|
auto fd_index = 0;
|
|
for (auto& p2p_port : list_p2p_ports)
|
|
{
|
|
if ((p2p_fd[fd_index].revents & POLLIN) == POLLIN || (p2p_fd[fd_index].revents & POLLRDNORM) == POLLRDNORM)
|
|
{
|
|
while (p2p_port.second.recv_data())
|
|
;
|
|
}
|
|
fd_index++;
|
|
}
|
|
}
|
|
else if (ret_p2p < 0)
|
|
{
|
|
sys_net.error("[P2P] Error poll on master P2P socket: %d", get_last_error(false));
|
|
}
|
|
}
|
|
}
|
|
|
|
std::lock_guard lock(s_nw_mutex);
|
|
|
|
for (usz i = 0; i < socklist.size(); i++)
|
|
{
|
|
#ifdef _WIN32
|
|
socklist[i]->handle_events(fds[i], was_connecting[i] && !connecting[i]);
|
|
#else
|
|
socklist[i]->handle_events(fds[i]);
|
|
#endif
|
|
}
|
|
|
|
s_to_awake.erase(std::unique(s_to_awake.begin(), s_to_awake.end()), s_to_awake.end());
|
|
|
|
for (ppu_thread* ppu : s_to_awake)
|
|
{
|
|
network_clear_queue(*ppu);
|
|
lv2_obj::append(ppu);
|
|
}
|
|
|
|
if (!s_to_awake.empty())
|
|
{
|
|
lv2_obj::awake_all();
|
|
}
|
|
|
|
s_to_awake.clear();
|
|
socklist.clear();
|
|
|
|
// Obtain all native active sockets
|
|
idm::select<lv2_socket>([&](u32 id, lv2_socket& s)
|
|
{
|
|
if (s.get_type() == SYS_NET_SOCK_DGRAM || s.get_type() == SYS_NET_SOCK_STREAM)
|
|
{
|
|
socklist.emplace_back(idm::get_unlocked<lv2_socket>(id));
|
|
}
|
|
});
|
|
|
|
for (usz i = 0; i < socklist.size(); i++)
|
|
{
|
|
auto events = socklist[i]->get_events();
|
|
|
|
fds[i].fd = events ? socklist[i]->get_socket() : -1;
|
|
fds[i].events =
|
|
(events & lv2_socket::poll_t::read ? POLLIN : 0) |
|
|
(events & lv2_socket::poll_t::write ? POLLOUT : 0) |
|
|
0;
|
|
fds[i].revents = 0;
|
|
#ifdef _WIN32
|
|
const auto cur_connecting = socklist[i]->is_connecting();
|
|
was_connecting[i] = connecting;
|
|
connecting[i] = connecting;
|
|
#endif
|
|
}
|
|
}
|
|
}
|