xref: /aosp_15_r20/external/pigweed/pw_rpc/pwpb/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc_pw_protobuf:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker-----------
4*61c4878aSAndroid Build Coastguard Workerpw_protobuf
5*61c4878aSAndroid Build Coastguard Worker-----------
6*61c4878aSAndroid Build Coastguard Worker.. caution::
7*61c4878aSAndroid Build Coastguard Worker
8*61c4878aSAndroid Build Coastguard Worker   If you're starting a new project, Pigweed recommends Nanopb over
9*61c4878aSAndroid Build Coastguard Worker   ``pw_protobuf``. See :ref:`module-pw_rpc-guides-headers`.
10*61c4878aSAndroid Build Coastguard Worker
11*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` can generate services which encode/decode RPC requests and responses
12*61c4878aSAndroid Build Coastguard Workeras ``pw_protobuf`` message structs.
13*61c4878aSAndroid Build Coastguard Worker
14*61c4878aSAndroid Build Coastguard WorkerUsage
15*61c4878aSAndroid Build Coastguard Worker=====
16*61c4878aSAndroid Build Coastguard WorkerDefine a ``pw_proto_library`` containing the .proto file defining your service
17*61c4878aSAndroid Build Coastguard Worker(and optionally other related protos), then depend on the ``pwpb_rpc``
18*61c4878aSAndroid Build Coastguard Workerversion of that library in the code implementing the service.
19*61c4878aSAndroid Build Coastguard Worker
20*61c4878aSAndroid Build Coastguard Worker.. code-block::
21*61c4878aSAndroid Build Coastguard Worker
22*61c4878aSAndroid Build Coastguard Worker   # chat/BUILD.gn
23*61c4878aSAndroid Build Coastguard Worker
24*61c4878aSAndroid Build Coastguard Worker   import("$dir_pw_build/target_types.gni")
25*61c4878aSAndroid Build Coastguard Worker   import("$dir_pw_protobuf_compiler/proto.gni")
26*61c4878aSAndroid Build Coastguard Worker
27*61c4878aSAndroid Build Coastguard Worker   pw_proto_library("chat_protos") {
28*61c4878aSAndroid Build Coastguard Worker     sources = [ "chat_protos/chat_service.proto" ]
29*61c4878aSAndroid Build Coastguard Worker   }
30*61c4878aSAndroid Build Coastguard Worker
31*61c4878aSAndroid Build Coastguard Worker   # Library that implements the Chat service.
32*61c4878aSAndroid Build Coastguard Worker   pw_source_set("chat_service") {
33*61c4878aSAndroid Build Coastguard Worker     sources = [
34*61c4878aSAndroid Build Coastguard Worker       "chat_service.cc",
35*61c4878aSAndroid Build Coastguard Worker       "chat_service.h",
36*61c4878aSAndroid Build Coastguard Worker     ]
37*61c4878aSAndroid Build Coastguard Worker     public_deps = [ ":chat_protos.pwpb_rpc" ]
38*61c4878aSAndroid Build Coastguard Worker   }
39*61c4878aSAndroid Build Coastguard Worker
40*61c4878aSAndroid Build Coastguard WorkerA C++ header file is generated for each input .proto file, with the ``.proto``
41*61c4878aSAndroid Build Coastguard Workerextension replaced by ``.rpc.pwpb.h``. For example, given the input file
42*61c4878aSAndroid Build Coastguard Worker``chat_protos/chat_service.proto``, the generated header file will be placed
43*61c4878aSAndroid Build Coastguard Workerat the include path ``"chat_protos/chat_service.rpc.pwpb.h"``.
44*61c4878aSAndroid Build Coastguard Worker
45*61c4878aSAndroid Build Coastguard WorkerGenerated code API
46*61c4878aSAndroid Build Coastguard Worker==================
47*61c4878aSAndroid Build Coastguard WorkerAll examples in this document use the following RPC service definition.
48*61c4878aSAndroid Build Coastguard Worker
49*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
50*61c4878aSAndroid Build Coastguard Worker
51*61c4878aSAndroid Build Coastguard Worker   // chat/chat_protos/chat_service.proto
52*61c4878aSAndroid Build Coastguard Worker
53*61c4878aSAndroid Build Coastguard Worker   syntax = "proto3";
54*61c4878aSAndroid Build Coastguard Worker
55*61c4878aSAndroid Build Coastguard Worker   service Chat {
56*61c4878aSAndroid Build Coastguard Worker     // Returns information about a chatroom.
57*61c4878aSAndroid Build Coastguard Worker     rpc GetRoomInformation(RoomInfoRequest) returns (RoomInfoResponse) {}
58*61c4878aSAndroid Build Coastguard Worker
59*61c4878aSAndroid Build Coastguard Worker     // Lists all of the users in a chatroom. The response is streamed as there
60*61c4878aSAndroid Build Coastguard Worker     // may be a large amount of users.
61*61c4878aSAndroid Build Coastguard Worker     rpc ListUsersInRoom(ListUsersRequest) returns (stream ListUsersResponse) {}
62*61c4878aSAndroid Build Coastguard Worker
63*61c4878aSAndroid Build Coastguard Worker     // Uploads a file, in chunks, to a chatroom.
64*61c4878aSAndroid Build Coastguard Worker     rpc UploadFile(stream UploadFileRequest) returns (UploadFileResponse) {}
65*61c4878aSAndroid Build Coastguard Worker
66*61c4878aSAndroid Build Coastguard Worker     // Sends messages to a chatroom while receiving messages from other users.
67*61c4878aSAndroid Build Coastguard Worker     rpc Chat(stream ChatMessage) returns (stream ChatMessage) {}
68*61c4878aSAndroid Build Coastguard Worker   }
69*61c4878aSAndroid Build Coastguard Worker
70*61c4878aSAndroid Build Coastguard WorkerServer-side
71*61c4878aSAndroid Build Coastguard Worker-----------
72*61c4878aSAndroid Build Coastguard WorkerA C++ class is generated for each service in the .proto file. The class is
73*61c4878aSAndroid Build Coastguard Workerlocated within a special ``pw_rpc::pwpb`` sub-namespace of the file's package.
74*61c4878aSAndroid Build Coastguard Worker
75*61c4878aSAndroid Build Coastguard WorkerThe generated class is a base class which must be derived to implement the
76*61c4878aSAndroid Build Coastguard Workerservice's methods. The base class is templated on the derived class.
77*61c4878aSAndroid Build Coastguard Worker
78*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
79*61c4878aSAndroid Build Coastguard Worker
80*61c4878aSAndroid Build Coastguard Worker   #include "chat_protos/chat_service.rpc.pwpb.h"
81*61c4878aSAndroid Build Coastguard Worker
82*61c4878aSAndroid Build Coastguard Worker   class ChatService final : public pw_rpc::pwpb::Chat::Service<ChatService> {
83*61c4878aSAndroid Build Coastguard Worker    public:
84*61c4878aSAndroid Build Coastguard Worker     // Implementations of the service's RPC methods; see below.
85*61c4878aSAndroid Build Coastguard Worker   };
86*61c4878aSAndroid Build Coastguard Worker
87*61c4878aSAndroid Build Coastguard WorkerUnary RPC
88*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^
89*61c4878aSAndroid Build Coastguard WorkerA unary RPC is implemented as a function which takes in the RPC's request struct
90*61c4878aSAndroid Build Coastguard Workerand populates a response struct to send back, with a status indicating whether
91*61c4878aSAndroid Build Coastguard Workerthe request succeeded.
92*61c4878aSAndroid Build Coastguard Worker
93*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
94*61c4878aSAndroid Build Coastguard Worker
95*61c4878aSAndroid Build Coastguard Worker   pw::Status GetRoomInformation(const RoomInfoRequest::Message& request,
96*61c4878aSAndroid Build Coastguard Worker                                 RoomInfoResponse::Message& response);
97*61c4878aSAndroid Build Coastguard Worker
98*61c4878aSAndroid Build Coastguard WorkerServer streaming RPC
99*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^
100*61c4878aSAndroid Build Coastguard WorkerA server streaming RPC receives the client's request message alongside a
101*61c4878aSAndroid Build Coastguard Worker``ServerWriter``, used to stream back responses.
102*61c4878aSAndroid Build Coastguard Worker
103*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
104*61c4878aSAndroid Build Coastguard Worker
105*61c4878aSAndroid Build Coastguard Worker   void ListUsersInRoom(const ListUsersRequest::Message& request,
106*61c4878aSAndroid Build Coastguard Worker                        pw::rpc::ServerWriter<ListUsersResponse::Message>& writer);
107*61c4878aSAndroid Build Coastguard Worker
108*61c4878aSAndroid Build Coastguard WorkerThe ``ServerWriter`` object is movable, and remains active until it is manually
109*61c4878aSAndroid Build Coastguard Workerclosed or goes out of scope. The writer has a simple API to return responses:
110*61c4878aSAndroid Build Coastguard Worker
111*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status PwpbServerWriter::Write(const T::Message& response)
112*61c4878aSAndroid Build Coastguard Worker
113*61c4878aSAndroid Build Coastguard Worker  Writes a single response message to the stream. The returned status indicates
114*61c4878aSAndroid Build Coastguard Worker  whether the write was successful.
115*61c4878aSAndroid Build Coastguard Worker
116*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: void PwpbServerWriter::Finish(Status status = OkStatus())
117*61c4878aSAndroid Build Coastguard Worker
118*61c4878aSAndroid Build Coastguard Worker  Closes the stream and sends back the RPC's overall status to the client.
119*61c4878aSAndroid Build Coastguard Worker
120*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status PwpbServerWriter::TryFinish(Status status = OkStatus())
121*61c4878aSAndroid Build Coastguard Worker
122*61c4878aSAndroid Build Coastguard Worker  Closes the stream and sends back the RPC's overall status to the client only
123*61c4878aSAndroid Build Coastguard Worker  if the final packet is successfully sent.
124*61c4878aSAndroid Build Coastguard Worker
125*61c4878aSAndroid Build Coastguard WorkerOnce a ``ServerWriter`` has been closed, all future ``Write`` calls will fail.
126*61c4878aSAndroid Build Coastguard Worker
127*61c4878aSAndroid Build Coastguard Worker.. attention::
128*61c4878aSAndroid Build Coastguard Worker
129*61c4878aSAndroid Build Coastguard Worker  Make sure to use ``std::move`` when passing the ``ServerWriter`` around to
130*61c4878aSAndroid Build Coastguard Worker  avoid accidentally closing it and ending the RPC.
131*61c4878aSAndroid Build Coastguard Worker
132*61c4878aSAndroid Build Coastguard WorkerClient streaming RPC
133*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^
134*61c4878aSAndroid Build Coastguard Worker.. attention:: Supported, but the documentation is still under construction.
135*61c4878aSAndroid Build Coastguard Worker
136*61c4878aSAndroid Build Coastguard WorkerBidirectional streaming RPC
137*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^^^^^^
138*61c4878aSAndroid Build Coastguard Worker.. attention:: Supported, but the documentation is still under construction.
139*61c4878aSAndroid Build Coastguard Worker
140*61c4878aSAndroid Build Coastguard Worker
141*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc_pw_protobuf-client:
142*61c4878aSAndroid Build Coastguard Worker
143*61c4878aSAndroid Build Coastguard WorkerClient-side
144*61c4878aSAndroid Build Coastguard Worker-----------
145*61c4878aSAndroid Build Coastguard WorkerA corresponding client class is generated for every service defined in the proto
146*61c4878aSAndroid Build Coastguard Workerfile. To allow multiple types of clients to exist, it is placed under the
147*61c4878aSAndroid Build Coastguard Worker``pw_rpc::pwpb`` namespace. The ``Client`` class is nested under
148*61c4878aSAndroid Build Coastguard Worker``pw_rpc::pwpb::ServiceName``. For example, the ``Chat`` service would create
149*61c4878aSAndroid Build Coastguard Worker``pw_rpc::pwpb::Chat::Client``.
150*61c4878aSAndroid Build Coastguard Worker
151*61c4878aSAndroid Build Coastguard WorkerService clients are instantiated with a reference to the RPC client through
152*61c4878aSAndroid Build Coastguard Workerwhich they will send requests, and the channel ID they will use.
153*61c4878aSAndroid Build Coastguard Worker
154*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
155*61c4878aSAndroid Build Coastguard Worker
156*61c4878aSAndroid Build Coastguard Worker   // Nested under pw_rpc::pwpb::ServiceName.
157*61c4878aSAndroid Build Coastguard Worker   class Client {
158*61c4878aSAndroid Build Coastguard Worker    public:
159*61c4878aSAndroid Build Coastguard Worker     Client(::pw::rpc::Client& client, uint32_t channel_id);
160*61c4878aSAndroid Build Coastguard Worker
161*61c4878aSAndroid Build Coastguard Worker     pw::rpc::PwpbUnaryReceiver<RoomInfoResponse::Message> GetRoomInformation(
162*61c4878aSAndroid Build Coastguard Worker         const RoomInfoRequest::Message& request,
163*61c4878aSAndroid Build Coastguard Worker         ::pw::Function<void(Status, const RoomInfoResponse::Message&)> on_response,
164*61c4878aSAndroid Build Coastguard Worker         ::pw::Function<void(Status)> on_rpc_error = nullptr);
165*61c4878aSAndroid Build Coastguard Worker
166*61c4878aSAndroid Build Coastguard Worker     // ...and more (see below).
167*61c4878aSAndroid Build Coastguard Worker   };
168*61c4878aSAndroid Build Coastguard Worker
169*61c4878aSAndroid Build Coastguard WorkerRPCs can also be invoked individually as free functions:
170*61c4878aSAndroid Build Coastguard Worker
171*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
172*61c4878aSAndroid Build Coastguard Worker
173*61c4878aSAndroid Build Coastguard Worker   pw::rpc::PwpbUnaryReceiver<RoomInfoResponse::Message> call = pw_rpc::pwpb::Chat::GetRoomInformation(
174*61c4878aSAndroid Build Coastguard Worker       client, channel_id, request, on_response, on_rpc_error);
175*61c4878aSAndroid Build Coastguard Worker
176*61c4878aSAndroid Build Coastguard WorkerThe client class has member functions for each method defined within the
177*61c4878aSAndroid Build Coastguard Workerservice's protobuf descriptor. The arguments to these methods vary depending on
178*61c4878aSAndroid Build Coastguard Workerthe type of RPC. Each method returns a client call object which stores the
179*61c4878aSAndroid Build Coastguard Workercontext of the ongoing RPC call. For more information on call objects, refer to
180*61c4878aSAndroid Build Coastguard Workerthe :ref:`core RPC docs <module-pw_rpc-making-calls>`.
181*61c4878aSAndroid Build Coastguard Worker
182*61c4878aSAndroid Build Coastguard WorkerIf dynamic allocation is enabled (:c:macro:`PW_RPC_DYNAMIC_ALLOCATION` is 1), a
183*61c4878aSAndroid Build Coastguard Worker``DynamicClient`` is generated, which dynamically allocates the call object with
184*61c4878aSAndroid Build Coastguard Worker:c:macro:`PW_RPC_MAKE_UNIQUE_PTR`. For example:
185*61c4878aSAndroid Build Coastguard Worker
186*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
187*61c4878aSAndroid Build Coastguard Worker
188*61c4878aSAndroid Build Coastguard Worker   my_namespace::pw_rpc::pwpb::ServiceName::DynamicClient dynamic_client(
189*61c4878aSAndroid Build Coastguard Worker       client, channel_id);
190*61c4878aSAndroid Build Coastguard Worker   auto call = dynamic_client.TestUnaryRpc(request, response_callback);
191*61c4878aSAndroid Build Coastguard Worker
192*61c4878aSAndroid Build Coastguard Worker   if (call->active()) {  // Access the call as a std::unique_ptr
193*61c4878aSAndroid Build Coastguard Worker     // ...
194*61c4878aSAndroid Build Coastguard Worker
195*61c4878aSAndroid Build Coastguard Worker.. admonition:: Callback invocation
196*61c4878aSAndroid Build Coastguard Worker
197*61c4878aSAndroid Build Coastguard Worker  RPC callbacks are invoked synchronously from ``Client::ProcessPacket``.
198*61c4878aSAndroid Build Coastguard Worker
199*61c4878aSAndroid Build Coastguard WorkerMethod APIs
200*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^
201*61c4878aSAndroid Build Coastguard WorkerThe arguments provided when invoking a method depend on its type.
202*61c4878aSAndroid Build Coastguard Worker
203*61c4878aSAndroid Build Coastguard WorkerUnary RPC
204*61c4878aSAndroid Build Coastguard Worker~~~~~~~~~
205*61c4878aSAndroid Build Coastguard WorkerA unary RPC call takes the request struct and a callback to invoke when a
206*61c4878aSAndroid Build Coastguard Workerresponse is received. The callback receives the RPC's status and response
207*61c4878aSAndroid Build Coastguard Workerstruct.
208*61c4878aSAndroid Build Coastguard Worker
209*61c4878aSAndroid Build Coastguard WorkerAn optional second callback can be provided to handle internal errors.
210*61c4878aSAndroid Build Coastguard Worker
211*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
212*61c4878aSAndroid Build Coastguard Worker
213*61c4878aSAndroid Build Coastguard Worker   pw::rpc::PwpbUnaryReceiver<RoomInfoResponse::Message> GetRoomInformation(
214*61c4878aSAndroid Build Coastguard Worker       const RoomInfoRequest::Message& request,
215*61c4878aSAndroid Build Coastguard Worker       ::pw::Function<void(const RoomInfoResponse::Message&, Status)> on_response,
216*61c4878aSAndroid Build Coastguard Worker       ::pw::Function<void(Status)> on_rpc_error = nullptr);
217*61c4878aSAndroid Build Coastguard Worker
218*61c4878aSAndroid Build Coastguard WorkerServer streaming RPC
219*61c4878aSAndroid Build Coastguard Worker~~~~~~~~~~~~~~~~~~~~
220*61c4878aSAndroid Build Coastguard WorkerA server streaming RPC call takes the initial request struct and two callbacks.
221*61c4878aSAndroid Build Coastguard WorkerThe first is invoked on every stream response received, and the second is
222*61c4878aSAndroid Build Coastguard Workerinvoked once the stream is complete with its overall status.
223*61c4878aSAndroid Build Coastguard Worker
224*61c4878aSAndroid Build Coastguard WorkerAn optional third callback can be provided to handle internal errors.
225*61c4878aSAndroid Build Coastguard Worker
226*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
227*61c4878aSAndroid Build Coastguard Worker
228*61c4878aSAndroid Build Coastguard Worker   pw::rpc::PwpbClientReader<ListUsersResponse::Message> ListUsersInRoom(
229*61c4878aSAndroid Build Coastguard Worker       const ListUsersRequest::Message& request,
230*61c4878aSAndroid Build Coastguard Worker       ::pw::Function<void(const ListUsersResponse::Message&)> on_response,
231*61c4878aSAndroid Build Coastguard Worker       ::pw::Function<void(Status)> on_stream_end,
232*61c4878aSAndroid Build Coastguard Worker       ::pw::Function<void(Status)> on_rpc_error = nullptr);
233*61c4878aSAndroid Build Coastguard Worker
234*61c4878aSAndroid Build Coastguard WorkerClient streaming RPC
235*61c4878aSAndroid Build Coastguard Worker~~~~~~~~~~~~~~~~~~~~
236*61c4878aSAndroid Build Coastguard Worker.. attention:: Supported, but the documentation is still under construction.
237*61c4878aSAndroid Build Coastguard Worker
238*61c4878aSAndroid Build Coastguard WorkerBidirectional streaming RPC
239*61c4878aSAndroid Build Coastguard Worker~~~~~~~~~~~~~~~~~~~~~~~~~~~
240*61c4878aSAndroid Build Coastguard Worker.. attention:: Supported, but the documentation is still under construction.
241*61c4878aSAndroid Build Coastguard Worker
242*61c4878aSAndroid Build Coastguard WorkerExample usage
243*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^
244*61c4878aSAndroid Build Coastguard WorkerThe following example demonstrates how to call an RPC method using a pw_protobuf
245*61c4878aSAndroid Build Coastguard Workerservice client and receive the response.
246*61c4878aSAndroid Build Coastguard Worker
247*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
248*61c4878aSAndroid Build Coastguard Worker
249*61c4878aSAndroid Build Coastguard Worker   #include "chat_protos/chat_service.rpc.pwpb.h"
250*61c4878aSAndroid Build Coastguard Worker
251*61c4878aSAndroid Build Coastguard Worker   namespace {
252*61c4878aSAndroid Build Coastguard Worker
253*61c4878aSAndroid Build Coastguard Worker     using ChatClient = pw_rpc::pwpb::Chat::Client;
254*61c4878aSAndroid Build Coastguard Worker
255*61c4878aSAndroid Build Coastguard Worker     MyChannelOutput output;
256*61c4878aSAndroid Build Coastguard Worker     pw::rpc::Channel channels[] = {pw::rpc::Channel::Create<1>(&output)};
257*61c4878aSAndroid Build Coastguard Worker     pw::rpc::Client client(channels);
258*61c4878aSAndroid Build Coastguard Worker
259*61c4878aSAndroid Build Coastguard Worker     // Callback function for GetRoomInformation.
260*61c4878aSAndroid Build Coastguard Worker     void LogRoomInformation(const RoomInfoResponse::Message& response,
261*61c4878aSAndroid Build Coastguard Worker                             Status status);
262*61c4878aSAndroid Build Coastguard Worker
263*61c4878aSAndroid Build Coastguard Worker   }  // namespace
264*61c4878aSAndroid Build Coastguard Worker
265*61c4878aSAndroid Build Coastguard Worker   void InvokeSomeRpcs() {
266*61c4878aSAndroid Build Coastguard Worker     // Instantiate a service client to call Chat service methods on channel 1.
267*61c4878aSAndroid Build Coastguard Worker     ChatClient chat_client(client, 1);
268*61c4878aSAndroid Build Coastguard Worker
269*61c4878aSAndroid Build Coastguard Worker     // The RPC will remain active as long as `call` is alive.
270*61c4878aSAndroid Build Coastguard Worker     auto call = chat_client.GetRoomInformation(
271*61c4878aSAndroid Build Coastguard Worker         {.room = "pigweed"}, LogRoomInformation);
272*61c4878aSAndroid Build Coastguard Worker     if (!call.active()) {
273*61c4878aSAndroid Build Coastguard Worker       // The invocation may fail. This could occur due to an invalid channel ID,
274*61c4878aSAndroid Build Coastguard Worker       // for example. The failure status is forwarded to the to call's
275*61c4878aSAndroid Build Coastguard Worker       // on_rpc_error callback.
276*61c4878aSAndroid Build Coastguard Worker       return;
277*61c4878aSAndroid Build Coastguard Worker     }
278*61c4878aSAndroid Build Coastguard Worker
279*61c4878aSAndroid Build Coastguard Worker     // For simplicity, block until the call completes. An actual implementation
280*61c4878aSAndroid Build Coastguard Worker     // would likely std::move the call somewhere to keep it active while doing
281*61c4878aSAndroid Build Coastguard Worker     // other work.
282*61c4878aSAndroid Build Coastguard Worker     while (call.active()) {
283*61c4878aSAndroid Build Coastguard Worker       Wait();
284*61c4878aSAndroid Build Coastguard Worker     }
285*61c4878aSAndroid Build Coastguard Worker
286*61c4878aSAndroid Build Coastguard Worker     // Do other stuff now that we have the room information.
287*61c4878aSAndroid Build Coastguard Worker   }
288