aboutsummaryrefslogtreecommitdiff
path: root/pw_rpc_transport/public/pw_rpc_transport/rpc_transport.h
diff options
context:
space:
mode:
Diffstat (limited to 'pw_rpc_transport/public/pw_rpc_transport/rpc_transport.h')
-rw-r--r--pw_rpc_transport/public/pw_rpc_transport/rpc_transport.h108
1 files changed, 108 insertions, 0 deletions
diff --git a/pw_rpc_transport/public/pw_rpc_transport/rpc_transport.h b/pw_rpc_transport/public/pw_rpc_transport/rpc_transport.h
new file mode 100644
index 000000000..f21cd7689
--- /dev/null
+++ b/pw_rpc_transport/public/pw_rpc_transport/rpc_transport.h
@@ -0,0 +1,108 @@
+// Copyright 2023 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+#include "pw_bytes/span.h"
+#include "pw_function/function.h"
+#include "pw_status/status.h"
+
+namespace pw::rpc {
+
+// pw_rpc transport layer interfaces.
+
+// Framed RPC data ready to be sent via `RpcFrameSender`. Consists of a header
+// and a payload. Some RPC transport encodings may not require a header and put
+// all of the framed data into the payload (in which case the header can be
+// an empty span).
+//
+// A single RPC packet can be split into multiple RpcFrame's depending on the
+// MTU of the transport.
+//
+// All frames for an RPC packet are expected to be sent and received in order
+// without being interleaved by other packets' frames.
+struct RpcFrame {
+ ConstByteSpan header;
+ ConstByteSpan payload;
+};
+
+// RpcFrameSender encapsulates the details of sending the packet over
+// some communication channel (e.g. a hardware mailbox, shared memory, or a
+// socket). It exposes its maximum transmission unit (MTU) size and generally
+// should know how to send an `RpcFrame` of a size that is smaller or equal than
+// the MTU.
+class RpcFrameSender {
+ public:
+ virtual ~RpcFrameSender() = default;
+ virtual size_t MaximumTransmissionUnit() const = 0;
+ virtual Status Send(RpcFrame frame) = 0;
+};
+
+// Gets called by `RpcPacketEncoder` for each frame that it emits.
+using OnRpcFrameEncodedCallback = pw::Function<Status(RpcFrame&)>;
+
+// Gets called by `RpcPacketDecoder` for each RPC packet that it detects.
+using OnRpcPacketDecodedCallback = pw::Function<void(ConstByteSpan)>;
+
+// RpcPacketEncoder takes an RPC packet, the max frame size, splits the packet
+// into frames not exceeding that size and calls the provided callback with
+// each produced frame.
+template <class Encoder>
+class RpcPacketEncoder {
+ public:
+ Status Encode(ConstByteSpan rpc_packet,
+ size_t max_frame_size,
+ OnRpcFrameEncodedCallback&& callback) {
+ return static_cast<Encoder*>(this)->Encode(
+ rpc_packet, max_frame_size, std::move(callback));
+ }
+};
+
+// RpcPacketDecoder finds and decodes RPC frames in the provided buffer. Once
+// all frames for an RPC packet are decoded, the callback is invoked with a
+// decoded RPC packet as an argument.
+//
+// Frames from the same RPC packet are expected to be received in order and
+// without being interleaved with frames from any other packets.
+template <class Decoder>
+class RpcPacketDecoder {
+ public:
+ Status Decode(ConstByteSpan buffer, OnRpcPacketDecodedCallback&& callback) {
+ return static_cast<Decoder*>(this)->Decode(buffer, std::move(callback));
+ }
+};
+
+// Provides means of sending an RPC packet. A typical implementation ties
+// transport and encoder together, although some implementations may not require
+// any encoding (e.g. LocalRpcEgress).
+class RpcEgressHandler {
+ public:
+ virtual ~RpcEgressHandler() = default;
+ virtual Status SendRpcPacket(ConstByteSpan rpc_packet) = 0;
+};
+
+// Provides means of receiving a stream of RPC packets. A typical implementation
+// ties transport and decoder together.
+class RpcIngressHandler {
+ public:
+ virtual ~RpcIngressHandler() = default;
+ virtual Status ProcessIncomingData(ConstByteSpan buffer) = 0;
+};
+
+// A decoded RPC packet is passed to RpcPacketProcessor for further handling.
+class RpcPacketProcessor {
+ public:
+ virtual ~RpcPacketProcessor() = default;
+ virtual Status ProcessRpcPacket(ConstByteSpan rpc_packet) = 0;
+};
+} // namespace pw::rpc