-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathFrame.cpp
120 lines (92 loc) · 2.7 KB
/
Frame.cpp
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
* Copyright © 2017-2022 Matt Robinson
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <cstring>
#include <arpa/inet.h>
#include "Frame.h"
#include "FramingException.h"
static const uint8_t START_BYTE = 0x02;
static const uint8_t END_BYTE = 0x03;
static const uint LENGTH_ADJUST = 2;
struct Header
{
uint8_t start : 8;
FrameType type : 16;
uint8_t length : 8;
uint16_t function : 16;
} __attribute__((__packed__));
struct Trailer
{
uint8_t csum : 8;
uint8_t end : 8;
} __attribute__((__packed__));
Frame::Frame(const std::vector<uint8_t> &raw)
{
if(raw.size() < sizeof(Header) + sizeof(Trailer))
{
throw FramingException("Not enough data for a valid frame");
}
struct Header header;
memcpy(&header, &raw[0], sizeof(header));
if(header.start != START_BYTE)
{
throw FramingException("Incorrect start byte value");
}
if(header.length + LENGTH_ADJUST != raw.size())
{
throw FramingException("Header length (" + std::to_string(header.length) + ") does not match actual length (" + std::to_string(raw.size() - LENGTH_ADJUST) + ")");
}
type = header.type;
function = (FrameFunction)ntohs(header.function);
struct Trailer trailer;
memcpy(&trailer, &raw[raw.size() - sizeof(trailer)], sizeof(trailer));
uint8_t csum = 0;
for(uint i = 1; i < raw.size() - 2; i++)
{
csum = csum ^ raw[i];
}
if(trailer.csum != csum)
{
throw FramingException("Trailer checksum (" + std::to_string(trailer.csum) + ") does not match calculated (" + std::to_string(csum) + ")");
}
if(trailer.end != END_BYTE)
{
throw FramingException("Incorrect end byte value");
}
data = std::vector<uint8_t>(raw.begin() + sizeof(header), raw.begin() + (raw.size() - sizeof(trailer)));
}
Frame::operator std::vector<uint8_t>()
{
std::vector<uint8_t> raw(sizeof(Header) + this->data.size() + sizeof(Trailer));
struct Header header;
header.start = START_BYTE;
header.type = this->type;
header.length = raw.size() - LENGTH_ADJUST;
header.function = htons((uint16_t)this->function);
memcpy(&raw[0], &header, sizeof(header));
memcpy(&raw[sizeof(Header)], &this->data[0], this->data.size());
uint8_t csum = 0;
for(uint i = 1; i < raw.size() - 2; i++)
{
csum = csum ^ raw[i];
}
struct Trailer trailer;
trailer.csum = csum;
trailer.end = END_BYTE;
memcpy(&raw[raw.size() - sizeof(trailer)], &trailer, sizeof(trailer));
return raw;
}
FrameType Frame::getType()
{
return this->type;
}
FrameFunction Frame::getFunction()
{
return this->function;
}
std::vector<uint8_t> Frame::getData()
{
return this->data;
}