internal.h 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. #pragma once
  2. #include <array>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <memory>
  6. #include <new>
  7. #include <optional>
  8. #include <span>
  9. #include <string_view>
  10. #include <type_traits>
  11. #include <utility>
  12. #include <variant>
  13. #include "../../../middleware/bap/family_unsubscription.h"
  14. #include "../../../middleware/bap/frame.h"
  15. #include "../../../middleware/queuez/subscription.h"
  16. #include "../../web_service/web_service_runtime.h"
  17. #include "../internal.h"
  18. #include "activity_message/definition.h"
  19. #include "queuez/definition.h"
  20. #include "transactions/definition.h"
  21. namespace sunrise::server::bap::encrypted {
  22. /** Response-body codecs picked by the authenticated request service. */
  23. enum class BodyCodec : std::uint8_t {
  24. empty,
  25. accountTranslationResponse,
  26. activityHostManagerResponse,
  27. activityMessageRequest,
  28. activityHostResponse,
  29. clientConfigResponse,
  30. familySubscription,
  31. familyUnsubscription,
  32. matchmakingResponse,
  33. steamCertificate,
  34. userMessageResponse,
  35. webService,
  36. };
  37. /** Equipment mutation and the exact QueueZ after-image promised by its response. */
  38. struct EquipmentSwapTransaction {
  39. std::unique_ptr<state::PendingEquipmentSwap> pending{};
  40. queuez::EquipmentSwap update{};
  41. };
  42. /** Socket mutation and the exact QueueZ after-image promised by its response. */
  43. struct SocketPlugTransaction {
  44. std::unique_ptr<state::PendingSocketPlug> pending{};
  45. queuez::SocketPlug update{};
  46. };
  47. /** Subclass ability selection and the exact QueueZ after-image promised by its response. */
  48. struct SubclassSelectionTransaction {
  49. std::unique_ptr<state::PendingSubclassSelection> pending{};
  50. queuez::SubclassSelection update{};
  51. };
  52. /** Item-state mutation and the exact QueueZ character after-image promised by its response. */
  53. struct ItemStateTransaction {
  54. std::unique_ptr<state::PendingItemState> pending{};
  55. queuez::EquipmentSwap update{};
  56. };
  57. /** Artifact purchase and the exact selected-character after-image promised by opcode 901. */
  58. struct ArtifactPurchaseTransaction {
  59. std::unique_ptr<state::PendingArtifactPurchase> pending{};
  60. queuez::EquipmentSwap update{};
  61. };
  62. /** Current-activity mutation and the exact QueueZ character after-image sent with its reply. */
  63. struct CurrentActivityTransaction {
  64. state::PendingCurrentActivity pending{};
  65. queuez::EquipmentSwap update{};
  66. };
  67. /** Character acquisition and its exact QueueZ after-image. */
  68. struct ItemAcquisitionTransaction {
  69. std::unique_ptr<state::PendingItemAcquisition> pending{};
  70. queuez::ItemAcquisition update{};
  71. };
  72. /** Profile acquisition and its exact account/resident QueueZ after-image. */
  73. struct ProfileItemAcquisitionTransaction {
  74. std::unique_ptr<state::PendingProfileItemAcquisition> pending{};
  75. queuez::ProfileItemAcquisition update{};
  76. };
  77. /** Dismantle mutation and its exact QueueZ after-image. */
  78. struct ItemDismantleTransaction {
  79. std::unique_ptr<state::PendingItemDismantle> pending{};
  80. queuez::ItemDismantle update{};
  81. };
  82. /** Record-claim reward batch and its exact Queuez after-image. */
  83. struct RecordRewardGrantTransaction {
  84. std::unique_ptr<state::PendingRecordRewardGrant> pending{};
  85. queuez::RecordRewardGrant update{};
  86. };
  87. /** Season reward grant plus the exact Queuez after-image promised by opcode 2400. */
  88. struct SeasonPassRewardTransaction {
  89. std::unique_ptr<state::PendingSeasonPassReward> pending{};
  90. std::variant<std::monostate,
  91. queuez::ItemAcquisition,
  92. queuez::ProfileItemAcquisition,
  93. queuez::RecordRewardGrant>
  94. update{};
  95. };
  96. /** Optional side effect produced while decoding one authenticated service body. */
  97. struct ServiceOutcome {
  98. bool hasSubscription{};
  99. /** A Triumph claim changed the account flag bank and its image has to follow. */
  100. bool hasRecordClaim{};
  101. bool hasArtifactReset{};
  102. state::ArtifactResetResult artifactReset{};
  103. middleware::queuez::Subscription subscription{};
  104. bool hasUnsubscription{};
  105. middleware::bap::family_unsubscription::Request unsubscription{};
  106. bool hasChangeCharacter{};
  107. bool hasSelectCharacter{};
  108. /** One service owns at most one independently versioned, exact-sized transaction. */
  109. using Transaction = std::variant<std::monostate,
  110. std::unique_ptr<state::activity::PendingAllocation>,
  111. std::unique_ptr<activity_message::ActivityPlan>,
  112. std::unique_ptr<state::matchmaking::PendingMutation>,
  113. std::unique_ptr<queuez::ChangeCharacter>,
  114. std::unique_ptr<queuez::SelectCharacter>,
  115. std::unique_ptr<EquipmentSwapTransaction>,
  116. std::unique_ptr<SubclassSelectionTransaction>,
  117. std::unique_ptr<SocketPlugTransaction>,
  118. std::unique_ptr<ItemStateTransaction>,
  119. std::unique_ptr<ArtifactPurchaseTransaction>,
  120. std::unique_ptr<CurrentActivityTransaction>,
  121. std::unique_ptr<ItemAcquisitionTransaction>,
  122. std::unique_ptr<ProfileItemAcquisitionTransaction>,
  123. std::unique_ptr<ItemDismantleTransaction>,
  124. std::unique_ptr<RecordRewardGrantTransaction>,
  125. std::unique_ptr<SeasonPassRewardTransaction>,
  126. std::unique_ptr<state::PendingSettingsUpdate>>;
  127. Transaction transaction{};
  128. };
  129. /** Allocates only the selected transaction outside the request's already deep call stack. */
  130. template <typename Transaction, typename... Args>
  131. [[nodiscard]] Transaction* emplace_transaction(ServiceOutcome& outcome, Args&&... args) noexcept {
  132. static_assert(std::is_nothrow_constructible_v<Transaction, Args...>);
  133. outcome.transaction.template emplace<std::monostate>();
  134. auto storage =
  135. std::unique_ptr<Transaction>{new (std::nothrow) Transaction(std::forward<Args>(args)...)};
  136. if (storage == nullptr) {
  137. return nullptr;
  138. }
  139. auto* transaction = storage.get();
  140. outcome.transaction.template emplace<std::unique_ptr<Transaction>>(std::move(storage));
  141. return transaction;
  142. }
  143. /** @return The service transaction of the requested type, or null for another route. */
  144. template <typename Transaction>
  145. [[nodiscard]] Transaction* transaction_if(ServiceOutcome& outcome) noexcept {
  146. auto* storage = std::get_if<std::unique_ptr<Transaction>>(&outcome.transaction);
  147. return storage == nullptr ? nullptr : storage->get();
  148. }
  149. /** @return The service transaction of the requested type, or null for another route. */
  150. template <typename Transaction>
  151. [[nodiscard]] const Transaction* transaction_if(const ServiceOutcome& outcome) noexcept {
  152. const auto* storage = std::get_if<std::unique_ptr<Transaction>>(&outcome.transaction);
  153. return storage == nullptr ? nullptr : storage->get();
  154. }
  155. [[nodiscard]] inline bool has_transaction(const ServiceOutcome& outcome) noexcept {
  156. return outcome.transaction.index() != 0;
  157. }
  158. inline void clear_transaction(ServiceOutcome& outcome) noexcept {
  159. outcome.transaction.template emplace<std::monostate>();
  160. }
  161. /** Outbound delivery behavior picked for one authenticated request service. */
  162. enum class ResponseMode : std::uint8_t {
  163. none,
  164. reply,
  165. /** Processes a request body and may emit notifications without a status response. */
  166. uncorrelatedPush,
  167. };
  168. /** Static response metadata for one supported encrypted request service. */
  169. struct ServiceRoute {
  170. ResponseMode responseMode{};
  171. middleware::bap::ResponseService response{};
  172. BodyCodec bodyCodec{};
  173. };
  174. /** Owns encrypted service-to-response routing. */
  175. namespace routing {
  176. [[nodiscard]] bool resolve(std::uint16_t request, ServiceRoute& route) noexcept;
  177. } // namespace routing
  178. /** Owns failure reporting for encrypted requests. */
  179. namespace diagnostics {
  180. void report_failure(std::uint16_t service, std::string_view stage) noexcept;
  181. /** Reports one refusal that names which branch refused. */
  182. void report_failure(std::uint16_t service,
  183. std::string_view stage,
  184. std::string_view reason) noexcept;
  185. } // namespace diagnostics
  186. /** Owns correlated reply construction for one authenticated request. */
  187. namespace reply {
  188. /**
  189. * Encodes, seals, and frames one correlated status-200 reply.
  190. * @param scratch Lock-owned transform buffers.
  191. * @param route Service route data naming the response service.
  192. * @param taskId Request correlation id to echo.
  193. * @param key Active AES-GCM session key.
  194. * @param nonce Send-direction nonce for this reply.
  195. * @param body Encoded response body, which is empty when its codec refused.
  196. * @param framedSize Receives the complete outer-frame size, or zero on failure.
  197. * @return True when the payload, seal, and outer frame all fit.
  198. */
  199. [[nodiscard]] bool encode(Scratch& scratch,
  200. const ServiceRoute& route,
  201. std::uint32_t taskId,
  202. std::span<const std::byte, state::kAesKeySize> key,
  203. std::span<const std::byte, state::kBapNonceSize> nonce,
  204. std::span<const std::byte> body,
  205. std::size_t& framedSize) noexcept;
  206. } // namespace reply
  207. /** Owns request-body processing for an encrypted service route. */
  208. namespace body {
  209. /**
  210. * Processes a request body and encodes a correlated body when the route needs one.
  211. * @param route Service route data found earlier.
  212. * @param queuezState Queuez versions and residents set up by this BAP peer.
  213. * @param activity Exact ActivityClient generation owned by this BAP session.
  214. * @param rosterDecode Last complete msg-5 identity map delivered on this connection.
  215. * @param matchmakingContext State-owned logical context for this BAP session.
  216. * @param requestBody Borrowed decrypted request body.
  217. * @param output Caller-owned response-body storage.
  218. * @param written Receives encoded body bytes.
  219. * @param outcome Receives one validated transport action or deferred State transaction.
  220. * @return True when the chosen body codec succeeds.
  221. */
  222. [[nodiscard]] bool process(const ServiceRoute& route,
  223. const queuez::SessionState& queuezState,
  224. const ActivityClientBinding& activity,
  225. const RosterDecodeMap& rosterDecode,
  226. state::matchmaking::ContextHandle matchmakingContext,
  227. std::span<const std::byte> requestBody,
  228. std::span<std::byte> output,
  229. std::size_t& written,
  230. ServiceOutcome& outcome) noexcept;
  231. } // namespace body
  232. /** Owns server-initiated encrypted frames appended after correlated replies. */
  233. namespace push {
  234. /**
  235. * Canonicalizes the account before any family builder reads it.
  236. * Families 0, 3 and 4 each snapshot the account, so a migration inside one builder would leave
  237. * the others describing a different account. Idempotent.
  238. */
  239. void ensure_account_canonical() noexcept;
  240. /**
  241. * Appends the queuez snapshots one subscription needs, including the Family-4 companion.
  242. * A snapshot that cannot be built is reported and skipped. The subscribe is answered either way,
  243. * because a request left without a response kills the link on the Client's missing-recipient path.
  244. * @param scratch Lock-owned transform buffers.
  245. * @param before Queuez state visible to the current BAP peer.
  246. * @param subscription Family the Client picked.
  247. * @param key Active AES-GCM session key.
  248. * @param nonce Push-direction nonce, advanced once per appended frame.
  249. * @param response Caller-owned output containing the existing response prefix.
  250. * @param written Existing byte count, updated after each complete push is appended.
  251. * @param after Receives the queuez state published after caller output is copied.
  252. * @param armsRepush Receives whether the Family-4 companion needs its delayed second copy.
  253. * @param armsBannerRepush Receives whether a family-zero body needs its delayed second copy.
  254. */
  255. void append_queuez_notification(Scratch& scratch,
  256. const queuez::SessionState& before,
  257. const middleware::queuez::Subscription& subscription,
  258. std::span<const std::byte, state::kAesKeySize> key,
  259. std::array<std::byte, state::kBapNonceSize>& nonce,
  260. std::span<std::byte> response,
  261. std::size_t& written,
  262. queuez::SessionState& after,
  263. bool& armsRepush,
  264. bool& armsBannerRepush) noexcept;
  265. /** Appends one next-version full Family-4 snapshot used to resynchronize another peer. */
  266. [[nodiscard]] bool append_account_resync_notification(
  267. Scratch& scratch,
  268. const queuez::SessionState& before,
  269. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  270. std::span<const std::byte, state::kAesKeySize> key,
  271. std::array<std::byte, state::kBapNonceSize>& nonce,
  272. std::span<std::byte> response,
  273. std::size_t& written,
  274. queuez::SessionState& after) noexcept;
  275. /** Publishes one Season package as new residents plus their acquisition descriptors. */
  276. [[nodiscard]] bool append_season_pass_package_notification(
  277. Scratch& scratch,
  278. const queuez::SessionState& before,
  279. const state::PendingDirectItemBundle& mutation,
  280. std::uint16_t rewardIndex,
  281. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  282. std::span<const std::byte, state::kAesKeySize> key,
  283. std::span<const std::byte, state::kBapNonceSize> nonce,
  284. std::span<std::byte> response,
  285. std::size_t& written,
  286. queuez::SessionState& after) noexcept;
  287. /** Publishes every item and the claimed record in one Family-4 revision. */
  288. [[nodiscard]] bool append_record_reward_notification(
  289. Scratch& scratch,
  290. const queuez::SessionState& before,
  291. const queuez::RecordRewardGrant& update,
  292. const state::PendingRecordRewardGrant& mutation,
  293. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  294. std::span<const std::byte, state::kAesKeySize> key,
  295. std::span<const std::byte, state::kBapNonceSize> nonce,
  296. std::span<std::byte> response,
  297. std::size_t& written) noexcept;
  298. /**
  299. * Appends the family-zero banner pair as its own notification.
  300. * Sent twice per boot at the same version, which is what survives the state-1 DECLARED race.
  301. * `after` records the delivery, or a later 504 move cannot name the record it must release.
  302. * @param scratch Lock-owned transform buffers.
  303. * @param before Queuez state the pair is delivered against.
  304. * @param familyRootSoid Root the Client subscribed for Family 3.
  305. * @param key Active AES-GCM session key.
  306. * @param nonce Push-direction nonce, advanced only by a complete frame.
  307. * @param response Caller-owned output containing prior frames.
  308. * @param written Existing byte count, updated by a complete frame.
  309. * @param after Receives the state carrying the recorded delivery.
  310. * @return True when the banner frame is appended.
  311. */
  312. [[nodiscard]] bool append_banner_notification(Scratch& scratch,
  313. const queuez::SessionState& before,
  314. std::uint64_t familyRootSoid,
  315. std::span<const std::byte, state::kAesKeySize> key,
  316. std::array<std::byte, state::kBapNonceSize>& nonce,
  317. std::span<std::byte> response,
  318. std::size_t& written,
  319. queuez::SessionState& after) noexcept;
  320. /**
  321. * Appends the family-zero pair that follows an opcode-504 pick.
  322. * The Client holds the objIdx-1 buffer for one character at a time, so the pair moves with it. A
  323. * pick naming the character it already holds republishes the pair in place.
  324. * @param before Queuez state after the family-four move.
  325. * @param selectedCharacter Character the pick named.
  326. * @param key Active AES-GCM session key.
  327. * @param nonce Push-direction nonce, advanced only by a complete frame.
  328. * @param response Caller-owned output containing prior frames.
  329. * @param written Existing byte count, updated by a complete frame.
  330. * @param after Receives the state published once the frame is copied.
  331. * @return True when a frame went out and `after` carries the advanced ladder.
  332. */
  333. [[nodiscard]] bool
  334. append_banner_move_notification(Scratch& scratch,
  335. const queuez::SessionState& before,
  336. std::uint64_t selectedCharacter,
  337. std::span<const std::byte, state::kAesKeySize> key,
  338. std::array<std::byte, state::kBapNonceSize>& nonce,
  339. std::span<std::byte> response,
  340. std::size_t& written,
  341. queuez::SessionState& after) noexcept;
  342. /**
  343. * Appends the fixed opcode-505 Family-4 selection patch.
  344. * @param scratch Lock-owned transform buffers.
  345. * @param change Staged queuez after-image and account definition.
  346. * @param key Active AES-GCM session key.
  347. * @param nonce Push-direction nonce after the correlated svc-11 response.
  348. * @param response Caller-owned output containing the existing response prefix.
  349. * @param written Existing byte count, updated after the complete push is appended.
  350. * @return True when the exact 17-byte patch and complete svc-123 frame fit.
  351. */
  352. [[nodiscard]] bool
  353. append_change_character_notification(Scratch& scratch,
  354. const queuez::ChangeCharacter& change,
  355. std::span<const std::byte, state::kAesKeySize> key,
  356. std::span<const std::byte, state::kBapNonceSize> nonce,
  357. std::span<std::byte> response,
  358. std::size_t& written) noexcept;
  359. /**
  360. * Appends the opcode-504 Family-4 move to the picked character.
  361. * @param scratch Lock-owned transform buffers.
  362. * @param select Staged after-image, object definitions, and both character keys.
  363. * @param key Active AES-GCM session key.
  364. * @param nonce Push-direction nonce after the correlated svc-11 response.
  365. * @param response Caller-owned output containing the existing response prefix.
  366. * @param written Existing byte count, updated after the complete push is appended.
  367. * @return True when the 3 object operations and the whole svc-123 frame fit.
  368. */
  369. [[nodiscard]] bool
  370. append_select_character_notification(Scratch& scratch,
  371. const queuez::SelectCharacter& select,
  372. std::span<const std::byte, state::kAesKeySize> key,
  373. std::span<const std::byte, state::kBapNonceSize> nonce,
  374. std::span<std::byte> response,
  375. std::size_t& written) noexcept;
  376. /** Appends the opcode-403 Family-4 character upsert that exposes the equipped item swap. */
  377. [[nodiscard]] bool append_equipment_swap_notification(
  378. Scratch& scratch,
  379. const queuez::EquipmentSwap& swap,
  380. const state::PendingEquipmentSwap& mutation,
  381. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  382. std::span<const std::byte, state::kAesKeySize> key,
  383. std::span<const std::byte, state::kBapNonceSize> nonce,
  384. std::span<std::byte> response,
  385. std::size_t& written) noexcept;
  386. /** Appends the Family-4 character upsert carrying the character's new current activity. */
  387. [[nodiscard]] bool
  388. append_current_activity_notification(Scratch& scratch,
  389. const queuez::EquipmentSwap& swap,
  390. const state::PendingCurrentActivity& mutation,
  391. std::span<const std::byte, state::kAesKeySize> key,
  392. std::span<const std::byte, state::kBapNonceSize> nonce,
  393. std::span<std::byte> response,
  394. std::size_t& written) noexcept;
  395. /** Appends the opcode-406 Family-4 character upsert carrying changed inventory-row flags. */
  396. [[nodiscard]] bool append_item_state_notification(
  397. Scratch& scratch,
  398. const queuez::EquipmentSwap& update,
  399. const state::PendingItemState& mutation,
  400. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  401. std::span<const std::byte, state::kAesKeySize> key,
  402. std::span<const std::byte, state::kBapNonceSize> nonce,
  403. std::span<std::byte> response,
  404. std::size_t& written) noexcept;
  405. /** Appends the selected-character upsert carrying one artifact ownership transition. */
  406. [[nodiscard]] bool append_artifact_purchase_notification(
  407. Scratch& scratch,
  408. const queuez::EquipmentSwap& update,
  409. const state::PendingArtifactPurchase& mutation,
  410. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  411. std::span<const std::byte, state::kAesKeySize> key,
  412. std::span<const std::byte, state::kBapNonceSize> nonce,
  413. std::span<std::byte> response,
  414. std::size_t& written) noexcept;
  415. /**
  416. * Appends the global family-five unlock overrides as one full-snapshot notification.
  417. * @param scratch Lock-owned transform buffers.
  418. * @param version Family version this frame carries; -1 is refused by the Client.
  419. * @param key Active AES-GCM session key.
  420. * @param nonce Push-direction nonce after any correlated response.
  421. * @param response Caller-owned output containing prior frames.
  422. * @param written Existing byte count, updated by a complete frame.
  423. * @return True when State encodes and the whole frame fits.
  424. */
  425. [[nodiscard]] bool
  426. append_family5_override_notification(Scratch& scratch,
  427. std::int32_t version,
  428. std::span<const std::byte, state::kAesKeySize> key,
  429. std::span<const std::byte, state::kBapNonceSize> nonce,
  430. std::span<std::byte> response,
  431. std::size_t& written) noexcept;
  432. /** Appends the account and selected-character state changed by an artifact reset. */
  433. [[nodiscard]] bool
  434. append_artifact_reset_notification(Scratch& scratch,
  435. const queuez::EquipmentSwap& update,
  436. std::span<const std::byte, state::kAesKeySize> key,
  437. std::span<const std::byte, state::kBapNonceSize> nonce,
  438. std::span<std::byte> response,
  439. std::size_t& written) noexcept;
  440. /** Appends one current item resident after artifact reset cleared an authored socket. */
  441. [[nodiscard]] bool
  442. append_artifact_item_refresh_notification(Scratch& scratch,
  443. const queuez::EquipmentSwap& update,
  444. std::uint64_t instanceSoid,
  445. std::span<const std::byte, state::kAesKeySize> key,
  446. std::span<const std::byte, state::kBapNonceSize> nonce,
  447. std::span<std::byte> response,
  448. std::size_t& written) noexcept;
  449. /**
  450. * Appends the same-character Family-0 appearance upsert paired with one equipment swap.
  451. * The update owns its nonce advance only after the complete notification fits.
  452. */
  453. [[nodiscard]] bool
  454. append_equipment_appearance_refresh_notification(Scratch& scratch,
  455. const queuez::CharacterAppearanceRefresh& refresh,
  456. const state::PendingEquipmentSwap& mutation,
  457. std::span<const std::byte, state::kAesKeySize> key,
  458. std::array<std::byte, state::kBapNonceSize>& nonce,
  459. std::span<std::byte> response,
  460. std::size_t& written) noexcept;
  461. /** Appends the Family-0 refresh owed by a socket change on an equipped item. */
  462. [[nodiscard]] bool
  463. append_socket_appearance_refresh_notification(Scratch& scratch,
  464. const queuez::CharacterAppearanceRefresh& refresh,
  465. const state::PendingSocketPlug& mutation,
  466. std::span<const std::byte, state::kAesKeySize> key,
  467. std::array<std::byte, state::kBapNonceSize>& nonce,
  468. std::span<std::byte> response,
  469. std::size_t& written) noexcept;
  470. /** Appends the Family-0 character ability refresh owed by a subclass selection. */
  471. [[nodiscard]] bool
  472. append_subclass_appearance_refresh_notification(Scratch& scratch,
  473. const queuez::CharacterAppearanceRefresh& refresh,
  474. const state::PendingSubclassSelection& mutation,
  475. std::span<const std::byte, state::kAesKeySize> key,
  476. std::array<std::byte, state::kBapNonceSize>& nonce,
  477. std::span<std::byte> response,
  478. std::size_t& written) noexcept;
  479. /** Appends a Family-3 character record followed by the changed account roster after equip. */
  480. [[nodiscard]] bool
  481. append_equipment_roster_refresh_notification(Scratch& scratch,
  482. const queuez::RosterAppearanceRefresh& refresh,
  483. const state::PendingEquipmentSwap& mutation,
  484. std::span<const std::byte, state::kAesKeySize> key,
  485. std::array<std::byte, state::kBapNonceSize>& nonce,
  486. std::span<std::byte> response,
  487. std::size_t& written) noexcept;
  488. /** Appends a Family-3 character-only appearance refresh after an equipped socket change. */
  489. [[nodiscard]] bool
  490. append_socket_roster_refresh_notification(Scratch& scratch,
  491. const queuez::RosterAppearanceRefresh& refresh,
  492. const state::PendingSocketPlug& mutation,
  493. std::span<const std::byte, state::kAesKeySize> key,
  494. std::array<std::byte, state::kBapNonceSize>& nonce,
  495. std::span<std::byte> response,
  496. std::size_t& written) noexcept;
  497. /** Appends a Family-3 character-only appearance refresh after a subclass selection. */
  498. [[nodiscard]] bool
  499. append_subclass_roster_refresh_notification(Scratch& scratch,
  500. const queuez::RosterAppearanceRefresh& refresh,
  501. const state::PendingSubclassSelection& mutation,
  502. std::span<const std::byte, state::kAesKeySize> key,
  503. std::array<std::byte, state::kBapNonceSize>& nonce,
  504. std::span<std::byte> response,
  505. std::size_t& written) noexcept;
  506. /** Refreshes the selected character's complete Family-0 appearance from committed State. */
  507. [[nodiscard]] bool
  508. append_account_resync_appearance_notification(Scratch& scratch,
  509. const queuez::SessionState& before,
  510. std::span<const std::byte, state::kAesKeySize> key,
  511. std::array<std::byte, state::kBapNonceSize>& nonce,
  512. std::span<std::byte> response,
  513. std::size_t& written,
  514. queuez::SessionState& after) noexcept;
  515. /** Refreshes the selected character and account roster from committed State. */
  516. [[nodiscard]] bool
  517. append_account_resync_roster_notification(Scratch& scratch,
  518. const queuez::SessionState& before,
  519. std::span<const std::byte, state::kAesKeySize> key,
  520. std::array<std::byte, state::kBapNonceSize>& nonce,
  521. std::span<std::byte> response,
  522. std::size_t& written,
  523. queuez::SessionState& after) noexcept;
  524. /** Appends the opcode-903 Family-4 item-instance upsert exposing one socket selection. */
  525. [[nodiscard]] bool
  526. append_socket_plug_notification(Scratch& scratch,
  527. const queuez::SocketPlug& socketPlug,
  528. const state::PendingSocketPlug& mutation,
  529. std::span<const std::byte, state::kAesKeySize> key,
  530. std::span<const std::byte, state::kBapNonceSize> nonce,
  531. std::span<std::byte> response,
  532. std::size_t& written) noexcept;
  533. /** Appends the opcode-801 Family-4 subclass item-instance upsert. */
  534. [[nodiscard]] bool
  535. append_subclass_selection_notification(Scratch& scratch,
  536. const queuez::SubclassSelection& selection,
  537. const state::PendingSubclassSelection& mutation,
  538. std::span<const std::byte, state::kAesKeySize> key,
  539. std::span<const std::byte, state::kBapNonceSize> nonce,
  540. std::span<std::byte> response,
  541. std::size_t& written) noexcept;
  542. /** Appends a Family-4 character upsert plus newly acquired item-instance upsert. */
  543. [[nodiscard]] bool append_item_acquisition_notification(
  544. Scratch& scratch,
  545. const queuez::ItemAcquisition& acquisition,
  546. const state::PendingItemAcquisition& mutation,
  547. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  548. std::span<const std::byte, state::kAesKeySize> key,
  549. std::span<const std::byte, state::kBapNonceSize> nonce,
  550. std::span<std::byte> response,
  551. std::size_t& written) noexcept;
  552. /** Appends one full Family-4 account upsert for a profile-stack acquisition. */
  553. [[nodiscard]] bool
  554. append_profile_item_acquisition_notification(Scratch& scratch,
  555. const queuez::ProfileItemAcquisition& acquisition,
  556. const state::PendingProfileItemAcquisition& mutation,
  557. std::span<const std::byte, state::kAesKeySize> key,
  558. std::span<const std::byte, state::kBapNonceSize> nonce,
  559. std::span<std::byte> response,
  560. std::size_t& written) noexcept;
  561. /** Appends the character/account increment that makes one seasonal XP gain visible in the HUD. */
  562. [[nodiscard]] bool append_seasonal_experience_notification(
  563. Scratch& scratch,
  564. const queuez::SessionState& before,
  565. std::int32_t amount,
  566. std::int32_t mutationSerial,
  567. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  568. std::span<const std::byte, state::kAesKeySize> key,
  569. std::span<const std::byte, state::kBapNonceSize> nonce,
  570. std::span<std::byte> response,
  571. std::size_t& written,
  572. queuez::SessionState& after) noexcept;
  573. /** Appends a Family-4 character upsert followed by one empty item-instance release. */
  574. [[nodiscard]] bool
  575. append_item_dismantle_notification(Scratch& scratch,
  576. const queuez::ItemDismantle& dismantle,
  577. const state::PendingItemDismantle& mutation,
  578. std::span<const std::byte, state::kAesKeySize> key,
  579. std::span<const std::byte, state::kBapNonceSize> nonce,
  580. std::span<std::byte> response,
  581. std::size_t& written) noexcept;
  582. } // namespace push
  583. } // namespace sunrise::server::bap::encrypted