queuez_select_character.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. #include <optional>
  2. #include "../../../../../middleware/datagen/definitions.h"
  3. #include "../../queuez/queuez_state_validation.h"
  4. #include "../snapshot/internal.h"
  5. #include "queuez_update_frame.h"
  6. namespace sunrise::server::bap::encrypted::push {
  7. /** Appends the opcode-504 Family-4 character-selection update. */
  8. bool append_select_character_notification(Scratch& scratch,
  9. const queuez::SelectCharacter& select,
  10. std::span<const std::byte, state::kAesKeySize> key,
  11. std::span<const std::byte, state::kBapNonceSize> nonce,
  12. std::span<std::byte> response,
  13. std::size_t& written) noexcept {
  14. snapshot::Prepared prepared{};
  15. if (!snapshot::prepare_selection_move(scratch, select, prepared)) {
  16. return false;
  17. }
  18. if (!queuez_frame::append(scratch,
  19. prepared.family,
  20. prepared.rawClearSize,
  21. prepared.compressedClearSize,
  22. key,
  23. nonce,
  24. response,
  25. written)) {
  26. return false;
  27. }
  28. return true;
  29. }
  30. /** Appends the opcode-403 character upsert as one increment above the current peer version. */
  31. bool append_equipment_swap_notification(
  32. Scratch& scratch,
  33. const queuez::EquipmentSwap& swap,
  34. const state::PendingEquipmentSwap& mutation,
  35. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  36. std::span<const std::byte, state::kAesKeySize> key,
  37. std::span<const std::byte, state::kBapNonceSize> nonce,
  38. std::span<std::byte> response,
  39. std::size_t& written) noexcept {
  40. snapshot::Prepared prepared{};
  41. if (!snapshot::prepare_equipment_swap(
  42. scratch, swap, mutation, acquisitionPresentationRows, prepared)) {
  43. return false;
  44. }
  45. if (!queuez_frame::append(scratch,
  46. prepared.family,
  47. prepared.rawClearSize,
  48. prepared.compressedClearSize,
  49. key,
  50. nonce,
  51. response,
  52. written)) {
  53. return false;
  54. }
  55. return true;
  56. }
  57. /** Appends one opcode-406 selected-character item-state upsert. */
  58. bool append_item_state_notification(
  59. Scratch& scratch,
  60. const queuez::EquipmentSwap& update,
  61. const state::PendingItemState& mutation,
  62. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  63. std::span<const std::byte, state::kAesKeySize> key,
  64. std::span<const std::byte, state::kBapNonceSize> nonce,
  65. std::span<std::byte> response,
  66. std::size_t& written) noexcept {
  67. snapshot::Prepared prepared{};
  68. if (!snapshot::prepare_item_state(
  69. scratch, update, mutation, acquisitionPresentationRows, prepared)) {
  70. return false;
  71. }
  72. const std::size_t objectCount = prepared.family.objects.size();
  73. if (objectCount != 1 || prepared.family.objects.front().id != update.characterDefinitionId
  74. || prepared.family.objects.front().version != update.characterSoid
  75. || prepared.family.objects.front().encoding != middleware::queuez::Encoding::oodle
  76. || prepared.family.objects.front().payload.empty()
  77. || !queuez_frame::append(scratch,
  78. prepared.family,
  79. prepared.rawClearSize,
  80. prepared.compressedClearSize,
  81. key,
  82. nonce,
  83. response,
  84. written)) {
  85. return false;
  86. }
  87. return true;
  88. }
  89. /** Appends one opcode-901 selected-character artifact ownership upsert. */
  90. bool append_artifact_purchase_notification(
  91. Scratch& scratch,
  92. const queuez::EquipmentSwap& update,
  93. const state::PendingArtifactPurchase& mutation,
  94. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  95. std::span<const std::byte, state::kAesKeySize> key,
  96. std::span<const std::byte, state::kBapNonceSize> nonce,
  97. std::span<std::byte> response,
  98. std::size_t& written) noexcept {
  99. snapshot::Prepared prepared{};
  100. if (!snapshot::prepare_artifact_purchase(
  101. scratch, update, mutation, acquisitionPresentationRows, prepared)) {
  102. return false;
  103. }
  104. return prepared.family.objects.size() == 1
  105. && prepared.family.objects.front().id == update.characterDefinitionId
  106. && prepared.family.objects.front().version == update.characterSoid
  107. && prepared.family.objects.front().encoding == middleware::queuez::Encoding::oodle
  108. && !prepared.family.objects.front().payload.empty()
  109. && queuez_frame::append(scratch,
  110. prepared.family,
  111. prepared.rawClearSize,
  112. prepared.compressedClearSize,
  113. key,
  114. nonce,
  115. response,
  116. written);
  117. }
  118. /** Appends a reset increment without the full-snapshot acquisition semantics. */
  119. bool append_artifact_reset_notification(
  120. Scratch& scratch,
  121. const queuez::EquipmentSwap& update,
  122. std::span<const std::byte, state::kAesKeySize> key,
  123. std::span<const std::byte, state::kBapNonceSize> nonce,
  124. std::span<std::byte> response,
  125. std::size_t& written) noexcept {
  126. snapshot::Prepared prepared{};
  127. if (!snapshot::prepare_artifact_reset(scratch, update, prepared)) {
  128. return false;
  129. }
  130. return prepared.family.objects.size() == 2
  131. && prepared.family.objects[1].id == update.characterDefinitionId
  132. && prepared.family.objects[1].version == update.characterSoid
  133. && queuez_frame::append(scratch,
  134. prepared.family,
  135. prepared.rawClearSize,
  136. prepared.compressedClearSize,
  137. key,
  138. nonce,
  139. response,
  140. written);
  141. }
  142. /** Appends one exact resident upsert after artifact reset. */
  143. bool append_artifact_item_refresh_notification(
  144. Scratch& scratch,
  145. const queuez::EquipmentSwap& update,
  146. std::uint64_t instanceSoid,
  147. std::span<const std::byte, state::kAesKeySize> key,
  148. std::span<const std::byte, state::kBapNonceSize> nonce,
  149. std::span<std::byte> response,
  150. std::size_t& written) noexcept {
  151. snapshot::Prepared prepared{};
  152. if (!snapshot::prepare_artifact_item_refresh(scratch, update, instanceSoid, prepared)) {
  153. return false;
  154. }
  155. return prepared.family.objects.size() == 1
  156. && prepared.family.objects.front().version == instanceSoid
  157. && prepared.family.objects.front().encoding == middleware::queuez::Encoding::oodle
  158. && !prepared.family.objects.front().payload.empty()
  159. && queuez_frame::append(scratch,
  160. prepared.family,
  161. prepared.rawClearSize,
  162. prepared.compressedClearSize,
  163. key,
  164. nonce,
  165. response,
  166. written);
  167. }
  168. /** Appends one socket item upsert and its charged account balances when required. */
  169. bool append_socket_plug_notification(Scratch& scratch,
  170. const queuez::SocketPlug& socketPlug,
  171. const state::PendingSocketPlug& mutation,
  172. std::span<const std::byte, state::kAesKeySize> key,
  173. std::span<const std::byte, state::kBapNonceSize> nonce,
  174. std::span<std::byte> response,
  175. std::size_t& written) noexcept {
  176. snapshot::Prepared prepared{};
  177. if (!snapshot::prepare_socket_plug(scratch, socketPlug, mutation, prepared)) {
  178. return false;
  179. }
  180. const std::size_t objectCount = prepared.family.objects.size();
  181. const std::size_t expectedObjectCount = socketPlug.updatesAccount ? 2U : 1U;
  182. if (objectCount != expectedObjectCount
  183. || prepared.family.objects.front().id != socketPlug.itemInstanceDefinitionId
  184. || prepared.family.objects.front().version != socketPlug.targetInstanceSoid
  185. || prepared.family.objects.front().encoding != middleware::queuez::Encoding::oodle
  186. || prepared.family.objects.front().payload.empty()
  187. || (socketPlug.updatesAccount
  188. && (prepared.family.objects[1].id != socketPlug.accountDefinitionId
  189. || prepared.family.objects[1].version != socketPlug.accountSoid
  190. || prepared.family.objects[1].encoding != middleware::queuez::Encoding::oodle
  191. || prepared.family.objects[1].payload.empty()))
  192. || !queuez_frame::append(scratch,
  193. prepared.family,
  194. prepared.rawClearSize,
  195. prepared.compressedClearSize,
  196. key,
  197. nonce,
  198. response,
  199. written)) {
  200. return false;
  201. }
  202. return true;
  203. }
  204. /** Appends one subclass item-instance upsert after an opcode-801 selection. */
  205. bool append_subclass_selection_notification(Scratch& scratch,
  206. const queuez::SubclassSelection& selection,
  207. const state::PendingSubclassSelection& mutation,
  208. std::span<const std::byte, state::kAesKeySize> key,
  209. std::span<const std::byte, state::kBapNonceSize> nonce,
  210. std::span<std::byte> response,
  211. std::size_t& written) noexcept {
  212. snapshot::Prepared prepared{};
  213. if (!snapshot::prepare_subclass_selection(scratch, selection, mutation, prepared)) {
  214. return false;
  215. }
  216. const std::size_t objectCount = prepared.family.objects.size();
  217. if (objectCount != 1 || prepared.family.objects.front().id != selection.itemInstanceDefinitionId
  218. || prepared.family.objects.front().version != selection.subclassInstanceSoid
  219. || prepared.family.objects.front().encoding != middleware::queuez::Encoding::oodle
  220. || prepared.family.objects.front().payload.empty()
  221. || !queuez_frame::append(scratch,
  222. prepared.family,
  223. prepared.rawClearSize,
  224. prepared.compressedClearSize,
  225. key,
  226. nonce,
  227. response,
  228. written)) {
  229. return false;
  230. }
  231. return true;
  232. }
  233. /** Appends one atomic new-instance-before-character Family-4 acquisition update. */
  234. bool append_item_acquisition_notification(
  235. Scratch& scratch,
  236. const queuez::ItemAcquisition& acquisition,
  237. const state::PendingItemAcquisition& mutation,
  238. std::optional<std::uint16_t> pendingSeasonReward,
  239. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  240. std::span<const std::byte, state::kAesKeySize> key,
  241. std::span<const std::byte, state::kBapNonceSize> nonce,
  242. std::span<std::byte> response,
  243. std::size_t& written) noexcept {
  244. snapshot::Prepared prepared{};
  245. if (!snapshot::prepare_item_acquisition(scratch,
  246. acquisition,
  247. mutation,
  248. pendingSeasonReward,
  249. acquisitionPresentationRows,
  250. prepared)) {
  251. return false;
  252. }
  253. const std::size_t objectCount = prepared.family.objects.size();
  254. const std::size_t expectedObjectCount = acquisition.updatesAccount ? 3U : 2U;
  255. if (objectCount != expectedObjectCount
  256. || prepared.family.objects[0].id != acquisition.itemInstanceDefinitionId
  257. || prepared.family.objects[0].version != acquisition.acquiredInstanceSoid
  258. || prepared.family.objects[0].encoding != middleware::queuez::Encoding::oodle
  259. || prepared.family.objects[0].payload.empty()
  260. || prepared.family.objects[1].id != acquisition.characterDefinitionId
  261. || prepared.family.objects[1].version != acquisition.characterSoid
  262. || prepared.family.objects[1].encoding != middleware::queuez::Encoding::oodle
  263. || prepared.family.objects[1].payload.empty()
  264. || (acquisition.updatesAccount
  265. && (prepared.family.objects[2].id != acquisition.accountDefinitionId
  266. || prepared.family.objects[2].version != acquisition.accountSoid
  267. || prepared.family.objects[2].encoding != middleware::queuez::Encoding::oodle
  268. || prepared.family.objects[2].payload.empty()))
  269. || !queuez_frame::append(scratch,
  270. prepared.family,
  271. prepared.rawClearSize,
  272. prepared.compressedClearSize,
  273. key,
  274. nonce,
  275. response,
  276. written)) {
  277. return false;
  278. }
  279. return true;
  280. }
  281. /** Appends an optional new profile resident followed by the full account after-image. */
  282. bool append_profile_item_acquisition_notification(
  283. Scratch& scratch,
  284. const queuez::ProfileItemAcquisition& acquisition,
  285. const state::PendingProfileItemAcquisition& mutation,
  286. std::optional<std::uint16_t> pendingSeasonReward,
  287. std::span<const std::byte, state::kAesKeySize> key,
  288. std::span<const std::byte, state::kBapNonceSize> nonce,
  289. std::span<std::byte> response,
  290. std::size_t& written) noexcept {
  291. snapshot::Prepared prepared{};
  292. if (!snapshot::prepare_profile_item_acquisition(
  293. scratch, acquisition, mutation, pendingSeasonReward, prepared)) {
  294. return false;
  295. }
  296. const std::size_t objectCount = prepared.family.objects.size();
  297. const std::size_t expectedObjectCount = acquisition.appendedResident ? 2U : 1U;
  298. const std::size_t accountIndex = acquisition.appendedResident ? 1U : 0U;
  299. if (prepared.family.type != queuez::kAccountFamilyType
  300. || prepared.family.rootSoid != acquisition.after.family4RootSoid
  301. || prepared.family.version != acquisition.after.family4Version || prepared.family.flags != 0
  302. || objectCount != expectedObjectCount || accountIndex >= objectCount
  303. || prepared.family.objects[accountIndex].id != acquisition.accountDefinitionId
  304. || prepared.family.objects[accountIndex].version != acquisition.accountSoid
  305. || prepared.family.objects[accountIndex].encoding != middleware::queuez::Encoding::oodle
  306. || prepared.family.objects[accountIndex].payload.empty()
  307. || (acquisition.appendedResident
  308. && (prepared.family.objects.front().id != acquisition.itemInstanceDefinitionId
  309. || prepared.family.objects.front().version != acquisition.acquiredInstanceSoid
  310. || prepared.family.objects.front().encoding != middleware::queuez::Encoding::oodle
  311. || prepared.family.objects.front().payload.empty()))
  312. || !queuez_frame::append(scratch,
  313. prepared.family,
  314. prepared.rawClearSize,
  315. prepared.compressedClearSize,
  316. key,
  317. nonce,
  318. response,
  319. written)) {
  320. return false;
  321. }
  322. return true;
  323. }
  324. /** Publishes the transient XP row and its matching account progression in one increment. */
  325. bool append_seasonal_experience_notification(
  326. Scratch& scratch,
  327. const queuez::SessionState& before,
  328. std::int32_t amount,
  329. std::int32_t mutationSerial,
  330. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  331. std::span<const std::byte, state::kAesKeySize> key,
  332. std::span<const std::byte, state::kBapNonceSize> nonce,
  333. std::span<std::byte> response,
  334. std::size_t& written,
  335. queuez::SessionState& after) noexcept {
  336. after = before;
  337. snapshot::Prepared prepared{};
  338. if (!snapshot::prepare_seasonal_experience_presentation(
  339. scratch, before, amount, mutationSerial, acquisitionPresentationRows, prepared)) {
  340. return false;
  341. }
  342. const std::size_t objectCount = prepared.family.objects.size();
  343. if (objectCount != 2 || prepared.family.type != queuez::kAccountFamilyType
  344. || prepared.family.rootSoid != before.family4RootSoid
  345. || prepared.family.version != before.family4Version + 1 || prepared.family.flags != 0
  346. || prepared.family.objects[0].version != before.family4RootSoid
  347. || prepared.family.objects[0].id != before.family4Residents.front().definitionId
  348. || prepared.family.objects[0].payload.empty()
  349. || prepared.family.objects[1].version == before.family4RootSoid
  350. || prepared.family.objects[1].payload.empty()
  351. || !queuez_frame::append(scratch,
  352. prepared.family,
  353. prepared.rawClearSize,
  354. prepared.compressedClearSize,
  355. key,
  356. nonce,
  357. response,
  358. written)) {
  359. return false;
  360. }
  361. after.family4Version = prepared.family.version;
  362. if (!queuez::valid(after)) {
  363. after = before;
  364. return false;
  365. }
  366. return true;
  367. }
  368. /** Publishes every item in one rank-one class package as an ordinary acquisition. */
  369. bool append_season_pass_package_notification(
  370. Scratch& scratch,
  371. const queuez::SessionState& before,
  372. const state::PendingDirectItemBundle& mutation,
  373. std::uint16_t rewardIndex,
  374. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  375. std::span<const std::byte, state::kAesKeySize> key,
  376. std::span<const std::byte, state::kBapNonceSize> nonce,
  377. std::span<std::byte> response,
  378. std::size_t& written,
  379. queuez::SessionState& after) noexcept {
  380. after = before;
  381. snapshot::Prepared prepared{};
  382. const std::size_t itemCount = mutation.itemCount;
  383. if (!snapshot::prepare_season_pass_package(
  384. scratch, before, mutation, rewardIndex, acquisitionPresentationRows, prepared)
  385. || itemCount == 0 || prepared.family.objects.size() != itemCount + 2U
  386. || prepared.family.type != queuez::kAccountFamilyType
  387. || prepared.family.rootSoid != before.family4RootSoid
  388. || prepared.family.version != before.family4Version + 1 || prepared.family.flags != 0
  389. || before.family4ResidentCount + itemCount > before.family4Residents.size()) {
  390. return false;
  391. }
  392. std::uint32_t itemDefinitionId = 0;
  393. if (!middleware::datagen::object_id(
  394. queuez::kAccountFamilyType, middleware::datagen::kItemInstanceSlot, itemDefinitionId)) {
  395. return false;
  396. }
  397. for (std::size_t index = 0; index < itemCount; ++index) {
  398. const middleware::queuez::Object& object = prepared.family.objects[index];
  399. if (object.id != itemDefinitionId || object.version != mutation.firstInstanceSoid + index
  400. || object.payload.empty()) {
  401. return false;
  402. }
  403. for (std::size_t residentIndex = 0; residentIndex < before.family4ResidentCount;
  404. ++residentIndex) {
  405. if (before.family4Residents[residentIndex].objectSoid == object.version) {
  406. return false;
  407. }
  408. }
  409. after.family4Residents[after.family4ResidentCount++] =
  410. queuez::ResidentObject{object.version, object.id};
  411. }
  412. const middleware::queuez::Object& characterObject = prepared.family.objects[itemCount];
  413. const middleware::queuez::Object& accountObject = prepared.family.objects[itemCount + 1U];
  414. std::size_t characterMatches = 0;
  415. for (std::size_t index = 0; index < before.family4ResidentCount; ++index) {
  416. const queuez::ResidentObject& resident = before.family4Residents[index];
  417. characterMatches +=
  418. static_cast<std::size_t>(resident.objectSoid == characterObject.version
  419. && resident.definitionId == characterObject.id);
  420. }
  421. if (characterMatches != 1 || characterObject.payload.empty()
  422. || accountObject.version != before.family4RootSoid
  423. || accountObject.id != before.family4Residents.front().definitionId
  424. || accountObject.payload.empty()) {
  425. return false;
  426. }
  427. after.family4Version = prepared.family.version;
  428. if (!queuez::valid(after)
  429. || !queuez_frame::append(scratch,
  430. prepared.family,
  431. prepared.rawClearSize,
  432. prepared.compressedClearSize,
  433. key,
  434. nonce,
  435. response,
  436. written)) {
  437. after = before;
  438. return false;
  439. }
  440. return true;
  441. }
  442. /** Publishes one prepared record-reward batch. */
  443. bool append_record_reward_notification(
  444. Scratch& scratch,
  445. const queuez::SessionState& before,
  446. const queuez::RecordRewardGrant& update,
  447. const state::PendingRecordRewardGrant& mutation,
  448. std::optional<std::uint16_t> pendingSeasonReward,
  449. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  450. std::span<const std::byte, state::kAesKeySize> key,
  451. std::span<const std::byte, state::kBapNonceSize> nonce,
  452. std::span<std::byte> response,
  453. std::size_t& written) noexcept {
  454. snapshot::Prepared prepared{};
  455. if (!snapshot::prepare_record_reward_grant(scratch,
  456. before,
  457. update,
  458. mutation,
  459. pendingSeasonReward,
  460. acquisitionPresentationRows,
  461. prepared)
  462. || prepared.family.type != queuez::kAccountFamilyType
  463. || prepared.family.rootSoid != before.family4RootSoid
  464. || prepared.family.version != before.family4Version + 1 || prepared.family.flags != 0
  465. || prepared.family.objects.size() != update.appendedResidentCount + 2U) {
  466. return false;
  467. }
  468. for (std::size_t index = 0; index < update.appendedResidentCount; ++index) {
  469. const auto& object = prepared.family.objects[index];
  470. const auto& resident = update.after.family4Residents[before.family4ResidentCount + index];
  471. if (object.id != update.itemInstanceDefinitionId || object.version != resident.objectSoid
  472. || object.payload.empty()) {
  473. return false;
  474. }
  475. }
  476. const auto& character = prepared.family.objects[update.appendedResidentCount];
  477. const auto& account = prepared.family.objects[update.appendedResidentCount + 1U];
  478. return character.id == update.characterDefinitionId && character.version == update.characterSoid
  479. && !character.payload.empty() && account.id == update.accountDefinitionId
  480. && account.version == update.accountSoid && !account.payload.empty()
  481. && queuez_frame::append(scratch,
  482. prepared.family,
  483. prepared.rawClearSize,
  484. prepared.compressedClearSize,
  485. key,
  486. nonce,
  487. response,
  488. written);
  489. }
  490. /** Appends one atomic dismantle update, including any account-wide material payout. */
  491. bool append_item_dismantle_notification(Scratch& scratch,
  492. const queuez::ItemDismantle& dismantle,
  493. const state::PendingItemDismantle& mutation,
  494. std::span<const std::byte, state::kAesKeySize> key,
  495. std::span<const std::byte, state::kBapNonceSize> nonce,
  496. std::span<std::byte> response,
  497. std::size_t& written) noexcept {
  498. snapshot::Prepared prepared{};
  499. if (!snapshot::prepare_item_dismantle(scratch, dismantle, mutation, prepared)) {
  500. return false;
  501. }
  502. const std::size_t objectCount = prepared.family.objects.size();
  503. const std::size_t expectedObjectCount = dismantle.updatesAccount ? 3U : 2U;
  504. if (objectCount != expectedObjectCount
  505. || prepared.family.objects[0].id != dismantle.characterDefinitionId
  506. || prepared.family.objects[0].version != dismantle.characterSoid
  507. || prepared.family.objects[1].id != dismantle.itemInstanceDefinitionId
  508. || prepared.family.objects[1].version != dismantle.dismantledInstanceSoid
  509. || prepared.family.objects[1].encoding != middleware::queuez::Encoding::oodle
  510. || !prepared.family.objects[1].payload.empty()
  511. || (dismantle.updatesAccount
  512. && (prepared.family.objects[2].id != dismantle.accountDefinitionId
  513. || prepared.family.objects[2].version != dismantle.accountSoid
  514. || prepared.family.objects[2].encoding != middleware::queuez::Encoding::oodle
  515. || prepared.family.objects[2].payload.empty()))
  516. || !queuez_frame::append(scratch,
  517. prepared.family,
  518. prepared.rawClearSize,
  519. prepared.compressedClearSize,
  520. key,
  521. nonce,
  522. response,
  523. written)) {
  524. return false;
  525. }
  526. return true;
  527. }
  528. } // namespace sunrise::server::bap::encrypted::push