MCPcopy Create free account
hub / github.com/Selectively11/CloudRedirect / hook_NotificationDirect

Function hook_NotificationDirect

src/platform/linux/cloud_hooks.cpp:743–811  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

741}
742
743extern "C" int hook_NotificationDirect(void* pThis, const char* methodName, void* body, int* flags)
744{
745 HookGuard guard;
746 if (g_shuttingDown.load(std::memory_order_acquire)) {
747 auto fn = g_origNotificationDirect.load(std::memory_order_acquire);
748 return fn ? fn(pThis, methodName, body, flags) : 0;
749 }
750 CrashContextScope crashContext("NotificationDirect:entry", methodName, 0);
751 auto origFn = g_origNotificationDirect.load(std::memory_order_acquire);
752 for (int i = 0; !origFn && i < 1000; ++i) {
753 usleep(100);
754 origFn = g_origNotificationDirect.load(std::memory_order_acquire);
755 }
756 if (!origFn) return 0;
757
758 // Only intercept Cloud.* notifications
759 if (!IsCloudRpc(methodName)) {
760 return origFn(pThis, methodName, body, flags);
761 }
762
763 uint32_t appId = CheckNotificationNamespaceApp(methodName, body);
764 CR_SetCrashContext("NotificationDirect:checked", methodName, appId);
765 if (appId == 0) {
766 // Not a namespace app - pass through to Steam servers
767 LOG("[Hook-Notif] %s: not namespace, passing through", methodName);
768 return origFn(pThis, methodName, body, flags);
769 }
770
771 // ExitSyncDone: let Steam process it (updates remotecache.vdf CN).
772 if (strcmp(methodName, CloudIntercept::RPC_EXIT_SYNC) == 0) {
773 CR_SetCrashContext("NotificationDirect:exit-sync", methodName, appId);
774 auto bodyBytes = SerializeMessage(body);
775 auto fields = PB::Parse(bodyBytes.data(), bodyBytes.size());
776 uint64_t clientId = 0;
777 bool uploadsCompleted = false;
778 bool uploadsRequired = false;
779 if (auto* f = PB::FindField(fields, 2)) clientId = f->varintVal;
780 if (auto* f = PB::FindField(fields, 3)) uploadsCompleted = f->varintVal != 0;
781 if (auto* f = PB::FindField(fields, 4)) uploadsRequired = f->varintVal != 0;
782 uint32_t accountId = CloudIntercept::GetAccountId();
783 if (accountId != 0) {
784 PendingOpsJournal::RecordExitSyncState(accountId, appId,
785 uploadsCompleted, uploadsRequired, clientId);
786 // Native-faithful: ExitSyncDone is fire-and-forget (notification, no
787 // response). Dispatch session release off Steam's thread.
788 std::thread([accountId, appId, clientId] {
789 CloudStorage::InflightSyncScope guard;
790 if (!guard.entered) return; // shutting down, skip session release
791 CloudStorage::ReleaseCloudSession(accountId, appId, clientId);
792 }).detach();
793 }
794 LOG("[Hook-Notif] %s app=%u: letting Steam process internally", methodName, appId);
795 return origFn(pThis, methodName, body, flags);
796 }
797
798 // ConflictResolution: parse chose_local_files so HandleLaunchIntent
799 // knows whether to skip pre-restore (user chose "keep local files").
800 if (strcmp(methodName, CloudIntercept::RPC_CONFLICT) == 0) {

Callers

nothing calls this directly

Calls 11

IsCloudRpcFunction · 0.85
CR_SetCrashContextFunction · 0.85
SerializeMessageFunction · 0.85
FindFieldFunction · 0.85
RecordExitSyncStateFunction · 0.85
ReleaseCloudSessionFunction · 0.85
RecordConflictResolutionFunction · 0.85
sizeMethod · 0.80
GetAccountIdFunction · 0.70
ParseFunction · 0.50

Tested by

no test coverage detected