1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker================ 4*61c4878aSAndroid Build Coastguard WorkerDesign & roadmap 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 Worker.. _module-pw_rpc-design-overview: 10*61c4878aSAndroid Build Coastguard Worker 11*61c4878aSAndroid Build Coastguard Worker-------- 12*61c4878aSAndroid Build Coastguard WorkerOverview 13*61c4878aSAndroid Build Coastguard Worker-------- 14*61c4878aSAndroid Build Coastguard WorkerThe semantics of ``pw_rpc`` are similar to `gRPC 15*61c4878aSAndroid Build Coastguard Worker<https://grpc.io/docs/what-is-grpc/core-concepts/>`_. 16*61c4878aSAndroid Build Coastguard Worker 17*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-lifecycle: 18*61c4878aSAndroid Build Coastguard Worker 19*61c4878aSAndroid Build Coastguard WorkerRPC call lifecycle 20*61c4878aSAndroid Build Coastguard Worker================== 21*61c4878aSAndroid Build Coastguard WorkerIn ``pw_rpc``, an RPC begins when the client sends an initial packet. The server 22*61c4878aSAndroid Build Coastguard Workerreceives the packet, looks up the relevant service method, then calls into the 23*61c4878aSAndroid Build Coastguard WorkerRPC function. The RPC is considered active until the server sends a status to 24*61c4878aSAndroid Build Coastguard Workerfinish the RPC. The client may terminate an ongoing RPC by cancelling it. 25*61c4878aSAndroid Build Coastguard WorkerMultiple concurrent RPC requests to the same method may be made simultaneously 26*61c4878aSAndroid Build Coastguard Worker(Note: Concurrent requests are not yet possible using the Java client. See 27*61c4878aSAndroid Build Coastguard Worker`Issue 237418397 <https://issues.pigweed.dev/issues/237418397>`_). 28*61c4878aSAndroid Build Coastguard Worker 29*61c4878aSAndroid Build Coastguard WorkerDepending the type of RPC, the client and server exchange zero or more protobuf 30*61c4878aSAndroid Build Coastguard Workerrequest or response payloads. There are four RPC types: 31*61c4878aSAndroid Build Coastguard Worker 32*61c4878aSAndroid Build Coastguard Worker* **Unary**. The client sends one request and the server sends one 33*61c4878aSAndroid Build Coastguard Worker response with a status. 34*61c4878aSAndroid Build Coastguard Worker* **Server streaming**. The client sends one request and the server sends zero 35*61c4878aSAndroid Build Coastguard Worker or more responses followed by a status. 36*61c4878aSAndroid Build Coastguard Worker* **Client streaming**. The client sends zero or more requests and the server 37*61c4878aSAndroid Build Coastguard Worker sends one response with a status. 38*61c4878aSAndroid Build Coastguard Worker* **Bidirectional streaming**. The client sends zero or more requests and the 39*61c4878aSAndroid Build Coastguard Worker server sends zero or more responses followed by a status. 40*61c4878aSAndroid Build Coastguard Worker 41*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-events: 42*61c4878aSAndroid Build Coastguard Worker 43*61c4878aSAndroid Build Coastguard WorkerEvents 44*61c4878aSAndroid Build Coastguard Worker------ 45*61c4878aSAndroid Build Coastguard WorkerThe key events in the RPC lifecycle are: 46*61c4878aSAndroid Build Coastguard Worker 47*61c4878aSAndroid Build Coastguard Worker* **Start**. The client initiates the RPC. The server's RPC body executes. 48*61c4878aSAndroid Build Coastguard Worker* **Finish**. The server sends a status and completes the RPC. The client calls 49*61c4878aSAndroid Build Coastguard Worker a callback. 50*61c4878aSAndroid Build Coastguard Worker* **Request**. The client sends a request protobuf. The server calls a callback 51*61c4878aSAndroid Build Coastguard Worker when it receives it. In unary and server streaming RPCs, there is only one 52*61c4878aSAndroid Build Coastguard Worker request and it is handled when the RPC starts. 53*61c4878aSAndroid Build Coastguard Worker* **Response**. The server sends a response protobuf. The client calls a 54*61c4878aSAndroid Build Coastguard Worker callback when it receives it. In unary and client streaming RPCs, there is 55*61c4878aSAndroid Build Coastguard Worker only one response and it is handled when the RPC completes. 56*61c4878aSAndroid Build Coastguard Worker* **Error**. The server or client terminates the RPC abnormally with a status. 57*61c4878aSAndroid Build Coastguard Worker The receiving endpoint calls a callback. 58*61c4878aSAndroid Build Coastguard Worker* **Request Completion**. The client sends a message that it would like to 59*61c4878aSAndroid Build Coastguard Worker request call completion. The server calls a callback when it receives it. Some 60*61c4878aSAndroid Build Coastguard Worker servers may ignore the request completion message. In client and bidirectional 61*61c4878aSAndroid Build Coastguard Worker streaming RPCs, this also indicates that client has finished sending requests. 62*61c4878aSAndroid Build Coastguard Worker 63*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-services: 64*61c4878aSAndroid Build Coastguard Worker 65*61c4878aSAndroid Build Coastguard WorkerServices 66*61c4878aSAndroid Build Coastguard Worker======== 67*61c4878aSAndroid Build Coastguard WorkerA service is a logical grouping of RPCs defined within a ``.proto`` file. ``pw_rpc`` 68*61c4878aSAndroid Build Coastguard Workeruses these ``.proto`` definitions to generate code for a base service, from which 69*61c4878aSAndroid Build Coastguard Workeruser-defined RPCs are implemented. 70*61c4878aSAndroid Build Coastguard Worker 71*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` supports multiple protobuf libraries, and the generated code API 72*61c4878aSAndroid Build Coastguard Workerdepends on which is used. 73*61c4878aSAndroid Build Coastguard Worker 74*61c4878aSAndroid Build Coastguard WorkerServices must be registered with a server in order to call their methods. 75*61c4878aSAndroid Build Coastguard WorkerServices may later be unregistered, which cancels calls for methods in that 76*61c4878aSAndroid Build Coastguard Workerservice and prevents future calls to them, until the service is re-registered. 77*61c4878aSAndroid Build Coastguard Worker 78*61c4878aSAndroid Build Coastguard WorkerBackground: 79*61c4878aSAndroid Build Coastguard Worker 80*61c4878aSAndroid Build Coastguard Worker* `Protocol Buffer service 81*61c4878aSAndroid Build Coastguard Worker <https://developers.google.com/protocol-buffers/docs/proto3#services>`_ 82*61c4878aSAndroid Build Coastguard Worker* `gRPC service definition 83*61c4878aSAndroid Build Coastguard Worker <https://grpc.io/docs/what-is-grpc/core-concepts/#service-definition>`_ 84*61c4878aSAndroid Build Coastguard Worker 85*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-status-codes: 86*61c4878aSAndroid Build Coastguard Worker 87*61c4878aSAndroid Build Coastguard WorkerStatus codes 88*61c4878aSAndroid Build Coastguard Worker============ 89*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` call objects (``ClientReaderWriter``, ``ServerReaderWriter``, etc.) 90*61c4878aSAndroid Build Coastguard Workeruse certain status codes to indicate what occurred. These codes are returned 91*61c4878aSAndroid Build Coastguard Workerfrom functions like ``Write()`` or ``Finish()``. 92*61c4878aSAndroid Build Coastguard Worker 93*61c4878aSAndroid Build Coastguard Worker* ``OK`` -- The operation succeeded. 94*61c4878aSAndroid Build Coastguard Worker* ``UNAVAILABLE`` -- The channel is not currently registered with the server or 95*61c4878aSAndroid Build Coastguard Worker client. 96*61c4878aSAndroid Build Coastguard Worker* ``UNKNOWN`` -- Sending a packet failed due to an unrecoverable 97*61c4878aSAndroid Build Coastguard Worker :cpp:func:`pw::rpc::ChannelOutput::Send` error. 98*61c4878aSAndroid Build Coastguard Worker 99*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-unrequested-responses: 100*61c4878aSAndroid Build Coastguard Worker 101*61c4878aSAndroid Build Coastguard WorkerUnrequested responses 102*61c4878aSAndroid Build Coastguard Worker===================== 103*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` supports sending responses to RPCs that have not yet been invoked by 104*61c4878aSAndroid Build Coastguard Workera client. This is useful in testing and in situations like an RPC that triggers 105*61c4878aSAndroid Build Coastguard Workerreboot. After the reboot, the device opens the writer object and sends its 106*61c4878aSAndroid Build Coastguard Workerresponse to the client. 107*61c4878aSAndroid Build Coastguard Worker 108*61c4878aSAndroid Build Coastguard WorkerThe C++ API for opening a server reader/writer takes the generated RPC function 109*61c4878aSAndroid Build Coastguard Workeras a template parameter. The server to use, channel ID, and service instance are 110*61c4878aSAndroid Build Coastguard Workerpassed as arguments. The API is the same for all RPC types, except the 111*61c4878aSAndroid Build Coastguard Workerappropriate reader/writer class must be used. 112*61c4878aSAndroid Build Coastguard Worker 113*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++ 114*61c4878aSAndroid Build Coastguard Worker 115*61c4878aSAndroid Build Coastguard Worker // Open a ServerWriter for a server streaming RPC. 116*61c4878aSAndroid Build Coastguard Worker auto writer = RawServerWriter::Open<pw_rpc::raw::ServiceName::MethodName>( 117*61c4878aSAndroid Build Coastguard Worker server, channel_id, service_instance); 118*61c4878aSAndroid Build Coastguard Worker 119*61c4878aSAndroid Build Coastguard Worker // Send some responses, even though the client has not yet called this RPC. 120*61c4878aSAndroid Build Coastguard Worker CHECK_OK(writer.Write(encoded_response_1)); 121*61c4878aSAndroid Build Coastguard Worker CHECK_OK(writer.Write(encoded_response_2)); 122*61c4878aSAndroid Build Coastguard Worker 123*61c4878aSAndroid Build Coastguard Worker // Finish the RPC. 124*61c4878aSAndroid Build Coastguard Worker CHECK_OK(writer.Finish(OkStatus())); 125*61c4878aSAndroid Build Coastguard Worker 126*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-errata: 127*61c4878aSAndroid Build Coastguard Worker 128*61c4878aSAndroid Build Coastguard WorkerErrata 129*61c4878aSAndroid Build Coastguard Worker------ 130*61c4878aSAndroid Build Coastguard WorkerPrior to support for concurrent requests to a single method, no identifier was 131*61c4878aSAndroid Build Coastguard Workerpresent to distinguish different calls to the same method. When a "call ID" 132*61c4878aSAndroid Build Coastguard Workerfeature was first introduced to solve this issue, existing clients and servers 133*61c4878aSAndroid Build Coastguard Worker(1) set this value to zero and (2) ignored this value. 134*61c4878aSAndroid Build Coastguard Worker 135*61c4878aSAndroid Build Coastguard WorkerWhen initial support for concurrent methods was added, a separate "open call ID" 136*61c4878aSAndroid Build Coastguard Workerwas introduced to distinguish unrequested responses. However, legacy servers 137*61c4878aSAndroid Build Coastguard Workerbuilt prior to this change continue to send unrequested responses with call ID 138*61c4878aSAndroid Build Coastguard Workerzero. Prior to `this fix 139*61c4878aSAndroid Build Coastguard Worker<https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/192311>`_, clients 140*61c4878aSAndroid Build Coastguard Workerwhich used "open call ID" would not accept unrequested responses from legacy 141*61c4878aSAndroid Build Coastguard Workerservers. Clients built after that change will accept unrequested responses which 142*61c4878aSAndroid Build Coastguard Workeruse both "open call ID" and call ID zero. 143*61c4878aSAndroid Build Coastguard Worker 144*61c4878aSAndroid Build Coastguard WorkerSee `Issue 237418397 <https://issues.pigweed.dev/issues/237418397>`_ for more 145*61c4878aSAndroid Build Coastguard Workerdetails and discussion. 146*61c4878aSAndroid Build Coastguard Worker 147*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-naming: 148*61c4878aSAndroid Build Coastguard Worker 149*61c4878aSAndroid Build Coastguard Worker------ 150*61c4878aSAndroid Build Coastguard WorkerNaming 151*61c4878aSAndroid Build Coastguard Worker------ 152*61c4878aSAndroid Build Coastguard Worker 153*61c4878aSAndroid Build Coastguard WorkerFor upstream Pigweed services, this naming style is a requirement. Note that 154*61c4878aSAndroid Build Coastguard Workersome services created before this was established may use non-compliant 155*61c4878aSAndroid Build Coastguard Workernames. For Pigweed users, this naming style is a suggestion. 156*61c4878aSAndroid Build Coastguard Worker 157*61c4878aSAndroid Build Coastguard WorkerReserved names 158*61c4878aSAndroid Build Coastguard Worker============== 159*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` reserves a few service method names so they can be used for generated 160*61c4878aSAndroid Build Coastguard Workerclasses. The following names cannot be used for service methods: 161*61c4878aSAndroid Build Coastguard Worker 162*61c4878aSAndroid Build Coastguard Worker- ``Client`` 163*61c4878aSAndroid Build Coastguard Worker- ``Service`` 164*61c4878aSAndroid Build Coastguard Worker- Any reserved words in the languages ``pw_rpc`` supports (e.g. ``class``). 165*61c4878aSAndroid Build Coastguard Worker 166*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` does not reserve any service names, but the restriction of avoiding 167*61c4878aSAndroid Build Coastguard Workerreserved words in supported languages applies. 168*61c4878aSAndroid Build Coastguard Worker 169*61c4878aSAndroid Build Coastguard WorkerService naming style 170*61c4878aSAndroid Build Coastguard Worker==================== 171*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` service names should use capitalized camel case and should not use 172*61c4878aSAndroid Build Coastguard Workerthe term "Service". Appending "Service" to a service name is redundant, similar 173*61c4878aSAndroid Build Coastguard Workerto appending "Class" or "Function" to a class or function name. The 174*61c4878aSAndroid Build Coastguard WorkerC++ implementation class may use "Service" in its name, however. 175*61c4878aSAndroid Build Coastguard Worker 176*61c4878aSAndroid Build Coastguard WorkerFor example, a service for accessing a file system should simply be named 177*61c4878aSAndroid Build Coastguard Worker``service FileSystem``, rather than ``service FileSystemService``, in the 178*61c4878aSAndroid Build Coastguard Worker``.proto`` file. 179*61c4878aSAndroid Build Coastguard Worker 180*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf 181*61c4878aSAndroid Build Coastguard Worker 182*61c4878aSAndroid Build Coastguard Worker // file.proto 183*61c4878aSAndroid Build Coastguard Worker package pw.file; 184*61c4878aSAndroid Build Coastguard Worker 185*61c4878aSAndroid Build Coastguard Worker service FileSystem { 186*61c4878aSAndroid Build Coastguard Worker rpc List(ListRequest) returns (stream ListResponse); 187*61c4878aSAndroid Build Coastguard Worker } 188*61c4878aSAndroid Build Coastguard Worker 189*61c4878aSAndroid Build Coastguard WorkerThe C++ service implementation class may append "Service" to the name. 190*61c4878aSAndroid Build Coastguard Worker 191*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 192*61c4878aSAndroid Build Coastguard Worker 193*61c4878aSAndroid Build Coastguard Worker // file_system_service.h 194*61c4878aSAndroid Build Coastguard Worker #include "pw_file/file.raw_rpc.pb.h" 195*61c4878aSAndroid Build Coastguard Worker 196*61c4878aSAndroid Build Coastguard Worker namespace pw::file { 197*61c4878aSAndroid Build Coastguard Worker 198*61c4878aSAndroid Build Coastguard Worker class FileSystemService : public pw_rpc::raw::FileSystem::Service<FileSystemService> { 199*61c4878aSAndroid Build Coastguard Worker void List(ConstByteSpan request, RawServerWriter& writer); 200*61c4878aSAndroid Build Coastguard Worker }; 201*61c4878aSAndroid Build Coastguard Worker 202*61c4878aSAndroid Build Coastguard Worker } // namespace pw::file 203*61c4878aSAndroid Build Coastguard Worker 204*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-roadmap: 205*61c4878aSAndroid Build Coastguard Worker 206*61c4878aSAndroid Build Coastguard Worker------- 207*61c4878aSAndroid Build Coastguard WorkerRoadmap 208*61c4878aSAndroid Build Coastguard Worker------- 209*61c4878aSAndroid Build Coastguard WorkerConcurrent requests were not initially supported in pw_rpc (added in `C++ 210*61c4878aSAndroid Build Coastguard Worker<https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/109077>`_, `Python 211*61c4878aSAndroid Build Coastguard Worker<https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/139610>`_, and 212*61c4878aSAndroid Build Coastguard Worker`TypeScript 213*61c4878aSAndroid Build Coastguard Worker<https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/160792>`_). As a 214*61c4878aSAndroid Build Coastguard Workerresult, some user-written service implementations may not expect or correctly 215*61c4878aSAndroid Build Coastguard Workersupport concurrent requests. 216