mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-05 06:26:49 +00:00
rpcn: signaling handler improvements & upnp
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
This commit is contained in:
parent
364c33060b
commit
6186ac0245
45 changed files with 1290 additions and 747 deletions
|
|
@ -5,6 +5,7 @@
|
|||
#include "Emu/Cell/Modules/cellSysutil.h"
|
||||
#include "np_handler.h"
|
||||
#include "Emu/NP/vport0.h"
|
||||
#include "Emu/NP/np_helpers.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
|
|
@ -51,7 +52,7 @@ void signaling_handler::set_sig_cb(u32 sig_cb_ctx, vm::ptr<SceNpSignalingHandler
|
|||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
this->sig_cb_ctx = sig_cb_ctx;
|
||||
this->sig_cb = sig_cb;
|
||||
this->sig_cb = sig_cb;
|
||||
this->sig_cb_arg = sig_cb_arg;
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ void signaling_handler::set_ext_sig_cb(u32 sig_ext_cb_ctx, vm::ptr<SceNpSignalin
|
|||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
this->sig_ext_cb_ctx = sig_ext_cb_ctx;
|
||||
this->sig_ext_cb = sig_ext_cb;
|
||||
this->sig_ext_cb = sig_ext_cb;
|
||||
this->sig_ext_cb_arg = sig_ext_cb_arg;
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +68,7 @@ void signaling_handler::set_sig2_cb(u16 sig2_cb_ctx, vm::ptr<SceNpMatching2Signa
|
|||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
this->sig2_cb_ctx = sig2_cb_ctx;
|
||||
this->sig2_cb = sig2_cb;
|
||||
this->sig2_cb = sig2_cb;
|
||||
this->sig2_cb_arg = sig2_cb_arg;
|
||||
}
|
||||
|
||||
|
|
@ -102,17 +103,15 @@ void signaling_handler::signal_ext_sig_callback(u32 conn_id, int event) const
|
|||
|
||||
void signaling_handler::signal_sig2_callback(u64 room_id, u16 member_id, SceNpMatching2Event event) const
|
||||
{
|
||||
// Signal the callback
|
||||
if (sig2_cb)
|
||||
if (room_id && sig2_cb)
|
||||
{
|
||||
sysutil_register_cb([sig2_cb = this->sig2_cb, sig2_cb_ctx = this->sig2_cb_ctx, room_id, member_id, event, sig2_cb_arg = this->sig2_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
sig2_cb(cb_ppu, sig2_cb_ctx, room_id, member_id, event, 0, sig2_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
sign_log.notice("Called sig2 CB: 0x%x (room_id: %d, member_id: %d)", event, room_id, member_id);
|
||||
}
|
||||
|
||||
sign_log.notice("Called sig2 CB: 0x%x (room_id: %d, member_id: %d)", event, room_id, member_id);
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
|
|
@ -125,7 +124,7 @@ void signaling_handler::reschedule_packet(std::shared_ptr<signaling_info>& si, S
|
|||
{
|
||||
if (it->second.packet.command == cmd && it->second.sig_info == si)
|
||||
{
|
||||
auto new_queue = qpackets.extract(it);
|
||||
auto new_queue = qpackets.extract(it);
|
||||
new_queue.key() = new_timepoint;
|
||||
qpackets.insert(std::move(new_queue));
|
||||
return;
|
||||
|
|
@ -164,9 +163,21 @@ bool signaling_handler::validate_signaling_packet(const signaling_packet* sp)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (sp->version != 1u && sp->version != 2u)
|
||||
if (sp->version != SIGNALING_VERSION)
|
||||
{
|
||||
sign_log.error("Invalid version in signaling packet");
|
||||
sign_log.error("Invalid version in signaling packet: %d, expected: %d", sp->version, SIGNALING_VERSION);
|
||||
|
||||
if (sp->version > SIGNALING_VERSION)
|
||||
sign_log.error("You are most likely using an outdated version of RPCS3");
|
||||
else
|
||||
sign_log.error("The other user is most likely using an outdated version of RPCS3");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!np::is_valid_npid(sp->npid))
|
||||
{
|
||||
sign_log.error("Invalid npid in signaling packet");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -187,57 +198,36 @@ void signaling_handler::process_incoming_messages()
|
|||
|
||||
auto op_addr = msg.src_addr;
|
||||
auto op_port = msg.src_port;
|
||||
auto* sp = reinterpret_cast<const signaling_packet*>(msg.data.data());
|
||||
const auto* sp = reinterpret_cast<const signaling_packet*>(msg.data.data());
|
||||
|
||||
if (!validate_signaling_packet(sp))
|
||||
continue;
|
||||
|
||||
if (sign_log.trace)
|
||||
{
|
||||
in_addr addr;
|
||||
in_addr addr{};
|
||||
addr.s_addr = op_addr;
|
||||
char ip_str[16];
|
||||
inet_ntop(AF_INET, &addr, ip_str, sizeof(ip_str));
|
||||
std::string_view npid(sp->npid.handle.data);
|
||||
|
||||
if (sp->version == 1u)
|
||||
{
|
||||
char npid_buf[17]{};
|
||||
memcpy(npid_buf, sp->V1.npid.handle.data, 16);
|
||||
std::string npid(npid_buf);
|
||||
|
||||
char ip_str[16];
|
||||
inet_ntop(AF_INET, &addr, ip_str, sizeof(ip_str));
|
||||
|
||||
sign_log.trace("sig1 %s from %s:%d(%s)", sp->command, ip_str, op_port, npid);
|
||||
}
|
||||
else
|
||||
{
|
||||
char inet_addr[16];
|
||||
const char* inet_addr_string = inet_ntop(AF_INET, &addr, inet_addr, sizeof(inet_addr));
|
||||
|
||||
sign_log.trace("sig2 %s from %s:%d(%d:%d)", sp->command, inet_addr_string, op_port, sp->V2.room_id, sp->V2.member_id);
|
||||
}
|
||||
sign_log.trace("SP %s from %s:%d(npid: %s)", sp->command, ip_str, op_port, npid);
|
||||
}
|
||||
|
||||
bool reply = false, schedule_repeat = false;
|
||||
auto& sent_packet = sp->version == 1u ? sig1_packet : sig2_packet;
|
||||
auto& sent_packet = sig_packet;
|
||||
|
||||
// Get signaling info for user to know if we should even bother looking further
|
||||
auto si = get_signaling_ptr(sp);
|
||||
|
||||
if (!si && sp->version == 1u && sp->command == signal_connect)
|
||||
if (!si && sp->command == signal_connect)
|
||||
{
|
||||
// Connection can be remotely established and not mutual
|
||||
const u32 conn_id = create_sig_infos(&sp->V1.npid);
|
||||
si = ::at32(sig1_peers, conn_id);
|
||||
// Activate the connection without triggering the main CB
|
||||
si->connStatus = SCE_NP_SIGNALING_CONN_STATUS_ACTIVE;
|
||||
si->addr = op_addr;
|
||||
si->port = op_port;
|
||||
si->ext_status = ext_sign_peer;
|
||||
// Notify extended callback that peer activated
|
||||
signal_ext_sig_callback(conn_id, SCE_NP_SIGNALING_EVENT_EXT_PEER_ACTIVATED);
|
||||
const u32 conn_id = get_always_conn_id(sp->npid);
|
||||
si = ::at32(sig_peers, conn_id);
|
||||
}
|
||||
|
||||
if (!si || (si->connStatus == SCE_NP_SIGNALING_CONN_STATUS_INACTIVE && sp->command != signal_finished))
|
||||
if (!si && sp->command != signal_finished)
|
||||
{
|
||||
// User is unknown to us or the connection is inactive
|
||||
// Ignore packet unless it's a finished packet in case the finished_ack wasn't received by opponent
|
||||
|
|
@ -258,7 +248,7 @@ void signaling_handler::process_incoming_messages()
|
|||
}
|
||||
}
|
||||
|
||||
sent_packet.command = signal_ping;
|
||||
sent_packet.command = signal_ping;
|
||||
sent_packet.timestamp_sender = now.time_since_epoch().count();
|
||||
send_signaling_packet(sent_packet, si->addr, si->port);
|
||||
queue_signaling_packet(sent_packet, si, now + REPEAT_PING_DELAY);
|
||||
|
|
@ -266,12 +256,12 @@ void signaling_handler::process_incoming_messages()
|
|||
|
||||
const auto update_rtt = [&](u64 rtt_timestamp)
|
||||
{
|
||||
u32 rtt = now.time_since_epoch().count() - rtt_timestamp;
|
||||
u32 rtt = now.time_since_epoch().count() - rtt_timestamp;
|
||||
si->last_rtts[(si->rtt_counters % 6)] = rtt;
|
||||
si->rtt_counters++;
|
||||
|
||||
std::size_t num_rtts = std::min(static_cast<std::size_t>(6), si->rtt_counters);
|
||||
u64 sum = 0;
|
||||
u64 sum = 0;
|
||||
for (std::size_t index = 0; index < num_rtts; index++)
|
||||
{
|
||||
sum += si->last_rtts[index];
|
||||
|
|
@ -283,59 +273,57 @@ void signaling_handler::process_incoming_messages()
|
|||
switch (sp->command)
|
||||
{
|
||||
case signal_ping:
|
||||
reply = true;
|
||||
schedule_repeat = false;
|
||||
sent_packet.command = signal_pong;
|
||||
reply = true;
|
||||
schedule_repeat = false;
|
||||
sent_packet.command = signal_pong;
|
||||
sent_packet.timestamp_sender = sp->timestamp_sender;
|
||||
break;
|
||||
case signal_pong:
|
||||
update_rtt(sp->timestamp_sender);
|
||||
reply = false;
|
||||
reply = false;
|
||||
schedule_repeat = false;
|
||||
reschedule_packet(si, signal_ping, now + 10s);
|
||||
break;
|
||||
case signal_connect:
|
||||
reply = true;
|
||||
schedule_repeat = true;
|
||||
sent_packet.command = signal_connect_ack;
|
||||
reply = true;
|
||||
schedule_repeat = true;
|
||||
sent_packet.command = signal_connect_ack;
|
||||
sent_packet.timestamp_sender = sp->timestamp_sender;
|
||||
sent_packet.timestamp_receiver = now.time_since_epoch().count();
|
||||
// connection is established
|
||||
update_si_addr(si, op_addr, op_port);
|
||||
break;
|
||||
case signal_connect_ack:
|
||||
update_rtt(sp->timestamp_sender);
|
||||
reply = true;
|
||||
reply = true;
|
||||
schedule_repeat = false;
|
||||
setup_ping();
|
||||
sent_packet.command = signal_confirm;
|
||||
sent_packet.timestamp_receiver = now.time_since_epoch().count();
|
||||
retire_packet(si, signal_connect);
|
||||
// connection is active
|
||||
update_si_addr(si, op_addr, op_port);
|
||||
update_si_mapped_addr(si, sp->sent_addr, sp->sent_port);
|
||||
update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE);
|
||||
break;
|
||||
case signal_confirm:
|
||||
update_rtt(sp->timestamp_receiver);
|
||||
reply = false;
|
||||
reply = false;
|
||||
schedule_repeat = false;
|
||||
setup_ping();
|
||||
retire_packet(si, signal_connect_ack);
|
||||
// connection is active
|
||||
update_si_addr(si, op_addr, op_port);
|
||||
update_si_mapped_addr(si, sp->sent_addr, sp->sent_port);
|
||||
update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE, true);
|
||||
update_ext_si_status(si, true);
|
||||
break;
|
||||
case signal_finished:
|
||||
reply = true;
|
||||
schedule_repeat = false;
|
||||
reply = true;
|
||||
schedule_repeat = false;
|
||||
sent_packet.command = signal_finished_ack;
|
||||
// terminate connection
|
||||
update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_INACTIVE);
|
||||
update_ext_si_status(si, false);
|
||||
break;
|
||||
case signal_finished_ack:
|
||||
reply = false;
|
||||
reply = false;
|
||||
schedule_repeat = false;
|
||||
update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_INACTIVE);
|
||||
retire_packet(si, signal_finished);
|
||||
break;
|
||||
default: sign_log.error("Invalid signaling command received"); continue;
|
||||
|
|
@ -369,37 +357,39 @@ void signaling_handler::operator()()
|
|||
|
||||
for (auto it = qpackets.begin(); it != qpackets.end();)
|
||||
{
|
||||
if (it->first > now)
|
||||
auto& [timestamp, sig] = *it;
|
||||
|
||||
if (timestamp > now)
|
||||
break;
|
||||
|
||||
if (it->second.sig_info->time_last_msg_recvd < now - 60s)
|
||||
if (sig.sig_info->time_last_msg_recvd < now - 60s)
|
||||
{
|
||||
// We had no connection to opponent for 60 seconds, consider the connection dead
|
||||
sign_log.trace("Timeout disconnection");
|
||||
update_si_status(it->second.sig_info, SCE_NP_SIGNALING_CONN_STATUS_INACTIVE);
|
||||
break; // qpackets will be emptied of all packets from this user so we're requeuing
|
||||
sign_log.notice("Timeout disconnection");
|
||||
update_si_status(sig.sig_info, SCE_NP_SIGNALING_CONN_STATUS_INACTIVE);
|
||||
break; // qpackets will be emptied of all packets for this user so we're requeuing
|
||||
}
|
||||
|
||||
// Update the timestamp if necessary
|
||||
switch (it->second.packet.command)
|
||||
switch (sig.packet.command)
|
||||
{
|
||||
case signal_connect:
|
||||
case signal_ping:
|
||||
it->second.packet.timestamp_sender = now.time_since_epoch().count();
|
||||
sig.packet.timestamp_sender = now.time_since_epoch().count();
|
||||
break;
|
||||
case signal_connect_ack:
|
||||
it->second.packet.timestamp_receiver = now.time_since_epoch().count();
|
||||
sig.packet.timestamp_receiver = now.time_since_epoch().count();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Resend the packet
|
||||
send_signaling_packet(it->second.packet, it->second.sig_info->addr, it->second.sig_info->port);
|
||||
send_signaling_packet(sig.packet, sig.sig_info->addr, sig.sig_info->port);
|
||||
|
||||
// Reschedule another packet
|
||||
SignalingCommand cmd = it->second.packet.command;
|
||||
auto& si = it->second.sig_info;
|
||||
SignalingCommand cmd = sig.packet.command;
|
||||
auto& si = sig.sig_info;
|
||||
|
||||
std::chrono::milliseconds delay(500);
|
||||
switch (cmd)
|
||||
|
|
@ -442,16 +432,20 @@ void signaling_handler::update_si_addr(std::shared_ptr<signaling_info>& si, u32
|
|||
|
||||
if (si->addr != new_addr || si->port != new_port)
|
||||
{
|
||||
in_addr addr_old, addr_new;
|
||||
addr_old.s_addr = si->addr;
|
||||
addr_new.s_addr = new_addr;
|
||||
if (sign_log.trace)
|
||||
{
|
||||
in_addr addr_old, addr_new;
|
||||
addr_old.s_addr = si->addr;
|
||||
addr_new.s_addr = new_addr;
|
||||
|
||||
char ip_str_old[16];
|
||||
char ip_str_new[16];
|
||||
inet_ntop(AF_INET, &addr_old, ip_str_old, sizeof(ip_str_old));
|
||||
inet_ntop(AF_INET, &addr_new, ip_str_new, sizeof(ip_str_new));
|
||||
char ip_str_old[16];
|
||||
char ip_str_new[16];
|
||||
inet_ntop(AF_INET, &addr_old, ip_str_old, sizeof(ip_str_old));
|
||||
inet_ntop(AF_INET, &addr_new, ip_str_new, sizeof(ip_str_new));
|
||||
|
||||
sign_log.trace("Updated Address from %s:%d to %s:%d", ip_str_old, si->port, ip_str_new, new_port);
|
||||
}
|
||||
|
||||
sign_log.trace("Updated Address from %s:%d to %s:%d", ip_str_old, si->port, ip_str_new, new_port);
|
||||
si->addr = new_addr;
|
||||
si->port = new_port;
|
||||
}
|
||||
|
|
@ -461,87 +455,90 @@ void signaling_handler::update_si_mapped_addr(std::shared_ptr<signaling_info>& s
|
|||
{
|
||||
ensure(si);
|
||||
|
||||
if (si->addr != new_addr || si->port != new_port)
|
||||
if (si->mapped_addr != new_addr || si->mapped_port != new_port)
|
||||
{
|
||||
in_addr addr_old, addr_new;
|
||||
addr_old.s_addr = si->mapped_addr;
|
||||
addr_new.s_addr = new_addr;
|
||||
if (sign_log.trace)
|
||||
{
|
||||
in_addr addr_old, addr_new;
|
||||
addr_old.s_addr = si->mapped_addr;
|
||||
addr_new.s_addr = new_addr;
|
||||
|
||||
char ip_str_old[16];
|
||||
char ip_str_new[16];
|
||||
inet_ntop(AF_INET, &addr_old, ip_str_old, sizeof(ip_str_old));
|
||||
inet_ntop(AF_INET, &addr_new, ip_str_new, sizeof(ip_str_new));
|
||||
char ip_str_old[16];
|
||||
char ip_str_new[16];
|
||||
inet_ntop(AF_INET, &addr_old, ip_str_old, sizeof(ip_str_old));
|
||||
inet_ntop(AF_INET, &addr_new, ip_str_new, sizeof(ip_str_new));
|
||||
|
||||
sign_log.trace("Updated Mapped Address from %s:%d to %s:%d", ip_str_old, si->mapped_port, ip_str_new, new_port);
|
||||
}
|
||||
|
||||
sign_log.trace("Updated Mapped Address from %s:%d to %s:%d", ip_str_old, si->mapped_port, ip_str_new, new_port);
|
||||
si->mapped_addr = new_addr;
|
||||
si->mapped_port = new_port;
|
||||
}
|
||||
}
|
||||
|
||||
void signaling_handler::update_si_status(std::shared_ptr<signaling_info>& si, s32 new_status, bool confirm_packet)
|
||||
void signaling_handler::update_si_status(std::shared_ptr<signaling_info>& si, s32 new_status)
|
||||
{
|
||||
if (!si)
|
||||
return;
|
||||
|
||||
if (si->connStatus == SCE_NP_SIGNALING_CONN_STATUS_PENDING && new_status == SCE_NP_SIGNALING_CONN_STATUS_ACTIVE)
|
||||
if (si->conn_status == SCE_NP_SIGNALING_CONN_STATUS_PENDING && new_status == SCE_NP_SIGNALING_CONN_STATUS_ACTIVE)
|
||||
{
|
||||
si->connStatus = SCE_NP_SIGNALING_CONN_STATUS_ACTIVE;
|
||||
ensure(si->version == 1u || si->version == 2u);
|
||||
if (si->version == 1u)
|
||||
signal_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_ESTABLISHED);
|
||||
else
|
||||
signal_sig2_callback(si->room_id, si->member_id, SCE_NP_MATCHING2_SIGNALING_EVENT_Established);
|
||||
si->conn_status = SCE_NP_SIGNALING_CONN_STATUS_ACTIVE;
|
||||
|
||||
return;
|
||||
signal_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_ESTABLISHED);
|
||||
signal_sig2_callback(si->room_id, si->member_id, SCE_NP_MATCHING2_SIGNALING_EVENT_Established);
|
||||
|
||||
if (si->op_activated)
|
||||
signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_MUTUAL_ACTIVATED);
|
||||
}
|
||||
|
||||
if ((si->connStatus == SCE_NP_SIGNALING_CONN_STATUS_PENDING || si->connStatus == SCE_NP_SIGNALING_CONN_STATUS_ACTIVE) && new_status == SCE_NP_SIGNALING_CONN_STATUS_INACTIVE)
|
||||
else if ((si->conn_status == SCE_NP_SIGNALING_CONN_STATUS_PENDING || si->conn_status == SCE_NP_SIGNALING_CONN_STATUS_ACTIVE) && new_status == SCE_NP_SIGNALING_CONN_STATUS_INACTIVE)
|
||||
{
|
||||
si->connStatus = SCE_NP_SIGNALING_CONN_STATUS_INACTIVE;
|
||||
ensure(si->version == 1u || si->version == 2u);
|
||||
if (si->version == 1u)
|
||||
signal_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_DEAD);
|
||||
else
|
||||
signal_sig2_callback(si->room_id, si->member_id, SCE_NP_MATCHING2_SIGNALING_EVENT_Dead);
|
||||
|
||||
si->conn_status = SCE_NP_SIGNALING_CONN_STATUS_INACTIVE;
|
||||
signal_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_DEAD);
|
||||
signal_sig2_callback(si->room_id, si->member_id, SCE_NP_MATCHING2_SIGNALING_EVENT_Dead);
|
||||
retire_all_packets(si);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (confirm_packet && si->version == 1u && si->ext_status == ext_sign_none)
|
||||
void signaling_handler::update_ext_si_status(std::shared_ptr<signaling_info>& si, bool op_activated)
|
||||
{
|
||||
if (op_activated && !si->op_activated)
|
||||
{
|
||||
si->ext_status = ext_sign_mutual;
|
||||
signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_MUTUAL_ACTIVATED);
|
||||
si->op_activated = true;
|
||||
|
||||
if (si->conn_status != SCE_NP_SIGNALING_CONN_STATUS_ACTIVE)
|
||||
signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_PEER_ACTIVATED);
|
||||
else
|
||||
signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_MUTUAL_ACTIVATED);
|
||||
}
|
||||
else if (!op_activated && si->op_activated)
|
||||
{
|
||||
si->op_activated = false;
|
||||
|
||||
signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_PEER_DEACTIVATED);
|
||||
}
|
||||
}
|
||||
|
||||
void signaling_handler::set_self_sig_info(SceNpId& npid)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
sig1_packet.V1.npid = npid;
|
||||
}
|
||||
|
||||
void signaling_handler::set_self_sig2_info(u64 room_id, u16 member_id)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
sig2_packet.V2.room_id = room_id;
|
||||
sig2_packet.V2.member_id = member_id;
|
||||
sig_packet.npid = npid;
|
||||
}
|
||||
|
||||
void signaling_handler::send_signaling_packet(signaling_packet& sp, u32 addr, u16 port) const
|
||||
{
|
||||
std::vector<u8> packet(sizeof(signaling_packet) + VPORT_0_HEADER_SIZE);
|
||||
reinterpret_cast<le_t<u16>&>(packet[0]) = 0; // VPort 0
|
||||
packet[2] = SUBSET_SIGNALING;
|
||||
sp.sent_addr = addr;
|
||||
sp.sent_port = port;
|
||||
packet[2] = SUBSET_SIGNALING;
|
||||
sp.sent_addr = addr;
|
||||
sp.sent_port = port;
|
||||
memcpy(packet.data() + VPORT_0_HEADER_SIZE, &sp, sizeof(signaling_packet));
|
||||
|
||||
sockaddr_in dest;
|
||||
memset(&dest, 0, sizeof(sockaddr_in));
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_addr.s_addr = addr;
|
||||
dest.sin_port = std::bit_cast<u16, be_t<u16>>(port);
|
||||
dest.sin_port = std::bit_cast<u16, be_t<u16>>(port);
|
||||
|
||||
char ip_str[16];
|
||||
inet_ntop(AF_INET, &dest.sin_addr, ip_str, sizeof(ip_str));
|
||||
|
|
@ -558,55 +555,41 @@ void signaling_handler::queue_signaling_packet(signaling_packet& sp, std::shared
|
|||
{
|
||||
queued_packet qp;
|
||||
qp.sig_info = std::move(si);
|
||||
qp.packet = sp;
|
||||
qp.packet = sp;
|
||||
qpackets.emplace(wakeup_time, std::move(qp));
|
||||
}
|
||||
|
||||
std::shared_ptr<signaling_info> signaling_handler::get_signaling_ptr(const signaling_packet* sp)
|
||||
{
|
||||
// V1
|
||||
if (sp->version == 1u)
|
||||
{
|
||||
char npid_buf[17]{};
|
||||
memcpy(npid_buf, sp->V1.npid.handle.data, 16);
|
||||
std::string npid(npid_buf);
|
||||
u32 conn_id;
|
||||
|
||||
if (!npid_to_conn_id.contains(npid))
|
||||
return nullptr;
|
||||
char npid_buf[17]{};
|
||||
memcpy(npid_buf, sp->npid.handle.data, 16);
|
||||
std::string npid(npid_buf);
|
||||
|
||||
const u32 conn_id = ::at32(npid_to_conn_id, npid);
|
||||
if (!sig1_peers.contains(conn_id))
|
||||
{
|
||||
sign_log.error("Discrepancy in signaling 1 data");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ::at32(sig1_peers, conn_id);
|
||||
}
|
||||
|
||||
// V2
|
||||
auto room_id = sp->V2.room_id;
|
||||
auto member_id = sp->V2.member_id;
|
||||
if (!sig2_peers.contains(room_id) || !::at32(sig2_peers, room_id).contains(member_id))
|
||||
if (!npid_to_conn_id.contains(npid))
|
||||
return nullptr;
|
||||
|
||||
return ::at32(::at32(sig2_peers, room_id), member_id);
|
||||
conn_id = ::at32(npid_to_conn_id, npid);
|
||||
|
||||
if (!sig_peers.contains(conn_id))
|
||||
{
|
||||
sign_log.error("Discrepancy in signaling data");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ::at32(sig_peers, conn_id);
|
||||
}
|
||||
|
||||
void signaling_handler::start_sig(u32 conn_id, u32 addr, u16 port)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
start_sig_nl(conn_id, addr, port);
|
||||
}
|
||||
|
||||
void signaling_handler::start_sig_nl(u32 conn_id, u32 addr, u16 port)
|
||||
{
|
||||
auto& sent_packet = sig1_packet;
|
||||
auto& sent_packet = sig_packet;
|
||||
sent_packet.command = signal_connect;
|
||||
sent_packet.timestamp_sender = steady_clock::now().time_since_epoch().count();
|
||||
|
||||
ensure(sig1_peers.contains(conn_id));
|
||||
std::shared_ptr<signaling_info> si = ::at32(sig1_peers, conn_id);
|
||||
ensure(sig_peers.contains(conn_id));
|
||||
std::shared_ptr<signaling_info> si = ::at32(sig_peers, conn_id);
|
||||
|
||||
si->addr = addr;
|
||||
si->port = port;
|
||||
|
|
@ -616,133 +599,113 @@ void signaling_handler::start_sig_nl(u32 conn_id, u32 addr, u16 port)
|
|||
wake_up();
|
||||
}
|
||||
|
||||
void signaling_handler::stop_sig_nl(u32 conn_id)
|
||||
{
|
||||
if (!sig_peers.contains(conn_id))
|
||||
return;
|
||||
|
||||
auto& sent_packet = sig_packet;
|
||||
sent_packet.command = signal_finished;
|
||||
|
||||
std::shared_ptr<signaling_info> si = ::at32(sig_peers, conn_id);
|
||||
|
||||
send_signaling_packet(sent_packet, si->addr, si->port);
|
||||
queue_signaling_packet(sent_packet, std::move(si), steady_clock::now() + REPEAT_FINISHED_DELAY);
|
||||
}
|
||||
|
||||
void signaling_handler::stop_sig(u32 conn_id)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
|
||||
if (!sig1_peers.contains(conn_id))
|
||||
return;
|
||||
|
||||
auto& sent_packet = sig1_packet;
|
||||
sent_packet.command = signal_finished;
|
||||
|
||||
std::shared_ptr<signaling_info> si = ::at32(sig1_peers, conn_id);
|
||||
|
||||
send_signaling_packet(sent_packet, si->addr, si->port);
|
||||
queue_signaling_packet(sent_packet, si, steady_clock::now() + REPEAT_FINISHED_DELAY);
|
||||
}
|
||||
|
||||
void signaling_handler::start_sig2(u64 room_id, u16 member_id)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
|
||||
auto& sent_packet = sig2_packet;
|
||||
sent_packet.command = signal_connect;
|
||||
sent_packet.timestamp_sender = steady_clock::now().time_since_epoch().count();
|
||||
|
||||
ensure(sig2_peers.contains(room_id));
|
||||
const auto& sp = ::at32(sig2_peers, room_id);
|
||||
|
||||
ensure(sp.contains(member_id));
|
||||
std::shared_ptr<signaling_info> si = ::at32(sp, member_id);
|
||||
|
||||
send_signaling_packet(sent_packet, si->addr, si->port);
|
||||
queue_signaling_packet(sent_packet, si, steady_clock::now() + REPEAT_CONNECT_DELAY);
|
||||
wake_up();
|
||||
stop_sig_nl(conn_id);
|
||||
}
|
||||
|
||||
void signaling_handler::disconnect_sig2_users(u64 room_id)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
|
||||
if (!sig2_peers.contains(room_id))
|
||||
return;
|
||||
|
||||
auto& sent_packet = sig2_packet;
|
||||
|
||||
sent_packet.command = signal_finished;
|
||||
|
||||
for (const auto& member : ::at32(sig2_peers, room_id))
|
||||
for (auto& [conn_id, si] : sig_peers)
|
||||
{
|
||||
auto& si = member.second;
|
||||
if (si->connStatus != SCE_NP_SIGNALING_CONN_STATUS_INACTIVE && !si->self)
|
||||
if (si->room_id == room_id)
|
||||
{
|
||||
send_signaling_packet(sent_packet, si->addr, si->port);
|
||||
queue_signaling_packet(sent_packet, si, steady_clock::now() + REPEAT_FINISHED_DELAY);
|
||||
stop_sig_nl(conn_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 signaling_handler::create_sig_infos(const SceNpId* npid)
|
||||
u32 signaling_handler::get_always_conn_id(const SceNpId& npid)
|
||||
{
|
||||
ensure(npid->handle.data[16] == 0);
|
||||
std::string npid_str(reinterpret_cast<const char*>(npid->handle.data));
|
||||
|
||||
std::string npid_str(reinterpret_cast<const char*>(npid.handle.data));
|
||||
if (npid_to_conn_id.contains(npid_str))
|
||||
{
|
||||
return ::at32(npid_to_conn_id, npid_str);
|
||||
}
|
||||
|
||||
const u32 conn_id = cur_conn_id++;
|
||||
npid_to_conn_id.emplace(npid_str, conn_id);
|
||||
sig1_peers.emplace(conn_id, std::make_shared<signaling_info>());
|
||||
::at32(sig1_peers, conn_id)->version = 1;
|
||||
::at32(sig1_peers, conn_id)->conn_id = conn_id;
|
||||
::at32(sig1_peers, conn_id)->npid = *npid;
|
||||
npid_to_conn_id.emplace(std::move(npid_str), conn_id);
|
||||
sig_peers.emplace(conn_id, std::make_shared<signaling_info>());
|
||||
auto& si = ::at32(sig_peers, conn_id);
|
||||
si->conn_id = conn_id;
|
||||
si->npid = npid;
|
||||
|
||||
return conn_id;
|
||||
}
|
||||
|
||||
u32 signaling_handler::init_sig_infos(const SceNpId* npid)
|
||||
u32 signaling_handler::init_sig1(const SceNpId& npid)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
|
||||
const u32 conn_id = create_sig_infos(npid);
|
||||
const u32 conn_id = get_always_conn_id(npid);
|
||||
|
||||
if (sig1_peers[conn_id]->connStatus == SCE_NP_SIGNALING_CONN_STATUS_INACTIVE)
|
||||
if (sig_peers[conn_id]->conn_status == SCE_NP_SIGNALING_CONN_STATUS_INACTIVE)
|
||||
{
|
||||
sign_log.trace("Creating new sig1 connection and requesting infos from RPCN");
|
||||
sig1_peers[conn_id]->connStatus = SCE_NP_SIGNALING_CONN_STATUS_PENDING;
|
||||
sig_peers[conn_id]->conn_status = SCE_NP_SIGNALING_CONN_STATUS_PENDING;
|
||||
|
||||
// Request peer infos from RPCN
|
||||
std::string npid_str(reinterpret_cast<const char*>(npid->handle.data));
|
||||
std::string npid_str(reinterpret_cast<const char*>(npid.handle.data));
|
||||
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
||||
nph.req_sign_infos(npid_str, conn_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Connection already exists(from passive connection)
|
||||
if (sig1_peers[conn_id]->connStatus == SCE_NP_SIGNALING_CONN_STATUS_ACTIVE && sig1_peers[conn_id]->ext_status == ext_sign_peer)
|
||||
{
|
||||
sign_log.trace("Activating already peer activated connection");
|
||||
sig1_peers[conn_id]->ext_status = ext_sign_mutual;
|
||||
start_sig_nl(conn_id, sig1_peers[conn_id]->addr, sig1_peers[conn_id]->port);
|
||||
signal_sig_callback(conn_id, SCE_NP_SIGNALING_EVENT_ESTABLISHED);
|
||||
signal_ext_sig_callback(conn_id, SCE_NP_SIGNALING_EVENT_EXT_MUTUAL_ACTIVATED);
|
||||
}
|
||||
}
|
||||
|
||||
return conn_id;
|
||||
}
|
||||
|
||||
signaling_info signaling_handler::get_sig_infos(u32 conn_id)
|
||||
u32 signaling_handler::init_sig2(const SceNpId& npid, u64 room_id, u16 member_id)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
return *sig1_peers[conn_id];
|
||||
u32 conn_id = get_always_conn_id(npid);
|
||||
auto& si = ::at32(sig_peers, conn_id);
|
||||
si->room_id = room_id;
|
||||
si->member_id = member_id;
|
||||
si->conn_status = SCE_NP_SIGNALING_CONN_STATUS_PENDING;
|
||||
|
||||
return conn_id;
|
||||
}
|
||||
|
||||
std::optional<u32> signaling_handler::get_conn_id_from_npid(const SceNpId* npid)
|
||||
std::optional<u32> signaling_handler::get_conn_id_from_npid(const SceNpId& npid)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
// Diff behaviour here depending on SDK version, 420+ always succeeds
|
||||
return create_sig_infos(npid);
|
||||
|
||||
std::string npid_str(reinterpret_cast<const char*>(npid.handle.data));
|
||||
if (npid_to_conn_id.contains(npid_str))
|
||||
return ::at32(npid_to_conn_id, npid_str);
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<signaling_info> signaling_handler::get_sig_infos(u32 conn_id)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
if (sig_peers.contains(conn_id))
|
||||
return *::at32(sig_peers, conn_id);
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<u32> signaling_handler::get_conn_id_from_addr(u32 addr, u16 port)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
|
||||
for (const auto& [conn_id, conn_info] : sig1_peers)
|
||||
for (const auto& [conn_id, conn_info] : sig_peers)
|
||||
{
|
||||
if (conn_info && std::bit_cast<u32, be_t<u32>>(conn_info->addr) == addr && conn_info->port == port)
|
||||
{
|
||||
|
|
@ -752,36 +715,3 @@ std::optional<u32> signaling_handler::get_conn_id_from_addr(u32 addr, u16 port)
|
|||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void signaling_handler::set_sig2_infos(u64 room_id, u16 member_id, s32 status, u32 addr, u16 port, const SceNpId& npid, bool self)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
if (!sig2_peers[room_id][member_id])
|
||||
sig2_peers[room_id][member_id] = std::make_shared<signaling_info>();
|
||||
|
||||
auto& peer = sig2_peers[room_id][member_id];
|
||||
peer->connStatus = status;
|
||||
peer->addr = addr;
|
||||
peer->port = port;
|
||||
peer->self = self;
|
||||
peer->version = 2;
|
||||
peer->room_id = room_id;
|
||||
peer->member_id = member_id;
|
||||
peer->npid = npid;
|
||||
}
|
||||
|
||||
signaling_info signaling_handler::get_sig2_infos(u64 room_id, u16 member_id)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
|
||||
if (!sig2_peers[room_id][member_id])
|
||||
{
|
||||
sig2_peers[room_id][member_id] = std::make_shared<signaling_info>();
|
||||
auto& peer = sig2_peers[room_id][member_id];
|
||||
peer->room_id = room_id;
|
||||
peer->member_id = member_id;
|
||||
peer->version = 2;
|
||||
}
|
||||
|
||||
return *sig2_peers[room_id][member_id];
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue