diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index 2941b47071..16cec30ff9 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -1860,7 +1860,7 @@ error_code sceNpBasicGetFriendPresenceByNpId2(vm::cptr npid, vm::ptr npid, vm::cptr description) { - sceNp.todo("sceNpBasicAddPlayersHistory(npid=*0x%x, description=*0x%x)", npid, description); + sceNp.warning("sceNpBasicAddPlayersHistory(npid=*0x%x, description=*0x%x)", npid, description); auto& nph = g_fxo->get>(); @@ -1886,7 +1886,7 @@ error_code sceNpBasicAddPlayersHistory(vm::cptr npid, vm::cptr de error_code sceNpBasicAddPlayersHistoryAsync(vm::cptr npids, u32 count, vm::cptr description, vm::ptr reqId) { - sceNp.todo("sceNpBasicAddPlayersHistoryAsync(npids=*0x%x, count=%d, description=*0x%x, reqId=*0x%x)", npids, count, description, reqId); + sceNp.warning("sceNpBasicAddPlayersHistoryAsync(npids=*0x%x, count=%d, description=*0x%x, reqId=*0x%x)", npids, count, description, reqId); auto& nph = g_fxo->get>(); @@ -6749,7 +6749,7 @@ error_code sceNpSignalingActivateConnection(u32 ctx_id, vm::ptr npId, v error_code sceNpSignalingDeactivateConnection(u32 ctx_id, u32 conn_id) { - sceNp.todo("sceNpSignalingDeactivateConnection(ctx_id=%d, conn_id=%d)", ctx_id, conn_id); + sceNp.warning("sceNpSignalingDeactivateConnection(ctx_id=%d, conn_id=%d)", ctx_id, conn_id); auto& nph = g_fxo->get>(); @@ -6758,6 +6758,10 @@ error_code sceNpSignalingDeactivateConnection(u32 ctx_id, u32 conn_id) return SCE_NP_SIGNALING_ERROR_NOT_INITIALIZED; } + auto& sigh = g_fxo->get>(); + + sigh.stop_sig(conn_id, true); + return CELL_OK; } @@ -6774,7 +6778,7 @@ error_code sceNpSignalingTerminateConnection(u32 ctx_id, u32 conn_id) auto& sigh = g_fxo->get>(); - sigh.stop_sig(conn_id); + sigh.stop_sig(conn_id, false); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.cpp b/rpcs3/Emu/Cell/Modules/sceNp2.cpp index a10691d0b7..117d50e3bd 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp2.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp2.cpp @@ -1664,7 +1664,7 @@ error_code sceNpMatching2SendLobbyInvitation( error_code sceNpMatching2ContextStop(SceNpMatching2ContextId ctxId) { - sceNp2.todo("sceNpMatching2ContextStop(ctxId=%d)", ctxId); + sceNp2.warning("sceNpMatching2ContextStop(ctxId=%d)", ctxId); auto& nph = g_fxo->get>(); diff --git a/rpcs3/Emu/Cell/Modules/sceNpPlus.cpp b/rpcs3/Emu/Cell/Modules/sceNpPlus.cpp index 6f8874b2d6..70b3f5181b 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpPlus.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNpPlus.cpp @@ -8,7 +8,7 @@ error_code sceNpManagerIsSP() { sceNpPlus.warning("sceNpManagerIsSP()"); // TODO seems to be cut to 1 byte by pshome likely a bool but may be more. - return CELL_OK; + return not_an_error(1); } DECLARE(ppu_module_manager::sceNpPlus)("sceNpPlus", []() diff --git a/rpcs3/Emu/Cell/lv2/sys_net.cpp b/rpcs3/Emu/Cell/lv2/sys_net.cpp index ff563f5d8a..01ab791d42 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net.cpp @@ -770,7 +770,7 @@ error_code sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr buf, u32 { ppu.state += cpu_flag::wait; - sys_net.warning("sys_net_bnet_recvfrom(s=%d, buf=*0x%x, len=%u, flags=0x%x, addr=*0x%x, paddrlen=*0x%x)", s, buf, len, flags, addr, paddrlen); + sys_net.trace("sys_net_bnet_recvfrom(s=%d, buf=*0x%x, len=%u, flags=0x%x, addr=*0x%x, paddrlen=*0x%x)", s, buf, len, flags, addr, paddrlen); // If addr is null, paddrlen must be null as well if (!buf || !len || addr.operator bool() != paddrlen.operator bool()) @@ -984,7 +984,7 @@ error_code sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr buf, u32 l { ppu.state += cpu_flag::wait; - sys_net.warning("sys_net_bnet_sendto(s=%d, buf=*0x%x, len=%u, flags=0x%x, addr=*0x%x, addrlen=%u)", s, buf, len, flags, addr, addrlen); + sys_net.trace("sys_net_bnet_sendto(s=%d, buf=*0x%x, len=%u, flags=0x%x, addr=*0x%x, addrlen=%u)", s, buf, len, flags, addr, addrlen); if (flags & ~(SYS_NET_MSG_DONTWAIT | SYS_NET_MSG_WAITALL | SYS_NET_MSG_USECRYPTO | SYS_NET_MSG_USESIGNATURE)) { @@ -1256,7 +1256,7 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr fds, s32 n { ppu.state += cpu_flag::wait; - sys_net.warning("sys_net_bnet_poll(fds=*0x%x, nfds=%d, ms=%d)", fds, nfds, ms); + sys_net.trace("sys_net_bnet_poll(fds=*0x%x, nfds=%d, ms=%d)", fds, nfds, ms); if (nfds <= 0) { @@ -1438,7 +1438,7 @@ error_code sys_net_bnet_select(ppu_thread& ppu, s32 nfds, vm::ptr signaled{0}; 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 6c7df86c09..b77d08773a 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp @@ -9,6 +9,11 @@ LOG_CHANNEL(sys_net); lv2_socket_p2p::lv2_socket_p2p(lv2_socket_family family, lv2_socket_type type, lv2_ip_protocol protocol) : lv2_socket(family, type, protocol) { + sockopt_cache cache_type; + cache_type.data._int = SYS_NET_SOCK_DGRAM_P2P; + cache_type.len = 4; + + sockopts[(static_cast(SYS_NET_SOL_SOCKET) << 32ull) | SYS_NET_SO_TYPE] = cache_type; } lv2_socket_p2p::lv2_socket_p2p(utils::serial& ar, lv2_socket_type type) 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 4474164ed5..4553d73614 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp @@ -243,6 +243,11 @@ std::vector generate_u2s_packet(const p2ps_encapsulated_tcp& header, const u lv2_socket_p2ps::lv2_socket_p2ps(lv2_socket_family family, lv2_socket_type type, lv2_ip_protocol protocol) : lv2_socket_p2p(family, type, protocol) { + sockopt_cache cache_type; + cache_type.data._int = SYS_NET_SOCK_STREAM_P2P; + cache_type.len = 4; + + sockopts[(static_cast(SYS_NET_SOL_SOCKET) << 32ull) | SYS_NET_SO_TYPE] = cache_type; } lv2_socket_p2ps::lv2_socket_p2ps(socket_type socket, u16 port, u16 vport, u32 op_addr, u16 op_port, u16 op_vport, u64 cur_seq, u64 data_beg_seq, s32 so_nbio) diff --git a/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp b/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp index e3d5cdda4a..6c284a14e6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp @@ -19,6 +19,9 @@ s32 send_packet_from_p2p_port(const std::vector& data, const sockaddr_in& ad { auto& def_port = ::at32(nc.list_p2p_ports, SCE_NP_PORT); res = ::sendto(def_port.p2p_socket, reinterpret_cast(data.data()), ::size32(data), 0, reinterpret_cast(&addr), sizeof(sockaddr_in)); + + if (res == -1) + sys_net.error("Failed to send signaling packet: %s", get_last_error(false, false)); } else { diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index 51a13f2923..b5bee8750f 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -1122,6 +1122,7 @@ namespace np case rpcn::NotificationType::UpdatedRoomMemberDataInternal: notif_updated_room_member_data_internal(notif.second); break; case rpcn::NotificationType::SignalP2PConnect: notif_p2p_connect(notif.second); break; case rpcn::NotificationType::RoomMessageReceived: notif_room_message_received(notif.second); break; + case rpcn::NotificationType::SignalingInfo: notif_signaling_info(notif.second); break; default: rpcn_log.error("Unknown notification(%d) received!", notif.first); break; } } @@ -1240,7 +1241,7 @@ namespace np ret.cb = (optParam && optParam->cbFunc) ? optParam->cbFunc : ctx->default_match2_optparam.cbFunc; ret.event_type = event_type; - nph_log.warning("Callback used is 0x%x", ret.cb); + nph_log.trace("Callback used is 0x%x with req_id %d", ret.cb, req_id); { std::lock_guard lock(mutex_pending_requests); diff --git a/rpcs3/Emu/NP/np_handler.h b/rpcs3/Emu/NP/np_handler.h index 085dfa522e..bc83f26440 100644 --- a/rpcs3/Emu/NP/np_handler.h +++ b/rpcs3/Emu/NP/np_handler.h @@ -268,6 +268,7 @@ namespace np void notif_updated_room_data_internal(std::vector& data); void notif_updated_room_member_data_internal(std::vector& data); void notif_p2p_connect(std::vector& data); + void notif_signaling_info(std::vector& data); void notif_room_message_received(std::vector& data); // Reply handlers diff --git a/rpcs3/Emu/NP/np_notifications.cpp b/rpcs3/Emu/NP/np_notifications.cpp index 14db3a6b8d..f064cf1c5d 100644 --- a/rpcs3/Emu/NP/np_notifications.cpp +++ b/rpcs3/Emu/NP/np_notifications.cpp @@ -241,4 +241,24 @@ namespace np const u32 conn_id = sigh.init_sig2(*npid, room_id, member_id); sigh.start_sig(conn_id, addr_p2p, port_p2p); } + + void np_handler::notif_signaling_info(std::vector& data) + { + vec_stream noti(data); + const u32 addr_p2p = noti.get(); + const u32 port_p2p = noti.get(); + const std::string str_npid = noti.get_string(false); + + if (noti.is_error()) + { + rpcn_log.error("Received faulty SignalingInfo notification"); + return; + } + + SceNpId npid_p2p; + string_to_npid(str_npid, npid_p2p); + + auto& sigh = g_fxo->get>(); + sigh.send_information_packets(addr_p2p, port_p2p, npid_p2p); + } } // namespace np diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp index 187f73542a..c42845ba9f 100644 --- a/rpcs3/Emu/NP/rpcn_client.cpp +++ b/rpcs3/Emu/NP/rpcn_client.cpp @@ -84,7 +84,7 @@ namespace rpcn rpcn_log.notice("online: %s, pr_com_id: %s, pr_title: %s, pr_status: %s, pr_comment: %s, pr_data: %s", online ? "true" : "false", pr_com_id.data, pr_title, pr_status, pr_comment, fmt::buf_to_hexstring(pr_data.data(), pr_data.size())); } - constexpr u32 RPCN_PROTOCOL_VERSION = 22; + constexpr u32 RPCN_PROTOCOL_VERSION = 23; constexpr usz RPCN_HEADER_SIZE = 15; bool is_error(ErrorType err) diff --git a/rpcs3/Emu/NP/rpcn_client.h b/rpcs3/Emu/NP/rpcn_client.h index 082a3bc60f..af432d787a 100644 --- a/rpcs3/Emu/NP/rpcn_client.h +++ b/rpcs3/Emu/NP/rpcn_client.h @@ -241,6 +241,7 @@ namespace rpcn RoomMessageReceived, MessageReceived, FriendPresenceChanged, + SignalingInfo, }; enum class rpcn_state diff --git a/rpcs3/Emu/NP/signaling_handler.cpp b/rpcs3/Emu/NP/signaling_handler.cpp index cfb4aa153d..bb1e8fb9a4 100644 --- a/rpcs3/Emu/NP/signaling_handler.cpp +++ b/rpcs3/Emu/NP/signaling_handler.cpp @@ -17,7 +17,6 @@ LOG_CHANNEL(sign_log, "Signaling"); - template <> void fmt_class_string::format(std::string& out, u64 arg) { @@ -32,6 +31,7 @@ void fmt_class_string::format(std::string& out, u64 arg) case signal_confirm: return "CONFIRM"; case signal_finished: return "FINISHED"; case signal_finished_ack: return "FINISHED_ACK"; + case signal_info: return "INFO"; } return unknown; @@ -70,42 +70,42 @@ void signaling_handler::set_sig2_cb(u16 sig2_cb_ctx, vm::ptrsig2_cb_arg = sig2_cb_arg; } -void signaling_handler::signal_sig_callback(u32 conn_id, int event) +void signaling_handler::signal_sig_callback(u32 conn_id, int event, int error_code) { if (sig_cb) { - sysutil_register_cb([sig_cb = this->sig_cb, sig_cb_ctx = this->sig_cb_ctx, conn_id, event, sig_cb_arg = this->sig_cb_arg](ppu_thread& cb_ppu) -> s32 + sysutil_register_cb([sig_cb = this->sig_cb, sig_cb_ctx = this->sig_cb_ctx, conn_id, event, error_code, sig_cb_arg = this->sig_cb_arg](ppu_thread& cb_ppu) -> s32 { - sig_cb(cb_ppu, sig_cb_ctx, conn_id, event, 0, sig_cb_arg); + sig_cb(cb_ppu, sig_cb_ctx, conn_id, event, error_code, sig_cb_arg); return 0; }); sign_log.notice("Called sig CB: 0x%x (conn_id: %d)", event, conn_id); } // extended callback also receives normal events - signal_ext_sig_callback(conn_id, event); + signal_ext_sig_callback(conn_id, event, error_code); } -void signaling_handler::signal_ext_sig_callback(u32 conn_id, int event) const +void signaling_handler::signal_ext_sig_callback(u32 conn_id, int event, int error_code) const { if (sig_ext_cb) { - sysutil_register_cb([sig_ext_cb = this->sig_ext_cb, sig_ext_cb_ctx = this->sig_ext_cb_ctx, conn_id, event, sig_ext_cb_arg = this->sig_ext_cb_arg](ppu_thread& cb_ppu) -> s32 + sysutil_register_cb([sig_ext_cb = this->sig_ext_cb, sig_ext_cb_ctx = this->sig_ext_cb_ctx, conn_id, event, error_code, sig_ext_cb_arg = this->sig_ext_cb_arg](ppu_thread& cb_ppu) -> s32 { - sig_ext_cb(cb_ppu, sig_ext_cb_ctx, conn_id, event, 0, sig_ext_cb_arg); + sig_ext_cb(cb_ppu, sig_ext_cb_ctx, conn_id, event, error_code, sig_ext_cb_arg); return 0; }); sign_log.notice("Called EXT sig CB: 0x%x (conn_id: %d)", event, conn_id); } } -void signaling_handler::signal_sig2_callback(u64 room_id, u16 member_id, SceNpMatching2Event event) const +void signaling_handler::signal_sig2_callback(u64 room_id, u16 member_id, SceNpMatching2Event event, int error_code) const { 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 + sysutil_register_cb([sig2_cb = this->sig2_cb, sig2_cb_ctx = this->sig2_cb_ctx, room_id, member_id, event, error_code, 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); + sig2_cb(cb_ppu, sig2_cb_ctx, room_id, member_id, event, error_code, sig2_cb_arg); return 0; }); sign_log.notice("Called sig2 CB: 0x%x (room_id: %d, member_id: %d)", event, room_id, member_id); @@ -223,7 +223,7 @@ void signaling_handler::process_incoming_messages() // Get signaling info for user to know if we should even bother looking further auto si = get_signaling_ptr(sp); - if (!si && sp->command == signal_connect) + if (!si && (sp->command == signal_connect || sp->command == signal_info)) { // Connection can be remotely established and not mutual const u32 conn_id = get_always_conn_id(sp->npid); @@ -288,6 +288,11 @@ void signaling_handler::process_incoming_messages() schedule_repeat = false; reschedule_packet(si, signal_ping, now + 10s); break; + case signal_info: + update_si_addr(si, op_addr, op_port); + reply = false; + schedule_repeat = false; + break; case signal_connect: reply = true; schedule_repeat = true; @@ -306,7 +311,7 @@ void signaling_handler::process_incoming_messages() retire_packet(si, signal_connect); 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); + update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE, CELL_OK); break; case signal_confirm: update_rtt(sp->timestamp_receiver); @@ -327,7 +332,7 @@ void signaling_handler::process_incoming_messages() case signal_finished_ack: reply = false; schedule_repeat = false; - update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_INACTIVE); + update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_INACTIVE, SCE_NP_SIGNALING_ERROR_TERMINATED_BY_MYSELF); retire_packet(si, signal_finished); break; default: sign_log.error("Invalid signaling command received"); continue; @@ -371,12 +376,15 @@ void signaling_handler::operator()() if (timestamp > now) break; - if (sig.sig_info->time_last_msg_recvd < now - 60s) + SignalingCommand cmd = sig.packet.command; + + if (sig.sig_info->time_last_msg_recvd < now - 60s && cmd != signal_info) { // We had no connection to opponent for 60 seconds, consider the connection dead 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_si_status(sig.sig_info, SCE_NP_SIGNALING_CONN_STATUS_INACTIVE, SCE_NP_SIGNALING_ERROR_TIMEOUT); + retire_packet(sig.sig_info, signal_ping); // Retire ping packet if necessary + break; // qpackets has been emptied of all packets for this user so we're requeuing } // Update the timestamp if necessary @@ -397,7 +405,6 @@ void signaling_handler::operator()() send_signaling_packet(sig.packet, sig.sig_info->addr, sig.sig_info->port); // Reschedule another packet - SignalingCommand cmd = sig.packet.command; auto& si = sig.sig_info; std::chrono::milliseconds delay(500); @@ -416,9 +423,21 @@ void signaling_handler::operator()() case signal_finished_ack: delay = REPEAT_FINISHED_DELAY; break; + case signal_info: + // Don't reschedule + if (si->info_counter == 0) + { + it = qpackets.erase(it); + continue; + } + + delay = REPEAT_INFO_DELAY; + si->info_counter--; + break; } it++; + reschedule_packet(si, cmd, now + delay); } @@ -505,7 +524,7 @@ void signaling_handler::update_si_mapped_addr(std::shared_ptr& s } } -void signaling_handler::update_si_status(std::shared_ptr& si, s32 new_status) +void signaling_handler::update_si_status(std::shared_ptr& si, s32 new_status, int error_code) { if (!si) return; @@ -514,17 +533,17 @@ void signaling_handler::update_si_status(std::shared_ptr& si, s3 { si->conn_status = SCE_NP_SIGNALING_CONN_STATUS_ACTIVE; - 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); + signal_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_ESTABLISHED, error_code); + signal_sig2_callback(si->room_id, si->member_id, SCE_NP_MATCHING2_SIGNALING_EVENT_Established, error_code); if (si->op_activated) - signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_MUTUAL_ACTIVATED); + signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_MUTUAL_ACTIVATED, CELL_OK); } 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->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); + signal_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_DEAD, error_code); + signal_sig2_callback(si->room_id, si->member_id, SCE_NP_MATCHING2_SIGNALING_EVENT_Dead, error_code); retire_all_packets(si); } } @@ -536,15 +555,15 @@ void signaling_handler::update_ext_si_status(std::shared_ptr& si 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); + signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_PEER_ACTIVATED, CELL_OK); else - signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_MUTUAL_ACTIVATED); + signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_MUTUAL_ACTIVATED, CELL_OK); } 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); + signal_ext_sig_callback(si->conn_id, SCE_NP_SIGNALING_EVENT_EXT_PEER_DEACTIVATED, CELL_OK); } } @@ -620,21 +639,35 @@ void signaling_handler::start_sig(u32 conn_id, u32 addr, u16 port) ensure(sig_peers.contains(conn_id)); std::shared_ptr si = ::at32(sig_peers, conn_id); - si->addr = addr; - si->port = port; + const auto now = steady_clock::now(); + + si->time_last_msg_recvd = now; + + // Only update if those haven't been set before(possible we received a signal_info before) + if (si->addr == 0 || si->port == 0) + { + si->addr = addr; + si->port = port; + } send_signaling_packet(sent_packet, si->addr, si->port); - queue_signaling_packet(sent_packet, si, steady_clock::now() + REPEAT_CONNECT_DELAY); + queue_signaling_packet(sent_packet, si, now + REPEAT_CONNECT_DELAY); wake_up(); } -void signaling_handler::stop_sig_nl(u32 conn_id) +void signaling_handler::stop_sig_nl(u32 conn_id, bool forceful) { if (!sig_peers.contains(conn_id)) return; std::shared_ptr si = ::at32(sig_peers, conn_id); + retire_all_packets(si); + + // If forceful we don't go through any transition and don't call any CB + if (forceful) + si->conn_status = SCE_NP_SIGNALING_CONN_STATUS_INACTIVE; + // Do not queue packets for an already dead connection if (si->conn_status == SCE_NP_SIGNALING_CONN_STATUS_INACTIVE) return; @@ -644,13 +677,13 @@ void signaling_handler::stop_sig_nl(u32 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); + wake_up(); } -void signaling_handler::stop_sig(u32 conn_id) +void signaling_handler::stop_sig(u32 conn_id, bool forceful) { std::lock_guard lock(data_mutex); - - stop_sig_nl(conn_id); + stop_sig_nl(conn_id, forceful); } void signaling_handler::disconnect_sig2_users(u64 room_id) @@ -661,11 +694,29 @@ void signaling_handler::disconnect_sig2_users(u64 room_id) { if (si->room_id == room_id) { - stop_sig_nl(conn_id); + stop_sig_nl(conn_id, false); } } } +void signaling_handler::send_information_packets(u32 addr, u16 port, const SceNpId& npid) +{ + std::lock_guard lock(data_mutex); + + const u32 conn_id = get_always_conn_id(npid); + std::shared_ptr si = ::at32(sig_peers, conn_id); + si->addr = addr; + si->port = port; + si->info_counter = 10; + + auto& sent_packet = sig_packet; + sent_packet.command = signal_info; + + send_signaling_packet(sent_packet, addr, port); + queue_signaling_packet(sent_packet, si, steady_clock::now() + REPEAT_INFO_DELAY); + wake_up(); +} + u32 signaling_handler::get_always_conn_id(const SceNpId& npid) { std::string npid_str(reinterpret_cast(npid.handle.data)); @@ -709,7 +760,12 @@ u32 signaling_handler::init_sig2(const SceNpId& npid, u64 room_id, u16 member_id 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; + + // If connection exists from prior state notify + if (si->conn_status == SCE_NP_SIGNALING_CONN_STATUS_ACTIVE) + signal_sig2_callback(si->room_id, si->member_id, SCE_NP_MATCHING2_SIGNALING_EVENT_Established, CELL_OK); + else + si->conn_status = SCE_NP_SIGNALING_CONN_STATUS_PENDING; return conn_id; } diff --git a/rpcs3/Emu/NP/signaling_handler.h b/rpcs3/Emu/NP/signaling_handler.h index 6b55af8bc5..fb90fdb8d7 100644 --- a/rpcs3/Emu/NP/signaling_handler.h +++ b/rpcs3/Emu/NP/signaling_handler.h @@ -26,6 +26,7 @@ struct signaling_info // Signaling u32 conn_id = 0; bool op_activated = false; + u32 info_counter = 10; // Matching2 u64 room_id = 0; @@ -48,6 +49,7 @@ enum SignalingCommand : u32 signal_confirm, signal_finished, signal_finished_ack, + signal_info, }; class signaling_handler @@ -71,7 +73,8 @@ public: void set_sig2_cb(u16 sig2_cb_ctx, vm::ptr sig2_cb, vm::ptr sig2_cb_arg); void start_sig(u32 conn_id, u32 addr, u16 port); - void stop_sig(u32 conn_id); + void stop_sig(u32 conn_id, bool forceful); + void send_information_packets(u32 addr, u16 port, const SceNpId& npid); void disconnect_sig2_users(u64 room_id); @@ -81,6 +84,7 @@ private: static constexpr auto REPEAT_CONNECT_DELAY = std::chrono::milliseconds(200); static constexpr auto REPEAT_PING_DELAY = std::chrono::milliseconds(500); static constexpr auto REPEAT_FINISHED_DELAY = std::chrono::milliseconds(500); + static constexpr auto REPEAT_INFO_DELAY = std::chrono::milliseconds(200); static constexpr be_t SIGNALING_SIGNATURE = (static_cast('S') << 24 | static_cast('I') << 16 | static_cast('G') << 8 | static_cast('N')); static constexpr le_t SIGNALING_VERSION = 3; @@ -98,7 +102,7 @@ private: struct queued_packet { - signaling_packet packet; + signaling_packet packet{}; std::shared_ptr sig_info; }; @@ -119,17 +123,17 @@ private: u32 get_always_conn_id(const SceNpId& npid); static void update_si_addr(std::shared_ptr& si, u32 new_addr, u16 new_port); static void update_si_mapped_addr(std::shared_ptr& si, u32 new_addr, u16 new_port); - void update_si_status(std::shared_ptr& si, s32 new_status); + void update_si_status(std::shared_ptr& si, s32 new_status, int error_code); void update_ext_si_status(std::shared_ptr& si, bool op_activated); - void signal_sig_callback(u32 conn_id, int event); - void signal_ext_sig_callback(u32 conn_id, int event) const; - void signal_sig2_callback(u64 room_id, u16 member_id, SceNpMatching2Event event) const; + void signal_sig_callback(u32 conn_id, int event, int error_code); + void signal_ext_sig_callback(u32 conn_id, int event, int error_code) const; + void signal_sig2_callback(u64 room_id, u16 member_id, SceNpMatching2Event event, int error_code) const; static bool validate_signaling_packet(const signaling_packet* sp); void reschedule_packet(std::shared_ptr& si, SignalingCommand cmd, steady_clock::time_point new_timepoint); void retire_packet(std::shared_ptr& si, SignalingCommand cmd); void retire_all_packets(std::shared_ptr& si); - void stop_sig_nl(u32 conn_id); + void stop_sig_nl(u32 conn_id, bool forceful); shared_mutex data_mutex; atomic_t wakey = 0;