#include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" #include #include // Peer-to-peer signaling needs the network: contexts exist, but sessions never activate. static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT = static_cast(0x80553303); static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_CONN_NOT_FOUND = static_cast(0x8055330C); static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_UNAVAILABLE = static_cast(0x80552D06); static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED = static_cast(0x80553301); static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_ALREADY_INITIALIZED = static_cast(0x80553302); static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_LIMIT = static_cast(0x80553307); static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_NOT_FOUND = static_cast(0x80553308); static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_GROUP_NOT_FOUND = static_cast(0x8055330A); struct SessionSignalingContext { std::uint32_t id; std::int32_t userId; bool active; }; static std::mutex g_mutex; static bool g_initialized = false; static std::array g_contexts{}; struct SessionSignalingInitParam { std::int32_t userId; std::uint64_t poolSize; std::uint64_t affinityMask; std::int32_t threadPriority; std::uint64_t stackSize; }; struct SessionSignalingMemoryInfo { std::uint64_t poolSize; std::uint64_t usedSize; std::uint64_t peakUsedSize; }; struct SessionSignalingPeerAddress { std::uint64_t accountId; std::uint32_t platform; }; struct SessionSignalingSessionParam { std::uint32_t mode; std::uint32_t option; }; struct SessionSignalingNetAddress { std::uint32_t address; std::uint16_t port; }; union SessionSignalingConnectionInfo { std::uint32_t value; SessionSignalingNetAddress netAddress; SessionSignalingPeerAddress peerAddress; }; struct SessionSignalingLocalNetInfo { std::uint32_t localAddress; std::uint32_t mappedAddress; std::uint32_t mappedPort; std::uint32_t mappingStatus; }; using SessionSignalingEventCallback = void (APS5_VABI *)(std::uint32_t, std::uint32_t, std::int32_t, const SessionSignalingPeerAddress*, std::int32_t, void*); using SessionSignalingConnectionCallback = void (APS5_VABI *)(std::uint32_t, std::uint32_t, std::int32_t, std::int32_t, void*); using SessionSignalingConnectionCallback2 = void (APS5_VABI *)(std::uint32_t, std::uint32_t, std::uint32_t, std::int32_t, std::int32_t, void*); template struct SessionSignalingContextParam { std::int32_t userId; std::uint32_t serviceLabel; SessionSignalingEventCallback prepareCallback; void* prepareUserData; SessionSignalingEventCallback sessionCallback; void* sessionUserData; TConnectionCallback connectionCallback; void* connectionUserData; }; using SessionSignalingContextParam1 = SessionSignalingContextParam; using SessionSignalingContextParam2 = SessionSignalingContextParam; struct SessionSignalingConnectionStatistics { std::uint32_t peakConnectionCount; std::uint32_t connectionCount; std::uint32_t connectingCount; std::uint32_t connectedCount; }; struct SessionSignalingGroupInfo { std::uint32_t connectionIds[64]; std::uint64_t connectionCount; }; static_assert(sizeof(SessionSignalingMemoryInfo) == 24); static_assert(sizeof(SessionSignalingInitParam) == 40); static_assert(offsetof(SessionSignalingInitParam, poolSize) == 8); static_assert(offsetof(SessionSignalingInitParam, affinityMask) == 16); static_assert(offsetof(SessionSignalingInitParam, threadPriority) == 24); static_assert(offsetof(SessionSignalingInitParam, stackSize) == 32); static_assert(offsetof(SessionSignalingMemoryInfo, usedSize) == 8); static_assert(offsetof(SessionSignalingMemoryInfo, peakUsedSize) == 16); static_assert(sizeof(SessionSignalingPeerAddress) == 16); static_assert(sizeof(SessionSignalingSessionParam) == 8); static_assert(offsetof(SessionSignalingSessionParam, option) == 4); static_assert(sizeof(SessionSignalingNetAddress) == 8); static_assert(offsetof(SessionSignalingNetAddress, port) == 4); static_assert(sizeof(SessionSignalingConnectionInfo) == 16); static_assert(sizeof(SessionSignalingLocalNetInfo) == 16); static_assert(offsetof(SessionSignalingLocalNetInfo, mappedAddress) == 4); static_assert(offsetof(SessionSignalingLocalNetInfo, mappedPort) == 8); static_assert(offsetof(SessionSignalingLocalNetInfo, mappingStatus) == 12); static_assert(sizeof(SessionSignalingContextParam1) == 56); static_assert(sizeof(SessionSignalingContextParam2) == 56); static_assert(offsetof(SessionSignalingContextParam1, prepareCallback) == 8); static_assert(offsetof(SessionSignalingContextParam1, sessionCallback) == 24); static_assert(offsetof(SessionSignalingContextParam1, connectionCallback) == 40); static_assert(offsetof(SessionSignalingContextParam2, connectionCallback) == 40); static_assert(offsetof(SessionSignalingContextParam2, connectionUserData) == 48); static_assert(offsetof(SessionSignalingPeerAddress, platform) == 8); static_assert(sizeof(SessionSignalingConnectionStatistics) == 16); static_assert(offsetof(SessionSignalingConnectionStatistics, connectionCount) == 4); static_assert(offsetof(SessionSignalingConnectionStatistics, connectingCount) == 8); static_assert(offsetof(SessionSignalingConnectionStatistics, connectedCount) == 12); static_assert(sizeof(SessionSignalingGroupInfo) == 264); static_assert(offsetof(SessionSignalingGroupInfo, connectionCount) == 256); static SessionSignalingContext* FindContext(std::uint32_t contextId) { auto& context = g_contexts[contextId % g_contexts.size()]; return context.active && context.id == contextId ? &context : nullptr; } template static int CreateContext(const SessionSignalingContextParam* param, std::uint32_t* contextId) { std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; if (!param || !contextId) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT; for (const auto& context : g_contexts) { if (context.active && context.userId == param->userId) return SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_LIMIT; } for (auto& context : g_contexts) { if (!context.active) { context.userId = param->userId; context.active = true; *contextId = context.id; return 0; } } return SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_LIMIT; } extern "C" { int APS5_VABI sceNpSessionSignalingInitialize(const SessionSignalingInitParam* param) { std::lock_guard lock(g_mutex); if (g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_ALREADY_INITIALIZED; if (!param || !param->poolSize) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT; for (std::uint32_t index = 0; index < g_contexts.size(); ++index) { g_contexts[index] = {1000 + index, 0, false}; } g_initialized = true; return 0; } int APS5_VABI sceNpSessionSignalingActivateSession(std::uint32_t contextId, const char* sessionId, std::uint32_t sessionType, const SessionSignalingSessionParam* param, std::uint32_t* groupId) { std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; if (!sessionId || !param || !groupId) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT; if (!FindContext(contextId)) return SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_NOT_FOUND; if ((param->mode == 1 && param->option != 0) || (param->mode == 2 && param->option == 0)) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT; return SCE_NP_SESSION_SIGNALING_ERROR_UNAVAILABLE; } int APS5_VABI sceNpSessionSignalingCreateContext2(const SessionSignalingContextParam2* param, std::uint32_t* contextId) { return CreateContext(param, contextId); } int APS5_VABI sceNpSessionSignalingCreateContext(const SessionSignalingContextParam1* param, std::uint32_t* contextId) { return CreateContext(param, contextId); } int APS5_VABI sceNpSessionSignalingDeactivate(std::uint32_t contextId, std::uint32_t connectionId) { std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; if (!FindContext(contextId)) return SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_NOT_FOUND; return SCE_NP_SESSION_SIGNALING_ERROR_GROUP_NOT_FOUND; } int APS5_VABI sceNpSessionSignalingDestroyContext(std::uint32_t contextId) { std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; auto* context = FindContext(contextId); if (!context) return SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_NOT_FOUND; context->active = false; const auto nextId = context->id + static_cast(g_contexts.size()); context->id = nextId < 100001 ? nextId : 1000 + contextId % static_cast(g_contexts.size()); return 0; } int APS5_VABI sceNpSessionSignalingGetConnectionInfo(std::uint32_t contextId, std::uint32_t connectionId, std::uint32_t code, SessionSignalingConnectionInfo* info) { std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; if (!info) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT; if (!FindContext(contextId)) return SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_NOT_FOUND; return SCE_NP_SESSION_SIGNALING_ERROR_CONN_NOT_FOUND; } int APS5_VABI sceNpSessionSignalingActivateUser(std::uint32_t contextId, const SessionSignalingPeerAddress* peerAddress, std::uint32_t* connectionId) { std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; if (!peerAddress || !connectionId) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT; if (!FindContext(contextId)) return SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_NOT_FOUND; return SCE_NP_SESSION_SIGNALING_ERROR_UNAVAILABLE; } int APS5_VABI sceNpSessionSignalingGetConnectionFromPeerAddress2(std::uint32_t contextId, std::uint32_t groupId, const SessionSignalingPeerAddress* peerAddress, std::uint32_t* connectionId) { std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; if (!peerAddress || !connectionId) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT; if (!FindContext(contextId)) return SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_NOT_FOUND; return SCE_NP_SESSION_SIGNALING_ERROR_GROUP_NOT_FOUND; } int APS5_VABI sceNpSessionSignalingTerminate(void) { std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; g_initialized = false; for (auto& context : g_contexts) context.active = false; return 0; } int32_t APS5_VABI sceNpSessionSignalingGetConnectionStatus(std::uint32_t contextId, std::uint32_t connectionId, std::int32_t* status, std::uint32_t* peerAddress, std::uint16_t* peerPort) { (void)connectionId; (void)peerAddress; (void)peerPort; std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; if (!status) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT; if (!FindContext(contextId)) return SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_NOT_FOUND; return SCE_NP_SESSION_SIGNALING_ERROR_CONN_NOT_FOUND; } int32_t APS5_VABI sceNpSessionSignalingGetLocalNetInfo(std::uint32_t contextId, SessionSignalingLocalNetInfo* info) { (void)contextId; std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; if (!info) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT; return SCE_NP_SESSION_SIGNALING_ERROR_UNAVAILABLE; } int APS5_VABI sceNpSessionSignalingRequestPrepare(uint32_t contextId, uint32_t* requestId) { std::lock_guard lock(g_mutex); if (!g_initialized) return SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED; if (!requestId) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT; if (!FindContext(contextId)) return SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_NOT_FOUND; return SCE_NP_SESSION_SIGNALING_ERROR_UNAVAILABLE; } int APS5_VABI sceNpSessionSignalingGetMemoryInfo(SessionSignalingMemoryInfo* memoryInfo) { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingGetConnectionStatistics(SessionSignalingConnectionStatistics* statistics) { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingGetConnectionFromPeerAddress(std::uint32_t contextId, const SessionSignalingPeerAddress* peerAddress, std::uint32_t* connectionId) { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingGetGroupFromSessionId(std::uint32_t contextId, const char* sessionId, std::uint32_t* groupId) { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingGetGroupInfo(std::uint32_t contextId, std::uint32_t groupId, SessionSignalingGroupInfo* groupInfo) { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingGetConnectionFromNetAddress2(std::uint32_t contextId, std::uint32_t groupId, std::uint32_t address, std::uint16_t port, SessionSignalingGroupInfo* groupInfo) { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingCreateJoinActivate() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingGetConnectionFromNetAddress() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingGetCustomProperty() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingGetGroupFromPeerAddress() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingInitializeWithPort() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingJoinActivate() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceNpSessionSignalingSetCustomProperty() { NotImplemented_nid_no_patch(__func__); return 0; } }