libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
server.cpp
1#include "message.hpp"
2
3using namespace LibXR;
4
5Topic::Server::Server(size_t buffer_length)
6 : topic_map_([](const uint32_t& a, const uint32_t& b)
7 { return static_cast<int>(a) - static_cast<int>(b); }),
8 queue_(1, buffer_length)
9{
10 /* Minimum size: header8 + crc32 + length24 + crc8 + data + crc8 = 10 */
11 ASSERT(buffer_length > PACK_BASE_SIZE);
12 parse_buff_.size_ = buffer_length;
13 parse_buff_.addr_ = new uint8_t[buffer_length];
14}
15
17{
18 auto node = new RBTree<uint32_t>::Node<TopicHandle>(topic);
19 topic_map_.Insert(*node, topic->key);
20}
21
23{
24 return ParseDataRaw(data, false, false);
25}
26
28{
29 return ParseDataRaw(data, true, in_isr);
30}
31
32size_t Topic::Server::ParseDataRaw(ConstRawData data, bool from_callback, bool in_isr)
33{
34 size_t count = 0;
35
36 /* Preserve legacy backpressure behavior: if the parser queue is full, this batch is
37 * not appended and parsing continues with bytes that were already buffered. */
38 queue_.PushBatch(data.addr_, data.size_);
39
40 while (true)
41 {
42 if (status_ == Status::WAIT_START && !SyncToPacketStart())
43 {
44 return count;
45 }
46
47 if (status_ == Status::WAIT_TOPIC && !ReadHeader())
48 {
49 return count;
50 }
51
52 if (status_ == Status::WAIT_DATA_CRC)
53 {
54 switch (ReadPayload(from_callback, in_isr))
55 {
56 case ParseResult::NEED_MORE:
57 return count;
58 case ParseResult::DROPPED:
59 continue;
60 case ParseResult::DELIVERED:
61 count++;
62 continue;
63 }
64 }
65 }
66 return count;
67}
68
69bool Topic::Server::SyncToPacketStart()
70{
71 auto queue_size = queue_.Size();
72 for (uint32_t i = 0; i < queue_size; i++)
73 {
74 uint8_t prefix = 0;
75 queue_.Peek(&prefix);
76 if (prefix == PACKET_PREFIX)
77 {
78 status_ = Status::WAIT_TOPIC;
79 return true;
80 }
81 queue_.Pop();
82 }
83
84 return false;
85}
86
87bool Topic::Server::ReadHeader()
88{
89 if (queue_.Size() < sizeof(PackedDataHeader))
90 {
91 return false;
92 }
93
94 queue_.PopBatch(parse_buff_.addr_, sizeof(PackedDataHeader));
95 if (!CRC8::Verify(parse_buff_.addr_, sizeof(PackedDataHeader)))
96 {
97 ResetParser();
98 return true;
99 }
100
101 auto header = reinterpret_cast<PackedDataHeader*>(parse_buff_.addr_);
102 auto node = topic_map_.Search<TopicHandle>(header->topic_name_crc32);
103 if (node == nullptr)
104 {
105 ResetParser();
106 return true;
107 }
108
109 data_len_ = header->GetDataLen();
110 current_timestamp_ = header->GetTimestamp();
111 current_topic_ = *node;
112 if (data_len_ + PACK_BASE_SIZE > queue_.length_)
113 {
114 ResetParser();
115 return true;
116 }
117
118 status_ = Status::WAIT_DATA_CRC;
119 return true;
120}
121
122Topic::Server::ParseResult Topic::Server::ReadPayload(bool from_callback, bool in_isr)
123{
124 if (queue_.Size() < data_len_ + sizeof(uint8_t))
125 {
126 return ParseResult::NEED_MORE;
127 }
128
129 auto data = reinterpret_cast<uint8_t*>(parse_buff_.addr_) + sizeof(PackedDataHeader);
130 queue_.PopBatch(data, data_len_ + sizeof(uint8_t));
131
132 if (!CRC8::Verify(parse_buff_.addr_,
133 data_len_ + sizeof(PackedDataHeader) + sizeof(uint8_t)))
134 {
135 ResetParser();
136 return ParseResult::DROPPED;
137 }
138
139 if (data_len_ > current_topic_->data_.max_length)
140 {
141 data_len_ = current_topic_->data_.max_length;
142 }
143 auto topic = Topic(current_topic_);
144 if (from_callback)
145 {
146 topic.PublishFromCallback(data, data_len_, current_timestamp_, in_isr);
147 }
148 else
149 {
150 topic.Publish(data, data_len_, current_timestamp_);
151 }
152 ResetParser();
153 return ParseResult::DELIVERED;
154}
155
156void Topic::Server::ResetParser()
157{
158 status_ = Status::WAIT_START;
159 data_len_ = 0;
160 current_topic_ = nullptr;
161 current_timestamp_ = MicrosecondTimestamp();
162}
static bool Verify(const void *raw, size_t len)
验证数据的 CRC8 校验码 / Verifies the CRC8 checksum of the given data
Definition crc.hpp:92
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
微秒时间戳 / Microsecond timestamp
Key key
节点键值 (Key associated with the node).
Definition rbt.hpp:41
红黑树的泛型数据节点,继承自 BaseNode (Generic data node for Red-Black Tree, inheriting from BaseNode).
Definition rbt.hpp:64
红黑树实现,支持泛型键和值,并提供线程安全操作 (Red-Black Tree implementation supporting generic keys and values with thread...
Definition rbt.hpp:24
void Register(TopicHandle topic)
注册一个主题 Registers a topic
Definition server.cpp:16
size_t ParseData(ConstRawData data)
解析接收到的数据 Parses received data
Definition server.cpp:22
size_t ParseDataFromCallback(ConstRawData data, bool in_isr)
在回调函数中解析接收到的数据 Parses received data in a callback
Definition server.cpp:27
Server(size_t buffer_length)
构造函数,初始化服务器并分配缓冲区 Constructor to initialize the server and allocate buffer
Definition server.cpp:5
RBTree< uint32_t >::Node< Block > * TopicHandle
主题句柄,指向存储数据的红黑树节点。Handle pointing to a red-black tree node storing data.
Definition message.hpp:135
Topic()
默认构造函数,创建一个空的 Topic 实例 Default constructor, creates an empty Topic instance
Definition topic.cpp:132
LibXR 命名空间
Definition ch32_can.hpp:14