mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-10-12 02:22:27 +00:00
Added pTo and pFrom to OrbisNpPeerAddressA support (#5108)
* Added pTo and pFrom to OrbisNpPeerAddressA support * all mighty clang * improved OrbisNpSessionInvitationEventParam * changed diagnostic to debug * all mighty clang again
This commit is contained in:
@@ -117,12 +117,18 @@ struct OrbisNpSessionInvitationEventParam {
|
||||
OrbisNpInvitationId invitationId;
|
||||
OrbisNpSessionInvitationEventFlag flag;
|
||||
char padding[4];
|
||||
Libraries::Np::OrbisNpOnlineId onlineId;
|
||||
Libraries::Np::OrbisNpOnlineId onlineId; // accepting (local) user
|
||||
Libraries::UserService::OrbisUserServiceUserId userId; // accepting (local) user
|
||||
Libraries::Np::OrbisNpOnlineId referralOnlineId; // inviter
|
||||
Libraries::Np::OrbisNpAccountId referralAccountId; // inviter
|
||||
};
|
||||
static_assert(sizeof(OrbisNpSessionInvitationEventParam) == 0x8c,
|
||||
"SESSION_INVITATION param must be 140 bytes");
|
||||
static_assert(offsetof(OrbisNpSessionInvitationEventParam, flag) == 112);
|
||||
static_assert(offsetof(OrbisNpSessionInvitationEventParam, onlineId) == 120);
|
||||
static_assert(offsetof(OrbisNpSessionInvitationEventParam, userId) == 140);
|
||||
static_assert(offsetof(OrbisNpSessionInvitationEventParam, referralOnlineId) == 144);
|
||||
static_assert(offsetof(OrbisNpSessionInvitationEventParam, referralAccountId) == 168);
|
||||
static_assert(sizeof(OrbisNpSessionInvitationEventParam) == 176,
|
||||
"SESSION_INVITATION param must be 176 bytes");
|
||||
|
||||
union OrbisInvitationDialogDataParam {
|
||||
struct {
|
||||
|
||||
@@ -611,9 +611,11 @@ bool NpHandler::SendSessionInvitation(s32 user_id, const std::string& session_id
|
||||
return true;
|
||||
}
|
||||
|
||||
void NpHandler::PostSessionInvitationEvent(const std::string& session_id,
|
||||
void NpHandler::PostSessionInvitationEvent(s32 user_id, const std::string& session_id,
|
||||
const std::string& invitation_id,
|
||||
const std::string& accepter_online_id) {
|
||||
const std::string& accepter_online_id,
|
||||
const std::string& inviter_online_id,
|
||||
OrbisNpAccountId inviter_account_id) {
|
||||
using Libraries::InvitationDialog::ORBIS_NP_SESSION_INVITATION_EVENT_FLAG_INVITATION;
|
||||
using Libraries::InvitationDialog::OrbisNpSessionInvitationEventParam;
|
||||
|
||||
@@ -630,12 +632,19 @@ void NpHandler::PostSessionInvitationEvent(const std::string& session_id,
|
||||
} else {
|
||||
param->flag = 0; // join from session info (no invitation id in the push)
|
||||
}
|
||||
std::strncpy(param->onlineId.data, accepter_online_id.c_str(),
|
||||
sizeof(param->onlineId.data) - 1);
|
||||
// data[16] is followed by its own 'term' byte, so a full 16-char online id must not be cut.
|
||||
std::strncpy(param->onlineId.data, accepter_online_id.c_str(), sizeof(param->onlineId.data));
|
||||
param->userId = user_id;
|
||||
std::strncpy(param->referralOnlineId.data, inviter_online_id.c_str(),
|
||||
sizeof(param->referralOnlineId.data));
|
||||
param->referralAccountId = inviter_account_id;
|
||||
|
||||
Libraries::SystemService::PushSystemServiceEvent(event);
|
||||
LOG_INFO(NpHandler, "Posted SESSION_INVITATION session='{}' flag={} onlineId='{}'", session_id,
|
||||
param->flag, accepter_online_id);
|
||||
LOG_INFO(NpHandler,
|
||||
"Posted SESSION_INVITATION user_id={} session='{}' invitation='{}' flag={} "
|
||||
"onlineId='{}' referral='{}'({})",
|
||||
user_id, session_id, invitation_id, param->flag, accepter_online_id, inviter_online_id,
|
||||
inviter_account_id);
|
||||
}
|
||||
|
||||
std::vector<NpHandler::PendingInvitation> NpHandler::GetPendingInvitations(s32 user_id) const {
|
||||
@@ -685,7 +694,8 @@ bool NpHandler::AcceptSessionInvitation(s32 user_id, const std::string& invitati
|
||||
}
|
||||
// Raise the join event now that the user has explicitly accepted (via the RECV dialog or the
|
||||
// emulator's system-UI equivalent).
|
||||
PostSessionInvitationEvent(inv.session_id, invitation_id, inv.to_npid);
|
||||
PostSessionInvitationEvent(user_id, inv.session_id, invitation_id, inv.to_npid, inv.from_npid,
|
||||
inv.from_account_id);
|
||||
// Consume it server-side (PUT usedFlag=true).
|
||||
const std::string base_url = EmulatorSettings.GetShadNetWebApiServer();
|
||||
const std::string token = GetBearerToken(user_id);
|
||||
@@ -845,6 +855,27 @@ void NpHandler::OnWebApiPushEvent(s32 user_id, const ShadNet::NotifyWebApiPushEv
|
||||
SetNpOnlineId(ev.toOnlineId, n.toNpid);
|
||||
}
|
||||
ev.extdData = n.extdData; // extended-data (key,value) pairs -> dispatched as pExtdData
|
||||
// Account ids for pFrom/pTo.
|
||||
ev.toAccountId = n.toAccountId != 0 ? n.toAccountId : GetAccountId(user_id);
|
||||
ev.fromAccountId = n.fromAccountId;
|
||||
if (ev.fromAccountId == 0) {
|
||||
for (const auto& kv : n.extdData) {
|
||||
if (kv.first == "fromAccountId") {
|
||||
ev.fromAccountId = std::strtoull(kv.second.c_str(), nullptr, 10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev.toAccountId != 0) {
|
||||
ev.hasTo = true;
|
||||
if (n.toNpid.empty()) {
|
||||
// e.g. friendlist events carry no toNpid; the recipient is still us.
|
||||
std::lock_guard lock(m_mutex_clients);
|
||||
if (const auto it = m_np_ids.find(user_id); it != m_np_ids.end()) {
|
||||
std::memcpy(ev.toOnlineId.data, it->second.handle.data, sizeof(ev.toOnlineId.data));
|
||||
}
|
||||
}
|
||||
}
|
||||
NpWebApi::EnqueuePushEvent(ev);
|
||||
|
||||
// Also surface a SESSION_INVITATION system-service event for titles that watch it instead of
|
||||
@@ -870,7 +901,9 @@ void NpHandler::OnWebApiPushEvent(s32 user_id, const ShadNet::NotifyWebApiPushEv
|
||||
return p.invitation_id == invitation_id;
|
||||
}),
|
||||
v.end());
|
||||
v.push_back({session_id, invitation_id, n.fromNpid, n.toNpid, valid_until});
|
||||
PendingInvitation inv{session_id, invitation_id, n.fromNpid, n.toNpid, valid_until};
|
||||
inv.from_account_id = ev.fromAccountId;
|
||||
v.push_back(std::move(inv));
|
||||
}
|
||||
// ORBIS_SYSTEM_SERVICE_EVENT_SESSION_INVITATION is a *join* event: it
|
||||
// fires only after the user explicitly accepts, via the game-opened invitation dialog
|
||||
|
||||
@@ -82,16 +82,20 @@ public:
|
||||
|
||||
// Raises ORBIS_SYSTEM_SERVICE_EVENT_SESSION_INVITATION (0x10000002) so titles that watch the
|
||||
// system-service event learn about the invite.
|
||||
void PostSessionInvitationEvent(const std::string& session_id, const std::string& invitation_id,
|
||||
const std::string& accepter_online_id);
|
||||
void PostSessionInvitationEvent(s32 user_id, const std::string& session_id,
|
||||
const std::string& invitation_id,
|
||||
const std::string& accepter_online_id,
|
||||
const std::string& inviter_online_id,
|
||||
OrbisNpAccountId inviter_account_id);
|
||||
|
||||
// A session invitation surfaced from a shadNet push, stashed until the user acts on it.
|
||||
struct PendingInvitation {
|
||||
std::string session_id;
|
||||
std::string invitation_id;
|
||||
std::string from_npid; // sender (for display)
|
||||
std::string to_npid; // local recipient / accepter
|
||||
int64_t valid_until = 0; // ms since epoch; 0 = never expires
|
||||
std::string from_npid; // sender (for display)
|
||||
std::string to_npid; // local recipient / accepter
|
||||
int64_t valid_until = 0; // ms since epoch; 0 = never expires
|
||||
OrbisNpAccountId from_account_id = 0; // sender account id (0 = unknown)
|
||||
};
|
||||
// Pending invitations stashed for a local user (newest last), populated on arrival.
|
||||
std::vector<PendingInvitation> GetPendingInvitations(s32 user_id) const;
|
||||
|
||||
@@ -142,6 +142,9 @@ struct PushEventInput {
|
||||
bool hasFrom = false;
|
||||
OrbisNpOnlineId toOnlineId{};
|
||||
bool hasTo = false;
|
||||
// Account ids for the OrbisNpPeerAddressA pFrom/pTo of extended push callbacks.
|
||||
OrbisNpAccountId fromAccountId = 0;
|
||||
OrbisNpAccountId toAccountId = 0;
|
||||
std::vector<std::pair<std::string, std::string>> extdData; // (key,value) for extd push
|
||||
};
|
||||
void EnqueuePushEvent(const PushEventInput& ev);
|
||||
|
||||
@@ -1592,13 +1592,19 @@ s32 createExtendedPushEventFilterInternal(
|
||||
sizeof(OrbisNpWebApiExtdPushEventFilterParameter));
|
||||
LOG_INFO(Lib_NpWebApi, " filterParam[{}] dataType='{}' extdKeys={}", param_idx,
|
||||
copy.dataType.val, copy.extdDataKeyNum); // debug
|
||||
std::vector<std::string> keys;
|
||||
if (copy.pExtdDataKey != nullptr) {
|
||||
for (u64 k = 0; k < copy.extdDataKeyNum; k++) {
|
||||
LOG_INFO(Lib_NpWebApi, " extdDataKey[{}]='{}'", k,
|
||||
copy.pExtdDataKey[k].val); // debug
|
||||
keys.emplace_back(
|
||||
copy.pExtdDataKey[k].val,
|
||||
strnlen(copy.pExtdDataKey[k].val, sizeof(copy.pExtdDataKey[k].val)));
|
||||
}
|
||||
}
|
||||
copy.pExtdDataKey = nullptr; // guest memory, see extdDataKeys
|
||||
filter->filterParams.emplace_back(copy);
|
||||
filter->extdDataKeys.emplace_back(std::move(keys));
|
||||
// TODO: Every parameter is registered with an extended data filter through
|
||||
// sceNpPushRegisterExtendedDataFilter
|
||||
}
|
||||
@@ -2128,6 +2134,14 @@ void DrainPushEvents() {
|
||||
std::snprintf(dt.val, sizeof(dt.val), "%s", ev.dataType.c_str());
|
||||
const OrbisNpOnlineId* from_p = ev.hasFrom ? &ev.fromOnlineId : nullptr;
|
||||
const OrbisNpOnlineId* to_p = ev.hasTo ? &ev.toOnlineId : nullptr;
|
||||
OrbisNpPeerAddressA to_addr{};
|
||||
OrbisNpPeerAddressA from_addr{};
|
||||
to_addr.accountId = ev.toAccountId;
|
||||
to_addr.platform = OrbisNpPlatformType::PS4;
|
||||
from_addr.accountId = ev.fromAccountId;
|
||||
from_addr.platform = OrbisNpPlatformType::PS4;
|
||||
const OrbisNpPeerAddressA* to_addr_p = ev.toAccountId != 0 ? &to_addr : nullptr;
|
||||
const OrbisNpPeerAddressA* from_addr_p = ev.fromAccountId != 0 ? &from_addr : nullptr;
|
||||
|
||||
std::scoped_lock gl{g_global_mutex};
|
||||
for (auto& [libId, context] : g_contexts) {
|
||||
@@ -2162,9 +2176,29 @@ void DrainPushEvents() {
|
||||
if (!filterMatches(flt, ev.npServiceName, ev_has_service, ev.dataType)) {
|
||||
continue;
|
||||
}
|
||||
// Only hand the title the extended-data keys its filter asked for for this
|
||||
// dataType (SDK behaviour). This also keeps server-internal pairs such as
|
||||
// fromAccountId/toAccountId/fromPlatform out of pExtdData.
|
||||
const std::vector<std::string>* wanted_keys = nullptr;
|
||||
for (size_t i = 0; i < flt->filterParams.size(); ++i) {
|
||||
if (ev.dataType == flt->filterParams[i].dataType.val) {
|
||||
if (i < flt->extdDataKeys.size()) {
|
||||
wanted_keys = &flt->extdDataKeys[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto key_requested = [wanted_keys](const std::string& k) {
|
||||
return wanted_keys != nullptr &&
|
||||
std::find(wanted_keys->begin(), wanted_keys->end(), k) !=
|
||||
wanted_keys->end();
|
||||
};
|
||||
std::vector<OrbisNpWebApiExtdPushEventExtdData> exarr;
|
||||
exarr.reserve(ev.extdData.size());
|
||||
for (auto& [k, v] : ev.extdData) {
|
||||
if (!key_requested(k)) {
|
||||
continue;
|
||||
}
|
||||
OrbisNpWebApiExtdPushEventExtdData e{};
|
||||
std::snprintf(e.extdDataKey.val, sizeof(e.extdDataKey.val), "%s",
|
||||
k.c_str());
|
||||
@@ -2186,8 +2220,9 @@ void DrainPushEvents() {
|
||||
title_user_ctx_id, cbId,
|
||||
ev.dataType); // debug confirm the listener callback fires. to be removed
|
||||
reinterpret_cast<ExtdCbA>(raw)(
|
||||
title_user_ctx_id, cbId, svc, flt->npServiceLabel, nullptr, to_p, nullptr,
|
||||
from_p, &dt, ext_data, ev.data.size(), ext_arr, exarr.size(), cb->pUserArg);
|
||||
title_user_ctx_id, cbId, svc, flt->npServiceLabel, to_addr_p, to_p,
|
||||
from_addr_p, from_p, &dt, ext_data, ev.data.size(), ext_arr, exarr.size(),
|
||||
cb->pUserArg);
|
||||
}
|
||||
|
||||
// Service push
|
||||
|
||||
@@ -129,6 +129,7 @@ struct OrbisNpWebApiExtendedPushEventFilter {
|
||||
s32 filterId;
|
||||
bool internal;
|
||||
std::vector<OrbisNpWebApiExtdPushEventFilterParameter> filterParams;
|
||||
std::vector<std::vector<std::string>> extdDataKeys;
|
||||
std::string npServiceName;
|
||||
OrbisNpServiceLabel npServiceLabel;
|
||||
OrbisNpWebApiContext* parentContext;
|
||||
|
||||
@@ -2004,6 +2004,8 @@ s32 PS4_SYSV_ABI sceSystemServiceReceiveEvent(OrbisSystemServiceEvent* event) {
|
||||
|
||||
*event = g_event_queue.front();
|
||||
g_event_queue.pop();
|
||||
LOG_DEBUG(Lib_SystemService, "delivered event type={:#x} ({} still queued)",
|
||||
static_cast<u32>(event->event_type), g_event_queue.size());
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
||||
+15
-4
@@ -978,20 +978,31 @@ void ShadNetClient::HandleNotification(u16 cmd_raw, const std::vector<u8>& paylo
|
||||
if (off + 4 <= static_cast<int>(payload.size())) {
|
||||
const u32 count = GetLE32(payload.data() + off);
|
||||
off += 4;
|
||||
bool extd_complete = count <= 256;
|
||||
for (u32 i = 0; i < count && i < 256; ++i) {
|
||||
if (off + 4 > static_cast<int>(payload.size()))
|
||||
if (off + 4 > static_cast<int>(payload.size())) {
|
||||
extd_complete = false;
|
||||
break;
|
||||
}
|
||||
std::string key = ExtractBlob(payload, off);
|
||||
off += 4 + static_cast<int>(key.size());
|
||||
if (off + 4 > static_cast<int>(payload.size()))
|
||||
if (off + 4 > static_cast<int>(payload.size())) {
|
||||
extd_complete = false;
|
||||
break;
|
||||
}
|
||||
std::string val = ExtractBlob(payload, off);
|
||||
off += 4 + static_cast<int>(val.size());
|
||||
n.extdData.emplace_back(std::move(key), std::move(val));
|
||||
}
|
||||
if (extd_complete && off + 16 <= static_cast<int>(payload.size())) {
|
||||
n.fromAccountId = GetLE64(payload.data() + off);
|
||||
n.toAccountId = GetLE64(payload.data() + off + 8);
|
||||
}
|
||||
}
|
||||
LOG_INFO(ShadNet, "WebApiPushEvent svc='{}' type='{}' from='{}' bytes={} extd={}",
|
||||
n.npServiceName, n.dataType, n.fromNpid, n.data.size(), n.extdData.size());
|
||||
LOG_INFO(ShadNet,
|
||||
"WebApiPushEvent svc='{}' type='{}' from='{}'({}) to='{}'({}) bytes={} extd={}",
|
||||
n.npServiceName, n.dataType, n.fromNpid, n.fromAccountId, n.toNpid, n.toAccountId,
|
||||
n.data.size(), n.extdData.size());
|
||||
if (onWebApiPushEvent)
|
||||
onWebApiPushEvent(n);
|
||||
break;
|
||||
|
||||
@@ -222,6 +222,9 @@ struct NotifyWebApiPushEvent {
|
||||
// Optional extended-data (key,value) pairs (e.g. friendlist trigger/additionalTrigger,
|
||||
// presence gameStatus/gameData). Empty when the server sends none / is older.
|
||||
std::vector<std::pair<std::string, std::string>> extdData;
|
||||
// Optional trailing account ids (server >= push-account-ids). 0 = unknown / not sent.
|
||||
u64 fromAccountId = 0;
|
||||
u64 toAccountId = 0;
|
||||
};
|
||||
|
||||
struct MatchingBinAttr {
|
||||
|
||||
Reference in New Issue
Block a user