pw_rpc: Expand server-side packet processing
- Handle various error cases with incoming packets.
- Dynamically assign a channel when a packet's ID doesn't exist.
- Reserve space in the response buffer for packet "header" fields.
Change-Id: Ibdce99c8ff1d37aa46bb4e400a4d8f8e646a8ac7
diff --git a/pw_rpc/server_test.cc b/pw_rpc/server_test.cc
index aae410e..85eecc0 100644
--- a/pw_rpc/server_test.cc
+++ b/pw_rpc/server_test.cc
@@ -15,10 +15,13 @@
#include "pw_rpc/server.h"
#include "gtest/gtest.h"
+#include "pw_rpc/internal/packet.h"
namespace pw::rpc {
namespace {
+using internal::Packet;
+using internal::PacketType;
using std::byte;
template <size_t buffer_size>
@@ -39,35 +42,110 @@
span<const byte> sent_packet_;
};
-TestOutput<512> output(1);
+Packet MakePacket(uint32_t channel_id,
+ uint32_t service_id,
+ uint32_t method_id,
+ span<const byte> payload) {
+ Packet packet = Packet::Empty(PacketType::RPC);
+ packet.set_channel_id(channel_id);
+ packet.set_service_id(service_id);
+ packet.set_method_id(method_id);
+ packet.set_payload(payload);
+ return packet;
+}
-// clang-format off
-constexpr uint8_t encoded_packet[] = {
- // type = PacketType::kRpc
- 0x08, 0x00,
- // channel_id = 1
- 0x10, 0x01,
- // service_id = 42
- 0x18, 0x2a,
- // method_id = 27
- 0x20, 0x1b,
- // payload
- 0x82, 0x02, 0xff, 0xff,
-};
-// clang-format on
-
-TEST(Server, DoesStuff) {
+TEST(Server, ProcessPacket_SendsResponse) {
+ TestOutput<128> output(1);
Channel channels[] = {
- Channel(1, &output),
- Channel(2, &output),
+ Channel::Create<1>(&output),
+ Channel::Create<2>(&output),
};
Server server(channels);
internal::Service service(42, {});
server.RegisterService(service);
- server.ProcessPacket(as_bytes(span(encoded_packet)), output);
- auto packet = output.sent_packet();
- EXPECT_GT(packet.size(), 0u);
+ byte encoded_packet[64];
+ constexpr byte payload[] = {byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
+ Packet request = MakePacket(1, 42, 27, payload);
+ auto sws = request.Encode(encoded_packet);
+
+ server.ProcessPacket(span(encoded_packet, sws.size()), output);
+ Packet packet = Packet::FromBuffer(output.sent_packet());
+ EXPECT_EQ(packet.status(), Status::OK);
+ EXPECT_EQ(packet.channel_id(), 1u);
+ EXPECT_EQ(packet.service_id(), 42u);
+}
+
+TEST(Server, ProcessPacket_SendsNotFoundOnInvalidService) {
+ TestOutput<128> output(1);
+ Channel channels[] = {
+ Channel::Create<1>(&output),
+ Channel::Create<2>(&output),
+ };
+ Server server(channels);
+ internal::Service service(42, {});
+ server.RegisterService(service);
+
+ byte encoded_packet[64];
+ constexpr byte payload[] = {byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
+ Packet request = MakePacket(1, 43, 27, payload);
+ auto sws = request.Encode(encoded_packet);
+
+ server.ProcessPacket(span(encoded_packet, sws.size()), output);
+ Packet packet = Packet::FromBuffer(output.sent_packet());
+ EXPECT_EQ(packet.status(), Status::NOT_FOUND);
+ EXPECT_EQ(packet.channel_id(), 1u);
+ EXPECT_EQ(packet.service_id(), 0u);
+}
+
+TEST(Server, ProcessPacket_AssignsAnUnassignedChannel) {
+ TestOutput<128> output(1);
+ Channel channels[] = {
+ Channel::Create<1>(&output),
+ Channel::Create<2>(&output),
+ Channel(),
+ };
+ Server server(channels);
+ internal::Service service(42, {});
+ server.RegisterService(service);
+
+ byte encoded_packet[64];
+ constexpr byte payload[] = {byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
+ Packet request = MakePacket(/*channel_id=*/99, 42, 27, payload);
+ auto sws = request.Encode(encoded_packet);
+
+ TestOutput<128> unassigned_output(2);
+ server.ProcessPacket(span(encoded_packet, sws.size()), unassigned_output);
+ ASSERT_EQ(channels[2].id(), 99u);
+
+ Packet packet = Packet::FromBuffer(unassigned_output.sent_packet());
+ EXPECT_EQ(packet.status(), Status::OK);
+ EXPECT_EQ(packet.channel_id(), 99u);
+ EXPECT_EQ(packet.service_id(), 42u);
+}
+
+TEST(Server, ProcessPacket_SendsResourceExhaustedWhenChannelCantBeAssigned) {
+ TestOutput<128> output(1);
+ Channel channels[] = {
+ Channel::Create<1>(&output),
+ Channel::Create<2>(&output),
+ };
+ Server server(channels);
+ internal::Service service(42, {});
+ server.RegisterService(service);
+
+ byte encoded_packet[64];
+ constexpr byte payload[] = {byte(0x82), byte(0x02), byte(0xff), byte(0xff)};
+ Packet request = MakePacket(/*channel_id=*/99, 42, 27, payload);
+ auto sws = request.Encode(encoded_packet);
+
+ server.ProcessPacket(span(encoded_packet, sws.size()), output);
+
+ Packet packet = Packet::FromBuffer(output.sent_packet());
+ EXPECT_EQ(packet.status(), Status::RESOURCE_EXHAUSTED);
+ EXPECT_EQ(packet.channel_id(), 0u);
+ EXPECT_EQ(packet.service_id(), 0u);
+ EXPECT_EQ(packet.method_id(), 0u);
}
} // namespace