libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
server.cpp
1#include "server.hpp"
2
3#include <cstddef>
4#include <cstdint>
5
6#include "../packet/packet.hpp"
7#include "crc.hpp"
8#include "libxr_mem.hpp"
9
10using namespace LibXR;
11
12Topic::Server::Server(size_t buffer_length)
13 : topic_map_([](const uint32_t& a, const uint32_t& b) { return (a > b) - (a < b); }),
14 queue_(1, buffer_length)
15{
16 ASSERT(buffer_length > PACK_BASE_SIZE);
17 parse_buff_.size_ = buffer_length;
18 parse_buff_.addr_ =
19 new (std::align_val_t(LibXR::CACHE_LINE_SIZE)) uint8_t[parse_buff_.size_];
20}
21
23{
24 ASSERT(topic != nullptr);
25 ASSERT(topic->data_.payload_size != 0);
26 ASSERT(topic->data_.payload_alignment != 0);
27 ASSERT(topic->data_.payload_alignment <= LibXR::CACHE_LINE_SIZE);
28
29 ASSERT(topic->data_.payload_size + PACK_BASE_SIZE <= parse_buff_.size_);
30
31 auto* node = new RBTree<uint32_t>::Node<TopicHandle>(topic);
32 topic_map_.Insert(*node, topic->key);
33}
34
36{
37 return ParseDataRaw(data, false, false);
38}
39
41{
42 return ParseDataRaw(data, true, in_isr);
43}
44
45size_t Topic::Server::ParseDataRaw(ConstRawData data, bool from_callback, bool in_isr)
46{
47 size_t count = 0;
48
49 (void)queue_.PushBatchBytes(data.addr_, data.size_);
50
51 while (true)
52 {
53 if (status_ == Status::WAIT_START && !SyncToPacketStart())
54 {
55 return count;
56 }
57
58 if (status_ == Status::WAIT_TOPIC && !ReadHeader())
59 {
60 return count;
61 }
62
63 if (status_ == Status::WAIT_DATA_CRC)
64 {
65 switch (ReadPayload(from_callback, in_isr))
66 {
67 case ParseResult::NEED_MORE:
68 return count;
69 case ParseResult::DROPPED:
70 continue;
71 case ParseResult::DELIVERED:
72 count++;
73 continue;
74 }
75 }
76 }
77}
78
80{
81 auto queue_size = queue_.Size();
82 for (uint32_t i = 0; i < queue_size; i++)
83 {
84 uint8_t prefix = 0;
85 queue_.PeekBytes(&prefix);
86 if (prefix == PACKET_PREFIX)
87 {
88 status_ = Status::WAIT_TOPIC;
89 return true;
90 }
91 queue_.PopBytes();
92 }
93
94 return false;
95}
96
98{
99 if (queue_.Size() < sizeof(PackedDataHeader))
100 {
101 return false;
102 }
103
104 queue_.PopBatchBytes(parse_buff_.addr_, sizeof(PackedDataHeader));
105 if (!CRC8::Verify(parse_buff_.addr_, sizeof(PackedDataHeader)))
106 {
107 ResetParser();
108 return true;
109 }
110
111 auto* header = reinterpret_cast<PackedDataHeader*>(parse_buff_.addr_);
112 if (header->version != PACKET_VERSION)
113 {
114 ResetParser();
115 return true;
116 }
117
118 auto* node = topic_map_.Search<TopicHandle>(header->topic_name_crc32);
119 if (node == nullptr)
120 {
121 ResetParser();
122 return true;
123 }
124
125 data_len_ = header->GetDataLen();
126 current_timestamp_ = header->GetTimestamp();
127 current_topic_ = *node;
128 const auto target_size = current_topic_->data_.payload_size;
129
130 if (target_size + PACK_BASE_SIZE > parse_buff_.size_)
131 {
132 ResetParser();
133 return true;
134 }
135
136 if (data_len_ + PACK_BASE_SIZE > queue_.length_)
137 {
138 ResetParser();
139 return true;
140 }
141
142 status_ = Status::WAIT_DATA_CRC;
143 return true;
144}
145
147{
148 if (queue_.Size() < data_len_ + sizeof(uint8_t))
149 {
150 return ParseResult::NEED_MORE;
151 }
152
153 auto* payload_addr =
154 reinterpret_cast<uint8_t*>(parse_buff_.addr_) + sizeof(PackedDataHeader);
155 queue_.PopBatchBytes(payload_addr, data_len_ + sizeof(uint8_t));
156
157 if (!CRC8::Verify(parse_buff_.addr_,
158 data_len_ + sizeof(PackedDataHeader) + sizeof(uint8_t)))
159 {
160 ResetParser();
161 return ParseResult::DROPPED;
162 }
163
164 const auto target_size = current_topic_->data_.payload_size;
165 void* publish_addr = payload_addr;
166 if (reinterpret_cast<uintptr_t>(payload_addr) %
167 current_topic_->data_.payload_alignment !=
168 0)
169 {
170 publish_addr = parse_buff_.addr_;
171 if (data_len_ >= target_size)
172 {
173 LibXR::Memory::FastMove(publish_addr, payload_addr, target_size);
174 }
175 else
176 {
177 LibXR::Memory::FastMove(publish_addr, payload_addr, data_len_);
178 }
179 }
180
181 auto topic = Topic(current_topic_);
182 if (from_callback)
183 {
184 topic.PublishBytesFromServerCallback(publish_addr, target_size, current_timestamp_,
185 in_isr);
186 }
187 else
188 {
189 topic.PublishBytesFromServer(publish_addr, target_size, current_timestamp_);
190 }
191
192 ResetParser();
193 return ParseResult::DELIVERED;
194}
195
197{
198 status_ = Status::WAIT_START;
199 data_len_ = 0;
200 current_topic_ = nullptr;
201 current_timestamp_ = MicrosecondTimestamp();
202}
static bool Verify(const void *raw, size_t len)
验证数据的 CRC8 校验码 / Verifies the CRC8 checksum of the given data
Definition crc.hpp:78
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
static void FastMove(void *dst, const void *src, size_t size)
内存搬移 / Memory move
微秒时间戳 / Microsecond timestamp
Key key
节点键值 (Key associated with the node).
Definition rbt.hpp:40
红黑树的泛型数据节点,继承自 BaseNode (Generic data node for Red-Black Tree, inheriting from BaseNode).
Definition rbt.hpp:63
Data data_
存储的数据 (Stored data).
Definition rbt.hpp:98
红黑树实现,支持泛型键和值,并提供线程安全操作 (Red-Black Tree implementation supporting generic keys and values with thread...
Definition rbt.hpp:23
size_t ParseDataRaw(ConstRawData data, bool from_callback, bool in_isr)
ParseData*() 的共享实现 / Shared implementation behind ParseData*()
Definition server.cpp:45
void Register(TopicHandle topic)
注册一个可接收 packet 的 topic / Register one topic that may receive parsed packets
Definition server.cpp:22
void ResetParser()
清空当前包的解析上下文并回到找起点状态 / Clear the current packet parsing context and return to the start-search state
Definition server.cpp:196
size_t ParseData(ConstRawData data)
在普通上下文里喂入一批新字节 / Feed one new byte batch in normal context
Definition server.cpp:35
ParseResult
一次 payload 阶段处理结果 / Result of one payload-stage handling step
Definition server.hpp:88
size_t ParseDataFromCallback(ConstRawData data, bool in_isr)
在回调/ISR 路径里喂入一批新字节 / Feed one new byte batch in callback/ISR path
Definition server.cpp:40
bool ReadHeader()
在已对齐前缀后继续读取并校验完整头部 / Read and validate the full header after the prefix is aligned
Definition server.cpp:97
bool SyncToPacketStart()
把输入流同步到下一条 packet 起点 / Synchronize the input stream to the next packet start
Definition server.cpp:79
Server(size_t buffer_length)
构造 parser 并分配内部暂存队列 / Construct the parser and allocate its internal staging queue
Definition server.cpp:12
ParseResult ReadPayload(bool from_callback, bool in_isr)
读取当前包的 payload 和尾 CRC,并在成功时发布 / Read the payload and trailing CRC of the current packet and publish i...
Definition server.cpp:146
Topic()
构造一个空 topic 视图 / Construct one empty topic view
Definition topic.cpp:114
LibXR 命名空间
Definition ch32_can.hpp:14
constexpr size_t CACHE_LINE_SIZE
兼容旧代码的缓存行别名 / Backward-compatible cache-line alias for existing code
Definition libxr_def.hpp:66