internal.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. #pragma once
  2. #include <array>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <span>
  6. #include <string_view>
  7. #include <variant>
  8. #include "../../../middleware/bap/family_unsubscription.h"
  9. #include "../../../middleware/bap/frame.h"
  10. #include "../../../middleware/queuez/subscription.h"
  11. #include "../../web_service/web_service_runtime.h"
  12. #include "../internal.h"
  13. #include "activity_message/definition.h"
  14. #include "queuez/definition.h"
  15. #include "transactions/definition.h"
  16. namespace sunrise::server::bap::encrypted {
  17. /** Response-body codecs picked by the authenticated request service. */
  18. enum class BodyCodec : std::uint8_t {
  19. empty,
  20. accountTranslationResponse,
  21. activityHostManagerResponse,
  22. activityMessageRequest,
  23. activityHostResponse,
  24. clientConfigResponse,
  25. familySubscription,
  26. familyUnsubscription,
  27. matchmakingResponse,
  28. steamCertificate,
  29. userMessageResponse,
  30. webService,
  31. };
  32. /** Equipment mutation and the exact QueueZ after-image promised by its response. */
  33. struct EquipmentSwapTransaction {
  34. state::PendingEquipmentSwap pending{};
  35. queuez::EquipmentSwap update{};
  36. };
  37. /** Socket mutation and the exact QueueZ after-image promised by its response. */
  38. struct SocketPlugTransaction {
  39. state::PendingSocketPlug pending{};
  40. queuez::SocketPlug update{};
  41. };
  42. /** Item-state mutation and the exact QueueZ character after-image promised by its response. */
  43. struct ItemStateTransaction {
  44. state::PendingItemState pending{};
  45. queuez::EquipmentSwap update{};
  46. };
  47. /** Character acquisition and its exact QueueZ after-image. */
  48. struct ItemAcquisitionTransaction {
  49. state::PendingItemAcquisition pending{};
  50. queuez::ItemAcquisition update{};
  51. };
  52. /** Profile acquisition and its exact account/resident QueueZ after-image. */
  53. struct ProfileItemAcquisitionTransaction {
  54. state::PendingProfileItemAcquisition pending{};
  55. queuez::ProfileItemAcquisition update{};
  56. };
  57. /** Dismantle mutation and its exact QueueZ after-image. */
  58. struct ItemDismantleTransaction {
  59. state::PendingItemDismantle pending{};
  60. queuez::ItemDismantle update{};
  61. };
  62. /** Optional side effect produced while decoding one authenticated service body. */
  63. struct ServiceOutcome {
  64. bool hasSubscription{};
  65. middleware::queuez::Subscription subscription{};
  66. bool hasUnsubscription{};
  67. middleware::bap::family_unsubscription::Request unsubscription{};
  68. bool hasChangeCharacter{};
  69. queuez::ChangeCharacter changeCharacter{};
  70. bool hasSelectCharacter{};
  71. queuez::SelectCharacter selectCharacter{};
  72. /** One service owns at most one independently versioned transaction. */
  73. using Transaction = std::variant<std::monostate,
  74. state::activity::PendingAllocation,
  75. activity_message::ActivityPlan,
  76. state::matchmaking::PendingMutation,
  77. EquipmentSwapTransaction,
  78. SocketPlugTransaction,
  79. ItemStateTransaction,
  80. ItemAcquisitionTransaction,
  81. ProfileItemAcquisitionTransaction,
  82. ItemDismantleTransaction>;
  83. Transaction transaction{};
  84. };
  85. /** @return The service transaction of the requested type, or null for another route. */
  86. template <typename Transaction>
  87. [[nodiscard]] Transaction* transaction_if(ServiceOutcome& outcome) noexcept {
  88. return std::get_if<Transaction>(&outcome.transaction);
  89. }
  90. /** @return The service transaction of the requested type, or null for another route. */
  91. template <typename Transaction>
  92. [[nodiscard]] const Transaction* transaction_if(const ServiceOutcome& outcome) noexcept {
  93. return std::get_if<Transaction>(&outcome.transaction);
  94. }
  95. /** Outbound delivery behavior picked for one authenticated request service. */
  96. enum class ResponseMode : std::uint8_t {
  97. none,
  98. reply,
  99. /** Processes a request body and may emit notifications without a status response. */
  100. uncorrelatedPush,
  101. };
  102. /** Static response metadata for one supported encrypted request service. */
  103. struct ServiceRoute {
  104. ResponseMode responseMode{};
  105. middleware::bap::ResponseService response{};
  106. BodyCodec bodyCodec{};
  107. std::string_view successEvent{};
  108. };
  109. /** Owns encrypted service-to-response routing. */
  110. namespace routing {
  111. [[nodiscard]] bool resolve(std::uint16_t request, ServiceRoute& route) noexcept;
  112. } // namespace routing
  113. /** Owns failure reporting for encrypted requests. */
  114. namespace diagnostics {
  115. void report_failure(std::uint16_t service, std::string_view stage) noexcept;
  116. } // namespace diagnostics
  117. /** Owns correlated reply construction for one authenticated request. */
  118. namespace reply {
  119. /**
  120. * Encodes, seals, and frames one correlated status-200 reply.
  121. * @param scratch Lock-owned transform buffers.
  122. * @param route Service route data naming the response service.
  123. * @param taskId Request correlation id to echo.
  124. * @param key Active AES-GCM session key.
  125. * @param nonce Send-direction nonce for this reply.
  126. * @param body Encoded response body, which is empty when its codec refused.
  127. * @param framedSize Receives the complete outer-frame size, or zero on failure.
  128. * @return True when the payload, seal, and outer frame all fit.
  129. */
  130. [[nodiscard]] bool encode(Scratch& scratch,
  131. const ServiceRoute& route,
  132. std::uint32_t taskId,
  133. std::span<const std::byte, state::kAesKeySize> key,
  134. std::span<const std::byte, state::kBapNonceSize> nonce,
  135. std::span<const std::byte> body,
  136. std::size_t& framedSize) noexcept;
  137. } // namespace reply
  138. /** Owns request-body processing for an encrypted service route. */
  139. namespace body {
  140. /**
  141. * Processes a request body and encodes a correlated body when the route needs one.
  142. * @param route Service route data found earlier.
  143. * @param queuezState Queuez versions and residents set up by this BAP peer.
  144. * @param activitySessionId Activity capability allocated through this BAP session.
  145. * @param matchmakingContext State-owned logical context for this BAP session.
  146. * @param requestBody Borrowed decrypted request body.
  147. * @param output Caller-owned response-body storage.
  148. * @param written Receives encoded body bytes.
  149. * @param outcome Receives one validated transport action or deferred State transaction.
  150. * @return True when the chosen body codec succeeds.
  151. */
  152. [[nodiscard]] bool process(const ServiceRoute& route,
  153. const queuez::SessionState& queuezState,
  154. std::uint64_t activitySessionId,
  155. state::matchmaking::ContextHandle matchmakingContext,
  156. std::span<const std::byte> requestBody,
  157. std::span<std::byte> output,
  158. std::size_t& written,
  159. ServiceOutcome& outcome) noexcept;
  160. } // namespace body
  161. /** Owns server-initiated encrypted frames appended after correlated replies. */
  162. namespace push {
  163. /**
  164. * Appends the queuez snapshots one subscription needs, including the Family-4 companion.
  165. * A snapshot that cannot be built is reported and skipped. The subscribe is answered either way,
  166. * because a request left without a response kills the link on the Client's missing-recipient path.
  167. * @param scratch Lock-owned transform buffers.
  168. * @param before Queuez state visible to the current BAP peer.
  169. * @param subscription Family the Client picked.
  170. * @param key Active AES-GCM session key.
  171. * @param nonce Push-direction nonce, advanced once per appended frame.
  172. * @param response Caller-owned output containing the existing response prefix.
  173. * @param written Existing byte count, updated after each complete push is appended.
  174. * @param after Receives the queuez state published after caller output is copied.
  175. * @param armsRepush Receives whether the Family-4 companion needs its delayed second copy.
  176. * @param armsBannerRepush Receives whether a family-zero body needs its delayed second copy.
  177. */
  178. void append_queuez_notification(Scratch& scratch,
  179. const queuez::SessionState& before,
  180. const middleware::queuez::Subscription& subscription,
  181. std::span<const std::byte, state::kAesKeySize> key,
  182. std::array<std::byte, state::kBapNonceSize>& nonce,
  183. std::span<std::byte> response,
  184. std::size_t& written,
  185. queuez::SessionState& after,
  186. bool& armsRepush,
  187. bool& armsBannerRepush) noexcept;
  188. /** Appends one next-version full Family-4 snapshot used to resynchronize another peer. */
  189. [[nodiscard]] bool
  190. append_account_resync_notification(Scratch& scratch,
  191. const queuez::SessionState& before,
  192. std::span<const std::byte, state::kAesKeySize> key,
  193. std::array<std::byte, state::kBapNonceSize>& nonce,
  194. std::span<std::byte> response,
  195. std::size_t& written,
  196. queuez::SessionState& after) noexcept;
  197. /**
  198. * Appends the family-zero banner pair as its own notification.
  199. * Sent twice per boot at the same version, which is what survives the state-1 DECLARED race.
  200. * `after` records the delivery, or a later 504 move cannot name the record it must release.
  201. * @param scratch Lock-owned transform buffers.
  202. * @param before Queuez state the pair is delivered against.
  203. * @param familyRootSoid Root the Client subscribed for Family 3.
  204. * @param key Active AES-GCM session key.
  205. * @param nonce Push-direction nonce, advanced only by a complete frame.
  206. * @param response Caller-owned output containing prior frames.
  207. * @param written Existing byte count, updated by a complete frame.
  208. * @param after Receives the state carrying the recorded delivery.
  209. * @return True when the banner frame is appended.
  210. */
  211. [[nodiscard]] bool append_banner_notification(Scratch& scratch,
  212. const queuez::SessionState& before,
  213. std::uint64_t familyRootSoid,
  214. std::span<const std::byte, state::kAesKeySize> key,
  215. std::array<std::byte, state::kBapNonceSize>& nonce,
  216. std::span<std::byte> response,
  217. std::size_t& written,
  218. queuez::SessionState& after) noexcept;
  219. /**
  220. * Appends the family-zero move that follows an opcode-504 pick.
  221. * The Client holds the objIdx-1 buffer for one character at a time, so the pair moves with it.
  222. * @param before Queuez state after the family-four move.
  223. * @param selectedCharacter Character the pick named.
  224. * @param key Active AES-GCM session key.
  225. * @param nonce Push-direction nonce, advanced only by a complete frame.
  226. * @param response Caller-owned output containing prior frames.
  227. * @param written Existing byte count, updated by a complete frame.
  228. * @param after Receives the state published once the frame is copied.
  229. * @return True when a frame went out and `after` carries the advanced ladder.
  230. */
  231. [[nodiscard]] bool
  232. append_banner_move_notification(Scratch& scratch,
  233. const queuez::SessionState& before,
  234. std::uint64_t selectedCharacter,
  235. std::span<const std::byte, state::kAesKeySize> key,
  236. std::array<std::byte, state::kBapNonceSize>& nonce,
  237. std::span<std::byte> response,
  238. std::size_t& written,
  239. queuez::SessionState& after) noexcept;
  240. /**
  241. * Appends the fixed opcode-505 Family-4 selection patch.
  242. * @param scratch Lock-owned transform buffers.
  243. * @param change Staged queuez after-image and account definition.
  244. * @param key Active AES-GCM session key.
  245. * @param nonce Push-direction nonce after the correlated svc-11 response.
  246. * @param response Caller-owned output containing the existing response prefix.
  247. * @param written Existing byte count, updated after the complete push is appended.
  248. * @return True when the exact 17-byte patch and complete svc-123 frame fit.
  249. */
  250. [[nodiscard]] bool
  251. append_change_character_notification(Scratch& scratch,
  252. const queuez::ChangeCharacter& change,
  253. std::span<const std::byte, state::kAesKeySize> key,
  254. std::span<const std::byte, state::kBapNonceSize> nonce,
  255. std::span<std::byte> response,
  256. std::size_t& written) noexcept;
  257. /**
  258. * Appends the opcode-504 Family-4 move to the picked character.
  259. * @param scratch Lock-owned transform buffers.
  260. * @param select Staged after-image, object definitions, and both character keys.
  261. * @param key Active AES-GCM session key.
  262. * @param nonce Push-direction nonce after the correlated svc-11 response.
  263. * @param response Caller-owned output containing the existing response prefix.
  264. * @param written Existing byte count, updated after the complete push is appended.
  265. * @return True when the 3 object operations and the whole svc-123 frame fit.
  266. */
  267. [[nodiscard]] bool
  268. append_select_character_notification(Scratch& scratch,
  269. const queuez::SelectCharacter& select,
  270. std::span<const std::byte, state::kAesKeySize> key,
  271. std::span<const std::byte, state::kBapNonceSize> nonce,
  272. std::span<std::byte> response,
  273. std::size_t& written) noexcept;
  274. /** Appends the opcode-403 Family-4 character upsert that exposes the equipped item swap. */
  275. [[nodiscard]] bool
  276. append_equipment_swap_notification(Scratch& scratch,
  277. const queuez::EquipmentSwap& swap,
  278. const state::PendingEquipmentSwap& mutation,
  279. std::span<const std::byte, state::kAesKeySize> key,
  280. std::span<const std::byte, state::kBapNonceSize> nonce,
  281. std::span<std::byte> response,
  282. std::size_t& written) noexcept;
  283. /** Appends the opcode-406 Family-4 character upsert carrying changed inventory-row flags. */
  284. [[nodiscard]] bool
  285. append_item_state_notification(Scratch& scratch,
  286. const queuez::EquipmentSwap& update,
  287. const state::PendingItemState& mutation,
  288. std::span<const std::byte, state::kAesKeySize> key,
  289. std::span<const std::byte, state::kBapNonceSize> nonce,
  290. std::span<std::byte> response,
  291. std::size_t& written) noexcept;
  292. /**
  293. * Appends the same-character Family-0 appearance upsert paired with one equipment swap.
  294. * The
  295. * update owns its nonce advance only after the complete notification fits.
  296. */
  297. [[nodiscard]] bool
  298. append_equipment_appearance_refresh_notification(Scratch& scratch,
  299. const queuez::CharacterAppearanceRefresh& refresh,
  300. const state::PendingEquipmentSwap& mutation,
  301. std::span<const std::byte, state::kAesKeySize> key,
  302. std::array<std::byte, state::kBapNonceSize>& nonce,
  303. std::span<std::byte> response,
  304. std::size_t& written) noexcept;
  305. /** Appends the Family-0 refresh owed by a socket change on an equipped item. */
  306. [[nodiscard]] bool
  307. append_socket_appearance_refresh_notification(Scratch& scratch,
  308. const queuez::CharacterAppearanceRefresh& refresh,
  309. const state::PendingSocketPlug& mutation,
  310. std::span<const std::byte, state::kAesKeySize> key,
  311. std::array<std::byte, state::kBapNonceSize>& nonce,
  312. std::span<std::byte> response,
  313. std::size_t& written) noexcept;
  314. /** Appends a Family-3 character record followed by the changed account roster after equip. */
  315. [[nodiscard]] bool
  316. append_equipment_roster_refresh_notification(Scratch& scratch,
  317. const queuez::RosterAppearanceRefresh& refresh,
  318. const state::PendingEquipmentSwap& mutation,
  319. std::span<const std::byte, state::kAesKeySize> key,
  320. std::array<std::byte, state::kBapNonceSize>& nonce,
  321. std::span<std::byte> response,
  322. std::size_t& written) noexcept;
  323. /** Appends a Family-3 character-only appearance refresh after an equipped socket change. */
  324. [[nodiscard]] bool
  325. append_socket_roster_refresh_notification(Scratch& scratch,
  326. const queuez::RosterAppearanceRefresh& refresh,
  327. const state::PendingSocketPlug& mutation,
  328. std::span<const std::byte, state::kAesKeySize> key,
  329. std::array<std::byte, state::kBapNonceSize>& nonce,
  330. std::span<std::byte> response,
  331. std::size_t& written) noexcept;
  332. /** Refreshes the selected character's complete Family-0 appearance from committed State. */
  333. [[nodiscard]] bool
  334. append_account_resync_appearance_notification(Scratch& scratch,
  335. const queuez::SessionState& before,
  336. std::span<const std::byte, state::kAesKeySize> key,
  337. std::array<std::byte, state::kBapNonceSize>& nonce,
  338. std::span<std::byte> response,
  339. std::size_t& written,
  340. queuez::SessionState& after) noexcept;
  341. /** Refreshes the selected character and account roster from committed State. */
  342. [[nodiscard]] bool
  343. append_account_resync_roster_notification(Scratch& scratch,
  344. const queuez::SessionState& before,
  345. std::span<const std::byte, state::kAesKeySize> key,
  346. std::array<std::byte, state::kBapNonceSize>& nonce,
  347. std::span<std::byte> response,
  348. std::size_t& written,
  349. queuez::SessionState& after) noexcept;
  350. /** Appends the opcode-903 Family-4 item-instance upsert exposing one socket selection. */
  351. [[nodiscard]] bool
  352. append_socket_plug_notification(Scratch& scratch,
  353. const queuez::SocketPlug& socketPlug,
  354. const state::PendingSocketPlug& mutation,
  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. /** Appends a Family-4 character upsert plus newly acquired item-instance upsert. */
  360. [[nodiscard]] bool
  361. append_item_acquisition_notification(Scratch& scratch,
  362. const queuez::ItemAcquisition& acquisition,
  363. const state::PendingItemAcquisition& mutation,
  364. std::span<const std::byte, state::kAesKeySize> key,
  365. std::span<const std::byte, state::kBapNonceSize> nonce,
  366. std::span<std::byte> response,
  367. std::size_t& written) noexcept;
  368. /** Appends one full Family-4 account upsert for a profile-stack acquisition. */
  369. [[nodiscard]] bool
  370. append_profile_item_acquisition_notification(Scratch& scratch,
  371. const queuez::ProfileItemAcquisition& acquisition,
  372. const state::PendingProfileItemAcquisition& mutation,
  373. std::span<const std::byte, state::kAesKeySize> key,
  374. std::span<const std::byte, state::kBapNonceSize> nonce,
  375. std::span<std::byte> response,
  376. std::size_t& written) noexcept;
  377. /** Appends a Family-4 character upsert followed by one empty item-instance release. */
  378. [[nodiscard]] bool
  379. append_item_dismantle_notification(Scratch& scratch,
  380. const queuez::ItemDismantle& dismantle,
  381. const state::PendingItemDismantle& mutation,
  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. } // namespace push
  387. } // namespace sunrise::server::bap::encrypted