Files
AnyPS5/core/libs/prx/libSceNpSessionSignaling/Export.cpp
T

331 lines
14 KiB
C++

#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <array>
#include <mutex>
// 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<int>(0x80553303);
static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_CONN_NOT_FOUND = static_cast<int>(0x8055330C);
static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_UNAVAILABLE = static_cast<int>(0x80552D06);
static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_NOT_INITIALIZED = static_cast<int>(0x80553301);
static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_ALREADY_INITIALIZED = static_cast<int>(0x80553302);
static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_LIMIT = static_cast<int>(0x80553307);
static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_CONTEXT_NOT_FOUND = static_cast<int>(0x80553308);
static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_GROUP_NOT_FOUND = static_cast<int>(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<SessionSignalingContext, 10> 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<typename TConnectionCallback>
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<SessionSignalingConnectionCallback>;
using SessionSignalingContextParam2 = SessionSignalingContextParam<SessionSignalingConnectionCallback2>;
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<typename TConnectionCallback>
static int CreateContext(const SessionSignalingContextParam<TConnectionCallback>* 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<std::uint32_t>(g_contexts.size());
context->id = nextId < 100001 ? nextId : 1000 + contextId % static_cast<std::uint32_t>(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;
}
}