1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef CHRE_UTIL_PIGWEED_RPC_SERVER_H_
18 #define CHRE_UTIL_PIGWEED_RPC_SERVER_H_
19 
20 #include "chre/util/dynamic_vector.h"
21 #include "chre/util/macros.h"
22 #include "chre/util/non_copyable.h"
23 #include "chre/util/pigweed/chre_channel_output.h"
24 #include "chre/util/pigweed/permission.h"
25 #include "pw_rpc/server.h"
26 #include "pw_rpc/service.h"
27 #include "pw_span/span.h"
28 
29 namespace chre {
30 
31 /**
32  * RPC Server wrapping a Pigweed RPC server.
33  *
34  * This helper class handles Pigweed RPC calls on the server side.
35  *
36  * The services must be registered from the `nanoappStart` function using
37  * the `registerService` method.
38  *
39  * The `handleEvent` method must be called at the beginning of the
40  * `nanoappHandleEvent` function to respond to RPC calls from the clients.
41  */
42 class RpcServer : public NonCopyable {
43  public:
44   struct Service {
45     /** A Pigweed service. */
46     pw::rpc::Service &service;
47     /**
48      * The ID of the service, it must be generated according to RFC 4122, UUID
49      * version 4 (random). This ID must be unique within a given nanoapp.
50      */
51     uint64_t id;
52 
53     /**
54      * The version of the service. It should be in sync with the version on the
55      * client side.
56      */
57     uint32_t version;
58   };
59 
RpcServer()60   RpcServer() : mHostOutput(mPermission), mNanoappOutput(mPermission) {}
61 
62   /**
63    * Registers services to the server and to CHRE.
64    *
65    * This method must be called from `nanoappStart`.
66    *
67    * Although nanoapps are recommended to only call this API once with all
68    * services it intends to publish, if it is called multiple times, each
69    * call will append to the list of published services.
70    *
71    * @param numServices The number of services to register.
72    * @param services Service definitions.
73    * @return whether the registration was successful.
74    */
75   bool registerServices(size_t numServices, Service *services);
76 
77   /**
78    * Sets the permission for the next message to a client.
79    *
80    * While the permission are only actually used for messages to host clients,
81    * the value passed here only applies to the next message whether the client
82    * is a host client or a nanoapp.
83    *
84    * This method must be called:
85    * - from the body of a service implementation method in the case of unary
86    *   RPCs,
87    * - right before invoking ServerReader.Finish for client streaming and
88    *   bidirectional streaming RPCs,
89    * - right before invoking ServerWriter.Write and ServerWriter.Finish for
90    *   server streaming and bidirectional streaming RPCs.
91    *
92    * @params permission Bitmasked CHRE_MESSAGE_PERMISSION_.
93    *
94    * @see chreSendMessageWithPermissions
95    */
96   void setPermissionForNextMessage(uint32_t permission);
97 
98   /**
99    * Handles events related to RPC services.
100    *
101    * Handles the following events:
102    * - CHRE_EVENT_MESSAGE_FROM_HOST: respond to host RPC requests,
103    * - CHRE_EVENT_RPC_REQUEST: respond to nanoapp RPC requests,
104    * - CHRE_EVENT_HOST_ENDPOINT_NOTIFICATION: close the channel when the host
105    *   terminates,
106    * - CHRE_EVENT_NANOAPP_STOPPED: close the channel when a nanoapp
107    *   terminates.
108    *
109    * @param senderInstanceId The Instance ID for the source of this event.
110    * @param eventType The event type.
111    * @param eventData The associated data, if any, for this specific type of
112    *                  event.
113    * @return whether any event was handled successfully.
114    */
115   bool handleEvent(uint32_t senderInstanceId, uint16_t eventType,
116                    const void *eventData);
117 
118   /**
119    * Close all connections to the server.
120    *
121    * Must be called from the nanoapp end.
122    */
123   void close();
124 
125  private:
126   /**
127    * Handles messages from host clients.
128    *
129    * This method must be called when nanoapps receive a
130    * CHRE_EVENT_MESSAGE_FROM_HOST event.
131    *
132    * @param eventData  The associated data, if any.
133    * @return whether the RPC was handled successfully.
134    */
135   bool handleMessageFromHost(const void *eventData);
136 
137   /**
138    * Handles messages from nanoapp clients.
139    *
140    * This method must be called when nanoapps receive a CHRE_EVENT_RPC_REQUEST
141    * event.
142    *
143    * @param eventData  The associated data, if any.
144    * @return whether the RPC was handled successfully.
145    */
146   bool handleMessageFromNanoapp(uint32_t senderInstanceId,
147                                 const void *eventData);
148 
149   /**
150    * Closes the Pigweed channel when a host client disconnects.
151    *
152    * @param notification The notification from the host client
153    */
154   void handleHostClientNotification(const void *eventData);
155 
156   /**
157    * Closes the Pigweed channel when a nanoapp client disconnects.
158    *
159    * @param notification The eventData associated to a
160    *    CHRE_EVENT_NANOAPP_STOPPED event.
161    */
162   void handleNanoappStopped(const void *eventData);
163 
164   /**
165    * Closes a Pigweed channel.
166    *
167    * @param id The channel ID.
168    * @return either an ok or not found status if the channel was not opened.
169    */
170   pw::Status closeChannel(uint32_t id);
171 
172   // Permission for the next message sent by mServer.
173   RpcPermission mPermission;
174 
175   pw::rpc::Server mServer;
176 
177   ChreServerHostChannelOutput mHostOutput;
178   ChreServerNanoappChannelOutput mNanoappOutput;
179 
180   // Host endpoints for the connected clients.
181   DynamicVector<uint16_t> mConnectedHosts;
182 };
183 
184 }  // namespace chre
185 
186 #endif  // CHRE_UTIL_PIGWEED_RPC_SERVER_H_