-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcodec.cpp
More file actions
106 lines (90 loc) · 2.67 KB
/
codec.cpp
File metadata and controls
106 lines (90 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "codec.h"
#include "protocol.h"
#include "endian.h"
uint16_t compute_checksum(const uint8_t *data, size_t len)
{
uint16_t sum = 0;
for (size_t i = 0; i < len; ++i)
{
sum ^= static_cast<uint16_t>(data[i]) << ((i & 1) * 8);
}
return sum;
}
size_t encode_order(uint8_t *buf, size_t buf_len, const Order &order)
{
using namespace protocol;
using namespace protocol::offset;
using namespace endian;
if (buf_len < ORDER_MSG_SIZE)
{
return 0;
}
// Write header
write_u16(buf + MSG_TYPE, protocol::MSG_ORDER);
write_u16(buf + MSG_LEN, ORDER_MSG_SIZE);
// Checksum written after payload
// Write payload
uint8_t *payload = buf + PAYLOAD;
write_u64(payload + ORDER_ID, order.order_id);
write_u32(payload + PRICE, order.price);
write_u32(payload + QUANTITY, order.quantity);
write_u8(payload + SIDE, order.side);
write_u8(payload + SIDE + 1, 0x00); // Padding byte
// Compute checksum over payload only
uint16_t checksum = compute_checksum(payload, ORDER_PAYLOAD_SIZE);
write_u16(buf + CHECKSUM, checksum);
return ORDER_MSG_SIZE;
}
CodecResult decode_order(const uint8_t *buf, size_t buf_len, Order &out)
{
using namespace protocol;
using namespace protocol::offset;
using namespace endian;
if (buf_len < ORDER_MSG_SIZE)
{
return CodecResult::BUFFER_TOO_SMALL;
}
// Read and validate header
uint16_t msg_type = read_u16(buf + MSG_TYPE);
uint16_t msg_len = read_u16(buf + MSG_LEN);
uint16_t checksum = read_u16(buf + CHECKSUM);
if (msg_type != protocol::MSG_ORDER)
{
return CodecResult::INVALID_MSG_TYPE;
}
if (msg_len != ORDER_MSG_SIZE)
{
return CodecResult::INVALID_MSG_LEN;
}
// Verify checksum
const uint8_t *payload = buf + PAYLOAD;
uint16_t computed = compute_checksum(payload, ORDER_PAYLOAD_SIZE);
if (computed != checksum)
{
return CodecResult::CHECKSUM_MISMATCH;
}
// Read payload
out.order_id = read_u64(payload + ORDER_ID);
out.price = read_u32(payload + PRICE);
out.quantity = read_u32(payload + QUANTITY);
out.side = read_u8(payload + SIDE);
return CodecResult::OK;
}
const char *codec_result_str(CodecResult result)
{
switch (result)
{
case CodecResult::OK:
return "OK";
case CodecResult::BUFFER_TOO_SMALL:
return "BUFFER_TOO_SMALL";
case CodecResult::INVALID_MSG_TYPE:
return "INVALID_MSG_TYPE";
case CodecResult::INVALID_MSG_LEN:
return "INVALID_MSG_LEN";
case CodecResult::CHECKSUM_MISMATCH:
return "CHECKSUM_MISMATCH";
default:
return "UNKNOWN";
}
}