1 // Copyright 2023 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include "pw_bytes/span.h" 17 #include "pw_function/function.h" 18 #include "pw_status/status.h" 19 20 namespace pw::rpc { 21 22 // pw_rpc transport layer interfaces. 23 24 // Framed RPC data ready to be sent via `RpcFrameSender`. Consists of a header 25 // and a payload. Some RPC transport encodings may not require a header and put 26 // all of the framed data into the payload (in which case the header can be 27 // an empty span). 28 // 29 // A single RPC packet can be split into multiple RpcFrame's depending on the 30 // MTU of the transport. 31 // 32 // All frames for an RPC packet are expected to be sent and received in order 33 // without being interleaved by other packets' frames. 34 struct RpcFrame { 35 ConstByteSpan header; 36 ConstByteSpan payload; 37 }; 38 39 // RpcFrameSender encapsulates the details of sending the packet over 40 // some communication channel (e.g. a hardware mailbox, shared memory, or a 41 // socket). It exposes its maximum transmission unit (MTU) size and generally 42 // should know how to send an `RpcFrame` of a size that is smaller or equal than 43 // the MTU. 44 class RpcFrameSender { 45 public: 46 virtual ~RpcFrameSender() = default; 47 virtual size_t MaximumTransmissionUnit() const = 0; 48 virtual Status Send(RpcFrame frame) = 0; 49 }; 50 51 // Gets called by `RpcPacketEncoder` for each frame that it emits. 52 using OnRpcFrameEncodedCallback = pw::Function<Status(RpcFrame&)>; 53 54 // Gets called by `RpcPacketDecoder` for each RPC packet that it detects. 55 using OnRpcPacketDecodedCallback = pw::Function<void(ConstByteSpan)>; 56 57 // RpcPacketEncoder takes an RPC packet, the max frame size, splits the packet 58 // into frames not exceeding that size and calls the provided callback with 59 // each produced frame. 60 template <class Encoder> 61 class RpcPacketEncoder { 62 public: Encode(ConstByteSpan rpc_packet,size_t max_frame_size,OnRpcFrameEncodedCallback && callback)63 Status Encode(ConstByteSpan rpc_packet, 64 size_t max_frame_size, 65 OnRpcFrameEncodedCallback&& callback) { 66 return static_cast<Encoder*>(this)->Encode( 67 rpc_packet, max_frame_size, std::move(callback)); 68 } 69 }; 70 71 // RpcPacketDecoder finds and decodes RPC frames in the provided buffer. Once 72 // all frames for an RPC packet are decoded, the callback is invoked with a 73 // decoded RPC packet as an argument. 74 // 75 // Frames from the same RPC packet are expected to be received in order and 76 // without being interleaved with frames from any other packets. 77 template <class Decoder> 78 class RpcPacketDecoder { 79 public: Decode(ConstByteSpan buffer,OnRpcPacketDecodedCallback && callback)80 Status Decode(ConstByteSpan buffer, OnRpcPacketDecodedCallback&& callback) { 81 return static_cast<Decoder*>(this)->Decode(buffer, std::move(callback)); 82 } 83 }; 84 85 // Provides means of sending an RPC packet. A typical implementation ties 86 // transport and encoder together, although some implementations may not require 87 // any encoding (e.g. LocalRpcEgress). 88 class RpcEgressHandler { 89 public: 90 virtual ~RpcEgressHandler() = default; 91 virtual Status SendRpcPacket(ConstByteSpan rpc_packet) = 0; 92 }; 93 94 // Provides means of receiving a stream of RPC packets. A typical implementation 95 // ties transport and decoder together. 96 class RpcIngressHandler { 97 public: 98 virtual ~RpcIngressHandler() = default; 99 virtual Status ProcessIncomingData(ConstByteSpan buffer) = 0; 100 }; 101 102 // A decoded RPC packet is passed to RpcPacketProcessor for further handling. 103 class RpcPacketProcessor { 104 public: 105 virtual ~RpcPacketProcessor() = default; 106 virtual Status ProcessRpcPacket(ConstByteSpan rpc_packet) = 0; 107 }; 108 } // namespace pw::rpc 109