xref: /aosp_15_r20/external/pigweed/pw_rpc/cpp.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-cpp:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker=====================
4*61c4878aSAndroid Build Coastguard WorkerC++ server and client
5*61c4878aSAndroid Build Coastguard Worker=====================
6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module-subpage::
7*61c4878aSAndroid Build Coastguard Worker   :name: pw_rpc
8*61c4878aSAndroid Build Coastguard Worker
9*61c4878aSAndroid Build Coastguard WorkerThis page provides further guidance on how to use the C++ server
10*61c4878aSAndroid Build Coastguard Workerand client libraries.
11*61c4878aSAndroid Build Coastguard Worker
12*61c4878aSAndroid Build Coastguard Worker----------
13*61c4878aSAndroid Build Coastguard WorkerRPC server
14*61c4878aSAndroid Build Coastguard Worker----------
15*61c4878aSAndroid Build Coastguard WorkerDeclare an instance of ``rpc::Server`` and register services with it.
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard WorkerSize report
18*61c4878aSAndroid Build Coastguard Worker===========
19*61c4878aSAndroid Build Coastguard WorkerThe following size report showcases the memory usage of the core RPC server. It
20*61c4878aSAndroid Build Coastguard Workeris configured with a single channel using a basic transport interface that
21*61c4878aSAndroid Build Coastguard Workerdirectly reads from and writes to ``pw_sys_io``. The transport has a 128-byte
22*61c4878aSAndroid Build Coastguard Workerpacket buffer, which comprises the plurality of the example's RAM usage. This is
23*61c4878aSAndroid Build Coastguard Workernot a suitable transport for an actual product; a real implementation would have
24*61c4878aSAndroid Build Coastguard Workeradditional overhead proportional to the complexity of the transport.
25*61c4878aSAndroid Build Coastguard Worker
26*61c4878aSAndroid Build Coastguard Worker.. include:: server_size
27*61c4878aSAndroid Build Coastguard Worker
28*61c4878aSAndroid Build Coastguard WorkerRPC server implementation
29*61c4878aSAndroid Build Coastguard Worker=========================
30*61c4878aSAndroid Build Coastguard Worker
31*61c4878aSAndroid Build Coastguard WorkerThe Method class
32*61c4878aSAndroid Build Coastguard Worker----------------
33*61c4878aSAndroid Build Coastguard WorkerThe RPC Server depends on the ``pw::rpc::internal::Method`` class. ``Method``
34*61c4878aSAndroid Build Coastguard Workerserves as the bridge between the ``pw_rpc`` server library and the user-defined
35*61c4878aSAndroid Build Coastguard WorkerRPC functions. Each supported protobuf implementation extends ``Method`` to
36*61c4878aSAndroid Build Coastguard Workerimplement its request and response proto handling. The ``pw_rpc`` server
37*61c4878aSAndroid Build Coastguard Workercalls into the ``Method`` implementation through the base class's ``Invoke``
38*61c4878aSAndroid Build Coastguard Workerfunction.
39*61c4878aSAndroid Build Coastguard Worker
40*61c4878aSAndroid Build Coastguard Worker``Method`` implementations store metadata about each method, including a
41*61c4878aSAndroid Build Coastguard Workerfunction pointer to the user-defined method implementation. They also provide
42*61c4878aSAndroid Build Coastguard Worker``static constexpr`` functions for creating each type of method. ``Method``
43*61c4878aSAndroid Build Coastguard Workerimplementations must satisfy the ``MethodImplTester`` test class in
44*61c4878aSAndroid Build Coastguard Worker``pw_rpc/internal/method_impl_tester.h``.
45*61c4878aSAndroid Build Coastguard Worker
46*61c4878aSAndroid Build Coastguard WorkerSee ``pw_rpc/internal/method.h`` for more details about ``Method``.
47*61c4878aSAndroid Build Coastguard Worker
48*61c4878aSAndroid Build Coastguard WorkerPacket flow
49*61c4878aSAndroid Build Coastguard Worker-----------
50*61c4878aSAndroid Build Coastguard Worker
51*61c4878aSAndroid Build Coastguard WorkerRequests
52*61c4878aSAndroid Build Coastguard Worker^^^^^^^^
53*61c4878aSAndroid Build Coastguard Worker
54*61c4878aSAndroid Build Coastguard Worker.. mermaid::
55*61c4878aSAndroid Build Coastguard Worker   :alt: Request Packet Flow
56*61c4878aSAndroid Build Coastguard Worker
57*61c4878aSAndroid Build Coastguard Worker   flowchart LR
58*61c4878aSAndroid Build Coastguard Worker       packets[Packets]
59*61c4878aSAndroid Build Coastguard Worker
60*61c4878aSAndroid Build Coastguard Worker       subgraph pw_rpc [pw_rpc Library]
61*61c4878aSAndroid Build Coastguard Worker           direction TB
62*61c4878aSAndroid Build Coastguard Worker           internalMethod[[internal::Method]]
63*61c4878aSAndroid Build Coastguard Worker           Server --> Service --> internalMethod
64*61c4878aSAndroid Build Coastguard Worker       end
65*61c4878aSAndroid Build Coastguard Worker
66*61c4878aSAndroid Build Coastguard Worker       packets --> Server
67*61c4878aSAndroid Build Coastguard Worker
68*61c4878aSAndroid Build Coastguard Worker       generatedServices{{generated services}}
69*61c4878aSAndroid Build Coastguard Worker       userDefinedRPCs(user-defined RPCs)
70*61c4878aSAndroid Build Coastguard Worker
71*61c4878aSAndroid Build Coastguard Worker       generatedServices --> userDefinedRPCs
72*61c4878aSAndroid Build Coastguard Worker       internalMethod --> generatedServices
73*61c4878aSAndroid Build Coastguard Worker
74*61c4878aSAndroid Build Coastguard WorkerResponses
75*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^
76*61c4878aSAndroid Build Coastguard Worker
77*61c4878aSAndroid Build Coastguard Worker.. mermaid::
78*61c4878aSAndroid Build Coastguard Worker   :alt: Request Packet Flow
79*61c4878aSAndroid Build Coastguard Worker
80*61c4878aSAndroid Build Coastguard Worker   flowchart LR
81*61c4878aSAndroid Build Coastguard Worker       generatedServices{{generated services}}
82*61c4878aSAndroid Build Coastguard Worker       userDefinedRPCs(user-defined RPCs)
83*61c4878aSAndroid Build Coastguard Worker
84*61c4878aSAndroid Build Coastguard Worker       subgraph pw_rpc [pw_rpc Library]
85*61c4878aSAndroid Build Coastguard Worker           direction TB
86*61c4878aSAndroid Build Coastguard Worker           internalMethod[[internal::Method]]
87*61c4878aSAndroid Build Coastguard Worker           internalMethod --> Server --> Channel
88*61c4878aSAndroid Build Coastguard Worker       end
89*61c4878aSAndroid Build Coastguard Worker
90*61c4878aSAndroid Build Coastguard Worker       packets[Packets]
91*61c4878aSAndroid Build Coastguard Worker       Channel --> packets
92*61c4878aSAndroid Build Coastguard Worker
93*61c4878aSAndroid Build Coastguard Worker       userDefinedRPCs --> generatedServices
94*61c4878aSAndroid Build Coastguard Worker       generatedServices --> internalMethod
95*61c4878aSAndroid Build Coastguard Worker
96*61c4878aSAndroid Build Coastguard Worker----------
97*61c4878aSAndroid Build Coastguard WorkerRPC client
98*61c4878aSAndroid Build Coastguard Worker----------
99*61c4878aSAndroid Build Coastguard WorkerThe RPC client is used to send requests to a server and manages the contexts of
100*61c4878aSAndroid Build Coastguard Workerongoing RPCs.
101*61c4878aSAndroid Build Coastguard Worker
102*61c4878aSAndroid Build Coastguard WorkerSetting up a client
103*61c4878aSAndroid Build Coastguard Worker===================
104*61c4878aSAndroid Build Coastguard WorkerThe ``pw::rpc::Client`` class is instantiated with a list of channels that it
105*61c4878aSAndroid Build Coastguard Workeruses to communicate. These channels can be shared with a server, but multiple
106*61c4878aSAndroid Build Coastguard Workerclients cannot use the same channels.
107*61c4878aSAndroid Build Coastguard Worker
108*61c4878aSAndroid Build Coastguard WorkerTo send incoming RPC packets from the transport layer to be processed by a
109*61c4878aSAndroid Build Coastguard Workerclient, the client's ``ProcessPacket`` function is called with the packet data.
110*61c4878aSAndroid Build Coastguard Worker
111*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
112*61c4878aSAndroid Build Coastguard Worker
113*61c4878aSAndroid Build Coastguard Worker   #include "pw_rpc/client.h"
114*61c4878aSAndroid Build Coastguard Worker
115*61c4878aSAndroid Build Coastguard Worker   namespace {
116*61c4878aSAndroid Build Coastguard Worker
117*61c4878aSAndroid Build Coastguard Worker   pw::rpc::Channel my_channels[] = {
118*61c4878aSAndroid Build Coastguard Worker       pw::rpc::Channel::Create<1>(&my_channel_output)};
119*61c4878aSAndroid Build Coastguard Worker   pw::rpc::Client my_client(my_channels);
120*61c4878aSAndroid Build Coastguard Worker
121*61c4878aSAndroid Build Coastguard Worker   }  // namespace
122*61c4878aSAndroid Build Coastguard Worker
123*61c4878aSAndroid Build Coastguard Worker   // Called when the transport layer receives an RPC packet.
124*61c4878aSAndroid Build Coastguard Worker   void ProcessRpcPacket(ConstByteSpan packet) {
125*61c4878aSAndroid Build Coastguard Worker     my_client.ProcessPacket(packet);
126*61c4878aSAndroid Build Coastguard Worker   }
127*61c4878aSAndroid Build Coastguard Worker
128*61c4878aSAndroid Build Coastguard WorkerNote that client processing such as callbacks will be invoked within
129*61c4878aSAndroid Build Coastguard Workerthe body of ``ProcessPacket``.
130*61c4878aSAndroid Build Coastguard Worker
131*61c4878aSAndroid Build Coastguard WorkerIf certain packets need to be filtered out, or if certain client processing
132*61c4878aSAndroid Build Coastguard Workerneeds to be invoked from a specific thread or context, the ``PacketMeta`` class
133*61c4878aSAndroid Build Coastguard Workercan be used to determine which service or channel a packet is targeting. After
134*61c4878aSAndroid Build Coastguard Workerfiltering, ``ProcessPacket`` can be called from the appropriate environment.
135*61c4878aSAndroid Build Coastguard Worker
136*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-making-calls:
137*61c4878aSAndroid Build Coastguard Worker
138*61c4878aSAndroid Build Coastguard WorkerMaking RPC calls
139*61c4878aSAndroid Build Coastguard Worker================
140*61c4878aSAndroid Build Coastguard WorkerRPC calls are not made directly through the client, but using one of its
141*61c4878aSAndroid Build Coastguard Workerregistered channels instead. A service client class is generated from a .proto
142*61c4878aSAndroid Build Coastguard Workerfile for each selected protobuf library, which is then used to send RPC requests
143*61c4878aSAndroid Build Coastguard Workerthrough a given channel. The API for this depends on the protobuf library;
144*61c4878aSAndroid Build Coastguard Workerplease refer to the
145*61c4878aSAndroid Build Coastguard Worker:ref:`appropriate documentation <module-pw_rpc-libraries>`. Multiple
146*61c4878aSAndroid Build Coastguard Workerservice client implementations can exist simulatenously and share the same
147*61c4878aSAndroid Build Coastguard Worker``Client`` class.
148*61c4878aSAndroid Build Coastguard Worker
149*61c4878aSAndroid Build Coastguard WorkerWhen a call is made, a call object is returned to the caller. This object tracks
150*61c4878aSAndroid Build Coastguard Workerthe ongoing RPC call, and can be used to manage it. An RPC call is only active
151*61c4878aSAndroid Build Coastguard Workeras long as its call object is alive.
152*61c4878aSAndroid Build Coastguard Worker
153*61c4878aSAndroid Build Coastguard Worker.. tip::
154*61c4878aSAndroid Build Coastguard Worker
155*61c4878aSAndroid Build Coastguard Worker   Use ``std::move`` when passing around call objects to keep RPCs alive.
156*61c4878aSAndroid Build Coastguard Worker
157*61c4878aSAndroid Build Coastguard WorkerExample
158*61c4878aSAndroid Build Coastguard Worker-------
159*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
160*61c4878aSAndroid Build Coastguard Worker
161*61c4878aSAndroid Build Coastguard Worker   #include "pw_rpc/echo_service_nanopb.h"
162*61c4878aSAndroid Build Coastguard Worker
163*61c4878aSAndroid Build Coastguard Worker   namespace {
164*61c4878aSAndroid Build Coastguard Worker   // Generated clients are namespaced with their proto library.
165*61c4878aSAndroid Build Coastguard Worker   using EchoClient = pw_rpc::nanopb::EchoService::Client;
166*61c4878aSAndroid Build Coastguard Worker
167*61c4878aSAndroid Build Coastguard Worker   // RPC channel ID on which to make client calls. RPC calls cannot be made on
168*61c4878aSAndroid Build Coastguard Worker   // channel 0 (Channel::kUnassignedChannelId).
169*61c4878aSAndroid Build Coastguard Worker   constexpr uint32_t kDefaultChannelId = 1;
170*61c4878aSAndroid Build Coastguard Worker
171*61c4878aSAndroid Build Coastguard Worker   pw::rpc::NanopbUnaryReceiver<pw_rpc_EchoMessage> echo_call;
172*61c4878aSAndroid Build Coastguard Worker
173*61c4878aSAndroid Build Coastguard Worker   // Callback invoked when a response is received. This is called synchronously
174*61c4878aSAndroid Build Coastguard Worker   // from Client::ProcessPacket.
175*61c4878aSAndroid Build Coastguard Worker   void EchoResponse(const pw_rpc_EchoMessage& response,
176*61c4878aSAndroid Build Coastguard Worker                     pw::Status status) {
177*61c4878aSAndroid Build Coastguard Worker     if (status.ok()) {
178*61c4878aSAndroid Build Coastguard Worker       PW_LOG_INFO("Received echo response: %s", response.msg);
179*61c4878aSAndroid Build Coastguard Worker     } else {
180*61c4878aSAndroid Build Coastguard Worker       PW_LOG_ERROR("Echo failed with status %d",
181*61c4878aSAndroid Build Coastguard Worker                    static_cast<int>(status.code()));
182*61c4878aSAndroid Build Coastguard Worker     }
183*61c4878aSAndroid Build Coastguard Worker   }
184*61c4878aSAndroid Build Coastguard Worker
185*61c4878aSAndroid Build Coastguard Worker   }  // namespace
186*61c4878aSAndroid Build Coastguard Worker
187*61c4878aSAndroid Build Coastguard Worker   void CallEcho(const char* message) {
188*61c4878aSAndroid Build Coastguard Worker     // Create a client to call the EchoService.
189*61c4878aSAndroid Build Coastguard Worker     EchoClient echo_client(my_rpc_client, kDefaultChannelId);
190*61c4878aSAndroid Build Coastguard Worker
191*61c4878aSAndroid Build Coastguard Worker     pw_rpc_EchoMessage request{};
192*61c4878aSAndroid Build Coastguard Worker     pw::string::Copy(message, request.msg);
193*61c4878aSAndroid Build Coastguard Worker
194*61c4878aSAndroid Build Coastguard Worker     // By assigning the returned call to the global echo_call, the RPC
195*61c4878aSAndroid Build Coastguard Worker     // call is kept alive until it completes. When a response is received, it
196*61c4878aSAndroid Build Coastguard Worker     // will be logged by the handler function and the call will complete.
197*61c4878aSAndroid Build Coastguard Worker     echo_call = echo_client.Echo(request, EchoResponse);
198*61c4878aSAndroid Build Coastguard Worker     if (!echo_call.active()) {
199*61c4878aSAndroid Build Coastguard Worker       // The RPC call was not sent. This could occur due to, for example, an
200*61c4878aSAndroid Build Coastguard Worker       // invalid channel ID. Handle if necessary.
201*61c4878aSAndroid Build Coastguard Worker     }
202*61c4878aSAndroid Build Coastguard Worker   }
203*61c4878aSAndroid Build Coastguard Worker
204*61c4878aSAndroid Build Coastguard Worker--------
205*61c4878aSAndroid Build Coastguard WorkerChannels
206*61c4878aSAndroid Build Coastguard Worker--------
207*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` sends all of its packets over channels. These are logical,
208*61c4878aSAndroid Build Coastguard Workerapplication-layer routes used to tell the RPC system where a packet should go.
209*61c4878aSAndroid Build Coastguard Worker
210*61c4878aSAndroid Build Coastguard WorkerChannels over a client-server connection must all have a unique ID, which can be
211*61c4878aSAndroid Build Coastguard Workerassigned statically at compile time or dynamically.
212*61c4878aSAndroid Build Coastguard Worker
213*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
214*61c4878aSAndroid Build Coastguard Worker
215*61c4878aSAndroid Build Coastguard Worker   // Creating a channel with the static ID 3.
216*61c4878aSAndroid Build Coastguard Worker   pw::rpc::Channel static_channel = pw::rpc::Channel::Create<3>(&output);
217*61c4878aSAndroid Build Coastguard Worker
218*61c4878aSAndroid Build Coastguard Worker   // Grouping channel IDs within an enum can lead to clearer code.
219*61c4878aSAndroid Build Coastguard Worker   enum ChannelId {
220*61c4878aSAndroid Build Coastguard Worker     kUartChannel = 1,
221*61c4878aSAndroid Build Coastguard Worker     kSpiChannel = 2,
222*61c4878aSAndroid Build Coastguard Worker   };
223*61c4878aSAndroid Build Coastguard Worker
224*61c4878aSAndroid Build Coastguard Worker   // Creating a channel with a static ID defined within an enum.
225*61c4878aSAndroid Build Coastguard Worker   pw::rpc::Channel another_static_channel =
226*61c4878aSAndroid Build Coastguard Worker       pw::rpc::Channel::Create<ChannelId::kUartChannel>(&output);
227*61c4878aSAndroid Build Coastguard Worker
228*61c4878aSAndroid Build Coastguard Worker   // Creating a channel with a dynamic ID (note that no output is provided; it
229*61c4878aSAndroid Build Coastguard Worker   // will be set when the channel is used.
230*61c4878aSAndroid Build Coastguard Worker   pw::rpc::Channel dynamic_channel;
231*61c4878aSAndroid Build Coastguard Worker
232*61c4878aSAndroid Build Coastguard WorkerSometimes, the ID and output of a channel are not known at compile time as they
233*61c4878aSAndroid Build Coastguard Workerdepend on information stored on the physical device. To support this use case, a
234*61c4878aSAndroid Build Coastguard Workerdynamically-assignable channel can be configured once at runtime with an ID and
235*61c4878aSAndroid Build Coastguard Workeroutput.
236*61c4878aSAndroid Build Coastguard Worker
237*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
238*61c4878aSAndroid Build Coastguard Worker
239*61c4878aSAndroid Build Coastguard Worker   // Create a dynamic channel without a compile-time ID or output.
240*61c4878aSAndroid Build Coastguard Worker   pw::rpc::Channel dynamic_channel;
241*61c4878aSAndroid Build Coastguard Worker
242*61c4878aSAndroid Build Coastguard Worker   void Init() {
243*61c4878aSAndroid Build Coastguard Worker     // Called during boot to pull the channel configuration from the system.
244*61c4878aSAndroid Build Coastguard Worker     dynamic_channel.Configure(GetChannelId(), some_output);
245*61c4878aSAndroid Build Coastguard Worker   }
246*61c4878aSAndroid Build Coastguard Worker
247*61c4878aSAndroid Build Coastguard WorkerAdding and removing channels
248*61c4878aSAndroid Build Coastguard Worker============================
249*61c4878aSAndroid Build Coastguard WorkerNew channels may be registered with the ``OpenChannel`` function. If dynamic
250*61c4878aSAndroid Build Coastguard Workerallocation is enabled (:c:macro:`PW_RPC_DYNAMIC_ALLOCATION` is 1), any number of
251*61c4878aSAndroid Build Coastguard Workerchannels may be registered. If dynamic allocation is disabled, new channels may
252*61c4878aSAndroid Build Coastguard Workeronly be registered if there are availale channel slots in the span provided to
253*61c4878aSAndroid Build Coastguard Workerthe RPC endpoint at construction.
254*61c4878aSAndroid Build Coastguard Worker
255*61c4878aSAndroid Build Coastguard WorkerA channel may be closed and unregistered with an endpoint by calling
256*61c4878aSAndroid Build Coastguard Worker``ChannelClose`` on the endpoint with the corresponding channel ID.  This
257*61c4878aSAndroid Build Coastguard Workerwill terminate any pending calls and call their ``on_error`` callback
258*61c4878aSAndroid Build Coastguard Workerwith the ``ABORTED`` status.
259*61c4878aSAndroid Build Coastguard Worker
260*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
261*61c4878aSAndroid Build Coastguard Worker
262*61c4878aSAndroid Build Coastguard Worker   // When a channel is closed, any pending calls will receive
263*61c4878aSAndroid Build Coastguard Worker   // on_error callbacks with ABORTED status.
264*61c4878aSAndroid Build Coastguard Worker   client->CloseChannel(1);
265*61c4878aSAndroid Build Coastguard Worker
266*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-remap:
267*61c4878aSAndroid Build Coastguard Worker
268*61c4878aSAndroid Build Coastguard WorkerRemapping channels
269*61c4878aSAndroid Build Coastguard Worker==================
270*61c4878aSAndroid Build Coastguard WorkerSome pw_rpc deployments may find it helpful to remap channel IDs in RPC packets.
271*61c4878aSAndroid Build Coastguard WorkerThis can remove the need for globally known channel IDs. Clients can use a
272*61c4878aSAndroid Build Coastguard Workergeneric channel ID. The server remaps the generic channel ID to an ID associated
273*61c4878aSAndroid Build Coastguard Workerwith the transport the client is using.
274*61c4878aSAndroid Build Coastguard Worker
275*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::rpc
276*61c4878aSAndroid Build Coastguard Worker
277*61c4878aSAndroid Build Coastguard Worker.. doxygengroup:: pw_rpc_channel_functions
278*61c4878aSAndroid Build Coastguard Worker   :content-only:
279*61c4878aSAndroid Build Coastguard Worker
280*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
281*61c4878aSAndroid Build Coastguard Worker
282*61c4878aSAndroid Build Coastguard WorkerA future revision of the pw_rpc protocol will remove the need for global channel
283*61c4878aSAndroid Build Coastguard WorkerIDs without requiring remapping.
284*61c4878aSAndroid Build Coastguard Worker
285*61c4878aSAndroid Build Coastguard WorkerExample deployment
286*61c4878aSAndroid Build Coastguard Worker==================
287*61c4878aSAndroid Build Coastguard WorkerThis section describes a hypothetical pw_rpc deployment that supports arbitrary
288*61c4878aSAndroid Build Coastguard Workerpw_rpc clients with one pw_rpc server. Note that this assumes that the
289*61c4878aSAndroid Build Coastguard Workerunderlying transport provides some sort of addressing that the server-side can
290*61c4878aSAndroid Build Coastguard Workerassociate with a channel ID.
291*61c4878aSAndroid Build Coastguard Worker
292*61c4878aSAndroid Build Coastguard Worker- A pw_rpc server is running on one core. A variable number of pw_rpc clients
293*61c4878aSAndroid Build Coastguard Worker  need to call RPCs on the server from a different core.
294*61c4878aSAndroid Build Coastguard Worker- The client core opens a socket (or similar feature) to connect to the server
295*61c4878aSAndroid Build Coastguard Worker  core.
296*61c4878aSAndroid Build Coastguard Worker- The server core detects the inbound connection and allocates a new channel ID.
297*61c4878aSAndroid Build Coastguard Worker  It creates a new channel by calling :cpp:func:`pw::rpc::Server::OpenChannel`
298*61c4878aSAndroid Build Coastguard Worker  with the channel ID and a :cpp:class:`pw::rpc::ChannelOutput` associated with
299*61c4878aSAndroid Build Coastguard Worker  the new connection.
300*61c4878aSAndroid Build Coastguard Worker- The server maintains a mapping between channel IDs and pw_rpc client
301*61c4878aSAndroid Build Coastguard Worker  connections.
302*61c4878aSAndroid Build Coastguard Worker- On the client core, pw_rpc clients all use the same channel ID (e.g.  ``1``).
303*61c4878aSAndroid Build Coastguard Worker- As packets arrive from pw_rpc client connections, the server-side code calls
304*61c4878aSAndroid Build Coastguard Worker  :cpp:func:`pw::rpc::ChangeEncodedChannelId` on the encoded packet to replace
305*61c4878aSAndroid Build Coastguard Worker  the generic channel ID (``1``) with the server-side channel ID allocated when
306*61c4878aSAndroid Build Coastguard Worker  the client connected. The encoded packet is then passed to
307*61c4878aSAndroid Build Coastguard Worker  :cpp:func:`pw::rpc::Server::ProcessPacket`.
308*61c4878aSAndroid Build Coastguard Worker- When the server sends pw_rpc packets, the :cpp:class:`pw::rpc::ChannelOutput`
309*61c4878aSAndroid Build Coastguard Worker  calls :cpp:func:`pw::rpc::ChangeEncodedChannelId` to set the channel ID back
310*61c4878aSAndroid Build Coastguard Worker  to the generic ``1``.
311*61c4878aSAndroid Build Coastguard Worker
312*61c4878aSAndroid Build Coastguard Worker------------------------------
313*61c4878aSAndroid Build Coastguard WorkerC++ payload sizing limitations
314*61c4878aSAndroid Build Coastguard Worker------------------------------
315*61c4878aSAndroid Build Coastguard WorkerThe individual size of each sent RPC request or response is limited by
316*61c4878aSAndroid Build Coastguard Worker``pw_rpc``'s ``PW_RPC_ENCODING_BUFFER_SIZE_BYTES`` configuration option when
317*61c4878aSAndroid Build Coastguard Workerusing Pigweed's C++ implementation. While multiple RPC messages can be enqueued
318*61c4878aSAndroid Build Coastguard Worker(as permitted by the underlying transport), if a single individual sent message
319*61c4878aSAndroid Build Coastguard Workerexceeds the limitations of the statically allocated encode buffer, the packet
320*61c4878aSAndroid Build Coastguard Workerwill fail to encode and be dropped.
321*61c4878aSAndroid Build Coastguard Worker
322*61c4878aSAndroid Build Coastguard WorkerThis applies to all C++ RPC service implementations (nanopb, raw, and pwpb),
323*61c4878aSAndroid Build Coastguard Workerso it's important to ensure request and response message sizes do not exceed
324*61c4878aSAndroid Build Coastguard Workerthis limitation.
325*61c4878aSAndroid Build Coastguard Worker
326*61c4878aSAndroid Build Coastguard WorkerAs ``pw_rpc`` has some additional encoding overhead, a helper,
327*61c4878aSAndroid Build Coastguard Worker``pw::rpc::MaxSafePayloadSize()`` is provided to expose the practical max RPC
328*61c4878aSAndroid Build Coastguard Workermessage payload size.
329*61c4878aSAndroid Build Coastguard Worker
330*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
331*61c4878aSAndroid Build Coastguard Worker
332*61c4878aSAndroid Build Coastguard Worker   #include "pw_file/file.raw_rpc.pb.h"
333*61c4878aSAndroid Build Coastguard Worker   #include "pw_rpc/channel.h"
334*61c4878aSAndroid Build Coastguard Worker
335*61c4878aSAndroid Build Coastguard Worker   namespace pw::file {
336*61c4878aSAndroid Build Coastguard Worker
337*61c4878aSAndroid Build Coastguard Worker   class FileSystemService : public pw_rpc::raw::FileSystem::Service<FileSystemService> {
338*61c4878aSAndroid Build Coastguard Worker    public:
339*61c4878aSAndroid Build Coastguard Worker     void List(ConstByteSpan request, RawServerWriter& writer);
340*61c4878aSAndroid Build Coastguard Worker
341*61c4878aSAndroid Build Coastguard Worker    private:
342*61c4878aSAndroid Build Coastguard Worker     // Allocate a buffer for building proto responses.
343*61c4878aSAndroid Build Coastguard Worker     static constexpr size_t kEncodeBufferSize = pw::rpc::MaxSafePayloadSize();
344*61c4878aSAndroid Build Coastguard Worker     std::array<std::byte, kEncodeBufferSize> encode_buffer_;
345*61c4878aSAndroid Build Coastguard Worker   };
346*61c4878aSAndroid Build Coastguard Worker
347*61c4878aSAndroid Build Coastguard Worker   }  // namespace pw::file
348*61c4878aSAndroid Build Coastguard Worker
349*61c4878aSAndroid Build Coastguard Worker------------
350*61c4878aSAndroid Build Coastguard WorkerCall objects
351*61c4878aSAndroid Build Coastguard Worker------------
352*61c4878aSAndroid Build Coastguard WorkerAn RPC call is represented by a call object. Server and client calls use the
353*61c4878aSAndroid Build Coastguard Workersame base call class in C++, but the public API is different depending on the
354*61c4878aSAndroid Build Coastguard Workertype of call and whether it is being used by the server or client. See
355*61c4878aSAndroid Build Coastguard Worker:ref:`module-pw_rpc-design-lifecycle`.
356*61c4878aSAndroid Build Coastguard Worker
357*61c4878aSAndroid Build Coastguard WorkerThe public call types are as follows:
358*61c4878aSAndroid Build Coastguard Worker
359*61c4878aSAndroid Build Coastguard Worker.. list-table::
360*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
361*61c4878aSAndroid Build Coastguard Worker
362*61c4878aSAndroid Build Coastguard Worker   * - RPC Type
363*61c4878aSAndroid Build Coastguard Worker     - Server call
364*61c4878aSAndroid Build Coastguard Worker     - Client call
365*61c4878aSAndroid Build Coastguard Worker   * - Unary
366*61c4878aSAndroid Build Coastguard Worker     - ``(Raw|Nanopb|Pwpb)UnaryResponder``
367*61c4878aSAndroid Build Coastguard Worker     - ``(Raw|Nanopb|Pwpb)UnaryReceiver``
368*61c4878aSAndroid Build Coastguard Worker   * - Server streaming
369*61c4878aSAndroid Build Coastguard Worker     - ``(Raw|Nanopb|Pwpb)ServerWriter``
370*61c4878aSAndroid Build Coastguard Worker     - ``(Raw|Nanopb|Pwpb)ClientReader``
371*61c4878aSAndroid Build Coastguard Worker   * - Client streaming
372*61c4878aSAndroid Build Coastguard Worker     - ``(Raw|Nanopb|Pwpb)ServerReader``
373*61c4878aSAndroid Build Coastguard Worker     - ``(Raw|Nanopb|Pwpb)ClientWriter``
374*61c4878aSAndroid Build Coastguard Worker   * - Bidirectional streaming
375*61c4878aSAndroid Build Coastguard Worker     - ``(Raw|Nanopb|Pwpb)ServerReaderWriter``
376*61c4878aSAndroid Build Coastguard Worker     - ``(Raw|Nanopb|Pwpb)ClientReaderWriter``
377*61c4878aSAndroid Build Coastguard Worker
378*61c4878aSAndroid Build Coastguard WorkerClient call API
379*61c4878aSAndroid Build Coastguard Worker===============
380*61c4878aSAndroid Build Coastguard WorkerClient call objects provide a few common methods.
381*61c4878aSAndroid Build Coastguard Worker
382*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: pw::rpc::ClientCallType
383*61c4878aSAndroid Build Coastguard Worker
384*61c4878aSAndroid Build Coastguard Worker   The ``ClientCallType`` will be one of the following types:
385*61c4878aSAndroid Build Coastguard Worker
386*61c4878aSAndroid Build Coastguard Worker   - ``(Raw|Nanopb|Pwpb)UnaryReceiver`` for unary
387*61c4878aSAndroid Build Coastguard Worker   - ``(Raw|Nanopb|Pwpb)ClientReader`` for server streaming
388*61c4878aSAndroid Build Coastguard Worker   - ``(Raw|Nanopb|Pwpb)ClientWriter`` for client streaming
389*61c4878aSAndroid Build Coastguard Worker   - ``(Raw|Nanopb|Pwpb)ClientReaderWriter`` for bidirectional streaming
390*61c4878aSAndroid Build Coastguard Worker
391*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: bool active() const
392*61c4878aSAndroid Build Coastguard Worker
393*61c4878aSAndroid Build Coastguard Worker      Returns true if the call is active.
394*61c4878aSAndroid Build Coastguard Worker
395*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: uint32_t channel_id() const
396*61c4878aSAndroid Build Coastguard Worker
397*61c4878aSAndroid Build Coastguard Worker      Returns the channel ID of this call, which is 0 if the call is inactive.
398*61c4878aSAndroid Build Coastguard Worker
399*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: uint32_t id() const
400*61c4878aSAndroid Build Coastguard Worker
401*61c4878aSAndroid Build Coastguard Worker      Returns the call ID, a unique identifier for this call.
402*61c4878aSAndroid Build Coastguard Worker
403*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: void Write(RequestType)
404*61c4878aSAndroid Build Coastguard Worker
405*61c4878aSAndroid Build Coastguard Worker      Only available on client and bidirectional streaming calls. Sends a stream
406*61c4878aSAndroid Build Coastguard Worker      request. Returns:
407*61c4878aSAndroid Build Coastguard Worker
408*61c4878aSAndroid Build Coastguard Worker      - ``OK`` - the request was successfully sent
409*61c4878aSAndroid Build Coastguard Worker      - ``FAILED_PRECONDITION`` - the writer is closed
410*61c4878aSAndroid Build Coastguard Worker      - ``INTERNAL`` - pw_rpc was unable to encode message; does not apply to
411*61c4878aSAndroid Build Coastguard Worker        raw calls
412*61c4878aSAndroid Build Coastguard Worker      - other errors - the :cpp:class:`ChannelOutput` failed to send the packet;
413*61c4878aSAndroid Build Coastguard Worker        the error codes are determined by the :cpp:class:`ChannelOutput`
414*61c4878aSAndroid Build Coastguard Worker        implementation
415*61c4878aSAndroid Build Coastguard Worker
416*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: void WriteCallback(Function<StatusWithSize(ByteSpan)>)
417*61c4878aSAndroid Build Coastguard Worker
418*61c4878aSAndroid Build Coastguard Worker      Raw RPC only. Invokes the provided callback with the available RPC payload
419*61c4878aSAndroid Build Coastguard Worker      buffer, allowing payloads to be encoded directly into it. Sends a stream
420*61c4878aSAndroid Build Coastguard Worker      packet with the payload if the callback is successful.
421*61c4878aSAndroid Build Coastguard Worker
422*61c4878aSAndroid Build Coastguard Worker      The buffer provided to the callback is only valid for the duration of the
423*61c4878aSAndroid Build Coastguard Worker      callback. The callback should return an OK status with the size of the
424*61c4878aSAndroid Build Coastguard Worker      encoded payload on success, or an error status on failure.
425*61c4878aSAndroid Build Coastguard Worker
426*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: pw::Status RequestCompletion()
427*61c4878aSAndroid Build Coastguard Worker
428*61c4878aSAndroid Build Coastguard Worker      Notifies the server that client has requested for call completion. On
429*61c4878aSAndroid Build Coastguard Worker      client and bidirectional streaming calls no further client stream messages
430*61c4878aSAndroid Build Coastguard Worker      will be sent.
431*61c4878aSAndroid Build Coastguard Worker
432*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: pw::Status Cancel()
433*61c4878aSAndroid Build Coastguard Worker
434*61c4878aSAndroid Build Coastguard Worker      Cancels this RPC. Closes the call and sends a ``CANCELLED`` error to the
435*61c4878aSAndroid Build Coastguard Worker      server. Return statuses are the same as :cpp:func:`Write`.
436*61c4878aSAndroid Build Coastguard Worker
437*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: void Abandon()
438*61c4878aSAndroid Build Coastguard Worker
439*61c4878aSAndroid Build Coastguard Worker      Closes this RPC locally. Sends a ``CLIENT_REQUEST_COMPLETION``, but no cancellation
440*61c4878aSAndroid Build Coastguard Worker      packet. Future packets for this RPC are dropped, and the client sends a
441*61c4878aSAndroid Build Coastguard Worker      ``FAILED_PRECONDITION`` error in response because the call is not active.
442*61c4878aSAndroid Build Coastguard Worker
443*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: void CloseAndWaitForCallbacks()
444*61c4878aSAndroid Build Coastguard Worker
445*61c4878aSAndroid Build Coastguard Worker      Abandons this RPC and additionally blocks on completion of any running callbacks.
446*61c4878aSAndroid Build Coastguard Worker
447*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: void set_on_completed(pw::Function<void(ResponseTypeIfUnaryOnly, pw::Status)>)
448*61c4878aSAndroid Build Coastguard Worker
449*61c4878aSAndroid Build Coastguard Worker      Sets the callback that is called when the RPC completes normally. The
450*61c4878aSAndroid Build Coastguard Worker      signature depends on whether the call has a unary or stream response.
451*61c4878aSAndroid Build Coastguard Worker
452*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: void set_on_error(pw::Function<void(pw::Status)>)
453*61c4878aSAndroid Build Coastguard Worker
454*61c4878aSAndroid Build Coastguard Worker      Sets the callback that is called when the RPC is terminated due to an error.
455*61c4878aSAndroid Build Coastguard Worker
456*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: void set_on_next(pw::Function<void(ResponseType)>)
457*61c4878aSAndroid Build Coastguard Worker
458*61c4878aSAndroid Build Coastguard Worker      Only available on server and bidirectional streaming calls. Sets the callback
459*61c4878aSAndroid Build Coastguard Worker      that is called for each stream response.
460*61c4878aSAndroid Build Coastguard Worker
461*61c4878aSAndroid Build Coastguard WorkerCallbacks
462*61c4878aSAndroid Build Coastguard Worker=========
463*61c4878aSAndroid Build Coastguard WorkerThe C++ call objects allow users to set callbacks that are invoked when RPC
464*61c4878aSAndroid Build Coastguard Worker:ref:`events <module-pw_rpc-design-events>` occur.
465*61c4878aSAndroid Build Coastguard Worker
466*61c4878aSAndroid Build Coastguard Worker.. list-table::
467*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
468*61c4878aSAndroid Build Coastguard Worker
469*61c4878aSAndroid Build Coastguard Worker   * - Name
470*61c4878aSAndroid Build Coastguard Worker     - Stream signature
471*61c4878aSAndroid Build Coastguard Worker     - Non-stream signature
472*61c4878aSAndroid Build Coastguard Worker     - Server
473*61c4878aSAndroid Build Coastguard Worker     - Client
474*61c4878aSAndroid Build Coastguard Worker   * - ``on_error``
475*61c4878aSAndroid Build Coastguard Worker     - ``void(pw::Status)``
476*61c4878aSAndroid Build Coastguard Worker     - ``void(pw::Status)``
477*61c4878aSAndroid Build Coastguard Worker     - ✅
478*61c4878aSAndroid Build Coastguard Worker     - ✅
479*61c4878aSAndroid Build Coastguard Worker   * - ``on_next``
480*61c4878aSAndroid Build Coastguard Worker     - n/a
481*61c4878aSAndroid Build Coastguard Worker     - ``void(const PayloadType&)``
482*61c4878aSAndroid Build Coastguard Worker     - ✅
483*61c4878aSAndroid Build Coastguard Worker     - ✅
484*61c4878aSAndroid Build Coastguard Worker   * - ``on_completed``
485*61c4878aSAndroid Build Coastguard Worker     - ``void(pw::Status)``
486*61c4878aSAndroid Build Coastguard Worker     - ``void(const PayloadType&, pw::Status)``
487*61c4878aSAndroid Build Coastguard Worker     -
488*61c4878aSAndroid Build Coastguard Worker     - ✅
489*61c4878aSAndroid Build Coastguard Worker   * - ``on_client_requested_completion``
490*61c4878aSAndroid Build Coastguard Worker     - ``void()``
491*61c4878aSAndroid Build Coastguard Worker     - n/a
492*61c4878aSAndroid Build Coastguard Worker     - ✅ (:c:macro:`optional <PW_RPC_COMPLETION_REQUEST_CALLBACK>`)
493*61c4878aSAndroid Build Coastguard Worker     -
494*61c4878aSAndroid Build Coastguard Worker
495*61c4878aSAndroid Build Coastguard WorkerLimitations and restrictions
496*61c4878aSAndroid Build Coastguard Worker----------------------------
497*61c4878aSAndroid Build Coastguard WorkerRPC callbacks are free to perform most actions, including invoking new RPCs or
498*61c4878aSAndroid Build Coastguard Workercancelling pending calls. However, the C++ implementation imposes some
499*61c4878aSAndroid Build Coastguard Workerlimitations and restrictions that must be observed.
500*61c4878aSAndroid Build Coastguard Worker
501*61c4878aSAndroid Build Coastguard WorkerDestructors & moves wait for callbacks to complete
502*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
503*61c4878aSAndroid Build Coastguard Worker* Callbacks must not destroy their call object. Attempting to do so will result
504*61c4878aSAndroid Build Coastguard Worker  in deadlock.
505*61c4878aSAndroid Build Coastguard Worker* Other threads may destroy a call while its callback is running, but that
506*61c4878aSAndroid Build Coastguard Worker  thread will block until all callbacks complete.
507*61c4878aSAndroid Build Coastguard Worker* Callbacks must not move their call object if it the call is still active. They
508*61c4878aSAndroid Build Coastguard Worker  may move their call object after it has terminated. Callbacks may move a
509*61c4878aSAndroid Build Coastguard Worker  different call into their call object, since moving closes the destination
510*61c4878aSAndroid Build Coastguard Worker  call.
511*61c4878aSAndroid Build Coastguard Worker* Other threads may move a call object while it has a callback running, but they
512*61c4878aSAndroid Build Coastguard Worker  will block until the callback completes if the call is still active.
513*61c4878aSAndroid Build Coastguard Worker
514*61c4878aSAndroid Build Coastguard Worker.. warning::
515*61c4878aSAndroid Build Coastguard Worker
516*61c4878aSAndroid Build Coastguard Worker   Deadlocks or crashes occur if a callback:
517*61c4878aSAndroid Build Coastguard Worker
518*61c4878aSAndroid Build Coastguard Worker   - attempts to destroy its call object
519*61c4878aSAndroid Build Coastguard Worker   - attempts to move its call object while the call is still active
520*61c4878aSAndroid Build Coastguard Worker   - never returns
521*61c4878aSAndroid Build Coastguard Worker
522*61c4878aSAndroid Build Coastguard Worker   If ``pw_rpc`` a callback violates these restrictions, a crash may occur,
523*61c4878aSAndroid Build Coastguard Worker   depending on the value of :c:macro:`PW_RPC_CALLBACK_TIMEOUT_TICKS`. These
524*61c4878aSAndroid Build Coastguard Worker   crashes have a message like the following:
525*61c4878aSAndroid Build Coastguard Worker
526*61c4878aSAndroid Build Coastguard Worker   .. code-block:: text
527*61c4878aSAndroid Build Coastguard Worker
528*61c4878aSAndroid Build Coastguard Worker      A callback for RPC 1:cc0f6de0/31e616ce has not finished after 10000 ticks.
529*61c4878aSAndroid Build Coastguard Worker      This may indicate that an RPC callback attempted to destroy or move its own
530*61c4878aSAndroid Build Coastguard Worker      call object, which is not permitted. Fix this condition or change the value of
531*61c4878aSAndroid Build Coastguard Worker      PW_RPC_CALLBACK_TIMEOUT_TICKS to avoid this crash.
532*61c4878aSAndroid Build Coastguard Worker
533*61c4878aSAndroid Build Coastguard Worker      See https://pigweed.dev/pw_rpc#destructors-moves-wait-for-callbacks-to-complete
534*61c4878aSAndroid Build Coastguard Worker      for details.
535*61c4878aSAndroid Build Coastguard Worker
536*61c4878aSAndroid Build Coastguard WorkerOnly one thread at a time may execute ``on_next``
537*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
538*61c4878aSAndroid Build Coastguard WorkerOnly one thread may execute the ``on_next`` callback for a specific service
539*61c4878aSAndroid Build Coastguard Workermethod at a time. If a second thread calls ``ProcessPacket()`` with a stream
540*61c4878aSAndroid Build Coastguard Workerpacket before the ``on_next`` callback for the previous packet completes, the
541*61c4878aSAndroid Build Coastguard Workersecond packet will be dropped. The RPC endpoint logs a warning when this occurs.
542*61c4878aSAndroid Build Coastguard Worker
543*61c4878aSAndroid Build Coastguard WorkerExample warning for a dropped stream packet:
544*61c4878aSAndroid Build Coastguard Worker
545*61c4878aSAndroid Build Coastguard Worker.. code-block:: text
546*61c4878aSAndroid Build Coastguard Worker
547*61c4878aSAndroid Build Coastguard Worker   WRN  Received stream packet for 1:cc0f6de0/31e616ce before the callback for
548*61c4878aSAndroid Build Coastguard Worker        a previous packet completed! This packet will be dropped. This can be
549*61c4878aSAndroid Build Coastguard Worker        avoided by handling packets for a particular RPC on only one thread.
550*61c4878aSAndroid Build Coastguard Worker
551*61c4878aSAndroid Build Coastguard Worker-----------------------
552*61c4878aSAndroid Build Coastguard WorkerRPC calls introspection
553*61c4878aSAndroid Build Coastguard Worker-----------------------
554*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` provides ``pw_rpc/method_info.h`` header that allows to obtain
555*61c4878aSAndroid Build Coastguard Workerinformation about the generated RPC method in compile time.
556*61c4878aSAndroid Build Coastguard Worker
557*61c4878aSAndroid Build Coastguard WorkerFor now it provides only two types: ``MethodRequestType<RpcMethod>`` and
558*61c4878aSAndroid Build Coastguard Worker``MethodResponseType<RpcMethod>``. They are aliases to the types that are used
559*61c4878aSAndroid Build Coastguard Workeras a request and response respectively for the given RpcMethod.
560*61c4878aSAndroid Build Coastguard Worker
561*61c4878aSAndroid Build Coastguard WorkerExample
562*61c4878aSAndroid Build Coastguard Worker=======
563*61c4878aSAndroid Build Coastguard WorkerWe have an RPC service ``SpecialService`` with ``MyMethod`` method:
564*61c4878aSAndroid Build Coastguard Worker
565*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
566*61c4878aSAndroid Build Coastguard Worker
567*61c4878aSAndroid Build Coastguard Worker   package some.package;
568*61c4878aSAndroid Build Coastguard Worker   service SpecialService {
569*61c4878aSAndroid Build Coastguard Worker     rpc MyMethod(MyMethodRequest) returns (MyMethodResponse) {}
570*61c4878aSAndroid Build Coastguard Worker   }
571*61c4878aSAndroid Build Coastguard Worker
572*61c4878aSAndroid Build Coastguard WorkerWe also have a templated Storage type alias:
573*61c4878aSAndroid Build Coastguard Worker
574*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
575*61c4878aSAndroid Build Coastguard Worker
576*61c4878aSAndroid Build Coastguard Worker   template <auto kMethod>
577*61c4878aSAndroid Build Coastguard Worker   using Storage =
578*61c4878aSAndroid Build Coastguard Worker      std::pair<MethodRequestType<kMethod>, MethodResponseType<kMethod>>;
579*61c4878aSAndroid Build Coastguard Worker
580*61c4878aSAndroid Build Coastguard Worker``Storage<some::package::pw_rpc::pwpb::SpecialService::MyMethod>`` will
581*61c4878aSAndroid Build Coastguard Workerinstantiate as:
582*61c4878aSAndroid Build Coastguard Worker
583*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
584*61c4878aSAndroid Build Coastguard Worker
585*61c4878aSAndroid Build Coastguard Worker   std::pair<some::package::MyMethodRequest::Message,
586*61c4878aSAndroid Build Coastguard Worker             some::package::MyMethodResponse::Message>;
587*61c4878aSAndroid Build Coastguard Worker
588*61c4878aSAndroid Build Coastguard Worker.. note::
589*61c4878aSAndroid Build Coastguard Worker
590*61c4878aSAndroid Build Coastguard Worker   Only nanopb and pw_protobuf have real types as
591*61c4878aSAndroid Build Coastguard Worker   ``MethodRequestType<RpcMethod>``/``MethodResponseType<RpcMethod>``. Raw has
592*61c4878aSAndroid Build Coastguard Worker   them both set as ``void``. In reality, they are ``pw::ConstByteSpan``. Any
593*61c4878aSAndroid Build Coastguard Worker   helper/trait that wants to use this types for raw methods should do a custom
594*61c4878aSAndroid Build Coastguard Worker   implementation that copies the bytes under the span instead of copying just
595*61c4878aSAndroid Build Coastguard Worker   the span.
596*61c4878aSAndroid Build Coastguard Worker
597*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-client-sync-call-wrappers:
598*61c4878aSAndroid Build Coastguard Worker
599*61c4878aSAndroid Build Coastguard Worker--------------------------------
600*61c4878aSAndroid Build Coastguard WorkerClient synchronous call wrappers
601*61c4878aSAndroid Build Coastguard Worker--------------------------------
602*61c4878aSAndroid Build Coastguard Worker.. doxygenfile:: pw_rpc/synchronous_call.h
603*61c4878aSAndroid Build Coastguard Worker   :sections: detaileddescription
604*61c4878aSAndroid Build Coastguard Worker
605*61c4878aSAndroid Build Coastguard WorkerExample
606*61c4878aSAndroid Build Coastguard Worker=======
607*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
608*61c4878aSAndroid Build Coastguard Worker
609*61c4878aSAndroid Build Coastguard Worker   #include "pw_rpc/synchronous_call.h"
610*61c4878aSAndroid Build Coastguard Worker
611*61c4878aSAndroid Build Coastguard Worker   void InvokeUnaryRpc() {
612*61c4878aSAndroid Build Coastguard Worker     pw::rpc::Client client;
613*61c4878aSAndroid Build Coastguard Worker     pw::rpc::Channel channel;
614*61c4878aSAndroid Build Coastguard Worker
615*61c4878aSAndroid Build Coastguard Worker     RoomInfoRequest request;
616*61c4878aSAndroid Build Coastguard Worker     SynchronousCallResult<RoomInfoResponse> result =
617*61c4878aSAndroid Build Coastguard Worker       SynchronousCall<Chat::GetRoomInformation>(client, channel.id(), request);
618*61c4878aSAndroid Build Coastguard Worker
619*61c4878aSAndroid Build Coastguard Worker     if (result.is_rpc_error()) {
620*61c4878aSAndroid Build Coastguard Worker       ShutdownClient(client);
621*61c4878aSAndroid Build Coastguard Worker     } else if (result.is_server_error()) {
622*61c4878aSAndroid Build Coastguard Worker       HandleServerError(result.status());
623*61c4878aSAndroid Build Coastguard Worker     } else if (result.is_timeout()) {
624*61c4878aSAndroid Build Coastguard Worker       // SynchronousCall will block indefinitely, so we should never get here.
625*61c4878aSAndroid Build Coastguard Worker       PW_UNREACHABLE();
626*61c4878aSAndroid Build Coastguard Worker     }
627*61c4878aSAndroid Build Coastguard Worker     HandleRoomInformation(std::move(result).response());
628*61c4878aSAndroid Build Coastguard Worker   }
629*61c4878aSAndroid Build Coastguard Worker
630*61c4878aSAndroid Build Coastguard Worker   void AnotherExample() {
631*61c4878aSAndroid Build Coastguard Worker     pw_rpc::nanopb::Chat::Client chat_client(client, channel);
632*61c4878aSAndroid Build Coastguard Worker     constexpr auto kTimeout = pw::chrono::SystemClock::for_at_least(500ms);
633*61c4878aSAndroid Build Coastguard Worker
634*61c4878aSAndroid Build Coastguard Worker     RoomInfoRequest request;
635*61c4878aSAndroid Build Coastguard Worker     auto result = SynchronousCallFor<Chat::GetRoomInformation>(
636*61c4878aSAndroid Build Coastguard Worker         chat_client, request, kTimeout);
637*61c4878aSAndroid Build Coastguard Worker
638*61c4878aSAndroid Build Coastguard Worker     if (result.is_timeout()) {
639*61c4878aSAndroid Build Coastguard Worker       RetryRoomRequest();
640*61c4878aSAndroid Build Coastguard Worker     } else {
641*61c4878aSAndroid Build Coastguard Worker     ...
642*61c4878aSAndroid Build Coastguard Worker     }
643*61c4878aSAndroid Build Coastguard Worker   }
644*61c4878aSAndroid Build Coastguard Worker
645*61c4878aSAndroid Build Coastguard WorkerThe ``SynchronousCallResult<Response>`` is also compatible with the
646*61c4878aSAndroid Build Coastguard Worker:c:macro:`PW_TRY` family of macros, but users should be aware that their use
647*61c4878aSAndroid Build Coastguard Workerwill lose information about the type of error. This should only be used if the
648*61c4878aSAndroid Build Coastguard Workercaller will handle all error scenarios the same.
649*61c4878aSAndroid Build Coastguard Worker
650*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
651*61c4878aSAndroid Build Coastguard Worker
652*61c4878aSAndroid Build Coastguard Worker   pw::Status SyncRpc() {
653*61c4878aSAndroid Build Coastguard Worker     const RoomInfoRequest request;
654*61c4878aSAndroid Build Coastguard Worker     PW_TRY_ASSIGN(const RoomInfoResponse& response,
655*61c4878aSAndroid Build Coastguard Worker                   SynchronousCall<Chat::GetRoomInformation>(client, request));
656*61c4878aSAndroid Build Coastguard Worker     HandleRoomInformation(response);
657*61c4878aSAndroid Build Coastguard Worker     return pw::OkStatus();
658*61c4878aSAndroid Build Coastguard Worker   }
659*61c4878aSAndroid Build Coastguard Worker
660*61c4878aSAndroid Build Coastguard Worker------------
661*61c4878aSAndroid Build Coastguard WorkerClientServer
662*61c4878aSAndroid Build Coastguard Worker------------
663*61c4878aSAndroid Build Coastguard WorkerSometimes, a device needs to both process RPCs as a server, as well as making
664*61c4878aSAndroid Build Coastguard Workercalls to another device as a client. To do this, both a client and server must
665*61c4878aSAndroid Build Coastguard Workerbe set up, and incoming packets must be sent to both of them.
666*61c4878aSAndroid Build Coastguard Worker
667*61c4878aSAndroid Build Coastguard WorkerPigweed simplifies this setup by providing a ``ClientServer`` class which wraps
668*61c4878aSAndroid Build Coastguard Workeran RPC client and server with the same set of channels.
669*61c4878aSAndroid Build Coastguard Worker
670*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
671*61c4878aSAndroid Build Coastguard Worker
672*61c4878aSAndroid Build Coastguard Worker   pw::rpc::Channel channels[] = {
673*61c4878aSAndroid Build Coastguard Worker       pw::rpc::Channel::Create<1>(&channel_output)};
674*61c4878aSAndroid Build Coastguard Worker
675*61c4878aSAndroid Build Coastguard Worker   // Creates both a client and a server.
676*61c4878aSAndroid Build Coastguard Worker   pw::rpc::ClientServer client_server(channels);
677*61c4878aSAndroid Build Coastguard Worker
678*61c4878aSAndroid Build Coastguard Worker   void ProcessRpcData(pw::ConstByteSpan packet) {
679*61c4878aSAndroid Build Coastguard Worker     // Calls into both the client and the server, sending the packet to the
680*61c4878aSAndroid Build Coastguard Worker     // appropriate one.
681*61c4878aSAndroid Build Coastguard Worker     client_server.ProcessPacket(packet);
682*61c4878aSAndroid Build Coastguard Worker   }
683*61c4878aSAndroid Build Coastguard Worker
684*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-cpp-testing:
685*61c4878aSAndroid Build Coastguard Worker
686*61c4878aSAndroid Build Coastguard Worker-------
687*61c4878aSAndroid Build Coastguard WorkerTesting
688*61c4878aSAndroid Build Coastguard Worker-------
689*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` provides utilities for unit testing RPC services and client calls.
690*61c4878aSAndroid Build Coastguard Worker
691*61c4878aSAndroid Build Coastguard WorkerClient unit testing in C++
692*61c4878aSAndroid Build Coastguard Worker==========================
693*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` supports invoking RPCs, simulating server responses, and checking
694*61c4878aSAndroid Build Coastguard Workerwhat packets are sent by an RPC client in tests. Raw, Nanopb and Pwpb interfaces
695*61c4878aSAndroid Build Coastguard Workerare supported. Code that uses the raw API may be tested with the raw test
696*61c4878aSAndroid Build Coastguard Workerhelpers, and vice versa. The Nanopb and Pwpb APIs also provides a test helper
697*61c4878aSAndroid Build Coastguard Workerwith a real client-server pair that supports testing of asynchronous messaging.
698*61c4878aSAndroid Build Coastguard Worker
699*61c4878aSAndroid Build Coastguard WorkerTo test synchronous code that invokes RPCs, declare a ``RawClientTestContext``,
700*61c4878aSAndroid Build Coastguard Worker``PwpbClientTestContext``,  or ``NanopbClientTestContext``. These test context
701*61c4878aSAndroid Build Coastguard Workerobjects provide a preconfigured RPC client, channel, server fake, and buffer for
702*61c4878aSAndroid Build Coastguard Workerencoding packets.
703*61c4878aSAndroid Build Coastguard Worker
704*61c4878aSAndroid Build Coastguard WorkerThese test classes are defined in ``pw_rpc/raw/client_testing.h``,
705*61c4878aSAndroid Build Coastguard Worker``pw_rpc/pwpb/client_testing.h``, or ``pw_rpc/nanopb/client_testing.h``.
706*61c4878aSAndroid Build Coastguard Worker
707*61c4878aSAndroid Build Coastguard WorkerUse the context's ``client()`` and ``channel()`` to invoke RPCs. Use the
708*61c4878aSAndroid Build Coastguard Workercontext's ``server()`` to simulate responses. To verify that the client sent the
709*61c4878aSAndroid Build Coastguard Workerexpected data, use the context's ``output()``, which is a ``FakeChannelOutput``.
710*61c4878aSAndroid Build Coastguard Worker
711*61c4878aSAndroid Build Coastguard WorkerFor example, the following tests a class that invokes an RPC. It checks that
712*61c4878aSAndroid Build Coastguard Workerthe expected data was sent and then simulates a response from the server.
713*61c4878aSAndroid Build Coastguard Worker
714*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
715*61c4878aSAndroid Build Coastguard Worker
716*61c4878aSAndroid Build Coastguard Worker   #include "pw_rpc/raw/client_testing.h"
717*61c4878aSAndroid Build Coastguard Worker
718*61c4878aSAndroid Build Coastguard Worker   class ClientUnderTest {
719*61c4878aSAndroid Build Coastguard Worker    public:
720*61c4878aSAndroid Build Coastguard Worker     // To support injecting an RPC client for testing, classes that make RPC
721*61c4878aSAndroid Build Coastguard Worker     // calls should take an RPC client and channel ID or an RPC service client
722*61c4878aSAndroid Build Coastguard Worker     // (e.g. pw_rpc::raw::MyService::Client).
723*61c4878aSAndroid Build Coastguard Worker     ClientUnderTest(pw::rpc::Client& client, uint32_t channel_id);
724*61c4878aSAndroid Build Coastguard Worker
725*61c4878aSAndroid Build Coastguard Worker     void DoSomethingThatInvokesAnRpc();
726*61c4878aSAndroid Build Coastguard Worker
727*61c4878aSAndroid Build Coastguard Worker     bool SetToTrueWhenRpcCompletes();
728*61c4878aSAndroid Build Coastguard Worker   };
729*61c4878aSAndroid Build Coastguard Worker
730*61c4878aSAndroid Build Coastguard Worker   TEST(TestAThing, InvokesRpcAndHandlesResponse) {
731*61c4878aSAndroid Build Coastguard Worker     RawClientTestContext context;
732*61c4878aSAndroid Build Coastguard Worker     ClientUnderTest thing(context.client(), context.channel().id());
733*61c4878aSAndroid Build Coastguard Worker
734*61c4878aSAndroid Build Coastguard Worker     // Execute the code that invokes the MyService.TheMethod RPC.
735*61c4878aSAndroid Build Coastguard Worker     things.DoSomethingThatInvokesAnRpc();
736*61c4878aSAndroid Build Coastguard Worker
737*61c4878aSAndroid Build Coastguard Worker     // Find and verify the payloads sent for the MyService.TheMethod RPC.
738*61c4878aSAndroid Build Coastguard Worker     auto msgs = context.output().payloads<pw_rpc::raw::MyService::TheMethod>();
739*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(msgs.size(), 1u);
740*61c4878aSAndroid Build Coastguard Worker
741*61c4878aSAndroid Build Coastguard Worker     VerifyThatTheExpectedMessageWasSent(msgs.back());
742*61c4878aSAndroid Build Coastguard Worker
743*61c4878aSAndroid Build Coastguard Worker     // Send the response packet from the server and verify that the class reacts
744*61c4878aSAndroid Build Coastguard Worker     // accordingly.
745*61c4878aSAndroid Build Coastguard Worker     EXPECT_FALSE(thing.SetToTrueWhenRpcCompletes());
746*61c4878aSAndroid Build Coastguard Worker
747*61c4878aSAndroid Build Coastguard Worker     context_.server().SendResponse<pw_rpc::raw::MyService::TheMethod>(
748*61c4878aSAndroid Build Coastguard Worker         final_message, OkStatus());
749*61c4878aSAndroid Build Coastguard Worker
750*61c4878aSAndroid Build Coastguard Worker     EXPECT_TRUE(thing.SetToTrueWhenRpcCompletes());
751*61c4878aSAndroid Build Coastguard Worker   }
752*61c4878aSAndroid Build Coastguard Worker
753*61c4878aSAndroid Build Coastguard WorkerTo test client code that uses asynchronous responses, encapsulates multiple
754*61c4878aSAndroid Build Coastguard Workerrpc calls to one or more services, or uses a custom service implementation,
755*61c4878aSAndroid Build Coastguard Workerdeclare a ``NanopbClientServerTestContextThreaded`` or
756*61c4878aSAndroid Build Coastguard Worker``PwpbClientServerTestContextThreaded``. These test object are defined in
757*61c4878aSAndroid Build Coastguard Worker``pw_rpc/nanopb/client_server_testing_threaded.h`` and
758*61c4878aSAndroid Build Coastguard Worker``pw_rpc/pwpb/client_server_testing_threaded.h``.
759*61c4878aSAndroid Build Coastguard Worker
760*61c4878aSAndroid Build Coastguard WorkerUse the context's ``server()`` to register a ``Service`` implementation, and
761*61c4878aSAndroid Build Coastguard Worker``client()`` and ``channel()`` to invoke RPCs. Create a ``Thread`` using the
762*61c4878aSAndroid Build Coastguard Workercontext as a ``ThreadCore`` to have it asynchronously forward request/responses or
763*61c4878aSAndroid Build Coastguard Workercall ``ForwardNewPackets`` to synchronously process all messages. To verify that
764*61c4878aSAndroid Build Coastguard Workerthe client/server sent the expected data, use the context's
765*61c4878aSAndroid Build Coastguard Worker``request(uint32_t index)`` and ``response(uint32_t index)`` to retrieve the
766*61c4878aSAndroid Build Coastguard Workerordered messages.
767*61c4878aSAndroid Build Coastguard Worker
768*61c4878aSAndroid Build Coastguard WorkerFor example, the following tests a class that invokes an RPC and blocks till a
769*61c4878aSAndroid Build Coastguard Workerresponse is received. It verifies that expected data was both sent and received.
770*61c4878aSAndroid Build Coastguard Worker
771*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
772*61c4878aSAndroid Build Coastguard Worker
773*61c4878aSAndroid Build Coastguard Worker   #include "my_library_protos/my_service.rpc.pb.h"
774*61c4878aSAndroid Build Coastguard Worker   #include "pw_rpc/nanopb/client_server_testing_threaded.h"
775*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread_stl/options.h"
776*61c4878aSAndroid Build Coastguard Worker
777*61c4878aSAndroid Build Coastguard Worker   class ClientUnderTest {
778*61c4878aSAndroid Build Coastguard Worker    public:
779*61c4878aSAndroid Build Coastguard Worker     // To support injecting an RPC client for testing, classes that make RPC
780*61c4878aSAndroid Build Coastguard Worker     // calls should take an RPC client and channel ID or an RPC service client
781*61c4878aSAndroid Build Coastguard Worker     // (e.g. pw_rpc::raw::MyService::Client).
782*61c4878aSAndroid Build Coastguard Worker     ClientUnderTest(pw::rpc::Client& client, uint32_t channel_id);
783*61c4878aSAndroid Build Coastguard Worker
784*61c4878aSAndroid Build Coastguard Worker     Status BlockOnResponse(uint32_t value);
785*61c4878aSAndroid Build Coastguard Worker   };
786*61c4878aSAndroid Build Coastguard Worker
787*61c4878aSAndroid Build Coastguard Worker
788*61c4878aSAndroid Build Coastguard Worker   class TestService final : public MyService<TestService> {
789*61c4878aSAndroid Build Coastguard Worker    public:
790*61c4878aSAndroid Build Coastguard Worker     Status TheMethod(const pw_rpc_test_TheMethod& request,
791*61c4878aSAndroid Build Coastguard Worker                         pw_rpc_test_TheMethod& response) {
792*61c4878aSAndroid Build Coastguard Worker       response.value = request.integer + 1;
793*61c4878aSAndroid Build Coastguard Worker       return pw::OkStatus();
794*61c4878aSAndroid Build Coastguard Worker     }
795*61c4878aSAndroid Build Coastguard Worker   };
796*61c4878aSAndroid Build Coastguard Worker
797*61c4878aSAndroid Build Coastguard Worker   TEST(TestServiceTest, ReceivesUnaryRpcResponse) {
798*61c4878aSAndroid Build Coastguard Worker     NanopbClientServerTestContextThreaded<> ctx(pw::thread::stl::Options{});
799*61c4878aSAndroid Build Coastguard Worker     TestService service;
800*61c4878aSAndroid Build Coastguard Worker     ctx.server().RegisterService(service);
801*61c4878aSAndroid Build Coastguard Worker     ClientUnderTest client(ctx.client(), ctx.channel().id());
802*61c4878aSAndroid Build Coastguard Worker
803*61c4878aSAndroid Build Coastguard Worker     // Execute the code that invokes the MyService.TheMethod RPC.
804*61c4878aSAndroid Build Coastguard Worker     constexpr uint32_t value = 1;
805*61c4878aSAndroid Build Coastguard Worker     const auto result = client.BlockOnResponse(value);
806*61c4878aSAndroid Build Coastguard Worker     const auto request = ctx.request<MyService::TheMethod>(0);
807*61c4878aSAndroid Build Coastguard Worker     const auto response = ctx.response<MyService::TheMethod>(0);
808*61c4878aSAndroid Build Coastguard Worker
809*61c4878aSAndroid Build Coastguard Worker     // Verify content of messages
810*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(result, pw::OkStatus());
811*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(request.value, value);
812*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(response.value, value + 1);
813*61c4878aSAndroid Build Coastguard Worker   }
814*61c4878aSAndroid Build Coastguard Worker
815*61c4878aSAndroid Build Coastguard WorkerUse the context's
816*61c4878aSAndroid Build Coastguard Worker``response(uint32_t index, Response<kMethod>& response)`` to decode messages
817*61c4878aSAndroid Build Coastguard Workerinto a provided response object. You would use this version if decoder callbacks
818*61c4878aSAndroid Build Coastguard Workerare needed to fully decode a message. For instance if it uses ``repeated``
819*61c4878aSAndroid Build Coastguard Workerfields.
820*61c4878aSAndroid Build Coastguard Worker
821*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
822*61c4878aSAndroid Build Coastguard Worker
823*61c4878aSAndroid Build Coastguard Worker   TestResponse::Message response{};
824*61c4878aSAndroid Build Coastguard Worker   response.repeated_field.SetDecoder(
825*61c4878aSAndroid Build Coastguard Worker       [&values](TestResponse::StreamDecoder& decoder) {
826*61c4878aSAndroid Build Coastguard Worker         return decoder.ReadRepeatedField(values);
827*61c4878aSAndroid Build Coastguard Worker       });
828*61c4878aSAndroid Build Coastguard Worker   ctx.response<test::GeneratedService::TestAnotherUnaryRpc>(0, response);
829*61c4878aSAndroid Build Coastguard Worker
830*61c4878aSAndroid Build Coastguard WorkerSynchronous versions of these test contexts also exist that may be used on
831*61c4878aSAndroid Build Coastguard Workernon-threaded systems ``NanopbClientServerTestContext`` and
832*61c4878aSAndroid Build Coastguard Worker``PwpbClientServerTestContext``. While these do not allow for asynchronous
833*61c4878aSAndroid Build Coastguard Workermessaging they support the use of service implementations and use a similar
834*61c4878aSAndroid Build Coastguard Workersyntax. When these are used ``.ForwardNewPackets()`` should be called after each
835*61c4878aSAndroid Build Coastguard Workerrpc call to trigger sending of queued messages.
836*61c4878aSAndroid Build Coastguard Worker
837*61c4878aSAndroid Build Coastguard WorkerFor example, the following tests a class that invokes an RPC that is responded
838*61c4878aSAndroid Build Coastguard Workerto with a test service implementation.
839*61c4878aSAndroid Build Coastguard Worker
840*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
841*61c4878aSAndroid Build Coastguard Worker
842*61c4878aSAndroid Build Coastguard Worker   #include "my_library_protos/my_service.rpc.pb.h"
843*61c4878aSAndroid Build Coastguard Worker   #include "pw_rpc/nanopb/client_server_testing.h"
844*61c4878aSAndroid Build Coastguard Worker
845*61c4878aSAndroid Build Coastguard Worker   class ClientUnderTest {
846*61c4878aSAndroid Build Coastguard Worker    public:
847*61c4878aSAndroid Build Coastguard Worker     ClientUnderTest(pw::rpc::Client& client, uint32_t channel_id);
848*61c4878aSAndroid Build Coastguard Worker
849*61c4878aSAndroid Build Coastguard Worker     Status SendRpcCall(uint32_t value);
850*61c4878aSAndroid Build Coastguard Worker   };
851*61c4878aSAndroid Build Coastguard Worker
852*61c4878aSAndroid Build Coastguard Worker
853*61c4878aSAndroid Build Coastguard Worker   class TestService final : public MyService<TestService> {
854*61c4878aSAndroid Build Coastguard Worker    public:
855*61c4878aSAndroid Build Coastguard Worker     Status TheMethod(const pw_rpc_test_TheMethod& request,
856*61c4878aSAndroid Build Coastguard Worker                         pw_rpc_test_TheMethod& response) {
857*61c4878aSAndroid Build Coastguard Worker       response.value = request.integer + 1;
858*61c4878aSAndroid Build Coastguard Worker       return pw::OkStatus();
859*61c4878aSAndroid Build Coastguard Worker     }
860*61c4878aSAndroid Build Coastguard Worker   };
861*61c4878aSAndroid Build Coastguard Worker
862*61c4878aSAndroid Build Coastguard Worker   TEST(TestServiceTest, ReceivesUnaryRpcResponse) {
863*61c4878aSAndroid Build Coastguard Worker     NanopbClientServerTestContext<> ctx();
864*61c4878aSAndroid Build Coastguard Worker     TestService service;
865*61c4878aSAndroid Build Coastguard Worker     ctx.server().RegisterService(service);
866*61c4878aSAndroid Build Coastguard Worker     ClientUnderTest client(ctx.client(), ctx.channel().id());
867*61c4878aSAndroid Build Coastguard Worker
868*61c4878aSAndroid Build Coastguard Worker     // Execute the code that invokes the MyService.TheMethod RPC.
869*61c4878aSAndroid Build Coastguard Worker     constexpr uint32_t value = 1;
870*61c4878aSAndroid Build Coastguard Worker     const auto result = client.SendRpcCall(value);
871*61c4878aSAndroid Build Coastguard Worker     // Needed after ever RPC call to trigger forward of packets
872*61c4878aSAndroid Build Coastguard Worker     ctx.ForwardNewPackets();
873*61c4878aSAndroid Build Coastguard Worker     const auto request = ctx.request<MyService::TheMethod>(0);
874*61c4878aSAndroid Build Coastguard Worker     const auto response = ctx.response<MyService::TheMethod>(0);
875*61c4878aSAndroid Build Coastguard Worker
876*61c4878aSAndroid Build Coastguard Worker     // Verify content of messages
877*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(result, pw::OkStatus());
878*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(request.value, value);
879*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(response.value, value + 1);
880*61c4878aSAndroid Build Coastguard Worker   }
881*61c4878aSAndroid Build Coastguard Worker
882*61c4878aSAndroid Build Coastguard WorkerCustom packet processing for ClientServerTestContext
883*61c4878aSAndroid Build Coastguard Worker====================================================
884*61c4878aSAndroid Build Coastguard WorkerOptional constructor arguments for nanopb/pwpb ``*ClientServerTestContext`` and
885*61c4878aSAndroid Build Coastguard Worker``*ClientServerTestContextThreaded`` allow allow customized packet processing.
886*61c4878aSAndroid Build Coastguard WorkerBy default the only thing is done is ``ProcessPacket()`` call on the
887*61c4878aSAndroid Build Coastguard Worker``ClientServer`` instance.
888*61c4878aSAndroid Build Coastguard Worker
889*61c4878aSAndroid Build Coastguard WorkerFor cases when additional instrumentation or offloading to separate thread is
890*61c4878aSAndroid Build Coastguard Workerneeded, separate client and server processors can be passed to context
891*61c4878aSAndroid Build Coastguard Workerconstructors. A packet processor is a function that returns ``pw::Status`` and
892*61c4878aSAndroid Build Coastguard Workeraccepts two arguments: ``pw::rpc::ClientServer&`` and ``pw::ConstByteSpan``.
893*61c4878aSAndroid Build Coastguard WorkerDefault packet processing is equivalent to the next processor:
894*61c4878aSAndroid Build Coastguard Worker
895*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
896*61c4878aSAndroid Build Coastguard Worker
897*61c4878aSAndroid Build Coastguard Worker   [](ClientServer& client_server, pw::ConstByteSpan packet) -> pw::Status {
898*61c4878aSAndroid Build Coastguard Worker     return client_server.ProcessPacket(packet);
899*61c4878aSAndroid Build Coastguard Worker   };
900*61c4878aSAndroid Build Coastguard Worker
901*61c4878aSAndroid Build Coastguard WorkerThe Server processor will be applied to all packets sent to the server (i.e.
902*61c4878aSAndroid Build Coastguard Workerrequests) and client processor will be applied to all packets sent to the client
903*61c4878aSAndroid Build Coastguard Worker(i.e. responses).
904*61c4878aSAndroid Build Coastguard Worker
905*61c4878aSAndroid Build Coastguard Worker.. note::
906*61c4878aSAndroid Build Coastguard Worker
907*61c4878aSAndroid Build Coastguard Worker  The packet processor MUST call ``ClientServer::ProcessPacket()`` method.
908*61c4878aSAndroid Build Coastguard Worker  Otherwise the packet won't be processed.
909*61c4878aSAndroid Build Coastguard Worker
910*61c4878aSAndroid Build Coastguard Worker.. note::
911*61c4878aSAndroid Build Coastguard Worker
912*61c4878aSAndroid Build Coastguard Worker  If the packet processor offloads processing to the separate thread, it MUST
913*61c4878aSAndroid Build Coastguard Worker  copy the ``packet``. After the packet processor returns, the underlying array
914*61c4878aSAndroid Build Coastguard Worker  can go out of scope or be reused for other purposes.
915*61c4878aSAndroid Build Coastguard Worker
916*61c4878aSAndroid Build Coastguard WorkerSendResponseIfCalled() helper
917*61c4878aSAndroid Build Coastguard Worker=============================
918*61c4878aSAndroid Build Coastguard Worker``SendResponseIfCalled()`` function waits on ``*ClientTestContext*`` output to
919*61c4878aSAndroid Build Coastguard Workerhave a call for the specified method and then responses to it. It supports
920*61c4878aSAndroid Build Coastguard Workertimeout for the waiting part (default timeout is 100ms).
921*61c4878aSAndroid Build Coastguard Worker
922*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
923*61c4878aSAndroid Build Coastguard Worker
924*61c4878aSAndroid Build Coastguard Worker   #include "pw_rpc/test_helpers.h"
925*61c4878aSAndroid Build Coastguard Worker
926*61c4878aSAndroid Build Coastguard Worker   pw::rpc::PwpbClientTestContext client_context;
927*61c4878aSAndroid Build Coastguard Worker   other::pw_rpc::pwpb::OtherService::Client other_service_client(
928*61c4878aSAndroid Build Coastguard Worker       client_context.client(), client_context.channel().id());
929*61c4878aSAndroid Build Coastguard Worker
930*61c4878aSAndroid Build Coastguard Worker   PW_PWPB_TEST_METHOD_CONTEXT(MyService, GetData)
931*61c4878aSAndroid Build Coastguard Worker   context(other_service_client);
932*61c4878aSAndroid Build Coastguard Worker   context.call({});
933*61c4878aSAndroid Build Coastguard Worker
934*61c4878aSAndroid Build Coastguard Worker   PW_TEST_ASSERT_OK(pw::rpc::test::SendResponseIfCalled<
935*61c4878aSAndroid Build Coastguard Worker             other::pw_rpc::pwpb::OtherService::GetPart>(
936*61c4878aSAndroid Build Coastguard Worker       client_context, {.value = 42}));
937*61c4878aSAndroid Build Coastguard Worker
938*61c4878aSAndroid Build Coastguard Worker   // At this point MyService::GetData handler received the GetPartResponse.
939*61c4878aSAndroid Build Coastguard Worker
940*61c4878aSAndroid Build Coastguard WorkerIntegration testing with ``pw_rpc``
941*61c4878aSAndroid Build Coastguard Worker===================================
942*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` provides utilities to simplify writing integration tests for systems
943*61c4878aSAndroid Build Coastguard Workerthat communicate with ``pw_rpc``. The integration test utitilies set up a socket
944*61c4878aSAndroid Build Coastguard Workerto use for IPC between an RPC server and client process.
945*61c4878aSAndroid Build Coastguard Worker
946*61c4878aSAndroid Build Coastguard WorkerThe server binary uses the system RPC server facade defined
947*61c4878aSAndroid Build Coastguard Worker``pw_rpc_system_server/rpc_server.h``. The client binary uses the functions
948*61c4878aSAndroid Build Coastguard Workerdefined in ``pw_rpc/integration_testing.h``:
949*61c4878aSAndroid Build Coastguard Worker
950*61c4878aSAndroid Build Coastguard Worker.. cpp:var:: constexpr uint32_t kChannelId
951*61c4878aSAndroid Build Coastguard Worker
952*61c4878aSAndroid Build Coastguard Worker   The RPC channel for integration test RPCs.
953*61c4878aSAndroid Build Coastguard Worker
954*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: pw::rpc::Client& pw::rpc::integration_test::Client()
955*61c4878aSAndroid Build Coastguard Worker
956*61c4878aSAndroid Build Coastguard Worker   Returns the global RPC client for integration test use.
957*61c4878aSAndroid Build Coastguard Worker
958*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: pw::Status pw::rpc::integration_test::InitializeClient(int argc, char* argv[], const char* usage_args = "PORT")
959*61c4878aSAndroid Build Coastguard Worker
960*61c4878aSAndroid Build Coastguard Worker   Initializes logging and the global RPC client for integration testing. Starts
961*61c4878aSAndroid Build Coastguard Worker   a background thread that processes incoming.
962*61c4878aSAndroid Build Coastguard Worker
963*61c4878aSAndroid Build Coastguard Worker---------------------
964*61c4878aSAndroid Build Coastguard WorkerConfiguration options
965*61c4878aSAndroid Build Coastguard Worker---------------------
966*61c4878aSAndroid Build Coastguard WorkerThe following configurations can be adjusted via compile-time configuration of
967*61c4878aSAndroid Build Coastguard Workerthis module, see the
968*61c4878aSAndroid Build Coastguard Worker:ref:`module documentation <module-structure-compile-time-configuration>` for
969*61c4878aSAndroid Build Coastguard Workermore details.
970*61c4878aSAndroid Build Coastguard Worker
971*61c4878aSAndroid Build Coastguard Worker.. doxygenfile:: pw_rpc/public/pw_rpc/internal/config.h
972*61c4878aSAndroid Build Coastguard Worker   :sections: define
973*61c4878aSAndroid Build Coastguard Worker
974*61c4878aSAndroid Build Coastguard Worker------------------------------
975*61c4878aSAndroid Build Coastguard WorkerSharing server and client code
976*61c4878aSAndroid Build Coastguard Worker------------------------------
977*61c4878aSAndroid Build Coastguard WorkerStreaming RPCs support writing multiple requests or responses. To facilitate
978*61c4878aSAndroid Build Coastguard Workersharing code between servers and clients, ``pw_rpc`` provides the
979*61c4878aSAndroid Build Coastguard Worker``pw::rpc::Writer`` interface. On the client side, a client or bidirectional
980*61c4878aSAndroid Build Coastguard Workerstreaming RPC call object (``ClientWriter`` or ``ClientReaderWriter``) can be
981*61c4878aSAndroid Build Coastguard Workerused as a ``pw::rpc::Writer&``. On the server side, a server or bidirectional
982*61c4878aSAndroid Build Coastguard Workerstreaming RPC call object (``ServerWriter`` or ``ServerReaderWriter``) can be
983*61c4878aSAndroid Build Coastguard Workerused as a ``pw::rpc::Writer&``. Call ``as_writer()`` to get a ``Writer&`` of the
984*61c4878aSAndroid Build Coastguard Workerclient or server call object.
985*61c4878aSAndroid Build Coastguard Worker
986*61c4878aSAndroid Build Coastguard Worker----------------------------
987*61c4878aSAndroid Build Coastguard WorkerEncoding and sending packets
988*61c4878aSAndroid Build Coastguard Worker----------------------------
989*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` has to manage interactions among multiple RPC clients, servers,
990*61c4878aSAndroid Build Coastguard Workerclient calls, and server calls. To safely synchronize these interactions with
991*61c4878aSAndroid Build Coastguard Workerminimal overhead, ``pw_rpc`` uses a single, global mutex (when
992*61c4878aSAndroid Build Coastguard Worker``PW_RPC_USE_GLOBAL_MUTEX`` is enabled).
993*61c4878aSAndroid Build Coastguard Worker
994*61c4878aSAndroid Build Coastguard WorkerBecause ``pw_rpc`` uses a global mutex, it also uses a global buffer to encode
995*61c4878aSAndroid Build Coastguard Workeroutgoing packets. The size of the buffer is set with
996*61c4878aSAndroid Build Coastguard Worker``PW_RPC_ENCODING_BUFFER_SIZE_BYTES``, which defaults to 512 B. If dynamic
997*61c4878aSAndroid Build Coastguard Workerallocation is enabled, this size does not affect how large RPC messages can be,
998*61c4878aSAndroid Build Coastguard Workerbut it is still used for sizing buffers in test utilities.
999*61c4878aSAndroid Build Coastguard Worker
1000*61c4878aSAndroid Build Coastguard WorkerUsers of ``pw_rpc`` must implement the :cpp:class:`pw::rpc::ChannelOutput`
1001*61c4878aSAndroid Build Coastguard Workerinterface.
1002*61c4878aSAndroid Build Coastguard Worker
1003*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-ChannelOutput:
1004*61c4878aSAndroid Build Coastguard Worker.. cpp:class:: pw::rpc::ChannelOutput
1005*61c4878aSAndroid Build Coastguard Worker
1006*61c4878aSAndroid Build Coastguard Worker   ``pw_rpc`` endpoints use :cpp:class:`ChannelOutput` instances to send
1007*61c4878aSAndroid Build Coastguard Worker   packets.  Systems that integrate pw_rpc must use one or more
1008*61c4878aSAndroid Build Coastguard Worker   :cpp:class:`ChannelOutput` instances.
1009*61c4878aSAndroid Build Coastguard Worker
1010*61c4878aSAndroid Build Coastguard Worker   .. cpp:member:: static constexpr size_t kUnlimited = std::numeric_limits<size_t>::max()
1011*61c4878aSAndroid Build Coastguard Worker
1012*61c4878aSAndroid Build Coastguard Worker      Value returned from :cpp:func:`MaximumTransmissionUnit` to indicate an
1013*61c4878aSAndroid Build Coastguard Worker      unlimited MTU.
1014*61c4878aSAndroid Build Coastguard Worker
1015*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: virtual size_t MaximumTransmissionUnit()
1016*61c4878aSAndroid Build Coastguard Worker
1017*61c4878aSAndroid Build Coastguard Worker      Returns the size of the largest packet the :cpp:class:`ChannelOutput` can
1018*61c4878aSAndroid Build Coastguard Worker      send. :cpp:class:`ChannelOutput` implementations should only override this
1019*61c4878aSAndroid Build Coastguard Worker      function if they impose a limit on the MTU. The default implementation
1020*61c4878aSAndroid Build Coastguard Worker      returns :cpp:member:`kUnlimited`, which indicates that there is no MTU
1021*61c4878aSAndroid Build Coastguard Worker      limit.
1022*61c4878aSAndroid Build Coastguard Worker
1023*61c4878aSAndroid Build Coastguard Worker   .. cpp:function:: virtual pw::Status Send(span<std::byte> packet)
1024*61c4878aSAndroid Build Coastguard Worker
1025*61c4878aSAndroid Build Coastguard Worker      Sends an encoded RPC packet. Returns OK if further packets may be sent,
1026*61c4878aSAndroid Build Coastguard Worker      even if the current packet could not be sent. Returns any other status if
1027*61c4878aSAndroid Build Coastguard Worker      the Channel is no longer able to send packets.
1028*61c4878aSAndroid Build Coastguard Worker
1029*61c4878aSAndroid Build Coastguard Worker      The RPC system's internal lock is held while this function is
1030*61c4878aSAndroid Build Coastguard Worker      called. Avoid long-running operations, since these will delay any other
1031*61c4878aSAndroid Build Coastguard Worker      users of the RPC system.
1032*61c4878aSAndroid Build Coastguard Worker
1033*61c4878aSAndroid Build Coastguard Worker      .. danger::
1034*61c4878aSAndroid Build Coastguard Worker
1035*61c4878aSAndroid Build Coastguard Worker         No ``pw_rpc`` APIs may be accessed in this function! Implementations
1036*61c4878aSAndroid Build Coastguard Worker         MUST NOT access any RPC endpoints (:cpp:class:`pw::rpc::Client`,
1037*61c4878aSAndroid Build Coastguard Worker         :cpp:class:`pw::rpc::Server`) or call objects
1038*61c4878aSAndroid Build Coastguard Worker         (:cpp:class:`pw::rpc::ServerReaderWriter`
1039*61c4878aSAndroid Build Coastguard Worker         :cpp:class:`pw::rpc::ClientReaderWriter`, etc.) inside the
1040*61c4878aSAndroid Build Coastguard Worker         :cpp:func:`Send` function or any descendent calls. Doing so will result
1041*61c4878aSAndroid Build Coastguard Worker         in deadlock! RPC APIs may be used by other threads, just not within
1042*61c4878aSAndroid Build Coastguard Worker         :cpp:func:`Send`.
1043*61c4878aSAndroid Build Coastguard Worker
1044*61c4878aSAndroid Build Coastguard Worker         The buffer provided in ``packet`` must NOT be accessed outside of this
1045*61c4878aSAndroid Build Coastguard Worker         function. It must be sent immediately or copied elsewhere before the
1046*61c4878aSAndroid Build Coastguard Worker         function returns.
1047