internal.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. #pragma once
  2. #include <array>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <span>
  6. #include "../../client/network/consumer.h"
  7. #include "../../core/threading/srw_lock.h"
  8. #include "../../middleware/bap/activity_message/activity_patch_epoch_parser.h"
  9. #include "../../middleware/bap/activity_message/replicate_membership.h"
  10. #include "../../middleware/bap/activity_message/sensor_auth_update.h"
  11. #include "../../middleware/bap/frame.h"
  12. #include "../../middleware/content/packages/tables/scenario_reader.h"
  13. #include "../../state/activity/bubble_authority/definition.h"
  14. #include "../../state/activity/definition.h"
  15. #include "../../state/activity/mission/definition.h"
  16. #include "../../state/activity_sdk/runtime.h"
  17. #include "../../state/build_data/scenarios/definition.h"
  18. #include "../../state/gameplay/external/squad_entity_retirement.h"
  19. #include "../../state/runtime/runtime.h"
  20. #include "../activity/host_runtime.h"
  21. #include "activity_authority_query_owner.h"
  22. #include "activity_authority_reset_owner.h"
  23. #include "encrypted/queuez/definition.h"
  24. #include "runtime.h"
  25. namespace sunrise::server::bap {
  26. /** One session per transport peer slot, so a connection id indexes this array directly. */
  27. inline constexpr std::size_t kSessionCount = client::network::kBapConnectionCount;
  28. /**
  29. * A delivered activity frame defers the next silence-prevention write.
  30. * This is the host's own period. It is not the floor handed to the client, which is a separate
  31. * value, and no bulk body may be scheduled on it.
  32. */
  33. inline constexpr std::uint64_t kActivityKeepaliveIntervalMs = 2'000;
  34. /** Counts matching authenticated links while the caller already owns the BAP lock. */
  35. [[nodiscard]] std::size_t
  36. activity_link_count_locked(const state::activity::SessionBinding& binding) noexcept;
  37. // Top-level groups the client can hold; the largest installed scenario has 78 in every state.
  38. inline constexpr std::size_t kScenarioWideGroupCapacity =
  39. middleware::bap::activity_message::sensor_auth_update::kClientGroupCapacity;
  40. /** Fixed scratch storage owned by the lock, kept off the Client thread's stack. */
  41. struct Scratch {
  42. std::array<std::byte, client::network::kBapFrameCapacity> plaintext{};
  43. std::array<std::byte, client::network::kBapFrameCapacity> responseBody{};
  44. std::array<std::byte, client::network::kBapFrameCapacity> responsePayload{};
  45. std::array<std::byte, client::network::kBapFrameCapacity> sealed{};
  46. std::array<std::byte, client::network::kBapFrameCapacity> framed{};
  47. /** Roster groups the outbound body's slot spans point into, top-level and per-bubble alike. */
  48. std::array<state::build_data::scenarios::RosterGroup,
  49. middleware::bap::activity_message::sensor_auth_update::kPublishedGroupCapacity>
  50. rosterGroups{};
  51. /** One group held aside while the appended groups are put into first-seen order. */
  52. state::build_data::scenarios::RosterGroup rosterGroupSpare{};
  53. /** Groups of the objects present in every state of the bound scenario. */
  54. std::array<state::build_data::scenarios::RosterGroup, kScenarioWideGroupCapacity>
  55. rosterWideGroups{};
  56. /** Exact typed auth bodies the outbound snapshot span points into. */
  57. std::array<middleware::bap::activity_message::sensor_auth_update::AuthOverride,
  58. middleware::bap::activity_message::sensor_auth_update::kAuthOverrideCapacity>
  59. rosterAuthOverrides{};
  60. /** Decoded device channels from the exact Auth rows written by the current roster. */
  61. std::array<state::activity::mission::DevicePublication,
  62. middleware::bap::activity_message::sensor_auth_update::kAuthOverrideCapacity>
  63. rosterDevicePublications{};
  64. std::array<middleware::bap::activity_message::sensor_auth_update::SenseOverride,
  65. middleware::bap::activity_message::sensor_auth_update::kAuthOverrideCapacity>
  66. rosterSenseOverrides{};
  67. /** SDK-authored scene inputs staged before their exact msg-5 targets are installed. */
  68. std::array<state::activity_sdk::AuthoredSceneSeed,
  69. middleware::bap::activity_message::sensor_auth_update::kAuthOverrideCapacity>
  70. rosterSceneSeeds{};
  71. /** Per-bubble sub-blocks the outbound body's field-1 span points into. */
  72. std::array<middleware::bap::activity_message::sensor_auth_update::BubbleSubBlock,
  73. state::build_data::scenarios::kBubbleCapacity>
  74. rosterSubBlocks{};
  75. /** Keys each sub-block carries, which its own span points into. */
  76. std::array<
  77. std::array<std::uint32_t,
  78. middleware::bap::activity_message::sensor_auth_update::kBubbleKeyCapacity>,
  79. state::build_data::scenarios::kBubbleCapacity>
  80. rosterSubBlockKeys{};
  81. };
  82. /** One registry key and its package object tag copied from an exact msg-5 roster snapshot. */
  83. struct RosterDecodeEntry final {
  84. std::uint32_t registryKey{};
  85. std::uint32_t objectTag{};
  86. };
  87. /** Complete msg-5 roster identity map retained for one exact ActivityClient generation. */
  88. struct RosterDecodeMap final {
  89. std::array<RosterDecodeEntry,
  90. middleware::bap::activity_message::sensor_auth_update::kPublishedGroupCapacity>
  91. entries{};
  92. std::uint64_t bindingGeneration{};
  93. std::uint16_t count{};
  94. bool valid{};
  95. };
  96. /**
  97. * One published group's registration identity and the revision last sent beside its key.
  98. * The wire carries one revision byte per key. The client tears down and rebuilds a group's
  99. * objects only when that byte moves, so the byte stays put while the group's identity holds.
  100. */
  101. struct RosterGroupLease {
  102. std::uint32_t key{};
  103. std::uint32_t identityFold{};
  104. /** Bubbles this key was ever registered under; a later push keeps it in every one of them. */
  105. std::uint64_t bubbles{};
  106. std::uint8_t sequence{};
  107. /** Group revision the client last received. A new revision rebuilds the group and its Sense. */
  108. std::uint8_t publishedSequence{};
  109. bool published{};
  110. bool used{};
  111. };
  112. /** Lease slots mirror the roster's published-group capacity. */
  113. inline constexpr std::size_t kRosterGroupLeaseCapacity =
  114. middleware::bap::activity_message::sensor_auth_update::kPublishedGroupCapacity;
  115. /**
  116. * What one staged roster body owes State, and the counters to put back if it is discarded.
  117. * A bubble is offered once, and each group revision may rebuild that registry key. Counters and
  118. * staged per-group revisions may move only once the frame reaches the caller.
  119. */
  120. struct RosterPublication {
  121. state::activity::bubble_authority::Grant grant{};
  122. state::gameplay::squad_entity_retirement::RetirementPlan entityRetirement{};
  123. /** Epochs remain staged until both retirement and roster frames reach the caller. */
  124. std::uint8_t retirementPriorEpoch{};
  125. std::uint8_t retirementBaseEpoch{};
  126. std::uint8_t retirementEpoch{};
  127. bool priorRosterOwedForEpoch{};
  128. /** Exact decode identities carried by this staged complete roster snapshot. */
  129. RosterDecodeMap decodeMap{};
  130. /** These proofs become report eligibility only after the frame reaches the caller. */
  131. std::array<state::activity::mission::DevicePublication,
  132. middleware::bap::activity_message::sensor_auth_update::kAuthOverrideCapacity>
  133. devicePublications{};
  134. state::activity::mission::DevicePublicationBoundary devicePublicationBoundary{};
  135. state::activity::SessionBinding devicePublicationBinding{};
  136. std::uint16_t devicePublicationCount{};
  137. /** Exact typed body carried by this staged roster, if any. */
  138. activity::host::PendingScriptableOverride scriptableOverride{};
  139. /** ActivityClient generation that staged this grant and its roster counters. */
  140. std::uint64_t bindingGeneration{};
  141. /** Group leases as they stood before this body, put back if it never reaches the caller. */
  142. std::array<RosterGroupLease, kRosterGroupLeaseCapacity> priorLeases{};
  143. std::uint8_t priorSends{};
  144. std::uint8_t priorState{};
  145. /** Region epoch and the bubble it was stamped for, put back with the leases above. */
  146. std::uint8_t priorRegionEpoch{};
  147. std::int32_t priorRegionBubble{-1};
  148. /** Generated squad-group revision carried by this staged body. */
  149. std::uint8_t squadStateSequence{};
  150. /** Activity Host state revision carried by this body. */
  151. std::uint64_t hostStateRevision{};
  152. /** SDK selected-state roster lease revision carried by this body. */
  153. std::uint64_t missionSeedRevision{};
  154. /** Type-17 lifetime state carried for that revision. */
  155. std::uint8_t hostLifetimeState{};
  156. /** Exact authored region that owns the staged state-local group. */
  157. std::int32_t stateLocalRegion{-1};
  158. /** Set when the staged body carried a bubble grant that State has not recorded yet. */
  159. bool hasGrant{};
  160. /** Set when this body carries a pending Activity Host state revision. */
  161. bool hasHostState{};
  162. /** Set when this body carries a not-yet-published SDK selected-state roster lease revision. */
  163. bool hasMissionSeedRevision{};
  164. /** Set when this body carries the pending typed body above. */
  165. bool hasScriptableOverride{};
  166. /** Set when the delivered body merges into this binding's retained squad Auth set. */
  167. bool activatesSquadOverride{};
  168. /** Set when the staged squad body carries its own per-group revision. */
  169. bool hasSquadStateSequence{};
  170. /** Set when this body is the leave delta answering activity msg 15. */
  171. bool peerLeave{};
  172. /** Set when this body carries the team wait bit, built before the client's arrival report. */
  173. bool awaitClientSync{};
  174. /** Set while a roster body is staged and its outcome is undecided. */
  175. bool staged{};
  176. };
  177. /** Compact retained squad body; shared target fields and the generated group live on its group. */
  178. struct RetainedSquadAuth {
  179. std::array<std::byte, middleware::bap::activity_message::squad_auth::kMaximumRetainedByteCount>
  180. body{};
  181. std::uint32_t generation{};
  182. std::uint16_t rosterSlotOffset{};
  183. std::uint16_t slotIndex{};
  184. std::uint16_t bitCount{};
  185. std::uint16_t byteCount{};
  186. /** Dense retained-group index that owns this body. */
  187. std::uint8_t groupIndex{};
  188. };
  189. /** One generated registry key and the squad Auth bodies that target its slots. */
  190. struct RetainedSquadGroup {
  191. /** Fields shared by this group's retained slots; only slot offset and index vary. */
  192. activity::host::ScriptableTarget scopeTarget{};
  193. /** Exact generated SDK group shared by this group's retained slots. */
  194. state::build_data::scenarios::RosterGroup stateLocalRosterGroup{};
  195. std::int32_t region{-1};
  196. std::uint16_t authCount{};
  197. /** Last delivered revision of the generated state-local roster group. */
  198. std::uint8_t stateSequence{};
  199. /** Region epoch the revision was armed under; a newer one re-arms the group. */
  200. std::uint8_t regionEpoch{};
  201. };
  202. /** All generated squad groups retained by one exact ActivityClient binding. */
  203. struct SquadOverrideLease {
  204. std::array<RetainedSquadAuth,
  205. middleware::bap::activity_message::sensor_auth_update::kAuthOverrideCapacity>
  206. authBodies{};
  207. std::array<RetainedSquadGroup,
  208. middleware::bap::activity_message::sensor_auth_update::kPublishedGroupCapacity>
  209. groups{};
  210. std::uint64_t bindingGeneration{};
  211. std::uint16_t authCount{};
  212. std::uint16_t groupCount{};
  213. bool active{};
  214. };
  215. /** Off-by-default generated selected-state roster plan pinned to one exact ActivityClient
  216. * generation. */
  217. struct MissionSeedLease {
  218. ActivityMissionSeedPlan plan{};
  219. std::uint64_t bindingGeneration{};
  220. std::uint64_t revision{};
  221. std::uint64_t publishedRevision{};
  222. /**
  223. * Every authored region this lease has selected, in selection order. The peer's registered set
  224. * only grows: a group is torn down by a changed state byte, never by being left out, and every
  225. * message must seed its sync records. So each publication carries the union of these regions.
  226. */
  227. std::array<std::uint32_t, middleware::content::packages::tables::kSliceSetIndexFactor>
  228. registeredRegions{};
  229. std::uint8_t registeredRegionCount{};
  230. bool configured{};
  231. /**
  232. * Set once the complete selected-state set has been published. It only ratchets: shrinking
  233. * the published set back to the transition subset would re-register the shared groups.
  234. */
  235. bool fullSetPublished{};
  236. /**
  237. * The plan the previous selection held, kept while a region change waits for the client to
  238. * arrive. Publications in that window answer this plan's region: the client is tearing its
  239. * old world down, and registering the new region's groups into it races the teardown.
  240. */
  241. ActivityMissionSeedPlan previousPlan{};
  242. /** True from a region-changing selection until the client's post-arrival solicited answer. */
  243. bool regionArrivalPending{};
  244. /** Set when a mission script selected the plan. An adopted default plan is not a selection. */
  245. bool scriptSelected{};
  246. };
  247. static_assert(middleware::bap::activity_message::sensor_auth_update::kAuthOverrideCapacity
  248. == state::build_data::scenarios::kRosterSlotCapacity);
  249. /** ActivityClient role owned by one authenticated BAP link. */
  250. enum class ActivityClientRole : std::uint8_t {
  251. none,
  252. privateCurrent,
  253. publicTarget,
  254. };
  255. /** Exact activity-session generations owned by one BAP link. */
  256. struct ActivityClientBinding {
  257. /** Target/current session that every activity envelope on this link names. */
  258. state::activity::SessionBinding session{};
  259. /** Same as session for private links; advertised source for public targets. */
  260. state::activity::SessionBinding source{};
  261. std::uint64_t groupSessionId{};
  262. std::uint64_t hostGeneration{};
  263. /** Changes on every bind and rejoin, even when the session id stays the same. */
  264. std::uint64_t bindingGeneration{};
  265. /** Epoch this host authored in the accepted join result. */
  266. std::uint8_t replicationEpoch{};
  267. /** Private: last citizen region. Public: immutable region captured by the host binding. */
  268. std::int32_t advertisedRegion{-1};
  269. /** True when the last advertisement named a private region's own Bubble Host. */
  270. bool advertisedPrivate{};
  271. ActivityClientRole role{ActivityClientRole::none};
  272. };
  273. /** Patch epoch tied to the exact ActivityClient binding that received it. */
  274. struct BoundPatchEpoch {
  275. middleware::bap::activity_message::patch_epoch::PatchEpoch value{};
  276. std::uint64_t bindingGeneration{};
  277. bool seen{};
  278. };
  279. /** Host rows one membership body's directory holds against replacement. */
  280. struct AdvertisementRetains {
  281. std::array<std::uint64_t,
  282. middleware::bap::activity_message::replicate_membership::kCitizenCapacity>
  283. hostGenerations{};
  284. std::uint8_t count{};
  285. };
  286. /** Host-session retains staged by one membership body until its frame is published. */
  287. struct AdvertisementPublication {
  288. AdvertisementRetains retains{};
  289. bool staged{};
  290. };
  291. /** One staged msg-19 host output, committed only after its complete frame reaches the caller. */
  292. struct IncidentPublication {
  293. std::uint64_t bindingGeneration{};
  294. std::uint64_t revision{};
  295. bool staged{};
  296. };
  297. /** One generation-bound activity message 44 request. */
  298. struct ReplicationEpochPublication {
  299. std::uint64_t bindingGeneration{};
  300. std::uint8_t generation{};
  301. bool pending{};
  302. bool staged{};
  303. };
  304. /** Which inventory one world reward lands in. */
  305. enum class WorldRewardKind : std::uint8_t {
  306. item,
  307. profileItem,
  308. };
  309. /** One reward earned in world, held until a Family-4 peer can publish it. */
  310. struct WorldRewardRequest {
  311. std::uint64_t id{};
  312. std::int32_t quantity{};
  313. std::uint16_t itemDefinitionIndex{};
  314. WorldRewardKind kind{};
  315. };
  316. /** The changed character projections still owed after their source state commits. */
  317. enum class CharacterRefreshScope : std::uint8_t { none, records, recordsAndRoster };
  318. /** Mutable transport state owned by one BAP connection. */
  319. struct Session {
  320. std::uint64_t activityAdvertisementHostGeneration{};
  321. std::uint64_t acquisitionPresentationUntilTick{};
  322. std::array<encrypted::queuez::AcquisitionPresentationRow,
  323. encrypted::queuez::kAcquisitionPresentationRowCapacity>
  324. acquisitionPresentationRows{};
  325. std::uint32_t id{};
  326. std::uint32_t activityRosterGroups{};
  327. std::int32_t pendingSeasonalExperienceAmount{};
  328. std::uint32_t pendingSeasonalExperienceMutationSerial{};
  329. bool authenticated{};
  330. /** Owes one family-five snapshot for the unlock overrides an artifact change moved. */
  331. bool artifactRefreshArmed{};
  332. bool artifactFamily4RefreshArmed{};
  333. std::uint64_t artifactFamily4RefreshDueTick{};
  334. state::ArtifactResetResult artifactResetRefresh{};
  335. std::size_t artifactResetRefreshCursor{};
  336. std::uint8_t acquisitionPresentationRowCount{};
  337. std::array<std::byte, state::kBapNonceSize> sendNonce{};
  338. std::array<std::byte, state::kBapNonceSize> receiveNonce{};
  339. /** This connection's own AES-GCM key. Sharing one across links reuses key and nonce pairs. */
  340. std::array<std::byte, state::kAesKeySize> sessionKey{};
  341. /** Opaque State handle taken only after the server hello authenticates. */
  342. state::matchmaking::ContextHandle matchmakingContext{};
  343. /** Exact private or public ActivityClient generation owned by this connection. */
  344. ActivityClientBinding activity{};
  345. /** Tick count after which the activity link owes its next keepalive write. */
  346. std::uint64_t activityKeepaliveDueTick{};
  347. /** Client member key from the join request. It seeds the membership id. */
  348. std::uint64_t activityMemberKey{};
  349. /** Binding generation whose entity-slot join committed, including a zero member key. */
  350. std::uint64_t activityJoinGeneration{};
  351. /**
  352. * Character the join request named, or zero when it carried none.
  353. * The roster's participation key must be the character the client signed in on. The client
  354. * binds its player by matching that value.
  355. */
  356. std::uint64_t activityCharacterSoid{};
  357. /**
  358. * Binding generation whose membership body this link has already delivered.
  359. * The client sets its membership flag once and never clears it, and never acknowledges a body
  360. * on a public-target link, so this is a one-shot per binding. Latched on delivery, not encode.
  361. */
  362. std::uint64_t activityMembershipSentGeneration{};
  363. /** Binding generation whose client-authored type-23 identity has committed. */
  364. std::uint64_t activityClientIdentitySeenGeneration{};
  365. /**
  366. * Binding generation whose committed type-23 identity reached the client in membership.
  367. * The initial roster must not consume its object-rebuild revisions before this latch.
  368. */
  369. std::uint64_t activityClientIdentityPublishedGeneration{};
  370. /**
  371. * Set when the join burst staged a membership body, and read once the frame is published.
  372. * The generation it belongs to does not exist until publication, so the latch cannot be written
  373. * at staging time.
  374. */
  375. bool activityJoinMembershipStaged{};
  376. /** The client's own patch epoch, scoped to the binding that received message 52. */
  377. BoundPatchEpoch activityPatchEpoch{};
  378. /** Replication epoch held until its encrypted frame reaches the transport caller. */
  379. ReplicationEpochPublication activityReplicationEpoch{};
  380. /** Per published group key: its registration identity and the revision the client holds. */
  381. std::array<RosterGroupLease, kRosterGroupLeaseCapacity> activityRosterGroupLeases{};
  382. /** Bubbles in the order their sub-block first went out; the client keys them by position. */
  383. std::array<std::uint8_t, state::build_data::scenarios::kBubbleCapacity>
  384. activityRosterBubbleOrder{};
  385. std::size_t activityRosterBubbleOrderCount{};
  386. /** Per bubble, its keys in the order they first went out; a later key only appends. */
  387. std::array<
  388. std::array<std::uint32_t,
  389. middleware::bap::activity_message::sensor_auth_update::kBubbleKeyCapacity>,
  390. state::build_data::scenarios::kBubbleCapacity>
  391. activityRosterBubbleKeyOrder{};
  392. std::array<std::size_t, state::build_data::scenarios::kBubbleCapacity>
  393. activityRosterBubbleKeyOrderCount{};
  394. /**
  395. * A roster answer was refused for want of the client's patch epoch, and is still owed.
  396. * The epoch arriving is what makes that answer possible, so message 52 discharges it.
  397. */
  398. bool activityRosterOwedForEpoch{};
  399. /**
  400. * Binding generation whose leave delta reached the client, or zero.
  401. * The client reported it is leaving, so no later roster may go out on that link.
  402. */
  403. std::uint64_t activityLeftGeneration{};
  404. /**
  405. * Region-rebuild epoch, folded into every group's identity. It advances once per region
  406. * transition so every group's revision byte moves and the client re-registers the groups for
  407. * the region it entered. Without that move, object intents into the new bubble are refused.
  408. */
  409. std::uint8_t activityRosterRegionEpoch{};
  410. /** Bubble the epoch was stamped for; a change in it is the region transition. */
  411. std::int32_t activityRosterRegionBubble{-1};
  412. /** One-shot first-roster flag; the mission seed's adoption guard reads it. */
  413. std::uint8_t activityRosterSends{};
  414. /** Group-revision allocator; each value is spent on one group registration change. */
  415. std::uint8_t activityRosterState{};
  416. /** Latest Activity Host revision staged into this connection's transport output. */
  417. std::uint64_t activityHostStateRevision{};
  418. /** The delivered roster carries the team wait bit; the arrival report is answered while set. */
  419. bool activityRosterAwaitClientSync{};
  420. /** One bounded authority-mask readback owned by this exact ActivityClient generation. */
  421. authority_query::Owner activityAuthorityQuery{};
  422. /** One bounded authority-mask reset owned by this exact ActivityClient generation. */
  423. authority_reset::Owner activityAuthorityReset{};
  424. /** Operator incident held until the complete encrypted frame reaches the transport caller. */
  425. IncidentPublication activityIncidentStaged{};
  426. /** Earliest tick at which a refused incident frame may be rebuilt. */
  427. std::uint64_t activityIncidentRetryDueTick{};
  428. /** Host rows retained by the last delivered host directory. */
  429. AdvertisementRetains activityAdvertisementHeld{};
  430. /** Host rows retained by a staged membership body until publication is known. */
  431. AdvertisementPublication activityAdvertisementStaged{};
  432. /**
  433. * Reason code of the last logged roster outcome.
  434. * The push runs every second, so a refusal is logged only when the reason changes. One flag
  435. * for every reason hides the second failure behind the first.
  436. */
  437. std::uint8_t activityRosterReason{};
  438. /** What one staged roster body owes, and what to put back if it never reaches the caller. */
  439. RosterPublication activityRosterStaged{};
  440. /** Last complete msg-5 roster known to have reached this exact connection generation. */
  441. RosterDecodeMap activityRosterDecode{};
  442. /** Delivered squad Auth bodies, all re-emitted so phase-2 reset cannot clear any slot. */
  443. SquadOverrideLease activitySquadOverride{};
  444. /** Generated selected-state roster lease. Disabled until an operator enables its SDK row. */
  445. MissionSeedLease activityMissionSeed{};
  446. /** Queuez versions and residents published only through this authenticated peer. */
  447. encrypted::queuez::SessionState queuez{};
  448. /** Tick count after which the owed Family-4 re-push may go out. */
  449. std::uint64_t family4RepushDueTick{};
  450. /** Root the owed re-push must use. */
  451. std::uint64_t family4RepushRoot{};
  452. /** True while one Family-4 re-push is still owed to this peer. */
  453. bool family4RepushArmed{};
  454. /** Tick count after which the owed banner re-push may go out. */
  455. std::uint64_t bannerRepushDueTick{};
  456. /** Root the owed banner re-push must use. */
  457. std::uint64_t bannerRepushRoot{};
  458. /** True while one banner re-push is still owed to this peer. */
  459. bool bannerRepushArmed{};
  460. /** Root the last family-two subscribe was answered against, and the re-push must reuse. */
  461. std::uint64_t socialRosterRepushRoot{};
  462. /** True while one family-two re-push is still owed to this peer. */
  463. bool socialRosterRepushArmed{};
  464. /** Latest shared-account generation this peer has received. */
  465. std::uint64_t accountGeneration{};
  466. /** Newest shared-account generation owed as a full cross-peer refresh. */
  467. std::uint64_t accountResyncGeneration{};
  468. /** Set by encrypted processing only after one account mutation commits and is copied out. */
  469. bool accountMutationPublished{};
  470. /** True while another peer's account mutation still needs a full local refresh. */
  471. bool accountResyncArmed{};
  472. /**
  473. * Tick count after which the owed ability-icon refresh may go out. A subclass selection
  474. * invalidates the published ability buckets and the rebuild runs off the Client
  475. * content-extraction pump, so the inline refresh can carry empty ones; this one re-derives.
  476. */
  477. std::uint64_t abilityRefreshDueTick{};
  478. /** A roster change remains owed when later socket changes also refresh the character. */
  479. CharacterRefreshScope characterRefreshScope{};
  480. /**
  481. * True while the launch cinematic hold has parked the account player-record for this peer.
  482. * Set when the family-0 park push is armed on a loading launch, cleared when arrival arms the
  483. * family-4 completion that resolves it. Gates the two phases so each fires once per launch.
  484. */
  485. bool cinematicHeld{};
  486. };
  487. /** Guards the session table; hold it for the whole event and never re-enter it from a route. */
  488. [[nodiscard]] core::threading::SrwLock& session_lock() noexcept;
  489. /** @return Every session slot, open or not. Caller owns the session lock. */
  490. [[nodiscard]] std::span<Session> sessions() noexcept;
  491. /** @return True while any authenticated peer holds a Family-4 subscription. */
  492. [[nodiscard]] bool has_active_family4_peer() noexcept;
  493. /**
  494. * Finds one exact authenticated ActivityClient while the caller owns the session lock.
  495. * @param binding Exact Activity Host generation selected by the caller.
  496. * @param count Receives how many links own the binding.
  497. * @return The link when exactly one owns the binding, else null.
  498. */
  499. [[nodiscard]] const Session*
  500. unique_activity_link_locked(const state::activity::SessionBinding& binding,
  501. std::size_t& count) noexcept;
  502. /** @return Region index this connection's msg-5 builder selects. Caller owns the session lock. */
  503. [[nodiscard]] std::int32_t selected_region_index_locked(const Session& session) noexcept;
  504. /** Loads the scenario layout one lock-held ActivityClient owns. @return False when it has none. */
  505. [[nodiscard]] bool
  506. session_scenario_layout(const Session& session,
  507. state::build_data::scenarios::Definition& output) noexcept;
  508. /** Commits every queued world reward with no presentation and empties the queue. */
  509. void drain_world_rewards() noexcept;
  510. /** Arms every other Family-4 peer after the origin publishes a complete account mutation. */
  511. void arm_account_resync_elsewhere(Session& origin) noexcept;
  512. /** Arms every Family-4 peer, including the origin, for a full account resync. */
  513. void arm_account_resync_everywhere() noexcept;
  514. /** Holds this peer's full Family-4 refreshes until its acquisition flyout has finished. */
  515. void arm_acquisition_presentation_hold(Session& session) noexcept;
  516. /** Queues one character item for normal acquisition feedback. */
  517. [[nodiscard]] bool arm_world_item_acquisition(std::uint16_t itemDefinitionIndex) noexcept;
  518. /** Queues one profile material for normal acquisition feedback. */
  519. [[nodiscard]] bool arm_world_profile_item_acquisition(std::uint16_t itemDefinitionIndex,
  520. std::int32_t quantity) noexcept;
  521. /** Reads the oldest queued world reward without removing it. */
  522. [[nodiscard]] bool current_world_reward(WorldRewardRequest& request) noexcept;
  523. /** Removes the world reward returned by current_world_reward. */
  524. [[nodiscard]] bool complete_world_reward(std::uint64_t id) noexcept;
  525. /** Commits the queued reward with no flyout once its presentation cannot be built. */
  526. void settle_world_reward() noexcept;
  527. /** Queues one transient XP item update so the native HUD presents a seasonal XP gain. */
  528. [[nodiscard]] bool arm_seasonal_experience_presentation(std::int32_t amount) noexcept;
  529. /**
  530. * Finds one unambiguous registry identity in a committed connection-local roster map.
  531. * @param map Last complete msg-5 map delivered on one BAP connection.
  532. * @param expectedBindingGeneration Exact ActivityClient generation routing the client message.
  533. * @param registryKey Client-reported registry key from that roster.
  534. * @return The unique entry, or null for an invalid/stale map, absent key, or duplicate key.
  535. */
  536. [[nodiscard]] const RosterDecodeEntry*
  537. find_roster_decode_entry(const RosterDecodeMap& map,
  538. std::uint64_t expectedBindingGeneration,
  539. std::uint32_t registryKey) noexcept;
  540. namespace plaintext {
  541. /**
  542. * Handles plaintext bootstrap services, arms encryption after service 25, and routes the rest.
  543. * @param session Auth and nonce state owned by the connection.
  544. * @param scratch Transform buffers owned by the lock, kept off the Client thread stack.
  545. * @param outer Parsed outer frame carrying the service id and its body.
  546. * @param response Whole-frame storage owned by the caller.
  547. * @param written Gets the encoded response size in bytes.
  548. * @return True when the service owes no reply, or its response is encoded.
  549. */
  550. [[nodiscard]] bool consume(Session& session,
  551. Scratch& scratch,
  552. const middleware::bap::OuterFrame& outer,
  553. std::span<std::byte> response,
  554. std::size_t& written) noexcept;
  555. } // namespace plaintext
  556. namespace encrypted {
  557. /**
  558. * Authenticates and routes one encrypted post-bootstrap service frame.
  559. * @param session Auth and nonce state owned by the connection.
  560. * @param scratch Transform buffers owned by the lock, kept off the Client thread stack.
  561. * @param outer Validated encrypted outer frame.
  562. * @param response Whole-frame storage owned by the caller.
  563. * @param written Gets the encoded response size in bytes.
  564. * @return True when routing works, any response fits, State commits and the nonce is published.
  565. */
  566. [[nodiscard]] bool consume(Session& session,
  567. Scratch& scratch,
  568. const middleware::bap::OuterFrame& outer,
  569. std::span<std::byte> response,
  570. std::size_t& written) noexcept;
  571. /**
  572. * Sends the owed Family-4 re-push once its delay has passed.
  573. * @param session Auth, nonce and queuez state owned by the connection.
  574. * @param scratch Transform buffers owned by the lock, kept off the Client thread stack.
  575. * @param response Whole-frame storage owned by the caller.
  576. * @param written Gets the encoded notification size in bytes.
  577. * @param touchesScratch Set before any scratch buffer is used.
  578. * @return True when a whole Family-4 notification is published.
  579. */
  580. [[nodiscard]] bool consume_deferred(Session& session,
  581. Scratch& scratch,
  582. std::span<std::byte> response,
  583. std::size_t& written,
  584. bool& touchesScratch) noexcept;
  585. } // namespace encrypted
  586. } // namespace sunrise::server::bap