group_migration_receipts.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include "group_migration_receipts.h"
  2. #include "../../../middleware/gameplay/group/migration_messages.h"
  3. #include "../../../middleware/gameplay/group/notice_messages.h"
  4. #include "../gameplay_log.h"
  5. namespace sunrise::server::gameplay::group::migration {
  6. namespace {
  7. namespace wire = middleware::gameplay::group;
  8. namespace bits = middleware::encoding::bits;
  9. /** @return True when the id names a migration body carrying nothing but a group session. */
  10. [[nodiscard]] bool session_only(std::uint8_t id) noexcept {
  11. return id == static_cast<std::uint8_t>(wire::MigrationMessageId::reestablishPending)
  12. || id == static_cast<std::uint8_t>(wire::MigrationMessageId::peerReestablish);
  13. }
  14. /**
  15. * Reads a handoff or its acknowledgement.
  16. * @param id Registry message id, which names which half of the pair this is.
  17. * @param reader Reader positioned at the body.
  18. * @return True when the body was completely read.
  19. */
  20. [[nodiscard]] bool consume_handoff(std::uint8_t id, bits::Reader& reader) noexcept {
  21. wire::HostHandoff body{};
  22. if (!wire::read_host_handoff(reader, body)) {
  23. return false;
  24. }
  25. report(core::log::Level::info,
  26. "ev=gameplay stage=migration result=handoff id=%u session=0x%016llX successor=%u",
  27. static_cast<unsigned>(id),
  28. static_cast<unsigned long long>(body.sessionId),
  29. static_cast<unsigned>(body.successorIndex));
  30. return true;
  31. }
  32. /**
  33. * Reads one body a group host normally emits and records what it said.
  34. * @param id Registry message id.
  35. * @param reader Reader positioned at the body.
  36. * @return True when the id is one of these messages and its body was completely read.
  37. */
  38. [[nodiscard]] bool consume_notice(std::uint8_t id, bits::Reader& reader) noexcept {
  39. if (id == static_cast<std::uint8_t>(wire::NoticeMessageId::peerConnectNotice)) {
  40. wire::PeerConnectNotice body{};
  41. if (!wire::read_peer_connect(reader, body)) {
  42. return false;
  43. }
  44. report(core::log::Level::debug,
  45. "ev=gameplay stage=notice result=peer_connect session=0x%016llX machine=0x%016llX "
  46. "protocol=0x%04X",
  47. static_cast<unsigned long long>(body.sessionId),
  48. static_cast<unsigned long long>(body.machineId),
  49. static_cast<unsigned>(body.protocolVersion));
  50. return true;
  51. }
  52. if (id == static_cast<std::uint8_t>(wire::NoticeMessageId::sessionBootNotice)) {
  53. wire::SessionBootNotice body{};
  54. if (!wire::read_session_boot(reader, body)) {
  55. return false;
  56. }
  57. report(core::log::Level::warn,
  58. "ev=gameplay stage=notice result=boot session=0x%016llX kind=%u reason=%u",
  59. static_cast<unsigned long long>(body.sessionId),
  60. static_cast<unsigned>(body.kind),
  61. static_cast<unsigned>(body.reason));
  62. return true;
  63. }
  64. const bool delegate =
  65. id == static_cast<std::uint8_t>(wire::NoticeMessageId::delegateLeadership);
  66. if (delegate || id == static_cast<std::uint8_t>(wire::NoticeMessageId::bootMachine)) {
  67. wire::AddressedNotice body{};
  68. if (!wire::read_addressed_notice(reader, !delegate, body)) {
  69. return false;
  70. }
  71. report(core::log::Level::warn,
  72. "ev=gameplay stage=notice result=%s session=0x%016llX kind=%u",
  73. delegate ? "delegate" : "boot_machine",
  74. static_cast<unsigned long long>(body.sessionId),
  75. static_cast<unsigned>(body.kind));
  76. return true;
  77. }
  78. if (id == static_cast<std::uint8_t>(wire::NoticeMessageId::playerRefuse)) {
  79. wire::PlayerRefuse body{};
  80. if (!wire::read_player_refuse(reader, body)) {
  81. return false;
  82. }
  83. report(core::log::Level::warn,
  84. "ev=gameplay stage=notice result=player_refuse session=0x%016llX player=0x%016llX "
  85. "reason=%u",
  86. static_cast<unsigned long long>(body.sessionId),
  87. static_cast<unsigned long long>(body.playerId),
  88. static_cast<unsigned>(body.reason));
  89. return true;
  90. }
  91. if (id == static_cast<std::uint8_t>(wire::NoticeMessageId::voiceRegistration)) {
  92. if (!wire::read_voice_registration(reader)) {
  93. return false;
  94. }
  95. report(core::log::Level::debug, "ev=gameplay stage=notice result=voice");
  96. return true;
  97. }
  98. return false;
  99. }
  100. } // namespace
  101. /** Reads one host-migration or election message and records what it said. */
  102. bool consume(std::uint8_t id, bits::Reader& reader) noexcept {
  103. if (id == static_cast<std::uint8_t>(wire::MigrationMessageId::hostHandoff)
  104. || id == static_cast<std::uint8_t>(wire::MigrationMessageId::peerHandoff)) {
  105. return consume_handoff(id, reader);
  106. }
  107. if (id == static_cast<std::uint8_t>(wire::MigrationMessageId::hostTransition)) {
  108. wire::HostTransition body{};
  109. if (!wire::read_host_transition(reader, body)) {
  110. return false;
  111. }
  112. report(core::log::Level::info,
  113. "ev=gameplay stage=migration result=transition session=0x%016llX progress=%u "
  114. "token=0x%08X",
  115. static_cast<unsigned long long>(body.sessionId),
  116. static_cast<unsigned>(body.progress),
  117. body.transitionToken);
  118. return true;
  119. }
  120. if (id == static_cast<std::uint8_t>(wire::MigrationMessageId::hostReestablish)) {
  121. wire::HostReestablish body{};
  122. if (!wire::read_host_reestablish(reader, body)) {
  123. return false;
  124. }
  125. // The new host is recorded and not installed. Installing one from a peer's own claim is
  126. // how a group ends up with two hosts.
  127. report(core::log::Level::warn,
  128. "ev=gameplay stage=migration result=reestablish session=0x%016llX machine=0x%016llX",
  129. static_cast<unsigned long long>(body.sessionId),
  130. static_cast<unsigned long long>(body.machineId));
  131. return true;
  132. }
  133. if (session_only(id)) {
  134. std::uint64_t sessionId = 0;
  135. if (!wire::read_migration_session(reader, sessionId)) {
  136. return false;
  137. }
  138. report(core::log::Level::debug,
  139. "ev=gameplay stage=migration result=pending id=%u session=0x%016llX",
  140. static_cast<unsigned>(id),
  141. static_cast<unsigned long long>(sessionId));
  142. return true;
  143. }
  144. if (id == static_cast<std::uint8_t>(wire::MigrationMessageId::hostDecline)) {
  145. wire::HostDecline body{};
  146. if (!wire::read_host_decline(reader, body)) {
  147. return false;
  148. }
  149. report(core::log::Level::info,
  150. "ev=gameplay stage=migration result=decline session=0x%016llX data=%u flag=%u",
  151. static_cast<unsigned long long>(body.sessionId),
  152. static_cast<unsigned>(body.hasDeclineData),
  153. static_cast<unsigned>(body.declineFlag));
  154. return true;
  155. }
  156. if (id == static_cast<std::uint8_t>(wire::MigrationMessageId::election)) {
  157. wire::Election body{};
  158. if (!wire::read_election(reader, body)) {
  159. return false;
  160. }
  161. report(core::log::Level::warn,
  162. "ev=gameplay stage=migration result=election session=0x%016llX candidates=%u "
  163. "tail=%u",
  164. static_cast<unsigned long long>(body.sessionId),
  165. static_cast<unsigned>(body.candidateCount),
  166. body.tailBits);
  167. // The candidate value width is unrecovered, so the bitsets behind the addresses were not
  168. // located and no later message in this container can be found.
  169. return false;
  170. }
  171. if (id == static_cast<std::uint8_t>(wire::MigrationMessageId::electionRefuse)) {
  172. wire::ElectionRefuse body{};
  173. if (!wire::read_election_refuse(reader, body)) {
  174. return false;
  175. }
  176. report(core::log::Level::info,
  177. "ev=gameplay stage=migration result=election_refuse session=0x%016llX code=%u",
  178. static_cast<unsigned long long>(body.sessionId),
  179. static_cast<unsigned>(body.refuseCode));
  180. return true;
  181. }
  182. return consume_notice(id, reader);
  183. }
  184. } // namespace sunrise::server::gameplay::group::migration