internal.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #pragma once
  2. #include <array>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <span>
  6. #include "../../client/network/consumer.h"
  7. #include "../../middleware/bap/activity_message/activity_patch_epoch_parser.h"
  8. #include "../../middleware/bap/activity_message/sensor_auth_update.h"
  9. #include "../../middleware/bap/frame.h"
  10. #include "../../state/activity/bubble_authority/definition.h"
  11. #include "../../state/activity/definition.h"
  12. #include "../../state/build_data/scenarios/definition.h"
  13. #include "../../state/runtime/state.h"
  14. #include "encrypted/queuez/definition.h"
  15. namespace sunrise::server::bap {
  16. /** One session per transport peer slot, so a connection id indexes this array directly. */
  17. inline constexpr std::size_t kSessionCount = client::network::kBapConnectionCount;
  18. /** A delivered activity frame defers the next silence-prevention write by five seconds. */
  19. inline constexpr std::uint64_t kActivityKeepaliveIntervalMs = 5'000;
  20. /** Fixed scratch storage owned by the lock, kept off the Client thread's stack. */
  21. struct Scratch {
  22. std::array<std::byte, client::network::kBapFrameCapacity> plaintext{};
  23. std::array<std::byte, client::network::kBapFrameCapacity> responseBody{};
  24. std::array<std::byte, client::network::kBapFrameCapacity> responsePayload{};
  25. std::array<std::byte, client::network::kBapFrameCapacity> sealed{};
  26. std::array<std::byte, client::network::kBapFrameCapacity> framed{};
  27. /** Roster groups the outbound body's slot spans point into, top-level and per-bubble alike. */
  28. std::array<state::build_data::scenarios::RosterGroup,
  29. middleware::bap::activity_message::sensor_auth_update::kGroupCapacity>
  30. rosterGroups{};
  31. /** Per-bubble sub-blocks the outbound body's field-1 span points into. */
  32. std::array<middleware::bap::activity_message::sensor_auth_update::BubbleSubBlock,
  33. state::build_data::scenarios::kBubbleCapacity>
  34. rosterSubBlocks{};
  35. /** Keys each sub-block carries, which its own span points into. */
  36. std::array<
  37. std::array<std::uint32_t, state::build_data::scenarios::kDestinationBubbleGroupCapacity>,
  38. state::build_data::scenarios::kBubbleCapacity>
  39. rosterSubBlockKeys{};
  40. };
  41. /**
  42. * What one staged roster body owes State, and the counters to put back if it is discarded.
  43. * A bubble is offered once, and the state byte rebuilds every object the roster owns. Both may
  44. * move only once the frame reaches the caller.
  45. */
  46. struct RosterPublication {
  47. state::activity::bubble_authority::Grant grant{};
  48. /** ActivityClient generation that staged this grant and its roster counters. */
  49. std::uint64_t bindingGeneration{};
  50. std::uint32_t priorGroups{};
  51. std::uint8_t priorSends{};
  52. std::uint8_t priorState{};
  53. /** Set when the staged body carried a bubble grant that State has not recorded yet. */
  54. bool hasGrant{};
  55. /** Set while a roster body is staged and its outcome is undecided. */
  56. bool staged{};
  57. };
  58. /** ActivityClient role owned by one authenticated BAP link. */
  59. enum class ActivityClientRole : std::uint8_t {
  60. none,
  61. privateCurrent,
  62. publicTarget,
  63. };
  64. /** Exact activity-session generations owned by one BAP link. */
  65. struct ActivityClientBinding {
  66. /** Target/current session that every activity envelope on this link names. */
  67. state::activity::SessionBinding session{};
  68. /** Same as session for private links; advertised source for public targets. */
  69. state::activity::SessionBinding source{};
  70. std::uint64_t groupSessionId{};
  71. std::uint64_t hostGeneration{};
  72. /** Changes on every bind and rejoin, even when the session id stays the same. */
  73. std::uint64_t bindingGeneration{};
  74. /** Private: last citizen region. Public: immutable region captured by the host binding. */
  75. std::int32_t advertisedRegion{-1};
  76. ActivityClientRole role{ActivityClientRole::none};
  77. };
  78. /** Patch epoch tied to the exact ActivityClient binding that received it. */
  79. struct BoundPatchEpoch {
  80. middleware::bap::activity_message::patch_epoch::PatchEpoch value{};
  81. std::uint64_t bindingGeneration{};
  82. bool seen{};
  83. };
  84. /** Host-session retain staged by one membership body until its frame is published. */
  85. struct AdvertisementPublication {
  86. std::uint64_t hostGeneration{};
  87. bool staged{};
  88. };
  89. /** Mutable transport state owned by one BAP connection. */
  90. struct Session {
  91. std::uint32_t id{};
  92. bool authenticated{};
  93. std::array<std::byte, state::kBapNonceSize> sendNonce{};
  94. std::array<std::byte, state::kBapNonceSize> receiveNonce{};
  95. /** Opaque State handle taken only after the server hello authenticates. */
  96. state::matchmaking::ContextHandle matchmakingContext{};
  97. /** Exact private or public ActivityClient generation owned by this connection. */
  98. ActivityClientBinding activity{};
  99. /** Tick count after which the activity link owes its next keepalive write. */
  100. std::uint64_t activityKeepaliveDueTick{};
  101. /** Client member key from the join request. It seeds the membership id. */
  102. std::uint64_t activityMemberKey{};
  103. /**
  104. * Character the join request named, or zero when it carried none.
  105. * The roster's participation key must be the character the client signed in on. The client
  106. * binds its player by matching that value.
  107. */
  108. std::uint64_t activityCharacterSoid{};
  109. /** Tick count after which the activity link owes its next roster update. */
  110. std::uint64_t activityRosterDueTick{};
  111. /**
  112. * Binding generation whose membership body this link has already delivered.
  113. * The client sets its membership flag once and never clears it, and never acknowledges a body
  114. * on a public-target link, so this is a one-shot per binding. Latched on delivery, not encode.
  115. */
  116. std::uint64_t activityMembershipSentGeneration{};
  117. /**
  118. * Tick count until which the client is loading, so the roster runs at its faster cadence.
  119. * A join and a transition-token change are the only two things that open it.
  120. */
  121. std::uint64_t activityTransitionUntilTick{};
  122. /** The client's own patch epoch, scoped to the binding that received message 52. */
  123. BoundPatchEpoch activityPatchEpoch{};
  124. /** Group set the last roster update published, folded into one comparable value. */
  125. std::uint32_t activityRosterGroups{};
  126. /** Roster updates sent on this connection, capped once the warm-up bumps are spent. */
  127. std::uint8_t activityRosterSends{};
  128. /** Per-entry state byte the last roster update carried. */
  129. std::uint8_t activityRosterState{};
  130. /** Host row retained by the last delivered citizen advertisement. */
  131. std::uint64_t activityAdvertisementHostGeneration{};
  132. /** Host row retained by a staged membership body until publication is known. */
  133. AdvertisementPublication activityAdvertisementStaged{};
  134. /**
  135. * Reason code of the last logged roster outcome.
  136. * The push runs every second, so a refusal is logged only when the reason changes. One flag
  137. * for every reason hides the second failure behind the first.
  138. */
  139. std::uint8_t activityRosterReason{};
  140. /** What one staged roster body owes, and what to put back if it never reaches the caller. */
  141. RosterPublication activityRosterStaged{};
  142. /** Queuez versions and residents published only through this authenticated peer. */
  143. encrypted::queuez::SessionState queuez{};
  144. /** Tick count after which the owed Family-4 re-push may go out. */
  145. std::uint64_t family4RepushDueTick{};
  146. /** Root the owed re-push must use. */
  147. std::uint64_t family4RepushRoot{};
  148. /** True while one Family-4 re-push is still owed to this peer. */
  149. bool family4RepushArmed{};
  150. /** Tick count after which the owed banner re-push may go out. */
  151. std::uint64_t bannerRepushDueTick{};
  152. /** Root the owed banner re-push must use. */
  153. std::uint64_t bannerRepushRoot{};
  154. /** True while one banner re-push is still owed to this peer. */
  155. bool bannerRepushArmed{};
  156. /** Latest shared-account generation this peer has received. */
  157. std::uint64_t accountGeneration{};
  158. /** Newest shared-account generation owed as a full cross-peer refresh. */
  159. std::uint64_t accountResyncGeneration{};
  160. /** Set by encrypted processing only after one account mutation commits and is copied out. */
  161. bool accountMutationPublished{};
  162. /** True while another peer's account mutation still needs a full local refresh. */
  163. bool accountResyncArmed{};
  164. /**
  165. * Tick count after which the owed ability-icon refresh may go out. A subclass selection
  166. * invalidates the published ability buckets and the rebuild runs off the Client
  167. * content-extraction pump, so the inline refresh can carry empty ones; this one re-derives.
  168. */
  169. std::uint64_t abilityRefreshDueTick{};
  170. /** True while one ability-icon refresh is still owed to this peer. */
  171. bool abilityRefreshArmed{};
  172. };
  173. /**
  174. * Arms every active peer to re-read the account, including the one that caused the change.
  175. *
  176. * `publish_account_mutation` deliberately skips the origin, because a web service transaction
  177. * carries the new account back in its own response. A change made outside such a transaction has no
  178. * response to carry, so the peer that caused it would otherwise keep showing stale state until some
  179. * unrelated action happened to stage an image. Picking up a collectible is such a change.
  180. */
  181. void arm_account_resync_everywhere() noexcept;
  182. namespace plaintext {
  183. /**
  184. * Handles plaintext bootstrap services, arms encryption after service 25, and routes the rest.
  185. * @param session Auth and nonce state owned by the connection.
  186. * @param scratch Transform buffers owned by the lock, kept off the Client thread stack.
  187. * @param outer Parsed outer frame carrying the service id and its body.
  188. * @param response Whole-frame storage owned by the caller.
  189. * @param written Gets the encoded response size in bytes.
  190. * @return True when the service owes no reply, or its response is encoded.
  191. */
  192. [[nodiscard]] bool consume(Session& session,
  193. Scratch& scratch,
  194. const middleware::bap::OuterFrame& outer,
  195. std::span<std::byte> response,
  196. std::size_t& written) noexcept;
  197. } // namespace plaintext
  198. namespace encrypted {
  199. /**
  200. * Authenticates and routes one encrypted post-bootstrap service frame.
  201. * @param session Auth and nonce state owned by the connection.
  202. * @param scratch Transform buffers owned by the lock, kept off the Client thread stack.
  203. * @param outer Validated encrypted outer frame.
  204. * @param response Whole-frame storage owned by the caller.
  205. * @param written Gets the encoded response size in bytes.
  206. * @return True when routing works, any response fits, State commits and the nonce is published.
  207. */
  208. [[nodiscard]] bool consume(Session& session,
  209. Scratch& scratch,
  210. const middleware::bap::OuterFrame& outer,
  211. std::span<std::byte> response,
  212. std::size_t& written) noexcept;
  213. /**
  214. * Sends the owed Family-4 re-push once its delay has passed.
  215. * @param session Auth, nonce and queuez state owned by the connection.
  216. * @param scratch Transform buffers owned by the lock, kept off the Client thread stack.
  217. * @param response Whole-frame storage owned by the caller.
  218. * @param written Gets the encoded notification size in bytes.
  219. * @param touchesScratch Set before any scratch buffer is used.
  220. * @return True when a whole Family-4 notification is published.
  221. */
  222. [[nodiscard]] bool consume_deferred(Session& session,
  223. Scratch& scratch,
  224. std::span<std::byte> response,
  225. std::size_t& written,
  226. bool& touchesScratch) noexcept;
  227. } // namespace encrypted
  228. } // namespace sunrise::server::bap