xref: /aosp_15_r20/external/pigweed/pw_rpc_transport/public/pw_rpc_transport/rpc_transport.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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