diff options
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.h | 108 |
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 |