Skip to content

Commit 6a954fa

Browse files
committed
TBT feat: server using decoder. mod: wrapper handles incomplete parameters deserialization. todo discard_packet needed to recover malformed client requests
1 parent 0ec6ea9 commit 6a954fa

File tree

5 files changed

+115
-52
lines changed

5 files changed

+115
-52
lines changed

examples/rpc_lite_server/rpc_lite_server.ino

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include <Arduino_RPClite.h>
2-
#include <HardwareSerial.h>
32

4-
SerialTransport transport(&Serial2);
3+
SerialTransport transport(&Serial0);
54
RPCServer server(transport);
65

76
int add(int a, int b){
@@ -17,7 +16,7 @@ MsgPack::str_t loopback(MsgPack::str_t message){
1716
}
1817

1918
void setup() {
20-
Serial2.begin(115200);
19+
Serial0.begin(115200);
2120
transport.begin();
2221
pinMode(LED_BUILTIN, OUTPUT);
2322
Serial.begin(9600);
@@ -37,5 +36,5 @@ void blink_before(){
3736

3837
void loop() {
3938
blink_before();
40-
server.loop();
39+
server.run();
4140
}

src/decoder.h

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#ifndef RPCLITE_DECODER_H
22
#define RPCLITE_DECODER_H
3-
#include "transport.h"
3+
44
#include "MsgPack.h"
5+
#include "transport.h"
6+
#include "dispatcher.h"
57

68

79
#define NO_MSG -1
@@ -113,6 +115,74 @@ class RpcDecoder {
113115

114116
}
115117

118+
template<size_t N>
119+
void process_requests(RpcFunctionDispatcher<N>& dispatcher) {
120+
if (_packet_type!=CALL_MSG && _packet_type!=NOTIFY_MSG) return;
121+
122+
static MsgPack::Unpacker unpacker;
123+
static MsgPack::Packer packer;
124+
125+
size_t bytes_checked = 0;
126+
127+
while (bytes_checked < _bytes_stored) {
128+
bytes_checked++;
129+
unpacker.clear();
130+
if (!unpacker.feed(_raw_buffer, bytes_checked)) continue;
131+
132+
int msg_type;
133+
int msg_id;
134+
MsgPack::str_t method;
135+
MsgPack::arr_size_t req_size;
136+
137+
if (!unpacker.deserialize(req_size, msg_type)) break;
138+
// todo HANDLE MALFORMED CLIENT REQ ERRORS
139+
if ((req_size.size() == REQUEST_SIZE) && (msg_type == CALL_MSG)){
140+
if (!unpacker.deserialize(msg_id, method)) {
141+
discard_packet();
142+
break;
143+
}
144+
} else if ((req_size.size() == NOTIFY_SIZE) && (msg_type == NOTIFY_MSG)) {
145+
if (!unpacker.deserialize(method)) {
146+
discard_packet();
147+
break;
148+
}
149+
} else if ((req_size.size() == RESPONSE_SIZE) && (msg_type == RESP_MSG)) { // this should never happen
150+
break;
151+
} else {
152+
discard_packet();
153+
break;
154+
}
155+
156+
MsgPack::arr_size_t resp_size(RESPONSE_SIZE);
157+
packer.clear();
158+
packer.serialize(resp_size, RESP_MSG, msg_id);
159+
size_t headers_size = packer.size();
160+
161+
if (!dispatcher.call(method, unpacker, packer)) {
162+
if (packer.size()==headers_size) {
163+
// Call didn't go through bc parameters are not ready yet
164+
continue;
165+
} else {
166+
// something went wrong the call raised an error or the client issued a malformed request
167+
if (msg_type == CALL_MSG) {
168+
send(reinterpret_cast<const uint8_t*>(packer.data()), packer.size()) == packer.size();
169+
} // if notification client will never know something went wrong
170+
discard_packet(); // agnostic pop
171+
break;
172+
}
173+
} else {
174+
// all is well we can respond and pop the deserialized packet
175+
if (msg_type == CALL_MSG){
176+
send(reinterpret_cast<const uint8_t*>(packer.data()), packer.size()) == packer.size();
177+
}
178+
pop_packet(bytes_checked);
179+
break;
180+
}
181+
182+
}
183+
184+
}
185+
116186
void process(){
117187
if (advance()) parse_packet();
118188
}
@@ -192,6 +262,13 @@ class RpcDecoder {
192262
return size;
193263
}
194264

265+
size_t discard_packet() {
266+
// todo recursive packet size measurement
267+
// use pop_packet with size
268+
// return popped bytes
269+
return 0;
270+
}
271+
195272
inline size_t size() const {return _bytes_stored;}
196273

197274
#ifdef DEBUG

src/decoder_manager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
template<size_t MaxTransports = RPCLITE_MAX_TRANSPORTS>
1313
class RpcDecoderManager {
1414
public:
15+
// todo parametrize so the RpcDecoder returned has a user defined buffer size ?
1516
static RpcDecoder<>& getDecoder(ITransport& transport) {
1617
for (auto& entry : decoders_) {
1718
if (entry.transport == &transport) {

src/server.h

Lines changed: 9 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,65 +5,33 @@
55
#ifndef RPCLITE_SERVER_H
66
#define RPCLITE_SERVER_H
77

8-
#include "rpc.h"
98
#include "error.h"
109
#include "wrapper.h"
1110
#include "dispatcher.h"
11+
#include "decoder.h"
12+
#include "decoder_manager.h"
1213

1314
#define MAX_CALLBACKS 100
1415

1516
class RPCServer {
1617
ITransport& transport;
18+
RpcDecoder<>& decoder;
19+
RpcFunctionDispatcher<MAX_CALLBACKS> dispatcher;
1720

1821
public:
19-
RPCServer(ITransport& t) : transport(t) {}
22+
RPCServer(ITransport& t) : transport(t), decoder(RpcDecoderManager<>::getDecoder(t)) {}
2023

2124
template<typename F>
2225
void bind(const MsgPack::str_t& name, F&& func){
2326
dispatcher.bind(name, func);
2427
}
2528

26-
void loop() {
27-
28-
if (!recv_msg(transport, unpacker)) return;
29-
30-
int msg_type;
31-
int msg_id;
32-
MsgPack::str_t method;
33-
MsgPack::arr_size_t req_size;
34-
35-
if (!unpacker.deserialize(req_size, msg_type, msg_id, method)){
36-
Serial.println("unable to deserialize a msg received");
37-
38-
for (size_t i=0; i<raw_buffer_fill; i++){
39-
Serial.print(raw_buffer[i], HEX);
40-
Serial.print(" ");
41-
}
42-
Serial.println(" ");
43-
44-
flush_buffer();
45-
return;
46-
} else {
47-
Serial.print("calling method: ");
48-
Serial.println(method);
49-
}
50-
51-
MsgPack::arr_size_t resp_size(4);
52-
packer.clear();
53-
packer.serialize(resp_size, RESP_MSG, msg_id);
54-
55-
dispatcher.call(method, unpacker, packer);
56-
flush_buffer();
57-
send_msg(transport, packer.packet());
58-
29+
void run() {
30+
decoder.process();
31+
decoder.process_requests(dispatcher);
32+
delay(1);
5933
}
6034

61-
private:
62-
63-
RpcFunctionDispatcher<MAX_CALLBACKS> dispatcher;
64-
MsgPack::Unpacker unpacker;
65-
MsgPack::Packer packer;
66-
6735
};
6836

6937
#endif //RPCLITE_SERVER_H

src/wrapper.h

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@ class RpcFunctionWrapper<R(Args...)>: public IFunctionWrapper {
9494
return false;
9595
}
9696

97-
auto args = deserialize_all<Args...>(unpacker);
97+
//unpacker not ready if deserialization fails at this point
98+
std::tuple<Args...> args;
99+
if (!deserialize_all<Args...>(unpacker, args)) return false;
100+
98101
if constexpr (std::is_void<R>::value){
99102
invoke_with_tuple(_func, args, arx::stdx::make_index_sequence<sizeof...(Args)>{});
100103
packer.serialize(nil, nil);
@@ -119,16 +122,31 @@ class RpcFunctionWrapper<R(Args...)>: public IFunctionWrapper {
119122
private:
120123
std::function<R(Args...)> _func;
121124

125+
template<size_t I = 0, typename... Ts>
126+
inline typename std::enable_if<I == sizeof...(Ts), bool>::type
127+
deserialize_tuple(MsgPack::Unpacker& unpacker, std::tuple<Ts...>& out) {
128+
return true; // Base case
129+
}
130+
131+
template<size_t I = 0, typename... Ts>
132+
inline typename std::enable_if<I < sizeof...(Ts), bool>::type
133+
deserialize_tuple(MsgPack::Unpacker& unpacker, std::tuple<Ts...>& out) {
134+
if (!deserialize_single(unpacker, std::get<I>(out))) {
135+
return false;
136+
}
137+
return deserialize_tuple<I+1>(unpacker, out); // Recursive unpacking
138+
}
139+
122140
template<typename... Ts>
123-
std::tuple<Ts...> deserialize_all(MsgPack::Unpacker& unpacker) {
124-
return std::make_tuple(deserialize_single<Ts>(unpacker)...);
141+
bool deserialize_all(MsgPack::Unpacker& unpacker, std::tuple<Ts...>& values) {
142+
return deserialize_tuple(unpacker, values);
125143
}
126144

127145
template<typename T>
128-
static T deserialize_single(MsgPack::Unpacker& unpacker) {
129-
T value;
146+
static bool deserialize_single(MsgPack::Unpacker& unpacker, T& value) {
147+
if (!unpacker.unpackable(value)) return false;
130148
unpacker.deserialize(value);
131-
return value;
149+
return true;
132150
}
133151
};
134152

0 commit comments

Comments
 (0)