BCNP 3.2.1
Batched Command Network Protocol
Loading...
Searching...
No Matches
packet.cpp
Go to the documentation of this file.
1
9#include "bcnp/packet.h"
10
11#include <algorithm>
12#include <array>
13#include <cmath>
14#include <cstring>
15#include <limits>
16
17namespace bcnp {
18namespace {
19
28constexpr std::array<uint32_t, 256> MakeCrcTable() {
29 std::array<uint32_t, 256> table{};
30 for (uint32_t i = 0; i < 256; ++i) {
31 uint32_t crc = i;
32 for (uint32_t bit = 0; bit < 8; ++bit) {
33 if (crc & 1U) {
34 crc = (crc >> 1U) ^ 0xEDB88320U;
35 } else {
36 crc >>= 1U;
37 }
38 }
39 table[i] = crc;
40 }
41 return table;
42}
43
45constexpr auto kCrc32Table = MakeCrcTable();
46
47} // namespace
48
49uint32_t ComputeCrc32(const uint8_t* data, std::size_t length) {
50 uint32_t crc = 0xFFFFFFFFU;
51 for (std::size_t i = 0; i < length; ++i) {
52 const uint8_t index = static_cast<uint8_t>((crc ^ data[i]) & 0xFFU);
53 crc = (crc >> 8U) ^ kCrc32Table[index];
54 }
55 return crc ^ 0xFFFFFFFFU;
56}
57
58std::size_t PacketView::GetPayloadSize() const {
60 if (!info) return 0;
61 return info->wireSize * header.messageCount;
62}
63
64
76DecodeViewResult DecodePacketViewWithSize(const uint8_t* data, std::size_t length, std::size_t wireSize) {
77 DecodeViewResult result{};
78
79 if (length < kHeaderSizeV3) {
80 result.error = PacketError::TooSmall;
81 return result;
82 }
83
84 // Parse header
85 PacketHeader header;
86 header.major = data[kHeaderMajorIndex];
87 header.minor = data[kHeaderMinorIndex];
88 header.flags = data[kHeaderFlagsIndex];
89 header.messageType = static_cast<MessageTypeId>(detail::LoadU16(&data[kHeaderMsgTypeIndex]));
91
92 // Version check
93 if (header.major != kProtocolMajorV3 || header.minor != kProtocolMinorV3) {
95 result.bytesConsumed = 1;
96 return result;
97 }
98
100 result.error = PacketError::TooManyMessages;
101 result.bytesConsumed = 1;
102 return result;
103 }
104
105 // Calculate sizes based on provided wire size
106 const std::size_t payloadSize = kHeaderSizeV3 + (header.messageCount * wireSize);
107 const std::size_t expectedSize = payloadSize + kChecksumSize;
108 if (length < expectedSize) {
109 result.error = PacketError::Truncated;
110 return result;
111 }
112
113 // CRC validation
114 const uint32_t transmittedCrc = detail::LoadU32(&data[payloadSize]);
115 const uint32_t computedCrc = ComputeCrc32(data, payloadSize);
116 if (transmittedCrc != computedCrc) {
117 result.error = PacketError::ChecksumMismatch;
118 result.bytesConsumed = expectedSize;
119 return result;
120 }
121
122 PacketView view;
123 view.header = header;
124 view.payloadStart = data + kHeaderSizeV3;
125
126 result.view = view;
127 result.error = PacketError::None;
128 result.bytesConsumed = expectedSize;
129 return result;
130}
131
143DecodeViewResult DecodePacketView(const uint8_t* data, std::size_t length) {
144 DecodeViewResult result{};
145
146 if (length < kHeaderSizeV3) {
147 result.error = PacketError::TooSmall;
148 return result;
149 }
150
151 // Parse header to get message type
152 const auto messageType = static_cast<MessageTypeId>(detail::LoadU16(&data[kHeaderMsgTypeIndex]));
153
154 // Look up wire size from registry
155 auto msgInfo = GetMessageInfo(messageType);
156 if (!msgInfo) {
157 result.error = PacketError::UnknownMessageType;
158 result.bytesConsumed = 1;
159 return result;
160 }
161
162 return DecodePacketViewWithSize(data, length, msgInfo->wireSize);
163}
164
165} // namespace bcnp
constexpr std::size_t kHeaderMajorIndex
Byte offset of major version in header.
Definition packet.h:57
constexpr std::size_t kHeaderMinorIndex
Byte offset of minor version in header.
Definition packet.h:60
constexpr std::size_t kHeaderFlagsIndex
Byte offset of flags byte in header.
Definition packet.h:63
constexpr std::size_t kMaxMessagesPerPacket
Maximum number of messages allowed in a single packet.
Definition packet.h:34
constexpr std::size_t kChecksumSize
Size of CRC32 checksum in bytes.
Definition packet.h:31
uint32_t LoadU32(const uint8_t *p)
uint16_t LoadU16(const uint8_t *p)
constexpr std::size_t kHeaderMsgCountIndex
std::optional< MessageInfo > GetMessageInfo(MessageTypeId typeId)
DecodeViewResult DecodePacketView(const uint8_t *data, std::size_t length)
Decode a packet using the global message type registry.
Definition packet.cpp:143
constexpr std::size_t kHeaderMsgTypeIndex
uint32_t ComputeCrc32(const uint8_t *data, std::size_t length)
Compute CRC32 checksum for data integrity verification.
Definition packet.cpp:49
constexpr uint8_t kProtocolMinorV3
@ UnsupportedVersion
Protocol version mismatch.
@ ChecksumMismatch
CRC32 validation failed.
@ TooManyMessages
Message count exceeds kMaxMessagesPerPacket.
@ Truncated
Buffer ends before expected packet length.
@ UnknownMessageType
Message type ID not in registry.
@ None
No error - packet decoded successfully.
@ TooSmall
Buffer too small to contain header.
DecodeViewResult DecodePacketViewWithSize(const uint8_t *data, std::size_t length, std::size_t wireSize)
Decode a packet with explicitly provided message wire size.
Definition packet.cpp:76
constexpr std::size_t kHeaderSizeV3
constexpr uint8_t kProtocolMajorV3
BCNP packet structures, encoding, and decoding utilities.
Result of decoding a packet from raw bytes.
Definition packet.h:289
Parsed packet header structure.
Definition packet.h:75
uint8_t minor
Protocol minor version.
Definition packet.h:77
uint8_t major
Protocol major version.
Definition packet.h:76
uint8_t flags
Packet flags (e.g., kFlagClearQueue)
Definition packet.h:78
uint16_t messageCount
Number of messages in payload.
Definition packet.h:80
MessageTypeId messageType
Type ID of messages in payload.
Definition packet.h:79
Zero-copy view into a decoded packet buffer.
Definition packet.h:170
PacketHeader header
Parsed header information.
Definition packet.h:171
std::size_t GetPayloadSize() const
Calculate total payload size in bytes.
Definition packet.cpp:58
const uint8_t * payloadStart
Pointer to first message in buffer.
Definition packet.h:172