Send schema request.
| 304 | |
| 305 | // Send schema request. |
| 306 | static bool SendSchemaRequest(uint32_t appId, uint64_t ownerId, |
| 307 | void* cmInterface, uint32_t connHandle) { |
| 308 | if (!g_ctor || !g_finalize || !g_cmSend || !g_typedVtable || |
| 309 | !g_defaultInstance || !g_parseFromArray || !cmInterface) |
| 310 | return false; |
| 311 | |
| 312 | // CProtoBufMsg<CMsgClientGetUserStats> on the stack (~44B; over-allocate). |
| 313 | alignas(16) uint8_t msg[128] = {0}; |
| 314 | |
| 315 | CallGuard guard; |
| 316 | int jmpSig = sigsetjmp(g_jmp, 1); |
| 317 | if (jmpSig != 0) { |
| 318 | LOG("[SchemaFetch] SendSchemaRequest app=%u caught signal %d -- aborting", appId, jmpSig); |
| 319 | return false; |
| 320 | } |
| 321 | |
| 322 | g_ctor(msg, (int)EMSG_GET_USER_STATS, 0); |
| 323 | *(void**)(msg + MSG_OFF_VTABLE) = g_typedVtable; |
| 324 | *(void**)(msg + MSG_OFF_DESC) = g_defaultInstance; |
| 325 | g_finalize(msg); |
| 326 | |
| 327 | void* body = *(void**)(msg + MSG_OFF_BODY); |
| 328 | void* hdr = *(void**)(msg + MSG_OFF_HDR); |
| 329 | if (!body || !hdr) { |
| 330 | LOG("[SchemaFetch] app=%u: body=%p hdr=%p NULL -> bail", appId, body, hdr); |
| 331 | return false; |
| 332 | } |
| 333 | |
| 334 | PB::Writer bodyW; |
| 335 | bodyW.WriteFixed64(BODY_GAME_ID, (uint64_t)appId); |
| 336 | bodyW.WriteVarint(BODY_CRC_STATS, 0); |
| 337 | // schema_local_version = -1: sign-extended 64-bit varint (forces "send latest") |
| 338 | bodyW.WriteVarint(BODY_SCHEMA_LOCAL_VERSION, (uint64_t)(int64_t)(-1)); |
| 339 | bodyW.WriteFixed64(BODY_STEAM_ID_FOR_USER, ownerId); |
| 340 | if (!g_parseFromArray(body, bodyW.Data().data(), (int)bodyW.Size())) { |
| 341 | LOG("[SchemaFetch] body ParseFromArray failed for app=%u", appId); |
| 342 | return false; |
| 343 | } |
| 344 | |
| 345 | // jobid_source must be a unique non-negative id (mirrors Windows); the CM |
| 346 | // routes the 819 reply back by it. -1 means "no source job" -> no reply. |
| 347 | static std::atomic<uint64_t> s_jobIdCounter{0x5C00000000000001ull}; |
| 348 | uint64_t jobId = s_jobIdCounter.fetch_add(1, std::memory_order_relaxed); |
| 349 | PB::Writer hdrW; |
| 350 | hdrW.WriteFixed64(HDR_STEAMID, g_steamId.load(std::memory_order_relaxed)); |
| 351 | hdrW.WriteVarint(HDR_SESSION_ID, (uint64_t)(uint32_t)g_sessionId.load(std::memory_order_relaxed)); |
| 352 | hdrW.WriteFixed64(HDR_JOBID_SOURCE, jobId); |
| 353 | hdrW.WriteVarint(HDR_REALM, (uint64_t)g_realm.load(std::memory_order_relaxed)); |
| 354 | // timeout_ms = -1 (no deadline). Required: assertion at msgprotobuf.cpp:980. |
| 355 | hdrW.WriteVarint(HDR_TIMEOUT_MS, (uint64_t)(int64_t)(-1)); |
| 356 | if (!g_parseFromArray(hdr, hdrW.Data().data(), (int)hdrW.Size())) { |
| 357 | LOG("[SchemaFetch] header ParseFromArray failed for app=%u", appId); |
| 358 | return false; |
| 359 | } |
| 360 | |
| 361 | uint8_t sent = g_cmSend(cmInterface, msg); |
| 362 | LOG("[SchemaFetch] SendSchemaRequest app=%u owner=%llu jobid=0x%llX -> %s", |
| 363 | appId, (unsigned long long)ownerId, |
no test coverage detected