incident.h 4.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #pragma once
  2. #include <array>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <span>
  6. #include "../../encoding/bit_writer.h"
  7. namespace sunrise::middleware::bap::activity_message::incident {
  8. /** Activity message type 19 carries one incident. Both sides can send it. */
  9. inline constexpr std::uint32_t kMessageType = 19;
  10. inline constexpr std::uint8_t kTargetWidth = 13;
  11. /** The highest valid target index. Above it the Client indexes handler tables unbounded. */
  12. inline constexpr std::uint32_t kTargetMaximum = 7'762;
  13. /** These three rows carry type code -1 and are a crash risk, so they never pass. */
  14. inline constexpr std::array<std::uint32_t, 3> kPoisonTargets{795, 4'690, 5'375};
  15. inline constexpr std::uint8_t kExtraCountWidth = 5;
  16. inline constexpr std::uint32_t kExtraTargetMaximum = 25;
  17. inline constexpr std::uint8_t kSelectorPresenceWidth = 1;
  18. inline constexpr std::uint8_t kSelectorLengthWidth = 9;
  19. inline constexpr std::uint32_t kSelectorMaximum = 260;
  20. inline constexpr std::uint8_t kOptionalPresenceWidth = 1;
  21. inline constexpr std::uint8_t kOptionalFieldWidth = 64;
  22. inline constexpr std::uint8_t kOptionalWordWidth = 32;
  23. inline constexpr std::uint8_t kPayloadLengthWidth = 9;
  24. inline constexpr std::uint32_t kPayloadMaximum = 500;
  25. /** The smallest body is the five fixed fields with every count zero. */
  26. inline constexpr std::size_t kMinimumBodyBits = kTargetWidth + kExtraCountWidth
  27. + kSelectorPresenceWidth + kOptionalPresenceWidth
  28. + kPayloadLengthWidth;
  29. /** Largest body after every explicit target and optional byte field is present. */
  30. inline constexpr std::size_t kMaximumBodyBits =
  31. kTargetWidth + kExtraCountWidth + kExtraTargetMaximum * kTargetWidth + kSelectorPresenceWidth
  32. + kSelectorLengthWidth + kSelectorMaximum * 8 + kOptionalPresenceWidth + kOptionalFieldWidth
  33. + kPayloadLengthWidth + kPayloadMaximum * 8;
  34. /** Fixed byte capacity needed by the largest padded incident body. */
  35. inline constexpr std::size_t kMaximumBodyBytes = (kMaximumBodyBits + 7) / 8;
  36. /** Why one incident did not pass validation. */
  37. enum class Verdict : std::uint8_t {
  38. accepted,
  39. truncated,
  40. targetOutOfRange,
  41. targetPoisoned,
  42. tooManyTargets,
  43. payloadTooLong,
  44. selectorTooLong,
  45. };
  46. /** One outer-valid incident, framed to the end of its payload. */
  47. struct Incident {
  48. std::array<std::byte, kSelectorMaximum> selector{};
  49. std::array<std::byte, kPayloadMaximum> payload{};
  50. std::uint32_t primaryTarget{};
  51. std::uint32_t extraTargets[kExtraTargetMaximum]{};
  52. std::uint32_t extraTargetCount{};
  53. std::uint32_t selectorLength{};
  54. std::uint32_t payloadLength{};
  55. std::uint32_t optionalWordA{};
  56. std::uint32_t optionalWordB{};
  57. /** Bits the body used. Below the payload's own bit count means trailing padding. */
  58. std::uint32_t consumedBits{};
  59. bool hasCompressedSelector{};
  60. /** Set when the two optional words are present. */
  61. bool hasOptionalBlock{};
  62. bool hasPayload{};
  63. };
  64. /** @return A short stable name for one verdict, for the log line. */
  65. [[nodiscard]] const char* verdict_name(Verdict verdict) noexcept;
  66. /** @return True when every outer wire field is bounded; payload semantics are not checked. */
  67. [[nodiscard]] bool outer_valid(const Incident& incident) noexcept;
  68. /**
  69. * Validates one incident body from its first target to the end of its payload.
  70. * Every target index is range and poison checked before anything else, because an out-of-range
  71. * index is a crash in the consumer rather than a decode error.
  72. * @param payload Activity message payload after the envelope.
  73. * @param parsed Cleared first. Receives every field reached before the verdict.
  74. * @return accepted, or the first rule the body broke.
  75. */
  76. [[nodiscard]] Verdict validate(std::span<const std::byte> payload, Incident& parsed) noexcept;
  77. /**
  78. * Writes one bounded incident body after outer-field preflight.
  79. * The caller still owns activity identity, output ordering, nonce commit and transport staging.
  80. */
  81. [[nodiscard]] bool write(encoding::bits::Writer& writer, const Incident& incident) noexcept;
  82. } // namespace sunrise::middleware::bap::activity_message::incident