diff --git a/.gitignore b/.gitignore
index f576495fd3..40fb58d238 100644
--- a/.gitignore
+++ b/.gitignore
@@ -122,6 +122,9 @@ yaml-cpp.pc
/3rdparty/libusb_cmake/config.h
/3rdparty/libusb_cmake/libusb-1.0.pc
+# miniupnp
+/3rdparty/miniupnp/x64/*
+
# ssl certificate
cacert.pem
diff --git a/.gitmodules b/.gitmodules
index 0d6c707eb6..8c19376012 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -80,3 +80,6 @@
path = 3rdparty/libsdl-org/SDL
url = https://github.com/libsdl-org/SDL.git
ignore = dirty
+[submodule "3rdparty/miniupnp/miniupnp"]
+ path = 3rdparty/miniupnp/miniupnp
+ url = https://github.com/miniupnp/miniupnp.git
diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt
index 2ad07551f2..60e006e811 100644
--- a/3rdparty/CMakeLists.txt
+++ b/3rdparty/CMakeLists.txt
@@ -358,6 +358,9 @@ if(USE_SDL)
endif()
endif()
+# MINIUPNP
+add_subdirectory(miniupnp EXCLUDE_FROM_ALL)
+
# add nice ALIAS targets for ease of use
if(USE_SYSTEM_LIBUSB)
add_library(3rdparty::libusb ALIAS usb-1.0-shared)
@@ -385,3 +388,4 @@ add_library(3rdparty::wolfssl ALIAS wolfssl)
add_library(3rdparty::libcurl ALIAS libcurl)
add_library(3rdparty::soundtouch ALIAS soundtouch)
add_library(3rdparty::sdl2 ALIAS ${SDL2_TARGET})
+add_library(3rdparty::miniupnpc ALIAS libminiupnpc-static)
diff --git a/3rdparty/miniupnp/CMakeLists.txt b/3rdparty/miniupnp/CMakeLists.txt
new file mode 100644
index 0000000000..93c3dc55cd
--- /dev/null
+++ b/3rdparty/miniupnp/CMakeLists.txt
@@ -0,0 +1,8 @@
+option (UPNPC_BUILD_STATIC "Build static library" TRUE)
+option (UPNPC_BUILD_SHARED "Build shared library" FALSE)
+option (UPNPC_BUILD_TESTS "Build test executables" FALSE)
+option (UPNPC_BUILD_SAMPLE "Build sample executables" FALSE)
+option (NO_GETADDRINFO "Define NO_GETADDRINFO" FALSE)
+option (UPNPC_NO_INSTALL "Disable installation" TRUE)
+
+add_subdirectory(miniupnp/miniupnpc EXCLUDE_FROM_ALL)
diff --git a/3rdparty/miniupnp/miniupnp b/3rdparty/miniupnp/miniupnp
new file mode 160000
index 0000000000..f4a739d730
--- /dev/null
+++ b/3rdparty/miniupnp/miniupnp
@@ -0,0 +1 @@
+Subproject commit f4a739d73083bee207af30b8aa3e668383ee070e
diff --git a/3rdparty/miniupnp/miniupnpc_static.vcxproj b/3rdparty/miniupnp/miniupnpc_static.vcxproj
new file mode 100644
index 0000000000..f8b876794b
--- /dev/null
+++ b/3rdparty/miniupnp/miniupnpc_static.vcxproj
@@ -0,0 +1,138 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ Win32Proj
+ {5228f863-e0dd-4de7-aa7b-5c52b14cd4d0}
+ miniupnpcstatic
+
+
+
+
+
+ StaticLibrary
+ true
+ Unicode
+
+
+ StaticLibrary
+ false
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)lib\$(Configuration)-$(Platform)\
+
+
+ false
+ $(SolutionDir)lib\$(Configuration)-$(Platform)\
+
+
+
+ Level3
+ true
+ _WINSOCK_DEPRECATED_NO_WARNINGS; _CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ NotUsing
+ pch.h
+ generated;miniupnp\miniupnpc;miniupnp\miniupnpc\include
+ MultiThreadedDebug
+
+
+ true
+ Windows
+
+
+ cd $(ProjectDir)miniupnp\miniupnpc\msvc
+cscript genminiupnpcstrings.vbs
+
+
+
+
+ Level3
+ true
+ true
+ true
+ _WINSOCK_DEPRECATED_NO_WARNINGS; _CRT_SECURE_NO_WARNINGS;MINIUPNP_STATICLIB;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ NotUsing
+ pch.h
+ generated;miniupnp\miniupnpc;miniupnp\miniupnpc\include
+ MultiThreaded
+
+
+
+
+ true
+ true
+ true
+
+
+ cd $(ProjectDir)miniupnp\miniupnpc\msvc
+cscript genminiupnpcstrings.vbs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rpcs3.sln b/rpcs3.sln
index 2f88bdf168..5f0efc1b92 100644
--- a/rpcs3.sln
+++ b/rpcs3.sln
@@ -74,7 +74,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcurl", "3rdparty\curl\li
{73973223-5EE8-41CA-8E88-1D60E89A237B} = {73973223-5EE8-41CA-8E88-1D60E89A237B}
EndProjectSection
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPIRV", "3rdparty\SPIRV\spirv.vcxproj", "{4CBD3DDD-5555-49A4-A44D-DD3D8CB516A1}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spirv", "3rdparty\SPIRV\spirv.vcxproj", "{4CBD3DDD-5555-49A4-A44D-DD3D8CB516A1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3rdParty", "3rdParty", "{6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}"
EndProject
@@ -93,6 +93,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pine", "pine", "{A55DA1B5-C
3rdparty\pine\pine_server.h = 3rdparty\pine\pine_server.h
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc_static", "3rdparty\miniupnp\miniupnpc_static.vcxproj", "{5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -187,6 +189,10 @@ Global
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}.Debug|x64.Build.0 = Debug|x64
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}.Release|x64.ActiveCfg = Release|x64
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}.Release|x64.Build.0 = Release|x64
+ {5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0}.Debug|x64.ActiveCfg = Debug|x64
+ {5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0}.Debug|x64.Build.0 = Debug|x64
+ {5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0}.Release|x64.ActiveCfg = Release|x64
+ {5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -216,6 +222,7 @@ Global
{508C291A-3D18-49F5-B25D-F7C8DB92CB21} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{A55DA1B5-CC17-4525-BE7F-1659CE17BB56} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
+ {5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {06CC7920-E085-4B81-9582-8DE8AAD42510}
diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt
index 4c06529b4c..4c6b604acf 100644
--- a/rpcs3/Emu/CMakeLists.txt
+++ b/rpcs3/Emu/CMakeLists.txt
@@ -159,6 +159,10 @@ target_link_libraries(rpcs3_emu
PUBLIC
3rdparty::soundtouch)
+target_link_libraries(rpcs3_emu
+ PUBLIC
+ 3rdparty::miniupnpc)
+
# Cell
target_sources(rpcs3_emu PRIVATE
Cell/MFC.cpp
@@ -411,6 +415,8 @@ target_sources(rpcs3_emu PRIVATE
NP/np_structs_extra.cpp
NP/rpcn_client.cpp
NP/rpcn_config.cpp
+ NP/upnp_config.cpp
+ NP/upnp_handler.cpp
)
# Memory
diff --git a/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp b/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp
index 96b803e15a..f8957e8556 100644
--- a/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp
@@ -221,16 +221,15 @@ error_code cellNetCtlGetInfo(s32 code, vm::ptr info)
switch (code)
{
case CELL_NET_CTL_INFO_DEVICE: info->device = CELL_NET_CTL_DEVICE_WIRED; break;
- // case CELL_NET_CTL_INFO_ETHER_ADDR: std::memset(info->ether_addr.data, 0xFF, sizeof(info->ether_addr.data)); break;
case CELL_NET_CTL_INFO_MTU: info->mtu = 1500; break;
case CELL_NET_CTL_INFO_LINK: info->link = CELL_NET_CTL_LINK_CONNECTED; break;
- case CELL_NET_CTL_INFO_LINK_TYPE: info->link_type = CELL_NET_CTL_LINK_TYPE_10BASE_FULL; break;
+ case CELL_NET_CTL_INFO_LINK_TYPE: info->link_type = CELL_NET_CTL_LINK_TYPE_100BASE_FULL; break;
case CELL_NET_CTL_INFO_IP_CONFIG: info->ip_config = CELL_NET_CTL_IP_STATIC; break;
case CELL_NET_CTL_INFO_DEFAULT_ROUTE: strcpy_trunc(info->default_route, "192.168.1.1"); break;
case CELL_NET_CTL_INFO_PRIMARY_DNS: strcpy_trunc(info->primary_dns, np::ip_to_string(nph.get_dns_ip())); break;
case CELL_NET_CTL_INFO_SECONDARY_DNS: strcpy_trunc(info->secondary_dns, np::ip_to_string(nph.get_dns_ip())); break;
- case CELL_NET_CTL_INFO_IP_ADDRESS: strcpy_trunc(info->ip_address, np::ip_to_string(nph.get_public_ip_addr())); break;
- case CELL_NET_CTL_INFO_NETMASK: strcpy_trunc(info->netmask, "255.255.255.255"); break;
+ case CELL_NET_CTL_INFO_IP_ADDRESS: strcpy_trunc(info->ip_address, np::ip_to_string(nph.get_local_ip_addr())); break; // verified on HW
+ case CELL_NET_CTL_INFO_NETMASK: strcpy_trunc(info->netmask, "255.255.255.0"); break;
case CELL_NET_CTL_INFO_HTTP_PROXY_CONFIG: info->http_proxy_config = 0; break;
case CELL_NET_CTL_INFO_DHCP_HOSTNAME: strcpy_trunc(info->dhcp_hostname, nph.get_hostname()); break;
default: cellNetCtl.error("Unsupported request: %s", InfoCodeToName(code)); break;
@@ -348,7 +347,7 @@ error_code cellNetCtlGetNatInfo(vm::ptr natInfo)
natInfo->nat_type = CELL_NET_CTL_NATINFO_NAT_TYPE_2;
natInfo->stun_status = CELL_NET_CTL_NATINFO_STUN_OK;
- natInfo->upnp_status = CELL_NET_CTL_NATINFO_UPNP_NO;
+ natInfo->upnp_status = nph.get_upnp_status();
return CELL_OK;
}
diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp
index 4e9b509489..9ed16d56ac 100644
--- a/rpcs3/Emu/Cell/Modules/sceNp.cpp
+++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp
@@ -18,6 +18,7 @@
#include "Emu/Cell/lv2/sys_fs.h"
#include "Emu/NP/np_handler.h"
#include "Emu/NP/np_contexts.h"
+#include "Emu/NP/np_helpers.h"
#include "Emu/system_config.h"
LOG_CHANNEL(sceNp);
@@ -5237,11 +5238,11 @@ error_code sceNpSignalingActivateConnection(u32 ctx_id, vm::ptr npId, v
return SCE_NP_SIGNALING_ERROR_INVALID_ARGUMENT;
}
- if (strncmp(nph.get_npid().handle.data, npId->handle.data, 16) == 0)
+ if (np::is_same_npid(nph.get_npid(), *npId))
return SCE_NP_SIGNALING_ERROR_OWN_NP_ID;
auto& sigh = g_fxo->get>();
- *conn_id = sigh.init_sig_infos(npId.get_ptr());
+ *conn_id = sigh.init_sig1(*npId);
return CELL_OK;
}
@@ -5298,19 +5299,15 @@ error_code sceNpSignalingGetConnectionStatus(u32 ctx_id, u32 conn_id, vm::ptrconn_status;
if (peer_addr)
- (*peer_addr).np_s_addr = si.addr; // infos.addr is already BE
+ (*peer_addr).np_s_addr = si->addr; // infos.addr is already BE
if (peer_port)
- *peer_port = si.port;
+ *peer_port = si->port;
return CELL_OK;
}
@@ -5334,33 +5331,36 @@ error_code sceNpSignalingGetConnectionInfo(u32 ctx_id, u32 conn_id, s32 code, vm
auto& sigh = g_fxo->get>();
const auto si = sigh.get_sig_infos(conn_id);
+ if (!si)
+ return SCE_NP_SIGNALING_ERROR_CONN_NOT_FOUND;
+
switch (code)
{
case SCE_NP_SIGNALING_CONN_INFO_RTT:
{
- info->rtt = si.rtt;
+ info->rtt = si->rtt;
break;
}
case SCE_NP_SIGNALING_CONN_INFO_BANDWIDTH:
{
- info->bandwidth = 10'000'000; // 10 MBPS HACK
+ info->bandwidth = 100'000'000; // 100 MBPS HACK
break;
}
case SCE_NP_SIGNALING_CONN_INFO_PEER_NPID:
{
- info->npId = si.npid;
+ info->npId = si->npid;
break;
}
case SCE_NP_SIGNALING_CONN_INFO_PEER_ADDRESS:
{
- info->address.port = std::bit_cast>(si.port);
- info->address.addr.np_s_addr = si.addr;
+ info->address.port = std::bit_cast>(si->port);
+ info->address.addr.np_s_addr = si->addr;
break;
}
case SCE_NP_SIGNALING_CONN_INFO_MAPPED_ADDRESS:
{
- info->address.port = std::bit_cast>(si.mapped_port);
- info->address.addr.np_s_addr = si.mapped_addr;
+ info->address.port = std::bit_cast>(si->mapped_port);
+ info->address.addr.np_s_addr = si->mapped_addr;
break;
}
case SCE_NP_SIGNALING_CONN_INFO_PACKET_LOSS:
@@ -5393,8 +5393,13 @@ error_code sceNpSignalingGetConnectionFromNpId(u32 ctx_id, vm::ptr npId
return SCE_NP_SIGNALING_ERROR_INVALID_ARGUMENT;
}
+ if (np::is_same_npid(*npId, nph.get_npid()))
+ {
+ return SCE_NP_SIGNALING_ERROR_OWN_NP_ID;
+ }
+
auto& sigh = g_fxo->get>();
- const auto found_conn_id = sigh.get_conn_id_from_npid(npId.get_ptr());
+ const auto found_conn_id = sigh.get_conn_id_from_npid(*npId);
if (!found_conn_id)
{
@@ -5455,9 +5460,9 @@ error_code sceNpSignalingGetLocalNetInfo(u32 ctx_id, vm::ptrmapped_addr = nph.get_public_ip_addr();
// Pure speculation below
- info->nat_status = 0;
- info->upnp_status = 0;
- info->npport_status = 0;
+ info->nat_status = SCE_NP_SIGNALING_NETINFO_NAT_STATUS_TYPE2;
+ info->upnp_status = nph.get_upnp_status();
+ info->npport_status = SCE_NP_SIGNALING_NETINFO_NPPORT_STATUS_OPEN;
info->npport = SCE_NP_PORT;
return CELL_OK;
@@ -5537,25 +5542,8 @@ error_code sceNpUtilCmpNpId(vm::ptr id1, vm::ptr id2)
return SCE_NP_UTIL_ERROR_INVALID_ARGUMENT;
}
- // Unknown what this constant means
- // if (id1->reserved[0] != 1 || id2->reserved[0] != 1)
- // {
- // return SCE_NP_UTIL_ERROR_INVALID_NP_ID;
- // }
-
- if (strncmp(id1->handle.data, id2->handle.data, 16))// || id1->unk1[0] != id2->unk1[0])
- {
+ if (!np::is_same_npid(*id1, *id2))
return not_an_error(SCE_NP_UTIL_ERROR_NOT_MATCH);
- }
-
- // if (id1->unk1[1] != id2->unk1[1])
- // {
- // // If either is zero they match
- // if (id1->opt[4] && id2->opt[4])
- // {
- // return SCE_NP_UTIL_ERROR_NOT_MATCH;
- // }
- // }
return CELL_OK;
}
diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.cpp b/rpcs3/Emu/Cell/Modules/sceNp2.cpp
index b4f9923bbe..91c62e7290 100644
--- a/rpcs3/Emu/Cell/Modules/sceNp2.cpp
+++ b/rpcs3/Emu/Cell/Modules/sceNp2.cpp
@@ -6,6 +6,7 @@
#include "sceNp2.h"
#include "Emu/NP/np_handler.h"
#include "Emu/NP/np_contexts.h"
+#include "Emu/NP/np_helpers.h"
#include "cellSysutil.h"
LOG_CHANNEL(sceNp2);
@@ -444,20 +445,35 @@ error_code sceNpMatching2SignalingGetConnectionStatus(
return SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT;
}
+ auto [res, npid] = nph.local_get_npid(roomId, memberId);
+
+ if (res)
+ return res;
+
+ if (np::is_same_npid(nph.get_npid(), *npid))
+ return SCE_NP_SIGNALING_ERROR_OWN_NP_ID;
+
auto& sigh = g_fxo->get>();
- const auto si = sigh.get_sig2_infos(roomId, memberId);
+ auto conn_id = sigh.get_conn_id_from_npid(*npid);
+ if (!conn_id)
+ return SCE_NP_SIGNALING_ERROR_CONN_NOT_FOUND;
- *connStatus = si.connStatus;
+ const auto si = sigh.get_sig_infos(*conn_id);
+
+ if (!si)
+ return SCE_NP_SIGNALING_ERROR_CONN_NOT_FOUND;
+
+ *connStatus = si->conn_status;
if (peerAddr)
{
- (*peerAddr).np_s_addr = si.addr; // infos.addr is already BE
+ (*peerAddr).np_s_addr = si->addr; // infos.addr is already BE
}
if (peerPort)
{
- *peerPort = si.port;
+ *peerPort = si->port;
}
return CELL_OK;
@@ -616,42 +632,58 @@ error_code sceNpMatching2SignalingGetConnectionInfo(
return SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT;
}
+ auto [res, npid] = nph.local_get_npid(roomId, memberId);
+
+ if (res)
+ return res;
+
+ if (np::is_same_npid(nph.get_npid(), *npid))
+ return SCE_NP_SIGNALING_ERROR_OWN_NP_ID;
+
auto& sigh = g_fxo->get>();
- const auto si = sigh.get_sig2_infos(roomId, memberId);
+
+ auto conn_id = sigh.get_conn_id_from_npid(*npid);
+ if (!conn_id)
+ return SCE_NP_SIGNALING_ERROR_CONN_NOT_FOUND;
+
+ const auto si = sigh.get_sig_infos(*conn_id);
+
+ if (!si)
+ return SCE_NP_SIGNALING_ERROR_CONN_NOT_FOUND;
switch (code)
{
case SCE_NP_SIGNALING_CONN_INFO_RTT:
{
- connInfo->rtt = si.rtt;
+ connInfo->rtt = si->rtt;
sceNp2.warning("Returning a RTT of %d microseconds", connInfo->rtt);
break;
}
case SCE_NP_SIGNALING_CONN_INFO_BANDWIDTH:
{
- connInfo->bandwidth = 10'000'000; // 10 MBPS HACK
+ connInfo->bandwidth = 100'000'000; // 100 MBPS HACK
break;
}
case SCE_NP_SIGNALING_CONN_INFO_PEER_NPID:
{
- connInfo->npId = si.npid;
+ connInfo->npId = si->npid;
break;
}
case SCE_NP_SIGNALING_CONN_INFO_PEER_ADDRESS:
{
- connInfo->address.port = std::bit_cast>(si.port);
- connInfo->address.addr.np_s_addr = si.addr;
+ connInfo->address.port = std::bit_cast>(si->port);
+ connInfo->address.addr.np_s_addr = si->addr;
break;
}
case SCE_NP_SIGNALING_CONN_INFO_MAPPED_ADDRESS:
{
- connInfo->address.port = std::bit_cast>(si.mapped_port);
- connInfo->address.addr.np_s_addr = si.mapped_addr;
+ connInfo->address.port = std::bit_cast>(si->mapped_port);
+ connInfo->address.addr.np_s_addr = si->mapped_addr;
break;
}
case SCE_NP_SIGNALING_CONN_INFO_PACKET_LOSS:
{
- connInfo->packet_loss = 1; // HACK
+ connInfo->packet_loss = 0; // HACK
break;
}
default:
@@ -709,7 +741,7 @@ error_code sceNpMatching2GetRoomMemberDataExternalList(SceNpMatching2ContextId c
error_code sceNpMatching2AbortRequest(SceNpMatching2ContextId ctxId, SceNpMatching2RequestId reqId)
{
- sceNp2.todo("sceNpMatching2AbortRequest(ctxId=%d, reqId=%d)", ctxId, reqId);
+ sceNp2.warning("sceNpMatching2AbortRequest(ctxId=%d, reqId=%d)", ctxId, reqId);
auto& nph = g_fxo->get>();
@@ -728,6 +760,9 @@ error_code sceNpMatching2AbortRequest(SceNpMatching2ContextId ctxId, SceNpMatchi
return SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND;
}
+ if (!nph.abort_request(reqId))
+ return SCE_NP_MATCHING2_ERROR_REQUEST_NOT_FOUND;
+
return CELL_OK;
}
@@ -1591,7 +1626,7 @@ error_code sceNpMatching2SignalingCancelPeerNetInfo(SceNpMatching2ContextId ctxI
error_code sceNpMatching2SignalingGetLocalNetInfo(vm::ptr netinfo)
{
- sceNp2.todo("sceNpMatching2SignalingGetLocalNetInfo(netinfo=*0x%x)", netinfo);
+ sceNp2.warning("sceNpMatching2SignalingGetLocalNetInfo(netinfo=*0x%x)", netinfo);
auto& nph = g_fxo->get>();
@@ -1600,12 +1635,17 @@ error_code sceNpMatching2SignalingGetLocalNetInfo(vm::ptrsize != sizeof(SceNpMatching2SignalingNetInfo))
{
- // TODO: check netinfo->size
return SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT;
}
+ netinfo->localAddr = nph.get_local_ip_addr();
+ netinfo->mappedAddr = nph.get_public_ip_addr();
+
+ // Pure speculation below
+ netinfo->natStatus = SCE_NP_SIGNALING_NETINFO_NAT_STATUS_TYPE2;
+
return CELL_OK;
}
@@ -1639,9 +1679,8 @@ error_code sceNpMatching2SignalingGetPeerNetInfoResult(SceNpMatching2ContextId c
return SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED;
}
- if (!netinfo)
+ if (!netinfo || netinfo->size != sizeof(SceNpMatching2SignalingNetInfo))
{
- // TODO: check netinfo->size
return SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT;
}
diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.h b/rpcs3/Emu/Cell/Modules/sceNp2.h
index 73c91827e2..711f050274 100644
--- a/rpcs3/Emu/Cell/Modules/sceNp2.h
+++ b/rpcs3/Emu/Cell/Modules/sceNp2.h
@@ -1555,9 +1555,9 @@ struct SceNpMatching2CbQueueInfo
u8 reserved[12];
};
-union SceNpMatching2SignalingNetInfo // TODO check values
+struct SceNpMatching2SignalingNetInfo
{
- be_t size;
+ be_t size;
be_t localAddr;
be_t mappedAddr;
be_t natStatus;
diff --git a/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp b/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp
index e4ace7fbbe..b26d604a25 100644
--- a/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp
+++ b/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp
@@ -39,8 +39,8 @@ struct bandwidth_test
}
}
- test_result.upload_bps = 16000.0;
- test_result.download_bps = 16000.0;
+ test_result.upload_bps = 100'000'000.0;
+ test_result.download_bps = 100'000'000.0;
test_result.result = CELL_OK;
status = SCE_NP_UTIL_BANDWIDTH_TEST_STATUS_FINISHED;
finished = true;
diff --git a/rpcs3/Emu/Cell/lv2/sys_net.cpp b/rpcs3/Emu/Cell/lv2/sys_net.cpp
index 653f2bee81..641bd5c1da 100644
--- a/rpcs3/Emu/Cell/lv2/sys_net.cpp
+++ b/rpcs3/Emu/Cell/lv2/sys_net.cpp
@@ -1769,7 +1769,7 @@ error_code sys_net_abort(ppu_thread& ppu, s32 type, u64 arg, s32 flags)
{
ppu.state += cpu_flag::wait;
- sys_net.todo("sys_net_abort(type=%d, arg=0x%x, flags=0x%x)", type, arg, flags);
+ sys_net.warning("sys_net_abort(type=%d, arg=0x%x, flags=0x%x)", type, arg, flags);
enum abort_type : s32
{
diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp
index 03ace40252..cc800a1633 100644
--- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp
+++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp
@@ -50,6 +50,13 @@ lv2_socket_native::~lv2_socket_native()
::close(socket);
#endif
}
+
+ if (bound_port)
+ {
+ auto& nph = g_fxo->get>();
+ nph.upnp_remove_port_mapping(bound_port, type == SYS_NET_SOCK_STREAM ? "TCP" : "UDP");
+ bound_port = 0;
+ }
}
s32 lv2_socket_native::create_socket()
@@ -143,10 +150,36 @@ s32 lv2_socket_native::bind(const sys_net_sockaddr& addr)
native_addr.sin_addr.s_addr = saddr;
::socklen_t native_addr_len = sizeof(native_addr);
+ // Note that this is a hack(TODO)
+ // ATM we don't support binding 3658 udp because we use it for the p2ps main socket
+ // Only Fat Princess is known to do this to my knowledge
+ if (psa_in->sin_port == 3658 && type == SYS_NET_SOCK_DGRAM)
+ {
+ native_addr.sin_port = std::bit_cast>(3659);
+ }
+
sys_net.warning("[Native] Trying to bind %s:%d", native_addr.sin_addr, std::bit_cast, u16>(native_addr.sin_port));
if (::bind(socket, reinterpret_cast(&native_addr), native_addr_len) == 0)
{
+ // Only UPNP port forward binds to 0.0.0.0
+ if (saddr == 0)
+ {
+ if (native_addr.sin_port == 0)
+ {
+ sockaddr_in client_addr;
+ socklen_t client_addr_size = sizeof(client_addr);
+ ensure(::getsockname(socket, reinterpret_cast(&client_addr), &client_addr_size) == 0);
+ bound_port = std::bit_cast>(client_addr.sin_port);
+ }
+ else
+ {
+ bound_port = std::bit_cast>(native_addr.sin_port);
+ }
+
+ nph.upnp_add_port_mapping(bound_port, type == SYS_NET_SOCK_STREAM ? "TCP" : "UDP");
+ }
+
last_bound_addr = addr;
return CELL_OK;
}
@@ -1011,6 +1044,13 @@ void lv2_socket_native::close()
auto& dnshook = g_fxo->get();
dnshook.remove_dns_spy(lv2_id);
+
+ if (bound_port)
+ {
+ auto& nph = g_fxo->get>();
+ nph.upnp_remove_port_mapping(bound_port, type == SYS_NET_SOCK_STREAM ? "TCP" : "UDP");
+ bound_port = 0;
+ }
}
s32 lv2_socket_native::shutdown(s32 how)
diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h
index 0fce833bea..f6b221b97d 100644
--- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h
+++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h
@@ -68,4 +68,5 @@ private:
s32 so_reuseaddr = 0;
s32 so_reuseport = 0;
#endif
+ u16 bound_port = 0;
};
diff --git a/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp b/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp
index cf04c3216f..984ac20dfb 100644
--- a/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp
+++ b/rpcs3/Emu/Cell/lv2/sys_net/network_context.cpp
@@ -83,14 +83,10 @@ void need_network()
initialize_tcp_timeout_monitor();
}
-network_thread::network_thread() noexcept
-{
- if (g_cfg.net.psn_status == np_psn_status::psn_rpcn)
- list_p2p_ports.emplace(std::piecewise_construct, std::forward_as_tuple(SCE_NP_PORT), std::forward_as_tuple(SCE_NP_PORT));
-}
-
-network_thread::~network_thread()
+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()()
diff --git a/rpcs3/Emu/Cell/lv2/sys_net/network_context.h b/rpcs3/Emu/Cell/lv2/sys_net/network_context.h
index 75897ed52e..accdcee027 100644
--- a/rpcs3/Emu/Cell/lv2/sys_net/network_context.h
+++ b/rpcs3/Emu/Cell/lv2/sys_net/network_context.h
@@ -17,10 +17,7 @@ struct network_thread
static constexpr auto thread_name = "Network Thread";
- network_thread() noexcept;
-
- ~network_thread();
-
+ void bind_sce_np_port();
void operator()();
};
diff --git a/rpcs3/Emu/Cell/lv2/sys_net/nt_p2p_port.cpp b/rpcs3/Emu/Cell/lv2/sys_net/nt_p2p_port.cpp
index d63d01fbab..1bcc4ca1a2 100644
--- a/rpcs3/Emu/Cell/lv2/sys_net/nt_p2p_port.cpp
+++ b/rpcs3/Emu/Cell/lv2/sys_net/nt_p2p_port.cpp
@@ -10,6 +10,7 @@
#include "Emu/NP/signaling_handler.h"
#include "sys_net_helpers.h"
#include "Emu/NP/vport0.h"
+#include "Emu/NP/np_handler.h"
LOG_CHANNEL(sys_net);
@@ -69,6 +70,9 @@ nt_p2p_port::nt_p2p_port(u16 port)
if (ret_bind == -1)
fmt::throw_exception("Failed to bind DGRAM socket to %d for P2P: %s!", port, get_last_error(true));
+ auto& nph = g_fxo->get>();
+ nph.upnp_add_port_mapping(port, "UDP");
+
sys_net.notice("P2P port %d was bound!", port);
}
@@ -82,6 +86,9 @@ nt_p2p_port::~nt_p2p_port()
::close(p2p_socket);
#endif
}
+
+ auto& nph = g_fxo->get>();
+ nph.upnp_remove_port_mapping(port, "UDP");
}
void nt_p2p_port::dump_packet(p2ps_encapsulated_tcp* tcph)
diff --git a/rpcs3/Emu/NP/np_cache.cpp b/rpcs3/Emu/NP/np_cache.cpp
index accbbc118f..743147feb6 100644
--- a/rpcs3/Emu/NP/np_cache.cpp
+++ b/rpcs3/Emu/NP/np_cache.cpp
@@ -3,6 +3,9 @@
#include "Emu/NP/np_allocator.h"
#include "Emu/NP/np_cache.h"
+#include "Emu/NP/np_helpers.h"
+
+LOG_CHANNEL(np_cache);
namespace np
{
@@ -80,20 +83,32 @@ namespace np
rooms[sce_roomdata->roomId].update(sce_roomdata);
}
- void cache_manager::add_member(SceNpMatching2RoomId room_id, const SceNpMatching2RoomMemberDataInternal* sce_roommemberdata)
+ bool cache_manager::add_member(SceNpMatching2RoomId room_id, const SceNpMatching2RoomMemberDataInternal* sce_roommemberdata)
{
std::lock_guard lock(mutex);
- ensure(rooms.contains(room_id), "cache_manager::add_member: Room not cached!");
+ if (!rooms.contains(room_id))
+ {
+ np_cache.error("np_cache::add_member cache miss: room_id(%d)", room_id);
+ return false;
+ }
+
rooms[room_id].members.insert_or_assign(sce_roommemberdata->memberId, member_cache(sce_roommemberdata));
+ return true;
}
- void cache_manager::del_member(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id)
+ bool cache_manager::del_member(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id)
{
std::lock_guard lock(mutex);
- ensure(rooms.contains(room_id), "cache_manager::del_member: Room not cached!");
+ if (!rooms.contains(room_id))
+ {
+ np_cache.error("np_cache::del_member cache miss: room_id(%d)/member_id(%d)", room_id, member_id);
+ return false;
+ }
+
rooms.erase(member_id);
+ return true;
}
void cache_manager::update_password(SceNpMatching2RoomId room_id, const std::optional& password)
@@ -121,7 +136,7 @@ namespace np
SceNpMatching2RoomJoinedSlotMask join_mask = 0;
for (const auto& member : room.members)
{
- join_mask |= (1 << (member.first - 1));
+ join_mask |= (1 << ((member.first >> 4) - 1));
}
slots.joinedSlotMask = join_mask;
slots.passwordSlotMask = room.mask_password;
@@ -307,14 +322,45 @@ namespace np
return needed_data_size;
}
- SceNpId cache_manager::get_npid(u64 room_id, u16 member_id)
+ std::pair> cache_manager::get_npid(u64 room_id, u16 member_id)
{
std::lock_guard lock(mutex);
- ensure(rooms.contains(room_id), "cache_manager::get_npid: Room not cached!");
- ensure(::at32(rooms, room_id).members.contains(member_id), "cache_manager::get_npid: Member not cached!");
+ if (!rooms.contains(room_id))
+ {
+ np_cache.error("np_cache::get_npid cache miss room_id: room_id(%d)/member_id(%d)", room_id, member_id);
+ return {SCE_NP_MATCHING2_ERROR_INVALID_ROOM_ID, std::nullopt};
+ }
- return ::at32(::at32(rooms, room_id).members, member_id).userInfo.npId;
+ if (!::at32(rooms, room_id).members.contains(member_id))
+ {
+ np_cache.error("np_cache::get_npid cache miss member_id: room_id(%d)/member_id(%d)", room_id, member_id);
+ return {SCE_NP_MATCHING2_ERROR_INVALID_MEMBER_ID, std::nullopt};
+ }
+
+ return {CELL_OK, ::at32(::at32(rooms, room_id).members, member_id).userInfo.npId};
+ }
+
+ std::optional cache_manager::get_memberid(u64 room_id, const SceNpId& npid)
+ {
+ std::lock_guard lock(mutex);
+
+ if (!rooms.contains(room_id))
+ {
+ np_cache.error("np_cache::get_memberid cache miss room_id: room_id(%d)/npid(%s)", room_id, static_cast(npid.handle.data));
+ return std::nullopt;
+ }
+
+ const auto& members = ::at32(rooms, room_id).members;
+
+ for (const auto& [id, member_cache] : members)
+ {
+ if (np::is_same_npid(member_cache.userInfo.npId, npid))
+ return id;
+ }
+
+ np_cache.error("np_cache::get_memberid cache miss member_id: room_id(%d)/npid(%s)", room_id, static_cast(npid.handle.data));
+ return std::nullopt;
}
} // namespace np
diff --git a/rpcs3/Emu/NP/np_cache.h b/rpcs3/Emu/NP/np_cache.h
index 7d66bf3067..976c3b5838 100644
--- a/rpcs3/Emu/NP/np_cache.h
+++ b/rpcs3/Emu/NP/np_cache.h
@@ -67,15 +67,16 @@ namespace np
cache_manager() = default;
void insert_room(const SceNpMatching2RoomDataInternal* sce_roomdata);
- void add_member(SceNpMatching2RoomId room_id, const SceNpMatching2RoomMemberDataInternal* sce_roommemberdata);
- void del_member(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id);
+ bool add_member(SceNpMatching2RoomId room_id, const SceNpMatching2RoomMemberDataInternal* sce_roommemberdata);
+ bool del_member(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id);
void update_password(SceNpMatching2RoomId room_id, const std::optional& password);
std::pair> get_slots(SceNpMatching2RoomId room_id);
std::pair> get_memberids(u64 room_id, s32 sort_method);
std::pair> get_password(SceNpMatching2RoomId room_id);
error_code get_member_and_attrs(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id, const std::vector& binattrs_list, SceNpMatching2RoomMemberDataInternal* ptr_member, u32 addr_data, u32 size_data);
- SceNpId get_npid(u64 room_id, u16 member_id);
+ std::pair> get_npid(u64 room_id, u16 member_id);
+ std::optional get_memberid(u64 room_id, const SceNpId& npid);
private:
shared_mutex mutex;
diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp
index 8d2353c31a..900899ece1 100644
--- a/rpcs3/Emu/NP/np_handler.cpp
+++ b/rpcs3/Emu/NP/np_handler.cpp
@@ -6,7 +6,6 @@
#include "Emu/Cell/Modules/sceNp2.h"
#include "Emu/Cell/Modules/cellNetCtl.h"
#include "Utilities/StrUtil.h"
-#include "Emu/Cell/Modules/cellSysutil.h"
#include "Emu/IdManager.h"
#include "Emu/NP/np_structs_extra.h"
#include "Emu/System.h"
@@ -14,6 +13,8 @@
#include "Emu/NP/np_contexts.h"
#include "Emu/NP/np_helpers.h"
#include "Emu/RSX/Overlays/overlay_message.h"
+#include "Emu/Cell/lv2/sys_net/network_context.h"
+#include "Emu/Cell/lv2/sys_net/sys_net_helpers.h"
#ifdef _WIN32
#include
@@ -342,21 +343,18 @@ namespace np
{
g_fxo->need>();
- std::lock_guard lock(mutex_rpcn);
- rpcn = rpcn::rpcn_client::get_instance();
-
is_connected = (g_cfg.net.net_active == np_internet_status::enabled);
- is_psn_active = (g_cfg.net.psn_status >= np_psn_status::psn_fake);
+ is_psn_active = (g_cfg.net.psn_status >= np_psn_status::psn_fake) && is_connected;
if (get_net_status() == CELL_NET_CTL_STATE_IPObtained)
{
- discover_ip_address();
- if (!discover_ether_address())
+ if (!discover_ether_address() || !discover_ip_address())
{
- nph_log.error("Failed to discover ethernet address!");
+ nph_log.error("Failed to discover ethernet or ip address!");
is_connected = false;
is_psn_active = false;
+ return;
}
// Convert dns address
@@ -383,6 +381,19 @@ namespace np
{
bind_ip = conv.s_addr;
}
+
+ if (g_cfg.net.upnp_enabled)
+ upnp.upnp_enable();
+ }
+
+ if (is_psn_active && g_cfg.net.psn_status == np_psn_status::psn_rpcn)
+ {
+ g_fxo->need();
+ auto& nc = g_fxo->get();
+ nc.bind_sce_np_port();
+
+ std::lock_guard lock(mutex_rpcn);
+ rpcn = rpcn::rpcn_client::get_instance();
}
}
@@ -449,46 +460,45 @@ namespace np
ar(m_pool, m_size, m_allocs, m_avail);
}
- void np_handler::discover_ip_address()
+ bool np_handler::discover_ip_address()
{
- hostname.clear();
- hostname.resize(1024);
+ auto sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- const auto use_default_ip_addr = [this](const std::string_view error_msg)
+ auto close_socket = [&]()
{
- nph_log.error("discover_ip_address: %s", error_msg);
- nph_log.error("discover_ip_address: Defaulting to 127.0.0.1!");
- local_ip_addr = 0x0100007f;
- public_ip_addr = local_ip_addr;
+#ifdef _WIN32
+ closesocket(sockfd);
+#else
+ close(sockfd);
+#endif
};
- if (gethostname(hostname.data(), hostname.size()) == -1)
+ ::sockaddr_in addr;
+ std::memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = 53;
+ addr.sin_addr.s_addr = 0x08080808;
+ if (connect(sockfd, reinterpret_cast(&addr), sizeof(addr)) != 0)
{
- use_default_ip_addr("gethostname failed!");
- return;
+ // If connect fails a route to the internet is not available
+ nph_log.error("connect to discover local ip failed: %d", get_native_error());
+ close_socket();
+ return false; // offline
}
- // nph_log.notice("discover_ip_address: Hostname was determined to be %s", hostname.c_str());
-
- hostent* host = gethostbyname(hostname.data());
- if (!host)
+ sockaddr_in client_addr;
+ socklen_t client_addr_size = sizeof(client_addr);
+ if (getsockname(sockfd, reinterpret_cast(&client_addr), &client_addr_size) != 0)
{
- use_default_ip_addr("gethostbyname failed!");
- return;
+ rpcn_log.error("getsockname to discover local ip failed: %d", get_native_error());
+ close_socket();
+ return true; // still assume online
}
- if (host->h_addrtype != AF_INET)
- {
- use_default_ip_addr("Could only find IPv6 addresses for current host!");
- return;
- }
-
- local_ip_addr = read_from_ptr(host->h_addr_list[0]);
-
- // Set public address to local discovered address for now, may be updated later from RPCN socket
- public_ip_addr = local_ip_addr;
-
- // nph_log.notice("discover_ip_address: IP was determined to be %s", ip_to_string(local_ip_addr));
+ local_ip_addr = client_addr.sin_addr.s_addr;
+ nph_log.trace("discover_ip_address: IP was determined to be %s", ip_to_string(local_ip_addr));
+ close_socket();
+ return true;
}
bool np_handler::discover_ether_address()
@@ -612,6 +622,14 @@ namespace np
return is_psn_active ? SCE_NP_MANAGER_STATUS_ONLINE : SCE_NP_MANAGER_STATUS_OFFLINE;
}
+ s32 np_handler::get_upnp_status() const
+ {
+ if (upnp.is_active())
+ return SCE_NP_SIGNALING_NETINFO_UPNP_STATUS_VALID;
+
+ return SCE_NP_SIGNALING_NETINFO_UPNP_STATUS_INVALID;
+ }
+
const SceNpId& np_handler::get_npid() const
{
return npid;
@@ -649,7 +667,7 @@ namespace np
std::string s_npid = g_cfg_rpcn.get_npid();
ensure(!s_npid.empty()); // It should have been generated before this
- string_to_npid(s_npid, &npid);
+ string_to_npid(s_npid, npid);
auto& sigh = g_fxo->get>();
sigh.set_self_sig_info(npid);
}
@@ -660,8 +678,8 @@ namespace np
break;
case np_psn_status::psn_fake:
{
- string_to_online_name("RPCS3's user", &online_name);
- string_to_avatar_url("https://rpcs3.net/cdn/netplay/DefaultAvatar.png", &avatar_url);
+ string_to_online_name("RPCS3's user", online_name);
+ string_to_avatar_url("https://rpcs3.net/cdn/netplay/DefaultAvatar.png", avatar_url);
break;
}
case np_psn_status::psn_rpcn:
@@ -692,8 +710,8 @@ namespace np
rsx::overlays::queue_message(localized_string_id::RPCN_SUCCESS_LOGGED_ON);
- string_to_online_name(rpcn->get_online_name(), &online_name);
- string_to_avatar_url(rpcn->get_avatar_url(), &avatar_url);
+ string_to_online_name(rpcn->get_online_name(), online_name);
+ string_to_avatar_url(rpcn->get_avatar_url(), avatar_url);
public_ip_addr = rpcn->get_addr_sig();
local_ip_addr = std::bit_cast>(rpcn->get_addr_local());
@@ -930,7 +948,7 @@ namespace np
return false;
}
- u32 np_handler::generate_callback_info(SceNpMatching2ContextId ctx_id, vm::cptr optParam)
+ u32 np_handler::generate_callback_info(SceNpMatching2ContextId ctx_id, vm::cptr optParam, SceNpMatching2Event event_type)
{
callback_info ret;
@@ -942,6 +960,7 @@ namespace np
ret.ctx_id = ctx_id;
ret.cb_arg = (optParam && optParam->cbFuncArg) ? optParam->cbFuncArg : ctx->default_match2_optparam.cbFuncArg;
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);
@@ -953,16 +972,31 @@ namespace np
return req_id;
}
- np_handler::callback_info np_handler::take_pending_request(u32 req_id)
+ std::optional np_handler::take_pending_request(u32 req_id)
{
std::lock_guard lock(mutex_pending_requests);
+ if (!pending_requests.contains(req_id))
+ return std::nullopt;
+
const auto cb_info = std::move(::at32(pending_requests, req_id));
pending_requests.erase(req_id);
return cb_info;
}
+ bool np_handler::abort_request(u32 req_id)
+ {
+ auto cb_info_opt = take_pending_request(req_id);
+
+ if (!cb_info_opt)
+ return false;
+
+ cb_info_opt->queue_callback(req_id, 0, SCE_NP_MATCHING2_ERROR_ABORTED, 0);
+
+ return true;
+ }
+
event_data& np_handler::allocate_req_result(u32 event_key, u32 max_size, u32 initial_size)
{
std::lock_guard lock(mutex_match2_req_results);
@@ -974,14 +1008,14 @@ namespace np
{
const u32 req_id = get_req_id(0);
- // if (basic_handler)
- // {
- // sysutil_register_cb([basic_handler = this->basic_handler, req_id, basic_handler_arg = this->basic_handler_arg](ppu_thread& cb_ppu) -> s32
- // {
- // basic_handler(cb_ppu, SCE_NP_BASIC_EVENT_ADD_PLAYERS_HISTORY_RESULT, 0, req_id, basic_handler_arg);
- // return 0;
- // });
- // }
+ if (basic_handler.handler_func)
+ {
+ sysutil_register_cb([req_id, cb = basic_handler.handler_func, cb_arg = basic_handler.handler_arg](ppu_thread& cb_ppu) -> s32
+ {
+ cb(cb_ppu, SCE_NP_BASIC_EVENT_ADD_PLAYERS_HISTORY_RESULT, 0, req_id, cb_arg);
+ return 0;
+ });
+ }
return req_id;
}
@@ -1006,11 +1040,16 @@ namespace np
}
SceNpId npid_friend;
- string_to_npid(str_friend.value(), &npid_friend);
+ string_to_npid(str_friend.value(), npid_friend);
return {CELL_OK, npid_friend};
}
+ std::pair> np_handler::local_get_npid(u64 room_id, u16 member_id)
+ {
+ return np_cache.get_npid(room_id, member_id);
+ }
+
std::pair> np_handler::local_get_room_password(SceNpMatching2RoomId room_id)
{
return np_cache.get_password(room_id);
@@ -1030,4 +1069,14 @@ namespace np
{
return np_cache.get_member_and_attrs(room_id, member_id, binattrs_list, ptr_member, addr_data, size_data);
}
+
+ void np_handler::upnp_add_port_mapping(u16 internal_port, std::string_view protocol)
+ {
+ upnp.add_port_redir(np::ip_to_string(get_local_ip_addr()), internal_port, protocol);
+ }
+
+ void np_handler::upnp_remove_port_mapping(u16 internal_port, std::string_view protocol)
+ {
+ upnp.remove_port_redir(internal_port, protocol);
+ }
} // namespace np
diff --git a/rpcs3/Emu/NP/np_handler.h b/rpcs3/Emu/NP/np_handler.h
index c26125e607..98456b8cf4 100644
--- a/rpcs3/Emu/NP/np_handler.h
+++ b/rpcs3/Emu/NP/np_handler.h
@@ -7,6 +7,7 @@
#include "Emu/Memory/vm_ptr.h"
#include "Emu/Cell/Modules/sceNp.h"
#include "Emu/Cell/Modules/sceNp2.h"
+#include "Emu/Cell/Modules/cellSysutil.h"
#include "Emu/NP/rpcn_client.h"
#include "Emu/NP/generated/np2_structs_generated.h"
@@ -15,6 +16,7 @@
#include "Emu/NP/np_cache.h"
#include "Emu/NP/np_event_data.h"
#include "Emu/NP/np_contexts.h"
+#include "Emu/NP/upnp_handler.h"
namespace np
{
@@ -83,6 +85,7 @@ namespace np
s32 get_psn_status() const;
s32 get_net_status() const;
+ s32 get_upnp_status() const;
const SceNpId& get_npid() const;
const SceNpOnlineId& get_online_id() const;
@@ -165,6 +168,7 @@ namespace np
void get_score_friend(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, bool include_self, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async);
// Local functions
+ std::pair> local_get_npid(u64 room_id, u16 member_id);
std::pair> local_get_room_slots(SceNpMatching2RoomId room_id);
std::pair> local_get_room_password(SceNpMatching2RoomId room_id);
std::pair> local_get_room_memberids(SceNpMatching2RoomId room_id, s32 sort_method);
@@ -179,10 +183,15 @@ namespace np
void req_ticket(u32 version, const SceNpId* npid, const char* service_id, const u8* cookie, u32 cookie_size, const char* entitlement_id, u32 consumed_count);
const ticket& get_ticket() const;
u32 add_players_to_history(vm::cptr npids, u32 count);
+ bool abort_request(u32 req_id);
// For signaling
void req_sign_infos(const std::string& npid, u32 conn_id);
+ // For UPNP
+ void upnp_add_port_mapping(u16 internal_port, std::string_view protocol);
+ void upnp_remove_port_mapping(u16 internal_port, std::string_view protocol);
+
// For custom menu
struct custom_menu_action
{
@@ -205,7 +214,7 @@ namespace np
private:
// Various generic helpers
- void discover_ip_address();
+ bool discover_ip_address();
bool discover_ether_address();
bool error_and_disconnect(const std::string& error_msg);
@@ -267,9 +276,23 @@ namespace np
SceNpMatching2ContextId ctx_id;
vm::ptr cb;
vm::ptr cb_arg;
+ SceNpMatching2Event event_type;
+
+ void queue_callback(u32 req_id, u32 event_key, s32 error_code, u32 data_size) const
+ {
+ if (cb)
+ {
+ sysutil_register_cb([=, *this](ppu_thread& cb_ppu) -> s32
+ {
+ cb(cb_ppu, ctx_id, req_id, event_type, event_key, error_code, data_size, cb_arg);
+ return 0;
+ });
+ }
+ }
};
- u32 generate_callback_info(SceNpMatching2ContextId ctx_id, vm::cptr optParam);
- callback_info take_pending_request(u32 req_id);
+
+ u32 generate_callback_info(SceNpMatching2ContextId ctx_id, vm::cptr optParam, SceNpMatching2Event event_type);
+ std::optional take_pending_request(u32 req_id);
shared_mutex mutex_pending_requests;
std::unordered_map pending_requests;
@@ -327,5 +350,8 @@ namespace np
// RPCN
shared_mutex mutex_rpcn;
std::shared_ptr rpcn;
+
+ // UPNP
+ upnp_handler upnp;
};
} // namespace np
diff --git a/rpcs3/Emu/NP/np_helpers.cpp b/rpcs3/Emu/NP/np_helpers.cpp
index dc06bdb09a..3bd3af7c38 100644
--- a/rpcs3/Emu/NP/np_helpers.cpp
+++ b/rpcs3/Emu/NP/np_helpers.cpp
@@ -22,25 +22,65 @@ namespace np
return fmt::format("%02X:%02X:%02X:%02X:%02X:%02X", ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
}
- void string_to_npid(std::string_view str, SceNpId* npid)
+ void string_to_npid(std::string_view str, SceNpId& npid)
{
- memset(npid, 0, sizeof(SceNpId));
- strcpy_trunc(npid->handle.data, str);
+ memset(&npid, 0, sizeof(npid));
+ strcpy_trunc(npid.handle.data, str);
// npid->reserved[0] = 1;
}
- void string_to_online_name(std::string_view str, SceNpOnlineName* online_name)
+ void string_to_online_name(std::string_view str, SceNpOnlineName& online_name)
{
- strcpy_trunc(online_name->data, str);
+ memset(&online_name, 0, sizeof(online_name));
+ strcpy_trunc(online_name.data, str);
}
- void string_to_avatar_url(std::string_view str, SceNpAvatarUrl* avatar_url)
+ void string_to_avatar_url(std::string_view str, SceNpAvatarUrl& avatar_url)
{
- strcpy_trunc(avatar_url->data, str);
+ memset(&avatar_url, 0, sizeof(avatar_url));
+ strcpy_trunc(avatar_url.data, str);
}
- void string_to_communication_id(std::string_view str, SceNpCommunicationId* comm_id)
+ void string_to_communication_id(std::string_view str, SceNpCommunicationId& comm_id)
{
- strcpy_trunc(comm_id->data, str);
+ memset(&comm_id, 0, sizeof(comm_id));
+ strcpy_trunc(comm_id.data, str);
+ }
+
+ bool is_valid_npid(const SceNpId& npid)
+ {
+ if (!std::all_of(npid.handle.data, npid.handle.data + 16, [](char c) { return std::isalnum(c) || c == '-' || c == '_' || c == 0; } )
+ || npid.handle.data[16] != 0
+ || !std::all_of(npid.handle.dummy, npid.handle.dummy + 3, [](char val) { return val == 0; }) )
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ bool is_same_npid(const SceNpId& npid_1, const SceNpId& npid_2)
+ {
+ // Unknown what this constant means
+ // if (id1->reserved[0] != 1 || id2->reserved[0] != 1)
+ // {
+ // return SCE_NP_UTIL_ERROR_INVALID_NP_ID;
+ // }
+
+ if (strncmp(npid_1.handle.data, npid_2.handle.data, 16) == 0) // || id1->unk1[0] != id2->unk1[0])
+ {
+ return true;
+ }
+
+ // if (id1->unk1[1] != id2->unk1[1])
+ // {
+ // // If either is zero they match
+ // if (id1->opt[4] && id2->opt[4])
+ // {
+ // return SCE_NP_UTIL_ERROR_NOT_MATCH;
+ // }
+ // }
+
+ return false;
}
}
diff --git a/rpcs3/Emu/NP/np_helpers.h b/rpcs3/Emu/NP/np_helpers.h
index f80f1c9def..a0cd17f822 100644
--- a/rpcs3/Emu/NP/np_helpers.h
+++ b/rpcs3/Emu/NP/np_helpers.h
@@ -1,3 +1,5 @@
+#pragma once
+
#include "util/types.hpp"
#include "Emu/Cell/Modules/sceNp.h"
#include "Emu/Cell/Modules/sceNp2.h"
@@ -7,8 +9,11 @@ namespace np
std::string ip_to_string(u32 addr);
std::string ether_to_string(std::array& ether);
- void string_to_npid(std::string_view str, SceNpId* npid);
- void string_to_online_name(std::string_view str, SceNpOnlineName* online_name);
- void string_to_avatar_url(std::string_view str, SceNpAvatarUrl* avatar_url);
- void string_to_communication_id(std::string_view str, SceNpCommunicationId* comm_id);
+ void string_to_npid(std::string_view str, SceNpId& npid);
+ void string_to_online_name(std::string_view str, SceNpOnlineName& online_name);
+ void string_to_avatar_url(std::string_view str, SceNpAvatarUrl& avatar_url);
+ void string_to_communication_id(std::string_view str, SceNpCommunicationId& comm_id);
+
+ bool is_valid_npid(const SceNpId& npid);
+ bool is_same_npid(const SceNpId& npid_1, const SceNpId& npid_2);
}
diff --git a/rpcs3/Emu/NP/np_notifications.cpp b/rpcs3/Emu/NP/np_notifications.cpp
index 532c1454f9..dda857ae9c 100644
--- a/rpcs3/Emu/NP/np_notifications.cpp
+++ b/rpcs3/Emu/NP/np_notifications.cpp
@@ -29,7 +29,8 @@ namespace np
RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(edata, update_info, notif_data);
np_memory.shrink_allocation(edata.addr(), edata.size());
- np_cache.add_member(room_id, notif_data->roomMemberDataInternal.get_ptr());
+ if (!np_cache.add_member(room_id, notif_data->roomMemberDataInternal.get_ptr()))
+ return;
rpcn_log.notice("Received notification that user %s(%d) joined the room(%d)", notif_data->roomMemberDataInternal->userInfo.npId.handle.data, notif_data->roomMemberDataInternal->memberId, room_id);
extra_nps::print_room_member_data_internal(notif_data->roomMemberDataInternal.get_ptr());
@@ -60,7 +61,8 @@ namespace np
RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(edata, update_info, notif_data);
np_memory.shrink_allocation(edata.addr(), edata.size());
- np_cache.del_member(room_id, notif_data->roomMemberDataInternal->memberId);
+ if (!np_cache.del_member(room_id, notif_data->roomMemberDataInternal->memberId))
+ return;
rpcn_log.notice("Received notification that user %s(%d) left the room(%d)", notif_data->roomMemberDataInternal->userInfo.npId.handle.data, notif_data->roomMemberDataInternal->memberId, room_id);
extra_nps::print_room_member_data_internal(notif_data->roomMemberDataInternal.get_ptr());
@@ -154,7 +156,8 @@ namespace np
RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(edata, update_info, notif_data);
np_memory.shrink_allocation(edata.addr(), edata.size());
- np_cache.add_member(room_id, notif_data->newRoomMemberDataInternal.get_ptr());
+ if (!np_cache.add_member(room_id, notif_data->newRoomMemberDataInternal.get_ptr()))
+ return;
rpcn_log.notice("Received notification that user's %s(%d) room (%d) data was updated", notif_data->newRoomMemberDataInternal->userInfo.npId.handle.data, notif_data->newRoomMemberDataInternal->memberId, room_id);
extra_nps::print_room_member_data_internal(notif_data->newRoomMemberDataInternal.get_ptr());
@@ -200,22 +203,27 @@ namespace np
void np_handler::notif_p2p_connect(std::vector& data)
{
- if (data.size() != 16)
+ vec_stream noti(data);
+ const u64 room_id = noti.get();
+ const u16 member_id = noti.get();
+ const u16 port_p2p = noti.get();
+ const u32 addr_p2p = noti.get();
+
+ if (noti.is_error())
{
- rpcn_log.error("Notification data for SignalP2PConnect != 14");
+ rpcn_log.error("Received faulty SignalP2PConnect notification");
return;
}
- const u64 room_id = read_from_ptr>(data);
- const u16 member_id = read_from_ptr>(data, 8);
- const u16 port_p2p = read_from_ptr>(data, 10);
- const u32 addr_p2p = read_from_ptr>(data, 12);
+ auto [res, npid] = np_cache.get_npid(room_id, member_id);
+ if (!npid)
+ return;
- rpcn_log.notice("Received notification to connect to member(%d) of room(%d): %s:%d", member_id, room_id, ip_to_string(addr_p2p), port_p2p);
+ rpcn_log.notice("Received notification to connect to member(%d=%s) of room(%d): %s:%d", member_id, reinterpret_cast((*npid).handle.data), room_id, ip_to_string(addr_p2p), port_p2p);
// Attempt Signaling
auto& sigh = g_fxo->get>();
- sigh.set_sig2_infos(room_id, member_id, SCE_NP_SIGNALING_CONN_STATUS_PENDING, addr_p2p, port_p2p, np_cache.get_npid(room_id, member_id));
- sigh.start_sig2(room_id, member_id);
+ const u32 conn_id = sigh.init_sig2(*npid, room_id, member_id);
+ sigh.start_sig(conn_id, addr_p2p, port_p2p);
}
} // namespace np
diff --git a/rpcs3/Emu/NP/np_requests.cpp b/rpcs3/Emu/NP/np_requests.cpp
index f0bc99066a..9fcdaa08a8 100644
--- a/rpcs3/Emu/NP/np_requests.cpp
+++ b/rpcs3/Emu/NP/np_requests.cpp
@@ -35,70 +35,47 @@ namespace np
u32 np_handler::get_server_status(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id)
{
// TODO: actually implement interaction with server for this?
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetServerInfo);
u32 event_key = get_event_key();
- auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_GetServerInfo, sizeof(SceNpMatching2GetServerInfoResponse));
+ auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_GetServerInfo, sizeof(SceNpMatching2GetServerInfoResponse));
SceNpMatching2GetServerInfoResponse* serv_info = reinterpret_cast(edata.data());
- serv_info->server.serverId = server_id;
- serv_info->server.status = SCE_NP_MATCHING2_SERVER_STATUS_AVAILABLE;
+ serv_info->server.serverId = server_id;
+ serv_info->server.status = SCE_NP_MATCHING2_SERVER_STATUS_AVAILABLE;
np_memory.shrink_allocation(edata.addr(), edata.size());
- const auto cb_info = take_pending_request(req_id);
-
- if (cb_info.cb)
- {
- sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_GetServerInfo, event_key, 0, size, cb_info.cb_arg);
- return 0;
- });
- }
+ const auto cb_info_opt = take_pending_request(req_id);
+ ensure(cb_info_opt);
+ cb_info_opt->queue_callback(req_id, event_key, 0, edata.size());
return req_id;
}
u32 np_handler::create_server_context(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 /*server_id*/)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
- u32 event_key = get_event_key();
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_CreateServerContext);
- const auto cb_info = take_pending_request(req_id);
-
- if (cb_info.cb)
- {
- sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_CreateServerContext, event_key, 0, 0, cb_info.cb_arg);
- return 0;
- });
- }
+ const auto cb_info_opt = take_pending_request(req_id);
+ ensure(cb_info_opt);
+ cb_info_opt->queue_callback(req_id, 0, 0, 0);
return req_id;
}
u32 np_handler::delete_server_context(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 /*server_id*/)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
- u32 event_key = get_event_key();
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_DeleteServerContext);
- const auto cb_info = take_pending_request(req_id);
-
- if (cb_info.cb)
- {
- sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_DeleteServerContext, event_key, 0, 0, cb_info.cb_arg);
- return 0;
- });
- }
+ const auto cb_info_opt = take_pending_request(req_id);
+ ensure(cb_info_opt);
+ cb_info_opt->queue_callback(req_id, 0, 0, 0);
return req_id;
}
u32 np_handler::get_world_list(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetWorldInfoList);
if (!rpcn->get_world_list(req_id, get_match2_context(ctx_id)->communicationId, server_id))
{
@@ -111,7 +88,10 @@ namespace np
bool np_handler::reply_get_world_list(u32 req_id, std::vector& reply_data)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
+
+ if (!cb_info_opt)
+ return true;
vec_stream reply(reply_data, 1);
@@ -129,8 +109,8 @@ namespace np
u32 event_key = get_event_key();
- auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_GetWorldInfoList, sizeof(SceNpMatching2GetWorldInfoListResponse));
- auto* world_info = reinterpret_cast(edata.data());
+ auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_GetWorldInfoList, sizeof(SceNpMatching2GetWorldInfoListResponse));
+ auto* world_info = reinterpret_cast(edata.data());
world_info->worldNum = world_list.size();
if (!world_list.empty())
@@ -138,32 +118,19 @@ namespace np
auto* worlds = edata.allocate(sizeof(SceNpMatching2World) * world_list.size(), world_info->world);
for (usz i = 0; i < world_list.size(); i++)
{
- worlds[i].worldId = world_list[i];
- worlds[i].numOfLobby = 1; // TODO
- worlds[i].maxNumOfTotalLobbyMember = 10000;
- worlds[i].curNumOfTotalLobbyMember = 1;
- worlds[i].curNumOfRoom = 1;
- worlds[i].curNumOfTotalRoomMember = 1;
+ worlds[i].worldId = world_list[i];
}
}
np_memory.shrink_allocation(edata.addr(), edata.size());
-
- if (cb_info.cb)
- {
- sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_GetWorldInfoList, event_key, 0, size, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, event_key, 0, edata.size());
return true;
}
u32 np_handler::create_join_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2CreateJoinRoomRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_CreateJoinRoom);
extra_nps::print_createjoinroom(req);
@@ -181,7 +148,10 @@ namespace np
bool np_handler::reply_create_join_room(u32 req_id, std::vector& reply_data)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
+
+ if (!cb_info_opt)
+ return true;
vec_stream reply(reply_data, 1);
auto* resp = reply.get_flatbuffer();
@@ -191,7 +161,7 @@ namespace np
u32 event_key = get_event_key();
- auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_CreateJoinRoom, sizeof(SceNpMatching2CreateJoinRoomResponse));
+ auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_CreateJoinRoom, sizeof(SceNpMatching2CreateJoinRoomResponse));
auto* room_resp = reinterpret_cast(edata.data());
auto* room_info = edata.allocate(sizeof(SceNpMatching2RoomDataInternal), room_resp->roomDataInternal);
RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, resp, room_info, npid);
@@ -200,29 +170,16 @@ namespace np
np_cache.insert_room(room_info);
np_cache.update_password(room_resp->roomDataInternal->roomId, cached_cj_password);
- // Establish Matching2 self signaling info
- auto& sigh = g_fxo->get>();
- sigh.set_self_sig2_info(room_info->roomId, 1);
- sigh.set_sig2_infos(room_info->roomId, 1, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE, rpcn->get_addr_sig(), rpcn->get_port_sig(), get_npid(), true);
- // TODO? Should this send a message to Signaling CB? Is this even necessary?
-
extra_nps::print_create_room_resp(room_resp);
- if (cb_info.cb)
- {
- sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_CreateJoinRoom, event_key, 0, size, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, event_key, 0, edata.size());
return true;
}
u32 np_handler::join_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2JoinRoomRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_JoinRoom);
extra_nps::print_joinroom(req);
@@ -237,6 +194,11 @@ namespace np
bool np_handler::reply_join_room(u32 req_id, std::vector& reply_data)
{
+ auto cb_info_opt = take_pending_request(req_id);
+
+ if (!cb_info_opt)
+ return true;
+
s32 error_code = 0;
if (rpcn::is_error(static_cast(reply_data[0])))
@@ -250,19 +212,9 @@ namespace np
}
}
- const auto cb_info = take_pending_request(req_id);
-
if (error_code != 0)
{
- if (cb_info.cb)
- {
- sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_JoinRoom, 0, error_code, 0, cb_info.cb_arg);
- return 0;
- });
- }
-
+ cb_info_opt->queue_callback(req_id, 0, error_code, 0);
return true;
}
@@ -275,37 +227,24 @@ namespace np
u32 event_key = get_event_key();
- auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_JoinRoom, sizeof(SceNpMatching2JoinRoomResponse));
+ auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_JoinRoom, sizeof(SceNpMatching2JoinRoomResponse));
auto* room_resp = reinterpret_cast(edata.data());
auto* room_info = edata.allocate(sizeof(SceNpMatching2RoomDataInternal), room_resp->roomDataInternal);
- u16 member_id = RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, resp, room_info, npid);
+ RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, resp, room_info, npid);
np_memory.shrink_allocation(edata.addr(), edata.size());
np_cache.insert_room(room_info);
extra_nps::print_room_data_internal(room_info);
- // Establish Matching2 self signaling info
- auto& sigh = g_fxo->get>();
- sigh.set_self_sig2_info(room_info->roomId, member_id);
- sigh.set_sig2_infos(room_info->roomId, member_id, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE, rpcn->get_addr_sig(), rpcn->get_port_sig(), get_npid(), true);
- // TODO? Should this send a message to Signaling CB? Is this even necessary?
-
- if (cb_info.cb)
- {
- sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_JoinRoom, event_key, 0, size, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, event_key, 0, edata.size());
return true;
}
u32 np_handler::leave_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2LeaveRoomRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_LeaveRoom);
if (!rpcn->leave_room(req_id, get_match2_context(ctx_id)->communicationId, req))
{
@@ -318,34 +257,27 @@ namespace np
bool np_handler::reply_leave_room(u32 req_id, std::vector& reply_data)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
+
+ if (!cb_info_opt)
+ return true;
vec_stream reply(reply_data, 1);
u64 room_id = reply.get();
if (reply.is_error())
return error_and_disconnect("Malformed reply to LeaveRoom command");
- u32 event_key = get_event_key(); // Unsure if necessary if there is no data
-
// Disconnect all users from that room
auto& sigh = g_fxo->get>();
sigh.disconnect_sig2_users(room_id);
-
- if (cb_info.cb)
- {
- sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_LeaveRoom, event_key, 0, 0, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, 0, 0, 0);
return true;
}
u32 np_handler::search_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SearchRoomRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SearchRoom);
extra_nps::print_search_room(req);
@@ -360,7 +292,10 @@ namespace np
bool np_handler::reply_search_room(u32 req_id, std::vector& reply_data)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
+
+ if (!cb_info_opt)
+ return true;
vec_stream reply(reply_data, 1);
auto* resp = reply.get_flatbuffer();
@@ -370,28 +305,20 @@ namespace np
u32 event_key = get_event_key();
- auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_SearchRoom, sizeof(SceNpMatching2SearchRoomResponse));
+ auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_SearchRoom, sizeof(SceNpMatching2SearchRoomResponse));
auto* search_resp = reinterpret_cast(edata.data());
SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(edata, resp, search_resp);
np_memory.shrink_allocation(edata.addr(), edata.size());
extra_nps::print_search_room_resp(search_resp);
-
- if (cb_info.cb)
- {
- sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SearchRoom, event_key, 0, size, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, event_key, 0, edata.size());
return true;
}
u32 np_handler::get_roomdata_external_list(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomDataExternalListRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataExternalList);
extra_nps::print_get_roomdata_external_list_req(req);
@@ -406,7 +333,10 @@ namespace np
bool np_handler::reply_get_roomdata_external_list(u32 req_id, std::vector& reply_data)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
+
+ if (!cb_info_opt)
+ return true;
vec_stream reply(reply_data, 1);
auto* resp = reply.get_flatbuffer();
@@ -416,28 +346,21 @@ namespace np
u32 event_key = get_event_key();
- auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_GetRoomDataExternalList, sizeof(SceNpMatching2GetRoomDataExternalListResponse));
+ auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_GetRoomDataExternalList, sizeof(SceNpMatching2GetRoomDataExternalListResponse));
auto* sce_get_room_ext_resp = reinterpret_cast(edata.data());
GetRoomDataExternalListResponse_to_SceNpMatching2GetRoomDataExternalListResponse(edata, resp, sce_get_room_ext_resp);
np_memory.shrink_allocation(edata.addr(), edata.size());
extra_nps::print_get_roomdata_external_list_resp(sce_get_room_ext_resp);
- if (cb_info.cb)
- {
- sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataExternalList, event_key, 0, size, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, event_key, 0, edata.size());
return true;
}
u32 np_handler::set_roomdata_external(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomDataExternalRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataExternal);
extra_nps::print_set_roomdata_ext_req(req);
@@ -452,25 +375,19 @@ namespace np
bool np_handler::reply_set_roomdata_external(u32 req_id, std::vector& /*reply_data*/)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
- u32 event_key = get_event_key(); // Unsure if necessary if there is no data
+ if (!cb_info_opt)
+ return true;
- if (cb_info.cb)
- {
- sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataExternal, event_key, 0, 0, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, 0, 0, 0);
return true;
}
u32 np_handler::get_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomDataInternalRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataInternal);
if (!rpcn->get_roomdata_internal(req_id, get_match2_context(ctx_id)->communicationId, req))
{
@@ -483,7 +400,10 @@ namespace np
bool np_handler::reply_get_roomdata_internal(u32 req_id, std::vector& reply_data)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
+
+ if (!cb_info_opt)
+ return true;
vec_stream reply(reply_data, 1);
@@ -494,7 +414,7 @@ namespace np
u32 event_key = get_event_key();
- auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_GetRoomDataInternal, sizeof(SceNpMatching2GetRoomDataInternalResponse));
+ auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_GetRoomDataInternal, sizeof(SceNpMatching2GetRoomDataInternalResponse));
auto* room_resp = reinterpret_cast(edata.data());
auto* room_info = edata.allocate(sizeof(SceNpMatching2RoomDataInternal), room_resp->roomDataInternal);
RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, resp, room_info, npid);
@@ -504,21 +424,14 @@ namespace np
extra_nps::print_room_data_internal(room_info);
- if (cb_info.cb)
- {
- sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataInternal, event_key, 0, size, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, event_key, 0, edata.size());
return true;
}
u32 np_handler::set_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomDataInternalRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataInternal);
// TODO: extra_nps::print_set_roomdata_req(req);
@@ -535,25 +448,19 @@ namespace np
bool np_handler::reply_set_roomdata_internal(u32 req_id, std::vector& /*reply_data*/)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
- u32 event_key = get_event_key(); // Unsure if necessary if there is no data
+ if (!cb_info_opt)
+ return true;
- if (cb_info.cb)
- {
- sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataInternal, event_key, 0, 0, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, 0, 0, 0);
return true;
}
u32 np_handler::set_roommemberdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomMemberDataInternalRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomMemberDataInternal);
extra_nps::print_set_roommemberdata_int_req(req);
@@ -568,25 +475,19 @@ namespace np
bool np_handler::reply_set_roommemberdata_internal(u32 req_id, std::vector& /*reply_data*/)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
- u32 event_key = get_event_key(); // Unsure if necessary if there is no data
+ if (!cb_info_opt)
+ return true;
- if (cb_info.cb)
- {
- sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomMemberDataInternal, event_key, 0, 0, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, 0, 0, 0);
return true;
}
u32 np_handler::get_ping_info(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SignalingGetPingInfoRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SignalingGetPingInfo);
if (!rpcn->ping_room_owner(req_id, get_match2_context(ctx_id)->communicationId, req->roomId))
{
@@ -599,7 +500,10 @@ namespace np
bool np_handler::reply_get_ping_info(u32 req_id, std::vector& reply_data)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
+
+ if (!cb_info_opt)
+ return true;
vec_stream reply(reply_data, 1);
@@ -610,26 +514,18 @@ namespace np
u32 event_key = get_event_key();
- auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_SignalingGetPingInfo, sizeof(SceNpMatching2SignalingGetPingInfoResponse));
+ auto& edata = allocate_req_result(event_key, SCE_NP_MATCHING2_EVENT_DATA_MAX_SIZE_SignalingGetPingInfo, sizeof(SceNpMatching2SignalingGetPingInfoResponse));
auto* final_ping_resp = reinterpret_cast(edata.data());
GetPingInfoResponse_to_SceNpMatching2SignalingGetPingInfoResponse(resp, final_ping_resp);
np_memory.shrink_allocation(edata.addr(), edata.size());
-
- if (cb_info.cb)
- {
- sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SignalingGetPingInfo, event_key, 0, size, cb_info.cb_arg);
- return 0;
- });
- }
+ cb_info_opt->queue_callback(req_id, event_key, 0, edata.size());
return true;
}
u32 np_handler::send_room_message(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SendRoomMessageRequest* req)
{
- u32 req_id = generate_callback_info(ctx_id, optParam);
+ u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomMessage);
if (!rpcn->send_room_message(req_id, get_match2_context(ctx_id)->communicationId, req))
{
@@ -642,16 +538,12 @@ namespace np
bool np_handler::reply_send_room_message(u32 req_id, std::vector& /*reply_data*/)
{
- const auto cb_info = take_pending_request(req_id);
+ auto cb_info_opt = take_pending_request(req_id);
- if (cb_info.cb)
- {
- sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
- {
- cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomMessage, 0, 0, 0, cb_info.cb_arg);
- return 0;
- });
- }
+ if (!cb_info_opt)
+ return true;
+
+ cb_info_opt->queue_callback(req_id, 0, 0, 0);
return true;
}
@@ -727,7 +619,7 @@ namespace np
if (reply.is_error())
return error_and_disconnect("Malformed reply to RequestTicket command");
- current_ticket = ticket(std::move(ticket_raw));
+ current_ticket = ticket(std::move(ticket_raw));
auto ticket_size = static_cast(current_ticket.size());
if (manager_cb)
@@ -785,7 +677,7 @@ namespace np
{
std::unique_lock lock(trans_ctx->mutex);
- u32 req_id = get_req_id(0x3334);
+ u32 req_id = get_req_id(0x3334);
trans_ctx->tdata = tdata_get_board_infos{.boardInfo = boardInfo};
rpcn->get_board_infos(req_id, trans_ctx->communicationId, boardId);
@@ -803,10 +695,10 @@ namespace np
SceNpScoreBoardInfo board_info;
- board_info.rankLimit = resp->rankLimit();
- board_info.updateMode = resp->updateMode();
- board_info.sortMode = resp->sortMode();
- board_info.uploadNumLimit = resp->uploadNumLimit();
+ board_info.rankLimit = resp->rankLimit();
+ board_info.updateMode = resp->updateMode();
+ board_info.sortMode = resp->sortMode();
+ board_info.uploadNumLimit = resp->uploadNumLimit();
board_info.uploadSizeLimit = resp->uploadSizeLimit();
std::lock_guard lock_trans(mutex_score_transactions);
@@ -832,8 +724,8 @@ namespace np
void np_handler::record_score(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, vm::cptr scoreComment, const u8* data, u32 data_size, vm::ptr tmpRank, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
- u32 req_id = get_req_id(0x3334);
- std::optional str_comment = scoreComment ? std::optional(std::string(reinterpret_cast(scoreComment->data))) : std::nullopt;
+ u32 req_id = get_req_id(0x3334);
+ std::optional str_comment = scoreComment ? std::optional(std::string(reinterpret_cast(scoreComment->data))) : std::nullopt;
std::optional> vec_data;
if (data)
@@ -904,7 +796,7 @@ namespace np
if (!tdata)
{
trans_ctx->tdata = tdata_record_score_data{.game_data_size = totalSize};
- tdata = std::get_if(&trans_ctx->tdata);
+ tdata = std::get_if(&trans_ctx->tdata);
tdata->game_data.reserve(totalSize);
}
@@ -913,7 +805,7 @@ namespace np
if (tdata->game_data.size() == tdata->game_data_size)
{
trans_ctx->result = std::nullopt;
- u32 req_id = get_req_id(0x3334);
+ u32 req_id = get_req_id(0x3334);
rpcn->record_score_data(req_id, trans_ctx->communicationId, trans_ctx->pcId, boardId, score, tdata->game_data);
score_async_handler(std::move(lock), trans_ctx, req_id, async);
}
@@ -984,7 +876,7 @@ namespace np
usz to_copy = std::min(tdata->game_data.size(), static_cast(recvSize));
std::memcpy(score_data.get_ptr(), tdata->game_data.data(), to_copy);
tdata->game_data.erase(tdata->game_data.begin(), tdata->game_data.begin() + to_copy);
- *totalSize = tdata->game_data_size;
+ *totalSize = tdata->game_data_size;
trans_ctx->result = not_an_error(to_copy);
}
@@ -1038,14 +930,14 @@ namespace np
u32 req_id = get_req_id(0x3334);
trans_ctx->tdata = tdata_get_score_generic{
- .rankArray = rankArray,
+ .rankArray = rankArray,
.rankArraySize = rankArraySize,
- .commentArray = commentArray,
- .infoArray = infoArray,
+ .commentArray = commentArray,
+ .infoArray = infoArray,
.infoArraySize = infoArraySize,
- .arrayNum = arrayNum,
- .lastSortDate = lastSortDate,
- .totalRecord = totalRecord,
+ .arrayNum = arrayNum,
+ .lastSortDate = lastSortDate,
+ .totalRecord = totalRecord,
};
bool with_comments = !!commentArray;
@@ -1088,9 +980,9 @@ namespace np
memset(tdata->rankArray.get_ptr(), 0, tdata->rankArraySize);
auto* fb_rankarray = resp->rankArray();
- u32 target_index = 0;
+ u32 target_index = 0;
- vm::ptr rankArray = vm::static_ptr_cast(tdata->rankArray);
+ vm::ptr rankArray = vm::static_ptr_cast(tdata->rankArray);
vm::ptr rankPlayerArray = vm::static_ptr_cast(tdata->rankArray);
for (flatbuffers::uoffset_t i = 0; i < fb_rankarray->size(); i++)
@@ -1109,18 +1001,18 @@ namespace np
else
{
rankPlayerArray[i].hasData = 1;
- cur_rank = &rankPlayerArray[i].rankData;
+ cur_rank = &rankPlayerArray[i].rankData;
}
- string_to_npid(fb_rankdata->npId()->string_view(), &cur_rank->npId);
- string_to_online_name(fb_rankdata->onlineName()->string_view(), &cur_rank->onlineName);
+ string_to_npid(fb_rankdata->npId()->string_view(), cur_rank->npId);
+ string_to_online_name(fb_rankdata->onlineName()->string_view(), cur_rank->onlineName);
- cur_rank->pcId = fb_rankdata->pcId();
- cur_rank->serialRank = fb_rankdata->rank();
- cur_rank->rank = fb_rankdata->rank();
- cur_rank->highestRank = fb_rankdata->rank();
- cur_rank->scoreValue = fb_rankdata->score();
- cur_rank->hasGameData = fb_rankdata->hasGameData();
+ cur_rank->pcId = fb_rankdata->pcId();
+ cur_rank->serialRank = fb_rankdata->rank();
+ cur_rank->rank = fb_rankdata->rank();
+ cur_rank->highestRank = fb_rankdata->rank();
+ cur_rank->scoreValue = fb_rankdata->score();
+ cur_rank->hasGameData = fb_rankdata->hasGameData();
cur_rank->recordDate.tick = fb_rankdata->recordDate();
target_index++;
@@ -1170,7 +1062,7 @@ namespace np
}
tdata->lastSortDate->tick = resp->lastSortDate();
- *tdata->totalRecord = resp->totalRecord();
+ *tdata->totalRecord = resp->totalRecord();
if (fb_rankarray->size())
trans_ctx->result = not_an_error(fb_rankarray->size());
@@ -1188,16 +1080,16 @@ namespace np
void np_handler::get_score_friend(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, bool include_self, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
- u32 req_id = get_req_id(0x3334);
+ u32 req_id = get_req_id(0x3334);
trans_ctx->tdata = tdata_get_score_generic{
- .rankArray = rankArray,
+ .rankArray = rankArray,
.rankArraySize = rankArraySize,
- .commentArray = commentArray,
- .infoArray = infoArray,
+ .commentArray = commentArray,
+ .infoArray = infoArray,
.infoArraySize = infoArraySize,
- .arrayNum = arrayNum,
- .lastSortDate = lastSortDate,
- .totalRecord = totalRecord,
+ .arrayNum = arrayNum,
+ .lastSortDate = lastSortDate,
+ .totalRecord = totalRecord,
};
bool with_comments = !!commentArray;
@@ -1215,16 +1107,16 @@ namespace np
void np_handler::get_score_npid(std::shared_ptr& trans_ctx, SceNpScoreBoardId boardId, const std::vector>& npid_vec, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, [[maybe_unused]] u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async)
{
std::unique_lock lock(trans_ctx->mutex);
- u32 req_id = get_req_id(0x3334);
+ u32 req_id = get_req_id(0x3334);
trans_ctx->tdata = tdata_get_score_generic{
- .rankArray = rankArray,
+ .rankArray = rankArray,
.rankArraySize = rankArraySize,
- .commentArray = commentArray,
- .infoArray = infoArray,
+ .commentArray = commentArray,
+ .infoArray = infoArray,
.infoArraySize = infoArraySize,
- .arrayNum = arrayNum,
- .lastSortDate = lastSortDate,
- .totalRecord = totalRecord,
+ .arrayNum = arrayNum,
+ .lastSortDate = lastSortDate,
+ .totalRecord = totalRecord,
};
bool with_comments = !!commentArray;
diff --git a/rpcs3/Emu/NP/np_structs_extra.cpp b/rpcs3/Emu/NP/np_structs_extra.cpp
index aad69fa80a..eb533886f1 100644
--- a/rpcs3/Emu/NP/np_structs_extra.cpp
+++ b/rpcs3/Emu/NP/np_structs_extra.cpp
@@ -18,6 +18,7 @@ namespace extra_nps
void print_sigoptparam(const SceNpMatching2SignalingOptParam* opt)
{
+ sceNp2.warning("SceNpMatching2SignalingOptParam:");
sceNp2.warning("type: %d", opt->type);
sceNp2.warning("flag: %d", opt->flag);
sceNp2.warning("hubMemberId: %d", opt->hubMemberId);
@@ -227,7 +228,10 @@ namespace extra_nps
sceNp2.warning("curMemberNum: %d", room->curMemberNum);
sceNp2.warning("SceNpMatching2RoomPasswordSlotMask: 0x%x", room->passwordSlotMask);
sceNp2.warning("owner: *0x%x", room->owner);
- print_userinfo2(room->owner.get_ptr());
+
+ if (room->owner)
+ print_userinfo2(room->owner.get_ptr());
+
sceNp2.warning("roomGroup: *0x%x", room->roomGroup);
// TODO: print roomGroup
sceNp2.warning("roomGroupNum: %d", room->roomGroupNum);
diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp
index bd98c196c6..fc65514943 100644
--- a/rpcs3/Emu/NP/rpcn_client.cpp
+++ b/rpcs3/Emu/NP/rpcn_client.cpp
@@ -71,7 +71,7 @@ namespace rpcn
return get_localized_string(rpcn_state_to_localized_string_id(state));
}
- constexpr u32 RPCN_PROTOCOL_VERSION = 18;
+ constexpr u32 RPCN_PROTOCOL_VERSION = 19;
constexpr usz RPCN_HEADER_SIZE = 15;
constexpr usz COMMUNICATION_ID_SIZE = 9;
diff --git a/rpcs3/Emu/NP/rpcn_config.cpp b/rpcs3/Emu/NP/rpcn_config.cpp
index d2c8fb3f1a..decdbb54e2 100644
--- a/rpcs3/Emu/NP/rpcn_config.cpp
+++ b/rpcs3/Emu/NP/rpcn_config.cpp
@@ -1,6 +1,6 @@
#include "stdafx.h"
#include "rpcn_config.h"
-#include "Emu/System.h"
+#include "Utilities/File.h"
cfg_rpcn g_cfg_rpcn;
diff --git a/rpcs3/Emu/NP/signaling_handler.cpp b/rpcs3/Emu/NP/signaling_handler.cpp
index 51cb18dc2f..5eb415569c 100644
--- a/rpcs3/Emu/NP/signaling_handler.cpp
+++ b/rpcs3/Emu/NP/signaling_handler.cpp
@@ -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
@@ -51,7 +52,7 @@ void signaling_handler::set_sig_cb(u32 sig_cb_ctx, vm::ptrsig_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::ptrsig_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::ptrsig2_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& 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(msg.data.data());
+ const auto* sp = reinterpret_cast(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(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& 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& 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& si, s32 new_status, bool confirm_packet)
+void signaling_handler::update_si_status(std::shared_ptr& 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& 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 packet(sizeof(signaling_packet) + VPORT_0_HEADER_SIZE);
reinterpret_cast&>(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>(port);
+ dest.sin_port = std::bit_cast>(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_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 si = ::at32(sig1_peers, conn_id);
+ ensure(sig_peers.contains(conn_id));
+ std::shared_ptr 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 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 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 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(npid->handle.data));
-
+ std::string npid_str(reinterpret_cast(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());
- ::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());
+ 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(npid->handle.data));
+ std::string npid_str(reinterpret_cast(npid.handle.data));
auto& nph = g_fxo->get>();
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 signaling_handler::get_conn_id_from_npid(const SceNpId* npid)
+std::optional 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(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_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 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>(conn_info->addr) == addr && conn_info->port == port)
{
@@ -752,36 +715,3 @@ std::optional 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();
-
- 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();
- 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];
-}
diff --git a/rpcs3/Emu/NP/signaling_handler.h b/rpcs3/Emu/NP/signaling_handler.h
index 0525a58a8b..bbfe78b04a 100644
--- a/rpcs3/Emu/NP/signaling_handler.h
+++ b/rpcs3/Emu/NP/signaling_handler.h
@@ -9,18 +9,11 @@
#include
#include
-enum ext_signaling_status : u8
-{
- ext_sign_none = 0,
- ext_sign_peer = 1,
- ext_sign_mutual = 2,
-};
-
struct signaling_info
{
- s32 connStatus = SCE_NP_SIGNALING_CONN_STATUS_INACTIVE;
- u32 addr = 0;
- u16 port = 0;
+ s32 conn_status = SCE_NP_SIGNALING_CONN_STATUS_INACTIVE;
+ u32 addr = 0;
+ u16 port = 0;
// User seen from that peer
u32 mapped_addr = 0;
@@ -28,16 +21,15 @@ struct signaling_info
// For handler
steady_clock::time_point time_last_msg_recvd = steady_clock::now();
- bool self = false;
- u32 version = 0;
+ bool self = false;
SceNpId npid{};
// Signaling
- u32 conn_id = 0;
- ext_signaling_status ext_status = ext_sign_none;
+ u32 conn_id = 0;
+ bool op_activated = false;
// Matching2
- u64 room_id = 0;
+ u64 room_id = 0;
u16 member_id = 0;
// Stats
@@ -68,16 +60,13 @@ public:
signaling_handler& operator=(thread_state);
void set_self_sig_info(SceNpId& npid);
- void set_self_sig2_info(u64 room_id, u16 member_id);
- u32 init_sig_infos(const SceNpId* npid);
- signaling_info get_sig_infos(u32 conn_id);
- std::optional get_conn_id_from_npid(const SceNpId* npid);
+ u32 init_sig1(const SceNpId& npid);
+ u32 init_sig2(const SceNpId& npid, u64 room_id, u16 member_id);
+ std::optional get_sig_infos(u32 conn_id);
+ std::optional get_conn_id_from_npid(const SceNpId& npid);
std::optional get_conn_id_from_addr(u32 addr, u16 port);
- void set_sig2_infos(u64 room_id, u16 member_id, s32 status, u32 addr, u16 port, const SceNpId& npid, bool self = false);
- signaling_info get_sig2_infos(u64 room_id, u16 member_id);
-
void set_sig_cb(u32 sig_cb_ctx, vm::ptr sig_cb, vm::ptr sig_cb_arg);
void set_ext_sig_cb(u32 sig_ext_cb_ctx, vm::ptr sig_ext_cb, vm::ptr sig_ext_cb_arg);
void set_sig2_cb(u16 sig2_cb_ctx, vm::ptr sig2_cb, vm::ptr sig2_cb_arg);
@@ -91,32 +80,22 @@ public:
static constexpr auto thread_name = "Signaling Manager Thread"sv;
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_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 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;
struct signaling_packet
{
be_t signature = SIGNALING_SIGNATURE;
- le_t version;
+ le_t version = SIGNALING_VERSION;
le_t timestamp_sender;
le_t timestamp_receiver;
le_t command;
le_t sent_addr;
le_t sent_port;
- union
- {
- struct
- {
- SceNpId npid;
- } V1;
- struct
- {
- le_t room_id;
- le_t member_id;
- } V2;
- };
+ SceNpId npid;
};
struct queued_packet
@@ -137,33 +116,32 @@ private:
vm::ptr sig2_cb{};
vm::ptr sig2_cb_arg{};
- u32 create_sig_infos(const SceNpId* npid);
+ 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, bool confirm_packet = false);
+ static void update_room_info(std::shared_ptr& si, u64 room_id, u16 member_id);
+ void update_si_status(std::shared_ptr& si, s32 new_status);
+ 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 start_sig_nl(u32 conn_id, u32 addr, u16 port);
-
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);
std::mutex data_mutex;
std::condition_variable wakey;
- signaling_packet sig1_packet{.version = 1u};
- signaling_packet sig2_packet{.version = 2u};
+ signaling_packet sig_packet{};
std::map